endoreg-db 0.8.4.4__py3-none-any.whl → 0.8.8.0__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.

Potentially problematic release.


This version of endoreg-db might be problematic. Click here for more details.

Files changed (372) hide show
  1. endoreg_db/authz/auth.py +74 -0
  2. endoreg_db/authz/backends.py +168 -0
  3. endoreg_db/authz/management/commands/list_routes.py +18 -0
  4. endoreg_db/authz/middleware.py +83 -0
  5. endoreg_db/authz/permissions.py +127 -0
  6. endoreg_db/authz/policy.py +218 -0
  7. endoreg_db/authz/views_auth.py +66 -0
  8. endoreg_db/config/env.py +13 -8
  9. endoreg_db/data/__init__.py +8 -31
  10. endoreg_db/data/_examples/disease.yaml +55 -0
  11. endoreg_db/data/_examples/disease_classification.yaml +13 -0
  12. endoreg_db/data/_examples/disease_classification_choice.yaml +62 -0
  13. endoreg_db/data/_examples/event.yaml +64 -0
  14. endoreg_db/data/_examples/examination.yaml +72 -0
  15. endoreg_db/data/_examples/finding/anatomy_colon.yaml +128 -0
  16. endoreg_db/data/_examples/finding/colonoscopy.yaml +40 -0
  17. endoreg_db/data/_examples/finding/colonoscopy_bowel_prep.yaml +56 -0
  18. endoreg_db/data/_examples/finding/complication.yaml +16 -0
  19. endoreg_db/data/_examples/finding/data.yaml +105 -0
  20. endoreg_db/data/_examples/finding/examination_setting.yaml +16 -0
  21. endoreg_db/data/_examples/finding/medication_related.yaml +18 -0
  22. endoreg_db/data/_examples/finding/outcome.yaml +12 -0
  23. endoreg_db/data/_examples/finding_classification/colonoscopy_bowel_preparation.yaml +68 -0
  24. endoreg_db/data/_examples/finding_classification/colonoscopy_jnet.yaml +22 -0
  25. endoreg_db/data/_examples/finding_classification/colonoscopy_kudo.yaml +25 -0
  26. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
  27. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
  28. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_size.yaml +68 -0
  29. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
  30. endoreg_db/data/_examples/finding_classification/colonoscopy_location.yaml +80 -0
  31. endoreg_db/data/_examples/finding_classification/colonoscopy_lst.yaml +21 -0
  32. endoreg_db/data/_examples/finding_classification/colonoscopy_nice.yaml +20 -0
  33. endoreg_db/data/_examples/finding_classification/colonoscopy_paris.yaml +26 -0
  34. endoreg_db/data/_examples/finding_classification/colonoscopy_sano.yaml +22 -0
  35. endoreg_db/data/_examples/finding_classification/colonoscopy_summary.yaml +53 -0
  36. endoreg_db/data/_examples/finding_classification/complication_generic.yaml +25 -0
  37. endoreg_db/data/_examples/finding_classification/examination_setting_generic.yaml +40 -0
  38. endoreg_db/data/_examples/finding_classification/histology_colo.yaml +51 -0
  39. endoreg_db/data/_examples/finding_classification/intervention_required.yaml +26 -0
  40. endoreg_db/data/_examples/finding_classification/medication_related.yaml +23 -0
  41. endoreg_db/data/_examples/finding_classification/visualized.yaml +33 -0
  42. endoreg_db/data/_examples/finding_classification_choice/bowel_preparation.yaml +78 -0
  43. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_circularity_default.yaml +32 -0
  44. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
  45. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
  46. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_lst.yaml +15 -0
  47. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_nice.yaml +17 -0
  48. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_paris.yaml +57 -0
  49. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_planarity_default.yaml +49 -0
  50. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_sano.yaml +14 -0
  51. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_surface_intact_default.yaml +36 -0
  52. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_location.yaml +229 -0
  53. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
  54. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_size.yaml +82 -0
  55. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
  56. endoreg_db/data/_examples/finding_classification_choice/complication_generic_types.yaml +15 -0
  57. endoreg_db/data/_examples/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
  58. endoreg_db/data/_examples/finding_classification_choice/histology.yaml +24 -0
  59. endoreg_db/data/_examples/finding_classification_choice/histology_polyp.yaml +20 -0
  60. endoreg_db/data/_examples/finding_classification_choice/outcome.yaml +19 -0
  61. endoreg_db/data/_examples/finding_classification_choice/yes_no_na.yaml +11 -0
  62. endoreg_db/data/_examples/finding_classification_type/colonoscopy_basic.yaml +48 -0
  63. endoreg_db/data/_examples/finding_intervention/endoscopy.yaml +43 -0
  64. endoreg_db/data/_examples/finding_intervention/endoscopy_colonoscopy.yaml +168 -0
  65. endoreg_db/data/_examples/finding_intervention/endoscopy_egd.yaml +128 -0
  66. endoreg_db/data/_examples/finding_intervention/endoscopy_ercp.yaml +32 -0
  67. endoreg_db/data/_examples/finding_intervention/endoscopy_eus_lower.yaml +9 -0
  68. endoreg_db/data/_examples/finding_intervention/endoscopy_eus_upper.yaml +36 -0
  69. endoreg_db/data/_examples/finding_intervention_type/endoscopy.yaml +15 -0
  70. endoreg_db/data/_examples/finding_type/data.yaml +43 -0
  71. endoreg_db/data/_examples/requirement/age.yaml +26 -0
  72. endoreg_db/data/_examples/requirement/colonoscopy_baseline_austria.yaml +45 -0
  73. endoreg_db/data/_examples/requirement/disease_cardiovascular.yaml +79 -0
  74. endoreg_db/data/_examples/requirement/disease_classification_choice_cardiovascular.yaml +41 -0
  75. endoreg_db/data/_examples/requirement/disease_hepatology.yaml +12 -0
  76. endoreg_db/data/_examples/requirement/disease_misc.yaml +12 -0
  77. endoreg_db/data/_examples/requirement/disease_renal.yaml +96 -0
  78. endoreg_db/data/_examples/requirement/endoscopy_bleeding_risk.yaml +59 -0
  79. endoreg_db/data/_examples/requirement/event_cardiology.yaml +251 -0
  80. endoreg_db/data/_examples/requirement/event_requirements.yaml +145 -0
  81. endoreg_db/data/_examples/requirement/finding_colon_polyp.yaml +50 -0
  82. endoreg_db/data/_examples/requirement/gender.yaml +25 -0
  83. endoreg_db/data/_examples/requirement/lab_value.yaml +441 -0
  84. endoreg_db/data/_examples/requirement/medication.yaml +93 -0
  85. endoreg_db/data/_examples/requirement_operator/age.yaml +13 -0
  86. endoreg_db/data/_examples/requirement_operator/lab_operators.yaml +129 -0
  87. endoreg_db/data/_examples/requirement_operator/model_operators.yaml +96 -0
  88. endoreg_db/data/_examples/requirement_set/01_endoscopy_generic.yaml +48 -0
  89. endoreg_db/data/_examples/requirement_set/colonoscopy_austria_screening.yaml +57 -0
  90. endoreg_db/data/_examples/yaml_examples.xlsx +0 -0
  91. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +4 -3
  92. endoreg_db/data/event_classification/data.yaml +4 -0
  93. endoreg_db/data/event_classification_choice/data.yaml +9 -0
  94. endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +43 -70
  95. endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +22 -52
  96. endoreg_db/data/finding_classification/colonoscopy_location.yaml +31 -62
  97. endoreg_db/data/finding_classification/histology_colo.yaml +28 -36
  98. endoreg_db/data/requirement/colon_polyp_intervention.yaml +49 -0
  99. endoreg_db/data/requirement/coloreg_colon_polyp.yaml +49 -0
  100. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +31 -12
  101. endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
  102. endoreg_db/data/requirement_set/02_endoscopy_bleeding_risk.yaml +46 -0
  103. endoreg_db/data/requirement_set/90_coloreg.yaml +178 -0
  104. endoreg_db/data/requirement_set/_old_ +109 -0
  105. endoreg_db/data/requirement_set_type/data.yaml +21 -0
  106. endoreg_db/data/setup_config.yaml +4 -4
  107. endoreg_db/data/tag/requirement_set_tags.yaml +21 -0
  108. endoreg_db/exceptions.py +5 -2
  109. endoreg_db/helpers/data_loader.py +1 -1
  110. endoreg_db/management/commands/create_model_meta_from_huggingface.py +21 -10
  111. endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
  112. endoreg_db/management/commands/import_video.py +9 -10
  113. endoreg_db/management/commands/import_video_with_classification.py +1 -1
  114. endoreg_db/management/commands/init_default_ai_model.py +1 -1
  115. endoreg_db/management/commands/list_routes.py +18 -0
  116. endoreg_db/management/commands/load_ai_model_data.py +2 -1
  117. endoreg_db/management/commands/load_center_data.py +12 -12
  118. endoreg_db/management/commands/load_requirement_data.py +60 -31
  119. endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
  120. endoreg_db/management/commands/setup_endoreg_db.py +14 -10
  121. endoreg_db/management/commands/storage_management.py +271 -203
  122. endoreg_db/migrations/0001_initial.py +1799 -1300
  123. endoreg_db/migrations/0002_requirementset_depends_on.py +18 -0
  124. endoreg_db/migrations/_old/0001_initial.py +1857 -0
  125. endoreg_db/migrations/_old/0004_employee_city_employee_post_code_employee_street_and_more.py +68 -0
  126. endoreg_db/migrations/_old/0004_remove_casetemplate_rules_and_more.py +77 -0
  127. endoreg_db/migrations/_old/0005_merge_20251111_1003.py +14 -0
  128. endoreg_db/migrations/_old/0006_sensitivemeta_anonymized_text_and_more.py +68 -0
  129. endoreg_db/migrations/_old/0007_remove_rule_attribute_dtype_remove_rule_rule_type_and_more.py +89 -0
  130. endoreg_db/migrations/_old/0008_remove_event_event_classification_and_more.py +27 -0
  131. endoreg_db/migrations/_old/0009_alter_modelmeta_options_and_more.py +21 -0
  132. endoreg_db/models/__init__.py +78 -123
  133. endoreg_db/models/administration/__init__.py +21 -42
  134. endoreg_db/models/administration/ai/active_model.py +2 -2
  135. endoreg_db/models/administration/ai/ai_model.py +7 -6
  136. endoreg_db/models/administration/case/__init__.py +1 -15
  137. endoreg_db/models/administration/case/case.py +3 -3
  138. endoreg_db/models/administration/case/case_template/__init__.py +2 -14
  139. endoreg_db/models/administration/case/case_template/case_template.py +2 -124
  140. endoreg_db/models/administration/case/case_template/case_template_rule.py +2 -268
  141. endoreg_db/models/administration/case/case_template/case_template_rule_value.py +2 -85
  142. endoreg_db/models/administration/case/case_template/case_template_type.py +2 -25
  143. endoreg_db/models/administration/center/center.py +33 -19
  144. endoreg_db/models/administration/center/center_product.py +12 -9
  145. endoreg_db/models/administration/center/center_resource.py +25 -19
  146. endoreg_db/models/administration/center/center_shift.py +21 -17
  147. endoreg_db/models/administration/center/center_waste.py +16 -8
  148. endoreg_db/models/administration/person/__init__.py +2 -0
  149. endoreg_db/models/administration/person/employee/employee.py +10 -5
  150. endoreg_db/models/administration/person/employee/employee_qualification.py +9 -4
  151. endoreg_db/models/administration/person/employee/employee_type.py +12 -6
  152. endoreg_db/models/administration/person/examiner/examiner.py +13 -11
  153. endoreg_db/models/administration/person/patient/__init__.py +2 -0
  154. endoreg_db/models/administration/person/patient/patient.py +103 -100
  155. endoreg_db/models/administration/person/patient/patient_external_id.py +37 -0
  156. endoreg_db/models/administration/person/person.py +4 -0
  157. endoreg_db/models/administration/person/profession/__init__.py +8 -4
  158. endoreg_db/models/administration/person/user/portal_user_information.py +11 -7
  159. endoreg_db/models/administration/product/product.py +20 -15
  160. endoreg_db/models/administration/product/product_material.py +17 -18
  161. endoreg_db/models/administration/product/product_weight.py +12 -8
  162. endoreg_db/models/administration/product/reference_product.py +23 -55
  163. endoreg_db/models/administration/qualification/qualification.py +7 -3
  164. endoreg_db/models/administration/qualification/qualification_type.py +7 -3
  165. endoreg_db/models/administration/shift/scheduled_days.py +8 -5
  166. endoreg_db/models/administration/shift/shift.py +16 -12
  167. endoreg_db/models/administration/shift/shift_type.py +23 -31
  168. endoreg_db/models/label/__init__.py +7 -8
  169. endoreg_db/models/label/annotation/image_classification.py +10 -9
  170. endoreg_db/models/label/annotation/video_segmentation_annotation.py +8 -5
  171. endoreg_db/models/label/label.py +15 -15
  172. endoreg_db/models/label/label_set.py +19 -6
  173. endoreg_db/models/label/label_type.py +1 -1
  174. endoreg_db/models/label/label_video_segment/_create_from_video.py +5 -8
  175. endoreg_db/models/label/label_video_segment/label_video_segment.py +76 -102
  176. endoreg_db/models/label/video_segmentation_label.py +4 -0
  177. endoreg_db/models/label/video_segmentation_labelset.py +4 -3
  178. endoreg_db/models/media/frame/frame.py +22 -22
  179. endoreg_db/models/media/pdf/raw_pdf.py +249 -177
  180. endoreg_db/models/media/pdf/report_file.py +25 -29
  181. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +30 -46
  182. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
  183. endoreg_db/models/media/video/__init__.py +1 -0
  184. endoreg_db/models/media/video/create_from_file.py +48 -56
  185. endoreg_db/models/media/video/pipe_1.py +30 -33
  186. endoreg_db/models/media/video/pipe_2.py +8 -9
  187. endoreg_db/models/media/video/video_file.py +359 -204
  188. endoreg_db/models/media/video/video_file_ai.py +288 -74
  189. endoreg_db/models/media/video/video_file_anonymize.py +38 -38
  190. endoreg_db/models/media/video/video_file_frames/__init__.py +3 -1
  191. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -8
  192. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +7 -9
  193. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +9 -8
  194. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +38 -45
  195. endoreg_db/models/media/video/video_file_frames/_get_frame.py +6 -8
  196. endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +4 -18
  197. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -3
  198. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +7 -6
  199. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +6 -8
  200. endoreg_db/models/media/video/video_file_frames/_get_frames.py +6 -8
  201. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +15 -25
  202. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +26 -23
  203. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +23 -14
  204. endoreg_db/models/media/video/video_file_io.py +109 -62
  205. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +3 -3
  206. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +5 -3
  207. endoreg_db/models/media/video/video_file_meta/get_fps.py +37 -34
  208. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +19 -25
  209. endoreg_db/models/media/video/video_file_meta/text_meta.py +41 -38
  210. endoreg_db/models/media/video/video_file_meta/video_meta.py +14 -7
  211. endoreg_db/models/media/video/video_file_segments.py +24 -17
  212. endoreg_db/models/media/video/video_metadata.py +19 -35
  213. endoreg_db/models/media/video/video_processing.py +96 -95
  214. endoreg_db/models/medical/contraindication/__init__.py +13 -3
  215. endoreg_db/models/medical/disease.py +22 -16
  216. endoreg_db/models/medical/event.py +31 -18
  217. endoreg_db/models/medical/examination/__init__.py +13 -6
  218. endoreg_db/models/medical/examination/examination.py +17 -18
  219. endoreg_db/models/medical/examination/examination_indication.py +26 -25
  220. endoreg_db/models/medical/examination/examination_time.py +16 -6
  221. endoreg_db/models/medical/examination/examination_time_type.py +9 -6
  222. endoreg_db/models/medical/examination/examination_type.py +3 -4
  223. endoreg_db/models/medical/finding/finding.py +38 -39
  224. endoreg_db/models/medical/finding/finding_classification.py +37 -48
  225. endoreg_db/models/medical/finding/finding_intervention.py +27 -22
  226. endoreg_db/models/medical/finding/finding_type.py +13 -12
  227. endoreg_db/models/medical/hardware/endoscope.py +20 -26
  228. endoreg_db/models/medical/hardware/endoscopy_processor.py +2 -2
  229. endoreg_db/models/medical/laboratory/lab_value.py +62 -91
  230. endoreg_db/models/medical/medication/medication.py +22 -10
  231. endoreg_db/models/medical/medication/medication_indication.py +29 -3
  232. endoreg_db/models/medical/medication/medication_indication_type.py +25 -14
  233. endoreg_db/models/medical/medication/medication_intake_time.py +31 -19
  234. endoreg_db/models/medical/medication/medication_schedule.py +27 -16
  235. endoreg_db/models/medical/organ/__init__.py +15 -12
  236. endoreg_db/models/medical/patient/medication_examples.py +1 -5
  237. endoreg_db/models/medical/patient/patient_disease.py +20 -23
  238. endoreg_db/models/medical/patient/patient_event.py +19 -22
  239. endoreg_db/models/medical/patient/patient_examination.py +48 -54
  240. endoreg_db/models/medical/patient/patient_examination_indication.py +16 -14
  241. endoreg_db/models/medical/patient/patient_finding.py +122 -139
  242. endoreg_db/models/medical/patient/patient_finding_classification.py +44 -49
  243. endoreg_db/models/medical/patient/patient_finding_intervention.py +8 -19
  244. endoreg_db/models/medical/patient/patient_lab_sample.py +28 -23
  245. endoreg_db/models/medical/patient/patient_lab_value.py +82 -89
  246. endoreg_db/models/medical/patient/patient_medication.py +27 -38
  247. endoreg_db/models/medical/patient/patient_medication_schedule.py +28 -36
  248. endoreg_db/models/medical/risk/risk.py +7 -6
  249. endoreg_db/models/medical/risk/risk_type.py +8 -5
  250. endoreg_db/models/metadata/model_meta.py +60 -29
  251. endoreg_db/models/metadata/model_meta_logic.py +139 -18
  252. endoreg_db/models/metadata/pdf_meta.py +19 -24
  253. endoreg_db/models/metadata/sensitive_meta.py +102 -85
  254. endoreg_db/models/metadata/sensitive_meta_logic.py +383 -43
  255. endoreg_db/models/metadata/video_meta.py +51 -31
  256. endoreg_db/models/metadata/video_prediction_logic.py +16 -23
  257. endoreg_db/models/metadata/video_prediction_meta.py +29 -33
  258. endoreg_db/models/other/distribution/date_value_distribution.py +89 -29
  259. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +21 -5
  260. endoreg_db/models/other/distribution/numeric_value_distribution.py +114 -53
  261. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +4 -3
  262. endoreg_db/models/other/emission/emission_factor.py +18 -8
  263. endoreg_db/models/other/gender.py +10 -5
  264. endoreg_db/models/other/information_source.py +25 -25
  265. endoreg_db/models/other/material.py +9 -5
  266. endoreg_db/models/other/resource.py +6 -4
  267. endoreg_db/models/other/tag.py +10 -5
  268. endoreg_db/models/other/transport_route.py +13 -8
  269. endoreg_db/models/other/unit.py +10 -6
  270. endoreg_db/models/other/waste.py +6 -5
  271. endoreg_db/models/requirement/requirement.py +580 -272
  272. endoreg_db/models/requirement/requirement_error.py +85 -0
  273. endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
  274. endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +3 -6
  275. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +90 -64
  276. endoreg_db/models/requirement/requirement_operator.py +36 -33
  277. endoreg_db/models/requirement/requirement_set.py +74 -57
  278. endoreg_db/models/state/__init__.py +4 -4
  279. endoreg_db/models/state/abstract.py +2 -2
  280. endoreg_db/models/state/anonymization.py +12 -0
  281. endoreg_db/models/state/audit_ledger.py +46 -47
  282. endoreg_db/models/state/label_video_segment.py +9 -0
  283. endoreg_db/models/state/raw_pdf.py +40 -46
  284. endoreg_db/models/state/sensitive_meta.py +6 -2
  285. endoreg_db/models/state/video.py +58 -53
  286. endoreg_db/models/upload_job.py +32 -55
  287. endoreg_db/models/utils.py +1 -2
  288. endoreg_db/root_urls.py +21 -2
  289. endoreg_db/serializers/__init__.py +26 -57
  290. endoreg_db/serializers/anonymization.py +18 -10
  291. endoreg_db/serializers/meta/report_meta.py +1 -1
  292. endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
  293. endoreg_db/serializers/misc/__init__.py +1 -1
  294. endoreg_db/serializers/misc/file_overview.py +33 -91
  295. endoreg_db/serializers/misc/{vop_patient_data.py → sensitive_patient_data.py} +1 -1
  296. endoreg_db/serializers/requirements/requirement_sets.py +92 -22
  297. endoreg_db/serializers/video/segmentation.py +2 -1
  298. endoreg_db/serializers/video/video_processing_history.py +20 -5
  299. endoreg_db/serializers/video_examination.py +198 -0
  300. endoreg_db/services/anonymization.py +75 -73
  301. endoreg_db/services/lookup_service.py +256 -73
  302. endoreg_db/services/lookup_store.py +174 -30
  303. endoreg_db/services/pdf_import.py +711 -310
  304. endoreg_db/services/storage_aware_video_processor.py +140 -114
  305. endoreg_db/services/video_import.py +266 -117
  306. endoreg_db/urls/__init__.py +27 -27
  307. endoreg_db/urls/label_video_segments.py +2 -0
  308. endoreg_db/urls/media.py +108 -66
  309. endoreg_db/urls/root_urls.py +29 -0
  310. endoreg_db/utils/__init__.py +15 -5
  311. endoreg_db/utils/ai/multilabel_classification_net.py +116 -20
  312. endoreg_db/utils/case_generator/__init__.py +3 -0
  313. endoreg_db/utils/dataloader.py +88 -16
  314. endoreg_db/utils/defaults/set_default_center.py +32 -0
  315. endoreg_db/utils/names.py +22 -16
  316. endoreg_db/utils/permissions.py +2 -1
  317. endoreg_db/utils/pipelines/process_video_dir.py +1 -1
  318. endoreg_db/utils/requirement_operator_logic/model_evaluators.py +414 -127
  319. endoreg_db/utils/setup_config.py +8 -5
  320. endoreg_db/utils/storage.py +115 -0
  321. endoreg_db/utils/validate_endo_roi.py +8 -2
  322. endoreg_db/utils/video/ffmpeg_wrapper.py +184 -188
  323. endoreg_db/views/__init__.py +5 -12
  324. endoreg_db/views/anonymization/media_management.py +198 -163
  325. endoreg_db/views/anonymization/overview.py +4 -1
  326. endoreg_db/views/anonymization/validate.py +174 -40
  327. endoreg_db/views/media/__init__.py +2 -0
  328. endoreg_db/views/media/pdf_media.py +131 -150
  329. endoreg_db/views/media/sensitive_metadata.py +46 -6
  330. endoreg_db/views/media/video_media.py +89 -82
  331. endoreg_db/views/media/video_segments.py +187 -260
  332. endoreg_db/views/meta/sensitive_meta_detail.py +0 -63
  333. endoreg_db/views/patient/patient.py +5 -4
  334. endoreg_db/views/pdf/__init__.py +5 -8
  335. endoreg_db/views/pdf/pdf_stream.py +186 -0
  336. endoreg_db/views/pdf/pdf_stream_views.py +0 -127
  337. endoreg_db/views/pdf/reimport.py +86 -91
  338. endoreg_db/views/requirement/evaluate.py +188 -187
  339. endoreg_db/views/requirement/lookup.py +186 -288
  340. endoreg_db/views/requirement/requirement_utils.py +89 -0
  341. endoreg_db/views/video/__init__.py +0 -4
  342. endoreg_db/views/video/correction.py +2 -2
  343. endoreg_db/views/video/video_examination_viewset.py +202 -289
  344. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/METADATA +7 -3
  345. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/RECORD +350 -255
  346. endoreg_db/models/administration/permissions/__init__.py +0 -44
  347. endoreg_db/models/media/video/refactor_plan.md +0 -0
  348. endoreg_db/models/media/video/video_file_frames.py +0 -0
  349. endoreg_db/models/metadata/frame_ocr_result.py +0 -0
  350. endoreg_db/models/rule/__init__.py +0 -13
  351. endoreg_db/models/rule/rule.py +0 -27
  352. endoreg_db/models/rule/rule_applicator.py +0 -224
  353. endoreg_db/models/rule/rule_attribute_dtype.py +0 -17
  354. endoreg_db/models/rule/rule_type.py +0 -20
  355. endoreg_db/models/rule/ruleset.py +0 -17
  356. endoreg_db/serializers/video/video_metadata.py +0 -105
  357. endoreg_db/urls/report.py +0 -48
  358. endoreg_db/urls/video.py +0 -61
  359. endoreg_db/utils/case_generator/case_generator.py +0 -159
  360. endoreg_db/utils/case_generator/utils.py +0 -30
  361. endoreg_db/views/pdf/pdf_media.py +0 -239
  362. endoreg_db/views/report/__init__.py +0 -9
  363. endoreg_db/views/report/report_list.py +0 -112
  364. endoreg_db/views/report/report_with_secure_url.py +0 -28
  365. endoreg_db/views/report/start_examination.py +0 -7
  366. endoreg_db/views/video/video_media.py +0 -158
  367. endoreg_db/views.py +0 -0
  368. /endoreg_db/data/{requirement_set → _examples/requirement_set}/endoscopy_bleeding_risk.yaml +0 -0
  369. /endoreg_db/migrations/{0002_add_video_correction_models.py → _old/0002_add_video_correction_models.py} +0 -0
  370. /endoreg_db/migrations/{0003_add_center_display_name.py → _old/0003_add_center_display_name.py} +0 -0
  371. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/WHEEL +0 -0
  372. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,19 +1,22 @@
