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
endoreg_db/urls/media.py CHANGED
@@ -1,37 +1,38 @@
1
- from PIL.PdfParser import PdfStream
2
1
  from django.urls import path
3
2
 
3
+ from endoreg_db.views import VideoStreamView
4
+ from endoreg_db.views.ai import label_list
4
5
  from endoreg_db.views.media import (
5
- VideoMediaView,
6
6
  PdfMediaView, # Alias to avoid conflict with legacy pdf.PDFMediaView
7
- video_segments_by_pk,
8
- video_segments_collection,
9
- video_segments_by_video,
10
- video_segment_detail,
11
- video_segments_stats,
12
- video_segment_validate,
13
- video_segments_validate_bulk,
14
- video_segments_validation_status,
15
- video_sensitive_metadata,
16
- video_sensitive_metadata_verify,
7
+ VideoMediaView,
8
+ get_sensitive_metadata_pk,
17
9
  pdf_sensitive_metadata,
10
+ pdf_sensitive_metadata_list,
18
11
  pdf_sensitive_metadata_verify,
19
12
  sensitive_metadata_list,
20
- pdf_sensitive_metadata_list,
13
+ video_sensitive_metadata,
14
+ video_sensitive_metadata_verify,
21
15
  )
22
- from endoreg_db.views import (
23
- VideoStreamView,
16
+ from endoreg_db.views.report.reimport import ReportReimportView
17
+ from endoreg_db.views.report.report_stream import ReportStreamView
18
+ from endoreg_db.views.video import (
19
+ VideoReimportView,
20
+ video_segment_detail,
21
+ video_segment_validate,
22
+ video_segments_by_video,
23
+ video_segments_collection,
24
+ video_segments_stats,
25
+ video_segments_validate_bulk,
26
+ video_segments_validation_status,
24
27
  )
25
- from endoreg_db.views.pdf.reimport import PdfReimportView
26
- from endoreg_db.views.pdf.pdf_stream import PdfStreamView
27
- from endoreg_db.views.video.reimport import VideoReimportView
28
28
  from endoreg_db.views.video.correction import (
29
- VideoMetadataView,
30
- VideoProcessingHistoryView,
31
29
  VideoApplyMaskView,
32
- VideoRemoveFramesView,
33
30
  VideoCorrectionView,
31
+ VideoMetadataStatsView,
32
+ VideoProcessingHistoryView,
33
+ VideoRemoveFramesView,
34
34
  )
35
+
35
36
  # ---------------------------------------------------------------------------------------
36
37
  # ANNOTATION API ENDPOINTS
37
38
  #
@@ -41,19 +42,32 @@ from endoreg_db.views.video.correction import (
41
42
  # ---------------------------------------------------------------------------------------
42
43
 
43
44
  # Simplified Meta and Validation Endpoints
44
-
45
+
45
46
  urlpatterns = [
47
+ path(
48
+ "media/sensitive-media-id/<int:pk>/<str:mediaType>/",
49
+ get_sensitive_metadata_pk,
50
+ name="sm-pk",
51
+ ),
46
52
  # Video media endpoints
47
53
  path("media/videos/", VideoMediaView.as_view(), name="video-list"),
48
- path("media/videos/<int:pk>/", VideoStreamView.as_view(), name="video-detail-stream"), # Support ?type= params
49
- path("media/videos/<int:pk>/details/", VideoMediaView.as_view(), name="video-detail"), # JSON metadata
50
- path("media/videos/<int:pk>/stream/", VideoStreamView.as_view(), name="video-stream"), # Legacy support
51
-
54
+ path(
55
+ "media/videos/<int:pk>/", VideoStreamView.as_view(), name="video-detail-stream"
56
+ ), # Support ?type= params
57
+ path(
58
+ "media/videos/<int:pk>/details/", VideoMediaView.as_view(), name="video-detail"
59
+ ), # JSON metadata
60
+ path(
61
+ "media/videos/<int:pk>/stream/", VideoStreamView.as_view(), name="video-stream"
62
+ ), # Legacy support
52
63
  # Video Re-import API endpoint (modern media framework)
53
64
  # POST /api/media/videos/<int:pk>/reimport/
54
65
  # Re-imports a video file to regenerate metadata when OCR failed or data is incomplete
55
- path("media/videos/<int:pk>/reimport/", VideoReimportView.as_view(), name="video-reimport"),
56
-
66
+ path(
67
+ "media/videos/<int:pk>/reimport/",
68
+ VideoReimportView.as_view(),
69
+ name="video-reimport",
70
+ ),
57
71
  # ---------------------------------------------------------------------------------------
58
72
  # VIDEO CORRECTION API ENDPOINTS (Modern Media Framework - October 14, 2025)
59
73
  #
@@ -66,69 +80,88 @@ urlpatterns = [
66
80
  # - Metadata: View analysis results
67
81
  # - History: Track all correction operations
68
82
  # ---------------------------------------------------------------------------------------
69
-
70
83
  # Video Correction API
71
84
  # GET /api/media/videos/video-correction/{id}/ - Get video details for correction
72
- path("media/videos/video-correction/<int:pk>", VideoCorrectionView.as_view(), name="video-correction"),
73
-
85
+ path(
86
+ "media/videos/video-correction/<int:pk>",
87
+ VideoCorrectionView.as_view(),
88
+ name="video-correction",
89
+ ),
74
90
  # Video Metadata API
75
91
  # GET /api/media/videos/<int:pk>/metadata/
76
92
  # Returns analysis results (sensitive frame count, ratio, frame IDs)
77
- path("media/videos/<int:pk>/metadata/", VideoMetadataView.as_view(), name="video-metadata"),
78
-
93
+ path(
94
+ "media/videos/<int:pk>/metadata/",
95
+ VideoMetadataStatsView.as_view(),
96
+ name="video-metadata",
97
+ ),
79
98
  # Video Processing History API
80
99
  # GET /api/media/videos/<int:pk>/processing-history/
81
100
  # Returns history of all processing operations (masking, frame removal, analysis)
82
- path("media/videos/<int:pk>/processing-history/", VideoProcessingHistoryView.as_view(), name="video-processing-history"),
83
-
101
+ path(
102
+ "media/videos/<int:pk>/processing-history/",
103
+ VideoProcessingHistoryView.as_view(),
104
+ name="video-processing-history",
105
+ ),
84
106
  # Video Analysis API
85
107
  # POST /api/media/videos/<int:pk>/analyze/
86
108
  # Analyzes video for sensitive frames using MiniCPM-o 2.6 or OCR+LLM
87
109
  # Body: { detection_method: 'minicpm'|'ocr_llm'|'hybrid', sample_interval: 30 }
88
-
89
110
  # Video Masking API
90
111
  # POST /api/media/videos/<int:pk>/apply-mask/
91
112
  # Applies device mask or custom ROI mask to video
92
113
  # Body: { mask_type: 'device'|'custom', device_name: 'olympus', roi: {...} }
93
- path("media/videos/<int:pk>/apply-mask/", VideoApplyMaskView.as_view(), name="video-apply-mask"),
94
-
114
+ path(
115
+ "media/videos/<int:pk>/apply-mask/",
116
+ VideoApplyMaskView.as_view(),
117
+ name="video-apply-mask",
118
+ ),
95
119
  # Video Frame Removal API
96
120
  # POST /api/media/videos/<int:pk>/remove-frames/
97
121
  # Removes specified frames from video
98
122
  # Body: { frame_list: [10,20,30] OR frame_ranges: '10-20,30' OR detection_method: 'automatic' }
99
- path("media/videos/<int:pk>/remove-frames/", VideoRemoveFramesView.as_view(), name="video-remove-frames"),
100
-
123
+ path(
124
+ "media/videos/<int:pk>/remove-frames/",
125
+ VideoRemoveFramesView.as_view(),
126
+ name="video-remove-frames",
127
+ ),
128
+ path("media/videos/labels/list/", label_list, name="get_lvs_list"),
101
129
  # ---------------------------------------------------------------------------------------
102
130
  # VIDEO SEGMENT API ENDPOINTS (Modern Media Framework - October 14, 2025)
103
- #
104
- # Unified segment management endpoints replacing legacy /api/video-segments/
105
- # Collection: GET/POST all segments across videos
106
- # Video-scoped: GET/POST segments for specific video
107
- # Detail: GET/PATCH/DELETE individual segment
108
- # ---------------------------------------------------------------------------------------
109
-
110
131
  # Video Segments Collection API
111
132
  # GET/POST /api/media/videos/segments/
112
133
  # List all video segments across videos or create new segment
113
- path("media/videos/segments/", video_segments_collection, name="video-segments-collection"),
114
-
134
+ path(
135
+ "media/videos/segments/",
136
+ video_segments_collection,
137
+ name="video-segments-collection",
138
+ ),
115
139
  # Video Segments Stats API
116
140
  # GET /api/media/videos/segments/stats/
117
141
  # Get statistics about video segments
118
- path("media/videos/segments/stats/", video_segments_stats, name="video-segments-stats"),
119
-
142
+ path(
143
+ "media/videos/segments/stats/",
144
+ video_segments_stats,
145
+ name="video-segments-stats",
146
+ ),
120
147
  # Video-Specific Segments API
121
148
  # GET/POST /api/media/videos/<int:pk>/segments/
122
149
  # List segments for specific video or create segment for video
123
- path("media/videos/<int:pk>/segments/", video_segments_by_video, name="video-segments-by-video"),
124
-
150
+ path(
151
+ "media/videos/<int:pk>/segments/",
152
+ video_segments_by_video,
153
+ name="video-segments-by-video",
154
+ ),
125
155
  # Segment Detail API
126
156
  # GET /api/media/videos/<int:pk>/segments/<int:segment_id>/
127
157
  # PATCH /api/media/videos/<int:pk>/segments/<int:segment_id>/
128
158
  # DELETE /api/media/videos/<int:pk>/segments/<int:segment_id>/
129
159
  # Manages individual segment operations
130
- path("media/videos/<int:pk>/segments/<int:segment_id>/", video_segment_detail, name="video-segment-detail"),
131
-
160
+ path(
161
+ "media/videos/<int:pk>/segments/<int:segment_id>/",
162
+ video_segment_detail,
163
+ name="video-segment-detail",
164
+ ),
132
165
  # ---------------------------------------------------------------------------------------
133
166
  # VIDEO SEGMENT VALIDATION API ENDPOINTS (Modern Media Framework - October 14, 2025)
134
167
  #
@@ -137,65 +170,68 @@ urlpatterns = [
137
170
  # Bulk: POST validate multiple segments
138
171
  # Status: GET/POST validation status for all segments
139
172
  # ---------------------------------------------------------------------------------------
140
-
141
173
  # Single Segment Validation API
142
174
  # POST /api/media/videos/<int:pk>/segments/<int:segment_id>/validate/
143
175
  # Validates a single video segment
144
176
  # Body: { "is_validated": true, "notes": "..." }
145
- path("media/videos/<int:pk>/segments/<int:segment_id>/validate/", video_segment_validate, name="video-segment-validate"),
146
-
177
+ path(
178
+ "media/videos/<int:pk>/segments/<int:segment_id>/validate/",
179
+ video_segment_validate,
180
+ name="video-segment-validate",
181
+ ),
147
182
  # Bulk Segment Validation API
148
183
  # POST /api/media/videos/<int:pk>/segments/validate-bulk/
149
184
  # Validates multiple segments at once
150
185
  # Body: { "segment_ids": [1,2,3], "is_validated": true, "notes": "..." }
151
- path("media/videos/<int:pk>/segments/validate-bulk/", video_segments_validate_bulk, name="video-segments-validate-bulk"),
152
-
186
+ path(
187
+ "media/videos/<int:pk>/segments/validate-bulk/",
188
+ video_segments_validate_bulk,
189
+ name="video-segments-validate-bulk",
190
+ ),
153
191
  # Segment Validation Status API
154
192
  # GET /api/media/videos/<int:pk>/segments/validation-status/
155
193
  # Returns validation statistics for all segments
156
194
  # POST /api/media/videos/<int:pk>/segments/validation-status/
157
195
  # Marks all segments (or filtered by label) as validated
158
196
  # Body: { "label_name": "polyp", "notes": "..." }
159
- path("media/videos/<int:pk>/segments/validation-status/", video_segments_validation_status, name="video-segments-validation-status"),
160
-
197
+ path(
198
+ "media/videos/<int:pk>/segments/validation-status/",
199
+ video_segments_validation_status,
200
+ name="video-segments-validation-status",
201
+ ),
161
202
  # ---------------------------------------------------------------------------------------
162
203
  # SENSITIVE METADATA ENDPOINTS (Modern Media Framework)
163
204
  # ---------------------------------------------------------------------------------------
164
-
165
205
  # Video Sensitive Metadata (Resource-Scoped)
166
206
  # GET/PATCH /api/media/videos/<pk>/sensitive-metadata/
167
207
  # Get or update sensitive patient data for a video
168
208
  path(
169
209
  "media/videos/<int:pk>/sensitive-metadata/",
170
210
  video_sensitive_metadata,
171
- name="video-sensitive-metadata"
211
+ name="video-sensitive-metadata",
172
212
  ),
173
-
174
213
  # POST /api/media/videos/<pk>/sensitive-metadata/verify/
175
214
  # Update verification state (dob_verified, names_verified)
176
215
  path(
177
216
  "media/videos/<int:pk>/sensitive-metadata/verify/",
178
217
  video_sensitive_metadata_verify,
179
- name="video-sensitive-metadata-verify"
218
+ name="video-sensitive-metadata-verify",
180
219
  ),
181
-
182
- # PDF Sensitive Metadata (Resource-Scoped)
220
+ # report Sensitive Metadata (Resource-Scoped)
183
221
  # GET/PATCH /api/media/pdfs/<pk>/sensitive-metadata/
184
- # Get or update sensitive patient data for a PDF
222
+ # Get or update sensitive patient data for a report
185
223
  path(
186
224
  "media/pdfs/<int:pk>/sensitive-metadata/",
187
225
  pdf_sensitive_metadata,
188
- name="pdf-sensitive-metadata"
226
+ name="pdf-sensitive-metadata",
189
227
  ),
190
-
191
228
  # POST /api/media/pdfs/<pk>/sensitive-metadata/verify/
192
229
  # Update verification state (dob_verified, names_verified)
193
230
  path(
194
231
  "media/pdfs/<int:pk>/sensitive-metadata/verify/",
195
232
  pdf_sensitive_metadata_verify,
196
- name="pdf-sensitive-metadata-verify"
233
+ name="pdf-sensitive-metadata-verify",
197
234
  ),
198
-
199
235
  # List Endpoints (Collection-Level)
200
236
  # GET /api/media/sensitive-metadata/
201
237
  # List all sensitive metadata (combined PDFs and Videos)
@@ -203,25 +239,27 @@ urlpatterns = [
203
239
  path(
204
240
  "media/sensitive-metadata/",
205
241
  sensitive_metadata_list,
206
- name="sensitive-metadata-list"
242
+ name="sensitive-metadata-list",
207
243
  ),
208
-
209
244
  # GET /api/media/pdfs/sensitive-metadata/
210
245
  # List sensitive metadata for PDFs only
211
246
  # Replaces legacy /api/pdf/sensitivemeta/list/
212
247
  path(
213
248
  "media/pdfs/sensitive-metadata/",
214
249
  pdf_sensitive_metadata_list,
215
- name="pdf-sensitive-metadata-list"
250
+ name="pdf-sensitive-metadata-list",
216
251
  ),
217
-
218
- # PDF media endpoints
252
+ # report media endpoints
219
253
  path("media/pdfs/", PdfMediaView.as_view(), name="pdf-list"),
220
254
  path("media/pdfs/<int:pk>/", PdfMediaView.as_view(), name="pdf-detail"),
221
- path("media/pdfs/<int:pk>/stream/", PdfStreamView.as_view(), name="pdf-stream"), # Support ?type=raw|anonymized params
222
- # PDF Re-import API endpoint (modern media framework)
255
+ path(
256
+ "media/pdfs/<int:pk>/stream/", ReportStreamView.as_view(), name="pdf-stream"
257
+ ), # Support ?type=raw|anonymized params
258
+ # report Re-import API endpoint (modern media framework)
223
259
  # POST /api/media/pdfs/<int:pk>/reimport/
224
- # Re-imports a PDF file to regenerate metadata when OCR failed or data is incomplete
225
- path("media/pdfs/<int:pk>/reimport/", PdfReimportView.as_view(), name="pdf-reimport"),
260
+ # Re-imports a report file to regenerate metadata when OCR failed or data is incomplete
261
+ path(
262
+ "media/pdfs/<int:pk>/reimport/", ReportReimportView.as_view(), name="report-reimport"
263
+ ),
226
264
  ]
227
- # ---------------------------------------------------------------------------------------
265
+ # ---------------------------------------------------------------------------------------
@@ -0,0 +1,29 @@
1
+ # endoreg_db/urls/root_urls.py
2
+ from django.contrib import admin
3
+ from django.urls import path, include
4
+ from django.http import HttpResponse
5
+ from django.conf import settings
6
+ from django.conf.urls.static import static
7
+
8
+ def public_home(_request):
9
+ return HttpResponse("Public home – no login required.")
10
+
11
+ urlpatterns = [
12
+ # Public landing page
13
+ path("", public_home, name="public_home"),
14
+
15
+ # Django admin (optional)
16
+ path("admin/", admin.site.urls),
17
+
18
+ # Mount ALL API routes under /api/
19
+ # This pulls the urlpatterns exported by endoreg_db/urls/__init__.py
20
+ path("api/", include("endoreg_db.urls")),
21
+
22
+ # Keycloak OIDC (mozilla-django-oidc provides /oidc/authenticate/ and /oidc/callback/)
23
+ path("oidc/", include("mozilla_django_oidc.urls")),
24
+ ]
25
+
26
+ # Serve static/media in DEBUG at the root (NOT under /api/)
27
+ if settings.DEBUG:
28
+ urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
29
+ urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
@@ -4,6 +4,7 @@
4
4
 
5
5
  # dataloader
6
6
  from endoreg_db.utils.video.ffmpeg_wrapper import assemble_video_from_frames, get_stream_info, transcode_video, transcode_videofile_if_required
7
+
7
8
  from .dataloader import load_model_data_from_yaml
8
9
 
9
10
  # dates
@@ -40,18 +41,23 @@ from .paths import data_paths
40
41
 
41
42
  # pydantic_models
42
43
  from .pydantic_models import DbConfig
44
+ from .storage import (
45
+ delete_field_file,
46
+ ensure_local_file,
47
+ save_local_file,
48
+ )
49
+ from .storage import (
50
+ file_exists as storage_file_exists,
51
+ )
43
52
 
44
53
  # validate_endo_roi
45
54
  from .validate_endo_roi import validate_endo_roi
55
+ from .video import split_video
46
56
 
47
57
  # ffmpeg_wrapper
48
58
  from .video.ffmpeg_wrapper import (
49
59
  extract_frames,
50
60
  )
51
- from .video import (
52
- split_video
53
- )
54
-
55
61
 
56
62
  # --- Exports ---
57
63
 
@@ -84,5 +90,9 @@ __all__ = [
84
90
  "transcode_video",
85
91
  "transcode_videofile_if_required", # Added
86
92
  "extract_frames", # Added
93
+ "split_video",
94
+ "delete_field_file",
95
+ "ensure_local_file",
96
+ "save_local_file",
97
+ "storage_file_exists",
87
98
  ]
88
-
@@ -1,10 +1,22 @@
1
+ import logging
2
+ from pathlib import Path
3
+
1
4
  import torch
2
5
  from torchvision import models
3
6
  import torch.nn as nn
4
7
  from pytorch_lightning import LightningModule
5
8
  import numpy as np
9
+ from safetensors.torch import load_file
6
10
  from sklearn.metrics import precision_score, recall_score, f1_score
7
11
 
12
+ try: # Torchvision >= 0.13 exposes explicit weight enums
13
+ from torchvision.models import EfficientNet_B4_Weights, RegNet_X_800MF_Weights
14
+ except ImportError: # pragma: no cover - compatibility with older torchvision
15
+ EfficientNet_B4_Weights = None
16
+ RegNet_X_800MF_Weights = None
17
+
18
+ logger = logging.getLogger(__name__)
19
+
8
20
  METRICS_ON_STEP = False
9
21
 
10
22
 
@@ -41,6 +53,29 @@ def calculate_metrics(pred, target, threshold=0.5):
41
53
  }
42
54
 
43
55
 
56
+ def _load_torchvision_backbone(factory, *, weights_enum=None, load_pretrained=False):
57
+ """Instantiate a torchvision model without triggering unwanted downloads."""
58
+ if weights_enum is not None:
59
+ try:
60
+ weights = weights_enum.DEFAULT if load_pretrained else None
61
+ return factory(weights=weights)
62
+ except (TypeError, AttributeError):
63
+ # Fall back to legacy keyword on older torchvision versions
64
+ pass
65
+
66
+ try:
67
+ return factory(pretrained=load_pretrained)
68
+ except TypeError:
69
+ # Newer torchvision versions removed the pretrained kwarg; call without hints
70
+ try:
71
+ return factory()
72
+ except Exception as exc: # pragma: no cover - surfaced to caller for visibility
73
+ raise RuntimeError(
74
+ "Failed to instantiate torchvision backbone with load_pretrained="
75
+ f"{load_pretrained}."
76
+ ) from exc
77
+
78
+
44
79
  class MultiLabelClassificationNet(LightningModule):
45
80
  def __init__(
46
81
  self,
@@ -49,26 +84,40 @@ class MultiLabelClassificationNet(LightningModule):
49
84
  weight_decay=0.001,
50
85
  pos_weight=2,
51
86
  model_type="EfficientNetB4",
87
+ load_imagenet_weights: bool = False,
88
+ track_hparams: bool = True,
52
89
  ):
53
90
  super().__init__()
54
- self.save_hyperparameters()
55
- self.model_type = "RegNetX800MF" # model_type
56
- self.labels = labels
57
- self.n_classes = len(labels)
58
- self.val_preds = []
59
- self.val_targets = []
91
+ if track_hparams:
92
+ self.save_hyperparameters()
93
+ if labels is None:
94
+ raise ValueError("labels must be provided to initialize MultiLabelClassificationNet")
95
+
96
+ self.model_type = model_type
97
+ self.labels = list(labels)
98
+ self.n_classes = len(self.labels)
99
+ self.val_preds: list[np.ndarray] = []
100
+ self.val_targets: list[np.ndarray] = []
60
101
  self.pos_weight = pos_weight
61
102
  self.weight_decay = weight_decay
62
103
  self.lr = lr
63
104
  self.sigm = nn.Sigmoid()
64
105
 
65
106
  if model_type == "EfficientNetB4":
66
- self.model = models.efficientnet_b4(pretrained=True)
107
+ self.model = _load_torchvision_backbone(
108
+ models.efficientnet_b4,
109
+ weights_enum=EfficientNet_B4_Weights,
110
+ load_pretrained=load_imagenet_weights,
111
+ )
67
112
  num_ftrs = self.model.classifier[1].in_features
68
113
  self.model.classifier[1] = nn.Linear(num_ftrs, len(labels))
69
114
 
70
115
  elif model_type == "RegNetX800MF":
71
- self.model = models.regnet_x_800mf(pretrained=True)
116
+ self.model = _load_torchvision_backbone(
117
+ models.regnet_x_800mf,
118
+ weights_enum=RegNet_X_800MF_Weights,
119
+ load_pretrained=load_imagenet_weights,
120
+ )
72
121
  num_ftrs = self.model.fc.in_features
73
122
  self.model.fc = nn.Linear(num_ftrs, len(labels))
74
123
 
@@ -78,10 +127,47 @@ class MultiLabelClassificationNet(LightningModule):
78
127
 
79
128
  @classmethod
80
129
  def load_from_checkpoint(cls, checkpoint_path, *args, **kwargs):
81
- instance = super(MultiLabelClassificationNet, cls).load_from_checkpoint(
130
+ path = Path(checkpoint_path)
131
+ suffix = path.suffix.lower()
132
+
133
+ if suffix == ".safetensors":
134
+ map_location = kwargs.pop("map_location", "cpu")
135
+ strict = kwargs.pop("strict", True)
136
+ labels = kwargs.pop("labels", None)
137
+ if not labels:
138
+ raise ValueError("labels must be provided when loading .safetensors checkpoints")
139
+ model_type = kwargs.pop("model_type", None) or "EfficientNetB4"
140
+ load_imagenet = kwargs.pop("load_imagenet_weights", False)
141
+
142
+ device = torch.device(map_location) if map_location is not None else torch.device("cpu")
143
+ if isinstance(device, torch.device):
144
+ device_hint = f"{device.type}:{device.index}" if device.index is not None else device.type
145
+ else:
146
+ device_hint = device
147
+
148
+ state_dict = load_file(path, device=device_hint)
149
+
150
+ instance = cls(
151
+ labels=labels,
152
+ model_type=model_type,
153
+ load_imagenet_weights=load_imagenet,
154
+ track_hparams=False,
155
+ *args,
156
+ **kwargs,
157
+ )
158
+ missing, unexpected = instance.load_state_dict(state_dict, strict=strict)
159
+
160
+ if missing:
161
+ logger.warning("Missing parameters when loading %s: %s", path, missing)
162
+ if unexpected:
163
+ logger.warning("Unexpected parameters when loading %s: %s", path, unexpected)
164
+
165
+ instance.to(device)
166
+ return instance
167
+
168
+ return super(MultiLabelClassificationNet, cls).load_from_checkpoint(
82
169
  checkpoint_path, *args, **kwargs
83
170
  )
84
- return instance
85
171
 
86
172
  def forward(self, x): # pylint: disable=arguments-differ
87
173
  x = self.model(x)
@@ -113,18 +199,24 @@ class MultiLabelClassificationNet(LightningModule):
113
199
 
114
200
  def validation_epoch_end(self, _outputs):
115
201
  """Called at the end of validation to aggregate outputs"""
116
- self.val_preds = np.concatenate([_ for _ in self.val_preds])
117
- self.val_targets = np.concatenate([_ for _ in self.val_targets])
118
-
119
- metrics = calculate_metrics(self.val_preds, self.val_targets, threshold=0.5)
120
- for key, value in metrics.items():
121
- value = value.tolist()
122
- if isinstance(value, list):
123
- for i, _value in enumerate(value):
202
+ val_preds_np = np.concatenate(self.val_preds)
203
+ val_targets_np = np.concatenate(self.val_targets)
204
+
205
+ metrics = calculate_metrics(val_preds_np, val_targets_np, threshold=0.5)
206
+ for key, metric_value in metrics.items():
207
+ if isinstance(metric_value, np.ndarray):
208
+ processed_value = metric_value.tolist()
209
+ elif isinstance(metric_value, (list, tuple)):
210
+ processed_value = list(metric_value)
211
+ else:
212
+ processed_value = float(metric_value)
213
+
214
+ if isinstance(processed_value, list):
215
+ for i, single_value in enumerate(processed_value):
124
216
  name = "val/" + f"{key}/{self.labels[i]}"
125
217
  self.log(
126
218
  name,
127
- _value,
219
+ float(single_value),
128
220
  on_epoch=True,
129
221
  on_step=METRICS_ON_STEP,
130
222
  prog_bar=False,
@@ -132,7 +224,11 @@ class MultiLabelClassificationNet(LightningModule):
132
224
  else:
133
225
  name = "val/" + f"{key}"
134
226
  self.log(
135
- name, value, on_epoch=True, on_step=METRICS_ON_STEP, prog_bar=True
227
+ name,
228
+ float(processed_value),
229
+ on_epoch=True,
230
+ on_step=METRICS_ON_STEP,
231
+ prog_bar=True,
136
232
  )
137
233
 
138
234
  self.val_preds = []
@@ -0,0 +1,3 @@
1
+ """Legacy case generator utilities based on deprecated case templates."""
2
+
3
+ __all__: list[str] = []