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
@@ -6,6 +6,7 @@ from rest_framework.response import Response
6
6
  from endoreg_db.utils.permissions import DEBUG_PERMISSIONS
7
7
 
8
8
  import logging
9
+
9
10
  logger = logging.getLogger(__name__)
10
11
 
11
12
 
@@ -20,20 +21,21 @@ class PatientExaminationListView(generics.ListAPIView):
20
21
  - limit: Number of results (default 20)
21
22
  - offset: Pagination offset (default 0)
22
23
  """
24
+
23
25
  serializer_class = PatientExaminationSerializer
24
26
  permission_classes = DEBUG_PERMISSIONS
25
27
 
26
28
  def get_queryset(self):
27
29
  queryset = PatientExamination.objects.select_related(
28
- 'patient', 'examination'
29
- ).order_by('-date_start', '-id')
30
+ "patient", "examination"
31
+ ).order_by("-date_start", "-id")
30
32
 
31
33
  # Apply filters
32
- patient_id = self.request.query_params.get('patient_id')
34
+ patient_id = self.request.query_params.get("patient_id")
33
35
  if patient_id:
34
36
  queryset = queryset.filter(patient_id=patient_id)
35
37
 
36
- examination_name = self.request.query_params.get('examination_name')
38
+ examination_name = self.request.query_params.get("examination_name")
37
39
  if examination_name:
38
40
  queryset = queryset.filter(examination__name__icontains=examination_name)
39
41
 
@@ -44,25 +46,27 @@ class PatientExaminationListView(generics.ListAPIView):
44
46
  queryset = self.get_queryset()
45
47
 
46
48
  # Pagination
47
- limit = int(request.query_params.get('limit', 20))
48
- offset = int(request.query_params.get('offset', 0))
49
+ limit = int(request.query_params.get("limit", 20))
50
+ offset = int(request.query_params.get("offset", 0))
49
51
 
50
52
  total_count = queryset.count()
51
- paginated_queryset = queryset[offset:offset + limit]
53
+ paginated_queryset = queryset[offset : offset + limit]
52
54
 
53
55
  serializer = self.get_serializer(paginated_queryset, many=True)
54
56
 
55
- return Response({
56
- 'results': serializer.data,
57
- 'total_count': total_count,
58
- 'limit': limit,
59
- 'offset': offset,
60
- 'has_more': (offset + limit) < total_count
61
- })
57
+ return Response(
58
+ {
59
+ "results": serializer.data,
60
+ "total_count": total_count,
61
+ "limit": limit,
62
+ "offset": offset,
63
+ "has_more": (offset + limit) < total_count,
64
+ }
65
+ )
62
66
 
63
67
  except Exception as e:
64
68
  logger.error(f"Error listing examinations: {str(e)}")
65
69
  return Response(
66
- {'error': 'Failed to list examinations'},
67
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
68
- )
70
+ {"error": "Failed to list examinations"},
71
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
72
+ )
@@ -5,30 +5,29 @@ from endoreg_db.models import (
5
5
  Examination,
6
6
  VideoFile,
7
7
  Finding,
8
- FindingClassification,
9
- PatientExamination, PatientFinding, PatientFindingClassification,
10
- PatientFindingIntervention,
8
+ PatientExamination,
11
9
  )
12
10
  from django.db import DatabaseError, transaction
13
11
  from django.utils import timezone
14
12
  import logging
15
13
  from rest_framework.decorators import api_view
16
14
 
15
+
17
16
  @api_view(["GET"])
18
17
  def get_examinations_for_video(request, video_id):
19
18
  _video = get_object_or_404(VideoFile, id=video_id)
20
- #TODO no functionality implemented yet
19
+ # TODO no functionality implemented yet
21
20
  return Response([])
22
21
 
22
+
23
23
  class VideoPatientExaminationViewSet(viewsets.ModelViewSet):
24
24
  """
