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,95 +1,111 @@
1
- from django.db import models
1
+ import logging
2
+
2
3
  # Removed hash utils, datetime, random, os, timezone, sha256 imports
3
4
  # Removed icecream import (was used in old save logic)
4
- from typing import TYPE_CHECKING, Dict, Any, Type, Self
5
- import logging # Add logging import
5
+ from typing import TYPE_CHECKING, Any, Dict, Self, Type, cast
6
+
7
+ from django.db import models
8
+
9
+ from ..administration.person.patient import PatientExternalID
10
+
11
+ # Import models needed for type hints and FKs
12
+ from ..state import SensitiveMetaState # Needed for post-save state check
6
13
 
7
14
  # Import logic functions
8
15
  from . import sensitive_meta_logic as logic
9
- # Import models needed for type hints and FKs
10
- from ..state import SensitiveMetaState # Needed for post-save state check
11
16
 
12
17
  if TYPE_CHECKING:
13
18
  from ..administration import (
14
19
  Center,
15
20
  Examiner,
16
- Patient,
17
- FirstName, # Keep for type hinting if needed
18
- LastName # Keep for type hinting if needed
21
+ Patient, # Keep for type hinting if needed
19
22
  )
20
- from ..other import Gender
21
23
  from ..medical import PatientExamination
24
+ from ..other import Gender
22
25
  # from ..state import SensitiveMetaState # Already imported above
23
26
 
24
- logger = logging.getLogger(__name__) # Add logger instance
27
+ logger = logging.getLogger(__name__) # Add logger instance
25
28
 
26
29
  # SECRET_SALT moved to logic
27
30
 
31
+
28
32
  class SensitiveMeta(models.Model):
29
33
  """
30
34
  Stores potentially sensitive information extracted from media.
31
35
  Logic for creation, hashing, pseudo-anonymization, and saving is in sensitive_meta_logic.py.
32
36
  """
37
+
38
+
39
+
40
+ # --- Examination and Patient Info ---
33
41
  examination_date = models.DateField(blank=True, null=True)
34
- pseudo_patient = models.ForeignKey(
35
- "Patient",
36
- on_delete=models.CASCADE,
37
- blank=True,
38
- null=True,
39
- help_text="FK to the pseudo-anonymized Patient record."
40
- ) # type: ignore
42
+ examination_time = models.TimeField(blank=True, null=True)
43
+ casenumber = models.CharField(max_length=255, blank=True, null=True)
44
+ file_path = models.CharField(max_length=1024, blank=True, null=True)
45
+
46
+
47
+ # --- Core FKs ---
48
+ pseudo_patient = models.ForeignKey("Patient", on_delete=models.CASCADE, blank=True, null=True, help_text="FK to the pseudo-anonymized Patient record.")
49
+ pseudo_examination = models.ForeignKey(
50
+ "PatientExamination", on_delete=models.CASCADE, blank=True, null=True, help_text="FK to the pseudo-anonymized PatientExamination record."
51
+ )
52
+ patient_gender = models.ForeignKey("Gender", on_delete=models.CASCADE, blank=True, null=True)
53
+ examiners = models.ManyToManyField("Examiner", blank=True, help_text="Pseudo-anonymized examiner(s)")
54
+ center = models.ForeignKey("Center", on_delete=models.CASCADE, blank=True, null=True)
55
+
56
+ # --- Names and DOB ---
41
57
  patient_first_name = models.CharField(max_length=255, blank=True, null=True)
42
58
  patient_last_name = models.CharField(max_length=255, blank=True, null=True)
