endoreg-db 0.8.4.4__py3-none-any.whl → 0.8.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (372) hide show
  1. endoreg_db/authz/auth.py +74 -0
  2. endoreg_db/authz/backends.py +168 -0
  3. endoreg_db/authz/management/commands/list_routes.py +18 -0
  4. endoreg_db/authz/middleware.py +83 -0
  5. endoreg_db/authz/permissions.py +127 -0
  6. endoreg_db/authz/policy.py +218 -0
  7. endoreg_db/authz/views_auth.py +66 -0
  8. endoreg_db/config/env.py +13 -8
  9. endoreg_db/data/__init__.py +8 -31
  10. endoreg_db/data/_examples/disease.yaml +55 -0
  11. endoreg_db/data/_examples/disease_classification.yaml +13 -0
  12. endoreg_db/data/_examples/disease_classification_choice.yaml +62 -0
  13. endoreg_db/data/_examples/event.yaml +64 -0
  14. endoreg_db/data/_examples/examination.yaml +72 -0
  15. endoreg_db/data/_examples/finding/anatomy_colon.yaml +128 -0
  16. endoreg_db/data/_examples/finding/colonoscopy.yaml +40 -0
  17. endoreg_db/data/_examples/finding/colonoscopy_bowel_prep.yaml +56 -0
  18. endoreg_db/data/_examples/finding/complication.yaml +16 -0
  19. endoreg_db/data/_examples/finding/data.yaml +105 -0
  20. endoreg_db/data/_examples/finding/examination_setting.yaml +16 -0
  21. endoreg_db/data/_examples/finding/medication_related.yaml +18 -0
  22. endoreg_db/data/_examples/finding/outcome.yaml +12 -0
  23. endoreg_db/data/_examples/finding_classification/colonoscopy_bowel_preparation.yaml +68 -0
  24. endoreg_db/data/_examples/finding_classification/colonoscopy_jnet.yaml +22 -0
  25. endoreg_db/data/_examples/finding_classification/colonoscopy_kudo.yaml +25 -0
  26. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
  27. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
  28. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_size.yaml +68 -0
  29. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
  30. endoreg_db/data/_examples/finding_classification/colonoscopy_location.yaml +80 -0
  31. endoreg_db/data/_examples/finding_classification/colonoscopy_lst.yaml +21 -0
  32. endoreg_db/data/_examples/finding_classification/colonoscopy_nice.yaml +20 -0
  33. endoreg_db/data/_examples/finding_classification/colonoscopy_paris.yaml +26 -0
  34. endoreg_db/data/_examples/finding_classification/colonoscopy_sano.yaml +22 -0
  35. endoreg_db/data/_examples/finding_classification/colonoscopy_summary.yaml +53 -0
  36. endoreg_db/data/_examples/finding_classification/complication_generic.yaml +25 -0
  37. endoreg_db/data/_examples/finding_classification/examination_setting_generic.yaml +40 -0
  38. endoreg_db/data/_examples/finding_classification/histology_colo.yaml +51 -0
  39. endoreg_db/data/_examples/finding_classification/intervention_required.yaml +26 -0
  40. endoreg_db/data/_examples/finding_classification/medication_related.yaml +23 -0
  41. endoreg_db/data/_examples/finding_classification/visualized.yaml +33 -0
  42. endoreg_db/data/_examples/finding_classification_choice/bowel_preparation.yaml +78 -0
  43. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_circularity_default.yaml +32 -0
  44. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
  45. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
  46. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_lst.yaml +15 -0
  47. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_nice.yaml +17 -0
  48. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_paris.yaml +57 -0
  49. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_planarity_default.yaml +49 -0
  50. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_sano.yaml +14 -0
  51. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_surface_intact_default.yaml +36 -0
  52. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_location.yaml +229 -0
  53. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
  54. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_size.yaml +82 -0
  55. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
  56. endoreg_db/data/_examples/finding_classification_choice/complication_generic_types.yaml +15 -0
  57. endoreg_db/data/_examples/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
  58. endoreg_db/data/_examples/finding_classification_choice/histology.yaml +24 -0
  59. endoreg_db/data/_examples/finding_classification_choice/histology_polyp.yaml +20 -0
  60. endoreg_db/data/_examples/finding_classification_choice/outcome.yaml +19 -0
  61. endoreg_db/data/_examples/finding_classification_choice/yes_no_na.yaml +11 -0
  62. endoreg_db/data/_examples/finding_classification_type/colonoscopy_basic.yaml +48 -0
  63. endoreg_db/data/_examples/finding_intervention/endoscopy.yaml +43 -0
  64. endoreg_db/data/_examples/finding_intervention/endoscopy_colonoscopy.yaml +168 -0
  65. endoreg_db/data/_examples/finding_intervention/endoscopy_egd.yaml +128 -0
  66. endoreg_db/data/_examples/finding_intervention/endoscopy_ercp.yaml +32 -0
  67. endoreg_db/data/_examples/finding_intervention/endoscopy_eus_lower.yaml +9 -0
  68. endoreg_db/data/_examples/finding_intervention/endoscopy_eus_upper.yaml +36 -0
  69. endoreg_db/data/_examples/finding_intervention_type/endoscopy.yaml +15 -0
  70. endoreg_db/data/_examples/finding_type/data.yaml +43 -0
  71. endoreg_db/data/_examples/requirement/age.yaml +26 -0
  72. endoreg_db/data/_examples/requirement/colonoscopy_baseline_austria.yaml +45 -0
  73. endoreg_db/data/_examples/requirement/disease_cardiovascular.yaml +79 -0
  74. endoreg_db/data/_examples/requirement/disease_classification_choice_cardiovascular.yaml +41 -0
  75. endoreg_db/data/_examples/requirement/disease_hepatology.yaml +12 -0
  76. endoreg_db/data/_examples/requirement/disease_misc.yaml +12 -0
  77. endoreg_db/data/_examples/requirement/disease_renal.yaml +96 -0
  78. endoreg_db/data/_examples/requirement/endoscopy_bleeding_risk.yaml +59 -0
  79. endoreg_db/data/_examples/requirement/event_cardiology.yaml +251 -0
  80. endoreg_db/data/_examples/requirement/event_requirements.yaml +145 -0
  81. endoreg_db/data/_examples/requirement/finding_colon_polyp.yaml +50 -0
  82. endoreg_db/data/_examples/requirement/gender.yaml +25 -0
  83. endoreg_db/data/_examples/requirement/lab_value.yaml +441 -0
  84. endoreg_db/data/_examples/requirement/medication.yaml +93 -0
  85. endoreg_db/data/_examples/requirement_operator/age.yaml +13 -0
  86. endoreg_db/data/_examples/requirement_operator/lab_operators.yaml +129 -0
  87. endoreg_db/data/_examples/requirement_operator/model_operators.yaml +96 -0
  88. endoreg_db/data/_examples/requirement_set/01_endoscopy_generic.yaml +48 -0
  89. endoreg_db/data/_examples/requirement_set/colonoscopy_austria_screening.yaml +57 -0
  90. endoreg_db/data/_examples/yaml_examples.xlsx +0 -0
  91. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +4 -3
  92. endoreg_db/data/event_classification/data.yaml +4 -0
  93. endoreg_db/data/event_classification_choice/data.yaml +9 -0
  94. endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +43 -70
  95. endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +22 -52
  96. endoreg_db/data/finding_classification/colonoscopy_location.yaml +31 -62
  97. endoreg_db/data/finding_classification/histology_colo.yaml +28 -36
  98. endoreg_db/data/requirement/colon_polyp_intervention.yaml +49 -0
  99. endoreg_db/data/requirement/coloreg_colon_polyp.yaml +49 -0
  100. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +31 -12
  101. endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
  102. endoreg_db/data/requirement_set/02_endoscopy_bleeding_risk.yaml +46 -0
  103. endoreg_db/data/requirement_set/90_coloreg.yaml +178 -0
  104. endoreg_db/data/requirement_set/_old_ +109 -0
  105. endoreg_db/data/requirement_set_type/data.yaml +21 -0
  106. endoreg_db/data/setup_config.yaml +4 -4
  107. endoreg_db/data/tag/requirement_set_tags.yaml +21 -0
  108. endoreg_db/exceptions.py +5 -2
  109. endoreg_db/helpers/data_loader.py +1 -1
  110. endoreg_db/management/commands/create_model_meta_from_huggingface.py +21 -10
  111. endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
  112. endoreg_db/management/commands/import_video.py +9 -10
  113. endoreg_db/management/commands/import_video_with_classification.py +1 -1
  114. endoreg_db/management/commands/init_default_ai_model.py +1 -1
  115. endoreg_db/management/commands/list_routes.py +18 -0
  116. endoreg_db/management/commands/load_ai_model_data.py +2 -1
  117. endoreg_db/management/commands/load_center_data.py +12 -12
  118. endoreg_db/management/commands/load_requirement_data.py +60 -31
  119. endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
  120. endoreg_db/management/commands/setup_endoreg_db.py +14 -10
  121. endoreg_db/management/commands/storage_management.py +271 -203
  122. endoreg_db/migrations/0001_initial.py +1799 -1300
  123. endoreg_db/migrations/0002_requirementset_depends_on.py +18 -0
  124. endoreg_db/migrations/_old/0001_initial.py +1857 -0
  125. endoreg_db/migrations/_old/0004_employee_city_employee_post_code_employee_street_and_more.py +68 -0
  126. endoreg_db/migrations/_old/0004_remove_casetemplate_rules_and_more.py +77 -0
  127. endoreg_db/migrations/_old/0005_merge_20251111_1003.py +14 -0
  128. endoreg_db/migrations/_old/0006_sensitivemeta_anonymized_text_and_more.py +68 -0
  129. endoreg_db/migrations/_old/0007_remove_rule_attribute_dtype_remove_rule_rule_type_and_more.py +89 -0
  130. endoreg_db/migrations/_old/0008_remove_event_event_classification_and_more.py +27 -0
  131. endoreg_db/migrations/_old/0009_alter_modelmeta_options_and_more.py +21 -0
  132. endoreg_db/models/__init__.py +78 -123
  133. endoreg_db/models/administration/__init__.py +21 -42
  134. endoreg_db/models/administration/ai/active_model.py +2 -2
  135. endoreg_db/models/administration/ai/ai_model.py +7 -6
  136. endoreg_db/models/administration/case/__init__.py +1 -15
  137. endoreg_db/models/administration/case/case.py +3 -3
  138. endoreg_db/models/administration/case/case_template/__init__.py +2 -14
  139. endoreg_db/models/administration/case/case_template/case_template.py +2 -124
  140. endoreg_db/models/administration/case/case_template/case_template_rule.py +2 -268
  141. endoreg_db/models/administration/case/case_template/case_template_rule_value.py +2 -85
  142. endoreg_db/models/administration/case/case_template/case_template_type.py +2 -25
  143. endoreg_db/models/administration/center/center.py +33 -19
  144. endoreg_db/models/administration/center/center_product.py +12 -9
  145. endoreg_db/models/administration/center/center_resource.py +25 -19
  146. endoreg_db/models/administration/center/center_shift.py +21 -17
  147. endoreg_db/models/administration/center/center_waste.py +16 -8
  148. endoreg_db/models/administration/person/__init__.py +2 -0
  149. endoreg_db/models/administration/person/employee/employee.py +10 -5
  150. endoreg_db/models/administration/person/employee/employee_qualification.py +9 -4
  151. endoreg_db/models/administration/person/employee/employee_type.py +12 -6
  152. endoreg_db/models/administration/person/examiner/examiner.py +13 -11
  153. endoreg_db/models/administration/person/patient/__init__.py +2 -0
  154. endoreg_db/models/administration/person/patient/patient.py +103 -100
  155. endoreg_db/models/administration/person/patient/patient_external_id.py +37 -0
  156. endoreg_db/models/administration/person/person.py +4 -0
  157. endoreg_db/models/administration/person/profession/__init__.py +8 -4
  158. endoreg_db/models/administration/person/user/portal_user_information.py +11 -7
  159. endoreg_db/models/administration/product/product.py +20 -15
  160. endoreg_db/models/administration/product/product_material.py +17 -18
  161. endoreg_db/models/administration/product/product_weight.py +12 -8
  162. endoreg_db/models/administration/product/reference_product.py +23 -55
  163. endoreg_db/models/administration/qualification/qualification.py +7 -3
  164. endoreg_db/models/administration/qualification/qualification_type.py +7 -3
  165. endoreg_db/models/administration/shift/scheduled_days.py +8 -5
  166. endoreg_db/models/administration/shift/shift.py +16 -12
  167. endoreg_db/models/administration/shift/shift_type.py +23 -31
  168. endoreg_db/models/label/__init__.py +7 -8
  169. endoreg_db/models/label/annotation/image_classification.py +10 -9
  170. endoreg_db/models/label/annotation/video_segmentation_annotation.py +8 -5
  171. endoreg_db/models/label/label.py +15 -15
  172. endoreg_db/models/label/label_set.py +19 -6
  173. endoreg_db/models/label/label_type.py +1 -1
  174. endoreg_db/models/label/label_video_segment/_create_from_video.py +5 -8
  175. endoreg_db/models/label/label_video_segment/label_video_segment.py +76 -102
  176. endoreg_db/models/label/video_segmentation_label.py +4 -0
  177. endoreg_db/models/label/video_segmentation_labelset.py +4 -3
  178. endoreg_db/models/media/frame/frame.py +22 -22
  179. endoreg_db/models/media/pdf/raw_pdf.py +249 -177
  180. endoreg_db/models/media/pdf/report_file.py +25 -29
  181. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +30 -46
  182. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
  183. endoreg_db/models/media/video/__init__.py +1 -0
  184. endoreg_db/models/media/video/create_from_file.py +48 -56
  185. endoreg_db/models/media/video/pipe_1.py +30 -33
  186. endoreg_db/models/media/video/pipe_2.py +8 -9
  187. endoreg_db/models/media/video/video_file.py +359 -204
  188. endoreg_db/models/media/video/video_file_ai.py +288 -74
  189. endoreg_db/models/media/video/video_file_anonymize.py +38 -38
  190. endoreg_db/models/media/video/video_file_frames/__init__.py +3 -1
  191. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -8
  192. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +7 -9
  193. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +9 -8
  194. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +38 -45
  195. endoreg_db/models/media/video/video_file_frames/_get_frame.py +6 -8
  196. endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +4 -18
  197. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -3
  198. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +7 -6
  199. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +6 -8
  200. endoreg_db/models/media/video/video_file_frames/_get_frames.py +6 -8
  201. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +15 -25
  202. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +26 -23
  203. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +23 -14
  204. endoreg_db/models/media/video/video_file_io.py +109 -62
  205. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +3 -3
  206. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +5 -3
  207. endoreg_db/models/media/video/video_file_meta/get_fps.py +37 -34
  208. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +19 -25
  209. endoreg_db/models/media/video/video_file_meta/text_meta.py +41 -38
  210. endoreg_db/models/media/video/video_file_meta/video_meta.py +14 -7
  211. endoreg_db/models/media/video/video_file_segments.py +24 -17
  212. endoreg_db/models/media/video/video_metadata.py +19 -35
  213. endoreg_db/models/media/video/video_processing.py +96 -95
  214. endoreg_db/models/medical/contraindication/__init__.py +13 -3
  215. endoreg_db/models/medical/disease.py +22 -16
  216. endoreg_db/models/medical/event.py +31 -18
  217. endoreg_db/models/medical/examination/__init__.py +13 -6
  218. endoreg_db/models/medical/examination/examination.py +17 -18
  219. endoreg_db/models/medical/examination/examination_indication.py +26 -25
  220. endoreg_db/models/medical/examination/examination_time.py +16 -6
  221. endoreg_db/models/medical/examination/examination_time_type.py +9 -6
  222. endoreg_db/models/medical/examination/examination_type.py +3 -4
  223. endoreg_db/models/medical/finding/finding.py +38 -39
  224. endoreg_db/models/medical/finding/finding_classification.py +37 -48
  225. endoreg_db/models/medical/finding/finding_intervention.py +27 -22
  226. endoreg_db/models/medical/finding/finding_type.py +13 -12
  227. endoreg_db/models/medical/hardware/endoscope.py +20 -26
  228. endoreg_db/models/medical/hardware/endoscopy_processor.py +2 -2
  229. endoreg_db/models/medical/laboratory/lab_value.py +62 -91
  230. endoreg_db/models/medical/medication/medication.py +22 -10
  231. endoreg_db/models/medical/medication/medication_indication.py +29 -3
  232. endoreg_db/models/medical/medication/medication_indication_type.py +25 -14
  233. endoreg_db/models/medical/medication/medication_intake_time.py +31 -19
  234. endoreg_db/models/medical/medication/medication_schedule.py +27 -16
  235. endoreg_db/models/medical/organ/__init__.py +15 -12
  236. endoreg_db/models/medical/patient/medication_examples.py +1 -5
  237. endoreg_db/models/medical/patient/patient_disease.py +20 -23
  238. endoreg_db/models/medical/patient/patient_event.py +19 -22
  239. endoreg_db/models/medical/patient/patient_examination.py +48 -54
  240. endoreg_db/models/medical/patient/patient_examination_indication.py +16 -14
  241. endoreg_db/models/medical/patient/patient_finding.py +122 -139
  242. endoreg_db/models/medical/patient/patient_finding_classification.py +44 -49
  243. endoreg_db/models/medical/patient/patient_finding_intervention.py +8 -19
  244. endoreg_db/models/medical/patient/patient_lab_sample.py +28 -23
  245. endoreg_db/models/medical/patient/patient_lab_value.py +82 -89
  246. endoreg_db/models/medical/patient/patient_medication.py +27 -38
  247. endoreg_db/models/medical/patient/patient_medication_schedule.py +28 -36
  248. endoreg_db/models/medical/risk/risk.py +7 -6
  249. endoreg_db/models/medical/risk/risk_type.py +8 -5
  250. endoreg_db/models/metadata/model_meta.py +60 -29
  251. endoreg_db/models/metadata/model_meta_logic.py +139 -18
  252. endoreg_db/models/metadata/pdf_meta.py +19 -24
  253. endoreg_db/models/metadata/sensitive_meta.py +102 -85
  254. endoreg_db/models/metadata/sensitive_meta_logic.py +383 -43
  255. endoreg_db/models/metadata/video_meta.py +51 -31
  256. endoreg_db/models/metadata/video_prediction_logic.py +16 -23
  257. endoreg_db/models/metadata/video_prediction_meta.py +29 -33
  258. endoreg_db/models/other/distribution/date_value_distribution.py +89 -29
  259. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +21 -5
  260. endoreg_db/models/other/distribution/numeric_value_distribution.py +114 -53
  261. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +4 -3
  262. endoreg_db/models/other/emission/emission_factor.py +18 -8
  263. endoreg_db/models/other/gender.py +10 -5
  264. endoreg_db/models/other/information_source.py +25 -25
  265. endoreg_db/models/other/material.py +9 -5
  266. endoreg_db/models/other/resource.py +6 -4
  267. endoreg_db/models/other/tag.py +10 -5
  268. endoreg_db/models/other/transport_route.py +13 -8
  269. endoreg_db/models/other/unit.py +10 -6
  270. endoreg_db/models/other/waste.py +6 -5
  271. endoreg_db/models/requirement/requirement.py +580 -272
  272. endoreg_db/models/requirement/requirement_error.py +85 -0
  273. endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
  274. endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +3 -6
  275. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +90 -64
  276. endoreg_db/models/requirement/requirement_operator.py +36 -33
  277. endoreg_db/models/requirement/requirement_set.py +74 -57
  278. endoreg_db/models/state/__init__.py +4 -4
  279. endoreg_db/models/state/abstract.py +2 -2
  280. endoreg_db/models/state/anonymization.py +12 -0
  281. endoreg_db/models/state/audit_ledger.py +46 -47
  282. endoreg_db/models/state/label_video_segment.py +9 -0
  283. endoreg_db/models/state/raw_pdf.py +40 -46
  284. endoreg_db/models/state/sensitive_meta.py +6 -2
  285. endoreg_db/models/state/video.py +58 -53
  286. endoreg_db/models/upload_job.py +32 -55
  287. endoreg_db/models/utils.py +1 -2
  288. endoreg_db/root_urls.py +21 -2
  289. endoreg_db/serializers/__init__.py +26 -57
  290. endoreg_db/serializers/anonymization.py +18 -10
  291. endoreg_db/serializers/meta/report_meta.py +1 -1
  292. endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
  293. endoreg_db/serializers/misc/__init__.py +1 -1
  294. endoreg_db/serializers/misc/file_overview.py +33 -91
  295. endoreg_db/serializers/misc/{vop_patient_data.py → sensitive_patient_data.py} +1 -1
  296. endoreg_db/serializers/requirements/requirement_sets.py +92 -22
  297. endoreg_db/serializers/video/segmentation.py +2 -1
  298. endoreg_db/serializers/video/video_processing_history.py +20 -5
  299. endoreg_db/serializers/video_examination.py +198 -0
  300. endoreg_db/services/anonymization.py +75 -73
  301. endoreg_db/services/lookup_service.py +256 -73
  302. endoreg_db/services/lookup_store.py +174 -30
  303. endoreg_db/services/pdf_import.py +711 -310
  304. endoreg_db/services/storage_aware_video_processor.py +140 -114
  305. endoreg_db/services/video_import.py +266 -117
  306. endoreg_db/urls/__init__.py +27 -27
  307. endoreg_db/urls/label_video_segments.py +2 -0
  308. endoreg_db/urls/media.py +108 -66
  309. endoreg_db/urls/root_urls.py +29 -0
  310. endoreg_db/utils/__init__.py +15 -5
  311. endoreg_db/utils/ai/multilabel_classification_net.py +116 -20
  312. endoreg_db/utils/case_generator/__init__.py +3 -0
  313. endoreg_db/utils/dataloader.py +88 -16
  314. endoreg_db/utils/defaults/set_default_center.py +32 -0
  315. endoreg_db/utils/names.py +22 -16
  316. endoreg_db/utils/permissions.py +2 -1
  317. endoreg_db/utils/pipelines/process_video_dir.py +1 -1
  318. endoreg_db/utils/requirement_operator_logic/model_evaluators.py +414 -127
  319. endoreg_db/utils/setup_config.py +8 -5
  320. endoreg_db/utils/storage.py +115 -0
  321. endoreg_db/utils/validate_endo_roi.py +8 -2
  322. endoreg_db/utils/video/ffmpeg_wrapper.py +184 -188
  323. endoreg_db/views/__init__.py +5 -12
  324. endoreg_db/views/anonymization/media_management.py +198 -163
  325. endoreg_db/views/anonymization/overview.py +4 -1
  326. endoreg_db/views/anonymization/validate.py +174 -40
  327. endoreg_db/views/media/__init__.py +2 -0
  328. endoreg_db/views/media/pdf_media.py +131 -150
  329. endoreg_db/views/media/sensitive_metadata.py +46 -6
  330. endoreg_db/views/media/video_media.py +89 -82
  331. endoreg_db/views/media/video_segments.py +187 -260
  332. endoreg_db/views/meta/sensitive_meta_detail.py +0 -63
  333. endoreg_db/views/patient/patient.py +5 -4
  334. endoreg_db/views/pdf/__init__.py +5 -8
  335. endoreg_db/views/pdf/pdf_stream.py +186 -0
  336. endoreg_db/views/pdf/pdf_stream_views.py +0 -127
  337. endoreg_db/views/pdf/reimport.py +86 -91
  338. endoreg_db/views/requirement/evaluate.py +188 -187
  339. endoreg_db/views/requirement/lookup.py +186 -288
  340. endoreg_db/views/requirement/requirement_utils.py +89 -0
  341. endoreg_db/views/video/__init__.py +0 -4
  342. endoreg_db/views/video/correction.py +2 -2
  343. endoreg_db/views/video/video_examination_viewset.py +202 -289
  344. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/METADATA +7 -3
  345. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/RECORD +350 -255
  346. endoreg_db/models/administration/permissions/__init__.py +0 -44
  347. endoreg_db/models/media/video/refactor_plan.md +0 -0
  348. endoreg_db/models/media/video/video_file_frames.py +0 -0
  349. endoreg_db/models/metadata/frame_ocr_result.py +0 -0
  350. endoreg_db/models/rule/__init__.py +0 -13
  351. endoreg_db/models/rule/rule.py +0 -27
  352. endoreg_db/models/rule/rule_applicator.py +0 -224
  353. endoreg_db/models/rule/rule_attribute_dtype.py +0 -17
  354. endoreg_db/models/rule/rule_type.py +0 -20
  355. endoreg_db/models/rule/ruleset.py +0 -17
  356. endoreg_db/serializers/video/video_metadata.py +0 -105
  357. endoreg_db/urls/report.py +0 -48
  358. endoreg_db/urls/video.py +0 -61
  359. endoreg_db/utils/case_generator/case_generator.py +0 -159
  360. endoreg_db/utils/case_generator/utils.py +0 -30
  361. endoreg_db/views/pdf/pdf_media.py +0 -239
  362. endoreg_db/views/report/__init__.py +0 -9
  363. endoreg_db/views/report/report_list.py +0 -112
  364. endoreg_db/views/report/report_with_secure_url.py +0 -28
  365. endoreg_db/views/report/start_examination.py +0 -7
  366. endoreg_db/views/video/video_media.py +0 -158
  367. endoreg_db/views.py +0 -0
  368. /endoreg_db/data/{requirement_set → _examples/requirement_set}/endoscopy_bleeding_risk.yaml +0 -0
  369. /endoreg_db/migrations/{0002_add_video_correction_models.py → _old/0002_add_video_correction_models.py} +0 -0
  370. /endoreg_db/migrations/{0003_add_center_display_name.py → _old/0003_add_center_display_name.py} +0 -0
  371. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/WHEEL +0 -0
  372. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,12 +1,14 @@