25
25
  ViewSet for PatientExamination CRUD operations in the context of video files
26
26
  Handles POST and PATCH for video examinations at timestamps
27
27
  """
28
28
 
29
-
30
29
  def get_queryset(self):
31
- video_id = self.request.query_params.get('videoId')
30
+ video_id = self.request.query_params.get("videoId")
32
31
  if video_id:
33
32
  return PatientExamination.objects.filter(video_id=video_id)
34
33
  return PatientExamination.objects.all()
@@ -42,50 +41,44 @@ class VideoPatientExaminationViewSet(viewsets.ModelViewSet):
42
41
  errors = {}
43
42
 
44
43
  # patient_id validation
45
- if 'patient_id' not in data:
46
- errors['patient_id'] = 'This field is required.'
44
+ if "patient_id" not in data:
45
+ errors["patient_id"] = "This field is required."
47
46
  else:
48
47
  try:
49
- data['patient_id'] = int(data['patient_id'])
48
+ data["patient_id"] = int(data["patient_id"])
50
49
  except (TypeError, ValueError):
51
- errors['patient_id'] = 'Must be an integer.'
50
+ errors["patient_id"] = "Must be an integer."
52
51
 
53
52
  # exam_date validation
54
- if 'exam_date' not in data:
55
- errors['exam_date'] = 'This field is required.'
53
+ if "exam_date" not in data:
54
+ errors["exam_date"] = "This field is required."
56
55
  else:
57
56
  from django.utils.dateparse import parse_date
58
- parsed = parse_date(data['exam_date'])
57
+
58
+ parsed = parse_date(data["exam_date"])
59
59
  if not parsed:
60
- errors['exam_date'] = 'Invalid date format.'
60
+ errors["exam_date"] = "Invalid date format."
61
61
  else:
62
- data['exam_date'] = parsed
62
+ data["exam_date"] = parsed
63
63
 
64
64
  # video_file presence
65
- if 'video_file' not in data:
66
- errors['video_file'] = 'This field is required.'
65
+ if "video_file" not in data:
66
+ errors["video_file"] = "This field is required."
67
67
 
68
68
  return data, errors
69
69
 
70
-
71
70
  def _create_examination_data(self, validated_data):
72
71
  """
73
72
  Create examination and video record, then return payload.
74
73
  """
75
74
  # assume Examination, Video imported above
76
75
  exam = Examination.objects.create(
77
- patient_id=validated_data['patient_id'],
78
- date=validated_data['exam_date']
76
+ patient_id=validated_data["patient_id"], date=validated_data["exam_date"]
79
77
  )
80
78
  vid = VideoFile.objects.create(
81
- examination=exam,
82
- file=validated_data['video_file']
79
+ examination=exam, file=validated_data["video_file"]
83
80
  )
84
- return {
85
- 'examination_id': exam.id,
86
- 'video_id': vid.id
87
- }
88
-
81
+ return {"examination_id": exam.id, "video_id": vid.id}
89
82
 
90
83
  def create(self, request, *args, **kwargs):
91
84
  """
@@ -94,101 +87,142 @@ class VideoPatientExaminationViewSet(viewsets.ModelViewSet):
94
87
  logger = logging.getLogger(__name__)
95
88
  clean_data, errors = self._validate_create_data(request)
96
89
  if errors:
97
- return Response({'errors': errors}, status=400)
90
+ return Response({"errors": errors}, status=400)
98
91
 
99
92
  try:
100
93
  payload = self._create_examination_data(clean_data)
101
94
  return Response(payload, status=201)
102
95
  except DatabaseError as db_err:
103
- return Response(
104
- {'error': f'Database error: {db_err}'},
105
- status=500
106
- )
96
+ return Response({"error": f"Database error: {db_err}"}, status=500)
107
97
  except Exception:
108
98
  logger.exception("Unexpected error in create()")
