endoreg-db 0.3.4__py3-none-any.whl → 0.3.6__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.
Files changed (350) hide show
  1. endoreg_db/admin.py +3 -3
  2. endoreg_db/apps.py +6 -6
  3. endoreg_db/data/__init__.py +65 -16
  4. endoreg_db/data/active_model/data.yaml +2 -2
  5. endoreg_db/data/case_template/rule/00_patient_lab_sample_add_default_value.yaml +167 -0
  6. endoreg_db/data/case_template/rule/01_patient-set-age.yaml +8 -0
  7. endoreg_db/data/case_template/rule/01_patient-set-gender.yaml +9 -0
  8. endoreg_db/data/case_template/rule/11_create_patient_lab_sample.yaml +23 -0
  9. endoreg_db/data/case_template/rule/12_create-patient_medication-anticoagulation.yaml +19 -0
  10. endoreg_db/data/case_template/rule/13_create-patient_medication_schedule-anticoagulation.yaml +19 -0
  11. endoreg_db/data/case_template/rule/19_create_patient.yaml +17 -0
  12. endoreg_db/data/case_template/rule_type/base_types.yaml +35 -0
  13. endoreg_db/data/case_template/rule_value_type/base_types.yaml +59 -0
  14. endoreg_db/data/case_template/template/base.yaml +8 -0
  15. endoreg_db/data/case_template/template_type/pre_endoscopy.yaml +3 -0
  16. endoreg_db/data/case_template/tmp/_rule_value +13 -0
  17. endoreg_db/data/case_template/tmp/rule/01_atrial_fibrillation.yaml +21 -0
  18. endoreg_db/data/case_template/tmp/rule/02_create_object.yaml +10 -0
  19. endoreg_db/data/case_template/tmp/template/atrial_fibrillation_low_risk.yaml +7 -0
  20. endoreg_db/data/center/data.yaml +60 -52
  21. endoreg_db/data/center_resource/green_endoscopy_dashboard_CenterResource.yaml +144 -0
  22. endoreg_db/data/center_waste/green_endoscopy_dashboard_CenterWaste.yaml +48 -0
  23. endoreg_db/data/disease/cardiovascular.yaml +37 -0
  24. endoreg_db/data/disease/hepatology.yaml +5 -0
  25. endoreg_db/data/disease/misc.yaml +6 -0
  26. endoreg_db/data/disease/renal.yaml +5 -0
  27. endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +6 -0
  28. endoreg_db/data/disease_classification/coronary_vessel_disease.yaml +6 -0
  29. endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +41 -0
  30. endoreg_db/data/disease_classification_choice/coronary_vessel_disease.yaml +20 -0
  31. endoreg_db/data/distribution/date/patient.yaml +7 -0
  32. endoreg_db/data/distribution/single_categorical/patient.yaml +7 -0
  33. endoreg_db/data/emission_factor/green_endoscopy_dashboard_EmissionFactor.yaml +132 -0
  34. endoreg_db/data/endoscope_type/data.yaml +10 -10
  35. endoreg_db/data/endoscopy_processor/data.yaml +45 -45
  36. endoreg_db/data/event/cardiology.yaml +28 -0
  37. endoreg_db/data/event/neurology.yaml +14 -0
  38. endoreg_db/data/event/surgery.yaml +13 -0
  39. endoreg_db/data/event/thrombembolism.yaml +20 -0
  40. endoreg_db/data/examination/examinations/data.yaml +65 -16
  41. endoreg_db/data/examination/time/data.yaml +47 -47
  42. endoreg_db/data/examination/time-type/data.yaml +7 -7
  43. endoreg_db/data/examination/type/data.yaml +5 -5
  44. endoreg_db/data/gender/data.yaml +18 -0
  45. endoreg_db/data/information_source/data.yaml +30 -30
  46. endoreg_db/data/information_source/medication.yaml +6 -0
  47. endoreg_db/data/lab_value/cardiac_enzymes.yaml +31 -0
  48. endoreg_db/data/lab_value/coagulation.yaml +49 -0
  49. endoreg_db/data/lab_value/electrolytes.yaml +190 -0
  50. endoreg_db/data/lab_value/gastrointestinal_function.yaml +121 -0
  51. endoreg_db/data/lab_value/hematology.yaml +169 -0
  52. endoreg_db/data/lab_value/hormones.yaml +53 -0
  53. endoreg_db/data/lab_value/lipids.yaml +44 -0
  54. endoreg_db/data/lab_value/misc.yaml +30 -0
  55. endoreg_db/data/lab_value/renal_function.yaml +11 -0
  56. endoreg_db/data/label/label/data.yaml +62 -62
  57. endoreg_db/data/label/label-set/data.yaml +17 -17
  58. endoreg_db/data/label/label-type/data.yaml +6 -6
  59. endoreg_db/data/material/material.yaml +91 -0
  60. endoreg_db/data/medication/anticoagulation.yaml +65 -0
  61. endoreg_db/data/medication/tah.yaml +70 -0
  62. endoreg_db/data/medication_indication/anticoagulation.yaml +120 -0
  63. endoreg_db/data/medication_indication_type/data.yaml +11 -0
  64. endoreg_db/data/medication_indication_type/thrombembolism.yaml +41 -0
  65. endoreg_db/data/medication_intake_time/base.yaml +31 -0
  66. endoreg_db/data/medication_schedule/apixaban.yaml +95 -0
  67. endoreg_db/data/medication_schedule/ass.yaml +12 -0
  68. endoreg_db/data/medication_schedule/enoxaparin.yaml +26 -0
  69. endoreg_db/data/model_type/data.yaml +6 -6
  70. endoreg_db/data/patient_lab_sample_type/generic.yaml +6 -0
  71. endoreg_db/data/pdf_type/data.yaml +28 -28
  72. endoreg_db/data/product/green_endoscopy_dashboard_Product.yaml +66 -0
  73. endoreg_db/data/product_group/green_endoscopy_dashboard_ProductGroup.yaml +33 -0
  74. endoreg_db/data/product_material/green_endoscopy_dashboard_ProductMaterial.yaml +308 -0
  75. endoreg_db/data/product_weight/green_endoscopy_dashboard_ProductWeight.yaml +88 -0
  76. endoreg_db/data/profession/data.yaml +70 -70
  77. endoreg_db/data/reference_product/green_endoscopy_dashboard_ReferenceProduct.yaml +55 -0
  78. endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +26 -26
  79. endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +19 -19
  80. endoreg_db/data/resource/green_endoscopy_dashboard_Resource.yaml +15 -0
  81. endoreg_db/data/tmp/chronic_kidney_disease.yaml +0 -0
  82. endoreg_db/data/tmp/congestive_heart_failure.yaml +0 -0
  83. endoreg_db/data/transport_route/green_endoscopy_dashboard_TransportRoute.yaml +12 -0
  84. endoreg_db/data/unit/concentration.yaml +92 -0
  85. endoreg_db/data/unit/data.yaml +17 -17
  86. endoreg_db/data/unit/length.yaml +30 -30
  87. endoreg_db/data/unit/misc.yaml +20 -0
  88. endoreg_db/data/unit/rate.yaml +6 -0
  89. endoreg_db/data/unit/time.yaml +13 -0
  90. endoreg_db/data/unit/volume.yaml +35 -26
  91. endoreg_db/data/unit/weight.yaml +37 -30
  92. endoreg_db/data/waste/data.yaml +12 -0
  93. endoreg_db/forms/__init__.py +2 -2
  94. endoreg_db/forms/questionnaires/tto_questionnaire.py +23 -23
  95. endoreg_db/forms/settings/__init__.py +8 -8
  96. endoreg_db/forms/unit.py +5 -5
  97. endoreg_db/management/commands/_load_model_template.py +40 -40
  98. endoreg_db/management/commands/delete_all.py +18 -18
  99. endoreg_db/management/commands/delete_legacy_images.py +19 -19
  100. endoreg_db/management/commands/delete_legacy_videos.py +16 -16
  101. endoreg_db/management/commands/extract_legacy_video_frames.py +18 -18
  102. endoreg_db/management/commands/fetch_legacy_image_dataset.py +32 -32
  103. endoreg_db/management/commands/fix_auth_permission.py +20 -20
  104. endoreg_db/management/commands/import_legacy_images.py +94 -94
  105. endoreg_db/management/commands/import_legacy_videos.py +76 -76
  106. endoreg_db/management/commands/load_active_model_data.py +44 -44
  107. endoreg_db/management/commands/load_ai_model_data.py +44 -44
  108. endoreg_db/management/commands/load_base_db_data.py +128 -71
  109. endoreg_db/management/commands/load_center_data.py +42 -42
  110. endoreg_db/management/commands/load_disease_classification_choices_data.py +41 -0
  111. endoreg_db/management/commands/load_disease_classification_data.py +41 -0
  112. endoreg_db/management/commands/load_disease_data.py +40 -0
  113. endoreg_db/management/commands/load_distribution_data.py +66 -0
  114. endoreg_db/management/commands/load_endoscope_type_data.py +44 -44
  115. endoreg_db/management/commands/load_endoscopy_processor_data.py +44 -44
  116. endoreg_db/management/commands/load_event_data.py +41 -0
  117. endoreg_db/management/commands/load_examination_data.py +74 -74
  118. endoreg_db/management/commands/load_g_play_data.py +113 -0
  119. endoreg_db/management/commands/load_gender_data.py +44 -0
  120. endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +133 -0
  121. endoreg_db/management/commands/load_information_source.py +44 -44
  122. endoreg_db/management/commands/load_lab_value_data.py +50 -0
  123. endoreg_db/management/commands/load_label_data.py +66 -66
  124. endoreg_db/management/commands/load_medication_data.py +41 -0
  125. endoreg_db/management/commands/load_medication_indication_data.py +63 -0
  126. endoreg_db/management/commands/load_medication_indication_type_data.py +41 -0
  127. endoreg_db/management/commands/load_medication_intake_time_data.py +41 -0
  128. endoreg_db/management/commands/load_medication_schedule_data.py +55 -0
  129. endoreg_db/management/commands/load_pdf_type_data.py +60 -60
  130. endoreg_db/management/commands/load_profession_data.py +43 -43
  131. endoreg_db/management/commands/load_report_reader_flag.py +45 -45
  132. endoreg_db/management/commands/load_unit_data.py +45 -45
  133. endoreg_db/management/commands/load_user_groups.py +28 -28
  134. endoreg_db/management/commands/register_ai_model.py +65 -65
  135. endoreg_db/management/commands/reset_celery_schedule.py +9 -9
  136. endoreg_db/migrations/0001_initial.py +582 -582
  137. endoreg_db/migrations/0002_rawvideofile.py +26 -26
  138. endoreg_db/migrations/0003_rawvideofile_frames_required.py +18 -18
  139. endoreg_db/migrations/0004_rename_hash_rawvideofile_video_hash.py +18 -18
  140. endoreg_db/migrations/0005_ffmpegmeta_remove_videoimportmeta_center_and_more.py +56 -56
  141. endoreg_db/migrations/0006_rawvideofile_center_alter_videometa_processor.py +25 -25
  142. endoreg_db/migrations/0007_rawvideofile_processor.py +19 -19
  143. endoreg_db/migrations/0008_rename_frames_required_rawvideofile_state_frames_required.py +18 -18
  144. endoreg_db/migrations/0009_sensitivemeta_rawvideofile_sensitive_meta.py +31 -31
  145. endoreg_db/migrations/0010_rename_endoscope_serial_number_sensitivemeta_endoscope_sn.py +18 -18
  146. endoreg_db/migrations/0011_rawvideofile_state_sensitive_data_retrieved.py +18 -18
  147. endoreg_db/migrations/0012_rawvideofile_prediction_dir_and_more.py +109 -109
  148. endoreg_db/migrations/0013_rawpdffile.py +31 -31
  149. endoreg_db/migrations/0014_pdftype_alter_rawpdffile_file_pdfmeta.py +38 -38
  150. endoreg_db/migrations/0015_rename_report_processed_rawpdffile_state_report_processed_and_more.py +31 -31
  151. endoreg_db/migrations/0016_rawpdffile_state_report_processing_required.py +18 -18
  152. endoreg_db/migrations/0017_firstname_lastname_center_first_names_and_more.py +37 -37
  153. endoreg_db/migrations/0018_reportreaderflag_reportreaderconfig.py +37 -37
  154. endoreg_db/migrations/0019_pdftype_cut_off_above_lines_and_more.py +42 -42
  155. endoreg_db/migrations/0020_rename_endoscopy_info_line_pdftype_endoscope_info_line.py +18 -18
  156. endoreg_db/migrations/0021_alter_pdftype_endoscope_info_line.py +19 -19
  157. endoreg_db/migrations/0022_alter_pdftype_endoscope_info_line.py +19 -19
  158. endoreg_db/migrations/0023_ttoquestionnaire_alter_pdftype_endoscope_info_line.py +59 -59
  159. endoreg_db/migrations/0024_remove_ttoquestionnaire_infections_and_more.py +27 -27
  160. endoreg_db/migrations/0025_event_alter_rawpdffile_file_patientevent.py +42 -0
  161. endoreg_db/migrations/0026_disease_diseaseclassification_and_more.py +166 -0
  162. endoreg_db/migrations/0027_labvalue_abbreviation_labvalue_default_normal_range_and_more.py +38 -0
  163. endoreg_db/migrations/0028_alter_unit_abbreviation.py +18 -0
  164. endoreg_db/migrations/0029_medicationintaketime_and_more.py +75 -0
  165. endoreg_db/migrations/0030_medicationindicationtype_and_more.py +101 -0
  166. endoreg_db/migrations/0031_rename_adapt_to_liver_function_medication_adapt_to_age_and_more.py +38 -0
  167. endoreg_db/migrations/0032_alter_medicationschedule_therapy_duration_d.py +18 -0
  168. endoreg_db/migrations/0033_medicationindication_sources.py +18 -0
  169. endoreg_db/migrations/0034_alter_rawpdffile_file.py +20 -0
  170. endoreg_db/migrations/0035_alter_medicationindication_sources.py +18 -0
  171. endoreg_db/migrations/0036_alter_rawpdffile_file.py +20 -0
  172. endoreg_db/migrations/0037_alter_medicationindication_sources.py +18 -0
  173. endoreg_db/migrations/0038_emissionfactor_material_product_productgroup_and_more.py +164 -0
  174. endoreg_db/migrations/0039_referenceproduct_name.py +19 -0
  175. endoreg_db/migrations/0040_quizanswertype_quizquestiontype_quizquestion_and_more.py +50 -0
  176. endoreg_db/migrations/0041_gender_patientmedication_medication_indication_and_more.py +40 -0
  177. endoreg_db/migrations/0042_casetemplateruletype_casetemplaterulevalue_and_more.py +74 -0
  178. endoreg_db/migrations/0043_casetemplatetype_name_de_casetemplatetype_name_en.py +23 -0
  179. endoreg_db/migrations/0044_casetemplateruletype_name_de_and_more.py +23 -0
  180. endoreg_db/migrations/0045_casetemplaterulevalue_value_type.py +19 -0
  181. endoreg_db/migrations/0046_casetemplaterulevalue_target_field.py +18 -0
  182. endoreg_db/migrations/0047_casetemplaterule_target_model.py +18 -0
  183. endoreg_db/migrations/0048_remove_casetemplaterule_chained_rules_and_more.py +22 -0
  184. endoreg_db/migrations/0049_remove_casetemplaterule_rule_values.py +17 -0
  185. endoreg_db/migrations/0050_casetemplaterule_rule_values.py +18 -0
  186. endoreg_db/migrations/0051_remove_casetemplaterule_calling_rules_and_more.py +27 -0
  187. endoreg_db/migrations/0052_rename_case_template_type_casetemplate_template_type.py +18 -0
  188. endoreg_db/migrations/0053_patientlabsampletype_patientlabsample_and_more.py +38 -0
  189. endoreg_db/migrations/0054_multiplecategoricalvaluedistribution_and_more.py +69 -0
  190. endoreg_db/migrations/0055_remove_casetemplaterule_rule_values_and_more.py +59 -0
  191. endoreg_db/migrations/0056_datevaluedistribution_and_more.py +32 -0
  192. endoreg_db/migrations/0057_remove_datevaluedistribution_max_date_and_more.py +72 -0
  193. endoreg_db/migrations/0058_datevaluedistribution_description_and_more.py +28 -0
  194. endoreg_db/migrations/0059_casetemplaterule_rule_values.py +18 -0
  195. endoreg_db/migrations/0060_labvalue__default_date_value_distribution_and_more.py +44 -0
  196. endoreg_db/migrations/0061_remove_patientlabvalue_date_patientlabvalue_datetime.py +24 -0
  197. endoreg_db/migrations/0062_labvalue_numeric_precision.py +18 -0
  198. endoreg_db/migrations/0063_alter_labvalue_numeric_precision.py +18 -0
  199. endoreg_db/migrations/0064_casetemplaterule_extra_parameters_and_more.py +23 -0
  200. endoreg_db/migrations/0065_rename__date_value_distribution_casetemplaterule_date_value_distribution_and_more.py +58 -0
  201. endoreg_db/migrations/0066_alter_patientlabvalue_patient_and_more.py +29 -0
  202. endoreg_db/migrations/0067_alter_medicationindication_indication_type.py +19 -0
  203. endoreg_db/models/__init__.py +74 -57
  204. endoreg_db/models/ai_model/__init__.py +3 -3
  205. endoreg_db/models/ai_model/active_model.py +9 -9
  206. endoreg_db/models/ai_model/model_meta.py +24 -24
  207. endoreg_db/models/ai_model/model_type.py +25 -25
  208. endoreg_db/models/ai_model/utils.py +8 -8
  209. endoreg_db/models/annotation/__init__.py +1 -1
  210. endoreg_db/models/annotation/binary_classification_annotation_task.py +80 -80
  211. endoreg_db/models/annotation/image_classification.py +26 -26
  212. endoreg_db/models/case_template/__init__.py +6 -0
  213. endoreg_db/models/case_template/case_template.py +81 -0
  214. endoreg_db/models/case_template/case_template_rule.py +276 -0
  215. endoreg_db/models/case_template/case_template_rule_value.py +73 -0
  216. endoreg_db/models/case_template/case_template_type.py +28 -0
  217. endoreg_db/models/center/__init__.py +4 -0
  218. endoreg_db/models/{center.py → center/center.py} +24 -24
  219. endoreg_db/models/center/center_product.py +34 -0
  220. endoreg_db/models/center/center_resource.py +19 -0
  221. endoreg_db/models/center/center_waste.py +11 -0
  222. endoreg_db/models/data_file/__init__.py +5 -5
  223. endoreg_db/models/data_file/base_classes/__init__.py +2 -2
  224. endoreg_db/models/data_file/base_classes/abstract_frame.py +50 -50
  225. endoreg_db/models/data_file/base_classes/abstract_video.py +200 -200
  226. endoreg_db/models/data_file/frame.py +45 -45
  227. endoreg_db/models/data_file/import_classes/__init__.py +31 -31
  228. endoreg_db/models/data_file/import_classes/processing_functions/__init__.py +34 -34
  229. endoreg_db/models/data_file/import_classes/processing_functions/pdf.py +28 -28
  230. endoreg_db/models/data_file/import_classes/processing_functions/video.py +260 -260
  231. endoreg_db/models/data_file/import_classes/raw_pdf.py +188 -185
  232. endoreg_db/models/data_file/import_classes/raw_video.py +343 -343
  233. endoreg_db/models/data_file/metadata/__init__.py +3 -3
  234. endoreg_db/models/data_file/metadata/pdf_meta.py +70 -70
  235. endoreg_db/models/data_file/metadata/sensitive_meta.py +31 -31
  236. endoreg_db/models/data_file/metadata/video_meta.py +132 -131
  237. endoreg_db/models/data_file/report_file.py +89 -89
  238. endoreg_db/models/data_file/video/__init__.py +6 -6
  239. endoreg_db/models/data_file/video/import_meta.py +25 -25
  240. endoreg_db/models/data_file/video/video.py +25 -25
  241. endoreg_db/models/data_file/video_segment.py +107 -107
  242. endoreg_db/models/disease.py +56 -0
  243. endoreg_db/models/emission/__init__.py +1 -0
  244. endoreg_db/models/emission/emission_factor.py +20 -0
  245. endoreg_db/models/event.py +22 -0
  246. endoreg_db/models/examination/__init__.py +3 -3
  247. endoreg_db/models/examination/examination.py +26 -26
  248. endoreg_db/models/examination/examination_time.py +27 -27
  249. endoreg_db/models/examination/examination_time_type.py +24 -24
  250. endoreg_db/models/examination/examination_type.py +18 -18
  251. endoreg_db/models/hardware/__init__.py +1 -1
  252. endoreg_db/models/hardware/endoscope.py +44 -44
  253. endoreg_db/models/hardware/endoscopy_processor.py +143 -143
  254. endoreg_db/models/information_source.py +29 -22
  255. endoreg_db/models/label/label.py +84 -84
  256. endoreg_db/models/laboratory/__init__.py +1 -0
  257. endoreg_db/models/laboratory/lab_value.py +102 -0
  258. endoreg_db/models/legacy_data/__init__.py +3 -3
  259. endoreg_db/models/legacy_data/image.py +34 -34
  260. endoreg_db/models/medication/__init__.py +1 -0
  261. endoreg_db/models/medication/medication.py +148 -0
  262. endoreg_db/models/other/__init__.py +5 -0
  263. endoreg_db/models/other/distribution.py +215 -0
  264. endoreg_db/models/other/material.py +16 -0
  265. endoreg_db/models/other/resource.py +18 -0
  266. endoreg_db/models/other/transport_route.py +21 -0
  267. endoreg_db/models/other/waste.py +20 -0
  268. endoreg_db/models/patient_examination/__init__.py +35 -35
  269. endoreg_db/models/permissions/__init__.py +44 -44
  270. endoreg_db/models/persons/__init__.py +7 -6
  271. endoreg_db/models/persons/examiner/__init__.py +1 -1
  272. endoreg_db/models/persons/examiner/examiner.py +15 -15
  273. endoreg_db/models/persons/examiner/examiner_type.py +1 -1
  274. endoreg_db/models/persons/first_name.py +17 -17
  275. endoreg_db/models/persons/gender.py +22 -0
  276. endoreg_db/models/persons/last_name.py +19 -19
  277. endoreg_db/models/persons/patient/__init__.py +8 -0
  278. endoreg_db/models/persons/patient/case/__init__.py +0 -0
  279. endoreg_db/models/persons/patient/case/case.py +30 -0
  280. endoreg_db/models/persons/patient/patient.py +216 -0
  281. endoreg_db/models/persons/patient/patient_disease.py +16 -0
  282. endoreg_db/models/persons/patient/patient_event.py +22 -0
  283. endoreg_db/models/persons/patient/patient_lab_sample.py +106 -0
  284. endoreg_db/models/persons/patient/patient_lab_value.py +176 -0
  285. endoreg_db/models/persons/patient/patient_medication.py +44 -0
  286. endoreg_db/models/persons/patient/patient_medication_schedule.py +28 -0
  287. endoreg_db/models/persons/person.py +31 -34
  288. endoreg_db/models/persons/portal_user_information.py +27 -29
  289. endoreg_db/models/prediction/__init__.py +1 -1
  290. endoreg_db/models/prediction/image_classification.py +37 -37
  291. endoreg_db/models/prediction/video_prediction_meta.py +244 -244
  292. endoreg_db/models/product/__init__.py +5 -0
  293. endoreg_db/models/product/product.py +97 -0
  294. endoreg_db/models/product/product_group.py +19 -0
  295. endoreg_db/models/product/product_material.py +24 -0
  296. endoreg_db/models/product/product_weight.py +26 -0
  297. endoreg_db/models/product/reference_product.py +99 -0
  298. endoreg_db/models/questionnaires/__init__.py +114 -114
  299. endoreg_db/models/quiz/__init__.py +2 -0
  300. endoreg_db/models/quiz/quiz_answer.py +41 -0
  301. endoreg_db/models/quiz/quiz_question.py +54 -0
  302. endoreg_db/models/report_reader/__init__.py +1 -1
  303. endoreg_db/models/report_reader/report_reader_config.py +53 -53
  304. endoreg_db/models/report_reader/report_reader_flag.py +19 -19
  305. endoreg_db/models/rules/__init__.py +5 -0
  306. endoreg_db/models/rules/rule.py +24 -0
  307. endoreg_db/models/rules/rule_applicator.py +224 -0
  308. endoreg_db/models/rules/rule_attribute_dtype.py +19 -0
  309. endoreg_db/models/rules/rule_type.py +22 -0
  310. endoreg_db/models/rules/ruleset.py +19 -0
  311. endoreg_db/models/unit.py +21 -19
  312. endoreg_db/queries/__init__.py +4 -4
  313. endoreg_db/queries/annotations/__init__.py +2 -2
  314. endoreg_db/queries/annotations/legacy.py +159 -159
  315. endoreg_db/queries/get/__init__.py +5 -5
  316. endoreg_db/queries/get/center.py +42 -42
  317. endoreg_db/queries/get/model.py +13 -13
  318. endoreg_db/queries/get/patient.py +14 -14
  319. endoreg_db/queries/get/patient_examination.py +20 -20
  320. endoreg_db/queries/get/report_file.py +33 -33
  321. endoreg_db/queries/get/video.py +31 -31
  322. endoreg_db/serializers/__init__.py +9 -9
  323. endoreg_db/serializers/ai_model.py +18 -18
  324. endoreg_db/serializers/annotation.py +17 -17
  325. endoreg_db/serializers/center.py +11 -11
  326. endoreg_db/serializers/examination.py +32 -32
  327. endoreg_db/serializers/frame.py +13 -13
  328. endoreg_db/serializers/hardware.py +20 -20
  329. endoreg_db/serializers/label.py +22 -22
  330. endoreg_db/serializers/patient.py +10 -10
  331. endoreg_db/serializers/prediction.py +15 -15
  332. endoreg_db/serializers/report_file.py +7 -7
  333. endoreg_db/serializers/video.py +27 -27
  334. endoreg_db/tests.py +3 -3
  335. endoreg_db/utils/cropping.py +28 -28
  336. endoreg_db/utils/dataloader.py +92 -185
  337. endoreg_db/utils/file_operations.py +30 -30
  338. endoreg_db/utils/hashs.py +33 -33
  339. endoreg_db/utils/legacy_ocr.py +201 -201
  340. endoreg_db/utils/ocr.py +197 -197
  341. endoreg_db/utils/uuid.py +4 -4
  342. endoreg_db/utils/video_metadata.py +87 -87
  343. endoreg_db/views.py +3 -3
  344. {endoreg_db-0.3.4.dist-info → endoreg_db-0.3.6.dist-info}/LICENSE +674 -674
  345. {endoreg_db-0.3.4.dist-info → endoreg_db-0.3.6.dist-info}/METADATA +2 -2
  346. endoreg_db-0.3.6.dist-info/RECORD +357 -0
  347. {endoreg_db-0.3.4.dist-info → endoreg_db-0.3.6.dist-info}/WHEEL +1 -1
  348. endoreg_db/models/persons/patient.py +0 -58
  349. endoreg_db/models.py +0 -3
  350. endoreg_db-0.3.4.dist-info/RECORD +0 -185
