endoreg-db 0.8.8.0__py3-none-any.whl → 0.8.8.9__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 (402) hide show
  1. endoreg_db/data/__init__.py +22 -8
  2. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +0 -1
  3. endoreg_db/data/examination/examinations/data.yaml +114 -14
  4. endoreg_db/data/examination/time-type/data.yaml +0 -3
  5. endoreg_db/data/examination_indication/endoscopy.yaml +108 -173
  6. endoreg_db/data/examination_indication_classification/endoscopy.yaml +0 -70
  7. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +33 -37
  8. endoreg_db/data/finding/00_generic.yaml +35 -0
  9. endoreg_db/data/finding/00_generic_complication.yaml +9 -0
  10. endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
  11. endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
  12. endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
  13. endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
  14. endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
  15. endoreg_db/data/finding_classification/00_generic.yaml +44 -0
  16. endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
  17. endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
  18. endoreg_db/data/finding_classification/{colonoscopy_bowel_preparation.yaml → 02_colonoscopy_baseline.yaml} +35 -20
  19. endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
  20. endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
  21. endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
  22. endoreg_db/data/finding_classification_choice/{yes_no_na.yaml → 00_generic.yaml} +5 -1
  23. endoreg_db/data/finding_classification_choice/{examination_setting_generic_types.yaml → 00_generic_baseline.yaml} +10 -2
  24. endoreg_db/data/finding_classification_choice/{complication_generic_types.yaml → 00_generic_complication.yaml} +1 -1
  25. endoreg_db/data/finding_classification_choice/{histology.yaml → 00_generic_histology.yaml} +1 -4
  26. endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
  27. endoreg_db/data/finding_classification_choice/{bowel_preparation.yaml → 02_colonoscopy_bowel_preparation.yaml} +1 -30
  28. endoreg_db/data/{_examples/finding_classification_choice/colonoscopy_not_complete_reason.yaml → finding_classification_choice/02_colonoscopy_generic.yaml} +1 -1
  29. endoreg_db/data/finding_classification_choice/{histology_polyp.yaml → 02_colonoscopy_histology.yaml} +1 -1
  30. endoreg_db/data/{_examples/finding_classification_choice/colonoscopy_location.yaml → finding_classification_choice/02_colonoscopy_location.yaml} +23 -4
  31. endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
  32. endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
  33. endoreg_db/data/{_examples/finding_classification_choice/colon_lesion_paris.yaml → finding_classification_choice/02_colonoscopy_polyp_morphology.yaml} +26 -8
  34. endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
  35. endoreg_db/data/finding_classification_type/{colonoscopy_basic.yaml → 00_generic.yaml} +18 -13
  36. endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
  37. endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
  38. endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
  39. endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
  40. endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
  41. endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
  42. endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
  43. endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
  44. endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
  45. endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
  46. endoreg_db/data/finding_type/data.yaml +8 -12
  47. endoreg_db/data/requirement/01_patient_data.yaml +93 -0
  48. endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
  49. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +0 -2
  50. endoreg_db/data/requirement_set/90_coloreg.yaml +20 -8
  51. endoreg_db/exceptions.py +0 -1
  52. endoreg_db/forms/examination_form.py +1 -1
  53. endoreg_db/helpers/data_loader.py +124 -52
  54. endoreg_db/helpers/default_objects.py +116 -81
  55. endoreg_db/import_files/__init__.py +27 -0
  56. endoreg_db/import_files/context/__init__.py +7 -0
  57. endoreg_db/import_files/context/default_sensitive_meta.py +81 -0
  58. endoreg_db/import_files/context/ensure_center.py +17 -0
  59. endoreg_db/import_files/context/file_lock.py +66 -0
  60. endoreg_db/import_files/context/import_context.py +43 -0
  61. endoreg_db/import_files/context/validate_directories.py +56 -0
  62. endoreg_db/import_files/file_storage/__init__.py +15 -0
  63. endoreg_db/import_files/file_storage/create_report_file.py +76 -0
  64. endoreg_db/import_files/file_storage/create_video_file.py +75 -0
  65. endoreg_db/import_files/file_storage/sensitive_meta_storage.py +39 -0
  66. endoreg_db/import_files/file_storage/state_management.py +400 -0
  67. endoreg_db/import_files/file_storage/storage.py +36 -0
  68. endoreg_db/import_files/import_service.md +26 -0
  69. endoreg_db/import_files/processing/__init__.py +11 -0
  70. endoreg_db/import_files/processing/report_processing/report_anonymization.py +94 -0
  71. endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
  72. endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
  73. endoreg_db/import_files/processing/video_processing/video_cleanup_on_error.py +119 -0
  74. endoreg_db/import_files/pseudonymization/fake.py +52 -0
  75. endoreg_db/import_files/pseudonymization/k_anonymity.py +182 -0
  76. endoreg_db/import_files/pseudonymization/k_pseudonymity.py +128 -0
  77. endoreg_db/import_files/report_import_service.py +141 -0
  78. endoreg_db/import_files/video_import_service.py +150 -0
  79. endoreg_db/management/commands/import_report.py +130 -65
  80. endoreg_db/management/commands/import_video_with_classification.py +1 -1
  81. endoreg_db/management/commands/load_ai_model_data.py +5 -5
  82. endoreg_db/management/commands/load_ai_model_label_data.py +9 -7
  83. endoreg_db/management/commands/load_base_db_data.py +5 -134
  84. endoreg_db/management/commands/load_contraindication_data.py +14 -16
  85. endoreg_db/management/commands/load_disease_classification_choices_data.py +15 -18
  86. endoreg_db/management/commands/load_disease_classification_data.py +15 -18
  87. endoreg_db/management/commands/load_disease_data.py +25 -28
  88. endoreg_db/management/commands/load_endoscope_data.py +20 -27
  89. endoreg_db/management/commands/load_event_data.py +14 -16
  90. endoreg_db/management/commands/load_examination_data.py +31 -44
  91. endoreg_db/management/commands/load_examination_indication_data.py +20 -21
  92. endoreg_db/management/commands/load_finding_data.py +52 -80
  93. endoreg_db/management/commands/load_information_source.py +21 -23
  94. endoreg_db/management/commands/load_lab_value_data.py +17 -26
  95. endoreg_db/management/commands/load_medication_data.py +13 -12
  96. endoreg_db/management/commands/load_organ_data.py +15 -19
  97. endoreg_db/management/commands/load_pdf_type_data.py +19 -18
  98. endoreg_db/management/commands/load_profession_data.py +14 -17
  99. endoreg_db/management/commands/load_qualification_data.py +20 -23
  100. endoreg_db/management/commands/load_report_reader_flag_data.py +17 -19
  101. endoreg_db/management/commands/load_requirement_data.py +14 -20
  102. endoreg_db/management/commands/load_risk_data.py +7 -6
  103. endoreg_db/management/commands/load_shift_data.py +20 -23
  104. endoreg_db/management/commands/load_tag_data.py +8 -11
  105. endoreg_db/management/commands/load_unit_data.py +17 -19
  106. endoreg_db/management/commands/start_filewatcher.py +46 -37
  107. endoreg_db/management/commands/validate_video_files.py +1 -5
  108. endoreg_db/migrations/0001_initial.py +1360 -1812
  109. endoreg_db/models/administration/person/patient/patient.py +72 -46
  110. endoreg_db/models/label/__init__.py +2 -2
  111. endoreg_db/models/label/annotation/video_segmentation_annotation.py +18 -26
  112. endoreg_db/models/label/label_video_segment/label_video_segment.py +23 -1
  113. endoreg_db/models/media/pdf/raw_pdf.py +136 -64
  114. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +34 -10
  115. endoreg_db/models/media/processing_history/__init__.py +5 -0
  116. endoreg_db/models/media/processing_history/processing_history.py +96 -0
  117. endoreg_db/models/media/video/create_from_file.py +101 -31
  118. endoreg_db/models/media/video/video_file.py +125 -105
  119. endoreg_db/models/media/video/video_file_io.py +31 -26
  120. endoreg_db/models/medical/contraindication/README.md +1 -0
  121. endoreg_db/models/medical/examination/examination.py +28 -8
  122. endoreg_db/models/medical/examination/examination_indication.py +13 -79
  123. endoreg_db/models/medical/examination/examination_time.py +8 -3
  124. endoreg_db/models/medical/finding/finding.py +5 -12
  125. endoreg_db/models/medical/finding/finding_classification.py +18 -37
  126. endoreg_db/models/medical/finding/finding_intervention.py +7 -9
  127. endoreg_db/models/medical/hardware/endoscope.py +6 -0
  128. endoreg_db/models/medical/patient/medication_examples.py +5 -1
  129. endoreg_db/models/medical/patient/patient_finding.py +1 -1
  130. endoreg_db/models/metadata/pdf_meta.py +22 -10
  131. endoreg_db/models/metadata/sensitive_meta.py +3 -0
  132. endoreg_db/models/metadata/sensitive_meta_logic.py +200 -124
  133. endoreg_db/models/other/information_source.py +27 -6
  134. endoreg_db/models/report/__init__.py +0 -0
  135. endoreg_db/models/report/images.py +0 -0
  136. endoreg_db/models/report/report.py +6 -0
  137. endoreg_db/models/requirement/requirement.py +59 -399
  138. endoreg_db/models/requirement/requirement_operator.py +86 -98
  139. endoreg_db/models/state/audit_ledger.py +4 -5
  140. endoreg_db/models/state/raw_pdf.py +69 -30
  141. endoreg_db/models/state/video.py +64 -49
  142. endoreg_db/models/upload_job.py +33 -9
  143. endoreg_db/models/utils.py +27 -23
  144. endoreg_db/queries/__init__.py +3 -1
  145. endoreg_db/schemas/examination_evaluation.py +1 -1
  146. endoreg_db/serializers/__init__.py +2 -8
  147. endoreg_db/serializers/label_video_segment/label_video_segment.py +2 -29
  148. endoreg_db/serializers/meta/__init__.py +1 -6
  149. endoreg_db/serializers/misc/sensitive_patient_data.py +50 -26
  150. endoreg_db/serializers/patient_examination/patient_examination.py +3 -3
  151. endoreg_db/serializers/pdf/anony_text_validation.py +39 -23
  152. endoreg_db/serializers/video/video_file_list.py +65 -34
  153. endoreg_db/services/__old/pdf_import.py +1487 -0
  154. endoreg_db/services/__old/video_import.py +1306 -0
  155. endoreg_db/services/anonymization.py +63 -26
  156. endoreg_db/services/lookup_service.py +28 -28
  157. endoreg_db/services/lookup_store.py +2 -2
  158. endoreg_db/services/pdf_import.py +0 -1480
  159. endoreg_db/services/report_import.py +10 -0
  160. endoreg_db/services/video_import.py +6 -1165
  161. endoreg_db/tasks/upload_tasks.py +79 -70
  162. endoreg_db/tasks/video_ingest.py +8 -4
  163. endoreg_db/urls/__init__.py +0 -14
  164. endoreg_db/urls/ai.py +32 -0
  165. endoreg_db/urls/media.py +21 -24
  166. endoreg_db/utils/dataloader.py +87 -57
  167. endoreg_db/utils/paths.py +110 -46
  168. endoreg_db/utils/pipelines/Readme.md +1 -1
  169. endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +97 -0
  170. endoreg_db/views/__init__.py +85 -173
  171. endoreg_db/views/ai/__init__.py +8 -0
  172. endoreg_db/views/ai/label.py +155 -0
  173. endoreg_db/views/anonymization/media_management.py +8 -7
  174. endoreg_db/views/anonymization/overview.py +97 -68
  175. endoreg_db/views/anonymization/validate.py +25 -21
  176. endoreg_db/views/media/__init__.py +5 -20
  177. endoreg_db/views/media/pdf_media.py +109 -65
  178. endoreg_db/views/media/sensitive_metadata.py +163 -148
  179. endoreg_db/views/meta/__init__.py +0 -8
  180. endoreg_db/views/misc/__init__.py +1 -7
  181. endoreg_db/views/misc/upload_views.py +94 -93
  182. endoreg_db/views/report/__init__.py +7 -0
  183. endoreg_db/views/{pdf → report}/reimport.py +45 -24
  184. endoreg_db/views/{pdf/pdf_stream.py → report/report_stream.py} +40 -32
  185. endoreg_db/views/requirement/lookup_store.py +22 -90
  186. endoreg_db/views/video/__init__.py +23 -22
  187. endoreg_db/views/video/correction.py +201 -172
  188. endoreg_db/views/video/reimport.py +1 -1
  189. endoreg_db/views/{media/video_segments.py → video/segments_crud.py} +75 -37
  190. endoreg_db/views/video/{video_meta.py → video_meta_stats.py} +2 -2
  191. endoreg_db/views/video/video_stream.py +7 -8
  192. {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.8.9.dist-info}/METADATA +2 -2
  193. {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.8.9.dist-info}/RECORD +217 -335
  194. {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.8.9.dist-info}/WHEEL +1 -1
  195. endoreg_db/data/_examples/disease.yaml +0 -55
  196. endoreg_db/data/_examples/disease_classification.yaml +0 -13
  197. endoreg_db/data/_examples/disease_classification_choice.yaml +0 -62
  198. endoreg_db/data/_examples/event.yaml +0 -64
  199. endoreg_db/data/_examples/examination.yaml +0 -72
  200. endoreg_db/data/_examples/finding/anatomy_colon.yaml +0 -128
  201. endoreg_db/data/_examples/finding/colonoscopy.yaml +0 -40
  202. endoreg_db/data/_examples/finding/colonoscopy_bowel_prep.yaml +0 -56
  203. endoreg_db/data/_examples/finding/complication.yaml +0 -16
  204. endoreg_db/data/_examples/finding/data.yaml +0 -105
  205. endoreg_db/data/_examples/finding/examination_setting.yaml +0 -16
  206. endoreg_db/data/_examples/finding/medication_related.yaml +0 -18
  207. endoreg_db/data/_examples/finding/outcome.yaml +0 -12
  208. endoreg_db/data/_examples/finding_classification/colonoscopy_bowel_preparation.yaml +0 -68
  209. endoreg_db/data/_examples/finding_classification/colonoscopy_jnet.yaml +0 -22
  210. endoreg_db/data/_examples/finding_classification/colonoscopy_kudo.yaml +0 -25
  211. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
  212. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
  213. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_size.yaml +0 -68
  214. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
  215. endoreg_db/data/_examples/finding_classification/colonoscopy_location.yaml +0 -80
  216. endoreg_db/data/_examples/finding_classification/colonoscopy_lst.yaml +0 -21
  217. endoreg_db/data/_examples/finding_classification/colonoscopy_nice.yaml +0 -20
  218. endoreg_db/data/_examples/finding_classification/colonoscopy_paris.yaml +0 -26
  219. endoreg_db/data/_examples/finding_classification/colonoscopy_sano.yaml +0 -22
  220. endoreg_db/data/_examples/finding_classification/colonoscopy_summary.yaml +0 -53
  221. endoreg_db/data/_examples/finding_classification/complication_generic.yaml +0 -25
  222. endoreg_db/data/_examples/finding_classification/examination_setting_generic.yaml +0 -40
  223. endoreg_db/data/_examples/finding_classification/histology_colo.yaml +0 -51
  224. endoreg_db/data/_examples/finding_classification/intervention_required.yaml +0 -26
  225. endoreg_db/data/_examples/finding_classification/medication_related.yaml +0 -23
  226. endoreg_db/data/_examples/finding_classification/visualized.yaml +0 -33
  227. endoreg_db/data/_examples/finding_classification_choice/bowel_preparation.yaml +0 -78
  228. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
  229. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
  230. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
  231. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_lst.yaml +0 -15
  232. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_nice.yaml +0 -17
  233. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
  234. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_sano.yaml +0 -14
  235. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
  236. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_size.yaml +0 -82
  237. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
  238. endoreg_db/data/_examples/finding_classification_choice/complication_generic_types.yaml +0 -15
  239. endoreg_db/data/_examples/finding_classification_choice/examination_setting_generic_types.yaml +0 -15
  240. endoreg_db/data/_examples/finding_classification_choice/histology.yaml +0 -24
  241. endoreg_db/data/_examples/finding_classification_choice/histology_polyp.yaml +0 -20
  242. endoreg_db/data/_examples/finding_classification_choice/outcome.yaml +0 -19
  243. endoreg_db/data/_examples/finding_classification_choice/yes_no_na.yaml +0 -11
  244. endoreg_db/data/_examples/finding_classification_type/colonoscopy_basic.yaml +0 -48
  245. endoreg_db/data/_examples/finding_intervention/endoscopy.yaml +0 -43
  246. endoreg_db/data/_examples/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
  247. endoreg_db/data/_examples/finding_intervention/endoscopy_egd.yaml +0 -128
  248. endoreg_db/data/_examples/finding_intervention/endoscopy_ercp.yaml +0 -32
  249. endoreg_db/data/_examples/finding_intervention/endoscopy_eus_lower.yaml +0 -9
  250. endoreg_db/data/_examples/finding_intervention/endoscopy_eus_upper.yaml +0 -36
  251. endoreg_db/data/_examples/finding_intervention_type/endoscopy.yaml +0 -15
  252. endoreg_db/data/_examples/finding_type/data.yaml +0 -43
  253. endoreg_db/data/_examples/requirement/age.yaml +0 -26
  254. endoreg_db/data/_examples/requirement/gender.yaml +0 -25
  255. endoreg_db/data/_examples/requirement_set/01_endoscopy_generic.yaml +0 -48
  256. endoreg_db/data/_examples/requirement_set/colonoscopy_austria_screening.yaml +0 -57
  257. endoreg_db/data/_examples/requirement_set/endoscopy_bleeding_risk.yaml +0 -52
  258. endoreg_db/data/_examples/yaml_examples.xlsx +0 -0
  259. endoreg_db/data/finding/anatomy_colon.yaml +0 -128
  260. endoreg_db/data/finding/colonoscopy.yaml +0 -40
  261. endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +0 -56
  262. endoreg_db/data/finding/complication.yaml +0 -16
  263. endoreg_db/data/finding/data.yaml +0 -105
  264. endoreg_db/data/finding/examination_setting.yaml +0 -16
  265. endoreg_db/data/finding/medication_related.yaml +0 -18
  266. endoreg_db/data/finding/outcome.yaml +0 -12
  267. endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +0 -22
  268. endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +0 -25
  269. endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
  270. endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
  271. endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +0 -38
  272. endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
  273. endoreg_db/data/finding_classification/colonoscopy_location.yaml +0 -49
  274. endoreg_db/data/finding_classification/colonoscopy_lst.yaml +0 -21
  275. endoreg_db/data/finding_classification/colonoscopy_nice.yaml +0 -20
  276. endoreg_db/data/finding_classification/colonoscopy_paris.yaml +0 -26
  277. endoreg_db/data/finding_classification/colonoscopy_sano.yaml +0 -22
  278. endoreg_db/data/finding_classification/colonoscopy_summary.yaml +0 -53
  279. endoreg_db/data/finding_classification/complication_generic.yaml +0 -25
  280. endoreg_db/data/finding_classification/examination_setting_generic.yaml +0 -40
  281. endoreg_db/data/finding_classification/histology_colo.yaml +0 -43
  282. endoreg_db/data/finding_classification/intervention_required.yaml +0 -26
  283. endoreg_db/data/finding_classification/medication_related.yaml +0 -23
  284. endoreg_db/data/finding_classification/visualized.yaml +0 -33
  285. endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
  286. endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
  287. endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
  288. endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +0 -15
  289. endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +0 -17
  290. endoreg_db/data/finding_classification_choice/colon_lesion_paris.yaml +0 -57
  291. endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
  292. endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +0 -14
  293. endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
  294. endoreg_db/data/finding_classification_choice/colonoscopy_location.yaml +0 -229
  295. endoreg_db/data/finding_classification_choice/colonoscopy_not_complete_reason.yaml +0 -19
  296. endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +0 -82
  297. endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
  298. endoreg_db/data/finding_classification_choice/outcome.yaml +0 -19
  299. endoreg_db/data/finding_intervention/endoscopy.yaml +0 -43
  300. endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
  301. endoreg_db/data/finding_intervention/endoscopy_egd.yaml +0 -128
  302. endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +0 -32
  303. endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +0 -9
  304. endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +0 -36
  305. endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +0 -79
  306. endoreg_db/data/requirement/age.yaml +0 -26
  307. endoreg_db/data/requirement/colonoscopy_baseline_austria.yaml +0 -45
  308. endoreg_db/data/requirement/disease_cardiovascular.yaml +0 -79
  309. endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +0 -41
  310. endoreg_db/data/requirement/disease_hepatology.yaml +0 -12
  311. endoreg_db/data/requirement/disease_misc.yaml +0 -12
  312. endoreg_db/data/requirement/disease_renal.yaml +0 -96
  313. endoreg_db/data/requirement/endoscopy_bleeding_risk.yaml +0 -59
  314. endoreg_db/data/requirement/event_cardiology.yaml +0 -251
  315. endoreg_db/data/requirement/event_requirements.yaml +0 -145
  316. endoreg_db/data/requirement/finding_colon_polyp.yaml +0 -50
  317. endoreg_db/data/requirement/gender.yaml +0 -25
  318. endoreg_db/data/requirement/lab_value.yaml +0 -441
  319. endoreg_db/data/requirement/medication.yaml +0 -93
  320. endoreg_db/data/requirement_operator/age.yaml +0 -13
  321. endoreg_db/data/requirement_operator/lab_operators.yaml +0 -129
  322. endoreg_db/data/requirement_operator/model_operators.yaml +0 -96
  323. endoreg_db/management/commands/init_default_ai_model.py +0 -112
  324. endoreg_db/management/commands/reset_celery_schedule.py +0 -9
  325. endoreg_db/management/commands/validate_video.py +0 -204
  326. endoreg_db/migrations/0002_requirementset_depends_on.py +0 -18
  327. endoreg_db/migrations/_old/0001_initial.py +0 -1857
  328. endoreg_db/migrations/_old/0002_add_video_correction_models.py +0 -52
  329. endoreg_db/migrations/_old/0003_add_center_display_name.py +0 -30
  330. endoreg_db/migrations/_old/0004_employee_city_employee_post_code_employee_street_and_more.py +0 -68
  331. endoreg_db/migrations/_old/0004_remove_casetemplate_rules_and_more.py +0 -77
  332. endoreg_db/migrations/_old/0005_merge_20251111_1003.py +0 -14
  333. endoreg_db/migrations/_old/0006_sensitivemeta_anonymized_text_and_more.py +0 -68
  334. endoreg_db/migrations/_old/0007_remove_rule_attribute_dtype_remove_rule_rule_type_and_more.py +0 -89
  335. endoreg_db/migrations/_old/0008_remove_event_event_classification_and_more.py +0 -27
  336. endoreg_db/migrations/_old/0009_alter_modelmeta_options_and_more.py +0 -21
  337. endoreg_db/renames.yml +0 -8
  338. endoreg_db/serializers/_old/raw_pdf_meta_validation.py +0 -223
  339. endoreg_db/serializers/_old/raw_video_meta_validation.py +0 -179
  340. endoreg_db/serializers/_old/video.py +0 -71
  341. endoreg_db/serializers/meta/pdf_file_meta_extraction.py +0 -115
  342. endoreg_db/serializers/meta/report_meta.py +0 -53
  343. endoreg_db/serializers/report/__init__.py +0 -9
  344. endoreg_db/serializers/report/mixins.py +0 -45
  345. endoreg_db/serializers/report/report.py +0 -105
  346. endoreg_db/serializers/report/report_list.py +0 -22
  347. endoreg_db/serializers/report/secure_file_url.py +0 -26
  348. endoreg_db/services/requirements_object.py +0 -147
  349. endoreg_db/services/storage_aware_video_processor.py +0 -370
  350. endoreg_db/urls/files.py +0 -6
  351. endoreg_db/urls/label_video_segment_validate.py +0 -33
  352. endoreg_db/urls/label_video_segments.py +0 -46
  353. endoreg_db/views/label/__init__.py +0 -5
  354. endoreg_db/views/label/label.py +0 -15
  355. endoreg_db/views/label_video_segment/__init__.py +0 -16
  356. endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +0 -44
  357. endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +0 -50
  358. endoreg_db/views/label_video_segment/label_video_segment.py +0 -77
  359. endoreg_db/views/label_video_segment/label_video_segment_by_label.py +0 -174
  360. endoreg_db/views/label_video_segment/label_video_segment_detail.py +0 -73
  361. endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +0 -46
  362. endoreg_db/views/label_video_segment/validate.py +0 -226
  363. endoreg_db/views/media/segments.py +0 -71
  364. endoreg_db/views/meta/available_files_list.py +0 -146
  365. endoreg_db/views/meta/report_meta.py +0 -53
  366. endoreg_db/views/meta/sensitive_meta_detail.py +0 -85
  367. endoreg_db/views/misc/secure_file_serving_view.py +0 -80
  368. endoreg_db/views/misc/secure_file_url_view.py +0 -84
  369. endoreg_db/views/misc/secure_url_validate.py +0 -79
  370. endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +0 -164
  371. endoreg_db/views/patient_finding_location/__init__.py +0 -5
  372. endoreg_db/views/patient_finding_location/pfl_create.py +0 -70
  373. endoreg_db/views/patient_finding_morphology/__init__.py +0 -5
  374. endoreg_db/views/patient_finding_morphology/pfm_create.py +0 -70
  375. endoreg_db/views/pdf/__init__.py +0 -8
  376. endoreg_db/views/video/segmentation.py +0 -274
  377. endoreg_db/views/video/task_status.py +0 -49
  378. endoreg_db/views/video/timeline.py +0 -46
  379. endoreg_db/views/video/video_analyze.py +0 -52
  380. /endoreg_db/data/requirement/{colon_polyp_intervention.yaml → old/colon_polyp_intervention.yaml} +0 -0
  381. /endoreg_db/data/{_examples/requirement → requirement/old}/colonoscopy_baseline_austria.yaml +0 -0
  382. /endoreg_db/data/requirement/{coloreg_colon_polyp.yaml → old/coloreg_colon_polyp.yaml} +0 -0
  383. /endoreg_db/data/{_examples/requirement → requirement/old}/disease_cardiovascular.yaml +0 -0
  384. /endoreg_db/data/{_examples/requirement → requirement/old}/disease_classification_choice_cardiovascular.yaml +0 -0
  385. /endoreg_db/data/{_examples/requirement → requirement/old}/disease_hepatology.yaml +0 -0
  386. /endoreg_db/data/{_examples/requirement → requirement/old}/disease_misc.yaml +0 -0
  387. /endoreg_db/data/{_examples/requirement → requirement/old}/disease_renal.yaml +0 -0
  388. /endoreg_db/data/{_examples/requirement → requirement/old}/endoscopy_bleeding_risk.yaml +0 -0
  389. /endoreg_db/data/{_examples/requirement → requirement/old}/event_cardiology.yaml +0 -0
  390. /endoreg_db/data/{_examples/requirement → requirement/old}/event_requirements.yaml +0 -0
  391. /endoreg_db/data/{_examples/requirement → requirement/old}/finding_colon_polyp.yaml +0 -0
  392. /endoreg_db/{migrations/__init__.py → data/requirement/old/gender.yaml} +0 -0
  393. /endoreg_db/data/{_examples/requirement → requirement/old}/lab_value.yaml +0 -0
  394. /endoreg_db/data/{_examples/requirement → requirement/old}/medication.yaml +0 -0
  395. /endoreg_db/data/{_examples/requirement_operator → requirement_operator/_old}/age.yaml +0 -0
  396. /endoreg_db/data/{_examples/requirement_operator → requirement_operator/_old}/lab_operators.yaml +0 -0
  397. /endoreg_db/data/{_examples/requirement_operator → requirement_operator/_old}/model_operators.yaml +0 -0
  398. /endoreg_db/{urls/sensitive_meta.py → import_files/pseudonymization/__init__.py} +0 -0
  399. /endoreg_db/{views/pdf/pdf_stream_views.py → import_files/pseudonymization/pseudonymize.py} +0 -0
  400. /endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py} +0 -0
  401. /endoreg_db/utils/requirement_operator_logic/{model_evaluators.py → _old/model_evaluators.py} +0 -0
  402. {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.8.9.dist-info}/licenses/LICENSE +0 -0