109
- return Response(
110
- {'error': 'Internal server error'},
111
- status=500
112
- )
99
+ return Response({"error": "Internal server error"}, status=500)
113
100
 
114
101
  def update(self, request, *args, **kwargs):
115
102
  logger = logging.getLogger(__name__)
116
103
  try:
117
- examination_id = kwargs.get('pk')
104
+ examination_id = kwargs.get("pk")
118
105
  if not examination_id:
119
- return Response({'error': 'Examination ID is required'}, status=status.HTTP_400_BAD_REQUEST)
106
+ return Response(
107
+ {"error": "Examination ID is required"},
108
+ status=status.HTTP_400_BAD_REQUEST,
109
+ )
120
110
  data = request.data
121
- if 'videoId' in data:
111
+ if "videoId" in data:
122
112
  try:
123
- data['videoId'] = int(data['videoId'])
113
+ data["videoId"] = int(data["videoId"])
124
114
  except (ValueError, TypeError):
125
- return Response({'error': 'Invalid videoId format'}, status=status.HTTP_400_BAD_REQUEST)
126
- if 'timestamp' in data:
115
+ return Response(
116
+ {"error": "Invalid videoId format"},
117
+ status=status.HTTP_400_BAD_REQUEST,
118
+ )
119
+ if "timestamp" in data:
127
120
  try:
128
- timestamp = float(data['timestamp'])
121
+ timestamp = float(data["timestamp"])
129
122
  if timestamp < 0:
130
- return Response({'error': 'Timestamp cannot be negative'}, status=status.HTTP_400_BAD_REQUEST)
131
- data['timestamp'] = timestamp
123
+ return Response(
124
+ {"error": "Timestamp cannot be negative"},
125
+ status=status.HTTP_400_BAD_REQUEST,
126
+ )
127
+ data["timestamp"] = timestamp
132
128
  except (ValueError, TypeError):
133
- return Response({'error': 'Invalid timestamp format'}, status=status.HTTP_400_BAD_REQUEST)
129
+ return Response(
130
+ {"error": "Invalid timestamp format"},
131
+ status=status.HTTP_400_BAD_REQUEST,
132
+ )
134
133
  with transaction.atomic():
135
- if 'videoId' in data:
134
+ if "videoId" in data:
136
135
  try:
137
- VideoFile.objects.get(id=data['videoId'])
136
+ VideoFile.objects.get(id=data["videoId"])
138
137
  except VideoFile.DoesNotExist:
139
- return Response({'error': 'Video not found'}, status=status.HTTP_404_NOT_FOUND)
140
- if 'examinationTypeId' in data:
138
+ return Response(
139
+ {"error": "Video not found"},
140
+ status=status.HTTP_404_NOT_FOUND,
141
+ )
142
+ if "examinationTypeId" in data:
141
143
  try:
142
- examination_type_id = int(data['examinationTypeId'])
144
+ examination_type_id = int(data["examinationTypeId"])
143
145
  Examination.objects.get(id=examination_type_id)
144
146
  except (ValueError, TypeError):
145
- return Response({'error': 'Invalid examination type ID format'}, status=status.HTTP_400_BAD_REQUEST)
147
+ return Response(
148
+ {"error": "Invalid examination type ID format"},
149
+ status=status.HTTP_400_BAD_REQUEST,
150
+ )
146
151
  except Examination.DoesNotExist:
147
- return Response({'error': 'Examination type not found'}, status=status.HTTP_404_NOT_FOUND)
148
- if 'findingId' in data:
152
+ return Response(
153
+ {"error": "Examination type not found"},
154
+ status=status.HTTP_404_NOT_FOUND,
155
+ )
156
+ if "findingId" in data:
149
157
  try:
150
- finding_id = int(data['findingId'])
158
+ finding_id = int(data["findingId"])
151
159
  Finding.objects.get(id=finding_id)
152
160
  except (ValueError, TypeError):
