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,52 +1,31 @@
1
1
  from endoreg_db.models.requirement.requirement import Requirement
2
+ from endoreg_db.views.requirement.requirement_utils import safe_evaluate_requirement
2
3
  from endoreg_db.models.requirement.requirement_set import RequirementSet
4
+ from endoreg_db.models.requirement.requirement_evaluation.evaluate_with_dependencies import (
5
+ evaluate_requirement_sets_with_dependencies,
6
+ RequirementStatus, # if you export it there, otherwise re-declare in view
7
+ )
3
8
  from endoreg_db.models.medical.patient.patient_examination import PatientExamination
4
-
5
-
6
9
  from rest_framework import status
7
10
  from rest_framework.decorators import api_view
8
11
  from rest_framework.response import Response
12
+ import json
9
13
  import logging
10
14
 
11
15
  logger = logging.getLogger(__name__)
12
- @api_view(['POST'])
16
+
17
+
18
+ @api_view(["POST"])
13
19
  def evaluate_requirements(request):
14
20
  """
15
- Evaluate requirements and always return 200 with structured results.
16
- Payload:
17
- {
18
- "requirement_set_ids": [<int>, ...], // optional; evaluates all if omitted
19
- "patient_examination_id": <int> // required
20
- }
21
-
22
- Response (HTTP 200 always):
23
- {
24
- "ok": <bool>, // false if any errors occurred
25
- "errors": [<str>, ...], // high-level problems (e.g. invalid input, missing PE)
26
- "meta": {
27
- "patientExaminationId": <int|null>,
28
- "setsEvaluated": <int>,
29
- "requirementsEvaluated": <int>,
30
- "status": "ok" | "partial" | "failed"
31
- },
32
- "results": [
33
- {
34
- "requirement_set_id": <int>,
35
- "requirement_set_name": <str>,
36
- "requirement_name": <str>,
37
- "met": <bool>,
38
- "details": <str>, // always a string for UI display
39
- "error": <str|null> // per-item error if evaluation failed
40
- }
41
- ]
42
- }
21
+ Evaluate requirements (all selected sets) and always return 200 with structured results.
43
22
  """
44
23
  payload = request.data or {}
45
24
  req_set_ids = payload.get("requirement_set_ids")
46
25
  pe_id = payload.get("patient_examination_id")
47
26
 
48
- results = []
49
- errors = []
27
+ results: list[dict] = []
28
+ errors: list[str] = []
50
29
  sets_evaluated = 0
51
30
  requirements_evaluated = 0
52
31
 
@@ -55,53 +34,63 @@ def evaluate_requirements(request):
55
34
  msg = "patient_examination_id is required"
56
35
  errors.append(msg)
57
36
  logger.warning("evaluate_requirements: %s; payload=%s", msg, payload)
