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,52 +1,87 @@
1
- '''Model for numeric value distribution'''
1
+ """Model for numeric value distribution"""
2
2
 
3
- from django.db import models
4
3
  import numpy as np
5
- from .base_value_distribution import BaseValueDistribution
4
+ from django.db import models
6
5
  from scipy.stats import skewnorm
6
+ from typing import TYPE_CHECKING
7
+
8
+ from .base_value_distribution import BaseValueDistribution
9
+
10
+ if TYPE_CHECKING:
11
+ from endoreg_db.models import LabValue, Patient
7
12
 
8
13
 
9
14
  class NumericValueDistributionManager(models.Manager):
10
- '''Object manager for NumericValueDistribution'''
15
+ """Object manager for NumericValueDistribution"""
16
+
11
17
  def get_by_natural_key(self, name):
12
- '''Retrieve a NumericValueDistribution by its natural key.'''
18
+ """Retrieve a NumericValueDistribution by its natural key."""
13
19
  return self.get(name=name)
14
20
 
21
+
15
22
  class NumericValueDistribution(BaseValueDistribution):
16
23
  """
17
24
  Numeric value distribution model.
18
25
  Supports uniform, normal, and skewed normal distributions with hard limits.
19
26
  """
27
+
20
28
  objects = NumericValueDistributionManager()
21
29
  DISTRIBUTION_CHOICES = [
22
- ('uniform', 'Uniform'),
23
- ('normal', 'Normal'),
24
- ('skewed_normal', 'Skewed Normal'),
30
+ ("uniform", "Uniform"),
31
+ ("normal", "Normal"),
32
+ ("skewed_normal", "Skewed Normal"),
25
33
  ]
26
34
 
27
35
  distribution_type = models.CharField(max_length=20, choices=DISTRIBUTION_CHOICES)
28
- min_descriptor = models.CharField(
29
- max_length=20
30
- )
31
-
32
- max_descriptor = models.CharField(
33
- max_length=20
34
- )
35
-
36
- def generate_value(self, lab_value, patient):
37
- '''Generate a value based on the distribution rules.'''
38
- #FIXME
39
- from endoreg_db.models import LabValue, Patient
40
- assert isinstance(patient, Patient)
41
- assert isinstance(lab_value, LabValue)
42
- default_normal_range_dict = lab_value.get_normal_range(patient.age(), patient.gender)
36
+ min_descriptor = models.CharField(max_length=20)
37
+ max_descriptor = models.CharField(max_length=20)
38
+ min_value = models.FloatField(blank=True, null=True, help_text="Lower hard limit for generated values")
39
+ max_value = models.FloatField(blank=True, null=True, help_text="Upper hard limit for generated values")
40
+ mean = models.FloatField(blank=True, null=True, help_text="Mean used for normal or skewed normal distributions")
41
+ std_dev = models.FloatField(blank=True, null=True, help_text="Standard deviation for bell-shaped distributions")
42
+ skewness = models.FloatField(blank=True, null=True, help_text="Shape parameter for skewed normal distributions")
43
+
44
+ @property
45
+ def min_value_safe(self):
46
+ if self.min_value is None:
47
+ raise ValueError("min_value is not set")
48
+ return self.min_value
49
+
50
+ @property
51
+ def max_value_safe(self):
52
+ if self.max_value is None:
53
+ raise ValueError("max_value is not set")
54
+ return self.max_value
55
+
56
+ @property
57
+ def mean_safe(self):
58
+ if self.mean is None:
59
+ raise ValueError("mean is not set")
60
+ return self.mean
61
+
62
+ @property
63
+ def std_dev_safe(self):
64
+ if self.std_dev is None:
65
+ raise ValueError("std_dev is not set")
66
+ return self.std_dev
67
+
68
+ @property
69
+ def skewness_safe(self):
70
+ if self.skewness is None:
71
+ raise ValueError("skewness is not set")
72
+ return self.skewness
73
+
74
+ def generate_value(self, lab_value: "LabValue", patient: "Patient"):
75
+ """Generate a value based on the distribution rules."""
76
+
77
+ default_normal_range_dict = lab_value.get_normal_range(patient.age_safe, patient.gender)
43
78
  assert isinstance(default_normal_range_dict, dict)
44
79
 
