diff --git a/lightly_studio/src/lightly_studio/migrations/versions/1791482578_3220ed4b892e_drop_tag_kind.py b/lightly_studio/src/lightly_studio/migrations/versions/1791482578_3220ed4b892e_drop_tag_kind.py new file mode 100644 index 0000000000..b1897dd2d6 --- /dev/null +++ b/lightly_studio/src/lightly_studio/migrations/versions/1791482578_3220ed4b892e_drop_tag_kind.py @@ -0,0 +1,61 @@ +"""drop tag kind column. + +A tag holds only samples of its own collection, so the sample type of the collection gives the +kind of the tag. The ``kind`` column only repeats that information. Tag names are already unique +per collection, so the drop cannot cause a name conflict. + +The downgrade re-adds ``kind`` as nullable, backfills it from the sample type of the collection +of each tag, and sets it ``NOT NULL``. A tag of an annotation collection gets ``'annotation'``. +All other tags get ``'sample'``, the default of the column. This includes a tag whose +collection was deleted. + +DuckDB builds its schema with ``create_all`` and has no migration step, so this migration only +matters for tracked Postgres databases. + +Revision ID: 3220ed4b892e +Revises: 68fcd3378db6 +Create Date: 2026-10-08 18:02:58.000000 + +""" + +from __future__ import annotations + +from collections.abc import Sequence + +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "3220ed4b892e" +down_revision: str | Sequence[str] | None = "68fcd3378db6" +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + + +def upgrade() -> None: + """Upgrade schema.""" + op.drop_column("tag", "kind") + + +def downgrade() -> None: + """Downgrade schema.""" + op.add_column( + "tag", + sa.Column("kind", sa.VARCHAR(), autoincrement=False, nullable=True), + ) + # The subquery is NULL for a tag whose collection was deleted, so that tag gets 'sample'. + op.execute( + sa.text( + """ + UPDATE tag SET kind = CASE ( + SELECT collection.sample_type + FROM collection + WHERE collection.collection_id = tag.collection_id + ) + WHEN 'ANNOTATION' THEN 'annotation' + ELSE 'sample' + END + """ + ) + ) + op.alter_column("tag", "kind", existing_type=sa.VARCHAR(), nullable=False) diff --git a/lightly_studio/src/lightly_studio/models/image.py b/lightly_studio/src/lightly_studio/models/image.py index 1981deb44c..0d5270a794 100644 --- a/lightly_studio/src/lightly_studio/models/image.py +++ b/lightly_studio/src/lightly_studio/models/image.py @@ -1,7 +1,7 @@ """This module defines the User model for the application.""" from datetime import datetime, timezone -from typing import Literal, Optional +from typing import Optional from uuid import UUID from pydantic import BaseModel, ConfigDict @@ -53,12 +53,6 @@ class ImageTable(ImageBase, table=True): sample: Mapped["SampleTable"] = Relationship() -TagKind = Literal[ - "sample", - "annotation", -] - - class ImageView(BaseModel): """Image class when retrieving.""" @@ -67,7 +61,6 @@ class ImageViewTag(BaseModel): tag_id: UUID name: str - kind: TagKind created_at: datetime updated_at: datetime @@ -116,7 +109,6 @@ def from_image_table( ImageView.ImageViewTag( tag_id=tag.tag_id, name=tag.name, - kind=tag.kind, created_at=tag.created_at, updated_at=tag.updated_at, ) diff --git a/lightly_studio/src/lightly_studio/models/tag.py b/lightly_studio/src/lightly_studio/models/tag.py index a22677c60a..6ce8109774 100644 --- a/lightly_studio/src/lightly_studio/models/tag.py +++ b/lightly_studio/src/lightly_studio/models/tag.py @@ -1,27 +1,19 @@ """This module contains the Tag model and related enumerations.""" from datetime import datetime, timezone -from typing import Literal from uuid import UUID, uuid4 from sqlalchemy import UniqueConstraint from sqlalchemy.orm import Mapped -from sqlmodel import Field, Relationship, SQLModel, String +from sqlmodel import Field, Relationship, SQLModel from lightly_studio.models.sample import SampleTable, SampleTagLinkTable -# TagKind is the kind of tag we support. -TagKind = Literal[ - "sample", - "annotation", -] - class TagBase(SQLModel): """Base class for the Tag model.""" name: str - kind: TagKind = "sample" class TagCreate(TagBase): @@ -44,7 +36,6 @@ class TagView(TagBase): """Tag model when retrieving.""" tag_id: UUID - kind: TagKind created_at: datetime updated_at: datetime @@ -53,11 +44,10 @@ class TagTable(TagBase, table=True): """This class defines the Tag model.""" __tablename__ = "tag" - # A tag name identifies a tag within a collection, irrespective of its kind. + # A tag name identifies a tag within a collection. __table_args__ = (UniqueConstraint("collection_id", "name", name="unique_name_constraint"),) tag_id: UUID = Field(default_factory=uuid4, primary_key=True) collection_id: UUID - kind: TagKind = Field(sa_type=String) created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc), index=True) updated_at: datetime = Field( default_factory=lambda: datetime.now(timezone.utc), diff --git a/lightly_studio/src/lightly_studio/resolvers/image_resolver/annotation_count_helpers/get_and_validate_sample_tags.py b/lightly_studio/src/lightly_studio/resolvers/image_resolver/annotation_count_helpers/get_and_validate_sample_tags.py index 16691a4bf9..e649cb9b13 100644 --- a/lightly_studio/src/lightly_studio/resolvers/image_resolver/annotation_count_helpers/get_and_validate_sample_tags.py +++ b/lightly_studio/src/lightly_studio/resolvers/image_resolver/annotation_count_helpers/get_and_validate_sample_tags.py @@ -19,14 +19,11 @@ def get_and_validate_sample_tags( """Return {tag_id: name} for the given IDs, raising if any are invalid.""" query = select(TagTable.tag_id, TagTable.name).where( col(TagTable.collection_id) == collection_id, - col(TagTable.kind) == "sample", db_array.in_array(column=col(TagTable.tag_id), values=sample_tag_ids), ) sample_tags = dict(session.exec(query).all()) invalid_ids = set(sample_tag_ids) - sample_tags.keys() if invalid_ids: ids = ", ".join(sorted(str(tag_id) for tag_id in invalid_ids)) - raise ValueError( - f"Tags must be sample tags belonging to collection {collection_id}: {ids}." - ) + raise ValueError(f"Tags must belong to collection {collection_id}: {ids}.") return sample_tags diff --git a/lightly_studio/src/lightly_studio/resolvers/tag_resolver/get_or_create_sample_tag_by_name.py b/lightly_studio/src/lightly_studio/resolvers/tag_resolver/get_or_create_sample_tag_by_name.py index 6a19b771a6..90d818e8b2 100644 --- a/lightly_studio/src/lightly_studio/resolvers/tag_resolver/get_or_create_sample_tag_by_name.py +++ b/lightly_studio/src/lightly_studio/resolvers/tag_resolver/get_or_create_sample_tag_by_name.py @@ -31,5 +31,5 @@ def get_or_create_sample_tag_by_name( if existing_tag: return existing_tag - new_tag = TagCreate(name=tag_name, collection_id=collection_id, kind="sample") + new_tag = TagCreate(name=tag_name, collection_id=collection_id) return tag_resolver.create(session=session, tag=new_tag) diff --git a/lightly_studio/src/lightly_studio/resolvers/tag_resolver/rename.py b/lightly_studio/src/lightly_studio/resolvers/tag_resolver/rename.py index 44b7f358fd..de4a267cae 100644 --- a/lightly_studio/src/lightly_studio/resolvers/tag_resolver/rename.py +++ b/lightly_studio/src/lightly_studio/resolvers/tag_resolver/rename.py @@ -57,7 +57,6 @@ def rename(session: Session, tag_id: UUID, new_name: str) -> TagTable | None: tag_id=tag_id, collection_id=tag.collection_id, name=new_name, - kind=tag.kind, created_at=tag.created_at, updated_at=datetime.now(timezone.utc), ) diff --git a/lightly_studio/src/lightly_studio/resolvers/tag_resolver/split_samples.py b/lightly_studio/src/lightly_studio/resolvers/tag_resolver/split_samples.py index 849df2e1a3..6127d3e951 100644 --- a/lightly_studio/src/lightly_studio/resolvers/tag_resolver/split_samples.py +++ b/lightly_studio/src/lightly_studio/resolvers/tag_resolver/split_samples.py @@ -67,7 +67,7 @@ def split_samples( counts = _allocate_counts(sample_count=len(unique_sample_ids), splits=normalized_splits) try: tags = [ - TagTable(name=split.tag_name, collection_id=collection_id, kind="sample") + TagTable(name=split.tag_name, collection_id=collection_id) for split in normalized_splits ] session.add_all(tags) diff --git a/lightly_studio/src/lightly_studio/services/sampling_service/validate_preselection.py b/lightly_studio/src/lightly_studio/services/sampling_service/validate_preselection.py index 8aeb713e8e..1e82eec0fd 100644 --- a/lightly_studio/src/lightly_studio/services/sampling_service/validate_preselection.py +++ b/lightly_studio/src/lightly_studio/services/sampling_service/validate_preselection.py @@ -27,7 +27,7 @@ def validate_preselection( return None tag = tag_resolver.get_by_id(session=session, tag_id=preselected_tag_id) - if tag is None or tag.collection_id != collection_id or tag.kind != "sample": + if tag is None or tag.collection_id != collection_id: raise ValueError("Invalid preselected sample tag.") preselected_sample_ids = tag_resolver.get_sample_ids_by_tag_id( diff --git a/lightly_studio/tests/api/routes/api/test_collection_tag.py b/lightly_studio/tests/api/routes/api/test_collection_tag.py index d45500b7ae..82caeda3ab 100644 --- a/lightly_studio/tests/api/routes/api/test_collection_tag.py +++ b/lightly_studio/tests/api/routes/api/test_collection_tag.py @@ -35,7 +35,7 @@ def test_add_samples_by_filter__image_empty_filter_tags_whole_collection( db_session: Session, test_client: TestClient ) -> None: collection_id = create_collection(session=db_session).collection_id - tag = create_tag(session=db_session, collection_id=collection_id, kind="sample") + tag = create_tag(session=db_session, collection_id=collection_id) images = create_images( db_session=db_session, collection_id=collection_id, @@ -57,7 +57,7 @@ def test_add_samples_by_filter__image_subset_filter_tags_only_subset( db_session: Session, test_client: TestClient ) -> None: collection_id = create_collection(session=db_session).collection_id - tag = create_tag(session=db_session, collection_id=collection_id, kind="sample") + tag = create_tag(session=db_session, collection_id=collection_id) wide = create_image( session=db_session, collection_id=collection_id, file_path_abs="wide.png", width=1920 ) @@ -78,7 +78,7 @@ def test_add_samples_by_filter__idempotent_on_rerun( db_session: Session, test_client: TestClient ) -> None: collection_id = create_collection(session=db_session).collection_id - tag = create_tag(session=db_session, collection_id=collection_id, kind="sample") + tag = create_tag(session=db_session, collection_id=collection_id) image = create_image(session=db_session, collection_id=collection_id, file_path_abs="s.png") body = {"filter": {"filter_type": "image"}} @@ -109,7 +109,7 @@ def test_add_samples_by_filter__annotation_grid( collection_id=collection.collection_id, sample_type=SampleType.ANNOTATION, ) - tag = create_tag(session=db_session, collection_id=annotation_collection_id, kind="annotation") + tag = create_tag(session=db_session, collection_id=annotation_collection_id) response = test_client.post( f"/api/collections/{annotation_collection_id}/tags/{tag.tag_id}/add/samples_by_filter", @@ -137,7 +137,7 @@ def test_add_samples_by_filter__wrong_collection_returns_404( db_session: Session, test_client: TestClient ) -> None: collection_id = create_collection(session=db_session).collection_id - tag = create_tag(session=db_session, collection_id=collection_id, kind="sample") + tag = create_tag(session=db_session, collection_id=collection_id) # Tag exists, but not in the collection on the path. response = test_client.post( @@ -154,7 +154,7 @@ def test_add_samples_by_filter__image_filter_with_embedding_region_tags_only_reg """Tagging by filter with an embedding region only tags samples inside the region.""" collection = create_collection(session=db_session) collection_id = collection.collection_id - tag = create_tag(session=db_session, collection_id=collection_id, kind="sample") + tag = create_tag(session=db_session, collection_id=collection_id) embedding_model = create_embedding_model( session=db_session, collection_id=collection_id, @@ -251,7 +251,7 @@ def test_add_samples_by_filter__annotations_filter_with_embedding_region_tags_on sample_id=image.sample_id, annotation_label_id=label.annotation_label_id, ) - tag = create_tag(session=db_session, collection_id=annotation_collection_id, kind="annotation") + tag = create_tag(session=db_session, collection_id=annotation_collection_id) embedding_model = create_embedding_model( session=db_session, collection_id=annotation_collection_id, diff --git a/lightly_studio/tests/api/routes/api/test_embeddings2d.py b/lightly_studio/tests/api/routes/api/test_embeddings2d.py index dfdf8f7682..d12f17f25d 100644 --- a/lightly_studio/tests/api/routes/api/test_embeddings2d.py +++ b/lightly_studio/tests/api/routes/api/test_embeddings2d.py @@ -115,7 +115,7 @@ def test_get_embeddings2d__2d__with_tag_filter( tag = tag_resolver.create( session=db_session, - tag=TagCreate(collection_id=collection_id, name="tagged", kind="sample"), + tag=TagCreate(collection_id=collection_id, name="tagged"), ) for sample in tagged_samples: tag_resolver.add_tag_to_sample(session=db_session, tag_id=tag.tag_id, sample=sample.sample) @@ -201,7 +201,7 @@ def test_get_embeddings2d__with_video_filter( tag = tag_resolver.create( session=db_session, - tag=TagCreate(collection_id=collection_id, name="tagged", kind="sample"), + tag=TagCreate(collection_id=collection_id, name="tagged"), ) tagged_video = videos[0] sample_table = sample_resolver.get_by_id(session=db_session, sample_id=tagged_video.sample_id) diff --git a/lightly_studio/tests/api/routes/api/test_embeddings2d__color_by.py b/lightly_studio/tests/api/routes/api/test_embeddings2d__color_by.py index 5d61cc5a39..5240b5d437 100644 --- a/lightly_studio/tests/api/routes/api/test_embeddings2d__color_by.py +++ b/lightly_studio/tests/api/routes/api/test_embeddings2d__color_by.py @@ -448,11 +448,11 @@ def test_get_embeddings2d__with_tag_color_by( tag_a = tag_resolver.create( session=db_session, - tag=TagCreate(collection_id=collection_id, name="alpha", kind="sample"), + tag=TagCreate(collection_id=collection_id, name="alpha"), ) tag_b = tag_resolver.create( session=db_session, - tag=TagCreate(collection_id=collection_id, name="beta", kind="sample"), + tag=TagCreate(collection_id=collection_id, name="beta"), ) # samples[0] in alpha only, samples[1] in beta only, @@ -523,15 +523,15 @@ def test_get_embeddings2d__with_tag_color_by_and_filter( tag_color = tag_resolver.create( session=db_session, - tag=TagCreate(collection_id=collection_id, name="color_tag", kind="sample"), + tag=TagCreate(collection_id=collection_id, name="color_tag"), ) tag_filter = tag_resolver.create( session=db_session, - tag=TagCreate(collection_id=collection_id, name="filter_tag", kind="sample"), + tag=TagCreate(collection_id=collection_id, name="filter_tag"), ) tag_hidden = tag_resolver.create( session=db_session, - tag=TagCreate(collection_id=collection_id, name="hidden_tag", kind="sample"), + tag=TagCreate(collection_id=collection_id, name="hidden_tag"), ) # All samples get the color tag. diff --git a/lightly_studio/tests/api/routes/api/test_image_count_by_sample_tags.py b/lightly_studio/tests/api/routes/api/test_image_count_by_sample_tags.py index d0bb804873..6759baaf94 100644 --- a/lightly_studio/tests/api/routes/api/test_image_count_by_sample_tags.py +++ b/lightly_studio/tests/api/routes/api/test_image_count_by_sample_tags.py @@ -68,21 +68,21 @@ def test_count_image_annotations_by_sample_tags( ] -def test_count_image_annotations_by_sample_tags__rejects_annotation_tag( +def test_count_image_annotations_by_sample_tags__rejects_foreign_collection_tag( test_client: TestClient, db_session: Session, ) -> None: collection = create_collection(session=db_session) - annotation_tag = create_tag( + other_collection = create_collection(session=db_session) + foreign_tag = create_tag( session=db_session, - collection_id=collection.collection_id, - kind="annotation", + collection_id=other_collection.collection_id, ) response = test_client.post( f"/api/collections/{collection.collection_id}/images/annotations/count-by-sample-tags", - json={"sample_tag_ids": [str(annotation_tag.tag_id)]}, + json={"sample_tag_ids": [str(foreign_tag.tag_id)]}, ) assert response.status_code == HTTP_STATUS_BAD_REQUEST - assert "must be sample tags belonging to collection" in response.json()["error"] + assert "must belong to collection" in response.json()["error"] diff --git a/lightly_studio/tests/api/routes/api/test_sampling.py b/lightly_studio/tests/api/routes/api/test_sampling.py index e3fe8a5c17..818c2964ae 100644 --- a/lightly_studio/tests/api/routes/api/test_sampling.py +++ b/lightly_studio/tests/api/routes/api/test_sampling.py @@ -220,32 +220,6 @@ def test_create_combination_sampling__unknown_preselected_tag( assert response.json()["error"] == "Invalid preselected sample tag." -def test_create_combination_sampling__annotation_preselected_tag( - test_client: TestClient, db_session: Session -) -> None: - collection_id = helpers_resolvers.fill_db_with_samples_and_embeddings( - session=db_session, n_samples=3, embedding_model_names=["test_embedding_model"] - ) - annotation_tag = helpers_resolvers.create_tag( - session=db_session, - collection_id=collection_id, - tag_name="annotations", - kind="annotation", - ) - - response = test_client.post( - f"/api/collections/{collection_id}/sampling", - json=_sampling_request_data( - n_samples_to_select=1, - sampling_result_tag_name="new_batch", - preselected_tag_id=annotation_tag.tag_id, - ), - ) - - assert response.status_code == 400 - assert response.json()["error"] == "Invalid preselected sample tag." - - def test_create_sampling__passes_request_to_sampling( db_session: Session, mocker: MockerFixture ) -> None: diff --git a/lightly_studio/tests/benchmarks/tag_assignment_benchmark.py b/lightly_studio/tests/benchmarks/tag_assignment_benchmark.py index 924ad68ed7..0426b5c02f 100644 --- a/lightly_studio/tests/benchmarks/tag_assignment_benchmark.py +++ b/lightly_studio/tests/benchmarks/tag_assignment_benchmark.py @@ -171,7 +171,6 @@ def _setup(config: BenchmarkConfig) -> tuple[list[UUID], UUID]: tag=TagCreate( name=DEFAULT_TAG_NAME, collection_id=collection.collection_id, - kind="sample", ), ) return sample_ids, tag.tag_id diff --git a/lightly_studio/tests/conftest.py b/lightly_studio/tests/conftest.py index 1c71c0de81..eed84204f9 100644 --- a/lightly_studio/tests/conftest.py +++ b/lightly_studio/tests/conftest.py @@ -355,7 +355,6 @@ def annotation_tags( TagCreate( collection_id=collections[i % 2].collection_id, name=f"Test Tag {i}", - kind="annotation", ), ) tags.append(tag) @@ -375,7 +374,6 @@ def sample_tags( TagCreate( collection_id=collection.collection_id, name=f"Test Sample Tag {i}", - kind="sample", ), ) tags.append(tag) @@ -504,7 +502,6 @@ def annotation_tags_assigned( session=db_session, collection_id=annotation_collection_id, tag_name=f"Test Annotation Tag {i}", - kind="annotation", ) for i in range(2) ] diff --git a/lightly_studio/tests/core/dataset_query/test_dataset_query__add_tag.py b/lightly_studio/tests/core/dataset_query/test_dataset_query__add_tag.py index 085948588a..6656f12c03 100644 --- a/lightly_studio/tests/core/dataset_query/test_dataset_query__add_tag.py +++ b/lightly_studio/tests/core/dataset_query/test_dataset_query__add_tag.py @@ -54,7 +54,6 @@ def test_add_tag__with_expressions(self, db_session: Session) -> None: ) assert tag is not None assert tag.name == "my_tag" - assert tag.kind == "sample" # Refresh samples to get updated tags db_session.refresh(image10) diff --git a/lightly_studio/tests/core/mcap/test_write_labels.py b/lightly_studio/tests/core/mcap/test_write_labels.py index b527cfd6e6..7ff764aac3 100644 --- a/lightly_studio/tests/core/mcap/test_write_labels.py +++ b/lightly_studio/tests/core/mcap/test_write_labels.py @@ -117,7 +117,6 @@ def test_write_sequence_labels__frame_tags( "lidar_dropout": {group_ids[0], group_ids[1]}, "night": {group_ids[0]}, } - assert all(tag.kind == "sample" for tag in tags) def test_write_sequence_labels__links_parent_tracks( diff --git a/lightly_studio/tests/database/test_db_migrations.py b/lightly_studio/tests/database/test_db_migrations.py index 7cf2493458..14887d007a 100644 --- a/lightly_studio/tests/database/test_db_migrations.py +++ b/lightly_studio/tests/database/test_db_migrations.py @@ -608,14 +608,14 @@ def test_postgres_tag_name_uniqueness__consolidates_cross_kind_duplicates( with engine.connect() as connection: tags = connection.execute( - statement=text("SELECT tag_id, kind FROM tag WHERE name = 'duplicate'") + statement=text("SELECT tag_id FROM tag WHERE name = 'duplicate'") ).all() links = connection.execute( statement=text( "SELECT sample_id, tag_id FROM sampletaglinktable ORDER BY sample_id" ) ).all() - assert [(str(tag_id), kind) for tag_id, kind in tags] == [(sample_tag_id, "sample")] + assert [str(tag_id) for (tag_id,) in tags] == [sample_tag_id] assert [(str(sample_id), str(tag_id)) for sample_id, tag_id in links] == [ (first_sample_id, sample_tag_id), (second_sample_id, sample_tag_id), @@ -749,7 +749,7 @@ def test_postgres_tag_links__moved_to_sample_collection( ) db_migrations._run_alembic_command( - engine=engine, config=config, fn=command.upgrade, revision="head" + engine=engine, config=config, fn=command.upgrade, revision="68fcd3378db6" ) with engine.connect() as connection: @@ -789,6 +789,9 @@ def test_postgres_tag_links__moved_to_sample_collection( ] assert [str(tag_id) for (tag_id,) in pred_review_tag_ids] == [pred_review_tag_id] + db_migrations._run_alembic_command( + engine=engine, config=config, fn=command.upgrade, revision="head" + ) config.attributes.pop("connection", None) command.check(config) finally: @@ -796,6 +799,122 @@ def test_postgres_tag_links__moved_to_sample_collection( engine.dispose() +def test_postgres_tag_kind__dropped_and_restored( + postgres_url: str | None, +) -> None: + """The migration drops the tag kind and the downgrade restores it from the collection.""" + if postgres_url is None: + pytest.skip("Requires --postgres") + + _reset_postgres_database(engine_url=postgres_url) + normalized_url = db_url.ensure_psycopg3_driver(engine_url=postgres_url) + engine = create_engine(normalized_url) + config = db_migrations.get_alembic_config(engine_url=postgres_url) + dataset_id = "00000000-0000-0000-0000-000000000001" + image_collection_id = "00000000-0000-0000-0000-000000000002" + gt_collection_id = "00000000-0000-0000-0000-000000000003" + image_tag_id = "00000000-0000-0000-0000-000000000004" + gt_tag_id = "00000000-0000-0000-0000-000000000005" + orphan_tag_id = "00000000-0000-0000-0000-000000000006" + deleted_collection_id = "00000000-0000-0000-0000-000000000007" + + try: + db_migrations._run_alembic_command( + engine=engine, + config=config, + fn=command.upgrade, + revision="68fcd3378db6", + ) + with engine.begin() as connection: + connection.execute( + statement=text("INSERT INTO dataset (dataset_id) VALUES (:dataset_id)"), + parameters={"dataset_id": dataset_id}, + ) + connection.execute( + statement=text( + """ + INSERT INTO collection ( + name, sample_type, collection_id, parent_collection_id, dataset_id, + created_at, updated_at + ) VALUES + ('images', 'IMAGE', :image_collection_id, NULL, :dataset_id, + NOW(), NOW()), + ('ground_truth', 'ANNOTATION', :gt_collection_id, :image_collection_id, + :dataset_id, NOW(), NOW()) + """ + ), + parameters={ + "dataset_id": dataset_id, + "image_collection_id": image_collection_id, + "gt_collection_id": gt_collection_id, + }, + ) + # The ground truth tag has no samples, so only its collection gives its kind. + # The collection of the orphaned tag was deleted. + connection.execute( + statement=text( + """ + INSERT INTO tag (name, kind, tag_id, collection_id, created_at, updated_at) + VALUES + ('selected', 'sample', :image_tag_id, :image_collection_id, + NOW(), NOW()), + ('reviewed', 'annotation', :gt_tag_id, :gt_collection_id, + NOW(), NOW()), + ('orphaned', 'annotation', :orphan_tag_id, :deleted_collection_id, + NOW(), NOW()) + """ + ), + parameters={ + "image_tag_id": image_tag_id, + "gt_tag_id": gt_tag_id, + "orphan_tag_id": orphan_tag_id, + "image_collection_id": image_collection_id, + "gt_collection_id": gt_collection_id, + "deleted_collection_id": deleted_collection_id, + }, + ) + + db_migrations._run_alembic_command( + engine=engine, config=config, fn=command.upgrade, revision="head" + ) + columns = db_migrations._get_inspector(engine=engine).get_columns(table_name="tag") + assert "kind" not in {column["name"] for column in columns} + with engine.connect() as connection: + tag_ids = connection.execute( + statement=text("SELECT tag_id FROM tag ORDER BY tag_id") + ).all() + assert [str(tag_id) for (tag_id,) in tag_ids] == [ + image_tag_id, + gt_tag_id, + orphan_tag_id, + ] + + config.attributes.pop("connection", None) + command.check(config) + + db_migrations._run_alembic_command( + engine=engine, + config=config, + fn=command.downgrade, + revision="68fcd3378db6", + ) + columns = db_migrations._get_inspector(engine=engine).get_columns(table_name="tag") + kind_column = next(column for column in columns if column["name"] == "kind") + assert kind_column["nullable"] is False + with engine.connect() as connection: + tags = connection.execute( + statement=text("SELECT tag_id, kind FROM tag ORDER BY tag_id") + ).all() + assert [(str(tag_id), kind) for tag_id, kind in tags] == [ + (image_tag_id, "sample"), + (gt_tag_id, "annotation"), + (orphan_tag_id, "sample"), + ] + finally: + _restore_shared_database_to_head(engine=engine, engine_url=postgres_url) + engine.dispose() + + def _metadata_column_data_type(engine: Engine, column_name: str) -> str: """Return the SQL ``data_type`` of a ``metadata`` column, e.g. ``json`` or ``jsonb``.""" with engine.connect() as connection: diff --git a/lightly_studio/tests/helpers_resolvers.py b/lightly_studio/tests/helpers_resolvers.py index 115547cdf2..1471e38024 100644 --- a/lightly_studio/tests/helpers_resolvers.py +++ b/lightly_studio/tests/helpers_resolvers.py @@ -35,7 +35,7 @@ SampleEmbeddingCreate, SampleEmbeddingTable, ) -from lightly_studio.models.tag import TagCreate, TagKind, TagTable +from lightly_studio.models.tag import TagCreate, TagTable from lightly_studio.resolvers import ( annotation_label_resolver, annotation_resolver, @@ -127,7 +127,6 @@ def create_tag( session: Session, collection_id: UUID, tag_name: str = "example_tag", - kind: TagKind = "sample", ) -> TagTable: """Helper function to create a tag.""" return tag_resolver.create( @@ -135,7 +134,6 @@ def create_tag( tag=TagCreate( collection_id=collection_id, name=tag_name, - kind=kind, description="example description", ), ) diff --git a/lightly_studio/tests/models/test_image.py b/lightly_studio/tests/models/test_image.py index 7e45d96ca2..d9bbf22248 100644 --- a/lightly_studio/tests/models/test_image.py +++ b/lightly_studio/tests/models/test_image.py @@ -139,7 +139,6 @@ def test_from_image_table__with_tags(self, db_session: Session) -> None: assert len(image_view.tags) == 1 assert image_view.tags[0].tag_id == tag.tag_id assert image_view.tags[0].name == "outdoor" - assert image_view.tags[0].kind == "sample" def test_from_image_table__with_all_relationships(self, db_session: Session) -> None: """Test conversion with all relationships populated.""" diff --git a/lightly_studio/tests/resolvers/annotations/test_delete_annotation.py b/lightly_studio/tests/resolvers/annotations/test_delete_annotation.py index 2598c11475..4cf9e5725b 100644 --- a/lightly_studio/tests/resolvers/annotations/test_delete_annotation.py +++ b/lightly_studio/tests/resolvers/annotations/test_delete_annotation.py @@ -80,7 +80,6 @@ def test_delete_annotation__deletes_sample_tag_links( session=db_session, collection_id=annotation_collection_id, tag_name="annotation-tag", - kind="annotation", ) annotation.sample.tags.append(tag) db_session.add(annotation.sample) diff --git a/lightly_studio/tests/resolvers/group_resolver/test_get_all.py b/lightly_studio/tests/resolvers/group_resolver/test_get_all.py index 3c97c39e65..938fcf4e95 100644 --- a/lightly_studio/tests/resolvers/group_resolver/test_get_all.py +++ b/lightly_studio/tests/resolvers/group_resolver/test_get_all.py @@ -109,7 +109,6 @@ def test_get_all__with_filters(db_session: Session) -> None: session=db_session, collection_id=group_col.collection_id, tag_name="test_tag", - kind="sample", ) front_images = create_images( diff --git a/lightly_studio/tests/resolvers/image_resolver/annotation_count_helpers/test_get_and_validate_sample_tags.py b/lightly_studio/tests/resolvers/image_resolver/annotation_count_helpers/test_get_and_validate_sample_tags.py index f3ac710a0a..24f3e7ac2d 100644 --- a/lightly_studio/tests/resolvers/image_resolver/annotation_count_helpers/test_get_and_validate_sample_tags.py +++ b/lightly_studio/tests/resolvers/image_resolver/annotation_count_helpers/test_get_and_validate_sample_tags.py @@ -26,7 +26,7 @@ def test_get_and_validate_sample_tags__raises_for_missing_id(db_session: Session collection = create_collection(session=db_session) missing_id = uuid4() - with pytest.raises(ValueError, match="must be sample tags belonging to collection"): + with pytest.raises(ValueError, match="must belong to collection"): annotation_count_helpers.get_and_validate_sample_tags( session=db_session, collection_id=collection.collection_id, @@ -34,20 +34,6 @@ def test_get_and_validate_sample_tags__raises_for_missing_id(db_session: Session ) -def test_get_and_validate_sample_tags__raises_for_annotation_tag(db_session: Session) -> None: - collection = create_collection(session=db_session) - annotation_tag = create_tag( - session=db_session, collection_id=collection.collection_id, kind="annotation" - ) - - with pytest.raises(ValueError, match="must be sample tags belonging to collection"): - annotation_count_helpers.get_and_validate_sample_tags( - session=db_session, - collection_id=collection.collection_id, - sample_tag_ids=[annotation_tag.tag_id], - ) - - def test_get_and_validate_sample_tags__raises_for_foreign_collection_tag( db_session: Session, ) -> None: @@ -55,7 +41,7 @@ def test_get_and_validate_sample_tags__raises_for_foreign_collection_tag( other_collection = create_collection(session=db_session) foreign_tag = create_tag(session=db_session, collection_id=other_collection.collection_id) - with pytest.raises(ValueError, match="must be sample tags belonging to collection"): + with pytest.raises(ValueError, match="must belong to collection"): annotation_count_helpers.get_and_validate_sample_tags( session=db_session, collection_id=collection.collection_id, diff --git a/lightly_studio/tests/resolvers/image_resolver/test_count_image_annotations_by_sample_tags.py b/lightly_studio/tests/resolvers/image_resolver/test_count_image_annotations_by_sample_tags.py index a1d336a5b3..de330f2193 100644 --- a/lightly_studio/tests/resolvers/image_resolver/test_count_image_annotations_by_sample_tags.py +++ b/lightly_studio/tests/resolvers/image_resolver/test_count_image_annotations_by_sample_tags.py @@ -206,19 +206,18 @@ def test_count_image_annotations_by_sample_tags__annotation_source_and_type_scop assert [(row.label_name, row.count) for row in result[0].counts] == [("scene", 1)] -@pytest.mark.parametrize("invalid_tag_kind", ["missing", "foreign", "annotation"]) +@pytest.mark.parametrize("invalid_tag_case", ["missing", "foreign"]) def test_count_image_annotations_by_sample_tags__rejects_invalid_tags( db_session: Session, - invalid_tag_kind: str, + invalid_tag_case: str, ) -> None: collection = create_collection(session=db_session) invalid_tag_id = _create_invalid_tag_id( session=db_session, - collection_id=collection.collection_id, - invalid_tag_kind=invalid_tag_kind, + invalid_tag_case=invalid_tag_case, ) - with pytest.raises(ValueError, match="must be sample tags belonging to collection"): + with pytest.raises(ValueError, match="must belong to collection"): image_resolver.count_image_annotations_by_sample_tags( session=db_session, collection_id=collection.collection_id, @@ -240,16 +239,9 @@ def test_count_image_annotations_by_sample_tags__empty_selection(db_session: Ses def _create_invalid_tag_id( session: Session, - collection_id: UUID, - invalid_tag_kind: str, + invalid_tag_case: str, ) -> UUID: - if invalid_tag_kind == "missing": + if invalid_tag_case == "missing": return uuid.uuid4() - if invalid_tag_kind == "annotation": - return create_tag( - session=session, - collection_id=collection_id, - kind="annotation", - ).tag_id foreign_collection = create_collection(session=session) return create_tag(session=session, collection_id=foreign_collection.collection_id).tag_id diff --git a/lightly_studio/tests/resolvers/image_resolver/test_get_all_by_dataset_id.py b/lightly_studio/tests/resolvers/image_resolver/test_get_all_by_dataset_id.py index bf97ef3258..b74f37e1ff 100644 --- a/lightly_studio/tests/resolvers/image_resolver/test_get_all_by_dataset_id.py +++ b/lightly_studio/tests/resolvers/image_resolver/test_get_all_by_dataset_id.py @@ -356,13 +356,11 @@ def test_get_all_by_collection_id__with_tag_filtering( session=db_session, collection_id=collection_id, tag_name="tag_1", - kind="sample", ) tag_part2 = create_tag( session=db_session, collection_id=collection_id, tag_name="tag_2", - kind="sample", ) total_samples = 10 diff --git a/lightly_studio/tests/resolvers/image_resolver/test_get_dimension_bounds.py b/lightly_studio/tests/resolvers/image_resolver/test_get_dimension_bounds.py index 0c7827c5ac..c752268b41 100644 --- a/lightly_studio/tests/resolvers/image_resolver/test_get_dimension_bounds.py +++ b/lightly_studio/tests/resolvers/image_resolver/test_get_dimension_bounds.py @@ -60,7 +60,6 @@ def test_get_dimension_bounds__with_tag_filtering( session=db_session, collection_id=collection_id, tag_name="bigger", - kind="sample", ) tag_resolver.add_sample_ids_to_tag_id( session=db_session, @@ -73,7 +72,6 @@ def test_get_dimension_bounds__with_tag_filtering( session=db_session, collection_id=collection_id, tag_name="smaller", - kind="sample", ) tag_resolver.add_sample_ids_to_tag_id( session=db_session, diff --git a/lightly_studio/tests/resolvers/sample_resolver/test_get_filtered_samples.py b/lightly_studio/tests/resolvers/sample_resolver/test_get_filtered_samples.py index ab0a609a1d..01dc4f3632 100644 --- a/lightly_studio/tests/resolvers/sample_resolver/test_get_filtered_samples.py +++ b/lightly_studio/tests/resolvers/sample_resolver/test_get_filtered_samples.py @@ -171,9 +171,7 @@ def test_get_filtered_samples__filters( ) # Add a tag to sample2 - tag = create_tag( - session=db_session, collection_id=collection_id, tag_name="tag1", kind="sample" - ) + tag = create_tag(session=db_session, collection_id=collection_id, tag_name="tag1") tag_resolver.add_sample_ids_to_tag_id( session=db_session, tag_id=tag.tag_id, diff --git a/lightly_studio/tests/resolvers/sample_resolver/test_sample_filter.py b/lightly_studio/tests/resolvers/sample_resolver/test_sample_filter.py index dd6f69cd2b..f1e49c0ccf 100644 --- a/lightly_studio/tests/resolvers/sample_resolver/test_sample_filter.py +++ b/lightly_studio/tests/resolvers/sample_resolver/test_sample_filter.py @@ -226,12 +226,8 @@ def test_query__tag_filter(self, db_session: Session) -> None: ) # Create tags - tag1 = create_tag( - session=db_session, collection_id=collection_id, tag_name="tag1", kind="sample" - ) - tag2 = create_tag( - session=db_session, collection_id=collection_id, tag_name="tag2", kind="sample" - ) + tag1 = create_tag(session=db_session, collection_id=collection_id, tag_name="tag1") + tag2 = create_tag(session=db_session, collection_id=collection_id, tag_name="tag2") # Add samples to tags tag_resolver.add_sample_ids_to_tag_id( @@ -276,12 +272,8 @@ def test_query__tag_filter_distinct_samples_only( ) # Create tags - tag1 = create_tag( - session=db_session, collection_id=collection_id, tag_name="tag1", kind="sample" - ) - tag2 = create_tag( - session=db_session, collection_id=collection_id, tag_name="tag2", kind="sample" - ) + tag1 = create_tag(session=db_session, collection_id=collection_id, tag_name="tag1") + tag2 = create_tag(session=db_session, collection_id=collection_id, tag_name="tag2") # Add tag1 and tag2 twice to the first sample tag_resolver.add_sample_ids_to_tag_id( @@ -435,12 +427,8 @@ def test_query__combination(self, db_session: Session) -> None: # Tag samples # Add tag1 to samples 1, 2 and tag2 to samples 0, 1 - tag1 = create_tag( - session=db_session, collection_id=collection_id, tag_name="tag1", kind="sample" - ) - tag2 = create_tag( - session=db_session, collection_id=collection_id, tag_name="tag2", kind="sample" - ) + tag1 = create_tag(session=db_session, collection_id=collection_id, tag_name="tag1") + tag2 = create_tag(session=db_session, collection_id=collection_id, tag_name="tag2") tag_resolver.add_sample_ids_to_tag_id( session=db_session, tag_id=tag1.tag_id, diff --git a/lightly_studio/tests/resolvers/tag_resolver/test_add_sample_ids_to_tag_id.py b/lightly_studio/tests/resolvers/tag_resolver/test_add_sample_ids_to_tag_id.py index 72c18a6547..1ab1b7cc0d 100644 --- a/lightly_studio/tests/resolvers/tag_resolver/test_add_sample_ids_to_tag_id.py +++ b/lightly_studio/tests/resolvers/tag_resolver/test_add_sample_ids_to_tag_id.py @@ -16,13 +16,11 @@ def test_add_and_remove_sample_ids_to_tag_id( session=db_session, collection_id=collection_id, tag_name="tag_all", - kind="sample", ) tag_2 = create_tag( session=db_session, collection_id=collection_id, tag_name="tag_odd", - kind="sample", ) total_samples = 10 @@ -84,7 +82,6 @@ def test_add_and_remove_sample_ids_to_tag_id__twice_same_sample_ids( session=db_session, collection_id=collection_id, tag_name="tag_all", - kind="sample", ) total_samples = 10 diff --git a/lightly_studio/tests/resolvers/tag_resolver/test_add_samples_to_tag_from_query.py b/lightly_studio/tests/resolvers/tag_resolver/test_add_samples_to_tag_from_query.py index f0189e83ae..9f8eff6d9c 100644 --- a/lightly_studio/tests/resolvers/tag_resolver/test_add_samples_to_tag_from_query.py +++ b/lightly_studio/tests/resolvers/tag_resolver/test_add_samples_to_tag_from_query.py @@ -9,7 +9,7 @@ def test_add_samples_to_tag_from_query__tags_only_query_matches(db_session: Session) -> None: collection_id = create_collection(session=db_session).collection_id - tag = create_tag(session=db_session, collection_id=collection_id, kind="sample") + tag = create_tag(session=db_session, collection_id=collection_id) images = [ create_image(session=db_session, collection_id=collection_id, file_path_abs=f"s{i}.png") for i in range(4) diff --git a/lightly_studio/tests/resolvers/tag_resolver/test_add_tag_to_sample.py b/lightly_studio/tests/resolvers/tag_resolver/test_add_tag_to_sample.py index 99632ec271..ac29e82ead 100644 --- a/lightly_studio/tests/resolvers/tag_resolver/test_add_tag_to_sample.py +++ b/lightly_studio/tests/resolvers/tag_resolver/test_add_tag_to_sample.py @@ -8,7 +8,7 @@ def test_add_tag_to_sample(db_session: Session) -> None: collection = create_collection(session=db_session) collection_id = collection.collection_id - tag = create_tag(session=db_session, collection_id=collection_id, kind="sample") + tag = create_tag(session=db_session, collection_id=collection_id) image = create_image(session=db_session, collection_id=collection_id) # add sample to tag diff --git a/lightly_studio/tests/resolvers/tag_resolver/test_create.py b/lightly_studio/tests/resolvers/tag_resolver/test_create.py index 9caab57e43..4b293cfa5b 100644 --- a/lightly_studio/tests/resolvers/tag_resolver/test_create.py +++ b/lightly_studio/tests/resolvers/tag_resolver/test_create.py @@ -27,30 +27,6 @@ def test_create_tag__unique_tag_name(db_session: Session) -> None: tag=TagCreate( collection_id=collection_id, name="example_tag", - kind="sample", - ), - ) - db_session.rollback() - - -def test_create_tag__unique_tag_name_across_kinds(db_session: Session) -> None: - collection = create_collection(session=db_session) - collection_id = collection.collection_id - - create_tag( - session=db_session, - collection_id=collection_id, - tag_name="example_tag", - kind="sample", - ) - - with pytest.raises(IntegrityError): - tag_resolver.create( - session=db_session, - tag=TagCreate( - collection_id=collection_id, - name="example_tag", - kind="annotation", ), ) db_session.rollback() diff --git a/lightly_studio/tests/resolvers/tag_resolver/test_get_or_create_sample_tag_by_name.py b/lightly_studio/tests/resolvers/tag_resolver/test_get_or_create_sample_tag_by_name.py index 79717db2ed..40cbee5620 100644 --- a/lightly_studio/tests/resolvers/tag_resolver/test_get_or_create_sample_tag_by_name.py +++ b/lightly_studio/tests/resolvers/tag_resolver/test_get_or_create_sample_tag_by_name.py @@ -27,4 +27,3 @@ def test_get_or_create_sample_tag_by_name(db_session: Session) -> None: assert new_tag.tag_id != existing_tag.tag_id assert new_tag.name == "new_tag" assert new_tag.collection_id == collection_id - assert new_tag.kind == "sample" diff --git a/lightly_studio/tests/resolvers/tag_resolver/test_remove_tag_from_sample.py b/lightly_studio/tests/resolvers/tag_resolver/test_remove_tag_from_sample.py index 3c20fe5e30..6a5fecf0e8 100644 --- a/lightly_studio/tests/resolvers/tag_resolver/test_remove_tag_from_sample.py +++ b/lightly_studio/tests/resolvers/tag_resolver/test_remove_tag_from_sample.py @@ -8,7 +8,7 @@ def test_remove_sample_from_tag(db_session: Session) -> None: collection = create_collection(session=db_session) collection_id = collection.collection_id - tag = create_tag(session=db_session, collection_id=collection_id, kind="sample") + tag = create_tag(session=db_session, collection_id=collection_id) image = create_image(session=db_session, collection_id=collection_id) # add sample to tag diff --git a/lightly_studio/tests/resolvers/tag_resolver/test_rename.py b/lightly_studio/tests/resolvers/tag_resolver/test_rename.py index 989024627f..22956cfc55 100644 --- a/lightly_studio/tests/resolvers/tag_resolver/test_rename.py +++ b/lightly_studio/tests/resolvers/tag_resolver/test_rename.py @@ -95,34 +95,6 @@ def test_rename_tag__unique_tag_name__preserves_original_tag_and_links( ) -def test_rename_tag__unique_tag_name__different_kind( - db_session: Session, -) -> None: - collection = create_collection(session=db_session) - collection_id = collection.collection_id - - sample_tag = create_tag( - session=db_session, - collection_id=collection_id, - kind="sample", - tag_name="sample_tag_1", - ) - annotation_tag = create_tag( - session=db_session, - collection_id=collection_id, - kind="annotation", - tag_name="annotation_tag_1", - ) - - # A name used by an annotation tag cannot be reused by a sample tag. - with pytest.raises(IntegrityError): - tag_resolver.rename( - session=db_session, - tag_id=sample_tag.tag_id, - new_name=annotation_tag.name, - ) - - def test_rename_tag__unknown_tag_returns_none(db_session: Session) -> None: collection = create_collection(session=db_session) collection_id = collection.collection_id diff --git a/lightly_studio/tests/resolvers/test_annotation_resolver.py b/lightly_studio/tests/resolvers/test_annotation_resolver.py index 9366d8eb09..1eddb86912 100644 --- a/lightly_studio/tests/resolvers/test_annotation_resolver.py +++ b/lightly_studio/tests/resolvers/test_annotation_resolver.py @@ -553,13 +553,11 @@ def test_get_all__with_tag_filtering(db_session: Session) -> None: session=db_session, collection_id=annotation_collection_id, tag_name="tag_all", - kind="annotation", ) tag_2 = create_tag( session=db_session, collection_id=annotation_collection_id, tag_name="tag_odd", - kind="annotation", ) # add first half to tag_1 diff --git a/lightly_studio/tests/resolvers/test_image_filter.py b/lightly_studio/tests/resolvers/test_image_filter.py index 03a0170af6..df69ead5b3 100644 --- a/lightly_studio/tests/resolvers/test_image_filter.py +++ b/lightly_studio/tests/resolvers/test_image_filter.py @@ -173,7 +173,6 @@ def test_query__sample_filter( session=db_session, collection_id=collection_id, tag_name="test_tag", - kind="sample", ) tag_resolver.add_sample_ids_to_tag_id( session=db_session, diff --git a/lightly_studio/tests/sampling/test_sampling_via_db.py b/lightly_studio/tests/sampling/test_sampling_via_db.py index c3e4da3e1e..985a2ae6a0 100644 --- a/lightly_studio/tests/sampling/test_sampling_via_db.py +++ b/lightly_studio/tests/sampling/test_sampling_via_db.py @@ -205,7 +205,6 @@ def test_sampling_via_database__embedding_diversity__sample_filter_tags( tag=TagCreate( collection_id=collection_id, name="samples_5_through_14", - kind="sample", description="A test tag", ), ) @@ -443,7 +442,6 @@ def test_sampling_via_database__zero_input_samples_available( tag=TagCreate( collection_id=collection_id, name="empty_tag", - kind="sample", description="A tag with no samples", ), ) @@ -687,7 +685,7 @@ def test_sampling_via_database__preselected_sample_id_not_in_input( sample_id = _all_sample_ids(db_session, collection_id)[0] preselected_tag = tag_resolver.create( session=db_session, - tag=TagCreate(collection_id=collection_id, name="preselected", kind="sample"), + tag=TagCreate(collection_id=collection_id, name="preselected"), ) tag_resolver.add_sample_ids_to_tag_id( session=db_session, diff --git a/lightly_studio_view/src/lib/components/AnnotationsGrid/AnnotationsGrid.svelte b/lightly_studio_view/src/lib/components/AnnotationsGrid/AnnotationsGrid.svelte index ecf879ae22..250273f9b4 100644 --- a/lightly_studio_view/src/lib/components/AnnotationsGrid/AnnotationsGrid.svelte +++ b/lightly_studio_view/src/lib/components/AnnotationsGrid/AnnotationsGrid.svelte @@ -38,8 +38,7 @@ // Use the collection_id for tags - tags should use the specific collection, not root const { tagsSelected } = $derived( useTags({ - collection_id: collection_id, - kind: ['annotation'] + collection_id: collection_id }) ); diff --git a/lightly_studio_view/src/lib/components/Images/Images.svelte b/lightly_studio_view/src/lib/components/Images/Images.svelte index df492a0f0d..95b9c4a610 100644 --- a/lightly_studio_view/src/lib/components/Images/Images.svelte +++ b/lightly_studio_view/src/lib/components/Images/Images.svelte @@ -47,8 +47,7 @@ const { tagsSelected } = $derived.by(() => useTags({ - collection_id, - kind: ['sample'] + collection_id }) ); diff --git a/lightly_studio_view/src/lib/components/Operator/OperatorDialog.svelte b/lightly_studio_view/src/lib/components/Operator/OperatorDialog.svelte index d5fb114d88..47561d870f 100644 --- a/lightly_studio_view/src/lib/components/Operator/OperatorDialog.svelte +++ b/lightly_studio_view/src/lib/components/Operator/OperatorDialog.svelte @@ -60,7 +60,7 @@ const collectionId = $page.params.collection_id!; - const { tagsSelected } = useTags({ collection_id: collectionId, kind: ['annotation'] }); + const { tagsSelected } = useTags({ collection_id: collectionId }); const { scopeLabel, contextFilter } = useOperatorContext(pageContext, tagsSelected); diff --git a/lightly_studio_view/src/lib/components/PlotPanel/PlotPanel.svelte b/lightly_studio_view/src/lib/components/PlotPanel/PlotPanel.svelte index ad57fd0fb6..70209ad2bb 100644 --- a/lightly_studio_view/src/lib/components/PlotPanel/PlotPanel.svelte +++ b/lightly_studio_view/src/lib/components/PlotPanel/PlotPanel.svelte @@ -113,11 +113,9 @@ }); const { selectedColorByType } = usePlotColorByType(untrack(() => collectionId)); - // Annotation samples carry annotation-kind tags. Captured once at mount, like - // collectionId above. + // Captured once at mount, like collectionId above. const { tags } = useTags({ - collection_id: untrack(() => collectionId), - kind: isAnnotationsRoute(page.route?.id ?? null) ? ['annotation'] : ['sample'] + collection_id: untrack(() => collectionId) }); const annotationLabelsQuery = useAnnotationLabels(() => ({ collectionId })); const annotationLabels = writable<{ annotation_label_id: string }[]>([]); diff --git a/lightly_studio_view/src/lib/components/PlotPanel/PlotPanel.test.ts b/lightly_studio_view/src/lib/components/PlotPanel/PlotPanel.test.ts index 0dc9bcf16e..e6d922108b 100644 --- a/lightly_studio_view/src/lib/components/PlotPanel/PlotPanel.test.ts +++ b/lightly_studio_view/src/lib/components/PlotPanel/PlotPanel.test.ts @@ -37,8 +37,8 @@ let metadataInfoStore: Writable>; const mockResetCategoryVisibility = vi.fn(); const tagsStore = writable([ - { tag_id: 'tag-a', name: 'alpha', kind: 'sample' }, - { tag_id: 'tag-b', name: 'beta', kind: 'sample' } + { tag_id: 'tag-a', name: 'alpha' }, + { tag_id: 'tag-b', name: 'beta' } ]); const mockSetShowEmbeddingPlot = vi.fn(); @@ -225,8 +225,8 @@ describe('PlotPanel.svelte', () => { colorLegendStore = writable(new Map()); metadataInfoStore = writable([{ name: 'split', type: 'string' }]); tagsStore.set([ - { tag_id: 'tag-a', name: 'alpha', kind: 'sample' }, - { tag_id: 'tag-b', name: 'beta', kind: 'sample' } + { tag_id: 'tag-a', name: 'alpha' }, + { tag_id: 'tag-b', name: 'beta' } ]); (useEmbeddings as vi.Mock).mockReturnValue( writable({ diff --git a/lightly_studio_view/src/lib/components/Sampling/PreselectedTagField/PreselectedTagField.test.ts b/lightly_studio_view/src/lib/components/Sampling/PreselectedTagField/PreselectedTagField.test.ts index 5225cfe4dc..56e4ffe7f0 100644 --- a/lightly_studio_view/src/lib/components/Sampling/PreselectedTagField/PreselectedTagField.test.ts +++ b/lightly_studio_view/src/lib/components/Sampling/PreselectedTagField/PreselectedTagField.test.ts @@ -3,8 +3,8 @@ import { describe, expect, it, vi } from 'vitest'; import { PreselectedTagField } from '.'; const tags = [ - { tag_id: 'tag-1', name: 'First batch', kind: 'sample' as const }, - { tag_id: 'tag-2', name: 'Second batch', kind: 'sample' as const } + { tag_id: 'tag-1', name: 'First batch' }, + { tag_id: 'tag-2', name: 'Second batch' } ]; describe('PreselectedTagField', () => { diff --git a/lightly_studio_view/src/lib/components/Sampling/SamplingCombinationDialog.test.ts b/lightly_studio_view/src/lib/components/Sampling/SamplingCombinationDialog.test.ts index dc0b0894ed..3e59265c5d 100644 --- a/lightly_studio_view/src/lib/components/Sampling/SamplingCombinationDialog.test.ts +++ b/lightly_studio_view/src/lib/components/Sampling/SamplingCombinationDialog.test.ts @@ -6,7 +6,6 @@ import SamplingCombinationDialog from './SamplingCombinationDialog.svelte'; type MockTag = { tag_id: string; name: string; - kind: 'sample'; }; const pageMock = vi.hoisted(() => ({ @@ -126,7 +125,7 @@ describe('SamplingCombinationDialog', () => { metadataInfoStore = readable([]); isSubmittingStore = writable(false); loadingMessageStore = writable(''); - tagsStore = writable([{ tag_id: 'tag-1', name: 'Query Tag', kind: 'sample' as const }]); + tagsStore = writable([{ tag_id: 'tag-1', name: 'Query Tag' }]); annotationLabelsData = []; annotationCollectionsData = []; categoricalMetadataData = undefined; diff --git a/lightly_studio_view/src/lib/components/Sampling/useSamplingCombinationDialog/useSamplingCombinationDialog.ts b/lightly_studio_view/src/lib/components/Sampling/useSamplingCombinationDialog/useSamplingCombinationDialog.ts index f718e5d8ec..a5baaaa650 100644 --- a/lightly_studio_view/src/lib/components/Sampling/useSamplingCombinationDialog/useSamplingCombinationDialog.ts +++ b/lightly_studio_view/src/lib/components/Sampling/useSamplingCombinationDialog/useSamplingCombinationDialog.ts @@ -24,8 +24,7 @@ export function useSamplingCombinationDialog({ onSubmitSuccess }: UseSamplingCombinationDialogParams) { const { tags, loadTags, setTagSelected } = useTags({ - collection_id: getCollectionId(), - kind: ['sample'] + collection_id: getCollectionId() }); const { filteredSampleCount } = useGlobalStorage(); diff --git a/lightly_studio_view/src/lib/components/SegmentTags/SegmentTags.svelte b/lightly_studio_view/src/lib/components/SegmentTags/SegmentTags.svelte index 07a116257e..280c9815af 100644 --- a/lightly_studio_view/src/lib/components/SegmentTags/SegmentTags.svelte +++ b/lightly_studio_view/src/lib/components/SegmentTags/SegmentTags.svelte @@ -1,8 +1,7 @@