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,678 @@
1
+ from typing import TYPE_CHECKING, List, Optional, Callable, Dict, Any
2
+ import re # Added import
3
+ from endoreg_db.models.medical.patient.patient_lab_value import PatientLabValue
4
+ from endoreg_db.models.requirement.requirement import Requirement
5
+ from datetime import datetime, timedelta
6
+
7
+ if TYPE_CHECKING:
8
+ from endoreg_db.utils.links.requirement_link import RequirementLinks # Added import
9
+ # from endoreg_db.models.requirement.requirement_operator import RequirementOperator # No longer directly used here
10
+
11
+
12
+ def get_latest_patient_lab_value(
13
+ patient_lab_values: List[PatientLabValue], lab_value_name: str
14
+ ) -> Optional[PatientLabValue]:
15
+ """
16
+ Retrieves the most recent PatientLabValue for a specific lab_value_name.
17
+ """
18
+ relevant_values = [
19
+ plv
20
+ for plv in patient_lab_values
21
+ if plv.lab_value and plv.lab_value.name == lab_value_name
22
+ ]
23
+ if not relevant_values:
24
+ return None
25
+ return max(relevant_values, key=lambda plv: plv.datetime)
26
+
27
+
28
+ def get_patient_lab_values_in_timeframe(
29
+ patient_lab_values: List[PatientLabValue],
30
+ lab_value_name: str,
31
+ days_min: Optional[int] = None,
32
+ days_max: Optional[int] = None,
33
+ ) -> List[PatientLabValue]:
34
+ """
35
+ Retrieves PatientLabValues for a specific lab_value_name within a given timeframe.
36
+ Timeframe is relative to the current date.
37
+ days_min: e.g., -7 for 7 days ago (start of timeframe)
38
+ days_max: e.g., 0 for today (end of timeframe)
39
+ """
40
+ relevant_values = [
41
+ plv
42
+ for plv in patient_lab_values
43
+ if plv.lab_value and plv.lab_value.name == lab_value_name
44
+ ]
45
+ if not relevant_values:
46
+ return []
47
+
48
+ today = datetime.now().date()
49
+ filtered_values = []
50
+
51
+ for plv in relevant_values:
52
+ plv_date = plv.datetime.date()
53
+ in_timeframe = True
54
+ if days_min is not None:
55
+ start_date = today + timedelta(days=days_min)
56
+ if plv_date < start_date:
57
+ in_timeframe = False
58
+ if days_max is not None:
59
+ end_date = today + timedelta(days=days_max)
60
+ if plv_date > end_date:
61
+ in_timeframe = False
62
+ if in_timeframe:
63
+ filtered_values.append(plv)
64
+ return filtered_values
65
+
66
+
67
+ def lab_latest_numeric_increased(
68
+ input_links: "RequirementLinks", # Changed
69
+ requirement: Requirement,
70
+ operator_kwargs: Dict[str, Any],
71
+ ) -> bool:
72
+ """
73
+ Returns True if the latest numeric lab value for all required lab values is above the normal maximum range; otherwise returns False.
74
+
75
+ Returns False if any required lab value is missing, the latest value is unavailable, or the value does not exceed the normal maximum.
76
+ """
77
+ patient_lab_values = input_links.patient_lab_values
78
+ if not requirement.lab_values.exists():
79
+ return False
80
+ for lab_value_model in requirement.lab_values.all():
81
+ latest_plv = get_latest_patient_lab_value(
82
+ patient_lab_values, lab_value_model.name
83
+ )
84
+ if not (latest_plv and latest_plv.value is not None and latest_plv.lab_value):
85
+ return False
86
+ patient_context = input_links.get_first_patient()
87
+ normal_range = latest_plv.lab_value.get_normal_range(
88
+ age=patient_context.age() if patient_context else None,
89
+ gender=patient_context.gender if patient_context else None,
90
+ )
91
+ if normal_range.get("max") is None or latest_plv.value <= normal_range["max"]:
92
+ return False
93
+ return True
94
+
95
+
96
+ def lab_latest_numeric_decreased(
97
+ input_links: "RequirementLinks", # Changed
98
+ requirement: Requirement,
99
+ operator_kwargs: Dict[str, Any],
100
+ ) -> bool:
101
+ """
102
+ Returns True if the latest numeric lab value for all required lab values is below the normal minimum range.
103
+
104
+ Returns False if any latest value is missing, lacks a normal range, or is not below the minimum.
105
+ """
106
+ patient_lab_values = input_links.patient_lab_values
107
+ if not requirement.lab_values.exists(): # Changed
108
+ return False
109
+ for lab_value_model in requirement.lab_values.all():
110
+ latest_plv = get_latest_patient_lab_value(
111
+ patient_lab_values, lab_value_model.name
112
+ )
113
+ if not (
114
+ latest_plv and latest_plv.value is not None and latest_plv.lab_value
115
+ ): # Added check for latest_plv.lab_value
116
+ return False
117
+ patient_context = input_links.get_first_patient()
118
+ normal_range = latest_plv.lab_value.get_normal_range(
119
+ age=patient_context.age() if patient_context else None,
120
+ gender=patient_context.gender if patient_context else None,
121
+ )
122
+ if normal_range.get("min") is None or latest_plv.value >= normal_range["min"]:
123
+ return False
124
+ return True
125
+
126
+
127
+ def lab_latest_numeric_normal(
128
+ input_links: "RequirementLinks", # Changed
129
+ requirement: Requirement,
130
+ operator_kwargs: Dict[str, Any],
131
+ ) -> bool:
132
+ """
133
+ Returns True if the latest numeric lab value for all required lab values is within the normal range.
134
+
135
+ Returns False if any latest value is missing, lacks a normal range, or falls outside the normal range.
136
+ """
137
+ patient_lab_values = input_links.patient_lab_values
138
+ if not requirement.lab_values.exists(): # Changed
139
+ return False
140
+ for lab_value_model in requirement.lab_values.all():
141
+ latest_plv = get_latest_patient_lab_value(
142
+ patient_lab_values, lab_value_model.name
143
+ )
144
+ if not (
145
+ latest_plv and latest_plv.value is not None and latest_plv.lab_value
146
+ ): # Added check for latest_plv.lab_value
147
+ return False
148
+ patient_context = input_links.get_first_patient()
149
+ normal_range = latest_plv.lab_value.get_normal_range(
150
+ age=patient_context.age() if patient_context else None,
151
+ gender=patient_context.gender if patient_context else None,
152
+ )
153
+ min_val = normal_range.get("min")
154
+ max_val = normal_range.get("max")
155
+ if min_val is None or max_val is None:
156
+ return False
157
+ if not (min_val <= latest_plv.value <= max_val):
158
+ return False
159
+ return True
160
+
161
+
162
+ def lab_latest_numeric_lower_than_value(
163
+ input_links: "RequirementLinks", # Changed
164
+ requirement: Requirement,
165
+ operator_kwargs: Dict[str, Any],
166
+ ) -> bool:
167
+ """
168
+ Returns True if the latest numeric lab value for all required lab values is lower than the specified threshold.
169
+
170
+ Returns False if any latest value is missing or not below the requirement's numeric value.
171
+ """
172
+ patient_lab_values = input_links.patient_lab_values
173
+ if (
174
+ not requirement.lab_values.exists() or requirement.numeric_value is None
175
+ ): # Changed
176
+ return False
177
+ for lab_value_model in requirement.lab_values.all():
178
+ latest_plv = get_latest_patient_lab_value(
179
+ patient_lab_values, lab_value_model.name
180
+ )
181
+ if not (latest_plv and latest_plv.value is not None):
182
+ return False
183
+ if not (latest_plv.value < requirement.numeric_value):
184
+ return False
185
+ return True
186
+
187
+
188
+ def lab_latest_numeric_greater_than_value(
189
+ input_links: "RequirementLinks", # Changed
190
+ requirement: Requirement,
191
+ operator_kwargs: Dict[str, Any],
192
+ ) -> bool:
193
+ """
194
+ Returns True if the latest numeric lab value for all required lab values is greater than the specified threshold.
195
+
196
+ Returns False if any latest value is missing or not greater than the requirement's numeric value.
197
+ """
198
+ patient_lab_values = input_links.patient_lab_values
199
+ if (
200
+ not requirement.lab_values.exists() or requirement.numeric_value is None
201
+ ): # Changed
202
+ return False
203
+ for lab_value_model in requirement.lab_values.all():
204
+ latest_plv = get_latest_patient_lab_value(
205
+ patient_lab_values, lab_value_model.name
206
+ )
207
+ if not (latest_plv and latest_plv.value is not None):
208
+ return False
209
+ if not (latest_plv.value > requirement.numeric_value):
210
+ return False
211
+ return True
212
+
213
+
214
+ # --- Operators with timeframe ---
215
+
216
+
217
+ def lab_latest_numeric_increased_factor_in_timeframe(
218
+ input_links: "RequirementLinks", # Changed
219
+ requirement: Requirement,
220
+ operator_kwargs: Dict[str, Any],
221
+ ) -> bool:
222
+ """
223
+ Checks if the numeric lab value has increased by a certain factor within a timeframe.
224
+ The factor is defined in requirement.numeric_value.
225
+ The timeframe (in days relative to now) is defined by
226
+ requirement.numeric_value_min (start, e.g., -7 for 7 days ago) and
227
+ requirement.numeric_value_max (end, e.g., 0 for today).
228
+ This operator checks if *any* value in the timeframe is increased by the factor compared to the value *at the start* of the timeframe.
229
+ More sophisticated checks (e.g., sustained increase, comparison to earliest value in overall history) might require different logic.
230
+ """
231
+ patient_lab_values = input_links.patient_lab_values
232
+ if (
233
+ not requirement.lab_values.exists()
234
+ or requirement.numeric_value is None
235
+ or requirement.numeric_value_min is None
236
+ or requirement.numeric_value_max is None
237
+ ):
238
+ return False
239
+
240
+ factor = requirement.numeric_value
241
+ days_min = int(requirement.numeric_value_min) # Start of timeframe
242
+ days_max = int(requirement.numeric_value_max) # End of timeframe
243
+
244
+ for lab_value_model in requirement.lab_values.all():
245
+ # Get all values for this lab type, not just within the timeframe initially
246
+ all_lab_values_for_type = sorted(
247
+ [
248
+ plv
249
+ for plv in patient_lab_values
250
+ if plv.lab_value
251
+ and plv.lab_value.name == lab_value_model.name
252
+ and plv.value is not None
253
+ ],
254
+ key=lambda plv: plv.datetime,
255
+ )
256
+
257
+ if not all_lab_values_for_type:
258
+ continue
259
+
260
+ # Determine the reference value: the one closest to, but before or at, the start of the timeframe
261
+ start_of_timeframe_date = (datetime.now() + timedelta(days=days_min)).date()
262
+ reference_plv = None
263
+ for plv in reversed(all_lab_values_for_type):
264
+ if plv.datetime.date() <= start_of_timeframe_date:
265
+ reference_plv = plv
266
+ break
267
+
268
+ if (
269
+ reference_plv is None and all_lab_values_for_type
270
+ ): # if no value before timeframe, use earliest available
271
+ reference_plv = all_lab_values_for_type[0]
272
+
273
+ if reference_plv and reference_plv.value is not None:
274
+ reference_value = reference_plv.value
275
+ # Now get values strictly within the defined timeframe
276
+ values_in_timeframe = get_patient_lab_values_in_timeframe(
277
+ patient_lab_values, lab_value_model.name, days_min, days_max
278
+ )
279
+ for plv_in_frame in values_in_timeframe:
280
+ if plv_in_frame.value is not None and plv_in_frame.value > (
281
+ reference_value * factor
282
+ ):
283
+ return True # Found a value increased by the factor
284
+ return False
285
+
286
+
287
+ def lab_latest_numeric_decreased_factor_in_timeframe(
288
+ input_links: "RequirementLinks",
289
+ requirement: Requirement,
290
+ operator_kwargs: Dict[str, Any],
291
+ ) -> bool:
292
+ """
293
+ Checks if the numeric lab value has decreased by a certain factor within a timeframe.
294
+ Factor is in requirement.numeric_value. Timeframe in numeric_value_min/max.
295
+ Compares values in timeframe to the value at the start of (or just before) the timeframe.
296
+ """
297
+ patient_lab_values = input_links.patient_lab_values
298
+ if (
299
+ not requirement.lab_values.exists()
300
+ or requirement.numeric_value is None
301
+ or requirement.numeric_value_min is None
302
+ or requirement.numeric_value_max is None
303
+ ):
304
+ return False
305
+
306
+ factor = requirement.numeric_value
307
+ days_min = int(requirement.numeric_value_min)
308
+ days_max = int(requirement.numeric_value_max)
309
+
310
+ for lab_value_model in requirement.lab_values.all():
311
+ all_lab_values_for_type = sorted(
312
+ [
313
+ plv
314
+ for plv in patient_lab_values
315
+ if plv.lab_value
316
+ and plv.lab_value.name == lab_value_model.name
317
+ and plv.value is not None
318
+ ],
319
+ key=lambda plv: plv.datetime,
320
+ )
321
+ if not all_lab_values_for_type:
322
+ continue
323
+
324
+ start_of_timeframe_date = (datetime.now() + timedelta(days=days_min)).date()
325
+ reference_plv = None
326
+ for plv in reversed(all_lab_values_for_type):
327
+ if plv.datetime.date() <= start_of_timeframe_date:
328
+ reference_plv = plv
329
+ break
330
+ if reference_plv is None and all_lab_values_for_type:
331
+ reference_plv = all_lab_values_for_type[0]
332
+
333
+ if reference_plv and reference_plv.value is not None:
334
+ reference_value = reference_plv.value
335
+ if (
336
+ reference_value == 0
337
+ ): # Avoid division by zero or issues with zero reference
338
+ continue
339
+ values_in_timeframe = get_patient_lab_values_in_timeframe(
340
+ patient_lab_values, lab_value_model.name, days_min, days_max
341
+ )
342
+ for plv_in_frame in values_in_timeframe:
343
+ if plv_in_frame.value is not None and plv_in_frame.value < (
344
+ reference_value / factor
345
+ ): # Decreased by factor
346
+ return True
347
+ return False
348
+
349
+
350
+ def lab_latest_numeric_normal_in_timeframe(
351
+ input_links: "RequirementLinks",
352
+ requirement: Requirement,
353
+ operator_kwargs: Dict[str, Any],
354
+ ) -> bool:
355
+ """
356
+ Checks if any numeric lab value within a timeframe is within its normal range.
357
+ Timeframe in requirement.numeric_value_min/max.
358
+ """
359
+ patient_lab_values = input_links.patient_lab_values
360
+ if (
361
+ not requirement.lab_values.exists()
362
+ or requirement.numeric_value_min is None
363
+ or requirement.numeric_value_max is None
364
+ ):
365
+ return False
366
+
367
+ days_min = int(requirement.numeric_value_min)
368
+ days_max = int(requirement.numeric_value_max)
369
+ patient_context = input_links.get_first_patient()
370
+
371
+ for lab_value_model in requirement.lab_values.all():
372
+ values_in_timeframe = get_patient_lab_values_in_timeframe(
373
+ patient_lab_values, lab_value_model.name, days_min, days_max
374
+ )
375
+ for plv in values_in_timeframe:
376
+ if plv.value is not None and plv.lab_value:
377
+ normal_range = plv.lab_value.get_normal_range(
378
+ age=patient_context.age() if patient_context else None,
379
+ gender=patient_context.gender if patient_context else None,
380
+ )
381
+ min_val = normal_range.get("min")
382
+ max_val = normal_range.get("max")
383
+ if min_val is not None and max_val is not None:
384
+ if min_val <= plv.value <= max_val:
385
+ return True
386
+ return False
387
+
388
+
389
+ def lab_latest_numeric_lower_than_value_in_timeframe(
390
+ input_links: "RequirementLinks",
391
+ requirement: Requirement,
392
+ operator_kwargs: Dict[str, Any],
393
+ ) -> bool:
394
+ """
395
+ Checks if any numeric lab value within a timeframe is lower than requirement.numeric_value.
396
+ Timeframe in requirement.numeric_value_min/max.
397
+ """
398
+ patient_lab_values = input_links.patient_lab_values
399
+ if (
400
+ not requirement.lab_values.exists()
401
+ or requirement.numeric_value is None
402
+ or requirement.numeric_value_min is None
403
+ or requirement.numeric_value_max is None
404
+ ):
405
+ return False
406
+
407
+ threshold = requirement.numeric_value
408
+ days_min = int(requirement.numeric_value_min)
409
+ days_max = int(requirement.numeric_value_max)
410
+
411
+ for lab_value_model in requirement.lab_values.all():
412
+ values_in_timeframe = get_patient_lab_values_in_timeframe(
413
+ patient_lab_values, lab_value_model.name, days_min, days_max
414
+ )
415
+ for plv in values_in_timeframe:
416
+ if plv.value is not None and plv.value < threshold:
417
+ return True
418
+ return False
419
+
420
+
421
+ def lab_latest_numeric_greater_than_value_in_timeframe(
422
+ input_links: "RequirementLinks",
423
+ requirement: Requirement,
424
+ operator_kwargs: Dict[str, Any],
425
+ ) -> bool:
426
+ """
427
+ Checks if any numeric lab value within a timeframe is greater than requirement.numeric_value.
428
+ Timeframe in requirement.numeric_value_min/max.
429
+ """
430
+ patient_lab_values = input_links.patient_lab_values
431
+ if (
432
+ not requirement.lab_values.exists()
433
+ or requirement.numeric_value is None
434
+ or requirement.numeric_value_min is None
435
+ or requirement.numeric_value_max is None
436
+ ):
437
+ return False
438
+
439
+ threshold = requirement.numeric_value
440
+ days_min = int(requirement.numeric_value_min)
441
+ days_max = int(requirement.numeric_value_max)
442
+
443
+ for lab_value_model in requirement.lab_values.all():
444
+ values_in_timeframe = get_patient_lab_values_in_timeframe(
445
+ patient_lab_values, lab_value_model.name, days_min, days_max
446
+ )
447
+ for plv in values_in_timeframe:
448
+ if plv.value is not None and plv.value > threshold:
449
+ return True
450
+ return False
451
+
452
+
453
+ # --- Categorical Operators ---
454
+ # Assuming PatientLabValue has a 'value_string' attribute for categorical results.
455
+
456
+
457
+ def lab_latest_categorical_match(
458
+ input_links: "RequirementLinks",
459
+ requirement: Requirement,
460
+ operator_kwargs: Dict[str, Any],
461
+ ) -> bool:
462
+ """
463
+ Checks if the latest categorical lab value matches requirement.string_value.
464
+ """
465
+ patient_lab_values = input_links.patient_lab_values
466
+ if not requirement.lab_values.exists() or requirement.string_value is None:
467
+ return False
468
+
469
+ match_string = requirement.string_value
470
+ for lab_value_model in requirement.lab_values.all():
471
+ latest_plv = get_latest_patient_lab_value(
472
+ patient_lab_values, lab_value_model.name
473
+ )
474
+ # Ensure latest_plv has value_str attribute
475
+ if (
476
+ latest_plv
477
+ and hasattr(latest_plv, "value_str")
478
+ and latest_plv.value_str is not None
479
+ ): # Changed value_string to value_str
480
+ if latest_plv.value_str == match_string:
481
+ return True
482
+ return False
483
+
484
+
485
+ def lab_latest_categorical_match_substring(
486
+ input_links: "RequirementLinks",
487
+ requirement: Requirement,
488
+ operator_kwargs: Dict[str, Any],
489
+ ) -> bool:
490
+ """
491
+ Checks if requirement.string_value is a substring of the latest categorical lab value.
492
+ """
493
+ patient_lab_values = input_links.patient_lab_values
494
+ if not requirement.lab_values.exists() or requirement.string_value is None:
495
+ return False
496
+
497
+ substring = requirement.string_value
498
+ for lab_value_model in requirement.lab_values.all():
499
+ latest_plv = get_latest_patient_lab_value(
500
+ patient_lab_values, lab_value_model.name
501
+ )
502
+ if (
503
+ latest_plv
504
+ and hasattr(latest_plv, "value_str")
505
+ and latest_plv.value_str is not None
506
+ ): # Changed value_string to value_str
507
+ if substring in latest_plv.value_str:
508
+ return True
509
+ return False
510
+
511
+
512
+ def lab_latest_categorical_match_regex(
513
+ input_links: "RequirementLinks",
514
+ requirement: Requirement,
515
+ operator_kwargs: Dict[str, Any],
516
+ ) -> bool:
517
+ """
518
+ Checks if the latest categorical lab value matches regex in requirement.string_value.
519
+ """
520
+ patient_lab_values = input_links.patient_lab_values
521
+ if not requirement.lab_values.exists() or requirement.string_value is None:
522
+ return False
523
+
524
+ regex_pattern = requirement.string_value
525
+ try:
526
+ compiled_regex = re.compile(regex_pattern)
527
+ except re.error:
528
+ return False # Invalid regex
529
+
530
+ for lab_value_model in requirement.lab_values.all():
531
+ latest_plv = get_latest_patient_lab_value(
532
+ patient_lab_values, lab_value_model.name
533
+ )
534
+ if (
535
+ latest_plv
536
+ and hasattr(latest_plv, "value_str")
537
+ and latest_plv.value_str is not None
538
+ ): # Changed value_string to value_str
539
+ if compiled_regex.search(latest_plv.value_str):
540
+ return True
541
+ return False
542
+
543
+
544
+ # --- Categorical Operators with Timeframe ---
545
+
546
+
547
+ def lab_latest_categorical_match_in_timeframe(
548
+ input_links: "RequirementLinks",
549
+ requirement: Requirement,
550
+ operator_kwargs: Dict[str, Any],
551
+ ) -> bool:
552
+ """
553
+ Checks if any categorical lab value in timeframe matches requirement.string_value.
554
+ Timeframe in requirement.numeric_value_min/max.
555
+ """
556
+ patient_lab_values = input_links.patient_lab_values
557
+ if (
558
+ not requirement.lab_values.exists()
559
+ or requirement.string_value is None
560
+ or requirement.numeric_value_min is None
561
+ or requirement.numeric_value_max is None
562
+ ):
563
+ return False
564
+
565
+ match_string = requirement.string_value
566
+ days_min = int(requirement.numeric_value_min)
567
+ days_max = int(requirement.numeric_value_max)
568
+
569
+ for lab_value_model in requirement.lab_values.all():
570
+ values_in_timeframe = get_patient_lab_values_in_timeframe(
571
+ patient_lab_values, lab_value_model.name, days_min, days_max
572
+ )
573
+ for plv in values_in_timeframe:
574
+ if (
575
+ hasattr(plv, "value_str") and plv.value_str is not None
576
+ ): # Changed value_string to value_str
577
+ if plv.value_str == match_string:
578
+ return True
579
+ return False
580
+
581
+
582
+ def lab_latest_categorical_match_substring_in_timeframe(
583
+ input_links: "RequirementLinks",
584
+ requirement: Requirement,
585
+ operator_kwargs: Dict[str, Any],
586
+ ) -> bool:
587
+ """
588
+ Checks if requirement.string_value is substring of any categorical lab value in timeframe.
589
+ Timeframe in requirement.numeric_value_min/max.
590
+ """
591
+ patient_lab_values = input_links.patient_lab_values
592
+ if (
593
+ not requirement.lab_values.exists()
594
+ or requirement.string_value is None
595
+ or requirement.numeric_value_min is None
596
+ or requirement.numeric_value_max is None
597
+ ):
598
+ return False
599
+
600
+ substring = requirement.string_value
601
+ days_min = int(requirement.numeric_value_min)
602
+ days_max = int(requirement.numeric_value_max)
603
+
604
+ for lab_value_model in requirement.lab_values.all():
605
+ values_in_timeframe = get_patient_lab_values_in_timeframe(
606
+ patient_lab_values, lab_value_model.name, days_min, days_max
607
+ )
608
+ for plv in values_in_timeframe:
609
+ if (
610
+ hasattr(plv, "value_str") and plv.value_str is not None
611
+ ): # Changed value_string to value_str
612
+ if substring in plv.value_str:
613
+ return True
614
+ return False
615
+
616
+
617
+ def lab_latest_categorical_match_regex_in_timeframe(
618
+ input_links: "RequirementLinks",
619
+ requirement: Requirement,
620
+ operator_kwargs: Dict[str, Any],
621
+ ) -> bool:
622
+ """
623
+ Checks if any categorical lab value in timeframe matches regex in requirement.string_value.
624
+ Timeframe in requirement.numeric_value_min/max.
625
+ """
626
+ patient_lab_values = input_links.patient_lab_values
627
+ if (
628
+ not requirement.lab_values.exists()
629
+ or requirement.string_value is None
630
+ or requirement.numeric_value_min is None
631
+ or requirement.numeric_value_max is None
632
+ ):
633
+ return False
634
+
635
+ regex_pattern = requirement.string_value
636
+ try:
637
+ compiled_regex = re.compile(regex_pattern)
638
+ except re.error:
639
+ return False
640
+
641
+ days_min = int(requirement.numeric_value_min)
642
+ days_max = int(requirement.numeric_value_max)
643
+
644
+ for lab_value_model in requirement.lab_values.all():
645
+ values_in_timeframe = get_patient_lab_values_in_timeframe(
646
+ patient_lab_values, lab_value_model.name, days_min, days_max
647
+ )
648
+ for plv in values_in_timeframe:
649
+ if (
650
+ hasattr(plv, "value_str") and plv.value_str is not None
651
+ ): # Changed value_string to value_str
652
+ if compiled_regex.search(plv.value_str):
653
+ return True
654
+ return False
655
+
656
+
657
+ # Mapping operator names to functions
658
+ LAB_VALUE_OPERATOR_FUNCTIONS: Dict[str, Callable] = {
659
+ "lab_latest_numeric_increased": lab_latest_numeric_increased,
660
+ "lab_latest_numeric_decreased": lab_latest_numeric_decreased,
661
+ "lab_latest_numeric_normal": lab_latest_numeric_normal,
662
+ "lab_latest_numeric_lower_than_value": lab_latest_numeric_lower_than_value,
663
+ "lab_latest_numeric_greater_than_value": lab_latest_numeric_greater_than_value,
664
+ # Aliases for backward compatibility, pointing to timeframe versions
665
+ "lab_latest_numeric_increased_factor": lab_latest_numeric_increased_factor_in_timeframe,
666
+ "lab_latest_numeric_decreased_factor": lab_latest_numeric_decreased_factor_in_timeframe,
667
+ "lab_latest_numeric_increased_factor_in_timeframe": lab_latest_numeric_increased_factor_in_timeframe,
668
+ "lab_latest_numeric_decreased_factor_in_timeframe": lab_latest_numeric_decreased_factor_in_timeframe,
669
+ "lab_latest_numeric_normal_in_timeframe": lab_latest_numeric_normal_in_timeframe,
670
+ "lab_latest_numeric_lower_than_value_in_timeframe": lab_latest_numeric_lower_than_value_in_timeframe,
671
+ "lab_latest_numeric_greater_than_value_in_timeframe": lab_latest_numeric_greater_than_value_in_timeframe,
672
+ "lab_latest_categorical_match": lab_latest_categorical_match,
673
+ "lab_latest_categorical_match_substring": lab_latest_categorical_match_substring,
674
+ "lab_latest_categorical_match_regex": lab_latest_categorical_match_regex,
675
+ "lab_latest_categorical_match_in_timeframe": lab_latest_categorical_match_in_timeframe,
676
+ "lab_latest_categorical_match_substring_in_timeframe": lab_latest_categorical_match_substring_in_timeframe,
677
+ "lab_latest_categorical_match_regex_in_timeframe": lab_latest_categorical_match_regex_in_timeframe,
678
+ }