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,290 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from endoreg_db.utils.hashs import (
|
|
3
|
+
get_patient_hash,
|
|
4
|
+
get_patient_examination_hash,
|
|
5
|
+
# get_hash_string,
|
|
6
|
+
)
|
|
7
|
+
from hashlib import sha256
|
|
8
|
+
|
|
9
|
+
# from datetime import date
|
|
10
|
+
from icecream import ic
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
# get DJANGO_SALT from settings
|
|
14
|
+
SECRET_SALT = os.getenv("DJANGO_SALT", "default_salt")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SensitiveMeta(models.Model):
|
|
18
|
+
examination_date = models.DateField(blank=True, null=True)
|
|
19
|
+
pseudo_patient = models.ForeignKey(
|
|
20
|
+
"Patient",
|
|
21
|
+
on_delete=models.CASCADE,
|
|
22
|
+
blank=True,
|
|
23
|
+
null=True,
|
|
24
|
+
)
|
|
25
|
+
patient_first_name = models.CharField(max_length=255, blank=True, null=True)
|
|
26
|
+
patient_last_name = models.CharField(max_length=255, blank=True, null=True)
|
|
27
|
+
patient_dob = models.DateField(blank=True, null=True)
|
|
28
|
+
pseudo_examination = models.ForeignKey(
|
|
29
|
+
"PatientExamination",
|
|
30
|
+
on_delete=models.CASCADE,
|
|
31
|
+
blank=True,
|
|
32
|
+
null=True,
|
|
33
|
+
)
|
|
34
|
+
patient_gender = models.ForeignKey(
|
|
35
|
+
"Gender",
|
|
36
|
+
on_delete=models.CASCADE,
|
|
37
|
+
blank=True,
|
|
38
|
+
null=True,
|
|
39
|
+
)
|
|
40
|
+
examiners = models.ManyToManyField(
|
|
41
|
+
"Examiner",
|
|
42
|
+
blank=True,
|
|
43
|
+
)
|
|
44
|
+
center = models.ForeignKey(
|
|
45
|
+
"Center",
|
|
46
|
+
on_delete=models.CASCADE,
|
|
47
|
+
blank=True,
|
|
48
|
+
null=True,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
examiner_first_name = models.CharField(max_length=255, blank=True, null=True)
|
|
52
|
+
examiner_last_name = models.CharField(max_length=255, blank=True, null=True)
|
|
53
|
+
|
|
54
|
+
examination_hash = models.CharField(max_length=255, blank=True, null=True)
|
|
55
|
+
patient_hash = models.CharField(max_length=255, blank=True, null=True)
|
|
56
|
+
|
|
57
|
+
endoscope_type = models.CharField(max_length=255, blank=True, null=True)
|
|
58
|
+
endoscope_sn = models.CharField(max_length=255, blank=True, null=True)
|
|
59
|
+
state_verified = models.BooleanField(default=False)
|
|
60
|
+
state_hash_generated = models.BooleanField(default=False)
|
|
61
|
+
state_names_substituted = models.BooleanField(default=False)
|
|
62
|
+
state_dob_substituted = models.BooleanField(default=False)
|
|
63
|
+
state_examination_date_substituted = models.BooleanField(default=False)
|
|
64
|
+
state_endoscope_sn_substituted = models.BooleanField(default=False)
|
|
65
|
+
state_examiners_substituted = models.BooleanField(default=False)
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def create_from_dict(cls, data: dict):
|
|
69
|
+
from endoreg_db.models import Center, Examiner
|
|
70
|
+
from endoreg_db.utils import guess_name_gender
|
|
71
|
+
|
|
72
|
+
# data can contain more fields than the model has
|
|
73
|
+
field_names = [_.name for _ in cls._meta.fields]
|
|
74
|
+
selected_data = {k: v for k, v in data.items() if k in field_names}
|
|
75
|
+
|
|
76
|
+
first_name = selected_data.get("patient_first_name")
|
|
77
|
+
last_name = selected_data.get("patient_last_name")
|
|
78
|
+
center_name = data.get("center_name")
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
center = Center.objects.get_by_natural_key(center_name)
|
|
82
|
+
except Exception as exc:
|
|
83
|
+
raise ValueError(f"Center with name {center_name} does not exist") from exc
|
|
84
|
+
|
|
85
|
+
selected_data["center"] = center
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
# TODO Add to documentation and replace with better method
|
|
89
|
+
gender = guess_name_gender(first_name)
|
|
90
|
+
except:
|
|
91
|
+
raise ValueError(f"Gender for name {first_name} could not be guessed")
|
|
92
|
+
|
|
93
|
+
selected_data["patient_gender"] = gender
|
|
94
|
+
|
|
95
|
+
if first_name and last_name:
|
|
96
|
+
# TODO Add to documentation
|
|
97
|
+
cls._update_name_db(first_name, last_name)
|
|
98
|
+
|
|
99
|
+
sensitive_meta = cls.objects.create(**selected_data)
|
|
100
|
+
sensitive_meta.get_or_create_pseudo_examiner()
|
|
101
|
+
sensitive_meta.get_or_create_pseudo_patient()
|
|
102
|
+
sensitive_meta.get_or_create_pseudo_patient_examination()
|
|
103
|
+
|
|
104
|
+
ic("EXAMINER_FIRST_NAME", sensitive_meta.examiner_first_name)
|
|
105
|
+
ic("EXAMINER_LAST_NAME", sensitive_meta.examiner_last_name)
|
|
106
|
+
|
|
107
|
+
return sensitive_meta
|
|
108
|
+
|
|
109
|
+
def get_or_create_pseudo_examiner(self):
|
|
110
|
+
ic("GETTING OR CREATING EXAMINER")
|
|
111
|
+
|
|
112
|
+
if self.examiners.exists():
|
|
113
|
+
examiner = self.examiners.first()
|
|
114
|
+
ic(f"Exisiting examiner: {examiner}")
|
|
115
|
+
|
|
116
|
+
else:
|
|
117
|
+
examiner = self.create_pseudo_examiner()
|
|
118
|
+
ic(f"Created examiner: {examiner}")
|
|
119
|
+
|
|
120
|
+
return examiner
|
|
121
|
+
|
|
122
|
+
def create_pseudo_examiner(self):
|
|
123
|
+
from endoreg_db.models import Examiner, Center
|
|
124
|
+
|
|
125
|
+
first_name = self.examiner_first_name
|
|
126
|
+
last_name = self.examiner_last_name
|
|
127
|
+
center = self.center
|
|
128
|
+
ic("CREATING EXAMINER", first_name, last_name, center)
|
|
129
|
+
if not first_name or not last_name or not center:
|
|
130
|
+
default_center = Center.objects.get_by_natural_key("endoreg_db_demo")
|
|
131
|
+
examiner, _created = Examiner.custom_get_or_create(
|
|
132
|
+
first_name="Unknown", last_name="Unknown", center=default_center
|
|
133
|
+
)
|
|
134
|
+
else:
|
|
135
|
+
examiner, _created = Examiner.custom_get_or_create(
|
|
136
|
+
first_name=first_name, last_name=last_name, center=center
|
|
137
|
+
)
|
|
138
|
+
self.examiners.add(examiner)
|
|
139
|
+
self.save()
|
|
140
|
+
|
|
141
|
+
return examiner
|
|
142
|
+
|
|
143
|
+
def get_or_create_pseudo_patient(self):
|
|
144
|
+
if not self.pseudo_patient:
|
|
145
|
+
self.pseudo_patient = self.create_pseudo_patient()
|
|
146
|
+
self.save()
|
|
147
|
+
return self.pseudo_patient
|
|
148
|
+
|
|
149
|
+
def create_pseudo_patient(self):
|
|
150
|
+
from endoreg_db.models import Patient
|
|
151
|
+
from datetime import date
|
|
152
|
+
|
|
153
|
+
dob = self.patient_dob
|
|
154
|
+
|
|
155
|
+
if isinstance(dob, str):
|
|
156
|
+
dob = date.fromisoformat(dob)
|
|
157
|
+
|
|
158
|
+
month = dob.month
|
|
159
|
+
year = dob.year
|
|
160
|
+
|
|
161
|
+
patient_hash = self.get_patient_hash()
|
|
162
|
+
patient, _created = Patient.get_or_create_pseudo_patient_by_hash(
|
|
163
|
+
patient_hash=patient_hash,
|
|
164
|
+
center=self.center,
|
|
165
|
+
gender=self.patient_gender,
|
|
166
|
+
birth_year=year,
|
|
167
|
+
birth_month=month,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
return patient
|
|
171
|
+
|
|
172
|
+
def get_or_create_pseudo_patient_examination(self):
|
|
173
|
+
from endoreg_db.models import PatientExamination
|
|
174
|
+
|
|
175
|
+
patient_hash = self.get_patient_hash()
|
|
176
|
+
examination_hash = self.get_patient_examination_hash()
|
|
177
|
+
|
|
178
|
+
patient_examination, _created = (
|
|
179
|
+
PatientExamination.get_or_create_pseudo_patient_examination_by_hash(
|
|
180
|
+
patient_hash, examination_hash
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
self.pseudo_examination = patient_examination
|
|
185
|
+
|
|
186
|
+
return patient_examination
|
|
187
|
+
|
|
188
|
+
def update_from_dict(self, data: dict):
|
|
189
|
+
# data can contain more fields than the model has
|
|
190
|
+
field_names = [_.name for _ in self._meta.fields]
|
|
191
|
+
selected_data = {k: v for k, v in data.items() if k in field_names}
|
|
192
|
+
|
|
193
|
+
for k, v in selected_data.items():
|
|
194
|
+
setattr(self, k, v)
|
|
195
|
+
|
|
196
|
+
self.save()
|
|
197
|
+
first_name = self.patient_first_name
|
|
198
|
+
last_name = self.patient_last_name
|
|
199
|
+
|
|
200
|
+
if first_name and last_name:
|
|
201
|
+
SensitiveMeta._update_name_db(first_name=first_name, last_name=last_name)
|
|
202
|
+
|
|
203
|
+
if not self.examination_hash:
|
|
204
|
+
self.examination_hash = self.get_patient_examination_hash()
|
|
205
|
+
if not self.patient_hash:
|
|
206
|
+
self.patient_hash = self.get_patient_hash()
|
|
207
|
+
|
|
208
|
+
examiner_first_name = data.get("examiner_first_name", "")
|
|
209
|
+
examiner_last_name = data.get("examiner_last_name", "")
|
|
210
|
+
|
|
211
|
+
if examiner_first_name and examiner_last_name:
|
|
212
|
+
self.examiner_first_name = examiner_first_name
|
|
213
|
+
self.examiner_last_name = examiner_last_name
|
|
214
|
+
_examiner = self.get_or_create_pseudo_examiner()
|
|
215
|
+
|
|
216
|
+
return self
|
|
217
|
+
|
|
218
|
+
def __str__(self):
|
|
219
|
+
result_str = "SensitiveMeta:"
|
|
220
|
+
result_str += f"\tExamination Date: {self.examination_date}"
|
|
221
|
+
result_str += f"\tFirst Name: {self.patient_first_name}"
|
|
222
|
+
result_str += f"\tLast Name: {self.patient_last_name}"
|
|
223
|
+
result_str += f"\tDate of Birth: (*{self.patient_dob})"
|
|
224
|
+
result_str += f"\tGender: {self.patient_gender}"
|
|
225
|
+
result_str += f"\tCenter: {self.center}"
|
|
226
|
+
result_str += f"\tExaminers: {self.examiners.all()}"
|
|
227
|
+
result_str += f"\tEndoscope Type: {self.endoscope_type}"
|
|
228
|
+
result_str += f"\tEndoscope SN: {self.endoscope_sn}"
|
|
229
|
+
result_str += f"\tState Verified: {self.state_verified}"
|
|
230
|
+
result_str += f"\tPatient Hash: {self.patient_hash}"
|
|
231
|
+
result_str += f"\tExamination Hash: {self.examination_hash}"
|
|
232
|
+
|
|
233
|
+
return result_str
|
|
234
|
+
|
|
235
|
+
def __repr__(self):
|
|
236
|
+
return self.__str__()
|
|
237
|
+
|
|
238
|
+
def get_patient_hash(self, salt=SECRET_SALT):
|
|
239
|
+
dob = self.patient_dob
|
|
240
|
+
first_name = self.patient_first_name
|
|
241
|
+
last_name = self.patient_last_name
|
|
242
|
+
center = self.center
|
|
243
|
+
|
|
244
|
+
assert dob, "Patient DOB is required"
|
|
245
|
+
assert center, "Center is required"
|
|
246
|
+
|
|
247
|
+
hash_str = get_patient_hash(
|
|
248
|
+
first_name=first_name,
|
|
249
|
+
last_name=last_name,
|
|
250
|
+
dob=dob,
|
|
251
|
+
center=self.center.name,
|
|
252
|
+
salt=salt,
|
|
253
|
+
)
|
|
254
|
+
return sha256(hash_str.encode()).hexdigest()
|
|
255
|
+
|
|
256
|
+
def get_patient_examination_hash(self, salt=SECRET_SALT):
|
|
257
|
+
dob = self.patient_dob
|
|
258
|
+
first_name = self.patient_first_name
|
|
259
|
+
last_name = self.patient_last_name
|
|
260
|
+
examination_date = self.examination_date
|
|
261
|
+
center = self.center
|
|
262
|
+
|
|
263
|
+
assert dob, "Patient DOB is required"
|
|
264
|
+
assert examination_date, "Examination date is required"
|
|
265
|
+
|
|
266
|
+
hash_str = get_patient_examination_hash(
|
|
267
|
+
first_name=first_name,
|
|
268
|
+
last_name=last_name,
|
|
269
|
+
dob=dob,
|
|
270
|
+
examination_date=examination_date,
|
|
271
|
+
center=center.name,
|
|
272
|
+
salt=salt,
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
return sha256(hash_str.encode()).hexdigest()
|
|
276
|
+
|
|
277
|
+
# override save method to update hashes
|
|
278
|
+
def save(self, *args, **kwargs):
|
|
279
|
+
self.examination_hash = self.get_patient_examination_hash()
|
|
280
|
+
self.patient_hash = self.get_patient_hash()
|
|
281
|
+
self.pseudo_patient = self.create_pseudo_patient()
|
|
282
|
+
self.pseudo_examination = self.get_or_create_pseudo_patient_examination()
|
|
283
|
+
super().save(*args, **kwargs)
|
|
284
|
+
|
|
285
|
+
@classmethod
|
|
286
|
+
def _update_name_db(cls, first_name, last_name):
|
|
287
|
+
from endoreg_db.models import FirstName, LastName
|
|
288
|
+
|
|
289
|
+
FirstName.objects.get_or_create(name=first_name)
|
|
290
|
+
LastName.objects.get_or_create(name=last_name)
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
import subprocess
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Optional, TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
# import endoreg_center_id from django settings
|
|
8
|
+
from django.conf import settings
|
|
9
|
+
|
|
10
|
+
# check if endoreg_center_id is set
|
|
11
|
+
if not hasattr(settings, "ENDOREG_CENTER_ID"):
|
|
12
|
+
ENDOREG_CENTER_ID = 9999
|
|
13
|
+
else:
|
|
14
|
+
ENDOREG_CENTER_ID = settings.ENDOREG_CENTER_ID
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from endoreg_db.models import EndoscopyProcessor, Endoscope, Center
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# VideoMeta
|
|
21
|
+
class VideoMeta(models.Model):
|
|
22
|
+
processor = models.ForeignKey(
|
|
23
|
+
"EndoscopyProcessor", on_delete=models.CASCADE, blank=True, null=True
|
|
24
|
+
)
|
|
25
|
+
endoscope = models.ForeignKey(
|
|
26
|
+
"Endoscope", on_delete=models.CASCADE, blank=True, null=True
|
|
27
|
+
)
|
|
28
|
+
center = models.ForeignKey("Center", on_delete=models.CASCADE)
|
|
29
|
+
import_meta = models.OneToOneField(
|
|
30
|
+
"VideoImportMeta", on_delete=models.CASCADE, blank=True, null=True
|
|
31
|
+
)
|
|
32
|
+
ffmpeg_meta = models.OneToOneField(
|
|
33
|
+
"FFMpegMeta", on_delete=models.CASCADE, blank=True, null=True
|
|
34
|
+
) ##
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def create_from_file(
|
|
38
|
+
cls,
|
|
39
|
+
file_path: Path,
|
|
40
|
+
center: Optional["Center"],
|
|
41
|
+
processor: Optional["EndoscopyProcessor"] = None,
|
|
42
|
+
endoscope: Optional["Endoscope"] = None,
|
|
43
|
+
):
|
|
44
|
+
"""Create a new VideoMeta from a file."""
|
|
45
|
+
meta = cls.objects.create(center=center)
|
|
46
|
+
meta.update_meta(file_path)
|
|
47
|
+
|
|
48
|
+
if processor:
|
|
49
|
+
meta.processor = processor
|
|
50
|
+
meta.get_endo_roi()
|
|
51
|
+
if endoscope:
|
|
52
|
+
meta.endoscope = endoscope
|
|
53
|
+
|
|
54
|
+
meta.save()
|
|
55
|
+
|
|
56
|
+
return meta
|
|
57
|
+
|
|
58
|
+
def __str__(self):
|
|
59
|
+
processor_name = self.processor.name if self.processor is not None else "None"
|
|
60
|
+
endoscope_name = self.endoscope.name if self.endoscope is not None else "None"
|
|
61
|
+
center_name = self.center.name if self.center is not None else "None"
|
|
62
|
+
ffmpeg_meta_str = self.ffmpeg_meta.__str__()
|
|
63
|
+
import_meta_str = self.import_meta.__str__()
|
|
64
|
+
|
|
65
|
+
result_html = ""
|
|
66
|
+
|
|
67
|
+
result_html += f"Processor: {processor_name}\n"
|
|
68
|
+
result_html += f"Endoscope: {endoscope_name}\n"
|
|
69
|
+
result_html += f"Center: {center_name}\n"
|
|
70
|
+
result_html += f"FFMpeg Meta: {ffmpeg_meta_str}\n"
|
|
71
|
+
result_html += f"Import Meta: {import_meta_str}\n"
|
|
72
|
+
|
|
73
|
+
return result_html
|
|
74
|
+
|
|
75
|
+
# import meta should be created when video meta is created
|
|
76
|
+
def save(self, *args, **kwargs):
|
|
77
|
+
if self.import_meta is None:
|
|
78
|
+
self.import_meta = VideoImportMeta.objects.create()
|
|
79
|
+
super(VideoMeta, self).save(*args, **kwargs)
|
|
80
|
+
|
|
81
|
+
def initialize_ffmpeg_meta(self, file_path):
|
|
82
|
+
"""Initializes FFMpeg metadata for the video file if not already done."""
|
|
83
|
+
self.ffmpeg_meta = FFMpegMeta.create_from_file(Path(file_path))
|
|
84
|
+
self.save()
|
|
85
|
+
|
|
86
|
+
def update_meta(self, file_path):
|
|
87
|
+
"""Updates the video metadata from the file."""
|
|
88
|
+
self.initialize_ffmpeg_meta(file_path)
|
|
89
|
+
self.save()
|
|
90
|
+
|
|
91
|
+
def get_endo_roi(self):
|
|
92
|
+
from endoreg_db.models import EndoscopyProcessor
|
|
93
|
+
|
|
94
|
+
processor: EndoscopyProcessor = self.processor
|
|
95
|
+
endo_roi = processor.get_roi_endoscope_image()
|
|
96
|
+
return endo_roi
|
|
97
|
+
|
|
98
|
+
def get_fps(self):
|
|
99
|
+
if not self.ffmpeg_meta:
|
|
100
|
+
return None
|
|
101
|
+
|
|
102
|
+
return self.ffmpeg_meta.frame_rate
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class FFMpegMeta(models.Model):
|
|
106
|
+
# Existing fields
|
|
107
|
+
duration = models.FloatField(blank=True, null=True)
|
|
108
|
+
width = models.IntegerField(blank=True, null=True)
|
|
109
|
+
height = models.IntegerField(blank=True, null=True)
|
|
110
|
+
frame_rate = models.FloatField(blank=True, null=True)
|
|
111
|
+
|
|
112
|
+
# New fields for comprehensive information
|
|
113
|
+
video_codec = models.CharField(max_length=50, blank=True, null=True)
|
|
114
|
+
audio_codec = models.CharField(max_length=50, blank=True, null=True)
|
|
115
|
+
audio_channels = models.IntegerField(blank=True, null=True)
|
|
116
|
+
audio_sample_rate = models.IntegerField(blank=True, null=True)
|
|
117
|
+
|
|
118
|
+
# Existing __str__ method can be updated to include new fields
|
|
119
|
+
|
|
120
|
+
@classmethod
|
|
121
|
+
def create_from_file(cls, file_path: Path):
|
|
122
|
+
cmd = [
|
|
123
|
+
"ffprobe",
|
|
124
|
+
"-v",
|
|
125
|
+
"quiet",
|
|
126
|
+
"-print_format",
|
|
127
|
+
"json",
|
|
128
|
+
"-show_streams",
|
|
129
|
+
str(file_path),
|
|
130
|
+
]
|
|
131
|
+
proc = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
132
|
+
probe = json.loads(proc.stdout)
|
|
133
|
+
|
|
134
|
+
video_stream = next(
|
|
135
|
+
(stream for stream in probe["streams"] if stream["codec_type"] == "video"),
|
|
136
|
+
None,
|
|
137
|
+
)
|
|
138
|
+
audio_streams = [
|
|
139
|
+
stream for stream in probe["streams"] if stream["codec_type"] == "audio"
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
if not video_stream:
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
metadata = {
|
|
146
|
+
"duration": float(video_stream.get("duration", 0)),
|
|
147
|
+
"width": int(video_stream.get("width", 0)),
|
|
148
|
+
"height": int(video_stream.get("height", 0)),
|
|
149
|
+
"frame_rate": float(
|
|
150
|
+
next(iter(video_stream.get("avg_frame_rate", "").split("/")), 0)
|
|
151
|
+
),
|
|
152
|
+
"video_codec": video_stream.get("codec_name", ""),
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if audio_streams:
|
|
156
|
+
first_audio_stream = audio_streams[0]
|
|
157
|
+
metadata.update(
|
|
158
|
+
{
|
|
159
|
+
"audio_codec": first_audio_stream.get("codec_name", ""),
|
|
160
|
+
"audio_channels": int(first_audio_stream.get("channels", 0)),
|
|
161
|
+
"audio_sample_rate": int(first_audio_stream.get("sample_rate", 0)),
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
return cls.objects.create(**metadata)
|
|
166
|
+
|
|
167
|
+
def __str__(self):
|
|
168
|
+
result_html = ""
|
|
169
|
+
|
|
170
|
+
result_html += f"Duration: {self.duration}\n"
|
|
171
|
+
result_html += f"Width: {self.width}\n"
|
|
172
|
+
result_html += f"Height: {self.height}\n"
|
|
173
|
+
result_html += f"Frame Rate: {self.frame_rate}\n"
|
|
174
|
+
result_html += f"Video Codec: {self.video_codec}\n"
|
|
175
|
+
result_html += f"Audio Codec: {self.audio_codec}\n"
|
|
176
|
+
result_html += f"Audio Channels: {self.audio_channels}\n"
|
|
177
|
+
result_html += f"Audio Sample Rate: {self.audio_sample_rate}\n"
|
|
178
|
+
|
|
179
|
+
return result_html
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class VideoImportMeta(models.Model):
|
|
183
|
+
video_anonymized = models.BooleanField(default=False)
|
|
184
|
+
video_patient_data_detected = models.BooleanField(default=False)
|
|
185
|
+
outside_detected = models.BooleanField(default=False)
|
|
186
|
+
patient_data_removed = models.BooleanField(default=False)
|
|
187
|
+
outside_removed = models.BooleanField(default=False)
|
|
188
|
+
|
|
189
|
+
def __str__(self):
|
|
190
|
+
result_html = ""
|
|
191
|
+
|
|
192
|
+
result_html += f"Video anonymized: {self.video_anonymized}\n"
|
|
193
|
+
result_html += (
|
|
194
|
+
f"Video patient data detected: {self.video_patient_data_detected}\n"
|
|
195
|
+
)
|
|
196
|
+
result_html += f"Outside detected: {self.outside_detected}\n"
|
|
197
|
+
result_html += f"Patient data removed: {self.patient_data_removed}\n"
|
|
198
|
+
result_html += f"Outside removed: {self.outside_removed}\n"
|
|
199
|
+
return result_html
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from datetime import date, time
|
|
2
|
+
from django.db import models
|
|
3
|
+
from .base_classes.abstract_pdf import AbstractPdfFile
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ReportFile(AbstractPdfFile):
|
|
7
|
+
meta = models.JSONField(blank=True, null=True)
|
|
8
|
+
text = models.TextField(blank=True, null=True)
|
|
9
|
+
# sensitive_meta = models.ForeignKey(
|
|
10
|
+
# "SensitiveMeta",
|
|
11
|
+
# on_delete=models.SET_NULL,
|
|
12
|
+
# related_name="report_files",
|
|
13
|
+
# null=True,
|
|
14
|
+
# blank=True,
|
|
15
|
+
# )
|
|
16
|
+
# examination = models.ForeignKey(
|
|
17
|
+
# "PatientExamination",
|
|
18
|
+
# on_delete=models.SET_NULL,
|
|
19
|
+
# blank=True,
|
|
20
|
+
# null=True,
|
|
21
|
+
# related_name="report_files",
|
|
22
|
+
# )
|
|
23
|
+
# patient = models.ForeignKey(
|
|
24
|
+
# "Patient", on_delete=models.DO_NOTHING, blank=True, null=True
|
|
25
|
+
# )
|
|
26
|
+
# examiner = models.ForeignKey(
|
|
27
|
+
# "Examiner", on_delete=models.DO_NOTHING, blank=True, null=True
|
|
28
|
+
# )
|
|
29
|
+
date = models.DateField(blank=True, null=True)
|
|
30
|
+
time = models.TimeField(blank=True, null=True)
|
|
31
|
+
|
|
32
|
+
def get_or_create_examiner(self, examiner_first_name, examiner_last_name):
|
|
33
|
+
from ..persons import Examiner
|
|
34
|
+
|
|
35
|
+
examiner_center = self.center
|
|
36
|
+
|
|
37
|
+
examiner, created = Examiner.objects.get_or_create(
|
|
38
|
+
first_name=examiner_first_name,
|
|
39
|
+
last_name=examiner_last_name,
|
|
40
|
+
center=examiner_center,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
return examiner, created
|
|
44
|
+
|
|
45
|
+
def set_examination_date_and_time(self, report_meta=None):
|
|
46
|
+
if not report_meta:
|
|
47
|
+
report_meta = self.meta
|
|
48
|
+
examination_date_str = report_meta["examination_date"]
|
|
49
|
+
examination_time_str = report_meta["examination_time"]
|
|
50
|
+
|
|
51
|
+
if examination_date_str:
|
|
52
|
+
# TODO: get django DateField compatible date from string (e.g. "2021-01-01")
|
|
53
|
+
self.date = date.fromisoformat(examination_date_str)
|
|
54
|
+
if examination_time_str:
|
|
55
|
+
# TODO: get django TimeField compatible time from string (e.g. "12:00")
|
|
56
|
+
self.time = time.fromisoformat(examination_time_str)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# from django.db import models
|
|
2
|
+
|
|
3
|
+
# class VideoImportMeta(models.Model):
|
|
4
|
+
# processor = models.ForeignKey('EndoscopyProcessor', on_delete=models.CASCADE)
|
|
5
|
+
# endoscope = models.ForeignKey('Endoscope', on_delete=models.CASCADE, blank=True, null=True)
|
|
6
|
+
# center = models.ForeignKey('Center', on_delete=models.CASCADE)
|
|
7
|
+
# video_anonymized = models.BooleanField(default=False)
|
|
8
|
+
# video_patient_data_detected = models.BooleanField(default=False)
|
|
9
|
+
# outside_detected = models.BooleanField(default=False)
|
|
10
|
+
# patient_data_removed = models.BooleanField(default=False)
|
|
11
|
+
# outside_removed = models.BooleanField(default=False)
|
|
12
|
+
|
|
13
|
+
# def __str__(self):
|
|
14
|
+
# result_html = ""
|
|
15
|
+
|
|
16
|
+
# result_html += f"Processor: {self.processor.name}<br>"
|
|
17
|
+
# result_html += f"Endoscope: {self.endoscope.name}<br>"
|
|
18
|
+
# result_html += f"Center: {self.center.name}<br>"
|
|
19
|
+
# result_html += f"Video anonymized: {self.video_anonymized}<br>"
|
|
20
|
+
# result_html += f"Video patient data detected: {self.video_patient_data_detected}<br>"
|
|
21
|
+
# result_html += f"Outside detected: {self.outside_detected}<br>"
|
|
22
|
+
# result_html += f"Patient data removed: {self.patient_data_removed}<br>"
|
|
23
|
+
# result_html += f"Outside removed: {self.outside_removed}<br>"
|
|
24
|
+
# return result_html
|
|
25
|
+
|