1
- from django.db import transaction
2
- from pathlib import Path
3
1
  import logging
4
2
  import shutil
5
3
  from datetime import datetime
4
+ from pathlib import Path
6
5
  from typing import Optional
7
6
 
8
- from endoreg_db.models import VideoFile, AnonymizationTask
7
+ from django.db import transaction
8
+
9
9
  from endoreg_db.exceptions import InsufficientStorageError
10
+ from endoreg_db.models import AnonymizationTask, VideoFile
11
+
10
12
  # from endoreg_db.models.media.video.create_from_file import check_storage_capacity
11
13
 
12
14
  logger = logging.getLogger(__name__)
@@ -16,209 +18,230 @@ class StorageAwareVideoProcessor:
16
18
  """
17
19
  Enhanced video processor with built-in storage management and automatic cleanup.
18
20
  """
19
-
21
+
20
22
  def __init__(self, auto_cleanup: bool = True, min_free_space_gb: float = 10.0):
21
23
  self.auto_cleanup = auto_cleanup
22
24
  self.min_free_space_gb = min_free_space_gb
23
-
25
+
24
26
  def check_and_ensure_storage(self, required_space_estimate: int = None) -> bool:
25
27
  """
26
28
  Check storage capacity and perform cleanup if needed.
27
-
29
+
28
30
  Args:
29
31
  required_space_estimate: Estimated space needed in bytes
30
-
32
+
31
33
  Returns:
32
34
  True if enough space is available, False otherwise
33
-
35
+
34
36
  Raises:
35
37
  InsufficientStorageError: If space cannot be freed
36
38
  """