@@ -1,7 +1,10 @@
1
1
  from logging import getLogger # Added logger
2
- from typing import TYPE_CHECKING
2
+ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Union
3
3
 
4
4
  from django.db import models
5
+ from pydantic import BaseModel
6
+
7
+ from endoreg_db.utils.requirement_operator_logic.new_operator_logic import REQUIREMENT_OPERATORS, model_attribute_set_any
5
8
 
6
9
  # see how operator evaluation function is fetched, add to docs #TODO
7
10
  # endoreg_db/utils/requirement_operator_logic/model_evaluators.py
@@ -14,6 +17,65 @@ if TYPE_CHECKING:
14
17
  logger = getLogger(__name__) # Added logger instance
15
18
 
16
19
 
20
+ class OperatorInstructions(BaseModel):
21
+ input_targets: List[str] = []
22
+ requirement_targets: List[str] = []
23
+ kwargs: Dict[str, Union[str, int, float, bool]] = {}
24
+ args: List[Union[str, int, float, bool]] = []
25
+
26
+
27
+ def _parse_operator_instructions(raw: str):
28
+ target_attributes_list = [_.strip() for _ in raw.split(";") if _.strip()]
29
+
30
+ input_targets = []
31
+ kwargs: Dict[str, Union[str, int, float, bool]] = {}
32
+ args: List[Union[str, int, float, bool]] = []
33
+
34
+ valid_prefixes = [
35
+ "!", # Requirement target
36
+ "?", # Input target
37
+ "$", # Keyword argument, keyword and value separated by ":"
38
+ "@", # Positional argument
39
+ ]
40
+
41
+ for entry in target_attributes_list:
42
+ _prefix = entry[0]
43
+
44
+ if _prefix in valid_prefixes:
45
+ _attribute = entry[1:].strip()
46
+ if _prefix == "!":
47
+ # Requirement target
48
+ input_targets.append(_attribute)
49
+ elif _prefix == "?":
50
+ # Input target
51
+ input_targets.append(_attribute)
52
+ elif _prefix == "$":
53
+ # Keyword argument
54
+ if ":" in _attribute:
55
+ key, value = _attribute.split(":", 1)
56
+ kwargs[key.strip()] = value.strip()
57
+ else:
58
+ raise ValueError(f"Invalid keyword argument format in target_attributes: '{entry}'. Expected format is '$key:value'.")
59
+ elif _prefix == "@":
60
+ # Positional argument
61
+ args.append(_attribute)
62
+ else:
63
+ raise ValueError(f"Invalid prefix '{_prefix}' in target_attributes entry: '{entry}'. Valid prefixes are {valid_prefixes}.")
64
+ return OperatorInstructions(
65
+ input_targets=input_targets,
66
+ requirement_targets=input_targets,
67
+ kwargs=kwargs,
68
+ args=args,
69
+ )
70
+
71
+
72
+ def _validate_operator_instructions(instance: "Requirement") -> bool:
73
+ """Ensures requirement fixtures declare at least one target attribute."""
74
+ if not instance.operator_instructions_parsed:
75
+ raise ValueError(f"Requirement '{instance.name}' must declare at least one target attribute.")
76
+ return True
77
+
78
+
17
79
  class RequirementOperatorManager(models.Manager):
