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,239 @@
1
+ from django.http import FileResponse, Http404, StreamingHttpResponse
2
+ import mimetypes
3
+ import os
4
+ import logging
5
+ import re
6
+ from ...models import RawPdfFile
7
+ from ...serializers._old.raw_pdf_meta_validation import PDFFileForMetaSerializer, SensitiveMetaUpdateSerializer
8
+ from rest_framework.views import APIView
9
+ from rest_framework.response import Response
10
+ from rest_framework import status
11
+ from ...models import SensitiveMeta
12
+ from django.views.decorators.clickjacking import xframe_options_sameorigin
13
+ from django.utils.decorators import method_decorator
14
+ from django.db import transaction
15
+ from django.urls import reverse
16
+ from django.utils.encoding import iri_to_uri
17
+ from endoreg_db.utils.paths import PDF_DIR, STORAGE_DIR
18
+ from .pdf_stream_views import ClosingFileWrapper
19
+
20
+ logger = logging.getLogger(__name__)
21
+ _RANGE_RE = re.compile(r"bytes=(\d+)-(\d*)")
22
+
23
+ class PDFMediaView(APIView):
24
+ """
25
+ Unified API for PDFs to support frontend flows:
26
+ - Without `id`: returns next PDF metadata (including anonymized_text) and stream URLs
27
+ - With `id`: streams the PDF (original by default; `?variant=anonymized` for anonymized)
28
+ - Integrates with Media Management expectations (clean deletion after validation is handled elsewhere)
29
+ """
30
+
31
+ def get(self, request):
32
+ """
33
+ Handles both:
34
+ - Fetching PDF metadata (if `id` is NOT provided)
35
+ - Streaming the actual PDF file (if `id` is provided)
36
+ """
37
+ pdf_id = request.GET.get("id")
38
+ last_id = request.GET.get("last_id")
39
+
40
+ if pdf_id:
41
+ return self.serve_pdf_file(pdf_id)
42
+ else:
43
+ return self.fetch_pdf_metadata(last_id)
44
+
45
+ def fetch_pdf_metadata(self, last_id):
46
+ """
47
+ Fetches the first or next available PDF metadata and provides stream URLs.
48
+ """
49
+ pdf_entry = PDFFileForMetaSerializer.get_next_pdf(last_id)
50
+ if pdf_entry is None:
51
+ return Response({"error": "No more PDFs available."}, status=status.HTTP_404_NOT_FOUND)
52
+
53
+ serialized_pdf = PDFFileForMetaSerializer(pdf_entry, context={'request': self.request})
54
+
55
+ # Build stream URLs pointing to this unified endpoint
56
+ try:
57
+ media_url = reverse('pdf_media')
58
+ except Exception:
59
+ media_url = "/api/pdf/media/"
60
+ stream_url = f"{media_url}?id={pdf_entry.id}"
61
+ anon_stream_url = f"{media_url}?id={pdf_entry.id}&variant=anonymized"
62
+
63
+ data = dict(serialized_pdf.data)
64
+ data.update({
65
+ 'stream_url': iri_to_uri(self.request.build_absolute_uri(stream_url)),
66
+ 'anonymized_stream_url': iri_to_uri(self.request.build_absolute_uri(anon_stream_url)),
67
+ 'pdf_id': pdf_entry.id,
68
+ 'has_anonymized': bool(getattr(pdf_entry, 'anonymized_file', None) and getattr(pdf_entry.anonymized_file, 'name', None)),
69
+ })
70
+ return Response(data, status=status.HTTP_200_OK)
71
+
72
+ @method_decorator(xframe_options_sameorigin)
73
+ def serve_pdf_file(self, pdf_id):
74
+ """
75
+ Streams the actual PDF file (original or anonymized) with Range support.
76
+ Query param `variant=anonymized` selects anonymized file; default is original.
77
+ """
78
+ variant = (self.request.GET.get('variant') or 'original').lower()
79
+ range_header = self.request.headers.get("Range")
80
+
81
+ try:
82
+ pdf_entry = RawPdfFile.objects.get(id=pdf_id)
83
+ except RawPdfFile.DoesNotExist:
84
+ return Response({"error": "Invalid PDF ID."}, status=status.HTTP_400_BAD_REQUEST)
85
+
86
+ # Choose file according to variant
87
+ file_field = None
88
+ if variant == 'anonymized' and getattr(pdf_entry, 'anonymized_file', None):
89
+ file_field = pdf_entry.anonymized_file
90
+ else:
91
+ file_field = pdf_entry.file
92
+
93
+ if not file_field:
94
+ return Response({"error": "PDF file not found."}, status=status.HTTP_404_NOT_FOUND)
95
+
96
+ # Resolve path and attempt self-heal for originals
97
+ try:
98
+ file_path = file_field.path
99
+ except Exception:
100
+ file_path = None
101
+
102
+ if not file_path or not os.path.exists(file_path):
103
+ if variant != 'anonymized':
104
+ # Try to self-heal original reference to sensitive storage
105
+ sensitive_path = os.path.join(str(PDF_DIR), "sensitive", f"{pdf_entry.pdf_hash}.pdf")
106
+ if os.path.exists(sensitive_path):
107
+ try:
108
+ relative_name = os.path.relpath(sensitive_path, str(STORAGE_DIR))
109
+ if getattr(pdf_entry.file, 'name', None) != relative_name:
110
+ pdf_entry.file.name = relative_name
111
+ pdf_entry.save(update_fields=['file'])
112
+ logger.info("Self-healed PDF file reference for ID %s -> %s", pdf_entry.id, pdf_entry.file.path)
113
+ file_path = sensitive_path
114
+ except Exception as e:
115
+ logger.error("Failed to self-heal file path for PDF %s: %s", pdf_entry.id, e)
116
+ file_path = sensitive_path
117
+ # If still missing (or anonymized missing), fail
118
+ if not file_path or not os.path.exists(file_path):
119
+ raise Http404("PDF file not found on server.")
120
+
121
+ # Prepare headers
122
+ safe_filename = os.path.basename(getattr(file_field, 'name', None) or f"document_{pdf_id}.pdf")
123
+ if not safe_filename.endswith('.pdf'):
124
+ safe_filename += '.pdf'
125
+
126
+ file_size = os.path.getsize(file_path)
127
+
128
+ # Range support
129
+ if range_header:
130
+ match = _RANGE_RE.match(range_header)
131
+ if match:
132
+ start = int(match.group(1))
133
+ end = int(match.group(2) or file_size - 1)
134
+
135
+ if start < 0 or start >= file_size:
136
+ raise Http404("Invalid range")
137
+ if end >= file_size:
138
+ end = file_size - 1
139
+
140
+ chunk_size = end - start + 1
141
+ try:
142
+ fh = open(file_path, 'rb')
143
+ fh.seek(start)
144
+ resp = StreamingHttpResponse(
145
+ ClosingFileWrapper(fh, blksize=8192),
146
+ status=206,
147
+ content_type="application/pdf",
148
+ )
149
+ resp["Content-Length"] = str(chunk_size)
150
+ resp["Content-Range"] = f"bytes {start}-{end}/{file_size}"
151
+ resp["Accept-Ranges"] = "bytes"
152
+ resp["Content-Disposition"] = f'inline; filename="{safe_filename}"'
153
+ return resp
154
+ except (OSError, IOError) as e:
155
+ logger.error(f"Error opening PDF file for range request: {e}")
156
+ raise Http404("Error accessing PDF file")
157
+
158
+ # Fallback: serve full file
159
+ mime_type, _ = mimetypes.guess_type(file_path)
160
+ try:
161
+ fh = open(file_path, 'rb')
162
+ response = FileResponse(fh, content_type=mime_type or "application/pdf")
163
+ response["Content-Length"] = str(file_size)
164
+ response["Accept-Ranges"] = "bytes"
165
+ response["Content-Disposition"] = f'inline; filename="{safe_filename}"'
166
+ return response
167
+ except (OSError, IOError) as e:
168
+ logger.error(f"Error opening PDF file: {e}")
169
+ raise Http404("Error accessing PDF file")
170
+
171
+ class UpdateSensitiveMetaView(APIView):
172
+ """
173
+ API endpoint to update patient details in the SensitiveMeta table.
174
+ Handles partial updates (only edited fields) and raw file deletion after validation acceptance.
175
+ """
176
+
177
+ @transaction.atomic
178
+ def patch(self, request, *args, **kwargs):
179
+ """
180
+ Updates the provided fields for a specific patient record.
181
+ Only updates fields that are sent in the request.
182
+ Automatically deletes raw PDF files when validation is accepted.
183
+ """
184
+ sensitive_meta_id = request.data.get("sensitive_meta_id")
185
+
186
+ if not sensitive_meta_id:
187
+ return Response({"error": "sensitive_meta_id is required."}, status=status.HTTP_400_BAD_REQUEST)
188
+
189
+ try:
190
+ sensitive_meta = SensitiveMeta.objects.get(id=sensitive_meta_id)
191
+ except SensitiveMeta.DoesNotExist:
192
+ return Response({"error": "Patient record not found."}, status=status.HTTP_404_NOT_FOUND)
193
+
194
+ is_accepting_validation = request.data.get("is_verified", False)
195
+ delete_raw_files = request.data.get("delete_raw_files", False)
196
+ if is_accepting_validation:
197
+ delete_raw_files = True
198
+ logger.info(f"Validation accepted for PDF SensitiveMeta {sensitive_meta_id}, marking raw files for deletion")
199
+
200
+ serializer = SensitiveMetaUpdateSerializer(sensitive_meta, data=request.data, partial=True)
201
+
202
+ if serializer.is_valid():
203
+ updated_sm = serializer.save()
204
+ if delete_raw_files and updated_sm.is_verified:
205
+ try:
206
+ pdf_file = RawPdfFile.objects.filter(sensitive_meta=updated_sm).first()
207
+ if pdf_file:
208
+ self._schedule_raw_file_deletion(pdf_file)
209
+ logger.info(f"Scheduled raw file deletion for PDF {pdf_file.id}")
210
+ else:
211
+ logger.warning(f"No PDF file found for SensitiveMeta {sensitive_meta_id}")
212
+ except Exception as e:
213
+ logger.error(f"Error scheduling raw file deletion for PDF SensitiveMeta {sensitive_meta_id}: {e}")
214
+ return Response({"message": "Patient information updated successfully.", "updated_data": serializer.data}, status=status.HTTP_200_OK)
215
+
216
+ return Response({"error": "Invalid data.", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
217
+
218
+ def _schedule_raw_file_deletion(self, pdf_file):
219
+ """
220
+ Schedule deletion of raw PDF file after validation acceptance.
221
+ Deletes the original (sensitive) file but keeps anonymized_file for frontend.
222
+ """
223
+ try:
224
+ def cleanup_raw_files():
225
+ try:
226
+ if pdf_file.file and getattr(pdf_file.file, 'path', None) and os.path.exists(pdf_file.file.path):
227
+ logger.info(f"Deleting original (sensitive) PDF file: {pdf_file.file.path}")
228
+ os.remove(pdf_file.file.path)
229
+ pdf_file.file = None
230
+ pdf_file.save(update_fields=['file'])
231
+ logger.info(f"Successfully deleted original file for PDF {pdf_file.id}")
232
+ else:
233
+ logger.info(f"Original file already deleted or not found for PDF {pdf_file.id}")
234
+ except Exception as e:
235
+ logger.error(f"Error during raw file cleanup for PDF {pdf_file.id}: {e}")
236
+ transaction.on_commit(cleanup_raw_files)
237
+ except Exception as e:
238
+ logger.error(f"Error scheduling raw file deletion for PDF {pdf_file.id}: {e}")
239
+ raise
@@ -0,0 +1,127 @@
1
+ import re
2
+ import logging
3
+ from django.http import FileResponse, StreamingHttpResponse, Http404
4
+ from rest_framework.views import APIView
5
+ from ...utils.permissions import EnvironmentAwarePermission
6
+ from endoreg_db.models import RawPdfFile
7
+ import os
8
+ from django.views.decorators.clickjacking import xframe_options_sameorigin
9
+
10
+ logger = logging.getLogger(__name__)
11
+ _RANGE_RE = re.compile(r"bytes=(\d+)-(\d*)")
12
+
13
+ class ClosingFileWrapper:
14
+ """Custom file wrapper that ensures file is closed after streaming"""
15
+ def __init__(self, file_handle, blksize=8192):
16
+ self.file_handle = file_handle
17
+ self.blksize = blksize
18
+
19
+ def __iter__(self):
20
+ return self
21
+
22
+ def __next__(self):
23
+ data = self.file_handle.read(self.blksize)
24
+ if not data:
25
+ self.file_handle.close()
26
+ raise StopIteration
27
+ return data
28
+
29
+ def close(self):
30
+ if hasattr(self.file_handle, 'close'):
31
+ self.file_handle.close()
32
+
33
+ class PDFStreamView(APIView):
34
+ """
35
+ Streams a PDF file with correct HTTP range support and proper file handle management.
36
+ """
37
+ permission_classes = [EnvironmentAwarePermission]
38
+
39
+ @xframe_options_sameorigin
40
+ def get(self, request, pdf_id: int, *args, **kwargs):
41
+ try:
42
+ pdf_obj = RawPdfFile.objects.filter(pk=pdf_id).first()
43
+ if not pdf_obj or not pdf_obj.file:
44
+ logger.warning(f"PDF not found: ID {pdf_id}")
45
+ raise Http404("PDF not found")
46
+
47
+ # Check if file exists on filesystem
48
+ try:
49
+ file_path = pdf_obj.file.path
50
+ if not os.path.exists(file_path):
51
+ logger.error(f"PDF file does not exist on filesystem: {file_path}")
52
+ raise Http404("PDF file not found on filesystem")
53
+
54
+ file_size = os.path.getsize(file_path)
55
+ except (OSError, IOError, AttributeError) as e:
56
+ logger.error(f"Error accessing PDF file {pdf_id}: {e}")
57
+ raise Http404("PDF file not accessible")
58
+
59
+ # Generate safe filename
60
+ safe_filename = os.path.basename(pdf_obj.file.name) if pdf_obj.file.name else f"document_{pdf_id}.pdf"
61
+ if not safe_filename.endswith('.pdf'):
62
+ safe_filename += '.pdf'
63
+
64
+ # Handle Range requests
65
+ range_header = request.headers.get("Range")
66
+ if range_header:
67
+ logger.debug(f"Range request for PDF {pdf_id}: {range_header}")
68
+ match = _RANGE_RE.match(range_header)
69
+ if match:
70
+ start = int(match.group(1))
71
+ end = int(match.group(2) or file_size - 1)
72
+
73
+ # Validate range
74
+ if start >= file_size or start < 0:
75
+ logger.warning(f"Invalid range start {start} for file size {file_size}")
76
+ raise Http404("Invalid range")
77
+
78
+ if end >= file_size:
79
+ end = file_size - 1
80
+
81
+ chunk_size = end - start + 1
82
+
83
+ try:
84
+ file_handle = open(file_path, "rb")
85
+ file_handle.seek(start)
86
+
87
+ logger.debug(f"Serving PDF {pdf_id} range {start}-{end}/{file_size}")
88
+
89
+ response = StreamingHttpResponse(
90
+ ClosingFileWrapper(file_handle, blksize=8192),
91
+ status=206,
92
+ content_type="application/pdf",
93
+ )
94
+ response["Content-Length"] = str(chunk_size)
95
+ response["Content-Range"] = f"bytes {start}-{end}/{file_size}"
96
+ response["Accept-Ranges"] = "bytes"
97
+ response["Content-Disposition"] = f'inline; filename="{safe_filename}"'
98
+
99
+ return response
100
+ except (OSError, IOError) as e:
101
+ logger.error(f"Error opening PDF file for range request: {e}")
102
+ raise Http404("Error accessing PDF file")
103
+ else:
104
+ logger.warning(f"Invalid Range header format: {range_header}")
105
+
106
+ # Serve entire file using FileResponse (automatically handles file closing)
107
+ logger.debug(f"Serving full PDF {pdf_id} ({file_size} bytes)")
108
+
109
+ try:
110
+ file_handle = open(file_path, "rb")
111
+ response = FileResponse(
112
+ file_handle,
113
+ content_type="application/pdf"
114
+ )
115
+ response["Content-Length"] = str(file_size)
116
+ response["Accept-Ranges"] = "bytes"
117
+ response["Content-Disposition"] = f'inline; filename="{safe_filename}"'
118
+
119
+ # FileResponse will take ownership of file_handle and close it after response
120
+ return response
121
+ except (OSError, IOError) as e:
122
+ logger.error(f"Error opening PDF file: {e}")
123
+ raise Http404("Error accessing PDF file")
124
+
125
+ except Exception as e:
126
+ logger.error(f"Unexpected error streaming PDF {pdf_id}: {e}", exc_info=True)
127
+ raise Http404("Error streaming PDF")
@@ -0,0 +1,161 @@
1
+ from rest_framework.views import APIView
2
+ from rest_framework.response import Response
3
+ from rest_framework import status
4
+ import logging
5
+ from pathlib import Path
6
+ from django.db import transaction
7
+ from ...models import RawPdfFile, SensitiveMeta
8
+ from ...services.pdf_import import PdfImportService
9
+ logger = logging.getLogger(__name__)
10
+
11
+ class PdfReimportView(APIView):
12
+ """
13
+ API endpoint to re-import a pdf file and regenerate metadata.
14
+ This is useful when OCR failed or metadata is incomplete.
15
+ """
16
+
17
+ def __init__(self, **kwargs):
18
+ super().__init__(**kwargs)
19
+ self.pdf_service = PdfImportService()
20
+
21
+ def post(self, request, pk):
22
+ """
23
+ Re-import a pdf file to regenerate SensitiveMeta and other metadata.
24
+ Instead of creating a new pdf, this updates the existing one.
25
+
26
+ Args:
27
+ request: HTTP request object
28
+ pk: PDF primary key (ID)
29
+ """
30
+ pdf_id = pk # Align with media framework naming convention
31
+
32
+ # Validate pdf_id parameter
33
+ if not pdf_id or not isinstance(pdf_id, int):
34
+ return Response(
35
+ {"error": "Invalid PDF ID provided."},
36
+ status=status.HTTP_400_BAD_REQUEST
37
+ )
38
+
39
+ try:
40
+ pdf = RawPdfFile.objects.get(id=pdf_id)
41
+ logger.info(f"Found PDF {pdf.uuid} (ID: {pdf_id}) for re-import")
42
+ except RawPdfFile.DoesNotExist:
43
+ logger.warning(f"PDF with ID {pdf_id} not found")
44
+ return Response(
45
+ {"error": f"PDF with ID {pdf_id} not found."},
46
+ status=status.HTTP_404_NOT_FOUND
47
+ )
48
+
49
+
50
+
51
+ # Check if the raw file actually exists on disk
52
+ raw_file_path = Path(pdf.file.path)
53
+ if not raw_file_path.exists():
54
+ logger.error(f"Raw file not found on disk: {raw_file_path}")
55
+ return Response(
56
+ {"error": f"PDF file not found on server: {raw_file_path.name}"},
57
+ status=status.HTTP_400_BAD_REQUEST
58
+ )
59
+
60
+ # Check if PDF has required relationships
61
+ if not pdf.center:
62
+ logger.warning(f"PDF {pdf.uuid} has no associated center")
63
+ return Response(
64
+ {"error": "Video has no associated center."},
65
+ status=status.HTTP_400_BAD_REQUEST
66
+ )
67
+
68
+ try:
69
+ logger.info(f"Starting in-place re-import for pdf {pdf.uuid} (ID: {pdf_id})")
70
+
71
+ with transaction.atomic():
72
+ # Clear existing metadata to force regeneration
73
+ old_meta_id = None
74
+ if pdf.sensitive_meta:
75
+ old_meta_id = pdf.sensitive_meta.id
76
+ logger.info(f"Clearing existing SensitiveMeta {old_meta_id} for pdf {pdf.uuid}")
77
+ pdf.sensitive_meta = None
78
+ pdf.save(update_fields=['sensitive_meta'])
79
+
80
+ # Delete the old SensitiveMeta record
81
+ try:
82
+ SensitiveMeta.objects.filter(id=old_meta_id).delete()
83
+ logger.info(f"Deleted old SensitiveMeta {old_meta_id}")
84
+ except Exception as e:
85
+ logger.warning(f"Could not delete old SensitiveMeta {old_meta_id}: {e}")
86
+
87
+
88
+
89
+
90
+
91
+ # Ensure minimum patient data is available
92
+ logger.info(f"Ensuring minimum patient data for {pdf.uuid}")
93
+ self.pdf_service._ensure_default_patient_data(pdf)
94
+
95
+ # Refresh from database to get updated data
96
+ pdf.refresh_from_db()
97
+
98
+ # Use VideoImportService for anonymization
99
+ try:
100
+
101
+ logger.info(f"Starting anonymization using VideoImportService for {pdf.uuid}")
102
+ self.pdf_service.import_and_anonymize(
103
+ file_path=raw_file_path,
104
+ center_name=pdf.center.name,
105
+ processor_name=pdf.processor.name if pdf.processor else "Unknown",
106
+ save_video=True,
107
+ delete_source=False
108
+ )
109
+
110
+ logger.info(f"VideoImportService anonymization completed for {pdf.uuid}")
111
+
112
+
113
+ return Response({
114
+ "message": "Video re-import with VideoImportService completed successfully.",
115
+ "pdf_id": pdf_id,
116
+ "uuid": str(pdf.uuid),
117
+ "frame_cleaning_applied": True,
118
+ "sensitive_meta_created": pdf.sensitive_meta is not None,
119
+ "sensitive_meta_id": pdf.sensitive_meta.id if pdf.sensitive_meta else None,
120
+ "updated_in_place": True,
121
+ "status": "done"
122
+ }, status=status.HTTP_200_OK)
123
+
124
+ except Exception as e:
125
+ logger.exception(f"VideoImportService anonymization failed for pdf {pdf.uuid}: {e}")
126
+ logger.warning("Continuing without anonymization due to error")
127
+
128
+ # Refresh from database to get final state
129
+ pdf.refresh_from_db()
130
+
131
+ return Response({
132
+ "message": "PDF re-import completed successfully.",
133
+ "pdf_id": pdf_id,
134
+ "uuid": str(pdf.uuid),
135
+ "sensitive_meta_created": pdf.sensitive_meta is not None,
136
+ "sensitive_meta_id": pdf.sensitive_meta.id if pdf.sensitive_meta else None,
137
+ "updated_in_place": True,
138
+ "status": "done"
139
+ }, status=status.HTTP_200_OK)
140
+
141
+ except Exception as e:
142
+ logger.error(f"Failed to re-import pdf {pdf.uuid}: {str(e)}", exc_info=True)
143
+
144
+ # Handle specific error types
145
+ error_msg = str(e)
146
+ if any(phrase in error_msg.lower() for phrase in ["insufficient storage", "no space left", "disk full"]):
147
+ # Storage error - return specific error message
148
+ return Response({
149
+ "error": f"Storage error during re-import: {error_msg}",
150
+ "error_type": "storage_error",
151
+ "pdf_id": pdf_id,
152
+ "uuid": str(pdf.uuid)
153
+ }, status=status.HTTP_507_INSUFFICIENT_STORAGE)
154
+ else:
155
+ # Other errors
156
+ return Response({
157
+ "error": f"Re-import failed: {error_msg}",
158
+ "error_type": "processing_error",
159
+ "pdf_id": pdf_id,
160
+ "uuid": str(pdf.uuid)
161
+ }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@@ -0,0 +1,9 @@
1
+ from .report_list import ReportListView
2
+ from .report_with_secure_url import ReportWithSecureUrlView
3
+ from .start_examination import start_examination
4
+
5
+ __all__ = [
6
+ "ReportListView",
7
+ "ReportWithSecureUrlView",
8
+ "start_examination",
9
+ ]
@@ -0,0 +1,112 @@
1
+ from endoreg_db.models import RawPdfFile
2
+ from endoreg_db.serializers.report.report_list import ReportListSerializer
3
+
4
+ from django.core.paginator import Paginator
5
+ from django.db.models import Q
6
+ from rest_framework import status
7
+ from rest_framework.response import Response
8
+ from rest_framework.views import APIView
9
+
10
+ import logging
11
+ logger = logging.getLogger(__name__)
12
+
13
+ class ReportListView(APIView):
14
+ """
15
+ API-Endpunkt für paginierte Report-Listen mit optionaler Filterung
16
+ GET /api/reports/
17
+ """
18
+
19
+ def get(self, request):
20
+ try:
21
+ # Query-Parameter abrufen
22
+ page = int(request.GET.get('page', 1))
23
+ page_size = min(int(request.GET.get('page_size', 20)), 100) # Max 100 pro Seite
24
+
25
+ # Filter-Parameter
26
+ file_type_filter = request.GET.get('file_type')
27
+ patient_name_filter = request.GET.get('patient_name')
28
+ casenumber_filter = request.GET.get('casenumber')
29
+ date_from = request.GET.get('date_from')
30
+ date_to = request.GET.get('date_to')
31
+
32
+ # Base QuerySet mit related data
33
+ queryset = RawPdfFile.objects.select_related('sensitive_meta').all()
34
+
35
+ # Filter anwenden
36
+ if patient_name_filter:
37
+ queryset = queryset.filter(
38
+ Q(sensitive_meta__patient_first_name__icontains=patient_name_filter) |
39
+ Q(sensitive_meta__patient_last_name__icontains=patient_name_filter)
40
+ )
41
+
42
+ if casenumber_filter:
43
+ queryset = queryset.filter(
44
+ sensitive_meta__case_number__icontains=casenumber_filter
45
+ )
46
+
47
+ if file_type_filter:
48
+ # Filter basierend auf Dateiendung
49
+ queryset = queryset.filter(file__endswith=f'.{file_type_filter}')
50
+
51
+ if date_from:
52
+ queryset = queryset.filter(created_at__gte=date_from)
53
+
54
+ if date_to:
55
+ queryset = queryset.filter(created_at__lte=date_to)
56
+
57
+ # Sortierung (neueste zuerst)
58
+ queryset = queryset.order_by('-created_at')
59
+
60
+ # Paginierung
61
+ paginator = Paginator(queryset, page_size)
62
+
63
+ if page > paginator.num_pages:
64
+ return Response({
65
+ 'count': paginator.count,
66
+ 'next': None,
67
+ 'previous': None,
68
+ 'results': []
69
+ })
70
+
71
+ page_obj = paginator.get_page(page)
72
+
73
+ # Serialisierung
74
+ serializer = ReportListSerializer(
75
+ page_obj.object_list,
76
+ many=True,
77
+ context={'request': request}
78
+ )
79
+
80
+ # URLs für Paginierung
81
+ next_url = None
82
+ previous_url = None
83
+
84
+ if page_obj.has_next():
85
+ next_url = request.build_absolute_uri(
86
+ f"?page={page_obj.next_page_number()}&page_size={page_size}"
87
+ )
88
+
89
+ if page_obj.has_previous():
90
+ previous_url = request.build_absolute_uri(
91
+ f"?page={page_obj.previous_page_number()}&page_size={page_size}"
92
+ )
93
+
94
+ return Response({
95
+ 'count': paginator.count,
96
+ 'next': next_url,
97
+ 'previous': previous_url,
98
+ 'results': serializer.data
99
+ })
100
+
101
+ except ValueError as e:
102
+ logger.error("Ungültige Parameter in ReportListView: %s", str(e))
103
+ return Response(
104
+ {"error": "Ungültige Parameter"},
105
+ status=status.HTTP_400_BAD_REQUEST
106
+ )
107
+ except (AttributeError, TypeError, OSError) as e:
108
+ logger.error("Fehler in ReportListView: %s", str(e))
109
+ return Response(
110
+ {"error": "Fehler beim Laden der Reports"},
111
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR
112
+ )
@@ -0,0 +1,28 @@
1
+ from endoreg_db.models import RawPdfFile
2
+ from endoreg_db.serializers.report.report import ReportDataSerializer
3
+
4
+ from django.shortcuts import get_object_or_404
5
+ from rest_framework import status
6
+ from rest_framework.response import Response
7
+ from rest_framework.views import APIView
8
+
9
+ import logging
10
+ logger = logging.getLogger(__name__)
11
+
12
+ class ReportWithSecureUrlView(APIView):
13
+ """
14
+ API-Endpunkt für Reports mit sicherer URL-Generierung
15
+ GET /api/reports/{report_id}/with-secure-url/
16
+ """
17
+
18
+ def get(self, request, report_id):
19
+ try:
20
+ report = get_object_or_404(RawPdfFile, id=report_id)
21
+ serializer = ReportDataSerializer(report, context={'request': request})
22
+ return Response(serializer.data)
23
+ except (ValueError, TypeError) as e:
24
+ logger.error("Fehler beim Laden des Reports %s: %s", report_id, str(e))
25
+ return Response(
26
+ {"error": "Report konnte nicht geladen werden"},
27
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR
28
+ )