153
- return Response({'error': 'Invalid finding ID format'}, status=status.HTTP_400_BAD_REQUEST)
161
+ return Response(
162
+ {"error": "Invalid finding ID format"},
163
+ status=status.HTTP_400_BAD_REQUEST,
164
+ )
154
165
  except Finding.DoesNotExist:
155
- return Response({'error': 'Finding not found'}, status=status.HTTP_404_NOT_FOUND)
166
+ return Response(
167
+ {"error": "Finding not found"},
168
+ status=status.HTTP_404_NOT_FOUND,
169
+ )
156
170
  examination_data = {
157
- 'id': examination_id,
158
- 'video_id': data.get('videoId'),
159
- 'timestamp': data.get('timestamp'),
160
- 'examination_type': data.get('examinationTypeId'),
161
- 'finding': data.get('findingId'),
162
- 'location_classification': data.get('locationClassificationId'),
163
- 'location_choice': data.get('locationChoiceId'),
164
- 'morphology_classification': data.get('morphologyClassificationId'),
165
- 'morphology_choice': data.get('morphologyChoiceId'),
166
- 'interventions': data.get('interventionIds', []),
167
- 'notes': data.get('notes', ''),
168
- 'updated_at': timezone.now().isoformat()
171
+ "id": examination_id,
172
+ "video_id": data.get("videoId"),
173
+ "timestamp": data.get("timestamp"),
174
+ "examination_type": data.get("examinationTypeId"),
175
+ "finding": data.get("findingId"),
176
+ "location_classification": data.get("locationClassificationId"),
177
+ "location_choice": data.get("locationChoiceId"),
178
+ "morphology_classification": data.get("morphologyClassificationId"),
179
+ "morphology_choice": data.get("morphologyChoiceId"),
180
+ "interventions": data.get("interventionIds", []),
181
+ "notes": data.get("notes", ""),
182
+ "updated_at": timezone.now().isoformat(),
169
183
  }
170
184
  logger.info(f"Updated video examination {examination_id}")
171
185
  return Response(examination_data, status=status.HTTP_200_OK)
172
186
  except Exception as e:
