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,389 @@
1
+ from ..person import Person
2
+ from django import forms
3
+ from django.forms import DateInput
4
+ from ...patient import PatientExamination
5
+ from ...data_file import ReportFile
6
+ from django.db import models
7
+ from faker import Faker
8
+ import random
9
+ from datetime import datetime
10
+ from icecream import ic
11
+ from typing import TYPE_CHECKING
12
+
13
+ if TYPE_CHECKING:
14
+ from endoreg_db.models import Center, Gender
15
+
16
+
17
+ class Patient(Person):
18
+ """
19
+ A class representing a patient.
20
+
21
+ Attributes inhereted from Person:
22
+ first_name (str): The first name of the patient.
23
+ last_name (str): The last name of the patient.
24
+ dob (datetime.date): The date of birth of the patient.
25
+ gender (Foreign Key): The gender of the patient.
26
+ email (str): The email address of the patient.
27
+ phone (str): The phone number of the patient.
28
+
29
+ """
30
+
31
+ # -----gc-08-dev--changings---
32
+ first_name = models.CharField(max_length=100)
33
+ last_name = models.CharField(max_length=100)
34
+ dob = models.DateField(null=True, blank=True)
35
+ gender = models.ForeignKey(
36
+ "Gender", on_delete=models.SET_NULL, null=True, blank=True
37
+ )
38
+ center = models.ForeignKey(
39
+ "Center", on_delete=models.SET_NULL, null=True, blank=True
40
+ )
41
+ patient_hash = models.CharField(max_length=255, blank=True, null=True)
42
+
43
+ def __str__(self):
44
+ return f"{self.first_name} {self.last_name} ({self.dob})"
45
+
46
+ @classmethod
47
+ def get_or_create_pseudo_patient_by_hash(
48
+ cls,
49
+ patient_hash: str,
50
+ center: "Center" = None,
51
+ gender: "Gender" = None,
52
+ birth_month: int = None,
53
+ birth_year: int = None,
54
+ ):
55
+ from endoreg_db.utils import random_day_by_year, create_mock_patient_name
56
+
57
+ created = False
58
+
59
+ existing_pathient = cls.objects.filter(patient_hash=patient_hash).first()
60
+ if existing_pathient:
61
+ ic(f"Patient with hash {patient_hash} already exists")
62
+ ic(f"Returning existing patient: {existing_pathient}")
63
+ return existing_pathient, created
64
+
65
+ # If no patient with the given hash exists, create a new pseudo patient
66
+ assert center, "Center must be provided to create a new pseudo patient"
67
+ assert gender, "Gender must be provided to create a new pseudo patient"
68
+ assert birth_month, (
69
+ "Birth month must be provided to create a new pseudo patient"
70
+ )
71
+ assert birth_year, "Birth year must be provided to create a new pseudo patient"
72
+
73
+ pseudo_dob = random_day_by_year(birth_year)
74
+ gender_name = gender.name
75
+ first_name, last_name = create_mock_patient_name(gender_name)
76
+
77
+ ic(f"Creating pseudo patient with hash {patient_hash}")
78
+ ic(f"Generated name: {first_name} {last_name}")
79
+
80
+ patient = cls.objects.create(
81
+ first_name=first_name,
82
+ last_name=last_name,
83
+ dob=pseudo_dob,
84
+ patient_hash=patient_hash,
85
+ is_real_person=False,
86
+ )
87
+
88
+ patient.save()
89
+ created = True
90
+
91
+ return patient, created
92
+
93
+ def export_patient_examinations(self):
94
+ """
95
+ Get all associated PatientExaminations, ReportFiles, and Videos for the patient.
96
+ """
97
+ from endoreg_db.models import PatientExamination, ReportFile, Video
98
+
99
+ patient_examinations = PatientExamination.objects.filter(patient=self)
100
+ report_files, videos = [], []
101
+ for patient_examination in patient_examinations:
102
+ rr = patient_examination.reportfile_set.all()
103
+ vv = patient_examination.videos.all()
104
+
105
+ report_files.extend(rr)
106
+ videos.extend(vv)
107
+
108
+ return patient_examinations, report_files, videos
109
+
110
+ def get_dob(self) -> datetime.date:
111
+ dob: datetime.date = self.dob
112
+ return dob
113
+
114
+ def get_unmatched_report_files(
115
+ self,
116
+ ): # field: self.report_files; filter: report_file.patient_examination = None
117
+ """Returns all report files for this patient that are not matched to a patient examination."""
118
+
119
+ return self.reportfile_set.filter(patient_examination=None)
120
+
121
+ def get_unmatched_video_files(
122
+ self,
123
+ ): # field: self.videos; filter: video.patient_examination = None
124
+ """Returns all video files for this patient that are not matched to a patient examination."""
125
+ return self.videos.filter(patient_examination=None)
126
+
127
+ def get_patient_examinations(self): # field: self.patient_examinations
128
+ """Returns all patient examinations for this patient ordered by date (most recent is first)."""
129
+ return self.patient_examinations.order_by("-date")
130
+
131
+ def create_examination(
132
+ self,
133
+ examination_name_str: str = None,
134
+ date_start: datetime = None,
135
+ date_end: datetime = None,
136
+ ):
137
+ """Creates a patient examination for this patient."""
138
+
139
+ if examination_name_str:
140
+ from endoreg_db.models import Examination
141
+
142
+ examination = Examination.objects.get(name=examination_name_str)
143
+ patient_examination = PatientExamination(
144
+ patient=self,
145
+ examination=examination,
146
+ date_start=date_start,
147
+ date_end=date_end,
148
+ )
149
+
150
+ else:
151
+ patient_examination = PatientExamination(
152
+ patient=self, date_start=date_start, date_end=date_end
153
+ )
154
+
155
+ patient_examination.save()
156
+
157
+ return patient_examination
158
+
159
+ def create_examination_by_indication(
160
+ self, indication, date_start: datetime = None, date_end: datetime = None
161
+ ):
162
+ from endoreg_db.models import (
163
+ ExaminationIndication,
164
+ Examination,
165
+ PatientExaminationIndication,
166
+ )
167
+
168
+ assert isinstance(indication, ExaminationIndication)
169
+
170
+ examination = indication.get_examination()
171
+
172
+ assert isinstance(examination, Examination)
173
+
174
+ patient_examination = PatientExamination.objects.create(
175
+ patient=self,
176
+ examination=examination,
177
+ date_start=date_start,
178
+ date_end=date_end,
179
+ )
180
+
181
+ patient_examination.save()
182
+
183
+ patient_examination_indication = PatientExaminationIndication.objects.create(
184
+ patient_examination=patient_examination, examination_indication=indication
185
+ )
186
+ patient_examination_indication.save()
187
+
188
+ return patient_examination, patient_examination_indication
189
+
190
+ def create_event(
191
+ self,
192
+ event_name_str: str,
193
+ date_start: datetime = None,
194
+ date_end: datetime = None,
195
+ description: str = None,
196
+ ):
197
+ from endoreg_db.models import Event, PatientEvent
198
+
199
+ event = Event.objects.get(name=event_name_str)
200
+
201
+ if not date_start:
202
+ date_start = datetime.now()
203
+
204
+ patient_event = PatientEvent.objects.create(
205
+ patient=self,
206
+ event=event,
207
+ date_start=date_start,
208
+ )
209
+
210
+ return patient_event
211
+
212
+ def create_examination_by_report_file(self, report_file: ReportFile):
213
+ """Creates a patient examination for this patient based on the given report file."""
214
+ patient_examination = PatientExamination(patient=self, report_file=report_file)
215
+ patient_examination.save()
216
+ return patient_examination
217
+
218
+ @classmethod
219
+ def get_random_gender(cls, p_male=0.5, p_female=0.5):
220
+ """
221
+ Get a Gender object by name (male, female) from the database with given probability.
222
+
223
+ :param p_male: Probability of selecting 'male' gender.
224
+ :param p_female: Probability of selecting 'female' gender.
225
+ :return: Gender object selected based on given probabilities.
226
+ """
227
+ from endoreg_db.models import Gender
228
+
229
+ # Extract names and probabilities
230
+ gender_names = ["male", "female"]
231
+ probabilities = [p_male, p_female]
232
+
233
+ # Debug: print the names and probabilities
234
+ # print(f"Gender names: {gender_names}")
235
+ # print(f"Probabilities: {probabilities}")
236
+
237
+ # Select a gender based on the given probabilities
238
+ selected_gender = random.choices(gender_names, probabilities)[0]
239
+ # Debug: print the selected gender
240
+ # print(f"Selected gender: {selected_gender}")
241
+
242
+ # Fetch the corresponding Gender object from the database
243
+ gender_obj = Gender.objects.get(name=selected_gender)
244
+
245
+ return gender_obj
246
+
247
+ @classmethod
248
+ def get_random_age(
249
+ cls, min_age=55, max_age=90, mean_age=65, std_age=10, distribution="normal"
250
+ ):
251
+ """
252
+ Get a random age based on the given distribution.
253
+
254
+ :param min_age: Minimum age.
255
+ :param max_age: Maximum age.
256
+ :param mean_age: Mean age.
257
+ :param std_age: Standard deviation of the age.
258
+ :param distribution: Distribution of the age.
259
+ :return: Random age based on the given distribution.
260
+ """
261
+ if distribution == "normal":
262
+ age = int(random.normalvariate(mean_age, std_age))
263
+ else:
264
+ age = int(random.uniform(min_age, max_age))
265
+
266
+ return age
267
+
268
+ @classmethod
269
+ def get_dob_from_age(cls, age, current_date=None):
270
+ """
271
+ Get a date of birth based on the given age and current date.
272
+
273
+ :param age: Age of the patient.
274
+ :param current_date: Current date.
275
+ :return: Date of birth based on the given age and current date.
276
+ """
277
+ if current_date is None:
278
+ current_date = datetime.now()
279
+ dob = current_date.replace(year=current_date.year - age).date()
280
+
281
+ # TODO
282
+ # randomize the day and month by adding a random number of days (0-364) to the date
283
+
284
+ return dob
285
+
286
+ @classmethod
287
+ def get_random_name_for_gender(cls, gender_obj, locale="de_DE"):
288
+ gender = gender_obj.name
289
+ fake = Faker(locale)
290
+
291
+ if gender == "male":
292
+ first_name = fake.first_name_male()
293
+ last_name = fake.last_name_male()
294
+
295
+ else:
296
+ first_name = fake.first_name_female()
297
+ last_name = fake.last_name_female()
298
+
299
+ return last_name, first_name
300
+
301
+ @classmethod
302
+ def create_generic(cls, center="gplay_case_generator"):
303
+ """
304
+ Create a generic patient with random attributes.
305
+
306
+ :param center: The center of the patient.
307
+ :return: The created patient.
308
+ """
309
+ from endoreg_db.models import Center
310
+
311
+ gender = Patient.get_random_gender()
312
+ last_name, first_name = Patient.get_random_name_for_gender(gender)
313
+
314
+ age = Patient.get_random_age()
315
+ dob = Patient.get_dob_from_age(age)
316
+
317
+ center = Center.objects.get(name=center)
318
+
319
+ patient = Patient.objects.create(
320
+ first_name=first_name,
321
+ last_name=last_name,
322
+ dob=dob,
323
+ gender=gender,
324
+ )
325
+ patient.save()
326
+ return patient
327
+
328
+ def age(self):
329
+ """
330
+ Get the age of the patient.
331
+
332
+ :return: The age of the patient.
333
+ """
334
+ # calculate correct age based on current date including day and month
335
+ current_date = datetime.now()
336
+ dob = self.dob
337
+ age = (
338
+ current_date.year
339
+ - dob.year
340
+ - ((current_date.month, current_date.day) < (dob.month, dob.day))
341
+ )
342
+ return age
343
+
344
+ def create_lab_sample(self, sample_type="generic", date=None, save=True):
345
+ """
346
+ Create a lab sample for this patient.
347
+
348
+ :param sample_type: The sample type. Should be either string of the sample types
349
+ name or the sample type object. If not set, the default sample type ("generic") is used.
350
+ :param date: The date of the lab sample.
351
+ :return: The created lab sample.
352
+ """
353
+ from endoreg_db.models import PatientLabSample, PatientLabSampleType
354
+
355
+ if date is None:
356
+ date = datetime.now()
357
+
358
+ if isinstance(sample_type, str):
359
+ sample_type = PatientLabSampleType.objects.get(name=sample_type)
360
+ assert sample_type is not None, (
361
+ f"Sample type with name '{sample_type}' not found."
362
+ ) #
363
+ elif not isinstance(sample_type, PatientLabSampleType):
364
+ raise ValueError(
365
+ "Sample type must be either a string or a PatientLabSampleType object."
366
+ )
367
+
368
+ patient_lab_sample = PatientLabSample.objects.create(
369
+ patient=self, sample_type=sample_type, date=date
370
+ )
371
+
372
+ if save:
373
+ patient_lab_sample.save()
374
+
375
+ return patient_lab_sample
376
+
377
+
378
+ class PatientForm(forms.ModelForm):
379
+ class Meta:
380
+ model = Patient
381
+ fields = "__all__"
382
+ widgets = {
383
+ "dob": DateInput(attrs={"type": "date"}),
384
+ }
385
+
386
+ def __init__(self, *args, **kwargs):
387
+ super().__init__(*args, **kwargs)
388
+ for field in self.fields.values():
389
+ field.widget.attrs["class"] = "form-control"
@@ -0,0 +1,22 @@
1
+ from django.db import models
2
+
3
+
4
+
5
+ class PatientDisease(models.Model):
6
+ patient = models.ForeignKey("Patient", on_delete=models.CASCADE)
7
+ disease = models.ForeignKey("Disease", on_delete=models.CASCADE)
8
+ classification_choices = models.ManyToManyField("DiseaseClassificationChoice")
9
+ start_date = models.DateField(blank=True, null=True)
10
+ end_date = models.DateField(blank=True, null=True)
11
+ numerical_descriptors = models.JSONField(default=dict)
12
+ subcategories = models.JSONField(default=dict)
13
+
14
+ last_update = models.DateTimeField(auto_now=True)
15
+
16
+ def __str__(self):
17
+ return f"{self.patient} - {self.disease}"
18
+
19
+ class Meta:
20
+ # unique_together = ('patient', 'disease', 'start_date')
21
+ verbose_name = 'Patient Disease'
22
+ verbose_name_plural = 'Patient Diseases'
@@ -0,0 +1,52 @@
1
+ from django.db import models
2
+ from .patient import Patient
3
+
4
+ class PatientEvent(models.Model):
5
+ """
6
+ A class representing an event for a patient.
7
+
8
+ Attributes:
9
+ patient (Patient): The patient associated with this event.
10
+ date (datetime.date): The date of the event.
11
+ description (str): A description of the event.
12
+ """
13
+ patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
14
+ event = models.ForeignKey("Event", on_delete=models.CASCADE)
15
+ date_start = models.DateField()
16
+ date_end = models.DateField(blank=True, null=True)
17
+ description = models.TextField(blank=True, null=True)
18
+ classification_choice = models.ForeignKey(
19
+ "EventClassificationChoice", on_delete=models.CASCADE, blank=True, null=True
20
+ )
21
+
22
+ subcategories = models.JSONField(default=dict)
23
+ numerical_descriptors = models.JSONField(default=dict)
24
+
25
+ last_update = models.DateTimeField(auto_now=True)
26
+
27
+ def __str__(self):
28
+ return str(self.date_start) + ": " + self.event.name
29
+
30
+ def set_subcategories_from_classification_choice(self):
31
+ """
32
+ Sets the subcategories for this event from the classification choice.
33
+ """
34
+ from endoreg_db.models import EventClassificationChoice
35
+ if self.classification_choice:
36
+ self.classification_choice:EventClassificationChoice
37
+ self.subcategories = self.classification_choice.subcategories
38
+ self.save()
39
+
40
+ return self.subcategories
41
+
42
+ def set_numerical_descriptors_from_classification_choice(self):
43
+ """
44
+ Sets the numerical descriptors for this event from the classification choice.
45
+ """
46
+ from endoreg_db.models import EventClassificationChoice
47
+ if self.classification_choice:
48
+ self.classification_choice:EventClassificationChoice
49
+ self.numerical_descriptors = self.classification_choice.numerical_descriptors
50
+ self.save()
51
+
52
+ return self.numerical_descriptors
@@ -0,0 +1,32 @@
1
+ from django.db import models
2
+
3
+ class PatientExaminationIndication(models.Model):
4
+ '''A model to store the indication for a patient examination.'''
5
+ patient_examination = models.ForeignKey('PatientExamination', on_delete=models.CASCADE, related_name='indications')
6
+ examination_indication = models.ForeignKey('ExaminationIndication', on_delete=models.CASCADE)
7
+ indication_choice = models.ForeignKey('ExaminationIndicationClassificationChoice', on_delete=models.CASCADE, blank=True, null=True)
8
+
9
+ def __str__(self):
10
+ return f"{self.patient_examination} - {self.examination_indication}"
11
+
12
+ def get_examination(self):
13
+ from endoreg_db.models import Examination
14
+ pe = self.get_patient_examination()
15
+ e: Examination = pe.examination
16
+
17
+ return e
18
+
19
+ def get_patient_examination(self):
20
+ from endoreg_db.models import PatientExamination
21
+ pe: PatientExamination = self.patient_examination
22
+ return pe
23
+
24
+ def get_choices(self):
25
+ from endoreg_db.models import (
26
+ ExaminationIndicationClassificationChoice,
27
+ ExaminationIndication
28
+ )
29
+ examination_indication:ExaminationIndication = self.examination_indication
30
+ choices = [_ for _ in examination_indication.get_choices()]
31
+ return choices
32
+
@@ -0,0 +1,108 @@
1
+ from django.db import models
2
+
3
+ DEFAULT_PATIENT_LAB_SAMPLE_TYPE_NAME = "generic"
4
+
5
+ class PatientLabSampleTypeManager(models.Manager):
6
+ def get_by_natural_key(self, name):
7
+ return self.get(name=name)
8
+
9
+ class PatientLabSampleType(models.Model):
10
+ """
11
+ A class representing a patient lab sample type.
12
+
13
+ Attributes:
14
+ name (str): The name of the patient lab sample type.
15
+ description (str): A description of the patient lab sample type.
16
+
17
+ """
18
+ name = models.CharField(max_length=255)
19
+ name_de = models.CharField(max_length=255, null=True)
20
+ name_en = models.CharField(max_length=255, null=True)
21
+ description = models.TextField(blank=True, null=True)
22
+
23
+ objects = PatientLabSampleTypeManager()
24
+
25
+ def natural_key(self):
26
+ return (self.name,)
27
+
28
+ def __str__(self):
29
+ return self.name
30
+
31
+ @classmethod
32
+ def get_default_sample_type(cls):
33
+ """
34
+ Get the default patient lab sample type.
35
+
36
+ Returns:
37
+ PatientLabSampleType: The default patient lab sample type.
38
+
39
+ """
40
+ return cls.objects.get_or_create(name="default")[0]
41
+
42
+ from datetime import datetime as dt
43
+ from datetime import timezone
44
+ class PatientLabSample(models.Model):
45
+ """
46
+ A class representing a patient lab sample.
47
+
48
+ Attributes:
49
+ patient (Patient): The patient to which the lab sample belongs.
50
+ sample_type (PatientLabSampleType): The type of the lab sample.
51
+ date (datetime): The date of the lab sample.
52
+ values (PatientLabValue; One2Many): The value of the lab sample.
53
+ unit (Unit): The unit of the lab sample.
54
+
55
+ """
56
+ patient = models.ForeignKey("Patient", on_delete=models.CASCADE, related_name="lab_samples")
57
+ sample_type = models.ForeignKey("PatientLabSampleType", on_delete=models.CASCADE)
58
+ date = models.DateTimeField()
59
+
60
+ def __str__(self):
61
+
62
+ formatted_datetime = self.date.strftime('%Y-%m-%d %H:%M')
63
+ return f"{self.patient} - {self.sample_type} - {formatted_datetime} ()"
64
+
65
+ def get_values(self):
66
+ return self.values.all()
67
+
68
+ @classmethod
69
+ def create_by_patient(cls, patient=None, sample_type=None, date=None, save = True):
70
+ """
71
+ Create a new patient lab sample by patient.
72
+
73
+ Args:
74
+ patient (Patient): The patient to which the lab sample belongs.
75
+ sample_type (PatientLabSampleType): The type of the lab sample.
76
+ date (datetime): The date of the lab sample.
77
+
78
+ Returns:
79
+ PatientLabSample: The new patient lab sample.
80
+
81
+ """
82
+ from endoreg_db.models.persons.patient import Patient, PatientLabSampleType
83
+ from warnings import warn
84
+
85
+ if not patient:
86
+ warn("No patient given. Cannot create patient lab sample.")
87
+ return None
88
+ if not sample_type:
89
+ sample_type = PatientLabSampleType.get_default_sample_type()
90
+ else:
91
+ sample_type = PatientLabSampleType.objects.get(name=sample_type)
92
+ if not date:
93
+ date = dt.now(timezone.utc)
94
+
95
+ patient_lab_sample = cls.objects.create(
96
+ patient=patient,
97
+ sample_type=sample_type,
98
+ date=date
99
+ )
100
+
101
+ if save:
102
+ patient_lab_sample.save()
103
+
104
+ return patient_lab_sample
105
+
106
+
107
+
108
+