43
- patient_dob = models.DateTimeField(
44
- blank=True,
45
- null=True,
46
- help_text="Date of birth (can be auto-generated if missing)."
47
- )
48
- pseudo_examination = models.ForeignKey(
49
- "PatientExamination",
50
- on_delete=models.CASCADE,
51
- blank=True,
52
- null=True,
53
- help_text="FK to the pseudo-anonymized PatientExamination record."
54
- ) # type: ignore
55
- patient_gender = models.ForeignKey(
56
- "Gender",
57
- on_delete=models.CASCADE,
58
- blank=True,
59
- null=True,
60
- ) # type: ignore
61
- examiners = models.ManyToManyField(
62
- "Examiner",
63
- blank=True,
64
- help_text="Pseudo-anonymized examiner(s) associated with the examination."
65
- ) # type: ignore
66
- center = models.ForeignKey(
67
- "Center",
68
- on_delete=models.CASCADE,
69
- blank=True, # Should ideally be False if always required before save
70
- null=True, # Should ideally be False
71
- ) # type: ignore
72
-
73
- # Raw examiner names stored temporarily until pseudo-examiner is created/linked
59
+ patient_dob = models.DateTimeField(blank=True, null=True, help_text="Date of birth (can be auto-generated).")
60
+
74
61
  examiner_first_name = models.CharField(max_length=255, blank=True, null=True, editable=False)
75
62
  examiner_last_name = models.CharField(max_length=255, blank=True, null=True, editable=False)
76
63
 
77
- # Hashes calculated and stored by save logic
78
- examination_hash = models.CharField(max_length=64, blank=True, null=True, editable=False, db_index=True) # Use 64 for sha256 hex
79
- patient_hash = models.CharField(max_length=64, blank=True, null=True, editable=False, db_index=True) # Use 64 for sha256 hex
64
+ # --- Hashes ---
65
+ patient_hash = models.CharField(max_length=64, blank=True, null=True, editable=False, db_index=True)
66
+ examination_hash = models.CharField(max_length=64, blank=True, null=True, editable=False, db_index=True)
80
67
 
68
+ # --- Endoscope Info ---
81
69
  endoscope_type = models.CharField(max_length=255, blank=True, null=True)
82
70
  endoscope_sn = models.CharField(max_length=255, blank=True, null=True)
83
71
 
84
- # Removed state_verified property, assuming state is handled via the related SensitiveMetaState model
72
+ # --- External patient ID ---
73
+ external_id = models.ForeignKey("PatientExternalID", on_delete=models.CASCADE, blank=True, null=True)
85
74
 
86
75
  if TYPE_CHECKING:
87
- examiners: models.QuerySet["Examiner"]
88
- pseudo_patient: "Patient"
89
- patient_gender: "Gender"
90
- pseudo_examination: "PatientExamination"
91
- state: "SensitiveMetaState" # Assuming related_name='state' is defined on SensitiveMetaState.origin
92
- center: "Center"
76
+ pseudo_patient: models.ForeignKey["Patient|None"]
77
+
78
+ patient_gender: models.ForeignKey["Gender|None"]
79
+ pseudo_examination: models.ForeignKey["PatientExamination|None"]
80
+ state: models.ForeignKey["SensitiveMetaState|None"] # Assuming related_name='state' is defined on SensitiveMetaState.origin
81
+ center: models.ForeignKey["Center|None"]
82
+
83
+ examiners = cast(models.manager.RelatedManager["Examiner"], examiners)
84
+
85
+ @property
86
+ def external_id_origin(self) -> str | None:
87
+ """Returns the origin system from the linked external ID, if available."""
88
+ if self.external_id:
89
+ return self.external_id.origin
90
+ return None
91
+
92
+ # --- Text Fields ---
93
+ text = models.TextField(blank=True, null=True)
94
+ anonymized_text = models.TextField(blank=True, null=True)
95
+
96
+ # --- Anonymization helper method ---
97
+ create_anonymized_record = logic._create_anonymized_record
98
+
99
+ # --- State ---
100
+ @property
101
+ def state_verified(self) -> bool | None:
102
+ """
103
+ Convenience alias to check if the related state is verified.
104
+ Returns None if state is not set.
105
+ """
106
+ if hasattr(self, "state") and self.state is not None:
107
+ return self.state.is_verified
108
+ return None
93
109
 
94
110
  @staticmethod
95
111
  def _generate_random_dob():
