endoreg-db 0.8.6.1__py3-none-any.whl → 0.8.8.9__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 (503) 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 +2 -11
  10. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +3 -3
  11. endoreg_db/data/event_classification/data.yaml +4 -0
  12. endoreg_db/data/event_classification_choice/data.yaml +9 -0
  13. endoreg_db/data/examination/examinations/data.yaml +114 -14
  14. endoreg_db/data/examination/time-type/data.yaml +0 -3
  15. endoreg_db/data/examination_indication/endoscopy.yaml +108 -173
  16. endoreg_db/data/examination_indication_classification/endoscopy.yaml +0 -70
  17. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +33 -37
  18. endoreg_db/data/finding/00_generic.yaml +35 -0
  19. endoreg_db/data/finding/00_generic_complication.yaml +9 -0
  20. endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
  21. endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
  22. endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
  23. endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
  24. endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
  25. endoreg_db/data/finding_classification/00_generic.yaml +44 -0
  26. endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
  27. endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
  28. endoreg_db/data/finding_classification/02_colonoscopy_baseline.yaml +83 -0
  29. endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
  30. endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
  31. endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
  32. endoreg_db/data/finding_classification_choice/{yes_no_na.yaml → 00_generic.yaml} +5 -1
  33. endoreg_db/data/finding_classification_choice/{examination_setting_generic_types.yaml → 00_generic_baseline.yaml} +10 -2
  34. endoreg_db/data/finding_classification_choice/{complication_generic_types.yaml → 00_generic_complication.yaml} +1 -1
  35. endoreg_db/data/finding_classification_choice/{histology.yaml → 00_generic_histology.yaml} +1 -4
  36. endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
  37. endoreg_db/data/finding_classification_choice/{bowel_preparation.yaml → 02_colonoscopy_bowel_preparation.yaml} +1 -30
  38. endoreg_db/data/finding_classification_choice/{colonoscopy_not_complete_reason.yaml → 02_colonoscopy_generic.yaml} +1 -1
  39. endoreg_db/data/finding_classification_choice/{histology_polyp.yaml → 02_colonoscopy_histology.yaml} +1 -1
  40. endoreg_db/data/finding_classification_choice/{colonoscopy_location.yaml → 02_colonoscopy_location.yaml} +23 -4
  41. endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
  42. endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
  43. endoreg_db/data/finding_classification_choice/{colon_lesion_paris.yaml → 02_colonoscopy_polyp_morphology.yaml} +26 -8
  44. endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
  45. endoreg_db/data/finding_classification_type/{colonoscopy_basic.yaml → 00_generic.yaml} +18 -13
  46. endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
  47. endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
  48. endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
  49. endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
  50. endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
  51. endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
  52. endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
  53. endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
  54. endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
  55. endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
  56. endoreg_db/data/finding_type/data.yaml +8 -12
  57. endoreg_db/data/requirement/01_patient_data.yaml +93 -0
  58. endoreg_db/data/requirement/old/colon_polyp_intervention.yaml +49 -0
  59. endoreg_db/data/requirement/old/coloreg_colon_polyp.yaml +49 -0
  60. endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
  61. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +29 -12
  62. endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
  63. endoreg_db/data/requirement_set/{endoscopy_bleeding_risk.yaml → 02_endoscopy_bleeding_risk.yaml} +0 -6
  64. endoreg_db/data/requirement_set/90_coloreg.yaml +190 -0
  65. endoreg_db/data/requirement_set/_old_ +109 -0
  66. endoreg_db/data/requirement_set_type/data.yaml +21 -0
  67. endoreg_db/data/setup_config.yaml +4 -4
  68. endoreg_db/data/tag/requirement_set_tags.yaml +21 -0
  69. endoreg_db/exceptions.py +4 -2
  70. endoreg_db/forms/examination_form.py +1 -1
  71. endoreg_db/helpers/data_loader.py +125 -53
  72. endoreg_db/helpers/default_objects.py +116 -81
  73. endoreg_db/import_files/__init__.py +27 -0
  74. endoreg_db/import_files/context/__init__.py +7 -0
  75. endoreg_db/import_files/context/default_sensitive_meta.py +81 -0
  76. endoreg_db/import_files/context/ensure_center.py +17 -0
  77. endoreg_db/import_files/context/file_lock.py +66 -0
  78. endoreg_db/import_files/context/import_context.py +43 -0
  79. endoreg_db/import_files/context/validate_directories.py +56 -0
  80. endoreg_db/import_files/file_storage/__init__.py +15 -0
  81. endoreg_db/import_files/file_storage/create_report_file.py +76 -0
  82. endoreg_db/import_files/file_storage/create_video_file.py +75 -0
  83. endoreg_db/import_files/file_storage/sensitive_meta_storage.py +39 -0
  84. endoreg_db/import_files/file_storage/state_management.py +400 -0
  85. endoreg_db/import_files/file_storage/storage.py +36 -0
  86. endoreg_db/import_files/import_service.md +26 -0
  87. endoreg_db/import_files/processing/__init__.py +11 -0
  88. endoreg_db/import_files/processing/report_processing/report_anonymization.py +94 -0
  89. endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
  90. endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
  91. endoreg_db/import_files/processing/video_processing/video_cleanup_on_error.py +119 -0
  92. endoreg_db/import_files/pseudonymization/fake.py +52 -0
  93. endoreg_db/import_files/pseudonymization/k_anonymity.py +182 -0
  94. endoreg_db/import_files/pseudonymization/k_pseudonymity.py +128 -0
  95. endoreg_db/import_files/report_import_service.py +141 -0
  96. endoreg_db/import_files/video_import_service.py +150 -0
  97. endoreg_db/management/commands/create_model_meta_from_huggingface.py +21 -10
  98. endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
  99. endoreg_db/management/commands/import_report.py +130 -65
  100. endoreg_db/management/commands/import_video.py +9 -10
  101. endoreg_db/management/commands/import_video_with_classification.py +2 -2
  102. endoreg_db/management/commands/list_routes.py +18 -0
  103. endoreg_db/management/commands/load_ai_model_data.py +5 -5
  104. endoreg_db/management/commands/load_ai_model_label_data.py +9 -7
  105. endoreg_db/management/commands/load_base_db_data.py +5 -134
  106. endoreg_db/management/commands/load_center_data.py +12 -12
  107. endoreg_db/management/commands/load_contraindication_data.py +14 -16
  108. endoreg_db/management/commands/load_disease_classification_choices_data.py +15 -18
  109. endoreg_db/management/commands/load_disease_classification_data.py +15 -18
  110. endoreg_db/management/commands/load_disease_data.py +25 -28
  111. endoreg_db/management/commands/load_endoscope_data.py +20 -27
  112. endoreg_db/management/commands/load_event_data.py +14 -16
  113. endoreg_db/management/commands/load_examination_data.py +31 -44
  114. endoreg_db/management/commands/load_examination_indication_data.py +20 -21
  115. endoreg_db/management/commands/load_finding_data.py +52 -80
  116. endoreg_db/management/commands/load_information_source.py +21 -23
  117. endoreg_db/management/commands/load_lab_value_data.py +17 -26
  118. endoreg_db/management/commands/load_medication_data.py +13 -12
  119. endoreg_db/management/commands/load_organ_data.py +15 -19
  120. endoreg_db/management/commands/load_pdf_type_data.py +19 -18
  121. endoreg_db/management/commands/load_profession_data.py +14 -17
  122. endoreg_db/management/commands/load_qualification_data.py +20 -23
  123. endoreg_db/management/commands/load_report_reader_flag_data.py +17 -19
  124. endoreg_db/management/commands/load_requirement_data.py +62 -39
  125. endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
  126. endoreg_db/management/commands/load_risk_data.py +7 -6
  127. endoreg_db/management/commands/load_shift_data.py +20 -23
  128. endoreg_db/management/commands/load_tag_data.py +8 -11
  129. endoreg_db/management/commands/load_unit_data.py +17 -19
  130. endoreg_db/management/commands/setup_endoreg_db.py +3 -3
  131. endoreg_db/management/commands/start_filewatcher.py +46 -37
  132. endoreg_db/management/commands/storage_management.py +271 -203
  133. endoreg_db/management/commands/validate_video_files.py +1 -5
  134. endoreg_db/migrations/0001_initial.py +297 -250
  135. endoreg_db/models/__init__.py +78 -123
  136. endoreg_db/models/administration/__init__.py +21 -42
  137. endoreg_db/models/administration/ai/active_model.py +2 -2
  138. endoreg_db/models/administration/ai/ai_model.py +7 -6
  139. endoreg_db/models/administration/case/__init__.py +1 -15
  140. endoreg_db/models/administration/case/case.py +3 -3
  141. endoreg_db/models/administration/case/case_template/__init__.py +2 -14
  142. endoreg_db/models/administration/case/case_template/case_template.py +2 -124
  143. endoreg_db/models/administration/case/case_template/case_template_rule.py +2 -268
  144. endoreg_db/models/administration/case/case_template/case_template_rule_value.py +2 -85
  145. endoreg_db/models/administration/case/case_template/case_template_type.py +2 -25
  146. endoreg_db/models/administration/center/center.py +33 -19
  147. endoreg_db/models/administration/center/center_product.py +12 -9
  148. endoreg_db/models/administration/center/center_resource.py +25 -19
  149. endoreg_db/models/administration/center/center_shift.py +21 -17
  150. endoreg_db/models/administration/center/center_waste.py +16 -8
  151. endoreg_db/models/administration/person/__init__.py +2 -0
  152. endoreg_db/models/administration/person/employee/employee.py +10 -5
  153. endoreg_db/models/administration/person/employee/employee_qualification.py +9 -4
  154. endoreg_db/models/administration/person/employee/employee_type.py +12 -6
  155. endoreg_db/models/administration/person/examiner/examiner.py +13 -11
  156. endoreg_db/models/administration/person/patient/__init__.py +2 -0
  157. endoreg_db/models/administration/person/patient/patient.py +129 -100
  158. endoreg_db/models/administration/person/patient/patient_external_id.py +37 -0
  159. endoreg_db/models/administration/person/person.py +4 -0
  160. endoreg_db/models/administration/person/profession/__init__.py +8 -4
  161. endoreg_db/models/administration/person/user/portal_user_information.py +11 -7
  162. endoreg_db/models/administration/product/product.py +20 -15
  163. endoreg_db/models/administration/product/product_material.py +17 -18
  164. endoreg_db/models/administration/product/product_weight.py +12 -8
  165. endoreg_db/models/administration/product/reference_product.py +23 -55
  166. endoreg_db/models/administration/qualification/qualification.py +7 -3
  167. endoreg_db/models/administration/qualification/qualification_type.py +7 -3
  168. endoreg_db/models/administration/shift/scheduled_days.py +8 -5
  169. endoreg_db/models/administration/shift/shift.py +16 -12
  170. endoreg_db/models/administration/shift/shift_type.py +23 -31
  171. endoreg_db/models/label/__init__.py +8 -9
  172. endoreg_db/models/label/annotation/image_classification.py +10 -9
  173. endoreg_db/models/label/annotation/video_segmentation_annotation.py +23 -28
  174. endoreg_db/models/label/label.py +15 -15
  175. endoreg_db/models/label/label_set.py +19 -6
  176. endoreg_db/models/label/label_type.py +1 -1
  177. endoreg_db/models/label/label_video_segment/_create_from_video.py +5 -8
  178. endoreg_db/models/label/label_video_segment/label_video_segment.py +98 -102
  179. endoreg_db/models/label/video_segmentation_label.py +4 -0
  180. endoreg_db/models/label/video_segmentation_labelset.py +4 -3
  181. endoreg_db/models/media/frame/frame.py +22 -22
  182. endoreg_db/models/media/pdf/raw_pdf.py +194 -194
  183. endoreg_db/models/media/pdf/report_file.py +25 -29
  184. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +55 -47
  185. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
  186. endoreg_db/models/media/processing_history/__init__.py +5 -0
  187. endoreg_db/models/media/processing_history/processing_history.py +96 -0
  188. endoreg_db/models/media/video/__init__.py +1 -0
  189. endoreg_db/models/media/video/create_from_file.py +139 -77
  190. endoreg_db/models/media/video/pipe_2.py +8 -9
  191. endoreg_db/models/media/video/video_file.py +174 -112
  192. endoreg_db/models/media/video/video_file_ai.py +288 -74
  193. endoreg_db/models/media/video/video_file_anonymize.py +38 -38
  194. endoreg_db/models/media/video/video_file_frames/__init__.py +3 -1
  195. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -8
  196. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +7 -9
  197. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +9 -8
  198. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +38 -45
  199. endoreg_db/models/media/video/video_file_frames/_get_frame.py +6 -8
  200. endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +4 -18
  201. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -3
  202. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +7 -6
  203. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +6 -8
  204. endoreg_db/models/media/video/video_file_frames/_get_frames.py +6 -8
  205. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +15 -25
  206. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +26 -23
  207. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +23 -14
  208. endoreg_db/models/media/video/video_file_io.py +113 -61
  209. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +3 -3
  210. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +5 -3
  211. endoreg_db/models/media/video/video_file_meta/get_fps.py +37 -34
  212. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +19 -25
  213. endoreg_db/models/media/video/video_file_meta/text_meta.py +41 -38
  214. endoreg_db/models/media/video/video_file_meta/video_meta.py +14 -7
  215. endoreg_db/models/media/video/video_file_segments.py +24 -17
  216. endoreg_db/models/media/video/video_metadata.py +19 -35
  217. endoreg_db/models/media/video/video_processing.py +96 -95
  218. endoreg_db/models/medical/contraindication/README.md +1 -0
  219. endoreg_db/models/medical/contraindication/__init__.py +13 -3
  220. endoreg_db/models/medical/disease.py +22 -16
  221. endoreg_db/models/medical/event.py +31 -18
  222. endoreg_db/models/medical/examination/__init__.py +13 -6
  223. endoreg_db/models/medical/examination/examination.py +39 -20
  224. endoreg_db/models/medical/examination/examination_indication.py +30 -95
  225. endoreg_db/models/medical/examination/examination_time.py +23 -8
  226. endoreg_db/models/medical/examination/examination_time_type.py +9 -6
  227. endoreg_db/models/medical/examination/examination_type.py +3 -4
  228. endoreg_db/models/medical/finding/finding.py +32 -40
  229. endoreg_db/models/medical/finding/finding_classification.py +42 -72
  230. endoreg_db/models/medical/finding/finding_intervention.py +25 -22
  231. endoreg_db/models/medical/finding/finding_type.py +13 -12
  232. endoreg_db/models/medical/hardware/endoscope.py +26 -26
  233. endoreg_db/models/medical/hardware/endoscopy_processor.py +2 -2
  234. endoreg_db/models/medical/laboratory/lab_value.py +62 -91
  235. endoreg_db/models/medical/medication/medication.py +22 -10
  236. endoreg_db/models/medical/medication/medication_indication.py +29 -3
  237. endoreg_db/models/medical/medication/medication_indication_type.py +25 -14
  238. endoreg_db/models/medical/medication/medication_intake_time.py +31 -19
  239. endoreg_db/models/medical/medication/medication_schedule.py +27 -16
  240. endoreg_db/models/medical/organ/__init__.py +15 -12
  241. endoreg_db/models/medical/patient/medication_examples.py +6 -6
  242. endoreg_db/models/medical/patient/patient_disease.py +20 -23
  243. endoreg_db/models/medical/patient/patient_event.py +19 -22
  244. endoreg_db/models/medical/patient/patient_examination.py +48 -54
  245. endoreg_db/models/medical/patient/patient_examination_indication.py +16 -14
  246. endoreg_db/models/medical/patient/patient_finding.py +122 -139
  247. endoreg_db/models/medical/patient/patient_finding_classification.py +44 -49
  248. endoreg_db/models/medical/patient/patient_finding_intervention.py +8 -19
  249. endoreg_db/models/medical/patient/patient_lab_sample.py +28 -23
  250. endoreg_db/models/medical/patient/patient_lab_value.py +82 -89
  251. endoreg_db/models/medical/patient/patient_medication.py +27 -38
  252. endoreg_db/models/medical/patient/patient_medication_schedule.py +28 -36
  253. endoreg_db/models/medical/risk/risk.py +7 -6
  254. endoreg_db/models/medical/risk/risk_type.py +8 -5
  255. endoreg_db/models/metadata/model_meta.py +60 -29
  256. endoreg_db/models/metadata/model_meta_logic.py +125 -18
  257. endoreg_db/models/metadata/pdf_meta.py +31 -24
  258. endoreg_db/models/metadata/sensitive_meta.py +105 -85
  259. endoreg_db/models/metadata/sensitive_meta_logic.py +198 -103
  260. endoreg_db/models/metadata/video_meta.py +51 -31
  261. endoreg_db/models/metadata/video_prediction_logic.py +16 -23
  262. endoreg_db/models/metadata/video_prediction_meta.py +29 -33
  263. endoreg_db/models/other/distribution/date_value_distribution.py +89 -29
  264. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +21 -5
  265. endoreg_db/models/other/distribution/numeric_value_distribution.py +114 -53
  266. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +4 -3
  267. endoreg_db/models/other/emission/emission_factor.py +18 -8
  268. endoreg_db/models/other/gender.py +10 -5
  269. endoreg_db/models/other/information_source.py +50 -29
  270. endoreg_db/models/other/material.py +9 -5
  271. endoreg_db/models/other/resource.py +6 -4
  272. endoreg_db/models/other/tag.py +10 -5
  273. endoreg_db/models/other/transport_route.py +13 -8
  274. endoreg_db/models/other/unit.py +10 -6
  275. endoreg_db/models/other/waste.py +6 -5
  276. endoreg_db/models/report/report.py +6 -0
  277. endoreg_db/models/requirement/requirement.py +329 -361
  278. endoreg_db/models/requirement/requirement_error.py +85 -0
  279. endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
  280. endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +3 -6
  281. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +90 -64
  282. endoreg_db/models/requirement/requirement_operator.py +103 -112
  283. endoreg_db/models/requirement/requirement_set.py +74 -57
  284. endoreg_db/models/state/__init__.py +4 -4
  285. endoreg_db/models/state/abstract.py +2 -2
  286. endoreg_db/models/state/anonymization.py +12 -0
  287. endoreg_db/models/state/audit_ledger.py +49 -51
  288. endoreg_db/models/state/label_video_segment.py +9 -0
  289. endoreg_db/models/state/raw_pdf.py +101 -68
  290. endoreg_db/models/state/sensitive_meta.py +6 -2
  291. endoreg_db/models/state/video.py +110 -90
  292. endoreg_db/models/upload_job.py +35 -34
  293. endoreg_db/models/utils.py +28 -25
  294. endoreg_db/queries/__init__.py +3 -1
  295. endoreg_db/root_urls.py +21 -2
  296. endoreg_db/schemas/examination_evaluation.py +1 -1
  297. endoreg_db/serializers/__init__.py +2 -10
  298. endoreg_db/serializers/anonymization.py +18 -10
  299. endoreg_db/serializers/label_video_segment/label_video_segment.py +2 -29
  300. endoreg_db/serializers/meta/__init__.py +1 -6
  301. endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
  302. endoreg_db/serializers/misc/file_overview.py +11 -99
  303. endoreg_db/serializers/misc/sensitive_patient_data.py +50 -26
  304. endoreg_db/serializers/patient_examination/patient_examination.py +3 -3
  305. endoreg_db/serializers/pdf/anony_text_validation.py +39 -23
  306. endoreg_db/serializers/requirements/requirement_sets.py +92 -22
  307. endoreg_db/serializers/video/segmentation.py +2 -1
  308. endoreg_db/serializers/video/video_file_list.py +65 -34
  309. endoreg_db/serializers/video/video_processing_history.py +20 -5
  310. endoreg_db/services/__old/pdf_import.py +1487 -0
  311. endoreg_db/services/__old/video_import.py +1306 -0
  312. endoreg_db/services/anonymization.py +128 -89
  313. endoreg_db/services/lookup_service.py +65 -52
  314. endoreg_db/services/lookup_store.py +2 -2
  315. endoreg_db/services/pdf_import.py +0 -1382
  316. endoreg_db/services/report_import.py +10 -0
  317. endoreg_db/services/video_import.py +6 -1255
  318. endoreg_db/tasks/upload_tasks.py +79 -70
  319. endoreg_db/tasks/video_ingest.py +8 -4
  320. endoreg_db/urls/__init__.py +5 -32
  321. endoreg_db/urls/ai.py +32 -0
  322. endoreg_db/urls/media.py +121 -83
  323. endoreg_db/urls/root_urls.py +29 -0
  324. endoreg_db/utils/__init__.py +15 -5
  325. endoreg_db/utils/ai/multilabel_classification_net.py +116 -20
  326. endoreg_db/utils/case_generator/__init__.py +3 -0
  327. endoreg_db/utils/dataloader.py +142 -40
  328. endoreg_db/utils/defaults/set_default_center.py +32 -0
  329. endoreg_db/utils/names.py +22 -16
  330. endoreg_db/utils/paths.py +110 -46
  331. endoreg_db/utils/permissions.py +2 -1
  332. endoreg_db/utils/pipelines/Readme.md +1 -1
  333. endoreg_db/utils/pipelines/process_video_dir.py +1 -1
  334. endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +655 -0
  335. endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +97 -0
  336. endoreg_db/utils/setup_config.py +8 -5
  337. endoreg_db/utils/storage.py +115 -0
  338. endoreg_db/utils/validate_endo_roi.py +8 -2
  339. endoreg_db/utils/video/ffmpeg_wrapper.py +184 -188
  340. endoreg_db/views/__init__.py +85 -183
  341. endoreg_db/views/ai/__init__.py +8 -0
  342. endoreg_db/views/ai/label.py +155 -0
  343. endoreg_db/views/anonymization/media_management.py +202 -166
  344. endoreg_db/views/anonymization/overview.py +99 -67
  345. endoreg_db/views/anonymization/validate.py +182 -44
  346. endoreg_db/views/media/__init__.py +7 -20
  347. endoreg_db/views/media/pdf_media.py +197 -174
  348. endoreg_db/views/media/sensitive_metadata.py +193 -138
  349. endoreg_db/views/media/video_media.py +89 -82
  350. endoreg_db/views/meta/__init__.py +0 -8
  351. endoreg_db/views/misc/__init__.py +1 -7
  352. endoreg_db/views/misc/upload_views.py +94 -93
  353. endoreg_db/views/patient/patient.py +5 -4
  354. endoreg_db/views/report/__init__.py +5 -7
  355. endoreg_db/views/{pdf → report}/reimport.py +22 -22
  356. endoreg_db/views/{pdf/pdf_stream.py → report/report_stream.py} +46 -39
  357. endoreg_db/views/requirement/evaluate.py +188 -187
  358. endoreg_db/views/requirement/lookup.py +17 -3
  359. endoreg_db/views/requirement/lookup_store.py +22 -90
  360. endoreg_db/views/requirement/requirement_utils.py +89 -0
  361. endoreg_db/views/video/__init__.py +23 -24
  362. endoreg_db/views/video/correction.py +201 -172
  363. endoreg_db/views/video/reimport.py +1 -1
  364. endoreg_db/views/{media/video_segments.py → video/segments_crud.py} +77 -40
  365. endoreg_db/views/video/{video_meta.py → video_meta_stats.py} +2 -2
  366. endoreg_db/views/video/video_stream.py +7 -8
  367. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/METADATA +7 -3
  368. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/RECORD +391 -413
  369. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/WHEEL +1 -1
  370. endoreg_db/data/finding/anatomy_colon.yaml +0 -128
  371. endoreg_db/data/finding/colonoscopy.yaml +0 -40
  372. endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +0 -56
  373. endoreg_db/data/finding/complication.yaml +0 -16
  374. endoreg_db/data/finding/data.yaml +0 -105
  375. endoreg_db/data/finding/examination_setting.yaml +0 -16
  376. endoreg_db/data/finding/medication_related.yaml +0 -18
  377. endoreg_db/data/finding/outcome.yaml +0 -12
  378. endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +0 -95
  379. endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +0 -22
  380. endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +0 -25
  381. endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
  382. endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
  383. endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +0 -68
  384. endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
  385. endoreg_db/data/finding_classification/colonoscopy_location.yaml +0 -80
  386. endoreg_db/data/finding_classification/colonoscopy_lst.yaml +0 -21
  387. endoreg_db/data/finding_classification/colonoscopy_nice.yaml +0 -20
  388. endoreg_db/data/finding_classification/colonoscopy_paris.yaml +0 -26
  389. endoreg_db/data/finding_classification/colonoscopy_sano.yaml +0 -22
  390. endoreg_db/data/finding_classification/colonoscopy_summary.yaml +0 -53
  391. endoreg_db/data/finding_classification/complication_generic.yaml +0 -25
  392. endoreg_db/data/finding_classification/examination_setting_generic.yaml +0 -40
  393. endoreg_db/data/finding_classification/histology_colo.yaml +0 -51
  394. endoreg_db/data/finding_classification/intervention_required.yaml +0 -26
  395. endoreg_db/data/finding_classification/medication_related.yaml +0 -23
  396. endoreg_db/data/finding_classification/visualized.yaml +0 -33
  397. endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
  398. endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
  399. endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
  400. endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +0 -15
  401. endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +0 -17
  402. endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
  403. endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +0 -14
  404. endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
  405. endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +0 -82
  406. endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
  407. endoreg_db/data/finding_classification_choice/outcome.yaml +0 -19
  408. endoreg_db/data/finding_intervention/endoscopy.yaml +0 -43
  409. endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
  410. endoreg_db/data/finding_intervention/endoscopy_egd.yaml +0 -128
  411. endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +0 -32
  412. endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +0 -9
  413. endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +0 -36
  414. endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +0 -79
  415. endoreg_db/data/requirement/age.yaml +0 -26
  416. endoreg_db/data/requirement/gender.yaml +0 -25
  417. endoreg_db/management/commands/init_default_ai_model.py +0 -112
  418. endoreg_db/management/commands/reset_celery_schedule.py +0 -9
  419. endoreg_db/management/commands/validate_video.py +0 -204
  420. endoreg_db/migrations/0002_add_video_correction_models.py +0 -52
  421. endoreg_db/migrations/0003_add_center_display_name.py +0 -30
  422. endoreg_db/models/administration/permissions/__init__.py +0 -44
  423. endoreg_db/models/rule/__init__.py +0 -13
  424. endoreg_db/models/rule/rule.py +0 -27
  425. endoreg_db/models/rule/rule_applicator.py +0 -224
  426. endoreg_db/models/rule/rule_attribute_dtype.py +0 -17
  427. endoreg_db/models/rule/rule_type.py +0 -20
  428. endoreg_db/models/rule/ruleset.py +0 -17
  429. endoreg_db/renames.yml +0 -8
  430. endoreg_db/serializers/_old/raw_pdf_meta_validation.py +0 -223
  431. endoreg_db/serializers/_old/raw_video_meta_validation.py +0 -179
  432. endoreg_db/serializers/_old/video.py +0 -71
  433. endoreg_db/serializers/meta/pdf_file_meta_extraction.py +0 -115
  434. endoreg_db/serializers/meta/report_meta.py +0 -53
  435. endoreg_db/serializers/report/__init__.py +0 -9
  436. endoreg_db/serializers/report/mixins.py +0 -45
  437. endoreg_db/serializers/report/report.py +0 -105
  438. endoreg_db/serializers/report/report_list.py +0 -22
  439. endoreg_db/serializers/report/secure_file_url.py +0 -26
  440. endoreg_db/serializers/video/video_metadata.py +0 -105
  441. endoreg_db/services/requirements_object.py +0 -147
  442. endoreg_db/services/storage_aware_video_processor.py +0 -344
  443. endoreg_db/urls/files.py +0 -6
  444. endoreg_db/urls/label_video_segment_validate.py +0 -33
  445. endoreg_db/urls/label_video_segments.py +0 -46
  446. endoreg_db/urls/report.py +0 -48
  447. endoreg_db/urls/video.py +0 -61
  448. endoreg_db/utils/case_generator/case_generator.py +0 -159
  449. endoreg_db/utils/case_generator/utils.py +0 -30
  450. endoreg_db/utils/requirement_operator_logic/model_evaluators.py +0 -368
  451. endoreg_db/views/label/__init__.py +0 -5
  452. endoreg_db/views/label/label.py +0 -15
  453. endoreg_db/views/label_video_segment/__init__.py +0 -16
  454. endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +0 -44
  455. endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +0 -50
  456. endoreg_db/views/label_video_segment/label_video_segment.py +0 -77
  457. endoreg_db/views/label_video_segment/label_video_segment_by_label.py +0 -174
  458. endoreg_db/views/label_video_segment/label_video_segment_detail.py +0 -73
  459. endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +0 -46
  460. endoreg_db/views/label_video_segment/validate.py +0 -226
  461. endoreg_db/views/media/segments.py +0 -71
  462. endoreg_db/views/meta/available_files_list.py +0 -146
  463. endoreg_db/views/meta/report_meta.py +0 -53
  464. endoreg_db/views/meta/sensitive_meta_detail.py +0 -148
  465. endoreg_db/views/misc/secure_file_serving_view.py +0 -80
  466. endoreg_db/views/misc/secure_file_url_view.py +0 -84
  467. endoreg_db/views/misc/secure_url_validate.py +0 -79
  468. endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +0 -164
  469. endoreg_db/views/patient_finding_location/__init__.py +0 -5
  470. endoreg_db/views/patient_finding_location/pfl_create.py +0 -70
  471. endoreg_db/views/patient_finding_morphology/__init__.py +0 -5
  472. endoreg_db/views/patient_finding_morphology/pfm_create.py +0 -70
  473. endoreg_db/views/pdf/__init__.py +0 -8
  474. endoreg_db/views/report/report_list.py +0 -112
  475. endoreg_db/views/report/report_with_secure_url.py +0 -28
  476. endoreg_db/views/report/start_examination.py +0 -7
  477. endoreg_db/views/video/segmentation.py +0 -274
  478. endoreg_db/views/video/task_status.py +0 -49
  479. endoreg_db/views/video/timeline.py +0 -46
  480. endoreg_db/views/video/video_analyze.py +0 -52
  481. endoreg_db/views.py +0 -0
  482. /endoreg_db/data/requirement/{colonoscopy_baseline_austria.yaml → old/colonoscopy_baseline_austria.yaml} +0 -0
  483. /endoreg_db/data/requirement/{disease_cardiovascular.yaml → old/disease_cardiovascular.yaml} +0 -0
  484. /endoreg_db/data/requirement/{disease_classification_choice_cardiovascular.yaml → old/disease_classification_choice_cardiovascular.yaml} +0 -0
  485. /endoreg_db/data/requirement/{disease_hepatology.yaml → old/disease_hepatology.yaml} +0 -0
  486. /endoreg_db/data/requirement/{disease_misc.yaml → old/disease_misc.yaml} +0 -0
  487. /endoreg_db/data/requirement/{disease_renal.yaml → old/disease_renal.yaml} +0 -0
  488. /endoreg_db/data/requirement/{endoscopy_bleeding_risk.yaml → old/endoscopy_bleeding_risk.yaml} +0 -0
  489. /endoreg_db/data/requirement/{event_cardiology.yaml → old/event_cardiology.yaml} +0 -0
  490. /endoreg_db/data/requirement/{event_requirements.yaml → old/event_requirements.yaml} +0 -0
  491. /endoreg_db/data/requirement/{finding_colon_polyp.yaml → old/finding_colon_polyp.yaml} +0 -0
  492. /endoreg_db/{migrations/__init__.py → data/requirement/old/gender.yaml} +0 -0
  493. /endoreg_db/data/requirement/{lab_value.yaml → old/lab_value.yaml} +0 -0
  494. /endoreg_db/data/requirement/{medication.yaml → old/medication.yaml} +0 -0
  495. /endoreg_db/data/requirement_operator/{age.yaml → _old/age.yaml} +0 -0
  496. /endoreg_db/data/requirement_operator/{lab_operators.yaml → _old/lab_operators.yaml} +0 -0
  497. /endoreg_db/data/requirement_operator/{model_operators.yaml → _old/model_operators.yaml} +0 -0
  498. /endoreg_db/{models/media/video/refactor_plan.md → import_files/pseudonymization/__init__.py} +0 -0
  499. /endoreg_db/{models/media/video/video_file_frames.py → import_files/pseudonymization/pseudonymize.py} +0 -0
  500. /endoreg_db/models/{metadata/frame_ocr_result.py → report/__init__.py} +0 -0
  501. /endoreg_db/{urls/sensitive_meta.py → models/report/images.py} +0 -0
  502. /endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py} +0 -0
  503. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/licenses/LICENSE +0 -0
