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

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

Potentially problematic release.


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

Files changed (503) hide show
  1. endoreg_db/authz/auth.py +74 -0
  2. endoreg_db/authz/backends.py +168 -0
  3. endoreg_db/authz/management/commands/list_routes.py +18 -0
  4. endoreg_db/authz/middleware.py +83 -0
  5. endoreg_db/authz/permissions.py +127 -0
  6. endoreg_db/authz/policy.py +218 -0
  7. endoreg_db/authz/views_auth.py +66 -0
  8. endoreg_db/config/env.py +13 -8
  9. endoreg_db/data/__init__.py +2 -11
  10. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +3 -3
  11. endoreg_db/data/event_classification/data.yaml +4 -0
  12. endoreg_db/data/event_classification_choice/data.yaml +9 -0
  13. endoreg_db/data/examination/examinations/data.yaml +114 -14
  14. endoreg_db/data/examination/time-type/data.yaml +0 -3
  15. endoreg_db/data/examination_indication/endoscopy.yaml +108 -173
  16. endoreg_db/data/examination_indication_classification/endoscopy.yaml +0 -70
  17. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +33 -37
  18. endoreg_db/data/finding/00_generic.yaml +35 -0
  19. endoreg_db/data/finding/00_generic_complication.yaml +9 -0
  20. endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
  21. endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
  22. endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
  23. endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
  24. endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
  25. endoreg_db/data/finding_classification/00_generic.yaml +44 -0
  26. endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
  27. endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
  28. endoreg_db/data/finding_classification/02_colonoscopy_baseline.yaml +83 -0
  29. endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
  30. endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
  31. endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
  32. endoreg_db/data/finding_classification_choice/{yes_no_na.yaml → 00_generic.yaml} +5 -1
  33. endoreg_db/data/finding_classification_choice/{examination_setting_generic_types.yaml → 00_generic_baseline.yaml} +10 -2
  34. endoreg_db/data/finding_classification_choice/{complication_generic_types.yaml → 00_generic_complication.yaml} +1 -1
  35. endoreg_db/data/finding_classification_choice/{histology.yaml → 00_generic_histology.yaml} +1 -4
  36. endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
  37. endoreg_db/data/finding_classification_choice/{bowel_preparation.yaml → 02_colonoscopy_bowel_preparation.yaml} +1 -30
  38. endoreg_db/data/finding_classification_choice/{colonoscopy_not_complete_reason.yaml → 02_colonoscopy_generic.yaml} +1 -1
  39. endoreg_db/data/finding_classification_choice/{histology_polyp.yaml → 02_colonoscopy_histology.yaml} +1 -1
  40. endoreg_db/data/finding_classification_choice/{colonoscopy_location.yaml → 02_colonoscopy_location.yaml} +23 -4
  41. endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
  42. endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
  43. endoreg_db/data/finding_classification_choice/{colon_lesion_paris.yaml → 02_colonoscopy_polyp_morphology.yaml} +26 -8
  44. endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
  45. endoreg_db/data/finding_classification_type/{colonoscopy_basic.yaml → 00_generic.yaml} +18 -13
  46. endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
  47. endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
  48. endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
  49. endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
  50. endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
  51. endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
  52. endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
  53. endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
  54. endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
  55. endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
  56. endoreg_db/data/finding_type/data.yaml +8 -12
  57. endoreg_db/data/requirement/01_patient_data.yaml +93 -0
  58. endoreg_db/data/requirement/old/colon_polyp_intervention.yaml +49 -0
  59. endoreg_db/data/requirement/old/coloreg_colon_polyp.yaml +49 -0
  60. endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
  61. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +29 -12
  62. endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
  63. endoreg_db/data/requirement_set/{endoscopy_bleeding_risk.yaml → 02_endoscopy_bleeding_risk.yaml} +0 -6
  64. endoreg_db/data/requirement_set/90_coloreg.yaml +190 -0
  65. endoreg_db/data/requirement_set/_old_ +109 -0
  66. endoreg_db/data/requirement_set_type/data.yaml +21 -0
  67. endoreg_db/data/setup_config.yaml +4 -4
  68. endoreg_db/data/tag/requirement_set_tags.yaml +21 -0
  69. endoreg_db/exceptions.py +4 -2
  70. endoreg_db/forms/examination_form.py +1 -1
  71. endoreg_db/helpers/data_loader.py +125 -53
  72. endoreg_db/helpers/default_objects.py +116 -81
  73. endoreg_db/import_files/__init__.py +27 -0
  74. endoreg_db/import_files/context/__init__.py +7 -0
  75. endoreg_db/import_files/context/default_sensitive_meta.py +81 -0
  76. endoreg_db/import_files/context/ensure_center.py +17 -0
  77. endoreg_db/import_files/context/file_lock.py +66 -0
  78. endoreg_db/import_files/context/import_context.py +43 -0
  79. endoreg_db/import_files/context/validate_directories.py +56 -0
  80. endoreg_db/import_files/file_storage/__init__.py +15 -0
  81. endoreg_db/import_files/file_storage/create_report_file.py +76 -0
  82. endoreg_db/import_files/file_storage/create_video_file.py +75 -0
  83. endoreg_db/import_files/file_storage/sensitive_meta_storage.py +39 -0
  84. endoreg_db/import_files/file_storage/state_management.py +400 -0
  85. endoreg_db/import_files/file_storage/storage.py +36 -0
  86. endoreg_db/import_files/import_service.md +26 -0
  87. endoreg_db/import_files/processing/__init__.py +11 -0
  88. endoreg_db/import_files/processing/report_processing/report_anonymization.py +94 -0
  89. endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
  90. endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
  91. endoreg_db/import_files/processing/video_processing/video_cleanup_on_error.py +119 -0
  92. endoreg_db/import_files/pseudonymization/fake.py +52 -0
  93. endoreg_db/import_files/pseudonymization/k_anonymity.py +182 -0
  94. endoreg_db/import_files/pseudonymization/k_pseudonymity.py +128 -0
  95. endoreg_db/import_files/report_import_service.py +141 -0
  96. endoreg_db/import_files/video_import_service.py +150 -0
  97. endoreg_db/management/commands/create_model_meta_from_huggingface.py +21 -10
  98. endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
  99. endoreg_db/management/commands/import_report.py +130 -65
  100. endoreg_db/management/commands/import_video.py +9 -10
  101. endoreg_db/management/commands/import_video_with_classification.py +2 -2
  102. endoreg_db/management/commands/list_routes.py +18 -0
  103. endoreg_db/management/commands/load_ai_model_data.py +5 -5
  104. endoreg_db/management/commands/load_ai_model_label_data.py +9 -7
  105. endoreg_db/management/commands/load_base_db_data.py +5 -134
  106. endoreg_db/management/commands/load_center_data.py +12 -12
  107. endoreg_db/management/commands/load_contraindication_data.py +14 -16
  108. endoreg_db/management/commands/load_disease_classification_choices_data.py +15 -18
  109. endoreg_db/management/commands/load_disease_classification_data.py +15 -18
  110. endoreg_db/management/commands/load_disease_data.py +25 -28
  111. endoreg_db/management/commands/load_endoscope_data.py +20 -27
  112. endoreg_db/management/commands/load_event_data.py +14 -16
  113. endoreg_db/management/commands/load_examination_data.py +31 -44
  114. endoreg_db/management/commands/load_examination_indication_data.py +20 -21
  115. endoreg_db/management/commands/load_finding_data.py +52 -80
  116. endoreg_db/management/commands/load_information_source.py +21 -23
  117. endoreg_db/management/commands/load_lab_value_data.py +17 -26
  118. endoreg_db/management/commands/load_medication_data.py +13 -12
  119. endoreg_db/management/commands/load_organ_data.py +15 -19
  120. endoreg_db/management/commands/load_pdf_type_data.py +19 -18
  121. endoreg_db/management/commands/load_profession_data.py +14 -17
  122. endoreg_db/management/commands/load_qualification_data.py +20 -23
  123. endoreg_db/management/commands/load_report_reader_flag_data.py +17 -19
  124. endoreg_db/management/commands/load_requirement_data.py +62 -39
  125. endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
  126. endoreg_db/management/commands/load_risk_data.py +7 -6
  127. endoreg_db/management/commands/load_shift_data.py +20 -23
  128. endoreg_db/management/commands/load_tag_data.py +8 -11
  129. endoreg_db/management/commands/load_unit_data.py +17 -19
  130. endoreg_db/management/commands/setup_endoreg_db.py +3 -3
  131. endoreg_db/management/commands/start_filewatcher.py +46 -37
  132. endoreg_db/management/commands/storage_management.py +271 -203
  133. endoreg_db/management/commands/validate_video_files.py +1 -5
  134. endoreg_db/migrations/0001_initial.py +297 -250
  135. endoreg_db/models/__init__.py +78 -123
  136. endoreg_db/models/administration/__init__.py +21 -42
  137. endoreg_db/models/administration/ai/active_model.py +2 -2
  138. endoreg_db/models/administration/ai/ai_model.py +7 -6
  139. endoreg_db/models/administration/case/__init__.py +1 -15
  140. endoreg_db/models/administration/case/case.py +3 -3
  141. endoreg_db/models/administration/case/case_template/__init__.py +2 -14
  142. endoreg_db/models/administration/case/case_template/case_template.py +2 -124
  143. endoreg_db/models/administration/case/case_template/case_template_rule.py +2 -268
  144. endoreg_db/models/administration/case/case_template/case_template_rule_value.py +2 -85
  145. endoreg_db/models/administration/case/case_template/case_template_type.py +2 -25
  146. endoreg_db/models/administration/center/center.py +33 -19
  147. endoreg_db/models/administration/center/center_product.py +12 -9
  148. endoreg_db/models/administration/center/center_resource.py +25 -19
  149. endoreg_db/models/administration/center/center_shift.py +21 -17
  150. endoreg_db/models/administration/center/center_waste.py +16 -8
  151. endoreg_db/models/administration/person/__init__.py +2 -0
  152. endoreg_db/models/administration/person/employee/employee.py +10 -5
  153. endoreg_db/models/administration/person/employee/employee_qualification.py +9 -4
  154. endoreg_db/models/administration/person/employee/employee_type.py +12 -6
  155. endoreg_db/models/administration/person/examiner/examiner.py +13 -11
  156. endoreg_db/models/administration/person/patient/__init__.py +2 -0
  157. endoreg_db/models/administration/person/patient/patient.py +129 -100
  158. endoreg_db/models/administration/person/patient/patient_external_id.py +37 -0
  159. endoreg_db/models/administration/person/person.py +4 -0
  160. endoreg_db/models/administration/person/profession/__init__.py +8 -4
  161. endoreg_db/models/administration/person/user/portal_user_information.py +11 -7
  162. endoreg_db/models/administration/product/product.py +20 -15
  163. endoreg_db/models/administration/product/product_material.py +17 -18
  164. endoreg_db/models/administration/product/product_weight.py +12 -8
  165. endoreg_db/models/administration/product/reference_product.py +23 -55
  166. endoreg_db/models/administration/qualification/qualification.py +7 -3
  167. endoreg_db/models/administration/qualification/qualification_type.py +7 -3
  168. endoreg_db/models/administration/shift/scheduled_days.py +8 -5
  169. endoreg_db/models/administration/shift/shift.py +16 -12
  170. endoreg_db/models/administration/shift/shift_type.py +23 -31
  171. endoreg_db/models/label/__init__.py +8 -9
  172. endoreg_db/models/label/annotation/image_classification.py +10 -9
  173. endoreg_db/models/label/annotation/video_segmentation_annotation.py +23 -28
  174. endoreg_db/models/label/label.py +15 -15
  175. endoreg_db/models/label/label_set.py +19 -6
  176. endoreg_db/models/label/label_type.py +1 -1
  177. endoreg_db/models/label/label_video_segment/_create_from_video.py +5 -8
  178. endoreg_db/models/label/label_video_segment/label_video_segment.py +98 -102
  179. endoreg_db/models/label/video_segmentation_label.py +4 -0
  180. endoreg_db/models/label/video_segmentation_labelset.py +4 -3
  181. endoreg_db/models/media/frame/frame.py +22 -22
  182. endoreg_db/models/media/pdf/raw_pdf.py +194 -194
  183. endoreg_db/models/media/pdf/report_file.py +25 -29
  184. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +55 -47
  185. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
  186. endoreg_db/models/media/processing_history/__init__.py +5 -0
  187. endoreg_db/models/media/processing_history/processing_history.py +96 -0
  188. endoreg_db/models/media/video/__init__.py +1 -0
  189. endoreg_db/models/media/video/create_from_file.py +139 -77
  190. endoreg_db/models/media/video/pipe_2.py +8 -9
  191. endoreg_db/models/media/video/video_file.py +174 -112
  192. endoreg_db/models/media/video/video_file_ai.py +288 -74
  193. endoreg_db/models/media/video/video_file_anonymize.py +38 -38
  194. endoreg_db/models/media/video/video_file_frames/__init__.py +3 -1
  195. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -8
  196. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +7 -9
  197. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +9 -8
  198. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +38 -45
  199. endoreg_db/models/media/video/video_file_frames/_get_frame.py +6 -8
  200. endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +4 -18
  201. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -3
  202. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +7 -6
  203. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +6 -8
  204. endoreg_db/models/media/video/video_file_frames/_get_frames.py +6 -8
  205. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +15 -25
  206. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +26 -23
  207. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +23 -14
  208. endoreg_db/models/media/video/video_file_io.py +113 -61
  209. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +3 -3
  210. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +5 -3
  211. endoreg_db/models/media/video/video_file_meta/get_fps.py +37 -34
  212. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +19 -25
  213. endoreg_db/models/media/video/video_file_meta/text_meta.py +41 -38
  214. endoreg_db/models/media/video/video_file_meta/video_meta.py +14 -7
  215. endoreg_db/models/media/video/video_file_segments.py +24 -17
  216. endoreg_db/models/media/video/video_metadata.py +19 -35
  217. endoreg_db/models/media/video/video_processing.py +96 -95
  218. endoreg_db/models/medical/contraindication/README.md +1 -0
  219. endoreg_db/models/medical/contraindication/__init__.py +13 -3
  220. endoreg_db/models/medical/disease.py +22 -16
  221. endoreg_db/models/medical/event.py +31 -18
  222. endoreg_db/models/medical/examination/__init__.py +13 -6
  223. endoreg_db/models/medical/examination/examination.py +39 -20
  224. endoreg_db/models/medical/examination/examination_indication.py +30 -95
  225. endoreg_db/models/medical/examination/examination_time.py +23 -8
  226. endoreg_db/models/medical/examination/examination_time_type.py +9 -6
  227. endoreg_db/models/medical/examination/examination_type.py +3 -4
  228. endoreg_db/models/medical/finding/finding.py +32 -40
  229. endoreg_db/models/medical/finding/finding_classification.py +42 -72
  230. endoreg_db/models/medical/finding/finding_intervention.py +25 -22
  231. endoreg_db/models/medical/finding/finding_type.py +13 -12
  232. endoreg_db/models/medical/hardware/endoscope.py +26 -26
  233. endoreg_db/models/medical/hardware/endoscopy_processor.py +2 -2
  234. endoreg_db/models/medical/laboratory/lab_value.py +62 -91
  235. endoreg_db/models/medical/medication/medication.py +22 -10
  236. endoreg_db/models/medical/medication/medication_indication.py +29 -3
  237. endoreg_db/models/medical/medication/medication_indication_type.py +25 -14
  238. endoreg_db/models/medical/medication/medication_intake_time.py +31 -19
  239. endoreg_db/models/medical/medication/medication_schedule.py +27 -16
  240. endoreg_db/models/medical/organ/__init__.py +15 -12
  241. endoreg_db/models/medical/patient/medication_examples.py +6 -6
  242. endoreg_db/models/medical/patient/patient_disease.py +20 -23
  243. endoreg_db/models/medical/patient/patient_event.py +19 -22
  244. endoreg_db/models/medical/patient/patient_examination.py +48 -54
  245. endoreg_db/models/medical/patient/patient_examination_indication.py +16 -14
  246. endoreg_db/models/medical/patient/patient_finding.py +122 -139
  247. endoreg_db/models/medical/patient/patient_finding_classification.py +44 -49
  248. endoreg_db/models/medical/patient/patient_finding_intervention.py +8 -19
  249. endoreg_db/models/medical/patient/patient_lab_sample.py +28 -23
  250. endoreg_db/models/medical/patient/patient_lab_value.py +82 -89
  251. endoreg_db/models/medical/patient/patient_medication.py +27 -38
  252. endoreg_db/models/medical/patient/patient_medication_schedule.py +28 -36
  253. endoreg_db/models/medical/risk/risk.py +7 -6
  254. endoreg_db/models/medical/risk/risk_type.py +8 -5
  255. endoreg_db/models/metadata/model_meta.py +60 -29
  256. endoreg_db/models/metadata/model_meta_logic.py +125 -18
  257. endoreg_db/models/metadata/pdf_meta.py +31 -24
  258. endoreg_db/models/metadata/sensitive_meta.py +105 -85
  259. endoreg_db/models/metadata/sensitive_meta_logic.py +198 -103
  260. endoreg_db/models/metadata/video_meta.py +51 -31
  261. endoreg_db/models/metadata/video_prediction_logic.py +16 -23
  262. endoreg_db/models/metadata/video_prediction_meta.py +29 -33
  263. endoreg_db/models/other/distribution/date_value_distribution.py +89 -29
  264. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +21 -5
  265. endoreg_db/models/other/distribution/numeric_value_distribution.py +114 -53
  266. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +4 -3
  267. endoreg_db/models/other/emission/emission_factor.py +18 -8
  268. endoreg_db/models/other/gender.py +10 -5
  269. endoreg_db/models/other/information_source.py +50 -29
  270. endoreg_db/models/other/material.py +9 -5
  271. endoreg_db/models/other/resource.py +6 -4
  272. endoreg_db/models/other/tag.py +10 -5
  273. endoreg_db/models/other/transport_route.py +13 -8
  274. endoreg_db/models/other/unit.py +10 -6
  275. endoreg_db/models/other/waste.py +6 -5
  276. endoreg_db/models/report/report.py +6 -0
  277. endoreg_db/models/requirement/requirement.py +329 -361
  278. endoreg_db/models/requirement/requirement_error.py +85 -0
  279. endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
  280. endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +3 -6
  281. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +90 -64
  282. endoreg_db/models/requirement/requirement_operator.py +103 -112
  283. endoreg_db/models/requirement/requirement_set.py +74 -57
  284. endoreg_db/models/state/__init__.py +4 -4
  285. endoreg_db/models/state/abstract.py +2 -2
  286. endoreg_db/models/state/anonymization.py +12 -0
  287. endoreg_db/models/state/audit_ledger.py +49 -51
  288. endoreg_db/models/state/label_video_segment.py +9 -0
  289. endoreg_db/models/state/raw_pdf.py +101 -68
  290. endoreg_db/models/state/sensitive_meta.py +6 -2
  291. endoreg_db/models/state/video.py +110 -90
  292. endoreg_db/models/upload_job.py +35 -34
  293. endoreg_db/models/utils.py +28 -25
  294. endoreg_db/queries/__init__.py +3 -1
  295. endoreg_db/root_urls.py +21 -2
  296. endoreg_db/schemas/examination_evaluation.py +1 -1
  297. endoreg_db/serializers/__init__.py +2 -10
  298. endoreg_db/serializers/anonymization.py +18 -10
  299. endoreg_db/serializers/label_video_segment/label_video_segment.py +2 -29
  300. endoreg_db/serializers/meta/__init__.py +1 -6
  301. endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
  302. endoreg_db/serializers/misc/file_overview.py +11 -99
  303. endoreg_db/serializers/misc/sensitive_patient_data.py +50 -26
  304. endoreg_db/serializers/patient_examination/patient_examination.py +3 -3
  305. endoreg_db/serializers/pdf/anony_text_validation.py +39 -23
  306. endoreg_db/serializers/requirements/requirement_sets.py +92 -22
  307. endoreg_db/serializers/video/segmentation.py +2 -1
  308. endoreg_db/serializers/video/video_file_list.py +65 -34
  309. endoreg_db/serializers/video/video_processing_history.py +20 -5
  310. endoreg_db/services/__old/pdf_import.py +1487 -0
  311. endoreg_db/services/__old/video_import.py +1306 -0
  312. endoreg_db/services/anonymization.py +128 -89
  313. endoreg_db/services/lookup_service.py +65 -52
  314. endoreg_db/services/lookup_store.py +2 -2
  315. endoreg_db/services/pdf_import.py +0 -1382
  316. endoreg_db/services/report_import.py +10 -0
  317. endoreg_db/services/video_import.py +6 -1255
  318. endoreg_db/tasks/upload_tasks.py +79 -70
  319. endoreg_db/tasks/video_ingest.py +8 -4
  320. endoreg_db/urls/__init__.py +5 -32
  321. endoreg_db/urls/ai.py +32 -0
  322. endoreg_db/urls/media.py +121 -83
  323. endoreg_db/urls/root_urls.py +29 -0
  324. endoreg_db/utils/__init__.py +15 -5
  325. endoreg_db/utils/ai/multilabel_classification_net.py +116 -20
  326. endoreg_db/utils/case_generator/__init__.py +3 -0
  327. endoreg_db/utils/dataloader.py +142 -40
  328. endoreg_db/utils/defaults/set_default_center.py +32 -0
  329. endoreg_db/utils/names.py +22 -16
  330. endoreg_db/utils/paths.py +110 -46
  331. endoreg_db/utils/permissions.py +2 -1
  332. endoreg_db/utils/pipelines/Readme.md +1 -1
  333. endoreg_db/utils/pipelines/process_video_dir.py +1 -1
  334. endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +655 -0
  335. endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +97 -0
  336. endoreg_db/utils/setup_config.py +8 -5
  337. endoreg_db/utils/storage.py +115 -0
  338. endoreg_db/utils/validate_endo_roi.py +8 -2
  339. endoreg_db/utils/video/ffmpeg_wrapper.py +184 -188
  340. endoreg_db/views/__init__.py +85 -183
  341. endoreg_db/views/ai/__init__.py +8 -0
  342. endoreg_db/views/ai/label.py +155 -0
  343. endoreg_db/views/anonymization/media_management.py +202 -166
  344. endoreg_db/views/anonymization/overview.py +99 -67
  345. endoreg_db/views/anonymization/validate.py +182 -44
  346. endoreg_db/views/media/__init__.py +7 -20
  347. endoreg_db/views/media/pdf_media.py +197 -174
  348. endoreg_db/views/media/sensitive_metadata.py +193 -138
  349. endoreg_db/views/media/video_media.py +89 -82
  350. endoreg_db/views/meta/__init__.py +0 -8
  351. endoreg_db/views/misc/__init__.py +1 -7
  352. endoreg_db/views/misc/upload_views.py +94 -93
  353. endoreg_db/views/patient/patient.py +5 -4
  354. endoreg_db/views/report/__init__.py +5 -7
  355. endoreg_db/views/{pdf → report}/reimport.py +22 -22
  356. endoreg_db/views/{pdf/pdf_stream.py → report/report_stream.py} +46 -39
  357. endoreg_db/views/requirement/evaluate.py +188 -187
  358. endoreg_db/views/requirement/lookup.py +17 -3
  359. endoreg_db/views/requirement/lookup_store.py +22 -90
  360. endoreg_db/views/requirement/requirement_utils.py +89 -0
  361. endoreg_db/views/video/__init__.py +23 -24
  362. endoreg_db/views/video/correction.py +201 -172
  363. endoreg_db/views/video/reimport.py +1 -1
  364. endoreg_db/views/{media/video_segments.py → video/segments_crud.py} +77 -40
  365. endoreg_db/views/video/{video_meta.py → video_meta_stats.py} +2 -2
  366. endoreg_db/views/video/video_stream.py +7 -8
  367. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/METADATA +7 -3
  368. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/RECORD +391 -413
  369. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/WHEEL +1 -1
  370. endoreg_db/data/finding/anatomy_colon.yaml +0 -128
  371. endoreg_db/data/finding/colonoscopy.yaml +0 -40
  372. endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +0 -56
  373. endoreg_db/data/finding/complication.yaml +0 -16
  374. endoreg_db/data/finding/data.yaml +0 -105
  375. endoreg_db/data/finding/examination_setting.yaml +0 -16
  376. endoreg_db/data/finding/medication_related.yaml +0 -18
  377. endoreg_db/data/finding/outcome.yaml +0 -12
  378. endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +0 -95
  379. endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +0 -22
  380. endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +0 -25
  381. endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
  382. endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
  383. endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +0 -68
  384. endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
  385. endoreg_db/data/finding_classification/colonoscopy_location.yaml +0 -80
  386. endoreg_db/data/finding_classification/colonoscopy_lst.yaml +0 -21
  387. endoreg_db/data/finding_classification/colonoscopy_nice.yaml +0 -20
  388. endoreg_db/data/finding_classification/colonoscopy_paris.yaml +0 -26
  389. endoreg_db/data/finding_classification/colonoscopy_sano.yaml +0 -22
  390. endoreg_db/data/finding_classification/colonoscopy_summary.yaml +0 -53
  391. endoreg_db/data/finding_classification/complication_generic.yaml +0 -25
  392. endoreg_db/data/finding_classification/examination_setting_generic.yaml +0 -40
  393. endoreg_db/data/finding_classification/histology_colo.yaml +0 -51
  394. endoreg_db/data/finding_classification/intervention_required.yaml +0 -26
  395. endoreg_db/data/finding_classification/medication_related.yaml +0 -23
  396. endoreg_db/data/finding_classification/visualized.yaml +0 -33
  397. endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
  398. endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
  399. endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
  400. endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +0 -15
  401. endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +0 -17
  402. endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
  403. endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +0 -14
  404. endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
  405. endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +0 -82
  406. endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
  407. endoreg_db/data/finding_classification_choice/outcome.yaml +0 -19
  408. endoreg_db/data/finding_intervention/endoscopy.yaml +0 -43
  409. endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
  410. endoreg_db/data/finding_intervention/endoscopy_egd.yaml +0 -128
  411. endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +0 -32
  412. endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +0 -9
  413. endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +0 -36
  414. endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +0 -79
  415. endoreg_db/data/requirement/age.yaml +0 -26
  416. endoreg_db/data/requirement/gender.yaml +0 -25
  417. endoreg_db/management/commands/init_default_ai_model.py +0 -112
  418. endoreg_db/management/commands/reset_celery_schedule.py +0 -9
  419. endoreg_db/management/commands/validate_video.py +0 -204
  420. endoreg_db/migrations/0002_add_video_correction_models.py +0 -52
  421. endoreg_db/migrations/0003_add_center_display_name.py +0 -30
  422. endoreg_db/models/administration/permissions/__init__.py +0 -44
  423. endoreg_db/models/rule/__init__.py +0 -13
  424. endoreg_db/models/rule/rule.py +0 -27
  425. endoreg_db/models/rule/rule_applicator.py +0 -224
  426. endoreg_db/models/rule/rule_attribute_dtype.py +0 -17
  427. endoreg_db/models/rule/rule_type.py +0 -20
  428. endoreg_db/models/rule/ruleset.py +0 -17
  429. endoreg_db/renames.yml +0 -8
  430. endoreg_db/serializers/_old/raw_pdf_meta_validation.py +0 -223
  431. endoreg_db/serializers/_old/raw_video_meta_validation.py +0 -179
  432. endoreg_db/serializers/_old/video.py +0 -71
  433. endoreg_db/serializers/meta/pdf_file_meta_extraction.py +0 -115
  434. endoreg_db/serializers/meta/report_meta.py +0 -53
  435. endoreg_db/serializers/report/__init__.py +0 -9
  436. endoreg_db/serializers/report/mixins.py +0 -45
  437. endoreg_db/serializers/report/report.py +0 -105
  438. endoreg_db/serializers/report/report_list.py +0 -22
  439. endoreg_db/serializers/report/secure_file_url.py +0 -26
  440. endoreg_db/serializers/video/video_metadata.py +0 -105
  441. endoreg_db/services/requirements_object.py +0 -147
  442. endoreg_db/services/storage_aware_video_processor.py +0 -344
  443. endoreg_db/urls/files.py +0 -6
  444. endoreg_db/urls/label_video_segment_validate.py +0 -33
  445. endoreg_db/urls/label_video_segments.py +0 -46
  446. endoreg_db/urls/report.py +0 -48
  447. endoreg_db/urls/video.py +0 -61
  448. endoreg_db/utils/case_generator/case_generator.py +0 -159
  449. endoreg_db/utils/case_generator/utils.py +0 -30
  450. endoreg_db/utils/requirement_operator_logic/model_evaluators.py +0 -368
  451. endoreg_db/views/label/__init__.py +0 -5
  452. endoreg_db/views/label/label.py +0 -15
  453. endoreg_db/views/label_video_segment/__init__.py +0 -16
  454. endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +0 -44
  455. endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +0 -50
  456. endoreg_db/views/label_video_segment/label_video_segment.py +0 -77
  457. endoreg_db/views/label_video_segment/label_video_segment_by_label.py +0 -174
  458. endoreg_db/views/label_video_segment/label_video_segment_detail.py +0 -73
  459. endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +0 -46
  460. endoreg_db/views/label_video_segment/validate.py +0 -226
  461. endoreg_db/views/media/segments.py +0 -71
  462. endoreg_db/views/meta/available_files_list.py +0 -146
  463. endoreg_db/views/meta/report_meta.py +0 -53
  464. endoreg_db/views/meta/sensitive_meta_detail.py +0 -148
  465. endoreg_db/views/misc/secure_file_serving_view.py +0 -80
  466. endoreg_db/views/misc/secure_file_url_view.py +0 -84
  467. endoreg_db/views/misc/secure_url_validate.py +0 -79
  468. endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +0 -164
  469. endoreg_db/views/patient_finding_location/__init__.py +0 -5
  470. endoreg_db/views/patient_finding_location/pfl_create.py +0 -70
  471. endoreg_db/views/patient_finding_morphology/__init__.py +0 -5
  472. endoreg_db/views/patient_finding_morphology/pfm_create.py +0 -70
  473. endoreg_db/views/pdf/__init__.py +0 -8
  474. endoreg_db/views/report/report_list.py +0 -112
  475. endoreg_db/views/report/report_with_secure_url.py +0 -28
  476. endoreg_db/views/report/start_examination.py +0 -7
  477. endoreg_db/views/video/segmentation.py +0 -274
  478. endoreg_db/views/video/task_status.py +0 -49
  479. endoreg_db/views/video/timeline.py +0 -46
  480. endoreg_db/views/video/video_analyze.py +0 -52
  481. endoreg_db/views.py +0 -0
  482. /endoreg_db/data/requirement/{colonoscopy_baseline_austria.yaml → old/colonoscopy_baseline_austria.yaml} +0 -0
  483. /endoreg_db/data/requirement/{disease_cardiovascular.yaml → old/disease_cardiovascular.yaml} +0 -0
  484. /endoreg_db/data/requirement/{disease_classification_choice_cardiovascular.yaml → old/disease_classification_choice_cardiovascular.yaml} +0 -0
  485. /endoreg_db/data/requirement/{disease_hepatology.yaml → old/disease_hepatology.yaml} +0 -0
  486. /endoreg_db/data/requirement/{disease_misc.yaml → old/disease_misc.yaml} +0 -0
  487. /endoreg_db/data/requirement/{disease_renal.yaml → old/disease_renal.yaml} +0 -0
  488. /endoreg_db/data/requirement/{endoscopy_bleeding_risk.yaml → old/endoscopy_bleeding_risk.yaml} +0 -0
  489. /endoreg_db/data/requirement/{event_cardiology.yaml → old/event_cardiology.yaml} +0 -0
  490. /endoreg_db/data/requirement/{event_requirements.yaml → old/event_requirements.yaml} +0 -0
  491. /endoreg_db/data/requirement/{finding_colon_polyp.yaml → old/finding_colon_polyp.yaml} +0 -0
  492. /endoreg_db/{migrations/__init__.py → data/requirement/old/gender.yaml} +0 -0
  493. /endoreg_db/data/requirement/{lab_value.yaml → old/lab_value.yaml} +0 -0
  494. /endoreg_db/data/requirement/{medication.yaml → old/medication.yaml} +0 -0
  495. /endoreg_db/data/requirement_operator/{age.yaml → _old/age.yaml} +0 -0
  496. /endoreg_db/data/requirement_operator/{lab_operators.yaml → _old/lab_operators.yaml} +0 -0
  497. /endoreg_db/data/requirement_operator/{model_operators.yaml → _old/model_operators.yaml} +0 -0
  498. /endoreg_db/{models/media/video/refactor_plan.md → import_files/pseudonymization/__init__.py} +0 -0
  499. /endoreg_db/{models/media/video/video_file_frames.py → import_files/pseudonymization/pseudonymize.py} +0 -0
  500. /endoreg_db/models/{metadata/frame_ocr_result.py → report/__init__.py} +0 -0
  501. /endoreg_db/{urls/sensitive_meta.py → models/report/images.py} +0 -0
  502. /endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py} +0 -0
  503. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/licenses/LICENSE +0 -0