@@ -113,10 +129,10 @@ class SensitiveMeta(models.Model):
113
129
  """Returns the linked pseudo examiner, if one exists."""
114
130
  if self.pk:
115
131
  return self.examiners.first()
116
- return None # Cannot determine before saving and linking
132
+ return None # Cannot determine before saving and linking
117
133
 
118
134
  # --- Update method delegates to logic ---
119
- def update_from_dict(self, data: Dict[str, Any]) -> Self:
135
+ def update_from_dict(self, data: Dict[str, Any]):
120
136
  """Updates the instance from a dictionary using external logic."""
121
137
  # Delegate to logic function
122
138
  return logic.update_sensitive_meta_from_dict(self, data)
@@ -126,7 +142,7 @@ class SensitiveMeta(models.Model):
126
142
  # Keep this method for basic representation, ensure fields are accessed safely
127
143
  center_name = self.center.name if self.center else "None"
128
144
  gender_str = str(self.patient_gender) if self.patient_gender else "None"
129
- dob_str = str(self.patient_dob.date()) if self.patient_dob else "None" # Show only date part
145
+ dob_str = str(self.patient_dob.date()) if self.patient_dob else "None" # Show only date part
130
146
  exam_date_str = str(self.examination_date) if self.examination_date else "None"
131
147
 
132
148
  examiners_str = "[Not saved yet]"
@@ -139,21 +155,27 @@ class SensitiveMeta(models.Model):
139
155
 
140
156
  state_verified = "Unknown"
141
157
  if self.pk:
142
- # Access state verification through the related state object
143
- state_verified = str(self.is_verified)
158
+ # Access state verification through the related state object
159
+ state_verified = str(self.is_verified)
144
160
  else:
145
161
  state_verified = "[Not saved yet]"
146
162
 
147
-
148
163
  return (
149
164
  f"SensitiveMeta(pk={self.pk}): "
150
165
  f"Patient={self.patient_last_name}, {self.patient_first_name} (*{dob_str}, {gender_str}), "
151
166
  f"ExamDate={exam_date_str}, Center={center_name}, "
152
167
  f"Examiners={examiners_str}, StateVerified={state_verified}, "
153
- f"PatientHash={str(self.patient_hash)[-8:] if self.patient_hash else 'None'}, " # Show last 8 chars
154
- f"ExamHash={str(self.examination_hash)[-8:] if self.examination_hash else 'None'}" # Show last 8 chars
168
+ f"PatientHash={str(self.patient_hash)[-8:] if self.patient_hash else 'None'}, " # Show last 8 chars
169
+ f"ExamHash={str(self.examination_hash)[-8:] if self.examination_hash else 'None'}" # Show last 8 chars
155
170
  )
156
171
 
172
+ @property
173
+ def state_safe(self) -> "SensitiveMetaState":
174
+ state = self.state
175
+ if not state:
176
+ raise SensitiveMetaState.DoesNotExist("SensitiveMetaState does not exist for this SensitiveMeta instance.")
177
+ return state
178
+
157
179
  @property
158
180
  def is_verified(self):
159
181
  """
@@ -163,7 +185,7 @@ class SensitiveMeta(models.Model):
163
185
  try:
164
186
  # Access the related state object directly via the 'state' attribute
165
187
  # This assumes the related_name on SensitiveMetaState.origin is 'state'
166
- return self.state.is_verified
188
+ return self.state_safe.is_verified
167
189
  except SensitiveMetaState.DoesNotExist:
168
190
  # If the state object doesn't exist, it's not verified
169
191
  return False
@@ -177,11 +199,9 @@ class SensitiveMeta(models.Model):
177
199
  Does not save the SensitiveMeta instance itself.
178
200
  """
179
201
  try:
180
- # Try accessing the state via the related name 'state'
181
- # This assumes the OneToOneField on SensitiveMetaState pointing to SensitiveMeta
182
- # has related_name='state'
183
- if self.state:
184
- return self.state
202
+ state = self.state_safe
203
+ return state
204
+
185
205
  except SensitiveMetaState.DoesNotExist:
