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
@@ -18,7 +18,9 @@ from rest_framework.decorators import api_view, permission_classes
18
18
  from rest_framework.response import Response
19
19
 
20
20
  from endoreg_db.models import Label, LabelVideoSegment, VideoFile
21
- from endoreg_db.serializers.label_video_segment.label_video_segment import LabelVideoSegmentSerializer
21
+ from endoreg_db.serializers.label_video_segment.label_video_segment import (
22
+ LabelVideoSegmentSerializer,
23
+ )
22
24
  from endoreg_db.utils.permissions import EnvironmentAwarePermission
23
25
 
24
26
  logger = logging.getLogger(__name__)
@@ -49,14 +51,21 @@ def video_segments_stats(request):
49
51
  stats = {
50
52
  "total_segments": total_segments,
51
53
  "videos_with_segments": videos_with_segments,
52
- "by_label": {item["label__name"]: item["count"] for item in label_counts if item["label__name"]},
54
+ "by_label": {
55
+ item["label__name"]: item["count"]
56
+ for item in label_counts
57
+ if item["label__name"]
58
+ },
53
59
  }
54
60
 
55
61
  return Response(stats, status=status.HTTP_200_OK)
56
62
 
57
63
  except Exception as e:
58
64
  logger.error(f"Error fetching video segment stats: {e}")