@@ -1,244 +1,244 @@
1
- from django.db import models
2
-
3
- from endoreg_db.models.label.label import LabelSet
4
- from ..data_file.video import LegacyVideo, Video
5
- from ..data_file.frame import LegacyFrame, Frame
6
- from .image_classification import ImageClassificationPrediction
7
- from ..data_file.video_segment import LegacyLabelVideoSegment, LabelVideoSegment, find_segments_in_prediction_array
8
- from ..information_source import get_prediction_information_source
9
- import numpy as np
10
- import pickle
11
-
12
- DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN = 1.5
13
- DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S = 1.0
14
-
15
- class AbstractVideoPredictionMeta(models.Model):
16
- model_meta = models.ForeignKey("ModelMeta", on_delete=models.CASCADE)
17
- date_created = models.DateTimeField(auto_now_add=True)
18
- date_modified = models.DateTimeField(auto_now=True)
19
- video = None # Placeholder for the video field, to be defined in derived classes
20
- prediction_array = models.BinaryField(blank=True, null=True)
21
-
22
- class Meta:
23
- abstract = True
24
- unique_together = ('model_meta', 'video')
25
-
26
- def __str__(self):
27
- return f"Video {self.video.id} - {self.model_meta.name}"
28
-
29
- def get_labelset(self):
30
- """
31
- Get the labelset of the predictions.
32
- """
33
- return self.model_meta.labelset
34
-
35
- def get_video_model(self):
36
- assert 1 == 2, "This method should be overridden in derived classes"
37
-
38
- def get_frame_model(self):
39
- assert 1 == 2, "This method should be overridden in derived classes"
40
-
41
- def get_label_list(self):
42
- """
43
- Get the label list of the predictions.
44
- """
45
- labelset:LabelSet = self.get_labelset()
46
- label_list = labelset.get_labels_in_order()
47
- return label_list
48
-
49
- def get_video_segment_model(self):
50
- assert 1 == 2, "This method should be overridden in derived classes"
51
-
52
- def save_prediction_array(self, prediction_array:np.array):
53
- """
54
- Save the prediction array to the database.
55
- """
56
- self.prediction_array = pickle.dumps(prediction_array)
57
- self.save()
58
-
59
- def get_prediction_array(self):
60
- """
61
- Get the prediction array from the database.
62
- """
63
- if self.prediction_array is None:
64
- return None
65
- else:
66
- return pickle.loads(self.prediction_array)
67
-
68
- def calculate_prediction_array(self):
69
- assert 1 == 2, "This method should be overridden in derived classes"
70
-
71
- def apply_running_mean(self, confidence_array, window_size_in_seconds: int = None):
72
- """
73
- Apply a running mean filter to the confidence array for smoothing, assuming a padding
74
- of 0.5 for the edges.
75
-
76
- Args:
77
- self: Object that has video and fps attributes, and to which this function belongs.
78
- confidence_array: A 2D numpy array with dimensions (num_frames),
79
- containing confidence scores for each label at each frame.
80
- window_size_in_seconds: The window size for the running mean in seconds.
81
-
82
- Returns:
83
- running_mean_array: A 2D numpy array with the same dimensions as confidence_array,
84
- containing the smoothed confidence scores.
85
- """
86
- video = self.video
87
- fps = video.fps
88
-
89
- if not window_size_in_seconds:
90
- window_size_in_seconds = DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN
91
-
92
- # Calculate window size in frames, ensuring at least one frame
93
- window_size_in_frames = int(window_size_in_seconds * fps)
94
- window_size_in_frames = max(window_size_in_frames, 1)
95
-
96
- # Define the window for the running mean
97
- window = np.ones(window_size_in_frames) / window_size_in_frames
98
-
99
- # Create running mean array with the same shape as the confidence array
100
- running_mean_array = np.zeros(confidence_array.shape)
101
-
102
- # Calculate the padding size
103
- pad_size = window_size_in_frames // 2
104
-
105
- # Pad the array with 0.5 on both sides
106
- padded_confidences = np.pad(confidence_array, (pad_size, pad_size), 'constant', constant_values=(0.5, 0.5))
107
-
108
- # Apply the running mean filter on the padded array
109
- running_mean = np.convolve(padded_confidences, window, mode='same')
110
-
111
- # Remove the padding from the result to match the original shape
112
- running_mean = running_mean[pad_size:-pad_size]
113
-
114
- return running_mean
115
-
116
-
117
- def create_video_segments_for_label(self, segments, label):
118
- """
119
- Creates video segments for the given label and segments.
120
- Segments is a list of tuples (start_frame_number, end_frame_number).
121
- Labels is a Label object.
122
- """
123
- video = self.video
124
- video_segment_model = self.get_video_segment_model()
125
- information_source = get_prediction_information_source()
126
-
127
- for segment in segments:
128
- start_frame_number, end_frame_number = segment
129
-
130
- video_segment = video_segment_model(
131
- video=video,
132
- prediction_meta=self,
133
- start_frame_number=start_frame_number,
134
- end_frame_number=end_frame_number,
135
- source=information_source,
136
- label=label,
137
- )
138
- video_segment.save()
139
-
140
- def create_video_segments(self, segment_length_threshold_in_s:float=None):
141
- if not segment_length_threshold_in_s:
142
- segment_length_threshold_in_s = DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S
143
-
144
- video = self.video
145
- fps = video.fps
146
- min_frame_length = int(segment_length_threshold_in_s * fps)
147
-
148
- label_list = self.get_label_list()
149
-
150
- # if prediction array doesnt exist, create it
151
- if self.prediction_array is None:
152
- self.calculate_prediction_array()
153
-
154
- prediction_array = self.get_prediction_array()
155
-
156
- for i, label in enumerate(label_list):
157
- # get predictions for this label
158
- predictions = prediction_array[:, i]
159
- # find segments of predictions that are longer than the threshold
160
- # segments is a list of tuples (start_frame_number, end_frame_number)
161
- segments = find_segments_in_prediction_array(predictions, min_frame_length)
162
-
163
- # create video segments
164
- self.create_video_segments_for_label(segments, label)
165
-
166
- import numpy as np
167
- class VideoPredictionMeta(AbstractVideoPredictionMeta):
168
- video = models.OneToOneField("Video", on_delete=models.CASCADE, related_name="video_prediction_meta")
169
-
170
- def get_video_model(self):
171
- return Video
172
-
173
- def get_frame_model(self):
174
- return Frame
175
-
176
- def get_video_segment_model(self):
177
- return LabelVideoSegment
178
-
179
- def calculate_prediction_array(self, window_size_in_seconds:int=None):
180
- """
181
- Fetches all predictions for this video, labelset, and model meta.
182
- """
183
- video:Video = self.video
184
-
185
- model_meta = self.model_meta
186
- label_list = self.get_label_list()
187
-
188
- prediction_array = np.zeros((video.get_frame_number, len(label_list)))
189
- for i, label in enumerate(label_list):
190
- # fetch all predictions for this label, video, and model meta ordered by ImageClassificationPrediction.frame.frame_number
191
- predictions = ImageClassificationPrediction.objects.filter(label=label, frame__video=video, model_meta=model_meta).order_by('frame__frame_number')
192
- confidences = np.array([prediction.confidence for prediction in predictions])
193
- smooth_confidences = self.apply_running_mean(confidences, window_size_in_seconds)
194
- # calculate binary predictions
195
- binary_predictions = smooth_confidences > 0.5
196
- # add to prediction array
197
- prediction_array[:, i] = binary_predictions
198
-
199
- # save prediction array
200
- self.save_prediction_array(prediction_array)
201
-
202
-
203
- class LegacyVideoPredictionMeta(AbstractVideoPredictionMeta):
204
- video = models.OneToOneField("LegacyVideo", on_delete=models.CASCADE, related_name="video_prediction_meta")
205
-
206
- def get_video_model(self):
207
- return LegacyVideo
208
-
209
- def get_frame_model(self):
210
- return LegacyFrame
211
-
212
- def get_video_segment_model(self):
213
- return LegacyLabelVideoSegment
214
-
215
- def calculate_prediction_array(self, window_size_in_seconds:int=None):
216
- """
217
- Fetches all predictions for this video, labelset, and model meta.
218
- """
219
- video:LegacyVideo = self.video
220
-
221
- model_meta = self.model_meta
222
- label_list = self.get_label_list()
223
-
224
- prediction_array = np.zeros((video.get_frame_number, len(label_list)))
225
- for i, label in enumerate(label_list):
226
- # fetch all predictions for this label, video, and model meta ordered by ImageClassificationPrediction.frame.frame_number
227
- predictions = ImageClassificationPrediction.objects.filter(label=label, legacy_frame__video=video, model_meta=model_meta).order_by('legacy_frame__frame_number')
228
- confidences = np.array([prediction.confidence for prediction in predictions])
229
- smooth_confidences = self.apply_running_mean(confidences, window_size_in_seconds)
230
- # calculate binary predictions
231
- binary_predictions = smooth_confidences > 0.5
232
- # add to prediction array
233
- prediction_array[:, i] = binary_predictions
234
-
235
- # save prediction array
236
- self.save_prediction_array(prediction_array)
237
-
238
-
239
-
240
-
241
-
242
-
243
-
244
-
1
+ from django.db import models
2
+
3
+ from endoreg_db.models.label.label import LabelSet
4
+ from ..data_file.video import LegacyVideo, Video
5
+ from ..data_file.frame import LegacyFrame, Frame
6
+ from .image_classification import ImageClassificationPrediction
7
+ from ..data_file.video_segment import LegacyLabelVideoSegment, LabelVideoSegment, find_segments_in_prediction_array
8
+ from ..information_source import get_prediction_information_source
9
+ import numpy as np
10
+ import pickle
11
+
12
+ DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN = 1.5
13
+ DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S = 1.0
14
+
15
+ class AbstractVideoPredictionMeta(models.Model):
16
+ model_meta = models.ForeignKey("ModelMeta", on_delete=models.CASCADE)
17
+ date_created = models.DateTimeField(auto_now_add=True)
18
+ date_modified = models.DateTimeField(auto_now=True)
19
+ video = None # Placeholder for the video field, to be defined in derived classes
20
+ prediction_array = models.BinaryField(blank=True, null=True)
21
+
22
+ class Meta:
23
+ abstract = True
24
+ unique_together = ('model_meta', 'video')
25
+
26
+ def __str__(self):
27
+ return f"Video {self.video.id} - {self.model_meta.name}"
28
+
29
+ def get_labelset(self):
30
+ """
31
+ Get the labelset of the predictions.
32
+ """
33
+ return self.model_meta.labelset
34
+
35
+ def get_video_model(self):
36
+ assert 1 == 2, "This method should be overridden in derived classes"
37
+
38
+ def get_frame_model(self):
39
+ assert 1 == 2, "This method should be overridden in derived classes"
40
+
41
+ def get_label_list(self):
42
+ """
43
+ Get the label list of the predictions.
44
+ """
45
+ labelset:LabelSet = self.get_labelset()
46
+ label_list = labelset.get_labels_in_order()
47
+ return label_list
48
+
49
+ def get_video_segment_model(self):
50
+ assert 1 == 2, "This method should be overridden in derived classes"
51
+
52
+ def save_prediction_array(self, prediction_array:np.array):
53
+ """
54
+ Save the prediction array to the database.
55
+ """
56
+ self.prediction_array = pickle.dumps(prediction_array)
57
+ self.save()
58
+
59
+ def get_prediction_array(self):
60
+ """
61
+ Get the prediction array from the database.
62
+ """
63
+ if self.prediction_array is None:
64
+ return None
65
+ else:
66
+ return pickle.loads(self.prediction_array)
67
+
68
+ def calculate_prediction_array(self):
69
+ assert 1 == 2, "This method should be overridden in derived classes"
70
+
71
+ def apply_running_mean(self, confidence_array, window_size_in_seconds: int = None):
72
+ """
73
+ Apply a running mean filter to the confidence array for smoothing, assuming a padding
74
+ of 0.5 for the edges.
75
+
76
+ Args:
77
+ self: Object that has video and fps attributes, and to which this function belongs.
78
+ confidence_array: A 2D numpy array with dimensions (num_frames),
79
+ containing confidence scores for each label at each frame.
80
+ window_size_in_seconds: The window size for the running mean in seconds.
81
+
82
+ Returns:
83
+ running_mean_array: A 2D numpy array with the same dimensions as confidence_array,
84
+ containing the smoothed confidence scores.
85
+ """
86
+ video = self.video
87
+ fps = video.fps
88
+
89
+ if not window_size_in_seconds:
90
+ window_size_in_seconds = DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN
91
+
92
+ # Calculate window size in frames, ensuring at least one frame
93
+ window_size_in_frames = int(window_size_in_seconds * fps)
94
+ window_size_in_frames = max(window_size_in_frames, 1)
95
+
96
+ # Define the window for the running mean
97
+ window = np.ones(window_size_in_frames) / window_size_in_frames
98
+
99
+ # Create running mean array with the same shape as the confidence array
100
+ running_mean_array = np.zeros(confidence_array.shape)
101
+
102
+ # Calculate the padding size
103
+ pad_size = window_size_in_frames // 2
104
+
105
+ # Pad the array with 0.5 on both sides
106
+ padded_confidences = np.pad(confidence_array, (pad_size, pad_size), 'constant', constant_values=(0.5, 0.5))
107
+
108
+ # Apply the running mean filter on the padded array
109
+ running_mean = np.convolve(padded_confidences, window, mode='same')
110
+
111
+ # Remove the padding from the result to match the original shape
112
+ running_mean = running_mean[pad_size:-pad_size]
113
+
114
+ return running_mean
115
+
116
+
117
+ def create_video_segments_for_label(self, segments, label):
118
+ """
119
+ Creates video segments for the given label and segments.
120
+ Segments is a list of tuples (start_frame_number, end_frame_number).
121
+ Labels is a Label object.
122
+ """
123
+ video = self.video
124
+ video_segment_model = self.get_video_segment_model()
125
+ information_source = get_prediction_information_source()
126
+
127
+ for segment in segments:
128
+ start_frame_number, end_frame_number = segment
129
+
130
+ video_segment = video_segment_model(
131
+ video=video,
132
+ prediction_meta=self,
133
+ start_frame_number=start_frame_number,
134
+ end_frame_number=end_frame_number,
135
+ source=information_source,
136
+ label=label,
137
+ )
138
+ video_segment.save()
139
+
140
+ def create_video_segments(self, segment_length_threshold_in_s:float=None):
141
+ if not segment_length_threshold_in_s:
142
+ segment_length_threshold_in_s = DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S
143
+
144
+ video = self.video
145
+ fps = video.fps
146
+ min_frame_length = int(segment_length_threshold_in_s * fps)
147
+
148
+ label_list = self.get_label_list()
149
+
150
+ # if prediction array doesnt exist, create it
151
+ if self.prediction_array is None:
152
+ self.calculate_prediction_array()
153
+
154
+ prediction_array = self.get_prediction_array()
155
+
156
+ for i, label in enumerate(label_list):
157
+ # get predictions for this label
158
+ predictions = prediction_array[:, i]
159
+ # find segments of predictions that are longer than the threshold
160
+ # segments is a list of tuples (start_frame_number, end_frame_number)
161
+ segments = find_segments_in_prediction_array(predictions, min_frame_length)
162
+
163
+ # create video segments
164
+ self.create_video_segments_for_label(segments, label)
165
+
166
+ import numpy as np
167
+ class VideoPredictionMeta(AbstractVideoPredictionMeta):
168
+ video = models.OneToOneField("Video", on_delete=models.CASCADE, related_name="video_prediction_meta")
169
+
170
+ def get_video_model(self):
171
+ return Video
172
+
173
+ def get_frame_model(self):
174
+ return Frame
175
+
176
+ def get_video_segment_model(self):
177
+ return LabelVideoSegment
178
+
179
+ def calculate_prediction_array(self, window_size_in_seconds:int=None):
180
+ """
181
+ Fetches all predictions for this video, labelset, and model meta.
182
+ """
183
+ video:Video = self.video
184
+
185
+ model_meta = self.model_meta
186
+ label_list = self.get_label_list()
187
+
188
+ prediction_array = np.zeros((video.get_frame_number, len(label_list)))
189
+ for i, label in enumerate(label_list):
190
+ # fetch all predictions for this label, video, and model meta ordered by ImageClassificationPrediction.frame.frame_number
191
+ predictions = ImageClassificationPrediction.objects.filter(label=label, frame__video=video, model_meta=model_meta).order_by('frame__frame_number')
192
+ confidences = np.array([prediction.confidence for prediction in predictions])
193
+ smooth_confidences = self.apply_running_mean(confidences, window_size_in_seconds)
194
+ # calculate binary predictions
195
+ binary_predictions = smooth_confidences > 0.5
196
+ # add to prediction array
197
+ prediction_array[:, i] = binary_predictions
198
+
199
+ # save prediction array
200
+ self.save_prediction_array(prediction_array)
201
+
202
+
203
+ class LegacyVideoPredictionMeta(AbstractVideoPredictionMeta):
204
+ video = models.OneToOneField("LegacyVideo", on_delete=models.CASCADE, related_name="video_prediction_meta")
205
+
206
+ def get_video_model(self):
207
+ return LegacyVideo
208
+
209
+ def get_frame_model(self):
210
+ return LegacyFrame
211
+
212
+ def get_video_segment_model(self):
213
+ return LegacyLabelVideoSegment
214
+
215
+ def calculate_prediction_array(self, window_size_in_seconds:int=None):
216
+ """
217
+ Fetches all predictions for this video, labelset, and model meta.
218
+ """
219
+ video:LegacyVideo = self.video
220
+
221
+ model_meta = self.model_meta
222
+ label_list = self.get_label_list()
223
+
224
+ prediction_array = np.zeros((video.get_frame_number, len(label_list)))
225
+ for i, label in enumerate(label_list):
226
+ # fetch all predictions for this label, video, and model meta ordered by ImageClassificationPrediction.frame.frame_number
227
+ predictions = ImageClassificationPrediction.objects.filter(label=label, legacy_frame__video=video, model_meta=model_meta).order_by('legacy_frame__frame_number')
228
+ confidences = np.array([prediction.confidence for prediction in predictions])
229
+ smooth_confidences = self.apply_running_mean(confidences, window_size_in_seconds)
230
+ # calculate binary predictions
231
+ binary_predictions = smooth_confidences > 0.5
232
+ # add to prediction array
233
+ prediction_array[:, i] = binary_predictions
234
+
235
+ # save prediction array
236
+ self.save_prediction_array(prediction_array)
237
+
238
+
239
+
240
+
241
+
242
+
243
+
244
+
@@ -0,0 +1,5 @@
1
+ from .product import Product
2
+ from .product_material import ProductMaterial
3
+ from .product_group import ProductGroup
4
+ from .reference_product import ReferenceProduct
5
+ from .product_weight import ProductWeight
@@ -0,0 +1,97 @@
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("ProductGroup", on_delete=models.SET_NULL, null=True)
44
+
45
+ def natural_key(self):
46
+ return (self.name,)
47
+
48
+ def __str__(self):
49
+ return self.name
50
+
51
+ def get_product_weight(self):
52
+ # check if there is a product material weight
53
+ from .product_material import ProductMaterial
54
+ product_materials = ProductMaterial.objects.filter(product=self, component="product")
55
+ if product_materials:
56
+ return self.get_product_material_weight()
57
+
58
+ # check if there is a product weight
59
+ #TODO
60
+
61
+ def get_package_weight(self):
62
+ # check if there is a package material weight
63
+ from .product_material import ProductMaterial
64
+ product_materials = ProductMaterial.objects.filter(product=self, component="package")
65
+ if product_materials:
66
+ return self.get_package_material_weight()
67
+
68
+ # check if there is a package weight
69
+ #TODO
70
+
71
+ def get_product_material_weight(self):
72
+ # get all materials with component == "product"
73
+ from .product_material import ProductMaterial
74
+ product_materials = ProductMaterial.objects.filter(product=self, component="product")
75
+
76
+ return sum_weights(product_materials)
77
+
78
+ def get_package_material_weight(self):
79
+ # get all materials with component == "package"
80
+ from .product_material import ProductMaterial
81
+ product_materials = ProductMaterial.objects.filter(product=self, component="package")
82
+
83
+ return sum_weights(product_materials)
84
+
85
+ def get_product_material_emission(self):
86
+ # get all materials with component == "product"
87
+ from .product_material import ProductMaterial
88
+ product_materials = ProductMaterial.objects.filter(product=self, component="product")
89
+
90
+ return sum_emissions(product_materials)
91
+
92
+ def get_package_material_emission(self):
93
+ # get all materials with component == "package"
94
+ from .product_material import ProductMaterial
95
+ product_materials = ProductMaterial.objects.filter(product=self, component="package")
96
+
97
+ return sum_emissions(product_materials)
@@ -0,0 +1,19 @@
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
+
@@ -0,0 +1,24 @@
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
+
@@ -0,0 +1,26 @@
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