173
- logger.error(f"Unexpected error updating examination {examination_id}: {str(e)}")
174
- return Response({'error': 'Internal server error while updating examination'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
187
+ logger.error(
188
+ f"Unexpected error updating examination {examination_id}: {str(e)}"
189
+ )
190
+ return Response(
191
+ {"error": "Internal server error while updating examination"},
192
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
193
+ )
175
194
 
176
195
  def destroy(self, request, *args, **kwargs):
177
196
  logger = logging.getLogger(__name__)
178
197
  try:
179
- examination_id = kwargs.get('pk')
198
+ examination_id = kwargs.get("pk")
180
199
  if not examination_id:
181
- return Response({'error': 'Examination ID is required'}, status=status.HTTP_400_BAD_REQUEST)
200
+ return Response(
201
+ {"error": "Examination ID is required"},
202
+ status=status.HTTP_400_BAD_REQUEST,
203
+ )
182
204
  try:
183
205
  if not str(examination_id).strip():
184
- return Response({'error': 'Invalid examination ID format'}, status=status.HTTP_400_BAD_REQUEST)
206
+ return Response(
207
+ {"error": "Invalid examination ID format"},
208
+ status=status.HTTP_400_BAD_REQUEST,
209
+ )
185
210
  except (ValueError, TypeError):
186
- return Response({'error': 'Invalid examination ID format'}, status=status.HTTP_400_BAD_REQUEST)
211
+ return Response(
212
+ {"error": "Invalid examination ID format"},
213
+ status=status.HTTP_400_BAD_REQUEST,
214
+ )
187
215
  with transaction.atomic():
188
216
  logger.info(f"Deleted video examination {examination_id}")
189
- return Response({'message': f'Examination {examination_id} deleted successfully'}, status=status.HTTP_204_NO_CONTENT)
217
+ return Response(
218
+ {"message": f"Examination {examination_id} deleted successfully"},
219
+ status=status.HTTP_204_NO_CONTENT,
220
+ )
190
221
  except Exception as e:
191
- logger.error(f"Unexpected error deleting examination {examination_id}: {str(e)}")
192
- return Response({'error': 'Internal server error while deleting examination'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
193
-
194
-
222
+ logger.error(
223
+ f"Unexpected error deleting examination {examination_id}: {str(e)}"
224
+ )
225
+ return Response(
226
+ {"error": "Internal server error while deleting examination"},
227
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
228
+ )
@@ -4,4 +4,4 @@ from .patient_finding_optimized import OptimizedPatientFindingViewSet
4
4
  __all__ = [
5
5
  "PatientFindingViewSet",
6
6
  "OptimizedPatientFindingViewSet",
7
- ]
7
+ ]
@@ -10,9 +10,13 @@ class PatientFindingViewSet(ModelViewSet):
10
10
  queryset = PatientFinding.objects.all()
11
11
  serializer_class = PatientFindingSerializer
12
12
  filter_backends = [DjangoFilterBackend]
13
- filterset_fields = ['patient_examination']
14
-
15
- @action(detail=False, methods=['get'], url_path='by-examination/(?P<patient_examination_id>[^/.]+)')
13
+ filterset_fields = ["patient_examination"]
14
+
15
+ @action(
16
+ detail=False,
17
+ methods=["get"],
18
+ url_path="by-examination/(?P<patient_examination_id>[^/.]+)",
19
+ )
16
20
  def get_patient_findings_by_examination(self, request, patient_examination_id=None):
17
21
  """Explicitly get patient findings by patient examination id_
18
22
 
@@ -23,12 +27,15 @@ class PatientFindingViewSet(ModelViewSet):
23
27
  Returns:
24
28
  _type_: _description_
25
29
  """
26
- patient_finding_objs = PatientFinding.objects.filter(patient_examination=patient_examination_id)
30
+ patient_finding_objs = PatientFinding.objects.filter(
31
+ patient_examination=patient_examination_id
32
+ )
27
33
  serializer = self.get_serializer(patient_finding_objs, many=True)
28
34
  return Response(serializer.data)
29
-
30
35
 
31
- @action(detail=False, methods=['get'], url_path='by-id/(?P<patient_finding_id>[^/.]+)')
36
+ @action(
37
+ detail=False, methods=["get"], url_path="by-id/(?P<patient_finding_id>[^/.]+)"
38
+ )
32
39
  def get_patient_finding_by_id(self, request, patient_finding_id=None):
33
40
  """_summary_
34
41
 
@@ -42,18 +49,18 @@ class PatientFindingViewSet(ModelViewSet):
42
49
  patient_finding_obj = PatientFinding.objects.filter(id=patient_finding_id)
43
50
  serializer = self.get_serializer(patient_finding_obj, many=True)
44
51
  return Response(serializer.data)
45
-
52
+
46
53
  def add_patient_finding(self, request):
47
54
  """
48
55
  Endpoint to add a new finding to a PatientExamination
49
56
  POST /api/patient_findings/add/
50
57
  """
51
-
58
+
52
59
  serializer = self.get_serializer(data=request.data)
53
60
  serializer.is_valid(raise_exception=True)
54
61
  serializer.save()
55
62
  return Response(serializer.data, status=201)
56
-
63
+
57
64
  def get_all_patient_findings(self, request):
58
65
  """
59
66
  Endpoint to retrieve all PatientFindings
@@ -61,4 +68,4 @@ class PatientFindingViewSet(ModelViewSet):
61
68
  """
62
69
  findings = PatientFinding.objects.all()
63
70
  serializer = self.get_serializer(findings, many=True)
64
- return Response(serializer.data)
71
+ return Response(serializer.data)