@@ -1,10 +1,12 @@
1
+ from typing import TYPE_CHECKING, List, Optional, cast
2
+
1
3
  from django.db import models
2
- from typing import List, TYPE_CHECKING, Optional
3
4
 
4
5
  if TYPE_CHECKING:
5
- from endoreg_db.models import Examination, Requirement, FindingIntervention
6
+ from endoreg_db.models import Examination, FindingIntervention, InformationSource, Requirement
6
7
  from endoreg_db.utils.links.requirement_link import RequirementLinks
7
8
 
9
+
8
10
  class ExaminationIndicationManager(models.Manager):
9
11
  """
10
12
  Manager for ExaminationIndication with custom query methods.
@@ -13,10 +15,10 @@ class ExaminationIndicationManager(models.Manager):
13
15
  def get_by_natural_key(self, name: str) -> "ExaminationIndication":
14
16
  """
15
17
  Retrieves an ExaminationIndication instance by its natural key.
16
-
18
+
17
19
  Args:
18
20
  name: The unique name identifying the examination indication.
19
-
21
+
20
22
  Returns:
21
23
  The ExaminationIndication instance corresponding to the specified name.
22
24
  """
@@ -43,35 +45,41 @@ class ExaminationIndication(models.Model):
43
45
  blank=True,
44
46
  )
45
47
 
46
- examinations = models.ManyToManyField(
47
- "Examination",
48
+ expected_interventions = models.ManyToManyField(
49
+ "FindingIntervention",
48
50
  related_name="indications",
49
51
  blank=True,
50
52
  )
51
53
 
52
- expected_interventions = models.ManyToManyField(
53
- "FindingIntervention",
54
- related_name="indications",
54
+ information_sources = models.ManyToManyField(
55
+ "InformationSource",
56
+ related_name="examination_indications",
55
57
  blank=True,
56
58
  )
57
59
 
58
60
  objects = ExaminationIndicationManager()
59
61
 
60
62
  if TYPE_CHECKING:
61
- classifications: "models.ManyToManyField[ExaminationIndicationClassification, ExaminationIndicationClassification]"
62
- examinations: "models.ManyToManyField[Examination, Examination]"
63
- related_requirements: "models.QuerySet[Requirement]"
64
- expected_interventions: "models.ManyToManyField[FindingIntervention, FindingIntervention]"
63
+ classifications = cast(models.manager.RelatedManager["ExaminationIndicationClassification"], classifications)
64
+ expected_interventions = cast(models.manager.RelatedManager["FindingIntervention"], expected_interventions)
65
+ information_sources = cast(models.manager.RelatedManager["InformationSource"], information_sources)
66
+
67
+ @property
68
+ def related_requirements(self) -> "models.manager.RelatedManager[Requirement]": ...
69
+
70
+ @property
71
+ def examinations(self) -> "models.manager.RelatedManager[Examination]": ...
65
72
 
66
73
  @property
67
74
  def links(self) -> "RequirementLinks":
68
75
  """
