endoreg-db 0.8.6.1__py3-none-any.whl → 0.8.8.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of endoreg-db might be problematic. Click here for more details.

Files changed (503) hide show
  1. endoreg_db/authz/auth.py +74 -0
  2. endoreg_db/authz/backends.py +168 -0
  3. endoreg_db/authz/management/commands/list_routes.py +18 -0
  4. endoreg_db/authz/middleware.py +83 -0
  5. endoreg_db/authz/permissions.py +127 -0
  6. endoreg_db/authz/policy.py +218 -0
  7. endoreg_db/authz/views_auth.py +66 -0
  8. endoreg_db/config/env.py +13 -8
  9. endoreg_db/data/__init__.py +2 -11
  10. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +3 -3
  11. endoreg_db/data/event_classification/data.yaml +4 -0
  12. endoreg_db/data/event_classification_choice/data.yaml +9 -0
  13. endoreg_db/data/examination/examinations/data.yaml +114 -14
  14. endoreg_db/data/examination/time-type/data.yaml +0 -3
  15. endoreg_db/data/examination_indication/endoscopy.yaml +108 -173
  16. endoreg_db/data/examination_indication_classification/endoscopy.yaml +0 -70
  17. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +33 -37
  18. endoreg_db/data/finding/00_generic.yaml +35 -0
  19. endoreg_db/data/finding/00_generic_complication.yaml +9 -0
  20. endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
  21. endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
  22. endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
  23. endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
  24. endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
  25. endoreg_db/data/finding_classification/00_generic.yaml +44 -0
  26. endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
  27. endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
  28. endoreg_db/data/finding_classification/02_colonoscopy_baseline.yaml +83 -0
  29. endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
  30. endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
  31. endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
  32. endoreg_db/data/finding_classification_choice/{yes_no_na.yaml → 00_generic.yaml} +5 -1
  33. endoreg_db/data/finding_classification_choice/{examination_setting_generic_types.yaml → 00_generic_baseline.yaml} +10 -2
  34. endoreg_db/data/finding_classification_choice/{complication_generic_types.yaml → 00_generic_complication.yaml} +1 -1
  35. endoreg_db/data/finding_classification_choice/{histology.yaml → 00_generic_histology.yaml} +1 -4
  36. endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
  37. endoreg_db/data/finding_classification_choice/{bowel_preparation.yaml → 02_colonoscopy_bowel_preparation.yaml} +1 -30
  38. endoreg_db/data/finding_classification_choice/{colonoscopy_not_complete_reason.yaml → 02_colonoscopy_generic.yaml} +1 -1
  39. endoreg_db/data/finding_classification_choice/{histology_polyp.yaml → 02_colonoscopy_histology.yaml} +1 -1
  40. endoreg_db/data/finding_classification_choice/{colonoscopy_location.yaml → 02_colonoscopy_location.yaml} +23 -4
  41. endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
  42. endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
  43. endoreg_db/data/finding_classification_choice/{colon_lesion_paris.yaml → 02_colonoscopy_polyp_morphology.yaml} +26 -8
  44. endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
  45. endoreg_db/data/finding_classification_type/{colonoscopy_basic.yaml → 00_generic.yaml} +18 -13
  46. endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
  47. endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
  48. endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
  49. endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
  50. endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
  51. endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
  52. endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
  53. endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
  54. endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
  55. endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
  56. endoreg_db/data/finding_type/data.yaml +8 -12
  57. endoreg_db/data/requirement/01_patient_data.yaml +93 -0
  58. endoreg_db/data/requirement/old/colon_polyp_intervention.yaml +49 -0
  59. endoreg_db/data/requirement/old/coloreg_colon_polyp.yaml +49 -0
  60. endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
  61. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +29 -12
  62. endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
  63. endoreg_db/data/requirement_set/{endoscopy_bleeding_risk.yaml → 02_endoscopy_bleeding_risk.yaml} +0 -6
  64. endoreg_db/data/requirement_set/90_coloreg.yaml +190 -0
  65. endoreg_db/data/requirement_set/_old_ +109 -0
  66. endoreg_db/data/requirement_set_type/data.yaml +21 -0
  67. endoreg_db/data/setup_config.yaml +4 -4
  68. endoreg_db/data/tag/requirement_set_tags.yaml +21 -0
  69. endoreg_db/exceptions.py +4 -2
  70. endoreg_db/forms/examination_form.py +1 -1
  71. endoreg_db/helpers/data_loader.py +125 -53
  72. endoreg_db/helpers/default_objects.py +116 -81
  73. endoreg_db/import_files/__init__.py +27 -0
  74. endoreg_db/import_files/context/__init__.py +7 -0
  75. endoreg_db/import_files/context/default_sensitive_meta.py +81 -0
  76. endoreg_db/import_files/context/ensure_center.py +17 -0
  77. endoreg_db/import_files/context/file_lock.py +66 -0
  78. endoreg_db/import_files/context/import_context.py +43 -0
  79. endoreg_db/import_files/context/validate_directories.py +56 -0
  80. endoreg_db/import_files/file_storage/__init__.py +15 -0
  81. endoreg_db/import_files/file_storage/create_report_file.py +76 -0
  82. endoreg_db/import_files/file_storage/create_video_file.py +75 -0
  83. endoreg_db/import_files/file_storage/sensitive_meta_storage.py +39 -0
  84. endoreg_db/import_files/file_storage/state_management.py +400 -0
  85. endoreg_db/import_files/file_storage/storage.py +36 -0
  86. endoreg_db/import_files/import_service.md +26 -0
  87. endoreg_db/import_files/processing/__init__.py +11 -0
  88. endoreg_db/import_files/processing/report_processing/report_anonymization.py +94 -0
  89. endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
  90. endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
  91. endoreg_db/import_files/processing/video_processing/video_cleanup_on_error.py +119 -0
  92. endoreg_db/import_files/pseudonymization/fake.py +52 -0
  93. endoreg_db/import_files/pseudonymization/k_anonymity.py +182 -0
  94. endoreg_db/import_files/pseudonymization/k_pseudonymity.py +128 -0
  95. endoreg_db/import_files/report_import_service.py +141 -0
  96. endoreg_db/import_files/video_import_service.py +150 -0
  97. endoreg_db/management/commands/create_model_meta_from_huggingface.py +21 -10
  98. endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
  99. endoreg_db/management/commands/import_report.py +130 -65
  100. endoreg_db/management/commands/import_video.py +9 -10
  101. endoreg_db/management/commands/import_video_with_classification.py +2 -2
  102. endoreg_db/management/commands/list_routes.py +18 -0
  103. endoreg_db/management/commands/load_ai_model_data.py +5 -5
  104. endoreg_db/management/commands/load_ai_model_label_data.py +9 -7
  105. endoreg_db/management/commands/load_base_db_data.py +5 -134
  106. endoreg_db/management/commands/load_center_data.py +12 -12
  107. endoreg_db/management/commands/load_contraindication_data.py +14 -16
  108. endoreg_db/management/commands/load_disease_classification_choices_data.py +15 -18
  109. endoreg_db/management/commands/load_disease_classification_data.py +15 -18
  110. endoreg_db/management/commands/load_disease_data.py +25 -28
  111. endoreg_db/management/commands/load_endoscope_data.py +20 -27
  112. endoreg_db/management/commands/load_event_data.py +14 -16
  113. endoreg_db/management/commands/load_examination_data.py +31 -44
  114. endoreg_db/management/commands/load_examination_indication_data.py +20 -21
  115. endoreg_db/management/commands/load_finding_data.py +52 -80
  116. endoreg_db/management/commands/load_information_source.py +21 -23
  117. endoreg_db/management/commands/load_lab_value_data.py +17 -26
  118. endoreg_db/management/commands/load_medication_data.py +13 -12
  119. endoreg_db/management/commands/load_organ_data.py +15 -19
  120. endoreg_db/management/commands/load_pdf_type_data.py +19 -18
  121. endoreg_db/management/commands/load_profession_data.py +14 -17
  122. endoreg_db/management/commands/load_qualification_data.py +20 -23
  123. endoreg_db/management/commands/load_report_reader_flag_data.py +17 -19
  124. endoreg_db/management/commands/load_requirement_data.py +62 -39
  125. endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
  126. endoreg_db/management/commands/load_risk_data.py +7 -6
  127. endoreg_db/management/commands/load_shift_data.py +20 -23
  128. endoreg_db/management/commands/load_tag_data.py +8 -11
  129. endoreg_db/management/commands/load_unit_data.py +17 -19
  130. endoreg_db/management/commands/setup_endoreg_db.py +3 -3
  131. endoreg_db/management/commands/start_filewatcher.py +46 -37
  132. endoreg_db/management/commands/storage_management.py +271 -203
  133. endoreg_db/management/commands/validate_video_files.py +1 -5
  134. endoreg_db/migrations/0001_initial.py +297 -250
  135. endoreg_db/models/__init__.py +78 -123
  136. endoreg_db/models/administration/__init__.py +21 -42
  137. endoreg_db/models/administration/ai/active_model.py +2 -2
  138. endoreg_db/models/administration/ai/ai_model.py +7 -6
  139. endoreg_db/models/administration/case/__init__.py +1 -15
  140. endoreg_db/models/administration/case/case.py +3 -3
  141. endoreg_db/models/administration/case/case_template/__init__.py +2 -14
  142. endoreg_db/models/administration/case/case_template/case_template.py +2 -124
  143. endoreg_db/models/administration/case/case_template/case_template_rule.py +2 -268
  144. endoreg_db/models/administration/case/case_template/case_template_rule_value.py +2 -85
  145. endoreg_db/models/administration/case/case_template/case_template_type.py +2 -25
  146. endoreg_db/models/administration/center/center.py +33 -19
  147. endoreg_db/models/administration/center/center_product.py +12 -9
  148. endoreg_db/models/administration/center/center_resource.py +25 -19
  149. endoreg_db/models/administration/center/center_shift.py +21 -17
  150. endoreg_db/models/administration/center/center_waste.py +16 -8
  151. endoreg_db/models/administration/person/__init__.py +2 -0
  152. endoreg_db/models/administration/person/employee/employee.py +10 -5
  153. endoreg_db/models/administration/person/employee/employee_qualification.py +9 -4
  154. endoreg_db/models/administration/person/employee/employee_type.py +12 -6
  155. endoreg_db/models/administration/person/examiner/examiner.py +13 -11
  156. endoreg_db/models/administration/person/patient/__init__.py +2 -0
  157. endoreg_db/models/administration/person/patient/patient.py +129 -100
  158. endoreg_db/models/administration/person/patient/patient_external_id.py +37 -0
  159. endoreg_db/models/administration/person/person.py +4 -0
  160. endoreg_db/models/administration/person/profession/__init__.py +8 -4
  161. endoreg_db/models/administration/person/user/portal_user_information.py +11 -7
  162. endoreg_db/models/administration/product/product.py +20 -15
  163. endoreg_db/models/administration/product/product_material.py +17 -18
  164. endoreg_db/models/administration/product/product_weight.py +12 -8
  165. endoreg_db/models/administration/product/reference_product.py +23 -55
  166. endoreg_db/models/administration/qualification/qualification.py +7 -3
  167. endoreg_db/models/administration/qualification/qualification_type.py +7 -3
  168. endoreg_db/models/administration/shift/scheduled_days.py +8 -5
  169. endoreg_db/models/administration/shift/shift.py +16 -12
  170. endoreg_db/models/administration/shift/shift_type.py +23 -31
  171. endoreg_db/models/label/__init__.py +8 -9
  172. endoreg_db/models/label/annotation/image_classification.py +10 -9
  173. endoreg_db/models/label/annotation/video_segmentation_annotation.py +23 -28
  174. endoreg_db/models/label/label.py +15 -15
  175. endoreg_db/models/label/label_set.py +19 -6
  176. endoreg_db/models/label/label_type.py +1 -1
  177. endoreg_db/models/label/label_video_segment/_create_from_video.py +5 -8
  178. endoreg_db/models/label/label_video_segment/label_video_segment.py +98 -102
  179. endoreg_db/models/label/video_segmentation_label.py +4 -0
  180. endoreg_db/models/label/video_segmentation_labelset.py +4 -3
  181. endoreg_db/models/media/frame/frame.py +22 -22
  182. endoreg_db/models/media/pdf/raw_pdf.py +194 -194
  183. endoreg_db/models/media/pdf/report_file.py +25 -29
  184. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +55 -47
  185. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
  186. endoreg_db/models/media/processing_history/__init__.py +5 -0
  187. endoreg_db/models/media/processing_history/processing_history.py +96 -0
  188. endoreg_db/models/media/video/__init__.py +1 -0
  189. endoreg_db/models/media/video/create_from_file.py +139 -77
  190. endoreg_db/models/media/video/pipe_2.py +8 -9
  191. endoreg_db/models/media/video/video_file.py +174 -112
  192. endoreg_db/models/media/video/video_file_ai.py +288 -74
  193. endoreg_db/models/media/video/video_file_anonymize.py +38 -38
  194. endoreg_db/models/media/video/video_file_frames/__init__.py +3 -1
  195. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -8
  196. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +7 -9
  197. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +9 -8
  198. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +38 -45
  199. endoreg_db/models/media/video/video_file_frames/_get_frame.py +6 -8
  200. endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +4 -18
  201. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -3
  202. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +7 -6
  203. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +6 -8
  204. endoreg_db/models/media/video/video_file_frames/_get_frames.py +6 -8
  205. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +15 -25
  206. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +26 -23
  207. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +23 -14
  208. endoreg_db/models/media/video/video_file_io.py +113 -61
  209. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +3 -3
  210. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +5 -3
  211. endoreg_db/models/media/video/video_file_meta/get_fps.py +37 -34
  212. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +19 -25
  213. endoreg_db/models/media/video/video_file_meta/text_meta.py +41 -38
  214. endoreg_db/models/media/video/video_file_meta/video_meta.py +14 -7
  215. endoreg_db/models/media/video/video_file_segments.py +24 -17
  216. endoreg_db/models/media/video/video_metadata.py +19 -35
  217. endoreg_db/models/media/video/video_processing.py +96 -95
  218. endoreg_db/models/medical/contraindication/README.md +1 -0
  219. endoreg_db/models/medical/contraindication/__init__.py +13 -3
  220. endoreg_db/models/medical/disease.py +22 -16
  221. endoreg_db/models/medical/event.py +31 -18
  222. endoreg_db/models/medical/examination/__init__.py +13 -6
  223. endoreg_db/models/medical/examination/examination.py +39 -20
  224. endoreg_db/models/medical/examination/examination_indication.py +30 -95
  225. endoreg_db/models/medical/examination/examination_time.py +23 -8
  226. endoreg_db/models/medical/examination/examination_time_type.py +9 -6
  227. endoreg_db/models/medical/examination/examination_type.py +3 -4
  228. endoreg_db/models/medical/finding/finding.py +32 -40
  229. endoreg_db/models/medical/finding/finding_classification.py +42 -72
  230. endoreg_db/models/medical/finding/finding_intervention.py +25 -22
  231. endoreg_db/models/medical/finding/finding_type.py +13 -12
  232. endoreg_db/models/medical/hardware/endoscope.py +26 -26
  233. endoreg_db/models/medical/hardware/endoscopy_processor.py +2 -2
  234. endoreg_db/models/medical/laboratory/lab_value.py +62 -91
  235. endoreg_db/models/medical/medication/medication.py +22 -10
  236. endoreg_db/models/medical/medication/medication_indication.py +29 -3
  237. endoreg_db/models/medical/medication/medication_indication_type.py +25 -14
  238. endoreg_db/models/medical/medication/medication_intake_time.py +31 -19
  239. endoreg_db/models/medical/medication/medication_schedule.py +27 -16
  240. endoreg_db/models/medical/organ/__init__.py +15 -12
  241. endoreg_db/models/medical/patient/medication_examples.py +6 -6
  242. endoreg_db/models/medical/patient/patient_disease.py +20 -23
  243. endoreg_db/models/medical/patient/patient_event.py +19 -22
  244. endoreg_db/models/medical/patient/patient_examination.py +48 -54
  245. endoreg_db/models/medical/patient/patient_examination_indication.py +16 -14
  246. endoreg_db/models/medical/patient/patient_finding.py +122 -139
  247. endoreg_db/models/medical/patient/patient_finding_classification.py +44 -49
  248. endoreg_db/models/medical/patient/patient_finding_intervention.py +8 -19
  249. endoreg_db/models/medical/patient/patient_lab_sample.py +28 -23
  250. endoreg_db/models/medical/patient/patient_lab_value.py +82 -89
  251. endoreg_db/models/medical/patient/patient_medication.py +27 -38
  252. endoreg_db/models/medical/patient/patient_medication_schedule.py +28 -36
  253. endoreg_db/models/medical/risk/risk.py +7 -6
  254. endoreg_db/models/medical/risk/risk_type.py +8 -5
  255. endoreg_db/models/metadata/model_meta.py +60 -29
  256. endoreg_db/models/metadata/model_meta_logic.py +125 -18
  257. endoreg_db/models/metadata/pdf_meta.py +31 -24
  258. endoreg_db/models/metadata/sensitive_meta.py +105 -85
  259. endoreg_db/models/metadata/sensitive_meta_logic.py +198 -103
  260. endoreg_db/models/metadata/video_meta.py +51 -31
  261. endoreg_db/models/metadata/video_prediction_logic.py +16 -23
  262. endoreg_db/models/metadata/video_prediction_meta.py +29 -33
  263. endoreg_db/models/other/distribution/date_value_distribution.py +89 -29
  264. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +21 -5
  265. endoreg_db/models/other/distribution/numeric_value_distribution.py +114 -53
  266. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +4 -3
  267. endoreg_db/models/other/emission/emission_factor.py +18 -8
  268. endoreg_db/models/other/gender.py +10 -5
  269. endoreg_db/models/other/information_source.py +50 -29
  270. endoreg_db/models/other/material.py +9 -5
  271. endoreg_db/models/other/resource.py +6 -4
  272. endoreg_db/models/other/tag.py +10 -5
  273. endoreg_db/models/other/transport_route.py +13 -8
  274. endoreg_db/models/other/unit.py +10 -6
  275. endoreg_db/models/other/waste.py +6 -5
  276. endoreg_db/models/report/report.py +6 -0
  277. endoreg_db/models/requirement/requirement.py +329 -361
  278. endoreg_db/models/requirement/requirement_error.py +85 -0
  279. endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
  280. endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +3 -6
  281. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +90 -64
  282. endoreg_db/models/requirement/requirement_operator.py +103 -112
  283. endoreg_db/models/requirement/requirement_set.py +74 -57
  284. endoreg_db/models/state/__init__.py +4 -4
  285. endoreg_db/models/state/abstract.py +2 -2
  286. endoreg_db/models/state/anonymization.py +12 -0
  287. endoreg_db/models/state/audit_ledger.py +49 -51
  288. endoreg_db/models/state/label_video_segment.py +9 -0
  289. endoreg_db/models/state/raw_pdf.py +101 -68
  290. endoreg_db/models/state/sensitive_meta.py +6 -2
  291. endoreg_db/models/state/video.py +110 -90
  292. endoreg_db/models/upload_job.py +35 -34
  293. endoreg_db/models/utils.py +28 -25
  294. endoreg_db/queries/__init__.py +3 -1
  295. endoreg_db/root_urls.py +21 -2
  296. endoreg_db/schemas/examination_evaluation.py +1 -1
  297. endoreg_db/serializers/__init__.py +2 -10
  298. endoreg_db/serializers/anonymization.py +18 -10
  299. endoreg_db/serializers/label_video_segment/label_video_segment.py +2 -29
  300. endoreg_db/serializers/meta/__init__.py +1 -6
  301. endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
  302. endoreg_db/serializers/misc/file_overview.py +11 -99
  303. endoreg_db/serializers/misc/sensitive_patient_data.py +50 -26
  304. endoreg_db/serializers/patient_examination/patient_examination.py +3 -3
  305. endoreg_db/serializers/pdf/anony_text_validation.py +39 -23
  306. endoreg_db/serializers/requirements/requirement_sets.py +92 -22
  307. endoreg_db/serializers/video/segmentation.py +2 -1
  308. endoreg_db/serializers/video/video_file_list.py +65 -34
  309. endoreg_db/serializers/video/video_processing_history.py +20 -5
  310. endoreg_db/services/__old/pdf_import.py +1487 -0
  311. endoreg_db/services/__old/video_import.py +1306 -0
  312. endoreg_db/services/anonymization.py +128 -89
  313. endoreg_db/services/lookup_service.py +65 -52
  314. endoreg_db/services/lookup_store.py +2 -2
  315. endoreg_db/services/pdf_import.py +0 -1382
  316. endoreg_db/services/report_import.py +10 -0
  317. endoreg_db/services/video_import.py +6 -1255
  318. endoreg_db/tasks/upload_tasks.py +79 -70
  319. endoreg_db/tasks/video_ingest.py +8 -4
  320. endoreg_db/urls/__init__.py +5 -32
  321. endoreg_db/urls/ai.py +32 -0
  322. endoreg_db/urls/media.py +121 -83
  323. endoreg_db/urls/root_urls.py +29 -0
  324. endoreg_db/utils/__init__.py +15 -5
  325. endoreg_db/utils/ai/multilabel_classification_net.py +116 -20
  326. endoreg_db/utils/case_generator/__init__.py +3 -0
  327. endoreg_db/utils/dataloader.py +142 -40
  328. endoreg_db/utils/defaults/set_default_center.py +32 -0
  329. endoreg_db/utils/names.py +22 -16
  330. endoreg_db/utils/paths.py +110 -46
  331. endoreg_db/utils/permissions.py +2 -1
  332. endoreg_db/utils/pipelines/Readme.md +1 -1
  333. endoreg_db/utils/pipelines/process_video_dir.py +1 -1
  334. endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +655 -0
  335. endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +97 -0
  336. endoreg_db/utils/setup_config.py +8 -5
  337. endoreg_db/utils/storage.py +115 -0
  338. endoreg_db/utils/validate_endo_roi.py +8 -2
  339. endoreg_db/utils/video/ffmpeg_wrapper.py +184 -188
  340. endoreg_db/views/__init__.py +85 -183
  341. endoreg_db/views/ai/__init__.py +8 -0
  342. endoreg_db/views/ai/label.py +155 -0
  343. endoreg_db/views/anonymization/media_management.py +202 -166
  344. endoreg_db/views/anonymization/overview.py +99 -67
  345. endoreg_db/views/anonymization/validate.py +182 -44
  346. endoreg_db/views/media/__init__.py +7 -20
  347. endoreg_db/views/media/pdf_media.py +197 -174
  348. endoreg_db/views/media/sensitive_metadata.py +193 -138
  349. endoreg_db/views/media/video_media.py +89 -82
  350. endoreg_db/views/meta/__init__.py +0 -8
  351. endoreg_db/views/misc/__init__.py +1 -7
  352. endoreg_db/views/misc/upload_views.py +94 -93
  353. endoreg_db/views/patient/patient.py +5 -4
  354. endoreg_db/views/report/__init__.py +5 -7
  355. endoreg_db/views/{pdf → report}/reimport.py +22 -22
  356. endoreg_db/views/{pdf/pdf_stream.py → report/report_stream.py} +46 -39
  357. endoreg_db/views/requirement/evaluate.py +188 -187
  358. endoreg_db/views/requirement/lookup.py +17 -3
  359. endoreg_db/views/requirement/lookup_store.py +22 -90
  360. endoreg_db/views/requirement/requirement_utils.py +89 -0
  361. endoreg_db/views/video/__init__.py +23 -24
  362. endoreg_db/views/video/correction.py +201 -172
  363. endoreg_db/views/video/reimport.py +1 -1
  364. endoreg_db/views/{media/video_segments.py → video/segments_crud.py} +77 -40
  365. endoreg_db/views/video/{video_meta.py → video_meta_stats.py} +2 -2
  366. endoreg_db/views/video/video_stream.py +7 -8
  367. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/METADATA +7 -3
  368. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/RECORD +391 -413
  369. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/WHEEL +1 -1
  370. endoreg_db/data/finding/anatomy_colon.yaml +0 -128
  371. endoreg_db/data/finding/colonoscopy.yaml +0 -40
  372. endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +0 -56
  373. endoreg_db/data/finding/complication.yaml +0 -16
  374. endoreg_db/data/finding/data.yaml +0 -105
  375. endoreg_db/data/finding/examination_setting.yaml +0 -16
  376. endoreg_db/data/finding/medication_related.yaml +0 -18
  377. endoreg_db/data/finding/outcome.yaml +0 -12
  378. endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +0 -95
  379. endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +0 -22
  380. endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +0 -25
  381. endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
  382. endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
  383. endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +0 -68
  384. endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
  385. endoreg_db/data/finding_classification/colonoscopy_location.yaml +0 -80
  386. endoreg_db/data/finding_classification/colonoscopy_lst.yaml +0 -21
  387. endoreg_db/data/finding_classification/colonoscopy_nice.yaml +0 -20
  388. endoreg_db/data/finding_classification/colonoscopy_paris.yaml +0 -26
  389. endoreg_db/data/finding_classification/colonoscopy_sano.yaml +0 -22
  390. endoreg_db/data/finding_classification/colonoscopy_summary.yaml +0 -53
  391. endoreg_db/data/finding_classification/complication_generic.yaml +0 -25
  392. endoreg_db/data/finding_classification/examination_setting_generic.yaml +0 -40
  393. endoreg_db/data/finding_classification/histology_colo.yaml +0 -51
  394. endoreg_db/data/finding_classification/intervention_required.yaml +0 -26
  395. endoreg_db/data/finding_classification/medication_related.yaml +0 -23
  396. endoreg_db/data/finding_classification/visualized.yaml +0 -33
  397. endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
  398. endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
  399. endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
  400. endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +0 -15
  401. endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +0 -17
  402. endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
  403. endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +0 -14
  404. endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
  405. endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +0 -82
  406. endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
  407. endoreg_db/data/finding_classification_choice/outcome.yaml +0 -19
  408. endoreg_db/data/finding_intervention/endoscopy.yaml +0 -43
  409. endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
  410. endoreg_db/data/finding_intervention/endoscopy_egd.yaml +0 -128
  411. endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +0 -32
  412. endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +0 -9
  413. endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +0 -36
  414. endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +0 -79
  415. endoreg_db/data/requirement/age.yaml +0 -26
  416. endoreg_db/data/requirement/gender.yaml +0 -25
  417. endoreg_db/management/commands/init_default_ai_model.py +0 -112
  418. endoreg_db/management/commands/reset_celery_schedule.py +0 -9
  419. endoreg_db/management/commands/validate_video.py +0 -204
  420. endoreg_db/migrations/0002_add_video_correction_models.py +0 -52
  421. endoreg_db/migrations/0003_add_center_display_name.py +0 -30
  422. endoreg_db/models/administration/permissions/__init__.py +0 -44
  423. endoreg_db/models/rule/__init__.py +0 -13
  424. endoreg_db/models/rule/rule.py +0 -27
  425. endoreg_db/models/rule/rule_applicator.py +0 -224
  426. endoreg_db/models/rule/rule_attribute_dtype.py +0 -17
  427. endoreg_db/models/rule/rule_type.py +0 -20
  428. endoreg_db/models/rule/ruleset.py +0 -17
  429. endoreg_db/renames.yml +0 -8
  430. endoreg_db/serializers/_old/raw_pdf_meta_validation.py +0 -223
  431. endoreg_db/serializers/_old/raw_video_meta_validation.py +0 -179
  432. endoreg_db/serializers/_old/video.py +0 -71
  433. endoreg_db/serializers/meta/pdf_file_meta_extraction.py +0 -115
  434. endoreg_db/serializers/meta/report_meta.py +0 -53
  435. endoreg_db/serializers/report/__init__.py +0 -9
  436. endoreg_db/serializers/report/mixins.py +0 -45
  437. endoreg_db/serializers/report/report.py +0 -105
  438. endoreg_db/serializers/report/report_list.py +0 -22
  439. endoreg_db/serializers/report/secure_file_url.py +0 -26
  440. endoreg_db/serializers/video/video_metadata.py +0 -105
  441. endoreg_db/services/requirements_object.py +0 -147
  442. endoreg_db/services/storage_aware_video_processor.py +0 -344
  443. endoreg_db/urls/files.py +0 -6
  444. endoreg_db/urls/label_video_segment_validate.py +0 -33
  445. endoreg_db/urls/label_video_segments.py +0 -46
  446. endoreg_db/urls/report.py +0 -48
  447. endoreg_db/urls/video.py +0 -61
  448. endoreg_db/utils/case_generator/case_generator.py +0 -159
  449. endoreg_db/utils/case_generator/utils.py +0 -30
  450. endoreg_db/utils/requirement_operator_logic/model_evaluators.py +0 -368
  451. endoreg_db/views/label/__init__.py +0 -5
  452. endoreg_db/views/label/label.py +0 -15
  453. endoreg_db/views/label_video_segment/__init__.py +0 -16
  454. endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +0 -44
  455. endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +0 -50
  456. endoreg_db/views/label_video_segment/label_video_segment.py +0 -77
  457. endoreg_db/views/label_video_segment/label_video_segment_by_label.py +0 -174
  458. endoreg_db/views/label_video_segment/label_video_segment_detail.py +0 -73
  459. endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +0 -46
  460. endoreg_db/views/label_video_segment/validate.py +0 -226
  461. endoreg_db/views/media/segments.py +0 -71
  462. endoreg_db/views/meta/available_files_list.py +0 -146
  463. endoreg_db/views/meta/report_meta.py +0 -53
  464. endoreg_db/views/meta/sensitive_meta_detail.py +0 -148
  465. endoreg_db/views/misc/secure_file_serving_view.py +0 -80
  466. endoreg_db/views/misc/secure_file_url_view.py +0 -84
  467. endoreg_db/views/misc/secure_url_validate.py +0 -79
  468. endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +0 -164
  469. endoreg_db/views/patient_finding_location/__init__.py +0 -5
  470. endoreg_db/views/patient_finding_location/pfl_create.py +0 -70
  471. endoreg_db/views/patient_finding_morphology/__init__.py +0 -5
  472. endoreg_db/views/patient_finding_morphology/pfm_create.py +0 -70
  473. endoreg_db/views/pdf/__init__.py +0 -8
  474. endoreg_db/views/report/report_list.py +0 -112
  475. endoreg_db/views/report/report_with_secure_url.py +0 -28
  476. endoreg_db/views/report/start_examination.py +0 -7
  477. endoreg_db/views/video/segmentation.py +0 -274
  478. endoreg_db/views/video/task_status.py +0 -49
  479. endoreg_db/views/video/timeline.py +0 -46
  480. endoreg_db/views/video/video_analyze.py +0 -52
  481. endoreg_db/views.py +0 -0
  482. /endoreg_db/data/requirement/{colonoscopy_baseline_austria.yaml → old/colonoscopy_baseline_austria.yaml} +0 -0
  483. /endoreg_db/data/requirement/{disease_cardiovascular.yaml → old/disease_cardiovascular.yaml} +0 -0
  484. /endoreg_db/data/requirement/{disease_classification_choice_cardiovascular.yaml → old/disease_classification_choice_cardiovascular.yaml} +0 -0
  485. /endoreg_db/data/requirement/{disease_hepatology.yaml → old/disease_hepatology.yaml} +0 -0
  486. /endoreg_db/data/requirement/{disease_misc.yaml → old/disease_misc.yaml} +0 -0
  487. /endoreg_db/data/requirement/{disease_renal.yaml → old/disease_renal.yaml} +0 -0
  488. /endoreg_db/data/requirement/{endoscopy_bleeding_risk.yaml → old/endoscopy_bleeding_risk.yaml} +0 -0
  489. /endoreg_db/data/requirement/{event_cardiology.yaml → old/event_cardiology.yaml} +0 -0
  490. /endoreg_db/data/requirement/{event_requirements.yaml → old/event_requirements.yaml} +0 -0
  491. /endoreg_db/data/requirement/{finding_colon_polyp.yaml → old/finding_colon_polyp.yaml} +0 -0
  492. /endoreg_db/{migrations/__init__.py → data/requirement/old/gender.yaml} +0 -0
  493. /endoreg_db/data/requirement/{lab_value.yaml → old/lab_value.yaml} +0 -0
  494. /endoreg_db/data/requirement/{medication.yaml → old/medication.yaml} +0 -0
  495. /endoreg_db/data/requirement_operator/{age.yaml → _old/age.yaml} +0 -0
  496. /endoreg_db/data/requirement_operator/{lab_operators.yaml → _old/lab_operators.yaml} +0 -0
  497. /endoreg_db/data/requirement_operator/{model_operators.yaml → _old/model_operators.yaml} +0 -0
  498. /endoreg_db/{models/media/video/refactor_plan.md → import_files/pseudonymization/__init__.py} +0 -0
  499. /endoreg_db/{models/media/video/video_file_frames.py → import_files/pseudonymization/pseudonymize.py} +0 -0
  500. /endoreg_db/models/{metadata/frame_ocr_result.py → report/__init__.py} +0 -0
  501. /endoreg_db/{urls/sensitive_meta.py → models/report/images.py} +0 -0
  502. /endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py} +0 -0
  503. {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/licenses/LICENSE +0 -0
@@ -1,226 +0,0 @@
1
- from rest_framework import status
2
- from rest_framework.response import Response
3
- from rest_framework.views import APIView
4
- from django.db import transaction
5
- from endoreg_db.models import LabelVideoSegment, VideoFile
6
- from endoreg_db.utils.permissions import DEBUG_PERMISSIONS
7
-
8
-
9
- class LabelVideoSegmentValidateView(APIView):
10
- """
11
- POST /api/label-video-segment/<int:segment_id>/validate/
12
-
13
- Validiert ein einzelnes LabelVideoSegment und markiert es als verifiziert.
14
- Dies wird verwendet, um vom Benutzer überprüfte Segment-Annotationen zu bestätigen.
15
-
16
- Body (optional):
17
- {
18
- "is_validated": true, // optional, default true
19
- "notes": "..." // optional, Validierungsnotizen
20
- }
21
- """
22
- permission_classes = DEBUG_PERMISSIONS
23
-
24
- @transaction.atomic
25
- def post(self, request, segment_id: int):
26
- try:
27
- # Segment abrufen
28
- segment = LabelVideoSegment.objects.select_related('state', 'video_file', 'label').get(pk=segment_id)
29
-
30
- # Validierungsstatus aus Request (default: True)
31
- is_validated = request.data.get('is_validated', True)
32
- notes = request.data.get('notes', '')
33
-
34
- # State-Objekt abrufen oder erstellen
35
- if not hasattr(segment, 'state') or segment.state is None:
36
- # State muss existieren - wenn nicht, könnte ein Model-Problem vorliegen
37
- return Response({
38
- "error": "Segment has no state object. Cannot validate."
39
- }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
40
-
41
- # State aktualisieren
42
- segment.state.is_validated = is_validated
43
- if notes:
44
- # Falls ein notes-Feld existiert
45
- if hasattr(segment.state, 'validation_notes'):
46
- segment.state.validation_notes = notes
47
- segment.state.save()
48
-
49
- return Response({
50
- "message": f"Segment {segment_id} validation status updated.",
51
- "segment_id": segment_id,
52
- "is_validated": is_validated,
53
- "label": segment.label.name if segment.label else None,
54
- "video_id": segment.video_file.id if segment.video_file else None,
55
- "start_frame": segment.start_frame_number,
56
- "end_frame": segment.end_frame_number
57
- }, status=status.HTTP_200_OK)
58
-
59
- except LabelVideoSegment.DoesNotExist:
60
- return Response({
61
- "error": f"Segment {segment_id} not found."
62
- }, status=status.HTTP_404_NOT_FOUND)
63
- except Exception as e:
64
- import logging
65
- logger = logging.getLogger(__name__)
66
- logger.error(f"Error validating segment {segment_id}: {e}")
67
- return Response({
68
- "error": f"Validation failed: {str(e)}"
69
- }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
70
-
71
-
72
- class BulkSegmentValidateView(APIView):
73
- """
74
- POST /api/label-video-segments/validate-bulk/
75
-
76
- Validiert mehrere LabelVideoSegments gleichzeitig.
77
- Nützlich für Batch-Validierung nach Review.
78
-
79
- Body:
80
- {
81
- "segment_ids": [1, 2, 3, ...],
82
- "is_validated": true, // optional, default true
83
- "notes": "..." // optional, gilt für alle Segmente
84
- }
85
- """
86
- permission_classes = DEBUG_PERMISSIONS
87
-
88
- @transaction.atomic
89
- def post(self, request):
90
- segment_ids = request.data.get('segment_ids', [])
91
- is_validated = request.data.get('is_validated', True)
92
- notes = request.data.get('notes', '')
93
-
94
- if not segment_ids:
95
- return Response({
96
- "error": "segment_ids is required"
97
- }, status=status.HTTP_400_BAD_REQUEST)
98
-
99
- try:
100
- # Alle Segmente abrufen
101
- segments = LabelVideoSegment.objects.filter(pk__in=segment_ids).select_related('state')
102
-
103
- if not segments.exists():
104
- return Response({
105
- "error": "No segments found with provided IDs"
106
- }, status=status.HTTP_404_NOT_FOUND)
107
-
108
- updated_count = 0
109
- failed_ids = []
110
-
111
- for segment in segments:
112
- try:
113
- if segment.state:
114
- segment.state.is_validated = is_validated
115
- if notes and hasattr(segment.state, 'validation_notes'):
116
- segment.state.validation_notes = notes
117
- segment.state.save()
118
- updated_count += 1
119
- else:
120
- failed_ids.append(segment.id)
121
- except Exception as e:
122
- import logging
123
- logger = logging.getLogger(__name__)
124
- logger.error(f"Error validating segment {segment.id}: {e}")
125
- failed_ids.append(segment.id)
126
-
127
- response_data = {
128
- "message": f"Bulk validation completed. {updated_count} segments updated.",
129
- "updated_count": updated_count,
130
- "requested_count": len(segment_ids),
131
- "is_validated": is_validated
132
- }
133
-
134
- if failed_ids:
135
- response_data["failed_ids"] = failed_ids
136
- response_data["warning"] = f"{len(failed_ids)} segments could not be validated"
137
-
138
- return Response(response_data, status=status.HTTP_200_OK)
139
-
140
- except Exception as e:
141
- import logging
142
- logger = logging.getLogger(__name__)
143
- logger.error(f"Error in bulk validation: {e}")
144
- return Response({
145
- "error": f"Bulk validation failed: {str(e)}"
146
- }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
147
-
148
-
149
- class VideoSegmentValidationCompleteView(APIView):
150
- """
151
- POST /api/videos/<int:video_id>/segments/validate-complete/
152
-
153
- Markiert alle Segmente eines Videos als validiert.
154
- Nützlich nach vollständiger Review eines Videos.
155
-
156
- Body (optional):
157
- {
158
- "label_name": "...", // optional, nur Segmente mit diesem Label validieren
159
- "notes": "..." // optional
160
- }
161
- """
162
- permission_classes = DEBUG_PERMISSIONS
163
-
164
- @transaction.atomic
165
- def post(self, request, video_id: int):
166
- try:
167
- # Video abrufen
168
- video = VideoFile.objects.get(pk=video_id)
169
-
170
- label_name = request.data.get('label_name')
171
- notes = request.data.get('notes', '')
172
-
173
- # Segmente filtern
174
- segments_query = LabelVideoSegment.objects.filter(video_file=video).select_related('state', 'label')
175
-
176
- if label_name:
177
- segments_query = segments_query.filter(label__name=label_name)
178
-
179
- segments = segments_query.all()
180
-
181
- if not segments.exists():
182
- return Response({
183
- "message": "No segments found to validate",
184
- "video_id": video_id,
185
- "updated_count": 0
186
- }, status=status.HTTP_200_OK)
187
-
188
- updated_count = 0
189
- failed_count = 0
190
-
191
- for segment in segments:
192
- try:
193
- if segment.state:
194
- segment.state.is_validated = True
195
- if notes and hasattr(segment.state, 'validation_notes'):
196
- segment.state.validation_notes = notes
197
- segment.state.save()
198
- updated_count += 1
199
- else:
200
- failed_count += 1
201
- except Exception as e:
202
- import logging
203
- logger = logging.getLogger(__name__)
204
- logger.error(f"Error validating segment {segment.id}: {e}")
205
- failed_count += 1
206
-
207
- return Response({
208
- "message": f"Video segment validation completed for video {video_id}",
209
- "video_id": video_id,
210
- "total_segments": len(segments),
211
- "updated_count": updated_count,
212
- "failed_count": failed_count,
213
- "label_filter": label_name
214
- }, status=status.HTTP_200_OK)
215
-
216
- except VideoFile.DoesNotExist:
217
- return Response({
218
- "error": f"Video {video_id} not found"
219
- }, status=status.HTTP_404_NOT_FOUND)
220
- except Exception as e:
221
- import logging
222
- logger = logging.getLogger(__name__)
223
- logger.error(f"Error completing validation for video {video_id}: {e}")
224
- return Response({
225
- "error": f"Validation completion failed: {str(e)}"
226
- }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@@ -1,71 +0,0 @@
1
- """
2
- Modern Media Framework - Video Segment API Views
3
- October 14, 2025 - Migration to unified /api/media/videos/<pk>/segments/ pattern
4
-
5
- This module provides modern framework views for video segment management,
6
- wrapping legacy segment views with pk-based parameter handling.
7
- """
8
- from endoreg_db.models import Label, LabelVideoSegment, VideoFile
9
- from endoreg_db.serializers.label_video_segment.label_video_segment import LabelVideoSegmentSerializer
10
-
11
- from django.db import transaction
12
- from rest_framework import status
13
- from rest_framework.decorators import api_view, permission_classes
14
- from rest_framework.response import Response
15
-
16
- from endoreg_db.utils.permissions import EnvironmentAwarePermission
17
- import logging
18
-
19
- logger = logging.getLogger(__name__)
20
-
21
-
22
- @api_view(['GET'])
23
- @permission_classes([EnvironmentAwarePermission])
24
- def video_segments_by_pk(request, pk):
25
- """
26
- Modern media framework endpoint for retrieving video segments.
27
-
28
- GET /api/media/videos/<int:pk>/segments/?label=<label_name>
29
-
30
- Returns all segments for a video, optionally filtered by label name.
31
- This is the modern replacement for /api/video/<id>/segments/
32
-
33
- Query Parameters:
34
- label (str, optional): Filter segments by label name (e.g., 'outside')
35
-
36
- Returns:
37
- 200: List of video segments
38
- 404: Video not found
39
- """
40
- try:
41
- video = VideoFile.objects.get(id=pk)
42
- except VideoFile.DoesNotExist:
43
- logger.warning(f"Video with pk {pk} not found")
44
- return Response(
45
- {'error': f'Video with id {pk} not found'},
46
- status=status.HTTP_404_NOT_FOUND
47
- )
48
-
49
- # Start with all segments for this video
50
- queryset = LabelVideoSegment.objects.filter(video_file=video)
51
-
52
- # Optional filtering by label name
53
- label_name = request.GET.get('label')
54
- if label_name:
55
- try:
56
- label = Label.objects.get(name=label_name)
57
- queryset = queryset.filter(label=label)
58
- logger.info(f"Filtering segments for video {pk} by label '{label_name}'")
59
- except Label.DoesNotExist:
60
- logger.warning(f"Label '{label_name}' not found, returning empty result")
61
- return Response(
62
- {'error': f"Label '{label_name}' not found"},
63
- status=status.HTTP_404_NOT_FOUND
64
- )
65
-
66
- # Order by start time for consistent results
67
- segments = queryset.order_by('start_frame_number')
68
- serializer = LabelVideoSegmentSerializer(segments, many=True)
69
-
70
- logger.info(f"Returning {len(segments)} segments for video {pk}")
71
- return Response(serializer.data)
@@ -1,146 +0,0 @@
1
- from endoreg_db.models import RawPdfFile, VideoFile
2
- from endoreg_db.utils.permissions import DEBUG_PERMISSIONS
3
- import logging
4
-
5
- from rest_framework import status
6
- from rest_framework.response import Response
7
- from rest_framework.views import APIView
8
-
9
- logger = logging.getLogger(__name__)
10
-
11
- class AvailableFilesListView(APIView):
12
- """
13
- API endpoint to list available PDFs and videos for anonymization selection.
14
-
15
- GET: Returns lists of available PDF and video files with their metadata
16
- """
17
-
18
- permission_classes = DEBUG_PERMISSIONS
19
-
20
- def _validate_pagination_params(self, request):
21
- """Validates and returns pagination parameters, raising ValueError on failure."""
22
- try:
23
- limit = int(request.query_params.get('limit', 50))
24
- offset = int(request.query_params.get('offset', 0))
25
- except (ValueError, TypeError):
26
- raise ValueError("Invalid 'limit' or 'offset' parameter. Must be integers.")
27
-
28
- if limit < 0 or offset < 0:
29
- raise ValueError("'limit' and 'offset' must be non-negative.")
30
-
31
- if limit > 100:
32
- logger.warning(f"Client requested limit of {limit}, capping at 100.")
33
- limit = 100
34
-
35
- return limit, offset
36
-
37
- def get(self, request):
38
- """
39
- List available PDF and video files for anonymization selection.
40
-
41
- Query Parameters:
42
- - type: Filter by file type ('pdf' or 'video')
43
- - status: Filter by anonymization status
44
- - limit: Number of results to return (default 50, max 100)
45
- - offset: Offset for pagination (default 0)
46
-
47
- Returns:
48
- {
49
- "pdfs": [...],
50
- "videos": [...],
51
- "total_pdfs": N,
52
- "total_videos": N
53
- }
54
- """
55
- try:
56
- limit, offset = self._validate_pagination_params(request)
57
- file_type = request.query_params.get('type', 'all').lower()
58
- except ValueError as e:
59
- return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
60
-
61
- try:
62
- response_data = {}
63
-
64
- # Get PDFs if requested
65
- if file_type in ['all', 'pdf']:
66
- pdf_queryset = RawPdfFile.objects.select_related('sensitive_meta').all()
67
- total_pdfs = pdf_queryset.count()
68
- paginated_pdfs = pdf_queryset[offset:offset + limit]
69
-
70
- pdf_list = []
71
- for pdf in paginated_pdfs:
72
- # Safely handle missing file attribute
73
- file_name = 'Unknown'
74
- file_path = None
75
- if hasattr(pdf, 'file') and pdf.file:
76
- file_name = pdf.file.name.split('/')[-1]
77
- file_path = pdf.file.name
78
- pdf_data = {
79
- 'id': pdf.id,
80
- 'filename': file_name,
81
- 'file_path': file_path,
82
- 'sensitive_meta_id': pdf.sensitive_meta_id,
83
- 'anonymized_text': getattr(pdf, 'anonymized_text', None),
84
- 'created_at': pdf.date_created if hasattr(pdf, 'created_at') else None,
85
- 'patient_info': None
86
- }
87
-
88
- # Add patient info if available
89
- if pdf.sensitive_meta:
90
- pdf_data['patient_info'] = {
91
- 'patient_first_name': pdf.sensitive_meta.patient_first_name,
92
- 'patient_last_name': pdf.sensitive_meta.patient_last_name,
93
- 'patient_dob': pdf.sensitive_meta.patient_dob,
94
- 'examination_date': pdf.sensitive_meta.examination_date,
95
- 'center_name': pdf.sensitive_meta.center.name if pdf.sensitive_meta.center else None
96
- }
97
-
98
- pdf_list.append(pdf_data)
99
-
100
- response_data['pdfs'] = pdf_list
101
- response_data['total_pdfs'] = total_pdfs
102
-
103
- # Get Videos if requested
104
- if file_type in ['all', 'video']:
105
- video_queryset = VideoFile.objects.select_related('sensitive_meta').all()
106
- total_videos = video_queryset.count()
107
- paginated_videos = video_queryset[offset:offset + limit]
108
-
109
- video_list = []
110
- for video in paginated_videos:
111
- # Safely handle missing raw_file attribute
112
- file_name = 'Unknown'
113
- file_path = None
114
- if hasattr(video, 'raw_file') and video.raw_file:
115
- file_name = video.raw_file.name.split('/')[-1]
116
- file_path = video.raw_file.name
117
- video_data = {
118
- 'id': video.id,
119
- 'filename': file_name,
120
- 'file_path': file_path,
121
- 'sensitive_meta_id': video.sensitive_meta_id,
122
- 'patient_info': None
123
- }
124
-
125
- # Add patient info if available
126
- if video.sensitive_meta:
127
- video_data['patient_info'] = {
128
- 'patient_first_name': video.sensitive_meta.patient_first_name,
129
- 'patient_last_name': video.sensitive_meta.patient_last_name,
130
- 'patient_dob': video.sensitive_meta.patient_dob,
131
- 'examination_date': video.sensitive_meta.examination_date,
132
- 'center_name': video.sensitive_meta.center.name if video.sensitive_meta.center else None
133
- }
134
-
135
- video_list.append(video_data)
136
-
137
- response_data['videos'] = video_list
138
- response_data['total_videos'] = total_videos
139
-
140
- return Response(response_data)
141
- except Exception as e:
142
- logger.error(f"Error listing available files: {e}", exc_info=True)
143
- return Response(
144
- {"error": "An unexpected error occurred while fetching files."},
145
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
146
- )
@@ -1,53 +0,0 @@
1
- from endoreg_db.models import RawPdfFile
2
-
3
- from django.shortcuts import get_object_or_404
4
- from rest_framework import status
5
- from rest_framework.response import Response
6
- from rest_framework.views import APIView
7
- from pathlib import Path
8
- import logging
9
-
10
- logger = logging.getLogger(__name__)
11
-
12
- class ReportFileMetadataView(APIView):
13
- """
14
- API-Endpunkt für Report-Datei-Metadaten
15
- GET /api/reports/{report_id}/file-metadata/
16
- """
17
-
18
- def get(self, _request, report_id):
19
- try:
20
- report = get_object_or_404(RawPdfFile, id=report_id)
21
-
22
- if not report.file:
23
- return Response(
24
- {"error": "Keine Datei für diesen Report verfügbar"},
25
- status=status.HTTP_404_NOT_FOUND
26
- )
27
-
28
- metadata = self._get_file_metadata(report)
29
- return Response(metadata)
30
-
31
- except (ValueError, TypeError) as e:
32
- logger.error("Fehler beim Laden der Datei-Metadaten: %s", str(e))
33
- return Response(
34
- {"error": "Metadaten konnten nicht geladen werden"},
35
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
36
- )
37
-
38
- def _get_file_metadata(self, report):
39
- """Sammelt Datei-Metadaten"""
40
- file_path = Path(report.file.name)
41
-
42
- try:
43
- file_size = report.file.size
44
- except OSError:
45
- file_size = 0
46
-
47
- return {
48
- 'filename': file_path.name,
49
- 'file_type': file_path.suffix.lower().lstrip('.'),
50
- 'file_size': file_size,
51
- 'upload_date': report.created_at if hasattr(report, 'created_at') else None,
52
- 'last_modified': report.updated_at if hasattr(report, 'updated_at') else None
53
- }
@@ -1,148 +0,0 @@
1
- from endoreg_db.models import SensitiveMeta
2
- from endoreg_db.serializers import SensitiveMetaDetailSerializer, SensitiveMetaUpdateSerializer
3
-
4
- from django.db import transaction
5
- from django.shortcuts import get_object_or_404
6
- from rest_framework import status
7
- from rest_framework.response import Response
8
- from rest_framework.views import APIView
9
-
10
- from endoreg_db.utils.permissions import DEBUG_PERMISSIONS
11
- import logging
12
-
13
- logger = logging.getLogger(__name__)
14
-
15
- class SensitiveMetaDetailView(APIView):
16
- """
17
- API endpoint to retrieve and update SensitiveMeta details with verification state.
18
-
19
- GET: Returns detailed SensitiveMeta information for annotation/verification
20
- PATCH: Updates SensitiveMeta fields including verification state
21
- """
22
-
23
- permission_classes = DEBUG_PERMISSIONS # Changed from IsAuthenticated for development
24
-
25
- def get(self, request, sensitive_meta_id=None):
26
- """
27
- Retrieve SensitiveMeta details for display and annotation.
28
-
29
- Supports both URL parameter and query parameter access patterns:
30
- - /api/pdf/sensitivemeta/123/ (URL parameter)
31
- - /api/pdf/sensitivemeta/?id=123 (query parameter - for backward compatibility)
32
- - /api/pdf/sensitivemeta/ (list all - returns empty list instead of 400)
33
-
34
- Returns detailed information suitable for user verification.
35
- """
36
- # Handle both URL parameter and query parameter patterns
37
- if not sensitive_meta_id:
38
- sensitive_meta_id = request.query_params.get('id')
39
-
40
- # If no ID provided, return empty list instead of error
41
- if not sensitive_meta_id:
42
- return Response([], status=status.HTTP_200_OK)
43
-
44
- try:
45
- # Convert to int if it's a string
46
- sensitive_meta_id = int(sensitive_meta_id)
47
-
48
- # Get the SensitiveMeta instance with related data
49
- sensitive_meta = SensitiveMeta.objects.select_related(
50
- 'center',
51
- 'patient_gender',
52
- 'pseudo_patient',
53
- 'pseudo_examination'
54
- ).prefetch_related(
55
- 'examiners',
56
- 'state'
57
- ).get(id=sensitive_meta_id)
58
-
59
- # Serialize for display
60
- serializer = SensitiveMetaDetailSerializer(sensitive_meta)
61
-
62
- # Return direct data to match anonymization store expectations
63
- # Instead of wrapping in "sensitive_meta" key, return data directly
64
- response_data = serializer.data
65
-
66
- logger.info(f"Retrieved SensitiveMeta {sensitive_meta_id} for user {request.user}")
67
- return Response(response_data, status=status.HTTP_200_OK)
68
-
69
- except ValueError:
70
- return Response(
71
- {"error": "Invalid sensitive_meta_id format. Must be an integer."},
72
- status=status.HTTP_400_BAD_REQUEST
73
- )
74
- except SensitiveMeta.DoesNotExist:
75
- return Response(
76
- {"error": f"SensitiveMeta with ID {sensitive_meta_id} not found"},
77
- status=status.HTTP_404_NOT_FOUND
78
- )
79
- except Exception as e:
80
- logger.error(f"Error retrieving SensitiveMeta {sensitive_meta_id}: {e}")
81
- return Response(
82
- {"error": "Internal server error occurred"},
83
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
84
- )
85
-
86
- @transaction.atomic
87
- def patch(self, request, sensitive_meta_id=None):
88
- """
89
- Update SensitiveMeta fields including verification state.
90
-
91
- Accepts partial updates for any field in SensitiveMetaUpdateSerializer.
92
- Special handling for verification state changes.
93
- """
94
- if not sensitive_meta_id:
95
- return Response(
96
- {"error": "sensitive_meta_id is required"},
97
- status=status.HTTP_400_BAD_REQUEST
98
- )
99
-
100
- try:
101
- # Get the SensitiveMeta instance
102
- sensitive_meta = get_object_or_404(SensitiveMeta, id=sensitive_meta_id)
103
-
104
- # Validate and update using serializer
105
- serializer = SensitiveMetaUpdateSerializer(
106
- sensitive_meta,
107
- data=request.data,
108
- partial=True
109
- )
110
-
111
- if serializer.is_valid():
112
- updated_instance = serializer.save()
113
-
114
- # Return updated data using detail serializer
115
- response_serializer = SensitiveMetaDetailSerializer(updated_instance)
116
-
117
- response_data = {
118
- "message": "SensitiveMeta updated successfully",
119
- "sensitive_meta": response_serializer.data,
120
- "updated_fields": list(request.data.keys())
121
- }
122
-
123
- logger.info(
124
- f"Updated SensitiveMeta {sensitive_meta_id} by user {request.user}. "
125
- f"Fields: {list(request.data.keys())}"
126
- )
127
-
128
- return Response(response_data, status=status.HTTP_200_OK)
129
- else:
130
- return Response(
131
- {
132
- "error": "Validation failed",
133
- "details": serializer.errors
134
- },
135
- status=status.HTTP_400_BAD_REQUEST
136
- )
137
-
138
- except SensitiveMeta.DoesNotExist:
139
- return Response(
140
- {"error": f"SensitiveMeta with ID {sensitive_meta_id} not found"},
141
- status=status.HTTP_404_NOT_FOUND
142
- )
143
- except Exception as e:
144
- logger.error(f"Error updating SensitiveMeta {sensitive_meta_id}: {e}")
145
- return Response(
146
- {"error": "Internal server error occurred"},
147
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
148
- )