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,306 @@
1
+ from typing import Union, TYPE_CHECKING
2
+ from django.db import models
3
+
4
+ from endoreg_db.models.label.label import LabelSet
5
+ from ..data_file.video import Video
6
+ from ..data_file.import_classes import RawVideoFile
7
+ from ..data_file.frame import Frame
8
+ from .image_classification import ImageClassificationPrediction
9
+ from ..data_file import (
10
+ LabelVideoSegment,
11
+ find_segments_in_prediction_array,
12
+ )
13
+
14
+ # from ..information_source import get_prediction_information_source
15
+ import numpy as np
16
+ import pickle
17
+
18
+ DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN = 1.5
19
+ DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S = 1.0
20
+
21
+ if TYPE_CHECKING:
22
+ from endoreg_db.models import ModelMeta
23
+
24
+
25
+ class AbstractVideoPredictionMeta(models.Model):
26
+ model_meta = models.ForeignKey("ModelMeta", on_delete=models.CASCADE)
27
+ date_created = models.DateTimeField(auto_now_add=True)
28
+ date_modified = models.DateTimeField(auto_now=True)
29
+ video = None # Placeholder for the video field, to be defined in derived classes
30
+ prediction_array = models.BinaryField(blank=True, null=True)
31
+ is_raw = models.BooleanField(default=False)
32
+
33
+ if TYPE_CHECKING:
34
+ model_meta: "ModelMeta"
35
+ video: Union["Video", "RawVideoFile"]
36
+
37
+ class Meta:
38
+ abstract = True
39
+ unique_together = ("model_meta", "video")
40
+
41
+ def is_raw_video_prediction_meta(self):
42
+ if isinstance(self, RawVideoPredictionMeta):
43
+ return True
44
+ return False
45
+
46
+ def __str__(self):
47
+ return f"Video {self.video.id} - {self.model_meta.name}"
48
+
49
+ # override save method to set is_raw field
50
+ def save(self, *args, **kwargs):
51
+ self.is_raw = self.is_raw_video_prediction_meta()
52
+ super().save(*args, **kwargs)
53
+
54
+ def get_labelset(self):
55
+ """
56
+ Get the labelset of the predictions.
57
+ """
58
+ if self.is_raw:
59
+ return self.model_meta.labelset
60
+
61
+ def get_video_model(self):
62
+ if self.is_raw:
63
+ return RawVideoFile
64
+
65
+ return Video
66
+
67
+ def get_frame_model(self):
68
+ return Frame
69
+
70
+ def get_video_segment_model(self):
71
+ from endoreg_db.models import LabelRawVideoSegment
72
+
73
+ if self.is_raw:
74
+ return LabelRawVideoSegment
75
+ return LabelVideoSegment
76
+
77
+ def get_label_list(self):
78
+ """
79
+ Get the label list of the predictions.
80
+ """
81
+ labelset: LabelSet = self.get_labelset()
82
+ label_list = labelset.get_labels_in_order()
83
+ return label_list
84
+
85
+ def save_prediction_array(self, prediction_array: np.array):
86
+ """
87
+ Save the prediction array to the database.
88
+ """
89
+ self.prediction_array = pickle.dumps(prediction_array)
90
+ self.save()
91
+
92
+ def get_prediction_array(self):
93
+ """
94
+ Get the prediction array from the database.
95
+ """
96
+ if self.prediction_array is None:
97
+ return None
98
+ else:
99
+ return pickle.loads(self.prediction_array)
100
+
101
+ def calculate_prediction_array(self):
102
+ assert 1 == 2, "This method should be overridden in derived classes"
103
+
104
+ def apply_running_mean(self, confidence_array, window_size_in_seconds: int = None):
105
+ """
106
+ Apply a running mean filter to the confidence array for smoothing, assuming a padding
107
+ of 0.5 for the edges.
108
+
109
+ Args:
110
+ self: Object that has video and fps attributes, and to which this function belongs.
111
+ confidence_array: A 2D numpy array with dimensions (num_frames),
112
+ containing confidence scores for each label at each frame.
113
+ window_size_in_seconds: The window size for the running mean in seconds.
114
+
115
+ Returns:
116
+ running_mean_array: A 2D numpy array with the same dimensions as confidence_array,
117
+ containing the smoothed confidence scores.
118
+ """
119
+ video = self.video
120
+ fps = video.fps
121
+
122
+ if not window_size_in_seconds:
123
+ window_size_in_seconds = DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN
124
+
125
+ # Calculate window size in frames, ensuring at least one frame
126
+ window_size_in_frames = int(window_size_in_seconds * fps)
127
+ window_size_in_frames = max(window_size_in_frames, 1)
128
+
129
+ # Define the window for the running mean
130
+ window = np.ones(window_size_in_frames) / window_size_in_frames
131
+
132
+ # Create running mean array with the same shape as the confidence array
133
+ _running_mean_array = np.zeros(confidence_array.shape)
134
+
135
+ # Calculate the padding size
136
+ pad_size = window_size_in_frames // 2
137
+
138
+ # Pad the array with 0.5 on both sides
139
+ padded_confidences = np.pad(
140
+ confidence_array,
141
+ (pad_size, pad_size),
142
+ "constant",
143
+ constant_values=(0.5, 0.5),
144
+ )
145
+
146
+ # Apply the running mean filter on the padded array
147
+ running_mean = np.convolve(padded_confidences, window, mode="same")
148
+
149
+ # Remove the padding from the result to match the original shape
150
+ running_mean = running_mean[pad_size:-pad_size]
151
+
152
+ return running_mean
153
+
154
+ # FIXME
155
+ # def create_video_segments_for_label(self, segments, label):
156
+ # """
157
+ # Creates video segments for the given label and segments.
158
+ # Segments is a list of tuples (start_frame_number, end_frame_number).
159
+ # Labels is a Label object.
160
+ # """
161
+ # video = self.video
162
+ # video_segment_model = self.get_video_segment_model()
163
+ # information_source = get_prediction_information_source()
164
+
165
+ # for segment in segments:
166
+ # start_frame_number, end_frame_number = segment
167
+
168
+ # video_segment = video_segment_model(
169
+ # video=video,
170
+ # prediction_meta=self,
171
+ # start_frame_number=start_frame_number,
172
+ # end_frame_number=end_frame_number,
173
+ # source=information_source,
174
+ # label=label,
175
+ # )
176
+ # video_segment.save()
177
+
178
+ def create_video_segments(self, segment_length_threshold_in_s: float = None):
179
+ if not segment_length_threshold_in_s:
180
+ segment_length_threshold_in_s = DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S
181
+
182
+ video = self.video
183
+ fps = video.fps
184
+ min_frame_length = int(segment_length_threshold_in_s * fps)
185
+
186
+ label_list = self.get_label_list()
187
+
188
+ # if prediction array doesnt exist, create it
189
+ if self.prediction_array is None:
190
+ self.calculate_prediction_array()
191
+
192
+ prediction_array = self.get_prediction_array()
193
+
194
+ for i, label in enumerate(label_list):
195
+ # get predictions for this label
196
+ predictions = prediction_array[:, i]
197
+ # find segments of predictions that are longer than the threshold
198
+ # segments is a list of tuples (start_frame_number, end_frame_number)
199
+ segments = find_segments_in_prediction_array(predictions, min_frame_length)
200
+
201
+ # create video segments
202
+ self.create_video_segments_for_label(segments, label)
203
+
204
+
205
+ class RawVideoPredictionMeta(AbstractVideoPredictionMeta):
206
+ """
207
+ Model for storing video predictions for a specific model and video.
208
+ """
209
+
210
+ video = models.ForeignKey(
211
+ "RawVideoFile", on_delete=models.CASCADE, related_name="video_prediction_meta"
212
+ )
213
+
214
+ def calculate_prediction_array(self, window_size_in_seconds: int = None):
215
+ """
216
+ Fetches all predictions for this video, labelset, and model meta.
217
+ """
218
+ video: Video = self.video
219
+
220
+ model_meta = self.model_meta
221
+ label_list = self.get_label_list()
222
+
223
+ prediction_array = np.zeros((video.get_frame_number, len(label_list)))
224
+ for i, label in enumerate(label_list):
225
+ # fetch all predictions for this label, video, and model meta ordered by ImageClassificationPrediction.frame.frame_number
226
+ predictions = ImageClassificationPrediction.objects.filter(
227
+ label=label, frame__video=video, model_meta=model_meta
228
+ ).order_by("frame__frame_number")
229
+ confidences = np.array(
230
+ [prediction.confidence for prediction in predictions]
231
+ )
232
+ smooth_confidences = self.apply_running_mean(
233
+ confidences, window_size_in_seconds
234
+ )
235
+ # calculate binary predictions
236
+ binary_predictions = smooth_confidences > 0.5
237
+ # add to prediction array
238
+ prediction_array[:, i] = binary_predictions
239
+
240
+ # save prediction array
241
+ self.save_prediction_array(prediction_array)
242
+
243
+
244
+ class VideoPredictionMeta(AbstractVideoPredictionMeta):
245
+ """
246
+ Model for storing video predictions for a specific model and video.
247
+ """
248
+
249
+ video = models.ForeignKey(
250
+ "Video", on_delete=models.CASCADE, related_name="video_prediction_meta"
251
+ )
252
+
253
+ @classmethod
254
+ def from_raw(
255
+ cls, video: "Video", raw_video_prediction_meta: RawVideoPredictionMeta
256
+ ):
257
+ """
258
+ Create a new VideoPrediction from an existing RawVideoPredictionMeta.
259
+ """
260
+ cls_dict = {
261
+ "video": video,
262
+ "model_meta": raw_video_prediction_meta.model_meta,
263
+ "date_created": raw_video_prediction_meta.date_created,
264
+ "date_modified": raw_video_prediction_meta.date_modified,
265
+ "prediction_array": raw_video_prediction_meta.prediction_array,
266
+ "is_raw": False,
267
+ }
268
+
269
+ # check if exists
270
+ if cls.objects.filter(
271
+ video=video, model_meta=raw_video_prediction_meta.model_meta
272
+ ).exists():
273
+ return cls.objects.get(
274
+ video=video, model_meta=raw_video_prediction_meta.model_meta
275
+ )
276
+ else:
277
+ return cls.objects.create(**cls_dict)
278
+
279
+ def calculate_prediction_array(self, window_size_in_seconds: int = None):
280
+ """
281
+ Fetches all predictions for this video, labelset, and model meta.
282
+ """
283
+ video: Video = self.video
284
+
285
+ model_meta = self.model_meta
286
+ label_list = self.get_label_list()
287
+
288
+ prediction_array = np.zeros((video.get_frame_number, len(label_list)))
289
+ for i, label in enumerate(label_list):
290
+ # fetch all predictions for this label, video, and model meta ordered by ImageClassificationPrediction.frame.frame_number
291
+ predictions = ImageClassificationPrediction.objects.filter(
292
+ label=label, frame__video=video, model_meta=model_meta
293
+ ).order_by("frame__frame_number")
294
+ confidences = np.array(
295
+ [prediction.confidence for prediction in predictions]
296
+ )
297
+ smooth_confidences = self.apply_running_mean(
298
+ confidences, window_size_in_seconds
299
+ )
300
+ # calculate binary predictions
301
+ binary_predictions = smooth_confidences > 0.5
302
+ # add to prediction array
303
+ prediction_array[:, i] = binary_predictions
304
+
305
+ # save prediction array
306
+ self.save_prediction_array(prediction_array)
@@ -0,0 +1,14 @@
1
+ '''Module for product models'''
2
+ from .product import Product
3
+ from .product_material import ProductMaterial
4
+ from .product_group import ProductGroup
5
+ from .reference_product import ReferenceProduct
6
+ from .product_weight import ProductWeight
7
+
8
+ __all__ = [
9
+ 'Product',
10
+ 'ProductMaterial',
11
+ 'ProductGroup',
12
+ 'ReferenceProduct',
13
+ 'ProductWeight',
14
+ ]
@@ -0,0 +1,110 @@
1
+ from django.db import models
2
+
3
+ class ProductManager(models.Manager):
4
+ def get_by_natural_key(self, name):
5
+ return self.get(name=name)
6
+
7
+ def sum_weights(product_materials):
8
+ # sum up the weights
9
+ weight = 0
10
+ reference_unit = None
11
+ for product_material in product_materials:
12
+ if not reference_unit:
13
+ reference_unit = product_material.unit
14
+ else:
15
+ assert reference_unit == product_material.unit, "ProductMaterial units do not match"
16
+ weight += product_material.quantity
17
+
18
+ return weight, reference_unit
19
+
20
+ def sum_emissions(product_materials):
21
+ # sum up the emissions
22
+ emission = 0
23
+ reference_unit = None
24
+ for product_material in product_materials:
25
+ if not reference_unit:
26
+ reference_unit = product_material.unit
27
+ else:
28
+ assert reference_unit == product_material.unit, "ProductMaterial units do not match"
29
+ emission, emission_unit = product_material.get_emission()
30
+ assert reference_unit == emission_unit, "ProductMaterial units do not match"
31
+ emission += emission
32
+
33
+ return emission, reference_unit
34
+
35
+ class Product(models.Model):
36
+ objects = ProductManager()
37
+
38
+ name = models.CharField(max_length=255)
39
+ name_de = models.CharField(max_length=255, null=True)
40
+ name_en = models.CharField(max_length=255, null=True)
41
+
42
+ transport_route = models.ForeignKey("TransportRoute", on_delete=models.SET_NULL, null=True)
43
+ product_group = models.ForeignKey(
44
+ "ProductGroup", on_delete=models.SET_NULL, null=True
45
+ )
46
+
47
+ def natural_key(self):
48
+ return (self.name,)
49
+
50
+ def __str__(self):
51
+ result = f"{self.name}"
52
+ if self.product_group:
53
+ result += f" ({self.product_group}, "
54
+ else:
55
+ result += " (no product group, "
56
+
57
+ if self.transport_route:
58
+ result += f"{self.transport_route})"
59
+ else:
60
+ result += "no transport route)"
61
+
62
+ return result
63
+
64
+ def get_product_weight(self):
65
+ # check if there is a product material weight
66
+ from .product_material import ProductMaterial
67
+ product_materials = ProductMaterial.objects.filter(product=self, component="product")
68
+ if product_materials:
69
+ return self.get_product_material_weight()
70
+
71
+ # check if there is a product weight
72
+ #TODO
73
+
74
+ def get_package_weight(self):
75
+ # check if there is a package material weight
76
+ from .product_material import ProductMaterial
77
+ product_materials = ProductMaterial.objects.filter(product=self, component="package")
78
+ if product_materials:
79
+ return self.get_package_material_weight()
80
+
81
+ # check if there is a package weight
82
+ #TODO
83
+
84
+ def get_product_material_weight(self):
85
+ # get all materials with component == "product"
86
+ from .product_material import ProductMaterial
87
+ product_materials = ProductMaterial.objects.filter(product=self, component="product")
88
+
89
+ return sum_weights(product_materials)
90
+
91
+ def get_package_material_weight(self):
92
+ # get all materials with component == "package"
93
+ from .product_material import ProductMaterial
94
+ product_materials = ProductMaterial.objects.filter(product=self, component="package")
95
+
96
+ return sum_weights(product_materials)
97
+
98
+ def get_product_material_emission(self):
99
+ # get all materials with component == "product"
100
+ from .product_material import ProductMaterial
101
+ product_materials = ProductMaterial.objects.filter(product=self, component="product")
102
+
103
+ return sum_emissions(product_materials)
104
+
105
+ def get_package_material_emission(self):
106
+ # get all materials with component == "package"
107
+ from .product_material import ProductMaterial
108
+ product_materials = ProductMaterial.objects.filter(product=self, component="package")
109
+
110
+ return sum_emissions(product_materials)
@@ -0,0 +1,27 @@
1
+ from django.db import models
2
+
3
+ class ProductGroupManager(models.Manager):
4
+ def get_by_natural_key(self, name):
5
+ return self.get(name=name)
6
+
7
+ class ProductGroup(models.Model):
8
+ objects = ProductGroupManager()
9
+
10
+ name = models.CharField(max_length=255)
11
+ name_de = models.CharField(max_length=255, null=True)
12
+ name_en = models.CharField(max_length=255, null=True)
13
+
14
+ def natural_key(self):
15
+ return (self.name,)
16
+
17
+ def __str__(self):
18
+ return self.name
19
+
20
+ def get_products(self):
21
+ from endoreg_db.models import Product
22
+ return Product.objects.filter(product_group=self)
23
+
24
+ def get_reference_product(self):
25
+ from endoreg_db.models import ReferenceProduct
26
+ return ReferenceProduct.objects.get(product_group=self)
27
+
@@ -0,0 +1,28 @@
1
+ from django.db import models
2
+
3
+ class ProductMaterial(models.Model):
4
+ component = models.CharField(max_length=255)
5
+ material = models.ForeignKey("Material", on_delete=models.CASCADE)
6
+ product = models.ForeignKey("Product", on_delete=models.CASCADE, related_name="product_materials")
7
+ unit = models.ForeignKey("Unit", on_delete=models.CASCADE)
8
+ quantity = models.FloatField()
9
+
10
+ def get_emission(self):
11
+ from ..emission import EmissionFactor
12
+ emission_factor:EmissionFactor = self.material.emission_factor
13
+ if emission_factor is None:
14
+ raise Exception("No emission factor for material " + self.material.name + " found.")
15
+
16
+ # make sure product_material.unit is the same as emission_factor.unit
17
+ if self.unit != emission_factor.unit:
18
+ raise Exception("Unit mismatch: " + self.unit.name + " != " + emission_factor.unit.name)
19
+
20
+ emmision_value = emission_factor.value * self.quantity
21
+ emission_unit = emission_factor.unit
22
+ return emmision_value, emission_unit
23
+
24
+ def __str__(self):
25
+ return f"{self.product.name} - {self.material.name} - {self.quantity} {self.unit.name}"
26
+
27
+
28
+
@@ -0,0 +1,38 @@
1
+ from django.db import models
2
+ import pandas as pd
3
+
4
+ class ProductWeightManager(models.Manager):
5
+ def get_by_natural_key(self, product, product_group, weight):
6
+ return self.get(product=product, product_group=product_group, weight=weight)
7
+
8
+ class ProductWeight(models.Model):
9
+ objects = ProductWeightManager()
10
+
11
+ name = models.CharField(max_length=255, null = True)
12
+ product = models.ForeignKey("Product", on_delete=models.CASCADE)
13
+ measured = models.FloatField(null=True)
14
+ verified = models.FloatField(null=True)
15
+ manufacturer = models.FloatField(null=True)
16
+ unit = models.ForeignKey("Unit", on_delete=models.SET_NULL, null=True)
17
+
18
+ def get_weight(self):
19
+ if not pd.isnull(self.verified):
20
+ return self.verified
21
+ elif not pd.isnull(self.measured):
22
+ return self.measured
23
+ elif not pd.isnull(self.manufacturer):
24
+ return self.manufacturer
25
+ else:
26
+ return None
27
+
28
+ def get_weight_source(self):
29
+ if not pd.isnull(self.verified):
30
+ return "verified"
31
+ elif not pd.isnull(self.measured):
32
+ return "measured"
33
+ elif not pd.isnull(self.manufacturer):
34
+ return "manufacturer"
35
+ else:
36
+ return None
37
+ def __str__(self):
38
+ return f"{self.product} - {self.get_weight()} {self.unit} (Source: {self.get_weight_source()})"
@@ -0,0 +1,115 @@
1
+ from django.db import models
2
+ from typing import List
3
+
4
+ class ReferenceProductManager(models.Manager):
5
+ def get_by_natural_key(self, product_name:str, product_group_name:str):
6
+ return self.get(product__name=product_name, product_group__name=product_group_name)
7
+
8
+ class ReferenceProduct(models.Model):
9
+ name = models.CharField(max_length=255)
10
+ product = models.ForeignKey("Product", on_delete=models.CASCADE)
11
+ product_group = models.OneToOneField("ProductGroup", on_delete=models.CASCADE, related_name="reference_product")
12
+ emission_factor_total = models.ForeignKey(
13
+ "EmissionFactor",
14
+ on_delete=models.SET_NULL,
15
+ null=True,
16
+ blank = True,
17
+ # related_name="reference_product_total"
18
+ )
19
+ emission_factor_package = models.ForeignKey(
20
+ "EmissionFactor",
21
+ on_delete=models.SET_NULL,
22
+ null=True,
23
+ related_name="reference_product_package"
24
+ )
25
+ emission_factor_product = models.ForeignKey(
26
+ "EmissionFactor",
27
+ on_delete=models.SET_NULL,
28
+ null=True,
29
+ related_name="reference_product_product"
30
+ )
31
+
32
+ objects = ReferenceProductManager()
33
+
34
+ def __str__(self):
35
+ return self.product.name + " (" + self.product_group.name + ")"
36
+
37
+ def set_emission_factors(self):
38
+ from .product import Product
39
+ from .product_material import ProductMaterial
40
+ from ..emission import EmissionFactor
41
+
42
+ product:Product = self.product
43
+ materials = product.product_materials.all()
44
+ emission_factor_name = f"{self.product_group.name}_{product.name}_total_emission_factor"
45
+ emission_factor_package_name = f"{self.product_group.name}_{product.name}_package_emission_factor"
46
+ emission_factor_product_name = f"{self.product_group.name}_{product.name}_product_emission_factor"
47
+
48
+ product_emissions = 0
49
+ package_emissions = 0
50
+
51
+ product_weight, product_weight_unit = product.get_product_material_weight()
52
+ package_weight, package_weight_unit = product.get_package_material_weight()
53
+ product_emission, product_emission_unit = product.get_product_material_emission()
54
+ package_emission, package_emission_unit = product.get_package_material_emission()
55
+
56
+ total_weight = product_weight + package_weight
57
+ total_emission = product_emission + package_emission
58
+
59
+ reference_unit = product_weight_unit
60
+ assert reference_unit == package_weight_unit, "Package weight units do not match"
61
+ assert reference_unit == product_emission_unit, "Product emission units do not match"
62
+ assert reference_unit == package_emission_unit, "Package emission units do not match"
63
+
64
+ product_emission_factor_value = product_emission / product_weight
65
+ package_emission_factor_value = package_emission / package_weight
66
+ total_emission_factor_value = total_emission / total_weight
67
+
68
+ emission_factor, created = EmissionFactor.objects.get_or_create(
69
+ name=emission_factor_name,
70
+ defaults={
71
+ "name": emission_factor_name,
72
+ "value": total_emission_factor_value,
73
+ "unit": reference_unit
74
+ }
75
+ )
76
+ self.emission_factor_total = emission_factor
77
+
78
+ emission_factor_package, created = EmissionFactor.objects.get_or_create(
79
+ name=emission_factor_package_name,
80
+ defaults={
81
+ "name": emission_factor_package_name,
82
+ "value": package_emission_factor_value,
83
+ "unit": reference_unit
84
+ }
85
+ )
86
+ self.emission_factor_package = emission_factor_package
87
+
88
+ emission_factor_product, created = EmissionFactor.objects.get_or_create(
89
+ name=emission_factor_product_name,
90
+ defaults={
91
+ "name": emission_factor_product_name,
92
+ "value": product_emission_factor_value,
93
+ "unit": reference_unit
94
+ }
95
+ )
96
+ self.emission_factor_product = emission_factor_product
97
+
98
+ self.save()
99
+
100
+ def get_emission_factor(self, component:str):
101
+ # check if emission_factor_total exists:
102
+ if self.emission_factor_total is None:
103
+ self.set_emission_factors()
104
+
105
+ if component == "total":
106
+ return self.emission_factor_total
107
+ elif component == "package":
108
+ return self.emission_factor_package
109
+ elif component == "product":
110
+ return self.emission_factor_product
111
+ else:
112
+ raise Exception("Unknown component: " + component)
113
+
114
+
115
+