endoreg-db 0.8.9.32__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 (787) hide show
  1. endoreg_db/__init__.py +0 -0
  2. endoreg_db/_version.py +34 -0
  3. endoreg_db/admin.py +97 -0
  4. endoreg_db/api/serializers/finding_descriptions.py +0 -0
  5. endoreg_db/api/views/finding_descriptions.py +0 -0
  6. endoreg_db/api_urls.py +4 -0
  7. endoreg_db/apps.py +17 -0
  8. endoreg_db/assets/dummy_model.ckpt +1 -0
  9. endoreg_db/authz/auth.py +78 -0
  10. endoreg_db/authz/backends.py +168 -0
  11. endoreg_db/authz/management/commands/list_routes.py +20 -0
  12. endoreg_db/authz/middleware.py +84 -0
  13. endoreg_db/authz/permissions.py +138 -0
  14. endoreg_db/authz/policy.py +224 -0
  15. endoreg_db/authz/settings.py +64 -0
  16. endoreg_db/authz/views_auth.py +70 -0
  17. endoreg_db/codemods/readme.md +88 -0
  18. endoreg_db/codemods/rename_datetime_fields.py +99 -0
  19. endoreg_db/config/__init__.py +0 -0
  20. endoreg_db/config/env.py +106 -0
  21. endoreg_db/config/settings/__init__.py +6 -0
  22. endoreg_db/config/settings/base.py +148 -0
  23. endoreg_db/config/settings/case_gen.py +32 -0
  24. endoreg_db/config/settings/dev.py +108 -0
  25. endoreg_db/config/settings/keycloak.py +177 -0
  26. endoreg_db/config/settings/prod.py +66 -0
  27. endoreg_db/config/settings/test.py +72 -0
  28. endoreg_db/data/__init__.py +135 -0
  29. endoreg_db/data/ai_model/data.yaml +7 -0
  30. endoreg_db/data/ai_model_label/label/data.yaml +88 -0
  31. endoreg_db/data/ai_model_label/label/polyp_classification.yaml +52 -0
  32. endoreg_db/data/ai_model_label/label-set/data.yaml +40 -0
  33. endoreg_db/data/ai_model_label/label-set/polyp_classifications.yaml +25 -0
  34. endoreg_db/data/ai_model_label/label-type/data.yaml +7 -0
  35. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +27 -0
  36. endoreg_db/data/ai_model_type/data.yaml +7 -0
  37. endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml +176 -0
  38. endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml +20 -0
  39. endoreg_db/data/case_template/rule/00_patient_lab_sample_add_default_value.yaml +167 -0
  40. endoreg_db/data/case_template/rule/01_patient-set-age.yaml +8 -0
  41. endoreg_db/data/case_template/rule/01_patient-set-gender.yaml +9 -0
  42. endoreg_db/data/case_template/rule/11_create_patient_lab_sample.yaml +23 -0
  43. endoreg_db/data/case_template/rule/12_create-patient_medication-anticoagulation.yaml +19 -0
  44. endoreg_db/data/case_template/rule/13_create-patient_medication_schedule-anticoagulation.yaml +19 -0
  45. endoreg_db/data/case_template/rule/19_create_patient.yaml +17 -0
  46. endoreg_db/data/case_template/rule_type/base_types.yaml +35 -0
  47. endoreg_db/data/case_template/rule_value/.init +0 -0
  48. endoreg_db/data/case_template/rule_value_type/base_types.yaml +59 -0
  49. endoreg_db/data/case_template/template/base.yaml +8 -0
  50. endoreg_db/data/case_template/template_type/pre_endoscopy.yaml +3 -0
  51. endoreg_db/data/case_template/tmp/_rule_value +13 -0
  52. endoreg_db/data/case_template/tmp/rule/01_atrial_fibrillation.yaml +21 -0
  53. endoreg_db/data/case_template/tmp/rule/02_create_object.yaml +10 -0
  54. endoreg_db/data/case_template/tmp/template/atrial_fibrillation_low_risk.yaml +7 -0
  55. endoreg_db/data/center/data.yaml +99 -0
  56. endoreg_db/data/center_resource/green_endoscopy_dashboard_CenterResource.yaml +144 -0
  57. endoreg_db/data/center_shift/ukw.yaml +9 -0
  58. endoreg_db/data/center_waste/green_endoscopy_dashboard_CenterWaste.yaml +48 -0
  59. endoreg_db/data/contraindication/bleeding.yaml +11 -0
  60. endoreg_db/data/db_summary.csv +58 -0
  61. endoreg_db/data/db_summary.xlsx +0 -0
  62. endoreg_db/data/disease/cardiovascular.yaml +37 -0
  63. endoreg_db/data/disease/hepatology.yaml +5 -0
  64. endoreg_db/data/disease/misc.yaml +5 -0
  65. endoreg_db/data/disease/renal.yaml +5 -0
  66. endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +6 -0
  67. endoreg_db/data/disease_classification/coronary_vessel_disease.yaml +6 -0
  68. endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +41 -0
  69. endoreg_db/data/disease_classification_choice/coronary_vessel_disease.yaml +20 -0
  70. endoreg_db/data/distribution/date/patient.yaml +7 -0
  71. endoreg_db/data/distribution/multiple_categorical/.init +0 -0
  72. endoreg_db/data/distribution/numeric/data.yaml +14 -0
  73. endoreg_db/data/distribution/single_categorical/patient.yaml +7 -0
  74. endoreg_db/data/emission_factor/green_endoscopy_dashboard_EmissionFactor.yaml +132 -0
  75. endoreg_db/data/endoscope/data.yaml +93 -0
  76. endoreg_db/data/endoscope_type/data.yaml +11 -0
  77. endoreg_db/data/endoscopy_processor/data.yaml +50 -0
  78. endoreg_db/data/event/cardiology.yaml +15 -0
  79. endoreg_db/data/event/neurology.yaml +14 -0
  80. endoreg_db/data/event/surgery.yaml +13 -0
  81. endoreg_db/data/event/thrombembolism.yaml +20 -0
  82. endoreg_db/data/event_classification/data.yaml +4 -0
  83. endoreg_db/data/event_classification_choice/data.yaml +9 -0
  84. endoreg_db/data/examination/examinations/data.yaml +172 -0
  85. endoreg_db/data/examination/time/data.yaml +48 -0
  86. endoreg_db/data/examination/time-type/data.yaml +5 -0
  87. endoreg_db/data/examination/type/data.yaml +17 -0
  88. endoreg_db/data/examination_indication/endoscopy.yaml +359 -0
  89. endoreg_db/data/examination_indication_classification/endoscopy.yaml +90 -0
  90. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +97 -0
  91. endoreg_db/data/examination_requirement_set/colonoscopy.yaml +15 -0
  92. endoreg_db/data/finding/00_generic.yaml +35 -0
  93. endoreg_db/data/finding/00_generic_complication.yaml +9 -0
  94. endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
  95. endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
  96. endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
  97. endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
  98. endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
  99. endoreg_db/data/finding_classification/00_generic.yaml +44 -0
  100. endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
  101. endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
  102. endoreg_db/data/finding_classification/02_colonoscopy_baseline.yaml +83 -0
  103. endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
  104. endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
  105. endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
  106. endoreg_db/data/finding_classification_choice/00_generic.yaml +15 -0
  107. endoreg_db/data/finding_classification_choice/00_generic_baseline.yaml +23 -0
  108. endoreg_db/data/finding_classification_choice/00_generic_complication.yaml +15 -0
  109. endoreg_db/data/finding_classification_choice/00_generic_histology.yaml +21 -0
  110. endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
  111. endoreg_db/data/finding_classification_choice/02_colonoscopy_bowel_preparation.yaml +49 -0
  112. endoreg_db/data/finding_classification_choice/02_colonoscopy_generic.yaml +19 -0
  113. endoreg_db/data/finding_classification_choice/02_colonoscopy_histology.yaml +20 -0
  114. endoreg_db/data/finding_classification_choice/02_colonoscopy_location.yaml +248 -0
  115. endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
  116. endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
  117. endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_morphology.yaml +75 -0
  118. endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
  119. endoreg_db/data/finding_classification_type/00_generic.yaml +53 -0
  120. endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
  121. endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
  122. endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
  123. endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
  124. endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
  125. endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
  126. endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
  127. endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
  128. endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
  129. endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
  130. endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
  131. endoreg_db/data/finding_type/data.yaml +39 -0
  132. endoreg_db/data/gender/data.yaml +42 -0
  133. endoreg_db/data/information_source/annotation.yaml +6 -0
  134. endoreg_db/data/information_source/data.yaml +30 -0
  135. endoreg_db/data/information_source/endoscopy_guidelines.yaml +7 -0
  136. endoreg_db/data/information_source/medication.yaml +6 -0
  137. endoreg_db/data/information_source/prediction.yaml +7 -0
  138. endoreg_db/data/information_source_type/data.yaml +8 -0
  139. endoreg_db/data/lab_value/cardiac_enzymes.yaml +37 -0
  140. endoreg_db/data/lab_value/coagulation.yaml +54 -0
  141. endoreg_db/data/lab_value/electrolytes.yaml +228 -0
  142. endoreg_db/data/lab_value/gastrointestinal_function.yaml +133 -0
  143. endoreg_db/data/lab_value/hematology.yaml +184 -0
  144. endoreg_db/data/lab_value/hormones.yaml +59 -0
  145. endoreg_db/data/lab_value/lipids.yaml +53 -0
  146. endoreg_db/data/lab_value/misc.yaml +76 -0
  147. endoreg_db/data/lab_value/renal_function.yaml +12 -0
  148. endoreg_db/data/log_type/data.yaml +57 -0
  149. endoreg_db/data/lx_client_tag/base.yaml +54 -0
  150. endoreg_db/data/lx_client_type/base.yaml +30 -0
  151. endoreg_db/data/lx_permission/base.yaml +24 -0
  152. endoreg_db/data/lx_permission/endoreg.yaml +52 -0
  153. endoreg_db/data/material/material.yaml +91 -0
  154. endoreg_db/data/medication/anticoagulation.yaml +65 -0
  155. endoreg_db/data/medication/tah.yaml +70 -0
  156. endoreg_db/data/medication_indication/anticoagulation.yaml +115 -0
  157. endoreg_db/data/medication_indication_type/data.yaml +11 -0
  158. endoreg_db/data/medication_indication_type/thrombembolism.yaml +41 -0
  159. endoreg_db/data/medication_intake_time/base.yaml +31 -0
  160. endoreg_db/data/medication_schedule/apixaban.yaml +95 -0
  161. endoreg_db/data/medication_schedule/ass.yaml +12 -0
  162. endoreg_db/data/medication_schedule/enoxaparin.yaml +26 -0
  163. endoreg_db/data/names_first/first_names.yaml +54 -0
  164. endoreg_db/data/names_last/last_names.yaml +51 -0
  165. endoreg_db/data/network_device/data.yaml +59 -0
  166. endoreg_db/data/network_device_type/data.yaml +12 -0
  167. endoreg_db/data/organ/data.yaml +29 -0
  168. endoreg_db/data/patient_lab_sample_type/generic.yaml +6 -0
  169. endoreg_db/data/pdf_type/data.yaml +46 -0
  170. endoreg_db/data/product/green_endoscopy_dashboard_Product.yaml +66 -0
  171. endoreg_db/data/product_group/green_endoscopy_dashboard_ProductGroup.yaml +33 -0
  172. endoreg_db/data/product_material/green_endoscopy_dashboard_ProductMaterial.yaml +308 -0
  173. endoreg_db/data/product_weight/green_endoscopy_dashboard_ProductWeight.yaml +88 -0
  174. endoreg_db/data/profession/data.yaml +70 -0
  175. endoreg_db/data/qualification/endoscopy.yaml +36 -0
  176. endoreg_db/data/qualification/m2.yaml +39 -0
  177. endoreg_db/data/qualification/outpatient_clinic.yaml +35 -0
  178. endoreg_db/data/qualification/sonography.yaml +36 -0
  179. endoreg_db/data/qualification_type/base.yaml +29 -0
  180. endoreg_db/data/reference_product/green_endoscopy_dashboard_ReferenceProduct.yaml +55 -0
  181. endoreg_db/data/report_reader_flag/rkh-histology-generic.yaml +10 -0
  182. endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +30 -0
  183. endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +24 -0
  184. endoreg_db/data/requirement/01_patient_data.yaml +93 -0
  185. endoreg_db/data/requirement/old/colon_polyp_intervention.yaml +49 -0
  186. endoreg_db/data/requirement/old/colonoscopy_baseline_austria.yaml +45 -0
  187. endoreg_db/data/requirement/old/coloreg_colon_polyp.yaml +49 -0
  188. endoreg_db/data/requirement/old/disease_cardiovascular.yaml +79 -0
  189. endoreg_db/data/requirement/old/disease_classification_choice_cardiovascular.yaml +41 -0
  190. endoreg_db/data/requirement/old/disease_hepatology.yaml +12 -0
  191. endoreg_db/data/requirement/old/disease_misc.yaml +12 -0
  192. endoreg_db/data/requirement/old/disease_renal.yaml +96 -0
  193. endoreg_db/data/requirement/old/endoscopy_bleeding_risk.yaml +59 -0
  194. endoreg_db/data/requirement/old/event_cardiology.yaml +251 -0
  195. endoreg_db/data/requirement/old/event_requirements.yaml +145 -0
  196. endoreg_db/data/requirement/old/finding_colon_polyp.yaml +50 -0
  197. endoreg_db/data/requirement/old/gender.yaml +0 -0
  198. endoreg_db/data/requirement/old/lab_value.yaml +441 -0
  199. endoreg_db/data/requirement/old/medication.yaml +93 -0
  200. endoreg_db/data/requirement_operator/_old/age.yaml +13 -0
  201. endoreg_db/data/requirement_operator/_old/lab_operators.yaml +129 -0
  202. endoreg_db/data/requirement_operator/_old/model_operators.yaml +96 -0
  203. endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
  204. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +65 -0
  205. endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
  206. endoreg_db/data/requirement_set/02_endoscopy_bleeding_risk.yaml +46 -0
  207. endoreg_db/data/requirement_set/90_coloreg.yaml +190 -0
  208. endoreg_db/data/requirement_set/_old_ +109 -0
  209. endoreg_db/data/requirement_set/colonoscopy_austria_screening.yaml +57 -0
  210. endoreg_db/data/requirement_set_type/data.yaml +41 -0
  211. endoreg_db/data/requirement_type/requirement_types.yaml +165 -0
  212. endoreg_db/data/resource/green_endoscopy_dashboard_Resource.yaml +15 -0
  213. endoreg_db/data/risk/bleeding.yaml +26 -0
  214. endoreg_db/data/risk/thrombosis.yaml +37 -0
  215. endoreg_db/data/risk_type/data.yaml +27 -0
  216. endoreg_db/data/setup_config.yaml +38 -0
  217. endoreg_db/data/shift/endoscopy.yaml +21 -0
  218. endoreg_db/data/shift/m2.yaml +0 -0
  219. endoreg_db/data/shift_type/base.yaml +35 -0
  220. endoreg_db/data/tag/requirement_set_tags.yaml +32 -0
  221. endoreg_db/data/tmp/chronic_kidney_disease.yaml +0 -0
  222. endoreg_db/data/tmp/congestive_heart_failure.yaml +0 -0
  223. endoreg_db/data/transport_route/green_endoscopy_dashboard_TransportRoute.yaml +12 -0
  224. endoreg_db/data/unit/concentration.yaml +115 -0
  225. endoreg_db/data/unit/data.yaml +17 -0
  226. endoreg_db/data/unit/length.yaml +31 -0
  227. endoreg_db/data/unit/misc.yaml +20 -0
  228. endoreg_db/data/unit/rate.yaml +6 -0
  229. endoreg_db/data/unit/time.yaml +48 -0
  230. endoreg_db/data/unit/volume.yaml +35 -0
  231. endoreg_db/data/unit/weight.yaml +38 -0
  232. endoreg_db/data/waste/data.yaml +12 -0
  233. endoreg_db/exceptions.py +24 -0
  234. endoreg_db/export/frames/export.py +6 -0
  235. endoreg_db/export/frames/export_frames_with_labels.py +616 -0
  236. endoreg_db/factories/__init__.py +0 -0
  237. endoreg_db/forms/__init__.py +4 -0
  238. endoreg_db/forms/examination_form.py +12 -0
  239. endoreg_db/forms/patient_finding_intervention_form.py +40 -0
  240. endoreg_db/forms/patient_form.py +23 -0
  241. endoreg_db/forms/questionnaires/__init__.py +1 -0
  242. endoreg_db/forms/questionnaires/tto_questionnaire.py +23 -0
  243. endoreg_db/forms/settings/__init__.py +11 -0
  244. endoreg_db/forms/unit.py +7 -0
  245. endoreg_db/helpers/__init__.py +0 -0
  246. endoreg_db/helpers/count_db.py +48 -0
  247. endoreg_db/helpers/data_loader.py +280 -0
  248. endoreg_db/helpers/default_objects.py +414 -0
  249. endoreg_db/helpers/download_segmentation_model.py +32 -0
  250. endoreg_db/helpers/interact.py +1 -0
  251. endoreg_db/helpers/test_video_helper.py +127 -0
  252. endoreg_db/import_files/__init__.py +27 -0
  253. endoreg_db/import_files/context/__init__.py +7 -0
  254. endoreg_db/import_files/context/default_sensitive_meta.py +83 -0
  255. endoreg_db/import_files/context/ensure_center.py +17 -0
  256. endoreg_db/import_files/context/file_lock.py +66 -0
  257. endoreg_db/import_files/context/import_context.py +42 -0
  258. endoreg_db/import_files/context/validate_directories.py +57 -0
  259. endoreg_db/import_files/file_storage/__init__.py +15 -0
  260. endoreg_db/import_files/file_storage/create_report_file.py +99 -0
  261. endoreg_db/import_files/file_storage/create_video_file.py +104 -0
  262. endoreg_db/import_files/file_storage/sensitive_meta_storage.py +42 -0
  263. endoreg_db/import_files/file_storage/state_management.py +463 -0
  264. endoreg_db/import_files/file_storage/storage.py +42 -0
  265. endoreg_db/import_files/import_service.md +26 -0
  266. endoreg_db/import_files/processing/__init__.py +11 -0
  267. endoreg_db/import_files/processing/report_processing/report_anonymization.py +99 -0
  268. endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
  269. endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
  270. endoreg_db/import_files/pseudonymization/__init__.py +0 -0
  271. endoreg_db/import_files/pseudonymization/fake.py +52 -0
  272. endoreg_db/import_files/pseudonymization/k_anonymity.py +181 -0
  273. endoreg_db/import_files/pseudonymization/k_pseudonymity.py +139 -0
  274. endoreg_db/import_files/pseudonymization/pseudonymize.py +0 -0
  275. endoreg_db/import_files/report_import_service.py +147 -0
  276. endoreg_db/import_files/video_import_service.py +154 -0
  277. endoreg_db/logger_conf.py +156 -0
  278. endoreg_db/management/__init__.py +1 -0
  279. endoreg_db/management/commands/__init__.py +1 -0
  280. endoreg_db/management/commands/anonymize_video.py +0 -0
  281. endoreg_db/management/commands/check_auth.py +132 -0
  282. endoreg_db/management/commands/create_model_meta_from_huggingface.py +177 -0
  283. endoreg_db/management/commands/create_multilabel_model_meta.py +419 -0
  284. endoreg_db/management/commands/export_frame_annot.py +196 -0
  285. endoreg_db/management/commands/fix_missing_patient_data.py +206 -0
  286. endoreg_db/management/commands/fix_video_paths.py +186 -0
  287. endoreg_db/management/commands/import_report.py +361 -0
  288. endoreg_db/management/commands/list_routes.py +20 -0
  289. endoreg_db/management/commands/load_ai_model_data.py +83 -0
  290. endoreg_db/management/commands/load_ai_model_label_data.py +60 -0
  291. endoreg_db/management/commands/load_base_db_data.py +63 -0
  292. endoreg_db/management/commands/load_center_data.py +68 -0
  293. endoreg_db/management/commands/load_contraindication_data.py +39 -0
  294. endoreg_db/management/commands/load_disease_classification_choices_data.py +38 -0
  295. endoreg_db/management/commands/load_disease_classification_data.py +38 -0
  296. endoreg_db/management/commands/load_disease_data.py +59 -0
  297. endoreg_db/management/commands/load_distribution_data.py +63 -0
  298. endoreg_db/management/commands/load_endoscope_data.py +58 -0
  299. endoreg_db/management/commands/load_event_data.py +39 -0
  300. endoreg_db/management/commands/load_examination_data.py +78 -0
  301. endoreg_db/management/commands/load_examination_indication_data.py +85 -0
  302. endoreg_db/management/commands/load_finding_data.py +115 -0
  303. endoreg_db/management/commands/load_gender_data.py +37 -0
  304. endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +142 -0
  305. endoreg_db/management/commands/load_information_source.py +46 -0
  306. endoreg_db/management/commands/load_lab_value_data.py +52 -0
  307. endoreg_db/management/commands/load_legacy_data.py +303 -0
  308. endoreg_db/management/commands/load_medication_data.py +104 -0
  309. endoreg_db/management/commands/load_name_data.py +36 -0
  310. endoreg_db/management/commands/load_organ_data.py +39 -0
  311. endoreg_db/management/commands/load_pdf_type_data.py +58 -0
  312. endoreg_db/management/commands/load_profession_data.py +40 -0
  313. endoreg_db/management/commands/load_qualification_data.py +56 -0
  314. endoreg_db/management/commands/load_report_reader_flag_data.py +40 -0
  315. endoreg_db/management/commands/load_requirement_data.py +207 -0
  316. endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
  317. endoreg_db/management/commands/load_risk_data.py +57 -0
  318. endoreg_db/management/commands/load_shift_data.py +57 -0
  319. endoreg_db/management/commands/load_tag_data.py +54 -0
  320. endoreg_db/management/commands/load_unit_data.py +40 -0
  321. endoreg_db/management/commands/load_user_groups.py +26 -0
  322. endoreg_db/management/commands/model_input.py +169 -0
  323. endoreg_db/management/commands/register_ai_model.py +70 -0
  324. endoreg_db/management/commands/setup_endoreg_db.py +459 -0
  325. endoreg_db/management/commands/start_filewatcher.py +115 -0
  326. endoreg_db/management/commands/storage_management.py +622 -0
  327. endoreg_db/management/commands/summarize_db_content.py +280 -0
  328. endoreg_db/management/commands/train_image_multilabel_model.py +144 -0
  329. endoreg_db/management/commands/validate_video_files.py +189 -0
  330. endoreg_db/management/commands/video_validation.py +20 -0
  331. endoreg_db/mermaid/Overall_flow_patient_finding_intervention.md +10 -0
  332. endoreg_db/mermaid/anonymized_image_annotation.md +20 -0
  333. endoreg_db/mermaid/binary_classification_annotation.md +50 -0
  334. endoreg_db/mermaid/classification.md +8 -0
  335. endoreg_db/mermaid/examination.md +8 -0
  336. endoreg_db/mermaid/findings.md +7 -0
  337. endoreg_db/mermaid/image_classification.md +28 -0
  338. endoreg_db/mermaid/interventions.md +8 -0
  339. endoreg_db/mermaid/morphology.md +8 -0
  340. endoreg_db/mermaid/patient_creation.md +14 -0
  341. endoreg_db/mermaid/video_segmentation_annotation.md +17 -0
  342. endoreg_db/migrations/0001_initial.py +1953 -0
  343. endoreg_db/migrations/__init__.py +0 -0
  344. endoreg_db/models/__init__.py +322 -0
  345. endoreg_db/models/administration/__init__.py +95 -0
  346. endoreg_db/models/administration/ai/__init__.py +9 -0
  347. endoreg_db/models/administration/ai/active_model.py +35 -0
  348. endoreg_db/models/administration/ai/ai_model.py +180 -0
  349. endoreg_db/models/administration/ai/model_type.py +42 -0
  350. endoreg_db/models/administration/case/__init__.py +5 -0
  351. endoreg_db/models/administration/case/case.py +114 -0
  352. endoreg_db/models/administration/case/case_template/__init__.py +3 -0
  353. endoreg_db/models/administration/case/case_template/case_template.py +3 -0
  354. endoreg_db/models/administration/case/case_template/case_template_rule.py +3 -0
  355. endoreg_db/models/administration/case/case_template/case_template_rule_value.py +3 -0
  356. endoreg_db/models/administration/case/case_template/case_template_type.py +3 -0
  357. endoreg_db/models/administration/center/__init__.py +13 -0
  358. endoreg_db/models/administration/center/center.py +85 -0
  359. endoreg_db/models/administration/center/center_product.py +67 -0
  360. endoreg_db/models/administration/center/center_resource.py +69 -0
  361. endoreg_db/models/administration/center/center_shift.py +94 -0
  362. endoreg_db/models/administration/center/center_waste.py +42 -0
  363. endoreg_db/models/administration/person/__init__.py +26 -0
  364. endoreg_db/models/administration/person/employee/__init__.py +3 -0
  365. endoreg_db/models/administration/person/employee/employee.py +40 -0
  366. endoreg_db/models/administration/person/employee/employee_qualification.py +44 -0
  367. endoreg_db/models/administration/person/employee/employee_type.py +50 -0
  368. endoreg_db/models/administration/person/examiner/__init__.py +4 -0
  369. endoreg_db/models/administration/person/examiner/examiner.py +64 -0
  370. endoreg_db/models/administration/person/names/__init__.py +0 -0
  371. endoreg_db/models/administration/person/names/first_name.py +20 -0
  372. endoreg_db/models/administration/person/names/last_name.py +20 -0
  373. endoreg_db/models/administration/person/patient/__init__.py +7 -0
  374. endoreg_db/models/administration/person/patient/patient.py +488 -0
  375. endoreg_db/models/administration/person/patient/patient_external_id.py +36 -0
  376. endoreg_db/models/administration/person/person.py +35 -0
  377. endoreg_db/models/administration/person/profession/__init__.py +28 -0
  378. endoreg_db/models/administration/person/user/__init__.py +5 -0
  379. endoreg_db/models/administration/person/user/portal_user_information.py +41 -0
  380. endoreg_db/models/administration/product/__init__.py +15 -0
  381. endoreg_db/models/administration/product/product.py +106 -0
  382. endoreg_db/models/administration/product/product_group.py +41 -0
  383. endoreg_db/models/administration/product/product_material.py +60 -0
  384. endoreg_db/models/administration/product/product_weight.py +51 -0
  385. endoreg_db/models/administration/product/reference_product.py +147 -0
  386. endoreg_db/models/administration/qualification/__init__.py +7 -0
  387. endoreg_db/models/administration/qualification/qualification.py +43 -0
  388. endoreg_db/models/administration/qualification/qualification_type.py +39 -0
  389. endoreg_db/models/administration/shift/__init__.py +9 -0
  390. endoreg_db/models/administration/shift/scheduled_days.py +72 -0
  391. endoreg_db/models/administration/shift/shift.py +57 -0
  392. endoreg_db/models/administration/shift/shift_type.py +108 -0
  393. endoreg_db/models/aidataset/__init__.py +5 -0
  394. endoreg_db/models/aidataset/aidataset.py +193 -0
  395. endoreg_db/models/label/__init__.py +23 -0
  396. endoreg_db/models/label/annotation/__init__.py +12 -0
  397. endoreg_db/models/label/annotation/image_classification.py +85 -0
  398. endoreg_db/models/label/annotation/video_segmentation_annotation.py +61 -0
  399. endoreg_db/models/label/label.py +91 -0
  400. endoreg_db/models/label/label_set.py +68 -0
  401. endoreg_db/models/label/label_type.py +29 -0
  402. endoreg_db/models/label/label_video_segment/__init__.py +3 -0
  403. endoreg_db/models/label/label_video_segment/_create_from_video.py +42 -0
  404. endoreg_db/models/label/label_video_segment/label_video_segment.py +611 -0
  405. endoreg_db/models/label/video_segmentation_label.py +35 -0
  406. endoreg_db/models/label/video_segmentation_labelset.py +28 -0
  407. endoreg_db/models/media/__init__.py +23 -0
  408. endoreg_db/models/media/frame/__init__.py +3 -0
  409. endoreg_db/models/media/frame/frame.py +137 -0
  410. endoreg_db/models/media/pdf/__init__.py +12 -0
  411. endoreg_db/models/media/pdf/raw_pdf.py +764 -0
  412. endoreg_db/models/media/pdf/report_file.py +162 -0
  413. endoreg_db/models/media/pdf/report_reader/__init__.py +7 -0
  414. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +85 -0
  415. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +46 -0
  416. endoreg_db/models/media/video/__init__.py +9 -0
  417. endoreg_db/models/media/video/create_from_file.py +402 -0
  418. endoreg_db/models/media/video/pipe_1.py +258 -0
  419. endoreg_db/models/media/video/pipe_2.py +129 -0
  420. endoreg_db/models/media/video/video_file.py +907 -0
  421. endoreg_db/models/media/video/video_file_ai.py +828 -0
  422. endoreg_db/models/media/video/video_file_anonymize.py +524 -0
  423. endoreg_db/models/media/video/video_file_frames/__init__.py +49 -0
  424. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +25 -0
  425. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +23 -0
  426. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +126 -0
  427. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +233 -0
  428. endoreg_db/models/media/video/video_file_frames/_get_frame.py +36 -0
  429. endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +13 -0
  430. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +24 -0
  431. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +40 -0
  432. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +44 -0
  433. endoreg_db/models/media/video/video_file_frames/_get_frames.py +30 -0
  434. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +205 -0
  435. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +228 -0
  436. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +107 -0
  437. endoreg_db/models/media/video/video_file_io.py +272 -0
  438. endoreg_db/models/media/video/video_file_meta/__init__.py +22 -0
  439. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +58 -0
  440. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +62 -0
  441. endoreg_db/models/media/video/video_file_meta/get_fps.py +183 -0
  442. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +198 -0
  443. endoreg_db/models/media/video/video_file_meta/text_meta.py +178 -0
  444. endoreg_db/models/media/video/video_file_meta/video_meta.py +105 -0
  445. endoreg_db/models/media/video/video_file_segments.py +317 -0
  446. endoreg_db/models/media/video/video_metadata.py +67 -0
  447. endoreg_db/models/media/video/video_processing.py +192 -0
  448. endoreg_db/models/medical/__init__.py +136 -0
  449. endoreg_db/models/medical/contraindication/README.md +1 -0
  450. endoreg_db/models/medical/contraindication/__init__.py +29 -0
  451. endoreg_db/models/medical/disease.py +174 -0
  452. endoreg_db/models/medical/event.py +154 -0
  453. endoreg_db/models/medical/examination/__init__.py +20 -0
  454. endoreg_db/models/medical/examination/examination.py +183 -0
  455. endoreg_db/models/medical/examination/examination_indication.py +229 -0
  456. endoreg_db/models/medical/examination/examination_time.py +68 -0
  457. endoreg_db/models/medical/examination/examination_time_type.py +44 -0
  458. endoreg_db/models/medical/examination/examination_type.py +47 -0
  459. endoreg_db/models/medical/finding/__init__.py +20 -0
  460. endoreg_db/models/medical/finding/finding.py +113 -0
  461. endoreg_db/models/medical/finding/finding_classification.py +131 -0
  462. endoreg_db/models/medical/finding/finding_intervention.py +68 -0
  463. endoreg_db/models/medical/finding/finding_type.py +38 -0
  464. endoreg_db/models/medical/hardware/__init__.py +8 -0
  465. endoreg_db/models/medical/hardware/endoscope.py +77 -0
  466. endoreg_db/models/medical/hardware/endoscopy_processor.py +182 -0
  467. endoreg_db/models/medical/laboratory/__init__.py +5 -0
  468. endoreg_db/models/medical/laboratory/lab_value.py +490 -0
  469. endoreg_db/models/medical/medication/__init__.py +23 -0
  470. endoreg_db/models/medical/medication/medication.py +45 -0
  471. endoreg_db/models/medical/medication/medication_indication.py +78 -0
  472. endoreg_db/models/medical/medication/medication_indication_type.py +58 -0
  473. endoreg_db/models/medical/medication/medication_intake_time.py +58 -0
  474. endoreg_db/models/medical/medication/medication_schedule.py +58 -0
  475. endoreg_db/models/medical/organ/__init__.py +38 -0
  476. endoreg_db/models/medical/patient/__init__.py +48 -0
  477. endoreg_db/models/medical/patient/medication_examples.py +56 -0
  478. endoreg_db/models/medical/patient/patient_disease.py +72 -0
  479. endoreg_db/models/medical/patient/patient_event.py +80 -0
  480. endoreg_db/models/medical/patient/patient_examination.py +280 -0
  481. endoreg_db/models/medical/patient/patient_examination_indication.py +57 -0
  482. endoreg_db/models/medical/patient/patient_finding.py +416 -0
  483. endoreg_db/models/medical/patient/patient_finding_classification.py +231 -0
  484. endoreg_db/models/medical/patient/patient_finding_intervention.py +37 -0
  485. endoreg_db/models/medical/patient/patient_lab_sample.py +157 -0
  486. endoreg_db/models/medical/patient/patient_lab_value.py +247 -0
  487. endoreg_db/models/medical/patient/patient_medication.py +111 -0
  488. endoreg_db/models/medical/patient/patient_medication_schedule.py +152 -0
  489. endoreg_db/models/medical/risk/__init__.py +7 -0
  490. endoreg_db/models/medical/risk/risk.py +73 -0
  491. endoreg_db/models/medical/risk/risk_type.py +54 -0
  492. endoreg_db/models/metadata/__init__.py +19 -0
  493. endoreg_db/models/metadata/model_meta.py +266 -0
  494. endoreg_db/models/metadata/model_meta_logic.py +485 -0
  495. endoreg_db/models/metadata/pdf_meta.py +96 -0
  496. endoreg_db/models/metadata/sensitive_meta.py +345 -0
  497. endoreg_db/models/metadata/sensitive_meta_logic.py +1161 -0
  498. endoreg_db/models/metadata/video_meta.py +459 -0
  499. endoreg_db/models/metadata/video_prediction_logic.py +232 -0
  500. endoreg_db/models/metadata/video_prediction_meta.py +319 -0
  501. endoreg_db/models/operation_log.py +63 -0
  502. endoreg_db/models/other/__init__.py +40 -0
  503. endoreg_db/models/other/distribution/__init__.py +46 -0
  504. endoreg_db/models/other/distribution/base_value_distribution.py +22 -0
  505. endoreg_db/models/other/distribution/date_value_distribution.py +163 -0
  506. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +50 -0
  507. endoreg_db/models/other/distribution/numeric_value_distribution.py +211 -0
  508. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +23 -0
  509. endoreg_db/models/other/emission/__init__.py +5 -0
  510. endoreg_db/models/other/emission/emission_factor.py +110 -0
  511. endoreg_db/models/other/gender.py +32 -0
  512. endoreg_db/models/other/information_source.py +190 -0
  513. endoreg_db/models/other/material.py +34 -0
  514. endoreg_db/models/other/resource.py +24 -0
  515. endoreg_db/models/other/tag.py +32 -0
  516. endoreg_db/models/other/transport_route.py +40 -0
  517. endoreg_db/models/other/unit.py +40 -0
  518. endoreg_db/models/other/waste.py +28 -0
  519. endoreg_db/models/report/__init__.py +0 -0
  520. endoreg_db/models/report/images.py +0 -0
  521. endoreg_db/models/report/report.py +5 -0
  522. endoreg_db/models/requirement/__init__.py +11 -0
  523. endoreg_db/models/requirement/requirement.py +792 -0
  524. endoreg_db/models/requirement/requirement_error.py +84 -0
  525. endoreg_db/models/requirement/requirement_evaluation/__init__.py +6 -0
  526. endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
  527. endoreg_db/models/requirement/requirement_evaluation/get_values.py +40 -0
  528. endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +6 -0
  529. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +137 -0
  530. endoreg_db/models/requirement/requirement_operator.py +187 -0
  531. endoreg_db/models/requirement/requirement_set.py +327 -0
  532. endoreg_db/models/state/__init__.py +13 -0
  533. endoreg_db/models/state/abstract.py +11 -0
  534. endoreg_db/models/state/anonymization.py +30 -0
  535. endoreg_db/models/state/audit_ledger.py +155 -0
  536. endoreg_db/models/state/label_video_segment.py +31 -0
  537. endoreg_db/models/state/processing_history/__init__.py +3 -0
  538. endoreg_db/models/state/processing_history/processing_history.py +136 -0
  539. endoreg_db/models/state/raw_pdf.py +219 -0
  540. endoreg_db/models/state/sensitive_meta.py +50 -0
  541. endoreg_db/models/state/video.py +251 -0
  542. endoreg_db/models/upload_job.py +100 -0
  543. endoreg_db/models/utils.py +138 -0
  544. endoreg_db/queries/__init__.py +3 -0
  545. endoreg_db/queries/annotations/__init__.py +1 -0
  546. endoreg_db/queries/annotations/legacy.py +169 -0
  547. endoreg_db/queries/sanity/__init_.py +0 -0
  548. endoreg_db/root_urls.py +27 -0
  549. endoreg_db/schemas/__init__.py +0 -0
  550. endoreg_db/schemas/examination_evaluation.py +30 -0
  551. endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +861 -0
  552. endoreg_db/serializers/__init__.py +104 -0
  553. endoreg_db/serializers/administration/__init__.py +13 -0
  554. endoreg_db/serializers/administration/ai/__init__.py +9 -0
  555. endoreg_db/serializers/administration/ai/active_model.py +12 -0
  556. endoreg_db/serializers/administration/ai/ai_model.py +20 -0
  557. endoreg_db/serializers/administration/ai/model_type.py +12 -0
  558. endoreg_db/serializers/administration/center.py +14 -0
  559. endoreg_db/serializers/administration/gender.py +11 -0
  560. endoreg_db/serializers/anonymization.py +77 -0
  561. endoreg_db/serializers/evaluation/examination_evaluation.py +0 -0
  562. endoreg_db/serializers/examination/__init__.py +10 -0
  563. endoreg_db/serializers/examination/base.py +45 -0
  564. endoreg_db/serializers/examination/dropdown.py +20 -0
  565. endoreg_db/serializers/examination_serializer.py +9 -0
  566. endoreg_db/serializers/finding/__init__.py +5 -0
  567. endoreg_db/serializers/finding/finding.py +61 -0
  568. endoreg_db/serializers/finding_classification/__init__.py +7 -0
  569. endoreg_db/serializers/finding_classification/choice.py +19 -0
  570. endoreg_db/serializers/finding_classification/classification.py +11 -0
  571. endoreg_db/serializers/label_video_segment/__init__.py +9 -0
  572. endoreg_db/serializers/label_video_segment/image_classification_annotation.py +62 -0
  573. endoreg_db/serializers/label_video_segment/label/__init__.py +6 -0
  574. endoreg_db/serializers/label_video_segment/label/label.py +15 -0
  575. endoreg_db/serializers/label_video_segment/label_video_segment.py +427 -0
  576. endoreg_db/serializers/meta/__init__.py +13 -0
  577. endoreg_db/serializers/meta/sensitive_meta_detail.py +122 -0
  578. endoreg_db/serializers/meta/sensitive_meta_update.py +153 -0
  579. endoreg_db/serializers/meta/sensitive_meta_verification.py +62 -0
  580. endoreg_db/serializers/meta/video_meta.py +39 -0
  581. endoreg_db/serializers/misc/__init__.py +14 -0
  582. endoreg_db/serializers/misc/file_overview.py +72 -0
  583. endoreg_db/serializers/misc/sensitive_patient_data.py +144 -0
  584. endoreg_db/serializers/misc/stats.py +35 -0
  585. endoreg_db/serializers/misc/translatable_field_mix_in.py +44 -0
  586. endoreg_db/serializers/misc/upload_job.py +74 -0
  587. endoreg_db/serializers/patient/__init__.py +12 -0
  588. endoreg_db/serializers/patient/patient.py +103 -0
  589. endoreg_db/serializers/patient/patient_dropdown.py +35 -0
  590. endoreg_db/serializers/patient_examination/__init__.py +7 -0
  591. endoreg_db/serializers/patient_examination/patient_examination.py +168 -0
  592. endoreg_db/serializers/patient_finding/__init__.py +15 -0
  593. endoreg_db/serializers/patient_finding/patient_finding.py +32 -0
  594. endoreg_db/serializers/patient_finding/patient_finding_classification.py +47 -0
  595. endoreg_db/serializers/patient_finding/patient_finding_detail.py +62 -0
  596. endoreg_db/serializers/patient_finding/patient_finding_intervention.py +28 -0
  597. endoreg_db/serializers/patient_finding/patient_finding_list.py +40 -0
  598. endoreg_db/serializers/patient_finding/patient_finding_write.py +135 -0
  599. endoreg_db/serializers/pdf/__init__.py +3 -0
  600. endoreg_db/serializers/pdf/anony_text_validation.py +101 -0
  601. endoreg_db/serializers/requirements/requirement_schema.py +20 -0
  602. endoreg_db/serializers/requirements/requirement_sets.py +99 -0
  603. endoreg_db/serializers/sensitive_meta_serializer.py +301 -0
  604. endoreg_db/serializers/video/__init__.py +7 -0
  605. endoreg_db/serializers/video/video_file.py +283 -0
  606. endoreg_db/serializers/video/video_file_brief.py +14 -0
  607. endoreg_db/serializers/video/video_file_detail.py +96 -0
  608. endoreg_db/serializers/video/video_file_list.py +100 -0
  609. endoreg_db/serializers/video/video_processing_history.py +172 -0
  610. endoreg_db/serializers/video_examination.py +198 -0
  611. endoreg_db/services/__init__.py +5 -0
  612. endoreg_db/services/anonymization.py +274 -0
  613. endoreg_db/services/examination_evaluation.py +172 -0
  614. endoreg_db/services/finding_description_service.py +0 -0
  615. endoreg_db/services/lookup_service.py +424 -0
  616. endoreg_db/services/lookup_store.py +266 -0
  617. endoreg_db/services/model_meta_from_hf.py +76 -0
  618. endoreg_db/services/pdf_import.py +0 -0
  619. endoreg_db/services/polling_coordinator.py +319 -0
  620. endoreg_db/services/pseudonym_service.py +94 -0
  621. endoreg_db/services/report_import.py +13 -0
  622. endoreg_db/services/segment_sync.py +171 -0
  623. endoreg_db/services/video_import.py +9 -0
  624. endoreg_db/templates/admin/patient_finding_intervention.html +253 -0
  625. endoreg_db/templates/admin/start_examination.html +12 -0
  626. endoreg_db/templates/timeline.html +176 -0
  627. endoreg_db/urls/__init__.py +56 -0
  628. endoreg_db/urls/ai.py +14 -0
  629. endoreg_db/urls/anonymization.py +78 -0
  630. endoreg_db/urls/auth.py +16 -0
  631. endoreg_db/urls/classification.py +34 -0
  632. endoreg_db/urls/examination.py +63 -0
  633. endoreg_db/urls/media.py +251 -0
  634. endoreg_db/urls/patient.py +23 -0
  635. endoreg_db/urls/requirements.py +15 -0
  636. endoreg_db/urls/root_urls.py +28 -0
  637. endoreg_db/urls/stats.py +54 -0
  638. endoreg_db/urls/upload.py +12 -0
  639. endoreg_db/urls.py +9 -0
  640. endoreg_db/utils/__init__.py +97 -0
  641. endoreg_db/utils/ai/__init__.py +9 -0
  642. endoreg_db/utils/ai/data_loader_for_model_input.py +262 -0
  643. endoreg_db/utils/ai/data_loader_for_model_training.py +262 -0
  644. endoreg_db/utils/ai/get.py +6 -0
  645. endoreg_db/utils/ai/inference_dataset.py +51 -0
  646. endoreg_db/utils/ai/model_training/config.py +117 -0
  647. endoreg_db/utils/ai/model_training/dataset.py +74 -0
  648. endoreg_db/utils/ai/model_training/losses.py +68 -0
  649. endoreg_db/utils/ai/model_training/metrics.py +78 -0
  650. endoreg_db/utils/ai/model_training/model_backbones.py +155 -0
  651. endoreg_db/utils/ai/model_training/model_gastronet_resnet.py +118 -0
  652. endoreg_db/utils/ai/model_training/trainer_gastronet_multilabel.py +771 -0
  653. endoreg_db/utils/ai/multilabel_classification_net.py +270 -0
  654. endoreg_db/utils/ai/postprocess.py +63 -0
  655. endoreg_db/utils/ai/predict.py +293 -0
  656. endoreg_db/utils/ai/preprocess.py +76 -0
  657. endoreg_db/utils/calc_duration_seconds.py +24 -0
  658. endoreg_db/utils/case_generator/__init__.py +3 -0
  659. endoreg_db/utils/case_generator/lab_sample_factory.py +32 -0
  660. endoreg_db/utils/check_video_files.py +175 -0
  661. endoreg_db/utils/cropping.py +30 -0
  662. endoreg_db/utils/dataloader.py +285 -0
  663. endoreg_db/utils/dates.py +59 -0
  664. endoreg_db/utils/defaults/set_default_center.py +33 -0
  665. endoreg_db/utils/env.py +37 -0
  666. endoreg_db/utils/extract_specific_frames.py +87 -0
  667. endoreg_db/utils/file_operations.py +70 -0
  668. endoreg_db/utils/fix_video_path_direct.py +157 -0
  669. endoreg_db/utils/frame_anonymization_utils.py +463 -0
  670. endoreg_db/utils/hashs.py +138 -0
  671. endoreg_db/utils/links/__init__.py +0 -0
  672. endoreg_db/utils/links/requirement_link.py +237 -0
  673. endoreg_db/utils/mime_types.py +0 -0
  674. endoreg_db/utils/names.py +82 -0
  675. endoreg_db/utils/ocr.py +195 -0
  676. endoreg_db/utils/operation_log.py +87 -0
  677. endoreg_db/utils/parse_and_generate_yaml.py +45 -0
  678. endoreg_db/utils/paths.py +159 -0
  679. endoreg_db/utils/permissions.py +160 -0
  680. endoreg_db/utils/pipelines/Readme.md +235 -0
  681. endoreg_db/utils/pipelines/__init__.py +0 -0
  682. endoreg_db/utils/pipelines/process_video_dir.py +144 -0
  683. endoreg_db/utils/product/__init__.py +0 -0
  684. endoreg_db/utils/product/sum_emissions.py +22 -0
  685. endoreg_db/utils/product/sum_weights.py +20 -0
  686. endoreg_db/utils/pydantic_models/__init__.py +5 -0
  687. endoreg_db/utils/pydantic_models/db_config.py +57 -0
  688. endoreg_db/utils/requirement_helpers.py +0 -0
  689. endoreg_db/utils/requirement_operator_logic/__init__.py +0 -0
  690. endoreg_db/utils/requirement_operator_logic/_old/lab_value_operators.py +678 -0
  691. endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +842 -0
  692. endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +114 -0
  693. endoreg_db/utils/setup_config.py +196 -0
  694. endoreg_db/utils/storage.py +117 -0
  695. endoreg_db/utils/translation.py +31 -0
  696. endoreg_db/utils/uuid.py +5 -0
  697. endoreg_db/utils/validate_endo_roi.py +33 -0
  698. endoreg_db/utils/validate_subcategory_dict.py +93 -0
  699. endoreg_db/utils/validate_video_detailed.py +415 -0
  700. endoreg_db/utils/video/__init__.py +30 -0
  701. endoreg_db/utils/video/extract_frames.py +100 -0
  702. endoreg_db/utils/video/ffmpeg_wrapper.py +996 -0
  703. endoreg_db/utils/video/names.py +47 -0
  704. endoreg_db/utils/video/streaming_processor.py +386 -0
  705. endoreg_db/utils/video/video_splitter.py +105 -0
  706. endoreg_db/versioning.md +79 -0
  707. endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +247 -0
  708. endoreg_db/views/__init__.py +157 -0
  709. endoreg_db/views/anonymization/__init__.py +31 -0
  710. endoreg_db/views/anonymization/media_management.py +486 -0
  711. endoreg_db/views/anonymization/overview.py +307 -0
  712. endoreg_db/views/anonymization/validate.py +310 -0
  713. endoreg_db/views/auth/__init__.py +13 -0
  714. endoreg_db/views/auth/keycloak.py +146 -0
  715. endoreg_db/views/examination/__init__.py +30 -0
  716. endoreg_db/views/examination/examination.py +37 -0
  717. endoreg_db/views/examination/examination_manifest_cache.py +26 -0
  718. endoreg_db/views/examination/get_finding_classification_choices.py +62 -0
  719. endoreg_db/views/examination/get_finding_classifications.py +38 -0
  720. endoreg_db/views/examination/get_findings.py +39 -0
  721. endoreg_db/views/examination/get_instruments.py +19 -0
  722. endoreg_db/views/examination/get_interventions.py +14 -0
  723. endoreg_db/views/finding/__init__.py +9 -0
  724. endoreg_db/views/finding/finding.py +116 -0
  725. endoreg_db/views/finding/get_classifications.py +14 -0
  726. endoreg_db/views/finding/get_interventions.py +17 -0
  727. endoreg_db/views/finding_classification/__init__.py +13 -0
  728. endoreg_db/views/finding_classification/base.py +0 -0
  729. endoreg_db/views/finding_classification/finding_classification.py +41 -0
  730. endoreg_db/views/finding_classification/get_classification_choices.py +54 -0
  731. endoreg_db/views/media/__init__.py +32 -0
  732. endoreg_db/views/media/pdf_media.py +411 -0
  733. endoreg_db/views/media/sensitive_metadata.py +372 -0
  734. endoreg_db/views/media/video_media.py +275 -0
  735. endoreg_db/views/meta/__init__.py +7 -0
  736. endoreg_db/views/meta/sensitive_meta_list.py +102 -0
  737. endoreg_db/views/meta/sensitive_meta_verification.py +74 -0
  738. endoreg_db/views/misc/__init__.py +29 -0
  739. endoreg_db/views/misc/center.py +14 -0
  740. endoreg_db/views/misc/csrf.py +8 -0
  741. endoreg_db/views/misc/gender.py +15 -0
  742. endoreg_db/views/misc/stats.py +255 -0
  743. endoreg_db/views/misc/upload_views.py +241 -0
  744. endoreg_db/views/patient/__init__.py +3 -0
  745. endoreg_db/views/patient/patient.py +253 -0
  746. endoreg_db/views/patient_examination/__init__.py +11 -0
  747. endoreg_db/views/patient_examination/patient_examination.py +141 -0
  748. endoreg_db/views/patient_examination/patient_examination_create.py +58 -0
  749. endoreg_db/views/patient_examination/patient_examination_detail.py +63 -0
  750. endoreg_db/views/patient_examination/patient_examination_list.py +72 -0
  751. endoreg_db/views/patient_examination/video.py +228 -0
  752. endoreg_db/views/patient_finding/__init__.py +7 -0
  753. endoreg_db/views/patient_finding/base.py +0 -0
  754. endoreg_db/views/patient_finding/patient_finding.py +71 -0
  755. endoreg_db/views/patient_finding/patient_finding_optimized.py +291 -0
  756. endoreg_db/views/patient_finding_classification/__init__.py +5 -0
  757. endoreg_db/views/patient_finding_classification/pfc_create.py +75 -0
  758. endoreg_db/views/report/__init__.py +7 -0
  759. endoreg_db/views/report/reimport.py +177 -0
  760. endoreg_db/views/report/report_stream.py +191 -0
  761. endoreg_db/views/requirement/__init__.py +11 -0
  762. endoreg_db/views/requirement/evaluate.py +278 -0
  763. endoreg_db/views/requirement/lookup.py +380 -0
  764. endoreg_db/views/requirement/lookup_store.py +183 -0
  765. endoreg_db/views/requirement/requirement_utils.py +87 -0
  766. endoreg_db/views/requirement_lookup/lookup.py +0 -0
  767. endoreg_db/views/requirement_lookup/lookup_store.py +0 -0
  768. endoreg_db/views/stats/__init__.py +13 -0
  769. endoreg_db/views/stats/stats_views.py +266 -0
  770. endoreg_db/views/video/__init__.py +49 -0
  771. endoreg_db/views/video/ai/__init__.py +8 -0
  772. endoreg_db/views/video/ai/label.py +159 -0
  773. endoreg_db/views/video/correction.py +529 -0
  774. endoreg_db/views/video/reimport.py +230 -0
  775. endoreg_db/views/video/segments_crud.py +709 -0
  776. endoreg_db/views/video/video_apply_mask.py +49 -0
  777. endoreg_db/views/video/video_correction.py +22 -0
  778. endoreg_db/views/video/video_download_processed.py +58 -0
  779. endoreg_db/views/video/video_examination_viewset.py +242 -0
  780. endoreg_db/views/video/video_metadata.py +101 -0
  781. endoreg_db/views/video/video_processing_history.py +25 -0
  782. endoreg_db/views/video/video_remove_frames.py +49 -0
  783. endoreg_db/views/video/video_stream.py +334 -0
  784. endoreg_db-0.8.9.32.dist-info/METADATA +404 -0
  785. endoreg_db-0.8.9.32.dist-info/RECORD +787 -0
  786. endoreg_db-0.8.9.32.dist-info/WHEEL +4 -0
  787. endoreg_db-0.8.9.32.dist-info/licenses/LICENSE +674 -0
