endoreg-db 0.8.5.1__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 (794) hide show
  1. endoreg_db/__init__.py +0 -0
  2. endoreg_db/admin.py +92 -0
  3. endoreg_db/api/serializers/finding_descriptions.py +0 -0
  4. endoreg_db/api/views/finding_descriptions.py +0 -0
  5. endoreg_db/api_urls.py +4 -0
  6. endoreg_db/apps.py +18 -0
  7. endoreg_db/assets/dummy_model.ckpt +1 -0
  8. endoreg_db/codemods/readme.md +88 -0
  9. endoreg_db/codemods/rename_datetime_fields.py +92 -0
  10. endoreg_db/config/__init__.py +0 -0
  11. endoreg_db/config/env.py +101 -0
  12. endoreg_db/data/__init__.py +144 -0
  13. endoreg_db/data/ai_model/data.yaml +7 -0
  14. endoreg_db/data/ai_model_label/label/data.yaml +88 -0
  15. endoreg_db/data/ai_model_label/label/polyp_classification.yaml +52 -0
  16. endoreg_db/data/ai_model_label/label-set/data.yaml +40 -0
  17. endoreg_db/data/ai_model_label/label-set/polyp_classifications.yaml +25 -0
  18. endoreg_db/data/ai_model_label/label-type/data.yaml +7 -0
  19. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +27 -0
  20. endoreg_db/data/ai_model_type/data.yaml +7 -0
  21. endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml +176 -0
  22. endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml +20 -0
  23. endoreg_db/data/case_template/rule/00_patient_lab_sample_add_default_value.yaml +167 -0
  24. endoreg_db/data/case_template/rule/01_patient-set-age.yaml +8 -0
  25. endoreg_db/data/case_template/rule/01_patient-set-gender.yaml +9 -0
  26. endoreg_db/data/case_template/rule/11_create_patient_lab_sample.yaml +23 -0
  27. endoreg_db/data/case_template/rule/12_create-patient_medication-anticoagulation.yaml +19 -0
  28. endoreg_db/data/case_template/rule/13_create-patient_medication_schedule-anticoagulation.yaml +19 -0
  29. endoreg_db/data/case_template/rule/19_create_patient.yaml +17 -0
  30. endoreg_db/data/case_template/rule_type/base_types.yaml +35 -0
  31. endoreg_db/data/case_template/rule_value/.init +0 -0
  32. endoreg_db/data/case_template/rule_value_type/base_types.yaml +59 -0
  33. endoreg_db/data/case_template/template/base.yaml +8 -0
  34. endoreg_db/data/case_template/template_type/pre_endoscopy.yaml +3 -0
  35. endoreg_db/data/case_template/tmp/_rule_value +13 -0
  36. endoreg_db/data/case_template/tmp/rule/01_atrial_fibrillation.yaml +21 -0
  37. endoreg_db/data/case_template/tmp/rule/02_create_object.yaml +10 -0
  38. endoreg_db/data/case_template/tmp/template/atrial_fibrillation_low_risk.yaml +7 -0
  39. endoreg_db/data/center/data.yaml +91 -0
  40. endoreg_db/data/center_resource/green_endoscopy_dashboard_CenterResource.yaml +144 -0
  41. endoreg_db/data/center_shift/ukw.yaml +9 -0
  42. endoreg_db/data/center_waste/green_endoscopy_dashboard_CenterWaste.yaml +48 -0
  43. endoreg_db/data/contraindication/bleeding.yaml +11 -0
  44. endoreg_db/data/db_summary.csv +58 -0
  45. endoreg_db/data/db_summary.xlsx +0 -0
  46. endoreg_db/data/disease/cardiovascular.yaml +37 -0
  47. endoreg_db/data/disease/hepatology.yaml +5 -0
  48. endoreg_db/data/disease/misc.yaml +5 -0
  49. endoreg_db/data/disease/renal.yaml +5 -0
  50. endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +6 -0
  51. endoreg_db/data/disease_classification/coronary_vessel_disease.yaml +6 -0
  52. endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +41 -0
  53. endoreg_db/data/disease_classification_choice/coronary_vessel_disease.yaml +20 -0
  54. endoreg_db/data/distribution/date/patient.yaml +7 -0
  55. endoreg_db/data/distribution/multiple_categorical/.init +0 -0
  56. endoreg_db/data/distribution/numeric/data.yaml +14 -0
  57. endoreg_db/data/distribution/single_categorical/patient.yaml +7 -0
  58. endoreg_db/data/emission_factor/green_endoscopy_dashboard_EmissionFactor.yaml +132 -0
  59. endoreg_db/data/endoscope/data.yaml +93 -0
  60. endoreg_db/data/endoscope_type/data.yaml +11 -0
  61. endoreg_db/data/endoscopy_processor/data.yaml +50 -0
  62. endoreg_db/data/event/cardiology.yaml +15 -0
  63. endoreg_db/data/event/neurology.yaml +14 -0
  64. endoreg_db/data/event/surgery.yaml +13 -0
  65. endoreg_db/data/event/thrombembolism.yaml +20 -0
  66. endoreg_db/data/examination/examinations/data.yaml +72 -0
  67. endoreg_db/data/examination/time/data.yaml +48 -0
  68. endoreg_db/data/examination/time-type/data.yaml +8 -0
  69. endoreg_db/data/examination/type/data.yaml +17 -0
  70. endoreg_db/data/examination_indication/endoscopy.yaml +424 -0
  71. endoreg_db/data/examination_indication_classification/endoscopy.yaml +160 -0
  72. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
  73. endoreg_db/data/examination_requirement_set/colonoscopy.yaml +15 -0
  74. endoreg_db/data/finding/anatomy_colon.yaml +128 -0
  75. endoreg_db/data/finding/colonoscopy.yaml +40 -0
  76. endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +56 -0
  77. endoreg_db/data/finding/complication.yaml +16 -0
  78. endoreg_db/data/finding/data.yaml +105 -0
  79. endoreg_db/data/finding/examination_setting.yaml +16 -0
  80. endoreg_db/data/finding/medication_related.yaml +18 -0
  81. endoreg_db/data/finding/outcome.yaml +12 -0
  82. endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +95 -0
  83. endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +22 -0
  84. endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +25 -0
  85. endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
  86. endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
  87. endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +68 -0
  88. endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
  89. endoreg_db/data/finding_classification/colonoscopy_location.yaml +80 -0
  90. endoreg_db/data/finding_classification/colonoscopy_lst.yaml +21 -0
  91. endoreg_db/data/finding_classification/colonoscopy_nice.yaml +20 -0
  92. endoreg_db/data/finding_classification/colonoscopy_paris.yaml +26 -0
  93. endoreg_db/data/finding_classification/colonoscopy_sano.yaml +22 -0
  94. endoreg_db/data/finding_classification/colonoscopy_summary.yaml +53 -0
  95. endoreg_db/data/finding_classification/complication_generic.yaml +25 -0
  96. endoreg_db/data/finding_classification/examination_setting_generic.yaml +40 -0
  97. endoreg_db/data/finding_classification/histology_colo.yaml +51 -0
  98. endoreg_db/data/finding_classification/intervention_required.yaml +26 -0
  99. endoreg_db/data/finding_classification/medication_related.yaml +23 -0
  100. endoreg_db/data/finding_classification/visualized.yaml +33 -0
  101. endoreg_db/data/finding_classification_choice/bowel_preparation.yaml +78 -0
  102. endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +32 -0
  103. endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
  104. endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
  105. endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +15 -0
  106. endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +17 -0
  107. endoreg_db/data/finding_classification_choice/colon_lesion_paris.yaml +57 -0
  108. endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +49 -0
  109. endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +14 -0
  110. endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +36 -0
  111. endoreg_db/data/finding_classification_choice/colonoscopy_location.yaml +229 -0
  112. endoreg_db/data/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
  113. endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +82 -0
  114. endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
  115. endoreg_db/data/finding_classification_choice/complication_generic_types.yaml +15 -0
  116. endoreg_db/data/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
  117. endoreg_db/data/finding_classification_choice/histology.yaml +24 -0
  118. endoreg_db/data/finding_classification_choice/histology_polyp.yaml +20 -0
  119. endoreg_db/data/finding_classification_choice/outcome.yaml +19 -0
  120. endoreg_db/data/finding_classification_choice/yes_no_na.yaml +11 -0
  121. endoreg_db/data/finding_classification_type/colonoscopy_basic.yaml +48 -0
  122. endoreg_db/data/finding_intervention/endoscopy.yaml +43 -0
  123. endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +168 -0
  124. endoreg_db/data/finding_intervention/endoscopy_egd.yaml +128 -0
  125. endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +32 -0
  126. endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +9 -0
  127. endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +36 -0
  128. endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
  129. endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
  130. endoreg_db/data/finding_type/data.yaml +43 -0
  131. endoreg_db/data/gender/data.yaml +42 -0
  132. endoreg_db/data/information_source/annotation.yaml +6 -0
  133. endoreg_db/data/information_source/data.yaml +30 -0
  134. endoreg_db/data/information_source/endoscopy_guidelines.yaml +7 -0
  135. endoreg_db/data/information_source/medication.yaml +6 -0
  136. endoreg_db/data/information_source/prediction.yaml +7 -0
  137. endoreg_db/data/information_source_type/data.yaml +8 -0
  138. endoreg_db/data/lab_value/cardiac_enzymes.yaml +37 -0
  139. endoreg_db/data/lab_value/coagulation.yaml +54 -0
  140. endoreg_db/data/lab_value/electrolytes.yaml +228 -0
  141. endoreg_db/data/lab_value/gastrointestinal_function.yaml +133 -0
  142. endoreg_db/data/lab_value/hematology.yaml +184 -0
  143. endoreg_db/data/lab_value/hormones.yaml +59 -0
  144. endoreg_db/data/lab_value/lipids.yaml +53 -0
  145. endoreg_db/data/lab_value/misc.yaml +76 -0
  146. endoreg_db/data/lab_value/renal_function.yaml +12 -0
  147. endoreg_db/data/log_type/data.yaml +57 -0
  148. endoreg_db/data/lx_client_tag/base.yaml +54 -0
  149. endoreg_db/data/lx_client_type/base.yaml +30 -0
  150. endoreg_db/data/lx_permission/base.yaml +24 -0
  151. endoreg_db/data/lx_permission/endoreg.yaml +52 -0
  152. endoreg_db/data/material/material.yaml +91 -0
  153. endoreg_db/data/medication/anticoagulation.yaml +65 -0
  154. endoreg_db/data/medication/tah.yaml +70 -0
  155. endoreg_db/data/medication_indication/anticoagulation.yaml +115 -0
  156. endoreg_db/data/medication_indication_type/data.yaml +11 -0
  157. endoreg_db/data/medication_indication_type/thrombembolism.yaml +41 -0
  158. endoreg_db/data/medication_intake_time/base.yaml +31 -0
  159. endoreg_db/data/medication_schedule/apixaban.yaml +95 -0
  160. endoreg_db/data/medication_schedule/ass.yaml +12 -0
  161. endoreg_db/data/medication_schedule/enoxaparin.yaml +26 -0
  162. endoreg_db/data/names_first/first_names.yaml +54 -0
  163. endoreg_db/data/names_last/last_names.yaml +51 -0
  164. endoreg_db/data/network_device/data.yaml +59 -0
  165. endoreg_db/data/network_device_type/data.yaml +12 -0
  166. endoreg_db/data/organ/data.yaml +29 -0
  167. endoreg_db/data/patient_lab_sample_type/generic.yaml +6 -0
  168. endoreg_db/data/pdf_type/data.yaml +46 -0
  169. endoreg_db/data/product/green_endoscopy_dashboard_Product.yaml +66 -0
  170. endoreg_db/data/product_group/green_endoscopy_dashboard_ProductGroup.yaml +33 -0
  171. endoreg_db/data/product_material/green_endoscopy_dashboard_ProductMaterial.yaml +308 -0
  172. endoreg_db/data/product_weight/green_endoscopy_dashboard_ProductWeight.yaml +88 -0
  173. endoreg_db/data/profession/data.yaml +70 -0
  174. endoreg_db/data/qualification/endoscopy.yaml +36 -0
  175. endoreg_db/data/qualification/m2.yaml +39 -0
  176. endoreg_db/data/qualification/outpatient_clinic.yaml +35 -0
  177. endoreg_db/data/qualification/sonography.yaml +36 -0
  178. endoreg_db/data/qualification_type/base.yaml +29 -0
  179. endoreg_db/data/reference_product/green_endoscopy_dashboard_ReferenceProduct.yaml +55 -0
  180. endoreg_db/data/report_reader_flag/rkh-histology-generic.yaml +10 -0
  181. endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +30 -0
  182. endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +24 -0
  183. endoreg_db/data/requirement/age.yaml +26 -0
  184. endoreg_db/data/requirement/colonoscopy_baseline_austria.yaml +45 -0
  185. endoreg_db/data/requirement/disease_cardiovascular.yaml +79 -0
  186. endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +41 -0
  187. endoreg_db/data/requirement/disease_hepatology.yaml +12 -0
  188. endoreg_db/data/requirement/disease_misc.yaml +12 -0
  189. endoreg_db/data/requirement/disease_renal.yaml +96 -0
  190. endoreg_db/data/requirement/endoscopy_bleeding_risk.yaml +59 -0
  191. endoreg_db/data/requirement/event_cardiology.yaml +251 -0
  192. endoreg_db/data/requirement/event_requirements.yaml +145 -0
  193. endoreg_db/data/requirement/finding_colon_polyp.yaml +50 -0
  194. endoreg_db/data/requirement/gender.yaml +25 -0
  195. endoreg_db/data/requirement/lab_value.yaml +441 -0
  196. endoreg_db/data/requirement/medication.yaml +93 -0
  197. endoreg_db/data/requirement_operator/age.yaml +13 -0
  198. endoreg_db/data/requirement_operator/lab_operators.yaml +129 -0
  199. endoreg_db/data/requirement_operator/model_operators.yaml +96 -0
  200. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +48 -0
  201. endoreg_db/data/requirement_set/colonoscopy_austria_screening.yaml +57 -0
  202. endoreg_db/data/requirement_set/endoscopy_bleeding_risk.yaml +52 -0
  203. endoreg_db/data/requirement_set_type/data.yaml +20 -0
  204. endoreg_db/data/requirement_type/requirement_types.yaml +165 -0
  205. endoreg_db/data/resource/green_endoscopy_dashboard_Resource.yaml +15 -0
  206. endoreg_db/data/risk/bleeding.yaml +26 -0
  207. endoreg_db/data/risk/thrombosis.yaml +37 -0
  208. endoreg_db/data/risk_type/data.yaml +27 -0
  209. endoreg_db/data/setup_config.yaml +38 -0
  210. endoreg_db/data/shift/endoscopy.yaml +21 -0
  211. endoreg_db/data/shift/m2.yaml +0 -0
  212. endoreg_db/data/shift_type/base.yaml +35 -0
  213. endoreg_db/data/tag/requirement_set_tags.yaml +11 -0
  214. endoreg_db/data/tmp/chronic_kidney_disease.yaml +0 -0
  215. endoreg_db/data/tmp/congestive_heart_failure.yaml +0 -0
  216. endoreg_db/data/transport_route/green_endoscopy_dashboard_TransportRoute.yaml +12 -0
  217. endoreg_db/data/unit/concentration.yaml +115 -0
  218. endoreg_db/data/unit/data.yaml +17 -0
  219. endoreg_db/data/unit/length.yaml +31 -0
  220. endoreg_db/data/unit/misc.yaml +20 -0
  221. endoreg_db/data/unit/rate.yaml +6 -0
  222. endoreg_db/data/unit/time.yaml +48 -0
  223. endoreg_db/data/unit/volume.yaml +35 -0
  224. endoreg_db/data/unit/weight.yaml +38 -0
  225. endoreg_db/data/waste/data.yaml +12 -0
  226. endoreg_db/exceptions.py +19 -0
  227. endoreg_db/factories/__init__.py +0 -0
  228. endoreg_db/forms/__init__.py +5 -0
  229. endoreg_db/forms/examination_form.py +11 -0
  230. endoreg_db/forms/patient_finding_intervention_form.py +18 -0
  231. endoreg_db/forms/patient_form.py +27 -0
  232. endoreg_db/forms/questionnaires/__init__.py +1 -0
  233. endoreg_db/forms/questionnaires/tto_questionnaire.py +23 -0
  234. endoreg_db/forms/settings/__init__.py +8 -0
  235. endoreg_db/forms/unit.py +6 -0
  236. endoreg_db/helpers/__init__.py +0 -0
  237. endoreg_db/helpers/count_db.py +45 -0
  238. endoreg_db/helpers/data_loader.py +208 -0
  239. endoreg_db/helpers/default_objects.py +378 -0
  240. endoreg_db/helpers/download_segmentation_model.py +31 -0
  241. endoreg_db/helpers/interact.py +6 -0
  242. endoreg_db/helpers/test_video_helper.py +119 -0
  243. endoreg_db/logger_conf.py +140 -0
  244. endoreg_db/management/__init__.py +1 -0
  245. endoreg_db/management/commands/__init__.py +1 -0
  246. endoreg_db/management/commands/anonymize_video.py +0 -0
  247. endoreg_db/management/commands/check_auth.py +125 -0
  248. endoreg_db/management/commands/create_model_meta_from_huggingface.py +115 -0
  249. endoreg_db/management/commands/create_multilabel_model_meta.py +214 -0
  250. endoreg_db/management/commands/fix_missing_patient_data.py +172 -0
  251. endoreg_db/management/commands/fix_video_paths.py +165 -0
  252. endoreg_db/management/commands/import_fallback_video.py +203 -0
  253. endoreg_db/management/commands/import_report.py +298 -0
  254. endoreg_db/management/commands/import_video.py +423 -0
  255. endoreg_db/management/commands/import_video_with_classification.py +367 -0
  256. endoreg_db/management/commands/init_default_ai_model.py +112 -0
  257. endoreg_db/management/commands/load_ai_model_data.py +77 -0
  258. endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
  259. endoreg_db/management/commands/load_base_db_data.py +192 -0
  260. endoreg_db/management/commands/load_center_data.py +68 -0
  261. endoreg_db/management/commands/load_contraindication_data.py +41 -0
  262. endoreg_db/management/commands/load_disease_classification_choices_data.py +41 -0
  263. endoreg_db/management/commands/load_disease_classification_data.py +41 -0
  264. endoreg_db/management/commands/load_disease_data.py +62 -0
  265. endoreg_db/management/commands/load_distribution_data.py +66 -0
  266. endoreg_db/management/commands/load_endoscope_data.py +68 -0
  267. endoreg_db/management/commands/load_event_data.py +41 -0
  268. endoreg_db/management/commands/load_examination_data.py +75 -0
  269. endoreg_db/management/commands/load_examination_indication_data.py +86 -0
  270. endoreg_db/management/commands/load_finding_data.py +128 -0
  271. endoreg_db/management/commands/load_gender_data.py +44 -0
  272. endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +132 -0
  273. endoreg_db/management/commands/load_information_source.py +51 -0
  274. endoreg_db/management/commands/load_lab_value_data.py +50 -0
  275. endoreg_db/management/commands/load_medication_data.py +103 -0
  276. endoreg_db/management/commands/load_name_data.py +37 -0
  277. endoreg_db/management/commands/load_organ_data.py +43 -0
  278. endoreg_db/management/commands/load_pdf_type_data.py +61 -0
  279. endoreg_db/management/commands/load_profession_data.py +44 -0
  280. endoreg_db/management/commands/load_qualification_data.py +59 -0
  281. endoreg_db/management/commands/load_report_reader_flag_data.py +46 -0
  282. endoreg_db/management/commands/load_requirement_data.py +180 -0
  283. endoreg_db/management/commands/load_risk_data.py +56 -0
  284. endoreg_db/management/commands/load_shift_data.py +60 -0
  285. endoreg_db/management/commands/load_tag_data.py +57 -0
  286. endoreg_db/management/commands/load_unit_data.py +46 -0
  287. endoreg_db/management/commands/load_user_groups.py +28 -0
  288. endoreg_db/management/commands/register_ai_model.py +64 -0
  289. endoreg_db/management/commands/reset_celery_schedule.py +9 -0
  290. endoreg_db/management/commands/setup_endoreg_db.py +381 -0
  291. endoreg_db/management/commands/start_filewatcher.py +106 -0
  292. endoreg_db/management/commands/storage_management.py +548 -0
  293. endoreg_db/management/commands/summarize_db_content.py +189 -0
  294. endoreg_db/management/commands/validate_video.py +204 -0
  295. endoreg_db/management/commands/validate_video_files.py +161 -0
  296. endoreg_db/management/commands/video_validation.py +22 -0
  297. endoreg_db/mermaid/Overall_flow_patient_finding_intervention.md +10 -0
  298. endoreg_db/mermaid/anonymized_image_annotation.md +20 -0
  299. endoreg_db/mermaid/binary_classification_annotation.md +50 -0
  300. endoreg_db/mermaid/classification.md +8 -0
  301. endoreg_db/mermaid/examination.md +8 -0
  302. endoreg_db/mermaid/findings.md +7 -0
  303. endoreg_db/mermaid/image_classification.md +28 -0
  304. endoreg_db/mermaid/interventions.md +8 -0
  305. endoreg_db/mermaid/morphology.md +8 -0
  306. endoreg_db/mermaid/patient_creation.md +14 -0
  307. endoreg_db/mermaid/video_segmentation_annotation.md +17 -0
  308. endoreg_db/migrations/0001_initial.py +1857 -0
  309. endoreg_db/migrations/0002_add_video_correction_models.py +52 -0
  310. endoreg_db/migrations/0003_add_center_display_name.py +30 -0
  311. endoreg_db/migrations/__init__.py +0 -0
  312. endoreg_db/models/__init__.py +359 -0
  313. endoreg_db/models/administration/__init__.py +116 -0
  314. endoreg_db/models/administration/ai/__init__.py +9 -0
  315. endoreg_db/models/administration/ai/active_model.py +35 -0
  316. endoreg_db/models/administration/ai/ai_model.py +156 -0
  317. endoreg_db/models/administration/ai/model_type.py +41 -0
  318. endoreg_db/models/administration/case/__init__.py +19 -0
  319. endoreg_db/models/administration/case/case.py +114 -0
  320. endoreg_db/models/administration/case/case_template/__init__.py +15 -0
  321. endoreg_db/models/administration/case/case_template/case_template.py +125 -0
  322. endoreg_db/models/administration/case/case_template/case_template_rule.py +269 -0
  323. endoreg_db/models/administration/case/case_template/case_template_rule_value.py +86 -0
  324. endoreg_db/models/administration/case/case_template/case_template_type.py +26 -0
  325. endoreg_db/models/administration/center/__init__.py +13 -0
  326. endoreg_db/models/administration/center/center.py +67 -0
  327. endoreg_db/models/administration/center/center_product.py +64 -0
  328. endoreg_db/models/administration/center/center_resource.py +49 -0
  329. endoreg_db/models/administration/center/center_shift.py +88 -0
  330. endoreg_db/models/administration/center/center_waste.py +30 -0
  331. endoreg_db/models/administration/permissions/__init__.py +44 -0
  332. endoreg_db/models/administration/person/__init__.py +24 -0
  333. endoreg_db/models/administration/person/employee/__init__.py +3 -0
  334. endoreg_db/models/administration/person/employee/employee.py +35 -0
  335. endoreg_db/models/administration/person/employee/employee_qualification.py +39 -0
  336. endoreg_db/models/administration/person/employee/employee_type.py +42 -0
  337. endoreg_db/models/administration/person/examiner/__init__.py +4 -0
  338. endoreg_db/models/administration/person/examiner/examiner.py +54 -0
  339. endoreg_db/models/administration/person/names/__init__.py +0 -0
  340. endoreg_db/models/administration/person/names/first_name.py +18 -0
  341. endoreg_db/models/administration/person/names/last_name.py +19 -0
  342. endoreg_db/models/administration/person/patient/__init__.py +5 -0
  343. endoreg_db/models/administration/person/patient/patient.py +460 -0
  344. endoreg_db/models/administration/person/person.py +31 -0
  345. endoreg_db/models/administration/person/profession/__init__.py +24 -0
  346. endoreg_db/models/administration/person/user/__init__.py +5 -0
  347. endoreg_db/models/administration/person/user/portal_user_information.py +37 -0
  348. endoreg_db/models/administration/product/__init__.py +14 -0
  349. endoreg_db/models/administration/product/product.py +97 -0
  350. endoreg_db/models/administration/product/product_group.py +39 -0
  351. endoreg_db/models/administration/product/product_material.py +54 -0
  352. endoreg_db/models/administration/product/product_weight.py +47 -0
  353. endoreg_db/models/administration/product/reference_product.py +130 -0
  354. endoreg_db/models/administration/qualification/__init__.py +7 -0
  355. endoreg_db/models/administration/qualification/qualification.py +37 -0
  356. endoreg_db/models/administration/qualification/qualification_type.py +35 -0
  357. endoreg_db/models/administration/shift/__init__.py +9 -0
  358. endoreg_db/models/administration/shift/scheduled_days.py +69 -0
  359. endoreg_db/models/administration/shift/shift.py +51 -0
  360. endoreg_db/models/administration/shift/shift_type.py +108 -0
  361. endoreg_db/models/label/__init__.py +24 -0
  362. endoreg_db/models/label/annotation/__init__.py +12 -0
  363. endoreg_db/models/label/annotation/image_classification.py +84 -0
  364. endoreg_db/models/label/annotation/video_segmentation_annotation.py +66 -0
  365. endoreg_db/models/label/label.py +83 -0
  366. endoreg_db/models/label/label_set.py +53 -0
  367. endoreg_db/models/label/label_type.py +29 -0
  368. endoreg_db/models/label/label_video_segment/__init__.py +3 -0
  369. endoreg_db/models/label/label_video_segment/_create_from_video.py +41 -0
  370. endoreg_db/models/label/label_video_segment/label_video_segment.py +511 -0
  371. endoreg_db/models/label/video_segmentation_label.py +31 -0
  372. endoreg_db/models/label/video_segmentation_labelset.py +27 -0
  373. endoreg_db/models/media/__init__.py +16 -0
  374. endoreg_db/models/media/frame/__init__.py +3 -0
  375. endoreg_db/models/media/frame/frame.py +111 -0
  376. endoreg_db/models/media/pdf/__init__.py +11 -0
  377. endoreg_db/models/media/pdf/raw_pdf.py +613 -0
  378. endoreg_db/models/media/pdf/report_file.py +162 -0
  379. endoreg_db/models/media/pdf/report_reader/__init__.py +7 -0
  380. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +77 -0
  381. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +20 -0
  382. endoreg_db/models/media/video/__init__.py +8 -0
  383. endoreg_db/models/media/video/create_from_file.py +358 -0
  384. endoreg_db/models/media/video/pipe_1.py +213 -0
  385. endoreg_db/models/media/video/pipe_2.py +105 -0
  386. endoreg_db/models/media/video/refactor_plan.md +0 -0
  387. endoreg_db/models/media/video/video_file.py +699 -0
  388. endoreg_db/models/media/video/video_file_ai.py +443 -0
  389. endoreg_db/models/media/video/video_file_anonymize.py +349 -0
  390. endoreg_db/models/media/video/video_file_frames/__init__.py +47 -0
  391. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +22 -0
  392. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +23 -0
  393. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +104 -0
  394. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +174 -0
  395. endoreg_db/models/media/video/video_file_frames/_get_frame.py +28 -0
  396. endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +27 -0
  397. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +20 -0
  398. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +27 -0
  399. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +34 -0
  400. endoreg_db/models/media/video/video_file_frames/_get_frames.py +27 -0
  401. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +129 -0
  402. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +141 -0
  403. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +65 -0
  404. endoreg_db/models/media/video/video_file_frames.py +0 -0
  405. endoreg_db/models/media/video/video_file_io.py +168 -0
  406. endoreg_db/models/media/video/video_file_meta/__init__.py +22 -0
  407. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +45 -0
  408. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +39 -0
  409. endoreg_db/models/media/video/video_file_meta/get_fps.py +147 -0
  410. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +143 -0
  411. endoreg_db/models/media/video/video_file_meta/text_meta.py +134 -0
  412. endoreg_db/models/media/video/video_file_meta/video_meta.py +70 -0
  413. endoreg_db/models/media/video/video_file_segments.py +209 -0
  414. endoreg_db/models/media/video/video_metadata.py +65 -0
  415. endoreg_db/models/media/video/video_processing.py +152 -0
  416. endoreg_db/models/medical/__init__.py +146 -0
  417. endoreg_db/models/medical/contraindication/__init__.py +17 -0
  418. endoreg_db/models/medical/disease.py +156 -0
  419. endoreg_db/models/medical/event.py +137 -0
  420. endoreg_db/models/medical/examination/__init__.py +9 -0
  421. endoreg_db/models/medical/examination/examination.py +148 -0
  422. endoreg_db/models/medical/examination/examination_indication.py +278 -0
  423. endoreg_db/models/medical/examination/examination_time.py +49 -0
  424. endoreg_db/models/medical/examination/examination_time_type.py +41 -0
  425. endoreg_db/models/medical/examination/examination_type.py +48 -0
  426. endoreg_db/models/medical/finding/__init__.py +18 -0
  427. endoreg_db/models/medical/finding/finding.py +96 -0
  428. endoreg_db/models/medical/finding/finding_classification.py +142 -0
  429. endoreg_db/models/medical/finding/finding_intervention.py +52 -0
  430. endoreg_db/models/medical/finding/finding_type.py +35 -0
  431. endoreg_db/models/medical/hardware/__init__.py +8 -0
  432. endoreg_db/models/medical/hardware/endoscope.py +65 -0
  433. endoreg_db/models/medical/hardware/endoscopy_processor.py +182 -0
  434. endoreg_db/models/medical/laboratory/__init__.py +5 -0
  435. endoreg_db/models/medical/laboratory/lab_value.py +419 -0
  436. endoreg_db/models/medical/medication/__init__.py +19 -0
  437. endoreg_db/models/medical/medication/medication.py +31 -0
  438. endoreg_db/models/medical/medication/medication_indication.py +50 -0
  439. endoreg_db/models/medical/medication/medication_indication_type.py +39 -0
  440. endoreg_db/models/medical/medication/medication_intake_time.py +44 -0
  441. endoreg_db/models/medical/medication/medication_schedule.py +45 -0
  442. endoreg_db/models/medical/organ/__init__.py +35 -0
  443. endoreg_db/models/medical/patient/__init__.py +56 -0
  444. endoreg_db/models/medical/patient/medication_examples.py +38 -0
  445. endoreg_db/models/medical/patient/patient_disease.py +63 -0
  446. endoreg_db/models/medical/patient/patient_event.py +75 -0
  447. endoreg_db/models/medical/patient/patient_examination.py +249 -0
  448. endoreg_db/models/medical/patient/patient_examination_indication.py +44 -0
  449. endoreg_db/models/medical/patient/patient_finding.py +357 -0
  450. endoreg_db/models/medical/patient/patient_finding_classification.py +207 -0
  451. endoreg_db/models/medical/patient/patient_finding_intervention.py +40 -0
  452. endoreg_db/models/medical/patient/patient_lab_sample.py +148 -0
  453. endoreg_db/models/medical/patient/patient_lab_value.py +222 -0
  454. endoreg_db/models/medical/patient/patient_medication.py +104 -0
  455. endoreg_db/models/medical/patient/patient_medication_schedule.py +136 -0
  456. endoreg_db/models/medical/risk/__init__.py +7 -0
  457. endoreg_db/models/medical/risk/risk.py +72 -0
  458. endoreg_db/models/medical/risk/risk_type.py +51 -0
  459. endoreg_db/models/metadata/__init__.py +19 -0
  460. endoreg_db/models/metadata/frame_ocr_result.py +0 -0
  461. endoreg_db/models/metadata/model_meta.py +206 -0
  462. endoreg_db/models/metadata/model_meta_logic.py +343 -0
  463. endoreg_db/models/metadata/pdf_meta.py +89 -0
  464. endoreg_db/models/metadata/sensitive_meta.py +288 -0
  465. endoreg_db/models/metadata/sensitive_meta_logic.py +730 -0
  466. endoreg_db/models/metadata/video_meta.py +332 -0
  467. endoreg_db/models/metadata/video_prediction_logic.py +190 -0
  468. endoreg_db/models/metadata/video_prediction_meta.py +270 -0
  469. endoreg_db/models/other/__init__.py +40 -0
  470. endoreg_db/models/other/distribution/__init__.py +44 -0
  471. endoreg_db/models/other/distribution/base_value_distribution.py +20 -0
  472. endoreg_db/models/other/distribution/date_value_distribution.py +89 -0
  473. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
  474. endoreg_db/models/other/distribution/numeric_value_distribution.py +125 -0
  475. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
  476. endoreg_db/models/other/emission/__init__.py +5 -0
  477. endoreg_db/models/other/emission/emission_factor.py +94 -0
  478. endoreg_db/models/other/gender.py +27 -0
  479. endoreg_db/models/other/information_source.py +159 -0
  480. endoreg_db/models/other/material.py +28 -0
  481. endoreg_db/models/other/resource.py +22 -0
  482. endoreg_db/models/other/tag.py +27 -0
  483. endoreg_db/models/other/transport_route.py +33 -0
  484. endoreg_db/models/other/unit.py +32 -0
  485. endoreg_db/models/other/waste.py +27 -0
  486. endoreg_db/models/requirement/__init__.py +11 -0
  487. endoreg_db/models/requirement/requirement.py +767 -0
  488. endoreg_db/models/requirement/requirement_evaluation/__init__.py +6 -0
  489. endoreg_db/models/requirement/requirement_evaluation/get_values.py +40 -0
  490. endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +9 -0
  491. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +95 -0
  492. endoreg_db/models/requirement/requirement_operator.py +176 -0
  493. endoreg_db/models/requirement/requirement_set.py +287 -0
  494. endoreg_db/models/rule/__init__.py +13 -0
  495. endoreg_db/models/rule/rule.py +27 -0
  496. endoreg_db/models/rule/rule_applicator.py +224 -0
  497. endoreg_db/models/rule/rule_attribute_dtype.py +17 -0
  498. endoreg_db/models/rule/rule_type.py +20 -0
  499. endoreg_db/models/rule/ruleset.py +17 -0
  500. endoreg_db/models/state/__init__.py +12 -0
  501. endoreg_db/models/state/abstract.py +11 -0
  502. endoreg_db/models/state/audit_ledger.py +150 -0
  503. endoreg_db/models/state/label_video_segment.py +22 -0
  504. endoreg_db/models/state/raw_pdf.py +187 -0
  505. endoreg_db/models/state/sensitive_meta.py +46 -0
  506. endoreg_db/models/state/video.py +232 -0
  507. endoreg_db/models/upload_job.py +99 -0
  508. endoreg_db/models/utils.py +135 -0
  509. endoreg_db/queries/__init__.py +5 -0
  510. endoreg_db/queries/annotations/__init__.py +3 -0
  511. endoreg_db/queries/annotations/legacy.py +158 -0
  512. endoreg_db/queries/sanity/__init_.py +0 -0
  513. endoreg_db/renames.yml +8 -0
  514. endoreg_db/root_urls.py +9 -0
  515. endoreg_db/schemas/__init__.py +0 -0
  516. endoreg_db/schemas/examination_evaluation.py +27 -0
  517. endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +775 -0
  518. endoreg_db/serializers/__init__.py +147 -0
  519. endoreg_db/serializers/_old/raw_pdf_meta_validation.py +223 -0
  520. endoreg_db/serializers/_old/raw_video_meta_validation.py +179 -0
  521. endoreg_db/serializers/_old/video.py +71 -0
  522. endoreg_db/serializers/administration/__init__.py +14 -0
  523. endoreg_db/serializers/administration/ai/__init__.py +10 -0
  524. endoreg_db/serializers/administration/ai/active_model.py +10 -0
  525. endoreg_db/serializers/administration/ai/ai_model.py +18 -0
  526. endoreg_db/serializers/administration/ai/model_type.py +10 -0
  527. endoreg_db/serializers/administration/center.py +9 -0
  528. endoreg_db/serializers/administration/gender.py +9 -0
  529. endoreg_db/serializers/anonymization.py +69 -0
  530. endoreg_db/serializers/evaluation/examination_evaluation.py +1 -0
  531. endoreg_db/serializers/examination/__init__.py +10 -0
  532. endoreg_db/serializers/examination/base.py +46 -0
  533. endoreg_db/serializers/examination/dropdown.py +21 -0
  534. endoreg_db/serializers/examination_serializer.py +12 -0
  535. endoreg_db/serializers/finding/__init__.py +5 -0
  536. endoreg_db/serializers/finding/finding.py +54 -0
  537. endoreg_db/serializers/finding_classification/__init__.py +7 -0
  538. endoreg_db/serializers/finding_classification/choice.py +19 -0
  539. endoreg_db/serializers/finding_classification/classification.py +13 -0
  540. endoreg_db/serializers/label/__init__.py +7 -0
  541. endoreg_db/serializers/label/image_classification_annotation.py +62 -0
  542. endoreg_db/serializers/label/label.py +15 -0
  543. endoreg_db/serializers/label_video_segment/__init__.py +7 -0
  544. endoreg_db/serializers/label_video_segment/_lvs_create.py +149 -0
  545. endoreg_db/serializers/label_video_segment/_lvs_update.py +138 -0
  546. endoreg_db/serializers/label_video_segment/_lvs_validate.py +149 -0
  547. endoreg_db/serializers/label_video_segment/label_video_segment.py +344 -0
  548. endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +99 -0
  549. endoreg_db/serializers/label_video_segment/label_video_segment_update.py +163 -0
  550. endoreg_db/serializers/meta/__init__.py +19 -0
  551. endoreg_db/serializers/meta/pdf_file_meta_extraction.py +115 -0
  552. endoreg_db/serializers/meta/report_meta.py +53 -0
  553. endoreg_db/serializers/meta/sensitive_meta_detail.py +162 -0
  554. endoreg_db/serializers/meta/sensitive_meta_update.py +148 -0
  555. endoreg_db/serializers/meta/sensitive_meta_verification.py +59 -0
  556. endoreg_db/serializers/meta/video_meta.py +39 -0
  557. endoreg_db/serializers/misc/__init__.py +14 -0
  558. endoreg_db/serializers/misc/file_overview.py +152 -0
  559. endoreg_db/serializers/misc/stats.py +33 -0
  560. endoreg_db/serializers/misc/translatable_field_mix_in.py +44 -0
  561. endoreg_db/serializers/misc/upload_job.py +71 -0
  562. endoreg_db/serializers/misc/vop_patient_data.py +120 -0
  563. endoreg_db/serializers/patient/__init__.py +11 -0
  564. endoreg_db/serializers/patient/patient.py +86 -0
  565. endoreg_db/serializers/patient/patient_dropdown.py +27 -0
  566. endoreg_db/serializers/patient_examination/__init__.py +7 -0
  567. endoreg_db/serializers/patient_examination/patient_examination.py +141 -0
  568. endoreg_db/serializers/patient_finding/__init__.py +15 -0
  569. endoreg_db/serializers/patient_finding/patient_finding.py +31 -0
  570. endoreg_db/serializers/patient_finding/patient_finding_classification.py +39 -0
  571. endoreg_db/serializers/patient_finding/patient_finding_detail.py +53 -0
  572. endoreg_db/serializers/patient_finding/patient_finding_intervention.py +26 -0
  573. endoreg_db/serializers/patient_finding/patient_finding_list.py +41 -0
  574. endoreg_db/serializers/patient_finding/patient_finding_write.py +126 -0
  575. endoreg_db/serializers/pdf/__init__.py +5 -0
  576. endoreg_db/serializers/pdf/anony_text_validation.py +85 -0
  577. endoreg_db/serializers/report/__init__.py +9 -0
  578. endoreg_db/serializers/report/mixins.py +45 -0
  579. endoreg_db/serializers/report/report.py +105 -0
  580. endoreg_db/serializers/report/report_list.py +22 -0
  581. endoreg_db/serializers/report/secure_file_url.py +26 -0
  582. endoreg_db/serializers/requirements/requirement_schema.py +25 -0
  583. endoreg_db/serializers/requirements/requirement_sets.py +29 -0
  584. endoreg_db/serializers/sensitive_meta_serializer.py +282 -0
  585. endoreg_db/serializers/video/__init__.py +7 -0
  586. endoreg_db/serializers/video/segmentation.py +263 -0
  587. endoreg_db/serializers/video/video_file_brief.py +10 -0
  588. endoreg_db/serializers/video/video_file_detail.py +83 -0
  589. endoreg_db/serializers/video/video_file_list.py +67 -0
  590. endoreg_db/serializers/video/video_metadata.py +105 -0
  591. endoreg_db/serializers/video/video_processing_history.py +153 -0
  592. endoreg_db/services/__init__.py +5 -0
  593. endoreg_db/services/anonymization.py +223 -0
  594. endoreg_db/services/examination_evaluation.py +149 -0
  595. endoreg_db/services/finding_description_service.py +0 -0
  596. endoreg_db/services/lookup_service.py +241 -0
  597. endoreg_db/services/lookup_store.py +122 -0
  598. endoreg_db/services/pdf_import.py +1159 -0
  599. endoreg_db/services/polling_coordinator.py +288 -0
  600. endoreg_db/services/pseudonym_service.py +89 -0
  601. endoreg_db/services/requirements_object.py +147 -0
  602. endoreg_db/services/segment_sync.py +155 -0
  603. endoreg_db/services/storage_aware_video_processor.py +344 -0
  604. endoreg_db/services/video_import.py +1258 -0
  605. endoreg_db/tasks/upload_tasks.py +207 -0
  606. endoreg_db/tasks/video_ingest.py +157 -0
  607. endoreg_db/tasks/video_processing_tasks.py +327 -0
  608. endoreg_db/templates/admin/patient_finding_intervention.html +253 -0
  609. endoreg_db/templates/admin/start_examination.html +12 -0
  610. endoreg_db/templates/timeline.html +176 -0
  611. endoreg_db/urls/__init__.py +70 -0
  612. endoreg_db/urls/anonymization.py +32 -0
  613. endoreg_db/urls/auth.py +16 -0
  614. endoreg_db/urls/classification.py +39 -0
  615. endoreg_db/urls/examination.py +54 -0
  616. endoreg_db/urls/files.py +6 -0
  617. endoreg_db/urls/label_video_segment_validate.py +33 -0
  618. endoreg_db/urls/label_video_segments.py +44 -0
  619. endoreg_db/urls/media.py +226 -0
  620. endoreg_db/urls/patient.py +19 -0
  621. endoreg_db/urls/report.py +48 -0
  622. endoreg_db/urls/requirements.py +13 -0
  623. endoreg_db/urls/sensitive_meta.py +0 -0
  624. endoreg_db/urls/stats.py +46 -0
  625. endoreg_db/urls/upload.py +20 -0
  626. endoreg_db/urls/video.py +61 -0
  627. endoreg_db/urls.py +9 -0
  628. endoreg_db/utils/__init__.py +88 -0
  629. endoreg_db/utils/ai/__init__.py +9 -0
  630. endoreg_db/utils/ai/get.py +5 -0
  631. endoreg_db/utils/ai/inference_dataset.py +52 -0
  632. endoreg_db/utils/ai/multilabel_classification_net.py +159 -0
  633. endoreg_db/utils/ai/postprocess.py +63 -0
  634. endoreg_db/utils/ai/predict.py +291 -0
  635. endoreg_db/utils/ai/preprocess.py +68 -0
  636. endoreg_db/utils/calc_duration_seconds.py +24 -0
  637. endoreg_db/utils/case_generator/__init__.py +0 -0
  638. endoreg_db/utils/case_generator/case_generator.py +159 -0
  639. endoreg_db/utils/case_generator/lab_sample_factory.py +33 -0
  640. endoreg_db/utils/case_generator/utils.py +30 -0
  641. endoreg_db/utils/check_video_files.py +148 -0
  642. endoreg_db/utils/cropping.py +29 -0
  643. endoreg_db/utils/dataloader.py +175 -0
  644. endoreg_db/utils/dates.py +60 -0
  645. endoreg_db/utils/env.py +33 -0
  646. endoreg_db/utils/extract_specific_frames.py +72 -0
  647. endoreg_db/utils/file_operations.py +58 -0
  648. endoreg_db/utils/fix_video_path_direct.py +141 -0
  649. endoreg_db/utils/frame_anonymization_utils.py +463 -0
  650. endoreg_db/utils/hashs.py +153 -0
  651. endoreg_db/utils/links/__init__.py +0 -0
  652. endoreg_db/utils/links/requirement_link.py +193 -0
  653. endoreg_db/utils/mime_types.py +0 -0
  654. endoreg_db/utils/names.py +76 -0
  655. endoreg_db/utils/ocr.py +190 -0
  656. endoreg_db/utils/parse_and_generate_yaml.py +46 -0
  657. endoreg_db/utils/paths.py +95 -0
  658. endoreg_db/utils/permissions.py +143 -0
  659. endoreg_db/utils/pipelines/Readme.md +235 -0
  660. endoreg_db/utils/pipelines/__init__.py +0 -0
  661. endoreg_db/utils/pipelines/process_video_dir.py +120 -0
  662. endoreg_db/utils/product/__init__.py +0 -0
  663. endoreg_db/utils/product/sum_emissions.py +20 -0
  664. endoreg_db/utils/product/sum_weights.py +18 -0
  665. endoreg_db/utils/pydantic_models/__init__.py +6 -0
  666. endoreg_db/utils/pydantic_models/db_config.py +57 -0
  667. endoreg_db/utils/requirement_helpers.py +0 -0
  668. endoreg_db/utils/requirement_operator_logic/__init__.py +0 -0
  669. endoreg_db/utils/requirement_operator_logic/lab_value_operators.py +578 -0
  670. endoreg_db/utils/requirement_operator_logic/model_evaluators.py +368 -0
  671. endoreg_db/utils/setup_config.py +177 -0
  672. endoreg_db/utils/translation.py +27 -0
  673. endoreg_db/utils/uuid.py +4 -0
  674. endoreg_db/utils/validate_endo_roi.py +19 -0
  675. endoreg_db/utils/validate_subcategory_dict.py +91 -0
  676. endoreg_db/utils/validate_video_detailed.py +357 -0
  677. endoreg_db/utils/video/__init__.py +26 -0
  678. endoreg_db/utils/video/extract_frames.py +88 -0
  679. endoreg_db/utils/video/ffmpeg_wrapper.py +835 -0
  680. endoreg_db/utils/video/names.py +42 -0
  681. endoreg_db/utils/video/streaming_processor.py +312 -0
  682. endoreg_db/utils/video/video_splitter.py +94 -0
  683. endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +238 -0
  684. endoreg_db/views/__init__.py +272 -0
  685. endoreg_db/views/anonymization/__init__.py +27 -0
  686. endoreg_db/views/anonymization/media_management.py +454 -0
  687. endoreg_db/views/anonymization/overview.py +216 -0
  688. endoreg_db/views/anonymization/validate.py +107 -0
  689. endoreg_db/views/auth/__init__.py +13 -0
  690. endoreg_db/views/auth/keycloak.py +113 -0
  691. endoreg_db/views/examination/__init__.py +33 -0
  692. endoreg_db/views/examination/examination.py +37 -0
  693. endoreg_db/views/examination/examination_manifest_cache.py +26 -0
  694. endoreg_db/views/examination/get_finding_classification_choices.py +59 -0
  695. endoreg_db/views/examination/get_finding_classifications.py +36 -0
  696. endoreg_db/views/examination/get_findings.py +41 -0
  697. endoreg_db/views/examination/get_instruments.py +18 -0
  698. endoreg_db/views/examination/get_interventions.py +14 -0
  699. endoreg_db/views/finding/__init__.py +9 -0
  700. endoreg_db/views/finding/finding.py +112 -0
  701. endoreg_db/views/finding/get_classifications.py +14 -0
  702. endoreg_db/views/finding/get_interventions.py +17 -0
  703. endoreg_db/views/finding_classification/__init__.py +13 -0
  704. endoreg_db/views/finding_classification/base.py +0 -0
  705. endoreg_db/views/finding_classification/finding_classification.py +42 -0
  706. endoreg_db/views/finding_classification/get_classification_choices.py +55 -0
  707. endoreg_db/views/label/__init__.py +5 -0
  708. endoreg_db/views/label/label.py +15 -0
  709. endoreg_db/views/label_video_segment/__init__.py +16 -0
  710. endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +44 -0
  711. endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +50 -0
  712. endoreg_db/views/label_video_segment/label_video_segment.py +77 -0
  713. endoreg_db/views/label_video_segment/label_video_segment_by_label.py +174 -0
  714. endoreg_db/views/label_video_segment/label_video_segment_detail.py +73 -0
  715. endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +46 -0
  716. endoreg_db/views/label_video_segment/validate.py +226 -0
  717. endoreg_db/views/media/__init__.py +45 -0
  718. endoreg_db/views/media/pdf_media.py +386 -0
  719. endoreg_db/views/media/segments.py +71 -0
  720. endoreg_db/views/media/sensitive_metadata.py +314 -0
  721. endoreg_db/views/media/video_media.py +272 -0
  722. endoreg_db/views/media/video_segments.py +524 -0
  723. endoreg_db/views/meta/__init__.py +15 -0
  724. endoreg_db/views/meta/available_files_list.py +146 -0
  725. endoreg_db/views/meta/report_meta.py +53 -0
  726. endoreg_db/views/meta/sensitive_meta_detail.py +148 -0
  727. endoreg_db/views/meta/sensitive_meta_list.py +104 -0
  728. endoreg_db/views/meta/sensitive_meta_verification.py +71 -0
  729. endoreg_db/views/misc/__init__.py +63 -0
  730. endoreg_db/views/misc/center.py +13 -0
  731. endoreg_db/views/misc/csrf.py +7 -0
  732. endoreg_db/views/misc/gender.py +14 -0
  733. endoreg_db/views/misc/secure_file_serving_view.py +80 -0
  734. endoreg_db/views/misc/secure_file_url_view.py +84 -0
  735. endoreg_db/views/misc/secure_url_validate.py +79 -0
  736. endoreg_db/views/misc/stats.py +220 -0
  737. endoreg_db/views/misc/translation.py +182 -0
  738. endoreg_db/views/misc/upload_views.py +240 -0
  739. endoreg_db/views/patient/__init__.py +5 -0
  740. endoreg_db/views/patient/patient.py +210 -0
  741. endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +164 -0
  742. endoreg_db/views/patient_examination/__init__.py +11 -0
  743. endoreg_db/views/patient_examination/patient_examination.py +140 -0
  744. endoreg_db/views/patient_examination/patient_examination_create.py +63 -0
  745. endoreg_db/views/patient_examination/patient_examination_detail.py +66 -0
  746. endoreg_db/views/patient_examination/patient_examination_list.py +68 -0
  747. endoreg_db/views/patient_examination/video.py +194 -0
  748. endoreg_db/views/patient_finding/__init__.py +7 -0
  749. endoreg_db/views/patient_finding/base.py +0 -0
  750. endoreg_db/views/patient_finding/patient_finding.py +64 -0
  751. endoreg_db/views/patient_finding/patient_finding_optimized.py +259 -0
  752. endoreg_db/views/patient_finding_classification/__init__.py +5 -0
  753. endoreg_db/views/patient_finding_classification/pfc_create.py +67 -0
  754. endoreg_db/views/patient_finding_location/__init__.py +5 -0
  755. endoreg_db/views/patient_finding_location/pfl_create.py +70 -0
  756. endoreg_db/views/patient_finding_morphology/__init__.py +5 -0
  757. endoreg_db/views/patient_finding_morphology/pfm_create.py +70 -0
  758. endoreg_db/views/pdf/__init__.py +11 -0
  759. endoreg_db/views/pdf/pdf_media.py +239 -0
  760. endoreg_db/views/pdf/pdf_stream_views.py +127 -0
  761. endoreg_db/views/pdf/reimport.py +161 -0
  762. endoreg_db/views/report/__init__.py +9 -0
  763. endoreg_db/views/report/report_list.py +112 -0
  764. endoreg_db/views/report/report_with_secure_url.py +28 -0
  765. endoreg_db/views/report/start_examination.py +7 -0
  766. endoreg_db/views/requirement/__init__.py +10 -0
  767. endoreg_db/views/requirement/evaluate.py +279 -0
  768. endoreg_db/views/requirement/lookup.py +483 -0
  769. endoreg_db/views/requirement/lookup_store.py +252 -0
  770. endoreg_db/views/requirement_lookup/lookup.py +0 -0
  771. endoreg_db/views/requirement_lookup/lookup_store.py +0 -0
  772. endoreg_db/views/stats/__init__.py +13 -0
  773. endoreg_db/views/stats/stats_views.py +229 -0
  774. endoreg_db/views/video/__init__.py +61 -0
  775. endoreg_db/views/video/correction.py +530 -0
  776. endoreg_db/views/video/reimport.py +195 -0
  777. endoreg_db/views/video/segmentation.py +274 -0
  778. endoreg_db/views/video/task_status.py +49 -0
  779. endoreg_db/views/video/timeline.py +46 -0
  780. endoreg_db/views/video/video_analyze.py +52 -0
  781. endoreg_db/views/video/video_apply_mask.py +48 -0
  782. endoreg_db/views/video/video_correction.py +21 -0
  783. endoreg_db/views/video/video_download_processed.py +58 -0
  784. endoreg_db/views/video/video_examination_viewset.py +329 -0
  785. endoreg_db/views/video/video_media.py +158 -0
  786. endoreg_db/views/video/video_meta.py +29 -0
  787. endoreg_db/views/video/video_processing_history.py +24 -0
  788. endoreg_db/views/video/video_remove_frames.py +48 -0
  789. endoreg_db/views/video/video_stream.py +306 -0
  790. endoreg_db/views.py +0 -0
  791. endoreg_db-0.8.5.1.dist-info/METADATA +383 -0
  792. endoreg_db-0.8.5.1.dist-info/RECORD +794 -0
  793. endoreg_db-0.8.5.1.dist-info/WHEEL +4 -0
  794. endoreg_db-0.8.5.1.dist-info/licenses/LICENSE +674 -0