37
39
  try:
38
40
  # Get current storage stats
39
- total, used, free = shutil.disk_usage('/')
41
+ total, used, free = shutil.disk_usage("/")
40
42
  free_gb = free / (1024**3)
41
43
  usage_percent = (used / total) * 100
42
-
43
- logger.info(f"Storage check: {free_gb:.1f}GB free ({usage_percent:.1f}% used)")
44
-
44
+
45
+ logger.info(
46
+ f"Storage check: {free_gb:.1f}GB free ({usage_percent:.1f}% used)"
47
+ )
48
+
45
49
  # Check if we need emergency cleanup
46
50
  needs_cleanup = (
47
- usage_percent >= 95.0 or
48
- free_gb < self.min_free_space_gb or
49
- (required_space_estimate and free < required_space_estimate * 1.2)
51
+ usage_percent >= 95.0
52
+ or free_gb < self.min_free_space_gb
53
+ or (required_space_estimate and free < required_space_estimate * 1.2)
50
54
  )
51
-
55
+
52
56
  if needs_cleanup and self.auto_cleanup:
53
- logger.warning(f"Storage critically low ({usage_percent:.1f}%), performing automatic cleanup")
57
+ logger.warning(
58
+ f"Storage critically low ({usage_percent:.1f}%), performing automatic cleanup"
59
+ )
54
60
  self._perform_emergency_cleanup()