18
80
  def get_by_natural_key(self, name):
19
81
  """
@@ -48,16 +110,18 @@ class RequirementOperator(models.Model):
48
110
 
49
111
  requirements: models.QuerySet[Requirement]
50
112
 
51
- @property
52
- def operator_evaluation_models(self):
113
+ @classmethod
114
+ def parse_instructions(cls, raw: str) -> OperatorInstructions:
53
115
  """
54
- Returns a dictionary of operator evaluation models for this requirement operator.
116
+ Parses the raw target attributes string into structured operator instructions.
55
117
 
56
- This property dynamically imports and provides access to the available operator evaluation models.
57
- """
58
- from .requirement_evaluation.operator_evaluation_models import operator_evaluation_models
118
+ Args:
119
+ raw: The raw target attributes string.
59
120
 
60
- return operator_evaluation_models
121
+ Returns:
122
+ An OperatorInstructions instance containing parsed input targets, requirement targets, kwargs, and args.
123
+ """
124
+ return _parse_operator_instructions(raw)
61
125
 
62
126
  @property
63
127
  def data_model_dict(self):
@@ -84,96 +148,20 @@ class RequirementOperator(models.Model):
84
148
  """
85
149
  return str(self.name)
86
150
 
87
- def evaluate(self, requirement_links: "RequirementLinks", input_links: "RequirementLinks", **kwargs) -> bool: # Changed signature
88
- """
89
- Evaluates the requirement operator against the provided requirement links and input_links.
151
+ def get_operator_function(self) -> Callable[..., bool]:
152
+ _operator_function = REQUIREMENT_OPERATORS.get(self.name)
153
+ if not _operator_function:
154
+ raise ValueError(f"Operator function for '{self.name}' not found in REQUIREMENT_OPERATORS.")
155
+ return _operator_function
90
156
 
