lightly-studio 0.4.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lightly_studio/__init__.py +12 -0
- lightly_studio/api/__init__.py +0 -0
- lightly_studio/api/app.py +131 -0
- lightly_studio/api/cache.py +77 -0
- lightly_studio/api/db_tables.py +35 -0
- lightly_studio/api/features.py +5 -0
- lightly_studio/api/routes/api/annotation.py +305 -0
- lightly_studio/api/routes/api/annotation_label.py +87 -0
- lightly_studio/api/routes/api/annotations/__init__.py +7 -0
- lightly_studio/api/routes/api/annotations/create_annotation.py +52 -0
- lightly_studio/api/routes/api/caption.py +100 -0
- lightly_studio/api/routes/api/classifier.py +384 -0
- lightly_studio/api/routes/api/dataset.py +191 -0
- lightly_studio/api/routes/api/dataset_tag.py +266 -0
- lightly_studio/api/routes/api/embeddings2d.py +90 -0
- lightly_studio/api/routes/api/exceptions.py +114 -0
- lightly_studio/api/routes/api/export.py +114 -0
- lightly_studio/api/routes/api/features.py +17 -0
- lightly_studio/api/routes/api/frame.py +241 -0
- lightly_studio/api/routes/api/image.py +155 -0
- lightly_studio/api/routes/api/metadata.py +161 -0
- lightly_studio/api/routes/api/operator.py +75 -0
- lightly_studio/api/routes/api/sample.py +103 -0
- lightly_studio/api/routes/api/selection.py +87 -0
- lightly_studio/api/routes/api/settings.py +41 -0
- lightly_studio/api/routes/api/status.py +19 -0
- lightly_studio/api/routes/api/text_embedding.py +50 -0
- lightly_studio/api/routes/api/validators.py +17 -0
- lightly_studio/api/routes/api/video.py +133 -0
- lightly_studio/api/routes/healthz.py +13 -0
- lightly_studio/api/routes/images.py +104 -0
- lightly_studio/api/routes/video_frames_media.py +116 -0
- lightly_studio/api/routes/video_media.py +223 -0
- lightly_studio/api/routes/webapp.py +51 -0
- lightly_studio/api/server.py +94 -0
- lightly_studio/core/__init__.py +0 -0
- lightly_studio/core/add_samples.py +533 -0
- lightly_studio/core/add_videos.py +294 -0
- lightly_studio/core/dataset.py +780 -0
- lightly_studio/core/dataset_query/__init__.py +14 -0
- lightly_studio/core/dataset_query/boolean_expression.py +67 -0
- lightly_studio/core/dataset_query/dataset_query.py +317 -0
- lightly_studio/core/dataset_query/field.py +113 -0
- lightly_studio/core/dataset_query/field_expression.py +79 -0
- lightly_studio/core/dataset_query/match_expression.py +23 -0
- lightly_studio/core/dataset_query/order_by.py +79 -0
- lightly_studio/core/dataset_query/sample_field.py +37 -0
- lightly_studio/core/dataset_query/tags_expression.py +46 -0
- lightly_studio/core/image_sample.py +36 -0
- lightly_studio/core/loading_log.py +56 -0
- lightly_studio/core/sample.py +291 -0
- lightly_studio/core/start_gui.py +54 -0
- lightly_studio/core/video_sample.py +38 -0
- lightly_studio/dataset/__init__.py +0 -0
- lightly_studio/dataset/edge_embedding_generator.py +155 -0
- lightly_studio/dataset/embedding_generator.py +129 -0
- lightly_studio/dataset/embedding_manager.py +349 -0
- lightly_studio/dataset/env.py +20 -0
- lightly_studio/dataset/file_utils.py +49 -0
- lightly_studio/dataset/fsspec_lister.py +275 -0
- lightly_studio/dataset/mobileclip_embedding_generator.py +158 -0
- lightly_studio/dataset/perception_encoder_embedding_generator.py +260 -0
- lightly_studio/db_manager.py +166 -0
- lightly_studio/dist_lightly_studio_view_app/_app/env.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/0.GcXvs2l7.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/12.Dx6SXgAb.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/17.9X9_k6TP.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/18.BxiimdIO.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/2.CkOblLn7.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/ClassifierSamplesGrid.BJbCDlvs.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/LightlyLogo.BNjCIww-.png +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Bold.DGvYQtcs.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Italic-VariableFont_wdth_wght.B4AZ-wl6.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Medium.DVUZMR_6.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Regular.DxJTClRG.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-SemiBold.D3TTYgdB.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-VariableFont_wdth_wght.BZBpG5Iz.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_layout.CefECEWA.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_layout.D5tDcjY-.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.9X9_k6TP.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.BxiimdIO.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.Dx6SXgAb.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/transform._-1mPSEI.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/0dDyq72A.js +20 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/69_IOA4Y.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BK4An2kI.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BRmB-kJ9.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/B_1cpokE.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BiqpDEr0.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BpLiSKgx.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BscxbINH.js +39 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C1FmrZbK.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C80h3dJx.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C8mfFM-u.js +2 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CGY1p9L4.js +517 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/COfLknXM.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CWj6FrbW.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CYgJF_JY.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CmLg0ys7.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CvGjimpO.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D3RDXHoj.js +39 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D4y7iiT3.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D9SC3jBb.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DCuAdx1Q.js +20 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DDBy-_jD.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DIeogL5L.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DL9a7v5o.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DSKECuqX.js +39 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D_FFv0Oe.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DiZ5o5vz.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DkbXUtyG.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DmK2hulV.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DqnHaLTj.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DtWZc_tl.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DuUalyFS.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DwIonDAZ.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/Il-mSPmK.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/KNLP4aJU.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/KjYeVjkE.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/MErlcOXj.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VRI4prUD.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VYb2dkNs.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VqWvU2yF.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/dHC3otuL.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/da7Oy_lO.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/eAy8rZzC.js +2 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/erjNR5MX.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/f1oG3eFE.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/rsLi1iKv.js +20 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/rwuuBP9f.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/xGHZQ1pe.js +3 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/entry/app.DrTRUgT3.js +2 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/entry/start.BK5EOJl2.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/0.CIvTuljF.js +4 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/1.UBvSzxdA.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/10.CQ_tiLJa.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/11.KqkAcaxW.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/12.DoYsmxQc.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/13.571n2LZA.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/14.DGs689M-.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/15.CWG1ehzT.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/16.Dpq6jbSh.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/17.B5AZbHUU.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/18.CBga8cnq.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/2.D2HXgz-8.js +1090 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/3.f4HAg-y3.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/4.BKF4xuKQ.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/5.BAE0Pm_f.js +39 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/6.CouWWpzA.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/7.UBHT0ktp.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/8.FiYNElcc.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/9.B3-UaT23.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/workers/clustering.worker-DKqeLtG0.js +2 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/workers/search.worker-vNSty3B0.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/version.json +1 -0
- lightly_studio/dist_lightly_studio_view_app/apple-touch-icon-precomposed.png +0 -0
- lightly_studio/dist_lightly_studio_view_app/apple-touch-icon.png +0 -0
- lightly_studio/dist_lightly_studio_view_app/favicon.png +0 -0
- lightly_studio/dist_lightly_studio_view_app/index.html +45 -0
- lightly_studio/errors.py +5 -0
- lightly_studio/examples/example.py +25 -0
- lightly_studio/examples/example_coco.py +27 -0
- lightly_studio/examples/example_coco_caption.py +29 -0
- lightly_studio/examples/example_metadata.py +369 -0
- lightly_studio/examples/example_operators.py +111 -0
- lightly_studio/examples/example_selection.py +28 -0
- lightly_studio/examples/example_split_work.py +48 -0
- lightly_studio/examples/example_video.py +22 -0
- lightly_studio/examples/example_video_annotations.py +157 -0
- lightly_studio/examples/example_yolo.py +22 -0
- lightly_studio/export/coco_captions.py +69 -0
- lightly_studio/export/export_dataset.py +104 -0
- lightly_studio/export/lightly_studio_label_input.py +120 -0
- lightly_studio/export_schema.py +18 -0
- lightly_studio/export_version.py +57 -0
- lightly_studio/few_shot_classifier/__init__.py +0 -0
- lightly_studio/few_shot_classifier/classifier.py +80 -0
- lightly_studio/few_shot_classifier/classifier_manager.py +644 -0
- lightly_studio/few_shot_classifier/random_forest_classifier.py +495 -0
- lightly_studio/metadata/complex_metadata.py +47 -0
- lightly_studio/metadata/compute_similarity.py +84 -0
- lightly_studio/metadata/compute_typicality.py +67 -0
- lightly_studio/metadata/gps_coordinate.py +41 -0
- lightly_studio/metadata/metadata_protocol.py +17 -0
- lightly_studio/models/__init__.py +1 -0
- lightly_studio/models/annotation/__init__.py +0 -0
- lightly_studio/models/annotation/annotation_base.py +303 -0
- lightly_studio/models/annotation/instance_segmentation.py +56 -0
- lightly_studio/models/annotation/links.py +17 -0
- lightly_studio/models/annotation/object_detection.py +47 -0
- lightly_studio/models/annotation/semantic_segmentation.py +44 -0
- lightly_studio/models/annotation_label.py +47 -0
- lightly_studio/models/caption.py +49 -0
- lightly_studio/models/classifier.py +20 -0
- lightly_studio/models/dataset.py +70 -0
- lightly_studio/models/embedding_model.py +30 -0
- lightly_studio/models/image.py +96 -0
- lightly_studio/models/metadata.py +208 -0
- lightly_studio/models/range.py +17 -0
- lightly_studio/models/sample.py +154 -0
- lightly_studio/models/sample_embedding.py +36 -0
- lightly_studio/models/settings.py +69 -0
- lightly_studio/models/tag.py +96 -0
- lightly_studio/models/two_dim_embedding.py +16 -0
- lightly_studio/models/video.py +161 -0
- lightly_studio/plugins/__init__.py +0 -0
- lightly_studio/plugins/base_operator.py +60 -0
- lightly_studio/plugins/operator_registry.py +47 -0
- lightly_studio/plugins/parameter.py +70 -0
- lightly_studio/py.typed +0 -0
- lightly_studio/resolvers/__init__.py +0 -0
- lightly_studio/resolvers/annotation_label_resolver/__init__.py +22 -0
- lightly_studio/resolvers/annotation_label_resolver/create.py +27 -0
- lightly_studio/resolvers/annotation_label_resolver/delete.py +28 -0
- lightly_studio/resolvers/annotation_label_resolver/get_all.py +37 -0
- lightly_studio/resolvers/annotation_label_resolver/get_by_id.py +24 -0
- lightly_studio/resolvers/annotation_label_resolver/get_by_ids.py +25 -0
- lightly_studio/resolvers/annotation_label_resolver/get_by_label_name.py +24 -0
- lightly_studio/resolvers/annotation_label_resolver/names_by_ids.py +25 -0
- lightly_studio/resolvers/annotation_label_resolver/update.py +38 -0
- lightly_studio/resolvers/annotation_resolver/__init__.py +40 -0
- lightly_studio/resolvers/annotation_resolver/count_annotations_by_dataset.py +129 -0
- lightly_studio/resolvers/annotation_resolver/create_many.py +124 -0
- lightly_studio/resolvers/annotation_resolver/delete_annotation.py +87 -0
- lightly_studio/resolvers/annotation_resolver/delete_annotations.py +60 -0
- lightly_studio/resolvers/annotation_resolver/get_all.py +85 -0
- lightly_studio/resolvers/annotation_resolver/get_all_with_payload.py +179 -0
- lightly_studio/resolvers/annotation_resolver/get_by_id.py +34 -0
- lightly_studio/resolvers/annotation_resolver/get_by_id_with_payload.py +130 -0
- lightly_studio/resolvers/annotation_resolver/update_annotation_label.py +142 -0
- lightly_studio/resolvers/annotation_resolver/update_bounding_box.py +68 -0
- lightly_studio/resolvers/annotations/__init__.py +1 -0
- lightly_studio/resolvers/annotations/annotations_filter.py +88 -0
- lightly_studio/resolvers/caption_resolver.py +129 -0
- lightly_studio/resolvers/dataset_resolver/__init__.py +55 -0
- lightly_studio/resolvers/dataset_resolver/check_dataset_type.py +29 -0
- lightly_studio/resolvers/dataset_resolver/create.py +20 -0
- lightly_studio/resolvers/dataset_resolver/delete.py +20 -0
- lightly_studio/resolvers/dataset_resolver/export.py +267 -0
- lightly_studio/resolvers/dataset_resolver/get_all.py +19 -0
- lightly_studio/resolvers/dataset_resolver/get_by_id.py +16 -0
- lightly_studio/resolvers/dataset_resolver/get_by_name.py +12 -0
- lightly_studio/resolvers/dataset_resolver/get_dataset_details.py +27 -0
- lightly_studio/resolvers/dataset_resolver/get_hierarchy.py +31 -0
- lightly_studio/resolvers/dataset_resolver/get_or_create_child_dataset.py +58 -0
- lightly_studio/resolvers/dataset_resolver/get_parent_dataset_by_sample_id.py +27 -0
- lightly_studio/resolvers/dataset_resolver/get_parent_dataset_id.py +22 -0
- lightly_studio/resolvers/dataset_resolver/get_root_dataset.py +61 -0
- lightly_studio/resolvers/dataset_resolver/get_root_datasets_overview.py +41 -0
- lightly_studio/resolvers/dataset_resolver/update.py +25 -0
- lightly_studio/resolvers/embedding_model_resolver.py +120 -0
- lightly_studio/resolvers/image_filter.py +50 -0
- lightly_studio/resolvers/image_resolver/__init__.py +21 -0
- lightly_studio/resolvers/image_resolver/create_many.py +52 -0
- lightly_studio/resolvers/image_resolver/delete.py +20 -0
- lightly_studio/resolvers/image_resolver/filter_new_paths.py +23 -0
- lightly_studio/resolvers/image_resolver/get_all_by_dataset_id.py +117 -0
- lightly_studio/resolvers/image_resolver/get_by_id.py +14 -0
- lightly_studio/resolvers/image_resolver/get_dimension_bounds.py +75 -0
- lightly_studio/resolvers/image_resolver/get_many_by_id.py +22 -0
- lightly_studio/resolvers/image_resolver/get_samples_excluding.py +43 -0
- lightly_studio/resolvers/metadata_resolver/__init__.py +15 -0
- lightly_studio/resolvers/metadata_resolver/metadata_filter.py +163 -0
- lightly_studio/resolvers/metadata_resolver/sample/__init__.py +21 -0
- lightly_studio/resolvers/metadata_resolver/sample/bulk_update_metadata.py +46 -0
- lightly_studio/resolvers/metadata_resolver/sample/get_by_sample_id.py +24 -0
- lightly_studio/resolvers/metadata_resolver/sample/get_metadata_info.py +104 -0
- lightly_studio/resolvers/metadata_resolver/sample/get_value_for_sample.py +27 -0
- lightly_studio/resolvers/metadata_resolver/sample/set_value_for_sample.py +53 -0
- lightly_studio/resolvers/sample_embedding_resolver.py +132 -0
- lightly_studio/resolvers/sample_resolver/__init__.py +17 -0
- lightly_studio/resolvers/sample_resolver/count_by_dataset_id.py +16 -0
- lightly_studio/resolvers/sample_resolver/create.py +16 -0
- lightly_studio/resolvers/sample_resolver/create_many.py +25 -0
- lightly_studio/resolvers/sample_resolver/get_by_id.py +14 -0
- lightly_studio/resolvers/sample_resolver/get_filtered_samples.py +56 -0
- lightly_studio/resolvers/sample_resolver/get_many_by_id.py +22 -0
- lightly_studio/resolvers/sample_resolver/sample_filter.py +74 -0
- lightly_studio/resolvers/settings_resolver.py +62 -0
- lightly_studio/resolvers/tag_resolver.py +299 -0
- lightly_studio/resolvers/twodim_embedding_resolver.py +119 -0
- lightly_studio/resolvers/video_frame_resolver/__init__.py +23 -0
- lightly_studio/resolvers/video_frame_resolver/count_video_frames_annotations.py +83 -0
- lightly_studio/resolvers/video_frame_resolver/create_many.py +57 -0
- lightly_studio/resolvers/video_frame_resolver/get_all_by_dataset_id.py +63 -0
- lightly_studio/resolvers/video_frame_resolver/get_by_id.py +13 -0
- lightly_studio/resolvers/video_frame_resolver/get_table_fields_bounds.py +44 -0
- lightly_studio/resolvers/video_frame_resolver/video_frame_annotations_counter_filter.py +47 -0
- lightly_studio/resolvers/video_frame_resolver/video_frame_filter.py +57 -0
- lightly_studio/resolvers/video_resolver/__init__.py +27 -0
- lightly_studio/resolvers/video_resolver/count_video_frame_annotations_by_video_dataset.py +86 -0
- lightly_studio/resolvers/video_resolver/create_many.py +58 -0
- lightly_studio/resolvers/video_resolver/filter_new_paths.py +33 -0
- lightly_studio/resolvers/video_resolver/get_all_by_dataset_id.py +181 -0
- lightly_studio/resolvers/video_resolver/get_by_id.py +22 -0
- lightly_studio/resolvers/video_resolver/get_table_fields_bounds.py +72 -0
- lightly_studio/resolvers/video_resolver/get_view_by_id.py +52 -0
- lightly_studio/resolvers/video_resolver/video_count_annotations_filter.py +50 -0
- lightly_studio/resolvers/video_resolver/video_filter.py +98 -0
- lightly_studio/selection/__init__.py +1 -0
- lightly_studio/selection/mundig.py +143 -0
- lightly_studio/selection/select.py +203 -0
- lightly_studio/selection/select_via_db.py +273 -0
- lightly_studio/selection/selection_config.py +49 -0
- lightly_studio/services/annotations_service/__init__.py +33 -0
- lightly_studio/services/annotations_service/create_annotation.py +64 -0
- lightly_studio/services/annotations_service/delete_annotation.py +22 -0
- lightly_studio/services/annotations_service/get_annotation_by_id.py +31 -0
- lightly_studio/services/annotations_service/update_annotation.py +54 -0
- lightly_studio/services/annotations_service/update_annotation_bounding_box.py +36 -0
- lightly_studio/services/annotations_service/update_annotation_label.py +48 -0
- lightly_studio/services/annotations_service/update_annotations.py +29 -0
- lightly_studio/setup_logging.py +59 -0
- lightly_studio/type_definitions.py +31 -0
- lightly_studio/utils/__init__.py +3 -0
- lightly_studio/utils/download.py +94 -0
- lightly_studio/vendor/__init__.py +1 -0
- lightly_studio/vendor/mobileclip/ACKNOWLEDGEMENTS +422 -0
- lightly_studio/vendor/mobileclip/LICENSE +31 -0
- lightly_studio/vendor/mobileclip/LICENSE_weights_data +50 -0
- lightly_studio/vendor/mobileclip/README.md +5 -0
- lightly_studio/vendor/mobileclip/__init__.py +96 -0
- lightly_studio/vendor/mobileclip/clip.py +77 -0
- lightly_studio/vendor/mobileclip/configs/mobileclip_b.json +18 -0
- lightly_studio/vendor/mobileclip/configs/mobileclip_s0.json +18 -0
- lightly_studio/vendor/mobileclip/configs/mobileclip_s1.json +18 -0
- lightly_studio/vendor/mobileclip/configs/mobileclip_s2.json +18 -0
- lightly_studio/vendor/mobileclip/image_encoder.py +67 -0
- lightly_studio/vendor/mobileclip/logger.py +154 -0
- lightly_studio/vendor/mobileclip/models/__init__.py +10 -0
- lightly_studio/vendor/mobileclip/models/mci.py +933 -0
- lightly_studio/vendor/mobileclip/models/vit.py +433 -0
- lightly_studio/vendor/mobileclip/modules/__init__.py +4 -0
- lightly_studio/vendor/mobileclip/modules/common/__init__.py +4 -0
- lightly_studio/vendor/mobileclip/modules/common/mobileone.py +341 -0
- lightly_studio/vendor/mobileclip/modules/common/transformer.py +451 -0
- lightly_studio/vendor/mobileclip/modules/image/__init__.py +4 -0
- lightly_studio/vendor/mobileclip/modules/image/image_projection.py +113 -0
- lightly_studio/vendor/mobileclip/modules/image/replknet.py +188 -0
- lightly_studio/vendor/mobileclip/modules/text/__init__.py +4 -0
- lightly_studio/vendor/mobileclip/modules/text/repmixer.py +281 -0
- lightly_studio/vendor/mobileclip/modules/text/tokenizer.py +38 -0
- lightly_studio/vendor/mobileclip/text_encoder.py +245 -0
- lightly_studio/vendor/perception_encoder/LICENSE.PE +201 -0
- lightly_studio/vendor/perception_encoder/README.md +11 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/__init__.py +0 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/bpe_simple_vocab_16e6.txt.gz +0 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/config.py +205 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/config_src.py +264 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/pe.py +766 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/rope.py +352 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/tokenizer.py +347 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/transforms.py +36 -0
- lightly_studio-0.4.6.dist-info/METADATA +88 -0
- lightly_studio-0.4.6.dist-info/RECORD +356 -0
- lightly_studio-0.4.6.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""Handler for database operations related to sample embeddings."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
from uuid import UUID
|
|
7
|
+
|
|
8
|
+
from sqlalchemy import String, cast, func
|
|
9
|
+
from sqlmodel import Session, col, select
|
|
10
|
+
|
|
11
|
+
from lightly_studio.models.sample import SampleTable
|
|
12
|
+
from lightly_studio.models.sample_embedding import (
|
|
13
|
+
SampleEmbeddingCreate,
|
|
14
|
+
SampleEmbeddingTable,
|
|
15
|
+
)
|
|
16
|
+
from lightly_studio.resolvers.sample_resolver.sample_filter import SampleFilter
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def create(session: Session, sample_embedding: SampleEmbeddingCreate) -> SampleEmbeddingTable:
|
|
20
|
+
"""Create a new SampleEmbedding in the database."""
|
|
21
|
+
db_sample_embedding = SampleEmbeddingTable.model_validate(sample_embedding)
|
|
22
|
+
session.add(db_sample_embedding)
|
|
23
|
+
session.commit()
|
|
24
|
+
session.refresh(db_sample_embedding)
|
|
25
|
+
return db_sample_embedding
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def create_many(session: Session, sample_embeddings: list[SampleEmbeddingCreate]) -> None:
|
|
29
|
+
"""Create many sample embeddings in a single database commit."""
|
|
30
|
+
db_sample_embeddings = [SampleEmbeddingTable.model_validate(e) for e in sample_embeddings]
|
|
31
|
+
session.bulk_save_objects(db_sample_embeddings)
|
|
32
|
+
session.commit()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_by_sample_ids(
|
|
36
|
+
session: Session,
|
|
37
|
+
sample_ids: list[UUID],
|
|
38
|
+
embedding_model_id: UUID,
|
|
39
|
+
) -> list[SampleEmbeddingTable]:
|
|
40
|
+
"""Get sample embeddings for the specified sample IDs.
|
|
41
|
+
|
|
42
|
+
Output order matches the input order.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
session: The database session.
|
|
46
|
+
sample_ids: List of sample IDs to get embeddings for.
|
|
47
|
+
embedding_model_id: The embedding model ID to filter by.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
List of sample embeddings associated with the provided IDs.
|
|
51
|
+
"""
|
|
52
|
+
string_ids = [str(id_) for id_ in sample_ids]
|
|
53
|
+
results = list(
|
|
54
|
+
session.exec(
|
|
55
|
+
select(SampleEmbeddingTable)
|
|
56
|
+
.where(cast(SampleEmbeddingTable.sample_id, String).in_(string_ids))
|
|
57
|
+
.where(SampleEmbeddingTable.embedding_model_id == embedding_model_id)
|
|
58
|
+
).all()
|
|
59
|
+
)
|
|
60
|
+
# Return embeddings in the same order as the input IDs
|
|
61
|
+
embedding_map = {embedding.sample_id: embedding for embedding in results}
|
|
62
|
+
return [embedding_map[id_] for id_ in sample_ids if id_ in embedding_map]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def get_all_by_dataset_id(
|
|
66
|
+
session: Session,
|
|
67
|
+
dataset_id: UUID,
|
|
68
|
+
embedding_model_id: UUID,
|
|
69
|
+
filters: SampleFilter | None = None,
|
|
70
|
+
) -> list[SampleEmbeddingTable]:
|
|
71
|
+
"""Get all sample embeddings for samples in a specific dataset.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
session: The database session.
|
|
75
|
+
dataset_id: The dataset ID to filter by.
|
|
76
|
+
embedding_model_id: The embedding model ID to filter by.
|
|
77
|
+
filters: Filters to apply to the samples.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
List of sample embeddings associated with the dataset.
|
|
81
|
+
"""
|
|
82
|
+
query = (
|
|
83
|
+
select(SampleEmbeddingTable)
|
|
84
|
+
.join(SampleTable, col(SampleEmbeddingTable.sample_id) == col(SampleTable.sample_id))
|
|
85
|
+
.where(SampleTable.dataset_id == dataset_id)
|
|
86
|
+
.where(SampleEmbeddingTable.embedding_model_id == embedding_model_id)
|
|
87
|
+
.order_by(col(SampleTable.created_at).asc())
|
|
88
|
+
)
|
|
89
|
+
if filters:
|
|
90
|
+
query = filters.apply(query)
|
|
91
|
+
return list(session.exec(query).all())
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def get_hash_by_sample_ids(
|
|
95
|
+
session: Session,
|
|
96
|
+
sample_ids_ordered: list[UUID],
|
|
97
|
+
embedding_model_id: UUID,
|
|
98
|
+
) -> tuple[str, list[UUID]]:
|
|
99
|
+
"""Return a combined hash and the ordered sample IDs with stored embeddings.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
session: Database session.
|
|
103
|
+
sample_ids_ordered: Sample IDs to consider, order defines deterministic hash.
|
|
104
|
+
embedding_model_id: Embedding model identifier.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
Tuple of (combined hash, ordered sample IDs that have stored embeddings).
|
|
108
|
+
"""
|
|
109
|
+
if not sample_ids_ordered:
|
|
110
|
+
return "empty", []
|
|
111
|
+
|
|
112
|
+
rows = session.exec(
|
|
113
|
+
select(
|
|
114
|
+
SampleEmbeddingTable.sample_id,
|
|
115
|
+
func.hash(SampleEmbeddingTable.embedding).label("hash_column"),
|
|
116
|
+
)
|
|
117
|
+
.where(col(SampleEmbeddingTable.sample_id).in_(set(sample_ids_ordered)))
|
|
118
|
+
.where(SampleEmbeddingTable.embedding_model_id == embedding_model_id)
|
|
119
|
+
).all()
|
|
120
|
+
|
|
121
|
+
# Mypy does not get that 'hash_column' is an attribute of the returned rows
|
|
122
|
+
sample_id_to_hash = {row.sample_id: row.hash_column for row in rows} # type: ignore[attr-defined]
|
|
123
|
+
sample_ids_of_samples_with_embeddings = [
|
|
124
|
+
sample_id for sample_id in sample_ids_ordered if sample_id in sample_id_to_hash
|
|
125
|
+
]
|
|
126
|
+
hashes_ordered = [
|
|
127
|
+
sample_id_to_hash[sample_id] for sample_id in sample_ids_of_samples_with_embeddings
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
hasher = hashlib.sha256()
|
|
131
|
+
hasher.update("".join(str(h) for h in hashes_ordered).encode("utf-8"))
|
|
132
|
+
return hasher.hexdigest(), sample_ids_of_samples_with_embeddings
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Resolvers for database operations."""
|
|
2
|
+
|
|
3
|
+
from lightly_studio.resolvers.sample_resolver.count_by_dataset_id import count_by_dataset_id
|
|
4
|
+
from lightly_studio.resolvers.sample_resolver.create import create
|
|
5
|
+
from lightly_studio.resolvers.sample_resolver.create_many import create_many
|
|
6
|
+
from lightly_studio.resolvers.sample_resolver.get_by_id import get_by_id
|
|
7
|
+
from lightly_studio.resolvers.sample_resolver.get_filtered_samples import get_filtered_samples
|
|
8
|
+
from lightly_studio.resolvers.sample_resolver.get_many_by_id import get_many_by_id
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"count_by_dataset_id",
|
|
12
|
+
"create",
|
|
13
|
+
"create_many",
|
|
14
|
+
"get_by_id",
|
|
15
|
+
"get_filtered_samples",
|
|
16
|
+
"get_many_by_id",
|
|
17
|
+
]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Implementation of count_by_dataset_id for sample resolver."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
from sqlmodel import Session, func, select
|
|
8
|
+
|
|
9
|
+
from lightly_studio.models.sample import SampleTable
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def count_by_dataset_id(session: Session, dataset_id: UUID) -> int:
|
|
13
|
+
"""Count the number of samples in a dataset."""
|
|
14
|
+
return session.exec(
|
|
15
|
+
select(func.count()).select_from(SampleTable).where(SampleTable.dataset_id == dataset_id)
|
|
16
|
+
).one()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Implementation of create for sample resolver."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from sqlmodel import Session
|
|
6
|
+
|
|
7
|
+
from lightly_studio.models.sample import SampleCreate, SampleTable
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def create(session: Session, sample: SampleCreate) -> SampleTable:
|
|
11
|
+
"""Create a new sample in the database."""
|
|
12
|
+
db_sample = SampleTable.model_validate(sample)
|
|
13
|
+
session.add(db_sample)
|
|
14
|
+
session.commit()
|
|
15
|
+
session.refresh(db_sample)
|
|
16
|
+
return db_sample
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Implementation of create_many for sample resolver."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from uuid import UUID
|
|
7
|
+
|
|
8
|
+
from sqlalchemy import ScalarResult
|
|
9
|
+
from sqlmodel import Session, col, insert
|
|
10
|
+
|
|
11
|
+
from lightly_studio.models.sample import SampleCreate, SampleTable
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def create_many(session: Session, samples: Sequence[SampleCreate]) -> list[UUID]:
|
|
15
|
+
"""Create multiple samples in a single database commit."""
|
|
16
|
+
if not samples:
|
|
17
|
+
return []
|
|
18
|
+
# Note: We are using bulk insert for SampleTable to get sample_ids efficiently.
|
|
19
|
+
statement = (
|
|
20
|
+
insert(SampleTable)
|
|
21
|
+
.values([sample.model_dump() for sample in samples])
|
|
22
|
+
.returning(col(SampleTable.sample_id))
|
|
23
|
+
)
|
|
24
|
+
sample_ids: ScalarResult[UUID] = session.execute(statement).scalars()
|
|
25
|
+
return list(sample_ids)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Implementation of get_by_id for sample resolver."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
from sqlmodel import Session, select
|
|
8
|
+
|
|
9
|
+
from lightly_studio.models.sample import SampleTable
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_by_id(session: Session, sample_id: UUID) -> SampleTable | None:
|
|
13
|
+
"""Retrieve a single sample by ID."""
|
|
14
|
+
return session.exec(select(SampleTable).where(SampleTable.sample_id == sample_id)).one_or_none()
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Implementation of get_filtered_samples resolver function."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
from sqlmodel import Session, col, func, select
|
|
9
|
+
|
|
10
|
+
from lightly_studio.api.routes.api.validators import Paginated
|
|
11
|
+
from lightly_studio.models.sample import SampleTable
|
|
12
|
+
from lightly_studio.resolvers.sample_resolver.sample_filter import SampleFilter
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SamplesWithCount(BaseModel):
|
|
16
|
+
"""Result of getting all samples."""
|
|
17
|
+
|
|
18
|
+
samples: Sequence[SampleTable]
|
|
19
|
+
total_count: int
|
|
20
|
+
next_cursor: int | None = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_filtered_samples(
|
|
24
|
+
session: Session,
|
|
25
|
+
filters: SampleFilter | None = None,
|
|
26
|
+
pagination: Paginated | None = None,
|
|
27
|
+
) -> SamplesWithCount:
|
|
28
|
+
"""Retrieve samples for a specific dataset with optional filtering."""
|
|
29
|
+
samples_query = select(SampleTable)
|
|
30
|
+
total_count_query = select(func.count()).select_from(SampleTable)
|
|
31
|
+
|
|
32
|
+
if filters is not None:
|
|
33
|
+
samples_query = filters.apply(samples_query)
|
|
34
|
+
total_count_query = filters.apply(total_count_query)
|
|
35
|
+
|
|
36
|
+
# Apply default ordering
|
|
37
|
+
samples_query = samples_query.order_by(
|
|
38
|
+
col(SampleTable.created_at).asc(),
|
|
39
|
+
col(SampleTable.sample_id).asc(),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Apply pagination if provided
|
|
43
|
+
if pagination is not None:
|
|
44
|
+
samples_query = samples_query.offset(pagination.offset).limit(pagination.limit)
|
|
45
|
+
|
|
46
|
+
total_count = session.exec(total_count_query).one()
|
|
47
|
+
|
|
48
|
+
next_cursor = None
|
|
49
|
+
if pagination is not None and pagination.offset + pagination.limit < total_count:
|
|
50
|
+
next_cursor = pagination.offset + pagination.limit
|
|
51
|
+
|
|
52
|
+
return SamplesWithCount(
|
|
53
|
+
samples=session.exec(samples_query).all(),
|
|
54
|
+
total_count=total_count,
|
|
55
|
+
next_cursor=next_cursor,
|
|
56
|
+
)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Implementation of get_many_by_id for sample resolver."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
from sqlmodel import Session, col, select
|
|
8
|
+
|
|
9
|
+
from lightly_studio.models.sample import SampleTable
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_many_by_id(session: Session, sample_ids: list[UUID]) -> list[SampleTable]:
|
|
13
|
+
"""Retrieve multiple samples by their IDs.
|
|
14
|
+
|
|
15
|
+
Output order matches the input order.
|
|
16
|
+
"""
|
|
17
|
+
results = session.exec(
|
|
18
|
+
select(SampleTable).where(col(SampleTable.sample_id).in_(sample_ids))
|
|
19
|
+
).all()
|
|
20
|
+
# Return samples in the same order as the input IDs
|
|
21
|
+
sample_map = {sample.sample_id: sample for sample in results}
|
|
22
|
+
return [sample_map[id_] for id_ in sample_ids if id_ in sample_map]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""SampleFilter class."""
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
from sqlmodel import col, select
|
|
8
|
+
|
|
9
|
+
from lightly_studio.models.annotation.annotation_base import AnnotationBaseTable
|
|
10
|
+
from lightly_studio.models.annotation_label import AnnotationLabelTable
|
|
11
|
+
from lightly_studio.models.metadata import SampleMetadataTable
|
|
12
|
+
from lightly_studio.models.sample import SampleTable
|
|
13
|
+
from lightly_studio.models.tag import TagTable
|
|
14
|
+
from lightly_studio.resolvers.metadata_resolver import metadata_filter
|
|
15
|
+
from lightly_studio.resolvers.metadata_resolver.metadata_filter import MetadataFilter
|
|
16
|
+
from lightly_studio.type_definitions import QueryType
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SampleFilter(BaseModel):
|
|
20
|
+
"""Encapsulates filter parameters for querying samples."""
|
|
21
|
+
|
|
22
|
+
dataset_id: Optional[UUID] = None
|
|
23
|
+
annotation_label_ids: Optional[List[UUID]] = None
|
|
24
|
+
tag_ids: Optional[List[UUID]] = None
|
|
25
|
+
metadata_filters: Optional[List[MetadataFilter]] = None
|
|
26
|
+
sample_ids: Optional[List[UUID]] = None
|
|
27
|
+
has_captions: Optional[bool] = None
|
|
28
|
+
|
|
29
|
+
def apply(self, query: QueryType) -> QueryType:
|
|
30
|
+
"""Apply the filters to the given query."""
|
|
31
|
+
if self.dataset_id:
|
|
32
|
+
query = query.where(col(SampleTable.dataset_id) == self.dataset_id)
|
|
33
|
+
|
|
34
|
+
if self.sample_ids:
|
|
35
|
+
query = query.where(col(SampleTable.sample_id).in_(self.sample_ids))
|
|
36
|
+
|
|
37
|
+
# Apply annotation label filters to the query.
|
|
38
|
+
if self.annotation_label_ids:
|
|
39
|
+
sample_ids_subquery = (
|
|
40
|
+
select(AnnotationBaseTable.parent_sample_id)
|
|
41
|
+
.select_from(AnnotationBaseTable)
|
|
42
|
+
.join(AnnotationBaseTable.annotation_label)
|
|
43
|
+
.where(col(AnnotationLabelTable.annotation_label_id).in_(self.annotation_label_ids))
|
|
44
|
+
.distinct()
|
|
45
|
+
)
|
|
46
|
+
query = query.where(col(SampleTable.sample_id).in_(sample_ids_subquery))
|
|
47
|
+
|
|
48
|
+
# Apply tag filters to the query.
|
|
49
|
+
if self.tag_ids:
|
|
50
|
+
sample_ids_subquery = (
|
|
51
|
+
select(SampleTable.sample_id)
|
|
52
|
+
.join(SampleTable.tags)
|
|
53
|
+
.where(col(TagTable.tag_id).in_(self.tag_ids))
|
|
54
|
+
.distinct()
|
|
55
|
+
)
|
|
56
|
+
query = query.where(col(SampleTable.sample_id).in_(sample_ids_subquery))
|
|
57
|
+
|
|
58
|
+
# Apply metadata filters to the query.
|
|
59
|
+
if self.metadata_filters:
|
|
60
|
+
query = metadata_filter.apply_metadata_filters(
|
|
61
|
+
query,
|
|
62
|
+
self.metadata_filters,
|
|
63
|
+
metadata_model=SampleMetadataTable,
|
|
64
|
+
metadata_join_condition=SampleMetadataTable.sample_id == SampleTable.sample_id,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Apply caption presence filter to the query.
|
|
68
|
+
if self.has_captions is not None:
|
|
69
|
+
if self.has_captions:
|
|
70
|
+
query = query.where(col(SampleTable.captions).any())
|
|
71
|
+
else:
|
|
72
|
+
query = query.where(~col(SampleTable.captions).any())
|
|
73
|
+
|
|
74
|
+
return query
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""This module contains the resolvers for user settings."""
|
|
2
|
+
|
|
3
|
+
from sqlmodel import Session, select
|
|
4
|
+
|
|
5
|
+
from lightly_studio.models.settings import SettingTable, SettingView
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_settings(session: Session) -> SettingView:
|
|
9
|
+
"""Get current settings.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
session: Database session.
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
The current settings.
|
|
16
|
+
"""
|
|
17
|
+
statement = select(SettingTable)
|
|
18
|
+
result = session.exec(statement).first()
|
|
19
|
+
|
|
20
|
+
# If no settings exist, create default settings
|
|
21
|
+
if result is None:
|
|
22
|
+
result = SettingTable()
|
|
23
|
+
session.add(result)
|
|
24
|
+
session.commit()
|
|
25
|
+
session.refresh(result)
|
|
26
|
+
|
|
27
|
+
return SettingView.model_validate(result)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def set_settings(session: Session, settings: SettingView) -> SettingView:
|
|
31
|
+
"""Update settings.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
session: Database session.
|
|
35
|
+
settings: New settings to apply.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Updated settings.
|
|
39
|
+
"""
|
|
40
|
+
current_settings = session.exec(select(SettingTable)).first()
|
|
41
|
+
if current_settings is None:
|
|
42
|
+
current_settings = SettingTable()
|
|
43
|
+
session.add(current_settings)
|
|
44
|
+
|
|
45
|
+
# Update grid view sample rendering
|
|
46
|
+
current_settings.grid_view_sample_rendering = settings.grid_view_sample_rendering
|
|
47
|
+
|
|
48
|
+
# Update keyboard shortcut mapping
|
|
49
|
+
current_settings.key_hide_annotations = settings.key_hide_annotations
|
|
50
|
+
current_settings.key_go_back = settings.key_go_back
|
|
51
|
+
current_settings.key_toggle_edit_mode = settings.key_toggle_edit_mode
|
|
52
|
+
|
|
53
|
+
# Update show annotation text labels
|
|
54
|
+
current_settings.show_annotation_text_labels = settings.show_annotation_text_labels
|
|
55
|
+
|
|
56
|
+
# Update sample filename visibility
|
|
57
|
+
current_settings.show_sample_filenames = settings.show_sample_filenames
|
|
58
|
+
|
|
59
|
+
session.commit()
|
|
60
|
+
session.refresh(current_settings)
|
|
61
|
+
|
|
62
|
+
return SettingView.model_validate(current_settings)
|