55
-
61
+
56
62
  # Re-check after cleanup
57
- total, used, free = shutil.disk_usage('/')
63
+ total, used, free = shutil.disk_usage("/")
58
64
  free_gb = free / (1024**3)
59
65
  usage_percent = (used / total) * 100
60
-
66
+
61
67
  if usage_percent >= 98.0:
62
68
  raise InsufficientStorageError(
63
69
  f"Storage critically low even after cleanup: {usage_percent:.1f}% used, "
64
70
  f"only {free_gb:.1f}GB free",
65
- required_space=required_space_estimate or int(self.min_free_space_gb * 1024**3),
66
- available_space=free
71
+ required_space=required_space_estimate
72
+ or int(self.min_free_space_gb * 1024**3),
73
+ available_space=free,
67
74
  )
68
-
75
+
69
76
  return True
70
-
77
+
71
78
  except Exception as e:
72
79
  logger.error(f"Storage check failed: {e}")
73
80
  raise
74
-
81
+
75
82
  def _perform_emergency_cleanup(self) -> int:
76
83
  """
77
84
  Perform emergency storage cleanup.
78
-
85
+
79
86
  Returns:
80
87
  Bytes freed
81
88
  """
82
89
  total_freed = 0
83
-
90
+
84
91
  try:
85
92
  # 1. Clean up extracted frames for completed videos
