endoreg-db 0.8.6.1__py3-none-any.whl → 0.8.8.9__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (503) hide show
  1. endoreg_db/authz/auth.py +74 -0
  2. endoreg_db/authz/backends.py +168 -0
  3. endoreg_db/authz/management/commands/list_routes.py +18 -0
  4. endoreg_db/authz/middleware.py +83 -0
  5. endoreg_db/authz/permissions.py +127 -0
  6. endoreg_db/authz/policy.py +218 -0
  7. endoreg_db/authz/views_auth.py +66 -0
  8. endoreg_db/config/env.py +13 -8
  9. endoreg_db/data/__init__.py +2 -11
  10. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +3 -3
  11. endoreg_db/data/event_classification/data.yaml +4 -0
  12. endoreg_db/data/event_classification_choice/data.yaml +9 -0
  13. endoreg_db/data/examination/examinations/data.yaml +114 -14
  14. endoreg_db/data/examination/time-type/data.yaml +0 -3
  15. endoreg_db/data/examination_indication/endoscopy.yaml +108 -173
  16. endoreg_db/data/examination_indication_classification/endoscopy.yaml +0 -70
  17. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +33 -37
  18. endoreg_db/data/finding/00_generic.yaml +35 -0
  19. endoreg_db/data/finding/00_generic_complication.yaml +9 -0
  20. endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
  21. endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
  22. endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
  23. endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
  24. endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
  25. endoreg_db/data/finding_classification/00_generic.yaml +44 -0
  26. endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
  27. endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
  28. endoreg_db/data/finding_classification/02_colonoscopy_baseline.yaml +83 -0
  29. endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
  30. endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
  31. endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
  32. endoreg_db/data/finding_classification_choice/{yes_no_na.yaml → 00_generic.yaml} +5 -1
  33. endoreg_db/data/finding_classification_choice/{examination_setting_generic_types.yaml → 00_generic_baseline.yaml} +10 -2
  34. endoreg_db/data/finding_classification_choice/{complication_generic_types.yaml → 00_generic_complication.yaml} +1 -1
  35. endoreg_db/data/finding_classification_choice/{histology.yaml → 00_generic_histology.yaml} +1 -4
  36. endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
  37. endoreg_db/data/finding_classification_choice/{bowel_preparation.yaml → 02_colonoscopy_bowel_preparation.yaml} +1 -30
  38. endoreg_db/data/finding_classification_choice/{colonoscopy_not_complete_reason.yaml → 02_colonoscopy_generic.yaml} +1 -1
  39. endoreg_db/data/finding_classification_choice/{histology_polyp.yaml → 02_colonoscopy_histology.yaml} +1 -1
  40. endoreg_db/data/finding_classification_choice/{colonoscopy_location.yaml → 02_colonoscopy_location.yaml} +23 -4
  41. endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
  42. endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
  43. endoreg_db/data/finding_classification_choice/{colon_lesion_paris.yaml → 02_colonoscopy_polyp_morphology.yaml} +26 -8
  44. endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
  45. endoreg_db/data/finding_classification_type/{colonoscopy_basic.yaml → 00_generic.yaml} +18 -13
  46. endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
  47. endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
  48. endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
  49. endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
  50. endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
  51. endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
  52. endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
  53. endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
  54. endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
  55. endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
  56. endoreg_db/data/finding_type/data.yaml +8 -12
  57. endoreg_db/data/requirement/01_patient_data.yaml +93 -0
  58. endoreg_db/data/requirement/old/colon_polyp_intervention.yaml +49 -0
  59. endoreg_db/data/requirement/old/coloreg_colon_polyp.yaml +49 -0
  60. endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
  61. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +29 -12
  62. endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
  63. endoreg_db/data/requirement_set/{endoscopy_bleeding_risk.yaml → 02_endoscopy_bleeding_risk.yaml} +0 -6
  64. endoreg_db/data/requirement_set/90_coloreg.yaml +190 -0
  65. endoreg_db/data/requirement_set/_old_ +109 -0
  66. endoreg_db/data/requirement_set_type/data.yaml +21 -0
  67. endoreg_db/data/setup_config.yaml +4 -4
  68. endoreg_db/data/tag/requirement_set_tags.yaml +21 -0
  69. endoreg_db/exceptions.py +4 -2
  70. endoreg_db/forms/examination_form.py +1 -1
  71. endoreg_db/helpers/data_loader.py +125 -53
  72. endoreg_db/helpers/default_objects.py +116 -81
  73. endoreg_db/import_files/__init__.py +27 -0
  74. endoreg_db/import_files/context/__init__.py +7 -0
  75. endoreg_db/import_files/context/default_sensitive_meta.py +81 -0
  76. endoreg_db/import_files/context/ensure_center.py +17 -0
  77. endoreg_db/import_files/context/file_lock.py +66 -0
  78. endoreg_db/import_files/context/import_context.py +43 -0
  79. endoreg_db/import_files/context/validate_directories.py +56 -0
  80. endoreg_db/import_files/file_storage/__init__.py +15 -0
  81. endoreg_db/import_files/file_storage/create_report_file.py +76 -0
  82. endoreg_db/import_files/file_storage/create_video_file.py +75 -0
  83. endoreg_db/import_files/file_storage/sensitive_meta_storage.py +39 -0
  84. endoreg_db/import_files/file_storage/state_management.py +400 -0
  85. endoreg_db/import_files/file_storage/storage.py +36 -0
  86. endoreg_db/import_files/import_service.md +26 -0
  87. endoreg_db/import_files/processing/__init__.py +11 -0
  88. endoreg_db/import_files/processing/report_processing/report_anonymization.py +94 -0
  89. endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
  90. endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
  91. endoreg_db/import_files/processing/video_processing/video_cleanup_on_error.py +119 -0
  92. endoreg_db/import_files/pseudonymization/fake.py +52 -0
  93. endoreg_db/import_files/pseudonymization/k_anonymity.py +182 -0
  94. endoreg_db/import_files/pseudonymization/k_pseudonymity.py +128 -0
  95. endoreg_db/import_files/report_import_service.py +141 -0
  96. endoreg_db/import_files/video_import_service.py +150 -0
  97. endoreg_db/management/commands/create_model_meta_from_huggingface.py +21 -10
  98. endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
  99. endoreg_db/management/commands/import_report.py +130 -65
  100. endoreg_db/management/commands/import_video.py +9 -10
  101. endoreg_db/management/commands/import_video_with_classification.py +2 -2
  102. endoreg_db/management/commands/list_routes.py +18 -0
  103. endoreg_db/management/commands/load_ai_model_data.py +5 -5
  104. endoreg_db/management/commands/load_ai_model_label_data.py +9 -7
  105. endoreg_db/management/commands/load_base_db_data.py +5 -134
  106. endoreg_db/management/commands/load_center_data.py +12 -12
  107. endoreg_db/management/commands/load_contraindication_data.py +14 -16
  108. endoreg_db/management/commands/load_disease_classification_choices_data.py +15 -18
  109. endoreg_db/management/commands/load_disease_classification_data.py +15 -18
  110. endoreg_db/management/commands/load_disease_data.py +25 -28
  111. endoreg_db/management/commands/load_endoscope_data.py +20 -27
  112. endoreg_db/management/commands/load_event_data.py +14 -16
  113. endoreg_db/management/commands/load_examination_data.py +31 -44
  114. endoreg_db/management/commands/load_examination_indication_data.py +20 -21
  115. endoreg_db/management/commands/load_finding_data.py +52 -80
  116. endoreg_db/management/commands/load_information_source.py +21 -23
  117. endoreg_db/management/commands/load_lab_value_data.py +17 -26
  118. endoreg_db/management/commands/load_medication_data.py +13 -12
  119. endoreg_db/management/commands/load_organ_data.py +15 -19
  120. endoreg_db/management/commands/load_pdf_type_data.py +19 -18
  121. endoreg_db/management/commands/load_profession_data.py +14 -17
  122. endoreg_db/management/commands/load_qualification_data.py +20 -23
  123. endoreg_db/management/commands/load_report_reader_flag_data.py +17 -19
  124. endoreg_db/management/commands/load_requirement_data.py +62 -39
  125. endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
  126. endoreg_db/management/commands/load_risk_data.py +7 -6
  127. endoreg_db/management/commands/load_shift_data.py +20 -23
  128. endoreg_db/management/commands/load_tag_data.py +8 -11
  129. endoreg_db/management/commands/load_unit_data.py +17 -19
  130. endoreg_db/management/commands/setup_endoreg_db.py +3 -3
  131. endoreg_db/management/commands/start_filewatcher.py +46 -37
  132. endoreg_db/management/commands/storage_management.py +271 -203
  133. endoreg_db/management/commands/validate_video_files.py +1 -5
  134. endoreg_db/migrations/0001_initial.py +297 -250
  135. endoreg_db/models/__init__.py +78 -123
  136. endoreg_db/models/administration/__init__.py +21 -42
  137. endoreg_db/models/administration/ai/active_model.py +2 -2
  138. endoreg_db/models/administration/ai/ai_model.py +7 -6
  139. endoreg_db/models/administration/case/__init__.py +1 -15
  140. endoreg_db/models/administration/case/case.py +3 -3
  141. endoreg_db/models/administration/case/case_template/__init__.py +2 -14
  142. endoreg_db/models/administration/case/case_template/case_template.py +2 -124
  143. endoreg_db/models/administration/case/case_template/case_template_rule.py +2 -268
  144. endoreg_db/models/administration/case/case_template/case_template_rule_value.py +2 -85
  145. endoreg_db/models/administration/case/case_template/case_template_type.py +2 -25
  146. endoreg_db/models/administration/center/center.py +33 -19
  147. endoreg_db/models/administration/center/center_product.py +12 -9
  148. endoreg_db/models/administration/center/center_resource.py +25 -19
  149. endoreg_db/models/administration/center/center_shift.py +21 -17
  150. endoreg_db/models/administration/center/center_waste.py +16 -8
  151. endoreg_db/models/administration/person/__init__.py +2 -0
  152. endoreg_db/models/administration/person/employee/employee.py +10 -5
  153. endoreg_db/models/administration/person/employee/employee_qualification.py +9 -4
  154. endoreg_db/models/administration/person/employee/employee_type.py +12 -6
  155. endoreg_db/models/administration/person/examiner/examiner.py +13 -11
  156. endoreg_db/models/administration/person/patient/__init__.py +2 -0
  157. endoreg_db/models/administration/person/patient/patient.py +129 -100
  158. endoreg_db/models/administration/person/patient/patient_external_id.py +37 -0
  159. endoreg_db/models/administration/person/person.py +4 -0
  160. endoreg_db/models/administration/person/profession/__init__.py +8 -4
  161. endoreg_db/models/administration/person/user/portal_user_information.py +11 -7
  162. endoreg_db/models/administration/product/product.py +20 -15
  163. endoreg_db/models/administration/product/product_material.py +17 -18
  164. endoreg_db/models/administration/product/product_weight.py +12 -8
  165. endoreg_db/models/administration/product/reference_product.py +23 -55
  166. endoreg_db/models/administration/qualification/qualification.py +7 -3
  167. endoreg_db/models/administration/qualification/qualification_type.py +7 -3
  168. endoreg_db/models/administration/shift/scheduled_days.py +8 -5
  169. endoreg_db/models/administration/shift/shift.py +16 -12
  170. endoreg_db/models/administration/shift/shift_type.py +23 -31
  171. endoreg_db/models/label/__init__.py +8 -9
  172. endoreg_db/models/label/annotation/image_classification.py +10 -9
  173. endoreg_db/models/label/annotation/video_segmentation_annotation.py +23 -28
  174. endoreg_db/models/label/label.py +15 -15
  175. endoreg_db/models/label/label_set.py +19 -6
  176. endoreg_db/models/label/label_type.py +1 -1
  177. endoreg_db/models/label/label_video_segment/_create_from_video.py +5 -8
  178. endoreg_db/models/label/label_video_segment/label_video_segment.py +98 -102
  179. endoreg_db/models/label/video_segmentation_label.py +4 -0
  180. endoreg_db/models/label/video_segmentation_labelset.py +4 -3
  181. endoreg_db/models/media/frame/frame.py +22 -22
  182. endoreg_db/models/media/pdf/raw_pdf.py +194 -194
  183. endoreg_db/models/media/pdf/report_file.py +25 -29
  184. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +55 -47
  185. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
  186. endoreg_db/models/media/processing_history/__init__.py +5 -0
  187. endoreg_db/models/media/processing_history/processing_history.py +96 -0
  188. endoreg_db/models/media/video/__init__.py +1 -0
  189. endoreg_db/models/media/video/create_from_file.py +139 -77
  190. endoreg_db/models/media/video/pipe_2.py +8 -9
  191. endoreg_db/models/media/video/video_file.py +174 -112
  192. endoreg_db/models/media/video/video_file_ai.py +288 -74
  193. endoreg_db/models/media/video/video_file_anonymize.py +38 -38
  194. endoreg_db/models/media/video/video_file_frames/__init__.py +3 -1
  195. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -8
  196. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +7 -9
  197. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +9 -8
  198. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +38 -45
  199. endoreg_db/models/media/video/video_file_frames/_get_frame.py +6 -8
  200. endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +4 -18
  201. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -3
  202. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +7 -6
  203. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +6 -8
  204. endoreg_db/models/media/video/video_file_frames/_get_frames.py +6 -8
  205. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +15 -25
  206. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +26 -23
  207. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +23 -14
  208. endoreg_db/models/media/video/video_file_io.py +113 -61
  209. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +3 -3
  210. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +5 -3
  211. endoreg_db/models/media/video/video_file_meta/get_fps.py +37 -34
  212. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +19 -25
  213. endoreg_db/models/media/video/video_file_meta/text_meta.py +41 -38
  214. endoreg_db/models/media/video/video_file_meta/video_meta.py +14 -7
  215. endoreg_db/models/media/video/video_file_segments.py +24 -17
  216. endoreg_db/models/media/video/video_metadata.py +19 -35
  217. endoreg_db/models/media/video/video_processing.py +96 -95
  218. endoreg_db/models/medical/contraindication/README.md +1 -0
  219. endoreg_db/models/medical/contraindication/__init__.py +13 -3
  220. endoreg_db/models/medical/disease.py +22 -16
  221. endoreg_db/models/medical/event.py +31 -18
  222. endoreg_db/models/medical/examination/__init__.py +13 -6
  223. endoreg_db/models/medical/examination/examination.py +39 -20
  224. endoreg_db/models/medical/examination/examination_indication.py +30 -95
  225. endoreg_db/models/medical/examination/examination_time.py +23 -8
  226. endoreg_db/models/medical/examination/examination_time_type.py +9 -6
  227. endoreg_db/models/medical/examination/examination_type.py +3 -4
  228. endoreg_db/models/medical/finding/finding.py +32 -40
  229. endoreg_db/models/medical/finding/finding_classification.py +42 -72
  230. endoreg_db/models/medical/finding/finding_intervention.py +25 -22
  231. endoreg_db/models/medical/finding/finding_type.py +13 -12
  232. endoreg_db/models/medical/hardware/endoscope.py +26 -26
  233. endoreg_db/models/medical/hardware/endoscopy_processor.py +2 -2
  234. endoreg_db/models/medical/laboratory/lab_value.py +62 -91
  235. endoreg_db/models/medical/medication/medication.py +22 -10
  236. endoreg_db/models/medical/medication/medication_indication.py +29 -3
  237. endoreg_db/models/medical/medication/medication_indication_type.py +25 -14
  238. endoreg_db/models/medical/medication/medication_intake_time.py +31 -19
  239. endoreg_db/models/medical/medication/medication_schedule.py +27 -16
  240. endoreg_db/models/medical/organ/__init__.py +15 -12
  241. endoreg_db/models/medical/patient/medication_examples.py +6 -6
  242. endoreg_db/models/medical/patient/patient_disease.py +20 -23
  243. endoreg_db/models/medical/patient/patient_event.py +19 -22
  244. endoreg_db/models/medical/patient/patient_examination.py +48 -54
  245. endoreg_db/models/medical/patient/patient_examination_indication.py +16 -14
  246. endoreg_db/models/medical/patient/patient_finding.py +122 -139
  247. endoreg_db/models/medical/patient/patient_finding_classification.py +44 -49
  248. endoreg_db/models/medical/patient/patient_finding_intervention.py +8 -19
  249. endoreg_db/models/medical/patient/patient_lab_sample.py +28 -23
  250. endoreg_db/models/medical/patient/patient_lab_value.py +82 -89
  251. endoreg_db/models/medical/patient/patient_medication.py +27 -38
  252. endoreg_db/models/medical/patient/patient_medication_schedule.py +28 -36
  253. endoreg_db/models/medical/risk/risk.py +7 -6
  254. endoreg_db/models/medical/risk/risk_type.py +8 -5
  255. endoreg_db/models/metadata/model_meta.py +60 -29
  256. endoreg_db/models/metadata/model_meta_logic.py +125 -18
  257. endoreg_db/models/metadata/pdf_meta.py +31 -24
  258. endoreg_db/models/metadata/sensitive_meta.py +105 -85
  259. endoreg_db/models/metadata/sensitive_meta_logic.py +198 -103
  260. endoreg_db/models/metadata/video_meta.py +51 -31
  261. endoreg_db/models/metadata/video_prediction_logic.py +16 -23
  262. endoreg_db/models/metadata/video_prediction_meta.py +29 -33
  263. endoreg_db/models/other/distribution/date_value_distribution.py +89 -29
  264. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +21 -5
  265. endoreg_db/models/other/distribution/numeric_value_distribution.py +114 -53
  266. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +4 -3
  267. endoreg_db/models/other/emission/emission_factor.py +18 -8
  268. endoreg_db/models/other/gender.py +10 -5
  269. endoreg_db/models/other/information_source.py +50 -29
  270. endoreg_db/models/other/material.py +9 -5
  271. endoreg_db/models/other/resource.py +6 -4
  272. endoreg_db/models/other/tag.py +10 -5
  273. endoreg_db/models/other/transport_route.py +13 -8
  274. endoreg_db/models/other/unit.py +10 -6
  275. endoreg_db/models/other/waste.py +6 -5
  276. endoreg_db/models/report/report.py +6 -0
  277. endoreg_db/models/requirement/requirement.py +329 -361
  278. endoreg_db/models/requirement/requirement_error.py +85 -0
  279. endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
  280. endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +3 -6
  281. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +90 -64
  282. endoreg_db/models/requirement/requirement_operator.py +103 -112
  283. endoreg_db/models/requirement/requirement_set.py +74 -57
  284. endoreg_db/models/state/__init__.py +4 -4
  285. endoreg_db/models/state/abstract.py +2 -2
  286. endoreg_db/models/state/anonymization.py +12 -0
  287. endoreg_db/models/state/audit_ledger.py +49 -51
  288. endoreg_db/models/state/label_video_segment.py +9 -0
  289. endoreg_db/models/state/raw_pdf.py +101 -68
  290. endoreg_db/models/state/sensitive_meta.py +6 -2
  291. endoreg_db/models/state/video.py +110 -90
  292. endoreg_db/models/upload_job.py +35 -34
  293. endoreg_db/models/utils.py +28 -25
  294. endoreg_db/queries/__init__.py +3 -1
  295. endoreg_db/root_urls.py +21 -2
  296. endoreg_db/schemas/examination_evaluation.py +1 -1
  297. endoreg_db/serializers/__init__.py +2 -10
  298. endoreg_db/serializers/anonymization.py +18 -10
  299. endoreg_db/serializers/label_video_segment/label_video_segment.py +2 -29
  300. endoreg_db/serializers/meta/__init__.py +1 -6
  301. endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
  302. endoreg_db/serializers/misc/file_overview.py +11 -99
  303. endoreg_db/serializers/misc/sensitive_patient_data.py +50 -26
  304. endoreg_db/serializers/patient_examination/patient_examination.py +3 -3
  305. endoreg_db/serializers/pdf/anony_text_validation.py +39 -23
  306. endoreg_db/serializers/requirements/requirement_sets.py +92 -22
  307. endoreg_db/serializers/video/segmentation.py +2 -1
  308. endoreg_db/serializers/video/video_file_list.py +65 -34
  309. endoreg_db/serializers/video/video_processing_history.py +20 -5
  310. endoreg_db/services/__old/pdf_import.py +1487 -0
  311. endoreg_db/services/__old/video_import.py +1306 -0
  312. endoreg_db/services/anonymization.py +128 -89
  313. endoreg_db/services/lookup_service.py +65 -52
  314. endoreg_db/services/lookup_store.py +2 -2
  315. endoreg_db/services/pdf_import.py +0 -1382
  316. endoreg_db/services/report_import.py +10 -0
  317. endoreg_db/services/video_import.py +6 -1255
  318. endoreg_db/tasks/upload_tasks.py +79 -70
  319. endoreg_db/tasks/video_ingest.py +8 -4
  320. endoreg_db/urls/__init__.py +5 -32
  321. endoreg_db/urls/ai.py +32 -0
  322. endoreg_db/urls/media.py +121 -83
  323. endoreg_db/urls/root_urls.py +29 -0
  324. endoreg_db/utils/__init__.py +15 -5
  325. endoreg_db/utils/ai/multilabel_classification_net.py +116 -20
  326. endoreg_db/utils/case_generator/__init__.py +3 -0
  327. endoreg_db/utils/dataloader.py +142 -40
  328. endoreg_db/utils/defaults/set_default_center.py +32 -0
  329. endoreg_db/utils/names.py +22 -16
  330. endoreg_db/utils/paths.py +110 -46
  331. endoreg_db/utils/permissions.py +2 -1
  332. endoreg_db/utils/pipelines/Readme.md +1 -1
  333. endoreg_db/utils/pipelines/process_video_dir.py +1 -1
  334. endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +655 -0
  335. endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +97 -0
  336. endoreg_db/utils/setup_config.py +8 -5
  337. endoreg_db/utils/storage.py +115 -0
  338. endoreg_db/utils/validate_endo_roi.py +8 -2
  339. endoreg_db/utils/video/ffmpeg_wrapper.py +184 -188
  340. endoreg_db/views/__init__.py +85 -183
  341. endoreg_db/views/ai/__init__.py +8 -0
  342. endoreg_db/views/ai/label.py +155 -0
  343. endoreg_db/views/anonymization/media_management.py +202 -166
  344. endoreg_db/views/anonymization/overview.py +99 -67
  345. endoreg_db/views/anonymization/validate.py +182 -44
  346. endoreg_db/views/media/__init__.py +7 -20
  347. endoreg_db/views/media/pdf_media.py +197 -174
  348. endoreg_db/views/media/sensitive_metadata.py +193 -138
  349. endoreg_db/views/media/video_media.py +89 -82
  350. endoreg_db/views/meta/__init__.py +0 -8
  351. endoreg_db/views/misc/__init__.py +1 -7
  352. endoreg_db/views/misc/upload_views.py +94 -93
  353. endoreg_db/views/patient/patient.py +5 -4
  354. endoreg_db/views/report/__init__.py +5 -7
  355. endoreg_db/views/{pdf → report}/reimport.py +22 -22
  356. endoreg_db/views/{pdf/pdf_stream.py → report/report_stream.py} +46 -39
  357. endoreg_db/views/requirement/evaluate.py +188 -187
  358. endoreg_db/views/requirement/lookup.py +17 -3
  359. endoreg_db/views/requirement/lookup_store.py +22 -90
  360. endoreg_db/views/requirement/requirement_utils.py +89 -0
  361. endoreg_db/views/video/__init__.py +23 -24
  362. endoreg_db/views/video/correction.py +201 -172
  363. endoreg_db/views/video/reimport.py +1 -1
  364. endoreg_db/views/{media/video_segments.py → video/segments_crud.py} +77 -40
  365. endoreg_db/views/video/{video_meta.py → video_meta_stats.py} +2 -2
  366. endoreg_db/views/video/video_stream.py +7 -8
  367. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/METADATA +7 -3
  368. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/RECORD +391 -413
  369. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/WHEEL +1 -1
  370. endoreg_db/data/finding/anatomy_colon.yaml +0 -128
  371. endoreg_db/data/finding/colonoscopy.yaml +0 -40
  372. endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +0 -56
  373. endoreg_db/data/finding/complication.yaml +0 -16
  374. endoreg_db/data/finding/data.yaml +0 -105
  375. endoreg_db/data/finding/examination_setting.yaml +0 -16
  376. endoreg_db/data/finding/medication_related.yaml +0 -18
  377. endoreg_db/data/finding/outcome.yaml +0 -12
  378. endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +0 -95
  379. endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +0 -22
  380. endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +0 -25
  381. endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
  382. endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
  383. endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +0 -68
  384. endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
  385. endoreg_db/data/finding_classification/colonoscopy_location.yaml +0 -80
  386. endoreg_db/data/finding_classification/colonoscopy_lst.yaml +0 -21
  387. endoreg_db/data/finding_classification/colonoscopy_nice.yaml +0 -20
  388. endoreg_db/data/finding_classification/colonoscopy_paris.yaml +0 -26
  389. endoreg_db/data/finding_classification/colonoscopy_sano.yaml +0 -22
  390. endoreg_db/data/finding_classification/colonoscopy_summary.yaml +0 -53
  391. endoreg_db/data/finding_classification/complication_generic.yaml +0 -25
  392. endoreg_db/data/finding_classification/examination_setting_generic.yaml +0 -40
  393. endoreg_db/data/finding_classification/histology_colo.yaml +0 -51
  394. endoreg_db/data/finding_classification/intervention_required.yaml +0 -26
  395. endoreg_db/data/finding_classification/medication_related.yaml +0 -23
  396. endoreg_db/data/finding_classification/visualized.yaml +0 -33
  397. endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
  398. endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
  399. endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
  400. endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +0 -15
  401. endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +0 -17
  402. endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
  403. endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +0 -14
  404. endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
  405. endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +0 -82
  406. endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
  407. endoreg_db/data/finding_classification_choice/outcome.yaml +0 -19
  408. endoreg_db/data/finding_intervention/endoscopy.yaml +0 -43
  409. endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
  410. endoreg_db/data/finding_intervention/endoscopy_egd.yaml +0 -128
  411. endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +0 -32
  412. endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +0 -9
  413. endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +0 -36
  414. endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +0 -79
  415. endoreg_db/data/requirement/age.yaml +0 -26
  416. endoreg_db/data/requirement/gender.yaml +0 -25
  417. endoreg_db/management/commands/init_default_ai_model.py +0 -112
  418. endoreg_db/management/commands/reset_celery_schedule.py +0 -9
  419. endoreg_db/management/commands/validate_video.py +0 -204
  420. endoreg_db/migrations/0002_add_video_correction_models.py +0 -52
  421. endoreg_db/migrations/0003_add_center_display_name.py +0 -30
  422. endoreg_db/models/administration/permissions/__init__.py +0 -44
  423. endoreg_db/models/rule/__init__.py +0 -13
  424. endoreg_db/models/rule/rule.py +0 -27
  425. endoreg_db/models/rule/rule_applicator.py +0 -224
  426. endoreg_db/models/rule/rule_attribute_dtype.py +0 -17
  427. endoreg_db/models/rule/rule_type.py +0 -20
  428. endoreg_db/models/rule/ruleset.py +0 -17
  429. endoreg_db/renames.yml +0 -8
  430. endoreg_db/serializers/_old/raw_pdf_meta_validation.py +0 -223
  431. endoreg_db/serializers/_old/raw_video_meta_validation.py +0 -179
  432. endoreg_db/serializers/_old/video.py +0 -71
  433. endoreg_db/serializers/meta/pdf_file_meta_extraction.py +0 -115
  434. endoreg_db/serializers/meta/report_meta.py +0 -53
  435. endoreg_db/serializers/report/__init__.py +0 -9
  436. endoreg_db/serializers/report/mixins.py +0 -45
  437. endoreg_db/serializers/report/report.py +0 -105
  438. endoreg_db/serializers/report/report_list.py +0 -22
  439. endoreg_db/serializers/report/secure_file_url.py +0 -26
  440. endoreg_db/serializers/video/video_metadata.py +0 -105
  441. endoreg_db/services/requirements_object.py +0 -147
  442. endoreg_db/services/storage_aware_video_processor.py +0 -344
  443. endoreg_db/urls/files.py +0 -6
  444. endoreg_db/urls/label_video_segment_validate.py +0 -33
  445. endoreg_db/urls/label_video_segments.py +0 -46
  446. endoreg_db/urls/report.py +0 -48
  447. endoreg_db/urls/video.py +0 -61
  448. endoreg_db/utils/case_generator/case_generator.py +0 -159
  449. endoreg_db/utils/case_generator/utils.py +0 -30
  450. endoreg_db/utils/requirement_operator_logic/model_evaluators.py +0 -368
  451. endoreg_db/views/label/__init__.py +0 -5
  452. endoreg_db/views/label/label.py +0 -15
  453. endoreg_db/views/label_video_segment/__init__.py +0 -16
  454. endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +0 -44
  455. endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +0 -50
  456. endoreg_db/views/label_video_segment/label_video_segment.py +0 -77
  457. endoreg_db/views/label_video_segment/label_video_segment_by_label.py +0 -174
  458. endoreg_db/views/label_video_segment/label_video_segment_detail.py +0 -73
  459. endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +0 -46
  460. endoreg_db/views/label_video_segment/validate.py +0 -226
  461. endoreg_db/views/media/segments.py +0 -71
  462. endoreg_db/views/meta/available_files_list.py +0 -146
  463. endoreg_db/views/meta/report_meta.py +0 -53
  464. endoreg_db/views/meta/sensitive_meta_detail.py +0 -148
  465. endoreg_db/views/misc/secure_file_serving_view.py +0 -80
  466. endoreg_db/views/misc/secure_file_url_view.py +0 -84
  467. endoreg_db/views/misc/secure_url_validate.py +0 -79
  468. endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +0 -164
  469. endoreg_db/views/patient_finding_location/__init__.py +0 -5
  470. endoreg_db/views/patient_finding_location/pfl_create.py +0 -70
  471. endoreg_db/views/patient_finding_morphology/__init__.py +0 -5
  472. endoreg_db/views/patient_finding_morphology/pfm_create.py +0 -70
  473. endoreg_db/views/pdf/__init__.py +0 -8
  474. endoreg_db/views/report/report_list.py +0 -112
  475. endoreg_db/views/report/report_with_secure_url.py +0 -28
  476. endoreg_db/views/report/start_examination.py +0 -7
  477. endoreg_db/views/video/segmentation.py +0 -274
  478. endoreg_db/views/video/task_status.py +0 -49
  479. endoreg_db/views/video/timeline.py +0 -46
  480. endoreg_db/views/video/video_analyze.py +0 -52
  481. endoreg_db/views.py +0 -0
  482. /endoreg_db/data/requirement/{colonoscopy_baseline_austria.yaml → old/colonoscopy_baseline_austria.yaml} +0 -0
  483. /endoreg_db/data/requirement/{disease_cardiovascular.yaml → old/disease_cardiovascular.yaml} +0 -0
  484. /endoreg_db/data/requirement/{disease_classification_choice_cardiovascular.yaml → old/disease_classification_choice_cardiovascular.yaml} +0 -0
  485. /endoreg_db/data/requirement/{disease_hepatology.yaml → old/disease_hepatology.yaml} +0 -0
  486. /endoreg_db/data/requirement/{disease_misc.yaml → old/disease_misc.yaml} +0 -0
  487. /endoreg_db/data/requirement/{disease_renal.yaml → old/disease_renal.yaml} +0 -0
  488. /endoreg_db/data/requirement/{endoscopy_bleeding_risk.yaml → old/endoscopy_bleeding_risk.yaml} +0 -0
  489. /endoreg_db/data/requirement/{event_cardiology.yaml → old/event_cardiology.yaml} +0 -0
  490. /endoreg_db/data/requirement/{event_requirements.yaml → old/event_requirements.yaml} +0 -0
  491. /endoreg_db/data/requirement/{finding_colon_polyp.yaml → old/finding_colon_polyp.yaml} +0 -0
  492. /endoreg_db/{migrations/__init__.py → data/requirement/old/gender.yaml} +0 -0
  493. /endoreg_db/data/requirement/{lab_value.yaml → old/lab_value.yaml} +0 -0
  494. /endoreg_db/data/requirement/{medication.yaml → old/medication.yaml} +0 -0
  495. /endoreg_db/data/requirement_operator/{age.yaml → _old/age.yaml} +0 -0
  496. /endoreg_db/data/requirement_operator/{lab_operators.yaml → _old/lab_operators.yaml} +0 -0
  497. /endoreg_db/data/requirement_operator/{model_operators.yaml → _old/model_operators.yaml} +0 -0
  498. /endoreg_db/{models/media/video/refactor_plan.md → import_files/pseudonymization/__init__.py} +0 -0
  499. /endoreg_db/{models/media/video/video_file_frames.py → import_files/pseudonymization/pseudonymize.py} +0 -0
  500. /endoreg_db/models/{metadata/frame_ocr_result.py → report/__init__.py} +0 -0
  501. /endoreg_db/{urls/sensitive_meta.py → models/report/images.py} +0 -0
  502. /endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py} +0 -0
  503. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/licenses/LICENSE +0 -0