45
- if self.distribution_type == 'uniform':
80
+ if self.distribution_type == "uniform":
46
81
  assert self.min_descriptor and self.max_descriptor
47
-
48
- min_key_needed = self.min_descriptor.split('_')[0]
49
- max_key_needed = self.max_descriptor.split('_')[0]
82
+
83
+ min_key_needed = self.min_descriptor.split("_")[0]
84
+ max_key_needed = self.max_descriptor.split("_")[0]
50
85
 
51
86
  min_val_from_range = default_normal_range_dict.get(min_key_needed)
52
87
  max_val_from_range = default_normal_range_dict.get(max_key_needed)
@@ -61,7 +96,7 @@ class NumericValueDistribution(BaseValueDistribution):
61
96
  f"LabValue '{lab_value.name}' is gender-dependent: {lab_value.normal_range_gender_dependent}. "
62
97
  f"Check LabValue's default_normal_range definition for this patient context."
63
98
  )
64
-
99
+
65
100
  if max_val_from_range is None:
66
101
  raise ValueError(
67
102
  f"Cannot generate value for LabValue '{lab_value.name}' using distribution "
@@ -72,22 +107,29 @@ class NumericValueDistribution(BaseValueDistribution):
72
107
  f"LabValue '{lab_value.name}' is gender-dependent: {lab_value.normal_range_gender_dependent}. "
73
108
  f"Check LabValue's default_normal_range definition for this patient context."
74
109
  )
75
-
110
+
76
111
  value = self._generate_value_uniform(default_normal_range_dict)
77
-
112
+
78
113
  return value
79
-
80
- elif self.distribution_type == 'normal':
114
+
115
+ elif self.distribution_type == "normal":
116
+ self._validate_normal_parameters()
117
+ assert self.mean is not None
118
+ assert self.std_dev is not None
81
119
  value = np.random.normal(self.mean, self.std_dev)
82
- return np.clip(value, self.min_value, self.max_value)
83
- elif self.distribution_type == 'skewed_normal':
120
+ return self._clip_to_bounds(value)
121
+ elif self.distribution_type == "skewed_normal":
122
+ self._validate_skewed_normal_parameters()
123
+ assert self.mean is not None
124
+ assert self.std_dev is not None
125
+ assert self.skewness is not None
84
126
  value = skewnorm.rvs(a=self.skewness, loc=self.mean, scale=self.std_dev)
85
- return np.clip(value, self.min_value, self.max_value)
127
+ return self._clip_to_bounds(value)
86
128
  else:
87
129
  raise ValueError("Unsupported distribution type")
88
130
 
89
- def parse_value_descriptor(self, value_descriptor:str):
90
- '''Parse the value descriptor string into a dict with a lambda function.'''
131
+ def parse_value_descriptor(self, value_descriptor: str):
132
+ """Parse the value descriptor string into a dict with a lambda function."""
91
133
  # strings of shape f"{value_key}_{operator}_{value}"
92
134
  # extract value_key, operator, value
93
135
  value_key, operator, value = value_descriptor.split("_")
@@ -104,22 +146,41 @@ class NumericValueDistribution(BaseValueDistribution):
104
146
 
105
147
  # create dict with {value_key: lambda x: x operator value}
106
148
 
107
- def _generate_value_uniform(self, default_normal_range_dict:dict):
108
- value_function_dict = self.parse_value_descriptor(
109
- self.min_descriptor
110
- )
149
+ def _generate_value_uniform(self, default_normal_range_dict: dict):
150
+ value_function_dict = self.parse_value_descriptor(self.min_descriptor)
151
+ value_function_dict.update(self.parse_value_descriptor(self.max_descriptor))
111
152
 
112
- _ = self.parse_value_descriptor(
113
- self.max_descriptor
114
- )
115
-
116
- value_function_dict.update(_)
117
-
118
- result_dict = {
119
- key: value_function(default_normal_range_dict[key])
120
- for key, value_function in value_function_dict.items()
121
- }
153
+ result_dict = {key: value_function(default_normal_range_dict[key]) for key, value_function in value_function_dict.items()}
122
154
 
123
155
  # generate value