86
93
  frames_freed = self._cleanup_completed_video_frames()
87
94
  total_freed += frames_freed
88
-
95
+
89
96
  # 2. Clean up upload cache older than 1 day
90
97
  uploads_freed = self._cleanup_old_uploads(max_age_hours=24)
91
98
  total_freed += uploads_freed
92
-
99
+
93
100
  # 3. Clean up large log files
94
101
  logs_freed = self._cleanup_large_logs()
95
102
  total_freed += logs_freed
96
-
103
+
97
104
  # 4. Clean up temporary files
98
105
  temp_freed = self._cleanup_temp_files()
99
106
  total_freed += temp_freed
100
-
101
- logger.info(f"Emergency cleanup completed: {total_freed / (1024**3):.2f}GB freed")
102
-
107
+
108
+ logger.info(
109
+ f"Emergency cleanup completed: {total_freed / (1024**3):.2f}GB freed"
110
+ )
111
+
103
112
  except Exception as e:
104
113
  logger.error(f"Emergency cleanup failed: {e}")
105
-
114
+
106
115
  return total_freed
107
-
116
+
108
117
  def _cleanup_completed_video_frames(self) -> int:
109
118
  """Clean up frames for videos that have completed processing."""
110
119
  total_freed = 0
111
-
120
+
112
121
  try:
