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
@@ -4,148 +4,149 @@ Video Processing History Model
4
4
  Tracks all video correction operations (masking, frame removal, reprocessing).
5
5
  Created as part of Phase 1.1: Video Correction API Endpoints.
6
6
  """
7
+
8
+ import logging
9
+ from pathlib import Path
10
+
11
+ from django.conf import settings
7
12
  from django.db import models
8
13
  from django.utils import timezone
14
+
9
15
  from .video_file import VideoFile
10
16
 
17
+ logger = logging.getLogger(__name__)
18
+
19
+
11
20
  class VideoProcessingHistory(models.Model):
12
21
  """
13
22
  History of all video processing operations.
14
-
23
+
15
24
  Stores configuration and results of masking, frame removal, and reprocessing
16
25
  operations for audit trail and download access.
17
26
  """
18
-
27
+
19
28
  # Operation Types
20
- OPERATION_MASKING = 'mask_overlay'
21
- OPERATION_FRAME_REMOVAL = 'frame_removal'
22
- OPERATION_ANALYSIS = 'analysis'
23
- OPERATION_REPROCESSING = 'reprocessing'
24
-
29
+ OPERATION_MASKING = "mask_overlay"
30
+ OPERATION_FRAME_REMOVAL = "frame_removal"
31
+ OPERATION_ANALYSIS = "analysis"
32
+ OPERATION_REPROCESSING = "reprocessing"
33
+
25
34
  OPERATION_CHOICES = [
26
- (OPERATION_MASKING, 'Mask Overlay'),
27
- (OPERATION_FRAME_REMOVAL, 'Frame Removal'),
28
- (OPERATION_ANALYSIS, 'Sensitivity Analysis'),
29
- (OPERATION_REPROCESSING, 'Full Reprocessing'),
35
+ (OPERATION_MASKING, "Mask Overlay"),
36
+ (OPERATION_FRAME_REMOVAL, "Frame Removal"),
37
+ (OPERATION_ANALYSIS, "Sensitivity Analysis"),
38
+ (OPERATION_REPROCESSING, "Full Reprocessing"),
30
39
  ]
31
-
40
+
32
41
  # Status Types
33
- STATUS_PENDING = 'pending'
34
- STATUS_RUNNING = 'running'
35
- STATUS_SUCCESS = 'success'
36
- STATUS_FAILURE = 'failure'
37
- STATUS_CANCELLED = 'cancelled'
38
-
42
+ STATUS_PENDING = "pending"
43
+ STATUS_RUNNING = "running"
44
+ STATUS_SUCCESS = "success"
45
+ STATUS_FAILURE = "failure"
46
+ STATUS_CANCELLED = "cancelled"
47
+
39
48
  STATUS_CHOICES = [
40
- (STATUS_PENDING, 'Pending'),
41
- (STATUS_RUNNING, 'Running'),
42
- (STATUS_SUCCESS, 'Success'),
43
- (STATUS_FAILURE, 'Failure'),
44
- (STATUS_CANCELLED, 'Cancelled'),
49
+ (STATUS_PENDING, "Pending"),
50
+ (STATUS_RUNNING, "Running"),
51
+ (STATUS_SUCCESS, "Success"),
52
+ (STATUS_FAILURE, "Failure"),
53
+ (STATUS_CANCELLED, "Cancelled"),
45
54
  ]
46
-
47
- video = models.ForeignKey(
48
- VideoFile,
49
- on_delete=models.CASCADE,
50
- related_name='processing_history',
51
- help_text="Video file this operation was performed on"
52
- )
53
-
54
- operation = models.CharField(
55
- max_length=50,
56
- choices=OPERATION_CHOICES,
57
- help_text="Type of processing operation"
58
- )
59
-
60
- status = models.CharField(
61
- max_length=20,
62
- choices=STATUS_CHOICES,
63
- default=STATUS_PENDING,
64
- help_text="Current status of the operation"
65
- )
66
-
55
+
56
+ video = models.ForeignKey(VideoFile, on_delete=models.CASCADE, related_name="processing_history", help_text="Video file this operation was performed on")
57
+
58
+ operation = models.CharField(max_length=50, choices=OPERATION_CHOICES, help_text="Type of processing operation")
59
+
60
+ status = models.CharField(max_length=20, choices=STATUS_CHOICES, default=STATUS_PENDING, help_text="Current status of the operation")
61
+
67
62
  # Configuration & Results
68
- config = models.JSONField(
69
- default=dict,
70
- help_text="Operation configuration (mask settings, frame list, etc.)"
71
- )
72
-
73
- output_file = models.CharField(
74
- max_length=500,
75
- blank=True,
76
- help_text="Path to output file (relative to MEDIA_ROOT)"
77
- )
78
-
79
- details = models.TextField(
80
- blank=True,
81
- help_text="Additional details or error messages"
82
- )
83
-
63
+ config = models.JSONField(default=dict, help_text="Operation configuration (mask settings, frame list, etc.)")
64
+
65
+ output_file = models.CharField(max_length=500, blank=True, help_text="Path to output file (relative to MEDIA_ROOT)")
66
+
67
+ details = models.TextField(blank=True, help_text="Additional details or error messages")
68
+
84
69
  # Celery Integration
85
- task_id = models.CharField(
86
- max_length=100,
87
- blank=True,
88
- help_text="Celery task ID for progress tracking"
89
- )
90
-
70
+ task_id = models.CharField(max_length=100, blank=True, help_text="Celery task ID for progress tracking")
71
+
91
72
  # Timestamps
92
- created_at = models.DateTimeField(
93
- auto_now_add=True,
94
- help_text="When the operation was started"
95
- )
96
-
97
- completed_at = models.DateTimeField(
98
- null=True,
99
- blank=True,
100
- help_text="When the operation completed (success or failure)"
101
- )
102
-
73
+ created_at = models.DateTimeField(auto_now_add=True, help_text="When the operation was started")
74
+
75
+ completed_at = models.DateTimeField(null=True, blank=True, help_text="When the operation completed (success or failure)")
76
+
103
77
  class Meta:
104
- db_table = 'video_processing_history'
105
- verbose_name = 'Video Processing History'
106
- verbose_name_plural = 'Video Processing Histories'
107
- ordering = ['-created_at']
78
+ db_table = "video_processing_history"
79
+ verbose_name = "Video Processing History"
80
+ verbose_name_plural = "Video Processing Histories"
81
+ ordering = ["-created_at"]
108
82
  indexes = [
109
- models.Index(fields=['video', '-created_at']),
110
- models.Index(fields=['task_id']),
111
- models.Index(fields=['status']),
83
+ models.Index(fields=["video", "-created_at"]),
84
+ models.Index(fields=["task_id"]),
85
+ models.Index(fields=["status"]),
112
86
  ]
113
-
87
+
114
88
  def __str__(self):
115
- return f"{self.get_operation_display()} on {self.video.uuid} - {self.get_status_display()}"
116
-
89
+ operation_display = getattr(self, "get_operation_display", None)
90
+ status_display = getattr(self, "get_status_display", None)
91
+
92
+ operation = operation_display() if callable(operation_display) else self.operation
93
+ status = status_display() if callable(status_display) else self.status
94
+ return f"{operation} on {self.video.uuid} - {status}"
95
+
117
96
  def mark_running(self, save=True):
118
97
  """Mark operation as running."""
119
98
  self.status = self.STATUS_RUNNING
120
99
  if save:
121
- self.save(update_fields=['status'])
122
-
100
+ self.save(update_fields=["status"])
101
+
102
+ @staticmethod
103
+ def _normalize_output_path(path: str | Path | None) -> str:
104
+ """Return a path relative to MEDIA_ROOT when possible."""
105
+ if not path:
106
+ return ""
107
+
108
+ raw_path = Path(path)
109
+ if not raw_path.is_absolute():
110
+ return raw_path.as_posix()
111
+ media_root = Path(settings.MEDIA_ROOT)
112
+
113
+ try:
114
+ relative = raw_path.resolve().relative_to(media_root.resolve())
115
+ return relative.as_posix()
116
+ except (ValueError, RuntimeError):
117
+ logger.warning(
118
+ "Storing absolute output path '%s' because it is outside MEDIA_ROOT (%s).",
119
+ raw_path,
120
+ media_root,
121
+ )
122
+ return raw_path.as_posix()
123
+
123
124
  def mark_success(self, output_file=None, details=None, save=True):
124
125
  """Mark operation as successful."""
125
126
  self.status = self.STATUS_SUCCESS
126
127
  self.completed_at = timezone.now()
127
128
  if output_file:
128
- self.output_file = output_file
129
+ self.output_file = self._normalize_output_path(output_file)
129
130
  if details:
130
131
  self.details = details
131
132
  if save:
132
- self.save(update_fields=['status', 'completed_at', 'output_file', 'details'])
133
-
133
+ self.save(update_fields=["status", "completed_at", "output_file", "details"])
134
+
134
135
  def mark_failure(self, error_message, save=True):
135
136
  """Mark operation as failed."""
136
137
  self.status = self.STATUS_FAILURE
137
138
  self.completed_at = timezone.now()
138
139
  self.details = error_message
139
140
  if save:
140
- self.save(update_fields=['status', 'completed_at', 'details'])
141
-
141
+ self.save(update_fields=["status", "completed_at", "details"])
142
+
142
143
  @property
143
144
  def duration(self):
144
145
  """Calculate operation duration if completed."""
145
146
  if self.completed_at and self.created_at:
146
147
  return (self.completed_at - self.created_at).total_seconds()
147
148
  return None
148
-
149
+
149
150
  @property
150
151
  def is_complete(self) -> bool:
151
152
  """Check if operation is in a terminal state."""
@@ -0,0 +1 @@
1
+ not yet properly implemented
@@ -1,17 +1,27 @@
1
+ from typing import TYPE_CHECKING
2
+
1
3
  from django.db import models
2
4
 
5
+
3
6
  class ContraindicationManager(models.Manager):
4
7
  def get_by_natural_key(self, name):
5
8
  return self.get(name=name)
6
-
9
+
10
+
7
11
  class Contraindication(models.Model):
8
12
  name = models.CharField(max_length=100, unique=True)
9
13
  description = models.TextField(blank=True, null=True)
10
14
 
11
15
  objects = ContraindicationManager()
12
-
16
+
17
+ if TYPE_CHECKING:
18
+ from endoreg_db.models import FindingIntervention
19
+
20
+ @property
21
+ def contraindicating_finding_interventions(self) -> "models.manager.RelatedManager[FindingIntervention]": ...
22
+
13
23
  def natural_key(self):
14
24
  return (self.name,)
15
-
25
+
16
26
  def __str__(self):
17
27
  return str(self.name)
@@ -1,5 +1,6 @@
1
+ from typing import TYPE_CHECKING, List
2
+
1
3
  from django.db import models
2
- from typing import List, TYPE_CHECKING
3
4
 
4
5
  if TYPE_CHECKING:
5
6
  from .patient import PatientDisease
@@ -27,6 +28,7 @@ class Disease(models.Model):
27
28
 
28
29
  Can define associated subcategories and numerical descriptors applicable to the disease itself.
29
30
  """