69
76
  Aggregates related requirements, classifications, examination, and interventions into a RequirementLinks object.
70
-
77
+
71
78
  Returns:
72
79
  A RequirementLinks instance representing all entities linked to this examination indication.
73
80
  """
74
81
  from endoreg_db.utils.links.requirement_link import RequirementLinks
82
+
75
83
  return RequirementLinks(
76
84
  examination_indications=[self],
77
85
  examinations=list(self.examinations.all()),
@@ -93,41 +101,6 @@ class ExaminationIndication(models.Model):
93
101
  """
94
102
  return str(self.name)
95
103
 
96
- def get_choices(self) -> List["ExaminationIndicationClassificationChoice"]:
97
- """
98
- Retrieves all classification choices for the indication.
99
-
100
- Aggregates and returns the choices from each classification associated with the indication.
101
-
102
- Returns:
103
- List[ExaminationIndicationClassificationChoice]: A list of classification choices.
104
- """
105
- classifications = self.classifications.all()
106
- choices = []
107
- for classification in classifications:
108
- choices.extend(classification.choices.all())
109
- return choices
110
-
111
- def get_examination(self) -> Optional["Examination"]:
112
- """
113
- Returns the first examination associated with this indication, or None if no examinations exist.
114
-
115
- Note: Since this is now a many-to-many relationship, this method returns the first examination.
116
- Consider using get_examinations() for accessing all related examinations.
117
- """
118
- return self.examinations.first()
119
-
120
- def get_examinations(self) -> List["Examination"]:
121
- """
122
- Returns all examinations associated with this indication.
123
-
124
- Returns:
125
- List[Examination]: A list of all examinations linked to this indication.
126
- """
127
- return list(self.examinations.all())
128
-
129
-
130
-
131
104
 