113
122
  from django.conf import settings
114
- frames_dir = Path(settings.BASE_DIR).parent / 'storage' / 'frames'
115
-
123
+
124
+ frames_dir = Path(settings.BASE_DIR).parent / "storage" / "frames"
125
+
116
126
  if not frames_dir.exists():
117
127
  return 0
118
-
128
+
119
129
  # Find videos with completed anonymization
120
130
  completed_videos = VideoFile.objects.filter(
121
- anonymization_tasks__status='done'
131
+ anonymization_tasks__status="done_processing_anonymization"
122
132
  ).distinct()
123
-
133
+
124
134
  for video in completed_videos:
125
135
  # Find frame directories for this video
126
136
  video_frame_dirs = list(frames_dir.glob(f"*{video.uuid}*"))
127
-
137
+
128
138
  for frame_dir in video_frame_dirs:
129
139
  if frame_dir.is_dir():
130
140
  try:
131
141
  # Calculate directory size
132
142
  dir_size = sum(
133
- f.stat().st_size for f in frame_dir.rglob('*') if f.is_file()
143
+ f.stat().st_size
144
+ for f in frame_dir.rglob("*")
145
+ if f.is_file()
134
146
  )
135
-
147
+
136
148
  # Remove the directory
137
149
  shutil.rmtree(frame_dir, ignore_errors=True)