@@ -0,0 +1,613 @@
1
+ # models/data_file/import_classes/raw_pdf.py
2
+ # django db model "RawPdf"
3
+ # Class to store raw pdf file using django file field
4
+ # Class contains classmethod to create object from pdf file
5
+ # objects contains methods to extract text, extract metadata from text and anonymize text from pdf file uzing agl_report_reader.ReportReader class
6
+ # ------------------------------------------------------------------------------
7
+ import os
8
+ from django.db import models
9
+ from django.core.exceptions import ValidationError
10
+ from django.core.validators import FileExtensionValidator
11
+ from django.core.files import File
12
+ from numpy import isin # Import Django File
13
+ from endoreg_db.utils.file_operations import get_uuid_filename
14
+ from typing import TYPE_CHECKING, Optional, Union
15
+ # Use the specific paths from the centralized paths module
16
+ from ...utils import PDF_DIR
17
+ from endoreg_db.utils.hashs import get_pdf_hash
18
+
19
+ if TYPE_CHECKING:
20
+ from endoreg_db.models.administration.person import (
21
+ Patient,
22
+ Examiner,
23
+ )
24
+ from .report_file import AnonymExaminationReport
25
+ from ...medical.patient import PatientExamination
26
+ from ...administration import Center
27
+ from ...metadata.pdf_meta import PdfType
28
+ from ...state import RawPdfState
29
+ from ...metadata import SensitiveMeta
30
+
31
+ # setup logging to pdf_import.log
32
+ import logging
33
+
34
+ from pathlib import Path
35
+
36
+ logger = logging.getLogger("raw_pdf")
37
+
38
+ class RawPdfFile(models.Model):
39
+ # Fields from AbstractPdfFile
40
+ pdf_hash = models.CharField(max_length=255, unique=True)
41
+ pdf_type = models.ForeignKey(
42
+ "PdfType",
43
+ on_delete=models.SET_NULL,
44
+ blank=True,
45
+ null=True,
46
+ )
47
+ center = models.ForeignKey(
48
+ "Center",
49
+ on_delete=models.SET_NULL,
50
+ blank=True,
51
+ null=True,
52
+ ) # type: ignore
53
+ examination = models.ForeignKey(
54
+ "PatientExamination",
55
+ on_delete=models.SET_NULL,
56
+ blank=True,
57
+ null=True,
58
+ related_name="raw_pdf_files",
59
+ ) # type: ignore
60
+ examiner = models.ForeignKey(
61
+ "Examiner",
62
+ on_delete=models.SET_NULL,
63
+ blank=True,
64
+ null=True,
65
+ ) # type: ignore
66
+ text = models.TextField(blank=True, null=True)
67
+ date_created = models.DateTimeField(auto_now_add=True)
68
+ date_modified = models.DateTimeField(auto_now=True)
69
+ anonymized = models.BooleanField(default=False, help_text="True if the PDF has been anonymized.")
70
+
71
+ # Fields specific to RawPdfFile (keeping existing related_names)
72
+ file = models.FileField(
73
+ # Use the relative path from the specific PDF_DIR
74
+ upload_to=PDF_DIR.name,
75
+ validators=[FileExtensionValidator(allowed_extensions=["pdf"])],
76
+ ) # type: ignore
77
+
78
+ anonymized_file = models.FileField(
79
+ upload_to=PDF_DIR.name,
80
+ validators=[FileExtensionValidator(allowed_extensions=["pdf"])],
81
+ null=True,
82
+ blank=True,
83
+ ) # type: ignore
84
+
85
+ state = models.OneToOneField(
86
+ "RawPdfState",
87
+ on_delete=models.SET_NULL,
88
+ blank=True,
89
+ null=True,
90
+ related_name="raw_pdf_file",
91
+ ) # type: ignore
92
+
93
+ objects = models.Manager()
94
+
95
+ @property
96
+ def file_path(self) -> Path|None:
97
+ """
98
+ Returns the file path of the stored PDF file if available; otherwise, returns None.
99
+ """
100
+ # assert self.file has path attribute
101
+ assert isinstance(self.file, models.FieldFile)
102
+ if self.file and self.file.name:
103
+ try:
104
+ return Path(self.file.path)
105
+ except (ValueError, AttributeError, NotImplementedError):
106
+ return None
107
+ return None
108
+
109
+ def set_file_path(self, file_path: Path):
110
+ """
111
+ Sets the file path of the stored PDF file.
112
+ """
113
+ self.file = File(file_path) # type: ignore
114
+ self.save(update_fields=['file'])
115
+
116
+ @property
117
+ def anonymized_file_path(self) -> Path|None:
118
+ """
119
+ Returns the file path of the anonymized PDF file if available; otherwise, returns None.
120
+ """
121
+ if self.anonymized_file and self.anonymized_file.name:
122
+ try:
123
+ return Path(self.anonymized_file.path)
124
+ except (ValueError, AttributeError, NotImplementedError):
125
+ return None
126
+ return None
127
+
128
+ def set_anonymized_file_path(self, file_path: Path):
129
+ """
130
+ Sets the file path of the anonymized PDF file.
131
+ """
132
+ self.anonymized_file = File(file_path) # type: ignore
133
+ self.save(update_fields=['anonymized_file'])
134
+
135
+ @property
136
+ def file_url(self):
137
+ """
138
+ Returns the URL of the stored PDF file if available; otherwise, returns None.
139
+ """
140
+ try:
141
+ return self.file.url if self.file and self.file.name else None
142
+ except (ValueError, AttributeError):
143
+ return None
144
+
145
+ @property
146
+ def anonymized_file_url(self):
147
+ """
148
+ Returns the URL of the stored PDF file if available; otherwise, returns None.
149
+ """
150
+ try:
151
+ return self.anonymized_file.url if self.anonymized_file and self.anonymized_file.name else None
152
+ except (ValueError, AttributeError):
153
+ return None
154
+
155
+ patient = models.ForeignKey(
156
+ "Patient",
157
+ on_delete=models.SET_NULL,
158
+ blank=True,
159
+ null=True,
160
+ related_name="raw_pdf_files",
161
+ ) # type: ignore
162
+ sensitive_meta = models.ForeignKey(
163
+ "SensitiveMeta",
164
+ on_delete=models.SET_NULL,
165
+ related_name="raw_pdf_files",
166
+ null=True,
167
+ blank=True,
168
+ ) # type: ignore
169
+ state_report_processing_required = models.BooleanField(default=True)
170
+ state_report_processed = models.BooleanField(default=False)
171
+ raw_meta = models.JSONField(blank=True, null=True)
172
+ anonym_examination_report = models.OneToOneField(
173
+ "AnonymExaminationReport",
174
+ on_delete=models.SET_NULL,
175
+ blank=True,
176
+ null=True,
177
+ related_name="raw_pdf_file",
178
+ ) # type: ignore
179
+ anonymized_text = models.TextField(blank=True, null=True)
180
+
181
+ # Type hinting is needed, improve and use correct django types
182
+ if TYPE_CHECKING:
183
+ file : Optional[Union[models.FieldFile,models.FileField]]
184
+ anonymized_file : Optional[Union[models.FieldFile,models.FileField]]
185
+ pdf_type: Optional[models.ForeignKey]
186
+ examination: Optional[models.ForeignKey["PatientExamination"]]
187
+ examiner: Optional[models.ForeignKey["Examiner"]]
188
+ patient: Optional[models.ForeignKey["Patient"]]
189
+ center: Optional[models.ForeignKey["Center"]]
190
+ anonym_examination_report: Optional[models.OneToOneField["AnonymExaminationReport"]]
191
+ sensitive_meta: Optional[models.ForeignKey["SensitiveMeta"]]
192
+ state: Optional[models.ForeignKey["RawPdfState"]]
193
+
194
+ def __str__(self):
195
+ """
196
+ Return a string representation of the RawPdfFile, including its PDF hash, type, and center.
197
+ """
198
+ str_repr = f"{self.pdf_hash} ({self.pdf_type}, {self.center})"
199
+ return str_repr
200
+
201
+ def delete(self, *args, **kwargs):
202
+ """
203
+ Deletes the RawPdfFile instance from the database and removes the associated file from storage if it exists.
204
+
205
+ This method ensures that the physical PDF file is deleted from the file system after the database record is removed. Logs warnings or errors if the file cannot be found or deleted.
206
+ """
207
+ # Call the original delete method first to remove DB record
208
+ if self.file:
209
+ try:
210
+ if self.file_path:
211
+ os.remove(Path(self.file_path))
212
+ logger.info("Original file removed: %s", self.file)
213
+ except Exception as e:
214
+ logger.warning(f"Could not get file path for {self.file.name} before deletion: {e}")
215
+ if self.anonymized_file:
216
+ try:
217
+ if self.anonymized_file_path:
218
+ os.remove(Path(self.anonymized_file_path))
219
+ logger.info("Anonymized file removed: %s", self.anonymized_file.name)
220
+ except OSError as e:
221
+ logger.error("Error removing anonymized file %s: %s", self.anonymized_file.name, e)
222
+
223
+ super().delete(*args, **kwargs)
224
+
225
+
226
+ def validate_metadata_annotation(self, extracted_data_dict: Optional[dict] = None) -> bool:
227
+ """
228
+ Validate the metadata of the RawPdf instance.
229
+
230
+ Called after annotation in the frontend, this method deletes the associated active file, updates the sensitive meta data with the user annotated data.
231
+ It also ensures the video file is properly saved after the metadata update.
232
+ """
233
+
234
+ if not self.sensitive_meta:
235
+ logger.error("No sensitive meta data associated with this PDF file.")
236
+ return False
237
+
238
+ if not extracted_data_dict:
239
+ logger.error("No extracted data provided for validation.")
240
+ return False
241
+
242
+ # Update sensitive meta with the provided data
243
+ self.sensitive_meta.update_from_dict(extracted_data_dict)
244
+
245
+ # Save the sensitive meta to ensure changes are persisted
246
+ self.sensitive_meta.save()
247
+
248
+ # Save the RawPdfFile instance to ensure all changes are saved
249
+ self.save()
250
+
251
+ logger.info(f"Metadata for PDF {self.pk} validated and updated successfully.")
252
+
253
+ if self.file_path:
254
+ try:
255
+ os.unlink(self.file_path) # Delete the original file if it exists
256
+ except OSError as e:
257
+ logger.error(f"Error removing original file {self.file_path}: {e}")
258
+
259
+ if self.anonymized_file_path:
260
+ try:
261
+ os.unlink(self.anonymized_file_path)
262
+ except OSError as e:
263
+ logger.error(f"Error removing anonymized file {self.anonymized_file_path}: {e}")
264
+
265
+ self.save() # Save the model to persist the cleared file fields
266
+
267
+ logger.info(f"Files for PDF {self.pk} deleted successfully.")
268
+ return True
269
+
270
+
271
+ @classmethod
272
+ def create_from_file_initialized(
273
+ cls,
274
+ file_path: Path,
275
+ center_name: str,
276
+ delete_source: bool = True,
277
+ ):
278
+ """
279
+ Creates a RawPdfFile instance from a file and center name, ensuring an associated RawPdfState exists.
280
+
281
+ Parameters:
282
+ file_path (Path): Path to the source PDF file.
283
+ center_name (str): Name of the center to associate with the PDF.
284
+ delete_source (bool): Whether to delete the source file after processing. Defaults to True.
285
+
286
+ Returns:
287
+ RawPdfFile: The created or retrieved RawPdfFile instance with an associated RawPdfState.
288
+ """
289
+ raw_pdf = cls.create_from_file(
290
+ file_path=file_path,
291
+ center_name=center_name,
292
+ delete_source=delete_source,
293
+ )
294
+ _state = raw_pdf.get_or_create_state()
295
+
296
+ return raw_pdf
297
+
298
+ @classmethod
299
+ def create_from_file(
300
+ cls,
301
+ file_path: Path,
302
+ center_name,
303
+ save=True, # Parameter kept for compatibility, but save now happens internally
304
+ delete_source=True,
305
+ ):
306
+ """
307
+ Creates or retrieves a RawPdfFile instance from a given PDF file path and center name.
308
+
309
+ If a RawPdfFile with the same PDF hash already exists, verifies the file exists in storage and restores it if missing. Otherwise, creates a new RawPdfFile, assigns the file, and saves it to storage. Optionally deletes the source file after processing.
310
+
311
+ Parameters:
312
+ file_path (Path): Path to the source PDF file.
313
+ center_name (str): Name of the center to associate with the file.
314
+ save (bool, optional): Deprecated; saving occurs internally.
315
+ delete_source (bool, optional): Whether to delete the source file after processing (default True).
316
+
317
+ Returns:
318
+ RawPdfFile: The created or retrieved RawPdfFile instance.
319
+
320
+ Raises:
321
+ FileNotFoundError: If the source file does not exist.
322
+ Center.DoesNotExist: If the specified center is not found.
323
+ ValueError: If the PDF hash cannot be calculated.
324
+ IOError: If the file fails to save to storage.
325
+ """
326
+ from endoreg_db.models.administration import Center
327
+
328
+ if not file_path.exists():
329
+ logger.error(f"Source file does not exist: {file_path}")
330
+ raise FileNotFoundError(f"Source file not found: {file_path}")
331
+
332
+ # 1. Calculate hash from source file
333
+ try:
334
+ pdf_hash = get_pdf_hash(file_path)
335
+ logger.info(pdf_hash)
336
+ except Exception as e:
337
+ logger.error(f"Could not calculate hash for {file_path}: {e}")
338
+ raise ValueError(f"Could not calculate hash for {file_path}") from e
339
+
340
+ # 2. Check if record with this hash already exists
341
+ existing_pdf_file = cls.objects.filter(pdf_hash=pdf_hash).first()
342
+ if existing_pdf_file:
343
+ logger.warning("RawPdfFile with hash %s already exists (ID: %s)", pdf_hash, existing_pdf_file.pk)
344
+
345
+ # Verify physical file exists for the existing record
346
+ try:
347
+ if existing_pdf_file is not None and isinstance(existing_pdf_file, cls):
348
+ # Use storage API to check existence
349
+ _file = existing_pdf_file.file
350
+ assert _file is not None
351
+ if not _file.storage.exists(_file.name):
352
+ logger.warning("File for existing RawPdfFile %s not found in storage at %s. Attempting to restore from source %s", pdf_hash, _file.name, file_path)
353
+ # Re-save the file from the source to potentially fix it
354
+ with file_path.open("rb") as f:
355
+ django_file = File(f, name=Path(_file.name).name) # Use existing name if possible
356
+ existing_pdf_file.file = django_file # type: ignore
357
+ existing_pdf_file.save(update_fields=['file']) # Only update file field
358
+ else:
359
+ pass
360
+ # logger.debug("File for existing RawPdfFile %s already exists in storage.", pdf_hash)
361
+ except Exception as e:
362
+ logger.error("Error verifying/restoring file for existing record %s: %s", pdf_hash, e)
363
+
364
+ # Delete the source temp file if requested
365
+ if delete_source:
366
+ try:
367
+ file_path.unlink()
368
+ # logger.info("Deleted source file %s after finding existing record.", file_path)
369
+ except OSError as e:
370
+ logger.error("Error deleting source file %s: %s", file_path, e)
371
+
372
+ return existing_pdf_file
373
+
374
+ # --- Create new record if not existing ---
375
+ assert center_name is not None, "center_name is required"
376
+ try:
377
+ center = Center.objects.get(name=center_name)
378
+ except Center.DoesNotExist:
379
+ logger.error(f"Center with name '{center_name}' not found.")
380
+ raise
381
+
382
+ # Generate a unique filename (e.g., using UUID)
383
+ new_file_name, _uuid = get_uuid_filename(file_path)
384
+ logger.info(f"Generated new filename: {new_file_name}")
385
+
386
+ # Create model instance via manager so creation can be intercepted/mocked during tests
387
+ try:
388
+ with file_path.open("rb") as f:
389
+ django_file = File(f, name=new_file_name)
390
+ raw_pdf = cls.objects.create(
391
+ pdf_hash=pdf_hash,
392
+ center=center,
393
+ file=django_file,
394
+ )
395
+
396
+ _file = raw_pdf.file
397
+ assert _file is not None
398
+ logger.info(
399
+ "Created and saved new RawPdfFile %s with file %s", raw_pdf.pk, _file.name
400
+ )
401
+
402
+ if not _file.storage.exists(_file.name):
403
+ logger.error(
404
+ "File was not saved correctly to storage path %s after model save.",
405
+ _file.name,
406
+ )
407
+ raise IOError(
408
+ f"File not found at expected storage path after save: {_file.name}"
409
+ )
410
+
411
+ try:
412
+ logger.info("File saved to absolute path: %s", _file.path)
413
+ except NotImplementedError:
414
+ logger.info(
415
+ "File saved to storage path: %s (Absolute path not available from storage)",
416
+ _file.name,
417
+ )
418
+
419
+ except Exception as e:
420
+ logger.error("Error processing or saving file %s for new record: %s", file_path, e)
421
+ raise
422
+
423
+ # Delete source file *after* successful save and verification
424
+ if delete_source:
425
+ try:
426
+ file_path.unlink()
427
+ logger.info("Deleted source file %s after creating new record.", file_path)
428
+ except OSError as e:
429
+ logger.error("Error deleting source file %s: %s", file_path, e)
430
+
431
+ # raw_pdf.save() # unnecessary?
432
+ return raw_pdf
433
+
434
+ def save(self, *args, **kwargs):
435
+ # Ensure hash is calculated before the first save if possible and not already set
436
+ # This is primarily a fallback if instance created manually without using create_from_file
437
+ """
438
+ Saves the RawPdfFile instance, ensuring the PDF hash is set and related fields are derived from metadata.
439
+
440
+ If the PDF hash is missing, attempts to calculate it from the file before saving. Validates that the file has a `.pdf` extension. If related fields such as patient, examination, center, or examiner are unset but available in the associated sensitive metadata, they are populated accordingly before saving.
441
+ """
442
+ if not self.pk and not self.pdf_hash and self.file:
443
+ try:
444
+ file_path = Path(self.file.path).resolve()
445
+ if not file_path.exists():
446
+ raise FileNotFoundError(f"File path does not exist: {file_path}")
447
+ # Read from the file object before it's saved by storage
448
+ self.file.open('rb') # Ensure file is open
449
+ self.file.seek(0) # Go to beginning
450
+ self.pdf_hash = get_pdf_hash(file_path) # Assuming get_pdf_hash can handle file obj
451
+ self.file.seek(0) # Reset position
452
+ self.file.close() # Close after reading
453
+ logger.info(f"Calculated hash during pre-save for {self.file.name}")
454
+ except Exception as e:
455
+ logger.warning("Could not calculate hash before initial save for %s: %s", self.file.name, e)
456
+ # Ensure file is closed if opened
457
+ if hasattr(self.file, 'closed') and not self.file.closed:
458
+ self.file.close()
459
+
460
+ if self.file and not self.file.name.endswith(".pdf"):
461
+ raise ValidationError("Only PDF files are allowed")
462
+
463
+ # If hash is still missing after potential creation logic (e.g., direct instantiation)
464
+ # and the file exists in storage, try calculating it from storage path.
465
+ # This is less ideal as it requires the file to be saved first.
466
+ if not self.pdf_hash and self.pk and self.file and self.file.storage.exists(self.file.name):
467
+ try:
468
+ file_path = Path(self.file.path).resolve()
469
+ if not file_path.exists():
470
+ raise FileNotFoundError(f"File path does not exist: {file_path}")
471
+ logger.warning(f"Hash missing for saved file {self.file.name}. Recalculating.")
472
+ with self.file.storage.open(self.file.name, 'rb') as f:
473
+ self.pdf_hash = get_pdf_hash(file_path) # Assuming get_pdf_hash handles file obj
474
+ # No need to save again just for hash unless update_fields is used carefully
475
+ # Let the main super().save() handle saving the hash if it changed
476
+ except Exception as e:
477
+ logger.error("Could not calculate hash during save for existing file %s: %s", self.file.name, e)
478
+
479
+ # Derive related fields from sensitive_meta if available
480
+ if not self.patient and self.sensitive_meta:
481
+ self.patient = self.sensitive_meta.pseudo_patient
482
+ if not self.examination and self.sensitive_meta:
483
+ self.examination = self.sensitive_meta.pseudo_examination
484
+ if not self.center and self.sensitive_meta:
485
+ self.center = self.sensitive_meta.center
486
+ #TODO Outdated?
487
+ # if not self.examiner and self.sensitive_meta and hasattr(self.sensitive_meta, 'pseudo_examiner'):
488
+ # self.examiner = self.sensitive_meta.pseudo_examiner
489
+
490
+ super().save(*args, **kwargs)
491
+
492
+ def get_or_create_state(self) -> "RawPdfState":
493
+ """
494
+ Retrieve the associated RawPdfState for this RawPdfFile, creating and linking a new one if none exists.
495
+
496
+ Returns:
497
+ RawPdfState: The existing or newly created RawPdfState instance linked to this RawPdfFile.
498
+ """
499
+ from endoreg_db.models.state import RawPdfState
500
+
501
+ if self.state:
502
+ return self.state
503
+
504
+ # Create a new RawPdfState instance directly and assign it
505
+ state = RawPdfState()
506
+ state.save()
507
+ self.state = state
508
+ self.save(update_fields=["state"]) # Save the RawPdfFile to link the state
509
+ logger.info("Created new RawPdfState for RawPdfFile %s", self.pk)
510
+ return state
511
+
512
+ def verify_existing_file(self, fallback_file):
513
+ # This method might still be useful if called explicitly, but create_from_file now handles restoration
514
+ # Ensure fallback_file is a Path object.
515
+ """
516
+ Checks if the stored PDF file exists in storage and attempts to restore it from a fallback file path if missing.
517
+
518
+ Parameters:
519
+ fallback_file: Path or string representing the fallback file location to restore from if the stored file is missing.
520
+ """
521
+ if not isinstance(fallback_file, Path):
522
+ fallback_file = Path(fallback_file)
523
+
524
+ _file = self.file
525
+ assert _file is not None
526
+ try:
527
+ if not _file.field.storage.exists(_file.name):
528
+ logger.warning(f"File missing at storage path {_file.name}. Attempting copy from fallback {fallback_file}")
529
+ if fallback_file.exists():
530
+ with fallback_file.open("rb") as f:
531
+ # Use save method which handles storage backend
532
+ _file.save(Path(_file.name).name, File(f), save=True) # Re-save the file content
533
+ logger.info(f"Successfully restored file from fallback {fallback_file} to {_file.name}")
534
+ else:
535
+ logger.error(f"Fallback file {fallback_file} does not exist.")
536
+ except Exception as e:
537
+
538
+ logger.error(f"Error during verify_existing_file for {_file.name}: {e}")
539
+
540
+ def process_file(self, text, anonymized_text, report_meta, verbose):
541
+ self.text = text
542
+ self.anonymized_text = anonymized_text
543
+
544
+ assert self.center is not None, "Center must be set before processing file"
545
+
546
+ report_meta["center_name"] = self.center.name
547
+ if not self.sensitive_meta:
548
+ # Pass the original report_meta with date objects to SensitiveMeta logic
549
+ sensitive_meta = SensitiveMeta.create_from_dict(report_meta)
550
+ self.sensitive_meta = sensitive_meta
551
+ else:
552
+ sensitive_meta = self.sensitive_meta
553
+ # Pass the original report_meta with date objects to SensitiveMeta logic
554
+ sensitive_meta.update_from_dict(report_meta)
555
+
556
+ # For storing in raw_meta (JSONField), dates need to be strings.
557
+ # Create a serializable version of report_meta for raw_meta.
558
+ import copy
559
+ from datetime import date, datetime
560
+
561
+ serializable_report_meta = copy.deepcopy(report_meta)
562
+ for key, value in serializable_report_meta.items():
563
+ if isinstance(value, (datetime, date)):
564
+ serializable_report_meta[key] = value.isoformat()
565
+
566
+ self.raw_meta = serializable_report_meta # Assign the version with string dates
567
+
568
+ sensitive_meta.save() # Save SensitiveMeta first
569
+ self.save() # Then save RawPdfFile
570
+
571
+ return text, anonymized_text, report_meta
572
+
573
+ def get_report_reader_config(self):
574
+ from ...administration import Center
575
+ from ...metadata.pdf_meta import PdfType
576
+ from warnings import warn
577
+
578
+ _center = self.center
579
+ assert _center is not None, "Center must be set to get report reader config"
580
+
581
+ if not self.pdf_type:
582
+ warn("PdfType not set, using default settings")
583
+ pdf_type = PdfType.default_pdf_type()
584
+ else:
585
+ pdf_type: PdfType = self.pdf_type
586
+ center: Center = _center
587
+ if pdf_type.endoscope_info_line:
588
+ endoscope_info_line = pdf_type.endoscope_info_line.value
589
+
590
+ else:
591
+ endoscope_info_line = None
592
+ settings_dict = {
593
+ "locale": "de_DE",
594
+ "employee_first_names": [_.name for _ in center.first_names.all()],
595
+ "employee_last_names": [_.name for _ in center.last_names.all()],
596
+ "text_date_format": "%d.%m.%Y",
597
+ "flags": {
598
+ "patient_info_line": pdf_type.patient_info_line.value,
599
+ "endoscope_info_line": endoscope_info_line,
600
+ "examiner_info_line": pdf_type.examiner_info_line.value,
601
+ "cut_off_below": [_.value for _ in pdf_type.cut_off_below_lines.all()],
602
+ "cut_off_above": [_.value for _ in pdf_type.cut_off_above_lines.all()],
603
+ },
604
+ }
605
+
606
+ return settings_dict
607
+
608
+ @staticmethod
609
+ def get_pdf_by_id(pdf_id: int) -> "RawPdfFile":
610
+ try:
611
+ return RawPdfFile.objects.get(pk=pdf_id)
612
+ except RawPdfFile.DoesNotExist:
613
+ raise ValueError(f"PDF with ID {pdf_id} does not exist.")