132
105
  class ExaminationIndicationClassificationManager(models.Manager):
133
106
  """
@@ -137,10 +110,10 @@ class ExaminationIndicationClassificationManager(models.Manager):
137
110
  def get_by_natural_key(self, name: str) -> "ExaminationIndicationClassification":
138
111
  """
139
112
  Retrieves an ExaminationIndicationClassification by its natural key.
140
-
113
+
141
114
  Args:
142
115
  name: The unique name identifying the classification.
143
-
116
+
144
117
  Returns:
145
118
  The ExaminationIndicationClassification instance corresponding to the given name.
146
119
  """
@@ -159,18 +132,14 @@ class ExaminationIndicationClassification(models.Model):
159
132
 
160
133
  name = models.CharField(max_length=255, unique=True)
161
134
  description = models.TextField(blank=True, null=True)
162
- examinations = models.ManyToManyField(
163
- "Examination",
164
- related_name="indication_classifications",
135
+ choices = models.ManyToManyField(
136
+ "ExaminationIndicationClassificationChoice",
137
+ related_name="classifications",
165
138
  blank=True,
166
139
  )
167
140
 
168
141
  objects = ExaminationIndicationClassificationManager()
169
142
 
170
- if TYPE_CHECKING:
171
- examinations: "models.ManyToManyField[Examination, Examination]"
172
- choices: "models.QuerySet[ExaminationIndicationClassificationChoice]"
173
-
174
143
  def natural_key(self) -> tuple:
175
144
  """