59
- return Response({"error": "Failed to fetch segment statistics"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
65
+ return Response(
66
+ {"error": "Failed to fetch segment statistics"},
67
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
68
+ )
60
69
 
61
70
 
62
71
  @api_view(["GET", "POST"])
@@ -84,13 +93,24 @@ def video_segments_collection(request):
84
93
  try:
85
94
  segment = serializer.save()
86
95
  logger.info(f"Successfully created video segment {segment.pk}")
87
- return Response(LabelVideoSegmentSerializer(segment).data, status=status.HTTP_201_CREATED)
96
+ return Response(
97
+ LabelVideoSegmentSerializer(segment).data,
98
+ status=status.HTTP_201_CREATED,
99
+ )
88
100
  except Exception as e:
89
101
  logger.error(f"Error creating video segment: {str(e)}")
90
- return Response({"error": f"Failed to create segment: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
102
+ return Response(
103
+ {"error": f"Failed to create segment: {str(e)}"},
104
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
105
+ )
91
106
  else:
92
- logger.warning(f"Invalid data for video segment creation: {serializer.errors}")
93
- return Response({"error": "Invalid data", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
107
+ logger.warning(
108
+ f"Invalid data for video segment creation: {serializer.errors}"
109
+ )
110
+ return Response(
111
+ {"error": "Invalid data", "details": serializer.errors},
112
+ status=status.HTTP_400_BAD_REQUEST,
113
+ )
94
114
 
95
115
  elif request.method == "GET":
96
116
  # Optional filtering by video_id
@@ -104,14 +124,20 @@ def video_segments_collection(request):
104
124
  video = VideoFile.objects.get(id=video_id)
105
125
  queryset = queryset.filter(video_file=video)
106
126
  except VideoFile.DoesNotExist:
107
- return Response({"error": f"Video with id {video_id} not found"}, status=status.HTTP_404_NOT_FOUND)
127
+ return Response(
128
+ {"error": f"Video with id {video_id} not found"},
129
+ status=status.HTTP_404_NOT_FOUND,
130
+ )
108
131
 
109
132
  if label_id:
110
133
  try:
111
134
  label = Label.objects.get(id=label_id)
112
135
  queryset = queryset.filter(label=label)
113
136
  except Label.DoesNotExist:
114
- return Response({"error": f"Label with id {label_id} not found"}, status=status.HTTP_404_NOT_FOUND)
137
+ return Response(
138
+ {"error": f"Label with id {label_id} not found"},
139
+ status=status.HTTP_404_NOT_FOUND,
140
+ )
115
141
 
116
142
  # Order by video and start time for consistent results
117
143
  segments = queryset.order_by("video_file__id", "start_frame_number")
@@ -152,7 +178,10 @@ def video_segments_by_video(request, pk):
152
178
  label = Label.objects.get(name=label_name)
153
179
  queryset = queryset.filter(label=label)
154
180
  except Label.DoesNotExist:
155
- return Response({"error": f'Label "{label_name}" not found'}, status=status.HTTP_404_NOT_FOUND)
181
+ return Response(
182
+ {"error": f'Label "{label_name}" not found'},
183
+ status=status.HTTP_404_NOT_FOUND,
184
+ )
156
185
 
157
186
  segments = queryset.order_by("start_frame_number")
158
187
  serializer = LabelVideoSegmentSerializer(segments, many=True)
@@ -170,14 +199,27 @@ def video_segments_by_video(request, pk):
170
199
  if serializer.is_valid():
171
200
  try:
172
201
  segment = serializer.save()
173
- logger.info(f"Successfully created segment {segment.pk} for video {pk}")
174
- return Response(LabelVideoSegmentSerializer(segment).data, status=status.HTTP_201_CREATED)
202
+ logger.info(
203
+ f"Successfully created segment {segment.pk} for video {pk}"
204
+ )
205
+ return Response(
206
+ LabelVideoSegmentSerializer(segment).data,
207
+ status=status.HTTP_201_CREATED,
208
+ )
175
209
  except Exception as e:
176
210
  logger.error(f"Error creating segment for video {pk}: {str(e)}")
177
- return Response({"error": f"Failed to create segment: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
211
+ return Response(
212
+ {"error": f"Failed to create segment: {str(e)}"},
213
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
214
+ )
178
215
  else:
179
- logger.warning(f"Invalid data for segment creation: {serializer.errors}")
180
- return Response({"error": "Invalid data", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
216
+ logger.warning(
217
+ f"Invalid data for segment creation: {serializer.errors}"
218
+ )
219
+ return Response(
220
+ {"error": "Invalid data", "details": serializer.errors},
221
+ status=status.HTTP_400_BAD_REQUEST,
222
+ )
181
223
 
182
224
 
183
225
  @api_view(["GET", "PATCH", "DELETE"])
@@ -208,10 +250,14 @@ def video_segment_detail(request, pk, segment_id):
208
250
  return Response(serializer.data)
209
251
 
210
252
  elif request.method == "PATCH":
211
- logger.info(f"Updating segment {segment_id} for video {pk} with data: {request.data}")
253
+ logger.info(
254
+ f"Updating segment {segment_id} for video {pk} with data: {request.data}"
255
+ )
212
256
 
213
257
  with transaction.atomic():
214
- serializer = LabelVideoSegmentSerializer(segment, data=request.data, partial=True)
258
+ serializer = LabelVideoSegmentSerializer(
259
+ segment, data=request.data, partial=True
260
+ )
215
261
  if serializer.is_valid():
216
262
  try:
217
263
  segment = serializer.save()
@@ -219,10 +265,16 @@ def video_segment_detail(request, pk, segment_id):
219
265
  return Response(LabelVideoSegmentSerializer(segment).data)
220
266
  except Exception as e:
221
267
  logger.error(f"Error updating segment {segment_id}: {str(e)}")
222
- return Response({"error": f"Failed to update segment: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
268
+ return Response(
269
+ {"error": f"Failed to update segment: {str(e)}"},
270
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
271
+ )
223
272
  else:
224
273
  logger.warning(f"Invalid data for segment update: {serializer.errors}")
225
- return Response({"error": "Invalid data", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
274
+ return Response(
275
+ {"error": "Invalid data", "details": serializer.errors},
276
+ status=status.HTTP_400_BAD_REQUEST,
277
+ )
226
278
 
227
279
  elif request.method == "DELETE":
228
280
  logger.info(f"Deleting segment {segment_id} from video {pk}")
@@ -230,10 +282,16 @@ def video_segment_detail(request, pk, segment_id):
230
282
  with transaction.atomic():
231
283
  segment.delete()
232
284
  logger.info(f"Successfully deleted segment {segment_id}")
233
- return Response({"message": f"Segment {segment_id} deleted successfully"}, status=status.HTTP_204_NO_CONTENT)
285
+ return Response(
286
+ {"message": f"Segment {segment_id} deleted successfully"},
287
+ status=status.HTTP_204_NO_CONTENT,
288
+ )
234
289
  except Exception as e:
235
290
  logger.error(f"Error deleting segment {segment_id}: {str(e)}")
236
- return Response({"error": f"Failed to delete segment: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
291
+ return Response(
292
+ {"error": f"Failed to delete segment: {str(e)}"},
293
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
294
+ )
237
295
 
238
296
 
239
297
  # ============================================================================
@@ -282,7 +340,9 @@ def video_segment_validate(request, pk: int, segment_id: int):
282
340
  try:
283
341
  is_validated = request.data.get("is_validated", True)
284
342
  notes = request.data.get("notes", "")
285
- information_source_name = request.data.get("information_source_name", "manual_annotation")
343
+ information_source_name = request.data.get(
344
+ "information_source_name", "manual_annotation"
345
+ )
286
346
 
287
347
  # Optional: update times (seconds) before validation
288
348
  start_time = request.data.get("start_time")
@@ -299,7 +359,9 @@ def video_segment_validate(request, pk: int, segment_id: int):
299
359
  )
300
360
  segment.start_frame_number = new_start
301
361
  segment.end_frame_number = new_end
302
- segment.save(update_fields=["start_frame_number", "end_frame_number"])
362
+ segment.save(
363
+ update_fields=["start_frame_number", "end_frame_number"]
364
+ )
303
365
 
304
366
  segment.mark_validated(
305
367
  is_validated=is_validated,
@@ -323,9 +385,13 @@ def video_segment_validate(request, pk: int, segment_id: int):
323
385
 
324
386
  except Exception as e:
325
387
  logger.error(f"Error validating segment {segment_id} in video {pk}: {e}")
326
- return Response({"error": f"Validation failed: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
388
+ return Response(
389
+ {"error": f"Validation failed: {str(e)}"},
390
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
391
+ )
392
+
327
393
 
328
- #TODO Pass user based information source to backend. This is the endpoint currently used by the VideoExamination endpoint
394
+ # TODO Pass user based information source to backend. This is the endpoint currently used by the VideoExamination endpoint
329
395
  @api_view(["POST"])
330
396
  @permission_classes([EnvironmentAwarePermission])
331
397
  def video_segments_validate_bulk(request, pk: int):
@@ -351,22 +417,24 @@ def video_segments_validate_bulk(request, pk: int):
351
417
  segment_ids = request.data.get("segment_ids", [])
352
418
  is_validated = request.data.get("is_validated", True)
353
419
  notes = request.data.get("notes", "")
354
- information_source_name = request.data.get("information_source_name", "manual_annotation")
420
+ information_source_name = request.data.get(
421
+ "information_source_name", "manual_annotation"
422
+ )
355
423
  if notes:
356
424
  logger.info(f"Segment Validiert ${notes}")
357
425
  if not segment_ids:
358
- return Response({"error": "segment_ids is required"}, status=status.HTTP_400_BAD_REQUEST)
426
+ return Response(
427
+ {"error": "segment_ids is required"}, status=status.HTTP_400_BAD_REQUEST
428
+ )
359
429
 
360
430
  # optional per-segment timing info (seconds)
361
431
  segments_data_list = request.data.get("segments", []) or []
362
432
  segments_data = {int(s["id"]): s for s in segments_data_list if "id" in s}
363
433
 
364
434
  try:
365
- segments = (
366
- LabelVideoSegment.objects
367
- .filter(pk__in=segment_ids, video_file=video)
368
- .select_related("state", "video_file")
369
- )
435
+ segments = LabelVideoSegment.objects.filter(
436
+ pk__in=segment_ids, video_file=video
437
+ ).select_related("state", "video_file")
370
438
 
371
439
  if not segments.exists():
372
440
  return Response(
@@ -396,13 +464,18 @@ def video_segments_validate_bulk(request, pk: int):
396
464
  segment.start_frame_number = new_start
397
465
  segment.end_frame_number = new_end
398
466
  segment.save(
399
- update_fields=["start_frame_number", "end_frame_number"]
467
+ update_fields=[
468
+ "start_frame_number",
469
+ "end_frame_number",
470
+ ]
400
471
  )
401
472
 
402
473
  # 2) mark as validated + update information source + notes
403
474
  segment.mark_validated(
404
475
  is_validated=is_validated,
405
- information_source_name=str(information_source_name) if is_validated else str(None),
476
+ information_source_name=str(information_source_name)
477
+ if is_validated
478
+ else str(None),
406
479
  )
407
480
  updated_count += 1
408
481
 
@@ -422,13 +495,18 @@ def video_segments_validate_bulk(request, pk: int):
422
495
 
423
496
  if failed_ids:
424
497
  response_data["failed_ids"] = failed_ids
425
- response_data["warning"] = f"{len(failed_ids)} segments could not be validated"
498
+ response_data["warning"] = (
499
+ f"{len(failed_ids)} segments could not be validated"
500
+ )
426
501
 
427
502
  return Response(response_data, status=status.HTTP_200_OK)
428
503
 
429
504
  except Exception as e:
430
505
  logger.error(f"Error in bulk validation for video {pk}: {e}")
431
- return Response({"error": f"Bulk validation failed: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
506
+ return Response(
507
+ {"error": f"Bulk validation failed: {str(e)}"},
508
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
509
+ )
432
510
 
433
511
 
434
512
  @api_view(["GET", "POST"])
@@ -478,7 +556,9 @@ def video_segments_validation_status(request, pk: int):
478
556
  # Get validation status
479
557
  label_name = request.query_params.get("label_name")
480
558
 
481
- segments_query = LabelVideoSegment.objects.filter(video_file=video).select_related("state", "label")
559
+ segments_query = LabelVideoSegment.objects.filter(
560
+ video_file=video
561
+ ).select_related("state", "label")
482
562
 
483
563
  if label_name:
484
564
  segments_query = segments_query.filter(label__name=label_name)
@@ -505,7 +585,8 @@ def video_segments_validation_status(request, pk: int):
505
585
  "total_segments": total_count,
506
586
  "validated_count": validated_count,
507
587
  "unvalidated_count": total_count - validated_count,
508
- "validation_complete": validated_count == total_count and total_count > 0,
588
+ "validation_complete": validated_count == total_count
589
+ and total_count > 0,
509
590
  "by_label": by_label,
510
591
  "label_filter": label_name,
511
592
  },
@@ -517,7 +598,9 @@ def video_segments_validation_status(request, pk: int):
517
598
  label_name = request.data.get("label_name")
518
599
  notes = request.data.get("notes", "")
519
600
 
520
- segments_query = LabelVideoSegment.objects.filter(video_file=video).select_related("state", "label")
601
+ segments_query = LabelVideoSegment.objects.filter(
602
+ video_file=video
603
+ ).select_related("state", "label")
521
604
 
522
605
  if label_name:
523
606
  segments_query = segments_query.filter(label__name=label_name)
@@ -525,7 +608,14 @@ def video_segments_validation_status(request, pk: int):
525
608
  segments = segments_query.all()
526
609
 
527
610
  if not segments.exists():
528
- return Response({"message": "No segments found to validate", "video_id": pk, "updated_count": 0}, status=status.HTTP_200_OK)
611
+ return Response(
612
+ {
613
+ "message": "No segments found to validate",
614
+ "video_id": pk,
615
+ "updated_count": 0,
616
+ },
617
+ status=status.HTTP_200_OK,
618
+ )
529
619
 
530
620
  updated_count = 0
531
621
  failed_count = 0
@@ -535,8 +625,6 @@ def video_segments_validation_status(request, pk: int):
535
625
  try:
536
626
  if segment.state:
537
627
  segment.state.is_validated = True
538
- if notes and hasattr(segment.state, "validation_notes"):
539
- segment.state.validation_notes = notes
540
628
  segment.state.save()
541
629
  updated_count += 1
542
630
  else:
@@ -546,8 +634,10 @@ def video_segments_validation_status(request, pk: int):
546
634
  failed_count += 1
547
635
 
548
636
  logger.info(f"Completed validation for {updated_count} segments in video {pk}")
549
- logger.info(f"Removing Outside Segments")
550
- video_file.label_video_segments.filter(video_file=video, label="outside", state__is_validated=False).delete()
637
+ logger.info("Removing Outside Segments")
638
+ video.label_video_segments.filter(
639
+ video_file=video, label__name="outside", state__is_validated=False
640
+ ).delete()
551
641
  return Response(
552
642
  {
553
643
  "message": f"Video segment validation completed for video {pk}",
@@ -12,37 +12,38 @@ class VideoApplyMaskView(APIView):
12
12
  """
13
13
  POST /api/video-apply-mask/{id}/ - Apply mask to video using streaming processing
14
14
  """
15
+
15
16
  permission_classes = [EnvironmentAwarePermission]
16
17
 
17
18
  def post(self, request, pk):
18
19
  video = get_object_or_404(VideoFile, pk=pk)
19
20
 
20
- mask_type = request.data.get('mask_type', 'device_default')
21
- device_name = request.data.get('device_name', 'olympus_cv_1500')
22
- use_streaming = request.data.get('use_streaming', True)
23
- custom_mask = request.data.get('custom_mask')
21
+ mask_type = request.data.get("mask_type", "device_default")
22
+ device_name = request.data.get("device_name", "olympus_cv_1500")
23
+ use_streaming = request.data.get("use_streaming", True)
24
+ custom_mask = request.data.get("custom_mask")
24
25
 
25
26
  try:
26
27
  # Start async task for video masking
27
28
  from endoreg_db.tasks.video_processing_tasks import apply_video_mask_task
28
29
 
29
30
  task_data = {
30
- 'video_id': pk,
31
- 'mask_type': mask_type,
32
- 'device_name': device_name,
33
- 'use_streaming': use_streaming,
34
- 'custom_mask': custom_mask
31
+ "video_id": pk,
32
+ "mask_type": mask_type,
33
+ "device_name": device_name,
34
+ "use_streaming": use_streaming,
35
+ "custom_mask": custom_mask,
35
36
  }
36
37
 
37
38
  task = apply_video_mask_task.delay(**task_data)
38
39
 
39
40
  return Response(
40
41
  {"task_id": task.id, "status": "started"},
41
- status=status.HTTP_202_ACCEPTED
42
+ status=status.HTTP_202_ACCEPTED,
42
43
  )
43
44
 
44
45
  except Exception as e:
45
46
  return Response(
46
47
  {"error": f"Failed to start masking task: {str(e)}"},
47
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
48
- )
48
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
49
+ )
@@ -13,9 +13,10 @@ class VideoCorrectionView(APIView):
13
13
  """
14
14
  GET /api/video/media/video-correction/{id}/ - Get video details for correction
15
15
  """
16
+
16
17
  permission_classes = [EnvironmentAwarePermission]
17
18
 
18
19
  def get(self, request, pk):
19
20
  video = get_object_or_404(VideoFile, pk=pk)
20
21
  ser = VideoDetailSerializer(video, context={"request": request})
21
- return Response(ser.data, status=status.HTTP_200_OK)
22
+ return Response(ser.data, status=status.HTTP_200_OK)
@@ -13,46 +13,46 @@ class VideoDownloadProcessedView(APIView):
13
13
  """
14
14
  GET /api/video-download-processed/{id}/ - Download processed video result
15
15
  """
16
+
16
17
  permission_classes = [EnvironmentAwarePermission]
17
18
 
18
19
  def get(self, request, pk):
19
20
  # Remove unused 'video' variable
20
- output_path = request.query_params.get('path')
21
+ output_path = request.query_params.get("path")
21
22
 
22
23
  # Define the allowed base directory for processed videos
23
- processed_base_dir = os.path.abspath(os.getenv("PROCESSED_VIDEO_DIR", "/srv/processed_videos"))
24
+ processed_base_dir = os.path.abspath(
25
+ os.getenv("PROCESSED_VIDEO_DIR", "/srv/processed_videos")
26
+ )
24
27
  if not output_path:
25
28
  return Response(
26
- {"error": "Processed file not found"},
27
- status=status.HTTP_404_NOT_FOUND
29
+ {"error": "Processed file not found"}, status=status.HTTP_404_NOT_FOUND
28
30
  )
29
31
 
30
32
  # Resolve the absolute path and check if it's within the allowed directory
31
33
  abs_output_path = os.path.abspath(output_path)
32
34
  if not abs_output_path.startswith(processed_base_dir + os.sep):
33
35
  return Response(
34
- {"error": "Invalid file path"},
35
- status=status.HTTP_400_BAD_REQUEST
36
+ {"error": "Invalid file path"}, status=status.HTTP_400_BAD_REQUEST
36
37
  )
37
38
 
38
39
  if not os.path.exists(abs_output_path):
39
40
  return Response(
40
- {"error": "Processed file not found"},
41
- status=status.HTTP_404_NOT_FOUND
41
+ {"error": "Processed file not found"}, status=status.HTTP_404_NOT_FOUND
42
42
  )
43
43
 
44
44
  try:
45
45
  from django.http import FileResponse
46
- with open(abs_output_path, 'rb') as f:
47
- response = FileResponse(
48
- f,
49
- content_type='video/mp4'
46
+
47
+ with open(abs_output_path, "rb") as f:
48
+ response = FileResponse(f, content_type="video/mp4")
49
+ response["Content-Disposition"] = (
50
+ f'attachment; filename="{os.path.basename(abs_output_path)}"'
50
51
  )
51
- response['Content-Disposition'] = f'attachment; filename="{os.path.basename(abs_output_path)}"'
52
52
  return response
53
53
 
54
54
  except Exception as e:
55
55
  return Response(
56
56
  {"error": f"Failed to serve file: {str(e)}"},
57
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
58
- )
57
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
58
+ )
@@ -12,6 +12,7 @@ class VideoMetadataStatsView(APIView):
12
12
  """
13
13
  GET media/videos/{pk}/metadata/ - Get video metadata including sensitivity analysis
14
14
  """
15
+
15
16
  permission_classes = [EnvironmentAwarePermission]
16
17
 
17
18
  def get(self, request, pk):
@@ -19,11 +20,11 @@ class VideoMetadataStatsView(APIView):
19
20
 
20
21
  # Get or calculate metadata
21
22
  metadata = {
22
- 'sensitiveFrameCount': getattr(video, 'sensitive_frame_count', None),
23
- 'totalFrames': getattr(video, 'total_frames', None),
24
- 'sensitiveRatio': getattr(video, 'sensitive_ratio', None),
25
- 'duration': getattr(video, 'duration', None),
26
- 'resolution': getattr(video, 'resolution', None),
23
+ "sensitiveFrameCount": getattr(video, "sensitive_frame_count", None),
24
+ "totalFrames": getattr(video, "total_frames", None),
25
+ "sensitiveRatio": getattr(video, "sensitive_ratio", None),
26
+ "duration": getattr(video, "duration", None),
27
+ "resolution": getattr(video, "resolution", None),
27
28
  }
28
29
 
29
- return Response(metadata, status=status.HTTP_200_OK)
30
+ return Response(metadata, status=status.HTTP_200_OK)
@@ -12,13 +12,14 @@ class VideoProcessingHistoryView(APIView):
12
12
  """
13
13
  GET /api/video-processing-history/{id}/ - Get processing history for a video
14
14
  """
15
+
15
16
  permission_classes = [EnvironmentAwarePermission]
16
17
 
17
18
  def get(self, request, pk):
18
19
  _video = get_object_or_404(VideoFile, pk=pk)
19
20
 
20
21
  # For now, return empty history - can be extended with actual history tracking
21
- #TODO plan when to implement this
22
+ # TODO plan when to implement this
22
23
  history = []
23
24
 
24
- return Response(history, status=status.HTTP_200_OK)
25
+ return Response(history, status=status.HTTP_200_OK)
@@ -12,37 +12,38 @@ class VideoRemoveFramesView(APIView):
12
12
  """
13
13
  POST /api/video-remove-frames/{id}/ - Remove frames from video using streaming processing
14
14
  """
15
+
15
16
  permission_classes = [EnvironmentAwarePermission]
16
17
 
17
18
  def post(self, request, pk):
18
19
  video = get_object_or_404(VideoFile, pk=pk)
19
20
 
20
- selection_method = request.data.get('selection_method', 'automatic')
21
- detection_engine = request.data.get('detection_engine', 'minicpm')
22
- use_streaming = request.data.get('use_streaming', True)
23
- manual_frames = request.data.get('manual_frames')
21
+ selection_method = request.data.get("selection_method", "automatic")
22
+ detection_engine = request.data.get("detection_engine", "minicpm")
23
+ use_streaming = request.data.get("use_streaming", True)
24
+ manual_frames = request.data.get("manual_frames")
24
25
 
25
26
  try:
26
27
  # Start async task for frame removal
27
28
  from endoreg_db.tasks.video_processing_tasks import remove_video_frames_task
28
29
 
29
30
  task_data = {
30
- 'video_id': pk,
31
- 'selection_method': selection_method,
32
- 'detection_engine': detection_engine,
33
- 'use_streaming': use_streaming,
34
- 'manual_frames': manual_frames
31
+ "video_id": pk,
32
+ "selection_method": selection_method,
33
+ "detection_engine": detection_engine,
34
+ "use_streaming": use_streaming,
35
+ "manual_frames": manual_frames,
35
36
  }
36
37
 
37
38
  task = remove_video_frames_task.delay(**task_data)
38
39
 
39
40
  return Response(
40
41
  {"task_id": task.id, "status": "started"},
41
- status=status.HTTP_202_ACCEPTED
42
+ status=status.HTTP_202_ACCEPTED,
42
43
  )
43
44
 
44
45
  except Exception as e:
45
46
  return Response(
46
47
  {"error": f"Failed to start frame removal task: {str(e)}"},
47
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
48
- )
48
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
49
+ )