91
- Args:
92
- requirement_links: The RequirementLinks object from the Requirement model.
93
- input_links: The aggregated RequirementLinks object from the input arguments.
94
- **kwargs: Additional keyword arguments for specific operator logic.
95
- For lab value operators, this includes 'requirement' (the Requirement model instance).
96
- The 'requirement' instance is now passed for all operators.
157
+ def evaluate(self, operator_instructions: "OperatorInstructions", requirement: "Requirement", input_obj: Any, **kwargs) -> bool:
158
+ """ """
159
+ eval_result: bool = False
160
+ requirement_links: "RequirementLinks" = requirement.links
161
+ expected_input_models = requirement.expected_models
162
+ operator_function = self.get_operator_function()
97
163
 
98
- Returns:
99
- True if the condition defined by the operator is met, False otherwise.
164
+ input_model = type(input_obj)
165
+ assert input_model in expected_input_models, f"Input model {input_model} not in expected models {expected_input_models}"
100
166
 
101
- Raises:
102
- NotImplementedError: If the evaluation logic for the operator's name is not implemented.
103
- """
104
- # kwargs should contain 'requirement' (the Requirement instance) passed from Requirement.evaluate()
105
- if self.evaluation_function_name:
106
- eval_func = getattr(self, self.evaluation_function_name, None)
107
- if eval_func and callable(eval_func):
108
- result = eval_func(requirement_links=requirement_links, input_links=input_links, **kwargs)
109
- assert isinstance(result, bool), (
110
- f"Evaluation function '{self.evaluation_function_name}' for operator '{self.name}' must return a boolean value."
111
- )
112
- return result
113
- else:
114
- logger.error(
115
- f"Evaluation function '{self.evaluation_function_name}' not found or not callable on {self.__class__.__name__} for operator '{self.name}'."
116
- )
117
- raise NotImplementedError(f"Evaluation function '{self.evaluation_function_name}' not implemented correctly for operator '{self.name}'.")
118
- else:
119
- # Fallback to the central dispatcher if no specific function name is provided
120
- from endoreg_db.utils.requirement_operator_logic.model_evaluators import dispatch_operator_evaluation
121
-
122
- return dispatch_operator_evaluation(
123
- operator_name=self.name,
124
- requirement_links=requirement_links,
125
- input_links=input_links,
126
- operator_instance=self, # Pass the operator instance
127
- **kwargs,
128
- )
129
-
130
- from ..medical.medication import MedicationSchedule as MedicationScheduleTemplate # Added with alias
131
- from ..medical.patient.patient_medication import PatientMedication # Added
132
-
133
- def _evaluate_patient_medication_schedule_matches_template(
134
- self,
135
- requirement_links: "RequirementLinks",
136
- input_links: "RequirementLinks",
137
- requirement: "Requirement", # Added requirement
138
- **kwargs,
139
- ) -> bool:
140
- """
141
- Checks if any PatientMedication in the input PatientMedicationSchedule
142
- matches the profile (medication, dose, unit, intake times)
143
- of any MedicationSchedule template linked to the requirement.
144
- """
145
- # Get MedicationSchedule templates from the requirement
146
- req_schedule_templates = requirement_links.medication_schedules
147
- if not req_schedule_templates:
148
- # If the requirement doesn't specify any templates to match against,
149
- # it's ambiguous. Consider this a non-match.
150
- return False
151
-
152
- # Get PatientMedication instances from the input (derived from PatientMedicationSchedule.links)
153
- input_patient_medications = input_links.patient_medications
154
- if not input_patient_medications:
155
- # If the input schedule has no medications, it cannot match any template.
156
- return False
157
-
158
- for pm_instance in input_patient_medications:
159
- pm_intake_times_set = set(pm_instance.intake_times.all())
160
- for schedule_template in req_schedule_templates:
161
- template_intake_times_set = set(schedule_template.intake_times.all())
162
-
163
- # Check for profile match
164
- medication_match = pm_instance.medication == schedule_template.medication
165
- dose_match = pm_instance.dosage == schedule_template.dose
166
- unit_match = pm_instance.unit == schedule_template.unit
167
- intake_times_match = pm_intake_times_set == template_intake_times_set
168
-
169
- # Debugging output (optional, can be removed)
170
- # print(f"Comparing PM ID {pm_instance.id} with Template {schedule_template.name}:")
171
- # print(f" Medication: {pm_instance.medication} vs {schedule_template.medication} -> {medication_match}")
172
- # print(f" Dose: {pm_instance.dosage} vs {schedule_template.dose} -> {dose_match}")
173
- # print(f" Unit: {pm_instance.unit} vs {schedule_template.unit} -> {unit_match}")
174
- # print(f" Intake Times: {pm_intake_times_set} vs {template_intake_times_set} -> {intake_times_match}")
175
-
176
- if medication_match and dose_match and unit_match and intake_times_match:
177
- return True # Found a match
178
-
179
- return False # No PatientMedication matched any template
167
+ return eval_result
@@ -89,7 +89,7 @@ class AuditLedger(models.Model):
89
89
  """