@@ -0,0 +1,842 @@
1
+ import calendar
2
+ import datetime
3
+ from datetime import timedelta
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from endoreg_db.models.requirement.requirement import Requirement
8
+ from endoreg_db.utils.links.requirement_link import RequirementLinks
9
+ # from endoreg_db.models import Unit # Potentially needed for dynamic unit handling
10
+
11
+
12
+ # Helper function to check if a date is within the timeframe specified by a Requirement
13
+ def _normalize_timeframe_unit(requirement: "Requirement") -> str | None:
14
+ """Derives a canonical timeframe unit string from the requirement."""
15
+ if not requirement.unit:
16
+ return None
17
+
18
+ name = (requirement.unit.name or "").strip().lower()
19
+ abbreviation = (requirement.unit.abbreviation or "").strip().lower()
20
+
21
+ unit_aliases = {
22
+ "hour": "hours",
23
+ "hours": "hours",
24
+ "h": "hours",
25
+ "day": "days",
26
+ "days": "days",
27
+ "d": "days",
28
+ "week": "weeks",
29
+ "weeks": "weeks",
30
+ "w": "weeks",
31
+ "month": "months",
32
+ "months": "months",
33
+ "m": "months",
34
+ "year": "years",
35
+ "years": "years",
36
+ "y": "years",
37
+ }
38
+
39
+ if name in unit_aliases:
40
+ return unit_aliases[name]
41
+ if abbreviation in unit_aliases:
42
+ return unit_aliases[abbreviation]
43
+ return None
44
+
45
+
46
+ def _add_months(base_date: datetime.date, months: int) -> datetime.date:
47
+ """Shifts ``base_date`` by the given number of months, clamping the day when needed."""
48
+ if months == 0:
49
+ return base_date
50
+
51
+ total_months = base_date.month - 1 + months
52
+ year = base_date.year + total_months // 12
53
+ month = total_months % 12 + 1
54
+ day = min(base_date.day, calendar.monthrange(year, month)[1])
55
+ return base_date.replace(year=year, month=month, day=day)
56
+
57
+
58
+ def _shift_date_by_unit(
59
+ base_date: datetime.date, value: int, unit: str
60
+ ) -> datetime.date:
61
+ """Returns ``base_date`` shifted by ``value`` units using the supported unit set.
62
+
63
+ Hour-level offsets are not supported because ``base_date`` is a ``date``
64
+ object without time information; callers must switch to datetime-aware
65
+ handling before requesting hourly shifts.
66
+ """
67
+ if unit == "days":
68
+ return base_date + timedelta(days=value)
69
+ if unit == "hours":
70
+ raise NotImplementedError(
71
+ "Hour-level timeframe comparisons require datetime-aware inputs; _shift_date_by_unit only operates on date objects."
72
+ )
73
+ if unit == "weeks":
74
+ return base_date + timedelta(weeks=value)
75
+ if unit == "months":
76
+ return _add_months(base_date, value)
77
+ if unit == "years":
78
+ return _add_months(base_date, value * 12)
79
+ raise NotImplementedError(f"Timeframe unit '{unit}' is not supported.")
80
+
81
+
82
+ def _is_date_in_timeframe(
83
+ date_to_check: datetime.date | None, requirement: "Requirement"
84
+ ) -> bool:
85
+ """
86
+ Checks if a given date falls within the timeframe specified by a Requirement.
87
+
88
+ The timeframe is defined by `numeric_value_min` and `numeric_value_max` on the
89
+ Requirement, interpreted relative to the current date.
90
+
91
+ Currently supports day/week/month/year windows. Hour-level units are
92
+ explicitly rejected because the timeframe calculations operate on dates
93
+ rather than datetimes.
94
+
95
+ Args:
96
+ date_to_check: The date to evaluate. If None, returns False.
97
+ requirement: The Requirement instance containing timeframe definitions
98
+ (unit, numeric_value_min, numeric_value_max).
99
+
100
+ Returns:
101
+ True if the date_to_check is within the defined timeframe, False otherwise.
102
+ Returns False if date_to_check is None or if the requirement lacks
103
+ necessary timeframe information (unit, min/max values).
104
+
105
+ Raises:
106
+ NotImplementedError: If the requirement.unit resolves to an unsupported
107
+ unit (e.g. hours) or cannot be normalised.
108
+ """
109
+ if date_to_check is None:
110
+ return False
111
+ if requirement.numeric_value_min is None or requirement.numeric_value_max is None:
112
+ return False # Not enough information for timeframe evaluation
113
+
114
+ unit = _normalize_timeframe_unit(requirement)
115
+ if not unit:
116
+ raise NotImplementedError(
117
+ "Timeframe unit could not be resolved from requirement's Unit name/abbreviation."
118
+ )
119
+
120
+ today = datetime.date.today()
121
+ timeframe_start_delta = int(requirement.numeric_value_min)
122
+ timeframe_end_delta = int(requirement.numeric_value_max)
123
+
124
+ start_date_bound = _shift_date_by_unit(today, timeframe_start_delta, unit)
125
+ end_date_bound = _shift_date_by_unit(today, timeframe_end_delta, unit)
126
+
127
+ if start_date_bound > end_date_bound:
128
+ start_date_bound, end_date_bound = end_date_bound, start_date_bound
129
+
130
+ return start_date_bound <= date_to_check <= end_date_bound
131
+
132
+
133
+ def _evaluate_models_match_any(
134
+ requirement_links: "RequirementLinks", input_links: "RequirementLinks", **kwargs
135
+ ) -> bool:
136
+ """
137
+ Checks if the requirement_links matches any of the input_links.
138
+
139
+ Args:
140
+ requirement_links: The reference set of requirement links to compare against.
141
+ input_links: The aggregated requirement links from the input objects.
142
+
143
+ Returns:
144
+ True if the input set of requirement links matches according to requirement_links.match_any; otherwise, False.
145
+ """
146
+ return requirement_links.match_any(input_links)
147
+
148
+
149
+ def _evaluate_models_match_any_in_timeframe(
150
+ requirement_links: "RequirementLinks",
151
+ input_links: "RequirementLinks",
152
+ requirement: "Requirement", # Explicitly pass Requirement
153
+ **kwargs, # Keep for consistency, though 'requirement' is the main one used here
154
+ ) -> bool:
155
+ """
156
+ Checks if any relevant model in input_links matches a model specified in
157
+ requirement_links AND falls within the timeframe defined on the Requirement.
158
+
159
+ Currently focuses on PatientEvent instances and their dates.
160
+ """
161
+ if not _has_timeframe_configuration(requirement):
162
+ return False
163
+
164
+ active_req_links_dict = requirement_links.active()
165
+ if not active_req_links_dict:
166
+ # If the Requirement itself doesn't specify any models to match (e.g., requirement.events is empty),
167
+ # then it's vacuously true that "any" of these (non-existent) required models are matched.
168
+ # The timeframe aspect becomes irrelevant if no specific models are being checked.
169
+ return True
170
+
171
+ # --- Handle PatientEvents ---
172
+ # Check if the requirement is concerned with events
173
+ if requirement_links.events: # This list contains Event model instances
174
+ required_event_models = set(
175
+ requirement_links.events
176
+ ) # Target Event models from the Requirement
177
+
178
+ # input_links.patient_events contains PatientEvent instances provided as input
179
+ for patient_event_instance in input_links.patient_events:
180
+ # Check if the event of the current PatientEvent instance is one of the target events
181
+ if patient_event_instance.event in required_event_models:
182
+ # If it is, check if this PatientEvent's date is within the timeframe
183
+ if _is_date_in_timeframe(patient_event_instance.date, requirement):
184
+ return True # Found a matching event within the timeframe
185
+
186
+ # --- Handle Other Model Types (Example: PatientLabValue) ---
187
+ # if requirement_links.lab_values:
188
+ # required_lab_value_models = set(requirement_links.lab_values)
189
+ # for plv_instance in input_links.patient_lab_values:
190
+ # if plv_instance.lab_value in required_lab_value_models:
191
+ # date_to_check = None
192
+ # if hasattr(plv_instance, 'date_time_value') and plv_instance.date_time_value:
193
+ # date_to_check = plv_instance.date_time_value.date()
194
+ # elif hasattr(plv_instance, 'date') and plv_instance.date: # If it had a simple date field
195
+ # date_to_check = plv_instance.date
196
+ #
197
+ # if _is_date_in_timeframe(date_to_check, requirement):
198
+ # return True
199
+
200
+ # If the code reaches here, no matching model within the timeframe was found
201
+ # for any of the categories specified in requirement_links.
202
+ return False
203
+
204
+
205
+ def _evaluate_models_match_all_in_timeframe(
206
+ requirement_links: "RequirementLinks",
207
+ input_links: "RequirementLinks",
208
+ requirement: "Requirement",
209
+ **kwargs,
210
+ ) -> bool:
211
+ if not _evaluate_models_match_all(requirement_links, input_links, **kwargs):
212
+ return False
213
+
214
+ if not requirement_links.events:
215
+ return True
216
+
217
+ if not _has_timeframe_configuration(requirement):
218
+ return False
219
+
220
+ required_events = set(requirement_links.events)
221
+ patient_events = getattr(input_links, "patient_events", [])
222
+ if not patient_events:
223
+ return False
224
+
225
+ for event in required_events:
226
+ found_in_timeframe = False
227
+ for patient_event in patient_events:
228
+ if getattr(patient_event, "event", None) == event:
229
+ if _is_date_in_timeframe(
230
+ getattr(patient_event, "date", None), requirement
231
+ ):
232
+ found_in_timeframe = True
233
+ break
234
+ if not found_in_timeframe:
235
+ return False
236
+ return True
237
+
238
+ if requirement.unit is None:
239
+ return False
240
+
241
+
242
+ def _evaluate_models_match_none_in_timeframe(
243
+ requirement_links: "RequirementLinks",
244
+ input_links: "RequirementLinks",
245
+ requirement: "Requirement",
246
+ **kwargs,
247
+ ) -> bool:
248
+ if not requirement_links.events:
249
+ return True
250
+
251
+ if not _has_timeframe_configuration(requirement):
252
+ return False
253
+
254
+ required_events = set(requirement_links.events)
255
+ for patient_event in getattr(input_links, "patient_events", []):
256
+ if getattr(patient_event, "event", None) in required_events:
257
+ if _is_date_in_timeframe(getattr(patient_event, "date", None), requirement):
258
+ return False
259
+ return True
260
+
261
+
262
+ def _evaluate_models_match_all(
263
+ requirement_links: "RequirementLinks", input_links: "RequirementLinks", **kwargs
264
+ ) -> bool:
265
+ """
266
+ Evaluates if all active links in requirement_links are present in input_links.
267
+
268
+ For each category of links in requirement_links (e.g., diseases, examinations),
269
+ all items specified in that category in requirement_links must be present in the
270
+ corresponding category in input_links.
271
+
272
+ Args:
273
+ requirement_links: The RequirementLinks object from the Requirement model.
274
+ input_links: The aggregated RequirementLinks object from the input arguments.
275
+ **kwargs: Additional keyword arguments (currently unused).
276
+
277
+ Returns:
278
+ True if all specified items in requirement_links are found in input_links,
279
+ False otherwise.
280
+ """
281
+ active_req_links = (
282
+ requirement_links.active()
283
+ ) # Get dict of non-empty lists from requirement
284
+
285
+ if not active_req_links: # If the requirement specifies no actual items to link
286
+ return True # Vacuously true, as there are no conditions to fail
287
+
288
+ for link_category_name, req_items_list in active_req_links.items():
289
+ input_items_list = getattr(input_links, link_category_name, [])
290
+
291
+ try:
292
+ set_input_items = set(input_items_list)
293
+ set_req_items = set(req_items_list)
294
+ except TypeError:
295
+ for req_item in req_items_list:
296
+ if req_item not in input_items_list:
297
+ return False
298
+ continue
299
+
300
+ if not set_req_items.issubset(set_input_items):
301
+ return False
302
+
303
+ return True
304
+
305
+
306
+ def _evaluate_models_match_none(
307
+ requirement_links: "RequirementLinks", input_links: "RequirementLinks", **kwargs
308
+ ) -> bool:
309
+ """Returns True when no required models are present in the input links."""
310
+ active_req_links = requirement_links.active()
311
+ if not active_req_links:
312
+ return True
313
+
314
+ for link_category_name, req_items_list in active_req_links.items():
315
+ input_items_list = getattr(input_links, link_category_name, [])
316
+ if not input_items_list:
317
+ continue
318
+ try:
319
+ if set(req_items_list) & set(input_items_list):
320
+ return False
321
+ except TypeError:
322
+ for req_item in req_items_list:
323
+ if req_item in input_items_list:
324
+ return False
325
+ return True
326
+
327
+
328
+ def _count_matching_models(
329
+ requirement_links: "RequirementLinks",
330
+ input_links: "RequirementLinks",
331
+ ) -> int:
332
+ """Counts how many required models are present in the input links."""
333
+ active_req_links = requirement_links.active()
334
+ if not active_req_links:
335
+ return 0
336
+
337
+ match_count = 0
338
+ for link_category_name, req_items_list in active_req_links.items():
339
+ input_items_list = getattr(input_links, link_category_name, [])
340
+ if not input_items_list:
341
+ continue
342
+ try:
343
+ match_count += len(set(req_items_list) & set(input_items_list))
344
+ except TypeError:
345
+ for req_item in req_items_list:
346
+ if req_item in input_items_list:
347
+ match_count += 1
348
+ return match_count
349
+
350
+
351
+ def _resolve_expected_count(requirement: "Requirement") -> int | None:
352
+ """Extracts the expected count from numeric fields on the requirement."""
353
+ if requirement.numeric_value is not None:
354
+ return int(requirement.numeric_value)
355
+ if requirement.numeric_value_min is not None:
356
+ return int(requirement.numeric_value_min)
357
+ return None
358
+
359
+
360
+ def _has_timeframe_configuration(requirement: "Requirement") -> bool:
361
+ """Checks whether timeframe boundaries and unit are configured."""
362
+ return (
363
+ requirement.unit is not None
364
+ and requirement.numeric_value_min is not None
365
+ and requirement.numeric_value_max is not None
366
+ and _normalize_timeframe_unit(requirement) is not None
367
+ )
368
+
369
+
370
+ def _count_matching_events_in_timeframe(
371
+ requirement_links: "RequirementLinks",
372
+ input_links: "RequirementLinks",
373
+ requirement: "Requirement",
374
+ ) -> int:
375
+ """Counts required events that have a matching patient event within the timeframe."""
376
+ required_events = set(requirement_links.events)
377
+ if not required_events:
378
+ return 0
379
+
380
+ patient_events = getattr(input_links, "patient_events", [])
381
+ if not patient_events:
382
+ return 0
383
+
384
+ matched_events = 0
385
+ for event in required_events:
386
+ for patient_event in patient_events:
387
+ if getattr(patient_event, "event", None) != event:
388
+ continue
389
+ if _is_date_in_timeframe(getattr(patient_event, "date", None), requirement):
390
+ matched_events += 1
391
+ break
392
+ return matched_events
393
+
394
+
395
+ def _evaluate_models_match_n(
396
+ requirement_links: "RequirementLinks",
397
+ input_links: "RequirementLinks",
398
+ requirement: "Requirement",
399
+ **kwargs,
400
+ ) -> bool:
401
+ expected = _resolve_expected_count(requirement)
402
+ if expected is None:
403
+ return False
404
+ return _count_matching_models(requirement_links, input_links) == expected
405
+
406
+
407
+ def _evaluate_models_match_n_or_more(
408
+ requirement_links: "RequirementLinks",
409
+ input_links: "RequirementLinks",
410
+ requirement: "Requirement",
411
+ **kwargs,
412
+ ) -> bool:
413
+ threshold = _resolve_expected_count(requirement)
414
+ if threshold is None:
415
+ return False
416
+ return _count_matching_models(requirement_links, input_links) >= max(threshold, 0)
417
+
418
+
419
+ def _evaluate_models_match_n_or_less(
420
+ requirement_links: "RequirementLinks",
421
+ input_links: "RequirementLinks",
422
+ requirement: "Requirement",
423
+ **kwargs,
424
+ ) -> bool:
425
+ limit = _resolve_expected_count(requirement)
426
+ if limit is None:
427
+ return False
428
+ return _count_matching_models(requirement_links, input_links) <= limit
429
+
430
+
431
+ def _evaluate_models_match_count_in_range(
432
+ requirement_links: "RequirementLinks",
433
+ input_links: "RequirementLinks",
434
+ requirement: "Requirement",
435
+ **kwargs,
436
+ ) -> bool:
437
+ if requirement.numeric_value_min is None or requirement.numeric_value_max is None:
438
+ return False
439
+
440
+ lower = int(requirement.numeric_value_min)
441
+ upper = int(requirement.numeric_value_max)
442
+ if lower > upper:
443
+ lower, upper = upper, lower
444
+
445
+ match_count = _count_matching_models(requirement_links, input_links)
446
+ return lower <= match_count <= upper
447
+
448
+
449
+ def _evaluate_models_match_n_in_timeframe(
450
+ requirement_links: "RequirementLinks",
451
+ input_links: "RequirementLinks",
452
+ requirement: "Requirement",
453
+ **kwargs,
454
+ ) -> bool:
455
+ if not _has_timeframe_configuration(requirement):
456
+ return False
457
+
458
+ expected = _resolve_expected_count(requirement)
459
+ if expected is None:
460
+ return False
461
+
462
+ return (
463
+ _count_matching_events_in_timeframe(requirement_links, input_links, requirement)
464
+ == expected
465
+ )
466
+
467
+
468
+ def _evaluate_models_match_n_or_more_in_timeframe(
469
+ requirement_links: "RequirementLinks",
470
+ input_links: "RequirementLinks",
471
+ requirement: "Requirement",
472
+ **kwargs,
473
+ ) -> bool:
474
+ if not _has_timeframe_configuration(requirement):
475
+ return False
476
+
477
+ threshold = _resolve_expected_count(requirement)
478
+ if threshold is None:
479
+ return False
480
+
481
+ return _count_matching_events_in_timeframe(
482
+ requirement_links, input_links, requirement
483
+ ) >= max(threshold, 0)
484
+
485
+
486
+ def _evaluate_models_match_n_or_less_in_timeframe(
487
+ requirement_links: "RequirementLinks",
488
+ input_links: "RequirementLinks",
489
+ requirement: "Requirement",
490
+ **kwargs,
491
+ ) -> bool:
492
+ if not _has_timeframe_configuration(requirement):
493
+ return False
494
+
495
+ limit = _resolve_expected_count(requirement)
496
+ if limit is None:
497
+ return False
498
+
499
+ return (
500
+ _count_matching_events_in_timeframe(requirement_links, input_links, requirement)
501
+ <= limit
502
+ )
503
+
504
+
505
+ def _evaluate_age_gte(
506
+ requirement_links: "RequirementLinks",
507
+ input_links: "RequirementLinks",
508
+ requirement: "Requirement",
509
+ **kwargs,
510
+ ) -> bool:
511
+ """
512
+ Checks if any patient in the input has an age greater than or equal to the requirement's numeric_value.
513
+
514
+ Args:
515
+ requirement_links: The RequirementLinks object from the Requirement model (not used for age checks).
516
+ input_links: The aggregated RequirementLinks object from the input arguments.
517
+ requirement: The Requirement instance containing the minimum age in numeric_value.
518
+ **kwargs: Additional keyword arguments, should contain 'original_input_args' with the original Patient instances.
519
+
520
+ Returns:
521
+ True if any patient in the input has an age >= requirement.numeric_value, False otherwise.
522
+ """
523
+ import logging
524
+
525
+ from endoreg_db.models.administration.person.patient import Patient
526
+
527
+ logger = logging.getLogger(__name__)
528
+
529
+ if requirement.numeric_value is None:
530
+ logger.debug("age_gte: requirement.numeric_value is None, returning False")
531
+ return False # Cannot evaluate without a minimum age requirement
532
+
533
+ min_age = requirement.numeric_value
534
+ logger.debug(f"age_gte: Checking if any patient has age >= {min_age}")
535
+
536
+ # Check if we have Patient instances in the original_input_args
537
+ original_args = kwargs.get("original_input_args", [])
538
+ logger.debug(
539
+ f"age_gte: Found {len(original_args)} original input arguments: {[type(arg).__name__ for arg in original_args]}"
540
+ )
541
+
542
+ for i, arg in enumerate(original_args):
543
+ logger.debug(f"age_gte: Checking argument {i}: {type(arg).__name__}")
544
+ if isinstance(arg, Patient):
545
+ patient_age = arg.age()
546
+ logger.debug(
547
+ f"age_gte: Patient {arg} has age {patient_age}, comparing with min_age {min_age}"
548
+ )
549
+ if patient_age is not None and patient_age >= min_age:
550
+ logger.debug(
551
+ f"age_gte: Patient age {patient_age} >= {min_age}, returning True"
552
+ )
553
+ return True
554
+ else:
555
+ logger.debug(
556
+ f"age_gte: Patient age {patient_age} < {min_age} or is None"
557
+ )
558
+ # Handle QuerySets of patients
559
+ elif hasattr(arg, "model") and issubclass(arg.model, Patient):
560
+ logger.debug(f"age_gte: Found Patient QuerySet with {arg.count()} patients")
561
+ for patient in arg:
562
+ patient_age = patient.age()
563
+ logger.debug(
564
+ f"age_gte: Patient {patient} has age {patient_age}, comparing with min_age {min_age}"
565
+ )
566
+ if patient_age is not None and patient_age >= min_age:
567
+ logger.debug(
568
+ f"age_gte: Patient age {patient_age} >= {min_age}, returning True"
569
+ )
570
+ return True
571
+ else:
572
+ logger.debug(
573
+ f"age_gte: Argument {i} is not a Patient or Patient QuerySet: {type(arg)}"
574
+ )
575
+
576
+ logger.debug(f"age_gte: No patient found with age >= {min_age}, returning False")
577
+ return False
578
+
579
+
580
+ def _evaluate_age_lte(
581
+ requirement_links: "RequirementLinks",
582
+ input_links: "RequirementLinks",
583
+ requirement: "Requirement",
584
+ **kwargs,
585
+ ) -> bool:
586
+ """
587
+ Checks if any patient in the input has an age less than or equal to the requirement's numeric_value.
588
+
589
+ Args:
590
+ requirement_links: The RequirementLinks object from the Requirement model (not used for age checks).
591
+ input_links: The aggregated RequirementLinks object from the input arguments.
592
+ requirement: The Requirement instance containing the maximum age in numeric_value.
593
+ **kwargs: Additional keyword arguments, should contain 'original_input_args' with the original Patient instances.
594
+
595
+ Returns:
596
+ True if any patient in the input has an age <= requirement.numeric_value, False otherwise.
597
+ """
598
+ from endoreg_db.models.administration.person.patient import Patient
599
+
600
+ if requirement.numeric_value is None:
601
+ return False # Cannot evaluate without a maximum age requirement
602
+
603
+ max_age = requirement.numeric_value
604
+
605
+ # Check if we have Patient instances in the original_input_args
606
+ original_args = kwargs.get("original_input_args", [])
607
+ for arg in original_args:
608
+ if isinstance(arg, Patient):
609
+ patient_age = arg.age()
610
+ if patient_age is not None and patient_age <= max_age:
611
+ return True
612
+ # Handle QuerySets of patients
613
+ elif hasattr(arg, "model") and issubclass(arg.model, Patient):
614
+ for patient in arg:
615
+ patient_age = patient.age()
616
+ if patient_age is not None and patient_age <= max_age:
617
+ return True
618
+
619
+ return False
620
+
621
+
622
+ def dispatch_operator_evaluation(
623
+ operator_name: str,
624
+ requirement_links: "RequirementLinks",
625
+ input_links: "RequirementLinks",
626
+ **kwargs,
627
+ ) -> bool:
628
+ """
629
+ Dispatches the evaluation to the appropriate function based on the operator name.
630
+
631
+ Args:
632
+ operator_name: The name of the operator to evaluate.
633
+ requirement_links: The RequirementLinks object from the Requirement model.
634
+ input_links: The aggregated RequirementLinks object from the input arguments.
635
+ **kwargs: Additional keyword arguments for specific operator logic.
636
+ For lab value operators, this includes 'requirement' (the Requirement model instance).
637
+
638
+ Returns:
639
+ True if the condition defined by the operator is met, False otherwise.
640
+
641
+ Raises:
642
+ NotImplementedError: If the evaluation logic for the operator's name is not implemented.
643
+ """
644
+ from endoreg_db.models.requirement.requirement import (
645
+ Requirement,
646
+ ) # Runtime import for isinstance
647
+
648
+ from .lab_value_operators import LAB_VALUE_OPERATOR_FUNCTIONS
649
+
650
+ eval_func = None
651
+ requirement = kwargs.get(
652
+ "requirement"
653
+ ) # Get requirement for operators that need it
654
+
655
+ def _kwargs_without_requirement() -> dict:
656
+ return {k: v for k, v in kwargs.items() if k != "requirement"}
657
+
658
+ if operator_name == "models_match_any":
659
+ eval_func = _evaluate_models_match_any
660
+ return eval_func(
661
+ requirement_links=requirement_links, input_links=input_links, **kwargs
662
+ )
663
+ elif operator_name == "models_match_all":
664
+ eval_func = _evaluate_models_match_all
665
+ return eval_func(
666
+ requirement_links=requirement_links, input_links=input_links, **kwargs
667
+ )
668
+ elif operator_name == "models_match_none":
669
+ eval_func = _evaluate_models_match_none
670
+ return eval_func(
671
+ requirement_links=requirement_links, input_links=input_links, **kwargs
672
+ )
673
+ elif operator_name == "models_match_any_in_timeframe":
674
+ # 'requirement' is already extracted from kwargs via requirement = kwargs.get("requirement")
675
+ if not isinstance(
676
+ requirement, Requirement
677
+ ): # Ensure requirement is present and correct type
678
+ raise ValueError(
679
+ "models_match_any_in_timeframe operator requires a valid 'requirement' instance in kwargs."
680
+ )
681
+ kwargs_for_eval = _kwargs_without_requirement()
682
+ eval_func = _evaluate_models_match_any_in_timeframe
683
+ return eval_func(
684
+ requirement_links=requirement_links,
685
+ input_links=input_links,
686
+ requirement=requirement, # Pass the requirement instance explicitly
687
+ **kwargs_for_eval, # Pass the remaining kwargs
688
+ )
689
+ elif operator_name == "models_match_all_in_timeframe":
690
+ if not isinstance(requirement, Requirement):
691
+ raise ValueError(
692
+ "models_match_all_in_timeframe operator requires a valid 'requirement' instance in kwargs."
693
+ )
694
+ kwargs_for_eval = _kwargs_without_requirement()
695
+ return _evaluate_models_match_all_in_timeframe(
696
+ requirement_links=requirement_links,
697
+ input_links=input_links,
698
+ requirement=requirement,
699
+ **kwargs_for_eval,
700
+ )
701
+ elif operator_name == "models_match_none_in_timeframe":
702
+ if not isinstance(requirement, Requirement):
703
+ raise ValueError(
704
+ "models_match_none_in_timeframe operator requires a valid 'requirement' instance in kwargs."
705
+ )
706
+ kwargs_for_eval = _kwargs_without_requirement()
707
+ return _evaluate_models_match_none_in_timeframe(
708
+ requirement_links=requirement_links,
709
+ input_links=input_links,
710
+ requirement=requirement,
711
+ **kwargs_for_eval,
712
+ )
713
+ elif operator_name == "models_match_n":
714
+ if not isinstance(requirement, Requirement):
715
+ raise ValueError(
716
+ "models_match_n operator requires a valid 'requirement' instance in kwargs."
717
+ )
718
+ kwargs_for_eval = _kwargs_without_requirement()
719
+ return _evaluate_models_match_n(
720
+ requirement_links=requirement_links,
721
+ input_links=input_links,
722
+ requirement=requirement,
723
+ **kwargs_for_eval,
724
+ )
725
+ elif operator_name == "models_match_n_or_more":
726
+ if not isinstance(requirement, Requirement):
727
+ raise ValueError(
728
+ "models_match_n_or_more operator requires a valid 'requirement' instance in kwargs."
729
+ )
730
+ kwargs_for_eval = _kwargs_without_requirement()
731
+ return _evaluate_models_match_n_or_more(
732
+ requirement_links=requirement_links,
733
+ input_links=input_links,
734
+ requirement=requirement,
735
+ **kwargs_for_eval,
736
+ )
737
+ elif operator_name == "models_match_n_or_less":
738
+ if not isinstance(requirement, Requirement):
739
+ raise ValueError(
740
+ "models_match_n_or_less operator requires a valid 'requirement' instance in kwargs."
741
+ )
742
+ kwargs_for_eval = _kwargs_without_requirement()
743
+ return _evaluate_models_match_n_or_less(
744
+ requirement_links=requirement_links,
745
+ input_links=input_links,
746
+ requirement=requirement,
747
+ **kwargs_for_eval,
748
+ )
749
+ elif operator_name == "models_match_count_in_range":
750
+ if not isinstance(requirement, Requirement):
751
+ raise ValueError(
752
+ "models_match_count_in_range operator requires a valid 'requirement' instance in kwargs."
753
+ )
754
+ kwargs_for_eval = _kwargs_without_requirement()
755
+ return _evaluate_models_match_count_in_range(
756
+ requirement_links=requirement_links,
757
+ input_links=input_links,
758
+ requirement=requirement,
759
+ **kwargs_for_eval,
760
+ )
761
+ elif operator_name == "models_match_n_in_timeframe":
762
+ if not isinstance(requirement, Requirement):
763
+ raise ValueError(
764
+ "models_match_n_in_timeframe operator requires a valid 'requirement' instance in kwargs."
765
+ )
766
+ kwargs_for_eval = _kwargs_without_requirement()
767
+ return _evaluate_models_match_n_in_timeframe(
768
+ requirement_links=requirement_links,
769
+ input_links=input_links,
770
+ requirement=requirement,
771
+ **kwargs_for_eval,
772
+ )
773
+ elif operator_name == "models_match_n_or_more_in_timeframe":
774
+ if not isinstance(requirement, Requirement):
775
+ raise ValueError(
776
+ "models_match_n_or_more_in_timeframe operator requires a valid 'requirement' instance in kwargs."
777
+ )
778
+ kwargs_for_eval = _kwargs_without_requirement()
779
+ return _evaluate_models_match_n_or_more_in_timeframe(
780
+ requirement_links=requirement_links,
781
+ input_links=input_links,
782
+ requirement=requirement,
783
+ **kwargs_for_eval,
784
+ )
785
+ elif operator_name == "models_match_n_or_less_in_timeframe":
786
+ if not isinstance(requirement, Requirement):
787
+ raise ValueError(
788
+ "models_match_n_or_less_in_timeframe operator requires a valid 'requirement' instance in kwargs."
789
+ )
790
+ kwargs_for_eval = _kwargs_without_requirement()
791
+ return _evaluate_models_match_n_or_less_in_timeframe(
792
+ requirement_links=requirement_links,
793
+ input_links=input_links,
794
+ requirement=requirement,
795
+ **kwargs_for_eval,
796
+ )
797
+ elif operator_name in LAB_VALUE_OPERATOR_FUNCTIONS:
798
+ if not isinstance(
799
+ requirement, Requirement
800
+ ): # Ensure requirement is present and correct type
801
+ raise ValueError(
802
+ f"Lab value operator '{operator_name}' requires a valid 'requirement' instance in kwargs."
803
+ )
804
+
805
+ eval_func = LAB_VALUE_OPERATOR_FUNCTIONS[operator_name]
806
+ return eval_func(
807
+ input_links=input_links, requirement=requirement, operator_kwargs=kwargs
808
+ )
809
+ elif operator_name == "age_gte":
810
+ if not isinstance(requirement, Requirement):
811
+ raise ValueError(
812
+ "age_gte operator requires a valid 'requirement' instance in kwargs."
813
+ )
814
+
815
+ # Create a new kwargs dict for the call, excluding 'requirement' to avoid passing it twice
816
+ kwargs_for_eval = {k: v for k, v in kwargs.items() if k != "requirement"}
817
+
818
+ return _evaluate_age_gte(
819
+ requirement_links=requirement_links,
820
+ input_links=input_links,
821
+ requirement=requirement,
822
+ **kwargs_for_eval,
823
+ )
824
+ elif operator_name == "age_lte":
825
+ if not isinstance(requirement, Requirement):
826
+ raise ValueError(
827
+ "age_lte operator requires a valid 'requirement' instance in kwargs."
828
+ )
829
+
830
+ # Create a new kwargs dict for the call, excluding 'requirement' to avoid passing it twice
831
+ kwargs_for_eval = {k: v for k, v in kwargs.items() if k != "requirement"}
832
+
833
+ return _evaluate_age_lte(
834
+ requirement_links=requirement_links,
835
+ input_links=input_links,
836
+ requirement=requirement,
837
+ **kwargs_for_eval,
838
+ )
839
+ else:
840
+ raise NotImplementedError(
841
+ f"Evaluation logic for operator '{operator_name}' is not implemented."
842
+ )