58
- return Response({
59
- "ok": False,
60
- "errors": errors,
61
- "meta": {
62
- "patientExaminationId": None,
63
- "setsEvaluated": 0,
64
- "requirementsEvaluated": 0,
65
- "status": "failed",
37
+ return Response(
38
+ {
39
+ "ok": False,
40
+ "errors": errors,
41
+ "meta": {
42
+ "patientExaminationId": None,
43
+ "setsEvaluated": 0,
44
+ "requirementsEvaluated": 0,
45
+ "status": "failed",
46
+ },
47
+ "results": [],
66
48
  },
67
- "results": []
68
- }, status=status.HTTP_200_OK)
49
+ status=status.HTTP_200_OK,
50
+ )
69
51
 
70
52
  # ---- fetch PatientExamination
71
53
  try:
72
- pe = (PatientExamination.objects
73
- .select_related("patient")
74
- .get(id=pe_id))
54
+ pe = (
55
+ PatientExamination.objects.select_related("patient")
56
+ .get(id=pe_id)
57
+ )
75
58
  except PatientExamination.DoesNotExist:
76
59
  msg = f"PatientExamination with id {pe_id} does not exist"
77
60
  errors.append(msg)
78
61
  logger.warning("evaluate_requirements: %s", msg)
79
- return Response({
80
- "ok": False,
81
- "errors": errors,
82
- "meta": {
83
- "patientExaminationId": pe_id,
84
- "setsEvaluated": 0,
85
- "requirementsEvaluated": 0,
86
- "status": "failed",
62
+ return Response(
63
+ {
64
+ "ok": False,
65
+ "errors": errors,
66
+ "meta": {
67
+ "patientExaminationId": pe_id,
68
+ "setsEvaluated": 0,
69
+ "requirementsEvaluated": 0,
70
+ "status": "failed",
71
+ },
72
+ "results": [],
87
73
  },
88
- "results": []
89
- }, status=status.HTTP_200_OK)
74
+ status=status.HTTP_200_OK,
75
+ )
90
76
  except Exception as e:
91
77
  msg = f"Unexpected error retrieving PatientExamination {pe_id}: {e}"
92
78
  errors.append(msg)
93
79
  logger.exception("evaluate_requirements: %s", msg)
94
- return Response({
95
- "ok": False,
96
- "errors": errors,
97
- "meta": {
98
- "patientExaminationId": pe_id,
99
- "setsEvaluated": 0,
100
- "requirementsEvaluated": 0,
101
- "status": "failed",
80
+ return Response(
81
+ {
82
+ "ok": False,
83
+ "errors": errors,
84
+ "meta": {
85
+ "patientExaminationId": pe_id,
86
+ "setsEvaluated": 0,
87
+ "requirementsEvaluated": 0,
88
+ "status": "failed",
89
+ },
90
+ "results": [],
102
91
  },
103
- "results": []
104
- }, status=status.HTTP_200_OK)
92
+ status=status.HTTP_200_OK,
93
+ )
105
94
 
106
95
  # ---- determine requirement sets
107
96
  try:
@@ -120,75 +109,152 @@ def evaluate_requirements(request):
120
109
  msg = f"Error loading RequirementSets: {e}"
121
110
  errors.append(msg)
122
111
  logger.exception("evaluate_requirements: %s", msg)
123
- return Response({
124
- "ok": False,
112
+ return Response(
113
+ {
114
+ "ok": False,
115
+ "errors": errors,
116
+ "meta": {
117
+ "patientExaminationId": pe_id,
118
+ "setsEvaluated": 0,
119
+ "requirementsEvaluated": 0,
120
+ "status": "failed",
121
+ },
122
+ "results": [],
123
+ },
124
+ status=status.HTTP_200_OK,
125
+ )
126
+
127
+ # nothing to evaluate → still return 200
128
+ if not requirement_sets:
129
+ response_payload = {
130
+ "ok": len(errors) == 0,
125
131
  "errors": errors,
126
132
  "meta": {
127
133
  "patientExaminationId": pe_id,
128
134
  "setsEvaluated": 0,
129
135
  "requirementsEvaluated": 0,
130
- "status": "failed",
136
+ "status": "failed" if errors else "ok",
131
137
  },
132
- "results": []
133
- }, status=status.HTTP_200_OK)
138
+ "results": [],
139
+ }
140
+ return Response(response_payload, status=status.HTTP_200_OK)
141
+
142
+ # mapping from IDs to objects for later lookup
143
+ sets_by_id: dict[int, RequirementSet] = {s.id: s for s in requirement_sets}
144
+
145
+ # ---- main evaluation with set dependencies
146
+ try:
147
+ # returns: { set_id: { req_id: (status, details) } }
148
+ set_results = evaluate_requirement_sets_with_dependencies(
149
+ requirement_sets,
150
+ pe.patient,
151
+ mode="strict",
152
+ )
153
+
154
+ for set_id, req_dict in set_results.items():
155
+ req_set = sets_by_id.get(set_id)
156
+ set_name = getattr(
157
+ req_set, "name", str(set_id)
158
+ ) if req_set is not None else str(set_id)
134
159
 
135
- # ---- evaluate
136
- for req_set in requirement_sets:
137
- for req in req_set.requirements.all():
138
- # (optionally) reload Requirement to ensure fresh instance as in your original code
139
- try:
140
- requirement_obj = Requirement.objects.get(name=req.name)
141
- except Exception:
142
- # fall back to the prefetched instance
143
- requirement_obj = req
160
+ for req_id, (status_value, details) in req_dict.items():
161
+ try:
162
+ requirement_obj = Requirement.objects.get(id=req_id)
163
+ req_name = getattr(requirement_obj, "name", f"#{req_id}")
164
+ except Requirement.DoesNotExist:
165
+ requirement_obj = None
166
+ req_name = f"#{req_id}"
144
167
 
145
- try:
146
- met, details = requirement_obj.evaluate_with_details(pe.patient, mode="strict")
147
- # normalize details to a string for the frontend
168
+ # map RequirementStatus → met + error
169
+ if status_value == "PASSED":
170
+ met = True
171
+ error_str = None
172
+ elif status_value in ("FAILED", "BLOCKED"):
173
+ met = False
174
+ error_str = None
175
+ else: # "ERROR"
176
+ met = False
177
+ error_str = "Technischer Fehler bei der Auswertung"
178
+
179
+ # normalize details to string
148
180
  if isinstance(details, str):
149
181
  details_str = details
150
182
  else:
151
183
  try:
152
- details_str = json.dumps(details, ensure_ascii=False, default=str)
184
+ details_str = json.dumps(
185
+ details, ensure_ascii=False, default=str
186
+ )
153
187
  except Exception:
154
188
  details_str = str(details)
155
189
 
156
- results.append({
157
- "requirement_set_id": getattr(req_set, "id", None),
158
- "requirement_set_name": getattr(req_set, "name", str(getattr(req_set, "id", ""))),
159
- "requirement_name": getattr(requirement_obj, "name", "unknown"),
160
- "met": bool(met),
161
- "details": details_str if details_str else ("Voraussetzung erfüllt" if met else "Voraussetzung nicht erfüllt"),
162
- "error": None
163
- })
164
- except (TypeError, ValueError) as e:
165
- msg = f"Fehler bei der Bewertung der Voraussetzung: {e}"
166
- logger.warning("evaluate_requirements: requirement '%s' error: %s",
167
- getattr(requirement_obj, "name", "unknown"), e)
168
- results.append({
169
- "requirement_set_id": getattr(req_set, "id", None),
170
- "requirement_set_name": getattr(req_set, "name", str(getattr(req_set, "id", ""))),
171
- "requirement_name": getattr(requirement_obj, "name", "unknown"),
172
- "met": False,
173
- "details": msg,
174
- "error": f"{e.__class__.__name__}: {e}"
175
- })
176
- errors.append(msg)
177
- except Exception as e:
178
- msg = f"Unerwarteter Fehler bei der Bewertung: {e}"
179
- logger.exception("evaluate_requirements: requirement '%s' unexpected error",
180
- getattr(requirement_obj, "name", "unknown"))
181
- results.append({
182
- "requirement_set_id": getattr(req_set, "id", None),
183
- "requirement_set_name": getattr(req_set, "name", str(getattr(req_set, "id", ""))),
184
- "requirement_name": getattr(requirement_obj, "name", "unknown"),
185
- "met": False,
186
- "details": msg,
187
- "error": f"{e.__class__.__name__}: {e}"
188
- })
189
- errors.append(msg)
190
+ # default fallback text if details are empty
191
+ if not details_str:
192
+ details_str = (
193
+ "Voraussetzung erfüllt"
194
+ if met
195
+ else "Voraussetzung nicht erfüllt"
196
+ )
197
+
198
+ if status_value == "ERROR":
199
+ # add a high-level error for meta if there was an internal error
200
+ msg = (
201
+ f"Technischer Fehler bei der Auswertung von "
202
+ f"Voraussetzung '{req_name}' in Set '{set_name}'."
203
+ )
204
+ errors.append(msg)
205
+
206
+ results.append(
207
+ {
208
+ "requirement_set_id": set_id,
209
+ "requirement_set_name": set_name,
210
+ "requirement_name": req_name,
211
+ "met": bool(met),
212
+ "details": details_str,
213
+ "error": error_str,
214
+ "status": status_value,
215
+ }
216
+ )
217
+ requirements_evaluated += 1
218
+
219
+ except Exception as e:
220
+ # hard failure of the orchestrator → log and fall back to per-requirement evaluation
221
+ msg = f"Unerwarteter Fehler bei der gruppenbasierten Bewertung: {e}"
222
+ errors.append(msg)
223
+ logger.exception("evaluate_requirements: %s", msg)
224
+
225
+ for req_set in requirement_sets:
226
+ for req in req_set.requirements.all():
227
+ met, details, error = safe_evaluate_requirement(
228
+ req, pe.patient, mode="strict"
229
+ )
230
+ # normalize details to string
231
+ if not isinstance(details, str):
232
+ try:
233
+ details = json.dumps(details, ensure_ascii=False, default=str)
234
+ except Exception:
235
+ details = str(details)
236
+
237
+ if not details:
238
+ details = (
239
+ "Voraussetzung erfüllt"
240
+ if met
241
+ else "Voraussetzung nicht erfüllt"
242
+ )
190
243
 
191
- requirements_evaluated += 1
244
+ results.append(
245
+ {
246
+ "requirement_set_id": req_set.id,
247
+ "requirement_set_name": getattr(
248
+ req_set, "name", str(req_set.id)
249
+ ),
250
+ "requirement_name": getattr(req, "name", "unknown"),
251
+ "met": bool(met),
252
+ "details": details,
253
+ "error": error,
254
+ "status": "PASSED" if met else "FAILED",
255
+ }
256
+ )
257
+ requirements_evaluated += 1
192
258
 
193
259
  # ---- response meta & status summary
194
260
  any_errors = len(errors) > 0
@@ -201,79 +267,14 @@ def evaluate_requirements(request):
201
267
 
202
268
  response_payload = {
203
269
  "ok": not any_errors,
204
- "errors": errors, # frontend can render these in a toast / banner
270
+ "errors": errors,
205
271
  "meta": {
206
272
  "patientExaminationId": pe_id,
207
273
  "setsEvaluated": sets_evaluated,
208
274
  "requirementsEvaluated": requirements_evaluated,
209
- "status": status_label
275
+ "status": status_label,
210
276
  },
211
- "results": results
277
+ "results": results,
212
278
  }
213
279
 
214
280
  return Response(response_payload, status=status.HTTP_200_OK)
215
-
216
-
217
- def evaluate_requirement_set(request) -> Response:
218
- """
219
- Evaluate a specific RequirementSet based on provided RequirementLinks data.
220
-
221
- Expects a JSON payload with the following structure:
222
- {
223
- "requirement_set_ids": [<requirement_set_ids>],
224
- "patient_examination_id": <patient_examination_id>
225
- }
226
-
227
- Returns a JSON response with the evaluation results for the specified RequirementSet:
228
- {
229
- "results": [
230
- {
231
- "requirement_name": <requirement_name>,
232
- "met": <true/false>,
233
- "details": <additional_details>
234
- },
235
- ...
236
- ]
237
- }
238
- """
239
- try:
240
- data = request.data
241
- requirement_set_ids = data.get("requirement_set_ids", None)
242
- patient_examination_id = data.get("patient_examination_id")
243
-
244
- if not requirement_set_ids:
245
- return Response({"error": "requirement_set_ids is required"}, status=status.HTTP_400_BAD_REQUEST)
246
-
247
- if not patient_examination_id:
248
- return Response({"error": "patient_examination_id is required"}, status=status.HTTP_400_BAD_REQUEST)
249
-
250
- # Get the patient examination
251
- try:
252
- patient_examination = PatientExamination.objects.get(id=patient_examination_id)
253
- except PatientExamination.DoesNotExist:
254
- return Response({"error": f"PatientExamination with id {patient_examination_id} does not exist"}, status=status.HTTP_404_NOT_FOUND)
255
-
256
- results = []
257
-
258
- # Construct RequirementLinks from the provided data
259
- for requirement_set_id in requirement_set_ids:
260
- # Fetch the specified RequirementSet
261
- try:
262
- req_set = RequirementSet.objects.get(id=requirement_set_id)
263
- except RequirementSet.DoesNotExist:
264
- return Response({"error": f"RequirementSet with id {requirement_set_id} does not exist"}, status=status.HTTP_404_NOT_FOUND)
265
-
266
- for requirement in req_set.requirements.all():
267
- met, details = requirement.evaluate(patient_examination.patient, mode="strict")
268
- results.append({
269
- "requirement_name": requirement.name,
270
- "met": met,
271
- "details": details
272
- })
273
-
274
- return Response({
275
- "results": results
276
- }, status=status.HTTP_200_OK)
277
-
278
- except Exception as e:
279
- return Response({"results": str(e), details: "Fehler bei der Bewertung der Voraussetzung"}, status=status.HTTP_400_BAD_REQUEST)