138
150
  total_freed += dir_size
139
-
140
- logger.info(f"Cleaned frames for {video.uuid}: {dir_size / (1024**2):.1f}MB")
141
-
151
+
152
+ logger.info(
153
+ f"Cleaned frames for {video.uuid}: {dir_size / (1024**2):.1f}MB"
154
+ )
155
+
142
156
  except Exception as e:
143
- logger.warning(f"Failed to clean frames for {video.uuid}: {e}")
144
-
157
+ logger.warning(
158
+ f"Failed to clean frames for {video.uuid}: {e}"
159
+ )
160
+
145
161
  except Exception as e:
146
162
  logger.error(f"Frame cleanup failed: {e}")
147
-
163
+
148
164
  return total_freed
149
-
165
+
150
166
  def _cleanup_old_uploads(self, max_age_hours: int = 24) -> int:
151
167
  """Clean up old upload cache files."""
152
168
  total_freed = 0
153
-
169
+
154
170
  try:
155
171
  from django.conf import settings
156
- uploads_dir = Path(settings.BASE_DIR).parent / 'storage' / 'uploads'
157
-
172
+
173
+ uploads_dir = Path(settings.BASE_DIR).parent / "storage" / "uploads"
174
+
158
175
  if not uploads_dir.exists():
159
176
  return 0
160
-
177
+
161
178
  cutoff_time = datetime.now().timestamp() - (max_age_hours * 3600)
162
-
163
- for file_path in uploads_dir.rglob('*'):
179
+
180
+ for file_path in uploads_dir.rglob("*"):
164
181
  if file_path.is_file():
165
182
  try:
166
183
  if file_path.stat().st_mtime < cutoff_time:
167
184
  file_size = file_path.stat().st_size
168
185
  file_path.unlink()
169
186
  total_freed += file_size
170
-
187
+
171
188
  except Exception as e:
172
189
  logger.warning(f"Failed to clean upload file {file_path}: {e}")
173
-
190
+
174
191
  except Exception as e:
175
192
  logger.error(f"Upload cleanup failed: {e}")
176
-
193
+
177
194
  return total_freed
178
-
195
+
179
196
  def _cleanup_large_logs(self, max_size_mb: int = 50) -> int:
180
197
  """Clean up large log files by truncating them."""
181
198
  total_freed = 0
182
-
199
+
183
200
  try:
184
201
  from django.conf import settings
202
+
185
203
  project_root = Path(settings.BASE_DIR).parent
186
204
  max_size_bytes = max_size_mb * 1024 * 1024
187
-
188
- for log_file in project_root.rglob('*.log'):
205
+
206
+ for log_file in project_root.rglob("*.log"):
189
207
  try:
190
208
  if log_file.stat().st_size > max_size_bytes:
191
209
  original_size = log_file.stat().st_size
192
-
210
+
193
211
  # Truncate the log file
194
- with open(log_file, 'w') as f:
195
- f.write(f"# Log truncated at {datetime.now()} due to size limit\n")
196
-
212
+ with open(log_file, "w") as f:
213
+ f.write(
214
+ f"# Log truncated at {datetime.now()} due to size limit\n"
215
+ )
216
+
197
217
  total_freed += original_size
198
- logger.info(f"Truncated log {log_file}: {original_size / (1024**2):.1f}MB")
199
-
218
+ logger.info(
219
+ f"Truncated log {log_file}: {original_size / (1024**2):.1f}MB"
220
+ )
221
+
200
222
  except Exception as e:
201
223
  logger.warning(f"Failed to truncate log {log_file}: {e}")
202
-
224
+
203
225
  except Exception as e:
204
226
  logger.error(f"Log cleanup failed: {e}")
205
-
227
+
206
228
  return total_freed
207
-
229
+
208
230
  def _cleanup_temp_files(self) -> int:
209
231
  """Clean up temporary files."""
210
232
  total_freed = 0
211
-
233
+
212
234
  try:
213
235
  temp_patterns = [
214
- '/tmp/tmp*',
215
- '/tmp/temp*',
216
- '/tmp/django*',
217
- '/tmp/ffmpeg*',
236
+ "/tmp/tmp*",
237
+ "/tmp/temp*",
238
+ "/tmp/django*",
239
+ "/tmp/ffmpeg*",
218
240
  ]
219
-
241
+
220
242
  for pattern in temp_patterns:
221
243
  import glob
244
+
222
245
  for temp_file in glob.glob(pattern):
223
246
  try:
224
247
  temp_path = Path(temp_file)
@@ -226,119 +249,122 @@ class StorageAwareVideoProcessor:
226
249
  file_size = temp_path.stat().st_size
227
250
  temp_path.unlink()