176
145
  Returns the natural key for the classification.
@@ -189,48 +158,19 @@ class ExaminationIndicationClassification(models.Model):
189
158
  """
190
159
  return str(self.name)
191
160
 
192
- def get_choices(self) -> List["ExaminationIndicationClassificationChoice"]:
193
- """
194
- Retrieves all classification choices associated with this classification.
195
-
196
- Returns:
197
- List[ExaminationIndicationClassificationChoice]: A list of classification choice instances.
198
- """
199
- return list(self.choices.all())
200
-
201
- def get_examination(self) -> Optional["Examination"]:
202
- """
203
- Returns the first examination associated with this classification, or None if no examinations exist.
204
-
205
- Note: Since this is now a many-to-many relationship, this method returns the first examination.
206
- Consider using get_examinations() for accessing all related examinations.
207
- """
208
- return self.examinations.first()
209
-
210
- def get_examinations(self) -> List["Examination"]:
211
- """
212
- Returns all examinations associated with this classification.
213
-
214
- Returns:
215
- List[Examination]: A list of all examinations linked to this classification.
216
- """
217
- return list(self.examinations.all())
218
-
219
161
 
220
162
  class ExaminationIndicationClassificationChoiceManager(models.Manager):
221
163
  """
222
164
  Manager for ExaminationIndicationClassificationChoice with custom query methods.
