endoreg-db 0.6.4__py3-none-any.whl → 0.8.2__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 (779) hide show
  1. endoreg_db/admin.py +26 -26
  2. endoreg_db/api_urls.py +4 -0
  3. endoreg_db/apps.py +12 -0
  4. endoreg_db/assets/dummy_model.ckpt +1 -0
  5. endoreg_db/codemods/readme.md +88 -0
  6. endoreg_db/codemods/rename_datetime_fields.py +92 -0
  7. endoreg_db/config/env.py +101 -0
  8. endoreg_db/data/__init__.py +12 -0
  9. endoreg_db/data/ai_model/data.yaml +1 -1
  10. endoreg_db/data/ai_model_label/label/polyp_classification.yaml +52 -0
  11. endoreg_db/data/ai_model_label/label-set/data.yaml +20 -1
  12. endoreg_db/data/ai_model_label/label-set/polyp_classifications.yaml +25 -0
  13. endoreg_db/data/center/data.yaml +13 -12
  14. endoreg_db/data/center_shift/ukw.yaml +9 -0
  15. endoreg_db/data/db_summary.csv +58 -0
  16. endoreg_db/data/db_summary.xlsx +0 -0
  17. endoreg_db/data/disease/misc.yaml +1 -2
  18. endoreg_db/data/endoscopy_processor/data.yaml +3 -0
  19. endoreg_db/data/event/cardiology.yaml +0 -13
  20. endoreg_db/data/examination/examinations/data.yaml +14 -9
  21. endoreg_db/data/examination_indication/endoscopy.yaml +30 -30
  22. endoreg_db/data/examination_indication_classification/endoscopy.yaml +11 -11
  23. endoreg_db/data/examination_requirement_set/colonoscopy.yaml +15 -0
  24. endoreg_db/data/finding/anatomy_colon.yaml +128 -0
  25. endoreg_db/data/finding/colonoscopy.yaml +40 -0
  26. endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +56 -0
  27. endoreg_db/data/finding/complication.yaml +16 -0
  28. endoreg_db/data/finding/data.yaml +3 -46
  29. endoreg_db/data/finding/examination_setting.yaml +16 -0
  30. endoreg_db/data/finding/medication_related.yaml +18 -0
  31. endoreg_db/data/finding/outcome.yaml +12 -0
  32. endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +95 -0
  33. endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +22 -0
  34. endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +25 -0
  35. endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
  36. endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
  37. endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +68 -0
  38. endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
  39. endoreg_db/data/finding_classification/colonoscopy_location.yaml +80 -0
  40. endoreg_db/data/finding_classification/colonoscopy_lst.yaml +21 -0
  41. endoreg_db/data/finding_classification/colonoscopy_nice.yaml +20 -0
  42. endoreg_db/data/finding_classification/colonoscopy_paris.yaml +26 -0
  43. endoreg_db/data/finding_classification/colonoscopy_sano.yaml +22 -0
  44. endoreg_db/data/finding_classification/colonoscopy_summary.yaml +53 -0
  45. endoreg_db/data/finding_classification/complication_generic.yaml +25 -0
  46. endoreg_db/data/finding_classification/examination_setting_generic.yaml +40 -0
  47. endoreg_db/data/finding_classification/histology_colo.yaml +51 -0
  48. endoreg_db/data/finding_classification/intervention_required.yaml +26 -0
  49. endoreg_db/data/finding_classification/medication_related.yaml +23 -0
  50. endoreg_db/data/finding_classification/visualized.yaml +33 -0
  51. endoreg_db/data/finding_classification_choice/bowel_preparation.yaml +78 -0
  52. endoreg_db/data/{finding_morphology_classification_choice → finding_classification_choice}/colon_lesion_circularity_default.yaml +0 -2
  53. endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
  54. endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
  55. endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +15 -0
  56. endoreg_db/data/{finding_morphology_classification_choice → finding_classification_choice}/colon_lesion_nice.yaml +4 -7
  57. endoreg_db/data/{finding_morphology_classification_choice → finding_classification_choice}/colon_lesion_paris.yaml +0 -8
  58. endoreg_db/data/{finding_morphology_classification_choice → finding_classification_choice}/colon_lesion_planarity_default.yaml +6 -13
  59. endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +14 -0
  60. endoreg_db/data/{finding_morphology_classification_choice → finding_classification_choice}/colon_lesion_surface_intact_default.yaml +3 -6
  61. endoreg_db/data/{finding_location_classification_choice/colonoscopy.yaml → finding_classification_choice/colonoscopy_location.yaml} +11 -22
  62. endoreg_db/data/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
  63. endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +82 -0
  64. endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
  65. endoreg_db/data/finding_classification_choice/complication_generic_types.yaml +15 -0
  66. endoreg_db/data/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
  67. endoreg_db/data/finding_classification_choice/histology.yaml +24 -0
  68. endoreg_db/data/finding_classification_choice/histology_polyp.yaml +20 -0
  69. endoreg_db/data/finding_classification_choice/outcome.yaml +19 -0
  70. endoreg_db/data/finding_classification_choice/yes_no_na.yaml +11 -0
  71. endoreg_db/data/finding_classification_type/colonoscopy_basic.yaml +48 -0
  72. endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +8 -3
  73. endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +6 -6
  74. endoreg_db/data/finding_type/data.yaml +23 -10
  75. endoreg_db/data/gender/data.yaml +8 -1
  76. endoreg_db/data/information_source/annotation.yaml +6 -0
  77. endoreg_db/data/information_source/prediction.yaml +7 -0
  78. endoreg_db/data/information_source_type/data.yaml +8 -0
  79. endoreg_db/data/lab_value/misc.yaml +43 -0
  80. endoreg_db/data/medication/anticoagulation.yaml +5 -5
  81. endoreg_db/data/medication/tah.yaml +5 -5
  82. endoreg_db/data/medication_intake_time/base.yaml +4 -4
  83. endoreg_db/data/names_first/first_names.yaml +3 -0
  84. endoreg_db/data/pdf_type/data.yaml +26 -2
  85. endoreg_db/data/qualification/endoscopy.yaml +36 -0
  86. endoreg_db/data/qualification/m2.yaml +39 -0
  87. endoreg_db/data/qualification/outpatient_clinic.yaml +35 -0
  88. endoreg_db/data/qualification/sonography.yaml +36 -0
  89. endoreg_db/data/qualification_type/base.yaml +29 -0
  90. endoreg_db/data/report_reader_flag/rkh-histology-generic.yaml +10 -0
  91. endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +5 -0
  92. endoreg_db/data/requirement/age.yaml +26 -0
  93. endoreg_db/data/requirement/colonoscopy_baseline_austria.yaml +45 -0
  94. endoreg_db/data/requirement/disease_cardiovascular.yaml +6 -6
  95. endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +9 -6
  96. endoreg_db/data/requirement/disease_hepatology.yaml +1 -1
  97. endoreg_db/data/requirement/disease_misc.yaml +3 -3
  98. endoreg_db/data/requirement/disease_renal.yaml +18 -2
  99. endoreg_db/data/requirement/{colonoscopy_indications.yaml → endoscopy_bleeding_risk.yaml} +6 -3
  100. endoreg_db/data/requirement/event_cardiology.yaml +17 -17
  101. endoreg_db/data/requirement/event_requirements.yaml +145 -0
  102. endoreg_db/data/requirement/finding_colon_polyp.yaml +50 -0
  103. endoreg_db/data/requirement/gender.yaml +25 -0
  104. endoreg_db/data/requirement/lab_value.yaml +352 -31
  105. endoreg_db/data/requirement/medication.yaml +93 -0
  106. endoreg_db/data/requirement_operator/age.yaml +13 -0
  107. endoreg_db/data/requirement_operator/lab_operators.yaml +36 -35
  108. endoreg_db/data/requirement_operator/model_operators.yaml +13 -7
  109. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +48 -0
  110. endoreg_db/data/requirement_set/colonoscopy_austria_screening.yaml +57 -0
  111. endoreg_db/data/requirement_set/endoscopy_bleeding_risk.yaml +42 -2
  112. endoreg_db/data/requirement_type/requirement_types.yaml +82 -0
  113. endoreg_db/data/shift/endoscopy.yaml +21 -0
  114. endoreg_db/data/shift_type/base.yaml +35 -0
  115. endoreg_db/data/tag/requirement_set_tags.yaml +11 -0
  116. endoreg_db/data/unit/concentration.yaml +23 -0
  117. endoreg_db/exceptions.py +19 -0
  118. endoreg_db/forms/patient_finding_intervention_form.py +4 -5
  119. endoreg_db/forms/patient_form.py +7 -6
  120. endoreg_db/forms/questionnaires/__init__.py +1 -1
  121. endoreg_db/forms/questionnaires/tto_questionnaire.py +19 -19
  122. endoreg_db/helpers/count_db.py +45 -0
  123. endoreg_db/helpers/data_loader.py +208 -0
  124. endoreg_db/helpers/default_objects.py +359 -0
  125. endoreg_db/helpers/download_segmentation_model.py +31 -0
  126. endoreg_db/helpers/interact.py +6 -0
  127. endoreg_db/helpers/test_video_helper.py +119 -0
  128. endoreg_db/logger_conf.py +140 -0
  129. endoreg_db/management/__init__.py +1 -0
  130. endoreg_db/management/commands/__init__.py +1 -0
  131. endoreg_db/management/commands/anonymize_video.py +0 -0
  132. endoreg_db/management/commands/check_auth.py +125 -0
  133. endoreg_db/management/commands/create_multilabel_model_meta.py +214 -0
  134. endoreg_db/management/commands/fix_missing_patient_data.py +172 -0
  135. endoreg_db/management/commands/fix_video_paths.py +165 -0
  136. endoreg_db/management/commands/import_fallback_video.py +203 -0
  137. endoreg_db/management/commands/import_report.py +298 -0
  138. endoreg_db/management/commands/import_video.py +422 -0
  139. endoreg_db/management/commands/import_video_with_classification.py +367 -0
  140. endoreg_db/management/commands/init_default_ai_model.py +112 -0
  141. endoreg_db/management/commands/load_ai_model_data.py +2 -7
  142. endoreg_db/management/commands/load_base_db_data.py +1 -0
  143. endoreg_db/management/commands/load_endoscope_data.py +2 -2
  144. endoreg_db/management/commands/load_examination_indication_data.py +2 -3
  145. endoreg_db/management/commands/load_finding_data.py +49 -92
  146. endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +0 -1
  147. endoreg_db/management/commands/load_information_source.py +13 -7
  148. endoreg_db/management/commands/load_name_data.py +37 -0
  149. endoreg_db/management/commands/load_qualification_data.py +59 -0
  150. endoreg_db/management/commands/load_requirement_data.py +30 -6
  151. endoreg_db/management/commands/load_shift_data.py +60 -0
  152. endoreg_db/management/commands/load_tag_data.py +57 -0
  153. endoreg_db/management/commands/register_ai_model.py +1 -1
  154. endoreg_db/management/commands/start_filewatcher.py +106 -0
  155. endoreg_db/management/commands/storage_management.py +548 -0
  156. endoreg_db/management/commands/summarize_db_content.py +189 -0
  157. endoreg_db/management/commands/validate_video.py +204 -0
  158. endoreg_db/management/commands/validate_video_files.py +161 -0
  159. endoreg_db/management/commands/video_validation.py +22 -0
  160. endoreg_db/migrations/0001_initial.py +625 -813
  161. endoreg_db/migrations/0002_add_video_correction_models.py +52 -0
  162. endoreg_db/models/__init__.py +270 -307
  163. endoreg_db/models/administration/__init__.py +116 -0
  164. endoreg_db/models/{ai_model → administration/ai}/__init__.py +6 -1
  165. endoreg_db/models/administration/ai/active_model.py +35 -0
  166. endoreg_db/models/administration/ai/ai_model.py +156 -0
  167. endoreg_db/models/{ai_model → administration/ai}/model_type.py +6 -1
  168. endoreg_db/models/administration/case/__init__.py +19 -0
  169. endoreg_db/models/administration/case/case.py +114 -0
  170. endoreg_db/models/{case_template → administration/case/case_template}/case_template.py +3 -3
  171. endoreg_db/models/{case_template → administration/case/case_template}/case_template_rule.py +3 -10
  172. endoreg_db/models/{case_template → administration/case/case_template}/case_template_rule_value.py +2 -4
  173. endoreg_db/models/{case_template → administration/case/case_template}/case_template_type.py +1 -3
  174. endoreg_db/models/{center → administration/center}/__init__.py +3 -1
  175. endoreg_db/models/administration/center/center.py +61 -0
  176. endoreg_db/models/administration/center/center_product.py +64 -0
  177. endoreg_db/models/{center → administration/center}/center_resource.py +19 -3
  178. endoreg_db/models/administration/center/center_shift.py +88 -0
  179. endoreg_db/models/administration/center/center_waste.py +30 -0
  180. endoreg_db/models/administration/permissions/__init__.py +44 -0
  181. endoreg_db/models/administration/person/__init__.py +24 -0
  182. endoreg_db/models/administration/person/employee/__init__.py +3 -0
  183. endoreg_db/models/administration/person/employee/employee.py +35 -0
  184. endoreg_db/models/administration/person/employee/employee_qualification.py +39 -0
  185. endoreg_db/models/administration/person/employee/employee_type.py +42 -0
  186. endoreg_db/models/administration/person/examiner/__init__.py +4 -0
  187. endoreg_db/models/administration/person/examiner/examiner.py +54 -0
  188. endoreg_db/models/administration/person/names/__init__.py +0 -0
  189. endoreg_db/models/{persons → administration/person/names}/first_name.py +1 -1
  190. endoreg_db/models/{persons → administration/person/names}/last_name.py +2 -3
  191. endoreg_db/models/administration/person/patient/__init__.py +5 -0
  192. endoreg_db/models/administration/person/patient/patient.py +460 -0
  193. endoreg_db/models/administration/person/profession/__init__.py +24 -0
  194. endoreg_db/models/administration/person/user/__init__.py +5 -0
  195. endoreg_db/models/administration/person/user/portal_user_information.py +37 -0
  196. endoreg_db/models/administration/product/product.py +97 -0
  197. endoreg_db/models/administration/product/product_group.py +39 -0
  198. endoreg_db/models/administration/product/product_material.py +54 -0
  199. endoreg_db/models/{product → administration/product}/product_weight.py +9 -0
  200. endoreg_db/models/{product → administration/product}/reference_product.py +26 -11
  201. endoreg_db/models/administration/qualification/__init__.py +7 -0
  202. endoreg_db/models/administration/qualification/qualification.py +37 -0
  203. endoreg_db/models/administration/qualification/qualification_type.py +35 -0
  204. endoreg_db/models/administration/shift/__init__.py +9 -0
  205. endoreg_db/models/administration/shift/scheduled_days.py +69 -0
  206. endoreg_db/models/administration/shift/shift.py +51 -0
  207. endoreg_db/models/administration/shift/shift_type.py +108 -0
  208. endoreg_db/models/label/__init__.py +24 -1
  209. endoreg_db/models/label/annotation/__init__.py +12 -0
  210. endoreg_db/models/label/annotation/image_classification.py +84 -0
  211. endoreg_db/models/label/annotation/video_segmentation_annotation.py +66 -0
  212. endoreg_db/models/label/label.py +45 -74
  213. endoreg_db/models/label/label_set.py +53 -0
  214. endoreg_db/models/label/label_type.py +29 -0
  215. endoreg_db/models/label/label_video_segment/__init__.py +3 -0
  216. endoreg_db/models/label/label_video_segment/_create_from_video.py +41 -0
  217. endoreg_db/models/label/label_video_segment/label_video_segment.py +511 -0
  218. endoreg_db/models/label/video_segmentation_label.py +31 -0
  219. endoreg_db/models/{annotation → label}/video_segmentation_labelset.py +7 -0
  220. endoreg_db/models/media/__init__.py +14 -0
  221. endoreg_db/models/media/frame/__init__.py +3 -0
  222. endoreg_db/models/media/frame/frame.py +111 -0
  223. endoreg_db/models/media/pdf/__init__.py +11 -0
  224. endoreg_db/models/media/pdf/raw_pdf.py +608 -0
  225. endoreg_db/models/media/pdf/report_file.py +162 -0
  226. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +77 -0
  227. endoreg_db/models/media/video/__init__.py +4 -0
  228. endoreg_db/models/media/video/create_from_file.py +336 -0
  229. endoreg_db/models/media/video/pipe_1.py +207 -0
  230. endoreg_db/models/media/video/pipe_2.py +105 -0
  231. endoreg_db/models/media/video/refactor_plan.md +0 -0
  232. endoreg_db/models/media/video/video_file.py +680 -0
  233. endoreg_db/models/media/video/video_file_ai.py +443 -0
  234. endoreg_db/models/media/video/video_file_anonymize.py +348 -0
  235. endoreg_db/models/media/video/video_file_frames/__init__.py +47 -0
  236. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +22 -0
  237. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +23 -0
  238. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +104 -0
  239. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +174 -0
  240. endoreg_db/models/media/video/video_file_frames/_get_frame.py +28 -0
  241. endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +27 -0
  242. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +20 -0
  243. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +27 -0
  244. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +34 -0
  245. endoreg_db/models/media/video/video_file_frames/_get_frames.py +27 -0
  246. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +129 -0
  247. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +129 -0
  248. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +65 -0
  249. endoreg_db/models/media/video/video_file_frames.py +0 -0
  250. endoreg_db/models/media/video/video_file_io.py +166 -0
  251. endoreg_db/models/media/video/video_file_meta/__init__.py +22 -0
  252. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +45 -0
  253. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +39 -0
  254. endoreg_db/models/media/video/video_file_meta/get_fps.py +147 -0
  255. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +143 -0
  256. endoreg_db/models/media/video/video_file_meta/text_meta.py +134 -0
  257. endoreg_db/models/media/video/video_file_meta/video_meta.py +70 -0
  258. endoreg_db/models/media/video/video_file_meta.py +11 -0
  259. endoreg_db/models/media/video/video_file_segments.py +209 -0
  260. endoreg_db/models/medical/__init__.py +146 -0
  261. endoreg_db/models/{contraindication → medical/contraindication}/__init__.py +1 -5
  262. endoreg_db/models/{disease.py → medical/disease.py} +60 -52
  263. endoreg_db/models/{event.py → medical/event.py} +31 -54
  264. endoreg_db/models/{examination → medical/examination}/__init__.py +1 -1
  265. endoreg_db/models/medical/examination/examination.py +148 -0
  266. endoreg_db/models/{examination → medical/examination}/examination_indication.py +64 -35
  267. endoreg_db/models/{examination → medical/examination}/examination_time.py +0 -4
  268. endoreg_db/models/{examination → medical/examination}/examination_time_type.py +1 -8
  269. endoreg_db/models/{examination → medical/examination}/examination_type.py +1 -7
  270. endoreg_db/models/medical/finding/__init__.py +18 -0
  271. endoreg_db/models/medical/finding/finding.py +96 -0
  272. endoreg_db/models/medical/finding/finding_classification.py +142 -0
  273. endoreg_db/models/{finding → medical/finding}/finding_intervention.py +2 -10
  274. endoreg_db/models/medical/finding/finding_type.py +35 -0
  275. endoreg_db/models/medical/hardware/__init__.py +8 -0
  276. endoreg_db/models/{hardware → medical/hardware}/endoscope.py +28 -23
  277. endoreg_db/models/medical/laboratory/__init__.py +5 -0
  278. endoreg_db/models/medical/laboratory/lab_value.py +419 -0
  279. endoreg_db/models/{medication → medical/medication}/medication.py +1 -3
  280. endoreg_db/models/{medication → medical/medication}/medication_indication_type.py +8 -3
  281. endoreg_db/models/{medication → medical/medication}/medication_intake_time.py +21 -3
  282. endoreg_db/models/{medication → medical/medication}/medication_schedule.py +13 -5
  283. endoreg_db/models/{organ → medical/organ}/__init__.py +3 -6
  284. endoreg_db/models/medical/patient/__init__.py +56 -0
  285. endoreg_db/models/medical/patient/medication_examples.py +38 -0
  286. endoreg_db/models/medical/patient/patient_disease.py +63 -0
  287. endoreg_db/models/medical/patient/patient_event.py +75 -0
  288. endoreg_db/models/medical/patient/patient_examination.py +249 -0
  289. endoreg_db/models/{persons → medical}/patient/patient_examination_indication.py +21 -9
  290. endoreg_db/models/medical/patient/patient_finding.py +357 -0
  291. endoreg_db/models/medical/patient/patient_finding_classification.py +207 -0
  292. endoreg_db/models/{patient → medical/patient}/patient_finding_intervention.py +15 -1
  293. endoreg_db/models/medical/patient/patient_lab_sample.py +148 -0
  294. endoreg_db/models/{persons → medical}/patient/patient_lab_value.py +40 -15
  295. endoreg_db/models/medical/patient/patient_medication.py +104 -0
  296. endoreg_db/models/medical/patient/patient_medication_schedule.py +136 -0
  297. endoreg_db/models/{risk → medical/risk}/risk_type.py +0 -4
  298. endoreg_db/models/{data_file/metadata → metadata}/__init__.py +6 -0
  299. endoreg_db/models/metadata/frame_ocr_result.py +0 -0
  300. endoreg_db/models/metadata/model_meta.py +193 -0
  301. endoreg_db/models/metadata/model_meta_logic.py +236 -0
  302. endoreg_db/models/{data_file/metadata → metadata}/pdf_meta.py +28 -13
  303. endoreg_db/models/metadata/sensitive_meta.py +288 -0
  304. endoreg_db/models/metadata/sensitive_meta_logic.py +643 -0
  305. endoreg_db/models/metadata/video_meta.py +332 -0
  306. endoreg_db/models/metadata/video_prediction_logic.py +190 -0
  307. endoreg_db/models/metadata/video_prediction_meta.py +270 -0
  308. endoreg_db/models/other/__init__.py +17 -0
  309. endoreg_db/models/other/distribution/date_value_distribution.py +0 -2
  310. endoreg_db/models/other/distribution/numeric_value_distribution.py +30 -2
  311. endoreg_db/models/{emission → other/emission}/emission_factor.py +15 -6
  312. endoreg_db/models/{persons → other}/gender.py +8 -3
  313. endoreg_db/models/other/information_source.py +159 -0
  314. endoreg_db/models/other/material.py +10 -2
  315. endoreg_db/models/other/resource.py +6 -2
  316. endoreg_db/models/other/tag.py +27 -0
  317. endoreg_db/models/other/transport_route.py +13 -2
  318. endoreg_db/models/{unit.py → other/unit.py} +16 -6
  319. endoreg_db/models/other/waste.py +10 -3
  320. endoreg_db/models/requirement/requirement.py +556 -114
  321. endoreg_db/models/requirement/requirement_evaluation/__init__.py +4 -132
  322. endoreg_db/models/requirement/requirement_evaluation/get_values.py +40 -0
  323. endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +9 -0
  324. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +80 -87
  325. endoreg_db/models/requirement/requirement_operator.py +132 -14
  326. endoreg_db/models/requirement/requirement_set.py +181 -21
  327. endoreg_db/models/rule/__init__.py +13 -0
  328. endoreg_db/models/{rules → rule}/rule.py +6 -3
  329. endoreg_db/models/{rules → rule}/rule_attribute_dtype.py +0 -2
  330. endoreg_db/models/{rules → rule}/rule_type.py +0 -2
  331. endoreg_db/models/{rules → rule}/ruleset.py +0 -2
  332. endoreg_db/models/state/__init__.py +12 -0
  333. endoreg_db/models/state/abstract.py +11 -0
  334. endoreg_db/models/state/audit_ledger.py +150 -0
  335. endoreg_db/models/state/label_video_segment.py +22 -0
  336. endoreg_db/models/state/raw_pdf.py +187 -0
  337. endoreg_db/models/state/sensitive_meta.py +46 -0
  338. endoreg_db/models/state/video.py +232 -0
  339. endoreg_db/models/upload_job.py +99 -0
  340. endoreg_db/models/utils.py +135 -0
  341. endoreg_db/models/video_metadata.py +66 -0
  342. endoreg_db/models/video_processing.py +153 -0
  343. endoreg_db/renames.yml +8 -0
  344. endoreg_db/root_urls.py +9 -0
  345. endoreg_db/schemas/__init__.py +0 -0
  346. endoreg_db/schemas/examination_evaluation.py +27 -0
  347. endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +775 -0
  348. endoreg_db/serializers/__init__.py +147 -10
  349. endoreg_db/serializers/{raw_pdf_meta_validation.py → _old/raw_pdf_meta_validation.py} +3 -3
  350. endoreg_db/serializers/{raw_video_meta_validation.py → _old/raw_video_meta_validation.py} +18 -14
  351. endoreg_db/serializers/_old/video.py +71 -0
  352. endoreg_db/serializers/administration/__init__.py +14 -0
  353. endoreg_db/serializers/administration/ai/__init__.py +10 -0
  354. endoreg_db/serializers/administration/ai/active_model.py +10 -0
  355. endoreg_db/serializers/administration/ai/ai_model.py +18 -0
  356. endoreg_db/serializers/administration/ai/model_type.py +10 -0
  357. endoreg_db/serializers/administration/center.py +9 -0
  358. endoreg_db/serializers/administration/gender.py +9 -0
  359. endoreg_db/serializers/anonymization.py +69 -0
  360. endoreg_db/serializers/evaluation/examination_evaluation.py +1 -0
  361. endoreg_db/serializers/examination/__init__.py +10 -0
  362. endoreg_db/serializers/examination/base.py +46 -0
  363. endoreg_db/serializers/examination/dropdown.py +21 -0
  364. endoreg_db/serializers/examination_serializer.py +12 -0
  365. endoreg_db/serializers/finding/__init__.py +5 -0
  366. endoreg_db/serializers/finding/finding.py +54 -0
  367. endoreg_db/serializers/finding_classification/__init__.py +7 -0
  368. endoreg_db/serializers/finding_classification/choice.py +19 -0
  369. endoreg_db/serializers/finding_classification/classification.py +13 -0
  370. endoreg_db/serializers/label/__init__.py +7 -0
  371. endoreg_db/serializers/label/image_classification_annotation.py +62 -0
  372. endoreg_db/serializers/label/label.py +15 -0
  373. endoreg_db/serializers/label_video_segment/__init__.py +7 -0
  374. endoreg_db/serializers/label_video_segment/_lvs_create.py +149 -0
  375. endoreg_db/serializers/label_video_segment/_lvs_update.py +138 -0
  376. endoreg_db/serializers/label_video_segment/_lvs_validate.py +149 -0
  377. endoreg_db/serializers/label_video_segment/label_video_segment.py +344 -0
  378. endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +99 -0
  379. endoreg_db/serializers/label_video_segment/label_video_segment_update.py +163 -0
  380. endoreg_db/serializers/meta/__init__.py +19 -0
  381. endoreg_db/serializers/meta/pdf_file_meta_extraction.py +115 -0
  382. endoreg_db/serializers/meta/report_meta.py +53 -0
  383. endoreg_db/serializers/meta/sensitive_meta_detail.py +162 -0
  384. endoreg_db/serializers/meta/sensitive_meta_update.py +148 -0
  385. endoreg_db/serializers/meta/sensitive_meta_verification.py +59 -0
  386. endoreg_db/serializers/meta/video_meta.py +39 -0
  387. endoreg_db/serializers/misc/__init__.py +14 -0
  388. endoreg_db/serializers/misc/file_overview.py +152 -0
  389. endoreg_db/serializers/misc/stats.py +33 -0
  390. endoreg_db/serializers/misc/translatable_field_mix_in.py +44 -0
  391. endoreg_db/serializers/misc/upload_job.py +71 -0
  392. endoreg_db/serializers/misc/vop_patient_data.py +120 -0
  393. endoreg_db/serializers/patient/__init__.py +11 -0
  394. endoreg_db/serializers/patient/patient.py +86 -0
  395. endoreg_db/serializers/patient/patient_dropdown.py +27 -0
  396. endoreg_db/serializers/patient_examination/__init__.py +7 -0
  397. endoreg_db/serializers/patient_examination/patient_examination.py +141 -0
  398. endoreg_db/serializers/patient_finding/__init__.py +15 -0
  399. endoreg_db/serializers/patient_finding/patient_finding.py +31 -0
  400. endoreg_db/serializers/patient_finding/patient_finding_classification.py +39 -0
  401. endoreg_db/serializers/patient_finding/patient_finding_detail.py +53 -0
  402. endoreg_db/serializers/patient_finding/patient_finding_intervention.py +26 -0
  403. endoreg_db/serializers/patient_finding/patient_finding_list.py +41 -0
  404. endoreg_db/serializers/patient_finding/patient_finding_write.py +126 -0
  405. endoreg_db/serializers/pdf/__init__.py +5 -0
  406. endoreg_db/serializers/pdf/anony_text_validation.py +85 -0
  407. endoreg_db/serializers/report/__init__.py +9 -0
  408. endoreg_db/serializers/report/mixins.py +45 -0
  409. endoreg_db/serializers/report/report.py +105 -0
  410. endoreg_db/serializers/report/report_list.py +22 -0
  411. endoreg_db/serializers/report/secure_file_url.py +26 -0
  412. endoreg_db/serializers/requirements/requirement_schema.py +25 -0
  413. endoreg_db/serializers/requirements/requirement_sets.py +29 -0
  414. endoreg_db/serializers/sensitive_meta_serializer.py +282 -0
  415. endoreg_db/serializers/video/__init__.py +7 -0
  416. endoreg_db/serializers/video/segmentation.py +263 -0
  417. endoreg_db/serializers/video/video_file_brief.py +10 -0
  418. endoreg_db/serializers/video/video_file_detail.py +83 -0
  419. endoreg_db/serializers/video/video_file_list.py +67 -0
  420. endoreg_db/serializers/video/video_metadata.py +105 -0
  421. endoreg_db/serializers/video/video_processing_history.py +153 -0
  422. endoreg_db/services/__init__.py +5 -0
  423. endoreg_db/services/anonymization.py +223 -0
  424. endoreg_db/services/examination_evaluation.py +149 -0
  425. endoreg_db/services/finding_description_service.py +0 -0
  426. endoreg_db/services/lookup_service.py +241 -0
  427. endoreg_db/services/lookup_store.py +122 -0
  428. endoreg_db/services/ollama_api_docs.py +1528 -0
  429. endoreg_db/services/pdf_import.py +963 -0
  430. endoreg_db/services/polling_coordinator.py +288 -0
  431. endoreg_db/services/pseudonym_service.py +89 -0
  432. endoreg_db/services/requirements_object.py +147 -0
  433. endoreg_db/services/segment_sync.py +155 -0
  434. endoreg_db/services/storage_aware_video_processor.py +344 -0
  435. endoreg_db/services/video_import.py +1118 -0
  436. endoreg_db/tasks/upload_tasks.py +207 -0
  437. endoreg_db/tasks/video_ingest.py +157 -0
  438. endoreg_db/tasks/video_processing_tasks.py +327 -0
  439. endoreg_db/urls/__init__.py +70 -0
  440. endoreg_db/urls/anonymization.py +32 -0
  441. endoreg_db/urls/auth.py +16 -0
  442. endoreg_db/urls/classification.py +39 -0
  443. endoreg_db/urls/examination.py +54 -0
  444. endoreg_db/urls/files.py +6 -0
  445. endoreg_db/urls/label_video_segment_validate.py +33 -0
  446. endoreg_db/urls/label_video_segments.py +44 -0
  447. endoreg_db/urls/media.py +229 -0
  448. endoreg_db/urls/patient.py +19 -0
  449. endoreg_db/urls/report.py +48 -0
  450. endoreg_db/urls/requirements.py +13 -0
  451. endoreg_db/urls/stats.py +46 -0
  452. endoreg_db/urls/upload.py +20 -0
  453. endoreg_db/urls/video.py +61 -0
  454. endoreg_db/urls.py +6 -283
  455. endoreg_db/utils/__init__.py +66 -57
  456. endoreg_db/utils/ai/__init__.py +9 -0
  457. endoreg_db/{models/ai_model/utils.py → utils/ai/get.py} +1 -4
  458. endoreg_db/{models/ai_model/lightning → utils/ai}/inference_dataset.py +0 -1
  459. endoreg_db/{models/ai_model/lightning → utils/ai}/multilabel_classification_net.py +14 -10
  460. endoreg_db/{models/ai_model/lightning → utils/ai}/postprocess.py +15 -5
  461. endoreg_db/utils/ai/predict.py +291 -0
  462. endoreg_db/{models/ai_model/lightning → utils/ai}/preprocess.py +1 -1
  463. endoreg_db/utils/calc_duration_seconds.py +24 -0
  464. endoreg_db/utils/case_generator/__init__.py +0 -0
  465. endoreg_db/utils/check_video_files.py +148 -0
  466. endoreg_db/utils/dataloader.py +50 -12
  467. endoreg_db/utils/dates.py +21 -0
  468. endoreg_db/utils/env.py +33 -0
  469. endoreg_db/utils/extract_specific_frames.py +72 -0
  470. endoreg_db/utils/file_operations.py +29 -1
  471. endoreg_db/utils/fix_video_path_direct.py +141 -0
  472. endoreg_db/utils/frame_anonymization_utils.py +463 -0
  473. endoreg_db/utils/links/__init__.py +0 -0
  474. endoreg_db/utils/links/requirement_link.py +193 -0
  475. endoreg_db/utils/mime_types.py +0 -0
  476. endoreg_db/utils/names.py +2 -0
  477. endoreg_db/utils/paths.py +100 -82
  478. endoreg_db/utils/permissions.py +143 -0
  479. endoreg_db/utils/pipelines/Readme.md +235 -0
  480. endoreg_db/utils/pipelines/__init__.py +0 -0
  481. endoreg_db/utils/pipelines/process_video_dir.py +120 -0
  482. endoreg_db/utils/product/__init__.py +0 -0
  483. endoreg_db/utils/product/sum_emissions.py +20 -0
  484. endoreg_db/utils/product/sum_weights.py +18 -0
  485. endoreg_db/utils/pydantic_models/db_config.py +1 -1
  486. endoreg_db/utils/requirement_helpers.py +0 -0
  487. endoreg_db/utils/requirement_operator_logic/__init__.py +0 -0
  488. endoreg_db/utils/requirement_operator_logic/lab_value_operators.py +578 -0
  489. endoreg_db/utils/requirement_operator_logic/model_evaluators.py +368 -0
  490. endoreg_db/utils/translation.py +27 -0
  491. endoreg_db/utils/validate_video_detailed.py +357 -0
  492. endoreg_db/utils/video/__init__.py +19 -6
  493. endoreg_db/utils/video/extract_frames.py +37 -70
  494. endoreg_db/utils/video/ffmpeg_wrapper.py +772 -0
  495. endoreg_db/utils/video/names.py +42 -0
  496. endoreg_db/utils/video/streaming_processor.py +312 -0
  497. endoreg_db/utils/video/video_splitter.py +94 -0
  498. endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +238 -0
  499. endoreg_db/views/__init__.py +282 -2
  500. endoreg_db/views/anonymization/__init__.py +27 -0
  501. endoreg_db/views/anonymization/media_management.py +454 -0
  502. endoreg_db/views/anonymization/overview.py +216 -0
  503. endoreg_db/views/anonymization/validate.py +66 -0
  504. endoreg_db/views/auth/__init__.py +13 -0
  505. endoreg_db/views/{views.py → auth/keycloak.py} +19 -13
  506. endoreg_db/views/examination/__init__.py +33 -0
  507. endoreg_db/views/examination/examination.py +37 -0
  508. endoreg_db/views/examination/examination_manifest_cache.py +26 -0
  509. endoreg_db/views/examination/get_finding_classification_choices.py +59 -0
  510. endoreg_db/views/examination/get_finding_classifications.py +36 -0
  511. endoreg_db/views/examination/get_findings.py +41 -0
  512. endoreg_db/views/examination/get_instruments.py +18 -0
  513. endoreg_db/views/examination/get_interventions.py +14 -0
  514. endoreg_db/views/finding/__init__.py +9 -0
  515. endoreg_db/views/finding/finding.py +112 -0
  516. endoreg_db/views/finding/get_classifications.py +14 -0
  517. endoreg_db/views/finding/get_interventions.py +17 -0
  518. endoreg_db/views/finding_classification/__init__.py +13 -0
  519. endoreg_db/views/finding_classification/base.py +0 -0
  520. endoreg_db/views/finding_classification/finding_classification.py +42 -0
  521. endoreg_db/views/finding_classification/get_classification_choices.py +55 -0
  522. endoreg_db/views/label/__init__.py +5 -0
  523. endoreg_db/views/label/label.py +15 -0
  524. endoreg_db/views/label_video_segment/__init__.py +16 -0
  525. endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +44 -0
  526. endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +50 -0
  527. endoreg_db/views/label_video_segment/label_video_segment.py +77 -0
  528. endoreg_db/views/label_video_segment/label_video_segment_by_label.py +174 -0
  529. endoreg_db/views/label_video_segment/label_video_segment_detail.py +73 -0
  530. endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +46 -0
  531. endoreg_db/views/label_video_segment/validate.py +226 -0
  532. endoreg_db/views/media/__init__.py +45 -0
  533. endoreg_db/views/media/pdf_media.py +386 -0
  534. endoreg_db/views/media/segments.py +71 -0
  535. endoreg_db/views/media/sensitive_metadata.py +314 -0
  536. endoreg_db/views/media/video_media.py +272 -0
  537. endoreg_db/views/media/video_segments.py +596 -0
  538. endoreg_db/views/meta/__init__.py +15 -0
  539. endoreg_db/views/meta/available_files_list.py +146 -0
  540. endoreg_db/views/meta/report_meta.py +53 -0
  541. endoreg_db/views/meta/sensitive_meta_detail.py +148 -0
  542. endoreg_db/views/meta/sensitive_meta_list.py +104 -0
  543. endoreg_db/views/meta/sensitive_meta_verification.py +71 -0
  544. endoreg_db/views/misc/__init__.py +63 -0
  545. endoreg_db/views/misc/center.py +13 -0
  546. endoreg_db/views/misc/gender.py +14 -0
  547. endoreg_db/views/misc/secure_file_serving_view.py +80 -0
  548. endoreg_db/views/misc/secure_file_url_view.py +84 -0
  549. endoreg_db/views/misc/secure_url_validate.py +79 -0
  550. endoreg_db/views/misc/stats.py +220 -0
  551. endoreg_db/views/misc/translation.py +182 -0
  552. endoreg_db/views/misc/upload_views.py +240 -0
  553. endoreg_db/views/patient/__init__.py +5 -0
  554. endoreg_db/views/patient/patient.py +210 -0
  555. endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +164 -0
  556. endoreg_db/views/patient_examination/__init__.py +11 -0
  557. endoreg_db/views/patient_examination/patient_examination.py +140 -0
  558. endoreg_db/views/patient_examination/patient_examination_create.py +63 -0
  559. endoreg_db/views/patient_examination/patient_examination_detail.py +66 -0
  560. endoreg_db/views/patient_examination/patient_examination_list.py +68 -0
  561. endoreg_db/views/patient_examination/video.py +194 -0
  562. endoreg_db/views/patient_finding/__init__.py +7 -0
  563. endoreg_db/views/patient_finding/base.py +0 -0
  564. endoreg_db/views/patient_finding/patient_finding.py +64 -0
  565. endoreg_db/views/patient_finding/patient_finding_optimized.py +259 -0
  566. endoreg_db/views/patient_finding_classification/__init__.py +5 -0
  567. endoreg_db/views/patient_finding_classification/pfc_create.py +67 -0
  568. endoreg_db/views/patient_finding_location/__init__.py +5 -0
  569. endoreg_db/views/patient_finding_location/pfl_create.py +70 -0
  570. endoreg_db/views/patient_finding_morphology/__init__.py +5 -0
  571. endoreg_db/views/patient_finding_morphology/pfm_create.py +70 -0
  572. endoreg_db/views/pdf/__init__.py +11 -0
  573. endoreg_db/views/pdf/pdf_media.py +239 -0
  574. endoreg_db/views/pdf/pdf_stream_views.py +127 -0
  575. endoreg_db/views/pdf/reimport.py +161 -0
  576. endoreg_db/views/report/__init__.py +9 -0
  577. endoreg_db/views/report/report_list.py +112 -0
  578. endoreg_db/views/report/report_with_secure_url.py +28 -0
  579. endoreg_db/views/report/start_examination.py +7 -0
  580. endoreg_db/views/requirement/__init__.py +10 -0
  581. endoreg_db/views/requirement/evaluate.py +279 -0
  582. endoreg_db/views/requirement/lookup.py +483 -0
  583. endoreg_db/views/requirement/lookup_store.py +252 -0
  584. endoreg_db/views/requirement_lookup/lookup.py +0 -0
  585. endoreg_db/views/requirement_lookup/lookup_store.py +0 -0
  586. endoreg_db/views/stats/__init__.py +13 -0
  587. endoreg_db/views/stats/stats_views.py +229 -0
  588. endoreg_db/views/video/__init__.py +64 -0
  589. endoreg_db/views/video/correction.py +672 -0
  590. endoreg_db/views/video/reimport.py +195 -0
  591. endoreg_db/views/video/segmentation.py +274 -0
  592. endoreg_db/views/video/task_status.py +49 -0
  593. endoreg_db/views/{views_for_timeline.py → video/timeline.py} +3 -3
  594. endoreg_db/views/video/video_analyze.py +52 -0
  595. endoreg_db/views/video/video_apply_mask.py +48 -0
  596. endoreg_db/views/video/video_correction.py +21 -0
  597. endoreg_db/views/video/video_download_processed.py +58 -0
  598. endoreg_db/views/video/video_examination_viewset.py +329 -0
  599. endoreg_db/views/video/video_media.py +158 -0
  600. endoreg_db/views/video/video_meta.py +29 -0
  601. endoreg_db/views/video/video_processing_history.py +24 -0
  602. endoreg_db/views/video/video_remove_frames.py +48 -0
  603. endoreg_db/views/video/video_reprocess.py +40 -0
  604. endoreg_db/views/video/video_stream.py +306 -0
  605. endoreg_db-0.8.2.dist-info/METADATA +384 -0
  606. endoreg_db-0.8.2.dist-info/RECORD +790 -0
  607. endoreg_db/data/agl_service/data.yaml +0 -19
  608. endoreg_db/data/finding_location_classification/colonoscopy.yaml +0 -46
  609. endoreg_db/data/finding_morphology_classification/colonoscopy.yaml +0 -48
  610. endoreg_db/data/finding_morphology_classification_choice/colonoscopy_size.yaml +0 -57
  611. endoreg_db/management/commands/_load_model_template.py +0 -41
  612. endoreg_db/management/commands/delete_all.py +0 -18
  613. endoreg_db/management/commands/fetch_legacy_image_dataset.py +0 -32
  614. endoreg_db/management/commands/fix_auth_permission.py +0 -20
  615. endoreg_db/management/commands/load_active_model_data.py +0 -45
  616. endoreg_db/management/commands/load_g_play_data.py +0 -113
  617. endoreg_db/management/commands/load_logging_data.py +0 -39
  618. endoreg_db/management/commands/load_lx_data.py +0 -64
  619. endoreg_db/management/commands/load_medication_indication_data.py +0 -63
  620. endoreg_db/management/commands/load_medication_indication_type_data.py +0 -41
  621. endoreg_db/management/commands/load_medication_intake_time_data.py +0 -41
  622. endoreg_db/management/commands/load_medication_schedule_data.py +0 -55
  623. endoreg_db/management/commands/load_network_data.py +0 -57
  624. endoreg_db/migrations/0002_alter_frame_image_alter_rawframe_image.py +0 -23
  625. endoreg_db/migrations/0003_alter_frame_image_alter_rawframe_image.py +0 -23
  626. endoreg_db/migrations/0004_alter_rawvideofile_file_alter_video_file.py +0 -25
  627. endoreg_db/migrations/0005_rawvideofile_frame_count_and_more.py +0 -33
  628. endoreg_db/migrations/0006_frame_extracted_rawframe_extracted.py +0 -23
  629. endoreg_db/migrations/0007_rename_pseudo_patient_video_patient_and_more.py +0 -24
  630. endoreg_db/migrations/0008_remove_reportfile_patient_examination_and_more.py +0 -48
  631. endoreg_db/migrations/0009_requirementoperator_requirementsettype_and_more.py +0 -154
  632. endoreg_db/models/ai_model/active_model.py +0 -9
  633. endoreg_db/models/ai_model/ai_model.py +0 -90
  634. endoreg_db/models/ai_model/lightning/__init__.py +0 -3
  635. endoreg_db/models/ai_model/lightning/predict.py +0 -172
  636. endoreg_db/models/ai_model/lightning/prediction_visualizer.py +0 -55
  637. endoreg_db/models/ai_model/lightning/run_visualizer.py +0 -21
  638. endoreg_db/models/ai_model/model_meta.py +0 -240
  639. endoreg_db/models/annotation/__init__.py +0 -32
  640. endoreg_db/models/annotation/anonymized_image_annotation.py +0 -115
  641. endoreg_db/models/annotation/binary_classification_annotation_task.py +0 -117
  642. endoreg_db/models/annotation/image_classification.py +0 -86
  643. endoreg_db/models/annotation/video_segmentation_annotation.py +0 -52
  644. endoreg_db/models/case/__init__.py +0 -1
  645. endoreg_db/models/case/case.py +0 -34
  646. endoreg_db/models/center/center.py +0 -51
  647. endoreg_db/models/center/center_product.py +0 -33
  648. endoreg_db/models/center/center_waste.py +0 -16
  649. endoreg_db/models/data_file/__init__.py +0 -39
  650. endoreg_db/models/data_file/base_classes/__init__.py +0 -7
  651. endoreg_db/models/data_file/base_classes/abstract_frame.py +0 -98
  652. endoreg_db/models/data_file/base_classes/abstract_pdf.py +0 -127
  653. endoreg_db/models/data_file/base_classes/abstract_video.py +0 -806
  654. endoreg_db/models/data_file/base_classes/frame_helpers.py +0 -17
  655. endoreg_db/models/data_file/base_classes/prepare_bulk_frames.py +0 -19
  656. endoreg_db/models/data_file/base_classes/utils.py +0 -58
  657. endoreg_db/models/data_file/frame.py +0 -29
  658. endoreg_db/models/data_file/import_classes/__init__.py +0 -18
  659. endoreg_db/models/data_file/import_classes/processing_functions/__init__.py +0 -35
  660. endoreg_db/models/data_file/import_classes/processing_functions/pdf.py +0 -28
  661. endoreg_db/models/data_file/import_classes/processing_functions/video.py +0 -260
  662. endoreg_db/models/data_file/import_classes/raw_pdf.py +0 -254
  663. endoreg_db/models/data_file/import_classes/raw_video.py +0 -290
  664. endoreg_db/models/data_file/metadata/sensitive_meta.py +0 -290
  665. endoreg_db/models/data_file/metadata/video_meta.py +0 -199
  666. endoreg_db/models/data_file/report_file.py +0 -56
  667. endoreg_db/models/data_file/video/__init__.py +0 -11
  668. endoreg_db/models/data_file/video/import_meta.py +0 -25
  669. endoreg_db/models/data_file/video/video.py +0 -196
  670. endoreg_db/models/data_file/video_segment.py +0 -214
  671. endoreg_db/models/examination/examination.py +0 -67
  672. endoreg_db/models/finding/__init__.py +0 -11
  673. endoreg_db/models/finding/finding.py +0 -75
  674. endoreg_db/models/finding/finding_location_classification.py +0 -94
  675. endoreg_db/models/finding/finding_morphology_classification.py +0 -89
  676. endoreg_db/models/finding/finding_type.py +0 -22
  677. endoreg_db/models/hardware/__init__.py +0 -2
  678. endoreg_db/models/information_source.py +0 -65
  679. endoreg_db/models/laboratory/__init__.py +0 -1
  680. endoreg_db/models/laboratory/lab_value.py +0 -162
  681. endoreg_db/models/logging/__init__.py +0 -11
  682. endoreg_db/models/logging/agl_service.py +0 -19
  683. endoreg_db/models/logging/base.py +0 -22
  684. endoreg_db/models/logging/log_type.py +0 -23
  685. endoreg_db/models/logging/network_device.py +0 -27
  686. endoreg_db/models/lx/__init__.py +0 -4
  687. endoreg_db/models/lx/client.py +0 -57
  688. endoreg_db/models/lx/identity.py +0 -34
  689. endoreg_db/models/lx/permission.py +0 -18
  690. endoreg_db/models/lx/user.py +0 -16
  691. endoreg_db/models/network/__init__.py +0 -9
  692. endoreg_db/models/network/agl_service.py +0 -38
  693. endoreg_db/models/network/network_device.py +0 -58
  694. endoreg_db/models/network/network_device_type.py +0 -23
  695. endoreg_db/models/other/distribution.py +0 -5
  696. endoreg_db/models/patient/__init__.py +0 -24
  697. endoreg_db/models/patient/patient_examination.py +0 -182
  698. endoreg_db/models/patient/patient_finding.py +0 -143
  699. endoreg_db/models/patient/patient_finding_location.py +0 -120
  700. endoreg_db/models/patient/patient_finding_morphology.py +0 -166
  701. endoreg_db/models/permissions/__init__.py +0 -44
  702. endoreg_db/models/persons/__init__.py +0 -34
  703. endoreg_db/models/persons/examiner/__init__.py +0 -2
  704. endoreg_db/models/persons/examiner/examiner.py +0 -60
  705. endoreg_db/models/persons/examiner/examiner_type.py +0 -2
  706. endoreg_db/models/persons/patient/__init__.py +0 -8
  707. endoreg_db/models/persons/patient/patient.py +0 -389
  708. endoreg_db/models/persons/patient/patient_disease.py +0 -22
  709. endoreg_db/models/persons/patient/patient_event.py +0 -52
  710. endoreg_db/models/persons/patient/patient_lab_sample.py +0 -108
  711. endoreg_db/models/persons/patient/patient_medication.py +0 -59
  712. endoreg_db/models/persons/patient/patient_medication_schedule.py +0 -88
  713. endoreg_db/models/persons/portal_user_information.py +0 -27
  714. endoreg_db/models/prediction/__init__.py +0 -8
  715. endoreg_db/models/prediction/image_classification.py +0 -51
  716. endoreg_db/models/prediction/video_prediction_meta.py +0 -306
  717. endoreg_db/models/product/product.py +0 -110
  718. endoreg_db/models/product/product_group.py +0 -27
  719. endoreg_db/models/product/product_material.py +0 -28
  720. endoreg_db/models/questionnaires/__init__.py +0 -114
  721. endoreg_db/models/quiz/__init__.py +0 -9
  722. endoreg_db/models/quiz/quiz_answer.py +0 -41
  723. endoreg_db/models/quiz/quiz_question.py +0 -54
  724. endoreg_db/models/report_reader/report_reader_config.py +0 -53
  725. endoreg_db/models/rules/__init__.py +0 -5
  726. endoreg_db/queries/get/__init__.py +0 -6
  727. endoreg_db/queries/get/center.py +0 -42
  728. endoreg_db/queries/get/model.py +0 -13
  729. endoreg_db/queries/get/patient.py +0 -14
  730. endoreg_db/queries/get/patient_examination.py +0 -20
  731. endoreg_db/queries/get/report_file.py +0 -33
  732. endoreg_db/queries/get/video.py +0 -31
  733. endoreg_db/serializers/ai_model.py +0 -19
  734. endoreg_db/serializers/annotation.py +0 -14
  735. endoreg_db/serializers/center.py +0 -11
  736. endoreg_db/serializers/examination.py +0 -33
  737. endoreg_db/serializers/frame.py +0 -9
  738. endoreg_db/serializers/hardware.py +0 -21
  739. endoreg_db/serializers/label.py +0 -22
  740. endoreg_db/serializers/patient.py +0 -33
  741. endoreg_db/serializers/prediction.py +0 -10
  742. endoreg_db/serializers/raw_pdf_anony_text_validation.py +0 -137
  743. endoreg_db/serializers/report_file.py +0 -7
  744. endoreg_db/serializers/video.py +0 -20
  745. endoreg_db/serializers/video_segmentation.py +0 -574
  746. endoreg_db/tests.py +0 -3
  747. endoreg_db/utils/legacy_ocr.py +0 -201
  748. endoreg_db/utils/video/transcode_videofile.py +0 -111
  749. endoreg_db/views/patient_views.py +0 -90
  750. endoreg_db/views/raw_pdf_anony_text_validation_views.py +0 -95
  751. endoreg_db/views/raw_pdf_meta_validation_views.py +0 -111
  752. endoreg_db/views/raw_video_meta_validation_views.py +0 -148
  753. endoreg_db/views/report_views.py +0 -96
  754. endoreg_db/views/video_segmentation_views.py +0 -166
  755. endoreg_db-0.6.4.dist-info/METADATA +0 -161
  756. endoreg_db-0.6.4.dist-info/RECORD +0 -470
  757. /endoreg_db/{case_generator/__init__.py → api/serializers/finding_descriptions.py} +0 -0
  758. /endoreg_db/{queries/get/annotation.py → api/views/finding_descriptions.py} +0 -0
  759. /endoreg_db/{queries/get/prediction.py → data/shift/m2.yaml} +0 -0
  760. /endoreg_db/{queries/get/video_import_meta.py → factories/__init__.py} +0 -0
  761. /endoreg_db/{queries/get/video_prediction_meta.py → helpers/__init__.py} +0 -0
  762. /endoreg_db/models/{case_template → administration/case/case_template}/__init__.py +0 -0
  763. /endoreg_db/models/{persons → administration/person}/person.py +0 -0
  764. /endoreg_db/models/{product → administration/product}/__init__.py +0 -0
  765. /endoreg_db/models/{report_reader → media/pdf/report_reader}/__init__.py +0 -0
  766. /endoreg_db/models/{report_reader → media/pdf/report_reader}/report_reader_flag.py +0 -0
  767. /endoreg_db/models/{hardware → medical/hardware}/endoscopy_processor.py +0 -0
  768. /endoreg_db/models/{medication → medical/medication}/__init__.py +0 -0
  769. /endoreg_db/models/{medication → medical/medication}/medication_indication.py +0 -0
  770. /endoreg_db/models/{risk → medical/risk}/__init__.py +0 -0
  771. /endoreg_db/models/{risk → medical/risk}/risk.py +0 -0
  772. /endoreg_db/models/{emission → other/emission}/__init__.py +0 -0
  773. /endoreg_db/models/{rules → rule}/rule_applicator.py +0 -0
  774. /endoreg_db/{case_generator → utils/case_generator}/case_generator.py +0 -0
  775. /endoreg_db/{case_generator → utils/case_generator}/lab_sample_factory.py +0 -0
  776. /endoreg_db/{case_generator → utils/case_generator}/utils.py +0 -0
  777. /endoreg_db/views/{csrf.py → misc/csrf.py} +0 -0
  778. {endoreg_db-0.6.4.dist-info → endoreg_db-0.8.2.dist-info}/WHEEL +0 -0
  779. {endoreg_db-0.6.4.dist-info → endoreg_db-0.8.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,67 +1,46 @@
1
1
  from django.db import models
2
- from typing import TYPE_CHECKING, Optional
2
+ from typing import TYPE_CHECKING, Dict, List, Union
3
+ from endoreg_db.utils.links.requirement_link import RequirementLinks
4
+ import logging
5
+ from subprocess import run
6
+
7
+ logger = logging.getLogger(__name__)
3
8
 
4
- from pydantic import BaseModel
5
9
 
6
10
  QuerySet = models.QuerySet
7
11
 
8
12
  if TYPE_CHECKING:
9
13
  from endoreg_db.models import (
10
- RequirementOperator,
11
- RequirementSet,
12
- Examination,
13
- ExaminationIndication,
14
- LabValue,
15
14
  Disease,
16
15
  DiseaseClassificationChoice,
17
16
  Event,
17
+ EventClassification,
18
+ EventClassificationChoice,
19
+ Examination,
20
+ ExaminationIndication,
18
21
  Finding,
19
- FindingMorphologyClassificationChoice,
20
- FindingLocationClassificationChoice,
21
22
  FindingIntervention,
23
+ FindingClassification,
24
+ FindingClassificationChoice,
25
+ FindingClassificationType,
26
+ LabValue,
27
+ Medication,
28
+ MedicationIndication,
29
+ MedicationIntakeTime, # Added MedicationIntakeTime
30
+ MedicationSchedule,
31
+ PatientDisease,
32
+ PatientEvent,
33
+ PatientExamination,
34
+ PatientFinding,
35
+ PatientFindingIntervention,
36
+ PatientFindingClassification,
37
+ PatientLabValue,
38
+ PatientMedicationSchedule, # Added PatientMedicationSchedule
39
+ RequirementOperator,
40
+ RequirementSet,
41
+ Gender
22
42
  )
23
-
24
-
25
- class RequirementsModelDict(BaseModel):
26
- """
27
- A class representing a dictionary of models related to a requirement.
28
-
29
- Attributes:
30
- requirement_types (QuerySet[RequirementType]): A queryset of requirement types.
31
- operators (QuerySet[RequirementOperator]): A queryset of operators.
32
- requirement_sets (QuerySet[RequirementSet]): A queryset of requirement sets.
33
- examinations (QuerySet[Examination]): A queryset of examinations.
34
- examination_indications (QuerySet[ExaminationIndication]): A queryset of examination indications.
35
- lab_values (QuerySet[LabValue]): A queryset of lab values.
36
- diseases (QuerySet[Disease]): A queryset of diseases.
37
- disease_classification_choices (QuerySet[DiseaseClassificationChoice]): A queryset of disease classification choices.
38
- events (QuerySet[Event]): A queryset of events.
39
- findings (QuerySet[Finding]): A queryset of findings.
40
- finding_morphology_classification_choices (QuerySet[FindingMorphologyClassificationChoice]): A queryset of finding morphology classification choices.
41
- finding_location_classification_choices (QuerySet[FindingLocationClassificationChoice]): A queryset of finding location classification choices.
42
- finding_interventions (QuerySet[FindingIntervention]): A queryset of finding interventions.
43
- """
44
-
45
- model_config = {"arbitrary_types_allowed": True}
46
- requirement_types: Optional[QuerySet["RequirementType"]] = None
47
- operators: Optional[QuerySet["RequirementOperator"]] = None
48
- requirement_sets: Optional[QuerySet["RequirementSet"]] = None
49
- examinations: Optional[QuerySet["Examination"]] = None
50
- examination_indications: Optional[QuerySet["ExaminationIndication"]] = None
51
- lab_values: Optional[QuerySet["LabValue"]] = None
52
- diseases: Optional[QuerySet["Disease"]] = None
53
- disease_classification_choices: Optional[
54
- QuerySet["DiseaseClassificationChoice"]
55
- ] = None
56
- events: Optional[QuerySet["Event"]] = None
57
- findings: Optional[QuerySet["Finding"]] = None
58
- finding_morphology_classification_choices: Optional[
59
- QuerySet["FindingMorphologyClassificationChoice"]
60
- ] = None
61
- finding_location_classification_choices: Optional[
62
- QuerySet["FindingLocationClassificationChoice"]
63
- ] = None
64
- finding_interventions: Optional[QuerySet["FindingIntervention"]] = None
43
+ # from endoreg_db.utils.links.requirement_link import RequirementLinks # Already imported above
65
44
 
66
45
 
67
46
  class RequirementTypeManager(models.Manager):
@@ -86,13 +65,9 @@ class RequirementType(models.Model):
86
65
 
87
66
  Attributes:
88
67
  name (str): The name of the requirement type.
89
- name_de (str): The German name of the requirement type.
90
- name_en (str): The English name of the requirement type.
91
68
  """
92
69
 
93
70
  name = models.CharField(max_length=100, unique=True)
94
- name_de = models.CharField(max_length=100, blank=True, null=True)
95
- name_en = models.CharField(max_length=100, blank=True, null=True)
96
71
  description = models.TextField(blank=True, null=True)
97
72
 
98
73
  objects = RequirementTypeManager()
@@ -134,15 +109,12 @@ class Requirement(models.Model):
134
109
 
135
110
  Attributes:
136
111
  name (str): The name of the requirement.
137
- name_de (str): The German name of the requirement.
138
- name_en (str): The English name of the requirement.
139
112
  description (str): A description of the requirement.
140
113
  """
141
114
 
142
115
  name = models.CharField(max_length=100, unique=True)
143
- name_de = models.CharField(max_length=100, blank=True, null=True)
144
- name_en = models.CharField(max_length=100, blank=True, null=True)
145
116
  description = models.TextField(blank=True, null=True)
117
+
146
118
  numeric_value = models.FloatField(
147
119
  blank=True,
148
120
  null=True,
@@ -175,13 +147,13 @@ class Requirement(models.Model):
175
147
 
176
148
  objects = RequirementManager()
177
149
 
178
- requirement_types = models.ManyToManyField(
150
+ requirement_types = models.ManyToManyField( # type: ignore[assignment]
179
151
  "RequirementType",
180
152
  blank=True,
181
153
  related_name="linked_requirements",
182
154
  )
183
155
 
184
- operators = models.ManyToManyField(
156
+ operators = models.ManyToManyField( # type: ignore[assignment]
185
157
  "RequirementOperator",
186
158
  blank=True,
187
159
  related_name="required_in",
@@ -195,66 +167,96 @@ class Requirement(models.Model):
195
167
  null=True,
196
168
  )
197
169
 
198
- examinations = models.ManyToManyField(
170
+ examinations = models.ManyToManyField( # type: ignore[assignment]
199
171
  "Examination",
200
172
  blank=True,
201
173
  related_name="required_in",
202
174
  )
203
175
 
204
- examination_indications = models.ManyToManyField(
176
+ examination_indications = models.ManyToManyField( # type: ignore[assignment]
205
177
  "ExaminationIndication",
206
178
  blank=True,
207
179
  related_name="required_in",
208
180
  )
209
181
 
210
- diseases = models.ManyToManyField(
182
+ diseases = models.ManyToManyField( # type: ignore[assignment]
211
183
  "Disease",
212
184
  blank=True,
213
185
  related_name="required_in",
214
186
  )
215
187
 
216
- disease_classification_choices = models.ManyToManyField(
188
+ disease_classification_choices = models.ManyToManyField( # type: ignore[assignment]
217
189
  "DiseaseClassificationChoice",
218
190
  blank=True,
219
191
  related_name="required_in",
220
192
  )
221
193
 
222
- events = models.ManyToManyField(
194
+ events = models.ManyToManyField( # type: ignore[assignment]
223
195
  "Event",
224
196
  blank=True,
225
197
  related_name="required_in",
226
198
  )
227
199
 
228
- lab_values = models.ManyToManyField(
200
+ lab_values = models.ManyToManyField( # type: ignore[assignment]
229
201
  "LabValue",
230
202
  blank=True,
231
203
  related_name="required_in",
232
204
  )
233
205
 
234
- findings = models.ManyToManyField(
206
+ findings = models.ManyToManyField( # type: ignore[assignment]
235
207
  "Finding",
236
208
  blank=True,
237
209
  related_name="required_in",
238
210
  )
239
211
 
240
- finding_morphology_classification_choices = models.ManyToManyField(
241
- "FindingMorphologyClassificationChoice",
212
+ finding_classifications = models.ManyToManyField( # type: ignore[assignment]
213
+ "FindingClassification",
242
214
  blank=True,
243
215
  related_name="required_in",
244
216
  )
245
217
 
246
- finding_location_classification_choices = models.ManyToManyField(
247
- "FindingLocationClassificationChoice",
218
+ finding_classification_choices = models.ManyToManyField( # type: ignore[assignment]
219
+ "FindingClassificationChoice",
248
220
  blank=True,
249
221
  related_name="required_in",
250
222
  )
251
223
 
252
- finding_interventions = models.ManyToManyField(
224
+ finding_interventions = models.ManyToManyField( # type: ignore[assignment]
253
225
  "FindingIntervention",
254
226
  blank=True,
255
227
  related_name="required_in",
256
228
  )
257
229
 
230
+ medications = models.ManyToManyField( # type: ignore[assignment]
231
+ "Medication",
232
+ blank=True,
233
+ related_name="required_in",
234
+ )
235
+
236
+ medication_indications = models.ManyToManyField( # type: ignore[assignment]
237
+ "MedicationIndication",
238
+ blank=True,
239
+ related_name="required_in",
240
+ )
241
+
242
+ medication_intake_times = models.ManyToManyField( # type: ignore[assignment]
243
+ "MedicationIntakeTime",
244
+ blank=True,
245
+ related_name="required_in",
246
+ )
247
+
248
+ medication_schedules = models.ManyToManyField( # type: ignore[assignment]
249
+ "MedicationSchedule",
250
+ blank=True,
251
+ related_name="required_in",
252
+ )
253
+
254
+ genders = models.ManyToManyField( # type: ignore[assignment]
255
+ "Gender",
256
+ blank=True,
257
+ related_name="required_in",
258
+ )
259
+
258
260
  if TYPE_CHECKING:
259
261
  requirement_types: models.QuerySet[RequirementType]
260
262
  operators: models.QuerySet[RequirementOperator]
@@ -266,60 +268,500 @@ class Requirement(models.Model):
266
268
  disease_classification_choices: models.QuerySet[DiseaseClassificationChoice]
267
269
  events: models.QuerySet[Event]
268
270
  findings: models.QuerySet[Finding]
269
- finding_morphology_classification_choices: models.QuerySet[
270
- FindingMorphologyClassificationChoice
271
- ]
272
- finding_location_classification_choices: models.QuerySet[
273
- FindingLocationClassificationChoice
274
- ]
271
+ finding_classifications: models.QuerySet[FindingClassification]
272
+ finding_classification_choices: models.QuerySet[FindingClassificationChoice]
275
273
  finding_interventions: models.QuerySet[FindingIntervention]
274
+ medications: models.QuerySet[Medication]
275
+ medication_indications: models.QuerySet[MedicationIndication]
276
+ medication_intake_times: models.QuerySet[MedicationIntakeTime] # Added type hint
277
+ medication_schedules: models.QuerySet[MedicationSchedule]
278
+ genders: models.QuerySet[Gender]
276
279
 
277
280
  def natural_key(self):
278
281
  """
279
- Return a tuple containing the natural key of the instance.
280
-
281
- The tuple, comprised solely of the instance's name, serves as an alternative unique identifier for serialization.
282
+ Returns a tuple containing the instance's name as its natural key.
283
+
284
+ This tuple provides a unique identifier for serialization purposes.
282
285
  """
283
286
  return (self.name,)
284
287
 
285
288
  def __str__(self):
286
- """Return the string representation of the requirement's name.
289
+ """Returns the name of the requirement as its string representation."""
290
+ return str(self.name)
287
291
 
288
- Returns:
289
- str: The name of the requirement.
292
+ @property
293
+ def expected_models(self) -> List[Union[
294
+ "Disease",
295
+ "DiseaseClassificationChoice",
296
+ "Event",
297
+ "EventClassification",
298
+ "EventClassificationChoice",
299
+ "Examination",
300
+ "ExaminationIndication",
301
+ "Finding",
302
+ "FindingIntervention",
303
+ "FindingClassification",
304
+ "FindingClassificationChoice",
305
+ "FindingClassificationType",
306
+ "LabValue",
307
+ "Medication",
308
+ "MedicationIndication",
309
+ "MedicationIntakeTime", # Added MedicationIntakeTime
310
+ "PatientDisease",
311
+ "PatientEvent",
312
+ "PatientExamination",
313
+ "PatientFinding",
314
+ "PatientFindingIntervention",
315
+ "PatientFindingClassification",
316
+ "PatientLabValue",
317
+ "PatientMedicationSchedule", # Added PatientMedicationSchedule
318
+ ]]:
290
319
  """
291
- return str(self.name)
320
+ Return the list of model classes that are expected as input for evaluating this requirement.
321
+
322
+ The returned models correspond to the requirement types linked to this requirement, mapped via the internal data model dictionary.
323
+ """
324
+ req_types = self.requirement_types.all()
325
+ req_type_names = [_.name for _ in req_types]
326
+
327
+ expected_models = [self.data_model_dict[_] for _ in req_type_names]
328
+ # e.g. [PatientExamination, PatientFinding]
329
+ return expected_models
292
330
 
293
- def get_models_dict(self) -> RequirementsModelDict:
331
+ @property
332
+ def links(self) -> "RequirementLinks":
294
333
  """
295
- Returns a RequirementsModelDict with querysets of all associated models.
296
-
297
- This method aggregates related models by invoking .all() on each
298
- many-to-many field of the requirement. The resulting RequirementsModelDict
299
- includes querysets for requirement types, operators, requirement sets,
300
- examinations, examination indications, lab values, diseases, disease
301
- classification choices, events, findings, finding morphology classification
302
- choices, finding location classification choices, and finding interventions.
334
+ Return a RequirementLinks object containing all non-null related model instances for this requirement.
335
+
336
+ The returned object provides structured access to all associated entities, such as examinations, diseases, findings, classifications, interventions, medications, and related choices, aggregated from the requirement's many-to-many fields.
303
337
  """
304
- models_dict = RequirementsModelDict(
305
- requirement_types=self.requirement_types.all(),
306
- operators=self.operators.all(),
307
- requirement_sets=self.requirement_sets.all(),
308
- examinations=self.examinations.all(),
309
- examination_indications=self.examination_indications.all(),
310
- lab_values=self.lab_values.all(),
311
- diseases=self.diseases.all(),
312
- disease_classification_choices=self.disease_classification_choices.all(),
313
- events=self.events.all(),
314
- findings=self.findings.all(),
315
- finding_morphology_classification_choices=self.finding_morphology_classification_choices.all(),
316
- finding_location_classification_choices=self.finding_location_classification_choices.all(),
317
- finding_interventions=self.finding_interventions.all(),
338
+ # requirement_sets is not part of RequirementLinks (avoids circular import); collect other related models
339
+ models_dict = RequirementLinks(
340
+ examinations=[_ for _ in self.examinations.all() if _ is not None],
341
+ examination_indications=[_ for _ in self.examination_indications.all() if _ is not None],
342
+ lab_values=[_ for _ in self.lab_values.all() if _ is not None],
343
+ diseases=[_ for _ in self.diseases.all() if _ is not None],
344
+ disease_classification_choices=[_ for _ in self.disease_classification_choices.all() if _ is not None],
345
+ events=[_ for _ in self.events.all() if _ is not None],
346
+ findings=[_ for _ in self.findings.all() if _ is not None],
347
+ finding_classifications=[_ for _ in self.finding_classifications.all() if _ is not None],
348
+ finding_classification_choices=[_ for _ in self.finding_classification_choices.all() if _ is not None],
349
+ finding_interventions=[_ for _ in self.finding_interventions.all() if _ is not None],
350
+ medications=[_ for _ in self.medications.all() if _ is not None],
351
+ medication_indications=[_ for _ in self.medication_indications.all() if _ is not None],
352
+ medication_intake_times=[_ for _ in self.medication_intake_times.all() if _ is not None],
318
353
  )
319
354
  return models_dict
320
355
 
321
- def evaluate(self, **kwargs):
322
- #TODO refactor after prototyping
323
- # from .requirement_evaluation.requirement_type_parser import get_input_data
324
-
325
- return_value = True
356
+ @property
357
+ def data_model_dict(self) -> dict:
358
+ """
359
+ Provides a mapping from requirement type names to their corresponding model classes.
360
+
361
+ Returns:
362
+ A dictionary where keys are requirement type names and values are model classes used for requirement evaluation.
363
+ """
364
+ from .requirement_evaluation.requirement_type_parser import data_model_dict
365
+ return data_model_dict
366
+
367
+ @property
368
+ def active_links(self) -> Dict[str, List]:
369
+ """Returns a dictionary of linked models containing only non-empty entries.
370
+
371
+ The returned dictionary includes only those related model lists that have at least one linked instance.
372
+ """
373
+ return self.links.active()
374
+
375
+
376
+ def evaluate(self, *args, mode:str, **kwargs):
377
+ """
378
+ Evaluates whether the requirement is satisfied for the given input models using linked operators and gender constraints.
379
+
380
+ Args:
381
+ *args: Instances or QuerySets of expected model classes to be evaluated. Each must have a `.links` property returning a `RequirementLinks` object.
382
+ mode: Evaluation mode; "strict" requires all operators to pass, "loose" requires any operator to pass.
383
+ **kwargs: Additional keyword arguments passed to operator evaluations.
384
+
385
+ Returns:
386
+ True if the requirement is satisfied according to the specified mode, linked operators, and gender restrictions; otherwise, False.
387
+
388
+ Raises:
389
+ ValueError: If an invalid mode is provided.
390
+ TypeError: If an input is not an instance or QuerySet of expected models, or lacks a valid `.links` attribute.
391
+
392
+ If the requirement specifies genders, only input containing a patient with a matching gender will be considered valid for evaluation.
393
+ """
394
+ #TODO Review, Optimize or remove
395
+ if mode not in ["strict", "loose"]:
396
+ raise ValueError(f"Invalid mode: {mode}. Use 'strict' or 'loose'.")
397
+
398
+ evaluate_result_list_func = all if mode == "strict" else any
399
+
400
+ requirement_req_links = self.links
401
+ expected_models = self.expected_models
402
+
403
+ # helpers to avoid passing a complex tuple to isinstance/issubclass which confuses type checkers
404
+ def _is_expected_instance(obj) -> bool:
405
+ for cls in expected_models:
406
+ if isinstance(cls, type):
407
+ try:
408
+ if isinstance(obj, cls):
409
+ return True
410
+ except Exception:
411
+ # cls might not be a runtime type
412
+ continue
413
+ return False
414
+
415
+ def _is_queryset_of_expected(qs) -> bool:
416
+ if not isinstance(qs, models.QuerySet) or not hasattr(qs, 'model'):
417
+ return False
418
+ for cls in expected_models:
419
+ if isinstance(cls, type):
420
+ try:
421
+ if issubclass(qs.model, cls):
422
+ return True
423
+ except Exception:
424
+ continue
425
+ return False
426
+
427
+ # Aggregate RequirementLinks from all input arguments
428
+ aggregated_input_links_data = {}
429
+ processed_inputs_count = 0
430
+
431
+ for _input in args:
432
+ # Check if the input is an instance of any of the expected model types
433
+ if not _is_expected_instance(_input):
434
+ # Allow QuerySets of expected models
435
+ if _is_queryset_of_expected(_input):
436
+ # For QuerySets, evaluate each item individually and return True if any matches
437
+ if not _input.exists(): # Skip empty querysets
438
+ continue
439
+
440
+ queryset_results = []
441
+ for item in _input:
442
+ if not hasattr(item, 'links') or not isinstance(item.links, RequirementLinks):
443
+ raise TypeError(
444
+ f"Item {item} of type {type(item)} in QuerySet does not have a valid .links attribute of type RequirementLinks."
445
+ )
446
+
447
+ # Evaluate this single item against the requirement
448
+ item_input_links = RequirementLinks(**item.links.active())
449
+
450
+ # Evaluate all operators for this single item
451
+ item_operator_results = []
452
+ for operator in self.operators.all():
453
+ try:
454
+ operator_result = operator.evaluate(
455
+ requirement_links=requirement_req_links,
456
+ input_links=item_input_links,
457
+ requirement=self,
458
+ original_input_args=args,
459
+ **kwargs
460
+ )
461
+ item_operator_results.append(operator_result)
462
+ except Exception as e:
463
+ logger.debug(f"Operator {operator.name} evaluation failed for item {item}: {e}")
464
+ item_operator_results.append(False)
465
+
466
+ # Apply evaluation mode for this single item
467
+ item_result = evaluate_result_list_func(item_operator_results) if item_operator_results else True
468
+ queryset_results.append(item_result)
469
+ processed_inputs_count += 1
470
+
471
+ # If any item in the QuerySet matches, return True for the whole QuerySet evaluation
472
+ if any(queryset_results):
473
+ return True
474
+ continue # Move to the next arg after processing queryset
475
+ else:
476
+ raise TypeError(
477
+ f"Input type {type(_input)} is not among expected models: {self.expected_models} "
478
+ f"nor a QuerySet of expected models."
479
+ )
480
+
481
+ # Process single model instance
482
+ if not hasattr(_input, 'links') or not isinstance(_input.links, RequirementLinks):
483
+ raise TypeError(
484
+ f"Input {_input} of type {type(_input)} does not have a valid .links attribute of type RequirementLinks."
485
+ )
486
+
487
+ active_input_links = _input.links.active() # Get dict of non-empty lists
488
+ for link_key, link_list in active_input_links.items():
489
+ if link_key not in aggregated_input_links_data:
490
+ aggregated_input_links_data[link_key] = []
491
+ aggregated_input_links_data[link_key].extend(link_list)
492
+ processed_inputs_count += 1
493
+
494
+ if not processed_inputs_count and args: # If args were provided but none were processable (e.g. all empty querysets)
495
+ # This situation implies no relevant data was provided for evaluation against the requirement.
496
+ # Depending on operator logic (e.g., "requires at least one matching item"), this might lead to False.
497
+ # For "models_match_any", an empty input_links will likely result in False if requirement_req_links is not empty.
498
+ pass
499
+
500
+
501
+ # Deduplicate items within each list after aggregation
502
+ for key in aggregated_input_links_data:
503
+ try:
504
+ # Using dict.fromkeys to preserve order and remove duplicates for hashable items
505
+ aggregated_input_links_data[key] = list(dict.fromkeys(aggregated_input_links_data[key]))
506
+ except TypeError:
507
+ # Fallback for non-hashable items (though Django models are hashable)
508
+ temp_list = []
509
+ for item in aggregated_input_links_data[key]:
510
+ if item not in temp_list:
511
+ temp_list.append(item)
512
+ aggregated_input_links_data[key] = temp_list
513
+
514
+ final_input_links = RequirementLinks(**aggregated_input_links_data)
515
+
516
+ # Gender strict check: if this requirement has genders, only pass if patient.gender is in the set
517
+ genders_exist = self.genders.exists()
518
+ if genders_exist:
519
+ # Import here to avoid circular import
520
+ from endoreg_db.models.administration.person.patient import Patient
521
+ patient = None
522
+ for arg in args:
523
+ if isinstance(arg, Patient):
524
+ patient = arg
525
+ break
526
+ if patient is None or patient.gender is None:
527
+ return False
528
+ if not self.genders.filter(pk=patient.gender.pk).exists():
529
+ return False
530
+
531
+ operators = self.operators.all()
532
+ if not operators.exists(): # If a requirement has no operators, its evaluation is ambiguous.
533
+ # Consider if this should be True, False, or an error.
534
+ # For now, if no operators, and mode is strict, it's vacuously true. If loose, vacuously false.
535
+ # However, typically a requirement implies some condition.
536
+ # Let's assume if no operators, it cannot be satisfied unless it also has no specific links.
537
+ # This behavior might need further refinement based on business logic.
538
+ if not requirement_req_links.active(): # No conditions in requirement
539
+ return True # Vacuously true if requirement itself is empty
540
+ return False # Cannot be satisfied if requirement has conditions but no operators to check them
541
+
542
+
543
+ operator_results = []
544
+ for operator in operators:
545
+ # Prepare kwargs for the operator, including the current Requirement instance
546
+ op_kwargs = kwargs.copy() # Start with kwargs passed to Requirement.evaluate
547
+ op_kwargs['requirement'] = self # Add the Requirement instance itself
548
+ op_kwargs['original_input_args'] = args # Add the original input arguments for operators that need them (e.g., age operators)
549
+ operator_results.append(operator.evaluate(
550
+ requirement_links=requirement_req_links,
551
+ input_links=final_input_links,
552
+ **op_kwargs
553
+ ))
554
+
555
+ is_valid = evaluate_result_list_func(operator_results)
556
+
557
+ return is_valid
558
+
559
+ def evaluate_with_details(self, *args, mode:str, **kwargs):
560
+ """
561
+ Evaluates whether the requirement is satisfied for the given input models using linked operators and gender constraints.
562
+
563
+ Args:
564
+ *args: Instances or QuerySets of expected model classes to be evaluated. Each must have a `.links` property returning a `RequirementLinks` object.
565
+ mode: Evaluation mode; "strict" requires all operators to pass, "loose" requires any operator to pass.
566
+ **kwargs: Additional keyword arguments passed to operator evaluations.
567
+
568
+ Returns:
569
+ True if the requirement is satisfied according to the specified mode, linked operators, and gender restrictions; otherwise, False.
570
+
571
+ Raises:
572
+ ValueError: If an invalid mode is provided.
573
+ TypeError: If an input is not an instance or QuerySet of expected models, or lacks a valid `.links` attribute.
574
+
575
+ If the requirement specifies genders, only input containing a patient with a matching gender will be considered valid for evaluation.
576
+ """
577
+ #TODO Review, Optimize or remove
578
+ if mode not in ["strict", "loose"]:
579
+ raise ValueError(f"Invalid mode: {mode}. Use 'strict' or 'loose'.")
580
+
581
+ evaluate_result_list_func = all if mode == "strict" else any
582
+
583
+ requirement_req_links = self.links
584
+ expected_models = self.expected_models
585
+
586
+ # helpers to avoid passing a complex tuple to isinstance/issubclass which confuses type checkers
587
+ def _is_expected_instance(obj) -> bool:
588
+ for cls in expected_models:
589
+ if isinstance(cls, type):
590
+ try:
591
+ if isinstance(obj, cls):
592
+ return True
593
+ except Exception:
594
+ # cls might not be a runtime type
595
+ continue
596
+ return False
597
+
598
+ def _is_queryset_of_expected(qs) -> bool:
599
+ if not isinstance(qs, models.QuerySet) or not hasattr(qs, 'model'):
600
+ return False
601
+ for cls in expected_models:
602
+ if isinstance(cls, type):
603
+ try:
604
+ if issubclass(qs.model, cls):
605
+ return True
606
+ except Exception:
607
+ continue
608
+ return False
609
+
610
+ # Aggregate RequirementLinks from all input arguments
611
+ aggregated_input_links_data = {}
612
+ processed_inputs_count = 0
613
+
614
+ for _input in args:
615
+ # Check if the input is an instance of any of the expected model types
616
+ if not _is_expected_instance(_input):
617
+ # Allow QuerySets of expected models
618
+ if _is_queryset_of_expected(_input):
619
+ # For QuerySets, evaluate each item individually and return True if any matches
620
+ if not _input.exists(): # Skip empty querysets
621
+ continue
622
+
623
+ queryset_results = []
624
+ for item in _input:
625
+ if not hasattr(item, 'links') or not isinstance(item.links, RequirementLinks):
626
+ raise TypeError(
627
+ f"Item {item} of type {type(item)} in QuerySet does not have a valid .links attribute of type RequirementLinks."
628
+ )
629
+
630
+ # Evaluate this single item against the requirement
631
+ item_input_links = RequirementLinks(**item.links.active())
632
+
633
+ # Evaluate all operators for this single item
634
+ item_operator_results = []
635
+ for operator in self.operators.all():
636
+ try:
637
+ operator_result = operator.evaluate(
638
+ requirement_links=requirement_req_links,
639
+ input_links=item_input_links,
640
+ requirement=self,
641
+ original_input_args=args,
642
+ **kwargs
643
+ )
644
+ item_operator_results.append(operator_result)
645
+ except Exception as e:
646
+ logger.debug(f"Operator {operator.name} evaluation failed for item {item}: {e}")
647
+ item_operator_results.append(False)
648
+
649
+ # Apply evaluation mode for this single item
650
+ item_result = evaluate_result_list_func(item_operator_results) if item_operator_results else True
651
+ queryset_results.append(item_result)
652
+ processed_inputs_count += 1
653
+
654
+ # If any item in the QuerySet matches, return True for the whole QuerySet evaluation
655
+ if any(queryset_results):
656
+ return True
657
+ continue # Move to the next arg after processing queryset
658
+ else:
659
+ raise TypeError(
660
+ f"Input type {type(_input)} is not among expected models: {self.expected_models} "
661
+ f"nor a QuerySet of expected models."
662
+ )
663
+
664
+ # Process single model instance
665
+ if not hasattr(_input, 'links') or not isinstance(_input.links, RequirementLinks):
666
+ raise TypeError(
667
+ f"Input {_input} of type {type(_input)} does not have a valid .links attribute of type RequirementLinks."
668
+ )
669
+
670
+ active_input_links = _input.links.active() # Get dict of non-empty lists
671
+ for link_key, link_list in active_input_links.items():
672
+ if link_key not in aggregated_input_links_data:
673
+ aggregated_input_links_data[link_key] = []
674
+ aggregated_input_links_data[link_key].extend(link_list)
675
+ processed_inputs_count += 1
676
+
677
+ if not processed_inputs_count and args: # If args were provided but none were processable (e.g. all empty querysets)
678
+ # This situation implies no relevant data was provided for evaluation against the requirement.
679
+ # Depending on operator logic (e.g., "requires at least one matching item"), this might lead to False.
680
+ # For "models_match_any", an empty input_links will likely result in False if requirement_req_links is not empty.
681
+ pass
682
+
683
+
684
+ # Deduplicate items within each list after aggregation
685
+ for key in aggregated_input_links_data:
686
+ try:
687
+ # Using dict.fromkeys to preserve order and remove duplicates for hashable items
688
+ aggregated_input_links_data[key] = list(dict.fromkeys(aggregated_input_links_data[key]))
689
+ except TypeError:
690
+ # Fallback for non-hashable items (though Django models are hashable)
691
+ temp_list = []
692
+ for item in aggregated_input_links_data[key]:
693
+ if item not in temp_list:
694
+ temp_list.append(item)
695
+ aggregated_input_links_data[key] = temp_list
696
+
697
+ final_input_links = RequirementLinks(**aggregated_input_links_data)
698
+
699
+ # Gender strict check: if this requirement has genders, only pass if patient.gender is in the set
700
+ genders_exist = self.genders.exists()
701
+ if genders_exist:
702
+ # Import here to avoid circular import
703
+ from endoreg_db.models.administration.person.patient import Patient
704
+ patient = None
705
+ for arg in args:
706
+ if isinstance(arg, Patient):
707
+ patient = arg
708
+ break
709
+ if patient is None or patient.gender is None:
710
+ return False
711
+ if not self.genders.filter(pk=patient.gender.pk).exists():
712
+ return False
713
+
714
+ operators = self.operators.all()
715
+ if not operators.exists(): # If a requirement has no operators, its evaluation is ambiguous.
716
+ # Consider if this should be True, False, or an error.
717
+ # For now, if no operators, and mode is strict, it's vacuously true. If loose, vacuously false.
718
+ # However, typically a requirement implies some condition.
719
+ # Let's assume if no operators, it cannot be satisfied unless it also has no specific links.
720
+ # This behavior might need further refinement based on business logic.
721
+ if not requirement_req_links.active(): # No conditions in requirement
722
+ return True # Vacuously true if requirement itself is empty
723
+ return False # Cannot be satisfied if requirement has conditions but no operators to check them
724
+
725
+
726
+ operator_results = []
727
+ operator_details = []
728
+ for operator in operators:
729
+ # Prepare kwargs for the operator, including the current Requirement instance
730
+ op_kwargs = kwargs.copy() # Start with kwargs passed to Requirement.evaluate
731
+ op_kwargs['requirement'] = self # Add the Requirement instance itself
732
+ op_kwargs['original_input_args'] = args # Add the original input arguments for operators that need them (e.g., age operators)
733
+ try:
734
+ operator_result = operator.evaluate(
735
+ requirement_links=requirement_req_links,
736
+ input_links=final_input_links,
737
+ **op_kwargs
738
+ )
739
+ operator_results.append(operator_result)
740
+ operator_details.append(f"{operator.name}: {'Passed' if operator_result else 'Failed'}")
741
+ except Exception as e:
742
+ operator_results.append(False)
743
+ operator_details.append(f"{operator.name}: {str(e)}")
744
+
745
+ is_valid = evaluate_result_list_func(operator_results)
746
+
747
+ # Create detailed feedback
748
+ if not operator_results:
749
+ details = "Keine Operatoren für die Bewertung verfügbar"
750
+ elif len(operator_results) == 1:
751
+ details = operator_details[0]
752
+ else:
753
+ failed_details = [detail for detail, result in zip(operator_details, operator_results) if not result]
754
+ if failed_details:
755
+ details = "; ".join(failed_details)
756
+ else:
757
+ details = "Alle Operatoren erfolgreich"
758
+
759
+ # Append working directory for debugging convenience
760
+ try:
761
+ cwd = run("pwd", capture_output=True, text=True).stdout.strip()
762
+ details = f"{details}\ncwd: {cwd}"
763
+ except Exception:
764
+ # non-fatal: ignore if subprocess fails
765
+ pass
766
+
767
+ return is_valid, details