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
@@ -91,7 +91,9 @@ class MultiLabelClassificationNet(LightningModule):
91
91
  if track_hparams:
92
92
  self.save_hyperparameters()
93
93
  if labels is None:
94
- raise ValueError("labels must be provided to initialize MultiLabelClassificationNet")
94
+ raise ValueError(
95
+ "labels must be provided to initialize MultiLabelClassificationNet"
96
+ )
95
97
 
96
98
  self.model_type = model_type
97
99
  self.labels = list(labels)
@@ -135,13 +137,23 @@ class MultiLabelClassificationNet(LightningModule):
135
137
  strict = kwargs.pop("strict", True)
136
138
  labels = kwargs.pop("labels", None)
137
139
  if not labels:
138
- raise ValueError("labels must be provided when loading .safetensors checkpoints")
140
+ raise ValueError(
141
+ "labels must be provided when loading .safetensors checkpoints"
142
+ )
139
143
  model_type = kwargs.pop("model_type", None) or "EfficientNetB4"
140
144
  load_imagenet = kwargs.pop("load_imagenet_weights", False)
141
145
 
142
- device = torch.device(map_location) if map_location is not None else torch.device("cpu")
146
+ device = (
147
+ torch.device(map_location)
148
+ if map_location is not None
149
+ else torch.device("cpu")
150
+ )
143
151
  if isinstance(device, torch.device):
144
- device_hint = f"{device.type}:{device.index}" if device.index is not None else device.type
152
+ device_hint = (
153
+ f"{device.type}:{device.index}"
154
+ if device.index is not None
155
+ else device.type
156
+ )
145
157
  else:
146
158
  device_hint = device
147
159
 
@@ -160,7 +172,9 @@ class MultiLabelClassificationNet(LightningModule):
160
172
  if missing:
161
173
  logger.warning("Missing parameters when loading %s: %s", path, missing)
162
174
  if unexpected:
163
- logger.warning("Unexpected parameters when loading %s: %s", path, unexpected)
175
+ logger.warning(
176
+ "Unexpected parameters when loading %s: %s", path, unexpected
177
+ )
164
178
 
165
179
  instance.to(device)
166
180
  return instance
@@ -245,7 +259,8 @@ class MultiLabelClassificationNet(LightningModule):
245
259
  self.parameters(), self.lr, momentum=0.5, weight_decay=self.weight_decay
246
260
  )
247
261
  lr_scheduler = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(
248
- optimizer, T_0=20,
262
+ optimizer,
263
+ T_0=20,
249
264
  )
250
265
 