124
- return np.random.uniform(result_dict["min"], result_dict["max"])
125
-
156
+ return float(np.random.uniform(result_dict["min"], result_dict["max"]))
157
+
158
+ @property
159
+ def stddev(self):
160
+ """Alias to std_dev for backwards compatibility."""
161
+ return self.std_dev
162
+
163
+ @stddev.setter
164
+ def stddev(self, value):
165
+ self.std_dev = value
166
+
167
+ def _clip_to_bounds(self, value: float) -> float:
168
+ """Clip the provided value to the configured hard bounds if available."""
169
+ lower = self.min_value
170
+ upper = self.max_value
171
+
172
+ if lower is not None and upper is not None:
173
+ return float(np.clip(value, lower, upper))
174
+ if lower is not None:
175
+ return float(max(value, lower))
176
+ if upper is not None:
177
+ return float(min(value, upper))
178
+ return float(value)
179
+
180
+ def _validate_normal_parameters(self) -> None:
181
+ if self.mean is None or self.std_dev is None:
182
+ raise ValueError(f"Normal distribution '{getattr(self, 'name', self.pk)}' requires both mean and std_dev.")
183
+
184
+ def _validate_skewed_normal_parameters(self) -> None:
185
+ if self.mean is None or self.std_dev is None or self.skewness is None:
186
+ raise ValueError(f"Skewed normal distribution '{getattr(self, 'name', self.pk)}' requires mean, std_dev, and skewness.")
@@ -1,5 +1,6 @@
1
- from django.db import models
2
1
  import numpy as np
2
+ from django.db import models
3
+
3
4
  from .base_value_distribution import BaseValueDistribution
4
5
 
5
6
 
@@ -7,16 +8,16 @@ class SingleCategoricalValueDistributionManager(models.Manager):
7
8
  def get_by_natural_key(self, name):
8
9
  return self.get(name=name)
9
10
 
11
+
10
12
  class SingleCategoricalValueDistribution(BaseValueDistribution):
11
13
  """
12
14
  Single categorical value distribution model.
13
15
  Assigns a single value based on specified probabilities.
14
16
  """
17
+
15
18
  objects = SingleCategoricalValueDistributionManager()
16
19
  categories = models.JSONField() # { "category": "probability", ... }
17
20
 
18
21
  def generate_value(self):
19
22
  categories, probabilities = zip(*self.categories.items())
20
23
  return np.random.choice(categories, p=probabilities)
21
-
22
-
@@ -1,21 +1,26 @@
1
- from django.db import models
2
1
  from typing import TYPE_CHECKING, List
3
2
 
3
+ from django.db import models
4
+
4
5
  if TYPE_CHECKING:
5
6
  from ...administration import ReferenceProduct
6
7
  from ..unit import Unit
7
8
 
9
+
8
10
  class EmissionFactorManager(models.Manager):
9
11
  """
10
12
  Manager for EmissionFactor with custom query methods.
11
13
  """
14
+
12
15
  def get_by_natural_key(self, name: str) -> "EmissionFactor":
13
16
  return self.get(name=name)
14
17
 
18
+
15
19
  # get debug from settings
16
20
  # from django.conf import settings
17
21
  # DEBUG = settings.DEBUG
18
22
 
23
+
19
24
  class EmissionFactor(models.Model):
20
25
  """
21
26
  Represents an emission factor with associated unit and value.
@@ -25,6 +30,7 @@ class EmissionFactor(models.Model):
25
30
  unit (ForeignKey): The unit associated with the emission factor.
26
31
  value (float): The value of the emission factor.
27
32
  """
33
+
28
34
  objects = EmissionFactorManager()
29
35
 
30
36
  name = models.CharField(max_length=255)
@@ -32,13 +38,17 @@ class EmissionFactor(models.Model):
32
38
  value = models.FloatField()
33
39
 
34
40
  if TYPE_CHECKING:
35
- unit: "Unit"
36
- reference_products: models.QuerySet["ReferenceProduct"]
37
- reference_product_package: models.QuerySet["ReferenceProduct"]
38
- reference_product_product: models.QuerySet["ReferenceProduct"]
41
+ unit: models.ForeignKey["Unit|None"]
42
+
43
+ @property
44
+ def reference_products(self) -> models.QuerySet["ReferenceProduct"]: ...
45
+
46
+ @property
47
+ def reference_product_package(self) -> models.QuerySet["ReferenceProduct"]: ...
48
+
49
+ @property
50
+ def reference_product_product(self) -> models.QuerySet["ReferenceProduct"]: ...
39
51
 