90
90
  payload = {
91
91
  "ts": self.ts.isoformat(),
92
- "uid": str(self.user_id),
92
+ "uid": str(self.id),
93
93
  "obj": f"{self.object_type}:{self.object_pk}",
94
94
  "act": self.action,
95
95
  "data": self.data,
@@ -97,7 +97,7 @@ class AuditLedger(models.Model):
97
97
  }
98
98
  return hashlib.sha256(json.dumps(payload, sort_keys=True).encode()).hexdigest()
99
99
 
100
- def log_validation(user, instance, action: str, extra=None):
100
+ def log_validation(self, user, instance, action: str, extra=None):
101
101
  """
102
102
  Creates an audit record for a validation action performed by a user on a specific model instance.
103
103
 
@@ -115,7 +115,8 @@ class AuditLedger(models.Model):
115
115
  data=extra or {},
116
116
  )
117
117
 
118
- def _distinct(object_type: str, action: str):
118
+ @classmethod
119
+ def _distinct(self, object_type: str, action: str):
119
120
  """
120
121
  Returns the number of distinct objects of a given type that have a specific audit action recorded.
121
122
 
@@ -142,8 +143,6 @@ class AuditLedger(models.Model):
142
143
  "totalAnnotations": AuditLedger.objects.filter(action="annotation_added").count(),
