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.
Files changed (356) hide show
  1. lightly_studio/__init__.py +12 -0
  2. lightly_studio/api/__init__.py +0 -0
  3. lightly_studio/api/app.py +131 -0
  4. lightly_studio/api/cache.py +77 -0
  5. lightly_studio/api/db_tables.py +35 -0
  6. lightly_studio/api/features.py +5 -0
  7. lightly_studio/api/routes/api/annotation.py +305 -0
  8. lightly_studio/api/routes/api/annotation_label.py +87 -0
  9. lightly_studio/api/routes/api/annotations/__init__.py +7 -0
  10. lightly_studio/api/routes/api/annotations/create_annotation.py +52 -0
  11. lightly_studio/api/routes/api/caption.py +100 -0
  12. lightly_studio/api/routes/api/classifier.py +384 -0
  13. lightly_studio/api/routes/api/dataset.py +191 -0
  14. lightly_studio/api/routes/api/dataset_tag.py +266 -0
  15. lightly_studio/api/routes/api/embeddings2d.py +90 -0
  16. lightly_studio/api/routes/api/exceptions.py +114 -0
  17. lightly_studio/api/routes/api/export.py +114 -0
  18. lightly_studio/api/routes/api/features.py +17 -0
  19. lightly_studio/api/routes/api/frame.py +241 -0
  20. lightly_studio/api/routes/api/image.py +155 -0
  21. lightly_studio/api/routes/api/metadata.py +161 -0
  22. lightly_studio/api/routes/api/operator.py +75 -0
  23. lightly_studio/api/routes/api/sample.py +103 -0
  24. lightly_studio/api/routes/api/selection.py +87 -0
  25. lightly_studio/api/routes/api/settings.py +41 -0
  26. lightly_studio/api/routes/api/status.py +19 -0
  27. lightly_studio/api/routes/api/text_embedding.py +50 -0
  28. lightly_studio/api/routes/api/validators.py +17 -0
  29. lightly_studio/api/routes/api/video.py +133 -0
  30. lightly_studio/api/routes/healthz.py +13 -0
  31. lightly_studio/api/routes/images.py +104 -0
  32. lightly_studio/api/routes/video_frames_media.py +116 -0
  33. lightly_studio/api/routes/video_media.py +223 -0
  34. lightly_studio/api/routes/webapp.py +51 -0
  35. lightly_studio/api/server.py +94 -0
  36. lightly_studio/core/__init__.py +0 -0
  37. lightly_studio/core/add_samples.py +533 -0
  38. lightly_studio/core/add_videos.py +294 -0
  39. lightly_studio/core/dataset.py +780 -0
  40. lightly_studio/core/dataset_query/__init__.py +14 -0
  41. lightly_studio/core/dataset_query/boolean_expression.py +67 -0
  42. lightly_studio/core/dataset_query/dataset_query.py +317 -0
  43. lightly_studio/core/dataset_query/field.py +113 -0
  44. lightly_studio/core/dataset_query/field_expression.py +79 -0
  45. lightly_studio/core/dataset_query/match_expression.py +23 -0
  46. lightly_studio/core/dataset_query/order_by.py +79 -0
  47. lightly_studio/core/dataset_query/sample_field.py +37 -0
  48. lightly_studio/core/dataset_query/tags_expression.py +46 -0
  49. lightly_studio/core/image_sample.py +36 -0
  50. lightly_studio/core/loading_log.py +56 -0
  51. lightly_studio/core/sample.py +291 -0
  52. lightly_studio/core/start_gui.py +54 -0
  53. lightly_studio/core/video_sample.py +38 -0
  54. lightly_studio/dataset/__init__.py +0 -0
  55. lightly_studio/dataset/edge_embedding_generator.py +155 -0
  56. lightly_studio/dataset/embedding_generator.py +129 -0
  57. lightly_studio/dataset/embedding_manager.py +349 -0
  58. lightly_studio/dataset/env.py +20 -0
  59. lightly_studio/dataset/file_utils.py +49 -0
  60. lightly_studio/dataset/fsspec_lister.py +275 -0
  61. lightly_studio/dataset/mobileclip_embedding_generator.py +158 -0
  62. lightly_studio/dataset/perception_encoder_embedding_generator.py +260 -0
  63. lightly_studio/db_manager.py +166 -0
  64. lightly_studio/dist_lightly_studio_view_app/_app/env.js +1 -0
  65. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/0.GcXvs2l7.css +1 -0
  66. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/12.Dx6SXgAb.css +1 -0
  67. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/17.9X9_k6TP.css +1 -0
  68. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/18.BxiimdIO.css +1 -0
  69. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/2.CkOblLn7.css +1 -0
  70. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/ClassifierSamplesGrid.BJbCDlvs.css +1 -0
  71. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/LightlyLogo.BNjCIww-.png +0 -0
  72. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Bold.DGvYQtcs.ttf +0 -0
  73. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Italic-VariableFont_wdth_wght.B4AZ-wl6.ttf +0 -0
  74. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Medium.DVUZMR_6.ttf +0 -0
  75. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Regular.DxJTClRG.ttf +0 -0
  76. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-SemiBold.D3TTYgdB.ttf +0 -0
  77. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-VariableFont_wdth_wght.BZBpG5Iz.ttf +0 -0
  78. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_layout.CefECEWA.css +1 -0
  79. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_layout.D5tDcjY-.css +1 -0
  80. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.9X9_k6TP.css +1 -0
  81. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.BxiimdIO.css +1 -0
  82. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.Dx6SXgAb.css +1 -0
  83. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/transform._-1mPSEI.css +1 -0
  84. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/0dDyq72A.js +20 -0
  85. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/69_IOA4Y.js +1 -0
  86. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BK4An2kI.js +1 -0
  87. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BRmB-kJ9.js +1 -0
  88. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/B_1cpokE.js +1 -0
  89. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BiqpDEr0.js +1 -0
  90. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BpLiSKgx.js +1 -0
  91. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BscxbINH.js +39 -0
  92. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C1FmrZbK.js +1 -0
  93. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C80h3dJx.js +1 -0
  94. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C8mfFM-u.js +2 -0
  95. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CGY1p9L4.js +517 -0
  96. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/COfLknXM.js +1 -0
  97. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CWj6FrbW.js +1 -0
  98. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CYgJF_JY.js +1 -0
  99. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CmLg0ys7.js +1 -0
  100. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CvGjimpO.js +1 -0
  101. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D3RDXHoj.js +39 -0
  102. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D4y7iiT3.js +1 -0
  103. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D9SC3jBb.js +1 -0
  104. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DCuAdx1Q.js +20 -0
  105. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DDBy-_jD.js +1 -0
  106. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DIeogL5L.js +1 -0
  107. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DL9a7v5o.js +1 -0
  108. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DSKECuqX.js +39 -0
  109. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D_FFv0Oe.js +1 -0
  110. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DiZ5o5vz.js +1 -0
  111. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DkbXUtyG.js +1 -0
  112. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DmK2hulV.js +1 -0
  113. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DqnHaLTj.js +1 -0
  114. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DtWZc_tl.js +1 -0
  115. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DuUalyFS.js +1 -0
  116. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DwIonDAZ.js +1 -0
  117. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/Il-mSPmK.js +1 -0
  118. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/KNLP4aJU.js +1 -0
  119. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/KjYeVjkE.js +1 -0
  120. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/MErlcOXj.js +1 -0
  121. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VRI4prUD.js +1 -0
  122. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VYb2dkNs.js +1 -0
  123. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VqWvU2yF.js +1 -0
  124. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/dHC3otuL.js +1 -0
  125. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/da7Oy_lO.js +1 -0
  126. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/eAy8rZzC.js +2 -0
  127. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/erjNR5MX.js +1 -0
  128. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/f1oG3eFE.js +1 -0
  129. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/rsLi1iKv.js +20 -0
  130. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/rwuuBP9f.js +1 -0
  131. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/xGHZQ1pe.js +3 -0
  132. lightly_studio/dist_lightly_studio_view_app/_app/immutable/entry/app.DrTRUgT3.js +2 -0
  133. lightly_studio/dist_lightly_studio_view_app/_app/immutable/entry/start.BK5EOJl2.js +1 -0
  134. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/0.CIvTuljF.js +4 -0
  135. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/1.UBvSzxdA.js +1 -0
  136. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/10.CQ_tiLJa.js +1 -0
  137. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/11.KqkAcaxW.js +1 -0
  138. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/12.DoYsmxQc.js +1 -0
  139. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/13.571n2LZA.js +1 -0
  140. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/14.DGs689M-.js +1 -0
  141. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/15.CWG1ehzT.js +1 -0
  142. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/16.Dpq6jbSh.js +1 -0
  143. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/17.B5AZbHUU.js +1 -0
  144. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/18.CBga8cnq.js +1 -0
  145. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/2.D2HXgz-8.js +1090 -0
  146. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/3.f4HAg-y3.js +1 -0
  147. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/4.BKF4xuKQ.js +1 -0
  148. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/5.BAE0Pm_f.js +39 -0
  149. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/6.CouWWpzA.js +1 -0
  150. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/7.UBHT0ktp.js +1 -0
  151. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/8.FiYNElcc.js +1 -0
  152. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/9.B3-UaT23.js +1 -0
  153. lightly_studio/dist_lightly_studio_view_app/_app/immutable/workers/clustering.worker-DKqeLtG0.js +2 -0
  154. lightly_studio/dist_lightly_studio_view_app/_app/immutable/workers/search.worker-vNSty3B0.js +1 -0
  155. lightly_studio/dist_lightly_studio_view_app/_app/version.json +1 -0
  156. lightly_studio/dist_lightly_studio_view_app/apple-touch-icon-precomposed.png +0 -0
  157. lightly_studio/dist_lightly_studio_view_app/apple-touch-icon.png +0 -0
  158. lightly_studio/dist_lightly_studio_view_app/favicon.png +0 -0
  159. lightly_studio/dist_lightly_studio_view_app/index.html +45 -0
  160. lightly_studio/errors.py +5 -0
  161. lightly_studio/examples/example.py +25 -0
  162. lightly_studio/examples/example_coco.py +27 -0
  163. lightly_studio/examples/example_coco_caption.py +29 -0
  164. lightly_studio/examples/example_metadata.py +369 -0
  165. lightly_studio/examples/example_operators.py +111 -0
  166. lightly_studio/examples/example_selection.py +28 -0
  167. lightly_studio/examples/example_split_work.py +48 -0
  168. lightly_studio/examples/example_video.py +22 -0
  169. lightly_studio/examples/example_video_annotations.py +157 -0
  170. lightly_studio/examples/example_yolo.py +22 -0
  171. lightly_studio/export/coco_captions.py +69 -0
  172. lightly_studio/export/export_dataset.py +104 -0
  173. lightly_studio/export/lightly_studio_label_input.py +120 -0
  174. lightly_studio/export_schema.py +18 -0
  175. lightly_studio/export_version.py +57 -0
  176. lightly_studio/few_shot_classifier/__init__.py +0 -0
  177. lightly_studio/few_shot_classifier/classifier.py +80 -0
  178. lightly_studio/few_shot_classifier/classifier_manager.py +644 -0
  179. lightly_studio/few_shot_classifier/random_forest_classifier.py +495 -0
  180. lightly_studio/metadata/complex_metadata.py +47 -0
  181. lightly_studio/metadata/compute_similarity.py +84 -0
  182. lightly_studio/metadata/compute_typicality.py +67 -0
  183. lightly_studio/metadata/gps_coordinate.py +41 -0
  184. lightly_studio/metadata/metadata_protocol.py +17 -0
  185. lightly_studio/models/__init__.py +1 -0
  186. lightly_studio/models/annotation/__init__.py +0 -0
  187. lightly_studio/models/annotation/annotation_base.py +303 -0
  188. lightly_studio/models/annotation/instance_segmentation.py +56 -0
  189. lightly_studio/models/annotation/links.py +17 -0
  190. lightly_studio/models/annotation/object_detection.py +47 -0
  191. lightly_studio/models/annotation/semantic_segmentation.py +44 -0
  192. lightly_studio/models/annotation_label.py +47 -0
  193. lightly_studio/models/caption.py +49 -0
  194. lightly_studio/models/classifier.py +20 -0
  195. lightly_studio/models/dataset.py +70 -0
  196. lightly_studio/models/embedding_model.py +30 -0
  197. lightly_studio/models/image.py +96 -0
  198. lightly_studio/models/metadata.py +208 -0
  199. lightly_studio/models/range.py +17 -0
  200. lightly_studio/models/sample.py +154 -0
  201. lightly_studio/models/sample_embedding.py +36 -0
  202. lightly_studio/models/settings.py +69 -0
  203. lightly_studio/models/tag.py +96 -0
  204. lightly_studio/models/two_dim_embedding.py +16 -0
  205. lightly_studio/models/video.py +161 -0
  206. lightly_studio/plugins/__init__.py +0 -0
  207. lightly_studio/plugins/base_operator.py +60 -0
  208. lightly_studio/plugins/operator_registry.py +47 -0
  209. lightly_studio/plugins/parameter.py +70 -0
  210. lightly_studio/py.typed +0 -0
  211. lightly_studio/resolvers/__init__.py +0 -0
  212. lightly_studio/resolvers/annotation_label_resolver/__init__.py +22 -0
  213. lightly_studio/resolvers/annotation_label_resolver/create.py +27 -0
  214. lightly_studio/resolvers/annotation_label_resolver/delete.py +28 -0
  215. lightly_studio/resolvers/annotation_label_resolver/get_all.py +37 -0
  216. lightly_studio/resolvers/annotation_label_resolver/get_by_id.py +24 -0
  217. lightly_studio/resolvers/annotation_label_resolver/get_by_ids.py +25 -0
  218. lightly_studio/resolvers/annotation_label_resolver/get_by_label_name.py +24 -0
  219. lightly_studio/resolvers/annotation_label_resolver/names_by_ids.py +25 -0
  220. lightly_studio/resolvers/annotation_label_resolver/update.py +38 -0
  221. lightly_studio/resolvers/annotation_resolver/__init__.py +40 -0
  222. lightly_studio/resolvers/annotation_resolver/count_annotations_by_dataset.py +129 -0
  223. lightly_studio/resolvers/annotation_resolver/create_many.py +124 -0
  224. lightly_studio/resolvers/annotation_resolver/delete_annotation.py +87 -0
  225. lightly_studio/resolvers/annotation_resolver/delete_annotations.py +60 -0
  226. lightly_studio/resolvers/annotation_resolver/get_all.py +85 -0
  227. lightly_studio/resolvers/annotation_resolver/get_all_with_payload.py +179 -0
  228. lightly_studio/resolvers/annotation_resolver/get_by_id.py +34 -0
  229. lightly_studio/resolvers/annotation_resolver/get_by_id_with_payload.py +130 -0
  230. lightly_studio/resolvers/annotation_resolver/update_annotation_label.py +142 -0
  231. lightly_studio/resolvers/annotation_resolver/update_bounding_box.py +68 -0
  232. lightly_studio/resolvers/annotations/__init__.py +1 -0
  233. lightly_studio/resolvers/annotations/annotations_filter.py +88 -0
  234. lightly_studio/resolvers/caption_resolver.py +129 -0
  235. lightly_studio/resolvers/dataset_resolver/__init__.py +55 -0
  236. lightly_studio/resolvers/dataset_resolver/check_dataset_type.py +29 -0
  237. lightly_studio/resolvers/dataset_resolver/create.py +20 -0
  238. lightly_studio/resolvers/dataset_resolver/delete.py +20 -0
  239. lightly_studio/resolvers/dataset_resolver/export.py +267 -0
  240. lightly_studio/resolvers/dataset_resolver/get_all.py +19 -0
  241. lightly_studio/resolvers/dataset_resolver/get_by_id.py +16 -0
  242. lightly_studio/resolvers/dataset_resolver/get_by_name.py +12 -0
  243. lightly_studio/resolvers/dataset_resolver/get_dataset_details.py +27 -0
  244. lightly_studio/resolvers/dataset_resolver/get_hierarchy.py +31 -0
  245. lightly_studio/resolvers/dataset_resolver/get_or_create_child_dataset.py +58 -0
  246. lightly_studio/resolvers/dataset_resolver/get_parent_dataset_by_sample_id.py +27 -0
  247. lightly_studio/resolvers/dataset_resolver/get_parent_dataset_id.py +22 -0
  248. lightly_studio/resolvers/dataset_resolver/get_root_dataset.py +61 -0
  249. lightly_studio/resolvers/dataset_resolver/get_root_datasets_overview.py +41 -0
  250. lightly_studio/resolvers/dataset_resolver/update.py +25 -0
  251. lightly_studio/resolvers/embedding_model_resolver.py +120 -0
  252. lightly_studio/resolvers/image_filter.py +50 -0
  253. lightly_studio/resolvers/image_resolver/__init__.py +21 -0
  254. lightly_studio/resolvers/image_resolver/create_many.py +52 -0
  255. lightly_studio/resolvers/image_resolver/delete.py +20 -0
  256. lightly_studio/resolvers/image_resolver/filter_new_paths.py +23 -0
  257. lightly_studio/resolvers/image_resolver/get_all_by_dataset_id.py +117 -0
  258. lightly_studio/resolvers/image_resolver/get_by_id.py +14 -0
  259. lightly_studio/resolvers/image_resolver/get_dimension_bounds.py +75 -0
  260. lightly_studio/resolvers/image_resolver/get_many_by_id.py +22 -0
  261. lightly_studio/resolvers/image_resolver/get_samples_excluding.py +43 -0
  262. lightly_studio/resolvers/metadata_resolver/__init__.py +15 -0
  263. lightly_studio/resolvers/metadata_resolver/metadata_filter.py +163 -0
  264. lightly_studio/resolvers/metadata_resolver/sample/__init__.py +21 -0
  265. lightly_studio/resolvers/metadata_resolver/sample/bulk_update_metadata.py +46 -0
  266. lightly_studio/resolvers/metadata_resolver/sample/get_by_sample_id.py +24 -0
  267. lightly_studio/resolvers/metadata_resolver/sample/get_metadata_info.py +104 -0
  268. lightly_studio/resolvers/metadata_resolver/sample/get_value_for_sample.py +27 -0
  269. lightly_studio/resolvers/metadata_resolver/sample/set_value_for_sample.py +53 -0
  270. lightly_studio/resolvers/sample_embedding_resolver.py +132 -0
  271. lightly_studio/resolvers/sample_resolver/__init__.py +17 -0
  272. lightly_studio/resolvers/sample_resolver/count_by_dataset_id.py +16 -0
  273. lightly_studio/resolvers/sample_resolver/create.py +16 -0
  274. lightly_studio/resolvers/sample_resolver/create_many.py +25 -0
  275. lightly_studio/resolvers/sample_resolver/get_by_id.py +14 -0
  276. lightly_studio/resolvers/sample_resolver/get_filtered_samples.py +56 -0
  277. lightly_studio/resolvers/sample_resolver/get_many_by_id.py +22 -0
  278. lightly_studio/resolvers/sample_resolver/sample_filter.py +74 -0
  279. lightly_studio/resolvers/settings_resolver.py +62 -0
  280. lightly_studio/resolvers/tag_resolver.py +299 -0
  281. lightly_studio/resolvers/twodim_embedding_resolver.py +119 -0
  282. lightly_studio/resolvers/video_frame_resolver/__init__.py +23 -0
  283. lightly_studio/resolvers/video_frame_resolver/count_video_frames_annotations.py +83 -0
  284. lightly_studio/resolvers/video_frame_resolver/create_many.py +57 -0
  285. lightly_studio/resolvers/video_frame_resolver/get_all_by_dataset_id.py +63 -0
  286. lightly_studio/resolvers/video_frame_resolver/get_by_id.py +13 -0
  287. lightly_studio/resolvers/video_frame_resolver/get_table_fields_bounds.py +44 -0
  288. lightly_studio/resolvers/video_frame_resolver/video_frame_annotations_counter_filter.py +47 -0
  289. lightly_studio/resolvers/video_frame_resolver/video_frame_filter.py +57 -0
  290. lightly_studio/resolvers/video_resolver/__init__.py +27 -0
  291. lightly_studio/resolvers/video_resolver/count_video_frame_annotations_by_video_dataset.py +86 -0
  292. lightly_studio/resolvers/video_resolver/create_many.py +58 -0
  293. lightly_studio/resolvers/video_resolver/filter_new_paths.py +33 -0
  294. lightly_studio/resolvers/video_resolver/get_all_by_dataset_id.py +181 -0
  295. lightly_studio/resolvers/video_resolver/get_by_id.py +22 -0
  296. lightly_studio/resolvers/video_resolver/get_table_fields_bounds.py +72 -0
  297. lightly_studio/resolvers/video_resolver/get_view_by_id.py +52 -0
  298. lightly_studio/resolvers/video_resolver/video_count_annotations_filter.py +50 -0
  299. lightly_studio/resolvers/video_resolver/video_filter.py +98 -0
  300. lightly_studio/selection/__init__.py +1 -0
  301. lightly_studio/selection/mundig.py +143 -0
  302. lightly_studio/selection/select.py +203 -0
  303. lightly_studio/selection/select_via_db.py +273 -0
  304. lightly_studio/selection/selection_config.py +49 -0
  305. lightly_studio/services/annotations_service/__init__.py +33 -0
  306. lightly_studio/services/annotations_service/create_annotation.py +64 -0
  307. lightly_studio/services/annotations_service/delete_annotation.py +22 -0
  308. lightly_studio/services/annotations_service/get_annotation_by_id.py +31 -0
  309. lightly_studio/services/annotations_service/update_annotation.py +54 -0
  310. lightly_studio/services/annotations_service/update_annotation_bounding_box.py +36 -0
  311. lightly_studio/services/annotations_service/update_annotation_label.py +48 -0
  312. lightly_studio/services/annotations_service/update_annotations.py +29 -0
  313. lightly_studio/setup_logging.py +59 -0
  314. lightly_studio/type_definitions.py +31 -0
  315. lightly_studio/utils/__init__.py +3 -0
  316. lightly_studio/utils/download.py +94 -0
  317. lightly_studio/vendor/__init__.py +1 -0
  318. lightly_studio/vendor/mobileclip/ACKNOWLEDGEMENTS +422 -0
  319. lightly_studio/vendor/mobileclip/LICENSE +31 -0
  320. lightly_studio/vendor/mobileclip/LICENSE_weights_data +50 -0
  321. lightly_studio/vendor/mobileclip/README.md +5 -0
  322. lightly_studio/vendor/mobileclip/__init__.py +96 -0
  323. lightly_studio/vendor/mobileclip/clip.py +77 -0
  324. lightly_studio/vendor/mobileclip/configs/mobileclip_b.json +18 -0
  325. lightly_studio/vendor/mobileclip/configs/mobileclip_s0.json +18 -0
  326. lightly_studio/vendor/mobileclip/configs/mobileclip_s1.json +18 -0
  327. lightly_studio/vendor/mobileclip/configs/mobileclip_s2.json +18 -0
  328. lightly_studio/vendor/mobileclip/image_encoder.py +67 -0
  329. lightly_studio/vendor/mobileclip/logger.py +154 -0
  330. lightly_studio/vendor/mobileclip/models/__init__.py +10 -0
  331. lightly_studio/vendor/mobileclip/models/mci.py +933 -0
  332. lightly_studio/vendor/mobileclip/models/vit.py +433 -0
  333. lightly_studio/vendor/mobileclip/modules/__init__.py +4 -0
  334. lightly_studio/vendor/mobileclip/modules/common/__init__.py +4 -0
  335. lightly_studio/vendor/mobileclip/modules/common/mobileone.py +341 -0
  336. lightly_studio/vendor/mobileclip/modules/common/transformer.py +451 -0
  337. lightly_studio/vendor/mobileclip/modules/image/__init__.py +4 -0
  338. lightly_studio/vendor/mobileclip/modules/image/image_projection.py +113 -0
  339. lightly_studio/vendor/mobileclip/modules/image/replknet.py +188 -0
  340. lightly_studio/vendor/mobileclip/modules/text/__init__.py +4 -0
  341. lightly_studio/vendor/mobileclip/modules/text/repmixer.py +281 -0
  342. lightly_studio/vendor/mobileclip/modules/text/tokenizer.py +38 -0
  343. lightly_studio/vendor/mobileclip/text_encoder.py +245 -0
  344. lightly_studio/vendor/perception_encoder/LICENSE.PE +201 -0
  345. lightly_studio/vendor/perception_encoder/README.md +11 -0
  346. lightly_studio/vendor/perception_encoder/vision_encoder/__init__.py +0 -0
  347. lightly_studio/vendor/perception_encoder/vision_encoder/bpe_simple_vocab_16e6.txt.gz +0 -0
  348. lightly_studio/vendor/perception_encoder/vision_encoder/config.py +205 -0
  349. lightly_studio/vendor/perception_encoder/vision_encoder/config_src.py +264 -0
  350. lightly_studio/vendor/perception_encoder/vision_encoder/pe.py +766 -0
  351. lightly_studio/vendor/perception_encoder/vision_encoder/rope.py +352 -0
  352. lightly_studio/vendor/perception_encoder/vision_encoder/tokenizer.py +347 -0
  353. lightly_studio/vendor/perception_encoder/vision_encoder/transforms.py +36 -0
  354. lightly_studio-0.4.6.dist-info/METADATA +88 -0
  355. lightly_studio-0.4.6.dist-info/RECORD +356 -0
  356. 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
+ )