1
- from django.db import models
2
- import pandas as pd
3
1
  from typing import TYPE_CHECKING
4
2
 
3
+ import pandas as pd
4
+ from django.db import models
5
+
5
6
  if TYPE_CHECKING:
6
- from .product import Product
7
7
  from ...other.unit import Unit
8
+ from .product import Product
9
+
8
10
 
9
11
  class ProductWeightManager(models.Manager):
10
12
  def get_by_natural_key(self, product, product_group, weight):
11
13
  return self.get(product=product, product_group=product_group, weight=weight)
12
-
14
+
15
+
13
16
  class ProductWeight(models.Model):
14
17
  objects = ProductWeightManager()
15
18
 
16
- name = models.CharField(max_length=255, null = True)
19
+ name = models.CharField(max_length=255, null=True)
17
20
  product = models.ForeignKey("Product", on_delete=models.CASCADE)
18
21
  measured = models.FloatField(null=True)
19
22
  verified = models.FloatField(null=True)
@@ -21,8 +24,8 @@ class ProductWeight(models.Model):
21
24
  unit = models.ForeignKey("Unit", on_delete=models.SET_NULL, null=True)
22
25
 
23
26
  if TYPE_CHECKING:
24
- product: "Product"
25
- unit: "Unit"
27
+ product: models.ForeignKey["Product"]
28
+ unit: models.ForeignKey["Unit|None"]
26
29
 