31
+
30
32
  name = models.CharField(max_length=255, unique=True)
31
33
  subcategories = models.JSONField(default=dict)
32
34
  numerical_descriptors = models.JSONField(default=dict)
@@ -34,8 +36,12 @@ class Disease(models.Model):
34
36
  objects = DiseaseManager()
35
37
 
36
38
  if TYPE_CHECKING:
37
- disease_classifications: models.QuerySet["DiseaseClassification"]
38
- patient_diseases: models.QuerySet["PatientDisease"]
39
+
40
+ @property
41
+ def disease_classifications(self) -> models.QuerySet["DiseaseClassification"]: ...
42
+
43
+ @property
44
+ def patient_diseases(self) -> models.QuerySet["PatientDisease"]: ...
39
45
 
40
46
  def natural_key(self):
41
47
  """Returns the natural key (name) as a tuple."""
@@ -52,9 +58,7 @@ class Disease(models.Model):
52
58
  Returns:
53
59
  List[DiseaseClassification]: A list of related disease classification objects.
54
60
  """
55
- classifications: List[DiseaseClassification] = [
56
- _ for _ in self.disease_classifications.all()
57
- ]
61
+ classifications: List[DiseaseClassification] = [_ for _ in self.disease_classifications.all()]
58
62
  return classifications
59
63
 
60
64
 
@@ -78,17 +82,18 @@ class DiseaseClassification(models.Model):
78
82
  """
79
83
  Represents a classification system applicable to a specific disease (e.g., Forrest classification for ulcers).
80
84
  """
85
+
81
86
  name = models.CharField(max_length=255, unique=True)
82
87
 
83
- disease = models.ForeignKey(
84
- Disease, on_delete=models.CASCADE, related_name="disease_classifications"
85
- )
88
+ disease = models.ForeignKey(Disease, on_delete=models.CASCADE, related_name="disease_classifications")
86
89
 
87
90
  objects = DiseaseClassificationManager()
88
91
 
89
92
  if TYPE_CHECKING:
90
- disease: "Disease"
91
- disease_classification_choices: models.QuerySet["DiseaseClassificationChoice"]
93
+ disease: models.ForeignKey["Disease"]
94
+
95
+ @property
96
+ def disease_classification_choices(self) -> models.manager.RelatedManager["DiseaseClassificationChoice"]: ...
92
97
 
93
98
  def natural_key(self):
94
99
  """Returns the natural key (name) as a tuple."""
@@ -105,9 +110,7 @@ class DiseaseClassification(models.Model):
105
110
  Returns:
106
111
  List[DiseaseClassificationChoice]: A list of related disease classification choices.
107
112
  """
108
- choices: List[DiseaseClassificationChoice] = [
109
- _ for _ in self.disease_classification_choices.all()
110
- ]
113
+ choices: List[DiseaseClassificationChoice] = [_ for _ in self.disease_classification_choices.all()]
111
114
  return choices
112
115
 
113
116
 
@@ -133,6 +136,7 @@ class DiseaseClassificationChoice(models.Model):
133
136
  """
134
137
  Represents a specific choice within a disease classification system (e.g., Forrest IIa).
135
138
  """
139
+
136
140
  name = models.CharField(max_length=255, unique=True)
137
141
 
138
142
  disease_classification = models.ForeignKey(
@@ -144,8 +148,10 @@ class DiseaseClassificationChoice(models.Model):
144
148
  objects = DiseaseClassificationChoiceManager()
145
149
 
146
150
  if TYPE_CHECKING:
147
- disease_classification: "DiseaseClassification"
148
- patient_diseases: models.QuerySet["PatientDisease"]
151
+ disease_classification: models.ForeignKey["DiseaseClassification"]
152
+
153
+ @property
154
+ def patient_diseases(self) -> models.manager.RelatedManager["PatientDisease"]: ...
149
155
 
150
156
  def natural_key(self):
151
157
  """Returns the natural key (name) as a tuple."""
@@ -1,5 +1,6 @@
1
+ from typing import TYPE_CHECKING, List
2
+
1
3
  from django.db import models
2
- from typing import List, TYPE_CHECKING
3
4
 
4
5
  if TYPE_CHECKING:
5
6
  from endoreg_db.models import PatientEvent
@@ -13,14 +14,14 @@ class EventManager(models.Manager):
13
14
  def get_by_natural_key(self, name: str) -> "Event":
14
15
  """
15
16
  Retrieves an Event instance using its natural key.
16
-
17
+
17
18
  This method returns the event whose name matches the provided natural key.
18
- It is primarily used to support Django's natural key serialization during
19
+ It is primarily used to support Django's natural key serialization during
19
20
  data import/export and deserialization processes.
20
-
21
+
21
22
  Args:
22
23
  name: The unique event name serving as the natural key.
23
-
24
+
24
25
  Returns:
25
26
  The Event object corresponding to the given name.
26
27
  """
@@ -38,22 +39,19 @@ class Event(models.Model):
38
39
 
39
40
  name = models.CharField(max_length=100, unique=True)
40
41
  description = models.TextField(blank=True, null=True)
41
- event_classification: models.ForeignKey["EventClassification"] = models.ForeignKey(
42
- "EventClassification",
43
- on_delete=models.CASCADE,
44
- related_name="events",
45
- null=True,
46
- blank=True,
47
- )
42
+
48
43
  objects = EventManager()
49
44
 
50
45
  if TYPE_CHECKING:
51
- patient_events: models.QuerySet["PatientEvent"]
46
+ patient_events: models.ForeignKey["PatientEvent"]
47
+
48
+ @property
49
+ def event_classifications(self) -> models.QuerySet["EventClassification"]: ...
52
50
 
53
51
  def natural_key(self):
54
52
  """
55
53
  Returns a tuple representing the natural key for this instance.
56
-
54
+
57
55
  The natural key consists of the instance's unique name.
58
56
  """
59
57
  return (self.name,)
@@ -61,7 +59,7 @@ class Event(models.Model):
61
59
  def __str__(self):
62
60
  """
63
61
  Return a string representation of the instance's name.
64
-
62
+
65
63
  This method converts the 'name' attribute to a string, providing a human-readable
66
64
  representation of the model instance.
67
65
  """
@@ -85,6 +83,18 @@ class EventClassification(models.Model):
85
83
 
86
84
  objects = EventClassificationManager()
87
85
 
86
+ event = models.ForeignKey(
87
+ Event,
88
+ on_delete=models.CASCADE,
89
+ related_name="event_classifications",
90
+ )
91
+
92
+ if TYPE_CHECKING:
93
+ event: models.ForeignKey["Event"]
94
+
95
+ @property
96
+ def event_classification_choices(self) -> models.QuerySet["EventClassificationChoice"]: ...
97
+
88
98
  def natural_key(self):
89
99
  """Returns the natural key (name) as a tuple."""
90
100
  return (self.name,)
@@ -95,9 +105,7 @@ class EventClassification(models.Model):
95
105
 
96
106
  def get_choices(self) -> List["EventClassificationChoice"]:
97
107
  """Retrieves all choices associated with this classification."""
98
- choices: List[EventClassificationChoice] = [
99
- _ for _ in self.event_classification_choices.all()
100
- ]
108
+ choices: List[EventClassificationChoice] = [_ for _ in self.event_classification_choices.all()]
101
109
  return choices
102
110
 
103
111
 
@@ -128,6 +136,11 @@ class EventClassificationChoice(models.Model):
128
136
 
129
137
  objects = EventClassificationChoiceManager()
130
138
 
139
+ @property
140
+ def event(self):
141
+ """Returns the associated Event instance."""
142
+ return self.event_classification.event
143
+
131
144
  def natural_key(self):
132
145
  """Returns the natural key (name) as a tuple."""
133
146
  return (self.name,)
@@ -1,9 +1,16 @@
1
1
  from .examination import Examination, ExaminationRequirementSet
2
- from .examination_type import ExaminationType
2
+ from .examination_indication import ExaminationIndication, ExaminationIndicationClassification, ExaminationIndicationClassificationChoice
3
3
  from .examination_time import ExaminationTime
4
4
  from .examination_time_type import ExaminationTimeType
5
- from .examination_indication import(
6
- ExaminationIndication,
7
- ExaminationIndicationClassification,
8
- ExaminationIndicationClassificationChoice
9
- )
5
+ from .examination_type import ExaminationType
6
+
7
+ __all__ = [
8
+ "Examination",
9
+ "ExaminationRequirementSet",
10
+ "ExaminationType",
11
+ "ExaminationTime",
12
+ "ExaminationTimeType",
13
+ "ExaminationIndication",
14
+ "ExaminationIndicationClassification",
15
+ "ExaminationIndicationClassificationChoice",
16
+ ]
@@ -1,6 +1,6 @@
1
+ from typing import TYPE_CHECKING, List, cast
2
+
1
3
  from django.db import models
2
- from typing import List
3
- from typing import TYPE_CHECKING
4
4
 
5
5
  if TYPE_CHECKING:
6
6
  from endoreg_db.models import Finding
@@ -28,24 +28,43 @@ class Examination(models.Model):
28
28
  name = models.CharField(max_length=100, unique=True)
29
29
  examination_types = models.ManyToManyField("ExaminationType", blank=True)
30
30
  description = models.TextField(blank=True, null=True)
31
+ indications = models.ManyToManyField(
32
+ "ExaminationIndication",
33
+ related_name="examinations",
34
+ blank=True,
35
+ )
36
+ examination_times = models.ManyToManyField(
37
+ "ExaminationTime",
38
+ related_name="examinations",
39
+ blank=True,
40
+ )
41
+
42
+ findings = models.ManyToManyField(
43
+ "Finding",
44
+ blank=True,
45
+ related_name="examinations",
46
+ )
47
+ information_sources = models.ManyToManyField(
48
+ "InformationSource",
49
+ related_name="examinations",
50
+ blank=True,
51
+ )
31
52
 
32
53
  objects = ExaminationManager()
33
54
 
34
55
  if TYPE_CHECKING:
35
- from endoreg_db.models import ExaminationIndication, Finding, FindingClassification
36
- finding_classifications: models.QuerySet['FindingClassification']
37
- indications: models.QuerySet[ExaminationIndication]
38
- findings: models.QuerySet["Finding"]
39
- exam_reqset_links: models.QuerySet["ExaminationRequirementSet"]
40
-
41
- # # Requirement sets associated with the examination.
42
- # requirement_sets = models.ManyToManyField(
43
- # "RequirementSet",
44
- # through="ExaminationRequirementSet",
45
- # related_name="examinations",
46
- # blank=True,
47
- # )
56
+ from endoreg_db.models import ExaminationIndication, ExaminationTime, Finding, FindingClassification, InformationSource
57
+
58
+ indications = cast("models.manager.RelatedManager[ExaminationIndication]", indications)
59
+ examination_times = cast("models.manager.RelatedManager[ExaminationTime]", examination_times)
60
+ findings = cast("models.manager.RelatedManager[Finding]", findings)
61
+ information_sources = cast("models.manager.RelatedManager[InformationSource]", information_sources)
48
62
 
63
+ @property
64
+ def finding_classifications(self) -> "models.manager.RelatedManager[FindingClassification]": ...
65
+
66
+ @property
67
+ def exam_reqset_links(self) -> "models.manager.RelatedManager[ExaminationRequirementSet]": ...
49
68
 
50
69
  @property
51
70
  def links(self) -> "RequirementLinks":
@@ -61,7 +80,7 @@ class Examination(models.Model):
61
80
  examinations=[self],
62
81
  findings=list(self.findings.all()),
63
82
  finding_classifications=list(self.finding_classifications.all()),
64
- examination_indications=list(self.indications.all())
83
+ examination_indications=list(self.indications.all()),
65
84
  )
66
85
 
67
86
  def __str__(self) -> str:
@@ -108,12 +127,13 @@ class ExaminationRequirementSetManager(models.Manager):
108
127
  def get_by_natural_key(self, name: str) -> "ExaminationRequirementSet":
109
128
  return self.get(name=name)
110
129
 
111
-
130
+
112
131
  class ExaminationRequirementSet(models.Model):
113
132
  """
114
133
  Through table for Examination ↔ RequirementSet link.
115
134
  Lets you store per-link metadata (order, default, etc.)
116
135
  """
136
+
117
137
  examinations = models.ManyToManyField(
118
138
  "Examination",
119
139
  related_name="exam_reqset_links",
@@ -126,7 +146,7 @@ class ExaminationRequirementSet(models.Model):
126
146
  # )
127
147
  # Optional metadata
128
148
  enabled_by_default = models.BooleanField(default=False)
129
-
149
+
130
150
  name = models.CharField(max_length=100, unique=True)
131
151
 
132
152
  objects = ExaminationRequirementSetManager()
@@ -136,7 +156,7 @@ class ExaminationRequirementSet(models.Model):
136
156
 
137
157
  # def __str__(self) -> str:
138
158
  # return f"{self.examination} ↔ {self.requirement_set} (prio={self.priority})"
139
-
159
+
140
160
  def natural_key(self) -> tuple:
141
161
  """
142
162
  Returns the natural key for the ExaminationRequirementSet.
@@ -145,4 +165,3 @@ class ExaminationRequirementSet(models.Model):
145
165
  tuple: The natural key consisting of the name.
146
166
  """
147
167
  return (self.name,)
148
-