endoreg-db 0.8.9.32__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 (787) hide show
  1. endoreg_db/__init__.py +0 -0
  2. endoreg_db/_version.py +34 -0
  3. endoreg_db/admin.py +97 -0
  4. endoreg_db/api/serializers/finding_descriptions.py +0 -0
  5. endoreg_db/api/views/finding_descriptions.py +0 -0
  6. endoreg_db/api_urls.py +4 -0
  7. endoreg_db/apps.py +17 -0
  8. endoreg_db/assets/dummy_model.ckpt +1 -0
  9. endoreg_db/authz/auth.py +78 -0
  10. endoreg_db/authz/backends.py +168 -0
  11. endoreg_db/authz/management/commands/list_routes.py +20 -0
  12. endoreg_db/authz/middleware.py +84 -0
  13. endoreg_db/authz/permissions.py +138 -0
  14. endoreg_db/authz/policy.py +224 -0
  15. endoreg_db/authz/settings.py +64 -0
  16. endoreg_db/authz/views_auth.py +70 -0
  17. endoreg_db/codemods/readme.md +88 -0
  18. endoreg_db/codemods/rename_datetime_fields.py +99 -0
  19. endoreg_db/config/__init__.py +0 -0
  20. endoreg_db/config/env.py +106 -0
  21. endoreg_db/config/settings/__init__.py +6 -0
  22. endoreg_db/config/settings/base.py +148 -0
  23. endoreg_db/config/settings/case_gen.py +32 -0
  24. endoreg_db/config/settings/dev.py +108 -0
  25. endoreg_db/config/settings/keycloak.py +177 -0
  26. endoreg_db/config/settings/prod.py +66 -0
  27. endoreg_db/config/settings/test.py +72 -0
  28. endoreg_db/data/__init__.py +135 -0
  29. endoreg_db/data/ai_model/data.yaml +7 -0
  30. endoreg_db/data/ai_model_label/label/data.yaml +88 -0
  31. endoreg_db/data/ai_model_label/label/polyp_classification.yaml +52 -0
  32. endoreg_db/data/ai_model_label/label-set/data.yaml +40 -0
  33. endoreg_db/data/ai_model_label/label-set/polyp_classifications.yaml +25 -0
  34. endoreg_db/data/ai_model_label/label-type/data.yaml +7 -0
  35. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +27 -0
  36. endoreg_db/data/ai_model_type/data.yaml +7 -0
  37. endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml +176 -0
  38. endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml +20 -0
  39. endoreg_db/data/case_template/rule/00_patient_lab_sample_add_default_value.yaml +167 -0
  40. endoreg_db/data/case_template/rule/01_patient-set-age.yaml +8 -0
  41. endoreg_db/data/case_template/rule/01_patient-set-gender.yaml +9 -0
  42. endoreg_db/data/case_template/rule/11_create_patient_lab_sample.yaml +23 -0
  43. endoreg_db/data/case_template/rule/12_create-patient_medication-anticoagulation.yaml +19 -0
  44. endoreg_db/data/case_template/rule/13_create-patient_medication_schedule-anticoagulation.yaml +19 -0
  45. endoreg_db/data/case_template/rule/19_create_patient.yaml +17 -0
  46. endoreg_db/data/case_template/rule_type/base_types.yaml +35 -0
  47. endoreg_db/data/case_template/rule_value/.init +0 -0
  48. endoreg_db/data/case_template/rule_value_type/base_types.yaml +59 -0
  49. endoreg_db/data/case_template/template/base.yaml +8 -0
  50. endoreg_db/data/case_template/template_type/pre_endoscopy.yaml +3 -0
  51. endoreg_db/data/case_template/tmp/_rule_value +13 -0
  52. endoreg_db/data/case_template/tmp/rule/01_atrial_fibrillation.yaml +21 -0
  53. endoreg_db/data/case_template/tmp/rule/02_create_object.yaml +10 -0
  54. endoreg_db/data/case_template/tmp/template/atrial_fibrillation_low_risk.yaml +7 -0
  55. endoreg_db/data/center/data.yaml +99 -0
  56. endoreg_db/data/center_resource/green_endoscopy_dashboard_CenterResource.yaml +144 -0
  57. endoreg_db/data/center_shift/ukw.yaml +9 -0
  58. endoreg_db/data/center_waste/green_endoscopy_dashboard_CenterWaste.yaml +48 -0
  59. endoreg_db/data/contraindication/bleeding.yaml +11 -0
  60. endoreg_db/data/db_summary.csv +58 -0
  61. endoreg_db/data/db_summary.xlsx +0 -0
  62. endoreg_db/data/disease/cardiovascular.yaml +37 -0
  63. endoreg_db/data/disease/hepatology.yaml +5 -0
  64. endoreg_db/data/disease/misc.yaml +5 -0
  65. endoreg_db/data/disease/renal.yaml +5 -0
  66. endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +6 -0
  67. endoreg_db/data/disease_classification/coronary_vessel_disease.yaml +6 -0
  68. endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +41 -0
  69. endoreg_db/data/disease_classification_choice/coronary_vessel_disease.yaml +20 -0
  70. endoreg_db/data/distribution/date/patient.yaml +7 -0
  71. endoreg_db/data/distribution/multiple_categorical/.init +0 -0
  72. endoreg_db/data/distribution/numeric/data.yaml +14 -0
  73. endoreg_db/data/distribution/single_categorical/patient.yaml +7 -0
  74. endoreg_db/data/emission_factor/green_endoscopy_dashboard_EmissionFactor.yaml +132 -0
  75. endoreg_db/data/endoscope/data.yaml +93 -0
  76. endoreg_db/data/endoscope_type/data.yaml +11 -0
  77. endoreg_db/data/endoscopy_processor/data.yaml +50 -0
  78. endoreg_db/data/event/cardiology.yaml +15 -0
  79. endoreg_db/data/event/neurology.yaml +14 -0
  80. endoreg_db/data/event/surgery.yaml +13 -0
  81. endoreg_db/data/event/thrombembolism.yaml +20 -0
  82. endoreg_db/data/event_classification/data.yaml +4 -0
  83. endoreg_db/data/event_classification_choice/data.yaml +9 -0
  84. endoreg_db/data/examination/examinations/data.yaml +172 -0
  85. endoreg_db/data/examination/time/data.yaml +48 -0
  86. endoreg_db/data/examination/time-type/data.yaml +5 -0
  87. endoreg_db/data/examination/type/data.yaml +17 -0
  88. endoreg_db/data/examination_indication/endoscopy.yaml +359 -0
  89. endoreg_db/data/examination_indication_classification/endoscopy.yaml +90 -0
  90. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +97 -0
  91. endoreg_db/data/examination_requirement_set/colonoscopy.yaml +15 -0
  92. endoreg_db/data/finding/00_generic.yaml +35 -0
  93. endoreg_db/data/finding/00_generic_complication.yaml +9 -0
  94. endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
  95. endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
  96. endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
  97. endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
  98. endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
  99. endoreg_db/data/finding_classification/00_generic.yaml +44 -0
  100. endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
  101. endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
  102. endoreg_db/data/finding_classification/02_colonoscopy_baseline.yaml +83 -0
  103. endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
  104. endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
  105. endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
  106. endoreg_db/data/finding_classification_choice/00_generic.yaml +15 -0
  107. endoreg_db/data/finding_classification_choice/00_generic_baseline.yaml +23 -0
  108. endoreg_db/data/finding_classification_choice/00_generic_complication.yaml +15 -0
  109. endoreg_db/data/finding_classification_choice/00_generic_histology.yaml +21 -0
  110. endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
  111. endoreg_db/data/finding_classification_choice/02_colonoscopy_bowel_preparation.yaml +49 -0
  112. endoreg_db/data/finding_classification_choice/02_colonoscopy_generic.yaml +19 -0
  113. endoreg_db/data/finding_classification_choice/02_colonoscopy_histology.yaml +20 -0
  114. endoreg_db/data/finding_classification_choice/02_colonoscopy_location.yaml +248 -0
  115. endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
  116. endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
  117. endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_morphology.yaml +75 -0
  118. endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
  119. endoreg_db/data/finding_classification_type/00_generic.yaml +53 -0
  120. endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
  121. endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
  122. endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
  123. endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
  124. endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
  125. endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
  126. endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
  127. endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
  128. endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
  129. endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
  130. endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
  131. endoreg_db/data/finding_type/data.yaml +39 -0
  132. endoreg_db/data/gender/data.yaml +42 -0
  133. endoreg_db/data/information_source/annotation.yaml +6 -0
  134. endoreg_db/data/information_source/data.yaml +30 -0
  135. endoreg_db/data/information_source/endoscopy_guidelines.yaml +7 -0
  136. endoreg_db/data/information_source/medication.yaml +6 -0
  137. endoreg_db/data/information_source/prediction.yaml +7 -0
  138. endoreg_db/data/information_source_type/data.yaml +8 -0
  139. endoreg_db/data/lab_value/cardiac_enzymes.yaml +37 -0
  140. endoreg_db/data/lab_value/coagulation.yaml +54 -0
  141. endoreg_db/data/lab_value/electrolytes.yaml +228 -0
  142. endoreg_db/data/lab_value/gastrointestinal_function.yaml +133 -0
  143. endoreg_db/data/lab_value/hematology.yaml +184 -0
  144. endoreg_db/data/lab_value/hormones.yaml +59 -0
  145. endoreg_db/data/lab_value/lipids.yaml +53 -0
  146. endoreg_db/data/lab_value/misc.yaml +76 -0
  147. endoreg_db/data/lab_value/renal_function.yaml +12 -0
  148. endoreg_db/data/log_type/data.yaml +57 -0
  149. endoreg_db/data/lx_client_tag/base.yaml +54 -0
  150. endoreg_db/data/lx_client_type/base.yaml +30 -0
  151. endoreg_db/data/lx_permission/base.yaml +24 -0
  152. endoreg_db/data/lx_permission/endoreg.yaml +52 -0
  153. endoreg_db/data/material/material.yaml +91 -0
  154. endoreg_db/data/medication/anticoagulation.yaml +65 -0
  155. endoreg_db/data/medication/tah.yaml +70 -0
  156. endoreg_db/data/medication_indication/anticoagulation.yaml +115 -0
  157. endoreg_db/data/medication_indication_type/data.yaml +11 -0
  158. endoreg_db/data/medication_indication_type/thrombembolism.yaml +41 -0
  159. endoreg_db/data/medication_intake_time/base.yaml +31 -0
  160. endoreg_db/data/medication_schedule/apixaban.yaml +95 -0
  161. endoreg_db/data/medication_schedule/ass.yaml +12 -0
  162. endoreg_db/data/medication_schedule/enoxaparin.yaml +26 -0
  163. endoreg_db/data/names_first/first_names.yaml +54 -0
  164. endoreg_db/data/names_last/last_names.yaml +51 -0
  165. endoreg_db/data/network_device/data.yaml +59 -0
  166. endoreg_db/data/network_device_type/data.yaml +12 -0
  167. endoreg_db/data/organ/data.yaml +29 -0
  168. endoreg_db/data/patient_lab_sample_type/generic.yaml +6 -0
  169. endoreg_db/data/pdf_type/data.yaml +46 -0
  170. endoreg_db/data/product/green_endoscopy_dashboard_Product.yaml +66 -0
  171. endoreg_db/data/product_group/green_endoscopy_dashboard_ProductGroup.yaml +33 -0
  172. endoreg_db/data/product_material/green_endoscopy_dashboard_ProductMaterial.yaml +308 -0
  173. endoreg_db/data/product_weight/green_endoscopy_dashboard_ProductWeight.yaml +88 -0
  174. endoreg_db/data/profession/data.yaml +70 -0
  175. endoreg_db/data/qualification/endoscopy.yaml +36 -0
  176. endoreg_db/data/qualification/m2.yaml +39 -0
  177. endoreg_db/data/qualification/outpatient_clinic.yaml +35 -0
  178. endoreg_db/data/qualification/sonography.yaml +36 -0
  179. endoreg_db/data/qualification_type/base.yaml +29 -0
  180. endoreg_db/data/reference_product/green_endoscopy_dashboard_ReferenceProduct.yaml +55 -0
  181. endoreg_db/data/report_reader_flag/rkh-histology-generic.yaml +10 -0
  182. endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +30 -0
  183. endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +24 -0
  184. endoreg_db/data/requirement/01_patient_data.yaml +93 -0
  185. endoreg_db/data/requirement/old/colon_polyp_intervention.yaml +49 -0
  186. endoreg_db/data/requirement/old/colonoscopy_baseline_austria.yaml +45 -0
  187. endoreg_db/data/requirement/old/coloreg_colon_polyp.yaml +49 -0
  188. endoreg_db/data/requirement/old/disease_cardiovascular.yaml +79 -0
  189. endoreg_db/data/requirement/old/disease_classification_choice_cardiovascular.yaml +41 -0
  190. endoreg_db/data/requirement/old/disease_hepatology.yaml +12 -0
  191. endoreg_db/data/requirement/old/disease_misc.yaml +12 -0
  192. endoreg_db/data/requirement/old/disease_renal.yaml +96 -0
  193. endoreg_db/data/requirement/old/endoscopy_bleeding_risk.yaml +59 -0
  194. endoreg_db/data/requirement/old/event_cardiology.yaml +251 -0
  195. endoreg_db/data/requirement/old/event_requirements.yaml +145 -0
  196. endoreg_db/data/requirement/old/finding_colon_polyp.yaml +50 -0
  197. endoreg_db/data/requirement/old/gender.yaml +0 -0
  198. endoreg_db/data/requirement/old/lab_value.yaml +441 -0
  199. endoreg_db/data/requirement/old/medication.yaml +93 -0
  200. endoreg_db/data/requirement_operator/_old/age.yaml +13 -0
  201. endoreg_db/data/requirement_operator/_old/lab_operators.yaml +129 -0
  202. endoreg_db/data/requirement_operator/_old/model_operators.yaml +96 -0
  203. endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
  204. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +65 -0
  205. endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
  206. endoreg_db/data/requirement_set/02_endoscopy_bleeding_risk.yaml +46 -0
  207. endoreg_db/data/requirement_set/90_coloreg.yaml +190 -0
  208. endoreg_db/data/requirement_set/_old_ +109 -0
  209. endoreg_db/data/requirement_set/colonoscopy_austria_screening.yaml +57 -0
  210. endoreg_db/data/requirement_set_type/data.yaml +41 -0
  211. endoreg_db/data/requirement_type/requirement_types.yaml +165 -0
  212. endoreg_db/data/resource/green_endoscopy_dashboard_Resource.yaml +15 -0
  213. endoreg_db/data/risk/bleeding.yaml +26 -0
  214. endoreg_db/data/risk/thrombosis.yaml +37 -0
  215. endoreg_db/data/risk_type/data.yaml +27 -0
  216. endoreg_db/data/setup_config.yaml +38 -0
  217. endoreg_db/data/shift/endoscopy.yaml +21 -0
  218. endoreg_db/data/shift/m2.yaml +0 -0
  219. endoreg_db/data/shift_type/base.yaml +35 -0
  220. endoreg_db/data/tag/requirement_set_tags.yaml +32 -0
  221. endoreg_db/data/tmp/chronic_kidney_disease.yaml +0 -0
  222. endoreg_db/data/tmp/congestive_heart_failure.yaml +0 -0
  223. endoreg_db/data/transport_route/green_endoscopy_dashboard_TransportRoute.yaml +12 -0
  224. endoreg_db/data/unit/concentration.yaml +115 -0
  225. endoreg_db/data/unit/data.yaml +17 -0
  226. endoreg_db/data/unit/length.yaml +31 -0
  227. endoreg_db/data/unit/misc.yaml +20 -0
  228. endoreg_db/data/unit/rate.yaml +6 -0
  229. endoreg_db/data/unit/time.yaml +48 -0
  230. endoreg_db/data/unit/volume.yaml +35 -0
  231. endoreg_db/data/unit/weight.yaml +38 -0
  232. endoreg_db/data/waste/data.yaml +12 -0
  233. endoreg_db/exceptions.py +24 -0
  234. endoreg_db/export/frames/export.py +6 -0
  235. endoreg_db/export/frames/export_frames_with_labels.py +616 -0
  236. endoreg_db/factories/__init__.py +0 -0
  237. endoreg_db/forms/__init__.py +4 -0
  238. endoreg_db/forms/examination_form.py +12 -0
  239. endoreg_db/forms/patient_finding_intervention_form.py +40 -0
  240. endoreg_db/forms/patient_form.py +23 -0
  241. endoreg_db/forms/questionnaires/__init__.py +1 -0
  242. endoreg_db/forms/questionnaires/tto_questionnaire.py +23 -0
  243. endoreg_db/forms/settings/__init__.py +11 -0
  244. endoreg_db/forms/unit.py +7 -0
  245. endoreg_db/helpers/__init__.py +0 -0
  246. endoreg_db/helpers/count_db.py +48 -0
  247. endoreg_db/helpers/data_loader.py +280 -0
  248. endoreg_db/helpers/default_objects.py +414 -0
  249. endoreg_db/helpers/download_segmentation_model.py +32 -0
  250. endoreg_db/helpers/interact.py +1 -0
  251. endoreg_db/helpers/test_video_helper.py +127 -0
  252. endoreg_db/import_files/__init__.py +27 -0
  253. endoreg_db/import_files/context/__init__.py +7 -0
  254. endoreg_db/import_files/context/default_sensitive_meta.py +83 -0
  255. endoreg_db/import_files/context/ensure_center.py +17 -0
  256. endoreg_db/import_files/context/file_lock.py +66 -0
  257. endoreg_db/import_files/context/import_context.py +42 -0
  258. endoreg_db/import_files/context/validate_directories.py +57 -0
  259. endoreg_db/import_files/file_storage/__init__.py +15 -0
  260. endoreg_db/import_files/file_storage/create_report_file.py +99 -0
  261. endoreg_db/import_files/file_storage/create_video_file.py +104 -0
  262. endoreg_db/import_files/file_storage/sensitive_meta_storage.py +42 -0
  263. endoreg_db/import_files/file_storage/state_management.py +463 -0
  264. endoreg_db/import_files/file_storage/storage.py +42 -0
  265. endoreg_db/import_files/import_service.md +26 -0
  266. endoreg_db/import_files/processing/__init__.py +11 -0
  267. endoreg_db/import_files/processing/report_processing/report_anonymization.py +99 -0
  268. endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
  269. endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
  270. endoreg_db/import_files/pseudonymization/__init__.py +0 -0
  271. endoreg_db/import_files/pseudonymization/fake.py +52 -0
  272. endoreg_db/import_files/pseudonymization/k_anonymity.py +181 -0
  273. endoreg_db/import_files/pseudonymization/k_pseudonymity.py +139 -0
  274. endoreg_db/import_files/pseudonymization/pseudonymize.py +0 -0
  275. endoreg_db/import_files/report_import_service.py +147 -0
  276. endoreg_db/import_files/video_import_service.py +154 -0
  277. endoreg_db/logger_conf.py +156 -0
  278. endoreg_db/management/__init__.py +1 -0
  279. endoreg_db/management/commands/__init__.py +1 -0
  280. endoreg_db/management/commands/anonymize_video.py +0 -0
  281. endoreg_db/management/commands/check_auth.py +132 -0
  282. endoreg_db/management/commands/create_model_meta_from_huggingface.py +177 -0
  283. endoreg_db/management/commands/create_multilabel_model_meta.py +419 -0
  284. endoreg_db/management/commands/export_frame_annot.py +196 -0
  285. endoreg_db/management/commands/fix_missing_patient_data.py +206 -0
  286. endoreg_db/management/commands/fix_video_paths.py +186 -0
  287. endoreg_db/management/commands/import_report.py +361 -0
  288. endoreg_db/management/commands/list_routes.py +20 -0
  289. endoreg_db/management/commands/load_ai_model_data.py +83 -0
  290. endoreg_db/management/commands/load_ai_model_label_data.py +60 -0
  291. endoreg_db/management/commands/load_base_db_data.py +63 -0
  292. endoreg_db/management/commands/load_center_data.py +68 -0
  293. endoreg_db/management/commands/load_contraindication_data.py +39 -0
  294. endoreg_db/management/commands/load_disease_classification_choices_data.py +38 -0
  295. endoreg_db/management/commands/load_disease_classification_data.py +38 -0
  296. endoreg_db/management/commands/load_disease_data.py +59 -0
  297. endoreg_db/management/commands/load_distribution_data.py +63 -0
  298. endoreg_db/management/commands/load_endoscope_data.py +58 -0
  299. endoreg_db/management/commands/load_event_data.py +39 -0
  300. endoreg_db/management/commands/load_examination_data.py +78 -0
  301. endoreg_db/management/commands/load_examination_indication_data.py +85 -0
  302. endoreg_db/management/commands/load_finding_data.py +115 -0
  303. endoreg_db/management/commands/load_gender_data.py +37 -0
  304. endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +142 -0
  305. endoreg_db/management/commands/load_information_source.py +46 -0
  306. endoreg_db/management/commands/load_lab_value_data.py +52 -0
  307. endoreg_db/management/commands/load_legacy_data.py +303 -0
  308. endoreg_db/management/commands/load_medication_data.py +104 -0
  309. endoreg_db/management/commands/load_name_data.py +36 -0
  310. endoreg_db/management/commands/load_organ_data.py +39 -0
  311. endoreg_db/management/commands/load_pdf_type_data.py +58 -0
  312. endoreg_db/management/commands/load_profession_data.py +40 -0
  313. endoreg_db/management/commands/load_qualification_data.py +56 -0
  314. endoreg_db/management/commands/load_report_reader_flag_data.py +40 -0
  315. endoreg_db/management/commands/load_requirement_data.py +207 -0
  316. endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
  317. endoreg_db/management/commands/load_risk_data.py +57 -0
  318. endoreg_db/management/commands/load_shift_data.py +57 -0
  319. endoreg_db/management/commands/load_tag_data.py +54 -0
  320. endoreg_db/management/commands/load_unit_data.py +40 -0
  321. endoreg_db/management/commands/load_user_groups.py +26 -0
  322. endoreg_db/management/commands/model_input.py +169 -0
  323. endoreg_db/management/commands/register_ai_model.py +70 -0
  324. endoreg_db/management/commands/setup_endoreg_db.py +459 -0
  325. endoreg_db/management/commands/start_filewatcher.py +115 -0
  326. endoreg_db/management/commands/storage_management.py +622 -0
  327. endoreg_db/management/commands/summarize_db_content.py +280 -0
  328. endoreg_db/management/commands/train_image_multilabel_model.py +144 -0
  329. endoreg_db/management/commands/validate_video_files.py +189 -0
  330. endoreg_db/management/commands/video_validation.py +20 -0
  331. endoreg_db/mermaid/Overall_flow_patient_finding_intervention.md +10 -0
  332. endoreg_db/mermaid/anonymized_image_annotation.md +20 -0
  333. endoreg_db/mermaid/binary_classification_annotation.md +50 -0
  334. endoreg_db/mermaid/classification.md +8 -0
  335. endoreg_db/mermaid/examination.md +8 -0
  336. endoreg_db/mermaid/findings.md +7 -0
  337. endoreg_db/mermaid/image_classification.md +28 -0
  338. endoreg_db/mermaid/interventions.md +8 -0
  339. endoreg_db/mermaid/morphology.md +8 -0
  340. endoreg_db/mermaid/patient_creation.md +14 -0
  341. endoreg_db/mermaid/video_segmentation_annotation.md +17 -0
  342. endoreg_db/migrations/0001_initial.py +1953 -0
  343. endoreg_db/migrations/__init__.py +0 -0
  344. endoreg_db/models/__init__.py +322 -0
  345. endoreg_db/models/administration/__init__.py +95 -0
  346. endoreg_db/models/administration/ai/__init__.py +9 -0
  347. endoreg_db/models/administration/ai/active_model.py +35 -0
  348. endoreg_db/models/administration/ai/ai_model.py +180 -0
  349. endoreg_db/models/administration/ai/model_type.py +42 -0
  350. endoreg_db/models/administration/case/__init__.py +5 -0
  351. endoreg_db/models/administration/case/case.py +114 -0
  352. endoreg_db/models/administration/case/case_template/__init__.py +3 -0
  353. endoreg_db/models/administration/case/case_template/case_template.py +3 -0
  354. endoreg_db/models/administration/case/case_template/case_template_rule.py +3 -0
  355. endoreg_db/models/administration/case/case_template/case_template_rule_value.py +3 -0
  356. endoreg_db/models/administration/case/case_template/case_template_type.py +3 -0
  357. endoreg_db/models/administration/center/__init__.py +13 -0
  358. endoreg_db/models/administration/center/center.py +85 -0
  359. endoreg_db/models/administration/center/center_product.py +67 -0
  360. endoreg_db/models/administration/center/center_resource.py +69 -0
  361. endoreg_db/models/administration/center/center_shift.py +94 -0
  362. endoreg_db/models/administration/center/center_waste.py +42 -0
  363. endoreg_db/models/administration/person/__init__.py +26 -0
  364. endoreg_db/models/administration/person/employee/__init__.py +3 -0
  365. endoreg_db/models/administration/person/employee/employee.py +40 -0
  366. endoreg_db/models/administration/person/employee/employee_qualification.py +44 -0
  367. endoreg_db/models/administration/person/employee/employee_type.py +50 -0
  368. endoreg_db/models/administration/person/examiner/__init__.py +4 -0
  369. endoreg_db/models/administration/person/examiner/examiner.py +64 -0
  370. endoreg_db/models/administration/person/names/__init__.py +0 -0
  371. endoreg_db/models/administration/person/names/first_name.py +20 -0
  372. endoreg_db/models/administration/person/names/last_name.py +20 -0
  373. endoreg_db/models/administration/person/patient/__init__.py +7 -0
  374. endoreg_db/models/administration/person/patient/patient.py +488 -0
  375. endoreg_db/models/administration/person/patient/patient_external_id.py +36 -0
  376. endoreg_db/models/administration/person/person.py +35 -0
  377. endoreg_db/models/administration/person/profession/__init__.py +28 -0
  378. endoreg_db/models/administration/person/user/__init__.py +5 -0
  379. endoreg_db/models/administration/person/user/portal_user_information.py +41 -0
  380. endoreg_db/models/administration/product/__init__.py +15 -0
  381. endoreg_db/models/administration/product/product.py +106 -0
  382. endoreg_db/models/administration/product/product_group.py +41 -0
  383. endoreg_db/models/administration/product/product_material.py +60 -0
  384. endoreg_db/models/administration/product/product_weight.py +51 -0
  385. endoreg_db/models/administration/product/reference_product.py +147 -0
  386. endoreg_db/models/administration/qualification/__init__.py +7 -0
  387. endoreg_db/models/administration/qualification/qualification.py +43 -0
  388. endoreg_db/models/administration/qualification/qualification_type.py +39 -0
  389. endoreg_db/models/administration/shift/__init__.py +9 -0
  390. endoreg_db/models/administration/shift/scheduled_days.py +72 -0
  391. endoreg_db/models/administration/shift/shift.py +57 -0
  392. endoreg_db/models/administration/shift/shift_type.py +108 -0
  393. endoreg_db/models/aidataset/__init__.py +5 -0
  394. endoreg_db/models/aidataset/aidataset.py +193 -0
  395. endoreg_db/models/label/__init__.py +23 -0
  396. endoreg_db/models/label/annotation/__init__.py +12 -0
  397. endoreg_db/models/label/annotation/image_classification.py +85 -0
  398. endoreg_db/models/label/annotation/video_segmentation_annotation.py +61 -0
  399. endoreg_db/models/label/label.py +91 -0
  400. endoreg_db/models/label/label_set.py +68 -0
  401. endoreg_db/models/label/label_type.py +29 -0
  402. endoreg_db/models/label/label_video_segment/__init__.py +3 -0
  403. endoreg_db/models/label/label_video_segment/_create_from_video.py +42 -0
  404. endoreg_db/models/label/label_video_segment/label_video_segment.py +611 -0
  405. endoreg_db/models/label/video_segmentation_label.py +35 -0
  406. endoreg_db/models/label/video_segmentation_labelset.py +28 -0
  407. endoreg_db/models/media/__init__.py +23 -0
  408. endoreg_db/models/media/frame/__init__.py +3 -0
  409. endoreg_db/models/media/frame/frame.py +137 -0
  410. endoreg_db/models/media/pdf/__init__.py +12 -0
  411. endoreg_db/models/media/pdf/raw_pdf.py +764 -0
  412. endoreg_db/models/media/pdf/report_file.py +162 -0
  413. endoreg_db/models/media/pdf/report_reader/__init__.py +7 -0
  414. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +85 -0
  415. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +46 -0
  416. endoreg_db/models/media/video/__init__.py +9 -0
  417. endoreg_db/models/media/video/create_from_file.py +402 -0
  418. endoreg_db/models/media/video/pipe_1.py +258 -0
  419. endoreg_db/models/media/video/pipe_2.py +129 -0
  420. endoreg_db/models/media/video/video_file.py +907 -0
  421. endoreg_db/models/media/video/video_file_ai.py +828 -0
  422. endoreg_db/models/media/video/video_file_anonymize.py +524 -0
  423. endoreg_db/models/media/video/video_file_frames/__init__.py +49 -0
  424. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +25 -0
  425. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +23 -0
  426. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +126 -0
  427. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +233 -0
  428. endoreg_db/models/media/video/video_file_frames/_get_frame.py +36 -0
  429. endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +13 -0
  430. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +24 -0
  431. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +40 -0
  432. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +44 -0
  433. endoreg_db/models/media/video/video_file_frames/_get_frames.py +30 -0
  434. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +205 -0
  435. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +228 -0
  436. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +107 -0
  437. endoreg_db/models/media/video/video_file_io.py +272 -0
  438. endoreg_db/models/media/video/video_file_meta/__init__.py +22 -0
  439. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +58 -0
  440. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +62 -0
  441. endoreg_db/models/media/video/video_file_meta/get_fps.py +183 -0
  442. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +198 -0
  443. endoreg_db/models/media/video/video_file_meta/text_meta.py +178 -0
  444. endoreg_db/models/media/video/video_file_meta/video_meta.py +105 -0
  445. endoreg_db/models/media/video/video_file_segments.py +317 -0
  446. endoreg_db/models/media/video/video_metadata.py +67 -0
  447. endoreg_db/models/media/video/video_processing.py +192 -0
  448. endoreg_db/models/medical/__init__.py +136 -0
  449. endoreg_db/models/medical/contraindication/README.md +1 -0
  450. endoreg_db/models/medical/contraindication/__init__.py +29 -0
  451. endoreg_db/models/medical/disease.py +174 -0
  452. endoreg_db/models/medical/event.py +154 -0
  453. endoreg_db/models/medical/examination/__init__.py +20 -0
  454. endoreg_db/models/medical/examination/examination.py +183 -0
  455. endoreg_db/models/medical/examination/examination_indication.py +229 -0
  456. endoreg_db/models/medical/examination/examination_time.py +68 -0
  457. endoreg_db/models/medical/examination/examination_time_type.py +44 -0
  458. endoreg_db/models/medical/examination/examination_type.py +47 -0
  459. endoreg_db/models/medical/finding/__init__.py +20 -0
  460. endoreg_db/models/medical/finding/finding.py +113 -0
  461. endoreg_db/models/medical/finding/finding_classification.py +131 -0
  462. endoreg_db/models/medical/finding/finding_intervention.py +68 -0
  463. endoreg_db/models/medical/finding/finding_type.py +38 -0
  464. endoreg_db/models/medical/hardware/__init__.py +8 -0
  465. endoreg_db/models/medical/hardware/endoscope.py +77 -0
  466. endoreg_db/models/medical/hardware/endoscopy_processor.py +182 -0
  467. endoreg_db/models/medical/laboratory/__init__.py +5 -0
  468. endoreg_db/models/medical/laboratory/lab_value.py +490 -0
  469. endoreg_db/models/medical/medication/__init__.py +23 -0
  470. endoreg_db/models/medical/medication/medication.py +45 -0
  471. endoreg_db/models/medical/medication/medication_indication.py +78 -0
  472. endoreg_db/models/medical/medication/medication_indication_type.py +58 -0
  473. endoreg_db/models/medical/medication/medication_intake_time.py +58 -0
  474. endoreg_db/models/medical/medication/medication_schedule.py +58 -0
  475. endoreg_db/models/medical/organ/__init__.py +38 -0
  476. endoreg_db/models/medical/patient/__init__.py +48 -0
  477. endoreg_db/models/medical/patient/medication_examples.py +56 -0
  478. endoreg_db/models/medical/patient/patient_disease.py +72 -0
  479. endoreg_db/models/medical/patient/patient_event.py +80 -0
  480. endoreg_db/models/medical/patient/patient_examination.py +280 -0
  481. endoreg_db/models/medical/patient/patient_examination_indication.py +57 -0
  482. endoreg_db/models/medical/patient/patient_finding.py +416 -0
  483. endoreg_db/models/medical/patient/patient_finding_classification.py +231 -0
  484. endoreg_db/models/medical/patient/patient_finding_intervention.py +37 -0
  485. endoreg_db/models/medical/patient/patient_lab_sample.py +157 -0
  486. endoreg_db/models/medical/patient/patient_lab_value.py +247 -0
  487. endoreg_db/models/medical/patient/patient_medication.py +111 -0
  488. endoreg_db/models/medical/patient/patient_medication_schedule.py +152 -0
  489. endoreg_db/models/medical/risk/__init__.py +7 -0
  490. endoreg_db/models/medical/risk/risk.py +73 -0
  491. endoreg_db/models/medical/risk/risk_type.py +54 -0
  492. endoreg_db/models/metadata/__init__.py +19 -0
  493. endoreg_db/models/metadata/model_meta.py +266 -0
  494. endoreg_db/models/metadata/model_meta_logic.py +485 -0
  495. endoreg_db/models/metadata/pdf_meta.py +96 -0
  496. endoreg_db/models/metadata/sensitive_meta.py +345 -0
  497. endoreg_db/models/metadata/sensitive_meta_logic.py +1161 -0
  498. endoreg_db/models/metadata/video_meta.py +459 -0
  499. endoreg_db/models/metadata/video_prediction_logic.py +232 -0
  500. endoreg_db/models/metadata/video_prediction_meta.py +319 -0
  501. endoreg_db/models/operation_log.py +63 -0
  502. endoreg_db/models/other/__init__.py +40 -0
  503. endoreg_db/models/other/distribution/__init__.py +46 -0
  504. endoreg_db/models/other/distribution/base_value_distribution.py +22 -0
  505. endoreg_db/models/other/distribution/date_value_distribution.py +163 -0
  506. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +50 -0
  507. endoreg_db/models/other/distribution/numeric_value_distribution.py +211 -0
  508. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +23 -0
  509. endoreg_db/models/other/emission/__init__.py +5 -0
  510. endoreg_db/models/other/emission/emission_factor.py +110 -0
  511. endoreg_db/models/other/gender.py +32 -0
  512. endoreg_db/models/other/information_source.py +190 -0
  513. endoreg_db/models/other/material.py +34 -0
  514. endoreg_db/models/other/resource.py +24 -0
  515. endoreg_db/models/other/tag.py +32 -0
  516. endoreg_db/models/other/transport_route.py +40 -0
  517. endoreg_db/models/other/unit.py +40 -0
  518. endoreg_db/models/other/waste.py +28 -0
  519. endoreg_db/models/report/__init__.py +0 -0
  520. endoreg_db/models/report/images.py +0 -0
  521. endoreg_db/models/report/report.py +5 -0
  522. endoreg_db/models/requirement/__init__.py +11 -0
  523. endoreg_db/models/requirement/requirement.py +792 -0
  524. endoreg_db/models/requirement/requirement_error.py +84 -0
  525. endoreg_db/models/requirement/requirement_evaluation/__init__.py +6 -0
  526. endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
  527. endoreg_db/models/requirement/requirement_evaluation/get_values.py +40 -0
  528. endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +6 -0
  529. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +137 -0
  530. endoreg_db/models/requirement/requirement_operator.py +187 -0
  531. endoreg_db/models/requirement/requirement_set.py +327 -0
  532. endoreg_db/models/state/__init__.py +13 -0
  533. endoreg_db/models/state/abstract.py +11 -0
  534. endoreg_db/models/state/anonymization.py +30 -0
  535. endoreg_db/models/state/audit_ledger.py +155 -0
  536. endoreg_db/models/state/label_video_segment.py +31 -0
  537. endoreg_db/models/state/processing_history/__init__.py +3 -0
  538. endoreg_db/models/state/processing_history/processing_history.py +136 -0
  539. endoreg_db/models/state/raw_pdf.py +219 -0
  540. endoreg_db/models/state/sensitive_meta.py +50 -0
  541. endoreg_db/models/state/video.py +251 -0
  542. endoreg_db/models/upload_job.py +100 -0
  543. endoreg_db/models/utils.py +138 -0
  544. endoreg_db/queries/__init__.py +3 -0
  545. endoreg_db/queries/annotations/__init__.py +1 -0
  546. endoreg_db/queries/annotations/legacy.py +169 -0
  547. endoreg_db/queries/sanity/__init_.py +0 -0
  548. endoreg_db/root_urls.py +27 -0
  549. endoreg_db/schemas/__init__.py +0 -0
  550. endoreg_db/schemas/examination_evaluation.py +30 -0
  551. endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +861 -0
  552. endoreg_db/serializers/__init__.py +104 -0
  553. endoreg_db/serializers/administration/__init__.py +13 -0
  554. endoreg_db/serializers/administration/ai/__init__.py +9 -0
  555. endoreg_db/serializers/administration/ai/active_model.py +12 -0
  556. endoreg_db/serializers/administration/ai/ai_model.py +20 -0
  557. endoreg_db/serializers/administration/ai/model_type.py +12 -0
  558. endoreg_db/serializers/administration/center.py +14 -0
  559. endoreg_db/serializers/administration/gender.py +11 -0
  560. endoreg_db/serializers/anonymization.py +77 -0
  561. endoreg_db/serializers/evaluation/examination_evaluation.py +0 -0
  562. endoreg_db/serializers/examination/__init__.py +10 -0
  563. endoreg_db/serializers/examination/base.py +45 -0
  564. endoreg_db/serializers/examination/dropdown.py +20 -0
  565. endoreg_db/serializers/examination_serializer.py +9 -0
  566. endoreg_db/serializers/finding/__init__.py +5 -0
  567. endoreg_db/serializers/finding/finding.py +61 -0
  568. endoreg_db/serializers/finding_classification/__init__.py +7 -0
  569. endoreg_db/serializers/finding_classification/choice.py +19 -0
  570. endoreg_db/serializers/finding_classification/classification.py +11 -0
  571. endoreg_db/serializers/label_video_segment/__init__.py +9 -0
  572. endoreg_db/serializers/label_video_segment/image_classification_annotation.py +62 -0
  573. endoreg_db/serializers/label_video_segment/label/__init__.py +6 -0
  574. endoreg_db/serializers/label_video_segment/label/label.py +15 -0
  575. endoreg_db/serializers/label_video_segment/label_video_segment.py +427 -0
  576. endoreg_db/serializers/meta/__init__.py +13 -0
  577. endoreg_db/serializers/meta/sensitive_meta_detail.py +122 -0
  578. endoreg_db/serializers/meta/sensitive_meta_update.py +153 -0
  579. endoreg_db/serializers/meta/sensitive_meta_verification.py +62 -0
  580. endoreg_db/serializers/meta/video_meta.py +39 -0
  581. endoreg_db/serializers/misc/__init__.py +14 -0
  582. endoreg_db/serializers/misc/file_overview.py +72 -0
  583. endoreg_db/serializers/misc/sensitive_patient_data.py +144 -0
  584. endoreg_db/serializers/misc/stats.py +35 -0
  585. endoreg_db/serializers/misc/translatable_field_mix_in.py +44 -0
  586. endoreg_db/serializers/misc/upload_job.py +74 -0
  587. endoreg_db/serializers/patient/__init__.py +12 -0
  588. endoreg_db/serializers/patient/patient.py +103 -0
  589. endoreg_db/serializers/patient/patient_dropdown.py +35 -0
  590. endoreg_db/serializers/patient_examination/__init__.py +7 -0
  591. endoreg_db/serializers/patient_examination/patient_examination.py +168 -0
  592. endoreg_db/serializers/patient_finding/__init__.py +15 -0
  593. endoreg_db/serializers/patient_finding/patient_finding.py +32 -0
  594. endoreg_db/serializers/patient_finding/patient_finding_classification.py +47 -0
  595. endoreg_db/serializers/patient_finding/patient_finding_detail.py +62 -0
  596. endoreg_db/serializers/patient_finding/patient_finding_intervention.py +28 -0
  597. endoreg_db/serializers/patient_finding/patient_finding_list.py +40 -0
  598. endoreg_db/serializers/patient_finding/patient_finding_write.py +135 -0
  599. endoreg_db/serializers/pdf/__init__.py +3 -0
  600. endoreg_db/serializers/pdf/anony_text_validation.py +101 -0
  601. endoreg_db/serializers/requirements/requirement_schema.py +20 -0
  602. endoreg_db/serializers/requirements/requirement_sets.py +99 -0
  603. endoreg_db/serializers/sensitive_meta_serializer.py +301 -0
  604. endoreg_db/serializers/video/__init__.py +7 -0
  605. endoreg_db/serializers/video/video_file.py +283 -0
  606. endoreg_db/serializers/video/video_file_brief.py +14 -0
  607. endoreg_db/serializers/video/video_file_detail.py +96 -0
  608. endoreg_db/serializers/video/video_file_list.py +100 -0
  609. endoreg_db/serializers/video/video_processing_history.py +172 -0
  610. endoreg_db/serializers/video_examination.py +198 -0
  611. endoreg_db/services/__init__.py +5 -0
  612. endoreg_db/services/anonymization.py +274 -0
  613. endoreg_db/services/examination_evaluation.py +172 -0
  614. endoreg_db/services/finding_description_service.py +0 -0
  615. endoreg_db/services/lookup_service.py +424 -0
  616. endoreg_db/services/lookup_store.py +266 -0
  617. endoreg_db/services/model_meta_from_hf.py +76 -0
  618. endoreg_db/services/pdf_import.py +0 -0
  619. endoreg_db/services/polling_coordinator.py +319 -0
  620. endoreg_db/services/pseudonym_service.py +94 -0
  621. endoreg_db/services/report_import.py +13 -0
  622. endoreg_db/services/segment_sync.py +171 -0
  623. endoreg_db/services/video_import.py +9 -0
  624. endoreg_db/templates/admin/patient_finding_intervention.html +253 -0
  625. endoreg_db/templates/admin/start_examination.html +12 -0
  626. endoreg_db/templates/timeline.html +176 -0
  627. endoreg_db/urls/__init__.py +56 -0
  628. endoreg_db/urls/ai.py +14 -0
  629. endoreg_db/urls/anonymization.py +78 -0
  630. endoreg_db/urls/auth.py +16 -0
  631. endoreg_db/urls/classification.py +34 -0
  632. endoreg_db/urls/examination.py +63 -0
  633. endoreg_db/urls/media.py +251 -0
  634. endoreg_db/urls/patient.py +23 -0
  635. endoreg_db/urls/requirements.py +15 -0
  636. endoreg_db/urls/root_urls.py +28 -0
  637. endoreg_db/urls/stats.py +54 -0
  638. endoreg_db/urls/upload.py +12 -0
  639. endoreg_db/urls.py +9 -0
  640. endoreg_db/utils/__init__.py +97 -0
  641. endoreg_db/utils/ai/__init__.py +9 -0
  642. endoreg_db/utils/ai/data_loader_for_model_input.py +262 -0
  643. endoreg_db/utils/ai/data_loader_for_model_training.py +262 -0
  644. endoreg_db/utils/ai/get.py +6 -0
  645. endoreg_db/utils/ai/inference_dataset.py +51 -0
  646. endoreg_db/utils/ai/model_training/config.py +117 -0
  647. endoreg_db/utils/ai/model_training/dataset.py +74 -0
  648. endoreg_db/utils/ai/model_training/losses.py +68 -0
  649. endoreg_db/utils/ai/model_training/metrics.py +78 -0
  650. endoreg_db/utils/ai/model_training/model_backbones.py +155 -0
  651. endoreg_db/utils/ai/model_training/model_gastronet_resnet.py +118 -0
  652. endoreg_db/utils/ai/model_training/trainer_gastronet_multilabel.py +771 -0
  653. endoreg_db/utils/ai/multilabel_classification_net.py +270 -0
  654. endoreg_db/utils/ai/postprocess.py +63 -0
  655. endoreg_db/utils/ai/predict.py +293 -0
  656. endoreg_db/utils/ai/preprocess.py +76 -0
  657. endoreg_db/utils/calc_duration_seconds.py +24 -0
  658. endoreg_db/utils/case_generator/__init__.py +3 -0
  659. endoreg_db/utils/case_generator/lab_sample_factory.py +32 -0
  660. endoreg_db/utils/check_video_files.py +175 -0
  661. endoreg_db/utils/cropping.py +30 -0
  662. endoreg_db/utils/dataloader.py +285 -0
  663. endoreg_db/utils/dates.py +59 -0
  664. endoreg_db/utils/defaults/set_default_center.py +33 -0
  665. endoreg_db/utils/env.py +37 -0
  666. endoreg_db/utils/extract_specific_frames.py +87 -0
  667. endoreg_db/utils/file_operations.py +70 -0
  668. endoreg_db/utils/fix_video_path_direct.py +157 -0
  669. endoreg_db/utils/frame_anonymization_utils.py +463 -0
  670. endoreg_db/utils/hashs.py +138 -0
  671. endoreg_db/utils/links/__init__.py +0 -0
  672. endoreg_db/utils/links/requirement_link.py +237 -0
  673. endoreg_db/utils/mime_types.py +0 -0
  674. endoreg_db/utils/names.py +82 -0
  675. endoreg_db/utils/ocr.py +195 -0
  676. endoreg_db/utils/operation_log.py +87 -0
  677. endoreg_db/utils/parse_and_generate_yaml.py +45 -0
  678. endoreg_db/utils/paths.py +159 -0
  679. endoreg_db/utils/permissions.py +160 -0
  680. endoreg_db/utils/pipelines/Readme.md +235 -0
  681. endoreg_db/utils/pipelines/__init__.py +0 -0
  682. endoreg_db/utils/pipelines/process_video_dir.py +144 -0
  683. endoreg_db/utils/product/__init__.py +0 -0
  684. endoreg_db/utils/product/sum_emissions.py +22 -0
  685. endoreg_db/utils/product/sum_weights.py +20 -0
  686. endoreg_db/utils/pydantic_models/__init__.py +5 -0
  687. endoreg_db/utils/pydantic_models/db_config.py +57 -0
  688. endoreg_db/utils/requirement_helpers.py +0 -0
  689. endoreg_db/utils/requirement_operator_logic/__init__.py +0 -0
  690. endoreg_db/utils/requirement_operator_logic/_old/lab_value_operators.py +678 -0
  691. endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +842 -0
  692. endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +114 -0
  693. endoreg_db/utils/setup_config.py +196 -0
  694. endoreg_db/utils/storage.py +117 -0
  695. endoreg_db/utils/translation.py +31 -0
  696. endoreg_db/utils/uuid.py +5 -0
  697. endoreg_db/utils/validate_endo_roi.py +33 -0
  698. endoreg_db/utils/validate_subcategory_dict.py +93 -0
  699. endoreg_db/utils/validate_video_detailed.py +415 -0
  700. endoreg_db/utils/video/__init__.py +30 -0
  701. endoreg_db/utils/video/extract_frames.py +100 -0
  702. endoreg_db/utils/video/ffmpeg_wrapper.py +996 -0
  703. endoreg_db/utils/video/names.py +47 -0
  704. endoreg_db/utils/video/streaming_processor.py +386 -0
  705. endoreg_db/utils/video/video_splitter.py +105 -0
  706. endoreg_db/versioning.md +79 -0
  707. endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +247 -0
  708. endoreg_db/views/__init__.py +157 -0
  709. endoreg_db/views/anonymization/__init__.py +31 -0
  710. endoreg_db/views/anonymization/media_management.py +486 -0
  711. endoreg_db/views/anonymization/overview.py +307 -0
  712. endoreg_db/views/anonymization/validate.py +310 -0
  713. endoreg_db/views/auth/__init__.py +13 -0
  714. endoreg_db/views/auth/keycloak.py +146 -0
  715. endoreg_db/views/examination/__init__.py +30 -0
  716. endoreg_db/views/examination/examination.py +37 -0
  717. endoreg_db/views/examination/examination_manifest_cache.py +26 -0
  718. endoreg_db/views/examination/get_finding_classification_choices.py +62 -0
  719. endoreg_db/views/examination/get_finding_classifications.py +38 -0
  720. endoreg_db/views/examination/get_findings.py +39 -0
  721. endoreg_db/views/examination/get_instruments.py +19 -0
  722. endoreg_db/views/examination/get_interventions.py +14 -0
  723. endoreg_db/views/finding/__init__.py +9 -0
  724. endoreg_db/views/finding/finding.py +116 -0
  725. endoreg_db/views/finding/get_classifications.py +14 -0
  726. endoreg_db/views/finding/get_interventions.py +17 -0
  727. endoreg_db/views/finding_classification/__init__.py +13 -0
  728. endoreg_db/views/finding_classification/base.py +0 -0
  729. endoreg_db/views/finding_classification/finding_classification.py +41 -0
  730. endoreg_db/views/finding_classification/get_classification_choices.py +54 -0
  731. endoreg_db/views/media/__init__.py +32 -0
  732. endoreg_db/views/media/pdf_media.py +411 -0
  733. endoreg_db/views/media/sensitive_metadata.py +372 -0
  734. endoreg_db/views/media/video_media.py +275 -0
  735. endoreg_db/views/meta/__init__.py +7 -0
  736. endoreg_db/views/meta/sensitive_meta_list.py +102 -0
  737. endoreg_db/views/meta/sensitive_meta_verification.py +74 -0
  738. endoreg_db/views/misc/__init__.py +29 -0
  739. endoreg_db/views/misc/center.py +14 -0
  740. endoreg_db/views/misc/csrf.py +8 -0
  741. endoreg_db/views/misc/gender.py +15 -0
  742. endoreg_db/views/misc/stats.py +255 -0
  743. endoreg_db/views/misc/upload_views.py +241 -0
  744. endoreg_db/views/patient/__init__.py +3 -0
  745. endoreg_db/views/patient/patient.py +253 -0
  746. endoreg_db/views/patient_examination/__init__.py +11 -0
  747. endoreg_db/views/patient_examination/patient_examination.py +141 -0
  748. endoreg_db/views/patient_examination/patient_examination_create.py +58 -0
  749. endoreg_db/views/patient_examination/patient_examination_detail.py +63 -0
  750. endoreg_db/views/patient_examination/patient_examination_list.py +72 -0
  751. endoreg_db/views/patient_examination/video.py +228 -0
  752. endoreg_db/views/patient_finding/__init__.py +7 -0
  753. endoreg_db/views/patient_finding/base.py +0 -0
  754. endoreg_db/views/patient_finding/patient_finding.py +71 -0
  755. endoreg_db/views/patient_finding/patient_finding_optimized.py +291 -0
  756. endoreg_db/views/patient_finding_classification/__init__.py +5 -0
  757. endoreg_db/views/patient_finding_classification/pfc_create.py +75 -0
  758. endoreg_db/views/report/__init__.py +7 -0
  759. endoreg_db/views/report/reimport.py +177 -0
  760. endoreg_db/views/report/report_stream.py +191 -0
  761. endoreg_db/views/requirement/__init__.py +11 -0
  762. endoreg_db/views/requirement/evaluate.py +278 -0
  763. endoreg_db/views/requirement/lookup.py +380 -0
  764. endoreg_db/views/requirement/lookup_store.py +183 -0
  765. endoreg_db/views/requirement/requirement_utils.py +87 -0
  766. endoreg_db/views/requirement_lookup/lookup.py +0 -0
  767. endoreg_db/views/requirement_lookup/lookup_store.py +0 -0
  768. endoreg_db/views/stats/__init__.py +13 -0
  769. endoreg_db/views/stats/stats_views.py +266 -0
  770. endoreg_db/views/video/__init__.py +49 -0
  771. endoreg_db/views/video/ai/__init__.py +8 -0
  772. endoreg_db/views/video/ai/label.py +159 -0
  773. endoreg_db/views/video/correction.py +529 -0
  774. endoreg_db/views/video/reimport.py +230 -0
  775. endoreg_db/views/video/segments_crud.py +709 -0
  776. endoreg_db/views/video/video_apply_mask.py +49 -0
  777. endoreg_db/views/video/video_correction.py +22 -0
  778. endoreg_db/views/video/video_download_processed.py +58 -0
  779. endoreg_db/views/video/video_examination_viewset.py +242 -0
  780. endoreg_db/views/video/video_metadata.py +101 -0
  781. endoreg_db/views/video/video_processing_history.py +25 -0
  782. endoreg_db/views/video/video_remove_frames.py +49 -0
  783. endoreg_db/views/video/video_stream.py +334 -0
  784. endoreg_db-0.8.9.32.dist-info/METADATA +404 -0
  785. endoreg_db-0.8.9.32.dist-info/RECORD +787 -0
  786. endoreg_db-0.8.9.32.dist-info/WHEEL +4 -0
  787. endoreg_db-0.8.9.32.dist-info/licenses/LICENSE +674 -0
