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,50 @@
|
|
|
1
|
+
"""Utility functions for building database queries."""
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
from sqlmodel import col, select
|
|
7
|
+
|
|
8
|
+
from lightly_studio.models.annotation.annotation_base import AnnotationBaseTable
|
|
9
|
+
from lightly_studio.models.annotation_label import AnnotationLabelTable
|
|
10
|
+
from lightly_studio.models.video import VideoFrameTable, VideoTable
|
|
11
|
+
from lightly_studio.resolvers.video_resolver.video_filter import VideoFilter
|
|
12
|
+
from lightly_studio.type_definitions import QueryType
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class VideoCountAnnotationsFilter(BaseModel):
|
|
16
|
+
"""Encapsulates filter parameters for querying video frame annotations counter."""
|
|
17
|
+
|
|
18
|
+
video_filter: Optional[VideoFilter] = None
|
|
19
|
+
video_frames_annotations_labels: Optional[List[str]] = None
|
|
20
|
+
|
|
21
|
+
def apply(self, query: QueryType) -> QueryType:
|
|
22
|
+
"""Apply the filters to the given query."""
|
|
23
|
+
query = self._apply_annotations_label(query)
|
|
24
|
+
|
|
25
|
+
if self.video_filter:
|
|
26
|
+
query = self.video_filter.apply(query)
|
|
27
|
+
|
|
28
|
+
return query
|
|
29
|
+
|
|
30
|
+
def _apply_annotations_label(self, query: QueryType) -> QueryType:
|
|
31
|
+
if not self.video_frames_annotations_labels:
|
|
32
|
+
return query
|
|
33
|
+
|
|
34
|
+
frame_filtered_video_ids_subquery = (
|
|
35
|
+
select(VideoTable.sample_id)
|
|
36
|
+
.join(VideoTable.frames)
|
|
37
|
+
.join(
|
|
38
|
+
AnnotationBaseTable,
|
|
39
|
+
col(AnnotationBaseTable.parent_sample_id) == VideoFrameTable.sample_id,
|
|
40
|
+
)
|
|
41
|
+
.join(AnnotationBaseTable.annotation_label)
|
|
42
|
+
.where(
|
|
43
|
+
col(AnnotationLabelTable.annotation_label_name).in_(
|
|
44
|
+
self.video_frames_annotations_labels or []
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
.distinct()
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
return query.where(col(VideoTable.sample_id).in_(frame_filtered_video_ids_subquery))
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Utility functions for building database queries."""
|
|
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.range import FloatRange
|
|
11
|
+
from lightly_studio.models.video import VideoFrameTable, VideoTable
|
|
12
|
+
from lightly_studio.resolvers.image_filter import FilterDimensions
|
|
13
|
+
from lightly_studio.resolvers.sample_resolver.sample_filter import SampleFilter
|
|
14
|
+
from lightly_studio.type_definitions import QueryType
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class VideoFilter(BaseModel):
|
|
18
|
+
"""Encapsulates filter parameters for querying videos."""
|
|
19
|
+
|
|
20
|
+
width: Optional[FilterDimensions] = None
|
|
21
|
+
height: Optional[FilterDimensions] = None
|
|
22
|
+
fps: Optional[FloatRange] = None
|
|
23
|
+
duration_s: Optional[FloatRange] = None
|
|
24
|
+
annotation_frames_label_ids: Optional[List[UUID]] = None
|
|
25
|
+
sample_filter: Optional[SampleFilter] = None
|
|
26
|
+
|
|
27
|
+
def apply(self, query: QueryType) -> QueryType:
|
|
28
|
+
"""Apply the filters to the given query."""
|
|
29
|
+
query = self._apply_width_and_height_filters(query)
|
|
30
|
+
query = self._apply_fps_filters(query)
|
|
31
|
+
query = self._apply_duration_filters(query)
|
|
32
|
+
|
|
33
|
+
if self.annotation_frames_label_ids:
|
|
34
|
+
query = self._apply_annotations_ids(query)
|
|
35
|
+
if self.sample_filter:
|
|
36
|
+
query = self.sample_filter.apply(query)
|
|
37
|
+
|
|
38
|
+
return query
|
|
39
|
+
|
|
40
|
+
def _apply_width_and_height_filters(self, query: QueryType) -> QueryType:
|
|
41
|
+
if self.width:
|
|
42
|
+
if self.width.min is not None:
|
|
43
|
+
query = query.where(VideoTable.width >= self.width.min)
|
|
44
|
+
if self.width.max is not None:
|
|
45
|
+
query = query.where(VideoTable.width <= self.width.max)
|
|
46
|
+
if self.height:
|
|
47
|
+
if self.height.min is not None:
|
|
48
|
+
query = query.where(VideoTable.height >= self.height.min)
|
|
49
|
+
if self.height.max is not None:
|
|
50
|
+
query = query.where(VideoTable.height <= self.height.max)
|
|
51
|
+
return query
|
|
52
|
+
|
|
53
|
+
def _apply_fps_filters(self, query: QueryType) -> QueryType:
|
|
54
|
+
min_fps = self.fps.min if self.fps and self.fps.min is not None else None
|
|
55
|
+
max_fps = self.fps.max if self.fps and self.fps.max is not None else None
|
|
56
|
+
|
|
57
|
+
if min_fps is not None:
|
|
58
|
+
query = query.where(VideoTable.fps >= min_fps)
|
|
59
|
+
|
|
60
|
+
if max_fps is not None:
|
|
61
|
+
query = query.where(VideoTable.fps <= max_fps)
|
|
62
|
+
|
|
63
|
+
return query
|
|
64
|
+
|
|
65
|
+
def _apply_duration_filters(self, query: QueryType) -> QueryType:
|
|
66
|
+
min_duration_s = (
|
|
67
|
+
self.duration_s.min if self.duration_s and self.duration_s.min is not None else None
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
max_duration_s = (
|
|
71
|
+
self.duration_s.max if self.duration_s and self.duration_s.max is not None else None
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
if min_duration_s is not None:
|
|
75
|
+
query = query.where(col(VideoTable.duration_s) >= min_duration_s)
|
|
76
|
+
|
|
77
|
+
if max_duration_s is not None:
|
|
78
|
+
query = query.where(col(VideoTable.duration_s) <= max_duration_s)
|
|
79
|
+
|
|
80
|
+
return query
|
|
81
|
+
|
|
82
|
+
def _apply_annotations_ids(self, query: QueryType) -> QueryType:
|
|
83
|
+
frame_filtered_video_ids_subquery = (
|
|
84
|
+
select(VideoTable.sample_id)
|
|
85
|
+
.join(VideoTable.frames)
|
|
86
|
+
.join(
|
|
87
|
+
AnnotationBaseTable,
|
|
88
|
+
col(AnnotationBaseTable.parent_sample_id) == VideoFrameTable.sample_id,
|
|
89
|
+
)
|
|
90
|
+
.where(
|
|
91
|
+
col(AnnotationBaseTable.annotation_label_id).in_(
|
|
92
|
+
self.annotation_frames_label_ids or []
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
.distinct()
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
return query.where(col(VideoTable.sample_id).in_(frame_filtered_video_ids_subquery))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Selection package."""
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"""Python interface to the Mundig selection algorithm."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Iterable
|
|
6
|
+
|
|
7
|
+
# TODO(Malte, 08/2025): About the type ignore:
|
|
8
|
+
# Use pyo3 typing stubs once they are implemented.
|
|
9
|
+
# See https://github.com/PyO3/pyo3/issues/510
|
|
10
|
+
# Or remove the type ignore once typing stubs were added manually.
|
|
11
|
+
import lightly_mundig # type: ignore[import-untyped]
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
from lightly_studio.dataset.env import LIGHTLY_STUDIO_LICENSE_KEY
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Mundig:
|
|
18
|
+
"""Python interface for the Mundig selection algorithm.
|
|
19
|
+
|
|
20
|
+
This class provides a Python interface to the lightly_mundig Rust library
|
|
21
|
+
for sample selection. It allows combining different selection strategies
|
|
22
|
+
such as diversity and weighting.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self) -> None:
|
|
26
|
+
"""Initialize the Mundig selection interface."""
|
|
27
|
+
if LIGHTLY_STUDIO_LICENSE_KEY is None:
|
|
28
|
+
raise ValueError(
|
|
29
|
+
"LIGHTLY_STUDIO_LICENSE_KEY environment variable is not set. "
|
|
30
|
+
"Please set it to your LightlyStudio license key."
|
|
31
|
+
)
|
|
32
|
+
self.mundig = lightly_mundig.Selection(token=LIGHTLY_STUDIO_LICENSE_KEY)
|
|
33
|
+
|
|
34
|
+
self.n_input_samples: int | None = None
|
|
35
|
+
|
|
36
|
+
def run(self, n_samples: int) -> list[int]:
|
|
37
|
+
"""Run the selection algorithm and return selected sample indices.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
n_samples: The number of samples to select.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
A list of indices of the selected samples.
|
|
44
|
+
"""
|
|
45
|
+
selected: list[int] = self.mundig.run_selection(
|
|
46
|
+
n_total_samples=self.n_input_samples, n_samples_to_select=n_samples
|
|
47
|
+
)
|
|
48
|
+
return selected
|
|
49
|
+
|
|
50
|
+
def add_diversity(self, embeddings: Iterable[Iterable[float]], strength: float = 1.0) -> None:
|
|
51
|
+
"""Add diversity-based selection using sample embeddings.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
embeddings:
|
|
55
|
+
The embeddings of each sample.
|
|
56
|
+
First dimension is over the samples, the second dimension is
|
|
57
|
+
the embedding size. The embedding size must be the same for
|
|
58
|
+
all samples.
|
|
59
|
+
strength:
|
|
60
|
+
The strength of the diversity strategy.
|
|
61
|
+
|
|
62
|
+
"""
|
|
63
|
+
# Convert to ndarray with float32 dtype if not already
|
|
64
|
+
if isinstance(embeddings, np.ndarray) and embeddings.dtype == np.float32:
|
|
65
|
+
embeddings_ndarray = embeddings
|
|
66
|
+
else:
|
|
67
|
+
embeddings_ndarray = np.array(embeddings, dtype=np.float32)
|
|
68
|
+
self._check_consistent_input_size(embeddings_ndarray.shape[0])
|
|
69
|
+
self.mundig.add_diversifying_strategy(embeddings=embeddings_ndarray, strength=strength)
|
|
70
|
+
|
|
71
|
+
def add_weighting(self, weights: Iterable[float], strength: float = 1.0) -> None:
|
|
72
|
+
"""Add a weighting strategy.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
weights:
|
|
76
|
+
The weight or importance or utility of each sample.
|
|
77
|
+
strength:
|
|
78
|
+
The strength of the weighting strategy.
|
|
79
|
+
"""
|
|
80
|
+
weights_ndarray = np.array(weights, dtype=np.float32)
|
|
81
|
+
self._check_consistent_input_size(weights_ndarray.shape[0])
|
|
82
|
+
self.mundig.add_weighting_strategy(weights=weights_ndarray, strength=strength)
|
|
83
|
+
|
|
84
|
+
def add_class_balancing(
|
|
85
|
+
self,
|
|
86
|
+
class_distributions: Iterable[Iterable[float]],
|
|
87
|
+
target: Iterable[float],
|
|
88
|
+
strength: float = 1.0,
|
|
89
|
+
) -> None:
|
|
90
|
+
"""Add a class balancing strategy.
|
|
91
|
+
|
|
92
|
+
This strategy aims to select a subset of samples such that the
|
|
93
|
+
distribution of classes in the subset is close to the target
|
|
94
|
+
distribution.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
class_distributions:
|
|
98
|
+
First dimension is over all samples, second one is the distribution per sample over
|
|
99
|
+
the classes.
|
|
100
|
+
target:
|
|
101
|
+
The desired target distribution for the classes in the selected subset of samples.
|
|
102
|
+
The length of the target must match the number of classes in the class
|
|
103
|
+
distributions.
|
|
104
|
+
strength:
|
|
105
|
+
The strength of the balancing strategy.
|
|
106
|
+
"""
|
|
107
|
+
# Convert to ndarray with float32 dtype if not already
|
|
108
|
+
if isinstance(class_distributions, np.ndarray) and class_distributions.dtype == np.float32:
|
|
109
|
+
class_distributions_nparray = class_distributions
|
|
110
|
+
else:
|
|
111
|
+
class_distributions_nparray = np.array(class_distributions, dtype=np.float32)
|
|
112
|
+
self._check_consistent_input_size(class_distributions_nparray.shape[0])
|
|
113
|
+
target_nparray = np.array(target, dtype=np.float32)
|
|
114
|
+
if class_distributions_nparray.shape[1] != target_nparray.shape[0]:
|
|
115
|
+
raise ValueError(
|
|
116
|
+
f"The length of 'target' {target_nparray.shape[0]} doesn't match the width of "
|
|
117
|
+
f"'class_distributions': {class_distributions_nparray.shape[0]}"
|
|
118
|
+
)
|
|
119
|
+
self.mundig.add_balancing_strategy(
|
|
120
|
+
class_distributions=class_distributions_nparray,
|
|
121
|
+
target=target_nparray,
|
|
122
|
+
strength=strength,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
def _check_consistent_input_size(self, n_input_samples_strategy: int) -> None:
|
|
126
|
+
"""Assert that input samples count is consistent across strategies.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
n_input_samples_strategy:
|
|
130
|
+
The number of input samples in the currently added strategy.
|
|
131
|
+
|
|
132
|
+
Raises:
|
|
133
|
+
ValueError:
|
|
134
|
+
If the number of input samples in the new strategy differs
|
|
135
|
+
from the one used in previous strategies.
|
|
136
|
+
"""
|
|
137
|
+
if self.n_input_samples is None:
|
|
138
|
+
self.n_input_samples = n_input_samples_strategy
|
|
139
|
+
elif self.n_input_samples != n_input_samples_strategy:
|
|
140
|
+
raise ValueError(
|
|
141
|
+
f"Expected {self.n_input_samples} input samples, "
|
|
142
|
+
f"but the latest strategy passed {n_input_samples_strategy}."
|
|
143
|
+
)
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""Provides the user python interface to selection bound to sample ids."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterable
|
|
6
|
+
from typing import Final, Literal
|
|
7
|
+
from uuid import UUID
|
|
8
|
+
|
|
9
|
+
from sqlmodel import Session
|
|
10
|
+
|
|
11
|
+
from lightly_studio.selection.select_via_db import select_via_database
|
|
12
|
+
from lightly_studio.selection.selection_config import (
|
|
13
|
+
AnnotationClassBalancingStrategy,
|
|
14
|
+
AnnotationClassToTarget,
|
|
15
|
+
EmbeddingDiversityStrategy,
|
|
16
|
+
MetadataWeightingStrategy,
|
|
17
|
+
SelectionConfig,
|
|
18
|
+
SelectionStrategy,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Selection:
|
|
23
|
+
"""Smart selection interface.
|
|
24
|
+
|
|
25
|
+
The `Selection` class allows to select a subset of samples from a given set of input
|
|
26
|
+
samples. There are many different strategies to select samples, e.g. diversity based
|
|
27
|
+
on embeddings or weighting based on numeric metadata. Multiple strategies can be
|
|
28
|
+
combined to form more complex selection strategies.
|
|
29
|
+
|
|
30
|
+
The result of a selection is stored as a tag on the selected samples in the database.
|
|
31
|
+
The `selection_result_tag_name` must be a unique tag name that is not used yet.
|
|
32
|
+
|
|
33
|
+
# Creation of a Selection instance.
|
|
34
|
+
|
|
35
|
+
Creation of an instance of this is easiest via the `DatasetQuery` class. By using
|
|
36
|
+
a `match()` first, the samples to select from can be filtered down.
|
|
37
|
+
```python
|
|
38
|
+
from lightly_studio.core.dataset_query import SampleField
|
|
39
|
+
|
|
40
|
+
# Select from all samples in the dataset.
|
|
41
|
+
selection = dataset.query().selection()
|
|
42
|
+
|
|
43
|
+
# Select only from samples with width < 256.
|
|
44
|
+
query_narrow_images = dataset.query().match(SampleField.width < 256)
|
|
45
|
+
selection_among_narrow_images = query_narrow_images.selection()
|
|
46
|
+
```
|
|
47
|
+
See the `DatasetQuery.match()` documentation for more information on filtering.
|
|
48
|
+
By creating the `Selection` instance, the query is executed. Further changes to the
|
|
49
|
+
query do not affect the selection instance.
|
|
50
|
+
|
|
51
|
+
# Performing single-strategy selections.
|
|
52
|
+
|
|
53
|
+
Once a `Selection` instance is created, different selection strategies can be
|
|
54
|
+
applied to select samples. Single-strategy selections are performed by calling
|
|
55
|
+
the respective method on the `Selection` instance. All methods take the number of
|
|
56
|
+
samples to select and a tag name for the selection result as mandatory arguments.
|
|
57
|
+
```python
|
|
58
|
+
# Select 100 diverse samples based on embeddings
|
|
59
|
+
selection.diverse(
|
|
60
|
+
n_samples_to_select=100,
|
|
61
|
+
selection_result_tag_name="diverse selection",
|
|
62
|
+
)
|
|
63
|
+
# Select 50 samples weighted by numeric metadata "difficulty"
|
|
64
|
+
selection.metadata_weighting(
|
|
65
|
+
n_samples_to_select=50,
|
|
66
|
+
selection_result_tag_name="weighted selection",
|
|
67
|
+
metadata_key="difficulty",
|
|
68
|
+
)
|
|
69
|
+
# Select 100 samples with balanced annotation classes (e.g. uniform distribution)
|
|
70
|
+
selection.annotation_balancing(
|
|
71
|
+
n_samples_to_select=100,
|
|
72
|
+
selection_result_tag_name="balanced selection",
|
|
73
|
+
target_distribution="uniform",
|
|
74
|
+
)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
# Performing multi-strategy selections.
|
|
78
|
+
|
|
79
|
+
More complex selection strategies can be formed by combining multiple selection
|
|
80
|
+
strategies. This is done via the `multi_strategies()` method, which takes a
|
|
81
|
+
list of selection strategies as an argument.
|
|
82
|
+
```python
|
|
83
|
+
from lightly_studio.selection.selection_config import (
|
|
84
|
+
EmbeddingDiversityStrategy,
|
|
85
|
+
MetadataWeightingStrategy
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Select 75 samples that are diverse and weighted by "difficulty"
|
|
89
|
+
selection.multi_strategies(
|
|
90
|
+
n_samples_to_select=75,
|
|
91
|
+
selection_result_tag_name="diverse and weighted selection",
|
|
92
|
+
selection_strategies=[
|
|
93
|
+
EmbeddingDiversityStrategy(),
|
|
94
|
+
MetadataWeightingStrategy(metadata_key="difficulty"),
|
|
95
|
+
],
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
def __init__(
|
|
101
|
+
self,
|
|
102
|
+
dataset_id: UUID,
|
|
103
|
+
session: Session,
|
|
104
|
+
input_sample_ids: Iterable[UUID],
|
|
105
|
+
) -> None:
|
|
106
|
+
"""Create the selection interface.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
dataset_id: Dataset in which the selection is performed.
|
|
110
|
+
session: Database session to resolve selection dependencies.
|
|
111
|
+
input_sample_ids: Candidate sample ids considered for selection.
|
|
112
|
+
The iterable is consumed immediately to capture a stable snapshot.
|
|
113
|
+
"""
|
|
114
|
+
self._dataset_id: Final[UUID] = dataset_id
|
|
115
|
+
self._session: Final[Session] = session
|
|
116
|
+
self._input_sample_ids: list[UUID] = list(input_sample_ids)
|
|
117
|
+
|
|
118
|
+
def metadata_weighting(
|
|
119
|
+
self,
|
|
120
|
+
n_samples_to_select: int,
|
|
121
|
+
selection_result_tag_name: str,
|
|
122
|
+
metadata_key: str,
|
|
123
|
+
) -> None:
|
|
124
|
+
"""Select a subset based on numeric metadata weights.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
n_samples_to_select: Number of samples to select.
|
|
128
|
+
selection_result_tag_name: Tag name for the selection result.
|
|
129
|
+
metadata_key: Metadata key used as weights (float or int values).
|
|
130
|
+
"""
|
|
131
|
+
strategy = MetadataWeightingStrategy(metadata_key=metadata_key)
|
|
132
|
+
self.multi_strategies(
|
|
133
|
+
n_samples_to_select=n_samples_to_select,
|
|
134
|
+
selection_result_tag_name=selection_result_tag_name,
|
|
135
|
+
selection_strategies=[strategy],
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
def diverse(
|
|
139
|
+
self,
|
|
140
|
+
n_samples_to_select: int,
|
|
141
|
+
selection_result_tag_name: str,
|
|
142
|
+
embedding_model_name: str | None = None,
|
|
143
|
+
) -> None:
|
|
144
|
+
"""Select a diverse subset using embeddings.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
n_samples_to_select: Number of samples to select.
|
|
148
|
+
selection_result_tag_name: Tag name for the selection result.
|
|
149
|
+
embedding_model_name: Optional embedding model name. If None, uses the only
|
|
150
|
+
available model or raises if multiple exist.
|
|
151
|
+
"""
|
|
152
|
+
strategy = EmbeddingDiversityStrategy(embedding_model_name=embedding_model_name)
|
|
153
|
+
self.multi_strategies(
|
|
154
|
+
n_samples_to_select=n_samples_to_select,
|
|
155
|
+
selection_result_tag_name=selection_result_tag_name,
|
|
156
|
+
selection_strategies=[strategy],
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def annotation_balancing(
|
|
160
|
+
self,
|
|
161
|
+
n_samples_to_select: int,
|
|
162
|
+
selection_result_tag_name: str,
|
|
163
|
+
target_distribution: AnnotationClassToTarget | Literal["uniform"] | Literal["input"],
|
|
164
|
+
) -> None:
|
|
165
|
+
"""Select a subset using annotation class balancing.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
n_samples_to_select: Number of samples to select.
|
|
169
|
+
selection_result_tag_name: Tag name for the selection result.
|
|
170
|
+
target_distribution: Can be 'uniform', 'input',
|
|
171
|
+
or a dictionary mapping class names to target ratios.
|
|
172
|
+
"""
|
|
173
|
+
strategy = AnnotationClassBalancingStrategy(target_distribution=target_distribution)
|
|
174
|
+
self.multi_strategies(
|
|
175
|
+
n_samples_to_select=n_samples_to_select,
|
|
176
|
+
selection_result_tag_name=selection_result_tag_name,
|
|
177
|
+
selection_strategies=[strategy],
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
def multi_strategies(
|
|
181
|
+
self,
|
|
182
|
+
n_samples_to_select: int,
|
|
183
|
+
selection_result_tag_name: str,
|
|
184
|
+
selection_strategies: list[SelectionStrategy],
|
|
185
|
+
) -> None:
|
|
186
|
+
"""Select a subset based on multiple strategies.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
n_samples_to_select: Number of samples to select.
|
|
190
|
+
selection_result_tag_name: Tag name for the selection result.
|
|
191
|
+
selection_strategies: Strategies to compose for selection.
|
|
192
|
+
"""
|
|
193
|
+
config = SelectionConfig(
|
|
194
|
+
dataset_id=self._dataset_id,
|
|
195
|
+
n_samples_to_select=n_samples_to_select,
|
|
196
|
+
selection_result_tag_name=selection_result_tag_name,
|
|
197
|
+
strategies=selection_strategies,
|
|
198
|
+
)
|
|
199
|
+
select_via_database(
|
|
200
|
+
session=self._session,
|
|
201
|
+
config=config,
|
|
202
|
+
input_sample_ids=self._input_sample_ids,
|
|
203
|
+
)
|