endoreg-db 0.6.0__py3-none-any.whl → 0.6.2__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 (416) hide show
  1. endoreg_db/case_generator/__init__.py +0 -0
  2. endoreg_db/case_generator/case_generator.py +159 -0
  3. endoreg_db/case_generator/lab_sample_factory.py +33 -0
  4. endoreg_db/case_generator/utils.py +30 -0
  5. endoreg_db/data/__init__.py +118 -0
  6. endoreg_db/data/agl_service/data.yaml +19 -0
  7. endoreg_db/data/ai_model/data.yaml +7 -0
  8. endoreg_db/data/ai_model_label/label/data.yaml +88 -0
  9. endoreg_db/data/ai_model_label/label-set/data.yaml +21 -0
  10. endoreg_db/data/ai_model_label/label-type/data.yaml +7 -0
  11. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +5 -0
  12. endoreg_db/data/ai_model_type/data.yaml +7 -0
  13. endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml +176 -0
  14. endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml +20 -0
  15. endoreg_db/data/case_template/rule/00_patient_lab_sample_add_default_value.yaml +167 -0
  16. endoreg_db/data/case_template/rule/01_patient-set-age.yaml +8 -0
  17. endoreg_db/data/case_template/rule/01_patient-set-gender.yaml +9 -0
  18. endoreg_db/data/case_template/rule/11_create_patient_lab_sample.yaml +23 -0
  19. endoreg_db/data/case_template/rule/12_create-patient_medication-anticoagulation.yaml +19 -0
  20. endoreg_db/data/case_template/rule/13_create-patient_medication_schedule-anticoagulation.yaml +19 -0
  21. endoreg_db/data/case_template/rule/19_create_patient.yaml +17 -0
  22. endoreg_db/data/case_template/rule_type/base_types.yaml +35 -0
  23. endoreg_db/data/case_template/rule_value/.init +0 -0
  24. endoreg_db/data/case_template/rule_value_type/base_types.yaml +59 -0
  25. endoreg_db/data/case_template/template/base.yaml +8 -0
  26. endoreg_db/data/case_template/template_type/pre_endoscopy.yaml +3 -0
  27. endoreg_db/data/case_template/tmp/_rule_value +13 -0
  28. endoreg_db/data/case_template/tmp/rule/01_atrial_fibrillation.yaml +21 -0
  29. endoreg_db/data/case_template/tmp/rule/02_create_object.yaml +10 -0
  30. endoreg_db/data/case_template/tmp/template/atrial_fibrillation_low_risk.yaml +7 -0
  31. endoreg_db/data/center/data.yaml +90 -0
  32. endoreg_db/data/center_resource/green_endoscopy_dashboard_CenterResource.yaml +144 -0
  33. endoreg_db/data/center_waste/green_endoscopy_dashboard_CenterWaste.yaml +48 -0
  34. endoreg_db/data/contraindication/bleeding.yaml +11 -0
  35. endoreg_db/data/disease/cardiovascular.yaml +37 -0
  36. endoreg_db/data/disease/hepatology.yaml +5 -0
  37. endoreg_db/data/disease/misc.yaml +6 -0
  38. endoreg_db/data/disease/renal.yaml +5 -0
  39. endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +6 -0
  40. endoreg_db/data/disease_classification/coronary_vessel_disease.yaml +6 -0
  41. endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +41 -0
  42. endoreg_db/data/disease_classification_choice/coronary_vessel_disease.yaml +20 -0
  43. endoreg_db/data/distribution/date/patient.yaml +7 -0
  44. endoreg_db/data/distribution/multiple_categorical/.init +0 -0
  45. endoreg_db/data/distribution/numeric/data.yaml +14 -0
  46. endoreg_db/data/distribution/single_categorical/patient.yaml +7 -0
  47. endoreg_db/data/emission_factor/green_endoscopy_dashboard_EmissionFactor.yaml +132 -0
  48. endoreg_db/data/endoscope/data.yaml +93 -0
  49. endoreg_db/data/endoscope_type/data.yaml +11 -0
  50. endoreg_db/data/endoscopy_processor/data.yaml +47 -0
  51. endoreg_db/data/event/cardiology.yaml +28 -0
  52. endoreg_db/data/event/neurology.yaml +14 -0
  53. endoreg_db/data/event/surgery.yaml +13 -0
  54. endoreg_db/data/event/thrombembolism.yaml +20 -0
  55. endoreg_db/data/examination/examinations/data.yaml +66 -0
  56. endoreg_db/data/examination/time/data.yaml +48 -0
  57. endoreg_db/data/examination/time-type/data.yaml +8 -0
  58. endoreg_db/data/examination/type/data.yaml +5 -0
  59. endoreg_db/data/examination_indication/endoscopy.yaml +8 -0
  60. endoreg_db/data/examination_indication_classification/endoscopy.yaml +8 -0
  61. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
  62. endoreg_db/data/finding/data.yaml +141 -0
  63. endoreg_db/data/finding_intervention/endoscopy.yaml +138 -0
  64. endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
  65. endoreg_db/data/finding_location_classification/colonoscopy.yaml +46 -0
  66. endoreg_db/data/finding_location_classification_choice/colonoscopy.yaml +240 -0
  67. endoreg_db/data/finding_morphology_classification/colonoscopy.yaml +48 -0
  68. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_circularity_default.yaml +34 -0
  69. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_nice.yaml +20 -0
  70. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_paris.yaml +65 -0
  71. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_planarity_default.yaml +56 -0
  72. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_surface_intact_default.yaml +39 -0
  73. endoreg_db/data/finding_morphology_classification_choice/colonoscopy_size.yaml +57 -0
  74. endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
  75. endoreg_db/data/finding_type/data.yaml +30 -0
  76. endoreg_db/data/gender/data.yaml +35 -0
  77. endoreg_db/data/information_source/data.yaml +30 -0
  78. endoreg_db/data/information_source/medication.yaml +6 -0
  79. endoreg_db/data/lab_value/cardiac_enzymes.yaml +37 -0
  80. endoreg_db/data/lab_value/coagulation.yaml +54 -0
  81. endoreg_db/data/lab_value/electrolytes.yaml +228 -0
  82. endoreg_db/data/lab_value/gastrointestinal_function.yaml +133 -0
  83. endoreg_db/data/lab_value/hematology.yaml +184 -0
  84. endoreg_db/data/lab_value/hormones.yaml +59 -0
  85. endoreg_db/data/lab_value/lipids.yaml +53 -0
  86. endoreg_db/data/lab_value/misc.yaml +33 -0
  87. endoreg_db/data/lab_value/renal_function.yaml +12 -0
  88. endoreg_db/data/log_type/data.yaml +57 -0
  89. endoreg_db/data/lx_client_tag/base.yaml +54 -0
  90. endoreg_db/data/lx_client_type/base.yaml +30 -0
  91. endoreg_db/data/lx_permission/base.yaml +24 -0
  92. endoreg_db/data/lx_permission/endoreg.yaml +52 -0
  93. endoreg_db/data/material/material.yaml +91 -0
  94. endoreg_db/data/medication/anticoagulation.yaml +65 -0
  95. endoreg_db/data/medication/tah.yaml +70 -0
  96. endoreg_db/data/medication_indication/anticoagulation.yaml +115 -0
  97. endoreg_db/data/medication_indication_type/data.yaml +11 -0
  98. endoreg_db/data/medication_indication_type/thrombembolism.yaml +41 -0
  99. endoreg_db/data/medication_intake_time/base.yaml +31 -0
  100. endoreg_db/data/medication_schedule/apixaban.yaml +95 -0
  101. endoreg_db/data/medication_schedule/ass.yaml +12 -0
  102. endoreg_db/data/medication_schedule/enoxaparin.yaml +26 -0
  103. endoreg_db/data/names_first/first_names.yaml +51 -0
  104. endoreg_db/data/names_last/last_names.yaml +51 -0
  105. endoreg_db/data/network_device/data.yaml +59 -0
  106. endoreg_db/data/network_device_type/data.yaml +12 -0
  107. endoreg_db/data/organ/data.yaml +29 -0
  108. endoreg_db/data/patient_lab_sample_type/generic.yaml +6 -0
  109. endoreg_db/data/pdf_type/data.yaml +29 -0
  110. endoreg_db/data/product/green_endoscopy_dashboard_Product.yaml +66 -0
  111. endoreg_db/data/product_group/green_endoscopy_dashboard_ProductGroup.yaml +33 -0
  112. endoreg_db/data/product_material/green_endoscopy_dashboard_ProductMaterial.yaml +308 -0
  113. endoreg_db/data/product_weight/green_endoscopy_dashboard_ProductWeight.yaml +88 -0
  114. endoreg_db/data/profession/data.yaml +70 -0
  115. endoreg_db/data/reference_product/green_endoscopy_dashboard_ReferenceProduct.yaml +55 -0
  116. endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +30 -0
  117. endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +19 -0
  118. endoreg_db/data/resource/green_endoscopy_dashboard_Resource.yaml +15 -0
  119. endoreg_db/data/tmp/chronic_kidney_disease.yaml +0 -0
  120. endoreg_db/data/tmp/congestive_heart_failure.yaml +0 -0
  121. endoreg_db/data/transport_route/green_endoscopy_dashboard_TransportRoute.yaml +12 -0
  122. endoreg_db/data/unit/concentration.yaml +92 -0
  123. endoreg_db/data/unit/data.yaml +17 -0
  124. endoreg_db/data/unit/length.yaml +31 -0
  125. endoreg_db/data/unit/misc.yaml +20 -0
  126. endoreg_db/data/unit/rate.yaml +6 -0
  127. endoreg_db/data/unit/time.yaml +13 -0
  128. endoreg_db/data/unit/volume.yaml +35 -0
  129. endoreg_db/data/unit/weight.yaml +38 -0
  130. endoreg_db/data/waste/data.yaml +12 -0
  131. endoreg_db/forms/__init__.py +5 -0
  132. endoreg_db/forms/examination_form.py +11 -0
  133. endoreg_db/forms/patient_finding_intervention_form.py +19 -0
  134. endoreg_db/forms/patient_form.py +26 -0
  135. endoreg_db/forms/questionnaires/__init__.py +1 -0
  136. endoreg_db/forms/questionnaires/tto_questionnaire.py +23 -0
  137. endoreg_db/forms/settings/__init__.py +8 -0
  138. endoreg_db/forms/unit.py +6 -0
  139. endoreg_db/management/__init__.py +0 -0
  140. endoreg_db/management/commands/__init__.py +0 -0
  141. endoreg_db/management/commands/_load_model_template.py +41 -0
  142. endoreg_db/management/commands/delete_all.py +18 -0
  143. endoreg_db/management/commands/fetch_legacy_image_dataset.py +32 -0
  144. endoreg_db/management/commands/fix_auth_permission.py +20 -0
  145. endoreg_db/management/commands/load_active_model_data.py +45 -0
  146. endoreg_db/management/commands/load_ai_model_data.py +79 -0
  147. endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
  148. endoreg_db/management/commands/load_base_db_data.py +178 -0
  149. endoreg_db/management/commands/load_center_data.py +43 -0
  150. endoreg_db/management/commands/load_contraindication_data.py +41 -0
  151. endoreg_db/management/commands/load_disease_classification_choices_data.py +41 -0
  152. endoreg_db/management/commands/load_disease_classification_data.py +41 -0
  153. endoreg_db/management/commands/load_disease_data.py +62 -0
  154. endoreg_db/management/commands/load_distribution_data.py +66 -0
  155. endoreg_db/management/commands/load_endoscope_data.py +68 -0
  156. endoreg_db/management/commands/load_event_data.py +41 -0
  157. endoreg_db/management/commands/load_examination_data.py +75 -0
  158. endoreg_db/management/commands/load_examination_indication_data.py +65 -0
  159. endoreg_db/management/commands/load_finding_data.py +171 -0
  160. endoreg_db/management/commands/load_g_play_data.py +113 -0
  161. endoreg_db/management/commands/load_gender_data.py +44 -0
  162. endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +133 -0
  163. endoreg_db/management/commands/load_information_source.py +45 -0
  164. endoreg_db/management/commands/load_lab_value_data.py +50 -0
  165. endoreg_db/management/commands/load_logging_data.py +39 -0
  166. endoreg_db/management/commands/load_lx_data.py +64 -0
  167. endoreg_db/management/commands/load_medication_data.py +103 -0
  168. endoreg_db/management/commands/load_medication_indication_data.py +63 -0
  169. endoreg_db/management/commands/load_medication_indication_type_data.py +41 -0
  170. endoreg_db/management/commands/load_medication_intake_time_data.py +41 -0
  171. endoreg_db/management/commands/load_medication_schedule_data.py +55 -0
  172. endoreg_db/management/commands/load_name_data.py +37 -0
  173. endoreg_db/management/commands/load_network_data.py +57 -0
  174. endoreg_db/management/commands/load_organ_data.py +43 -0
  175. endoreg_db/management/commands/load_pdf_type_data.py +61 -0
  176. endoreg_db/management/commands/load_profession_data.py +44 -0
  177. endoreg_db/management/commands/load_report_reader_flag_data.py +46 -0
  178. endoreg_db/management/commands/load_unit_data.py +46 -0
  179. endoreg_db/management/commands/load_user_groups.py +28 -0
  180. endoreg_db/management/commands/register_ai_model.py +64 -0
  181. endoreg_db/management/commands/reset_celery_schedule.py +9 -0
  182. endoreg_db/migrations/0001_initial.py +2045 -0
  183. endoreg_db/migrations/0002_alter_frame_image_alter_rawframe_image.py +23 -0
  184. endoreg_db/migrations/0003_alter_frame_image_alter_rawframe_image.py +23 -0
  185. endoreg_db/migrations/0004_alter_rawvideofile_file_alter_video_file.py +25 -0
  186. endoreg_db/migrations/0005_rawvideofile_frame_count_and_more.py +33 -0
  187. endoreg_db/migrations/0006_frame_extracted_rawframe_extracted.py +23 -0
  188. endoreg_db/migrations/0007_rename_pseudo_patient_video_patient_and_more.py +24 -0
  189. endoreg_db/migrations/0008_remove_reportfile_patient_examination_and_more.py +48 -0
  190. endoreg_db/migrations/__init__.py +0 -0
  191. endoreg_db/models/__init__.py +376 -0
  192. endoreg_db/models/ai_model/__init__.py +4 -0
  193. endoreg_db/models/ai_model/active_model.py +9 -0
  194. endoreg_db/models/ai_model/ai_model.py +103 -0
  195. endoreg_db/models/ai_model/lightning/__init__.py +3 -0
  196. endoreg_db/models/ai_model/lightning/inference_dataset.py +53 -0
  197. endoreg_db/models/ai_model/lightning/multilabel_classification_net.py +155 -0
  198. endoreg_db/models/ai_model/lightning/postprocess.py +53 -0
  199. endoreg_db/models/ai_model/lightning/predict.py +172 -0
  200. endoreg_db/models/ai_model/lightning/prediction_visualizer.py +55 -0
  201. endoreg_db/models/ai_model/lightning/preprocess.py +68 -0
  202. endoreg_db/models/ai_model/lightning/run_visualizer.py +21 -0
  203. endoreg_db/models/ai_model/model_meta.py +250 -0
  204. endoreg_db/models/ai_model/model_type.py +36 -0
  205. endoreg_db/models/ai_model/utils.py +8 -0
  206. endoreg_db/models/annotation/__init__.py +32 -0
  207. endoreg_db/models/annotation/anonymized_image_annotation.py +115 -0
  208. endoreg_db/models/annotation/binary_classification_annotation_task.py +117 -0
  209. endoreg_db/models/annotation/image_classification.py +86 -0
  210. endoreg_db/models/annotation/video_segmentation_annotation.py +52 -0
  211. endoreg_db/models/annotation/video_segmentation_labelset.py +20 -0
  212. endoreg_db/models/case/__init__.py +1 -0
  213. endoreg_db/models/case/case.py +34 -0
  214. endoreg_db/models/case_template/__init__.py +15 -0
  215. endoreg_db/models/case_template/case_template.py +125 -0
  216. endoreg_db/models/case_template/case_template_rule.py +276 -0
  217. endoreg_db/models/case_template/case_template_rule_value.py +88 -0
  218. endoreg_db/models/case_template/case_template_type.py +28 -0
  219. endoreg_db/models/center/__init__.py +11 -0
  220. endoreg_db/models/center/center.py +51 -0
  221. endoreg_db/models/center/center_product.py +33 -0
  222. endoreg_db/models/center/center_resource.py +33 -0
  223. endoreg_db/models/center/center_waste.py +16 -0
  224. endoreg_db/models/contraindication/__init__.py +21 -0
  225. endoreg_db/models/data_file/__init__.py +39 -0
  226. endoreg_db/models/data_file/base_classes/__init__.py +7 -0
  227. endoreg_db/models/data_file/base_classes/abstract_frame.py +100 -0
  228. endoreg_db/models/data_file/base_classes/abstract_pdf.py +136 -0
  229. endoreg_db/models/data_file/base_classes/abstract_video.py +807 -0
  230. endoreg_db/models/data_file/base_classes/frame_helpers.py +17 -0
  231. endoreg_db/models/data_file/base_classes/prepare_bulk_frames.py +19 -0
  232. endoreg_db/models/data_file/base_classes/utils.py +80 -0
  233. endoreg_db/models/data_file/frame.py +29 -0
  234. endoreg_db/models/data_file/import_classes/__init__.py +18 -0
  235. endoreg_db/models/data_file/import_classes/processing_functions/__init__.py +35 -0
  236. endoreg_db/models/data_file/import_classes/processing_functions/pdf.py +28 -0
  237. endoreg_db/models/data_file/import_classes/processing_functions/video.py +260 -0
  238. endoreg_db/models/data_file/import_classes/raw_pdf.py +260 -0
  239. endoreg_db/models/data_file/import_classes/raw_video.py +288 -0
  240. endoreg_db/models/data_file/metadata/__init__.py +13 -0
  241. endoreg_db/models/data_file/metadata/pdf_meta.py +74 -0
  242. endoreg_db/models/data_file/metadata/sensitive_meta.py +290 -0
  243. endoreg_db/models/data_file/metadata/video_meta.py +199 -0
  244. endoreg_db/models/data_file/report_file.py +56 -0
  245. endoreg_db/models/data_file/video/__init__.py +11 -0
  246. endoreg_db/models/data_file/video/import_meta.py +25 -0
  247. endoreg_db/models/data_file/video/video.py +196 -0
  248. endoreg_db/models/data_file/video_segment.py +214 -0
  249. endoreg_db/models/disease.py +79 -0
  250. endoreg_db/models/emission/__init__.py +5 -0
  251. endoreg_db/models/emission/emission_factor.py +85 -0
  252. endoreg_db/models/event.py +73 -0
  253. endoreg_db/models/examination/__init__.py +9 -0
  254. endoreg_db/models/examination/examination.py +67 -0
  255. endoreg_db/models/examination/examination_indication.py +170 -0
  256. endoreg_db/models/examination/examination_time.py +53 -0
  257. endoreg_db/models/examination/examination_time_type.py +48 -0
  258. endoreg_db/models/examination/examination_type.py +40 -0
  259. endoreg_db/models/finding/__init__.py +11 -0
  260. endoreg_db/models/finding/finding.py +75 -0
  261. endoreg_db/models/finding/finding_intervention.py +60 -0
  262. endoreg_db/models/finding/finding_location_classification.py +94 -0
  263. endoreg_db/models/finding/finding_morphology_classification.py +89 -0
  264. endoreg_db/models/finding/finding_type.py +22 -0
  265. endoreg_db/models/hardware/__init__.py +2 -0
  266. endoreg_db/models/hardware/endoscope.py +60 -0
  267. endoreg_db/models/hardware/endoscopy_processor.py +155 -0
  268. endoreg_db/models/information_source.py +29 -0
  269. endoreg_db/models/label/__init__.py +1 -0
  270. endoreg_db/models/label/label.py +112 -0
  271. endoreg_db/models/laboratory/__init__.py +1 -0
  272. endoreg_db/models/laboratory/lab_value.py +111 -0
  273. endoreg_db/models/logging/__init__.py +11 -0
  274. endoreg_db/models/logging/agl_service.py +19 -0
  275. endoreg_db/models/logging/base.py +22 -0
  276. endoreg_db/models/logging/log_type.py +23 -0
  277. endoreg_db/models/logging/network_device.py +27 -0
  278. endoreg_db/models/lx/__init__.py +4 -0
  279. endoreg_db/models/lx/client.py +57 -0
  280. endoreg_db/models/lx/identity.py +34 -0
  281. endoreg_db/models/lx/permission.py +18 -0
  282. endoreg_db/models/lx/user.py +16 -0
  283. endoreg_db/models/medication/__init__.py +19 -0
  284. endoreg_db/models/medication/medication.py +33 -0
  285. endoreg_db/models/medication/medication_indication.py +50 -0
  286. endoreg_db/models/medication/medication_indication_type.py +34 -0
  287. endoreg_db/models/medication/medication_intake_time.py +26 -0
  288. endoreg_db/models/medication/medication_schedule.py +37 -0
  289. endoreg_db/models/network/__init__.py +9 -0
  290. endoreg_db/models/network/agl_service.py +38 -0
  291. endoreg_db/models/network/network_device.py +58 -0
  292. endoreg_db/models/network/network_device_type.py +23 -0
  293. endoreg_db/models/organ/__init__.py +38 -0
  294. endoreg_db/models/other/__init__.py +23 -0
  295. endoreg_db/models/other/distribution/__init__.py +44 -0
  296. endoreg_db/models/other/distribution/base_value_distribution.py +20 -0
  297. endoreg_db/models/other/distribution/date_value_distribution.py +91 -0
  298. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
  299. endoreg_db/models/other/distribution/numeric_value_distribution.py +97 -0
  300. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
  301. endoreg_db/models/other/distribution.py +5 -0
  302. endoreg_db/models/other/material.py +20 -0
  303. endoreg_db/models/other/resource.py +18 -0
  304. endoreg_db/models/other/transport_route.py +22 -0
  305. endoreg_db/models/other/waste.py +20 -0
  306. endoreg_db/models/patient/__init__.py +24 -0
  307. endoreg_db/models/patient/patient_examination.py +182 -0
  308. endoreg_db/models/patient/patient_finding.py +143 -0
  309. endoreg_db/models/patient/patient_finding_intervention.py +26 -0
  310. endoreg_db/models/patient/patient_finding_location.py +120 -0
  311. endoreg_db/models/patient/patient_finding_morphology.py +166 -0
  312. endoreg_db/models/permissions/__init__.py +44 -0
  313. endoreg_db/models/persons/__init__.py +34 -0
  314. endoreg_db/models/persons/examiner/__init__.py +2 -0
  315. endoreg_db/models/persons/examiner/examiner.py +60 -0
  316. endoreg_db/models/persons/examiner/examiner_type.py +2 -0
  317. endoreg_db/models/persons/first_name.py +18 -0
  318. endoreg_db/models/persons/gender.py +22 -0
  319. endoreg_db/models/persons/last_name.py +20 -0
  320. endoreg_db/models/persons/patient/__init__.py +8 -0
  321. endoreg_db/models/persons/patient/patient.py +389 -0
  322. endoreg_db/models/persons/patient/patient_disease.py +22 -0
  323. endoreg_db/models/persons/patient/patient_event.py +52 -0
  324. endoreg_db/models/persons/patient/patient_examination_indication.py +32 -0
  325. endoreg_db/models/persons/patient/patient_lab_sample.py +108 -0
  326. endoreg_db/models/persons/patient/patient_lab_value.py +197 -0
  327. endoreg_db/models/persons/patient/patient_medication.py +59 -0
  328. endoreg_db/models/persons/patient/patient_medication_schedule.py +88 -0
  329. endoreg_db/models/persons/person.py +31 -0
  330. endoreg_db/models/persons/portal_user_information.py +27 -0
  331. endoreg_db/models/prediction/__init__.py +8 -0
  332. endoreg_db/models/prediction/image_classification.py +51 -0
  333. endoreg_db/models/prediction/video_prediction_meta.py +306 -0
  334. endoreg_db/models/product/__init__.py +14 -0
  335. endoreg_db/models/product/product.py +110 -0
  336. endoreg_db/models/product/product_group.py +27 -0
  337. endoreg_db/models/product/product_material.py +28 -0
  338. endoreg_db/models/product/product_weight.py +38 -0
  339. endoreg_db/models/product/reference_product.py +115 -0
  340. endoreg_db/models/questionnaires/__init__.py +114 -0
  341. endoreg_db/models/quiz/__init__.py +9 -0
  342. endoreg_db/models/quiz/quiz_answer.py +41 -0
  343. endoreg_db/models/quiz/quiz_question.py +54 -0
  344. endoreg_db/models/report_reader/__init__.py +7 -0
  345. endoreg_db/models/report_reader/report_reader_config.py +53 -0
  346. endoreg_db/models/report_reader/report_reader_flag.py +20 -0
  347. endoreg_db/models/rules/__init__.py +5 -0
  348. endoreg_db/models/rules/rule.py +24 -0
  349. endoreg_db/models/rules/rule_applicator.py +224 -0
  350. endoreg_db/models/rules/rule_attribute_dtype.py +19 -0
  351. endoreg_db/models/rules/rule_type.py +22 -0
  352. endoreg_db/models/rules/ruleset.py +19 -0
  353. endoreg_db/models/unit.py +22 -0
  354. endoreg_db/queries/__init__.py +5 -0
  355. endoreg_db/queries/annotations/__init__.py +3 -0
  356. endoreg_db/queries/annotations/legacy.py +158 -0
  357. endoreg_db/queries/get/__init__.py +6 -0
  358. endoreg_db/queries/get/annotation.py +0 -0
  359. endoreg_db/queries/get/center.py +42 -0
  360. endoreg_db/queries/get/model.py +13 -0
  361. endoreg_db/queries/get/patient.py +14 -0
  362. endoreg_db/queries/get/patient_examination.py +20 -0
  363. endoreg_db/queries/get/prediction.py +0 -0
  364. endoreg_db/queries/get/report_file.py +33 -0
  365. endoreg_db/queries/get/video.py +31 -0
  366. endoreg_db/queries/get/video_import_meta.py +0 -0
  367. endoreg_db/queries/get/video_prediction_meta.py +0 -0
  368. endoreg_db/queries/sanity/__init_.py +0 -0
  369. endoreg_db/serializers/__init__.py +10 -0
  370. endoreg_db/serializers/ai_model.py +19 -0
  371. endoreg_db/serializers/annotation.py +14 -0
  372. endoreg_db/serializers/center.py +11 -0
  373. endoreg_db/serializers/examination.py +33 -0
  374. endoreg_db/serializers/frame.py +9 -0
  375. endoreg_db/serializers/hardware.py +21 -0
  376. endoreg_db/serializers/label.py +22 -0
  377. endoreg_db/serializers/patient.py +33 -0
  378. endoreg_db/serializers/prediction.py +10 -0
  379. endoreg_db/serializers/raw_video_meta_validation.py +13 -0
  380. endoreg_db/serializers/report_file.py +7 -0
  381. endoreg_db/serializers/video.py +20 -0
  382. endoreg_db/serializers/video_segmentation.py +492 -0
  383. endoreg_db/templates/admin/patient_finding_intervention.html +253 -0
  384. endoreg_db/templates/admin/start_examination.html +12 -0
  385. endoreg_db/templates/timeline.html +176 -0
  386. endoreg_db/utils/__init__.py +36 -0
  387. endoreg_db/utils/cropping.py +29 -0
  388. endoreg_db/utils/dataloader.py +118 -0
  389. endoreg_db/utils/dates.py +39 -0
  390. endoreg_db/utils/file_operations.py +30 -0
  391. endoreg_db/utils/hashs.py +152 -0
  392. endoreg_db/utils/legacy_ocr.py +201 -0
  393. endoreg_db/utils/names.py +74 -0
  394. endoreg_db/utils/ocr.py +190 -0
  395. endoreg_db/utils/parse_and_generate_yaml.py +46 -0
  396. endoreg_db/utils/pydantic_models/__init__.py +6 -0
  397. endoreg_db/utils/pydantic_models/db_config.py +57 -0
  398. endoreg_db/utils/uuid.py +4 -0
  399. endoreg_db/utils/validate_endo_roi.py +19 -0
  400. endoreg_db/utils/validate_subcategory_dict.py +91 -0
  401. endoreg_db/utils/video/__init__.py +13 -0
  402. endoreg_db/utils/video/extract_frames.py +121 -0
  403. endoreg_db/utils/video/transcode_videofile.py +111 -0
  404. endoreg_db/views/__init__.py +2 -0
  405. endoreg_db/views/csrf.py +7 -0
  406. endoreg_db/views/patient_views.py +90 -0
  407. endoreg_db/views/raw_video_meta_validation_views.py +38 -0
  408. endoreg_db/views/report_views.py +96 -0
  409. endoreg_db/views/video_segmentation_views.py +149 -0
  410. endoreg_db/views/views_for_timeline.py +46 -0
  411. {endoreg_db-0.6.0.dist-info → endoreg_db-0.6.2.dist-info}/METADATA +14 -4
  412. endoreg_db-0.6.2.dist-info/RECORD +420 -0
  413. {endoreg_db-0.6.0.dist-info → endoreg_db-0.6.2.dist-info}/WHEEL +1 -2
  414. endoreg_db-0.6.0.dist-info/RECORD +0 -11
  415. endoreg_db-0.6.0.dist-info/top_level.txt +0 -1
  416. {endoreg_db-0.6.0.dist-info → endoreg_db-0.6.2.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,260 @@
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
+
8
+ from django.db import models
9
+ from django.core.files.storage import FileSystemStorage
10
+ from django.conf import settings
11
+ from django.core.exceptions import ValidationError
12
+ from django.core.validators import FileExtensionValidator
13
+ from endoreg_db.utils.file_operations import get_uuid_filename
14
+ from icecream import ic
15
+
16
+ from agl_report_reader.report_reader import ReportReader
17
+
18
+ from endoreg_db.utils.hashs import get_pdf_hash
19
+ from ..metadata import SensitiveMeta
20
+ from ..base_classes.abstract_pdf import AbstractPdfFile
21
+
22
+ # setup logging to pdf_import.log
23
+ import logging
24
+
25
+ import shutil
26
+ from pathlib import Path
27
+
28
+ from ..base_classes.utils import (
29
+ STORAGE_LOCATION,
30
+ )
31
+
32
+ logger = logging.getLogger("pdf_import")
33
+
34
+ RAW_PDF_DIR_NAME = "raw_pdf"
35
+ RAW_PDF_DIR = STORAGE_LOCATION / RAW_PDF_DIR_NAME
36
+
37
+ if not RAW_PDF_DIR.exists():
38
+ RAW_PDF_DIR.mkdir(parents=True)
39
+
40
+
41
+ class RawPdfFile(AbstractPdfFile):
42
+ file = models.FileField(
43
+ upload_to=f"{RAW_PDF_DIR_NAME}/",
44
+ validators=[FileExtensionValidator(allowed_extensions=["pdf"])],
45
+ storage=FileSystemStorage(location=STORAGE_LOCATION.resolve().as_posix()),
46
+ )
47
+
48
+ patient = models.ForeignKey(
49
+ "Patient",
50
+ on_delete=models.SET_NULL,
51
+ blank=True,
52
+ null=True,
53
+ related_name="raw_pdf_files",
54
+ )
55
+
56
+ state_report_processing_required = models.BooleanField(default=True)
57
+ state_report_processed = models.BooleanField(default=False)
58
+ raw_meta = models.JSONField(blank=True, null=True)
59
+ # report_file = models.OneToOneField("ReportFile", on_delete=models.CASCADE, null=True, blank=True)
60
+ sensitive_meta = models.ForeignKey(
61
+ "SensitiveMeta",
62
+ on_delete=models.SET_NULL,
63
+ related_name="raw_pdf_files",
64
+ null=True,
65
+ blank=True,
66
+ )
67
+
68
+ report_file = models.ForeignKey(
69
+ "ReportFile",
70
+ on_delete=models.SET_NULL,
71
+ related_name="raw_pdf_files",
72
+ null=True,
73
+ blank=True,
74
+ )
75
+
76
+ anonymized_text = models.TextField(blank=True, null=True)
77
+
78
+ @classmethod
79
+ def create_from_file(
80
+ cls,
81
+ file_path: Path,
82
+ center_name,
83
+ save=True,
84
+ delete_source=True,
85
+ ):
86
+ from endoreg_db.models import Center
87
+
88
+ logger.info(f"Creating RawPdfFile object from file: {file_path}")
89
+ ic(f"Creating RawPdfFile object from file: {file_path}")
90
+
91
+ new_file_name, uuid = get_uuid_filename(file_path)
92
+
93
+ pdf_hash = get_pdf_hash(file_path)
94
+ ic(pdf_hash)
95
+ new_file_path = RAW_PDF_DIR / new_file_name
96
+ # check if pdf file already exists
97
+
98
+ if cls.objects.filter(pdf_hash=pdf_hash).exists():
99
+ existing_pdf_file = cls.objects.filter(pdf_hash=pdf_hash).get()
100
+ logger.warning(f"RawPdfFile with hash {pdf_hash} already exists")
101
+ ic(f"RawPdfFile with hash {pdf_hash} already exists")
102
+
103
+ existing_pdf_file.verify_existing_file(fallback_file=file_path)
104
+
105
+ return existing_pdf_file
106
+
107
+ else:
108
+ ic(f"No existing pdf file found for hash {pdf_hash}")
109
+
110
+ # assert pdf_type_name is not None, "pdf_type_name is required"
111
+ assert center_name is not None, "center_name is required"
112
+
113
+ # pdf_type = PdfType.objects.get(name=pdf_type_name)
114
+ center = Center.objects.get(name=center_name)
115
+
116
+ logger.info(f"Copying file to {new_file_path}")
117
+ ic(f"Copying file to {new_file_path}")
118
+ _success = shutil.copy(file_path, new_file_path)
119
+
120
+ # validate copy operation by comparing hashs
121
+ assert get_pdf_hash(new_file_path) == pdf_hash, "Copy operation failed"
122
+
123
+ raw_pdf = cls(
124
+ file=new_file_path.resolve().as_posix(),
125
+ pdf_hash=pdf_hash,
126
+ # pdf_type=pdf_type,
127
+ center=center,
128
+ )
129
+ raw_pdf.save()
130
+ logger.info(f"RawPdfFile object created: {raw_pdf}")
131
+ ic(f"RawPdfFile object created: {raw_pdf}")
132
+
133
+ # remove source file
134
+ if delete_source:
135
+ file_path.unlink()
136
+ logger.info(f"Source file removed: {file_path}")
137
+ ic(f"Source file removed: {file_path}")
138
+
139
+ if save:
140
+ raw_pdf.save()
141
+
142
+ return raw_pdf
143
+
144
+ def save(self, *args, **kwargs):
145
+ if not self.file.name.endswith(".pdf"):
146
+ raise ValidationError("Only PDF files are allowed")
147
+
148
+ if not self.pdf_hash:
149
+ self.pdf_hash = get_pdf_hash(self.file.path)
150
+
151
+ super().save(*args, **kwargs)
152
+
153
+ def verify_existing_file(self, fallback_file):
154
+ if not Path(self.file.path).exists():
155
+ logger.warning(f"File not found: {self.file.path}")
156
+ logger.warning(f"Using fallback file: {fallback_file}")
157
+ ic(f"File not found: {self.file.path}")
158
+ ic(f"Copy fallback file: {fallback_file} to existing filepath")
159
+
160
+ shutil.copy(fallback_file, self.file.path)
161
+
162
+ self.save()
163
+
164
+ def process_file(self, verbose=False):
165
+ pdf_path = self.file.path
166
+ rr_config = self.get_report_reader_config()
167
+
168
+ rr = ReportReader(
169
+ **rr_config
170
+ ) # FIXME In future we need to pass a configuration file
171
+ # This configuration file should be associated with pdf type
172
+
173
+ text, anonymized_text, report_meta = rr.process_report(
174
+ pdf_path, verbose=verbose
175
+ )
176
+
177
+ self.text = text
178
+ self.anonymized_text = anonymized_text
179
+
180
+ report_meta["center_name"] = self.center.name
181
+ if not self.sensitive_meta:
182
+ sensitive_meta = SensitiveMeta.create_from_dict(report_meta)
183
+ self.sensitive_meta = sensitive_meta
184
+
185
+ else:
186
+ # update existing sensitive meta
187
+ sensitive_meta = self.sensitive_meta
188
+ sensitive_meta.update_from_dict(report_meta)
189
+
190
+ self.raw_meta = report_meta
191
+
192
+ sensitive_meta.save()
193
+ self.save()
194
+
195
+ return text, anonymized_text, report_meta
196
+
197
+ def get_report_reader_config(self):
198
+ from endoreg_db.models import PdfType, Center
199
+ from warnings import warn
200
+
201
+ if not self.pdf_type:
202
+ warn("PdfType not set, using default settings")
203
+ pdf_type = PdfType.default_pdf_type()
204
+ else:
205
+ pdf_type: PdfType = self.pdf_type
206
+ center: Center = self.center
207
+ if pdf_type.endoscope_info_line:
208
+ endoscope_info_line = pdf_type.endoscope_info_line.value
209
+
210
+ else:
211
+ endoscope_info_line = None
212
+ settings_dict = {
213
+ "locale": "de_DE",
214
+ "employee_first_names": [_.name for _ in center.first_names.all()],
215
+ "employee_last_names": [_.name for _ in center.last_names.all()],
216
+ "text_date_format": "%d.%m.%Y",
217
+ "flags": {
218
+ "patient_info_line": pdf_type.patient_info_line.value,
219
+ "endoscope_info_line": endoscope_info_line,
220
+ "examiner_info_line": pdf_type.examiner_info_line.value,
221
+ "cut_off_below": [_.value for _ in pdf_type.cut_off_below_lines.all()],
222
+ "cut_off_above": [_.value for _ in pdf_type.cut_off_above_lines.all()],
223
+ },
224
+ }
225
+
226
+ return settings_dict
227
+
228
+ def get_or_create_report_file(self):
229
+ from endoreg_db.models import ReportFile
230
+
231
+ if self.report_file:
232
+ report_file = self.report_file
233
+
234
+ elif ReportFile.objects.filter(pdf_hash=self.pdf_hash).exists():
235
+ report_file = ReportFile.objects.filter(pdf_hash=self.pdf_hash).get()
236
+ self.report_file = report_file
237
+ self.save()
238
+ else:
239
+ # TODO Make sure all required states are set
240
+ patient = self.sensitive_meta.get_or_create_pseudo_patient()
241
+ examiner = self.sensitive_meta.get_or_create_pseudo_examiner()
242
+ patient_examination = (
243
+ self.sensitive_meta.get_or_create_pseudo_patient_examination()
244
+ )
245
+
246
+ report_file = ReportFile.objects.create(
247
+ pdf_hash=self.pdf_hash,
248
+ center=self.center,
249
+ sensitive_meta=self.sensitive_meta,
250
+ patient=patient,
251
+ examiner=examiner,
252
+ examination=patient_examination,
253
+ text=self.anonymized_text,
254
+ )
255
+
256
+ report_file.save()
257
+ self.report_file = report_file
258
+ self.save()
259
+
260
+ return report_file
@@ -0,0 +1,288 @@
1
+ import shutil
2
+ import subprocess
3
+ from pathlib import Path
4
+ from django.db import models
5
+ from typing import TYPE_CHECKING, List, Tuple
6
+
7
+ from icecream import ic
8
+ from tqdm import tqdm
9
+ import cv2
10
+ from django.core.validators import FileExtensionValidator
11
+ from django.core.files.storage import FileSystemStorage
12
+
13
+ from endoreg_db.utils.validate_endo_roi import validate_endo_roi
14
+ from ..base_classes.utils import (
15
+ anonymize_frame,
16
+ RAW_VIDEO_DIR_NAME,
17
+ VIDEO_DIR,
18
+ STORAGE_LOCATION,
19
+ )
20
+ from ..base_classes.abstract_video import AbstractVideoFile
21
+
22
+ if TYPE_CHECKING:
23
+ # import Queryset
24
+ from django.db.models import QuerySet
25
+ from endoreg_db.models import (
26
+ SensitiveMeta,
27
+ LabelVideoSegment,
28
+ )
29
+
30
+
31
+ # pylint: disable=attribute-defined-outside-init,no-member
32
+ class RawVideoFile(AbstractVideoFile):
33
+ """ """
34
+
35
+ file = models.FileField(
36
+ upload_to=RAW_VIDEO_DIR_NAME,
37
+ validators=[FileExtensionValidator(allowed_extensions=["mp4"])], # FIXME
38
+ storage=FileSystemStorage(location=STORAGE_LOCATION.resolve().as_posix()),
39
+ )
40
+
41
+ patient = models.ForeignKey(
42
+ "Patient", on_delete=models.SET_NULL, blank=True, null=True
43
+ )
44
+
45
+ sensitive_meta = models.ForeignKey(
46
+ "SensitiveMeta",
47
+ on_delete=models.SET_NULL,
48
+ related_name="raw_videos",
49
+ null=True,
50
+ blank=True,
51
+ )
52
+
53
+ video = models.ForeignKey(
54
+ "Video",
55
+ on_delete=models.SET_NULL,
56
+ related_name="raw_videos",
57
+ null=True,
58
+ blank=True,
59
+ )
60
+
61
+ if TYPE_CHECKING:
62
+ sensitive_meta: "SensitiveMeta"
63
+ label_video_segments: "QuerySet[LabelVideoSegment]"
64
+
65
+ # Crop Frames
66
+ state_anonymized_frames_generated = models.BooleanField(default=False)
67
+
68
+ ## OCR
69
+ state_ocr_required = models.BooleanField(default=True)
70
+ state_ocr_completed = models.BooleanField(default=False)
71
+ ## Validation
72
+ state_outside_validated = models.BooleanField(default=False)
73
+ state_ocr_result_validated = models.BooleanField(default=False)
74
+
75
+ state_sensitive_data_retrieved = models.BooleanField(default=False)
76
+
77
+ # Censor Outside
78
+ state_censor_outside_required = models.BooleanField(default=True)
79
+ state_censor_outside_completed = models.BooleanField(default=False)
80
+ state_make_anonymized_video_required = models.BooleanField(default=True)
81
+ state_make_anonymized_video_completed = models.BooleanField(default=False)
82
+
83
+ def get_anonymized_video_path(self):
84
+ video_dir = VIDEO_DIR
85
+ video_suffix = Path(self.file.path).suffix
86
+ video_name = f"{self.uuid}{video_suffix}"
87
+ anonymized_video_name = f"TMP_anonymized_{video_name}"
88
+ anonymized_video_path = video_dir / anonymized_video_name
89
+
90
+ return anonymized_video_path
91
+
92
+ def censor_outside_frames(self):
93
+ assert self.state_frames_extracted, "Frames not extracted"
94
+ assert self.state_initial_prediction_completed, (
95
+ "Initial prediction not completed"
96
+ )
97
+ assert self.state_sensitive_data_retrieved, "Sensitive data not retrieved"
98
+
99
+ ic(
100
+ "WARNING: Outside validation is not yet implemented and automatically set to true in this function"
101
+ )
102
+
103
+ self.state_outside_validated = True
104
+ self.save()
105
+
106
+ assert self.state_outside_validated, "Outside validation not completed"
107
+
108
+ outside_frame_paths = self.get_outside_frame_paths()
109
+
110
+ if not outside_frame_paths:
111
+ ic("No outside frames found")
112
+
113
+ else:
114
+ ic(f"Found {len(outside_frame_paths)} outside frames")
115
+ # use cv2 to replace all outside frames with completely black frames
116
+
117
+ for frame_path in tqdm(outside_frame_paths):
118
+ frame = cv2.imread(frame_path.as_posix())
119
+ frame.fill(0)
120
+ cv2.imwrite(frame_path.as_posix(), frame)
121
+
122
+ self.state_censor_outside_required = False
123
+ self.state_censor_outside_completed = True
124
+ self.save()
125
+
126
+ def get_anonymized_frame_dir(self):
127
+ anonymized_frame_dir = Path(self.frame_dir).parent / f"tmp_{self.uuid}"
128
+ return anonymized_frame_dir
129
+
130
+ def make_temporary_anonymized_frames(self) -> Tuple[Path, List[Path]]:
131
+ anonymized_frame_dir = self.get_anonymized_frame_dir()
132
+
133
+ assert self.state_frames_extracted, "Frames not extracted"
134
+ assert self.processor, "Processor not set"
135
+
136
+ anonymized_frame_dir.mkdir(parents=True, exist_ok=True)
137
+ endo_roi = self.get_endo_roi()
138
+ assert validate_endo_roi(endo_roi), "Endoscope ROI is not valid"
139
+ generated_frame_paths = []
140
+
141
+ all_frames = self.frames.all()
142
+ outside_frames = self.get_outside_frames() #
143
+ outside_frame_numbers = [frame.frame_number for frame in outside_frames]
144
+
145
+ # anonymize frames: copy endo-roi content while making other pixels black. (frames are Path objects to jpgs or pngs)
146
+ for frame in tqdm(all_frames):
147
+ frame_path = Path(frame.image.path)
148
+ frame_name = frame_path.name
149
+ frame_number = frame.frame_number
150
+
151
+ if frame_number in outside_frame_numbers:
152
+ all_black = True
153
+ else:
154
+ all_black = False
155
+
156
+ target_frame_path = anonymized_frame_dir / frame_name
157
+ anonymize_frame(
158
+ frame_path, target_frame_path, endo_roi, all_black=all_black
159
+ )
160
+ generated_frame_paths.append(target_frame_path)
161
+
162
+ return anonymized_frame_dir, generated_frame_paths
163
+
164
+ def make_anonymized_video(self):
165
+ """
166
+ Make an anonymized video from the anonymized frames.
167
+ """
168
+
169
+ assert self.state_initial_prediction_completed, (
170
+ "Initial prediction not completed"
171
+ )
172
+ assert self.state_sensitive_data_retrieved, "Sensitive data not retrieved"
173
+
174
+ ic(
175
+ "WARNING: Outside validation is not yet implemented and automatically set to true in this function"
176
+ )
177
+ self.state_outside_validated = True
178
+ self.save()
179
+
180
+ assert self.state_outside_validated, "Outside validation not completed"
181
+
182
+ _anonymized_frame_dir, generated_frame_paths = (
183
+ self.make_temporary_anonymized_frames()
184
+ )
185
+
186
+ anonymized_video_path = self.get_anonymized_video_path()
187
+ # if anonymized video already exists, delete it
188
+ if anonymized_video_path.exists():
189
+ anonymized_video_path.unlink()
190
+
191
+ # Use ffmpeg and the frame paths to create a video
192
+ fps = self.get_fps()
193
+ height, width = cv2.imread(generated_frame_paths[0].as_posix()).shape[:2]
194
+ ic("Assembling anonymized video")
195
+ ic(f"Frame width: {width}, height: {height}")
196
+ ic(f"FPS: {fps}")
197
+
198
+ command = [
199
+ "ffmpeg",
200
+ "-y",
201
+ "-pattern_type",
202
+ "glob",
203
+ "-f",
204
+ "image2",
205
+ "-framerate",
206
+ str(fps),
207
+ "-i",
208
+ f"{generated_frame_paths[0].parent.as_posix()}/frame_[0-9]*.jpg",
209
+ "-c:v",
210
+ "libx264",
211
+ "-pix_fmt",
212
+ "yuv420p",
213
+ "-vf",
214
+ f"scale={width}:{height}",
215
+ anonymized_video_path.as_posix(),
216
+ ]
217
+
218
+ subprocess.run(command, check=True)
219
+ ic(f"Anonymized video saved at {anonymized_video_path}")
220
+
221
+ self.state_make_anonymized_video_required = False
222
+ self.state_make_anonymized_video_completed = True
223
+ self.save()
224
+
225
+ return anonymized_video_path, generated_frame_paths
226
+
227
+ def delete_frames_anonymized(self):
228
+ """
229
+ Delete anonymized frames extracted from the video file.
230
+ """
231
+ frame_dir = Path(self.frame_dir)
232
+ anonymized_frame_dir = frame_dir.parent / f"anonymized_{self.uuid}"
233
+ if anonymized_frame_dir.exists():
234
+ shutil.rmtree(anonymized_frame_dir)
235
+ return f"Anonymized frames deleted from {anonymized_frame_dir}"
236
+ else:
237
+ return f"No anonymized frames to delete for {self.file.name}"
238
+
239
+ def get_or_create_video(self):
240
+ from endoreg_db.models import Video, Patient, PatientExamination
241
+
242
+ video = self.video
243
+ expected_path = self.get_anonymized_video_path()
244
+ if not video:
245
+ video_hash = self.video_hash
246
+ if Video.objects.filter(video_hash=video_hash).exists():
247
+ video = Video.objects.filter(video_hash=video_hash).first()
248
+
249
+ else:
250
+ if not expected_path.exists():
251
+ ic(
252
+ f"No anonymized video found at {expected_path}, Creating new one"
253
+ )
254
+ video_path, frame_paths = self.make_anonymized_video()
255
+
256
+ else:
257
+ ic(f"Anonymized video found at {expected_path}")
258
+ video_path = expected_path
259
+ frame_dir = self.get_anonymized_frame_dir()
260
+ ic(f"Frame dir: {frame_dir}")
261
+ frame_paths = list(frame_dir.glob("*.jpg"))
262
+ ic(f"Found {len(frame_paths)} frames")
263
+
264
+ video_object = Video.create_from_file(
265
+ video_path,
266
+ self.center,
267
+ self.processor,
268
+ video_dir=VIDEO_DIR,
269
+ frame_paths=frame_paths,
270
+ )
271
+
272
+ ex: PatientExamination = self.sensitive_meta.pseudo_examination
273
+ pat: Patient = self.sensitive_meta.pseudo_patient
274
+ video_object.examination = ex
275
+ video_object.patient = pat
276
+
277
+ self.video = video_object
278
+ self.save()
279
+ video_object.sync_from_raw_video()
280
+
281
+ ic(f"Video object created: {video_object}")
282
+ return video_object
283
+
284
+ self.video = video
285
+ self.save()
286
+
287
+ # self.vi
288
+ return video
@@ -0,0 +1,13 @@
1
+ from .sensitive_meta import SensitiveMeta
2
+ from .pdf_meta import PdfMeta, PdfType
3
+ from .video_meta import VideoMeta, FFMpegMeta, VideoImportMeta
4
+
5
+
6
+ __all__ = [
7
+ "SensitiveMeta",
8
+ "PdfMeta",
9
+ "PdfType",
10
+ "VideoMeta",
11
+ "FFMpegMeta",
12
+ "VideoImportMeta",
13
+ ]
@@ -0,0 +1,74 @@
1
+ from django.db import models
2
+
3
+ # import endoreg_center_id from django settings
4
+ from django.conf import settings
5
+
6
+
7
+ # import File class
8
+ from django.core.files import File
9
+
10
+ # # check if endoreg_center_id is set
11
+ # if not hasattr(settings, 'ENDOREG_CENTER_ID'):
12
+ # ENDOREG_CENTER_ID = 9999
13
+ # else:
14
+ # ENDOREG_CENTER_ID = settings.ENDOREG_CENTER_ID
15
+
16
+ class PdfType(models.Model):
17
+ name = models.CharField(max_length=255)
18
+
19
+ patient_info_line = models.ForeignKey(
20
+ "ReportReaderFlag",
21
+ related_name="pdf_type_patient_info_line",
22
+ on_delete=models.CASCADE
23
+ )
24
+ endoscope_info_line = models.ForeignKey(
25
+ "ReportReaderFlag",
26
+ related_name="pdf_type_endoscopy_info_line",
27
+ on_delete=models.CASCADE,
28
+ )
29
+ examiner_info_line = models.ForeignKey(
30
+ "ReportReaderFlag",
31
+ related_name="pdf_type_examiner_info_line",
32
+ on_delete=models.CASCADE
33
+ )
34
+ cut_off_above_lines = models.ManyToManyField(
35
+ "ReportReaderFlag",
36
+ related_name="pdf_type_cut_off_above_lines",
37
+ )
38
+ cut_off_below_lines = models.ManyToManyField(
39
+ "ReportReaderFlag",
40
+ related_name="pdf_type_cut_off_below_lines",
41
+ )
42
+
43
+
44
+ def __str__(self):
45
+ summary = f"{self.name}"
46
+ # add lines to summary
47
+ summary += f"\nPatient Info Line: {self.patient_info_line.value}"
48
+ summary += f"\nEndoscope Info Line: {self.endoscope_info_line.value}"
49
+ summary += f"\nExaminer Info Line: {self.examiner_info_line.value}"
50
+ summary += f"\nCut Off Above Lines: {[_.value for _ in self.cut_off_above_lines.all()]}"
51
+ summary += f"\nCut Off Below Lines: {[_.value for _ in self.cut_off_below_lines.all()]}"
52
+
53
+ return summary
54
+
55
+ @classmethod
56
+ def default_pdf_type(cls):
57
+ return PdfType.objects.get(name="ukw-endoscopy-examination-report-generic")
58
+
59
+ class PdfMeta(models.Model):
60
+ pdf_type = models.ForeignKey(PdfType, on_delete=models.CASCADE)
61
+ date = models.DateField()
62
+ time = models.TimeField()
63
+ pdf_hash = models.CharField(max_length=255, unique=True)
64
+
65
+ def __str__(self):
66
+ return self.pdf_hash
67
+
68
+ @classmethod
69
+ def create_from_file(cls, pdf_file):
70
+ pdf_file = File(pdf_file)
71
+ pdf_meta = cls(file=pdf_file)
72
+ pdf_meta.save()
73
+ return pdf_meta
74
+