251
266
  return {
@@ -85,11 +85,11 @@ class Classifier:
85
85
  with torch.inference_mode():
86
86
  if self.verbose:
87
87
  ic("Starting inference")
88
-
88
+
89
89
  # Ensure model exists
90
90
  if self.model is None:
91
91
  raise ValueError("Model is not loaded")
92
-
92
+
93
93
  # Use the device the model is currently on, with fallback to CPU
94
94
  try:
95
95
  # Check what device the model parameters are on
@@ -107,10 +107,10 @@ class Classifier:
107
107
  device = torch.device("cpu")
108
108
  if verbose:
109
109
  print(f"Device detection failed, using CPU: {e}")
110
-
110
+
111
111
  # Ensure model is in eval mode
112
112
  self.model.eval()
113
-
113
+
114
114
  for batch in tqdm(dl):
115
115
  batch = batch.to(device, non_blocking=True)
116
116
  prediction = self.model(batch)
@@ -1,6 +1,7 @@
1
1
  import numpy as np
2
2
  from PIL import Image, ImageOps # Import the required modules from Pillow
3
3
 
4
+
4
5
  def crop_img(img, crop):
5
6
  """
6
7
  Crops the image based on the specified dimensions and adds padding to maintain aspect ratio.
@@ -15,21 +16,26 @@ def crop_img(img, crop):
15
16
  # Convert crop dimensions to Pillow format: left, upper, right, lower
16
17
  ymin, ymax, xmin, xmax = crop
17
18
  img_cropped = img.crop((xmin, ymin, xmax, ymax))
18
-
19
+
19
20
  # Calculate the new size and the required padding
20
21
  width, height = img_cropped.size
21
22
  delta = width - height
22
-
23
+
23
24
  if delta > 0:
24
- padding = (0, abs(delta) // 2, 0, abs(delta) - abs(delta) // 2) # (left, top, right, bottom)
25
+ padding = (
26
+ 0,
27
+ abs(delta) // 2,
28
+ 0,
29
+ abs(delta) - abs(delta) // 2,
30
+ ) # (left, top, right, bottom)
25
31
  elif delta < 0:
26
32
  padding = (abs(delta) // 2, 0, abs(delta) - abs(delta) // 2, 0)
27
33
  else:
28
34
  padding = (0, 0, 0, 0)
29
-
35
+
30
36
  # Pad the image to make it square
31
37
  img_padded = ImageOps.expand(img_cropped, padding)
32
-
38
+
33
39
  return img_padded
34
40
 
35
41
 
@@ -37,7 +43,9 @@ class Cropper:
37
43
  def __init__(self):
38
44
  pass
39
45
 
40
- def __call__(self, img, crop=None, scale=None, scale_method=Image.Resampling.LANCZOS):
46
+ def __call__(
47
+ self, img, crop=None, scale=None, scale_method=Image.Resampling.LANCZOS
48
+ ):
41
49
  """
42
50
  Applies cropping and scaling transformations to the input image.
43
51
 
@@ -52,17 +60,17 @@ class Cropper:
52
60
  """
53
61
  # Convert numpy array to PIL Image if necessary
54
62
  if isinstance(img, np.ndarray):
55
- img = Image.fromarray(img.astype('uint8'), 'RGB')
56
-
63
+ img = Image.fromarray(img.astype("uint8"), "RGB")
64
+
57
65
  if crop is not None:
58
66
  img = crop_img(img, crop)
59
67
  else:
60
68
  raise Exception("Automatic crop detection not implemented yet")
61
-
69
+
62
70
  if scale is not None:
63
71
  img = img.resize(scale, resample=scale_method)
64
-
72
+
65
73
  # Convert PIL Image back to numpy array
66
74
  img = np.array(img)
67
-
75
+
68
76
  return img
@@ -4,7 +4,7 @@ if TYPE_CHECKING:
4
4
  from endoreg_db.models import VideoFile
5
5
 
6
6
 
7
- def _calc_duration_vf(obj:"VideoFile") -> float:
7
+ def _calc_duration_vf(obj: "VideoFile") -> float:
8
8
  """
9
9
  Calculate duration of a VideoFile.
10
10
  """
@@ -12,13 +12,13 @@ def _calc_duration_vf(obj:"VideoFile") -> float:
12
12
  raise ValueError("ffmpeg_meta is missing, cannot calculate duration.")
13
13
 
14
14
  fps = obj.get_fps()
15
- frame_count = obj.frame_count #TODO similar implementation as in get_fps
15
+ frame_count = obj.frame_count # TODO similar implementation as in get_fps
16
16
 
17
17
  duration = frame_count / fps if fps > 0 else -1
18
18
  if duration > 0:
19
19
  return duration
20
20
  else:
21
21
  raise ValueError(
22
- f"Invalid duration calculated for video {obj.uuid}: {duration}. "
22
+ f"Invalid duration calculated for video {obj.video_hash}: {duration}. "
23
23
  "Ensure the video file is valid and accessible."
24
- )
24
+ )
@@ -1,6 +1,7 @@
1
1
  from datetime import datetime, timezone
2
2
  from endoreg_db.models import Patient, PatientLabSample, PatientLabSampleType
3
3
 
4
+
4
5
  class LabSampleFactory:
5
6
  """
6
7
  Provides methods to generate lab samples.
@@ -25,9 +26,7 @@ class LabSampleFactory:
25
26
  sample_type = PatientLabSampleType.objects.get(name="generic")
26
27
 
27
28
  lab_sample = PatientLabSample.objects.create(
28
- patient=patient,
29
- sample_type=sample_type,
30
- date=datetime.now(tz=timezone.utc)
29
+ patient=patient, sample_type=sample_type, date=datetime.now(tz=timezone.utc)
31
30
  )
32
31
 
33
- return lab_sample
32
+ return lab_sample
@@ -3,146 +3,173 @@
3
3
  Simple video file existence checker and path corrector for VideoFile records.
4
4
  """
5
5
 
6
+ import argparse
6
7
  import os
7
8
  import sys
8
9
  from pathlib import Path
9
- import argparse
10
10
 
11
11
  # Parse command-line arguments and environment variables for configuration
12
- parser = argparse.ArgumentParser(description="Simple video file existence checker and path corrector for VideoFile records.")
13
- parser.add_argument('--django-base', type=str, default=os.environ.get('ENDOREG_DJANGO_PROJECT_PATH', str(Path(__file__).resolve().parent.parent.parent)),
14
- help='Path to the Django project base (default: env ENDOREG_DJANGO_PROJECT_PATH or project root)')
15
- parser.add_argument('--django-settings', type=str, default=os.environ.get('DJANGO_SETTINGS_MODULE', 'dev.dev_settings'),
16
- help='Django settings module (default: env DJANGO_SETTINGS_MODULE or dev.dev_settings)')
17
- parser.add_argument('--storage-dir', type=str, default=os.environ.get('ENDOREG_STORAGE_DIR', './storage'),
18
- help='Path to the storage directory (default: ./storage or $ENDOREG_STORAGE_DIR)')
12
+ parser = argparse.ArgumentParser(
13
+ description="Simple video file existence checker and path corrector for VideoFile records."
14
+ )
15
+ parser.add_argument(
16
+ "--django-base",
17
+ type=str,
18
+ default=os.environ.get(
19
+ "ENDOREG_DJANGO_PROJECT_PATH",
20
+ str(Path(__file__).resolve().parent.parent.parent),
21
+ ),
22
+ help="Path to the Django project base (default: env ENDOREG_DJANGO_PROJECT_PATH or project root)",
23
+ )
24
+ parser.add_argument(
25
+ "--django-settings",
26
+ type=str,
27
+ default=os.environ.get("DJANGO_SETTINGS_MODULE", "dev.dev_settings"),
28
+ help="Django settings module (default: env DJANGO_SETTINGS_MODULE or dev.dev_settings)",
29
+ )
30
+ parser.add_argument(
31
+ "--storage-dir",
32
+ type=str,
33
+ default=os.environ.get("ENDOREG_STORAGE_DIR", "./storage"),
34
+ help="Path to the storage directory (default: ./storage or $ENDOREG_STORAGE_DIR)",
35
+ )
19
36
  args, unknown = parser.parse_known_args()
20
37
 
21
38
  sys.path.insert(0, args.django_base)
22
- os.environ.setdefault('DJANGO_SETTINGS_MODULE', args.django_settings)
39
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", args.django_settings)
23
40
 
24
41
  try:
25
42
  import django
43
+
26
44
  django.setup()
27
45
  from endoreg_db.models import VideoFile
46
+
28
47
  DJANGO_AVAILABLE = True
29
48
  except Exception as e:
30
49
  print(f"Django not available: {e}")
31
50
  DJANGO_AVAILABLE = False
32
51
 
52
+
33
53
  def find_video_files():
34
54
  """Find all video files in storage directory."""
35
55
  storage_dir = Path(args.storage_dir)
36
56
  video_files = []
37
-
38
- for pattern in ['**/*.mp4', '**/*.avi', '**/*.mov', '**/*.mkv']:
57
+
58
+ for pattern in ["**/*.mp4", "**/*.avi", "**/*.mov", "**/*.mkv"]:
39
59
  video_files.extend(storage_dir.glob(pattern))
40
-
60
+
41
61
  return video_files
42
62
 
63
+
43
64
  def check_video_file_accessibility(file_path):
44
65
  """Check if a video file is accessible and valid."""
45
66
  try:
46
67
  if not file_path.exists():
47
68
  return False, "File does not exist"
48
-
69
+
49
70
  if file_path.stat().st_size == 0:
50
71
  return False, "File is empty (0 bytes)"
51
-
72
+
52
73
  if not os.access(file_path, os.R_OK):
53
74
  return False, "File is not readable"
54
-
75
+
55
76
  # Try to read first few bytes to check if it's actually a file
56
- with open(file_path, 'rb') as f:
77
+ with open(file_path, "rb") as f:
57
78
  header = f.read(8)
58
79
  if len(header) < 8:
59
80
  return False, "File too small or corrupted"
60
-
61
- return True, f"OK - {file_path.stat().st_size / (1024*1024):.1f} MB"
62
-
81
+
82
+ return True, f"OK - {file_path.stat().st_size / (1024 * 1024):.1f} MB"
83
+
63
84
  except Exception as e:
64
85
  return False, f"Error checking file: {e}"
65
86
 
87
+
66
88
  def main():
67
89
  print("🔍 VIDEO FILE EXISTENCE CHECKER")
68
90
  print("=" * 40)
69
-
91
+
70
92
  # Find all video files
71
93
  print("1. Scanning for video files...")
72
94
  video_files = find_video_files()
73
95
  print(f"Found {len(video_files)} video files in storage directory")
74
-
96
+
75
97
  if not video_files:
76
98
  print("❌ No video files found in storage directory!")
77
99
  return
78
-
100
+
79
101
  # Check each file
80
102
  print("\n2. Checking file accessibility...")
81
103
  accessible_files = []
82
-
104
+
83
105
  for video_file in video_files[:10]: # Check first 10
84
106
  accessible, message = check_video_file_accessibility(video_file)
85
107
  status = "✅" if accessible else "❌"
86
108
  print(f"{status} {video_file.name}: {message}")
87
-
109
+
88
110
  if accessible:
89
111
  accessible_files.append(video_file)
90
-
112
+
91
113
  if not accessible_files:
92
114
  print("\n❌ No accessible video files found!")
93
115
  return
94
-
116
+
95
117
  print(f"\n✅ Found {len(accessible_files)} accessible video files")
96
-
118
+
97
119
  # If Django is available, check database records
98
120
  if DJANGO_AVAILABLE:
99
121
  print("\n3. Checking database records...")
100
122
  try:
101
123
  video_5 = VideoFile.objects.get(pk=5)
102
- print(f"📋 Video ID 5 found in database:")
103
- print(f" UUID: {video_5.uuid}")
104
-
124
+ print("📋 Video ID 5 found in database:")
125
+ print(f" UUID: {video_5.video_hash}")
126
+
105
127
  # Check different file path attributes
106
- for attr in ['raw_file', 'processed_file']:
128
+ for attr in ["raw_file", "processed_file"]:
107
129
  if hasattr(video_5, attr):
108
130
  file_field = getattr(video_5, attr)
109
131
  if file_field:
110
132
  try:
111
133
  file_path = Path(file_field.path)
112
- accessible, message = check_video_file_accessibility(file_path)
134
+ accessible, message = check_video_file_accessibility(
135
+ file_path
136
+ )
113
137
  status = "✅" if accessible else "❌"
114
138
  print(f" {attr}: {status} {file_path} ({message})")
115
139
  except Exception as e:
116
140
  print(f" {attr}: ❌ Error accessing path: {e}")
117
141
  else:
118
142
  print(f" {attr}: ❌ No file set")
119
-
143
+
120
144
  # Check if UUID matches any found files
121
- uuid_str = str(video_5.uuid)
145
+ uuid_str = str(video_5.video_hash)
122
146
  matching_files = [f for f in accessible_files if uuid_str in str(f)]
123
-
147
+
124
148
  if matching_files:
125
149
  print(f"\n💡 Found matching files for UUID {uuid_str}:")
126
150
  for match in matching_files:
127
151
  accessible, message = check_video_file_accessibility(match)
128
152
  print(f" ✅ {match} ({message})")
129
-
130
- print(f"\n🔧 SOLUTION: Update VideoFile record to use:")
153
+
154
+ print("\n🔧 SOLUTION: Update VideoFile record to use:")
131
155
  print(f" {matching_files[0]}")
132
- print(f"\n🐍 Django command to fix:")
133
- print(f" video = VideoFile.objects.get(pk=5)")
134
- print(f" video.raw_file.name = '{matching_files[0].relative_to(Path(args.storage_dir))}'")
135
- print(f" video.save()")
156
+ print("\n🐍 Django command to fix:")
157
+ print(" video = VideoFile.objects.get(pk=5)")
158
+ print(
159
+ f" video.raw_file.name = '{matching_files[0].relative_to(Path(args.storage_dir))}'"
160
+ )
161
+ print(" video.save()")
136
162
  else:
137
163
  print(f"\n❌ No files found matching UUID {uuid_str}")
138
-
164
+
139
165
  except Exception as e:
140
166
  print(f"❌ Error checking database: {e}")
141
-
142
- print(f"\n4. 🎯 QUICK TEST RECOMMENDATION:")
143
- print(f" Use this accessible file for testing:")
167
+
168
+ print("\n4. 🎯 QUICK TEST RECOMMENDATION:")
169
+ print(" Use this accessible file for testing:")
144
170
  print(f" {accessible_files[0]}")
145
- print(f" Size: {accessible_files[0].stat().st_size / (1024*1024):.1f} MB")
171
+ print(f" Size: {accessible_files[0].stat().st_size / (1024 * 1024):.1f} MB")
172
+
146
173
 
147
174
  if __name__ == "__main__":
148
- main()
175
+ main()
@@ -1,29 +1,30 @@
1
1
  from PIL import Image
2
2
 
3
- def crop_and_insert(image:Image, x, y, h, w, bg_color=(255, 255, 255)):
3
+
4
+ def crop_and_insert(image: Image, x, y, h, w, bg_color=(255, 255, 255)):
4
5
  """
5
6
  Crops a region from an inverted grayscale image and inserts it into a white image of the same size as the original.
6
-
7
+
7
8
  Parameters:
8
9
  - fp: File path or a file object of the original image.
9
10
  - x, y: The top-left coordinates of the rectangle to be cropped.
10
11
  - h, w: The height and width of the rectangle to be cropped.
11
-
12
+
12
13
  Returns:
13
14
  A PIL Image object containing the original image with the specified region replaced.
14
15
  """
15
16
  # Load the original image
16
17
  original_image = image
17
-
18
+
18
19
  # Crop the specified region from the inverted image
19
20
  crop_rectangle = (x, y, x + w, y + h)
20
21
  cropped_content = original_image.crop(crop_rectangle)
21
-
22
+
22
23
  # Create a new white image of the same size as the original image
23
- white_background = Image.new('RGB', original_image.size, bg_color)
24
-
24
+ white_background = Image.new("RGB", original_image.size, bg_color)
25
+
25
26
  # Paste the cropped content onto the white image at the specified location
26
27
  white_background.paste(cropped_content, (x, y))
27
-
28
+
28
29
  # The final image can be displayed or saved as needed
29
- return white_background
30
+ return white_background
@@ -122,7 +122,9 @@ def load_data_with_foreign_keys(
122
122
  requirement_types = fields.get("requirement_types", [])
123
123
 
124
124
  if not requirement_types:
125
- raise ValueError(f"Requirement '{name}' must define at least one requirement_types entry.")
125
+ raise ValueError(
126
+ f"Requirement '{name}' must define at least one requirement_types entry."
127
+ )
126
128
 
127
129
  ####################
128
130
  # TODO REMOVE AFTER TRANSLATION SUPPORT IS ADDED
@@ -265,7 +267,9 @@ def load_data_with_foreign_keys(
265
267
  obj, created = _save_instance()
266
268
 
267
269
  if created and verbose:
268
- command.stdout.write(command.style.SUCCESS(f"Created {model.__name__} {name}"))
270
+ command.stdout.write(
271
+ command.style.SUCCESS(f"Created {model.__name__} {name}")
272
+ )
269
273
  elif verbose:
270
274
  pass
271
275
 
@@ -274,4 +278,8 @@ def load_data_with_foreign_keys(
274
278
  if related_objs: # Only set if there are objects to set
275
279
  getattr(obj, field_name).set(related_objs)
276
280
  if verbose:
277
- command.stdout.write(command.style.SUCCESS(f"Set {len(related_objs)} {field_name} for {model.__name__} {name}"))
281
+ command.stdout.write(
282
+ command.style.SUCCESS(
283
+ f"Set {len(related_objs)} {field_name} for {model.__name__} {name}"
284
+ )
285
+ )
endoreg_db/utils/dates.py CHANGED
@@ -2,7 +2,6 @@ from datetime import datetime, date, timedelta
2
2
  from random import randint
3
3
  from calendar import monthrange
4
4
  from django.utils import timezone
5
- import datetime
6
5
 
7
6
  # TODO replace used random_day_by_year function implementation when
8
7
  # creating pseudo patients with new function "random date by age_at_date and examination_date"
@@ -45,16 +44,16 @@ def ensure_aware_datetime(dt):
45
44
  """
46
45
  Ensures a datetime object is timezone-aware.
47
46
  If the datetime is naive (has no timezone info), the current timezone is applied.
48
-
47
+
49
48
  Args:
50
49
  dt: A datetime object that may be naive
51
-
50
+
52
51
  Returns:
53
52
  A timezone-aware datetime object
54
53
  """
55
54
  if dt is None:
56
55
  return None
57
-
56
+
58
57
  if isinstance(dt, datetime.datetime) and timezone.is_naive(dt):
59
58
  return timezone.make_aware(dt)
60
59
  return dt
@@ -1,5 +1,4 @@
1
1
  import subprocess
2
- from endoreg_db.models.administration.center import center
3
2
 
4
3
  # Start process with interactive pipes
5
4
  proc = subprocess.Popen(
@@ -8,7 +7,7 @@ proc = subprocess.Popen(
8
7
  stdout=subprocess.PIPE,
9
8
  stderr=subprocess.STDOUT,
10
9
  text=True,
11
- bufsize=1
10
+ bufsize=1,
12
11
  )
13
12
 
14
13
  proc.stdin.write("print('Trying to extract...')\n")
@@ -17,11 +16,13 @@ proc.stdin.flush()
17
16
  try:
18
17
  subprocess.run(["python", "manage.py", "load_center_data"], check=True)
19
18
  proc.stdout.write("print('found center')")
20
- except subprocess.CalledProcessError as e:
21
- proc.stdout.write("print('Didn't find center. Please add it to endoreg_db luxnix or via export DEFAULT_CENTER")
19
+ except subprocess.CalledProcessError:
20
+ proc.stdout.write(
21
+ "print('Didn't find center. Please add it to endoreg_db luxnix or via export DEFAULT_CENTER"
22
+ )
22
23
  # """
23
24
  # Future Implementation using dialogue
24
- #"""
25
+ # """
25
26
  # # Send commands as if from terminal
26
27
  # proc.stdin.write("print('You dont have a default center set up yet. Please enter one here.')\n\nprint('Rule: use_this_format_and_connect_words_with_underscore')")
27
28
  # proc.stdin.flush()
@@ -29,4 +30,4 @@ except subprocess.CalledProcessError as e:
29
30
  # # Read responses
30
31
  # for _ in range(3):
31
32
  # line = proc.stdout.readline()
32
- # print("Selected >>", line.strip())
33
+ # print("Selected >>", line.strip())
endoreg_db/utils/env.py CHANGED
@@ -2,6 +2,7 @@ import os
2
2
 
3
3
  DEBUG = os.getenv("DEBUG", "false").lower() == "true"
4
4
 
5
+
5
6
  def get_env_var(var_name: str, default: str = None) -> str | None:
6
7
  """
7
8
  Get the value of an environment variable, with an optional default value.
@@ -13,12 +14,13 @@ def get_env_var(var_name: str, default: str = None) -> str | None:
13
14
  """
14
15
  value = os.environ.get(var_name)
15
16
  if value:
16
- value = value.strip('"\'') # Strip both single and double quotes
17
+ value = value.strip("\"'") # Strip both single and double quotes
17
18
  if DEBUG:
18
19
  print(f"Environment variable {var_name}: {value}")
19
20
  return value
20
21
  return default
21
22
 
23
+
22
24
  def set_env_var(var_name: str, value: str) -> None:
23
25
  """
24
26
  Set the value of an environment variable.
@@ -29,5 +31,7 @@ def set_env_var(var_name: str, value: str) -> None:
29
31
  if DEBUG:
30
32
  print(f"Set environment variable {var_name}: {value}")
31
33
 
32
- DJANGO_SETTINGS_MODULE = get_env_var("DJANGO_SETTINGS_MODULE") or "endoreg_db.settings_dev"
33
34
 
35
+ DJANGO_SETTINGS_MODULE = (
36
+ get_env_var("DJANGO_SETTINGS_MODULE") or "endoreg_db.settings_dev"
37
+ )
@@ -1,13 +1,14 @@
1
1
  from pathlib import Path
2
2
  import shutil
3
3
 
4
+
4
5
  def extract_selected_frames(
5
6
  video_path: Path,
6
7
  frame_numbers: list,
7
8
  output_dir: Path,
8
9
  fps: int = 50,
9
10
  quality: int = 2,
10
- ext: str = "png"
11
+ ext: str = "png",
11
12
  ):
12
13
  """
13
14
  Extract specific frames from a video using the same quality logic as the original extractor.
@@ -43,12 +44,21 @@ def extract_selected_frames(
43
44
  timestamp=timestamp_sec,
44
45
  output_path=str(output_file),
45
46
  quality=quality,
46
- ext=ext
47
+ ext=ext,
47
48
  )
49
+
50
+
48
51
  import subprocess
49
52
  from pathlib import Path
50
53
 
51
- def extract_single_frame(input_path: str, timestamp: float, output_path: str, quality: int = 2, ext: str = "png"):
54
+
55
+ def extract_single_frame(
56
+ input_path: str,
57
+ timestamp: float,
58
+ output_path: str,
59
+ quality: int = 2,
60
+ ext: str = "png",
61
+ ):
52
62
  """
53
63
  Extract a single frame from a video using ffmpeg.
54
64
 
@@ -61,12 +71,17 @@ def extract_single_frame(input_path: str, timestamp: float, output_path: str, qu
61
71
  """
62
72
  cmd = [
63
73
  "ffmpeg",
64
- "-loglevel", "error",
65
- "-ss", f"{timestamp:.3f}",
66
- "-i", str(input_path),
67
- "-frames:v", "1",
68
- "-q:v", str(quality),
69
- str(output_path)
74
+ "-loglevel",
75
+ "error",
76
+ "-ss",
77
+ f"{timestamp:.3f}",
78
+ "-i",
79
+ str(input_path),
80
+ "-frames:v",
81
+ "1",
82
+ "-q:v",
83
+ str(quality),
84
+ str(output_path),
70
85
  ]
71
86
 
72
87
  subprocess.run(cmd, check=True)