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,253 @@
|
|
|
1
|
+
{% extends "admin/base_site.html" %}
|
|
2
|
+
{% block content %}
|
|
3
|
+
|
|
4
|
+
<h2>Patient Finding Intervention</h2>
|
|
5
|
+
|
|
6
|
+
<form method="POST" id="intervention-form">
|
|
7
|
+
{% csrf_token %}
|
|
8
|
+
|
|
9
|
+
<!-- Patient Selection -->
|
|
10
|
+
<div>
|
|
11
|
+
<label>Select Patient:</label><br>
|
|
12
|
+
<select name="patient" id="patient-dropdown">
|
|
13
|
+
<option value="">-- Select Patient --</option>
|
|
14
|
+
{% for patient in patients %}
|
|
15
|
+
<option value="{{ patient.id }}">{{ patient.first_name }} {{ patient.last_name }}</option>
|
|
16
|
+
{% endfor %}
|
|
17
|
+
</select>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<br>
|
|
21
|
+
|
|
22
|
+
<!-- Examination Selection -->
|
|
23
|
+
<div>
|
|
24
|
+
<label>Select Examination:</label><br>
|
|
25
|
+
<select name="examination" id="examination-dropdown">
|
|
26
|
+
<option value="">-- Select Examination --</option>
|
|
27
|
+
{% for examination in examinations %}
|
|
28
|
+
<option value="{{ examination.id }}">{{ examination.name }}</option>
|
|
29
|
+
{% endfor %}
|
|
30
|
+
</select>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<br>
|
|
34
|
+
|
|
35
|
+
<!-- Finding Selection -->
|
|
36
|
+
<div>
|
|
37
|
+
<label>Select Finding:</label><br>
|
|
38
|
+
<select name="finding" id="finding-dropdown">
|
|
39
|
+
<option value="">-- Select Finding --</option>
|
|
40
|
+
{% for finding in findings %}
|
|
41
|
+
<option value="{{ finding.id }}">{{ finding.name }}</option>
|
|
42
|
+
{% endfor %}
|
|
43
|
+
</select>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<br>
|
|
47
|
+
|
|
48
|
+
<!-- Select Location -->
|
|
49
|
+
<div>
|
|
50
|
+
<label>Select Location:</label><br>
|
|
51
|
+
<select name="location" id="location-dropdown" onchange="updateFormAction(this)">
|
|
52
|
+
<option value="">-- Select Location --</option>
|
|
53
|
+
{% for location in locations %}
|
|
54
|
+
<option value="{{ location.id }}" {% if location.id == selected_location %}selected{% endif %}>
|
|
55
|
+
{{ location.name }}
|
|
56
|
+
</option>
|
|
57
|
+
{% endfor %}
|
|
58
|
+
</select>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<br>
|
|
62
|
+
|
|
63
|
+
<!-- Select Location Choice -->
|
|
64
|
+
<div>
|
|
65
|
+
<label>Select Location Choice:</label><br>
|
|
66
|
+
<select name="location_choice" id="location-choice-dropdown">
|
|
67
|
+
<option value="">-- Select Location Choice --</option>
|
|
68
|
+
{% for choice in location_choices %}
|
|
69
|
+
<option value="{{ choice.id }}">{{ choice.name }}</option>
|
|
70
|
+
{% endfor %}
|
|
71
|
+
</select>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<br>
|
|
75
|
+
|
|
76
|
+
<!-- Select Morphology -->
|
|
77
|
+
<!-- Select Morphology (FindingMorphologyClassification) -->
|
|
78
|
+
<div>
|
|
79
|
+
<label>Select Morphology:</label><br>
|
|
80
|
+
<select name="morphology" id="morphology-dropdown">
|
|
81
|
+
<option value="">-- Select Morphology --</option>
|
|
82
|
+
{% for morphology in morphologies %}
|
|
83
|
+
<option value="{{ morphology.id }}">{{ morphology.name }}</option>
|
|
84
|
+
{% endfor %}
|
|
85
|
+
</select>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<br>
|
|
89
|
+
|
|
90
|
+
<!-- Select Morphology Choice (FindingMorphologyClassificationChoice) -->
|
|
91
|
+
<div>
|
|
92
|
+
<label>Select Morphology Choice:</label><br>
|
|
93
|
+
<select name="morphology_choice" id="morphology-choice-dropdown">
|
|
94
|
+
<option value="">-- Select Morphology Choice --</option>
|
|
95
|
+
{% for choice in morphology_choices %}
|
|
96
|
+
<option value="{{ choice.id }}">{{ choice.name }}</option>
|
|
97
|
+
{% endfor %}
|
|
98
|
+
</select>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
<br>
|
|
103
|
+
|
|
104
|
+
<!-- Select Finding Interventions -->
|
|
105
|
+
<div>
|
|
106
|
+
<label>Select Finding Interventions:</label><br>
|
|
107
|
+
<select name="finding_intervention" id="finding-intervention-dropdown">
|
|
108
|
+
<option value="">-- Select Finding Intervention --</option>
|
|
109
|
+
{% for intervention in finding_interventions %}
|
|
110
|
+
<option value="{{ intervention.id }}">{{ intervention.name }}</option>
|
|
111
|
+
{% endfor %}
|
|
112
|
+
</select>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<br>
|
|
116
|
+
|
|
117
|
+
<div>
|
|
118
|
+
<button type="button" id="generate-report-btn">Generate Report</button>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<!-- Display Report Section -->
|
|
122
|
+
<div id="report-section" style="display:none; margin-top: 20px;">
|
|
123
|
+
<h3>Generated Report</h3>
|
|
124
|
+
<p><strong>Patient:</strong> <span id="report-patient"></span></p>
|
|
125
|
+
<p><strong>Examination:</strong> <span id="report-examination"></span></p>
|
|
126
|
+
<p><strong>Finding:</strong> <span id="report-finding"></span></p>
|
|
127
|
+
<p><strong>Location:</strong> <span id="report-location"></span></p>
|
|
128
|
+
<p><strong>Location Choice:</strong> <span id="report-location-choice"></span></p>
|
|
129
|
+
<p><strong>Morphology:</strong> <span id="report-morphology"></span></p>
|
|
130
|
+
<p><strong>Morphology Choice:</strong> <span id="report-morphology-choice"></span></p>
|
|
131
|
+
<p><strong>Finding Intervention:</strong> <span id="report-finding-intervention"></span></p>
|
|
132
|
+
|
|
133
|
+
<button id="download-report-btn">Download Report</button>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
</form>
|
|
137
|
+
|
|
138
|
+
<script>
|
|
139
|
+
document.getElementById("location-dropdown").addEventListener("change", function() {
|
|
140
|
+
let locationId = this.value;
|
|
141
|
+
let locationChoiceDropdown = document.getElementById("location-choice-dropdown");
|
|
142
|
+
|
|
143
|
+
// Reset dropdown
|
|
144
|
+
locationChoiceDropdown.innerHTML = '<option value="">-- Select Location Choice --</option>';
|
|
145
|
+
|
|
146
|
+
// Fetch Choices Only If a Location is Selected
|
|
147
|
+
if (locationId) {
|
|
148
|
+
fetch(`/endoreg_db/get-location-choices/${locationId}/`)
|
|
149
|
+
.then(response => response.json())
|
|
150
|
+
.then(data => {
|
|
151
|
+
if (data.location_choices.length === 0) {
|
|
152
|
+
locationChoiceDropdown.innerHTML = `<option value="default">Rectum</option>`; // Default Value
|
|
153
|
+
} else {
|
|
154
|
+
data.location_choices.forEach(choice => {
|
|
155
|
+
locationChoiceDropdown.innerHTML += `<option value="${choice.id}">${choice.name}</option>`;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
.catch(error => {
|
|
160
|
+
console.error("Error loading location choices:", error);
|
|
161
|
+
alert("Error: Could not fetch location choices.");
|
|
162
|
+
});
|
|
163
|
+
} else {
|
|
164
|
+
locationChoiceDropdown.innerHTML = `<option value="default">Rectum</option>`; // Default Value
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
</script>
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
<script>
|
|
171
|
+
document.getElementById("generate-report-btn").addEventListener("click", function() {
|
|
172
|
+
let getText = (id, defaultValue = "Not Selected") => {
|
|
173
|
+
let element = document.getElementById(id);
|
|
174
|
+
return element.selectedOptions.length > 0 ? element.selectedOptions[0].text.trim() : defaultValue;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
document.getElementById("report-patient").textContent = getText("patient-dropdown");
|
|
178
|
+
document.getElementById("report-examination").textContent = getText("examination-dropdown");
|
|
179
|
+
document.getElementById("report-finding").textContent = getText("finding-dropdown");
|
|
180
|
+
document.getElementById("report-location").textContent = getText("location-dropdown");
|
|
181
|
+
document.getElementById("report-location-choice").textContent = getText("location-choice-dropdown", "Rectum");
|
|
182
|
+
document.getElementById("report-morphology").textContent = getText("morphology-dropdown");
|
|
183
|
+
document.getElementById("report-morphology-choice").textContent = getText("morphology-choice-dropdown");
|
|
184
|
+
document.getElementById("report-finding-intervention").textContent = getText("finding-intervention-dropdown");
|
|
185
|
+
|
|
186
|
+
document.getElementById("report-section").style.display = "block";
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
document.getElementById("download-report-btn").addEventListener("click", function() {
|
|
190
|
+
let reportContent = `
|
|
191
|
+
Patient: ${document.getElementById("report-patient").textContent}
|
|
192
|
+
Examination: ${document.getElementById("report-examination").textContent}
|
|
193
|
+
Finding: ${document.getElementById("report-finding").textContent}
|
|
194
|
+
Location: ${document.getElementById("report-location").textContent}
|
|
195
|
+
Location Choice: ${document.getElementById("report-location-choice").textContent}
|
|
196
|
+
Morphology: ${document.getElementById("report-morphology").textContent}
|
|
197
|
+
Morphology Choice: ${document.getElementById("report-morphology-choice").textContent}
|
|
198
|
+
Finding Intervention: ${document.getElementById("report-finding-intervention").textContent}
|
|
199
|
+
`;
|
|
200
|
+
|
|
201
|
+
let blob = new Blob([reportContent], { type: "text/plain" });
|
|
202
|
+
let link = document.createElement("a");
|
|
203
|
+
link.href = URL.createObjectURL(blob);
|
|
204
|
+
link.download = "Patient_Finding_Report.txt";
|
|
205
|
+
document.body.appendChild(link);
|
|
206
|
+
link.click();
|
|
207
|
+
document.body.removeChild(link);
|
|
208
|
+
});
|
|
209
|
+
</script>
|
|
210
|
+
|
|
211
|
+
<script>
|
|
212
|
+
document.getElementById("morphology-dropdown").addEventListener("change", function() {
|
|
213
|
+
let morphologyId = this.value;
|
|
214
|
+
let morphologyChoiceDropdown = document.getElementById("morphology-choice-dropdown");
|
|
215
|
+
|
|
216
|
+
// Reset Morphology Choice Dropdown
|
|
217
|
+
morphologyChoiceDropdown.innerHTML = '<option value="">-- Select Morphology Choice --</option>';
|
|
218
|
+
|
|
219
|
+
// Fetch Choices Only If a Morphology is Selected
|
|
220
|
+
if (morphologyId) {
|
|
221
|
+
fetch(`/endoreg_db/get-morphology-choices/${morphologyId}/`)
|
|
222
|
+
.then(response => {
|
|
223
|
+
if (!response.ok) {
|
|
224
|
+
throw new Error(`HTTP error! Status: ${response.status}`);
|
|
225
|
+
}
|
|
226
|
+
return response.json();
|
|
227
|
+
})
|
|
228
|
+
.then(data => {
|
|
229
|
+
if (data.error) {
|
|
230
|
+
console.error("Server Error:", data.error);
|
|
231
|
+
alert("Error: " + data.error);
|
|
232
|
+
} else {
|
|
233
|
+
if (data.morphology_choices.length === 0) {
|
|
234
|
+
morphologyChoiceDropdown.innerHTML = `<option value="default">No Choices Available</option>`; // Default Value
|
|
235
|
+
} else {
|
|
236
|
+
data.morphology_choices.forEach(choice => {
|
|
237
|
+
morphologyChoiceDropdown.innerHTML += `<option value="${choice.id}">${choice.name}</option>`;
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
})
|
|
242
|
+
.catch(error => {
|
|
243
|
+
console.error("Error loading morphology choices:", error);
|
|
244
|
+
alert("Error: Could not fetch morphology choices.");
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
</script>
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
{% endblock %}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!-- start_examination.html -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>Start Examination</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<h1>Hello World</h1>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<title>Frames Timeline (Outside Label)</title>
|
|
5
|
+
<style>
|
|
6
|
+
body { font-family: Arial, sans-serif; text-align: center; margin: 20px; }
|
|
7
|
+
video { width: 80%; margin-bottom: 20px; }
|
|
8
|
+
|
|
9
|
+
/* Timeline Container */
|
|
10
|
+
.timeline-container {
|
|
11
|
+
position: relative;
|
|
12
|
+
width: 80%;
|
|
13
|
+
height: 50px;
|
|
14
|
+
margin: auto;
|
|
15
|
+
background: #f0f0f0;
|
|
16
|
+
border-radius: 5px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Timeline Bar */
|
|
20
|
+
.timeline-bar {
|
|
21
|
+
width: 100%;
|
|
22
|
+
height: 8px;
|
|
23
|
+
background-color: #ccc;
|
|
24
|
+
position: absolute;
|
|
25
|
+
top: 50%;
|
|
26
|
+
transform: translateY(-50%);
|
|
27
|
+
border-radius: 4px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Red Highlight for Outside Label Segments */
|
|
31
|
+
.segment-box {
|
|
32
|
+
position: absolute;
|
|
33
|
+
height: 8px;
|
|
34
|
+
background-color: rgba(255, 0, 0, 0.7);
|
|
35
|
+
border-radius: 4px;
|
|
36
|
+
top: 50%;
|
|
37
|
+
transform: translateY(-50%);
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Draggable Vertical Markers */
|
|
42
|
+
.frame-marker {
|
|
43
|
+
position: absolute;
|
|
44
|
+
width: 6px;
|
|
45
|
+
height: 20px;
|
|
46
|
+
background-color: blue;
|
|
47
|
+
cursor: grab;
|
|
48
|
+
top: 50%;
|
|
49
|
+
transform: translate(-50%, -50%);
|
|
50
|
+
border-radius: 3px;
|
|
51
|
+
transition: background-color 0.2s;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.frame-marker:hover {
|
|
55
|
+
background-color: red;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.frame-marker:active {
|
|
59
|
+
cursor: grabbing;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
</style>
|
|
63
|
+
</head>
|
|
64
|
+
<body>
|
|
65
|
+
<h2>Frames Timeline (Outside Label)</h2>
|
|
66
|
+
|
|
67
|
+
<video id="videoPlayer" controls>
|
|
68
|
+
<source src="{{ video_url }}" type="video/mp4">
|
|
69
|
+
Your browser does not support the video tag.
|
|
70
|
+
</video>
|
|
71
|
+
|
|
72
|
+
<div class="timeline-container">
|
|
73
|
+
<div class="timeline-bar"></div>
|
|
74
|
+
<div id="segments"></div> <!-- Highlighted segments -->
|
|
75
|
+
<div id="frameMarkers"></div> <!-- Start & End markers -->
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<script>
|
|
79
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
80
|
+
const segments = JSON.parse('{{ segments|safe }}'); // Get "outside" label segments
|
|
81
|
+
const video = document.getElementById("videoPlayer");
|
|
82
|
+
const timelineContainer = document.querySelector(".timeline-container");
|
|
83
|
+
const segmentsContainer = document.getElementById("segments");
|
|
84
|
+
const frameMarkersContainer = document.getElementById("frameMarkers");
|
|
85
|
+
|
|
86
|
+
let videoDuration = {{ video_duration|default:1 }}; // Ensure valid duration
|
|
87
|
+
|
|
88
|
+
console.log("Loaded Segments:", segments);
|
|
89
|
+
console.log("Video Duration:", videoDuration);
|
|
90
|
+
|
|
91
|
+
if (segments.length === 0) {
|
|
92
|
+
console.warn("No segments available!");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Create segment boxes
|
|
97
|
+
segments.forEach(segment => {
|
|
98
|
+
const segmentDiv = document.createElement("div");
|
|
99
|
+
segmentDiv.classList.add("segment-box");
|
|
100
|
+
|
|
101
|
+
// Convert times to percentage positions
|
|
102
|
+
let startPercent = (segment.start_time / videoDuration) * 100;
|
|
103
|
+
let endPercent = (segment.end_time / videoDuration) * 100;
|
|
104
|
+
let widthPercent = endPercent - startPercent;
|
|
105
|
+
|
|
106
|
+
// Ensure last segment does not go beyond 100%
|
|
107
|
+
startPercent = Math.min(100, startPercent);
|
|
108
|
+
endPercent = Math.min(100, endPercent);
|
|
109
|
+
widthPercent = Math.max(0, endPercent - startPercent);
|
|
110
|
+
|
|
111
|
+
segmentDiv.style.left = startPercent + "%";
|
|
112
|
+
segmentDiv.style.width = widthPercent + "%";
|
|
113
|
+
|
|
114
|
+
// Clicking on segment seeks video
|
|
115
|
+
segmentDiv.addEventListener("click", function () {
|
|
116
|
+
video.currentTime = segment.start_time;
|
|
117
|
+
video.play();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
segmentsContainer.appendChild(segmentDiv);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Create draggable markers
|
|
124
|
+
segments.forEach(segment => {
|
|
125
|
+
["start_time", "end_time"].forEach(timeType => {
|
|
126
|
+
const marker = document.createElement("div");
|
|
127
|
+
marker.classList.add("frame-marker");
|
|
128
|
+
|
|
129
|
+
// Position marker
|
|
130
|
+
let percent = (segment[timeType] / videoDuration) * 100;
|
|
131
|
+
percent = Math.min(100, Math.max(0, percent)); // Keep within bounds
|
|
132
|
+
marker.style.left = percent + "%";
|
|
133
|
+
|
|
134
|
+
// Store initial marker time
|
|
135
|
+
marker.dataset.time = segment[timeType];
|
|
136
|
+
|
|
137
|
+
// Enable dragging
|
|
138
|
+
let isDragging = false;
|
|
139
|
+
|
|
140
|
+
marker.addEventListener("pointerdown", (event) => {
|
|
141
|
+
isDragging = true;
|
|
142
|
+
marker.style.cursor = "grabbing";
|
|
143
|
+
event.preventDefault();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
document.addEventListener("pointermove", (event) => {
|
|
147
|
+
if (!isDragging) return;
|
|
148
|
+
|
|
149
|
+
const rect = timelineContainer.getBoundingClientRect();
|
|
150
|
+
const offsetX = event.clientX - rect.left;
|
|
151
|
+
let percentX = (offsetX / rect.width) * 100;
|
|
152
|
+
|
|
153
|
+
// Keep marker within bounds (0-100%)
|
|
154
|
+
percentX = Math.min(100, Math.max(0, percentX));
|
|
155
|
+
|
|
156
|
+
const newTime = (percentX / 100) * videoDuration;
|
|
157
|
+
|
|
158
|
+
marker.style.left = percentX + "%";
|
|
159
|
+
video.currentTime = newTime;
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
document.addEventListener("pointerup", () => {
|
|
163
|
+
if (isDragging) {
|
|
164
|
+
isDragging = false;
|
|
165
|
+
marker.style.cursor = "grab";
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
frameMarkersContainer.appendChild(marker);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
});
|
|
174
|
+
</script>
|
|
175
|
+
</body>
|
|
176
|
+
</html>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Module for utility classes and functions."""
|
|
2
|
+
|
|
3
|
+
from .dataloader import load_model_data_from_yaml
|
|
4
|
+
from .parse_and_generate_yaml import collect_center_names
|
|
5
|
+
from .validate_endo_roi import validate_endo_roi
|
|
6
|
+
from .pydantic_models import DbConfig
|
|
7
|
+
from .dates import random_day_by_month_year, random_day_by_year
|
|
8
|
+
from .hashs import (
|
|
9
|
+
get_hash_string,
|
|
10
|
+
get_pdf_hash,
|
|
11
|
+
get_examiner_hash,
|
|
12
|
+
get_video_hash,
|
|
13
|
+
get_patient_examination_hash,
|
|
14
|
+
)
|
|
15
|
+
from .names import (
|
|
16
|
+
create_mock_patient_name,
|
|
17
|
+
create_mock_examiner_name,
|
|
18
|
+
guess_name_gender,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"load_model_data_from_yaml",
|
|
23
|
+
"collect_center_names",
|
|
24
|
+
"validate_endo_roi",
|
|
25
|
+
"get_examiner_hash",
|
|
26
|
+
"DbConfig",
|
|
27
|
+
"random_day_by_month_year",
|
|
28
|
+
"random_day_by_year",
|
|
29
|
+
"get_hash_string",
|
|
30
|
+
"create_mock_examiner_name",
|
|
31
|
+
"create_mock_patient_name",
|
|
32
|
+
"guess_name_gender",
|
|
33
|
+
"get_pdf_hash",
|
|
34
|
+
"get_video_hash",
|
|
35
|
+
"get_patient_examination_hash",
|
|
36
|
+
]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from PIL import Image
|
|
2
|
+
|
|
3
|
+
def crop_and_insert(image:Image, x, y, h, w, bg_color=(255, 255, 255)):
|
|
4
|
+
"""
|
|
5
|
+
Crops a region from an inverted grayscale image and inserts it into a white image of the same size as the original.
|
|
6
|
+
|
|
7
|
+
Parameters:
|
|
8
|
+
- fp: File path or a file object of the original image.
|
|
9
|
+
- x, y: The top-left coordinates of the rectangle to be cropped.
|
|
10
|
+
- h, w: The height and width of the rectangle to be cropped.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
A PIL Image object containing the original image with the specified region replaced.
|
|
14
|
+
"""
|
|
15
|
+
# Load the original image
|
|
16
|
+
original_image = image
|
|
17
|
+
|
|
18
|
+
# Crop the specified region from the inverted image
|
|
19
|
+
crop_rectangle = (x, y, x + w, y + h)
|
|
20
|
+
cropped_content = original_image.crop(crop_rectangle)
|
|
21
|
+
|
|
22
|
+
# Create a new white image of the same size as the original image
|
|
23
|
+
white_background = Image.new('RGB', original_image.size, bg_color)
|
|
24
|
+
|
|
25
|
+
# Paste the cropped content onto the white image at the specified location
|
|
26
|
+
white_background.paste(cropped_content, (x, y))
|
|
27
|
+
|
|
28
|
+
# The final image can be displayed or saved as needed
|
|
29
|
+
return white_background
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import yaml
|
|
3
|
+
from django.core.exceptions import ObjectDoesNotExist
|
|
4
|
+
|
|
5
|
+
from icecream import ic
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def load_model_data_from_yaml(command, model_name, metadata, verbose):
|
|
9
|
+
"""
|
|
10
|
+
Load model data from YAML files.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
command: Command object for stdout writing.
|
|
14
|
+
model_name: Name of the model being loaded.
|
|
15
|
+
metadata: Metadata including directory and foreign key information.
|
|
16
|
+
verbose: Boolean indicating whether to print verbose output.
|
|
17
|
+
"""
|
|
18
|
+
if verbose:
|
|
19
|
+
command.stdout.write(f"Start loading {model_name}")
|
|
20
|
+
model = metadata["model"]
|
|
21
|
+
dir_path = metadata["dir"]
|
|
22
|
+
foreign_keys = metadata["foreign_keys"]
|
|
23
|
+
foreign_key_models = metadata["foreign_key_models"]
|
|
24
|
+
|
|
25
|
+
_files = [f for f in os.listdir(dir_path) if f.endswith(".yaml")]
|
|
26
|
+
# sort
|
|
27
|
+
_files.sort()
|
|
28
|
+
for file in _files:
|
|
29
|
+
with open(os.path.join(dir_path, file), "r", encoding="utf-8") as file:
|
|
30
|
+
yaml_data = yaml.safe_load(file)
|
|
31
|
+
|
|
32
|
+
load_data_with_foreign_keys(
|
|
33
|
+
command, model, yaml_data, foreign_keys, foreign_key_models, verbose
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def load_data_with_foreign_keys(
|
|
38
|
+
command, model, yaml_data, foreign_keys, foreign_key_models, verbose
|
|
39
|
+
):
|
|
40
|
+
"""
|
|
41
|
+
Load data handling foreign keys and many-to-many relationships.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
command: Command object for stdout writing.
|
|
45
|
+
model: The Django model for the data.
|
|
46
|
+
yaml_data: Data loaded from YAML.
|
|
47
|
+
foreign_keys: List of foreign keys.
|
|
48
|
+
foreign_key_models: Corresponding models for the foreign keys.
|
|
49
|
+
verbose: Boolean indicating whether to print verbose output.
|
|
50
|
+
"""
|
|
51
|
+
for entry in yaml_data:
|
|
52
|
+
fields = entry.get("fields", {})
|
|
53
|
+
name = fields.pop("name", None)
|
|
54
|
+
m2m_relationships = {} # Store many-to-many relationships
|
|
55
|
+
# print(entry)
|
|
56
|
+
|
|
57
|
+
# Handle foreign keys and many-to-many relationships
|
|
58
|
+
for fk_field, fk_model in zip(foreign_keys, foreign_key_models):
|
|
59
|
+
# print(fk_field, fk_model)
|
|
60
|
+
target_keys = fields.pop(fk_field, None)
|
|
61
|
+
|
|
62
|
+
# Ensure the foreign key exists
|
|
63
|
+
if target_keys is None:
|
|
64
|
+
if verbose:
|
|
65
|
+
command.stdout.write(
|
|
66
|
+
command.style.WARNING(
|
|
67
|
+
f"Foreign key {fk_field} not found in fields"
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
continue # Skip if no foreign key provided
|
|
71
|
+
|
|
72
|
+
# Process many-to-many fields or foreign keys
|
|
73
|
+
if isinstance(target_keys, list): # Assume many-to-many relationship
|
|
74
|
+
related_objects = []
|
|
75
|
+
for key in target_keys:
|
|
76
|
+
obj, created = fk_model.objects.get_or_create(name=key)
|
|
77
|
+
if created and verbose:
|
|
78
|
+
command.stdout.write(
|
|
79
|
+
command.style.SUCCESS(f"Created {fk_model.__name__} {key}")
|
|
80
|
+
)
|
|
81
|
+
related_objects.append(obj)
|
|
82
|
+
m2m_relationships[fk_field] = related_objects
|
|
83
|
+
else: # Single foreign key relationship
|
|
84
|
+
try:
|
|
85
|
+
if model == "endoreg_db.case_template_rule":
|
|
86
|
+
# print(fk_model, target_keys)
|
|
87
|
+
pass
|
|
88
|
+
obj = fk_model.objects.get_by_natural_key(target_keys)
|
|
89
|
+
except ObjectDoesNotExist:
|
|
90
|
+
if verbose:
|
|
91
|
+
command.stdout.write(
|
|
92
|
+
command.style.WARNING(
|
|
93
|
+
f"{fk_model.__name__} with key {target_keys} not found"
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
continue
|
|
97
|
+
fields[fk_field] = obj
|
|
98
|
+
|
|
99
|
+
# Create or update the main object
|
|
100
|
+
if name is None:
|
|
101
|
+
obj, created = model.objects.get_or_create(**fields)
|
|
102
|
+
else:
|
|
103
|
+
obj, created = model.objects.update_or_create(defaults=fields, name=name)
|
|
104
|
+
if created and verbose:
|
|
105
|
+
command.stdout.write(
|
|
106
|
+
command.style.SUCCESS(f"Created {model.__name__} {name}")
|
|
107
|
+
)
|
|
108
|
+
elif verbose:
|
|
109
|
+
pass
|
|
110
|
+
# command.stdout.write(
|
|
111
|
+
# command.style.WARNING(
|
|
112
|
+
# f"Skipped {model.__name__} {name}, already exists"
|
|
113
|
+
# )
|
|
114
|
+
# )
|
|
115
|
+
|
|
116
|
+
# Set many-to-many relationships
|
|
117
|
+
for field_name, related_objs in m2m_relationships.items():
|
|
118
|
+
getattr(obj, field_name).set(related_objs)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from datetime import datetime, date, timedelta
|
|
2
|
+
from random import randint
|
|
3
|
+
from calendar import monthrange
|
|
4
|
+
|
|
5
|
+
# TODO replace used random_day_by_year function implementation when
|
|
6
|
+
# creating pseudo patients with new function "random date by age_at_date and examination_date"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def random_day_by_age_at_date(age_at_date: int, examination_date: date) -> date:
|
|
10
|
+
"""
|
|
11
|
+
Return a random birth day for a patient with the specified age at the specified examination date.
|
|
12
|
+
"""
|
|
13
|
+
examination_year = examination_date.year
|
|
14
|
+
latest_birthdate = examination_date.replace(year=examination_year - age_at_date)
|
|
15
|
+
valid_dates = [latest_birthdate - timedelta(days=i) for i in range(365)]
|
|
16
|
+
|
|
17
|
+
select = randint(0, len(valid_dates) - 1)
|
|
18
|
+
birth_date = valid_dates[select]
|
|
19
|
+
|
|
20
|
+
return birth_date
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def random_day_by_year(year: int) -> date:
|
|
24
|
+
"""
|
|
25
|
+
Return a random birth day within the specified year.
|
|
26
|
+
"""
|
|
27
|
+
month = randint(1, 12)
|
|
28
|
+
day = randint(1, monthrange(year, month)[1])
|
|
29
|
+
|
|
30
|
+
return date(year, month, day)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def random_day_by_month_year(month: int, year) -> date:
|
|
34
|
+
"""
|
|
35
|
+
Return a random birth day within the specified month and year.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
day = randint(1, monthrange(year, month)[1])
|
|
39
|
+
return date(year, month, day)
|