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
@@ -0,0 +1,85 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional, Any, Mapping, TYPE_CHECKING
3
+ if TYPE_CHECKING:
4
+ from endoreg_db.models.requirement.requirement import Requirement
5
+
6
+
7
+ @dataclass
8
+ class RequirementEvaluationErrorContext:
9
+ """
10
+ Extra context for evaluation errors.
11
+
12
+ - requirement: DB object (so we can use names, groups, translations, etc.)
13
+ - code: stable internal code, preferred over free-text matching
14
+ - user_message: optional pre-formatted text for UI
15
+ - meta: optional arbitrary payload for logging / debugging
16
+ """
17
+ requirement: "Requirement"
18
+ code: str
19
+ technical_message: str
20
+ user_message: Optional[str] = None
21
+ description: Optional[str] = None
22
+ meta: Optional[Mapping[str, Any]] = None
23
+
24
+
25
+
26
+ class RequirementEvaluationError(Exception):
27
+ """
28
+ Domain-level error that signals: this requirement could be evaluated.
29
+
30
+ It carries:
31
+ - a Requirement instance (from DB)
32
+ - a stable error code
33
+ - a technical message for logs
34
+ - an optional user-ready message
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ requirement: "Requirement",
40
+ code: str,
41
+ technical_message: str,
42
+ user_message: Optional[str] = None,
43
+ meta: Optional[Mapping[str, Any]] = None,
44
+ *args,
45
+ ) -> None:
46
+ self.context = RequirementEvaluationErrorContext(
47
+ requirement=requirement,
48
+ code=code,
49
+ technical_message=technical_message,
50
+ user_message=user_message,
51
+ meta=meta,
52
+ )
53
+ # Base Exception message = technical message
54
+ super().__init__(technical_message, *args)
55
+
56
+
57
+
58
+ @property
59
+ def requirement(self) -> "Requirement":
60
+ return self.context.requirement
61
+
62
+ @property
63
+ def requirement_name(self) -> str:
64
+ # This is the DB name, *not* the internal Python repr
65
+ return getattr(self.context.requirement, "name", "unknown")
66
+
67
+ @property
68
+ def requirement_description(self) -> str:
69
+ return getattr(self.context.requirement, "description")
70
+
71
+ @property
72
+ def code(self) -> str:
73
+ return self.context.code
74
+
75
+ @property
76
+ def technical_message(self) -> str:
77
+ return self.context.technical_message
78
+
79
+ @property
80
+ def user_message(self) -> Optional[str]:
81
+ return self.context.user_message
82
+
83
+ @property
84
+ def meta(self) -> Optional[Mapping[str, Any]]:
85
+ return self.context.meta
@@ -0,0 +1,268 @@
1
+ from collections import defaultdict, deque
2
+ from typing import Iterable, Dict, List, Literal, Tuple
3
+ from endoreg_db.models.requirement import Requirement, RequirementSet
4
+ from endoreg_db.models.requirement.requirement_error import RequirementEvaluationError
5
+ import logging
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ RequirementStatus = Literal["PASSED", "FAILED", "BLOCKED", "ERROR"]
10
+
11
+ def topologically_sort_requirement_sets(
12
+ sets: Iterable[RequirementSet],
13
+ ) -> List[RequirementSet]:
14
+ """
15
+ Topologically sort requirement sets by `depends_on`.
16
+
17
+ Raises ValueError if a cycle is detected.
18
+ """
19
+ sets = list(sets)
20
+ id_map = {s.id: s for s in sets}
21
+
22
+ depends = {s.id: {d.id for d in s.depends_on.all()} for s in sets}
23
+ indegree = defaultdict(int)
24
+ for set_id, deps in depends.items():
25
+ for d_id in deps:
26
+ indegree[set_id] += 1
27
+
28
+ queue = deque([sid for sid in id_map if indegree[sid] == 0])
29
+ ordered_ids: List[int] = []
30
+
31
+ while queue:
32
+ sid = queue.popleft()
33
+ ordered_ids.append(sid)
34
+ for other_id, deps in depends.items():
35
+ if sid in deps:
36
+ deps.remove(sid)
37
+ indegree[other_id] -= 1
38
+ if indegree[other_id] == 0:
39
+ queue.append(other_id)
40
+
41
+ if len(ordered_ids) != len(sets):
42
+ raise ValueError("RequirementSet dependency cycle detected.")
43
+
44
+ return [id_map[sid] for sid in ordered_ids]
45
+
46
+
47
+
48
+
49
+ def evaluate_requirement_sets_with_dependencies(
50
+ sets: Iterable[RequirementSet],
51
+ *args,
52
+ mode: str = "strict",
53
+ **kwargs,
54
+ ) -> Dict[int, Dict[int, Tuple[RequirementStatus, str]]]:
55
+ """
56
+ Evaluates RequirementSets with set-level `depends_on`.
57
+
58
+ Returns:
59
+ {
60
+ set_id: {
61
+ requirement_id: (status, details)
62
+ }
63
+ }
64
+ """
65
+ ordered_sets = topologically_sort_requirement_sets(sets)
66
+ set_results: Dict[int, Dict[int, Tuple[RequirementStatus, str]]] = {}
67
+ set_statuses: Dict[int, RequirementStatus] = {}
68
+
69
+ for req_set in ordered_sets:
70
+ set_id = req_set.id
71
+ dep_set_ids = [s.id for s in req_set.depends_on.all()]
72
+
73
+ # Any dependency set FAILED or ERROR → this set is BLOCKED
74
+ blocking_deps = [
75
+ (dep_id, set_statuses[dep_id])
76
+ for dep_id in dep_set_ids
77
+ if dep_id in set_statuses and set_statuses[dep_id] in ("FAILED", "ERROR")
78
+ ]
79
+
80
+ reqs = list(req_set.requirements.all())
81
+ set_results[set_id] = {}
82
+
83
+ if blocking_deps:
84
+ failed_names = ", ".join(
85
+ str(RequirementSet.objects.get(pk=dep_id).name)
86
+ for dep_id, _ in blocking_deps
87
+ )
88
+ msg = (
89
+ f"Die Voraussetzungengruppe '{req_set.name}' wurde nicht geprüft, "
90
+ f"weil die abhängige(n) Gruppe(n) {failed_names} "
91
+ "noch nicht erfüllt sind."
92
+ )
93
+ for req in reqs:
94
+ set_results[set_id][req.id] = ("BLOCKED", msg)
95
+ set_statuses[set_id] = "BLOCKED"
96
+ continue
97
+
98
+ # Dependencies only BLOCKED → also BLOCKED (design choice)
99
+ blocked_only = [
100
+ (dep_id, set_statuses[dep_id])
101
+ for dep_id in dep_set_ids
102
+ if dep_id in set_statuses and set_statuses[dep_id] == "BLOCKED"
103
+ ]
104
+ if blocked_only and not blocking_deps:
105
+ msg = (
106
+ f"Die Voraussetzungengruppe '{req_set.name}' wurde nicht geprüft, "
107
+ "weil abhängige Gruppen noch ausstehend sind."
108
+ )
109
+ for req in reqs:
110
+ set_results[set_id][req.id] = ("BLOCKED", msg)
111
+ set_statuses[set_id] = "BLOCKED"
112
+ continue
113
+
114
+ # All deps PASSED or no deps → evaluate each requirement
115
+ had_failed = False
116
+ had_error = False
117
+
118
+ for req in reqs:
119
+ try:
120
+ met, details = req.evaluate_with_details(*args, mode=mode, **kwargs)
121
+ status: RequirementStatus = "PASSED" if met else "FAILED"
122
+ if status == "FAILED":
123
+ had_failed = True
124
+ set_results[set_id][req.id] = (status, details)
125
+
126
+ except RequirementEvaluationError as exc:
127
+ # domain-level failure → treat as FAILED but with nice message
128
+ had_failed = True
129
+ msg = (
130
+ f"Fehler bei der Auswertung der Voraussetzung '{req.name}': "
131
+ f"{exc.code}: {exc.technical_message}"
132
+ )
133
+ logger.warning(
134
+ "RequirementSet %s / Requirement %s domain error: %s",
135
+ req_set.id,
136
+ req.id,
137
+ exc,
138
+ )
139
+ set_results[set_id][req.id] = ("FAILED", msg)
140
+
141
+ except Exception as exc:
142
+ had_error = True
143
+ logger.exception(
144
+ "Unexpected error while evaluating RequirementSet %s / Requirement %s",
145
+ req_set.id,
146
+ req.id,
147
+ )
148
+ msg = (
149
+ f"Technischer Fehler bei der Auswertung von '{req.name}': {exc}"
150
+ )
151
+ set_results[set_id][req.id] = ("ERROR", msg)
152
+
153
+ # derive set status
154
+ if had_failed:
155
+ set_statuses[set_id] = "FAILED"
156
+ elif had_error:
157
+ set_statuses[set_id] = "ERROR"
158
+ else:
159
+ # if no requirements → call it PASSED (vacuous truth), or adjust as you like
160
+ set_statuses[set_id] = "PASSED"
161
+
162
+ return set_results
163
+
164
+ #TODO Remove when sure that no per requirement evaluation will happen. Needs the depends on attribute for the reatuirements.
165
+
166
+ def topologically_sort_requirements(
167
+ requirements: Iterable[Requirement],
168
+ ) -> List[Requirement]:
169
+ """
170
+ Topologically sort requirements by `depends_on`.
171
+
172
+ Raises ValueError if a cycle is detected.
173
+ """
174
+ reqs = list(requirements)
175
+ id_map = {r.id: r for r in reqs}
176
+
177
+ # Build adjacency + indegree for Kahn's algorithm
178
+ depends = {r.id: {d.id for d in r.depends_on.all()} for r in reqs}
179
+ indegree = defaultdict(int)
180
+ for r_id, deps in depends.items():
181
+ for d_id in deps:
182
+ indegree[r_id] += 1
183
+
184
+ queue = deque([r_id for r_id in id_map if indegree[r_id] == 0])
185
+ ordered_ids: List[int] = []
186
+
187
+ while queue:
188
+ r_id = queue.popleft()
189
+ ordered_ids.append(r_id)
190
+ # remove this node as dep from others
191
+ for other_id, deps in depends.items():
192
+ if r_id in deps:
193
+ deps.remove(r_id)
194
+ indegree[other_id] -= 1
195
+ if indegree[other_id] == 0:
196
+ queue.append(other_id)
197
+
198
+ if len(ordered_ids) != len(reqs):
199
+ raise ValueError("Requirement dependency cycle detected.")
200
+
201
+ return [id_map[rid] for rid in ordered_ids]
202
+
203
+ def evaluate_requirements_with_dependencies(
204
+ requirements: Iterable[Requirement],
205
+ *args,
206
+ mode: str = "strict",
207
+ **kwargs,
208
+ ) -> Dict[int, Tuple[RequirementStatus, str]]:
209
+ ordered = topologically_sort_requirements(requirements)
210
+ results: Dict[int, Tuple[RequirementStatus, str]] = {}
211
+
212
+ for req in ordered:
213
+ dep_ids = [d.id for d in req.depends_on.all()]
214
+
215
+ # If any dependency FAILED or ERROR → BLOCKED
216
+ blocking = [
217
+ (dep_id, results[dep_id])
218
+ for dep_id in dep_ids
219
+ if dep_id in results and results[dep_id][0] in ("FAILED", "ERROR")
220
+ ]
221
+
222
+ if blocking:
223
+ failed_names = ", ".join(
224
+ str(Requirement.objects.get(pk=dep_id).name) for dep_id, _ in blocking
225
+ )
226
+ results[req.id] = (
227
+ "BLOCKED",
228
+ f"Die Voraussetzung '{req.name}' wurde nicht geprüft, "
229
+ f"weil die abhängige(n) Voraussetzung(en) {failed_names} "
230
+ "noch nicht erfüllt sind.",
231
+ )
232
+ continue
233
+
234
+ # If dependencies exist but are only BLOCKED → still BLOCKED (design choice)
235
+ blocked_only = [
236
+ (dep_id, results[dep_id])
237
+ for dep_id in dep_ids
238
+ if dep_id in results and results[dep_id][0] == "BLOCKED"
239
+ ]
240
+ if blocked_only and not blocking:
241
+ results[req.id] = (
242
+ "BLOCKED",
243
+ f"Die Voraussetzung '{req.name}' wurde nicht geprüft, "
244
+ "weil abhängige Voraussetzungen noch ausstehend sind.",
245
+ )
246
+ continue
247
+
248
+ # All deps passed (or none) → evaluate requirement itself
249
+ try:
250
+ met, details = req.evaluate_with_details(*args, mode=mode, **kwargs)
251
+ except RequirementEvaluationError as exc:
252
+ met = False
253
+ results[req.id] = (
254
+ "FAILED",
255
+ f"Nachtragebedarf bei der Auswertung von '{req.name}': {exc}"
256
+ )
257
+ except Exception as exc:
258
+ met = False
259
+ logger.exception("Unexpected error while evaluating requirement %s", req)
260
+ results[req.id] = (
261
+ "ERROR",
262
+ f"Technischer Fehler bei der Auswertung von '{req.name}': {exc}",
263
+ )
264
+ else:
265
+ status: RequirementStatus = "PASSED" if met else "FAILED"
266
+ results[req.id] = (status, details)
267
+
268
+ return results
@@ -1,9 +1,6 @@
1
- from endoreg_db.models import (
2
- PatientExamination
3
- )
1
+ from endoreg_db.models import PatientExamination
4
2
 
5
- #TODO this should be a list of all models that are used in the requirement evaluation
6
- #TODO All those models must have a "get_requirement_links" property
3
+ # TODO Still used anywhere?
7
4
  operator_evaluation_models = [
8
5
  PatientExamination,
9
- ]
6
+ ]
@@ -1,7 +1,17 @@
1
- # Currently those strings MUST match the ones
2
- # in the requirement_type data definitions
1
+ """
2
+ Validated registry of requirement-type model bindings.
3
+
4
+ The registry ensures the string keys stay aligned with the Django models while
5
+ providing structured validation via Pydantic. Downstream code should consume
6
+ ``data_model_dict``/``data_model_dict_reverse`` instead of re-declaring
7
+ unvalidated mappings.
8
+ """
9
+
10
+ from typing import Dict
11
+
12
+ from django.db import models
13
+ from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
3
14
 
4
- from typing import Dict, Union
5
15
  from endoreg_db.models import (
6
16
  Disease,
7
17
  DiseaseClassification,
@@ -12,23 +22,24 @@ from endoreg_db.models import (
12
22
  Examination,
13
23
  ExaminationIndication,
14
24
  Finding,
15
- FindingIntervention,
16
25
  FindingClassification,
17
26
  FindingClassificationChoice,
27
+ FindingIntervention,
18
28
  LabValue,
29
+ Patient,
19
30
  PatientDisease,
20
31
  PatientEvent,
21
32
  PatientExamination,
22
33
  PatientFinding,
23
34
  PatientFindingClassification,
24
35
  PatientFindingIntervention,
36
+ PatientLabSample,
25
37
  PatientLabValue,
26
- PatientLabSample, # Assuming PatientLabSample is defined elsewhere,
27
- Patient,
28
- PatientMedication, # Added PatientMedication
29
- PatientMedicationSchedule, # Added PatientMedicationSchedule
38
+ PatientMedication,
39
+ PatientMedicationSchedule,
30
40
  )
31
41
  from endoreg_db.models.other.gender import Gender
42
+
32
43
  # if TYPE_CHECKING:
33
44
  # from endoreg_db.models import (
34
45
  # RequirementOperator,
@@ -36,60 +47,75 @@ from endoreg_db.models.other.gender import Gender
36
47
  # )
37
48
 
38
49
 
50
+ class DataModelEntry(BaseModel):
51
+ """Validated binding between an identifier string and a Django model class."""
39
52
 
40
- data_model_dict: Dict[str, Union[
41
- Disease,
42
- DiseaseClassification,
43
- DiseaseClassificationChoice,
44
- Event,
45
- EventClassification,
46
- EventClassificationChoice,
47
- Examination,
48
- ExaminationIndication,
49
- Finding,
50
- FindingIntervention,
51
- FindingClassification,
52
- FindingClassificationChoice,
53
- LabValue,
54
- PatientDisease,
55
- PatientEvent,
56
- PatientExamination,
57
- PatientFinding,
58
- PatientFindingIntervention,
59
- PatientFindingClassification,
60
- PatientLabValue,
61
- PatientLabSample,
62
- Patient,
63
- PatientMedication, # Added PatientMedication
64
- PatientMedicationSchedule, # Added PatientMedicationSchedule
65
- ]] = {
66
- "disease": Disease,
67
- "disease_classification_choice": DiseaseClassificationChoice,
68
- "disease_classification": DiseaseClassification,
69
- "event": Event,
70
- "event_classification": EventClassification,
71
- "event_classification_choice": EventClassificationChoice,
72
- "examination": Examination,
73
- "examination_indication": ExaminationIndication,
74
- "finding": Finding,
75
- "finding_intervention": FindingIntervention,
76
- "finding_classification": FindingClassification,
77
- "finding_classification_choice": FindingClassificationChoice,
78
- "lab_value": LabValue,
79
- "patient_disease": PatientDisease,
80
- "patient_event": PatientEvent,
81
- "patient_examination": PatientExamination,
82
- "patient_finding": PatientFinding,
83
- "patient_finding_intervention": PatientFindingIntervention,
84
- "patient_finding_classification": PatientFindingClassification,
85
- "patient_lab_value": PatientLabValue,
86
- "patient_lab_sample": PatientLabSample, # Changed from string "PatientLabSample" to the class
87
- "patient": Patient,
88
- "patient_medication": PatientMedication, # Added PatientMedication mapping
89
- "patient_medication_schedule": PatientMedicationSchedule, # Added PatientMedicationSchedule mapping
90
- "gender": Gender,
91
- }
92
-
93
- data_model_dict_reverse = {
94
- v: k for k, v in data_model_dict.items()
95
- }
53
+ name: str = Field(min_length=1)
54
+ model: type[models.Model]
55
+
56
+ model_config = ConfigDict(arbitrary_types_allowed=True)
57
+
58
+ @field_validator("model")
59
+ @classmethod
60
+ def ensure_model_subclass(cls, value: type[models.Model]) -> type[models.Model]:
61
+ if not issubclass(value, models.Model): # Defensive: ensure provided class is a Django model
62
+ raise TypeError(f"{value!r} is not a Django model class")
63
+ return value
64
+
65
+
66
+ class DataModelRegistry(BaseModel):
67
+ """Collection of ``DataModelEntry`` items with duplicate safeguards."""
68
+
69
+ entries: tuple[DataModelEntry, ...]
70
+
71
+ model_config = ConfigDict(arbitrary_types_allowed=True)
72
+
73
+ @model_validator(mode="after")
74
+ def ensure_unique(self) -> "DataModelRegistry":
75
+ names = [entry.name for entry in self.entries]
76
+ models_set = [entry.model for entry in self.entries]
77
+ if len(names) != len(set(names)):
78
+ raise ValueError("Duplicate requirement type names detected")
79
+ if len(models_set) != len(set(models_set)):
80
+ raise ValueError("Duplicate Django model classes detected in registry")
81
+ return self
82
+
83
+ def as_mapping(self) -> Dict[str, type[models.Model]]:
84
+ return {entry.name: entry.model for entry in self.entries}
85
+
86
+ def as_reverse_mapping(self) -> Dict[type[models.Model], str]:
87
+ return {entry.model: entry.name for entry in self.entries}
88
+
89
+
90
+ DATA_MODEL_REGISTRY = DataModelRegistry(
91
+ entries=(
92
+ DataModelEntry(name="disease", model=Disease),
93
+ DataModelEntry(name="disease_classification_choice", model=DiseaseClassificationChoice),
94
+ DataModelEntry(name="disease_classification", model=DiseaseClassification),
95
+ DataModelEntry(name="event", model=Event),
96
+ DataModelEntry(name="event_classification", model=EventClassification),
97
+ DataModelEntry(name="event_classification_choice", model=EventClassificationChoice),
98
+ DataModelEntry(name="examination", model=Examination),
99
+ DataModelEntry(name="examination_indication", model=ExaminationIndication),
100
+ DataModelEntry(name="finding", model=Finding),
101
+ DataModelEntry(name="finding_intervention", model=FindingIntervention),
102
+ DataModelEntry(name="finding_classification", model=FindingClassification),
103
+ DataModelEntry(name="finding_classification_choice", model=FindingClassificationChoice),
104
+ DataModelEntry(name="lab_value", model=LabValue),
105
+ DataModelEntry(name="patient_disease", model=PatientDisease),
106
+ DataModelEntry(name="patient_event", model=PatientEvent),
107
+ DataModelEntry(name="patient_examination", model=PatientExamination),
108
+ DataModelEntry(name="patient_finding", model=PatientFinding),
109
+ DataModelEntry(name="patient_finding_intervention", model=PatientFindingIntervention),
110
+ DataModelEntry(name="patient_finding_classification", model=PatientFindingClassification),
111
+ DataModelEntry(name="patient_lab_value", model=PatientLabValue),
112
+ DataModelEntry(name="patient_lab_sample", model=PatientLabSample),
113
+ DataModelEntry(name="patient", model=Patient),
114
+ DataModelEntry(name="patient_medication", model=PatientMedication),
115
+ DataModelEntry(name="patient_medication_schedule", model=PatientMedicationSchedule),
116
+ DataModelEntry(name="gender", model=Gender),
117
+ ),
118
+ )
119
+
120
+ data_model_dict: Dict[str, type[models.Model]] = DATA_MODEL_REGISTRY.as_mapping()
121
+ data_model_dict_reverse: Dict[type[models.Model], str] = DATA_MODEL_REGISTRY.as_reverse_mapping()