143
144
  "totalAnonymizations": AuditLedger._distinct("VideoFile", "anonymized"),
144
145
  "totalImages": AuditLedger._distinct("Image", "created"),
145
- # video breakdown
146
146
  "videosCompleted": AuditLedger._distinct("VideoFile", "validated"),
147
147
  "videosAnonym": AuditLedger._distinct("VideoFile", "anonymized"),
148
- # add more as needed …
149
148
  }
@@ -1,12 +1,12 @@
1
1
  """
2
- Defines state tracking models related to PDF processing, including extraction of text and metadata, AI predictions, and anonymization status for RawPdfFile instances.
2
+ Defines state tracking models related to report processing, including extraction of text and metadata, AI predictions, and anonymization status for RawPdfFile instances.
3
3
  """
4
4
 
5
5
  import logging
6
6
  from enum import Enum
7
7
  from typing import TYPE_CHECKING
8
8
 
9
- from django.db import models
9
+ from django.db import models, transaction
10
10
 
11
11
  from endoreg_db.models.state.anonymization import AnonymizationState
12
12
 
@@ -22,7 +22,9 @@ class RawPdfState(models.Model):
22
22
  Uses BooleanFields for clear, distinct states.
23
23
  """
24
24
 
25
- text_meta_extracted = models.BooleanField(default=False, help_text="True if text metadata (OCR) has been extracted.")
25
+ text_meta_extracted = models.BooleanField(
26
+ default=False, help_text="True if text metadata (OCR) has been extracted."
27
+ )
26
28
 
27
29
  # AI / Annotation related states
28
30
  initial_prediction_completed = models.BooleanField(
@@ -31,26 +33,39 @@ class RawPdfState(models.Model):
31
33
 
32
34
  # Processing state
33
35
  sensitive_meta_processed = models.BooleanField(
34
- default=False, help_text="True if the video has been fully processed, meaning a anonymized person was created."
36
+ default=False,
37
+ help_text="True if the video has been fully processed, meaning a anonymized person was created.",
35
38
  )
36
39
 
37
40
  # Anonymization state
38
- anonymized = models.BooleanField(default=False, help_text="True if the anonymized video file has been created.")
39
- anonymization_validated = models.BooleanField(default=False, help_text="True if the anonymization process has been validated and confirmed.")
41
+ anonymized = models.BooleanField(
42
+ default=False, help_text="True if the anonymized video file has been created."
43
+ )
44
+ anonymization_validated = models.BooleanField(
45
+ default=False,
46
+ help_text="True if the anonymization process has been validated and confirmed.",
47
+ )
40
48
 
41
49
  # Processing state
42
- processing_started = models.BooleanField(default=False, help_text="True if the processing has started, but not yet completed.")
43
- processing_error = models.BooleanField(default=False, help_text="True if an error occurred during processing.")
50
+ processing_started = models.BooleanField(
51
+ default=False,
52
+ help_text="True if the processing has started, but not yet completed.",
53
+ )
54
+ processing_error = models.BooleanField(
55
+ default=False, help_text="True if an error occurred during processing."
56
+ )
44
57
 
45
58
  # Timestamps
46
59
  date_created = models.DateTimeField(auto_now_add=True)
47
60
  date_modified = models.DateTimeField(auto_now=True)
48
61
 
49
- was_created = models.BooleanField(default=True, help_text="True if this state was created for the first time.")
62
+ was_created = models.BooleanField(
63
+ default=True, help_text="True if this state was created for the first time."
64
+ )
50
65
 
51
- # PDF metadata extraction state
66
+ # report metadata extraction state
52
67
  pdf_meta_extracted = models.BooleanField(
53
- default=False, help_text="True if PDF metadata has been extracted."
68
+ default=False, help_text="True if report metadata has been extracted."
54
69
  )
55
70
 
56
71
  if TYPE_CHECKING:
@@ -58,7 +73,7 @@ class RawPdfState(models.Model):
58
73
 
59
74
  def __str__(self):
60
75
  """
61
- Return a string summarizing the RawPdfState instance, including the related PDF file UUID and key processing state flags with timestamps.
76
+ Return a string summarizing the RawPdfState instance, including the related report file UUID and key processing state flags with timestamps.
62
77
  """
63
78
  try:
64
79
  uuid = self.raw_pdf_file.pk
@@ -79,25 +94,50 @@ class RawPdfState(models.Model):
79
94
  @property
80
95
  def anonymization_status(self) -> AnonymizationState:
81
96
  """
82
- Determines the current anonymization workflow status for the PDF processing state.
97
+ Determines the current anonymization workflow status for the report processing state.
83
98
 
84
99
  Returns:
85
100
  AnonymizationStatus: The current status, reflecting progress or failure in the anonymization process.