223
165
  """
224
166
 
225
- def get_by_natural_key(
226
- self, name: str
227
- ) -> "ExaminationIndicationClassificationChoice":
167
+ def get_by_natural_key(self, name: str) -> "ExaminationIndicationClassificationChoice":
228
168
  """
229
169
  Retrieves an ExaminationIndicationClassificationChoice instance by its natural key.
230
-
170
+
231
171
  Args:
232
172
  name: The unique name serving as the natural key for the classification choice.
233
-
173
+
234
174
  Returns:
235
175
  An ExaminationIndicationClassificationChoice instance corresponding to the given name.
236
176
  """
@@ -251,11 +191,6 @@ class ExaminationIndicationClassificationChoice(models.Model):
251
191
  name = models.CharField(max_length=255, unique=True)
252
192
  subcategories = models.JSONField(default=dict)
253
193
  numerical_descriptors = models.JSONField(default=dict)
254
- classification = models.ForeignKey(
255
- ExaminationIndicationClassification,
256
- on_delete=models.CASCADE,
257
- related_name="choices",
258
- )
259
194
 
260
195
  objects = ExaminationIndicationClassificationChoiceManager()
261
196
 
@@ -1,13 +1,20 @@
1
+ from typing import TYPE_CHECKING, cast
2
+
1
3
  from django.db import models
2
- from rest_framework import serializers
4
+
5
+ if TYPE_CHECKING:
6
+ from endoreg_db.models import ExaminationTimeType, InformationSource
7
+
3
8
 
4
9
  class ExaminationTimeManager(models.Manager):
5
10
  """
6
11
  Manager for ExaminationTime with custom query methods.
7
12
  """
13
+
8
14
  def get_by_natural_key(self, name: str) -> "ExaminationTime":
9
15
  return self.get(name=name)
10
16
 
17
+
11
18
  class ExaminationTime(models.Model):
12
19
  """
13
20
  Represents a specific time configuration for examinations.
@@ -18,12 +25,21 @@ class ExaminationTime(models.Model):
18
25
  end_time (TimeField): The ending time for the examination.
19
26
  time_types (ManyToManyField): The types associated with this examination time.
20
27
  """
28
+
21
29
  name = models.CharField(max_length=100, unique=True)
22
- start_time = models.TimeField(blank=True, null=True)
23
- time_types = models.ManyToManyField('ExaminationTimeType', blank=True)
24
- end_time = models.TimeField(blank=True, null=True)
30
+ time_types = models.ManyToManyField("ExaminationTimeType", blank=True)
25
31
  objects = ExaminationTimeManager()
26
32
 
33
+ information_sources = models.ManyToManyField(
34
+ "InformationSource",
35
+ related_name="examination_times",
36
+ blank=True,
37
+ )
38
+
39
+ if TYPE_CHECKING:
40
+ time_types = cast(models.manager.RelatedManager["ExaminationTimeType"], time_types)
41
+ information_sources = cast(models.manager.RelatedManager["InformationSource"], information_sources)
42
+
27
43
  def __str__(self) -> str:
28
44
  """
