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,38 @@
1
+ """Update annotation label functionality."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from uuid import UUID
6
+
7
+ from sqlmodel import Session
8
+
9
+ from lightly_studio.models.annotation_label import (
10
+ AnnotationLabelCreate,
11
+ AnnotationLabelTable,
12
+ )
13
+
14
+ from .get_by_id import get_by_id
15
+
16
+
17
+ def update(
18
+ session: Session, label_id: UUID, label_data: AnnotationLabelCreate
19
+ ) -> AnnotationLabelTable | None:
20
+ """Update an existing annotation label.
21
+
22
+ Args:
23
+ session (Session): The database session.
24
+ label_id (UUID): The identifier of the annotation label to update.
25
+ label_data (AnnotationLabelCreate): The new data.
26
+
27
+ Returns:
28
+ AnnotationLabelTable | None: The updated annotation label if it exists,
29
+ otherwise None.
30
+ """
31
+ label = get_by_id(session=session, label_id=label_id)
32
+ if not label:
33
+ return None
34
+
35
+ label.annotation_label_name = label_data.annotation_label_name
36
+ session.commit()
37
+ session.refresh(label)
38
+ return label
@@ -0,0 +1,40 @@
1
+ """Resolvers for database operations."""
2
+
3
+ from lightly_studio.resolvers.annotation_resolver.count_annotations_by_dataset import (
4
+ count_annotations_by_dataset,
5
+ )
6
+ from lightly_studio.resolvers.annotation_resolver.create_many import create_many
7
+ from lightly_studio.resolvers.annotation_resolver.delete_annotation import (
8
+ delete_annotation,
9
+ )
10
+ from lightly_studio.resolvers.annotation_resolver.delete_annotations import (
11
+ delete_annotations,
12
+ )
13
+ from lightly_studio.resolvers.annotation_resolver.get_all import get_all
14
+ from lightly_studio.resolvers.annotation_resolver.get_all_with_payload import (
15
+ get_all_with_payload,
16
+ )
17
+ from lightly_studio.resolvers.annotation_resolver.get_by_id import get_by_id, get_by_ids
18
+ from lightly_studio.resolvers.annotation_resolver.get_by_id_with_payload import (
19
+ get_by_id_with_payload,
20
+ )
21
+ from lightly_studio.resolvers.annotation_resolver.update_annotation_label import (
22
+ update_annotation_label,
23
+ )
24
+ from lightly_studio.resolvers.annotation_resolver.update_bounding_box import (
25
+ update_bounding_box,
26
+ )
27
+
28
+ __all__ = [
29
+ "count_annotations_by_dataset",
30
+ "create_many",
31
+ "delete_annotation",
32
+ "delete_annotations",
33
+ "get_all",
34
+ "get_all_with_payload",
35
+ "get_by_id",
36
+ "get_by_id_with_payload",
37
+ "get_by_ids",
38
+ "update_annotation_label",
39
+ "update_bounding_box",
40
+ ]
@@ -0,0 +1,129 @@
1
+ """Handler for database operations related to annotations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from uuid import UUID
6
+
7
+ from sqlmodel import Session, col, func, select
8
+
9
+ from lightly_studio.models.annotation.annotation_base import (
10
+ AnnotationBaseTable,
11
+ )
12
+ from lightly_studio.models.annotation_label import AnnotationLabelTable
13
+ from lightly_studio.models.image import ImageTable
14
+ from lightly_studio.models.sample import SampleTable
15
+ from lightly_studio.models.tag import TagTable
16
+
17
+
18
+ def count_annotations_by_dataset( # noqa: PLR0913 // FIXME: refactor to use proper pydantic
19
+ session: Session,
20
+ dataset_id: UUID,
21
+ filtered_labels: list[str] | None = None,
22
+ min_width: int | None = None,
23
+ max_width: int | None = None,
24
+ min_height: int | None = None,
25
+ max_height: int | None = None,
26
+ tag_ids: list[UUID] | None = None,
27
+ ) -> list[tuple[str, int, int]]:
28
+ """Count annotations for a specific dataset.
29
+
30
+ Annotations for a specific dataset are grouped by annotation
31
+ label name and counted for total and filtered.
32
+ """
33
+ # Query for total counts (unfiltered)
34
+ total_counts_query = (
35
+ select(
36
+ AnnotationLabelTable.annotation_label_name,
37
+ func.count(col(AnnotationBaseTable.sample_id)).label("total_count"),
38
+ )
39
+ .join(
40
+ AnnotationBaseTable,
41
+ col(AnnotationBaseTable.annotation_label_id)
42
+ == col(AnnotationLabelTable.annotation_label_id),
43
+ )
44
+ .join(
45
+ ImageTable,
46
+ col(ImageTable.sample_id) == col(AnnotationBaseTable.parent_sample_id),
47
+ )
48
+ .join(
49
+ SampleTable,
50
+ col(SampleTable.sample_id) == col(ImageTable.sample_id),
51
+ )
52
+ .where(SampleTable.dataset_id == dataset_id)
53
+ .group_by(AnnotationLabelTable.annotation_label_name)
54
+ .order_by(col(AnnotationLabelTable.annotation_label_name).asc())
55
+ )
56
+
57
+ total_counts = {row[0]: row[1] for row in session.exec(total_counts_query).all()}
58
+
59
+ # Build filtered query for current counts
60
+ filtered_query = (
61
+ select(
62
+ AnnotationLabelTable.annotation_label_name,
63
+ func.count(col(AnnotationBaseTable.sample_id)).label("current_count"),
64
+ )
65
+ .join(
66
+ AnnotationBaseTable,
67
+ col(AnnotationBaseTable.annotation_label_id)
68
+ == col(AnnotationLabelTable.annotation_label_id),
69
+ )
70
+ .join(
71
+ ImageTable,
72
+ col(ImageTable.sample_id) == col(AnnotationBaseTable.parent_sample_id),
73
+ )
74
+ .join(
75
+ SampleTable,
76
+ col(SampleTable.sample_id) == col(ImageTable.sample_id),
77
+ )
78
+ .where(SampleTable.dataset_id == dataset_id)
79
+ )
80
+
81
+ # Add dimension filters
82
+ if min_width is not None:
83
+ filtered_query = filtered_query.where(ImageTable.width >= min_width)
84
+ if max_width is not None:
85
+ filtered_query = filtered_query.where(ImageTable.width <= max_width)
86
+ if min_height is not None:
87
+ filtered_query = filtered_query.where(ImageTable.height >= min_height)
88
+ if max_height is not None:
89
+ filtered_query = filtered_query.where(ImageTable.height <= max_height)
90
+
91
+ # Add label filter if specified
92
+ if filtered_labels:
93
+ filtered_query = filtered_query.where(
94
+ col(ImageTable.sample_id).in_(
95
+ select(ImageTable.sample_id)
96
+ .join(
97
+ AnnotationBaseTable,
98
+ col(ImageTable.sample_id) == col(AnnotationBaseTable.parent_sample_id),
99
+ )
100
+ .join(
101
+ AnnotationLabelTable,
102
+ col(AnnotationBaseTable.annotation_label_id)
103
+ == col(AnnotationLabelTable.annotation_label_id),
104
+ )
105
+ .where(col(AnnotationLabelTable.annotation_label_name).in_(filtered_labels))
106
+ )
107
+ )
108
+
109
+ # filter by tag_ids
110
+ if tag_ids:
111
+ filtered_query = (
112
+ filtered_query.join(AnnotationBaseTable.tags)
113
+ .where(AnnotationBaseTable.tags.any(col(TagTable.tag_id).in_(tag_ids)))
114
+ .distinct()
115
+ )
116
+
117
+ # Group by label name and sort
118
+ filtered_query = filtered_query.group_by(AnnotationLabelTable.annotation_label_name).order_by(
119
+ col(AnnotationLabelTable.annotation_label_name).asc()
120
+ )
121
+
122
+ _rows = session.exec(filtered_query).all()
123
+
124
+ current_counts = {row[0]: row[1] for row in _rows}
125
+
126
+ return [
127
+ (label, current_counts.get(label, 0), total_count)
128
+ for label, total_count in total_counts.items()
129
+ ]
@@ -0,0 +1,124 @@
1
+ """Handler for database operations related to annotations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from uuid import UUID
6
+
7
+ from sqlmodel import Session
8
+
9
+ from lightly_studio.models.annotation.annotation_base import (
10
+ AnnotationBaseTable,
11
+ AnnotationCreate,
12
+ )
13
+ from lightly_studio.models.annotation.instance_segmentation import (
14
+ InstanceSegmentationAnnotationTable,
15
+ )
16
+ from lightly_studio.models.annotation.object_detection import (
17
+ ObjectDetectionAnnotationTable,
18
+ )
19
+ from lightly_studio.models.annotation.semantic_segmentation import (
20
+ SemanticSegmentationAnnotationTable,
21
+ )
22
+ from lightly_studio.models.dataset import SampleType
23
+ from lightly_studio.models.sample import SampleCreate
24
+ from lightly_studio.resolvers import dataset_resolver, sample_resolver
25
+
26
+
27
+ def create_many(
28
+ session: Session,
29
+ parent_dataset_id: UUID,
30
+ annotations: list[AnnotationCreate],
31
+ ) -> list[UUID]:
32
+ """Create multiple annotations in bulk with their respective type-specific details.
33
+
34
+ Creates base annotations and their associated type-specific details (object detection,
35
+ instance segmentation, or semantic segmentation) in the annotation dataset child of
36
+ the provided parent dataset.
37
+
38
+ It is responsibility of the caller to ensure that all parent samples belong to the same
39
+ dataset with ID `parent_dataset_id`. This function does not perform this check for performance
40
+ reasons.
41
+
42
+ Args:
43
+ session: SQLAlchemy session for database operations.
44
+ parent_dataset_id: UUID of the parent dataset.
45
+ annotations: List of annotation objects to create.
46
+
47
+ Returns:
48
+ List of created annotation IDs.
49
+ """
50
+ # Step 1: Create all base annotations
51
+ base_annotations = []
52
+ object_detection_annotations = []
53
+ instance_segmentation_annotations = []
54
+ semantic_segmentation_annotations = []
55
+ annotation_dataset_id = dataset_resolver.get_or_create_child_dataset(
56
+ session=session, dataset_id=parent_dataset_id, sample_type=SampleType.ANNOTATION
57
+ )
58
+
59
+ sample_ids = sample_resolver.create_many(
60
+ session=session,
61
+ samples=[SampleCreate(dataset_id=annotation_dataset_id) for _ in annotations],
62
+ )
63
+ for annotation_create, sample_id in zip(annotations, sample_ids):
64
+ # Create base annotation
65
+ db_base_annotation = AnnotationBaseTable(
66
+ sample_id=sample_id,
67
+ annotation_label_id=annotation_create.annotation_label_id,
68
+ annotation_type=annotation_create.annotation_type,
69
+ confidence=annotation_create.confidence,
70
+ dataset_id=annotation_dataset_id,
71
+ parent_sample_id=annotation_create.parent_sample_id,
72
+ )
73
+
74
+ # Set other relationship details to None
75
+ db_base_annotation.instance_segmentation_details = None
76
+ db_base_annotation.semantic_segmentation_details = None
77
+ db_base_annotation.object_detection_details = None
78
+
79
+ base_annotations.append(db_base_annotation)
80
+
81
+ # Bulk save base annotations and flush to get IDs
82
+ session.bulk_save_objects(base_annotations)
83
+ session.flush()
84
+
85
+ # Step 2: Create specific annotation details
86
+ for i, annotation_create in enumerate(annotations):
87
+ # Create object detection details
88
+ if base_annotations[i].annotation_type == "object_detection":
89
+ db_object_detection = ObjectDetectionAnnotationTable(
90
+ sample_id=base_annotations[i].sample_id,
91
+ x=annotation_create.x,
92
+ y=annotation_create.y,
93
+ width=annotation_create.width,
94
+ height=annotation_create.height,
95
+ )
96
+ object_detection_annotations.append(db_object_detection)
97
+
98
+ # Create instance segmentation details
99
+ elif base_annotations[i].annotation_type == "instance_segmentation":
100
+ db_instance_segmentation = InstanceSegmentationAnnotationTable(
101
+ sample_id=base_annotations[i].sample_id,
102
+ segmentation_mask=annotation_create.segmentation_mask,
103
+ x=annotation_create.x,
104
+ y=annotation_create.y,
105
+ width=annotation_create.width,
106
+ height=annotation_create.height,
107
+ )
108
+ instance_segmentation_annotations.append(db_instance_segmentation)
109
+ elif base_annotations[i].annotation_type == "semantic_segmentation":
110
+ db_semantic_segmentation = SemanticSegmentationAnnotationTable(
111
+ sample_id=base_annotations[i].sample_id,
112
+ segmentation_mask=annotation_create.segmentation_mask,
113
+ )
114
+ semantic_segmentation_annotations.append(db_semantic_segmentation)
115
+
116
+ # Bulk save object detection annotations
117
+ session.bulk_save_objects(object_detection_annotations)
118
+ session.bulk_save_objects(instance_segmentation_annotations)
119
+ session.bulk_save_objects(semantic_segmentation_annotations)
120
+
121
+ # Commit everything
122
+ session.commit()
123
+
124
+ return [annotation.sample_id for annotation in base_annotations]
@@ -0,0 +1,87 @@
1
+ """Handler for database operations related to annotations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from uuid import UUID
6
+
7
+ from sqlmodel import Session, col, delete
8
+
9
+ from lightly_studio.models.annotation.annotation_base import AnnotationBaseTable
10
+ from lightly_studio.models.annotation.instance_segmentation import (
11
+ InstanceSegmentationAnnotationTable,
12
+ )
13
+ from lightly_studio.models.annotation.links import AnnotationTagLinkTable
14
+ from lightly_studio.models.annotation.object_detection import (
15
+ ObjectDetectionAnnotationTable,
16
+ )
17
+ from lightly_studio.models.annotation.semantic_segmentation import (
18
+ SemanticSegmentationAnnotationTable,
19
+ )
20
+ from lightly_studio.models.sample import SampleTable
21
+ from lightly_studio.resolvers import annotation_resolver
22
+
23
+
24
+ def delete_annotation(
25
+ session: Session,
26
+ annotation_id: UUID,
27
+ delete_sample: bool = True,
28
+ ) -> None:
29
+ """Delete all annotations and their tag links using filters.
30
+
31
+ Args:
32
+ session: Database session.
33
+ annotation_id: Annotation ID to filter by.
34
+ delete_sample: Whether to also delete the annotation's sample. Defaults to True.
35
+ Set to False when updating an annotation (to reuse the sample).
36
+ """
37
+ # Find annotation_ids to delete
38
+ annotation = annotation_resolver.get_by_id(
39
+ session,
40
+ annotation_id=annotation_id,
41
+ )
42
+ if not annotation:
43
+ raise ValueError(f"Annotation {annotation_id} not found")
44
+
45
+ # Store the annotation's sample_id before deletion
46
+ annotation_sample_id = annotation.sample_id
47
+
48
+ session.exec( # type: ignore
49
+ delete(ObjectDetectionAnnotationTable).where(
50
+ col(ObjectDetectionAnnotationTable.sample_id) == annotation.sample_id
51
+ )
52
+ )
53
+ session.exec( # type: ignore
54
+ delete(InstanceSegmentationAnnotationTable).where(
55
+ col(InstanceSegmentationAnnotationTable.sample_id) == annotation.sample_id
56
+ )
57
+ )
58
+ session.exec( # type: ignore
59
+ delete(SemanticSegmentationAnnotationTable).where(
60
+ col(SemanticSegmentationAnnotationTable.sample_id) == annotation.sample_id
61
+ )
62
+ )
63
+ session.commit()
64
+
65
+ # Delete tag links
66
+ session.exec( # type: ignore
67
+ delete(AnnotationTagLinkTable).where(
68
+ col(AnnotationTagLinkTable.annotation_sample_id).in_([annotation.sample_id])
69
+ )
70
+ )
71
+ session.commit()
72
+
73
+ # Delete the annotation using explicit DELETE to avoid relationship cascade issues
74
+ session.exec( # type: ignore
75
+ delete(AnnotationBaseTable).where(
76
+ col(AnnotationBaseTable.sample_id) == annotation.sample_id
77
+ )
78
+ )
79
+ session.commit()
80
+
81
+ # Then delete the annotation's sample (created specifically for this annotation)
82
+ # unless we're keeping it for reuse (e.g., when updating annotation label)
83
+ if delete_sample:
84
+ annotation_sample = session.get(SampleTable, annotation_sample_id)
85
+ if annotation_sample:
86
+ session.delete(annotation_sample)
87
+ session.commit()
@@ -0,0 +1,60 @@
1
+ """Handler for database operations related to annotations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from uuid import UUID
6
+
7
+ from sqlmodel import Session, col, delete
8
+
9
+ from lightly_studio.models.annotation.annotation_base import (
10
+ AnnotationBaseTable,
11
+ )
12
+ from lightly_studio.models.annotation.links import AnnotationTagLinkTable
13
+ from lightly_studio.resolvers import annotation_resolver
14
+ from lightly_studio.resolvers.annotations.annotations_filter import (
15
+ AnnotationsFilter,
16
+ )
17
+
18
+
19
+ def delete_annotations(
20
+ session: Session,
21
+ annotation_label_ids: list[UUID] | None,
22
+ ) -> None:
23
+ """Delete all annotations and their tag links using filters.
24
+
25
+ Args:
26
+ session: Database session.
27
+ annotation_label_ids: List of annotation label IDs to filter by.
28
+ """
29
+ # Find annotation_ids to delete
30
+ annotations = annotation_resolver.get_all(
31
+ session,
32
+ filters=AnnotationsFilter(
33
+ annotation_label_ids=annotation_label_ids,
34
+ ),
35
+ ).annotations
36
+ for annotation in annotations:
37
+ if annotation.object_detection_details:
38
+ session.delete(annotation.object_detection_details)
39
+ if annotation.instance_segmentation_details:
40
+ session.delete(annotation.instance_segmentation_details)
41
+ if annotation.semantic_segmentation_details:
42
+ session.delete(annotation.semantic_segmentation_details)
43
+ annotation_ids = [annotation.sample_id for annotation in annotations]
44
+ # TODO(Horatiu, 06/2025): Check if there is a way to delete the links
45
+ # automatically using SQLModel/SQLAlchemy.
46
+ if annotation_ids:
47
+ # Delete tag links first
48
+ session.exec( # type: ignore
49
+ delete(AnnotationTagLinkTable).where(
50
+ col(AnnotationTagLinkTable.annotation_sample_id).in_(annotation_ids)
51
+ )
52
+ )
53
+ session.commit()
54
+ # Now delete the annotations themselves
55
+ session.exec( # type: ignore
56
+ delete(AnnotationBaseTable).where(
57
+ col(AnnotationBaseTable.sample_id).in_(annotation_ids)
58
+ )
59
+ )
60
+ session.commit()
@@ -0,0 +1,85 @@
1
+ """Handler for database operations related to annotations."""
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.annotation.annotation_base import (
12
+ AnnotationBaseTable,
13
+ )
14
+ from lightly_studio.models.image import ImageTable
15
+ from lightly_studio.models.video import VideoFrameTable, VideoTable
16
+ from lightly_studio.resolvers.annotations.annotations_filter import (
17
+ AnnotationsFilter,
18
+ )
19
+
20
+
21
+ class GetAllAnnotationsResult(BaseModel):
22
+ """Result of getting all annotations."""
23
+
24
+ annotations: Sequence[AnnotationBaseTable]
25
+
26
+ total_count: int
27
+
28
+ next_cursor: int | None = None
29
+
30
+
31
+ def get_all(
32
+ session: Session,
33
+ pagination: Paginated | None = None,
34
+ filters: AnnotationsFilter | None = None,
35
+ ) -> GetAllAnnotationsResult:
36
+ """Get all annotations from the database.
37
+
38
+ Args:
39
+ session: Database session
40
+ pagination: Optional pagination parameters
41
+ filters: Optional filters to apply to the query
42
+
43
+ Returns:
44
+ List of annotations matching the filters
45
+ """
46
+ annotations_statement = select(AnnotationBaseTable)
47
+ annotations_statement = (
48
+ annotations_statement.outerjoin(
49
+ ImageTable, col(ImageTable.sample_id) == col(AnnotationBaseTable.parent_sample_id)
50
+ )
51
+ .outerjoin(
52
+ VideoFrameTable,
53
+ col(VideoFrameTable.sample_id) == col(AnnotationBaseTable.parent_sample_id),
54
+ )
55
+ .outerjoin(VideoTable, col(VideoTable.sample_id) == col(VideoFrameTable.parent_sample_id))
56
+ .order_by(
57
+ func.coalesce(ImageTable.file_path_abs, VideoTable.file_path_abs, "").asc(),
58
+ col(AnnotationBaseTable.created_at).asc(),
59
+ col(AnnotationBaseTable.sample_id).asc(),
60
+ )
61
+ )
62
+ total_count_statement = select(func.count()).select_from(AnnotationBaseTable)
63
+
64
+ # Apply filters if provided
65
+ if filters is not None:
66
+ annotations_statement = filters.apply(annotations_statement)
67
+ total_count_statement = filters.apply(total_count_statement)
68
+
69
+ # Apply pagination if provided
70
+ if pagination is not None:
71
+ annotations_statement = annotations_statement.offset(pagination.offset).limit(
72
+ pagination.limit
73
+ )
74
+
75
+ total_count = session.exec(total_count_statement).one()
76
+
77
+ next_cursor = None
78
+ if pagination and pagination.offset + pagination.limit < total_count:
79
+ next_cursor = pagination.offset + pagination.limit
80
+
81
+ return GetAllAnnotationsResult(
82
+ annotations=session.exec(annotations_statement).all(),
83
+ total_count=total_count,
84
+ next_cursor=next_cursor,
85
+ )