40
-
41
-
42
52
  def natural_key(self) -> tuple:
43
53
  """
44
54
  Returns the natural key for the emission factor.
@@ -65,7 +75,7 @@ class EmissionFactor(models.Model):
65
75
  result += f"\n\t\t{source}"
66
76
 
67
77
  return result
68
-
78
+
69
79
  def get_reference_products(self) -> List["ReferenceProduct"]:
70
80
  """
71
81
  Retrieves all reference products associated with the emission factor.
@@ -1,15 +1,19 @@
1
- from django.db import models
2
1
  from typing import TYPE_CHECKING
3
2
 
3
+ from django.db import models
4
+
4
5
  if TYPE_CHECKING:
5
6
  from ..administration import Patient
6
7
 
8
+
7
9
  class GenderManager(models.Manager):
8
10
  def get_by_natural_key(self, name):
9
11
  return self.get(name=name)
10
-
12
+
13
+
11
14
  class Gender(models.Model):
12
15
  """A class representing gender."""
16
+
13
17
  objects = GenderManager()
14
18
 
15
19
  name = models.CharField(max_length=255)
@@ -17,11 +21,12 @@ class Gender(models.Model):
17
21
  description = models.TextField(blank=True, null=True)
18
22
 
19
23
  if TYPE_CHECKING:
20
- patients: models.QuerySet["Patient"]
24
+
25
+ @property
26
+ def patients(self) -> models.QuerySet["Patient"]: ...
21
27
 
22
28
  def natural_key(self):
23
29
  return (self.name,)
24
-
30
+
25
31
  def __str__(self):
26
32
  return str(self.name)
27
-
@@ -1,12 +1,12 @@
1
- from django.db import models
2
1
  from typing import TYPE_CHECKING
3
- if TYPE_CHECKING:
4
- from endoreg_db.models import InformationSourceType
2
+
3
+ from django.db import models
4
+
5
5
 
6
6
  def get_prediction_information_source():
7
7
  """
8
8
  Returns the InformationSource instance with the name "prediction".
9
-
9
+
10
10
  Raises:
11
11
  AssertionError: If no InformationSource with the name "prediction" exists.
12
12
  """
@@ -21,10 +21,10 @@ class InformationSourceManager(models.Manager):
21
21
  def get_by_natural_key(self, name):
22
22
  """
23
23
  Retrieves a model instance using its natural key.
24
-
24
+
25
25
  Args:
26
26
  name: The natural key value corresponding to the model's 'name' field.
27
-
27
+
28
28
  Returns:
29
29
  The model instance that matches the provided natural key.
30
30
  """
@@ -42,11 +42,36 @@ class InformationSource(models.Model):
42
42
  date_created = models.DateField(auto_now_add=True)
43
43
  date_modified = models.DateField(auto_now=True)
44
44
  abbreviation = models.CharField(max_length=100, blank=True, null=True, unique=True)
45
-
45
+
46
46
  if TYPE_CHECKING:
47
- #information_source_types: models.QuerySet["InformationSourceType"]
48
- # Avoid self-referential import; use forward references instead
49
- pass
47
+ from endoreg_db.models import (
48
+ Examination,
49
+ ExaminationIndication,
50
+ ExaminationTime,
51
+ Finding,
52
+ FindingClassification,
53
+ FindingIntervention,
54
+ InformationSourceType,
55
+ )
56
+
57
+ @property
58
+ def examinations(self) -> "models.manager.RelatedManager[Examination]": ...
59
+
60
+ @property
61
+ def examination_indications(self) -> "models.manager.RelatedManager[ExaminationIndication]": ...
62
+
63
+ @property
64
+ def examination_times(self) -> "models.manager.RelatedManager[ExaminationTime]": ...
65
+
66
+ @property
67
+ def findings(self) -> "models.manager.RelatedManager[Finding]": ...
68
+
69
+ @property
70
+ def finding_interventions(self) -> "models.manager.RelatedManager[FindingIntervention]": ...
71
+
72
+ @property
73
+ def finding_classifications(self) -> "models.manager.RelatedManager[FindingClassification]": ...
74
+
50
75
  class Meta:
51
76
  verbose_name = "Information Source"
52
77
  verbose_name_plural = "Information Sources"