86
101
  """
87
102
  if self.anonymization_validated:
88
- return AnonymizationState.VALIDATED # Validation in Frontend completed -> Views related to this /home/admin/endoreg-db/endoreg_db/views/anonymization/validate.py
103
+ return AnonymizationState.VALIDATED # Validation in Frontend completed -> Views related to this /home/admin/endoreg-db/endoreg_db/views/anonymization/validate.py
89
104
  if self.sensitive_meta_processed:
90
- return AnonymizationState.DONE_PROCESSING_ANONYMIZATION # /home/admin/endoreg-db/endoreg_db/services/pdf_import.py
91
- if self.processing_started and not self.processing_error and not self.anonymized:
105
+ return (
106
+ AnonymizationState.DONE_PROCESSING_ANONYMIZATION
107
+ ) # /home/admin/endoreg-db/endoreg_db/services/pdf_import.py
108
+ if (
109
+ self.processing_started
110
+ and not self.processing_error
111
+ and not self.anonymized
112
+ ):
92
113
  return AnonymizationState.PROCESSING_ANONYMIZING
93
114
  if getattr(self, "processing_error", False):
94
- return AnonymizationState.FAILED # /home/admin/endoreg-db/endoreg_db/services/pdf_import.py
115
+ return (
116
+ AnonymizationState.FAILED
117
+ ) # /home/admin/endoreg-db/endoreg_db/services/pdf_import.py
95
118
  if self.processing_started:
96
- return AnonymizationState.STARTED # /home/admin/endoreg-db/endoreg_db/services/pdf_import.py
119
+ return (
120
+ AnonymizationState.STARTED
121
+ ) # /home/admin/endoreg-db/endoreg_db/services/pdf_import.py
97
122
  if self.anonymized:
98
123
  return AnonymizationState.ANONYMIZED
99
124
  return AnonymizationState.NOT_STARTED
100
125
 
126
+ def mark_processing_not_started(self) -> None:
127
+ """
128
+ Mark the processing as not started and optionally save the updated state.
129
+
130
+ Parameters:
131
+ save (bool): If True, persist the change to the database immediately. Defaults to True.
132
+ """
133
+ with transaction.atomic():
134
+ self.processing_started = False
135
+ self.anonymized = False
136
+ self.was_created = False
137
+ self.sensitive_meta_processed = False
138
+ self.anonymization_validated = False
139
+ self.save()
140
+
101
141
  def mark_processing_started(self, *, save: bool = True) -> None:
102
142
  """
103
143
  Mark the processing as started and optionally save the updated state.
@@ -106,13 +146,12 @@ class RawPdfState(models.Model):
106
146
  save (bool): If True, persist the change to the database immediately. Defaults to True.
107
147
  """
108
148
  self.processing_started = True
109
- if save:
110
- self.save(update_fields=["processing_started", "date_modified"])
149
+ self.save(update_fields=["processing_started", "date_modified"])
111
150
 
112
151
  # ---- Single‑responsibility mutators ---------------------------------
113
152
  def mark_sensitive_meta_processed(self, *, save: bool = True) -> None:
114
153
  """
115
- Mark the sensitive metadata processing step as completed for this PDF state.
154
+ Mark the sensitive metadata processing step as completed for this report state.
116
155
 
117
156
  Parameters:
118
157
  save (bool): If True, immediately saves the updated state to the database.
@@ -123,7 +162,7 @@ class RawPdfState(models.Model):
123
162
 
124
163
  def mark_anonymization_validated(self, *, save: bool = True) -> None:
125
164
  """
126
- Mark the anonymization as validated for this PDF processing state.
165
+ Mark the anonymization as validated for this report processing state.
127
166
 
128
167
  Parameters:
129
168
  save (bool): If True, immediately saves the updated state to the database.
@@ -134,18 +173,18 @@ class RawPdfState(models.Model):
134
173
 
135
174
  def mark_anonymized(self, *, save: bool = True) -> None:
136
175
  """
137
- Mark the PDF as anonymized and optionally save the updated state.
176
+ Mark the report as anonymized and optionally save the updated state.
138
177
 
139
178
  Parameters:
140
179
  save (bool): If True, persist the change to the database immediately. Defaults to True.
141
180
  """
142
- self.anonymized = True
143
- if save:
181
+ with transaction.atomic():
182
+ self.anonymized = True
144
183
  self.save(update_fields=["anonymized", "date_modified"])
145
184
 
146
185
  def mark_initial_prediction_completed(self, *, save: bool = True) -> None:
147
186
  """
148
- Mark the initial AI prediction step as completed for this PDF processing state.
187
+ Mark the initial AI prediction step as completed for this report processing state.
149
188
 
150
189
  Parameters:
151
190
  save (bool): If True, immediately saves the updated state to the database.
@@ -156,7 +195,7 @@ class RawPdfState(models.Model):
156
195
 
157
196
  def mark_pdf_meta_extracted(self, *, save: bool = True) -> None:
158
197
  """
159
- Mark the PDF metadata extraction step as completed for this state.
198
+ Mark the report metadata extraction step as completed for this state.
160
199
 
161
200
  Parameters:
162
201
  save (bool): If True, immediately saves the updated state to the database.
@@ -167,7 +206,7 @@ class RawPdfState(models.Model):
167
206
 
168
207
  def mark_text_meta_extracted(self, *, save: bool = True) -> None:
169
208
  """
170
- Mark the text metadata extraction step as completed for this PDF processing state.
209
+ Mark the text metadata extraction step as completed for this report processing state.
171
210
 
172
211
  Parameters:
173
212
  save (bool): If True, immediately saves the updated state to the database.
@@ -177,5 +216,5 @@ class RawPdfState(models.Model):
177
216
  self.save(update_fields=["text_meta_extracted", "date_modified"])
178
217
 
179
218
  class Meta:
180
- verbose_name = "Raw PDF Processing State"
181
- verbose_name_plural = "Raw PDF Processing States"
219
+ verbose_name = "Raw report Processing State"
220
+ verbose_name_plural = "Raw report Processing States"
@@ -6,7 +6,7 @@ import logging
6
6
  from enum import Enum
7
7
  from typing import TYPE_CHECKING, Optional
8
8
 
9
- from django.db import models
9
+ from django.db import models, transaction
10
10
 
11
11
  from endoreg_db.models.state.anonymization import AnonymizationState
12
12
 
@@ -22,14 +22,19 @@ class VideoState(models.Model):
22
22
  Uses BooleanFields for clear, distinct states.