29
45
  String representation of the examination time.
@@ -43,7 +59,6 @@ class ExaminationTime(models.Model):
43
59
  return (self.name,)
44
60
 
45
61
  class Meta:
46
- verbose_name = 'Examination Time'
47
- verbose_name_plural = 'Examination Times'
48
- ordering = ['name']
49
-
62
+ verbose_name = "Examination Time"
63
+ verbose_name_plural = "Examination Times"
64
+ ordering = ["name"]
@@ -1,12 +1,15 @@
1
1
  from django.db import models
2
2
 
3
+
3
4
  class ExaminationTimeTypeManager(models.Manager):
4
5
  """
5
6
  Manager for ExaminationTimeType with custom query methods.
6
7
  """
8
+
7
9
  def get_by_natural_key(self, name: str) -> "ExaminationTimeType":
8
10
  return self.get(name=name)
9
-
11
+
12
+
10
13
  class ExaminationTimeType(models.Model):
11
14
  """
12
15
  Represents a type of examination time.
@@ -15,9 +18,10 @@ class ExaminationTimeType(models.Model):
15
18
  name (str): The unique name of the examination time type.
16
19
  examinations: The examinations associated with this type.
17
20
  """
21
+
18
22
  objects = ExaminationTimeTypeManager()
19
23
  name = models.CharField(max_length=100, unique=True)
20
- examinations = models.ManyToManyField('Examination', blank=True)
24
+ examinations = models.ManyToManyField("Examination", blank=True)
21
25
 
22
26
  def __str__(self) -> str:
23
27
  """
@@ -35,7 +39,6 @@ class ExaminationTimeType(models.Model):
35
39
  return (self.name,)
36
40
 
37
41
  class Meta:
38
- verbose_name = 'Examination Time Type'
39
- verbose_name_plural = 'Examination Time Types'
40
- ordering = ['name']
41
-
42
+ verbose_name = "Examination Time Type"
43
+ verbose_name_plural = "Examination Time Types"
44
+ ordering = ["name"]
@@ -9,10 +9,10 @@ class ExaminationTypeManager(models.Manager):
9
9
  def get_by_natural_key(self, name: str) -> "ExaminationType":
10
10
  """
11
11
  Retrieves an ExaminationType instance using its natural key.
12
-
12
+
13
13
  Args:
14
14
  name: The natural identifier for the ExaminationType, typically the unique name.
15
-
15
+
16
16
  Returns:
17
17
  The ExaminationType instance that matches the given name.
18
18
  """
@@ -34,8 +34,7 @@ class ExaminationType(models.Model):
34
34
  """
35
35
  Return the string representation of the examination type using its name.
36
36
  """
37
- name = self.name_en or self.name
38
- name = str(name)
37
+ name = str(self.name)
39
38
  return name
40
39
 
41
40
  def natural_key(self) -> tuple:
@@ -1,86 +1,78 @@
1
1
  # Class to represent findings of examinations
2
+ from typing import TYPE_CHECKING, Optional, cast
3
+
2
4
  from django.db import models
3
- from typing import List
4
5
 
5
- from typing import TYPE_CHECKING
6
6
 
7
7
  class FindingManager(models.Manager):
8
8
  def get_by_natural_key(self, name):
9
9
  return self.get(name=name)
10
10
 
11
+
11
12
  class Finding(models.Model):
12
13
  name = models.CharField(max_length=100, unique=True)
13
14
  description = models.TextField(blank=True, null=True)
14
- examinations = models.ManyToManyField(
15
- 'Examination',
16
- blank=True,
17
- related_name='findings'
18
- ) # type: ignore
19
- finding_types = models.ManyToManyField(
20
- 'FindingType',
21
- blank=True,
22
- related_name='findings'
23
- ) # type: ignore
24
-
25
- finding_interventions = models.ManyToManyField(
26
- 'FindingIntervention',
27
- blank=True,
28
- related_name='findings'
29
- ) # type: ignore
30
-
15
+ finding_types = models.ManyToManyField("FindingType", blank=True, related_name="findings")
16
+ finding_interventions = models.ManyToManyField("FindingIntervention", blank=True, related_name="findings")
17
+ caused_by_interventions = models.ManyToManyField("FindingIntervention", blank=True, related_name="causes_findings")
18
+ finding_classifications = models.ManyToManyField("FindingClassification", blank=True, related_name="findings")
19
+ information_sources = models.ManyToManyField("InformationSource", blank=True, related_name="findings")
31
20
  objects = FindingManager()
32
21
 
33
22
  if TYPE_CHECKING:
34
23
  from endoreg_db.models import (
35
- Examination, FindingType, FindingIntervention, FindingClassificationType,
24
+ Examination,
36
25
  FindingClassification,
37
- PatientFindingClassification
26
+ FindingClassificationType,
27
+ FindingIntervention,
28
+ FindingType,
29
+ InformationSource,
30
+ PatientFindingClassification,
38
31
  )
39
-
40
- finding_classifications: models.QuerySet['FindingClassification']
41
- examinations: models.QuerySet[Examination]
42
- finding_types: models.QuerySet[FindingType]
43
- finding_interventions: models.QuerySet[FindingIntervention]
44
-
32
+
33
+ finding_types = cast(models.manager.RelatedManager["FindingType"], finding_types)
34
+ finding_interventions = cast(models.manager.RelatedManager["FindingIntervention"], finding_interventions)
35
+ finding_classifications = cast(models.manager.RelatedManager["FindingClassification"], finding_classifications)
36
+
45
37
  def natural_key(self):
46
38
  """
47
39
  Return a tuple containing the unique natural key for this Finding instance.
48
-
40
+
49
41
  Returns:
50
42
  tuple: A single-element tuple with the Finding's name.
51
43
  """
52
44
  return (self.name,)
53
-
45
+
54
46
  def __str__(self):
55
47
  return self.name
56
-
48
+
57
49
  def get_finding_types(self):
58
50
  """
59
51
  Return all finding types associated with this finding.
60
-
52
+
61
53
  Returns:
62
54
  QuerySet: All related FindingType instances.
63
55
  """
64
56
  return self.finding_types.all()
65
-
66
- def get_classifications(self, classification_type: str = None) -> models.QuerySet['FindingClassification']:
57
+
58
+ def get_classifications(self, classification_type: Optional[str] = None) -> models.QuerySet["FindingClassification"]:
67
59
  """
68
60
  Retrieve all classifications associated with this finding, optionally filtered by classification type.
69
-
61
+
70
62
  Parameters:
71
- classification_type (str, optional): If provided, only classifications with a matching type name are returned.
72
-
63
+ classification_type (str, optional): If provided, only classifications with a matching type name are returned.
64
+
73
65
  Returns:
74
- List[FindingClassification]: List of related classification objects, filtered by type if specified.
66
+ List[FindingClassification]: List of related classification objects, filtered by type if specified.
75
67
  """
76
68
  if classification_type:
77
69
  return self.finding_classifications.filter(classification_types__name=classification_type)
78
70
  return self.finding_classifications.all()
79
-
71
+
80
72
  def get_location_classifications(self):
81
73
  """
