endoreg-db 0.8.9.2__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 (450) 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 +89 -122
  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/models/__init__.py +8 -0
  82. endoreg_db/models/administration/ai/active_model.py +5 -5
  83. endoreg_db/models/administration/ai/ai_model.py +41 -18
  84. endoreg_db/models/administration/ai/model_type.py +1 -0
  85. endoreg_db/models/administration/case/case.py +22 -22
  86. endoreg_db/models/administration/center/__init__.py +5 -5
  87. endoreg_db/models/administration/center/center.py +6 -2
  88. endoreg_db/models/administration/center/center_resource.py +18 -4
  89. endoreg_db/models/administration/center/center_shift.py +3 -1
  90. endoreg_db/models/administration/center/center_waste.py +6 -2
  91. endoreg_db/models/administration/person/__init__.py +1 -1
  92. endoreg_db/models/administration/person/employee/__init__.py +1 -1
  93. endoreg_db/models/administration/person/employee/employee_type.py +3 -1
  94. endoreg_db/models/administration/person/examiner/__init__.py +1 -1
  95. endoreg_db/models/administration/person/examiner/examiner.py +10 -2
  96. endoreg_db/models/administration/person/names/first_name.py +6 -4
  97. endoreg_db/models/administration/person/names/last_name.py +4 -3
  98. endoreg_db/models/administration/person/patient/__init__.py +1 -1
  99. endoreg_db/models/administration/person/patient/patient.py +0 -1
  100. endoreg_db/models/administration/person/patient/patient_external_id.py +0 -1
  101. endoreg_db/models/administration/person/person.py +1 -1
  102. endoreg_db/models/administration/product/__init__.py +7 -6
  103. endoreg_db/models/administration/product/product.py +6 -2
  104. endoreg_db/models/administration/product/product_group.py +9 -7
  105. endoreg_db/models/administration/product/product_material.py +9 -2
  106. endoreg_db/models/administration/product/reference_product.py +64 -15
  107. endoreg_db/models/administration/qualification/qualification.py +3 -1
  108. endoreg_db/models/administration/shift/shift.py +3 -1
  109. endoreg_db/models/administration/shift/shift_type.py +12 -4
  110. endoreg_db/models/aidataset/__init__.py +5 -0
  111. endoreg_db/models/aidataset/aidataset.py +193 -0
  112. endoreg_db/models/label/__init__.py +1 -1
  113. endoreg_db/models/label/label.py +10 -2
  114. endoreg_db/models/label/label_set.py +3 -1
  115. endoreg_db/models/label/label_video_segment/_create_from_video.py +6 -2
  116. endoreg_db/models/label/label_video_segment/label_video_segment.py +148 -44
  117. endoreg_db/models/media/__init__.py +12 -5
  118. endoreg_db/models/media/frame/__init__.py +1 -1
  119. endoreg_db/models/media/frame/frame.py +34 -8
  120. endoreg_db/models/media/pdf/__init__.py +2 -1
  121. endoreg_db/models/media/pdf/raw_pdf.py +11 -4
  122. endoreg_db/models/media/pdf/report_file.py +6 -2
  123. endoreg_db/models/media/pdf/report_reader/__init__.py +3 -3
  124. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +15 -5
  125. endoreg_db/models/media/video/create_from_file.py +20 -41
  126. endoreg_db/models/media/video/pipe_1.py +75 -30
  127. endoreg_db/models/media/video/pipe_2.py +37 -12
  128. endoreg_db/models/media/video/video_file.py +36 -24
  129. endoreg_db/models/media/video/video_file_ai.py +235 -70
  130. endoreg_db/models/media/video/video_file_anonymize.py +240 -65
  131. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -1
  132. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +3 -1
  133. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +30 -9
  134. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +95 -29
  135. endoreg_db/models/media/video/video_file_frames/_get_frame.py +13 -3
  136. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -1
  137. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +15 -3
  138. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +15 -3
  139. endoreg_db/models/media/video/video_file_frames/_get_frames.py +7 -2
  140. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +109 -23
  141. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +111 -27
  142. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +46 -13
  143. endoreg_db/models/media/video/video_file_io.py +85 -33
  144. endoreg_db/models/media/video/video_file_meta/__init__.py +6 -6
  145. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +17 -4
  146. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +28 -7
  147. endoreg_db/models/media/video/video_file_meta/get_fps.py +46 -13
  148. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +81 -20
  149. endoreg_db/models/media/video/video_file_meta/text_meta.py +61 -20
  150. endoreg_db/models/media/video/video_file_meta/video_meta.py +40 -12
  151. endoreg_db/models/media/video/video_file_segments.py +118 -27
  152. endoreg_db/models/media/video/video_metadata.py +25 -6
  153. endoreg_db/models/media/video/video_processing.py +54 -15
  154. endoreg_db/models/medical/__init__.py +3 -13
  155. endoreg_db/models/medical/contraindication/__init__.py +3 -1
  156. endoreg_db/models/medical/disease.py +18 -6
  157. endoreg_db/models/medical/event.py +6 -2
  158. endoreg_db/models/medical/examination/__init__.py +5 -1
  159. endoreg_db/models/medical/examination/examination.py +22 -6
  160. endoreg_db/models/medical/examination/examination_indication.py +23 -7
  161. endoreg_db/models/medical/examination/examination_time.py +6 -2
  162. endoreg_db/models/medical/finding/__init__.py +3 -1
  163. endoreg_db/models/medical/finding/finding.py +37 -12
  164. endoreg_db/models/medical/finding/finding_classification.py +27 -8
  165. endoreg_db/models/medical/finding/finding_intervention.py +19 -6
  166. endoreg_db/models/medical/finding/finding_type.py +3 -1
  167. endoreg_db/models/medical/hardware/__init__.py +1 -1
  168. endoreg_db/models/medical/hardware/endoscope.py +14 -2
  169. endoreg_db/models/medical/laboratory/__init__.py +1 -1
  170. endoreg_db/models/medical/laboratory/lab_value.py +139 -39
  171. endoreg_db/models/medical/medication/__init__.py +7 -3
  172. endoreg_db/models/medical/medication/medication.py +3 -1
  173. endoreg_db/models/medical/medication/medication_indication.py +3 -1
  174. endoreg_db/models/medical/medication/medication_indication_type.py +11 -3
  175. endoreg_db/models/medical/medication/medication_intake_time.py +3 -1
  176. endoreg_db/models/medical/medication/medication_schedule.py +3 -1
  177. endoreg_db/models/medical/patient/__init__.py +2 -10
  178. endoreg_db/models/medical/patient/medication_examples.py +3 -14
  179. endoreg_db/models/medical/patient/patient_disease.py +17 -5
  180. endoreg_db/models/medical/patient/patient_event.py +12 -4
  181. endoreg_db/models/medical/patient/patient_examination.py +52 -15
  182. endoreg_db/models/medical/patient/patient_examination_indication.py +15 -4
  183. endoreg_db/models/medical/patient/patient_finding.py +105 -29
  184. endoreg_db/models/medical/patient/patient_finding_classification.py +41 -12
  185. endoreg_db/models/medical/patient/patient_finding_intervention.py +11 -3
  186. endoreg_db/models/medical/patient/patient_lab_sample.py +6 -2
  187. endoreg_db/models/medical/patient/patient_lab_value.py +42 -10
  188. endoreg_db/models/medical/patient/patient_medication.py +25 -7
  189. endoreg_db/models/medical/patient/patient_medication_schedule.py +34 -10
  190. endoreg_db/models/metadata/model_meta.py +40 -12
  191. endoreg_db/models/metadata/model_meta_logic.py +51 -16
  192. endoreg_db/models/metadata/sensitive_meta.py +65 -28
  193. endoreg_db/models/metadata/sensitive_meta_logic.py +28 -26
  194. endoreg_db/models/metadata/video_meta.py +146 -39
  195. endoreg_db/models/metadata/video_prediction_logic.py +70 -21
  196. endoreg_db/models/metadata/video_prediction_meta.py +80 -27
  197. endoreg_db/models/operation_log.py +63 -0
  198. endoreg_db/models/other/__init__.py +10 -10
  199. endoreg_db/models/other/distribution/__init__.py +9 -7
  200. endoreg_db/models/other/distribution/base_value_distribution.py +3 -1
  201. endoreg_db/models/other/distribution/date_value_distribution.py +19 -5
  202. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +3 -1
  203. endoreg_db/models/other/distribution/numeric_value_distribution.py +34 -9
  204. endoreg_db/models/other/emission/__init__.py +1 -1
  205. endoreg_db/models/other/emission/emission_factor.py +9 -3
  206. endoreg_db/models/other/information_source.py +15 -5
  207. endoreg_db/models/other/material.py +3 -1
  208. endoreg_db/models/other/transport_route.py +3 -1
  209. endoreg_db/models/other/unit.py +6 -2
  210. endoreg_db/models/report/report.py +0 -1
  211. endoreg_db/models/requirement/requirement.py +84 -27
  212. endoreg_db/models/requirement/requirement_error.py +5 -6
  213. endoreg_db/models/requirement/requirement_evaluation/__init__.py +1 -1
  214. endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +8 -8
  215. endoreg_db/models/requirement/requirement_evaluation/get_values.py +3 -3
  216. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +24 -8
  217. endoreg_db/models/requirement/requirement_operator.py +28 -8
  218. endoreg_db/models/requirement/requirement_set.py +34 -11
  219. endoreg_db/models/state/__init__.py +1 -0
  220. endoreg_db/models/state/audit_ledger.py +9 -2
  221. endoreg_db/models/{media → state}/processing_history/__init__.py +1 -3
  222. endoreg_db/models/state/processing_history/processing_history.py +136 -0
  223. endoreg_db/models/state/raw_pdf.py +0 -1
  224. endoreg_db/models/state/video.py +2 -4
  225. endoreg_db/models/utils.py +4 -2
  226. endoreg_db/queries/__init__.py +2 -6
  227. endoreg_db/queries/annotations/__init__.py +1 -3
  228. endoreg_db/queries/annotations/legacy.py +37 -26
  229. endoreg_db/root_urls.py +3 -4
  230. endoreg_db/schemas/examination_evaluation.py +3 -0
  231. endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +249 -163
  232. endoreg_db/serializers/__init__.py +2 -8
  233. endoreg_db/serializers/administration/__init__.py +1 -2
  234. endoreg_db/serializers/administration/ai/__init__.py +0 -1
  235. endoreg_db/serializers/administration/ai/active_model.py +3 -1
  236. endoreg_db/serializers/administration/ai/ai_model.py +5 -3
  237. endoreg_db/serializers/administration/ai/model_type.py +3 -1
  238. endoreg_db/serializers/administration/center.py +7 -2
  239. endoreg_db/serializers/administration/gender.py +4 -2
  240. endoreg_db/serializers/anonymization.py +13 -13
  241. endoreg_db/serializers/evaluation/examination_evaluation.py +0 -1
  242. endoreg_db/serializers/examination/__init__.py +1 -1
  243. endoreg_db/serializers/examination/base.py +12 -13
  244. endoreg_db/serializers/examination/dropdown.py +6 -7
  245. endoreg_db/serializers/examination_serializer.py +3 -6
  246. endoreg_db/serializers/finding/__init__.py +1 -1
  247. endoreg_db/serializers/finding/finding.py +14 -7
  248. endoreg_db/serializers/finding_classification/__init__.py +3 -3
  249. endoreg_db/serializers/finding_classification/choice.py +3 -3
  250. endoreg_db/serializers/finding_classification/classification.py +2 -4
  251. endoreg_db/serializers/label_video_segment/__init__.py +5 -3
  252. endoreg_db/serializers/{label → label_video_segment}/image_classification_annotation.py +5 -5
  253. endoreg_db/serializers/label_video_segment/label/__init__.py +6 -0
  254. endoreg_db/serializers/{label → label_video_segment/label}/label.py +1 -1
  255. endoreg_db/serializers/label_video_segment/label_video_segment.py +338 -228
  256. endoreg_db/serializers/meta/__init__.py +1 -2
  257. endoreg_db/serializers/meta/sensitive_meta_detail.py +28 -13
  258. endoreg_db/serializers/meta/sensitive_meta_update.py +51 -46
  259. endoreg_db/serializers/meta/sensitive_meta_verification.py +19 -16
  260. endoreg_db/serializers/misc/__init__.py +2 -2
  261. endoreg_db/serializers/misc/file_overview.py +11 -7
  262. endoreg_db/serializers/misc/stats.py +10 -8
  263. endoreg_db/serializers/misc/translatable_field_mix_in.py +6 -6
  264. endoreg_db/serializers/misc/upload_job.py +32 -29
  265. endoreg_db/serializers/patient/__init__.py +2 -1
  266. endoreg_db/serializers/patient/patient.py +32 -15
  267. endoreg_db/serializers/patient/patient_dropdown.py +11 -3
  268. endoreg_db/serializers/patient_examination/__init__.py +1 -1
  269. endoreg_db/serializers/patient_examination/patient_examination.py +67 -40
  270. endoreg_db/serializers/patient_finding/__init__.py +1 -1
  271. endoreg_db/serializers/patient_finding/patient_finding.py +2 -1
  272. endoreg_db/serializers/patient_finding/patient_finding_classification.py +17 -9
  273. endoreg_db/serializers/patient_finding/patient_finding_detail.py +26 -17
  274. endoreg_db/serializers/patient_finding/patient_finding_intervention.py +7 -5
  275. endoreg_db/serializers/patient_finding/patient_finding_list.py +10 -11
  276. endoreg_db/serializers/patient_finding/patient_finding_write.py +36 -27
  277. endoreg_db/serializers/pdf/__init__.py +1 -3
  278. endoreg_db/serializers/requirements/requirement_schema.py +1 -6
  279. endoreg_db/serializers/sensitive_meta_serializer.py +100 -81
  280. endoreg_db/serializers/video/__init__.py +2 -2
  281. endoreg_db/serializers/video/{segmentation.py → video_file.py} +66 -47
  282. endoreg_db/serializers/video/video_file_brief.py +6 -2
  283. endoreg_db/serializers/video/video_file_detail.py +36 -23
  284. endoreg_db/serializers/video/video_file_list.py +4 -2
  285. endoreg_db/serializers/video/video_processing_history.py +54 -50
  286. endoreg_db/services/__init__.py +1 -1
  287. endoreg_db/services/anonymization.py +2 -2
  288. endoreg_db/services/examination_evaluation.py +40 -17
  289. endoreg_db/services/model_meta_from_hf.py +76 -0
  290. endoreg_db/services/polling_coordinator.py +101 -70
  291. endoreg_db/services/pseudonym_service.py +27 -22
  292. endoreg_db/services/report_import.py +6 -3
  293. endoreg_db/services/segment_sync.py +75 -59
  294. endoreg_db/services/video_import.py +6 -7
  295. endoreg_db/urls/__init__.py +2 -2
  296. endoreg_db/urls/ai.py +7 -25
  297. endoreg_db/urls/anonymization.py +61 -15
  298. endoreg_db/urls/auth.py +4 -4
  299. endoreg_db/urls/classification.py +4 -9
  300. endoreg_db/urls/examination.py +27 -18
  301. endoreg_db/urls/media.py +27 -34
  302. endoreg_db/urls/patient.py +11 -7
  303. endoreg_db/urls/requirements.py +3 -1
  304. endoreg_db/urls/root_urls.py +2 -3
  305. endoreg_db/urls/stats.py +24 -16
  306. endoreg_db/urls/upload.py +3 -11
  307. endoreg_db/utils/__init__.py +14 -15
  308. endoreg_db/utils/ai/__init__.py +1 -1
  309. endoreg_db/utils/ai/data_loader_for_model_input.py +262 -0
  310. endoreg_db/utils/ai/data_loader_for_model_training.py +262 -0
  311. endoreg_db/utils/ai/get.py +2 -1
  312. endoreg_db/utils/ai/inference_dataset.py +14 -15
  313. endoreg_db/utils/ai/model_training/config.py +117 -0
  314. endoreg_db/utils/ai/model_training/dataset.py +74 -0
  315. endoreg_db/utils/ai/model_training/losses.py +68 -0
  316. endoreg_db/utils/ai/model_training/metrics.py +78 -0
  317. endoreg_db/utils/ai/model_training/model_backbones.py +155 -0
  318. endoreg_db/utils/ai/model_training/model_gastronet_resnet.py +118 -0
  319. endoreg_db/utils/ai/model_training/trainer_gastronet_multilabel.py +771 -0
  320. endoreg_db/utils/ai/multilabel_classification_net.py +21 -6
  321. endoreg_db/utils/ai/predict.py +4 -4
  322. endoreg_db/utils/ai/preprocess.py +19 -11
  323. endoreg_db/utils/calc_duration_seconds.py +4 -4
  324. endoreg_db/utils/case_generator/lab_sample_factory.py +3 -4
  325. endoreg_db/utils/check_video_files.py +74 -47
  326. endoreg_db/utils/cropping.py +10 -9
  327. endoreg_db/utils/dataloader.py +11 -3
  328. endoreg_db/utils/dates.py +3 -4
  329. endoreg_db/utils/defaults/set_default_center.py +7 -6
  330. endoreg_db/utils/env.py +6 -2
  331. endoreg_db/utils/extract_specific_frames.py +24 -9
  332. endoreg_db/utils/file_operations.py +30 -18
  333. endoreg_db/utils/fix_video_path_direct.py +57 -41
  334. endoreg_db/utils/frame_anonymization_utils.py +157 -157
  335. endoreg_db/utils/hashs.py +3 -18
  336. endoreg_db/utils/links/requirement_link.py +96 -52
  337. endoreg_db/utils/ocr.py +30 -25
  338. endoreg_db/utils/operation_log.py +61 -0
  339. endoreg_db/utils/parse_and_generate_yaml.py +12 -13
  340. endoreg_db/utils/paths.py +6 -6
  341. endoreg_db/utils/permissions.py +40 -24
  342. endoreg_db/utils/pipelines/process_video_dir.py +50 -26
  343. endoreg_db/utils/product/sum_emissions.py +5 -3
  344. endoreg_db/utils/product/sum_weights.py +4 -2
  345. endoreg_db/utils/pydantic_models/__init__.py +3 -4
  346. endoreg_db/utils/requirement_operator_logic/_old/lab_value_operators.py +207 -107
  347. endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +252 -65
  348. endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +27 -10
  349. endoreg_db/utils/setup_config.py +21 -5
  350. endoreg_db/utils/storage.py +3 -1
  351. endoreg_db/utils/translation.py +19 -15
  352. endoreg_db/utils/uuid.py +1 -0
  353. endoreg_db/utils/validate_endo_roi.py +12 -4
  354. endoreg_db/utils/validate_subcategory_dict.py +26 -24
  355. endoreg_db/utils/validate_video_detailed.py +207 -149
  356. endoreg_db/utils/video/__init__.py +7 -3
  357. endoreg_db/utils/video/extract_frames.py +30 -18
  358. endoreg_db/utils/video/names.py +11 -6
  359. endoreg_db/utils/video/streaming_processor.py +175 -101
  360. endoreg_db/utils/video/video_splitter.py +30 -19
  361. endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +59 -50
  362. endoreg_db/views/__init__.py +0 -20
  363. endoreg_db/views/anonymization/__init__.py +6 -2
  364. endoreg_db/views/anonymization/media_management.py +2 -6
  365. endoreg_db/views/anonymization/overview.py +34 -1
  366. endoreg_db/views/anonymization/validate.py +79 -18
  367. endoreg_db/views/auth/__init__.py +1 -1
  368. endoreg_db/views/auth/keycloak.py +16 -14
  369. endoreg_db/views/examination/__init__.py +12 -15
  370. endoreg_db/views/examination/examination.py +5 -5
  371. endoreg_db/views/examination/examination_manifest_cache.py +5 -5
  372. endoreg_db/views/examination/get_finding_classification_choices.py +8 -5
  373. endoreg_db/views/examination/get_finding_classifications.py +9 -7
  374. endoreg_db/views/examination/get_findings.py +8 -10
  375. endoreg_db/views/examination/get_instruments.py +3 -2
  376. endoreg_db/views/examination/get_interventions.py +1 -1
  377. endoreg_db/views/finding/__init__.py +2 -2
  378. endoreg_db/views/finding/finding.py +58 -54
  379. endoreg_db/views/finding/get_classifications.py +1 -1
  380. endoreg_db/views/finding/get_interventions.py +1 -1
  381. endoreg_db/views/finding_classification/__init__.py +5 -5
  382. endoreg_db/views/finding_classification/finding_classification.py +5 -6
  383. endoreg_db/views/finding_classification/get_classification_choices.py +3 -4
  384. endoreg_db/views/media/__init__.py +13 -13
  385. endoreg_db/views/media/pdf_media.py +9 -9
  386. endoreg_db/views/media/sensitive_metadata.py +10 -7
  387. endoreg_db/views/media/video_media.py +4 -4
  388. endoreg_db/views/meta/__init__.py +1 -1
  389. endoreg_db/views/meta/sensitive_meta_list.py +20 -22
  390. endoreg_db/views/meta/sensitive_meta_verification.py +14 -11
  391. endoreg_db/views/misc/__init__.py +6 -34
  392. endoreg_db/views/misc/center.py +2 -1
  393. endoreg_db/views/misc/csrf.py +2 -1
  394. endoreg_db/views/misc/gender.py +2 -1
  395. endoreg_db/views/misc/stats.py +141 -106
  396. endoreg_db/views/patient/__init__.py +1 -3
  397. endoreg_db/views/patient/patient.py +141 -99
  398. endoreg_db/views/patient_examination/__init__.py +5 -5
  399. endoreg_db/views/patient_examination/patient_examination.py +43 -42
  400. endoreg_db/views/patient_examination/patient_examination_create.py +10 -15
  401. endoreg_db/views/patient_examination/patient_examination_detail.py +12 -15
  402. endoreg_db/views/patient_examination/patient_examination_list.py +21 -17
  403. endoreg_db/views/patient_examination/video.py +114 -80
  404. endoreg_db/views/patient_finding/__init__.py +1 -1
  405. endoreg_db/views/patient_finding/patient_finding.py +17 -10
  406. endoreg_db/views/patient_finding/patient_finding_optimized.py +127 -95
  407. endoreg_db/views/patient_finding_classification/__init__.py +1 -1
  408. endoreg_db/views/patient_finding_classification/pfc_create.py +35 -27
  409. endoreg_db/views/report/reimport.py +1 -1
  410. endoreg_db/views/report/report_stream.py +5 -8
  411. endoreg_db/views/requirement/__init__.py +2 -1
  412. endoreg_db/views/requirement/evaluate.py +7 -9
  413. endoreg_db/views/requirement/lookup.py +2 -3
  414. endoreg_db/views/requirement/lookup_store.py +0 -1
  415. endoreg_db/views/requirement/requirement_utils.py +2 -4
  416. endoreg_db/views/stats/__init__.py +4 -4
  417. endoreg_db/views/stats/stats_views.py +152 -115
  418. endoreg_db/views/video/__init__.py +18 -27
  419. endoreg_db/views/{ai → video/ai}/__init__.py +2 -2
  420. endoreg_db/views/{ai → video/ai}/label.py +20 -16
  421. endoreg_db/views/video/correction.py +5 -6
  422. endoreg_db/views/video/reimport.py +134 -99
  423. endoreg_db/views/video/segments_crud.py +134 -44
  424. endoreg_db/views/video/video_apply_mask.py +13 -12
  425. endoreg_db/views/video/video_correction.py +2 -1
  426. endoreg_db/views/video/video_download_processed.py +15 -15
  427. endoreg_db/views/video/video_meta_stats.py +7 -6
  428. endoreg_db/views/video/video_processing_history.py +3 -2
  429. endoreg_db/views/video/video_remove_frames.py +13 -12
  430. endoreg_db/views/video/video_stream.py +110 -82
  431. {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/METADATA +9 -3
  432. {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/RECORD +434 -431
  433. endoreg_db/management/commands/import_fallback_video.py +0 -203
  434. endoreg_db/management/commands/import_video.py +0 -422
  435. endoreg_db/management/commands/import_video_with_classification.py +0 -367
  436. endoreg_db/models/media/processing_history/processing_history.py +0 -96
  437. endoreg_db/serializers/label/__init__.py +0 -7
  438. endoreg_db/serializers/label_video_segment/_lvs_create.py +0 -149
  439. endoreg_db/serializers/label_video_segment/_lvs_update.py +0 -138
  440. endoreg_db/serializers/label_video_segment/_lvs_validate.py +0 -149
  441. endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +0 -99
  442. endoreg_db/serializers/label_video_segment/label_video_segment_update.py +0 -163
  443. endoreg_db/services/__old/pdf_import.py +0 -1487
  444. endoreg_db/services/__old/video_import.py +0 -1306
  445. endoreg_db/tasks/upload_tasks.py +0 -216
  446. endoreg_db/tasks/video_ingest.py +0 -161
  447. endoreg_db/tasks/video_processing_tasks.py +0 -327
  448. endoreg_db/views/misc/translation.py +0 -182
  449. {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/WHEEL +0 -0
  450. {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/licenses/LICENSE +0 -0
@@ -1,31 +1,39 @@
1
- from typing import List, Optional, TYPE_CHECKING # Modified import
1
+ from typing import List, Optional, TYPE_CHECKING # Modified import
2
2
 
3
3
  from pydantic import BaseModel, Field
4
4
 
5
5
  from endoreg_db.models import (
6
- PatientDisease, Disease, DiseaseClassificationChoice,
7
- Event,
8
- PatientEvent, Examination, ExaminationIndication, ExaminationIndicationClassificationChoice,
9
- PatientExamination, PatientExaminationIndication,
6
+ PatientDisease,
7
+ Disease,
8
+ DiseaseClassificationChoice,
9
+ Event,
10
+ PatientEvent,
11
+ Examination,
12
+ ExaminationIndication,
13
+ ExaminationIndicationClassificationChoice,
14
+ PatientExamination,
15
+ PatientExaminationIndication,
10
16
  PatientFinding,
11
- Finding,
12
- FindingIntervention,
17
+ Finding,
18
+ FindingIntervention,
13
19
  FindingClassification,
14
- FindingClassificationChoice,
20
+ FindingClassificationChoice,
15
21
  LabValue,
16
22
  PatientLabValue,
17
23
  PatientLabSample,
18
24
  PatientLabSampleType,
19
- PatientMedication, # Added
20
- PatientMedicationSchedule, # Added
21
- Medication, # Added
22
- MedicationIndication, # Added
23
- MedicationIntakeTime, # Added
24
- MedicationSchedule, # Added
25
+ PatientMedication, # Added
26
+ PatientMedicationSchedule, # Added
27
+ Medication, # Added
28
+ MedicationIndication, # Added
29
+ MedicationIntakeTime, # Added
30
+ MedicationSchedule, # Added
25
31
  )
26
- if TYPE_CHECKING: # Added for Patient import
32
+
33
+ if TYPE_CHECKING: # Added for Patient import
27
34
  from endoreg_db.models.administration.person.patient import Patient
28
35
 
36
+
29
37
  class RequirementLinks(BaseModel):
30
38
  """
31
39
  A class representing a dictionary of models related to a requirement.
@@ -45,34 +53,49 @@ class RequirementLinks(BaseModel):
45
53
  finding_location_classification_choices (List[FindingLocationClassificationChoice]): A List of finding location classification choices.
46
54
  finding_interventions (List[FindingIntervention]): A List of finding interventions.
47
55
  """
56
+
48
57
  model_config = {"arbitrary_types_allowed": True}
49
- #
58
+ #
50
59
  # requirement_types: Optional[List["RequirementType"]] = None
51
60
  # operators: Optional[List["RequirementOperator"]] = None
52
61
  # The following model import causes circular import
53
- #requirement_sets: Optional[List["RequirementSet"]] = None
62
+ # requirement_sets: Optional[List["RequirementSet"]] = None
54
63
  examinations: List["Examination"] = Field(default_factory=list)
55
64
  examination_indications: List["ExaminationIndication"] = Field(default_factory=list)
56
- examination_indication_classification_choices: List["ExaminationIndicationClassificationChoice"] = Field(default_factory=list)
65
+ examination_indication_classification_choices: List[
66
+ "ExaminationIndicationClassificationChoice"
67
+ ] = Field(default_factory=list)
57
68
  patient_examinations: List["PatientExamination"] = Field(default_factory=list)
58
-
59
- patient_examination_indication: List["PatientExaminationIndication"] = Field(default_factory=list)
69
+
70
+ patient_examination_indication: List["PatientExaminationIndication"] = Field(
71
+ default_factory=list
72
+ )
60
73
  lab_values: List["LabValue"] = Field(default_factory=list)
61
74
  patient_lab_values: List["PatientLabValue"] = Field(default_factory=list)
62
75
  patient_lab_samples: List["PatientLabSample"] = Field(default_factory=list)
63
76
  patient_diseases: List["PatientDisease"] = Field(default_factory=list)
64
77
  diseases: List["Disease"] = Field(default_factory=list)
65
- disease_classification_choices: List["DiseaseClassificationChoice"] = Field(default_factory=list)
78
+ disease_classification_choices: List["DiseaseClassificationChoice"] = Field(
79
+ default_factory=list
80
+ )
66
81
  events: List["Event"] = Field(default_factory=list)
67
82
  patient_events: List["PatientEvent"] = Field(default_factory=list)
68
83
  patient_findings: List["PatientFinding"] = Field(default_factory=list)
69
84
  findings: List["Finding"] = Field(default_factory=list)
70
- finding_classification_choices: List["FindingClassificationChoice"] = Field(default_factory=list)
71
- finding_classifications: List["FindingClassification"] = Field(default_factory=list) # Added for direct classification checks if needed
85
+ finding_classification_choices: List["FindingClassificationChoice"] = Field(
86
+ default_factory=list
87
+ )
88
+ finding_classifications: List["FindingClassification"] = Field(
89
+ default_factory=list
90
+ ) # Added for direct classification checks if needed
72
91
  finding_interventions: List["FindingIntervention"] = Field(default_factory=list)
73
92
  patient_lab_sample_types: List["PatientLabSampleType"] = Field(default_factory=list)
74
- patient_medications: List["PatientMedication"] = Field(default_factory=list) # Added
75
- patient_medication_schedules: List["PatientMedicationSchedule"] = Field(default_factory=list) # Added
93
+ patient_medications: List["PatientMedication"] = Field(
94
+ default_factory=list
95
+ ) # Added
96
+ patient_medication_schedules: List["PatientMedicationSchedule"] = Field(
97
+ default_factory=list
98
+ ) # Added
76
99
  # Added direct medication-related fields
77
100
  medications: List["Medication"] = Field(default_factory=list)
78
101
  medication_indications: List["MedicationIndication"] = Field(default_factory=list)
@@ -87,38 +110,42 @@ class RequirementLinks(BaseModel):
87
110
  """
88
111
  if self.patient_lab_values:
89
112
  for plv in self.patient_lab_values:
90
- if hasattr(plv, 'sample') and plv.sample and \
91
- hasattr(plv.sample, 'patient') and plv.sample.patient:
113
+ if (
114
+ hasattr(plv, "sample")
115
+ and plv.sample
116
+ and hasattr(plv.sample, "patient")
117
+ and plv.sample.patient
118
+ ):
92
119
  return plv.sample.patient
93
120
  if self.patient_lab_samples:
94
121
  for pls in self.patient_lab_samples:
95
- if hasattr(pls, 'patient') and pls.patient:
122
+ if hasattr(pls, "patient") and pls.patient:
96
123
  return pls.patient
97
124
  if self.patient_examinations:
98
125
  for pe in self.patient_examinations:
99
- if hasattr(pe, 'patient') and pe.patient:
126
+ if hasattr(pe, "patient") and pe.patient:
100
127
  return pe.patient
101
128
  if self.patient_diseases:
102
129
  for pd in self.patient_diseases:
103
- if hasattr(pd, 'patient') and pd.patient:
130
+ if hasattr(pd, "patient") and pd.patient:
104
131
  return pd.patient
105
132
  if self.patient_events:
106
133
  for pev in self.patient_events:
107
- if hasattr(pev, 'patient') and pev.patient:
134
+ if hasattr(pev, "patient") and pev.patient:
108
135
  return pev.patient
109
136
  if self.patient_findings:
110
137
  for pf in self.patient_findings:
111
- if hasattr(pf, 'patient') and pf.patient:
138
+ if hasattr(pf, "patient") and pf.patient:
112
139
  return pf.patient
113
140
  # Check PatientMedication
114
141
  if self.patient_medications:
115
142
  for pm in self.patient_medications:
116
- if hasattr(pm, 'patient') and pm.patient:
143
+ if hasattr(pm, "patient") and pm.patient:
117
144
  return pm.patient
118
145
  # Check PatientMedicationSchedule
119
146
  if self.patient_medication_schedules:
120
147
  for pms in self.patient_medication_schedules:
121
- if hasattr(pms, 'patient') and pms.patient:
148
+ if hasattr(pms, "patient") and pms.patient:
122
149
  return pms.patient
123
150
  return None
124
151
 
@@ -126,32 +153,37 @@ class RequirementLinks(BaseModel):
126
153
  def data_model_dict(self):
127
154
  """
128
155
  Provides access to the data model dictionary used for requirement type parsing.
129
-
156
+
130
157
  Returns:
131
158
  The `data_model_dict` imported from the requirement type parser module.
132
159
  """
133
- from endoreg_db.models.requirement.requirement_evaluation.requirement_type_parser import data_model_dict
160
+ from endoreg_db.models.requirement.requirement_evaluation.requirement_type_parser import (
161
+ data_model_dict,
162
+ )
163
+
134
164
  return data_model_dict
135
165
 
136
166
  @property
137
167
  def data_model_dict_reverse(self):
138
168
  """
139
169
  Provides a reverse mapping dictionary for data model types used in requirement evaluation.
140
-
170
+
141
171
  Returns:
142
172
  The `data_model_dict_reverse` dictionary imported from the requirement type parser module.
143
173
  """
144
- from endoreg_db.models.requirement.requirement_evaluation.requirement_type_parser import data_model_dict_reverse
174
+ from endoreg_db.models.requirement.requirement_evaluation.requirement_type_parser import (
175
+ data_model_dict_reverse,
176
+ )
145
177
 
146
178
  return data_model_dict_reverse
147
179
 
148
- def match_any(self, other:"RequirementLinks") -> bool:
180
+ def match_any(self, other: "RequirementLinks") -> bool:
149
181
  """
150
182
  Determines if any linked model in this instance is also present in another RequirementLinks instance.
151
-
183
+
152
184
  Compares each list attribute of both instances and returns True if any element in any list overlaps.
153
185
  """
154
-
186
+
155
187
  other_dict = other.model_dump()
156
188
  self_dict = self.model_dump()
157
189
  for key in self_dict:
@@ -159,12 +191,12 @@ class RequirementLinks(BaseModel):
159
191
  if key in other_dict and self_dict[key] and other_dict[key]:
160
192
  if any(item in other_dict[key] for item in self_dict[key]):
161
193
  return True
162
- return False # Ensure False is returned if no match is found
163
-
194
+ return False # Ensure False is returned if no match is found
195
+
164
196
  def active(self) -> dict[str, list]:
165
197
  """
166
198
  Returns a dictionary of all non-empty linked model lists.
167
-
199
+
168
200
  Only attributes with non-empty lists are included in the returned dictionary.
169
201
  """
170
202
  active_links_dict = {}
@@ -180,14 +212,26 @@ class RequirementLinks(BaseModel):
180
212
  """
181
213
  data = self.model_dump()
182
214
  fields = [
183
- 'examinations', 'examination_indications', 'patient_examinations',
184
- 'lab_values', 'patient_lab_values', 'patient_diseases', 'diseases',
185
- 'disease_classification_choices', 'events', 'patient_events', 'findings',
186
- 'patient_findings', 'finding_classification_choices', 'finding_interventions',
187
- 'patient_medications', 'patient_medication_schedules', 'medications',
188
- 'medication_indications', 'medication_intake_times', 'medication_schedules'
215
+ "examinations",
216
+ "examination_indications",
217
+ "patient_examinations",
218
+ "lab_values",
219
+ "patient_lab_values",
220
+ "patient_diseases",
221
+ "diseases",
222
+ "disease_classification_choices",
223
+ "events",
224
+ "patient_events",
225
+ "findings",
226
+ "patient_findings",
227
+ "finding_classification_choices",
228
+ "finding_interventions",
229
+ "patient_medications",
230
+ "patient_medication_schedules",
231
+ "medications",
232
+ "medication_indications",
233
+ "medication_intake_times",
234
+ "medication_schedules",
189
235
  ]
190
236
  parts = [f"{f}={len(data.get(f, []))}" for f in fields]
191
237
  return f"RequirementLinks({', '.join(parts)})"
192
-
193
-
endoreg_db/utils/ocr.py CHANGED
@@ -1,18 +1,18 @@
1
1
  import pytesseract
2
- from PIL import Image, ImageOps, ImageFilter
2
+ from PIL import Image, ImageOps
3
+ import cv2
3
4
  import os
4
5
  from collections import Counter
5
6
  from tempfile import TemporaryDirectory
6
7
  import re
7
8
  from datetime import datetime
8
9
  from typing import Dict, List
9
- import numpy as np
10
10
  from endoreg_db.utils.cropping import crop_and_insert
11
11
 
12
12
 
13
-
14
13
  N_FRAMES_MEAN_OCR = 2
15
14
 
15
+
16
16
  # Helper function to process date strings
17
17
  def process_date_text(date_text):
18
18
  """
@@ -26,7 +26,7 @@ def process_date_text(date_text):
26
26
  """
27
27
  try:
28
28
  # Remove any non-digit characters
29
- date_text_clean = re.sub(r'\D', '', date_text)
29
+ date_text_clean = re.sub(r"\D", "", date_text)
30
30
  # Reformat to 'ddmmyyyy' if necessary
31
31
  if len(date_text_clean) == 8:
32
32
  return datetime.strptime(date_text_clean, "%d%m%Y").date()
@@ -37,14 +37,15 @@ def process_date_text(date_text):
37
37
  # set date to 1/1/1900
38
38
  return datetime.strptime("01011900", "%d%m%Y").date()
39
39
 
40
+
40
41
  # Helper function to process patient names
41
42
  def process_name_text(name_text):
42
43
  """
43
44
  Remove all numbers, punctuation, and whitespace from a string of text and return the result.
44
45
  """
45
- name = re.sub(r'[0-9!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~\s]+', '', name_text).strip()
46
+ name = re.sub(r'[0-9!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~\s]+', "", name_text).strip()
46
47
  # capitalize first letter of each word
47
- name = ' '.join([word.capitalize() for word in name.split()])
48
+ name = " ".join([word.capitalize() for word in name.split()])
48
49
  return name
49
50
 
50
51
 
@@ -53,7 +54,8 @@ def process_general_text(endoscope_text):
53
54
  """
54
55
  This function takes in a string of text from an endoscope and returns a cleaned version of the text.
55
56
  """
56
- return ' '.join(endoscope_text.split())
57
+ return " ".join(endoscope_text.split())
58
+
57
59
 
58
60
  def roi_values_valid(roi):
59
61
  """
@@ -61,6 +63,7 @@ def roi_values_valid(roi):
61
63
  """
62
64
  return all([value >= 0 for value in roi.values()])
63
65
 
66
+
64
67
  # Function to extract text from ROIs
65
68
  def extract_text_from_rois(image_path, processor):
66
69
  """
@@ -75,11 +78,11 @@ def extract_text_from_rois(image_path, processor):
75
78
  """
76
79
  # Read the image using Pillow
77
80
  image = Image.open(image_path)
78
- image_dimensions = image.size # (width, height)
81
+ image_dimensions = image.size # (width, height)
79
82
 
80
83
  ####### Adjust Image #######
81
84
  # Convert to grayscale
82
- gray = image.convert('L')
85
+ gray = image.convert("L")
83
86
 
84
87
  # Invert colors for white text on black background
85
88
  inverted = ImageOps.invert(gray)
@@ -89,36 +92,36 @@ def extract_text_from_rois(image_path, processor):
89
92
 
90
93
  # Define your ROIs and their corresponding post-processing functions in tuples
91
94
  rois_with_postprocessing = [
92
- ('examination_date', processor.get_roi_examination_date, process_date_text),
95
+ ("examination_date", processor.get_roi_examination_date, process_date_text),
93
96
  ("patient_first_name", processor.get_roi_patient_first_name, process_name_text),
94
- ('patient_last_name', processor.get_roi_patient_last_name, process_name_text),
95
- ('patient_dob', processor.get_roi_patient_dob, process_date_text),
96
- ('endoscope_type', processor.get_roi_endoscope_type, process_general_text),
97
- ('endoscope_sn', processor.get_roi_endoscopy_sn, process_general_text),
97
+ ("patient_last_name", processor.get_roi_patient_last_name, process_name_text),
98
+ ("patient_dob", processor.get_roi_patient_dob, process_date_text),
99
+ ("endoscope_type", processor.get_roi_endoscope_type, process_general_text),
100
+ ("endoscope_sn", processor.get_roi_endoscopy_sn, process_general_text),
98
101
  ]
99
102
 
100
103
  # Extract and post-process text for each ROI
101
104
  for roi_name, roi_function, post_process in rois_with_postprocessing:
102
105
  # Get the ROI dictionary
103
106
  roi = roi_function()
104
-
107
+
105
108
  # Check if the ROI has values
106
-
109
+
107
110
  if roi_values_valid(roi):
108
- x, y, w, h = roi['x'], roi['y'], roi['width'], roi['height']
109
-
111
+ x, y, w, h = roi["x"], roi["y"], roi["width"], roi["height"]
112
+
110
113
  # Get white image with original shape and just the roi remaining
111
- roi_image = crop_and_insert(inverted, x,y,h,w)
114
+ roi_image = crop_and_insert(inverted, x, y, h, w)
112
115
 
113
116
  # OCR configuration: Recognize white text on black background without corrections
114
- config = '--psm 10 -c tessedit_char_whitelist=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-üöäÜÖÄß'
117
+ config = "--psm 10 -c tessedit_char_whitelist=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-üöäÜÖÄß"
115
118
 
116
119
  # Use pytesseract to do OCR on the preprocessed ROI
117
120
  text = pytesseract.image_to_string(roi_image, config=config).strip()
118
121
 
119
122
  # Post-process extracted text
120
123
  processed_text = post_process(text)
121
-
124
+
122
125
  extracted_texts[roi_name] = processed_text
123
126
 
124
127
  else:
@@ -126,6 +129,7 @@ def extract_text_from_rois(image_path, processor):
126
129
 
127
130
  return extracted_texts
128
131
 
132
+
129
133
  def get_most_frequent_values(rois_texts: Dict[str, List[str]]) -> Dict[str, str]:
130
134
  """
131
135
  Given a dictionary of ROIs and their corresponding texts, returns a dictionary of the most frequent text for each ROI.
@@ -142,6 +146,7 @@ def get_most_frequent_values(rois_texts: Dict[str, List[str]]) -> Dict[str, str]
142
146
  most_frequent[key], _ = counter.most_common(1)[0] if counter else (None, None)
143
147
  return most_frequent
144
148
 
149
+
145
150
  def process_video(video_path, processor):
146
151
  """
147
152
  Processes a video file by extracting text from regions of interest (ROIs) in each frame.
@@ -169,10 +174,10 @@ def process_video(video_path, processor):
169
174
  frame_path = os.path.join(temp_dir, f"frame_{frame_number}.jpg")
170
175
  cv2.imwrite(frame_path, frame) # Save the frame as a JPEG file
171
176
  # cv2.imwrite(f"_tmp/frame_{frame_number}.jpg", frame)
172
-
177
+
173
178
  # Extract text from ROIs
174
179
  extracted_texts = extract_text_from_rois(frame_path, processor)
175
-
180
+
176
181
  # Store the extracted text from each ROI
177
182
  for key, text in extracted_texts.items():
178
183
  rois_texts[key].append(text)
@@ -180,11 +185,11 @@ def process_video(video_path, processor):
180
185
 
181
186
  frame_number += 1
182
187
 
183
- if frames_for_mean_extraction >= N_FRAMES_MEAN_OCR: break
188
+ if frames_for_mean_extraction >= N_FRAMES_MEAN_OCR:
189
+ break
184
190
 
185
191
  # Release the video capture object
186
192
  video.release()
187
193
 
188
194
  # Get the most frequent values for each ROI
189
195
  return get_most_frequent_values(rois_texts)
190
-
@@ -0,0 +1,61 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from typing import Any, Optional
5
+
6
+ from django.http import HttpRequest
7
+
8
+ from endoreg_db.models.operation_log import OperationLog
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ def record_operation(
14
+ request: HttpRequest,
15
+ *,
16
+ action: str,
17
+ resource_type: str = "",
18
+ resource_id: Optional[int] = None,
19
+ status_before: Optional[str] = None,
20
+ status_after: Optional[str] = None,
21
+ meta: Optional[dict[str, Any]] = None,
22
+ ) -> None:
23
+ """
24
+ Create an OperationLog entry from a view.
25
+ """
26
+ user = getattr(request, "user", None)
27
+
28
+ try:
29
+ log = OperationLog(
30
+ actor_user=user if getattr(user, "is_authenticated", False) else None,
31
+ actor_username=getattr(user, "username", "") if user else "",
32
+ actor_email=getattr(user, "email", "") if user else "",
33
+ actor_keycloak_id="", # fill later if you add it to your user model
34
+ action=action,
35
+ http_method=getattr(request, "method", ""),
36
+ path=getattr(request, "path", ""),
37
+ resource_type=resource_type,
38
+ resource_id=resource_id,
39
+ status_before=status_before or "",
40
+ status_after=status_after or "",
41
+ meta=meta or None,
42
+ )
43
+ log.save()
44
+ except Exception:
45
+ # Never kill the main request flow because of logging
46
+ logger.exception(
47
+ "Failed to record operation %s for %s(%s)",
48
+ action,
49
+ resource_type,
50
+ resource_id,
51
+ )
52
+
53
+
54
+ # TODO: will make the name more generic later base don the requirement,after merge
55
+ def get_resource_type_from_instance(obj):
56
+ name = obj.__class__.__name__
57
+ '''if name == "VideoFile":
58
+ return "video"
59
+ if name == "RawPdfFile":
60
+ return "pdf"'''
61
+ return name.lower()
@@ -7,25 +7,24 @@ module_root = file_path.parent.parent
7
7
  data_dir = module_root / "data"
8
8
 
9
9
 
10
- def collect_center_names(
11
- ):
10
+ def collect_center_names():
12
11
  input_file_path = data_dir / "center/data.yaml"
13
12
  fist_name_dir = data_dir / "names_first"
14
13
  last_name_dir = data_dir / "names_last"
15
14
  # Load the input YAML file
16
- with open(input_file_path, 'r', encoding='utf-8') as file:
15
+ with open(input_file_path, "r", encoding="utf-8") as file:
17
16
  data = yaml.safe_load(file)
18
-
17
+
19
18
  # Containers for first and last names
20
19
  first_names_set = set()
21
20
  last_names_set = set()
22
-
21
+
23
22
  # Extract first and last names from the YAML data
24
23
  for entry in data:
25
- fields = entry.get('fields', {})
26
- first_names_set.update(fields.get('first_names', []))
27
- last_names_set.update(fields.get('last_names', []))
28
-
24
+ fields = entry.get("fields", {})
25
+ first_names_set.update(fields.get("first_names", []))
26
+ last_names_set.update(fields.get("last_names", []))
27
+
29
28
  # Create a list of dictionaries for first and last names
30
29
  first_names_data = [
31
30
  {"model": "endoreg_db.first_name", "fields": {"name": name}}
@@ -35,12 +34,12 @@ def collect_center_names(
35
34
  {"model": "endoreg_db.last_name", "fields": {"name": name}}
36
35
  for name in sorted(last_names_set)
37
36
  ]
38
-
37
+
39
38
  # Write the data to separate YAML files
40
- with open(fist_name_dir/"first_names.yaml", "w", encoding='utf-8') as first_file:
39
+ with open(fist_name_dir / "first_names.yaml", "w", encoding="utf-8") as first_file:
41
40
  yaml.dump(first_names_data, first_file, allow_unicode=True, sort_keys=False)
42
-
43
- with open(last_name_dir/"last_names.yaml", "w", encoding='utf-8') as last_file:
41
+
42
+ with open(last_name_dir / "last_names.yaml", "w", encoding="utf-8") as last_file:
44
43
  yaml.dump(last_names_data, last_file, allow_unicode=True, sort_keys=False)
45
44
 
46
45
  # print("Generated first_names.yaml and last_names.yaml successfully.")
endoreg_db/utils/paths.py CHANGED
@@ -40,8 +40,8 @@ if not STORAGE_DIR.exists():
40
40
  IMPORT_DIR_NAME = "import"
41
41
  EXPORT_DIR_NAME = "export"
42
42
 
43
- IMPORT_DIR = IO_DIR / IMPORT_DIR_NAME # data/import
44
- EXPORT_DIR = IO_DIR / EXPORT_DIR_NAME # data/export
43
+ IMPORT_DIR = IO_DIR / IMPORT_DIR_NAME # data/import
44
+ EXPORT_DIR = IO_DIR / EXPORT_DIR_NAME # data/export
45
45
 
46
46
 
47
47
  IMPORT_VIDEO_DIR_NAME = "video_import"
@@ -64,7 +64,7 @@ DOCUMENT_DIR = STORAGE_DIR / "documents"
64
64
 
65
65
  # After initial import, files will remain here.
66
66
 
67
- TRANSCODING_DIR = STORAGE_DIR /"temp"
67
+ TRANSCODING_DIR = STORAGE_DIR / "temp"
68
68
 
69
69
  SENSITIVE_VIDEO_DIR_NAME = "sensitive_videos"
70
70
  SENSITIVE_REPORT_DIR_NAME = "sensitive_reports"
@@ -116,7 +116,7 @@ data_paths: Dict[str, Path] = {
116
116
  "weights_export": EXPORT_DIR / WEIGHTS_DIR_NAME,
117
117
  "transcoding": TRANSCODING_DIR,
118
118
  "frame": FRAME_DIR,
119
- "documents": DOCUMENT_DIR
119
+ "documents": DOCUMENT_DIR,
120
120
  }
121
121
 
122
122
  logger.info(f"Storage directory: {STORAGE_DIR.resolve()}")
@@ -126,7 +126,7 @@ for key, path in data_paths.items():
126
126
  path.mkdir(parents=True, exist_ok=True)
127
127
 
128
128
  logger.info(f"{key.capitalize()} directory: {path.resolve()}")
129
-
129
+
130
130
 
131
131
  def to_storage_relative(path: Union[str, Path]) -> str:
132
132
  """
@@ -156,4 +156,4 @@ def to_storage_relative(path: Union[str, Path]) -> str:
156
156
  return str(path)
157
157
 
158
158
  # Use POSIX-style separators for Django FileField
159
- return rel.as_posix()
159
+ return rel.as_posix()