186
206
  # If it doesn't exist, create it
187
207
  logger.info("Creating new SensitiveMetaState for SensitiveMeta %s", self.pk)
@@ -205,9 +225,6 @@ class SensitiveMeta(models.Model):
205
225
  # Cannot create state if the main instance has no PK
206
226
  raise ValueError("Cannot get or create state for an unsaved SensitiveMeta instance.")
207
227
 
208
- # If self.state existed initially, return it
209
- return self.state
210
-
211
228
  def __repr__(self):
212
229
  return self.__str__()
213
230
 
@@ -229,22 +246,22 @@ class SensitiveMeta(models.Model):
229
246
  def save(self, *args, **kwargs):
230
247
  """
231
248
  Saves the SensitiveMeta instance, ensuring data integrity, hash calculation, pseudo-entity linking, and related state management using external logic.
232
-
249
+
233
250
  This method performs pre-save operations via external logic, persists the instance, ensures the related SensitiveMetaState exists, and links the appropriate examiner to the instance.
234
251
  """
235
252
  # 1. Call the main logic function to perform pre-save checks, data generation,
236
253
  # and creation/linking of pseudo patient/examination FKs.
237
254
  # This function modifies the instance fields (hashes, FKs, dates).
238
255
  # It returns the examiner instance to be linked *after* saving.
239
- examiner_to_link = logic.perform_save_logic(self) # Pass only self
256
+ examiner_to_link = logic.perform_save_logic(self) # Pass only self
240
257
 
241
258
  # 2. Call the original Django save method to save the instance itself
242
259
  # (including updated FKs, hashes, dates).
243
- super().save(*args, **kwargs) # Pass original args/kwargs
260
+ super().save(*args, **kwargs) # Pass original args/kwargs
244
261
 
245
262
  # 3. Ensure SensitiveMetaState exists *after* saving the main instance
246
263
  # Use related name 'state' if defined, otherwise access via manager.
247
- if self.pk: # Ensure we have a PK
264
+ if self.pk: # Ensure we have a PK
248
265
  try:
249
266
  # Check if the related state object already exists using the related manager
250
267
  _ = self.state
@@ -252,13 +269,13 @@ class SensitiveMeta(models.Model):
252
269
  # If not, create a new one, linking it to the saved instance
253
270
  SensitiveMetaState.objects.create(origin=self)
254
271
  except AttributeError:
255
- # Fallback check if 'state' related_name is missing
256
- if not SensitiveMetaState.objects.filter(origin=self).exists():
272
+ # Fallback check if 'state' related_name is missing
273
+ if not SensitiveMetaState.objects.filter(origin=self).exists():
257
274
  SensitiveMetaState.objects.create(origin=self)
258
275
 
259
276
  # 4. Handle ManyToMany linking (examiners) *after* the instance has a PK.
260
277
  if examiner_to_link and self.pk and not self.examiners.filter(pk=examiner_to_link.pk).exists():
261
- self.examiners.add(examiner_to_link) # type: ignore
278
+ self.examiners.add(examiner_to_link)
262
279
  # Adding to M2M handles its own DB interaction, no second super().save() needed.
263
280
 
264
281
  def mark_dob_verified(self):
@@ -271,7 +288,7 @@ class SensitiveMeta(models.Model):
271
288
  def mark_names_verified(self):
272
289
  """
273
290
  Mark the patient's names as verified in the associated verification state.
274
-
291
+
275
292
  This method ensures the related SensitiveMetaState exists and updates its status to indicate that the patient's names have been verified.
276
293
  """
277
294
  state = self.get_or_create_state()
@@ -282,7 +299,7 @@ class SensitiveMeta(models.Model):
282
299
  # Delegate to logic
283
300
  """
284
301
  Update the name database with the provided first and last names using external logic.
285
-
302
+
286
303
  This method delegates the update operation to the external logic module responsible for managing name data.
287
304
  """
288
- logic.update_name_db(first_name, last_name)
305
+ logic.update_name_db(first_name, last_name)