228
251
  total_freed += file_size
229
-
252
+
230
253
  except Exception as e:
231
254
  logger.warning(f"Failed to clean temp file {temp_file}: {e}")
232
-
255
+
233
256
  except Exception as e:
234
257
  logger.error(f"Temp file cleanup failed: {e}")
235
-
258
+
236
259
  return total_freed
237
-
260
+
238
261
  def process_video_with_storage_management(
239
- self,
240
- video_file: VideoFile,
262
+ self,
263
+ video_file: VideoFile,
241
264
  cleanup_frames_after: bool = True,
242
- progress_callback: Optional[callable] = None
265
+ progress_callback: Optional[callable] = None,
243
266
  ) -> bool:
244
267
  """
245
268
  Process a video with automatic storage management.
246
-
269
+
247
270
  Args:
248
271
  video_file: VideoFile instance to process
249
272
  cleanup_frames_after: Whether to clean up frames after processing
250
273
  progress_callback: Optional progress callback function
251
-
274
+
252
275
  Returns:
253
276
  True if processing succeeded, False otherwise
254
277
  """
255
278
  try:
256
279
  # Estimate required space (rough calculation)
257
280
  video_size = 0
258
- if video_file.raw_file and hasattr(video_file.raw_file, 'size'):
281
+ if video_file.raw_file and hasattr(video_file.raw_file, "size"):
259
282
  video_size = video_file.raw_file.size
260
-
283
+
261
284
  # Estimate: frames ~= 3x video size, processing ~= 2x video size
262
285
  estimated_space_needed = video_size * 5
263
-
286
+
264
287
  # Check storage before starting
265
288
  self.check_and_ensure_storage(estimated_space_needed)
266
-
289
+
267
290
  # Update task status
268
291
  task = self._get_or_create_task(video_file)
269
292
  task.start_processing()
270
-
293
+
271
294
  if progress_callback:
272
295
  progress_callback(10, "Starting video processing...")
273
-
296
+
274
297
  # Run the actual video processing pipeline
275
298
  success = video_file.pipe_1(
276
299
  model_name="image_multilabel_classification_colonoscopy_default",
277
- delete_frames_after=cleanup_frames_after
300
+ delete_frames_after=cleanup_frames_after,
278
301
  )
279
-
302
+
280
303
  if success:
281
304
  if progress_callback:
282
305
  progress_callback(90, "Processing completed, cleaning up...")
283
-
306
+
284
307
  # Mark as completed
285
308
  task.mark_completed("Video processing completed successfully")
286
-
309
+
287
310
  # Additional cleanup if requested
288
311
  if cleanup_frames_after:
289
312
  self._cleanup_video_frames(video_file)
290
-
313
+
291
314
  if progress_callback:
292
315
  progress_callback(100, "Processing completed successfully")
293
-
294
- logger.info(f"Video processing completed successfully: {video_file.uuid}")
316
+
317
+ logger.info(
318
+ f"Video processing completed successfully: {video_file.uuid}"
319
+ )
295
320
  return True
296
321
 
297
322
  task.mark_failed("Video processing pipeline failed")
298
323
  logger.error(f"Video processing failed: {video_file.uuid}")
299
324
  return False
300
-
325
+
301
326
  except InsufficientStorageError as e:
302
327
  logger.error(f"Storage error during video processing: {e}")
303
328
  task = self._get_or_create_task(video_file)
304
329
  task.mark_failed(f"Insufficient storage: {e}")
305
330
  return False
306
-
331
+
307
332
  except Exception as e:
308
333
  logger.error(f"Video processing failed: {e}")
309
334
  task = self._get_or_create_task(video_file)
310
335
  task.mark_failed(f"Processing error: {e}")
311
336
  return False
312
-
337
+
313
338
  def _get_or_create_task(self, video_file: VideoFile) -> AnonymizationTask:
314
339
  """Get or create an anonymization task for the video."""
315
340
  task, created = AnonymizationTask.objects.get_or_create(
316
341
  video_file=video_file,
317
342
  defaults={
318
- 'status': 'not_started',
319
- 'progress': 0,
320
- 'message': 'Initializing...'
321
- }
343
+ "status": "not_started",
344
+ "progress": 0,
345
+ "message": "Initializing...",
346
+ },
322
347
  )
323
348
  return task
324
-
349
+
325
350
  def _cleanup_video_frames(self, video_file: VideoFile):
326
351
  """Clean up frames for a specific video."""
327
352
  try:
328
353
  from django.conf import settings
329
- frames_dir = Path(settings.BASE_DIR).parent / 'storage' / 'frames'
330
-
354
+
355
+ frames_dir = Path(settings.BASE_DIR).parent / "storage" / "frames"
356
+
331
357
  # Find frame directories for this video
332
358
  video_frame_dirs = list(frames_dir.glob(f"*{video_file.uuid}*"))
333
-
359
+
334
360
  for frame_dir in video_frame_dirs:
335
361
  if frame_dir.is_dir():
336
362
  shutil.rmtree(frame_dir, ignore_errors=True)
337
363
  logger.info(f"Cleaned up frames for video {video_file.uuid}")
338
-
364
+
339
365
  except Exception as e:
340
366
  logger.warning(f"Failed to clean up frames for {video_file.uuid}: {e}")
341
367
 
342
368
 
343
369
  # Global instance for easy access
344
- storage_aware_processor = StorageAwareVideoProcessor()
370
+ storage_aware_processor = StorageAwareVideoProcessor()