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.
- endoreg_db/case_generator/__init__.py +0 -0
- endoreg_db/case_generator/case_generator.py +159 -0
- endoreg_db/case_generator/lab_sample_factory.py +33 -0
- endoreg_db/case_generator/utils.py +30 -0
- endoreg_db/data/__init__.py +118 -0
- endoreg_db/data/agl_service/data.yaml +19 -0
- endoreg_db/data/ai_model/data.yaml +7 -0
- endoreg_db/data/ai_model_label/label/data.yaml +88 -0
- endoreg_db/data/ai_model_label/label-set/data.yaml +21 -0
- endoreg_db/data/ai_model_label/label-type/data.yaml +7 -0
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +5 -0
- endoreg_db/data/ai_model_type/data.yaml +7 -0
- endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml +176 -0
- endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml +20 -0
- endoreg_db/data/case_template/rule/00_patient_lab_sample_add_default_value.yaml +167 -0
- endoreg_db/data/case_template/rule/01_patient-set-age.yaml +8 -0
- endoreg_db/data/case_template/rule/01_patient-set-gender.yaml +9 -0
- endoreg_db/data/case_template/rule/11_create_patient_lab_sample.yaml +23 -0
- endoreg_db/data/case_template/rule/12_create-patient_medication-anticoagulation.yaml +19 -0
- endoreg_db/data/case_template/rule/13_create-patient_medication_schedule-anticoagulation.yaml +19 -0
- endoreg_db/data/case_template/rule/19_create_patient.yaml +17 -0
- endoreg_db/data/case_template/rule_type/base_types.yaml +35 -0
- endoreg_db/data/case_template/rule_value/.init +0 -0
- endoreg_db/data/case_template/rule_value_type/base_types.yaml +59 -0
- endoreg_db/data/case_template/template/base.yaml +8 -0
- endoreg_db/data/case_template/template_type/pre_endoscopy.yaml +3 -0
- endoreg_db/data/case_template/tmp/_rule_value +13 -0
- endoreg_db/data/case_template/tmp/rule/01_atrial_fibrillation.yaml +21 -0
- endoreg_db/data/case_template/tmp/rule/02_create_object.yaml +10 -0
- endoreg_db/data/case_template/tmp/template/atrial_fibrillation_low_risk.yaml +7 -0
- endoreg_db/data/center/data.yaml +90 -0
- endoreg_db/data/center_resource/green_endoscopy_dashboard_CenterResource.yaml +144 -0
- endoreg_db/data/center_waste/green_endoscopy_dashboard_CenterWaste.yaml +48 -0
- endoreg_db/data/contraindication/bleeding.yaml +11 -0
- endoreg_db/data/disease/cardiovascular.yaml +37 -0
- endoreg_db/data/disease/hepatology.yaml +5 -0
- endoreg_db/data/disease/misc.yaml +6 -0
- endoreg_db/data/disease/renal.yaml +5 -0
- endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +6 -0
- endoreg_db/data/disease_classification/coronary_vessel_disease.yaml +6 -0
- endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +41 -0
- endoreg_db/data/disease_classification_choice/coronary_vessel_disease.yaml +20 -0
- endoreg_db/data/distribution/date/patient.yaml +7 -0
- endoreg_db/data/distribution/multiple_categorical/.init +0 -0
- endoreg_db/data/distribution/numeric/data.yaml +14 -0
- endoreg_db/data/distribution/single_categorical/patient.yaml +7 -0
- endoreg_db/data/emission_factor/green_endoscopy_dashboard_EmissionFactor.yaml +132 -0
- endoreg_db/data/endoscope/data.yaml +93 -0
- endoreg_db/data/endoscope_type/data.yaml +11 -0
- endoreg_db/data/endoscopy_processor/data.yaml +47 -0
- endoreg_db/data/event/cardiology.yaml +28 -0
- endoreg_db/data/event/neurology.yaml +14 -0
- endoreg_db/data/event/surgery.yaml +13 -0
- endoreg_db/data/event/thrombembolism.yaml +20 -0
- endoreg_db/data/examination/examinations/data.yaml +66 -0
- endoreg_db/data/examination/time/data.yaml +48 -0
- endoreg_db/data/examination/time-type/data.yaml +8 -0
- endoreg_db/data/examination/type/data.yaml +5 -0
- endoreg_db/data/examination_indication/endoscopy.yaml +8 -0
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +8 -0
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
- endoreg_db/data/finding/data.yaml +141 -0
- endoreg_db/data/finding_intervention/endoscopy.yaml +138 -0
- endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/finding_location_classification/colonoscopy.yaml +46 -0
- endoreg_db/data/finding_location_classification_choice/colonoscopy.yaml +240 -0
- endoreg_db/data/finding_morphology_classification/colonoscopy.yaml +48 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_circularity_default.yaml +34 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_nice.yaml +20 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_paris.yaml +65 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_planarity_default.yaml +56 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_surface_intact_default.yaml +39 -0
- endoreg_db/data/finding_morphology_classification_choice/colonoscopy_size.yaml +57 -0
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
- endoreg_db/data/finding_type/data.yaml +30 -0
- endoreg_db/data/gender/data.yaml +35 -0
- endoreg_db/data/information_source/data.yaml +30 -0
- endoreg_db/data/information_source/medication.yaml +6 -0
- endoreg_db/data/lab_value/cardiac_enzymes.yaml +37 -0
- endoreg_db/data/lab_value/coagulation.yaml +54 -0
- endoreg_db/data/lab_value/electrolytes.yaml +228 -0
- endoreg_db/data/lab_value/gastrointestinal_function.yaml +133 -0
- endoreg_db/data/lab_value/hematology.yaml +184 -0
- endoreg_db/data/lab_value/hormones.yaml +59 -0
- endoreg_db/data/lab_value/lipids.yaml +53 -0
- endoreg_db/data/lab_value/misc.yaml +33 -0
- endoreg_db/data/lab_value/renal_function.yaml +12 -0
- endoreg_db/data/log_type/data.yaml +57 -0
- endoreg_db/data/lx_client_tag/base.yaml +54 -0
- endoreg_db/data/lx_client_type/base.yaml +30 -0
- endoreg_db/data/lx_permission/base.yaml +24 -0
- endoreg_db/data/lx_permission/endoreg.yaml +52 -0
- endoreg_db/data/material/material.yaml +91 -0
- endoreg_db/data/medication/anticoagulation.yaml +65 -0
- endoreg_db/data/medication/tah.yaml +70 -0
- endoreg_db/data/medication_indication/anticoagulation.yaml +115 -0
- endoreg_db/data/medication_indication_type/data.yaml +11 -0
- endoreg_db/data/medication_indication_type/thrombembolism.yaml +41 -0
- endoreg_db/data/medication_intake_time/base.yaml +31 -0
- endoreg_db/data/medication_schedule/apixaban.yaml +95 -0
- endoreg_db/data/medication_schedule/ass.yaml +12 -0
- endoreg_db/data/medication_schedule/enoxaparin.yaml +26 -0
- endoreg_db/data/names_first/first_names.yaml +51 -0
- endoreg_db/data/names_last/last_names.yaml +51 -0
- endoreg_db/data/network_device/data.yaml +59 -0
- endoreg_db/data/network_device_type/data.yaml +12 -0
- endoreg_db/data/organ/data.yaml +29 -0
- endoreg_db/data/patient_lab_sample_type/generic.yaml +6 -0
- endoreg_db/data/pdf_type/data.yaml +29 -0
- endoreg_db/data/product/green_endoscopy_dashboard_Product.yaml +66 -0
- endoreg_db/data/product_group/green_endoscopy_dashboard_ProductGroup.yaml +33 -0
- endoreg_db/data/product_material/green_endoscopy_dashboard_ProductMaterial.yaml +308 -0
- endoreg_db/data/product_weight/green_endoscopy_dashboard_ProductWeight.yaml +88 -0
- endoreg_db/data/profession/data.yaml +70 -0
- endoreg_db/data/reference_product/green_endoscopy_dashboard_ReferenceProduct.yaml +55 -0
- endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +30 -0
- endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +19 -0
- endoreg_db/data/resource/green_endoscopy_dashboard_Resource.yaml +15 -0
- endoreg_db/data/tmp/chronic_kidney_disease.yaml +0 -0
- endoreg_db/data/tmp/congestive_heart_failure.yaml +0 -0
- endoreg_db/data/transport_route/green_endoscopy_dashboard_TransportRoute.yaml +12 -0
- endoreg_db/data/unit/concentration.yaml +92 -0
- endoreg_db/data/unit/data.yaml +17 -0
- endoreg_db/data/unit/length.yaml +31 -0
- endoreg_db/data/unit/misc.yaml +20 -0
- endoreg_db/data/unit/rate.yaml +6 -0
- endoreg_db/data/unit/time.yaml +13 -0
- endoreg_db/data/unit/volume.yaml +35 -0
- endoreg_db/data/unit/weight.yaml +38 -0
- endoreg_db/data/waste/data.yaml +12 -0
- endoreg_db/forms/__init__.py +5 -0
- endoreg_db/forms/examination_form.py +11 -0
- endoreg_db/forms/patient_finding_intervention_form.py +19 -0
- endoreg_db/forms/patient_form.py +26 -0
- endoreg_db/forms/questionnaires/__init__.py +1 -0
- endoreg_db/forms/questionnaires/tto_questionnaire.py +23 -0
- endoreg_db/forms/settings/__init__.py +8 -0
- endoreg_db/forms/unit.py +6 -0
- endoreg_db/management/__init__.py +0 -0
- endoreg_db/management/commands/__init__.py +0 -0
- endoreg_db/management/commands/_load_model_template.py +41 -0
- endoreg_db/management/commands/delete_all.py +18 -0
- endoreg_db/management/commands/fetch_legacy_image_dataset.py +32 -0
- endoreg_db/management/commands/fix_auth_permission.py +20 -0
- endoreg_db/management/commands/load_active_model_data.py +45 -0
- endoreg_db/management/commands/load_ai_model_data.py +79 -0
- endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
- endoreg_db/management/commands/load_base_db_data.py +178 -0
- endoreg_db/management/commands/load_center_data.py +43 -0
- endoreg_db/management/commands/load_contraindication_data.py +41 -0
- endoreg_db/management/commands/load_disease_classification_choices_data.py +41 -0
- endoreg_db/management/commands/load_disease_classification_data.py +41 -0
- endoreg_db/management/commands/load_disease_data.py +62 -0
- endoreg_db/management/commands/load_distribution_data.py +66 -0
- endoreg_db/management/commands/load_endoscope_data.py +68 -0
- endoreg_db/management/commands/load_event_data.py +41 -0
- endoreg_db/management/commands/load_examination_data.py +75 -0
- endoreg_db/management/commands/load_examination_indication_data.py +65 -0
- endoreg_db/management/commands/load_finding_data.py +171 -0
- endoreg_db/management/commands/load_g_play_data.py +113 -0
- endoreg_db/management/commands/load_gender_data.py +44 -0
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +133 -0
- endoreg_db/management/commands/load_information_source.py +45 -0
- endoreg_db/management/commands/load_lab_value_data.py +50 -0
- endoreg_db/management/commands/load_logging_data.py +39 -0
- endoreg_db/management/commands/load_lx_data.py +64 -0
- endoreg_db/management/commands/load_medication_data.py +103 -0
- endoreg_db/management/commands/load_medication_indication_data.py +63 -0
- endoreg_db/management/commands/load_medication_indication_type_data.py +41 -0
- endoreg_db/management/commands/load_medication_intake_time_data.py +41 -0
- endoreg_db/management/commands/load_medication_schedule_data.py +55 -0
- endoreg_db/management/commands/load_name_data.py +37 -0
- endoreg_db/management/commands/load_network_data.py +57 -0
- endoreg_db/management/commands/load_organ_data.py +43 -0
- endoreg_db/management/commands/load_pdf_type_data.py +61 -0
- endoreg_db/management/commands/load_profession_data.py +44 -0
- endoreg_db/management/commands/load_report_reader_flag_data.py +46 -0
- endoreg_db/management/commands/load_unit_data.py +46 -0
- endoreg_db/management/commands/load_user_groups.py +28 -0
- endoreg_db/management/commands/register_ai_model.py +64 -0
- endoreg_db/management/commands/reset_celery_schedule.py +9 -0
- endoreg_db/migrations/0001_initial.py +2045 -0
- endoreg_db/migrations/0002_alter_frame_image_alter_rawframe_image.py +23 -0
- endoreg_db/migrations/0003_alter_frame_image_alter_rawframe_image.py +23 -0
- endoreg_db/migrations/0004_alter_rawvideofile_file_alter_video_file.py +25 -0
- endoreg_db/migrations/0005_rawvideofile_frame_count_and_more.py +33 -0
- endoreg_db/migrations/0006_frame_extracted_rawframe_extracted.py +23 -0
- endoreg_db/migrations/0007_rename_pseudo_patient_video_patient_and_more.py +24 -0
- endoreg_db/migrations/0008_remove_reportfile_patient_examination_and_more.py +48 -0
- endoreg_db/migrations/__init__.py +0 -0
- endoreg_db/models/__init__.py +376 -0
- endoreg_db/models/ai_model/__init__.py +4 -0
- endoreg_db/models/ai_model/active_model.py +9 -0
- endoreg_db/models/ai_model/ai_model.py +103 -0
- endoreg_db/models/ai_model/lightning/__init__.py +3 -0
- endoreg_db/models/ai_model/lightning/inference_dataset.py +53 -0
- endoreg_db/models/ai_model/lightning/multilabel_classification_net.py +155 -0
- endoreg_db/models/ai_model/lightning/postprocess.py +53 -0
- endoreg_db/models/ai_model/lightning/predict.py +172 -0
- endoreg_db/models/ai_model/lightning/prediction_visualizer.py +55 -0
- endoreg_db/models/ai_model/lightning/preprocess.py +68 -0
- endoreg_db/models/ai_model/lightning/run_visualizer.py +21 -0
- endoreg_db/models/ai_model/model_meta.py +250 -0
- endoreg_db/models/ai_model/model_type.py +36 -0
- endoreg_db/models/ai_model/utils.py +8 -0
- endoreg_db/models/annotation/__init__.py +32 -0
- endoreg_db/models/annotation/anonymized_image_annotation.py +115 -0
- endoreg_db/models/annotation/binary_classification_annotation_task.py +117 -0
- endoreg_db/models/annotation/image_classification.py +86 -0
- endoreg_db/models/annotation/video_segmentation_annotation.py +52 -0
- endoreg_db/models/annotation/video_segmentation_labelset.py +20 -0
- endoreg_db/models/case/__init__.py +1 -0
- endoreg_db/models/case/case.py +34 -0
- endoreg_db/models/case_template/__init__.py +15 -0
- endoreg_db/models/case_template/case_template.py +125 -0
- endoreg_db/models/case_template/case_template_rule.py +276 -0
- endoreg_db/models/case_template/case_template_rule_value.py +88 -0
- endoreg_db/models/case_template/case_template_type.py +28 -0
- endoreg_db/models/center/__init__.py +11 -0
- endoreg_db/models/center/center.py +51 -0
- endoreg_db/models/center/center_product.py +33 -0
- endoreg_db/models/center/center_resource.py +33 -0
- endoreg_db/models/center/center_waste.py +16 -0
- endoreg_db/models/contraindication/__init__.py +21 -0
- endoreg_db/models/data_file/__init__.py +39 -0
- endoreg_db/models/data_file/base_classes/__init__.py +7 -0
- endoreg_db/models/data_file/base_classes/abstract_frame.py +100 -0
- endoreg_db/models/data_file/base_classes/abstract_pdf.py +136 -0
- endoreg_db/models/data_file/base_classes/abstract_video.py +807 -0
- endoreg_db/models/data_file/base_classes/frame_helpers.py +17 -0
- endoreg_db/models/data_file/base_classes/prepare_bulk_frames.py +19 -0
- endoreg_db/models/data_file/base_classes/utils.py +80 -0
- endoreg_db/models/data_file/frame.py +29 -0
- endoreg_db/models/data_file/import_classes/__init__.py +18 -0
- endoreg_db/models/data_file/import_classes/processing_functions/__init__.py +35 -0
- endoreg_db/models/data_file/import_classes/processing_functions/pdf.py +28 -0
- endoreg_db/models/data_file/import_classes/processing_functions/video.py +260 -0
- endoreg_db/models/data_file/import_classes/raw_pdf.py +260 -0
- endoreg_db/models/data_file/import_classes/raw_video.py +288 -0
- endoreg_db/models/data_file/metadata/__init__.py +13 -0
- endoreg_db/models/data_file/metadata/pdf_meta.py +74 -0
- endoreg_db/models/data_file/metadata/sensitive_meta.py +290 -0
- endoreg_db/models/data_file/metadata/video_meta.py +199 -0
- endoreg_db/models/data_file/report_file.py +56 -0
- endoreg_db/models/data_file/video/__init__.py +11 -0
- endoreg_db/models/data_file/video/import_meta.py +25 -0
- endoreg_db/models/data_file/video/video.py +196 -0
- endoreg_db/models/data_file/video_segment.py +214 -0
- endoreg_db/models/disease.py +79 -0
- endoreg_db/models/emission/__init__.py +5 -0
- endoreg_db/models/emission/emission_factor.py +85 -0
- endoreg_db/models/event.py +73 -0
- endoreg_db/models/examination/__init__.py +9 -0
- endoreg_db/models/examination/examination.py +67 -0
- endoreg_db/models/examination/examination_indication.py +170 -0
- endoreg_db/models/examination/examination_time.py +53 -0
- endoreg_db/models/examination/examination_time_type.py +48 -0
- endoreg_db/models/examination/examination_type.py +40 -0
- endoreg_db/models/finding/__init__.py +11 -0
- endoreg_db/models/finding/finding.py +75 -0
- endoreg_db/models/finding/finding_intervention.py +60 -0
- endoreg_db/models/finding/finding_location_classification.py +94 -0
- endoreg_db/models/finding/finding_morphology_classification.py +89 -0
- endoreg_db/models/finding/finding_type.py +22 -0
- endoreg_db/models/hardware/__init__.py +2 -0
- endoreg_db/models/hardware/endoscope.py +60 -0
- endoreg_db/models/hardware/endoscopy_processor.py +155 -0
- endoreg_db/models/information_source.py +29 -0
- endoreg_db/models/label/__init__.py +1 -0
- endoreg_db/models/label/label.py +112 -0
- endoreg_db/models/laboratory/__init__.py +1 -0
- endoreg_db/models/laboratory/lab_value.py +111 -0
- endoreg_db/models/logging/__init__.py +11 -0
- endoreg_db/models/logging/agl_service.py +19 -0
- endoreg_db/models/logging/base.py +22 -0
- endoreg_db/models/logging/log_type.py +23 -0
- endoreg_db/models/logging/network_device.py +27 -0
- endoreg_db/models/lx/__init__.py +4 -0
- endoreg_db/models/lx/client.py +57 -0
- endoreg_db/models/lx/identity.py +34 -0
- endoreg_db/models/lx/permission.py +18 -0
- endoreg_db/models/lx/user.py +16 -0
- endoreg_db/models/medication/__init__.py +19 -0
- endoreg_db/models/medication/medication.py +33 -0
- endoreg_db/models/medication/medication_indication.py +50 -0
- endoreg_db/models/medication/medication_indication_type.py +34 -0
- endoreg_db/models/medication/medication_intake_time.py +26 -0
- endoreg_db/models/medication/medication_schedule.py +37 -0
- endoreg_db/models/network/__init__.py +9 -0
- endoreg_db/models/network/agl_service.py +38 -0
- endoreg_db/models/network/network_device.py +58 -0
- endoreg_db/models/network/network_device_type.py +23 -0
- endoreg_db/models/organ/__init__.py +38 -0
- endoreg_db/models/other/__init__.py +23 -0
- endoreg_db/models/other/distribution/__init__.py +44 -0
- endoreg_db/models/other/distribution/base_value_distribution.py +20 -0
- endoreg_db/models/other/distribution/date_value_distribution.py +91 -0
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
- endoreg_db/models/other/distribution/numeric_value_distribution.py +97 -0
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
- endoreg_db/models/other/distribution.py +5 -0
- endoreg_db/models/other/material.py +20 -0
- endoreg_db/models/other/resource.py +18 -0
- endoreg_db/models/other/transport_route.py +22 -0
- endoreg_db/models/other/waste.py +20 -0
- endoreg_db/models/patient/__init__.py +24 -0
- endoreg_db/models/patient/patient_examination.py +182 -0
- endoreg_db/models/patient/patient_finding.py +143 -0
- endoreg_db/models/patient/patient_finding_intervention.py +26 -0
- endoreg_db/models/patient/patient_finding_location.py +120 -0
- endoreg_db/models/patient/patient_finding_morphology.py +166 -0
- endoreg_db/models/permissions/__init__.py +44 -0
- endoreg_db/models/persons/__init__.py +34 -0
- endoreg_db/models/persons/examiner/__init__.py +2 -0
- endoreg_db/models/persons/examiner/examiner.py +60 -0
- endoreg_db/models/persons/examiner/examiner_type.py +2 -0
- endoreg_db/models/persons/first_name.py +18 -0
- endoreg_db/models/persons/gender.py +22 -0
- endoreg_db/models/persons/last_name.py +20 -0
- endoreg_db/models/persons/patient/__init__.py +8 -0
- endoreg_db/models/persons/patient/patient.py +389 -0
- endoreg_db/models/persons/patient/patient_disease.py +22 -0
- endoreg_db/models/persons/patient/patient_event.py +52 -0
- endoreg_db/models/persons/patient/patient_examination_indication.py +32 -0
- endoreg_db/models/persons/patient/patient_lab_sample.py +108 -0
- endoreg_db/models/persons/patient/patient_lab_value.py +197 -0
- endoreg_db/models/persons/patient/patient_medication.py +59 -0
- endoreg_db/models/persons/patient/patient_medication_schedule.py +88 -0
- endoreg_db/models/persons/person.py +31 -0
- endoreg_db/models/persons/portal_user_information.py +27 -0
- endoreg_db/models/prediction/__init__.py +8 -0
- endoreg_db/models/prediction/image_classification.py +51 -0
- endoreg_db/models/prediction/video_prediction_meta.py +306 -0
- endoreg_db/models/product/__init__.py +14 -0
- endoreg_db/models/product/product.py +110 -0
- endoreg_db/models/product/product_group.py +27 -0
- endoreg_db/models/product/product_material.py +28 -0
- endoreg_db/models/product/product_weight.py +38 -0
- endoreg_db/models/product/reference_product.py +115 -0
- endoreg_db/models/questionnaires/__init__.py +114 -0
- endoreg_db/models/quiz/__init__.py +9 -0
- endoreg_db/models/quiz/quiz_answer.py +41 -0
- endoreg_db/models/quiz/quiz_question.py +54 -0
- endoreg_db/models/report_reader/__init__.py +7 -0
- endoreg_db/models/report_reader/report_reader_config.py +53 -0
- endoreg_db/models/report_reader/report_reader_flag.py +20 -0
- endoreg_db/models/rules/__init__.py +5 -0
- endoreg_db/models/rules/rule.py +24 -0
- endoreg_db/models/rules/rule_applicator.py +224 -0
- endoreg_db/models/rules/rule_attribute_dtype.py +19 -0
- endoreg_db/models/rules/rule_type.py +22 -0
- endoreg_db/models/rules/ruleset.py +19 -0
- endoreg_db/models/unit.py +22 -0
- endoreg_db/queries/__init__.py +5 -0
- endoreg_db/queries/annotations/__init__.py +3 -0
- endoreg_db/queries/annotations/legacy.py +158 -0
- endoreg_db/queries/get/__init__.py +6 -0
- endoreg_db/queries/get/annotation.py +0 -0
- endoreg_db/queries/get/center.py +42 -0
- endoreg_db/queries/get/model.py +13 -0
- endoreg_db/queries/get/patient.py +14 -0
- endoreg_db/queries/get/patient_examination.py +20 -0
- endoreg_db/queries/get/prediction.py +0 -0
- endoreg_db/queries/get/report_file.py +33 -0
- endoreg_db/queries/get/video.py +31 -0
- endoreg_db/queries/get/video_import_meta.py +0 -0
- endoreg_db/queries/get/video_prediction_meta.py +0 -0
- endoreg_db/queries/sanity/__init_.py +0 -0
- endoreg_db/serializers/__init__.py +10 -0
- endoreg_db/serializers/ai_model.py +19 -0
- endoreg_db/serializers/annotation.py +14 -0
- endoreg_db/serializers/center.py +11 -0
- endoreg_db/serializers/examination.py +33 -0
- endoreg_db/serializers/frame.py +9 -0
- endoreg_db/serializers/hardware.py +21 -0
- endoreg_db/serializers/label.py +22 -0
- endoreg_db/serializers/patient.py +33 -0
- endoreg_db/serializers/prediction.py +10 -0
- endoreg_db/serializers/raw_video_meta_validation.py +13 -0
- endoreg_db/serializers/report_file.py +7 -0
- endoreg_db/serializers/video.py +20 -0
- endoreg_db/serializers/video_segmentation.py +492 -0
- endoreg_db/templates/admin/patient_finding_intervention.html +253 -0
- endoreg_db/templates/admin/start_examination.html +12 -0
- endoreg_db/templates/timeline.html +176 -0
- endoreg_db/utils/__init__.py +36 -0
- endoreg_db/utils/cropping.py +29 -0
- endoreg_db/utils/dataloader.py +118 -0
- endoreg_db/utils/dates.py +39 -0
- endoreg_db/utils/file_operations.py +30 -0
- endoreg_db/utils/hashs.py +152 -0
- endoreg_db/utils/legacy_ocr.py +201 -0
- endoreg_db/utils/names.py +74 -0
- endoreg_db/utils/ocr.py +190 -0
- endoreg_db/utils/parse_and_generate_yaml.py +46 -0
- endoreg_db/utils/pydantic_models/__init__.py +6 -0
- endoreg_db/utils/pydantic_models/db_config.py +57 -0
- endoreg_db/utils/uuid.py +4 -0
- endoreg_db/utils/validate_endo_roi.py +19 -0
- endoreg_db/utils/validate_subcategory_dict.py +91 -0
- endoreg_db/utils/video/__init__.py +13 -0
- endoreg_db/utils/video/extract_frames.py +121 -0
- endoreg_db/utils/video/transcode_videofile.py +111 -0
- endoreg_db/views/__init__.py +2 -0
- endoreg_db/views/csrf.py +7 -0
- endoreg_db/views/patient_views.py +90 -0
- endoreg_db/views/raw_video_meta_validation_views.py +38 -0
- endoreg_db/views/report_views.py +96 -0
- endoreg_db/views/video_segmentation_views.py +149 -0
- endoreg_db/views/views_for_timeline.py +46 -0
- {endoreg_db-0.6.0.dist-info → endoreg_db-0.6.2.dist-info}/METADATA +14 -4
- endoreg_db-0.6.2.dist-info/RECORD +420 -0
- {endoreg_db-0.6.0.dist-info → endoreg_db-0.6.2.dist-info}/WHEEL +1 -2
- endoreg_db-0.6.0.dist-info/RECORD +0 -11
- endoreg_db-0.6.0.dist-info/top_level.txt +0 -1
- {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
|
+
|