endoreg_db/urls/report.py DELETED
@@ -1,48 +0,0 @@
1
- from django.urls import path
2
- from endoreg_db.views import (
3
- ReportListView,
4
- ReportWithSecureUrlView,
5
- ReportFileMetadataView,
6
- )
7
-
8
- url_patterns = [ # ---------------------------------------------------------------------------------------
9
- # REPORT SERVICE ENDPOINTS
10
- #
11
- # Neue API-Endpunkte für den Report-Service mit sicheren URLs
12
- #
13
- # Diese Endpunkte ermöglichen es dem Frontend (UniversalReportViewer),
14
- # Reports mit zeitlich begrenzten, sicheren URLs zu laden und anzuzeigen.
15
- #
16
- # Verwendung im Frontend:
17
- # - loadReportWithSecureUrl(reportId)
18
- # - generateSecureUrl(reportId, fileType)
19
- # - validateCurrentUrl()
20
- #
21
- # ---------------------------------------------------------------------------------------
22
-
23
- # API-Endpunkt für paginierte Report-Listen mit Filterung
24
- # GET /api/reports/?page=1&page_size=20&status=pending&file_type=pdf&patient_name=John
25
- # Lädt eine paginierte Liste aller Reports mit optionalen Filtern
26
- path('reports/',
27
- ReportListView.as_view(),
28
- name='report_list'
29
- ),
30
-
31
- # API-Endpunkt für Reports mit automatischer sicherer URL-Generierung
32
- # GET /api/reports/{report_id}/with-secure-url/
33
- # Lädt Report-Daten inklusive Metadaten und generiert automatisch eine sichere URL
34
- path(
35
- 'reports/<int:report_id>/with-secure-url/',
36
- ReportWithSecureUrlView.as_view(),
37
- name='report_with_secure_url'
38
- ),
39
-
40
- # API-Endpunkt für Report-Datei-Metadaten
41
- # GET /api/reports/{report_id}/file-metadata/
42
- # Gibt Datei-Metadaten zurück (Größe, Typ, Datum, etc.)
43
- path(
44
- 'reports/<int:report_id>/file-metadata/',
45
- ReportFileMetadataView.as_view(),
46
- name='report_file_metadata'
47
- ),
48
- ]
endoreg_db/urls/video.py DELETED
@@ -1,61 +0,0 @@
1
- from django.urls import path
2
-
3
- from endoreg_db.views import (
4
- SensitiveMetaDetailView,
5
- VideoLabelView,
6
- # Note: VideoStreamView moved to modern media framework. See: endoreg_db/urls/media.py
7
- # Note: All Video Correction Views moved to modern media framework. See: endoreg_db/urls/media.py
8
- )
9
-
10
- url_patterns = [
11
- # Video Label segments API endpoint
12
- # GET /api/videos/<int:video_id>/labels/<str:label_name>/
13
- # Retrieves time segments and frame predictions for a specific label on a video
14
- path(
15
- 'videos/<int:video_id>/labels/<str:label_name>/',
16
- VideoLabelView.as_view(),
17
- name='video_label_segments'
18
- ),
19
-
20
- # ---------------------------------------------------------------------------------------
21
- # VIDEO STREAMING - MOVED TO MODERN MEDIA FRAMEWORK
22
- #
23
- # Video streaming endpoint has been migrated to the media framework
24
- # as of October 14, 2025. Please use the new endpoints:
25
- #
26
- # OLD → NEW:
27
- # GET /api/videostream/<pk>/ → GET /api/media/videos/<pk>/
28
- # GET /api/videostream/<pk>/ → GET /api/media/videos/<pk>/stream/
29
- #
30
- # See: endoreg_db/urls/media.py for new URL registrations
31
- # ---------------------------------------------------------------------------------------
32
-
33
- # Note: Video Re-import moved to modern media framework
34
- # See: endoreg_db/urls/media.py - POST /api/media/videos/<int:pk>/reimport/
35
-
36
- # Video Sensitive Meta endpoints (for video anonymization)
37
- # GET /api/video/sensitivemeta/<int:sensitive_meta_id>/
38
- # PATCH /api/video/sensitivemeta/<int:sensitive_meta_id>/
39
- path(
40
- 'video/sensitivemeta/<int:sensitive_meta_id>/',
41
- SensitiveMetaDetailView.as_view(),
42
- name='video_sensitive_meta_detail'
43
- ),
44
-
45
- # ---------------------------------------------------------------------------------------
46
- # VIDEO CORRECTION API ENDPOINTS - MOVED TO MODERN MEDIA FRAMEWORK
47
- #
48
- # All video correction endpoints have been migrated to the modern media framework
49
- # as of October 14, 2025. Please use the new endpoints:
50
- #
51
- # OLD → NEW:
52
- # GET /api/video-metadata/<id>/ → GET /api/media/videos/<pk>/metadata/
53
- # GET /api/video-processing-history/<id>/ → GET /api/media/videos/<pk>/processing-history/
54
- # POST /api/video-analyze/<id>/ → POST /api/media/videos/<pk>/analyze/
55
- # POST /api/video-apply-mask/<id>/ → POST /api/media/videos/<pk>/apply-mask/
56
- # POST /api/video-remove-frames/<id>/ → POST /api/media/videos/<pk>/remove-frames/
57
- # POST /api/video-reprocess/<id>/ → POST /api/media/videos/<pk>/reprocess/
58
- #
59
- # See: endoreg_db/urls/media.py for new URL registrations
60
- # ---------------------------------------------------------------------------------------
61
- ]
@@ -1,159 +0,0 @@
1
- from endoreg_db.models import CaseTemplate, CaseTemplateRule, CaseTemplateRuleType
2
- from endoreg_db.case_generator.lab_sample_factory import LabSampleFactory
3
-
4
- DEFAULT_CASE_TEMPLATE_NAME = "pre_default_screening_colonoscopy"
5
-
6
- class CaseGenerator:
7
- """
8
- Provides methods to generate cases based on a template.
9
- """
10
-
11
- def __init__(self, template: CaseTemplate = None):
12
- """
13
- Initializes the CaseGenerator with a template.
14
-
15
- Args:
16
- template (CaseTemplate, optional): The template to use for case generation. Defaults to the predefined template.
17
- """
18
- self.template = template or CaseTemplate.objects.get(name=DEFAULT_CASE_TEMPLATE_NAME)
19
- self.lab_sample_factory = LabSampleFactory()
20
-
21
- # Define available rule types
22
- rule_type_names = [
23
- "create-object",
24
- "set-field-default",
25
- "set-field-by-distribution",
26
- "set-field-by-value",
27
- "set-field-single-choice",
28
- "set-field-multiple-choice",
29
- ]
30
- self.available_rule_types = CaseTemplateRuleType.objects.filter(name__in=rule_type_names)
31
-
32
- def _validate_rule_type(self, rule_type: CaseTemplateRuleType):
33
- """
34
- Validates if the rule type is supported.
35
-
36
- Args:
37
- rule_type (CaseTemplateRuleType): The rule type to validate.
38
-
39
- Raises:
40
- ValueError: If the rule type is not supported.
41
- """
42
- if rule_type not in self.available_rule_types:
43
- raise ValueError(f"Rule type {rule_type} is not supported.")
44
-
45
- def _apply_create_object(self, rule: CaseTemplateRule, parent=None):
46
- """
47
- Applies a create-object rule to generate a model instance.
48
-
49
- Args:
50
- rule (CaseTemplateRule): The rule to apply.
51
- parent (Optional[Model]): The parent object for the rule.
52
-
53
- Returns:
54
- Model: The created model instance.
55
- """
56
- target_model = rule.get_target_model()
57
- extra_params = rule.extra_parameters or {}
58
- create_method_info = extra_params.get("create_method", {})
59
-
60
- assert create_method_info, "Create method must be set for a create-object rule."
61
-
62
- create_method = getattr(target_model, create_method_info["name"])
63
- kwargs = create_method_info.get("kwargs", {})
64
-
65
- if parent:
66
- kwargs[rule.parent_field] = parent
67
-
68
- target_instance = create_method(**kwargs)
69
- target_instance.save()
70
-
71
- for action in extra_params.get("actions", []):
72
- action_method = getattr(target_instance, action["name"])
73
- action_kwargs = action.get("kwargs", {})
74
- action_method(**action_kwargs)
75
-
76
- for chained_rule in rule.chained_rules.all():
77
- self.apply_rule(chained_rule, parent=target_instance)
78
-
79
- return target_instance
80
-
81
- def _apply_set_field_by_distribution(self, rule: CaseTemplateRule, parent):
82
- """
83
- Applies a set-field-by-distribution rule.
84
-
85
- Args:
86
- rule (CaseTemplateRule): The rule to apply.
87
- parent (Model): The parent object for the rule.
88
-
89
- Returns:
90
- Model: The updated parent object.
91
- """
92
- assert parent, "Parent must be provided for set-field-by-distribution rules."
93
- assert rule.target_field, "Target field must be specified for the rule."
94
-
95
- distribution = rule.get_distribution()
96
- value = distribution.generate_value()
97
-
98
- setattr(parent, rule.target_field, value)
99
- parent.save()
100
- return parent
101
-
102
- def apply_rule(self, rule: CaseTemplateRule, parent=None):
103
- """
104
- Applies a rule based on its type to generate a case.
105
-
106
- Args:
107
- rule (CaseTemplateRule): The rule to apply.
108
- parent (Optional[Model]): The parent object for the rule.
109
-
110
- Returns:
111
- Model: The case by applying the rule.
112
- """
113
- self._validate_rule_type(rule.rule_type)
114
-
115
- if rule.rule_type.name == "create-object":
116
- return self._apply_create_object(rule, parent)
117
-
118
- if rule.rule_type.name == "set-field-by-distribution":
119
- return self._apply_set_field_by_distribution(rule, parent)
120
-
121
- raise ValueError(f"Unsupported rule type: {rule.rule_type.name}")
122
-
123
- def generate_case(self, case_template: CaseTemplate = None):
124
- """
125
- Generates a case based on the provided or default template.
126
-
127
- Args:
128
- case_template (CaseTemplate, optional): The template to use for case generation. Defaults to None.
129
-
130
- Returns:
131
- Tuple[Model, Model]: The generated patient and medication schedule.
132
- """
133
- case_template = case_template or CaseTemplate.objects.get(name=DEFAULT_CASE_TEMPLATE_NAME)
134
-
135
- create_patient_rule = case_template.get_create_patient_rule()
136
- patient = self.apply_rule(create_patient_rule)
137
-
138
- medication_schedule_rule = case_template.get_create_patient_medication_schedule_rule()
139
- medication_schedule = self.apply_rule(medication_schedule_rule, parent=patient)
140
-
141
- return patient, medication_schedule
142
-
143
- # if not create_new_patient:
144
- # raise NotImplementedError("Only new patients are supported at the moment.")
145
- # else:
146
- # # TODO Implement patient rules
147
- # patient_rules = None # all rules of type "create_patient"
148
- # patient = self.generate_patient(patient_rules)
149
-
150
- # # Generate case based on template
151
- # rules = self.template.get_rules()
152
- # chained_rules = set()
153
-
154
- # for rule in rules:
155
- # rule_chain = rule.get_all_downward_chained_rules()
156
- # chained_rules.add(rule)
157
- # chained_rules.update(rule_chain)
158
-
159
- # return chained_rules
@@ -1,30 +0,0 @@
1
- from endoreg_db.models import CaseTemplate
2
- from endoreg_db.case_generator.case_generator import CaseGenerator
3
-
4
- # TEMPLATE_NAME = "pre_endo-anticoagulation-af-low_risk"
5
- TEMPLATE_NAME = "pre_default_screening_colonoscopy"
6
-
7
- def fetch_template(template_name: str = DEFAULT_TEMPLATE_NAME) -> CaseTemplate:
8
- """
9
- Fetches a CaseTemplate by name.
10
-
11
- Args:
12
- template_name (str): The name of the template to fetch. Defaults to DEFAULT_TEMPLATE_NAME.
13
-
14
- Returns:
15
- CaseTemplate: The fetched CaseTemplate instance.
16
- """
17
- return CaseTemplate.objects.get(name=template_name)
18
-
19
- def initialize_case_generator(template_name: str = DEFAULT_TEMPLATE_NAME) -> CaseGenerator:
20
- """
21
- Initializes a CaseGenerator with the specified template.
22
-
23
- Args:
24
- template_name (str): The name of the template to use. Defaults to DEFAULT_TEMPLATE_NAME.
25
-
26
- Returns:
27
- CaseGenerator: An instance of CaseGenerator initialized with the template.
28
- """
29
- template = fetch_template(template_name)
30
- return CaseGenerator(template)
@@ -1,368 +0,0 @@
1
- import datetime # Add import
2
- from datetime import timedelta # Add import
3
- from typing import TYPE_CHECKING
4
-
5
- if TYPE_CHECKING:
6
- from endoreg_db.utils.links.requirement_link import RequirementLinks
7
- from endoreg_db.models.requirement.requirement import Requirement
8
- # from endoreg_db.models import Unit # Potentially needed for dynamic unit handling
9
-
10
-
11
- # Helper function to check if a date is within the timeframe specified by a Requirement
12
- def _is_date_in_timeframe(date_to_check: datetime.date | None, requirement: "Requirement") -> bool:
13
- """
14
- Checks if a given date falls within the timeframe specified by a Requirement.
15
-
16
- The timeframe is defined by `numeric_value_min` and `numeric_value_max` on the
17
- Requirement, interpreted relative to the current date.
18
-
19
- Currently, this function only supports timeframes specified in "days".
20
- If the Requirement's unit is not "days", a NotImplementedError will be raised.
21
-
22
- Args:
23
- date_to_check: The date to evaluate. If None, returns False.
24
- requirement: The Requirement instance containing timeframe definitions
25
- (unit, numeric_value_min, numeric_value_max).
26
-
27
- Returns:
28
- True if the date_to_check is within the defined timeframe, False otherwise.
29
- Returns False if date_to_check is None or if the requirement lacks
30
- necessary timeframe information (unit, min/max values).
31
-
32
- Raises:
33
- NotImplementedError: If the requirement.unit.name is not 'days' (case-insensitive).
34
- """
35
- if date_to_check is None:
36
- return False
37
- if not requirement.unit or requirement.numeric_value_min is None or requirement.numeric_value_max is None:
38
- return False # Not enough information for timeframe evaluation
39
-
40
- # For now, primarily supporting 'days'. Extend if other units are common.
41
- if requirement.unit.name.lower() != "days":
42
- raise NotImplementedError(
43
- f"Timeframe unit '{requirement.unit.name}' is not supported. "
44
- "Currently, only 'days' is implemented for timeframe checks."
45
- )
46
-
47
- today = datetime.date.today()
48
- # numeric_value_min is typically negative for "days ago" (e.g., -30 for 30 days ago)
49
- # numeric_value_max is typically 0 for "today"
50
- timeframe_start_delta = int(requirement.numeric_value_min)
51
- timeframe_end_delta = int(requirement.numeric_value_max)
52
-
53
- start_date_bound = today + timedelta(days=timeframe_start_delta)
54
- end_date_bound = today + timedelta(days=timeframe_end_delta)
55
-
56
- return start_date_bound <= date_to_check <= end_date_bound
57
-
58
-
59
- def _evaluate_models_match_any(
60
- requirement_links: "RequirementLinks",
61
- input_links: "RequirementLinks",
62
- **kwargs
63
- ) -> bool:
64
- """
65
- Checks if the requirement_links matches any of the input_links.
66
-
67
- Args:
68
- requirement_links: The reference set of requirement links to compare against.
69
- input_links: The aggregated requirement links from the input objects.
70
-
71
- Returns:
72
- True if the input set of requirement links matches according to requirement_links.match_any; otherwise, False.
73
- """
74
- return requirement_links.match_any(input_links)
75
-
76
-
77
- def _evaluate_models_match_any_in_timeframe(
78
- requirement_links: "RequirementLinks",
79
- input_links: "RequirementLinks",
80
- requirement: "Requirement", # Explicitly pass Requirement
81
- **kwargs # Keep for consistency, though 'requirement' is the main one used here
82
- ) -> bool:
83
- """
84
- Checks if any relevant model in input_links matches a model specified in
85
- requirement_links AND falls within the timeframe defined on the Requirement.
86
-
87
- Currently focuses on PatientEvent instances and their dates.
88
- """
89
- active_req_links_dict = requirement_links.active()
90
- if not active_req_links_dict:
91
- # If the Requirement itself doesn't specify any models to match (e.g., requirement.events is empty),
92
- # then it's vacuously true that "any" of these (non-existent) required models are matched.
93
- # The timeframe aspect becomes irrelevant if no specific models are being checked.
94
- return True
95
-
96
- # --- Handle PatientEvents ---
97
- # Check if the requirement is concerned with events
98
- if requirement_links.events: # This list contains Event model instances
99
- required_event_models = set(requirement_links.events) # Target Event models from the Requirement
100
-
101
- # input_links.patient_events contains PatientEvent instances provided as input
102
- for patient_event_instance in input_links.patient_events:
103
- # Check if the event of the current PatientEvent instance is one of the target events
104
- if patient_event_instance.event in required_event_models:
105
- # If it is, check if this PatientEvent's date is within the timeframe
106
- if _is_date_in_timeframe(patient_event_instance.date, requirement):
107
- return True # Found a matching event within the timeframe
108
-
109
- # --- Handle Other Model Types (Example: PatientLabValue) ---
110
- # if requirement_links.lab_values:
111
- # required_lab_value_models = set(requirement_links.lab_values)
112
- # for plv_instance in input_links.patient_lab_values:
113
- # if plv_instance.lab_value in required_lab_value_models:
114
- # date_to_check = None
115
- # if hasattr(plv_instance, 'date_time_value') and plv_instance.date_time_value:
116
- # date_to_check = plv_instance.date_time_value.date()
117
- # elif hasattr(plv_instance, 'date') and plv_instance.date: # If it had a simple date field
118
- # date_to_check = plv_instance.date
119
- #
120
- # if _is_date_in_timeframe(date_to_check, requirement):
121
- # return True
122
-
123
- # If the code reaches here, no matching model within the timeframe was found
124
- # for any of the categories specified in requirement_links.
125
- return False
126
-
127
-
128
- def _evaluate_models_match_all(
129
- requirement_links: "RequirementLinks",
130
- input_links: "RequirementLinks",
131
- **kwargs
132
- ) -> bool:
133
- """
134
- Evaluates if all active links in requirement_links are present in input_links.
135
-
136
- For each category of links in requirement_links (e.g., diseases, examinations),
137
- all items specified in that category in requirement_links must be present in the
138
- corresponding category in input_links.
139
-
140
- Args:
141
- requirement_links: The RequirementLinks object from the Requirement model.
142
- input_links: The aggregated RequirementLinks object from the input arguments.
143
- **kwargs: Additional keyword arguments (currently unused).
144
-
145
- Returns:
146
- True if all specified items in requirement_links are found in input_links,
147
- False otherwise.
148
- """
149
- active_req_links = requirement_links.active() # Get dict of non-empty lists from requirement
150
-
151
- if not active_req_links: # If the requirement specifies no actual items to link
152
- return True # Vacuously true, as there are no conditions to fail
153
-
154
- for link_category_name, req_items_list in active_req_links.items():
155
- input_items_list = getattr(input_links, link_category_name, [])
156
-
157
- try:
158
- set_input_items = set(input_items_list)
159
- set_req_items = set(req_items_list)
160
- except TypeError:
161
- for req_item in req_items_list:
162
- if req_item not in input_items_list:
163
- return False
164
- continue
165
-
166
- if not set_req_items.issubset(set_input_items):
167
- return False
168
-
169
- return True
170
-
171
- def _evaluate_age_gte(
172
- requirement_links: "RequirementLinks",
173
- input_links: "RequirementLinks",
174
- requirement: "Requirement",
175
- **kwargs
176
- ) -> bool:
177
- """
178
- Checks if any patient in the input has an age greater than or equal to the requirement's numeric_value.
179
-
180
- Args:
181
- requirement_links: The RequirementLinks object from the Requirement model (not used for age checks).
182
- input_links: The aggregated RequirementLinks object from the input arguments.
183
- requirement: The Requirement instance containing the minimum age in numeric_value.
184
- **kwargs: Additional keyword arguments, should contain 'original_input_args' with the original Patient instances.
185
-
186
- Returns:
187
- True if any patient in the input has an age >= requirement.numeric_value, False otherwise.
188
- """
189
- from endoreg_db.models.administration.person.patient import Patient
190
- import logging
191
-
192
- logger = logging.getLogger(__name__)
193
-
194
- if requirement.numeric_value is None:
195
- logger.debug("age_gte: requirement.numeric_value is None, returning False")
196
- return False # Cannot evaluate without a minimum age requirement
197
-
198
- min_age = requirement.numeric_value
199
- logger.debug(f"age_gte: Checking if any patient has age >= {min_age}")
200
-
201
- # Check if we have Patient instances in the original_input_args
202
- original_args = kwargs.get('original_input_args', [])
203
- logger.debug(f"age_gte: Found {len(original_args)} original input arguments: {[type(arg).__name__ for arg in original_args]}")
204
-
205
- for i, arg in enumerate(original_args):
206
- logger.debug(f"age_gte: Checking argument {i}: {type(arg).__name__}")
207
- if isinstance(arg, Patient):
208
- patient_age = arg.age()
209
- logger.debug(f"age_gte: Patient {arg} has age {patient_age}, comparing with min_age {min_age}")
210
- if patient_age is not None and patient_age >= min_age:
211
- logger.debug(f"age_gte: Patient age {patient_age} >= {min_age}, returning True")
212
- return True
213
- else:
214
- logger.debug(f"age_gte: Patient age {patient_age} < {min_age} or is None")
215
- # Handle QuerySets of patients
216
- elif hasattr(arg, 'model') and issubclass(arg.model, Patient):
217
- logger.debug(f"age_gte: Found Patient QuerySet with {arg.count()} patients")
218
- for patient in arg:
219
- patient_age = patient.age()
220
- logger.debug(f"age_gte: Patient {patient} has age {patient_age}, comparing with min_age {min_age}")
221
- if patient_age is not None and patient_age >= min_age:
222
- logger.debug(f"age_gte: Patient age {patient_age} >= {min_age}, returning True")
223
- return True
224
- else:
225
- logger.debug(f"age_gte: Argument {i} is not a Patient or Patient QuerySet: {type(arg)}")
226
-
227
- logger.debug(f"age_gte: No patient found with age >= {min_age}, returning False")
228
- return False
229
-
230
-
231
- def _evaluate_age_lte(
232
- requirement_links: "RequirementLinks",
233
- input_links: "RequirementLinks",
234
- requirement: "Requirement",
235
- **kwargs
236
- ) -> bool:
237
- """
238
- Checks if any patient in the input has an age less than or equal to the requirement's numeric_value.
239
-
240
- Args:
241
- requirement_links: The RequirementLinks object from the Requirement model (not used for age checks).
242
- input_links: The aggregated RequirementLinks object from the input arguments.
243
- requirement: The Requirement instance containing the maximum age in numeric_value.
244
- **kwargs: Additional keyword arguments, should contain 'original_input_args' with the original Patient instances.
245
-
246
- Returns:
247
- True if any patient in the input has an age <= requirement.numeric_value, False otherwise.
248
- """
249
- from endoreg_db.models.administration.person.patient import Patient
250
-
251
- if requirement.numeric_value is None:
252
- return False # Cannot evaluate without a maximum age requirement
253
-
254
- max_age = requirement.numeric_value
255
-
256
- # Check if we have Patient instances in the original_input_args
257
- original_args = kwargs.get('original_input_args', [])
258
- for arg in original_args:
259
- if isinstance(arg, Patient):
260
- patient_age = arg.age()
261
- if patient_age is not None and patient_age <= max_age:
262
- return True
263
- # Handle QuerySets of patients
264
- elif hasattr(arg, 'model') and issubclass(arg.model, Patient):
265
- for patient in arg:
266
- patient_age = patient.age()
267
- if patient_age is not None and patient_age <= max_age:
268
- return True
269
-
270
- return False
271
-
272
-
273
- def dispatch_operator_evaluation(
274
- operator_name: str,
275
- requirement_links: "RequirementLinks",
276
- input_links: "RequirementLinks",
277
- **kwargs
278
- ) -> bool:
279
- """
280
- Dispatches the evaluation to the appropriate function based on the operator name.
281
-
282
- Args:
283
- operator_name: The name of the operator to evaluate.
284
- requirement_links: The RequirementLinks object from the Requirement model.
285
- input_links: The aggregated RequirementLinks object from the input arguments.
286
- **kwargs: Additional keyword arguments for specific operator logic.
287
- For lab value operators, this includes 'requirement' (the Requirement model instance).
288
-
289
- Returns:
290
- True if the condition defined by the operator is met, False otherwise.
291
-
292
- Raises:
293
- NotImplementedError: If the evaluation logic for the operator's name is not implemented.
294
- """
295
- from .lab_value_operators import LAB_VALUE_OPERATOR_FUNCTIONS
296
- from endoreg_db.models.requirement.requirement import Requirement # Runtime import for isinstance
297
-
298
- eval_func = None
299
- requirement = kwargs.get("requirement") # Get requirement for operators that need it
300
-
301
- if operator_name == "models_match_any":
302
- eval_func = _evaluate_models_match_any
303
- return eval_func(
304
- requirement_links=requirement_links,
305
- input_links=input_links,
306
- **kwargs
307
- )
308
- elif operator_name == "models_match_all":
309
- eval_func = _evaluate_models_match_all
310
- return eval_func(
311
- requirement_links=requirement_links,
312
- input_links=input_links,
313
- **kwargs
314
- )
315
- elif operator_name == "models_match_any_in_timeframe":
316
- # 'requirement' is already extracted from kwargs via requirement = kwargs.get("requirement")
317
- if not isinstance(requirement, Requirement): # Ensure requirement is present and correct type
318
- raise ValueError("models_match_any_in_timeframe operator requires a valid 'requirement' instance in kwargs.")
319
-
320
- # Create a new kwargs dict for the call, excluding 'requirement' to avoid passing it twice,
321
- # as it's already an explicit parameter for _evaluate_models_match_any_in_timeframe.
322
- kwargs_for_eval = {k: v for k, v in kwargs.items() if k != 'requirement'}
323
-
324
- eval_func = _evaluate_models_match_any_in_timeframe
325
- return eval_func(
326
- requirement_links=requirement_links,
327
- input_links=input_links,
328
- requirement=requirement, # Pass the requirement instance explicitly
329
- **kwargs_for_eval # Pass the remaining kwargs
330
- )
331
- elif operator_name in LAB_VALUE_OPERATOR_FUNCTIONS:
332
- if not isinstance(requirement, Requirement): # Ensure requirement is present and correct type
333
- raise ValueError(f"Lab value operator \'{operator_name}\' requires a valid 'requirement' instance in kwargs.")
334
-
335
- eval_func = LAB_VALUE_OPERATOR_FUNCTIONS[operator_name]
336
- return eval_func(
337
- input_links=input_links,
338
- requirement=requirement,
339
- operator_kwargs=kwargs
340
- )
341
- elif operator_name == "age_gte":
342
- if not isinstance(requirement, Requirement):
343
- raise ValueError("age_gte operator requires a valid 'requirement' instance in kwargs.")
344
-
345
- # Create a new kwargs dict for the call, excluding 'requirement' to avoid passing it twice
346
- kwargs_for_eval = {k: v for k, v in kwargs.items() if k != 'requirement'}
347
-
348
- return _evaluate_age_gte(
349
- requirement_links=requirement_links,
350
- input_links=input_links,
351
- requirement=requirement,
352
- **kwargs_for_eval
353
- )
354
- elif operator_name == "age_lte":
355
- if not isinstance(requirement, Requirement):
356
- raise ValueError("age_lte operator requires a valid 'requirement' instance in kwargs.")
357
-
358
- # Create a new kwargs dict for the call, excluding 'requirement' to avoid passing it twice
359
- kwargs_for_eval = {k: v for k, v in kwargs.items() if k != 'requirement'}
360
-
361
- return _evaluate_age_lte(
362
- requirement_links=requirement_links,
363
- input_links=input_links,
364
- requirement=requirement,
365
- **kwargs_for_eval
366
- )
367
- else:
368
- raise NotImplementedError(f"Evaluation logic for operator '{operator_name}' is not implemented.")
@@ -1,5 +0,0 @@
1
- from .label import LabelViewSet
2
-
3
- __all__ = [
4
- "LabelViewSet",
5
- ]