23
23
  """
24
24
 
25
-
26
25
  # Frame related states
27
26
  if TYPE_CHECKING:
28
27
  video_file: models.OneToOneField["VideoFile"]
29
28
 
30
- frames_extracted = models.BooleanField(default=False, help_text="True if raw frames have been extracted to files.")
31
- frames_initialized = models.BooleanField(default=False, help_text="True if Frame DB objects have been created.")
32
- frame_count = models.PositiveIntegerField(null=True, blank=True, help_text="Number of frames extracted/initialized.")
29
+ frames_extracted = models.BooleanField(
30
+ default=False, help_text="True if raw frames have been extracted to files."
31
+ )
32
+ frames_initialized = models.BooleanField(
33
+ default=False, help_text="True if Frame DB objects have been created."
34
+ )
35
+ frame_count = models.PositiveIntegerField(
36
+ null=True, blank=True, help_text="Number of frames extracted/initialized."
37
+ )
33
38
 
34
39
  # Metadata related states
35
40
  video_meta_extracted = models.BooleanField(
@@ -41,63 +46,57 @@ class VideoState(models.Model):
41
46
  )
42
47
 
43
48
  # AI / Annotation related states
44
- initial_prediction_completed = models.BooleanField(default=False, help_text="True if initial AI prediction has run.")
45
- lvs_created = models.BooleanField(default=False, help_text="True if LabelVideoSegments have been created from predictions.")
46
- frame_annotations_generated = models.BooleanField(default=False, help_text="True if frame-level annotations have been generated from segments.")
49
+ initial_prediction_completed = models.BooleanField(
50
+ default=False, help_text="True if initial AI prediction has run."
51
+ )
52
+ lvs_created = models.BooleanField(
53
+ default=False,
54
+ help_text="True if LabelVideoSegments have been created from predictions.",
55
+ )
56
+ frame_annotations_generated = models.BooleanField(
57
+ default=False,
58
+ help_text="True if frame-level annotations have been generated from segments.",
59
+ )
47
60
 
48
61
  # Processing state
49
62
  sensitive_meta_processed = models.BooleanField(
50
- default=False, help_text="True if the video has been fully processed, meaning a anonymized person was created."
63
+ default=False,
64
+ help_text="True if the video has been fully processed, meaning a anonymized person was created.",
51
65
  )
52
66
 
53
67
  # Anonymization state
54
- anonymized = models.BooleanField(default=False, help_text="True if the anonymized video file has been created.")
55
- anonymization_validated = models.BooleanField(default=False, help_text="True if the anonymization process has been validated and confirmed.")
68
+ anonymized = models.BooleanField(
69
+ default=False, help_text="True if the anonymized video file has been created."
70
+ )
71
+ anonymization_validated = models.BooleanField(
72
+ default=False,
73
+ help_text="True if the anonymization process has been validated and confirmed.",
74
+ )
56
75
 
57
- processing_started = models.BooleanField(default=False, help_text="True if the processing has started, but not yet completed.")
76
+ processing_started = models.BooleanField(
77
+ default=False,
78
+ help_text="True if the processing has started, but not yet completed.",
79
+ )
58
80
 
59
81
  # Timestamps
60
82
  date_created = models.DateTimeField(auto_now_add=True)
61
83
  date_modified = models.DateTimeField(auto_now=True)
62
84
 
63
85
  # Segment Annotation State
64
- segment_annotations_created = models.BooleanField(default=False, help_text="True if segment annotations have been created from LabelVideoSegments.")
65
- segment_annotations_validated = models.BooleanField(default=False, help_text="True if segment annotations have been validated.")
86
+ segment_annotations_created = models.BooleanField(
87
+ default=False,
88
+ help_text="True if segment annotations have been created from LabelVideoSegments.",
89
+ )
90
+ segment_annotations_validated = models.BooleanField(
91
+ default=False, help_text="True if segment annotations have been validated."
92
+ )
66
93
 
67
- was_created = models.BooleanField(default=True, help_text="True if this state was created for the first time.")
94
+ was_created = models.BooleanField(
95
+ default=True, help_text="True if this state was created for the first time."
96
+ )
68
97
 
69
98
  objects = models.Manager()
70
99
 
71
- def __str__(self):
72
- # Find the related VideoFile's UUID if possible
73
- video_uuid = "Unknown"
74
- try:
75
- # Access the related VideoFile via the reverse relation 'video_file'
76
- if hasattr(self, "video_file") and self.video_file:
77
- video_uuid = self.video_file.uuid
78
- except Exception:
79
- pass # Ignore errors if relation doesn't exist or causes issues
80
- pass # Ignore errors if relation doesn't exist or causes issues
81
-
82
- states = [
83
- f"FramesExtracted={self.frames_extracted}",
84
- f"FramesInit={self.frames_initialized}",
85
- f"VideoMetaExtracted={self.video_meta_extracted}",
86
- f"TextMetaExtracted={self.text_meta_extracted}",
87
- f"PredictionDone={self.initial_prediction_completed}",
88
- f"LvsCreated={self.lvs_created}",
89
- f"Anonymized={self.anonymized}",
90
- f"AnonymizationValidated={self.anonymization_validated}",
91
- f"SensitiveMetaProcessed={self.sensitive_meta_processed}",
92
- f"FrameCount={self.frame_count}"
93
- if self.frame_count is not None
94
- else "FrameCount=None",
95
- f"SegmentAnnotationsCreated={self.segment_annotations_created}",
96
- f"SegmentAnnotationsValidated={self.segment_annotations_validated}",
97
- f"DateCreated={self.date_created.isoformat()}",
98
- f"DateModified={self.date_modified.isoformat()}",
99
- ]
100
- return f"VideoState(Video:{video_uuid}): {', '.join(states)}"
101
100
 
102
101
  @property
103
102
  def anonymization_status(self) -> AnonymizationState:
@@ -105,9 +104,9 @@ class VideoState(models.Model):
105
104
  Fast, side‑effect‑free status resolution used by API & UI.
106
105
  """
107
106
  if self.anonymization_validated:
108
- return AnonymizationState.VALIDATED # Validation in Frontend completed -> Views related to this /home/admin/endoreg-db/endoreg_db/views/anonymization/validate.py
107
+ return AnonymizationState.VALIDATED # Validation in Frontend completed -> Views related to this /home/admin/endoreg-db/endoreg_db/views/anonymization/validate.py
109
108
  if self.sensitive_meta_processed:
110
- return AnonymizationState.DONE_PROCESSING_ANONYMIZATION # /home/admin/endoreg-db/endoreg_db/services/video_import.py /home/admin/endoreg-db/endoreg_db/views/video/reimport.py
109
+ return AnonymizationState.DONE_PROCESSING_ANONYMIZATION # /home/admin/endoreg-db/endoreg_db/services/video_import.py /home/admin/endoreg-db/endoreg_db/views/video/reimport.py
111
110
  if self.frames_extracted and not self.anonymized:
112
111
  return AnonymizationState.PROCESSING_ANONYMIZING
113
112
  if self.was_created and not self.frames_extracted:
@@ -120,6 +119,22 @@ class VideoState(models.Model):
120
119
  return AnonymizationState.ANONYMIZED
121
120
  return AnonymizationState.NOT_STARTED
122
121
 
122
+ def mark_processing_not_started(self) -> None:
123
+ """
124
+ Mark the processing as not started and optionally save the updated state.
125
+
126
+ Parameters:
127
+ save (bool): If True, persist the change to the database immediately. Defaults to True.
128
+ """
129
+ with transaction.atomic():
130
+ self.processing_started = False
131
+ self.anonymized = False
132
+ self.was_created = False
133
+ self.sensitive_meta_processed = False
134
+ self.anonymization_validated = False
135
+ self.frames_extracted = False
136
+ self.save()
137
+
123
138
  # ---- Single‑responsibility mutators ---------------------------------
124
139
  def mark_sensitive_meta_processed(self, *, save: bool = True) -> None:
125
140
  self.sensitive_meta_processed = True
@@ -165,8 +180,8 @@ class VideoState(models.Model):
165
180
  Parameters:
166
181
  save (bool): If True, immediately saves the updated state to the database.
167
182
  """
168
- self.anonymized = True
169
- if save:
183
+ with transaction.atomic():
184
+ self.anonymized = True
170
185
  self.save(update_fields=["anonymized", "date_modified"])
171
186
 
172
187
  def mark_initial_prediction_completed(self, *, save: bool = True) -> None: