endoreg-db 0.8.8.9__py3-none-any.whl → 0.8.9.10__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 (453) hide show
  1. endoreg_db/admin.py +10 -5
  2. endoreg_db/apps.py +4 -7
  3. endoreg_db/authz/auth.py +1 -0
  4. endoreg_db/authz/backends.py +1 -1
  5. endoreg_db/authz/management/commands/list_routes.py +2 -0
  6. endoreg_db/authz/middleware.py +8 -7
  7. endoreg_db/authz/permissions.py +21 -10
  8. endoreg_db/authz/policy.py +14 -19
  9. endoreg_db/authz/views_auth.py +14 -10
  10. endoreg_db/codemods/rename_datetime_fields.py +8 -1
  11. endoreg_db/exceptions.py +5 -2
  12. endoreg_db/forms/__init__.py +0 -1
  13. endoreg_db/forms/examination_form.py +4 -3
  14. endoreg_db/forms/patient_finding_intervention_form.py +30 -8
  15. endoreg_db/forms/patient_form.py +9 -13
  16. endoreg_db/forms/questionnaires/__init__.py +1 -1
  17. endoreg_db/forms/settings/__init__.py +4 -1
  18. endoreg_db/forms/unit.py +2 -1
  19. endoreg_db/helpers/count_db.py +17 -14
  20. endoreg_db/helpers/default_objects.py +2 -1
  21. endoreg_db/helpers/download_segmentation_model.py +4 -3
  22. endoreg_db/helpers/interact.py +0 -5
  23. endoreg_db/helpers/test_video_helper.py +33 -25
  24. endoreg_db/import_files/__init__.py +1 -1
  25. endoreg_db/import_files/context/__init__.py +1 -1
  26. endoreg_db/import_files/context/default_sensitive_meta.py +11 -9
  27. endoreg_db/import_files/context/ensure_center.py +4 -4
  28. endoreg_db/import_files/context/file_lock.py +3 -3
  29. endoreg_db/import_files/context/import_context.py +11 -12
  30. endoreg_db/import_files/context/validate_directories.py +1 -0
  31. endoreg_db/import_files/file_storage/create_report_file.py +57 -34
  32. endoreg_db/import_files/file_storage/create_video_file.py +64 -35
  33. endoreg_db/import_files/file_storage/sensitive_meta_storage.py +5 -2
  34. endoreg_db/import_files/file_storage/state_management.py +146 -83
  35. endoreg_db/import_files/file_storage/storage.py +5 -1
  36. endoreg_db/import_files/processing/report_processing/report_anonymization.py +24 -19
  37. endoreg_db/import_files/processing/sensitive_meta_adapter.py +3 -3
  38. endoreg_db/import_files/processing/video_processing/video_anonymization.py +18 -18
  39. endoreg_db/import_files/pseudonymization/k_anonymity.py +8 -9
  40. endoreg_db/import_files/pseudonymization/k_pseudonymity.py +16 -5
  41. endoreg_db/import_files/report_import_service.py +36 -30
  42. endoreg_db/import_files/video_import_service.py +27 -23
  43. endoreg_db/logger_conf.py +56 -40
  44. endoreg_db/management/__init__.py +1 -1
  45. endoreg_db/management/commands/__init__.py +1 -1
  46. endoreg_db/management/commands/check_auth.py +45 -38
  47. endoreg_db/management/commands/create_model_meta_from_huggingface.py +53 -2
  48. endoreg_db/management/commands/create_multilabel_model_meta.py +54 -19
  49. endoreg_db/management/commands/fix_missing_patient_data.py +105 -71
  50. endoreg_db/management/commands/fix_video_paths.py +75 -54
  51. endoreg_db/management/commands/import_report.py +1 -3
  52. endoreg_db/management/commands/list_routes.py +2 -0
  53. endoreg_db/management/commands/load_ai_model_data.py +8 -2
  54. endoreg_db/management/commands/load_ai_model_label_data.py +0 -1
  55. endoreg_db/management/commands/load_center_data.py +3 -3
  56. endoreg_db/management/commands/load_distribution_data.py +35 -38
  57. endoreg_db/management/commands/load_endoscope_data.py +0 -3
  58. endoreg_db/management/commands/load_examination_data.py +20 -4
  59. endoreg_db/management/commands/load_finding_data.py +18 -3
  60. endoreg_db/management/commands/load_gender_data.py +17 -24
  61. endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +95 -85
  62. endoreg_db/management/commands/load_information_source.py +0 -3
  63. endoreg_db/management/commands/load_lab_value_data.py +14 -3
  64. endoreg_db/management/commands/load_legacy_data.py +303 -0
  65. endoreg_db/management/commands/load_name_data.py +1 -2
  66. endoreg_db/management/commands/load_pdf_type_data.py +4 -8
  67. endoreg_db/management/commands/load_profession_data.py +0 -1
  68. endoreg_db/management/commands/load_report_reader_flag_data.py +0 -4
  69. endoreg_db/management/commands/load_requirement_data.py +6 -2
  70. endoreg_db/management/commands/load_unit_data.py +0 -4
  71. endoreg_db/management/commands/load_user_groups.py +5 -7
  72. endoreg_db/management/commands/model_input.py +169 -0
  73. endoreg_db/management/commands/register_ai_model.py +22 -16
  74. endoreg_db/management/commands/setup_endoreg_db.py +110 -32
  75. endoreg_db/management/commands/storage_management.py +14 -8
  76. endoreg_db/management/commands/summarize_db_content.py +154 -63
  77. endoreg_db/management/commands/train_image_multilabel_model.py +144 -0
  78. endoreg_db/management/commands/validate_video_files.py +82 -50
  79. endoreg_db/management/commands/video_validation.py +4 -6
  80. endoreg_db/migrations/0001_initial.py +112 -63
  81. endoreg_db/migrations/__init__.py +0 -0
  82. endoreg_db/models/__init__.py +8 -0
  83. endoreg_db/models/administration/ai/active_model.py +5 -5
  84. endoreg_db/models/administration/ai/ai_model.py +41 -18
  85. endoreg_db/models/administration/ai/model_type.py +1 -0
  86. endoreg_db/models/administration/case/case.py +22 -22
  87. endoreg_db/models/administration/center/__init__.py +5 -5
  88. endoreg_db/models/administration/center/center.py +6 -2
  89. endoreg_db/models/administration/center/center_resource.py +18 -4
  90. endoreg_db/models/administration/center/center_shift.py +3 -1
  91. endoreg_db/models/administration/center/center_waste.py +6 -2
  92. endoreg_db/models/administration/person/__init__.py +1 -1
  93. endoreg_db/models/administration/person/employee/__init__.py +1 -1
  94. endoreg_db/models/administration/person/employee/employee_type.py +3 -1
  95. endoreg_db/models/administration/person/examiner/__init__.py +1 -1
  96. endoreg_db/models/administration/person/examiner/examiner.py +10 -2
  97. endoreg_db/models/administration/person/names/first_name.py +6 -4
  98. endoreg_db/models/administration/person/names/last_name.py +4 -3
  99. endoreg_db/models/administration/person/patient/__init__.py +1 -1
  100. endoreg_db/models/administration/person/patient/patient.py +0 -1
  101. endoreg_db/models/administration/person/patient/patient_external_id.py +0 -1
  102. endoreg_db/models/administration/person/person.py +1 -1
  103. endoreg_db/models/administration/product/__init__.py +7 -6
  104. endoreg_db/models/administration/product/product.py +6 -2
  105. endoreg_db/models/administration/product/product_group.py +9 -7
  106. endoreg_db/models/administration/product/product_material.py +9 -2
  107. endoreg_db/models/administration/product/reference_product.py +64 -15
  108. endoreg_db/models/administration/qualification/qualification.py +3 -1
  109. endoreg_db/models/administration/shift/shift.py +3 -1
  110. endoreg_db/models/administration/shift/shift_type.py +12 -4
  111. endoreg_db/models/aidataset/__init__.py +5 -0
  112. endoreg_db/models/aidataset/aidataset.py +193 -0
  113. endoreg_db/models/label/__init__.py +1 -1
  114. endoreg_db/models/label/label.py +10 -2
  115. endoreg_db/models/label/label_set.py +3 -1
  116. endoreg_db/models/label/label_video_segment/_create_from_video.py +6 -2
  117. endoreg_db/models/label/label_video_segment/label_video_segment.py +148 -44
  118. endoreg_db/models/media/__init__.py +12 -5
  119. endoreg_db/models/media/frame/__init__.py +1 -1
  120. endoreg_db/models/media/frame/frame.py +34 -8
  121. endoreg_db/models/media/pdf/__init__.py +2 -1
  122. endoreg_db/models/media/pdf/raw_pdf.py +11 -4
  123. endoreg_db/models/media/pdf/report_file.py +6 -2
  124. endoreg_db/models/media/pdf/report_reader/__init__.py +3 -3
  125. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +15 -5
  126. endoreg_db/models/media/video/create_from_file.py +20 -41
  127. endoreg_db/models/media/video/pipe_1.py +75 -30
  128. endoreg_db/models/media/video/pipe_2.py +37 -12
  129. endoreg_db/models/media/video/video_file.py +36 -24
  130. endoreg_db/models/media/video/video_file_ai.py +235 -70
  131. endoreg_db/models/media/video/video_file_anonymize.py +240 -65
  132. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -1
  133. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +3 -1
  134. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +30 -9
  135. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +95 -29
  136. endoreg_db/models/media/video/video_file_frames/_get_frame.py +13 -3
  137. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -1
  138. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +15 -3
  139. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +15 -3
  140. endoreg_db/models/media/video/video_file_frames/_get_frames.py +7 -2
  141. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +109 -23
  142. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +111 -27
  143. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +46 -13
  144. endoreg_db/models/media/video/video_file_io.py +85 -33
  145. endoreg_db/models/media/video/video_file_meta/__init__.py +6 -6
  146. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +17 -4
  147. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +28 -7
  148. endoreg_db/models/media/video/video_file_meta/get_fps.py +46 -13
  149. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +81 -20
  150. endoreg_db/models/media/video/video_file_meta/text_meta.py +61 -20
  151. endoreg_db/models/media/video/video_file_meta/video_meta.py +40 -12
  152. endoreg_db/models/media/video/video_file_segments.py +118 -27
  153. endoreg_db/models/media/video/video_metadata.py +25 -6
  154. endoreg_db/models/media/video/video_processing.py +54 -15
  155. endoreg_db/models/medical/__init__.py +3 -13
  156. endoreg_db/models/medical/contraindication/__init__.py +3 -1
  157. endoreg_db/models/medical/disease.py +18 -6
  158. endoreg_db/models/medical/event.py +6 -2
  159. endoreg_db/models/medical/examination/__init__.py +5 -1
  160. endoreg_db/models/medical/examination/examination.py +22 -6
  161. endoreg_db/models/medical/examination/examination_indication.py +23 -7
  162. endoreg_db/models/medical/examination/examination_time.py +6 -2
  163. endoreg_db/models/medical/finding/__init__.py +3 -1
  164. endoreg_db/models/medical/finding/finding.py +37 -12
  165. endoreg_db/models/medical/finding/finding_classification.py +27 -8
  166. endoreg_db/models/medical/finding/finding_intervention.py +19 -6
  167. endoreg_db/models/medical/finding/finding_type.py +3 -1
  168. endoreg_db/models/medical/hardware/__init__.py +1 -1
  169. endoreg_db/models/medical/hardware/endoscope.py +14 -2
  170. endoreg_db/models/medical/laboratory/__init__.py +1 -1
  171. endoreg_db/models/medical/laboratory/lab_value.py +139 -39
  172. endoreg_db/models/medical/medication/__init__.py +7 -3
  173. endoreg_db/models/medical/medication/medication.py +3 -1
  174. endoreg_db/models/medical/medication/medication_indication.py +3 -1
  175. endoreg_db/models/medical/medication/medication_indication_type.py +11 -3
  176. endoreg_db/models/medical/medication/medication_intake_time.py +3 -1
  177. endoreg_db/models/medical/medication/medication_schedule.py +3 -1
  178. endoreg_db/models/medical/patient/__init__.py +2 -10
  179. endoreg_db/models/medical/patient/medication_examples.py +3 -14
  180. endoreg_db/models/medical/patient/patient_disease.py +17 -5
  181. endoreg_db/models/medical/patient/patient_event.py +12 -4
  182. endoreg_db/models/medical/patient/patient_examination.py +52 -15
  183. endoreg_db/models/medical/patient/patient_examination_indication.py +15 -4
  184. endoreg_db/models/medical/patient/patient_finding.py +105 -29
  185. endoreg_db/models/medical/patient/patient_finding_classification.py +41 -12
  186. endoreg_db/models/medical/patient/patient_finding_intervention.py +11 -3
  187. endoreg_db/models/medical/patient/patient_lab_sample.py +6 -2
  188. endoreg_db/models/medical/patient/patient_lab_value.py +42 -10
  189. endoreg_db/models/medical/patient/patient_medication.py +25 -7
  190. endoreg_db/models/medical/patient/patient_medication_schedule.py +34 -10
  191. endoreg_db/models/metadata/model_meta.py +40 -12
  192. endoreg_db/models/metadata/model_meta_logic.py +51 -16
  193. endoreg_db/models/metadata/sensitive_meta.py +65 -28
  194. endoreg_db/models/metadata/sensitive_meta_logic.py +28 -26
  195. endoreg_db/models/metadata/video_meta.py +146 -39
  196. endoreg_db/models/metadata/video_prediction_logic.py +70 -21
  197. endoreg_db/models/metadata/video_prediction_meta.py +80 -27
  198. endoreg_db/models/operation_log.py +63 -0
  199. endoreg_db/models/other/__init__.py +10 -10
  200. endoreg_db/models/other/distribution/__init__.py +9 -7
  201. endoreg_db/models/other/distribution/base_value_distribution.py +3 -1
  202. endoreg_db/models/other/distribution/date_value_distribution.py +19 -5
  203. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +3 -1
  204. endoreg_db/models/other/distribution/numeric_value_distribution.py +34 -9
  205. endoreg_db/models/other/emission/__init__.py +1 -1
  206. endoreg_db/models/other/emission/emission_factor.py +9 -3
  207. endoreg_db/models/other/information_source.py +15 -5
  208. endoreg_db/models/other/material.py +3 -1
  209. endoreg_db/models/other/transport_route.py +3 -1
  210. endoreg_db/models/other/unit.py +6 -2
  211. endoreg_db/models/report/report.py +0 -1
  212. endoreg_db/models/requirement/requirement.py +84 -27
  213. endoreg_db/models/requirement/requirement_error.py +5 -6
  214. endoreg_db/models/requirement/requirement_evaluation/__init__.py +1 -1
  215. endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +8 -8
  216. endoreg_db/models/requirement/requirement_evaluation/get_values.py +3 -3
  217. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +24 -8
  218. endoreg_db/models/requirement/requirement_operator.py +28 -8
  219. endoreg_db/models/requirement/requirement_set.py +34 -11
  220. endoreg_db/models/state/__init__.py +1 -0
  221. endoreg_db/models/state/audit_ledger.py +9 -2
  222. endoreg_db/models/{media → state}/processing_history/__init__.py +1 -3
  223. endoreg_db/models/state/processing_history/processing_history.py +136 -0
  224. endoreg_db/models/state/raw_pdf.py +0 -1
  225. endoreg_db/models/state/video.py +2 -3
  226. endoreg_db/models/utils.py +4 -2
  227. endoreg_db/queries/__init__.py +2 -6
  228. endoreg_db/queries/annotations/__init__.py +1 -3
  229. endoreg_db/queries/annotations/legacy.py +37 -26
  230. endoreg_db/root_urls.py +3 -4
  231. endoreg_db/schemas/examination_evaluation.py +3 -0
  232. endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +249 -163
  233. endoreg_db/serializers/__init__.py +2 -8
  234. endoreg_db/serializers/administration/__init__.py +1 -2
  235. endoreg_db/serializers/administration/ai/__init__.py +0 -1
  236. endoreg_db/serializers/administration/ai/active_model.py +3 -1
  237. endoreg_db/serializers/administration/ai/ai_model.py +5 -3
  238. endoreg_db/serializers/administration/ai/model_type.py +3 -1
  239. endoreg_db/serializers/administration/center.py +7 -2
  240. endoreg_db/serializers/administration/gender.py +4 -2
  241. endoreg_db/serializers/anonymization.py +13 -13
  242. endoreg_db/serializers/evaluation/examination_evaluation.py +0 -1
  243. endoreg_db/serializers/examination/__init__.py +1 -1
  244. endoreg_db/serializers/examination/base.py +12 -13
  245. endoreg_db/serializers/examination/dropdown.py +6 -7
  246. endoreg_db/serializers/examination_serializer.py +3 -6
  247. endoreg_db/serializers/finding/__init__.py +1 -1
  248. endoreg_db/serializers/finding/finding.py +14 -7
  249. endoreg_db/serializers/finding_classification/__init__.py +3 -3
  250. endoreg_db/serializers/finding_classification/choice.py +3 -3
  251. endoreg_db/serializers/finding_classification/classification.py +2 -4
  252. endoreg_db/serializers/label_video_segment/__init__.py +5 -3
  253. endoreg_db/serializers/{label → label_video_segment}/image_classification_annotation.py +5 -5
  254. endoreg_db/serializers/label_video_segment/label/__init__.py +6 -0
  255. endoreg_db/serializers/{label → label_video_segment/label}/label.py +1 -1
  256. endoreg_db/serializers/label_video_segment/label_video_segment.py +338 -228
  257. endoreg_db/serializers/meta/__init__.py +1 -2
  258. endoreg_db/serializers/meta/sensitive_meta_detail.py +28 -13
  259. endoreg_db/serializers/meta/sensitive_meta_update.py +51 -46
  260. endoreg_db/serializers/meta/sensitive_meta_verification.py +19 -16
  261. endoreg_db/serializers/misc/__init__.py +2 -2
  262. endoreg_db/serializers/misc/file_overview.py +11 -7
  263. endoreg_db/serializers/misc/stats.py +10 -8
  264. endoreg_db/serializers/misc/translatable_field_mix_in.py +6 -6
  265. endoreg_db/serializers/misc/upload_job.py +32 -29
  266. endoreg_db/serializers/patient/__init__.py +2 -1
  267. endoreg_db/serializers/patient/patient.py +32 -15
  268. endoreg_db/serializers/patient/patient_dropdown.py +11 -3
  269. endoreg_db/serializers/patient_examination/__init__.py +1 -1
  270. endoreg_db/serializers/patient_examination/patient_examination.py +67 -40
  271. endoreg_db/serializers/patient_finding/__init__.py +1 -1
  272. endoreg_db/serializers/patient_finding/patient_finding.py +2 -1
  273. endoreg_db/serializers/patient_finding/patient_finding_classification.py +17 -9
  274. endoreg_db/serializers/patient_finding/patient_finding_detail.py +26 -17
  275. endoreg_db/serializers/patient_finding/patient_finding_intervention.py +7 -5
  276. endoreg_db/serializers/patient_finding/patient_finding_list.py +10 -11
  277. endoreg_db/serializers/patient_finding/patient_finding_write.py +36 -27
  278. endoreg_db/serializers/pdf/__init__.py +1 -3
  279. endoreg_db/serializers/requirements/requirement_schema.py +1 -6
  280. endoreg_db/serializers/sensitive_meta_serializer.py +100 -81
  281. endoreg_db/serializers/video/__init__.py +2 -2
  282. endoreg_db/serializers/video/{segmentation.py → video_file.py} +66 -47
  283. endoreg_db/serializers/video/video_file_brief.py +6 -2
  284. endoreg_db/serializers/video/video_file_detail.py +36 -23
  285. endoreg_db/serializers/video/video_file_list.py +4 -2
  286. endoreg_db/serializers/video/video_processing_history.py +54 -50
  287. endoreg_db/services/__init__.py +1 -1
  288. endoreg_db/services/anonymization.py +2 -2
  289. endoreg_db/services/examination_evaluation.py +40 -17
  290. endoreg_db/services/model_meta_from_hf.py +76 -0
  291. endoreg_db/services/polling_coordinator.py +101 -70
  292. endoreg_db/services/pseudonym_service.py +27 -22
  293. endoreg_db/services/report_import.py +6 -3
  294. endoreg_db/services/segment_sync.py +75 -59
  295. endoreg_db/services/video_import.py +6 -7
  296. endoreg_db/urls/__init__.py +2 -2
  297. endoreg_db/urls/ai.py +7 -25
  298. endoreg_db/urls/anonymization.py +61 -15
  299. endoreg_db/urls/auth.py +4 -4
  300. endoreg_db/urls/classification.py +4 -9
  301. endoreg_db/urls/examination.py +27 -18
  302. endoreg_db/urls/media.py +27 -34
  303. endoreg_db/urls/patient.py +11 -7
  304. endoreg_db/urls/requirements.py +3 -1
  305. endoreg_db/urls/root_urls.py +2 -3
  306. endoreg_db/urls/stats.py +24 -16
  307. endoreg_db/urls/upload.py +3 -11
  308. endoreg_db/utils/__init__.py +14 -15
  309. endoreg_db/utils/ai/__init__.py +1 -1
  310. endoreg_db/utils/ai/data_loader_for_model_input.py +262 -0
  311. endoreg_db/utils/ai/data_loader_for_model_training.py +262 -0
  312. endoreg_db/utils/ai/get.py +2 -1
  313. endoreg_db/utils/ai/inference_dataset.py +14 -15
  314. endoreg_db/utils/ai/model_training/config.py +117 -0
  315. endoreg_db/utils/ai/model_training/dataset.py +74 -0
  316. endoreg_db/utils/ai/model_training/losses.py +68 -0
  317. endoreg_db/utils/ai/model_training/metrics.py +78 -0
  318. endoreg_db/utils/ai/model_training/model_backbones.py +155 -0
  319. endoreg_db/utils/ai/model_training/model_gastronet_resnet.py +118 -0
  320. endoreg_db/utils/ai/model_training/trainer_gastronet_multilabel.py +771 -0
  321. endoreg_db/utils/ai/multilabel_classification_net.py +21 -6
  322. endoreg_db/utils/ai/predict.py +4 -4
  323. endoreg_db/utils/ai/preprocess.py +19 -11
  324. endoreg_db/utils/calc_duration_seconds.py +4 -4
  325. endoreg_db/utils/case_generator/lab_sample_factory.py +3 -4
  326. endoreg_db/utils/check_video_files.py +74 -47
  327. endoreg_db/utils/cropping.py +10 -9
  328. endoreg_db/utils/dataloader.py +11 -3
  329. endoreg_db/utils/dates.py +3 -4
  330. endoreg_db/utils/defaults/set_default_center.py +7 -6
  331. endoreg_db/utils/env.py +6 -2
  332. endoreg_db/utils/extract_specific_frames.py +24 -9
  333. endoreg_db/utils/file_operations.py +30 -18
  334. endoreg_db/utils/fix_video_path_direct.py +57 -41
  335. endoreg_db/utils/frame_anonymization_utils.py +157 -157
  336. endoreg_db/utils/hashs.py +3 -18
  337. endoreg_db/utils/links/requirement_link.py +96 -52
  338. endoreg_db/utils/ocr.py +30 -25
  339. endoreg_db/utils/operation_log.py +61 -0
  340. endoreg_db/utils/parse_and_generate_yaml.py +12 -13
  341. endoreg_db/utils/paths.py +6 -6
  342. endoreg_db/utils/permissions.py +40 -24
  343. endoreg_db/utils/pipelines/process_video_dir.py +50 -26
  344. endoreg_db/utils/product/sum_emissions.py +5 -3
  345. endoreg_db/utils/product/sum_weights.py +4 -2
  346. endoreg_db/utils/pydantic_models/__init__.py +3 -4
  347. endoreg_db/utils/requirement_operator_logic/_old/lab_value_operators.py +207 -107
  348. endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +252 -65
  349. endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +27 -10
  350. endoreg_db/utils/setup_config.py +21 -5
  351. endoreg_db/utils/storage.py +3 -1
  352. endoreg_db/utils/translation.py +19 -15
  353. endoreg_db/utils/uuid.py +1 -0
  354. endoreg_db/utils/validate_endo_roi.py +12 -4
  355. endoreg_db/utils/validate_subcategory_dict.py +26 -24
  356. endoreg_db/utils/validate_video_detailed.py +207 -149
  357. endoreg_db/utils/video/__init__.py +7 -3
  358. endoreg_db/utils/video/extract_frames.py +30 -18
  359. endoreg_db/utils/video/ffmpeg_wrapper.py +217 -52
  360. endoreg_db/utils/video/names.py +11 -6
  361. endoreg_db/utils/video/streaming_processor.py +175 -101
  362. endoreg_db/utils/video/video_splitter.py +30 -19
  363. endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +59 -50
  364. endoreg_db/views/__init__.py +0 -20
  365. endoreg_db/views/anonymization/__init__.py +6 -2
  366. endoreg_db/views/anonymization/media_management.py +2 -6
  367. endoreg_db/views/anonymization/overview.py +34 -1
  368. endoreg_db/views/anonymization/validate.py +79 -18
  369. endoreg_db/views/auth/__init__.py +1 -1
  370. endoreg_db/views/auth/keycloak.py +16 -14
  371. endoreg_db/views/examination/__init__.py +12 -15
  372. endoreg_db/views/examination/examination.py +5 -5
  373. endoreg_db/views/examination/examination_manifest_cache.py +5 -5
  374. endoreg_db/views/examination/get_finding_classification_choices.py +8 -5
  375. endoreg_db/views/examination/get_finding_classifications.py +9 -7
  376. endoreg_db/views/examination/get_findings.py +8 -10
  377. endoreg_db/views/examination/get_instruments.py +3 -2
  378. endoreg_db/views/examination/get_interventions.py +1 -1
  379. endoreg_db/views/finding/__init__.py +2 -2
  380. endoreg_db/views/finding/finding.py +58 -54
  381. endoreg_db/views/finding/get_classifications.py +1 -1
  382. endoreg_db/views/finding/get_interventions.py +1 -1
  383. endoreg_db/views/finding_classification/__init__.py +5 -5
  384. endoreg_db/views/finding_classification/finding_classification.py +5 -6
  385. endoreg_db/views/finding_classification/get_classification_choices.py +3 -4
  386. endoreg_db/views/media/__init__.py +13 -13
  387. endoreg_db/views/media/pdf_media.py +9 -9
  388. endoreg_db/views/media/sensitive_metadata.py +10 -7
  389. endoreg_db/views/media/video_media.py +4 -4
  390. endoreg_db/views/meta/__init__.py +1 -1
  391. endoreg_db/views/meta/sensitive_meta_list.py +20 -22
  392. endoreg_db/views/meta/sensitive_meta_verification.py +14 -11
  393. endoreg_db/views/misc/__init__.py +6 -34
  394. endoreg_db/views/misc/center.py +2 -1
  395. endoreg_db/views/misc/csrf.py +2 -1
  396. endoreg_db/views/misc/gender.py +2 -1
  397. endoreg_db/views/misc/stats.py +141 -106
  398. endoreg_db/views/patient/__init__.py +1 -3
  399. endoreg_db/views/patient/patient.py +141 -99
  400. endoreg_db/views/patient_examination/__init__.py +5 -5
  401. endoreg_db/views/patient_examination/patient_examination.py +43 -42
  402. endoreg_db/views/patient_examination/patient_examination_create.py +10 -15
  403. endoreg_db/views/patient_examination/patient_examination_detail.py +12 -15
  404. endoreg_db/views/patient_examination/patient_examination_list.py +21 -17
  405. endoreg_db/views/patient_examination/video.py +114 -80
  406. endoreg_db/views/patient_finding/__init__.py +1 -1
  407. endoreg_db/views/patient_finding/patient_finding.py +17 -10
  408. endoreg_db/views/patient_finding/patient_finding_optimized.py +127 -95
  409. endoreg_db/views/patient_finding_classification/__init__.py +1 -1
  410. endoreg_db/views/patient_finding_classification/pfc_create.py +35 -27
  411. endoreg_db/views/report/reimport.py +1 -1
  412. endoreg_db/views/report/report_stream.py +5 -8
  413. endoreg_db/views/requirement/__init__.py +2 -1
  414. endoreg_db/views/requirement/evaluate.py +7 -9
  415. endoreg_db/views/requirement/lookup.py +2 -3
  416. endoreg_db/views/requirement/lookup_store.py +0 -1
  417. endoreg_db/views/requirement/requirement_utils.py +2 -4
  418. endoreg_db/views/stats/__init__.py +4 -4
  419. endoreg_db/views/stats/stats_views.py +152 -115
  420. endoreg_db/views/video/__init__.py +18 -27
  421. endoreg_db/views/{ai → video/ai}/__init__.py +2 -2
  422. endoreg_db/views/{ai → video/ai}/label.py +20 -16
  423. endoreg_db/views/video/correction.py +5 -6
  424. endoreg_db/views/video/reimport.py +134 -99
  425. endoreg_db/views/video/segments_crud.py +134 -44
  426. endoreg_db/views/video/video_apply_mask.py +13 -12
  427. endoreg_db/views/video/video_correction.py +2 -1
  428. endoreg_db/views/video/video_download_processed.py +15 -15
  429. endoreg_db/views/video/video_meta_stats.py +7 -6
  430. endoreg_db/views/video/video_processing_history.py +3 -2
  431. endoreg_db/views/video/video_remove_frames.py +13 -12
  432. endoreg_db/views/video/video_stream.py +110 -82
  433. {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/METADATA +9 -3
  434. {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/RECORD +436 -433
  435. endoreg_db/import_files/processing/video_processing/video_cleanup_on_error.py +0 -119
  436. endoreg_db/management/commands/import_fallback_video.py +0 -203
  437. endoreg_db/management/commands/import_video.py +0 -422
  438. endoreg_db/management/commands/import_video_with_classification.py +0 -367
  439. endoreg_db/models/media/processing_history/processing_history.py +0 -96
  440. endoreg_db/serializers/label/__init__.py +0 -7
  441. endoreg_db/serializers/label_video_segment/_lvs_create.py +0 -149
  442. endoreg_db/serializers/label_video_segment/_lvs_update.py +0 -138
  443. endoreg_db/serializers/label_video_segment/_lvs_validate.py +0 -149
  444. endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +0 -99
  445. endoreg_db/serializers/label_video_segment/label_video_segment_update.py +0 -163
  446. endoreg_db/services/__old/pdf_import.py +0 -1487
  447. endoreg_db/services/__old/video_import.py +0 -1306
  448. endoreg_db/tasks/upload_tasks.py +0 -216
  449. endoreg_db/tasks/video_ingest.py +0 -161
  450. endoreg_db/tasks/video_processing_tasks.py +0 -327
  451. endoreg_db/views/misc/translation.py +0 -182
  452. {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/WHEEL +0 -0
  453. {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/licenses/LICENSE +0 -0
@@ -19,72 +19,77 @@ from django.utils import timezone
19
19
  logger = logging.getLogger(__name__)
20
20
 
21
21
  # Unterstützte Ausgabeformate
22
- SUPPORTED_OUTPUT_FORMATS = ['jpg', 'jpeg', 'png', 'webp']
22
+ SUPPORTED_OUTPUT_FORMATS = ["jpg", "jpeg", "png", "webp"]
23
23
 
24
24
  # Anonymisierungsgrade
25
- ANONYMIZATION_LEVELS = ['minimal', 'faces', 'full']
25
+ ANONYMIZATION_LEVELS = ["minimal", "faces", "full"]
26
26
 
27
27
  # Maximale Dateigröße für Frames (in MB)
28
28
  MAX_FRAME_SIZE_MB = 50
29
29
 
30
30
 
31
- def validate_anonymization_request(video_id: int, segment_ids: List[int],
32
- anonymization_level: str, output_format: str) -> Dict:
31
+ def validate_anonymization_request(
32
+ video_id: int, segment_ids: List[int], anonymization_level: str, output_format: str
33
+ ) -> Dict:
33
34
  """
34
35
  Validiert eine Frame-Anonymisierungsanfrage.
35
-
36
+
36
37
  Args:
37
38
  video_id: Video-ID
38
39
  segment_ids: Liste der Segment-IDs
39
40
  anonymization_level: Anonymisierungsgrad
40
41
  output_format: Ausgabeformat
41
-
42
+
42
43
  Returns:
43
44
  Dict mit Validierungsergebnis
44
-
45
+
45
46
  Raises:
46
47
  ValidationError: Bei ungültigen Parametern
47
48
  """
48
49
  errors = []
49
-
50
+
50
51
  # Anonymisierungsgrad validieren
51
52
  if anonymization_level not in ANONYMIZATION_LEVELS:
52
- errors.append(f"Invalid anonymization level: {anonymization_level}. "
53
- f"Supported levels: {', '.join(ANONYMIZATION_LEVELS)}")
54
-
53
+ errors.append(
54
+ f"Invalid anonymization level: {anonymization_level}. "
55
+ f"Supported levels: {', '.join(ANONYMIZATION_LEVELS)}"
56
+ )
57
+
55
58
  # Ausgabeformat validieren
56
59
  if output_format.lower() not in SUPPORTED_OUTPUT_FORMATS:
57
- errors.append(f"Invalid output format: {output_format}. "
58
- f"Supported formats: {', '.join(SUPPORTED_OUTPUT_FORMATS)}")
59
-
60
+ errors.append(
61
+ f"Invalid output format: {output_format}. "
62
+ f"Supported formats: {', '.join(SUPPORTED_OUTPUT_FORMATS)}"
63
+ )
64
+
60
65
  # Segment-IDs validieren
61
66
  if not segment_ids or len(segment_ids) == 0:
62
67
  errors.append("At least one segment ID must be provided")
63
-
68
+
64
69
  if len(segment_ids) > 100: # Reasonable limit
65
70
  errors.append("Too many segments requested (max 100)")
66
-
71
+
67
72
  # Video-ID validieren
68
73
  if video_id <= 0:
69
74
  errors.append("Invalid video ID")
70
-
75
+
71
76
  if errors:
72
77
  raise ValidationError(errors)
73
-
78
+
74
79
  return {
75
- 'valid': True,
76
- 'normalized_format': output_format.lower(),
77
- 'segment_count': len(segment_ids)
80
+ "valid": True,
81
+ "normalized_format": output_format.lower(),
82
+ "segment_count": len(segment_ids),
78
83
  }
79
84
 
80
85
 
81
86
  def generate_secure_token(length: int = 32) -> str:
82
87
  """
83
88
  Generiert einen sicheren Token für Downloads.
84
-
89
+
85
90
  Args:
86
91
  length: Token-Länge
87
-
92
+
88
93
  Returns:
89
94
  Sicherer Token
90
95
  """
@@ -94,54 +99,54 @@ def generate_secure_token(length: int = 32) -> str:
94
99
  def create_secure_download_url(frame_id: int, expiry_hours: int = 24) -> Dict:
95
100
  """
96
101
  Erstellt eine sichere Download-URL für einen anonymisierten Frame.
97
-
102
+
98
103
  Args:
99
104
  frame_id: Frame-ID
100
105
  expiry_hours: Gültigkeitsdauer in Stunden
101
-
106
+
102
107
  Returns:
103
108
  Dict mit URL und Token-Informationen
104
109
  """
105
110
  token = generate_secure_token()
106
111
  expiry_time = timezone.now() + timedelta(hours=expiry_hours)
107
-
112
+
108
113
  # Token hashen für Datenbank-Speicherung
109
114
  token_hash = hashlib.sha256(token.encode()).hexdigest()
110
-
115
+
111
116
  return {
112
- 'token': token,
113
- 'token_hash': token_hash,
114
- 'expires_at': expiry_time,
115
- 'frame_id': frame_id
117
+ "token": token,
118
+ "token_hash": token_hash,
119
+ "expires_at": expiry_time,
120
+ "frame_id": frame_id,
116
121
  }
117
122
 
118
123
 
119
124
  def validate_secure_token(token: str, frame_id: int) -> bool:
120
125
  """
121
126
  Validiert einen sicheren Download-Token.
122
-
127
+
123
128
  Args:
124
129
  token: Download-Token
125
130
  frame_id: Frame-ID
126
-
131
+
127
132
  Returns:
128
133
  True wenn Token gültig ist
129
134
  """
130
135
  try:
131
136
  from endoreg_db.models import AnonymousFrame
132
-
137
+
133
138
  # Token hashen
134
139
  token_hash = hashlib.sha256(token.encode()).hexdigest()
135
-
140
+
136
141
  # Frame mit Token finden
137
142
  frame = AnonymousFrame.objects.filter(
138
143
  id=frame_id,
139
144
  download_token_hash=token_hash,
140
- download_expires_at__gt=timezone.now()
145
+ download_expires_at__gt=timezone.now(),
141
146
  ).first()
142
-
147
+
143
148
  return frame is not None
144
-
149
+
145
150
  except Exception as e:
146
151
  logger.error(f"Token validation error: {str(e)}")
147
152
  return False
@@ -150,139 +155,137 @@ def validate_secure_token(token: str, frame_id: int) -> bool:
150
155
  def get_frame_file_info(frame_path: str) -> Optional[Dict]:
151
156
  """
152
157
  Holt Dateiinformationen für einen Frame.
153
-
158
+
154
159
  Args:
155
160
  frame_path: Pfad zum Frame
156
-
161
+
157
162
  Returns:
158
163
  Dict mit Dateiinformationen oder None
159
164
  """
160
165
  try:
161
166
  path = Path(frame_path)
162
-
167
+
163
168
  if not path.exists():
164
169
  return None
165
-
170
+
166
171
  stat = path.stat()
167
-
172
+
168
173
  return {
169
- 'filename': path.name,
170
- 'size_bytes': stat.st_size,
171
- 'size_mb': round(stat.st_size / (1024 * 1024), 2),
172
- 'created_at': datetime.fromtimestamp(stat.st_ctime),
173
- 'modified_at': datetime.fromtimestamp(stat.st_mtime),
174
- 'extension': path.suffix.lower(),
175
- 'exists': True
174
+ "filename": path.name,
175
+ "size_bytes": stat.st_size,
176
+ "size_mb": round(stat.st_size / (1024 * 1024), 2),
177
+ "created_at": datetime.fromtimestamp(stat.st_ctime),
178
+ "modified_at": datetime.fromtimestamp(stat.st_mtime),
179
+ "extension": path.suffix.lower(),
180
+ "exists": True,
176
181
  }
177
-
182
+
178
183
  except Exception as e:
179
184
  logger.error(f"Error getting file info for {frame_path}: {str(e)}")
180
185
  return None
181
186
 
182
187
 
183
- def calculate_anonymization_progress(total_frames: int, processed_frames: int,
184
- failed_frames: int) -> Dict:
188
+ def calculate_anonymization_progress(
189
+ total_frames: int, processed_frames: int, failed_frames: int
190
+ ) -> Dict:
185
191
  """
186
192
  Berechnet den Fortschritt der Anonymisierung.
187
-
193
+
188
194
  Args:
189
195
  total_frames: Gesamtzahl der Frames
190
196
  processed_frames: Anzahl verarbeiteter Frames
191
197
  failed_frames: Anzahl fehlgeschlagener Frames
192
-
198
+
193
199
  Returns:
194
200
  Dict mit Fortschrittsinformationen
195
201
  """
196
202
  if total_frames == 0:
197
203
  return {
198
- 'progress_percent': 0,
199
- 'completed_frames': 0,
200
- 'remaining_frames': 0,
201
- 'success_rate': 0,
202
- 'status': 'pending'
204
+ "progress_percent": 0,
205
+ "completed_frames": 0,
206
+ "remaining_frames": 0,
207
+ "success_rate": 0,
208
+ "status": "pending",
203
209
  }
204
-
210
+
205
211
  completed_frames = processed_frames + failed_frames
206
212
  progress_percent = (completed_frames / total_frames) * 100
207
- success_rate = (processed_frames / completed_frames * 100) if completed_frames > 0 else 0
208
-
213
+ success_rate = (
214
+ (processed_frames / completed_frames * 100) if completed_frames > 0 else 0
215
+ )
216
+
209
217
  # Status bestimmen
210
218
  if completed_frames == 0:
211
- status = 'pending'
219
+ status = "pending"
212
220
  elif completed_frames < total_frames:
213
- status = 'processing'
221
+ status = "processing"
214
222
  elif failed_frames == total_frames:
215
- status = 'failed'
223
+ status = "failed"
216
224
  else:
217
- status = 'completed'
218
-
225
+ status = "completed"
226
+
219
227
  return {
220
- 'progress_percent': round(progress_percent, 1),
221
- 'completed_frames': completed_frames,
222
- 'remaining_frames': total_frames - completed_frames,
223
- 'success_rate': round(success_rate, 1),
224
- 'status': status,
225
- 'total_frames': total_frames,
226
- 'processed_frames': processed_frames,
227
- 'failed_frames': failed_frames
228
+ "progress_percent": round(progress_percent, 1),
229
+ "completed_frames": completed_frames,
230
+ "remaining_frames": total_frames - completed_frames,
231
+ "success_rate": round(success_rate, 1),
232
+ "status": status,
233
+ "total_frames": total_frames,
234
+ "processed_frames": processed_frames,
235
+ "failed_frames": failed_frames,
228
236
  }
229
237
 
230
238
 
231
239
  def estimate_processing_time(total_frames: int, anonymization_level: str) -> Dict:
232
240
  """
233
241
  Schätzt die Verarbeitungszeit für die Anonymisierung.
234
-
242
+
235
243
  Args:
236
244
  total_frames: Anzahl der zu verarbeitenden Frames
237
245
  anonymization_level: Anonymisierungsgrad
238
-
246
+
239
247
  Returns:
240
248
  Dict mit Zeitschätzungen
241
249
  """
242
250
  # Geschätzte Verarbeitungszeit pro Frame (in Sekunden)
243
- time_per_frame = {
244
- 'minimal': 0.5,
245
- 'faces': 1.0,
246
- 'full': 0.8
247
- }
248
-
251
+ time_per_frame = {"minimal": 0.5, "faces": 1.0, "full": 0.8}
252
+
249
253
  base_time = time_per_frame.get(anonymization_level, 1.0)
250
254
  estimated_seconds = total_frames * base_time
251
-
255
+
252
256
  # Overhead für Setup und Cleanup
253
257
  overhead_seconds = min(30, total_frames * 0.1)
254
258
  total_seconds = estimated_seconds + overhead_seconds
255
-
259
+
256
260
  return {
257
- 'estimated_seconds': int(total_seconds),
258
- 'estimated_minutes': round(total_seconds / 60, 1),
259
- 'frames_per_second': round(1 / base_time, 1),
260
- 'anonymization_level': anonymization_level
261
+ "estimated_seconds": int(total_seconds),
262
+ "estimated_minutes": round(total_seconds / 60, 1),
263
+ "frames_per_second": round(1 / base_time, 1),
264
+ "anonymization_level": anonymization_level,
261
265
  }
262
266
 
263
267
 
264
268
  def cleanup_expired_tokens():
265
269
  """
266
270
  Bereinigt abgelaufene Download-Tokens.
267
-
271
+
268
272
  Returns:
269
273
  Anzahl bereinigter Tokens
270
274
  """
271
275
  try:
272
276
  from endoreg_db.models import AnonymousFrame
273
-
277
+
274
278
  # Frames mit abgelaufenen Tokens finden
275
279
  expired_frames = AnonymousFrame.objects.filter(
276
- download_expires_at__lt=timezone.now(),
277
- download_token_hash__isnull=False
280
+ download_expires_at__lt=timezone.now(), download_token_hash__isnull=False
278
281
  )
279
-
282
+
280
283
  count = expired_frames.count()
281
284
  expired_frames.update(download_token_hash=None, download_expires_at=None)
282
-
285
+
283
286
  logger.info(f"Cleaned up {count} expired download tokens")
284
287
  return count
285
-
288
+
286
289
  except Exception as e:
287
290
  logger.error(f"Error cleaning up expired tokens: {str(e)}")
288
291
  return 0
@@ -291,88 +294,83 @@ def cleanup_expired_tokens():
291
294
  def get_anonymization_statistics(video_id: Optional[int] = None) -> Dict:
292
295
  """
293
296
  Holt Statistiken zur Frame-Anonymisierung.
294
-
297
+
295
298
  Args:
296
299
  video_id: Optional - Video-ID für spezifische Statistiken
297
-
300
+
298
301
  Returns:
299
302
  Dict mit Statistiken
300
303
  """
301
304
  try:
302
305
  from endoreg_db.models import FrameAnonymizationRequest, AnonymousFrame
303
306
  from django.db.models import Count, Q
304
-
307
+
305
308
  # Basis-Queryset
306
309
  requests_qs = FrameAnonymizationRequest.objects.all()
307
310
  frames_qs = AnonymousFrame.objects.all()
308
-
311
+
309
312
  if video_id:
310
313
  requests_qs = requests_qs.filter(video_file_id=video_id)
311
314
  frames_qs = frames_qs.filter(video_file_id=video_id)
312
-
315
+
313
316
  # Request-Statistiken
314
317
  request_stats = requests_qs.aggregate(
315
- total_requests=Count('id'),
316
- pending_requests=Count('id', filter=Q(status='pending')),
317
- processing_requests=Count('id', filter=Q(status='processing')),
318
- completed_requests=Count('id', filter=Q(status='completed')),
319
- failed_requests=Count('id', filter=Q(status='failed'))
318
+ total_requests=Count("id"),
319
+ pending_requests=Count("id", filter=Q(status="pending")),
320
+ processing_requests=Count("id", filter=Q(status="processing")),
321
+ completed_requests=Count("id", filter=Q(status="completed")),
322
+ failed_requests=Count("id", filter=Q(status="failed")),
320
323
  )
321
-
324
+
322
325
  # Frame-Statistiken
323
326
  frame_stats = frames_qs.aggregate(
324
- total_frames=Count('id'),
325
- faces_anonymized=Count('id', filter=Q(anonymization_level='faces')),
326
- full_anonymized=Count('id', filter=Q(anonymization_level='full')),
327
- minimal_anonymized=Count('id', filter=Q(anonymization_level='minimal'))
327
+ total_frames=Count("id"),
328
+ faces_anonymized=Count("id", filter=Q(anonymization_level="faces")),
329
+ full_anonymized=Count("id", filter=Q(anonymization_level="full")),
330
+ minimal_anonymized=Count("id", filter=Q(anonymization_level="minimal")),
328
331
  )
329
-
332
+
330
333
  # Disk-Space Statistiken
331
334
  total_size = 0
332
- for frame in frames_qs.values_list('anonymized_frame_path', flat=True):
335
+ for frame in frames_qs.values_list("anonymized_frame_path", flat=True):
333
336
  file_info = get_frame_file_info(frame)
334
337
  if file_info:
335
- total_size += file_info['size_bytes']
336
-
338
+ total_size += file_info["size_bytes"]
339
+
337
340
  return {
338
- 'requests': request_stats,
339
- 'frames': frame_stats,
340
- 'storage': {
341
- 'total_size_bytes': total_size,
342
- 'total_size_mb': round(total_size / (1024 * 1024), 2)
341
+ "requests": request_stats,
342
+ "frames": frame_stats,
343
+ "storage": {
344
+ "total_size_bytes": total_size,
345
+ "total_size_mb": round(total_size / (1024 * 1024), 2),
343
346
  },
344
- 'video_id': video_id
347
+ "video_id": video_id,
345
348
  }
346
-
349
+
347
350
  except Exception as e:
348
351
  logger.error(f"Error getting anonymization statistics: {str(e)}")
349
- return {
350
- 'requests': {},
351
- 'frames': {},
352
- 'storage': {},
353
- 'error': str(e)
354
- }
352
+ return {"requests": {}, "frames": {}, "storage": {}, "error": str(e)}
355
353
 
356
354
 
357
355
  def validate_frame_path(frame_path: str) -> bool:
358
356
  """
359
357
  Validiert einen Frame-Pfad auf Sicherheit.
360
-
358
+
361
359
  Args:
362
360
  frame_path: Zu validierender Pfad
363
-
361
+
364
362
  Returns:
365
363
  True wenn Pfad sicher ist
366
364
  """
367
365
  try:
368
366
  path = Path(frame_path).resolve()
369
-
367
+
370
368
  # Basis-Verzeichnisse definieren
371
369
  allowed_dirs = [
372
370
  Path(settings.MEDIA_ROOT).resolve(),
373
- Path(getattr(settings, 'FRAME_STORAGE_ROOT', '/tmp')).resolve()
371
+ Path(getattr(settings, "FRAME_STORAGE_ROOT", "/tmp")).resolve(),
374
372
  ]
375
-
373
+
376
374
  # Prüfen ob Pfad in erlaubten Verzeichnissen liegt
377
375
  for allowed_dir in allowed_dirs:
378
376
  try:
@@ -380,10 +378,10 @@ def validate_frame_path(frame_path: str) -> bool:
380
378
  return True
381
379
  except ValueError:
382
380
  continue
383
-
381
+
384
382
  logger.warning(f"Frame path outside allowed directories: {frame_path}")
385
383
  return False
386
-
384
+
387
385
  except Exception as e:
388
386
  logger.error(f"Error validating frame path {frame_path}: {str(e)}")
389
387
  return False
@@ -392,32 +390,32 @@ def validate_frame_path(frame_path: str) -> bool:
392
390
  def get_video_frame_count(video_id: int) -> int:
393
391
  """
394
392
  Ermittelt die Anzahl verfügbarer Frames für ein Video.
395
-
393
+
396
394
  Args:
397
395
  video_id: Video-ID
398
-
396
+
399
397
  Returns:
400
398
  Anzahl der Frames
401
399
  """
402
400
  try:
403
401
  from endoreg_db.models import VideoFile
404
-
402
+
405
403
  video = VideoFile.objects.get(id=video_id)
406
-
404
+
407
405
  if not video.frame_dir:
408
406
  return 0
409
-
407
+
410
408
  frame_dir = Path(video.frame_dir)
411
409
  if not frame_dir.exists():
412
410
  return 0
413
-
411
+
414
412
  # Zähle alle Bilddateien
415
413
  frame_count = 0
416
- for ext in ['*.jpg', '*.jpeg', '*.png']:
414
+ for ext in ["*.jpg", "*.jpeg", "*.png"]:
417
415
  frame_count += len(list(frame_dir.glob(ext)))
418
-
416
+
419
417
  return frame_count
420
-
418
+
421
419
  except Exception as e:
422
420
  logger.error(f"Error counting frames for video {video_id}: {str(e)}")
423
421
  return 0
@@ -426,24 +424,26 @@ def get_video_frame_count(video_id: int) -> int:
426
424
  def format_file_size(size_bytes: int) -> str:
427
425
  """
428
426
  Formatiert Dateigröße in lesbares Format.
429
-
427
+
430
428
  Args:
431
429
  size_bytes: Größe in Bytes
432
-
430
+
433
431
  Returns:
434
432
  Formatierte Größe
435
433
  """
436
- for unit in ['B', 'KB', 'MB', 'GB']:
434
+ for unit in ["B", "KB", "MB", "GB"]:
437
435
  if size_bytes < 1024.0:
438
436
  return f"{size_bytes:.1f} {unit}"
439
437
  size_bytes /= 1024.0
440
438
  return f"{size_bytes:.1f} TB"
441
439
 
442
440
 
443
- def log_anonymization_activity(activity_type: str, details: Dict, user_id: Optional[int] = None):
441
+ def log_anonymization_activity(
442
+ activity_type: str, details: Dict, user_id: Optional[int] = None
443
+ ):
444
444
  """
445
445
  Protokolliert Anonymisierungsaktivitäten für Audit-Zwecke.
446
-
446
+
447
447
  Args:
448
448
  activity_type: Art der Aktivität
449
449
  details: Details der Aktivität
@@ -451,13 +451,13 @@ def log_anonymization_activity(activity_type: str, details: Dict, user_id: Optio
451
451
  """
452
452
  try:
453
453
  log_entry = {
454
- 'timestamp': timezone.now().isoformat(),
455
- 'activity_type': activity_type,
456
- 'details': details,
457
- 'user_id': user_id
454
+ "timestamp": timezone.now().isoformat(),
455
+ "activity_type": activity_type,
456
+ "details": details,
457
+ "user_id": user_id,
458
458
  }
459
-
459
+
460
460
  logger.info(f"Anonymization activity: {activity_type}", extra=log_entry)
461
-
461
+
462
462
  except Exception as e:
463
- logger.error(f"Error logging anonymization activity: {str(e)}")
463
+ logger.error(f"Error logging anonymization activity: {str(e)}")
endoreg_db/utils/hashs.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import hashlib
2
2
  from pathlib import Path
3
3
  from datetime import datetime, date
4
-
4
+ from endoreg_db.utils.file_operations import sha256_file
5
5
  import os
6
6
 
7
7
  SALT = os.getenv("DJANGO_SALT", "default_salt")
@@ -12,13 +12,7 @@ def get_video_hash(video_path):
12
12
  """
13
13
  Get the hash of a video file.
14
14
  """
15
- # Open the video file in read-binary mode:
16
- with open(video_path, "rb") as f:
17
- # Create the hash object, passing in the video contents for hashing:
18
- hash_object = hashlib.sha256(f.read())
19
- # Get the hexadecimal representation of the hash
20
- video_hash = hash_object.hexdigest()
21
- assert len(video_hash) <= 255, "Hash length exceeds 255 characters"
15
+ video_hash = sha256_file(video_path)
22
16
 
23
17
  return video_hash
24
18
 
@@ -27,17 +21,8 @@ def get_pdf_hash(pdf_path: Path):
27
21
  """
28
22
  Get the hash of a pdf file.
29
23
  """
30
- pdf_hash = None
31
-
32
- # Open the file in binary mode and read its contents
33
- with open(pdf_path, "rb") as f:
34
- pdf_contents = f.read()
35
- # Create a hash object using SHA-256 algorithm
36
24
 
37
- hash_object = hashlib.sha256(pdf_contents, usedforsecurity=False)
38
- # Get the hexadecimal representation of the hash
39
- pdf_hash = hash_object.hexdigest()
40
- assert len(pdf_hash) <= 255, "Hash length exceeds 255 characters"
25
+ pdf_hash = sha256_file(pdf_path)
41
26
 
42
27
  return pdf_hash
43
28