82
74
  Retrieve all related FindingClassification objects with classification type 'location'.
83
-
75
+
84
76
  Returns:
85
77
  QuerySet: All FindingClassification instances linked to this finding where the classification type name is 'location' (case-insensitive).
86
78
  """
@@ -89,7 +81,7 @@ class Finding(models.Model):
89
81
  def get_morphology_classifications(self):
90
82
  """
91
83
  Retrieve all related FindingClassification objects with classification type 'morphology'.
92
-
84
+
93
85
  Returns:
94
86
  QuerySet: A queryset of FindingClassification instances associated with this finding and classified as 'morphology'.
95
87
  """
@@ -1,31 +1,23 @@
1
+ from typing import TYPE_CHECKING, cast
2
+
1
3
  from django.db import models
2
- from typing import TYPE_CHECKING, List
4
+
3
5
 
4
6
  class FindingClassificationTypeManager(models.Manager):
5
7
  def get_by_natural_key(self, name):
6
8
  return self.get(name=name)
7
-
9
+
10
+
8
11
  class FindingClassificationType(models.Model):
9
12
  name = models.CharField(max_length=255, unique=True)
10
13
  description = models.TextField(blank=True)
11
-
12
14
  objects = FindingClassificationTypeManager()
13
-
15
+
14
16
  def natural_key(self):
15
17
  return (self.name,)
16
-
18
+
17
19
  def __str__(self):
18
20
  return str(self.name)
19
-
20
- @classmethod
21
- def get_required_classifications_for_finding(cls, finding):
22
- """
23
- Returns all required finding classification types for a given finding.
24
- """
25
- required_classification_types = [
26
- _ for _ in finding.required_morphology_classification_types.all()
27
- ]
28
- return required_classification_types
29
21
 
30
22
 
31
23
  class FindingClassificationManager(models.Manager):
@@ -36,32 +28,37 @@ class FindingClassificationManager(models.Manager):
36
28
  class FindingClassification(models.Model):
37
29
  name = models.CharField(max_length=255, unique=True)
38
30
  description = models.TextField(blank=True)
31
+ finding_types = models.ManyToManyField("FindingType", blank=True, related_name="finding_classifications")
32
+ choices = models.ManyToManyField("FindingClassificationChoice", related_name="classifications", blank=True)
33
+
39
34
  classification_types = models.ManyToManyField(
40
- to=FindingClassificationType,
35
+ to=FindingClassificationType,
41
36
  # on_delete=models.CASCADE
42
37
  )
43
- choices = models.ManyToManyField(
44
- 'FindingClassificationChoice',
45
- related_name='classifications',
46
- blank=True
38
+ information_sources = models.ManyToManyField(
39
+ "InformationSource",
40
+ related_name="finding_classifications",
41
+ blank=True,
47
42
  )
48
43
 
49
- findings = models.ManyToManyField('Finding', blank=True, related_name='finding_classifications')
50
- examinations = models.ManyToManyField('Examination', blank=True, related_name='finding_classifications')
51
- finding_types = models.ManyToManyField('FindingType', blank=True, related_name='finding_classifications')
44
+ @property
45
+ def examinations(self):
46
+ from endoreg_db.models import Examination
47
+
48
+ return Examination.objects.filter(findings__finding_classifications=self)
52
49
 
53
50
  objects = FindingClassificationManager()
54
51
 
55
52
  if TYPE_CHECKING:
56
- from endoreg_db.models import (
57
- Finding, Examination, FindingType, PatientFindingClassification
58
- )
59
- classification_types: models.ManyToManyField[FindingClassificationType]
60
- findings: models.QuerySet[Finding]
61
- examinations: models.QuerySet[Examination]
62
- finding_types: models.QuerySet[FindingType]
63
- choices: models.QuerySet['FindingClassificationChoice']
64
- patient_finding_classifications: models.QuerySet['PatientFindingClassification']
53
+ from endoreg_db.models import Examination, Finding, FindingType, InformationSource, PatientFindingClassification
54
+
55
+ classification_types = cast(models.manager.RelatedManager["FindingClassificationType"], classification_types)
56
+ choices = cast(models.manager.RelatedManager["FindingClassificationChoice"], choices)
57
+ finding_types = cast(models.manager.RelatedManager["FindingType"], finding_types)
58
+ information_sources = cast(models.manager.RelatedManager["InformationSource"], information_sources)
59
+
60
+ @property
61
+ def findings(self) -> "models.manager.RelatedManager[Finding]": ...
65
62
 
66
63
  def natural_key(self):
67
64
  return (self.name,)
@@ -72,71 +69,44 @@ class FindingClassification(models.Model):
72
69
  def get_choices(self):
73
70
  """
74
71
  Return all choices associated with this classification.
75
-
72
+
76
73
  Returns:
77
- QuerySet: All related FindingClassificationChoice instances.
74
+ QuerySet: All related FindingClassificationChoice instances.
78
75
  """
79
76
  return self.choices.all()
80
77
 
81
- @property
82
- def is_morphology(self):
83
- """
84
- Return True if any related classification type has the name "morphology" (case-insensitive).
85
- """
86
- return self.classification_types.filter(name__iexact="morphology").exists()
87
-
88
- @property
89
- def is_location(self):
90
- """
91
- Returns True if any related classification type has the name "location" (case-insensitive).
92
- """
93
- return self.classification_types.filter(name__iexact="location").exists()
94
-
95
78
 
96
79
  class FindingClassificationChoiceManager(models.Manager):
97
80
  def get_by_natural_key(self, name):
98
81
  """
99
82
  Retrieve an instance by its unique name using the natural key.
100
-
83
+
101
84
  Parameters:
102
85
  name (str): The unique name identifying the instance.
103
-
86
+
104
87
  Returns:
105
88
  The model instance with the specified name.
106
89
  """
107
90
  return self.get(name=name)
108
-
91
+
92
+
109
93
  class FindingClassificationChoice(models.Model):
110
94
  name = models.CharField(max_length=255, unique=True)
111
95
  description = models.TextField(blank=True)
112
- # classifications = models.ManyToManyField(
113
- # "FindingClassification",
114
- # related_name='choices'
115
- # )
116
-
117
- subcategories = models.JSONField(
118
- default = dict
119
- )
120
-
121
- numerical_descriptors = models.JSONField(
122
- default = dict
123
- )
124
-
96
+ subcategories = models.JSONField(default=dict)
97
+ numerical_descriptors = models.JSONField(default=dict)
125
98
  objects = FindingClassificationChoiceManager()
126
99
 
127
100
  if TYPE_CHECKING:
128
- from endoreg_db.models import (
129
- PatientFindingClassification
130
- )
131
- classifications: models.QuerySet['FindingClassification']
132
- patient_finding_classifications: models.QuerySet['PatientFindingClassification']
101
+ from endoreg_db.models import PatientFindingClassification
102
+
103
+ classifications: models.QuerySet["FindingClassification"]
104
+ patient_finding_classifications: models.QuerySet["PatientFindingClassification"]
133
105
 
134
-
135
106
  def natural_key(self):
136
107
  return (self.name,)
137
-
108
+
138
109
  def __str__(self):
139
110
  classifications_names = ", ".join([c.name for c in self.classifications.all()])
140
111
  _str = f"{self.name} ({classifications_names})"
141
112
  return _str
142
-