endoreg-db 0.6.0__py3-none-any.whl → 0.6.2__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 (416) hide show
  1. endoreg_db/case_generator/__init__.py +0 -0
  2. endoreg_db/case_generator/case_generator.py +159 -0
  3. endoreg_db/case_generator/lab_sample_factory.py +33 -0
  4. endoreg_db/case_generator/utils.py +30 -0
  5. endoreg_db/data/__init__.py +118 -0
  6. endoreg_db/data/agl_service/data.yaml +19 -0
  7. endoreg_db/data/ai_model/data.yaml +7 -0
  8. endoreg_db/data/ai_model_label/label/data.yaml +88 -0
  9. endoreg_db/data/ai_model_label/label-set/data.yaml +21 -0
  10. endoreg_db/data/ai_model_label/label-type/data.yaml +7 -0
  11. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +5 -0
  12. endoreg_db/data/ai_model_type/data.yaml +7 -0
  13. endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml +176 -0
  14. endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml +20 -0
  15. endoreg_db/data/case_template/rule/00_patient_lab_sample_add_default_value.yaml +167 -0
  16. endoreg_db/data/case_template/rule/01_patient-set-age.yaml +8 -0
  17. endoreg_db/data/case_template/rule/01_patient-set-gender.yaml +9 -0
  18. endoreg_db/data/case_template/rule/11_create_patient_lab_sample.yaml +23 -0
  19. endoreg_db/data/case_template/rule/12_create-patient_medication-anticoagulation.yaml +19 -0
  20. endoreg_db/data/case_template/rule/13_create-patient_medication_schedule-anticoagulation.yaml +19 -0
  21. endoreg_db/data/case_template/rule/19_create_patient.yaml +17 -0
  22. endoreg_db/data/case_template/rule_type/base_types.yaml +35 -0
  23. endoreg_db/data/case_template/rule_value/.init +0 -0
  24. endoreg_db/data/case_template/rule_value_type/base_types.yaml +59 -0
  25. endoreg_db/data/case_template/template/base.yaml +8 -0
  26. endoreg_db/data/case_template/template_type/pre_endoscopy.yaml +3 -0
  27. endoreg_db/data/case_template/tmp/_rule_value +13 -0
  28. endoreg_db/data/case_template/tmp/rule/01_atrial_fibrillation.yaml +21 -0
  29. endoreg_db/data/case_template/tmp/rule/02_create_object.yaml +10 -0
  30. endoreg_db/data/case_template/tmp/template/atrial_fibrillation_low_risk.yaml +7 -0
  31. endoreg_db/data/center/data.yaml +90 -0
  32. endoreg_db/data/center_resource/green_endoscopy_dashboard_CenterResource.yaml +144 -0
  33. endoreg_db/data/center_waste/green_endoscopy_dashboard_CenterWaste.yaml +48 -0
  34. endoreg_db/data/contraindication/bleeding.yaml +11 -0
  35. endoreg_db/data/disease/cardiovascular.yaml +37 -0
  36. endoreg_db/data/disease/hepatology.yaml +5 -0
  37. endoreg_db/data/disease/misc.yaml +6 -0
  38. endoreg_db/data/disease/renal.yaml +5 -0
  39. endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +6 -0
  40. endoreg_db/data/disease_classification/coronary_vessel_disease.yaml +6 -0
  41. endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +41 -0
  42. endoreg_db/data/disease_classification_choice/coronary_vessel_disease.yaml +20 -0
  43. endoreg_db/data/distribution/date/patient.yaml +7 -0
  44. endoreg_db/data/distribution/multiple_categorical/.init +0 -0
  45. endoreg_db/data/distribution/numeric/data.yaml +14 -0
  46. endoreg_db/data/distribution/single_categorical/patient.yaml +7 -0
  47. endoreg_db/data/emission_factor/green_endoscopy_dashboard_EmissionFactor.yaml +132 -0
  48. endoreg_db/data/endoscope/data.yaml +93 -0
  49. endoreg_db/data/endoscope_type/data.yaml +11 -0
  50. endoreg_db/data/endoscopy_processor/data.yaml +47 -0
  51. endoreg_db/data/event/cardiology.yaml +28 -0
  52. endoreg_db/data/event/neurology.yaml +14 -0
  53. endoreg_db/data/event/surgery.yaml +13 -0
  54. endoreg_db/data/event/thrombembolism.yaml +20 -0
  55. endoreg_db/data/examination/examinations/data.yaml +66 -0
  56. endoreg_db/data/examination/time/data.yaml +48 -0
  57. endoreg_db/data/examination/time-type/data.yaml +8 -0
  58. endoreg_db/data/examination/type/data.yaml +5 -0
  59. endoreg_db/data/examination_indication/endoscopy.yaml +8 -0
  60. endoreg_db/data/examination_indication_classification/endoscopy.yaml +8 -0
  61. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
  62. endoreg_db/data/finding/data.yaml +141 -0
  63. endoreg_db/data/finding_intervention/endoscopy.yaml +138 -0
  64. endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
  65. endoreg_db/data/finding_location_classification/colonoscopy.yaml +46 -0
  66. endoreg_db/data/finding_location_classification_choice/colonoscopy.yaml +240 -0
  67. endoreg_db/data/finding_morphology_classification/colonoscopy.yaml +48 -0
  68. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_circularity_default.yaml +34 -0
  69. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_nice.yaml +20 -0
  70. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_paris.yaml +65 -0
  71. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_planarity_default.yaml +56 -0
  72. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_surface_intact_default.yaml +39 -0
  73. endoreg_db/data/finding_morphology_classification_choice/colonoscopy_size.yaml +57 -0
  74. endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
  75. endoreg_db/data/finding_type/data.yaml +30 -0
  76. endoreg_db/data/gender/data.yaml +35 -0
  77. endoreg_db/data/information_source/data.yaml +30 -0
  78. endoreg_db/data/information_source/medication.yaml +6 -0
  79. endoreg_db/data/lab_value/cardiac_enzymes.yaml +37 -0
  80. endoreg_db/data/lab_value/coagulation.yaml +54 -0
  81. endoreg_db/data/lab_value/electrolytes.yaml +228 -0
  82. endoreg_db/data/lab_value/gastrointestinal_function.yaml +133 -0
  83. endoreg_db/data/lab_value/hematology.yaml +184 -0
  84. endoreg_db/data/lab_value/hormones.yaml +59 -0
  85. endoreg_db/data/lab_value/lipids.yaml +53 -0
  86. endoreg_db/data/lab_value/misc.yaml +33 -0
  87. endoreg_db/data/lab_value/renal_function.yaml +12 -0
  88. endoreg_db/data/log_type/data.yaml +57 -0
  89. endoreg_db/data/lx_client_tag/base.yaml +54 -0
  90. endoreg_db/data/lx_client_type/base.yaml +30 -0
  91. endoreg_db/data/lx_permission/base.yaml +24 -0
  92. endoreg_db/data/lx_permission/endoreg.yaml +52 -0
  93. endoreg_db/data/material/material.yaml +91 -0
  94. endoreg_db/data/medication/anticoagulation.yaml +65 -0
  95. endoreg_db/data/medication/tah.yaml +70 -0
  96. endoreg_db/data/medication_indication/anticoagulation.yaml +115 -0
  97. endoreg_db/data/medication_indication_type/data.yaml +11 -0
  98. endoreg_db/data/medication_indication_type/thrombembolism.yaml +41 -0
  99. endoreg_db/data/medication_intake_time/base.yaml +31 -0
  100. endoreg_db/data/medication_schedule/apixaban.yaml +95 -0
  101. endoreg_db/data/medication_schedule/ass.yaml +12 -0
  102. endoreg_db/data/medication_schedule/enoxaparin.yaml +26 -0
  103. endoreg_db/data/names_first/first_names.yaml +51 -0
  104. endoreg_db/data/names_last/last_names.yaml +51 -0
  105. endoreg_db/data/network_device/data.yaml +59 -0
  106. endoreg_db/data/network_device_type/data.yaml +12 -0
  107. endoreg_db/data/organ/data.yaml +29 -0
  108. endoreg_db/data/patient_lab_sample_type/generic.yaml +6 -0
  109. endoreg_db/data/pdf_type/data.yaml +29 -0
  110. endoreg_db/data/product/green_endoscopy_dashboard_Product.yaml +66 -0
  111. endoreg_db/data/product_group/green_endoscopy_dashboard_ProductGroup.yaml +33 -0
  112. endoreg_db/data/product_material/green_endoscopy_dashboard_ProductMaterial.yaml +308 -0
  113. endoreg_db/data/product_weight/green_endoscopy_dashboard_ProductWeight.yaml +88 -0
  114. endoreg_db/data/profession/data.yaml +70 -0
  115. endoreg_db/data/reference_product/green_endoscopy_dashboard_ReferenceProduct.yaml +55 -0
  116. endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +30 -0
  117. endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +19 -0
  118. endoreg_db/data/resource/green_endoscopy_dashboard_Resource.yaml +15 -0
  119. endoreg_db/data/tmp/chronic_kidney_disease.yaml +0 -0
  120. endoreg_db/data/tmp/congestive_heart_failure.yaml +0 -0
  121. endoreg_db/data/transport_route/green_endoscopy_dashboard_TransportRoute.yaml +12 -0
  122. endoreg_db/data/unit/concentration.yaml +92 -0
  123. endoreg_db/data/unit/data.yaml +17 -0
  124. endoreg_db/data/unit/length.yaml +31 -0
  125. endoreg_db/data/unit/misc.yaml +20 -0
  126. endoreg_db/data/unit/rate.yaml +6 -0
  127. endoreg_db/data/unit/time.yaml +13 -0
  128. endoreg_db/data/unit/volume.yaml +35 -0
  129. endoreg_db/data/unit/weight.yaml +38 -0
  130. endoreg_db/data/waste/data.yaml +12 -0
  131. endoreg_db/forms/__init__.py +5 -0
  132. endoreg_db/forms/examination_form.py +11 -0
  133. endoreg_db/forms/patient_finding_intervention_form.py +19 -0
  134. endoreg_db/forms/patient_form.py +26 -0
  135. endoreg_db/forms/questionnaires/__init__.py +1 -0
  136. endoreg_db/forms/questionnaires/tto_questionnaire.py +23 -0
  137. endoreg_db/forms/settings/__init__.py +8 -0
  138. endoreg_db/forms/unit.py +6 -0
  139. endoreg_db/management/__init__.py +0 -0
  140. endoreg_db/management/commands/__init__.py +0 -0
  141. endoreg_db/management/commands/_load_model_template.py +41 -0
  142. endoreg_db/management/commands/delete_all.py +18 -0
  143. endoreg_db/management/commands/fetch_legacy_image_dataset.py +32 -0
  144. endoreg_db/management/commands/fix_auth_permission.py +20 -0
  145. endoreg_db/management/commands/load_active_model_data.py +45 -0
  146. endoreg_db/management/commands/load_ai_model_data.py +79 -0
  147. endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
  148. endoreg_db/management/commands/load_base_db_data.py +178 -0
  149. endoreg_db/management/commands/load_center_data.py +43 -0
  150. endoreg_db/management/commands/load_contraindication_data.py +41 -0
  151. endoreg_db/management/commands/load_disease_classification_choices_data.py +41 -0
  152. endoreg_db/management/commands/load_disease_classification_data.py +41 -0
  153. endoreg_db/management/commands/load_disease_data.py +62 -0
  154. endoreg_db/management/commands/load_distribution_data.py +66 -0
  155. endoreg_db/management/commands/load_endoscope_data.py +68 -0
  156. endoreg_db/management/commands/load_event_data.py +41 -0
  157. endoreg_db/management/commands/load_examination_data.py +75 -0
  158. endoreg_db/management/commands/load_examination_indication_data.py +65 -0
  159. endoreg_db/management/commands/load_finding_data.py +171 -0
  160. endoreg_db/management/commands/load_g_play_data.py +113 -0
  161. endoreg_db/management/commands/load_gender_data.py +44 -0
  162. endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +133 -0
  163. endoreg_db/management/commands/load_information_source.py +45 -0
  164. endoreg_db/management/commands/load_lab_value_data.py +50 -0
  165. endoreg_db/management/commands/load_logging_data.py +39 -0
  166. endoreg_db/management/commands/load_lx_data.py +64 -0
  167. endoreg_db/management/commands/load_medication_data.py +103 -0
  168. endoreg_db/management/commands/load_medication_indication_data.py +63 -0
  169. endoreg_db/management/commands/load_medication_indication_type_data.py +41 -0
  170. endoreg_db/management/commands/load_medication_intake_time_data.py +41 -0
  171. endoreg_db/management/commands/load_medication_schedule_data.py +55 -0
  172. endoreg_db/management/commands/load_name_data.py +37 -0
  173. endoreg_db/management/commands/load_network_data.py +57 -0
  174. endoreg_db/management/commands/load_organ_data.py +43 -0
  175. endoreg_db/management/commands/load_pdf_type_data.py +61 -0
  176. endoreg_db/management/commands/load_profession_data.py +44 -0
  177. endoreg_db/management/commands/load_report_reader_flag_data.py +46 -0
  178. endoreg_db/management/commands/load_unit_data.py +46 -0
  179. endoreg_db/management/commands/load_user_groups.py +28 -0
  180. endoreg_db/management/commands/register_ai_model.py +64 -0
  181. endoreg_db/management/commands/reset_celery_schedule.py +9 -0
  182. endoreg_db/migrations/0001_initial.py +2045 -0
  183. endoreg_db/migrations/0002_alter_frame_image_alter_rawframe_image.py +23 -0
  184. endoreg_db/migrations/0003_alter_frame_image_alter_rawframe_image.py +23 -0
  185. endoreg_db/migrations/0004_alter_rawvideofile_file_alter_video_file.py +25 -0
  186. endoreg_db/migrations/0005_rawvideofile_frame_count_and_more.py +33 -0
  187. endoreg_db/migrations/0006_frame_extracted_rawframe_extracted.py +23 -0
  188. endoreg_db/migrations/0007_rename_pseudo_patient_video_patient_and_more.py +24 -0
  189. endoreg_db/migrations/0008_remove_reportfile_patient_examination_and_more.py +48 -0
  190. endoreg_db/migrations/__init__.py +0 -0
  191. endoreg_db/models/__init__.py +376 -0
  192. endoreg_db/models/ai_model/__init__.py +4 -0
  193. endoreg_db/models/ai_model/active_model.py +9 -0
  194. endoreg_db/models/ai_model/ai_model.py +103 -0
  195. endoreg_db/models/ai_model/lightning/__init__.py +3 -0
  196. endoreg_db/models/ai_model/lightning/inference_dataset.py +53 -0
  197. endoreg_db/models/ai_model/lightning/multilabel_classification_net.py +155 -0
  198. endoreg_db/models/ai_model/lightning/postprocess.py +53 -0
  199. endoreg_db/models/ai_model/lightning/predict.py +172 -0
  200. endoreg_db/models/ai_model/lightning/prediction_visualizer.py +55 -0
  201. endoreg_db/models/ai_model/lightning/preprocess.py +68 -0
  202. endoreg_db/models/ai_model/lightning/run_visualizer.py +21 -0
  203. endoreg_db/models/ai_model/model_meta.py +250 -0
  204. endoreg_db/models/ai_model/model_type.py +36 -0
  205. endoreg_db/models/ai_model/utils.py +8 -0
  206. endoreg_db/models/annotation/__init__.py +32 -0
  207. endoreg_db/models/annotation/anonymized_image_annotation.py +115 -0
  208. endoreg_db/models/annotation/binary_classification_annotation_task.py +117 -0
  209. endoreg_db/models/annotation/image_classification.py +86 -0
  210. endoreg_db/models/annotation/video_segmentation_annotation.py +52 -0
  211. endoreg_db/models/annotation/video_segmentation_labelset.py +20 -0
  212. endoreg_db/models/case/__init__.py +1 -0
  213. endoreg_db/models/case/case.py +34 -0
  214. endoreg_db/models/case_template/__init__.py +15 -0
  215. endoreg_db/models/case_template/case_template.py +125 -0
  216. endoreg_db/models/case_template/case_template_rule.py +276 -0
  217. endoreg_db/models/case_template/case_template_rule_value.py +88 -0
  218. endoreg_db/models/case_template/case_template_type.py +28 -0
  219. endoreg_db/models/center/__init__.py +11 -0
  220. endoreg_db/models/center/center.py +51 -0
  221. endoreg_db/models/center/center_product.py +33 -0
  222. endoreg_db/models/center/center_resource.py +33 -0
  223. endoreg_db/models/center/center_waste.py +16 -0
  224. endoreg_db/models/contraindication/__init__.py +21 -0
  225. endoreg_db/models/data_file/__init__.py +39 -0
  226. endoreg_db/models/data_file/base_classes/__init__.py +7 -0
  227. endoreg_db/models/data_file/base_classes/abstract_frame.py +100 -0
  228. endoreg_db/models/data_file/base_classes/abstract_pdf.py +136 -0
  229. endoreg_db/models/data_file/base_classes/abstract_video.py +807 -0
  230. endoreg_db/models/data_file/base_classes/frame_helpers.py +17 -0
  231. endoreg_db/models/data_file/base_classes/prepare_bulk_frames.py +19 -0
  232. endoreg_db/models/data_file/base_classes/utils.py +80 -0
  233. endoreg_db/models/data_file/frame.py +29 -0
  234. endoreg_db/models/data_file/import_classes/__init__.py +18 -0
  235. endoreg_db/models/data_file/import_classes/processing_functions/__init__.py +35 -0
  236. endoreg_db/models/data_file/import_classes/processing_functions/pdf.py +28 -0
  237. endoreg_db/models/data_file/import_classes/processing_functions/video.py +260 -0
  238. endoreg_db/models/data_file/import_classes/raw_pdf.py +260 -0
  239. endoreg_db/models/data_file/import_classes/raw_video.py +288 -0
  240. endoreg_db/models/data_file/metadata/__init__.py +13 -0
  241. endoreg_db/models/data_file/metadata/pdf_meta.py +74 -0
  242. endoreg_db/models/data_file/metadata/sensitive_meta.py +290 -0
  243. endoreg_db/models/data_file/metadata/video_meta.py +199 -0
  244. endoreg_db/models/data_file/report_file.py +56 -0
  245. endoreg_db/models/data_file/video/__init__.py +11 -0
  246. endoreg_db/models/data_file/video/import_meta.py +25 -0
  247. endoreg_db/models/data_file/video/video.py +196 -0
  248. endoreg_db/models/data_file/video_segment.py +214 -0
  249. endoreg_db/models/disease.py +79 -0
  250. endoreg_db/models/emission/__init__.py +5 -0
  251. endoreg_db/models/emission/emission_factor.py +85 -0
  252. endoreg_db/models/event.py +73 -0
  253. endoreg_db/models/examination/__init__.py +9 -0
  254. endoreg_db/models/examination/examination.py +67 -0
  255. endoreg_db/models/examination/examination_indication.py +170 -0
  256. endoreg_db/models/examination/examination_time.py +53 -0
  257. endoreg_db/models/examination/examination_time_type.py +48 -0
  258. endoreg_db/models/examination/examination_type.py +40 -0
  259. endoreg_db/models/finding/__init__.py +11 -0
  260. endoreg_db/models/finding/finding.py +75 -0
  261. endoreg_db/models/finding/finding_intervention.py +60 -0
  262. endoreg_db/models/finding/finding_location_classification.py +94 -0
  263. endoreg_db/models/finding/finding_morphology_classification.py +89 -0
  264. endoreg_db/models/finding/finding_type.py +22 -0
  265. endoreg_db/models/hardware/__init__.py +2 -0
  266. endoreg_db/models/hardware/endoscope.py +60 -0
  267. endoreg_db/models/hardware/endoscopy_processor.py +155 -0
  268. endoreg_db/models/information_source.py +29 -0
  269. endoreg_db/models/label/__init__.py +1 -0
  270. endoreg_db/models/label/label.py +112 -0
  271. endoreg_db/models/laboratory/__init__.py +1 -0
  272. endoreg_db/models/laboratory/lab_value.py +111 -0
  273. endoreg_db/models/logging/__init__.py +11 -0
  274. endoreg_db/models/logging/agl_service.py +19 -0
  275. endoreg_db/models/logging/base.py +22 -0
  276. endoreg_db/models/logging/log_type.py +23 -0
  277. endoreg_db/models/logging/network_device.py +27 -0
  278. endoreg_db/models/lx/__init__.py +4 -0
  279. endoreg_db/models/lx/client.py +57 -0
  280. endoreg_db/models/lx/identity.py +34 -0
  281. endoreg_db/models/lx/permission.py +18 -0
  282. endoreg_db/models/lx/user.py +16 -0
  283. endoreg_db/models/medication/__init__.py +19 -0
  284. endoreg_db/models/medication/medication.py +33 -0
  285. endoreg_db/models/medication/medication_indication.py +50 -0
  286. endoreg_db/models/medication/medication_indication_type.py +34 -0
  287. endoreg_db/models/medication/medication_intake_time.py +26 -0
  288. endoreg_db/models/medication/medication_schedule.py +37 -0
  289. endoreg_db/models/network/__init__.py +9 -0
  290. endoreg_db/models/network/agl_service.py +38 -0
  291. endoreg_db/models/network/network_device.py +58 -0
  292. endoreg_db/models/network/network_device_type.py +23 -0
  293. endoreg_db/models/organ/__init__.py +38 -0
  294. endoreg_db/models/other/__init__.py +23 -0
  295. endoreg_db/models/other/distribution/__init__.py +44 -0
  296. endoreg_db/models/other/distribution/base_value_distribution.py +20 -0
  297. endoreg_db/models/other/distribution/date_value_distribution.py +91 -0
  298. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
  299. endoreg_db/models/other/distribution/numeric_value_distribution.py +97 -0
  300. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
  301. endoreg_db/models/other/distribution.py +5 -0
  302. endoreg_db/models/other/material.py +20 -0
  303. endoreg_db/models/other/resource.py +18 -0
  304. endoreg_db/models/other/transport_route.py +22 -0
  305. endoreg_db/models/other/waste.py +20 -0
  306. endoreg_db/models/patient/__init__.py +24 -0
  307. endoreg_db/models/patient/patient_examination.py +182 -0
  308. endoreg_db/models/patient/patient_finding.py +143 -0
  309. endoreg_db/models/patient/patient_finding_intervention.py +26 -0
  310. endoreg_db/models/patient/patient_finding_location.py +120 -0
  311. endoreg_db/models/patient/patient_finding_morphology.py +166 -0
  312. endoreg_db/models/permissions/__init__.py +44 -0
  313. endoreg_db/models/persons/__init__.py +34 -0
  314. endoreg_db/models/persons/examiner/__init__.py +2 -0
  315. endoreg_db/models/persons/examiner/examiner.py +60 -0
  316. endoreg_db/models/persons/examiner/examiner_type.py +2 -0
  317. endoreg_db/models/persons/first_name.py +18 -0
  318. endoreg_db/models/persons/gender.py +22 -0
  319. endoreg_db/models/persons/last_name.py +20 -0
  320. endoreg_db/models/persons/patient/__init__.py +8 -0
  321. endoreg_db/models/persons/patient/patient.py +389 -0
  322. endoreg_db/models/persons/patient/patient_disease.py +22 -0
  323. endoreg_db/models/persons/patient/patient_event.py +52 -0
  324. endoreg_db/models/persons/patient/patient_examination_indication.py +32 -0
  325. endoreg_db/models/persons/patient/patient_lab_sample.py +108 -0
  326. endoreg_db/models/persons/patient/patient_lab_value.py +197 -0
  327. endoreg_db/models/persons/patient/patient_medication.py +59 -0
  328. endoreg_db/models/persons/patient/patient_medication_schedule.py +88 -0
  329. endoreg_db/models/persons/person.py +31 -0
  330. endoreg_db/models/persons/portal_user_information.py +27 -0
  331. endoreg_db/models/prediction/__init__.py +8 -0
  332. endoreg_db/models/prediction/image_classification.py +51 -0
  333. endoreg_db/models/prediction/video_prediction_meta.py +306 -0
  334. endoreg_db/models/product/__init__.py +14 -0
  335. endoreg_db/models/product/product.py +110 -0
  336. endoreg_db/models/product/product_group.py +27 -0
  337. endoreg_db/models/product/product_material.py +28 -0
  338. endoreg_db/models/product/product_weight.py +38 -0
  339. endoreg_db/models/product/reference_product.py +115 -0
  340. endoreg_db/models/questionnaires/__init__.py +114 -0
  341. endoreg_db/models/quiz/__init__.py +9 -0
  342. endoreg_db/models/quiz/quiz_answer.py +41 -0
  343. endoreg_db/models/quiz/quiz_question.py +54 -0
  344. endoreg_db/models/report_reader/__init__.py +7 -0
  345. endoreg_db/models/report_reader/report_reader_config.py +53 -0
  346. endoreg_db/models/report_reader/report_reader_flag.py +20 -0
  347. endoreg_db/models/rules/__init__.py +5 -0
  348. endoreg_db/models/rules/rule.py +24 -0
  349. endoreg_db/models/rules/rule_applicator.py +224 -0
  350. endoreg_db/models/rules/rule_attribute_dtype.py +19 -0
  351. endoreg_db/models/rules/rule_type.py +22 -0
  352. endoreg_db/models/rules/ruleset.py +19 -0
  353. endoreg_db/models/unit.py +22 -0
  354. endoreg_db/queries/__init__.py +5 -0
  355. endoreg_db/queries/annotations/__init__.py +3 -0
  356. endoreg_db/queries/annotations/legacy.py +158 -0
  357. endoreg_db/queries/get/__init__.py +6 -0
  358. endoreg_db/queries/get/annotation.py +0 -0
  359. endoreg_db/queries/get/center.py +42 -0
  360. endoreg_db/queries/get/model.py +13 -0
  361. endoreg_db/queries/get/patient.py +14 -0
  362. endoreg_db/queries/get/patient_examination.py +20 -0
  363. endoreg_db/queries/get/prediction.py +0 -0
  364. endoreg_db/queries/get/report_file.py +33 -0
  365. endoreg_db/queries/get/video.py +31 -0
  366. endoreg_db/queries/get/video_import_meta.py +0 -0
  367. endoreg_db/queries/get/video_prediction_meta.py +0 -0
  368. endoreg_db/queries/sanity/__init_.py +0 -0
  369. endoreg_db/serializers/__init__.py +10 -0
  370. endoreg_db/serializers/ai_model.py +19 -0
  371. endoreg_db/serializers/annotation.py +14 -0
  372. endoreg_db/serializers/center.py +11 -0
  373. endoreg_db/serializers/examination.py +33 -0
  374. endoreg_db/serializers/frame.py +9 -0
  375. endoreg_db/serializers/hardware.py +21 -0
  376. endoreg_db/serializers/label.py +22 -0
  377. endoreg_db/serializers/patient.py +33 -0
  378. endoreg_db/serializers/prediction.py +10 -0
  379. endoreg_db/serializers/raw_video_meta_validation.py +13 -0
  380. endoreg_db/serializers/report_file.py +7 -0
  381. endoreg_db/serializers/video.py +20 -0
  382. endoreg_db/serializers/video_segmentation.py +492 -0
  383. endoreg_db/templates/admin/patient_finding_intervention.html +253 -0
  384. endoreg_db/templates/admin/start_examination.html +12 -0
  385. endoreg_db/templates/timeline.html +176 -0
  386. endoreg_db/utils/__init__.py +36 -0
  387. endoreg_db/utils/cropping.py +29 -0
  388. endoreg_db/utils/dataloader.py +118 -0
  389. endoreg_db/utils/dates.py +39 -0
  390. endoreg_db/utils/file_operations.py +30 -0
  391. endoreg_db/utils/hashs.py +152 -0
  392. endoreg_db/utils/legacy_ocr.py +201 -0
  393. endoreg_db/utils/names.py +74 -0
  394. endoreg_db/utils/ocr.py +190 -0
  395. endoreg_db/utils/parse_and_generate_yaml.py +46 -0
  396. endoreg_db/utils/pydantic_models/__init__.py +6 -0
  397. endoreg_db/utils/pydantic_models/db_config.py +57 -0
  398. endoreg_db/utils/uuid.py +4 -0
  399. endoreg_db/utils/validate_endo_roi.py +19 -0
  400. endoreg_db/utils/validate_subcategory_dict.py +91 -0
  401. endoreg_db/utils/video/__init__.py +13 -0
  402. endoreg_db/utils/video/extract_frames.py +121 -0
  403. endoreg_db/utils/video/transcode_videofile.py +111 -0
  404. endoreg_db/views/__init__.py +2 -0
  405. endoreg_db/views/csrf.py +7 -0
  406. endoreg_db/views/patient_views.py +90 -0
  407. endoreg_db/views/raw_video_meta_validation_views.py +38 -0
  408. endoreg_db/views/report_views.py +96 -0
  409. endoreg_db/views/video_segmentation_views.py +149 -0
  410. endoreg_db/views/views_for_timeline.py +46 -0
  411. {endoreg_db-0.6.0.dist-info → endoreg_db-0.6.2.dist-info}/METADATA +14 -4
  412. endoreg_db-0.6.2.dist-info/RECORD +420 -0
  413. {endoreg_db-0.6.0.dist-info → endoreg_db-0.6.2.dist-info}/WHEEL +1 -2
  414. endoreg_db-0.6.0.dist-info/RECORD +0 -11
  415. endoreg_db-0.6.0.dist-info/top_level.txt +0 -1
  416. {endoreg_db-0.6.0.dist-info → endoreg_db-0.6.2.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,250 @@
1
+ """
2
+ This module defines the ModelMeta and ModelMetaManager classes for managing AI model metadata.
3
+ """
4
+
5
+ import os
6
+ from pathlib import Path
7
+ from typing import Optional, TYPE_CHECKING
8
+ import shutil
9
+
10
+ from django.db import models
11
+ from django.core.validators import FileExtensionValidator
12
+ from icecream import ic
13
+
14
+ if TYPE_CHECKING:
15
+ from endoreg_db.models import LabelSet, AiModel # pylint: disable=import-outside-toplevel
16
+
17
+ PSEUDO_DIR = Path(os.environ.get("DJANGO_PSEUDO_DIR", Path("./erc_data")))
18
+
19
+ STORAGE_LOCATION = PSEUDO_DIR
20
+ WEIGHTS_DIR_NAME = "db_model_weights"
21
+ WEIGHTS_DIR = STORAGE_LOCATION / WEIGHTS_DIR_NAME
22
+
23
+ if not WEIGHTS_DIR.exists():
24
+ WEIGHTS_DIR.mkdir(parents=True)
25
+
26
+
27
+ class ModelMetaManager(models.Manager):
28
+ """
29
+ Custom manager for ModelMeta with additional query methods.
30
+ """
31
+
32
+ def get_by_natural_key(self, name: str, version: str) -> "ModelMeta":
33
+ """Get the model by its natural key"""
34
+ return self.get(name=name, version=version)
35
+
36
+
37
+ class ModelMeta(models.Model):
38
+ """
39
+ Attributes:
40
+ name (str): The name of the model.
41
+ version (str): The version of the model.
42
+ type (ModelType): The type of the model.
43
+ labelset (LabelSet): Associated labels.
44
+ weights (FileField): Path to the model weights.
45
+ """
46
+
47
+ name = models.CharField(max_length=255)
48
+ version = models.CharField(max_length=255)
49
+
50
+ model = models.ForeignKey(
51
+ "AiModel", on_delete=models.CASCADE, related_name="models"
52
+ )
53
+
54
+ labelset = models.ForeignKey(
55
+ "LabelSet", on_delete=models.CASCADE, related_name="models"
56
+ )
57
+ activation = models.CharField(max_length=255, default="sigmoid")
58
+
59
+ weights = models.FileField(
60
+ upload_to=WEIGHTS_DIR_NAME,
61
+ validators=[FileExtensionValidator(allowed_extensions=["ckpt"])],
62
+ # storage=FileSystemStorage(location=STORAGE_LOCATION.resolve().as_posix()),
63
+ null=True,
64
+ blank=True,
65
+ )
66
+
67
+ # Means and stds for normalization
68
+ mean = models.CharField(max_length=255, default="0.45211223,0.27139644,0.19264949")
69
+ std = models.CharField(max_length=255, default="0.31418097,0.21088019,0.16059452")
70
+
71
+ size_x = models.IntegerField(default=716)
72
+ size_y = models.IntegerField(default=716)
73
+ axes = models.CharField(max_length=255, default="2,0,1")
74
+ batchsize = models.IntegerField(default=16)
75
+ num_workers = models.IntegerField(default=0)
76
+
77
+ description = models.TextField(blank=True, null=True)
78
+ date_created = models.DateTimeField(auto_now_add=True)
79
+
80
+ objects = ModelMetaManager()
81
+
82
+ if TYPE_CHECKING:
83
+ labelset: "LabelSet"
84
+ ai_model: "AiModel"
85
+
86
+ @classmethod
87
+ def create_from_file(
88
+ cls,
89
+ meta_name,
90
+ model_name,
91
+ model_meta_version,
92
+ labelset_name,
93
+ weights_file,
94
+ bump_version,
95
+ **kwargs,
96
+ ):
97
+ """Create a new model meta from a file"""
98
+
99
+ from endoreg_db.models import LabelSet, AiModel # pylint: disable=import-outside-toplevel
100
+
101
+ ic("Start")
102
+ model_meta_version = kwargs.get("model_meta_version", None)
103
+
104
+ ai_model = AiModel.objects.get(name=model_name)
105
+
106
+ # check If ModelMeta with same name and model already exists
107
+ if not model_meta_version:
108
+ if cls.objects.filter(name=meta_name, model=ai_model).exists():
109
+ # get highest version number
110
+ highest_version = (
111
+ cls.objects.filter(name=meta_name, model=ai_model)
112
+ .latest("version")
113
+ .version
114
+ )
115
+ version = int(highest_version) + 1
116
+ else:
117
+ version = 1
118
+ else:
119
+ version = model_meta_version
120
+
121
+ meta_exists = cls.objects.filter(
122
+ name=meta_name, model=ai_model, version=version
123
+ ).exists()
124
+ if meta_exists and not bump_version:
125
+ raise ValueError(
126
+ f"ModelMeta with name {meta_name} and version {version} already exists"
127
+ )
128
+
129
+ assert labelset_name is not None, "Labelset name must be provided"
130
+ labelset = LabelSet.objects.get(name=labelset_name)
131
+ assert labelset is not None, "Labelset not found"
132
+
133
+ weights_path = Path(weights_file)
134
+ # If not under our WEIGHTS_DIR, copy it there
135
+ if not str(weights_path).startswith(str(WEIGHTS_DIR)):
136
+ target_path = WEIGHTS_DIR / weights_path.name
137
+ if not target_path.exists():
138
+ shutil.copy(weights_path, target_path)
139
+ weights_file = target_path
140
+
141
+ return cls.objects.create(
142
+ name=meta_name,
143
+ model=ai_model,
144
+ version=version,
145
+ labelset=labelset,
146
+ weights=str(weights_file),
147
+ **kwargs,
148
+ )
149
+
150
+ @classmethod
151
+ def get_latest_version(cls, name) -> int:
152
+ """
153
+ get the model meta with the highest version. Assumes Model Name and Meta Name are the same
154
+ """
155
+ from endoreg_db.models import AiModel # pylint: disable=import-outside-toplevel
156
+
157
+ ai_model = AiModel.objects.get(name=name)
158
+ ic(f"Model: {ai_model}")
159
+ assert ai_model is not None, "Model not found"
160
+
161
+ model_meta = cls.objects.filter(name=name, model=ai_model).latest("version")
162
+ ic(f"Latest ModelMeta: {model_meta}")
163
+
164
+ latest_version = model_meta.version
165
+ ic(f"Latest Version: {latest_version}")
166
+
167
+ return int(latest_version)
168
+
169
+ @classmethod
170
+ def get_activation_function(cls, activation: str):
171
+ """get the activation function"""
172
+ from torch import nn # pylint: disable=import-outside-toplevel
173
+
174
+ lookup = {
175
+ "sigmoid": nn.Sigmoid(),
176
+ "softmax": nn.Softmax(),
177
+ "none": nn.Identity(),
178
+ }
179
+
180
+ return lookup[activation]
181
+
182
+ def get_inference_dataset_config(self):
183
+ """
184
+ Creates a dictionary with the configuration for the inference dataset.
185
+
186
+ Example:
187
+ sample_config = {
188
+ # mean and std for normalization
189
+ "mean": (0.45211223, 0.27139644, 0.19264949),
190
+ "std": (0.31418097, 0.21088019, 0.16059452),
191
+ # Image Size
192
+ "size_x": 716,
193
+ "size_y": 716,
194
+ # how to wrangle axes of the image before putting them in the network
195
+ "axes": [2,0,1], # 2,1,0 for opencv
196
+ "batchsize": 16,
197
+ "num_workers": 0, # always 1 for Windows systems # FIXME: fix celery crash if multiprocessing
198
+ # maybe add sigmoid after prediction?
199
+ "activation": nn.Sigmoid(),
200
+ "labels": ['appendix', 'blood', 'diverticule', 'grasper', 'ileocaecalvalve', 'ileum', 'low_quality', 'nbi', 'needle', 'outside', 'polyp', 'snare', 'water_jet', 'wound']
201
+ }
202
+ """
203
+ mean = list(map(float, str(self.mean).split(",")))
204
+ std = list(map(float, str(self.std).split(",")))
205
+ axes = list(map(int, str(self.axes).split(",")))
206
+
207
+ config = {
208
+ "mean": mean,
209
+ "std": std,
210
+ "size_x": self.size_x,
211
+ "size_y": self.size_y,
212
+ "axes": axes,
213
+ "batchsize": self.batchsize,
214
+ "num_workers": self.num_workers,
215
+ "activation": self.get_activation_function(self.activation),
216
+ "labels": self.labelset.get_labels_in_order(), # pylint: disable=no-member
217
+ }
218
+
219
+ ic(f"ModelMeta - get_inference_dataset_config: {config}")
220
+
221
+ return config
222
+
223
+ def natural_key(self):
224
+ """Return the natural key for this model"""
225
+ return (self.name, self.version)
226
+
227
+ def __str__(self):
228
+ return f"{self.name} (v: {self.version})"
229
+
230
+ def get_config_dict(self) -> dict:
231
+ """Return the configuration as a dictionary"""
232
+ conf_dict = {
233
+ "mean": list(map(float, str(self.mean).split(","))),
234
+ "std": list(map(float, str(self.std).split(","))),
235
+ "size_x": self.size_x,
236
+ "size_y": self.size_y,
237
+ "axes": list(map(int, str(self.axes).split(","))),
238
+ "batchsize": self.batchsize,
239
+ "num_workers": self.num_workers,
240
+ "activation": self.activation,
241
+ "labels": self.labelset.get_labels_in_order(), # pylint: disable=no-member
242
+ }
243
+ return conf_dict
244
+
245
+ @classmethod
246
+ def get_by_name(cls, name: str, version: Optional[int]) -> "ModelMeta":
247
+ """Get the model by its name and version"""
248
+ if version is None:
249
+ version = cls.get_latest_version(name)
250
+ return cls.objects.get(name=name, version=version)
@@ -0,0 +1,36 @@
1
+ from django.db import models
2
+ from django.core import serializers
3
+
4
+
5
+ class ModelTypeManager(models.Manager):
6
+ """
7
+ Custom manager for ModelType with additional query methods.
8
+ """
9
+
10
+ def get_by_natural_key(self, name: str) -> "ModelType":
11
+ """Get the model type by its natural key"""
12
+ return self.get(name=name)
13
+
14
+
15
+ class ModelType(models.Model):
16
+ """
17
+ A class representing a model type.
18
+
19
+ Attributes:
20
+ name (str): The name of the model type.
21
+ description (str): A description of the model type.
22
+
23
+ """
24
+
25
+ name = models.CharField(max_length=255)
26
+ description = models.TextField(blank=True, null=True)
27
+
28
+ objects = ModelTypeManager()
29
+
30
+ def natural_key(self):
31
+ """Return the natural key for this model type"""
32
+ return (self.name,)
33
+
34
+ def __str__(self):
35
+ """Return the name of the model type"""
36
+ return str(self.name)
@@ -0,0 +1,8 @@
1
+ from .model_meta import ModelMeta
2
+
3
+ # get latest model meta by model name
4
+
5
+ # TODO MOVE THIS TO A QUERY FILE
6
+ def get_latest_model_meta_by_model_name(model_name):
7
+ model_meta = ModelMeta.objects.filter(name=model_name).order_by('-version').first()
8
+ return model_meta
@@ -0,0 +1,32 @@
1
+ """Module for annotation models"""
2
+
3
+ from .image_classification import ImageClassificationAnnotation
4
+ from .binary_classification_annotation_task import (
5
+ BinaryClassificationAnnotationTask,
6
+ )
7
+ from .anonymized_image_annotation import (
8
+ AnonymousImageAnnotation,
9
+ DroppedName,
10
+ AnonymizedImageLabel,
11
+ AnonymizedFile,
12
+ UploadedFile,
13
+ )
14
+ from .video_segmentation_annotation import (
15
+ VideoSegmentationLabel,
16
+ VideoSegmentationAnnotation,
17
+ )
18
+
19
+ from .video_segmentation_labelset import VideoSegmentationLabelSet
20
+
21
+ __all__ = [
22
+ "ImageClassificationAnnotation",
23
+ "BinaryClassificationAnnotationTask",
24
+ "AnonymousImageAnnotation",
25
+ "DroppedName",
26
+ "AnonymizedImageLabel",
27
+ "AnonymizedFile",
28
+ "UploadedFile",
29
+ "VideoSegmentationLabel",
30
+ "VideoSegmentationLabelSet",
31
+ "VideoSegmentationAnnotation",
32
+ ]
@@ -0,0 +1,115 @@
1
+ from django.db import models
2
+ from django.utils.text import slugify
3
+ from django.utils import timezone
4
+
5
+ class AnonymizedImageLabel(models.Model):
6
+ """
7
+ Represents a label for anonymized image annotations.
8
+
9
+ Attributes:
10
+ name (str): Unique name of the label.
11
+ description (str): Optional description for the label.
12
+ """
13
+ name = models.CharField(max_length=255, unique=True)
14
+ description = models.TextField(blank=True, null=True)
15
+
16
+ def __str__(self) -> str:
17
+ return self.name
18
+
19
+
20
+ class AnonymousImageAnnotation(models.Model):
21
+ """
22
+ Represents an annotation for anonymized images.
23
+
24
+ Attributes:
25
+ label (ForeignKey): Associated label for the image.
26
+ image_name (str): Name of the image file.
27
+ original_image_url (str): URL of the original image.
28
+ slug (str): Unique identifier for the annotation.
29
+ polyp_count (int): Number of polyps identified in the image.
30
+ comments (str): Additional comments about the annotation.
31
+ gender (str): Gender associated with the annotation (if applicable).
32
+ name_image_url (str): URL of the name image.
33
+ date_created (datetime): Date when the annotation was created.
34
+ processed (bool): Indicates if the annotation has been processed.
35
+ """
36
+ label = models.ForeignKey(AnonymizedImageLabel, on_delete=models.CASCADE)
37
+ image_name = models.CharField(max_length=255)
38
+ original_image_url = models.CharField(max_length=255, default='https://example.com/placeholder.jpg')
39
+ slug = models.SlugField(unique=True, blank=True, null=True)
40
+ polyp_count = models.IntegerField()
41
+ comments = models.TextField(blank=True, null=True)
42
+ gender = models.CharField(max_length=255)
43
+ name_image_url = models.CharField(max_length=255)
44
+ date_created = models.DateTimeField(auto_now_add=True)
45
+ processed = models.BooleanField(default=False)
46
+
47
+ def save(self, *args, **kwargs):
48
+ """
49
+ Overrides the save method to generate a slug if not already set.
50
+ """
51
+ if not self.slug:
52
+ self.slug = slugify(f"{self.label}-{self.image_name}")
53
+ super().save(*args, **kwargs)
54
+
55
+ def __str__(self) -> str:
56
+ return f"{self.image_name} - {self.label}"
57
+
58
+
59
+ class DroppedName(models.Model):
60
+ """
61
+ Represents a dropped name in the annotation process.
62
+
63
+ Attributes:
64
+ annotation (ForeignKey): Associated annotation.
65
+ name (str): Dropped name.
66
+ gender (str): Gender associated with the name.
67
+ x (float): X-coordinate of the name.
68
+ y (float): Y-coordinate of the name.
69
+ name_image_url (str): URL of the name image.
70
+ box_coordinates (str): Optional coordinates of the bounding box.
71
+ """
72
+ annotation = models.ForeignKey(AnonymousImageAnnotation, related_name='dropped_names', on_delete=models.CASCADE)
73
+ name = models.CharField(max_length=255)
74
+ gender = models.CharField(max_length=255)
75
+ x = models.FloatField()
76
+ y = models.FloatField()
77
+ name_image_url = models.CharField(max_length=255)
78
+ box_coordinates = models.CharField(max_length=255, blank=True, null=True)
79
+
80
+ def __str__(self) -> str:
81
+ return f"{self.name} ({self.gender}) at ({self.x}, {self.y})"
82
+
83
+
84
+ class UploadedFile(models.Model):
85
+ """
86
+ Represents a file uploaded to the system.
87
+
88
+ Attributes:
89
+ original_file (FileField): The uploaded original file.
90
+ upload_date (datetime): Date when the file was uploaded.
91
+ description (str): Optional description of the file.
92
+ """
93
+ original_file = models.FileField(upload_to='uploads/original/')
94
+ upload_date = models.DateTimeField(default=timezone.now)
95
+ description = models.TextField(blank=True, null=True)
96
+
97
+ def __str__(self) -> str:
98
+ return self.original_file.name
99
+
100
+
101
+ class AnonymizedFile(models.Model):
102
+ """
103
+ Represents an anonymized version of an uploaded file.
104
+
105
+ Attributes:
106
+ original_file (OneToOneField): The original uploaded file.
107
+ anonymized_file (FileField): The anonymized file.
108
+ anonymization_date (datetime): Date when the file was anonymized.
109
+ """
110
+ original_file = models.OneToOneField(UploadedFile, on_delete=models.CASCADE, related_name='anonymized_file')
111
+ anonymized_file = models.FileField(upload_to='uploads/anonymized/')
112
+ anonymization_date = models.DateTimeField(default=timezone.now)
113
+
114
+ def __str__(self) -> str:
115
+ return f"Anonymized version of {self.original_file.original_file.name}"
@@ -0,0 +1,117 @@
1
+ from django.db import models
2
+ # from rest_framework import serializers
3
+ # from ..label import Label
4
+ # from .image_classification import ImageClassificationAnnotation
5
+
6
+ ANNOTATION_PER_S_THRESHOLD = 2
7
+
8
+ # TODO Migrate
9
+ # def clear_finished_legacy_tasks():
10
+ # """
11
+ # Deletes all finished LegacyBinaryClassificationAnnotationTask entries.
12
+ # """
13
+ # tasks = LegacyBinaryClassificationAnnotationTask.objects.filter(is_finished=True)
14
+ # tasks.delete()
15
+
16
+ # def get_legacy_binary_classification_annotation_tasks_by_label(label:Label, n:int=100, legacy=False):
17
+ # clear_finished_legacy_tasks()
18
+ # """
19
+ # Retrieves legacy binary classification annotation tasks for a specific label.
20
+
21
+ # Args:
22
+ # label (Label): The label to filter tasks by.
23
+ # n (int): Maximum number of tasks to retrieve. Defaults to 100.
24
+ # legacy (bool): If True, includes legacy tasks. Defaults to False.
25
+ # """
26
+ # if legacy:
27
+ # # fetch all LegacyLabelVideoSegments with the given label
28
+ # _segments = LegacyLabelVideoSegment.objects.filter(label=label)
29
+ # frames_for_tasks = []
30
+
31
+ # for segment in _segments:
32
+ # # check if the segment has already been annotated
33
+ # annotations = list(ImageClassificationAnnotation.objects.filter(legacy_frame__in=segment.get_frames(), label=label))
34
+ # segment_len_in_s = segment.get_segment_len_in_s()
35
+
36
+ # target_annotation_number = segment_len_in_s * ANNOTATION_PER_S_THRESHOLD
37
+
38
+ # if len(annotations) < target_annotation_number:
39
+ # get_frame_number = int(target_annotation_number - len(annotations))
40
+ # frames = segment.get_frames_without_annotation(get_frame_number)
41
+ # frames_for_tasks.extend(frames)
42
+
43
+ # if len(frames_for_tasks) >= n:
44
+ # break
45
+
46
+ # # create tasks
47
+ # tasks = []
48
+ # for frame in frames_for_tasks:
49
+
50
+ # # get_or_create task
51
+ # task, created = LegacyBinaryClassificationAnnotationTask.objects.get_or_create(
52
+ # label=label,
53
+ # image_path=frame.image.path,
54
+ # frame_id=frame.pk,
55
+ # )
56
+
57
+
58
+ class AbstractBinaryClassificationAnnotationTask(models.Model):
59
+ """
60
+ Abstract base class for binary classification annotation tasks.
61
+
62
+ Attributes:
63
+ label (ForeignKey): The associated label.
64
+ is_finished (bool): Indicates if the task is completed.
65
+ date_created (datetime): The creation date of the task.
66
+ date_finished (datetime): The completion date of the task.
67
+ image_path (str): Path to the associated image.
68
+ image_type (str): The type of the image (e.g., "frame" or "legacy").
69
+ frame_id (int): Identifier of the associated frame.
70
+ labelstudio_project_id (int): The Label Studio project ID.
71
+ labelstudio_task_id (int): The Label Studio task ID.
72
+ """
73
+
74
+ label = models.ForeignKey("Label", on_delete=models.CASCADE)
75
+ is_finished = models.BooleanField(default=False)
76
+ date_created = models.DateTimeField(auto_now_add=True)
77
+ date_finished = models.DateTimeField(blank=True, null=True)
78
+ image_path = models.CharField(max_length=255, blank=True, null=True)
79
+ image_type = models.CharField(max_length=255, blank=True, null=True)
80
+ frame_id = models.IntegerField(blank=True, null=True)
81
+ labelstudio_project_id = models.IntegerField(blank=True, null=True)
82
+ labelstudio_task_id = models.IntegerField(blank=True, null=True)
83
+
84
+ class Meta:
85
+ abstract = True
86
+
87
+
88
+ class BinaryClassificationAnnotationTask(AbstractBinaryClassificationAnnotationTask):
89
+ """
90
+ Represents a binary classification task for a frame.
91
+
92
+ Attributes:
93
+ frame (ForeignKey): The associated frame for this task.
94
+ """
95
+
96
+ frame = models.ForeignKey(
97
+ "Frame",
98
+ on_delete=models.CASCADE,
99
+ related_name="binary_classification_annotation_tasks",
100
+ )
101
+ image_type = models.CharField(
102
+ max_length=255, default="frame"
103
+ ) # Default image type for non-legacy tasks
104
+
105
+ def get_frame(self):
106
+ """
107
+ Retrieves the frame associated with this task.
108
+ """
109
+ from endoreg_db.models.data_file.frame import Frame
110
+
111
+ frame = self.frame
112
+ if not frame:
113
+ return None
114
+ else:
115
+ assert isinstance(frame, Frame)
116
+
117
+ return frame
@@ -0,0 +1,86 @@
1
+ from django.db import models
2
+
3
+ from typing import TYPE_CHECKING, Union
4
+
5
+ if TYPE_CHECKING:
6
+ from endoreg_db.models import Frame, RawFrame, Label
7
+
8
+
9
+ class ImageClassificationAnnotation(models.Model):
10
+ """
11
+ Represents an image classification annotation.
12
+
13
+ Attributes:
14
+ frame (ForeignKey): The frame associated with the annotation.
15
+ legacy_frame (ForeignKey): The legacy frame associated with the annotation.
16
+ legacy_image (ForeignKey): The legacy image associated with the annotation.
17
+ label (ForeignKey): The label assigned to the annotation.
18
+ value (bool): Indicates if the classification is valid.
19
+ annotator (str): The user who created the annotation.
20
+ date_created (datetime): The creation date of the annotation.
21
+ date_modified (datetime): The last modification date of the annotation.
22
+ """
23
+
24
+ # Foreign keys to Frame, LegacyFrame, and LegacyImage (only one of these should be set)
25
+ frame = models.ForeignKey(
26
+ "Frame",
27
+ on_delete=models.CASCADE,
28
+ blank=True,
29
+ null=True,
30
+ related_name="image_classification_annotations",
31
+ )
32
+
33
+ raw_frame = models.ForeignKey(
34
+ "RawFrame",
35
+ on_delete=models.CASCADE,
36
+ blank=True,
37
+ null=True,
38
+ related_name="image_classification_annotations",
39
+ )
40
+
41
+ label = models.ForeignKey(
42
+ "Label",
43
+ on_delete=models.CASCADE,
44
+ related_name="image_classification_annotations",
45
+ )
46
+ value = models.BooleanField()
47
+ float_value = models.FloatField(blank=True, null=True)
48
+ annotator = models.CharField(max_length=255, blank=True, null=True)
49
+ model_meta = models.ForeignKey(
50
+ "ModelMeta",
51
+ on_delete=models.SET_NULL,
52
+ related_name="image_classification_annotations",
53
+ default=None,
54
+ null=True,
55
+ blank=True,
56
+ )
57
+ date_created = models.DateTimeField(auto_now_add=True)
58
+ date_modified = models.DateTimeField(auto_now=True)
59
+ information_source = models.ForeignKey(
60
+ "InformationSource",
61
+ on_delete=models.SET_NULL,
62
+ related_name="image_classification_annotations",
63
+ default=None,
64
+ null=True,
65
+ blank=True,
66
+ )
67
+
68
+ if TYPE_CHECKING:
69
+ frame: "Frame"
70
+ raw_frame: "RawFrame"
71
+ label: "Label"
72
+
73
+ def __str__(self) -> str:
74
+ """
75
+ String representation of the annotation.
76
+ """
77
+ return f"{self.label.name} - {self.value}"
78
+
79
+ def get_frame(self):
80
+ """
81
+ Get the frame associated with the annotation.
82
+ """
83
+ if self.frame:
84
+ return self.frame
85
+ else:
86
+ return self.raw_frame