27
30
  def get_weight(self):
28
31
  if not pd.isnull(self.verified):
@@ -33,7 +36,7 @@ class ProductWeight(models.Model):
33
36
  return self.manufacturer
34
37
  else:
35
38
  return None
36
-
39
+
37
40
  def get_weight_source(self):
38
41
  if not pd.isnull(self.verified):
39
42
  return "verified"
@@ -43,5 +46,6 @@ class ProductWeight(models.Model):
43
46
  return "manufacturer"
44
47
  else:
45
48
  return None
49
+
46
50
  def __str__(self):
47
51
  return f"{self.product} - {self.get_weight()} {self.unit} (Source: {self.get_weight_source()})"
@@ -1,13 +1,18 @@
1
- from django.db import models
2
1
  from typing import TYPE_CHECKING
2
+
3
+ from django.db import models
4
+
3
5
  if TYPE_CHECKING:
4
6
  from ...other.emission import EmissionFactor
5
7
  from .product import Product
6
8
  from .product_group import ProductGroup
9
+
10
+
7
11
  class ReferenceProductManager(models.Manager):
8
- def get_by_natural_key(self, product_name:str, product_group_name:str):
12
+ def get_by_natural_key(self, product_name: str, product_group_name: str):
9
13
  return self.get(product__name=product_name, product_group__name=product_group_name)
10
14
 
15
+
11
16
  class ReferenceProduct(models.Model):
12
17
  name = models.CharField(max_length=255)
13
18
  product = models.ForeignKey(
@@ -18,51 +23,32 @@ class ReferenceProduct(models.Model):
18
23
  product_group = models.OneToOneField(
19
24
  "ProductGroup",
20
25
  on_delete=models.CASCADE,
21
- related_name="reference_product" # Changed from "reference_products"
22
- )
23
- emission_factor_total = models.ForeignKey(
24
- "EmissionFactor",
25
- on_delete=models.SET_NULL,
26
- null=True,
27
- blank = True,
28
- related_name="reference_products"
29
- )
30
- emission_factor_package = models.ForeignKey(
31
- "EmissionFactor",
32
- on_delete=models.SET_NULL,
33
- null=True,
34
- related_name="reference_product_package"
35
- )
36
- emission_factor_product = models.ForeignKey(
37
- "EmissionFactor",
38
- on_delete=models.SET_NULL,
39
- null=True,
40
- related_name="reference_product_product"
26
+ related_name="reference_product", # Changed from "reference_products"
41
27
  )
28
+ emission_factor_total = models.ForeignKey("EmissionFactor", on_delete=models.SET_NULL, null=True, blank=True, related_name="reference_products")
29
+ emission_factor_package = models.ForeignKey("EmissionFactor", on_delete=models.SET_NULL, null=True, related_name="reference_product_package")
30
+ emission_factor_product = models.ForeignKey("EmissionFactor", on_delete=models.SET_NULL, null=True, related_name="reference_product_product")
42
31
 
43
32
  if TYPE_CHECKING:
44
- product: "Product"
45
- product_group: "ProductGroup"
46
- emission_factor_total: "EmissionFactor"
47
- emission_factor_package: "EmissionFactor"
48
- emission_factor_product: "EmissionFactor"
49
-
33
+ product: models.ForeignKey["Product"]
34
+ product_group: models.ForeignKey["ProductGroup"]
35
+ emission_factor_total: models.ForeignKey["EmissionFactor|None"]
36
+ emission_factor_package: models.ForeignKey["EmissionFactor|None"]
37
+ emission_factor_product: models.ForeignKey["EmissionFactor|None"]
38
+
50
39
  objects = ReferenceProductManager()
51
40
 
52
41
  def __str__(self):
53
42
  return self.product.name + " (" + self.product_group.name + ")"
54
-
43
+
55
44
  def set_emission_factors(self):
56
45
  from ...other.emission import EmissionFactor
46
+
57
47
  product = self.product
58
- materials = product.product_materials.all()
59
48
  emission_factor_name = f"{self.product_group.name}_{product.name}_total_emission_factor"
60
49
  emission_factor_package_name = f"{self.product_group.name}_{product.name}_package_emission_factor"
61
50
  emission_factor_product_name = f"{self.product_group.name}_{product.name}_product_emission_factor"
62
51
 
63
- product_emissions = 0
64
- package_emissions = 0
65
-
66
52
  product_weight, product_weight_unit = product.get_product_material_weight()
67
53
  package_weight, package_weight_unit = product.get_package_material_weight()
68
54
  product_emission, product_emission_unit = product.get_product_material_emission()
@@ -81,38 +67,23 @@ class ReferenceProduct(models.Model):
81
67
  total_emission_factor_value = total_emission / total_weight
82
68
 
83
69
  emission_factor, created = EmissionFactor.objects.get_or_create(
84
- name=emission_factor_name,
85
- defaults={
86
- "name": emission_factor_name,
87
- "value": total_emission_factor_value,
88
- "unit": reference_unit
89
- }
70
+ name=emission_factor_name, defaults={"name": emission_factor_name, "value": total_emission_factor_value, "unit": reference_unit}
90
71
  )
91
72
  self.emission_factor_total = emission_factor
92
73
 
93
74
  emission_factor_package, created = EmissionFactor.objects.get_or_create(
94
- name=emission_factor_package_name,
95
- defaults={
96
- "name": emission_factor_package_name,
97
- "value": package_emission_factor_value,
98
- "unit": reference_unit
99
- }
75
+ name=emission_factor_package_name, defaults={"name": emission_factor_package_name, "value": package_emission_factor_value, "unit": reference_unit}
100
76
  )
101
77
  self.emission_factor_package = emission_factor_package
102
78
 
103
79
  emission_factor_product, created = EmissionFactor.objects.get_or_create(
104
- name=emission_factor_product_name,
105
- defaults={
106
- "name": emission_factor_product_name,
107
- "value": product_emission_factor_value,
108
- "unit": reference_unit
109
- }
80
+ name=emission_factor_product_name, defaults={"name": emission_factor_product_name, "value": product_emission_factor_value, "unit": reference_unit}
110
81
  )
111
82
  self.emission_factor_product = emission_factor_product
112
83
 
113
84
  self.save()
114
85
 
115
- def get_emission_factor(self, component:str):
86
+ def get_emission_factor(self, component: str):
116
87
  # check if emission_factor_total exists:
117
88
  if self.emission_factor_total is None:
118
89
  self.set_emission_factors()
@@ -125,6 +96,3 @@ class ReferenceProduct(models.Model):
125
96
  return self.emission_factor_product
126
97
  else:
127
98
  raise Exception("Unknown component: " + component)
128
-
129
-
130
-
@@ -1,22 +1,26 @@
1
+ from typing import TYPE_CHECKING, cast
2
+
1
3
  from django.db import models
2
- from typing import TYPE_CHECKING
3
4
 
4
5
  if TYPE_CHECKING:
5
6
  from endoreg_db.models import (
6
7
  QualificationType,
7
8
  )
8
9
 
10
+
9
11
  class QualificationManager(models.Manager):
10
12
  def get_queryset(self):
11
13
  """
12
14
  Returns a queryset of qualifications filtered to include only active entries.
13
15
  """
14
16
  return super().get_queryset().filter(is_active=True)
15
-
17
+
18
+
16
19
  class Qualification(models.Model):
17
20
  """
18
21
  Model representing a qualification.
19
22
  """
23
+
20
24
  name = models.CharField(max_length=255, unique=True)
21
25
  description = models.TextField(blank=True, null=True)
22
26
  is_active = models.BooleanField(default=True)
@@ -26,7 +30,7 @@ class Qualification(models.Model):
26
30
  related_name="qualifications",
27
31
  )
28
32
  if TYPE_CHECKING:
29
- qualification_types: models.QuerySet["QualificationType"]
33
+ qualification_types = cast(models.manager.RelatedManager["QualificationType"], qualification_types)
30
34
 
31
35
  objects = QualificationManager()
32
36
 
@@ -1,24 +1,28 @@
1
- from django.db import models
2
1
  from typing import TYPE_CHECKING
3
2
 
3
+ from django.db import models
4
+
4
5
  if TYPE_CHECKING:
5
6
  from endoreg_db.models import (
6
7
  Qualification,
7
8
  )
8
9
 
10
+
9
11
  class QualificationTypeManager(models.Manager):
10
12
  def get_queryset(self):
11
13
  """
12
14
  Returns a queryset of active qualification types.
13
-
15
+
14
16
  Only includes records where the `is_active` field is set to True.
15
17
  """
16
18
  return super().get_queryset().filter(is_active=True)
17
-
19
+
20
+
18
21
  class QualificationType(models.Model):
19
22
  """
20
23
  Model representing a qualification type.
21
24
  """
25
+
22
26
  name = models.CharField(max_length=255, unique=True)
23
27
  description = models.TextField(blank=True, null=True)
24
28
  is_active = models.BooleanField(default=True)
@@ -1,29 +1,32 @@
1
- from django.db import models
2
-
3
1
  from typing import TYPE_CHECKING
4
2
 
3
+ from django.db import models
4
+
5
5
  if TYPE_CHECKING:
6
6
  from endoreg_db.models import (
7
7
  CenterShift,
8
8
  )
9
9
 
10
+
10
11
  class ScheduledDaysManager(models.Manager):
11
12
  def get_by_natural_key(self, name):
12
13
  """
13
14
  Retrieves a ScheduledDays instance by its unique name.
14
-
15
+
15
16
  Args:
16
17
  name: The unique name of the ScheduledDays instance to retrieve.
17
-
18
+
18
19
  Returns:
19
20
  The ScheduledDays instance matching the given name.
20
21
  """
21
22
  return self.get(name=name)
22
-
23
+
24
+
23
25
  class ScheduledDays(models.Model):
24
26
  """
25
27
  Model representing scheduled days for a shift.
26
28
  """
29
+
27
30
  name = models.CharField(
28
31
  max_length=255,
29
32
  unique=True,
@@ -1,31 +1,33 @@
1
- from django.db import models
2
- from typing import TYPE_CHECKING
1
+ from typing import TYPE_CHECKING, cast
3
2
 
3
+ from django.db import models
4
4
 
5
5
  if TYPE_CHECKING:
6
6
  from endoreg_db.models import (
7
- ShiftType,
8
- Qualification,
9
7
  CenterShift,
8
+ Qualification,
9
+ ShiftType,
10
10
  )
11
11
 
12
+
12
13
  class ShiftManager(models.Manager):
13
14
  def get_queryset(self):
14
15
  """
15
16
  Returns a queryset of active shifts.
16
-
17
+
17
18
  Only includes shifts where the 'is_active' field is set to True.
18
19
  """
19
20
  return super().get_queryset().filter(is_active=True)
20
-
21
+
22
+
21
23
  class Shift(models.Model):
22
24
  """
23
25
  Model representing a shift.
24
26
  """
27
+
25
28
  name = models.CharField(max_length=255, unique=True)
26
29
  description = models.TextField(blank=True, null=True)
27
- is_active = models.BooleanField(default=True)
28
-
30
+ is_active = models.BooleanField(default=True)
29
31
 
30
32
  shift_types = models.ManyToManyField(
31
33
  "ShiftType",
@@ -38,9 +40,11 @@ class Shift(models.Model):
38
40
  )
39
41
 
40
42
  if TYPE_CHECKING:
41
- shift_types: models.QuerySet["ShiftType"]
42
- required_qualifications: models.QuerySet["Qualification"]
43
- center_shifts: models.QuerySet["CenterShift"]
43
+ shift_types = cast(models.QuerySet["ShiftType"], shift_types)
44
+ required_qualifications = cast(models.QuerySet["Qualification"], required_qualifications)
45
+
46
+ @property
47
+ def center_shifts(self) -> models.QuerySet["CenterShift"]: ...
44
48
 
45
49
  objects = ShiftManager()
46
50
 
@@ -48,4 +52,4 @@ class Shift(models.Model):
48
52
  """
49
53
  Returns the string representation of the shift using its name.
50
54
  """
51
- return str(self.name)
55
+ return str(self.name)
@@ -1,7 +1,8 @@
1
- import logging # Added import
2
- from django.db import models
1
+ import logging # Added import
3
2
  from typing import TYPE_CHECKING
4
3
 
4
+ from django.db import models
5
+
5
6
  if TYPE_CHECKING:
6
7
  from endoreg_db.models import Shift
7
8
 
@@ -11,7 +12,8 @@ NAME_ON_CALL = "on_call"
11
12
  NAME_WARD = "ward"
12
13
  NAME_OFF_HOURS = "off_hours"
13
14
 
14
- logger = logging.getLogger(__name__) # Added logger
15
+ logger = logging.getLogger(__name__) # Added logger
16
+
15
17
 
16
18
  class ShiftTypeManager(models.Manager):
17
19
  def get_queryset(self):
@@ -19,11 +21,13 @@ class ShiftTypeManager(models.Manager):
19
21
  Returns a queryset containing only active shift types.
20
22
  """
21
23
  return super().get_queryset().filter(is_active=True)
22
-
24
+
25
+
23
26
  class ShiftType(models.Model):
24
27
  """
25
28
  Model representing a Shift type.
26
29
  """
30
+
27
31
  name = models.CharField(max_length=255, unique=True)
28
32
  description = models.TextField(blank=True, null=True)
29
33
  is_active = models.BooleanField(default=True)
@@ -40,69 +44,57 @@ class ShiftType(models.Model):
40
44
  return str(self.name)
41
45
 
42
46
  @classmethod
43
- def get_type_regular(cls) -> "ShiftType | None": # Modified return type
47
+ def get_type_regular(cls) -> "ShiftType | None": # Modified return type
44
48
  """
45
49
  Retrieves the 'regular' shift type instance.
46
-
50
+
47
51
  Returns:
48
52
  The ShiftType instance with the name 'regular', or None if it does not exist.
49
53
  """
50
54
  try:
51
55
  return cls.objects.get(name=NAME_REGULAR)
52
56
  except cls.DoesNotExist:
53
- logger.error(
54
- f"ShiftType with name '{NAME_REGULAR}' does not exist. "
55
- "Base data might be missing."
56
- )
57
+ logger.error(f"ShiftType with name '{NAME_REGULAR}' does not exist. Base data might be missing.")
57
58
  return None
58
-
59
+
59
60
  @classmethod
60
- def get_type_on_call(cls) -> "ShiftType | None": # Modified return type
61
+ def get_type_on_call(cls) -> "ShiftType | None": # Modified return type
61
62
  """
62
63
  Retrieves the ShiftType instance representing the on-call shift type.
63
-
64
+
64
65
  Returns:
65
66
  The ShiftType instance with the on-call name, or None if it does not exist.
66
67
  """
67
68
  try:
68
69
  return cls.objects.get(name=NAME_ON_CALL)
69
70
  except cls.DoesNotExist:
70
- logger.error(
71
- f"ShiftType with name '{NAME_ON_CALL}' does not exist. "
72
- "Base data might be missing."
73
- )
71
+ logger.error(f"ShiftType with name '{NAME_ON_CALL}' does not exist. Base data might be missing.")
74
72
  return None
75
-
73
+
76
74
  @classmethod
77
- def get_type_ward(cls) -> "ShiftType | None": # Modified return type
75
+ def get_type_ward(cls) -> "ShiftType | None": # Modified return type
78
76
  """
79
77
  Retrieves the ShiftType instance representing a ward shift.
80
-
78
+
81
79
  Returns:
82
80
  The ShiftType instance with the name corresponding to a ward shift, or None if it does not exist.
83
81
  """
84
82
  try:
85
83
  return cls.objects.get(name=NAME_WARD)
86
84
  except cls.DoesNotExist:
87
- logger.error(
88
- f"ShiftType with name '{NAME_WARD}' does not exist. "
89
- "Base data might be missing."
90
- )
85
+ logger.error(f"ShiftType with name '{NAME_WARD}' does not exist. Base data might be missing.")
91
86
  return None
92
-
87
+
93
88
  @classmethod
94
- def get_type_off_hours(cls) -> "ShiftType | None": # Modified return type
89
+ def get_type_off_hours(cls) -> "ShiftType | None": # Modified return type
95
90
  """
96
91
  Retrieves the off-hours shift type instance by name.
97
-
92
+
98
93
  Returns:
99
94
  The ShiftType instance for off-hours if it exists, otherwise None.
100
95
  """
101
96
  try:
102
97
  return cls.objects.get(name=NAME_OFF_HOURS)
103
98
  except cls.DoesNotExist:
104
- logger.error(
105
- f"ShiftType with name '{NAME_OFF_HOURS}' does not exist. "
106
- "Base data might be missing."
107
- )
99
+ logger.error(f"ShiftType with name '{NAME_OFF_HOURS}' does not exist. Base data might be missing.")
108
100
  return None
@@ -1,16 +1,15 @@
1
+ from .annotation import (
2
+ ImageClassificationAnnotation,
3
+ VideoSegmentationAnnotation,
4
+ )
1
5
  from .label import Label
2
6
  from .label_set import LabelSet
3
7
  from .label_type import LabelType
4
- from .video_segmentation_label import VideoSegmentationLabel
5
- from .video_segmentation_labelset import VideoSegmentationLabelSet
6
8
  from .label_video_segment import (
7
9
  LabelVideoSegment,
8
10
  )
9
-
10
- from .annotation import (
11
- ImageClassificationAnnotation,
12
- VideoSegmentationAnnotation,
13
- )
11
+ from .video_segmentation_label import VideoSegmentationLabel
12
+ from .video_segmentation_labelset import VideoSegmentationLabelSet
14
13
 
15
14
  __all__ = [
16
15
  "Label",
@@ -21,4 +20,4 @@ __all__ = [
21
20
  "LabelVideoSegment",
22
21
  "ImageClassificationAnnotation",
23
22
  "VideoSegmentationAnnotation",
24
- ]
23
+ ]
@@ -1,12 +1,13 @@
1
- from django.db import models
2
-
3
1
  from typing import TYPE_CHECKING
4
2
 
3
+ from django.db import models
4
+
5
5
  if TYPE_CHECKING:
6
- from ..label import Label
7
6
  from ...media.frame import Frame
8
7
  from ...metadata import ModelMeta
9
8
  from ...other.information_source import InformationSource
9
+ from ..label import Label
10
+
10
11
 
11
12
  class ImageClassificationAnnotation(models.Model):
12
13
  """
@@ -64,15 +65,15 @@ class ImageClassificationAnnotation(models.Model):
64
65
  )
65
66
 
66
67
  if TYPE_CHECKING:
67
- frame: "Frame" # Updated type hint
68
- label: "Label"
69
- information_source: "InformationSource"
70
- model_meta: "ModelMeta" # Added for completeness
68
+ frame: models.ForeignKey["Frame"]
69
+ label: models.ForeignKey["Label"]
70
+ information_source: models.ForeignKey["InformationSource|None"]
71
+ model_meta: models.ForeignKey["ModelMeta|None"]
71
72
 
72
73
  class Meta:
73
74
  indexes = [
74
- models.Index(fields=['frame', 'label']),
75
- models.Index(fields=['frame']),
75
+ models.Index(fields=["frame", "label"]),
76
+ models.Index(fields=["frame"]),
76
77
  ]
77
78
 
78
79
  def __str__(self) -> str:
@@ -1,11 +1,13 @@
1
1
  from typing import TYPE_CHECKING
2
+
2
3
  from django.db import models
3
- from django.db.models import Q, CheckConstraint, F
4
+ from django.db.models import CheckConstraint, F, Q
4
5
 
5
6
  if TYPE_CHECKING:
6
7
  from ...media.video.video_file import VideoFile
7
8
  from ..video_segmentation_label import VideoSegmentationLabel
8
9
 
10
+
9
11
  class VideoSegmentationAnnotation(models.Model):
10
12
  """
11
13
  Represents a video segmentation annotation, linking a label to a time segment
@@ -20,6 +22,7 @@ class VideoSegmentationAnnotation(models.Model):
20
22
  stop_time (float): The stop time of the annotation in seconds.
21
23
  is_true (bool): Indicates if the annotation is valid (defaults to True).
22
24
  """
25
+
23
26
  # Foreign key to the unified VideoFile model.
24
27
  video_file = models.ForeignKey(
25
28
  "VideoFile",
@@ -35,14 +38,14 @@ class VideoSegmentationAnnotation(models.Model):
35
38
  is_true = models.BooleanField(default=True)
36
39
 
37
40
  if TYPE_CHECKING:
38
- video_file: "VideoFile"
39
- label: "VideoSegmentationLabel"
41
+ video_file: models.ForeignKey["VideoFile"]
42
+ label: models.ForeignKey["VideoSegmentationLabel"]
40
43
 
41
44
  def __str__(self) -> str:
42
45
  """
43
46
  String representation of the annotation.
44
47
  """
45
- video_repr = self.get_video() # Get the actual video object for representation
48
+ video_repr = self.get_video() # Get the actual video object for representation
46
49
  return f"{video_repr} - {self.label.name} - {self.start_time} to {self.stop_time}"
47
50
 
48
51
  def get_video(self) -> "VideoFile":
@@ -60,7 +63,7 @@ class VideoSegmentationAnnotation(models.Model):
60
63
  class Meta:
61
64
  constraints = [
62
65
  CheckConstraint(
63
- condition=Q(start_time__lt=F("stop_time")),
66
+ check=Q(start_time__lt=F("stop_time")),
64
67
  name="start_time_less_than_stop_time",
65
68
  ),
66
69
  ]
@@ -1,10 +1,12 @@
1
- from django.db import models
2
1
  from typing import TYPE_CHECKING
3
2
 
3
+ from django.db import models
4
4
 
5
5
  if TYPE_CHECKING:
6
- from .label_type import LabelType
7
6
  from .label_set import LabelSet
7
+ from .label_type import LabelType
8
+
9
+
8
10
  class LabelManager(models.Manager):
9
11
  """Manager class for handling Label model operations."""
10
12
 
@@ -25,16 +27,16 @@ class Label(models.Model):
25
27
  """
26
28
 
27
29
  name = models.CharField(max_length=255)
28
- label_type = models.ForeignKey(
29
- "LabelType", on_delete=models.CASCADE, related_name="labels", blank=True, null=True
30
- )
30
+ label_type = models.ForeignKey("LabelType", on_delete=models.CASCADE, related_name="labels", blank=True, null=True)
31
31
  description = models.TextField(blank=True, null=True)
32
32
 
33
33
  objects = LabelManager()
34
34
 
35
35
  if TYPE_CHECKING:
36
- label_type: "LabelType"
37
- label_sets: models.QuerySet["LabelSet"]
36
+ label_type: models.ForeignKey["LabelType|None"]
37
+
38
+ @property
39
+ def label_sets(self) -> models.QuerySet["LabelSet"]: ...
38
40
 
39
41
  def natural_key(self):
40
42
  """Return the natural key of this label"""
@@ -42,7 +44,7 @@ class Label(models.Model):
42
44
 
43
45
  def __str__(self):
44
46
  return str(self.name)
45
-
47
+
46
48
  @classmethod
47
49
  def get_outside_label(cls):
48
50
  """
@@ -57,7 +59,7 @@ class Label(models.Model):
57
59
  def get_low_quality_label(cls):
58
60
  """
59
61
  Retrieve the label instance with the name 'low_quality'.
60
-
62
+
61
63
  Raises:
62
64
  ValueError: If a label with the name 'low_quality' does not exist.
63
65
  """
@@ -65,19 +67,17 @@ class Label(models.Model):
65
67
  return cls.objects.get(name="low_quality")
66
68
  except Exception as exc:
67
69
  raise ValueError("'low_quality' label does not exist in the database") from exc
68
-
70
+
69
71
  @classmethod
70
- def get_or_create_from_name(cls, name:str):
72
+ def get_or_create_from_name(cls, name: str):
71
73
  """
72
74
  Retrieve or create a Label instance with the specified name.
73
-
75
+
74
76
  Parameters:
75
77
  name (str): The name of the label to retrieve or create.
76
-
78
+
77
79
  Returns:
78
80
  tuple: A tuple containing the Label instance and a boolean indicating whether the instance was created (True) or retrieved (False).
79
81
  """
80
82
  label, _created = cls.objects.get_or_create(name=name)
81
83
  return label, _created
82
-
83
-