@@ -1,20 +1,22 @@
1
1
  import logging
2
- from typing import TYPE_CHECKING, List, Tuple, Optional
2
+ from typing import TYPE_CHECKING, List, Optional, Tuple
3
+
3
4
  import numpy as np
4
5
 
5
- # Import necessary models and utils used by the logic
6
- from ..utils import find_segments_in_prediction_array
7
6
  from ..label.label_video_segment import LabelVideoSegment
8
7
 
8
+ # Import necessary models and utils used by the logic
9
+ from ..utils import find_segments_in_prediction_array
9
10
 
10
11
  logger = logging.getLogger(__name__)
11
12
 
13
+ # TODO configure via settings
12
14
  DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN = 1.5
13
15
  DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S = 1.0
14
16
 
15
17
  if TYPE_CHECKING:
16
- from .video_prediction_meta import VideoPredictionMeta
17
18
  from ..label import Label
19
+ from .video_prediction_meta import VideoPredictionMeta
18
20
 
19
21
 
20
22
  def apply_running_mean_logic(instance: "VideoPredictionMeta", confidence_array: np.ndarray, window_size_in_seconds: Optional[float] = None) -> np.ndarray:
@@ -63,6 +65,7 @@ def calculate_prediction_array_logic(instance: "VideoPredictionMeta", window_siz
63
65
  Does not save the array itself.
64
66
  """
65
67
  from ..label import ImageClassificationAnnotation
68
+
66
69
  video_obj = instance.get_video()
67
70
  model_meta = instance.model_meta
68
71
  label_list = instance.get_label_list()
@@ -78,15 +81,10 @@ def calculate_prediction_array_logic(instance: "VideoPredictionMeta", window_siz
78
81
 
79
82
  prediction_array = np.zeros((num_frames, len(label_list)))
80
83
 
81
- base_pred_qs = ImageClassificationAnnotation.objects.filter(
82
- model_meta=model_meta,
83
- frame__video_file=video_obj
84
- )
84
+ base_pred_qs = ImageClassificationAnnotation.objects.filter(model_meta=model_meta, frame__video_file=video_obj)
85
85
 
86
86
  for i, label in enumerate(label_list):
87
- predictions = base_pred_qs.filter(label=label).order_by("frame__frame_number").values_list(
88
- "frame__frame_number", "confidence"
89
- )
87
+ predictions = base_pred_qs.filter(label=label).order_by("frame__frame_number").values_list("frame__frame_number", "confidence")
90
88
 
91
89
  # Initialize with 0.5 (neutral confidence)
92
90
  confidences = np.full(num_frames, 0.5)
@@ -96,14 +94,12 @@ def calculate_prediction_array_logic(instance: "VideoPredictionMeta", window_siz
96
94
  confidences[frame_num] = confidence
97
95
  found_predictions = True
98
96
  else:
99
- logger.warning(f"Prediction found for out-of-bounds frame number {frame_num} (max: {num_frames-1}). Skipping.")
97
+ logger.warning(f"Prediction found for out-of-bounds frame number {frame_num} (max: {num_frames - 1}). Skipping.")
100
98
 
101
99
  if not found_predictions:
102
100
  logger.warning(f"No predictions found for label '{label.name}' in {video_obj}. Using default confidence.")
103
101
 
104
- smooth_confidences = apply_running_mean_logic(
105
- instance, confidences, window_size_in_seconds
106
- )
102
+ smooth_confidences = apply_running_mean_logic(instance, confidences, window_size_in_seconds)
107
103
  # Threshold smoothed confidences
108
104
  binary_predictions = smooth_confidences > 0.5
109
105
  prediction_array[:, i] = binary_predictions
@@ -116,6 +112,7 @@ def create_video_segments_for_label_logic(instance: "VideoPredictionMeta", segme
116
112
  Creates LabelVideoSegment instances for the given label and segments.
117
113
  """
118
114
  from ..other import InformationSource
115
+
119
116
  video_obj = instance.get_video()
120
117
  information_source, _ = InformationSource.objects.get_or_create(name="prediction")
121
118
 
@@ -131,11 +128,7 @@ def create_video_segments_for_label_logic(instance: "VideoPredictionMeta", segme
131
128
  }
132
129
  # Check for existence before creating the object instance
133
130
  if not LabelVideoSegment.objects.filter(
134
- video_file=video_obj,
135
- prediction_meta=instance,
136
- label=label,
137
- start_frame_number=start_frame,
138
- end_frame_number=end_frame
131
+ video_file=video_obj, prediction_meta=instance, label=label, start_frame_number=start_frame, end_frame_number=end_frame
139
132
  ).exists():
140
133
  segments_to_create.append(LabelVideoSegment(**segment_data))
141
134
 
@@ -161,7 +154,7 @@ def create_video_segments_logic(instance: "VideoPredictionMeta", segment_length_
161
154
  return
162
155
 
163
156
  min_frame_length = int(segment_length_threshold_in_s * fps)
164
- min_frame_length = max(min_frame_length, 1) # Ensure minimum length is at least 1
157
+ min_frame_length = max(min_frame_length, 1) # Ensure minimum length is at least 1
165
158
 
166
159
  label_list = instance.get_label_list()
167
160
  if not label_list:
@@ -171,8 +164,8 @@ def create_video_segments_logic(instance: "VideoPredictionMeta", segment_length_
171
164
  prediction_array = instance.get_prediction_array()
172
165
  if prediction_array is None:
173
166
  logger.info(f"Prediction array not found for {instance}. Calculating...")
174
- instance.calculate_prediction_array() # This will save the array internally
175
- prediction_array = instance.get_prediction_array() # Fetch again
167
+ instance.calculate_prediction_array() # This will save the array internally
168
+ prediction_array = instance.get_prediction_array() # Fetch again
176
169
  if prediction_array is None:
177
170
  logger.error(f"Failed to get or calculate prediction array for {instance}. Cannot create segments.")
178
171
  return
@@ -1,25 +1,25 @@
1
- from typing import TYPE_CHECKING, Optional, List, Tuple
2
- from django.db import models
3
1
  import logging
2
+ import pickle
3
+ from typing import TYPE_CHECKING, List, Optional, Tuple
4
+
5
+ import numpy as np
6
+ from django.db import models
4
7
 
5
8
  from endoreg_db.models.label import LabelSet
6
9
 
7
10
  from ..label.label_video_segment import (
8
11
  LabelVideoSegment,
9
-
10
12
  )
11
13
  from ..utils import find_segments_in_prediction_array
12
14
 
13
- import numpy as np
14
- import pickle
15
-
16
15
  logger = logging.getLogger(__name__)
17
16
 
18
17
  DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN = 1.5
19
18
  DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S = 1.0
20
19
 
21
20
  if TYPE_CHECKING:
22
- from endoreg_db.models import ModelMeta, Label
21
+ from endoreg_db.models import Label, ModelMeta
22
+
23
23
  from ..media.video.video_file import VideoFile
24
24
 
25
25
 
@@ -29,6 +29,7 @@ class VideoPredictionMeta(models.Model):
29
29
 
30
30
  Must be associated with exactly one `VideoFile`.
31
31
  """
32
+
32
33
  model_meta = models.ForeignKey("ModelMeta", on_delete=models.CASCADE)
33
34
  date_created = models.DateTimeField(auto_now_add=True)
34
35
  date_modified = models.DateTimeField(auto_now=True)
@@ -43,18 +44,24 @@ class VideoPredictionMeta(models.Model):
43
44
  )
44
45
 
45
46
  if TYPE_CHECKING:
46
- model_meta: "ModelMeta"
47
- video_file: "VideoFile"
47
+ model_meta: models.ForeignKey["ModelMeta"]
48
+ video_file: models.ForeignKey["VideoFile|None"]
48
49
  label_video_segments: "models.Manager[LabelVideoSegment]"
49
50
 
50
51
  class Meta:
51
- constraints = [
52
- models.UniqueConstraint(fields=['model_meta', 'video_file'], name='unique_prediction_per_video_model')
53
- ]
52
+ constraints = [models.UniqueConstraint(fields=["model_meta", "video_file"], name="unique_prediction_per_video_model")]
54
53
  indexes = [
55
54
  models.Index(fields=["model_meta", "video_file"]),
56
55
  ]
57
56
 
57
+ @property
58
+ def video_file_safe(self) -> "VideoFile":
59
+ """Returns the associated VideoFile instance."""
60
+ video_file = self.video_file
61
+ if not video_file:
62
+ raise ValueError("VideoPredictionMeta is not associated with a VideoFile.")
63
+ return video_file
64
+
58
65
  def get_video(self) -> "VideoFile":
59
66
  """Returns the associated VideoFile instance."""
60
67
  if self.video_file:
@@ -83,12 +90,12 @@ class VideoPredictionMeta(models.Model):
83
90
  return labelset.get_labels_in_order()
84
91
  return []
85
92
 
86
- def save_prediction_array(self, prediction_array: np.array):
93
+ def save_prediction_array(self, prediction_array: np.typing.NDArray):
87
94
  """
88
95
  Save the prediction array to the database.
89
96
  """
90
97
  self.prediction_array = pickle.dumps(prediction_array)
91
- self.save(update_fields=['prediction_array', 'date_modified'])
98
+ self.save(update_fields=["prediction_array", "date_modified"])
92
99
 
93
100
  def get_prediction_array(self):
94
101
  """
@@ -103,7 +110,7 @@ class VideoPredictionMeta(models.Model):
103
110
  logger.error(f"Error unpickling prediction array for {self}: {e}")
104
111
  return None
105
112
 
106
- def calculate_prediction_array(self, window_size_in_seconds: int = None):
113
+ def calculate_prediction_array(self, window_size_in_seconds: Optional[int] = None):
107
114
  """
108
115
  Fetches all predictions for the associated video, labelset, and model meta,
109
116
  applies smoothing, and saves the resulting binary prediction array.
@@ -125,15 +132,10 @@ class VideoPredictionMeta(models.Model):
125
132
 
126
133
  prediction_array = np.zeros((num_frames, len(label_list)))
127
134
 
128
- base_pred_qs = ImageClassificationAnnotation.objects.filter(
129
- model_meta=model_meta,
130
- frame__video_file=video_obj
131
- )
135
+ base_pred_qs = ImageClassificationAnnotation.objects.filter(model_meta=model_meta, frame__video_file=video_obj)
132
136
 
133
137
  for i, label in enumerate(label_list):
134
- predictions = base_pred_qs.filter(label=label).order_by("frame__frame_number").values_list(
135
- "frame__frame_number", "float_value"
136
- )
138
+ predictions = base_pred_qs.filter(label=label).order_by("frame__frame_number").values_list("frame__frame_number", "float_value")
137
139
 
138
140
  confidences = np.full(num_frames, 0.5)
139
141
  found_predictions = False
@@ -142,21 +144,19 @@ class VideoPredictionMeta(models.Model):
142
144
  confidences[frame_num] = confidence
143
145
  found_predictions = True
144
146
  else:
145
- logger.warning(f"Prediction found for out-of-bounds frame number {frame_num} (max: {num_frames-1}). Skipping.")
147
+ logger.warning(f"Prediction found for out-of-bounds frame number {frame_num} (max: {num_frames - 1}). Skipping.")
146
148
 
147
149
  if not found_predictions:
148
150
  logger.warning(f"No predictions found for label '{label.name}' in {video_obj}. Using default confidence.")
149
151
 
150
- smooth_confidences = self.apply_running_mean(
151
- confidences, window_size_in_seconds
152
- )
152
+ smooth_confidences = self.apply_running_mean(confidences, window_size_in_seconds)
153
153
  binary_predictions = smooth_confidences > 0.5
154
154
  prediction_array[:, i] = binary_predictions
155
155
 
156
156
  self.save_prediction_array(prediction_array)
157
157
  logger.info(f"Calculated and saved prediction array for {self}")
158
158
 
159
- def apply_running_mean(self, confidence_array, window_size_in_seconds: int = None):
159
+ def apply_running_mean(self, confidence_array, window_size_in_seconds: Optional[float] = None):
160
160
  """
161
161
  Apply a running mean filter to the confidence array for smoothing, assuming a padding
162
162
  of 0.5 for the edges.
@@ -215,11 +215,7 @@ class VideoPredictionMeta(models.Model):
215
215
  "video_file": video_obj,
216
216
  }
217
217
  if not LabelVideoSegment.objects.filter(
218
- video_file=video_obj,
219
- prediction_meta=self,
220
- label=label,
221
- start_frame_number=start_frame,
222
- end_frame_number=end_frame
218
+ video_file=video_obj, prediction_meta=self, label=label, start_frame_number=start_frame, end_frame_number=end_frame
223
219
  ).exists():
224
220
  segments_to_create.append(LabelVideoSegment(**segment_data))
225
221
 
@@ -229,7 +225,7 @@ class VideoPredictionMeta(models.Model):
229
225
  else:
230
226
  logger.info(f"No new video segments needed for label '{label.name}' in {video_obj}.")
231
227
 
232
- def create_video_segments(self, segment_length_threshold_in_s: float = None):
228
+ def create_video_segments(self, segment_length_threshold_in_s: Optional[float] = None):
233
229
  """
234
230
  Generates LabelVideoSegments based on the stored prediction array.
235
231
  """
@@ -1,15 +1,18 @@
1
- '''Model for date value distribution'''
1
+ """Model for date value distribution"""
2
2
 
3
3
  from datetime import date, timedelta
4
- from django.db import models
4
+
5
5
  import numpy as np
6
+ from django.db import models
6
7
 
7
8
  from .base_value_distribution import BaseValueDistribution
8
9
 
10
+
9
11
  class DateValueDistributionManager(models.Manager):
10
- '''Object manager for DateValueDistribution'''
12
+ """Object manager for DateValueDistribution"""
13
+
11
14
  def get_by_natural_key(self, name):
12
- '''Retrieve a DateValueDistribution by its natural key.'''
15
+ """Retrieve a DateValueDistribution by its natural key."""
13
16
  return self.get(name=name)
14
17
 
15
18
 
@@ -20,16 +23,17 @@ class DateValueDistribution(BaseValueDistribution):
20
23
  date_min, date_max, date_mean, date_std_dev or
21
24
  timedelta_days_min, timedelta_days_max, timedelta_days_mean, timedelta_days_std_dev
22
25
  """
26
+
23
27
  objects = DateValueDistributionManager()
24
28
  name = models.CharField(max_length=100)
25
29
  description = models.TextField(blank=True, null=True)
26
30
  DISTRIBUTION_CHOICES = [
27
- ('uniform', 'Uniform'),
28
- ('normal', 'Normal'),
31
+ ("uniform", "Uniform"),
32
+ ("normal", "Normal"),
29
33
  ]
30
34
  MODE_CHOICES = [
31
- ('date', 'Date'),
32
- ('timedelta', 'Timedelta'),
35
+ ("date", "Date"),
36
+ ("timedelta", "Timedelta"),
33
37
  ]
34
38
 
35
39
  distribution_type = models.CharField(max_length=20, choices=DISTRIBUTION_CHOICES)
@@ -47,43 +51,99 @@ class DateValueDistribution(BaseValueDistribution):
47
51
  timedelta_days_mean = models.IntegerField(blank=True, null=True)
48
52
  timedelta_days_std_dev = models.IntegerField(blank=True, null=True)
49
53
 
54
+ # create *_safe properties for dates and timedeltas
55
+ @property
56
+ def date_min_safe(self):
57
+ _date = self.date_min
58
+ if _date is None:
59
+ raise ValueError("date_min is not set")
60
+ return _date
61
+
62
+ @property
63
+ def date_max_safe(self):
64
+ _date = self.date_max
65
+ if _date is None:
66
+ raise ValueError("date_max is not set")
67
+ return _date
68
+
69
+ @property
70
+ def date_mean_safe(self):
71
+ _date = self.date_mean
72
+ if _date is None:
73
+ raise ValueError("date_mean is not set")
74
+ return _date
75
+
76
+ @property
77
+ def date_std_dev_safe(self):
78
+ _std_dev = self.date_std_dev
79
+ if _std_dev is None:
80
+ raise ValueError("date_std_dev is not set")
81
+ return _std_dev
82
+
83
+ @property
84
+ def timedelta_days_min_safe(self):
85
+ _min = self.timedelta_days_min
86
+ if _min is None:
87
+ raise ValueError("timedelta_days_min is not set")
88
+ return _min
89
+
90
+ @property
91
+ def timedelta_days_max_safe(self):
92
+ _max = self.timedelta_days_max
93
+ if _max is None:
94
+ raise ValueError("timedelta_days_max is not set")
95
+ return _max
96
+
97
+ @property
98
+ def timedelta_days_mean_safe(self):
99
+ _mean = self.timedelta_days_mean
100
+ if _mean is None:
101
+ raise ValueError("timedelta_days_mean is not set")
102
+ return _mean
103
+
104
+ @property
105
+ def timedelta_days_std_dev_safe(self):
106
+ _std_dev = self.timedelta_days_std_dev
107
+ if _std_dev is None:
108
+ raise ValueError("timedelta_days_std_dev is not set")
109
+ return _std_dev
110
+
50
111
  def generate_value(self):
51
- if self.mode == 'date':
112
+ if self.mode == "date":
52
113
  return self._generate_date_value()
53
- elif self.mode == 'timedelta':
114
+ elif self.mode == "timedelta":
54
115
  return self._generate_timedelta_value()
55
116
  else:
56
117
  raise ValueError("Unsupported mode")
57
118
 
58
119
  def _generate_date_value(self):
59
- #UNTESTED
60
- if self.distribution_type == 'uniform':
61
- start_date = self.date_min.toordinal()
62
- end_date = self.date_max.toordinal()
120
+ # UNTESTED
121
+ if self.distribution_type == "uniform":
122
+ start_date = self.date_min_safe.toordinal()
123
+ end_date = self.date_max_safe.toordinal()
63
124
  random_ordinal = np.random.randint(start_date, end_date)
64
125
  return date.fromordinal(random_ordinal)
65
- elif self.distribution_type == 'normal':
66
- mean_ordinal = self.date_mean.toordinal()
67
- std_dev_days = self.date_std_dev
126
+ elif self.distribution_type == "normal":
127
+ mean_ordinal = self.date_mean_safe.toordinal()
128
+ std_dev_days = self.date_std_dev_safe
68
129
  random_ordinal = int(np.random.normal(mean_ordinal, std_dev_days))
69
- random_ordinal = np.clip(random_ordinal, self.date_min.toordinal(), self.date_max.toordinal())
130
+ random_ordinal = np.clip(random_ordinal, self.date_min_safe.toordinal(), self.date_max_safe.toordinal())
70
131
  return date.fromordinal(random_ordinal)
71
132
  else:
72
133
  raise ValueError("Unsupported distribution type")
73
134
 
74
135
  def _generate_timedelta_value(self):
75
- if self.distribution_type == 'uniform':
76
- random_days = np.random.randint(self.timedelta_days_min, self.timedelta_days_max + 1)
77
-
78
-
79
- elif self.distribution_type == 'normal':
80
- random_days = int(np.random.normal(self.timedelta_days_mean, self.timedelta_days_std_dev))
81
- random_days = np.clip(random_days, self.timedelta_days_min, self.timedelta_days_max)
82
-
136
+ if self.distribution_type == "uniform":
137
+ random_days = np.random.randint(self.timedelta_days_min_safe, self.timedelta_days_max_safe + 1)
138
+
139
+ elif self.distribution_type == "normal":
140
+ random_days = int(np.random.normal(self.timedelta_days_mean_safe, self.timedelta_days_std_dev_safe))
141
+ random_days = np.clip(random_days, self.timedelta_days_min_safe, self.timedelta_days_max_safe)
142
+
83
143
  else:
84
144
  raise ValueError("Unsupported distribution type")
85
-
145
+
86
146
  current_date = date.today()
87
147
  generated_date = current_date - timedelta(days=random_days)
88
- print(generated_date)
89
- return(generated_date)
148
+
149
+ return generated_date
@@ -1,29 +1,45 @@
1
- from django.db import models
2
1
  import numpy as np
2
+ from django.db import models
3
+
3
4
  from .base_value_distribution import BaseValueDistribution
4
5
 
6
+
5
7
  class MultipleCategoricalValueDistributionManager(models.Manager):
6
8
  def get_by_natural_key(self, name):
7
9
  return self.get(name=name)
8
10
 
11
+
9
12
  class MultipleCategoricalValueDistribution(BaseValueDistribution):
10
13
  """
11
14
  Multiple categorical value distribution model.
12
15
  Assigns a specific number or varying number of values based on probabilities.
13
16
  """
17
+
14
18
  objects = MultipleCategoricalValueDistributionManager()
15
19
  categories = models.JSONField() # { "category": "probability", ... }
16
20
  min_count = models.IntegerField()
17
21
  max_count = models.IntegerField()
18
- count_distribution_type = models.CharField(max_length=20, choices=[('uniform', 'Uniform'), ('normal', 'Normal')])
22
+ count_distribution_type = models.CharField(max_length=20, choices=[("uniform", "Uniform"), ("normal", "Normal")])
19
23
  count_mean = models.FloatField(null=True, blank=True)
20
24
  count_std_dev = models.FloatField(null=True, blank=True)
21
25
 
26
+ @property
27
+ def count_mean_safe(self):
28
+ if self.count_mean is None:
29
+ raise ValueError("count_mean is not set")
30
+ return self.count_mean
31
+
32
+ @property
33
+ def count_std_dev_safe(self):
34
+ if self.count_std_dev is None:
35
+ raise ValueError("count_std_dev is not set")
36
+ return self.count_std_dev
37
+
22
38
  def generate_value(self):
23
- if self.count_distribution_type == 'uniform':
39
+ if self.count_distribution_type == "uniform":
24
40
  count = np.random.randint(self.min_count, self.max_count + 1)
25
- elif self.count_distribution_type == 'normal':
26
- count = int(np.random.normal(self.count_mean, self.count_std_dev))
41
+ elif self.count_distribution_type == "normal":
42
+ count = int(np.random.normal(self.count_mean_safe, self.count_std_dev_safe))
27
43
  count = np.clip(count, self.min_count, self.max_count)
28
44
  else:
29
45
  raise ValueError("Unsupported count distribution type")