@@ -0,0 +1,861 @@
1
+ from endoreg_db.utils.extract_specific_frames import extract_selected_frames
2
+ from rest_framework import serializers
3
+ from endoreg_db.models import Label, LabelVideoSegment
4
+ from itertools import combinations
5
+ from pathlib import Path
6
+ from django.conf import settings
7
+
8
+ # === CONFIGURABLE PARAMETERS - ForNiceClassificationSerializer ===
9
+ POLYP_LABEL_NAME = "polyp"
10
+ CHROMO_LABEL_NAMES = ["digital_chromo_endoscopy", "nbi"]
11
+ FPS = 50 # Frames per second- should fetch dynamically from videofile table
12
+ # Sequence-level filtering
13
+ MIN_SEQUENCE_GAP_SECONDS = 0.5 # Enforce diversity between sequences
14
+ MIN_SEQUENCE_GAP_FRAMES = FPS * MIN_SEQUENCE_GAP_SECONDS # Convert to frame count
15
+ # Minimum length of a segment in seconds
16
+ MIN_SEGMENT_LENGTH_SECONDS = 0.5
17
+ MIN_SEGMENT_LENGTH_FRAMES = FPS * MIN_SEGMENT_LENGTH_SECONDS
18
+
19
+ # Frame-level selection within a sequence
20
+ MIN_FRAME_GAP_SECONDS = 1 # Minimum gap between selected frames in seconds
21
+ MIN_FRAME_GAP_IN_SEQUENCE = FPS * MIN_FRAME_GAP_SECONDS # Convert to frame count
22
+ FRAMES_PER_SEQUENCE = 3 # Number of frames to select per matched sequence
23
+
24
+
25
+ # === Frame Filtering Rules ===
26
+ # All rules must return True to accept the frame
27
+ FRAME_SELECTION_RULES = [
28
+ lambda pred: pred.get("low_quality", 1.0) < 0.1,
29
+ lambda pred: pred.get("outside", 1.0) < 0.1,
30
+ lambda pred: pred.get("snare", 1.0) < 0.1,
31
+ # Add more rules easily here
32
+ ]
33
+
34
+ REQUIRED_FRAME_KEYS = [
35
+ "low_quality",
36
+ "outside",
37
+ "snare",
38
+ ] # need tp update when adding rules
39
+
40
+ POLYP_CONFIDENCE_THRESHOLDS = [
41
+ 0.9,
42
+ 0.8,
43
+ 0.7,
44
+ ] # basically this is the prediction value/score, we are using for frame selection
45
+ INSTRUMENT_LABEL_NAMES = ["instrument", "snare", "needle"] # Add more as needed later
46
+
47
+
48
+ class BaseClassificationSerializer(serializers.Serializer):
49
+ """
50
+ Base class for NICE and PARIS serializers.
51
+ Handles label lookup, chromo/instrument segment filtering, and shared utilities.
52
+ """
53
+
54
+ # TODO add create method
55
+ # TODO add update method
56
+ LABEL_NAME = "polyp" # default (can be overridden)
57
+ INSTRUMENT_LABEL_NAME = "instrument" # TODO @Hamzaukw we should define frequently used labels in a utils file
58
+
59
+ def get_label_id_by_name(self, label_name):
60
+ """
61
+ Get the ID of a label by its name.
62
+ Raises a validation error if not found.
63
+ """
64
+ try:
65
+ label = Label.objects.get(name=label_name)
66
+ return label.id
67
+ except Label.DoesNotExist:
68
+ raise serializers.ValidationError(
69
+ {"error": f"Label with name '{label_name}' does not exist."}
70
+ )
71
+
72
+ def get_label_ids_by_names(self, label_names):
73
+ """
74
+ Get a list of label IDs for a given list of label names.
75
+ Ensures all names exist in the database.
76
+ """
77
+ labels = Label.objects.filter(name__in=label_names)
78
+ label_map = {label.name: label.id for label in labels}
79
+
80
+ missing = set(label_names) - set(label_map.keys())
81
+ if missing:
82
+ raise serializers.ValidationError(
83
+ {"error": f"Labels not found: {', '.join(missing)}"}
84
+ )
85
+
86
+ return list(label_map.values())
87
+
88
+ def get_chromo_segments(self, video_id):
89
+ """
90
+ Fetch all segments that match chromo-like labels (e.g., chromo or NBI).
91
+ Used in both NICE and PARIS, but interpreted differently:
92
+ - NICE: chromo overlap is required
93
+ - PARIS: chromo overlap is disqualifying
94
+ """
95
+ chromo_label_ids = self.get_label_ids_by_names(CHROMO_LABEL_NAMES)
96
+ return LabelVideoSegment.objects.filter(
97
+ label_id__in=chromo_label_ids, video_file_id=video_id
98
+ )
99
+
100
+ def get_filtered_polyp_segments(self, video_id):
101
+ """
102
+ Return polyp segments that do NOT overlap with 'instrument' segments.
103
+ """
104
+ polyp_label_id = self.get_label_id_by_name(self.LABEL_NAME)
105
+ instrument_label_id = self.get_label_id_by_name(self.INSTRUMENT_LABEL_NAME)
106
+
107
+ print(
108
+ "polyp label id is :-",
109
+ polyp_label_id,
110
+ "and - instrument_label_id is ,",
111
+ instrument_label_id,
112
+ )
113
+
114
+ polyp_segments = LabelVideoSegment.objects.filter(
115
+ label_id=polyp_label_id, video_file_id=video_id
116
+ )
117
+
118
+ instrument_segments = LabelVideoSegment.objects.filter(
119
+ label_id=instrument_label_id, video_file_id=video_id
120
+ )
121
+ print(
122
+ "------------------------ --------------------------------- -------------------------------"
123
+ )
124
+ print(
125
+ "polyp label id is :-",
126
+ polyp_label_id,
127
+ "and - instrument_label_id is ,",
128
+ instrument_label_id,
129
+ )
130
+ print(
131
+ "polyp segments are",
132
+ polyp_segments,
133
+ "instrument_segments are",
134
+ instrument_segments,
135
+ )
136
+
137
+ def overlaps(seg1, seg2):
138
+ return (
139
+ seg1.start_frame_number <= seg2.end_frame_number
140
+ and seg1.end_frame_number >= seg2.start_frame_number
141
+ )
142
+
143
+ filtered_polyp_segments = []
144
+ for polyp_seg in polyp_segments:
145
+ if not any(
146
+ overlaps(polyp_seg, instr_seg) for instr_seg in instrument_segments
147
+ ):
148
+ filtered_polyp_segments.append(polyp_seg)
149
+
150
+ return filtered_polyp_segments
151
+
152
+ def get_polyp_segments(self, video_id):
153
+ polyp_label_id = self.get_label_id_by_name(self.LABEL_NAME)
154
+ return LabelVideoSegment.objects.filter(
155
+ label_id=polyp_label_id, video_file_id=video_id
156
+ )
157
+
158
+ def apply_sequence_diversity(self, matching_segments):
159
+ if not matching_segments:
160
+ return []
161
+
162
+ matching_segments.sort(key=lambda seg: seg["polyp"].start_frame_number)
163
+
164
+ valid_segments = [
165
+ seg
166
+ for seg in matching_segments
167
+ if (seg["polyp"].end_frame_number - seg["polyp"].start_frame_number)
168
+ >= MIN_SEGMENT_LENGTH_FRAMES
169
+ ]
170
+
171
+ if len(valid_segments) < 3:
172
+ valid_segments.sort(
173
+ key=lambda seg: seg["polyp"].end_frame_number
174
+ - seg["polyp"].start_frame_number,
175
+ reverse=True,
176
+ )
177
+ return valid_segments[:3]
178
+
179
+ best_combo = None
180
+ best_gap_sum = -1
181
+
182
+ for combo in combinations(valid_segments, 3):
183
+ sorted_combo = sorted(
184
+ combo, key=lambda seg: seg["polyp"].start_frame_number
185
+ )
186
+ s1, s2, s3 = sorted_combo
187
+ s1_end = s1["polyp"].end_frame_number
188
+ s2_start = s2["polyp"].start_frame_number
189
+ s2_end = s2["polyp"].end_frame_number
190
+ s3_start = s3["polyp"].start_frame_number
191
+ gap1 = s2_start - s1_end
192
+ gap2 = s3_start - s2_end
193
+
194
+ if gap1 >= MIN_SEQUENCE_GAP_FRAMES and gap2 >= MIN_SEQUENCE_GAP_FRAMES:
195
+ total_gap = gap1 + gap2
196
+ if total_gap > best_gap_sum:
197
+ best_gap_sum = total_gap
198
+ best_combo = sorted_combo
199
+
200
+ if best_combo:
201
+ return list(best_combo)
202
+
203
+ valid_segments.sort(
204
+ key=lambda seg: seg["polyp"].end_frame_number
205
+ - seg["polyp"].start_frame_number,
206
+ reverse=True,
207
+ )
208
+ return valid_segments[:3]
209
+
210
+ def select_frames_for_sequence(self, sequence):
211
+ """
212
+ Selects evenly spaced representative frames from a polyp segment.
213
+
214
+ Frames are chosen from the segment's frame range, ensuring a minimum gap between selected frames. Returns a list of dictionaries containing frame numbers and their corresponding file paths. If the video's frame directory is unavailable, returns an empty list.
215
+ """
216
+ polyp_sequence = sequence["polyp"]
217
+ video = polyp_sequence.video_file
218
+
219
+ start_frame = polyp_sequence.start_frame_number
220
+ end_frame = polyp_sequence.end_frame_number
221
+
222
+ frame_dir = getattr(video, "frame_dir", "")
223
+
224
+ if not frame_dir:
225
+ return []
226
+
227
+ # Just create frames assuming predictions aren't available
228
+ segment_frames = [
229
+ {
230
+ "frame_number": idx,
231
+ "frame_path": f"{frame_dir}/frame_{str(idx).zfill(7)}.png",
232
+ }
233
+ for idx in range(start_frame, end_frame + 1)
234
+ ]
235
+
236
+ selected_frames = []
237
+ last_selected_frame = -float("inf")
238
+
239
+ for frame in segment_frames:
240
+ if len(selected_frames) >= FRAMES_PER_SEQUENCE:
241
+ break
242
+
243
+ if frame["frame_number"] - last_selected_frame >= MIN_FRAME_GAP_IN_SEQUENCE:
244
+ selected_frames.append(
245
+ {
246
+ "frame_number": frame["frame_number"],
247
+ "frame_path": frame["frame_path"],
248
+ }
249
+ )
250
+ last_selected_frame = frame["frame_number"]
251
+
252
+ return selected_frames
253
+
254
+ def extract_and_save_selected_frames(
255
+ self, video, frame_numbers, classification_type: str
256
+ ):
257
+ """
258
+ Extract specific frames from the original video file and save them
259
+ into a structured folder path based on the classification type.
260
+
261
+ Args:
262
+ video (VideoFile): Video object with `original_file_name` and `frame_dir`.
263
+ frame_numbers (List[int]): List of frame numbers to extract.
264
+ classification_type (str): Either "nice" or "paris".
265
+ """
266
+ # Resolve the path to the original video
267
+ original_path = Path(video.original_file_name)
268
+ if not original_path.is_absolute():
269
+ base_video_dir = (
270
+ settings.BASE_DIR.parent.parent
271
+ / "production_test"
272
+ / "endoreg-db"
273
+ / "data"
274
+ / "coloreg_first_test_batch"
275
+ )
276
+ original_path = base_video_dir / original_path
277
+
278
+ # Define output directory based on classification and video ID
279
+ output_path = Path(video.frame_dir) / classification_type / f"video_{video.id}"
280
+
281
+ # Extract frames using the shared utility
282
+ extract_selected_frames(
283
+ video_path=original_path,
284
+ frame_numbers=frame_numbers,
285
+ output_dir=output_path,
286
+ fps=FPS,
287
+ )
288
+
289
+ """ # # If any error occurs in this function, use the commented one below(fallback:select_frames_for_sequence).
290
+ def select_frames_for_sequence(self, sequence):
291
+ # Extract the polyp segment from the current sequence
292
+ polyp_sequence = sequence['polyp']
293
+ video = polyp_sequence.video
294
+
295
+ # Get the start and end frame numbers of the segment/sequence
296
+ start_frame = polyp_sequence.start_frame_number
297
+ end_frame = polyp_sequence.end_frame_number
298
+
299
+ # here we aregetting the predictions and frame directory from the video object
300
+ predictions = getattr(video, "readable_predictions", [])
301
+ frame_dir = getattr(video, "frame_dir", "") #need to check
302
+
303
+ # If either predictions or frame_dir is missing, return an empty list
304
+ if not predictions or not frame_dir:
305
+ return []
306
+
307
+ # Build a list of prediction dictionaries for each frame in the segment
308
+ # Each entry includes frame number, selected prediction keys, path, and full prediction
309
+ segment_predictions = [
310
+ {
311
+ "frame_number": idx,
312
+ **{key: pred.get(key, 1.0) for key in REQUIRED_FRAME_KEYS + ["polyp"]},
313
+ "frame_path": f"{frame_dir}/frame_{str(idx).zfill(7)}.jpg",
314
+ "prediction": pred
315
+ }
316
+ for idx, pred in enumerate(predictions[start_frame:end_frame + 1], start=start_frame)
317
+ if isinstance(pred, dict)
318
+ ]
319
+
320
+ # Sort the frames by lowest 'low_quality' value first,# for higher quality images// changeable,
321
+ segment_predictions.sort(key=lambda x: x["low_quality"])
322
+
323
+ # Try frame selection with decreasing polyp confidence thresholds
324
+ #for polyp_threshold in [0.9, 0.8, 0.7]:
325
+ for polyp_threshold in POLYP_CONFIDENCE_THRESHOLDS:
326
+
327
+ # Filter frames that meet the current polyp threshold
328
+ candidate_frames = [
329
+ frame for frame in segment_predictions
330
+ if frame["prediction"].get("polyp", 0.0) > polyp_threshold
331
+ ]
332
+
333
+ # If no candidates at this threshold, try the next lower threshold
334
+ if not candidate_frames:
335
+ continue
336
+
337
+ # Initialize list of selected frames and track last selected frame number
338
+ selected_frames = []
339
+ last_selected_frame = -float('inf')
340
+
341
+ # Iterate through the candidate frames
342
+ for frame in candidate_frames:
343
+ # Stop if we've already selected enough frames
344
+ if len(selected_frames) >= FRAMES_PER_SEQUENCE:
345
+ break
346
+
347
+ # Apply the standard filtering rules and spacing condition
348
+ if (
349
+ frame["prediction"].get("low_quality", 1.0) < 0.1 and
350
+ frame["prediction"].get("outside", 1.0) < 0.1 and
351
+ frame["prediction"].get("snare", 1.0) < 0.1 and
352
+ frame["frame_number"] - last_selected_frame >= MIN_FRAME_GAP_IN_SEQUENCE
353
+ ):
354
+ # Frame passes all filters and spacing rule, so select it
355
+ selected_frames.append({
356
+ "frame_number": frame["frame_number"],
357
+ "low_quality": frame["low_quality"],
358
+ "polyp_score": frame["prediction"]["polyp"],
359
+ "frame_path": frame["frame_path"]
360
+ })
361
+ last_selected_frame = frame["frame_number"]
362
+
363
+ # If we found enough valid frames at this threshold, return them
364
+ if len(selected_frames) >= FRAMES_PER_SEQUENCE:
365
+ return selected_frames
366
+
367
+ # If no threshold yielded enough frames, return what was found in the last attempt (could be empty)
368
+ return selected_frames if selected_frames else []"""
369
+
370
+ # fallback:select_frames_for_sequence
371
+ """
372
+ def select_frames_for_sequence(self, sequence):
373
+ print("----------------------in selected_frames fro sequnces funtion ----------------------------------------")
374
+ polyp_sequence = sequence['polyp']
375
+ video = polyp_sequence.video
376
+ start_frame = polyp_sequence.start_frame_number
377
+ end_frame = polyp_sequence.end_frame_number
378
+ predictions = getattr(video, "readable_predictions", [])
379
+ frame_dir = getattr(video, "frame_dir", "")
380
+
381
+ if not predictions or not frame_dir:
382
+ return []
383
+
384
+ segment_predictions = [
385
+ {
386
+ "frame_number": idx,
387
+ **{key: pred.get(key, 1.0) for key in REQUIRED_FRAME_KEYS},
388
+ "frame_path": f"{frame_dir}/frame_{str(idx).zfill(7)}.jpg",
389
+ "prediction": pred
390
+ }
391
+ for idx, pred in enumerate(predictions[start_frame:end_frame + 1], start=start_frame)
392
+ if isinstance(pred, dict)
393
+ ]
394
+
395
+
396
+ segment_predictions.sort(key=lambda x: x["low_quality"])
397
+
398
+ selected_frames = []
399
+ last_selected_frame = -float('inf')
400
+
401
+ for frame in segment_predictions:
402
+ if len(selected_frames) >= FRAMES_PER_SEQUENCE:
403
+ break
404
+
405
+ if all(rule(frame["prediction"]) for rule in FRAME_SELECTION_RULES):
406
+ if frame["frame_number"] - last_selected_frame >= MIN_FRAME_GAP_IN_SEQUENCE:
407
+ selected_frames.append({
408
+ "frame_number": frame["frame_number"],
409
+ "low_quality": frame["low_quality"],
410
+ "frame_path": frame["frame_path"]
411
+ })
412
+ last_selected_frame = frame["frame_number"]
413
+
414
+ return selected_frames"""
415
+
416
+
417
+ class ForNiceClassificationSerializer(BaseClassificationSerializer):
418
+ """
419
+ NICE classification logic:
420
+ - Requires polyp segments
421
+ - Filters out any overlap with instrument labels
422
+ - Requires overlap with chromo-like labels (chromo/NBI)
423
+ - Selects diverse sequences and representative frames from each
424
+ """
425
+
426
+ def get_matching_sequences(self, video_id):
427
+ """
428
+ 1. Fetch all polyp segments in a video
429
+ 2. Remove parts overlapping with any instrument-type labels
430
+ 3. Keep only parts that still overlap with chromo/NBI
431
+ 4. Trim segments accordingly and return valid subsegments
432
+ """
433
+ polyp_label_id = self.get_label_id_by_name(self.LABEL_NAME)
434
+ instrument_label_ids = self.get_label_ids_by_names(INSTRUMENT_LABEL_NAMES)
435
+ # chromo_label_id = self.get_label_id_by_name(CHROMO_LABEL_NAME)
436
+ chromo_segments = self.get_chromo_segments(video_id)
437
+
438
+ polyp_segments = LabelVideoSegment.objects.filter(
439
+ label_id=polyp_label_id, video_file_id=video_id
440
+ )
441
+ instrument_segments = LabelVideoSegment.objects.filter(
442
+ label_id__in=instrument_label_ids, video_file_id=video_id
443
+ )
444
+
445
+ # chromo_segments = LabelVideoSegment.objects.filter(label_id=chromo_label_id, video_file_id=video_id)
446
+ print(
447
+ "polyp_label_id is", polyp_label_id, "and ployp_segment is ", polyp_segments
448
+ )
449
+ print("instrument_segments is", instrument_segments)
450
+ # print("chromo_segments is ",chromo_segments)
451
+
452
+ def overlaps(seg1, seg2):
453
+ return (
454
+ seg1.start_frame_number <= seg2.end_frame_number
455
+ and seg1.end_frame_number >= seg2.start_frame_number
456
+ )
457
+
458
+ def subtract_overlap(seg, overlaps):
459
+ start = seg.start_frame_number
460
+ end = seg.end_frame_number
461
+ blocks = [(o.start_frame_number, o.end_frame_number) for o in overlaps]
462
+ blocks.sort()
463
+
464
+ safe_ranges = []
465
+ curr = start
466
+
467
+ for o_start, o_end in blocks:
468
+ if o_end < curr:
469
+ continue
470
+ if o_start > end:
471
+ break
472
+ if o_start > curr:
473
+ safe_ranges.append((curr, min(o_start - 1, end)))
474
+ curr = max(curr, o_end + 1)
475
+
476
+ if curr <= end:
477
+ safe_ranges.append((curr, end))
478
+
479
+ return safe_ranges
480
+
481
+ matching_segments = []
482
+
483
+ for polyp in polyp_segments:
484
+ overlapping_instr = [
485
+ seg for seg in instrument_segments if overlaps(polyp, seg)
486
+ ]
487
+ safe_ranges = subtract_overlap(polyp, overlapping_instr)
488
+
489
+ for start, end in safe_ranges:
490
+ if end - start + 1 < MIN_SEGMENT_LENGTH_FRAMES:
491
+ continue
492
+
493
+ for chromo in chromo_segments:
494
+ if (
495
+ chromo.start_frame_number <= end
496
+ and chromo.end_frame_number >= start
497
+ ):
498
+ overlap_start = max(start, chromo.start_frame_number)
499
+ overlap_end = min(end, chromo.end_frame_number)
500
+
501
+ if overlap_end - overlap_start + 1 >= MIN_SEGMENT_LENGTH_FRAMES:
502
+ overlapping_segment = LabelVideoSegment(
503
+ video_file=polyp.video_file,
504
+ start_frame_number=overlap_start,
505
+ end_frame_number=overlap_end,
506
+ )
507
+ matching_segments.append({"polyp": overlapping_segment})
508
+
509
+ return matching_segments
510
+
511
+ def to_representation(self, videos):
512
+ """
513
+ Processes a list of videos:
514
+ - Applies NICE/PARIS rules to find segments
515
+ - Applies sequence diversity logic
516
+ - Selects frames per segment
517
+ - Extracts all frames for a video in a single call
518
+ - Returns structured output with messages per video
519
+ """
520
+ results = []
521
+
522
+ for video in videos:
523
+ try:
524
+ video_id = video.id
525
+ print("video-id is", video_id)
526
+
527
+ matching_segments = self.get_matching_sequences(video_id)
528
+ print("matching_segments are", matching_segments)
529
+ if not matching_segments:
530
+ results.append(
531
+ {
532
+ "video_id": video_id,
533
+ "message": "No valid polyp segments overlapping with chromo and not overlapping with instrument.",
534
+ }
535
+ )
536
+ continue
537
+
538
+ diverse_segments = self.apply_sequence_diversity(matching_segments)
539
+ if not diverse_segments:
540
+ results.append(
541
+ {
542
+ "video_id": video_id,
543
+ "message": "No diverse NICE sequences found — either too short or too close together.",
544
+ }
545
+ )
546
+ continue
547
+
548
+ # Collect all frame numbers to extract only once per video
549
+ all_frames = []
550
+ segment_results = []
551
+
552
+ for segment in diverse_segments:
553
+ frames = self.select_frames_for_sequence(segment)
554
+
555
+ if not frames:
556
+ segment_results.append(
557
+ {
558
+ "video_id": video_id,
559
+ "segment_start": segment["polyp"].start_frame_number,
560
+ "segment_end": segment["polyp"].end_frame_number,
561
+ "message": "No valid frames passed filtering rules (low_quality, outside, snare).",
562
+ }
563
+ )
564
+ else:
565
+ segment_results.append(
566
+ {
567
+ "video_id": video_id,
568
+ "segment_start": segment["polyp"].start_frame_number,
569
+ "segment_end": segment["polyp"].end_frame_number,
570
+ "frames": frames,
571
+ }
572
+ )
573
+ all_frames.extend(frames)
574
+
575
+ # Extract once per video
576
+ if all_frames:
577
+ unique_frame_numbers = sorted(
578
+ {f["frame_number"] for f in all_frames}
579
+ )
580
+ classification_type = (
581
+ "nice"
582
+ if isinstance(self, ForNiceClassificationSerializer)
583
+ else "paris"
584
+ )
585
+ self.extract_and_save_selected_frames(
586
+ video, unique_frame_numbers, classification_type
587
+ )
588
+
589
+ results.extend(segment_results)
590
+
591
+ except Exception as e:
592
+ results.append({"video_id": video.id, "error": str(e)})
593
+
594
+ if not results:
595
+ return [{"message": "No classification data generated for any videos."}]
596
+
597
+ return {
598
+ "message": "NICE classification data generated."
599
+ if isinstance(self, ForNiceClassificationSerializer)
600
+ else "PARIS classification data generated.",
601
+ "data": results,
602
+ }
603
+
604
+
605
+ class ForParisClassificationSerializer(BaseClassificationSerializer):
606
+ """
607
+ PARIS classification logic:
608
+ - Requires polyp segments
609
+ - Excludes any region overlapping with instruments or chromo/NBI
610
+ - Keeps remaining 'clean' subsegments
611
+ - Enforces minimum length and sequence diversity
612
+ - Selects frames from each valid segment
613
+ """
614
+
615
+ def get_filtered_polyp_segments(self, video_id):
616
+ """
617
+ 1. Fetch all polyp segments
618
+ 2. Subtract any overlap with chromo or instrument segments
619
+ 3. Keep only trimmed segments longer than the minimum threshold
620
+ """
621
+
622
+ polyp_label_id = self.get_label_id_by_name(self.LABEL_NAME)
623
+ instrument_label_ids = self.get_label_ids_by_names(INSTRUMENT_LABEL_NAMES)
624
+ # chromo_label_id = self.get_label_id_by_name(CHROMO_LABEL_NAME)
625
+
626
+ polyp_segments = LabelVideoSegment.objects.filter(
627
+ label_id=polyp_label_id, video_file_id=video_id
628
+ )
629
+ instrument_segments = LabelVideoSegment.objects.filter(
630
+ label_id__in=instrument_label_ids, video_file_id=video_id
631
+ )
632
+ # chromo_segments = LabelVideoSegment.objects.filter(label_id=chromo_label_id, video_file_id=video_id)
633
+ chromo_segments = self.get_chromo_segments(video_id)
634
+
635
+ def overlaps(seg1, seg2):
636
+ return (
637
+ seg1.start_frame_number <= seg2.end_frame_number
638
+ and seg1.end_frame_number >= seg2.start_frame_number
639
+ )
640
+
641
+ def subtract_overlap(seg, overlaps):
642
+ """
643
+ Given a base segment and list of overlapping segments,
644
+ returns list of non-overlapping sub-segments.
645
+ """
646
+ start = seg.start_frame_number
647
+ end = seg.end_frame_number
648
+ blocks = [(o.start_frame_number, o.end_frame_number) for o in overlaps]
649
+ blocks.sort()
650
+
651
+ safe_ranges = []
652
+ curr = start
653
+
654
+ for o_start, o_end in blocks:
655
+ if o_end < curr:
656
+ continue
657
+ if o_start > end:
658
+ break
659
+ if o_start > curr:
660
+ safe_ranges.append((curr, min(o_start - 1, end)))
661
+ curr = max(curr, o_end + 1)
662
+
663
+ if curr <= end:
664
+ safe_ranges.append((curr, end))
665
+
666
+ return safe_ranges
667
+
668
+ # Final valid sub-segments
669
+ trimmed_segments = []
670
+
671
+ for polyp_seg in polyp_segments:
672
+ # Collect all overlapping regions with instrument or chromo
673
+ overlapping = [
674
+ seg
675
+ for seg in (list(instrument_segments) + list(chromo_segments))
676
+ if overlaps(polyp_seg, seg)
677
+ ]
678
+
679
+ safe_ranges = subtract_overlap(polyp_seg, overlapping)
680
+
681
+ for start, end in safe_ranges:
682
+ if end - start + 1 >= MIN_SEGMENT_LENGTH_FRAMES:
683
+ trimmed_segments.append(
684
+ LabelVideoSegment(
685
+ video_file=polyp_seg.video_file,
686
+ start_frame_number=start,
687
+ end_frame_number=end,
688
+ )
689
+ )
690
+
691
+ return trimmed_segments
692
+
693
+ filtered_segments = []
694
+ for polyp_seg in polyp_segments:
695
+ if not any(
696
+ overlaps(polyp_seg, instr_seg) for instr_seg in instrument_segments
697
+ ) and not any(
698
+ overlaps(polyp_seg, chromo_seg) for chromo_seg in chromo_segments
699
+ ):
700
+ filtered_segments.append(polyp_seg)
701
+
702
+ return filtered_segments
703
+
704
+ def get_matching_sequences(self, video_id):
705
+ """
706
+ Wraps all valid polyp subsegments into a uniform data structure.
707
+ This is needed for consistent downstream processing.
708
+ """
709
+ segments = self.get_filtered_polyp_segments(video_id)
710
+ return [{"polyp": seg} for seg in segments]
711
+
712
+ def to_representation(self, videos):
713
+ """
714
+ Processes videos for PARIS classification.
715
+ Filters segments, selects diverse sequences, and picks valid frames.
716
+ Extracts all selected frames once per video.
717
+ Returns detailed per-video feedback or results.
718
+ """
719
+ results = []
720
+
721
+ for video in videos:
722
+ try:
723
+ video_id = video.id
724
+ matching_segments = self.get_matching_sequences(video_id)
725
+
726
+ if not matching_segments:
727
+ results.append(
728
+ {
729
+ "video_id": video_id,
730
+ "message": "No matching polyp segments found — possibly filtered due to overlap with 'instrument' label.",
731
+ }
732
+ )
733
+ continue
734
+
735
+ diverse_segments = self.apply_sequence_diversity(matching_segments)
736
+ if not diverse_segments:
737
+ results.append(
738
+ {
739
+ "video_id": video_id,
740
+ "message": "No diverse sequences found — either too short or too close to each other.",
741
+ }
742
+ )
743
+ continue
744
+
745
+ all_frames = []
746
+ segment_results = []
747
+
748
+ for segment in diverse_segments:
749
+ frames = self.select_frames_for_sequence(segment)
750
+
751
+ if not frames:
752
+ segment_results.append(
753
+ {
754
+ "video_id": video_id,
755
+ "segment_start": segment["polyp"].start_frame_number,
756
+ "segment_end": segment["polyp"].end_frame_number,
757
+ "message": "No valid frames selected due to prediction rules (e.g., quality, outside, snare).",
758
+ }
759
+ )
760
+ else:
761
+ segment_results.append(
762
+ {
763
+ "video_id": video_id,
764
+ "segment_start": segment["polyp"].start_frame_number,
765
+ "segment_end": segment["polyp"].end_frame_number,
766
+ "frames": frames,
767
+ }
768
+ )
769
+ all_frames.extend(frames)
770
+
771
+ if all_frames:
772
+ unique_frame_numbers = sorted(
773
+ {f["frame_number"] for f in all_frames}
774
+ )
775
+ self.extract_and_save_selected_frames(
776
+ video, unique_frame_numbers, classification_type="paris"
777
+ )
778
+
779
+ results.extend(segment_results)
780
+
781
+ except Exception as e:
782
+ results.append({"video_id": video.id, "error": str(e)})
783
+
784
+ if not results:
785
+ return [
786
+ {
787
+ "message": "No valid classification results could be generated for any video."
788
+ }
789
+ ]
790
+
791
+ return {"message": "PARIS classification data generated.", "data": results}
792
+
793
+
794
+ """
795
+ NICE Classification Serializer
796
+ ------------------------------
797
+
798
+ This serializer identifies clean polyp segments for NICE classification:
799
+ - Filters out segments overlapping with instruments
800
+ - Requires overlap with digital chromo or NBI
801
+ - Applies sequence diversity and selects clean frames
802
+
803
+ Configurable via:
804
+ - INSTRUMENT_LABEL_NAMES: defines what tools to exclude
805
+ - CHROMO_LABEL_NAMES: defines what chromo types to include
806
+
807
+ Returns:
808
+ {
809
+ "video_id": int,
810
+ "segment_start": int,
811
+ "segment_end": int,
812
+ "frames": [{ frame_number, frame_path }]
813
+ }
814
+ """
815
+
816
+
817
+ """
818
+ PARIS Classification Serializer
819
+ -------------------------------
820
+
821
+ This serializer identifies clean polyp segments for PARIS classification:
822
+ - Filters out segments that overlap with any instrument-type labels
823
+ - Also excludes any segments that overlap with digital chromo or NBI imaging
824
+ - Trims overlapping regions and returns only clean, usable subsegments
825
+ - Applies sequence diversity to avoid redundant or closely positioned segments
826
+ - Selects clean, representative frames from each remaining valid segment
827
+
828
+ Configurable via:
829
+ - INSTRUMENT_LABEL_NAMES: defines all instrument labels that must be excluded (e.g., 'instrument', 'snare', 'needle')
830
+ - CHROMO_LABEL_NAMES: defines chromo-like labels that should also be excluded (e.g., 'digital_chromo_endoscopy', 'nbi')
831
+
832
+ Returns:
833
+ {
834
+ "video_id": int,
835
+ "segment_start": int,
836
+ "segment_end": int,
837
+ "frames": [{ frame_number: int, frame_path: str }]
838
+ }
839
+ """
840
+
841
+
842
+ """
843
+ await import('https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js');
844
+ const fetchNiceClassification = async () => {
845
+ try {
846
+ const response = await axios.get("http://localhost:8000/videos/nice-classification/", {
847
+ headers: { "Accept": "application/json" }
848
+ });
849
+
850
+ console.log(" NICE Classification Response:", response.data);
851
+ alert("NICE Classification data fetched!");
852
+ return response.data;
853
+ } catch (error) {
854
+ console.error(" Error fetching NICE classification:", error.response?.data || error);
855
+ alert("Failed to fetch NICE classification data.");
856
+ return error.response?.data || { error: "Unknown error" };
857
+ }
858
+ };
859
+
860
+ fetchNiceClassification().then(data => console.log("Final Output:", data));
861
+ """