@@ -55,14 +80,13 @@ class InformationSource(models.Model):
55
80
  indexes = [
56
81
  models.Index(fields=["name"]),
57
82
  models.Index(fields=["abbreviation"]),
58
- ]
59
-
83
+ ]
60
84
 
61
85
  def natural_key(self):
62
86
  """
63
87
  Returns the natural key tuple for the information source.
64
-
65
- The tuple contains the object's name, which uniquely identifies it for
88
+
89
+ The tuple contains the object's name, which uniquely identifies it for
66
90
  serialization and natural key lookup.
67
91
  """
68
92
  return (self.name,)
@@ -73,19 +97,21 @@ class InformationSource(models.Model):
73
97
  """
74
98
  return str(self.name)
75
99
 
100
+
76
101
  class InformationSourceTypeManager(models.Manager):
77
102
  def get_by_natural_key(self, name):
78
103
  """
79
104
  Retrieve an instance of the model by its natural key, which is the 'name' field.
80
-
105
+
81
106
  Parameters:
82
107
  name (str): The value of the 'name' field to look up.
83
-
108
+
84
109
  Returns:
85
110
  The model instance with the specified name.
86
111
  """
87
112
  return self.get(name=name)
88
-
113
+
114
+
89
115
  class InformationSourceType(models.Model):
90
116
  objects = InformationSourceTypeManager()
91
117
 
@@ -108,10 +134,10 @@ class InformationSourceType(models.Model):
108
134
  def get_prediction_type(cls) -> "InformationSourceType":
109
135
  """
110
136
  Return the InformationSourceType instance with the name "prediction".
111
-
137
+
112
138
  Returns:
113
139
  InformationSourceType: The instance representing the "prediction" information source type.
114
-
140
+
115
141
  Raises:
116
142
  InformationSourceType.DoesNotExist: If no such instance exists.
117
143
 
@@ -119,20 +145,17 @@ class InformationSourceType(models.Model):
119
145
  try:
120
146
  return cls.objects.get(name="prediction")
121
147
  except cls.DoesNotExist as e:
122
- raise cls.DoesNotExist(
123
- "The 'prediction' InformationSourceType was not found. "
124
- "Please check your data fixtures or initial data migrations."
125
- ) from e
148
+ raise cls.DoesNotExist("The 'prediction' InformationSourceType was not found. Please check your data fixtures or initial data migrations.") from e
126
149
 
127
150
  @classmethod
128
151
  def get_manual_annotation_type(cls) -> "InformationSourceType":
129
152
  """
130
153
 
131
154
  Return the InformationSourceType instance representing manual annotation.
132
-
155
+
133
156
  Returns:
134
157
  InformationSourceType: The instance with name "annotation".
135
-
158
+
136
159
  Raises:
137
160
  AssertionError: If no InformationSourceType with name "annotation" exists.
138
161
 
@@ -141,11 +164,9 @@ class InformationSourceType(models.Model):
141
164
  return cls.objects.get(name="manual_annotation")
142
165
  except cls.DoesNotExist as e:
143
166
  raise cls.DoesNotExist(
144
- "The 'manual_annotation' InformationSourceType was not found. "
145
- "Please check your data fixtures or initial data migrations."
167
+ "The 'manual_annotation' InformationSourceType was not found. Please check your data fixtures or initial data migrations."
146
168
  ) from e
147
169
 
148
-
149
170
  def natural_key(self):
150
171
  """
151
172
  Return a tuple containing the name of the information source type for natural key serialization.
@@ -156,4 +177,4 @@ class InformationSourceType(models.Model):
156
177
  """
157
178
  Return the name of the InformationSourceType as its string representation.
158
179
  """
159
- return str(self.name)
180
+ return str(self.name)
@@ -1,15 +1,17 @@
1
- from django.db import models
2
1
  from typing import TYPE_CHECKING
3
2
 
3
+ from django.db import models
4
4
 
5
5
  if TYPE_CHECKING:
6
- from .emission import EmissionFactor
7
6
  from ..administration.product.product_material import ProductMaterial
7
+ from .emission import EmissionFactor
8
+
8
9
 
9
10
  class MaterialManager(models.Manager):
10
11
  def get_by_natural_key(self, name):
11
12
  return self.get(name=name)
12
13
 
14
+
13
15
  class Material(models.Model):
14
16
  objects = MaterialManager()
15
17
 
@@ -17,12 +19,14 @@ class Material(models.Model):
17
19
  emission_factor = models.ForeignKey("EmissionFactor", on_delete=models.SET_NULL, null=True)
18
20
 
19
21
  if TYPE_CHECKING:
20
- emission_factor: "EmissionFactor"
21
- material_product_materials: models.QuerySet["ProductMaterial"]
22
+ emission_factor: models.ForeignKey["EmissionFactor|None"]
23
+
24
+ @property
25
+ def material_product_materials(self) -> models.QuerySet["ProductMaterial"]: ...
22
26
 
23
27
  def natural_key(self):
24
28
  return (self.name,)
25
-
29
+
26
30
  def __str__(self):
27
31
  result = f"{self.name} - EmissionFactor: {self.emission_factor}"
28
32
  return result
@@ -1,9 +1,11 @@
1
1
  from django.db import models
2
2
 
3
+
3
4
  class ResourceManager(models.Manager):
4
5
  def get_by_natural_key(self, name):
5
6
  return self.get(name=name)
6
-
7
+
8
+
7
9
  class Resource(models.Model):
8
10
  objects = ResourceManager()
9
11
 
@@ -12,11 +14,11 @@ class Resource(models.Model):
12
14
  def natural_key(self):
13
15
  """
14
16
  Return a tuple representing the natural key for this resource instance.
15
-
17
+
16
18
  Returns:
17
19
  tuple: A one-element tuple containing the resource's name.
18
20
  """
19
21
  return (self.name,)
20
-
22
+
21
23
  def __str__(self):
22
- return self.name
24
+ return self.name
@@ -1,20 +1,25 @@
1
- from django.db import models
2
1
  from typing import TYPE_CHECKING
3
2
 
3
+ from django.db import models
4
+
4
5
  if TYPE_CHECKING:
5
6
  from endoreg_db.models import RequirementSet
6
7
 
8
+
7
9
  class TagManager(models.Manager):
8
10
  def get_by_natural_key(self, name):
9
11
  return self.get(name=name)
10
-
12
+
13
+
11
14
  class Tag(models.Model):
12
15
  name = models.CharField(max_length=100, unique=True)
13
16
 
14
17
  objects = TagManager()
15
-
18
+
16
19
  if TYPE_CHECKING:
17
- requirement_sets: "models.ManyToManyField[RequirementSet]"
20
+
21
+ @property
22
+ def requirement_sets(self) -> "models.QuerySet[RequirementSet]": ...
18
23
 
19
24
  class Meta:
20
25
  verbose_name = "Tag"
@@ -24,4 +29,4 @@ class Tag(models.Model):
24
29
  return self.name
25
30
 
26
31
  def natural_key(self):
27
- return (self.name,)
32
+ return (self.name,)
@@ -1,17 +1,20 @@
1
- from django.db import models
2
1
  from typing import TYPE_CHECKING
3
2
 
3
+ from django.db import models
4
+
4
5
  if TYPE_CHECKING:
5
6
  from endoreg_db.models import (
6
- Product,
7
7
  EmissionFactor,
8
+ Product,
8
9
  Unit,
9
10
  )
10
11
 
12
+
11
13
  class TransportRouteManager(models.Manager):
12
14
  def get_by_natural_key(self, name):
13
15
  return self.get(name=name)
14
-
16
+
17
+
15
18
  class TransportRoute(models.Model):
16
19
  objects = TransportRouteManager()
17
20
 
@@ -21,13 +24,15 @@ class TransportRoute(models.Model):
21
24
  unit = models.ForeignKey("Unit", on_delete=models.SET_NULL, null=True)
22
25
 
23
26
  if TYPE_CHECKING:
24
- emission_factor: "EmissionFactor"
25
- unit: "Unit"
26
- products: models.QuerySet["Product"]
27
+ emission_factor: models.ForeignKey["EmissionFactor|None"]
28
+ unit: models.ForeignKey["Unit|None"]
29
+
30
+ @property
31
+ def products(self) -> models.QuerySet["Product"]: ...
27
32
 
28
33
  def natural_key(self):
29
34
  return (self.name,)
30
-
35
+
31
36
  def __str__(self):
32
37
  result = f"{self.name} ({self.distance} {self.unit}) - {self.emission_factor}"
33
- return result
38
+ return result