endoreg-db 0.8.9.32__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/__init__.py +0 -0
- endoreg_db/_version.py +34 -0
- endoreg_db/admin.py +97 -0
- endoreg_db/api/serializers/finding_descriptions.py +0 -0
- endoreg_db/api/views/finding_descriptions.py +0 -0
- endoreg_db/api_urls.py +4 -0
- endoreg_db/apps.py +17 -0
- endoreg_db/assets/dummy_model.ckpt +1 -0
- endoreg_db/authz/auth.py +78 -0
- endoreg_db/authz/backends.py +168 -0
- endoreg_db/authz/management/commands/list_routes.py +20 -0
- endoreg_db/authz/middleware.py +84 -0
- endoreg_db/authz/permissions.py +138 -0
- endoreg_db/authz/policy.py +224 -0
- endoreg_db/authz/settings.py +64 -0
- endoreg_db/authz/views_auth.py +70 -0
- endoreg_db/codemods/readme.md +88 -0
- endoreg_db/codemods/rename_datetime_fields.py +99 -0
- endoreg_db/config/__init__.py +0 -0
- endoreg_db/config/env.py +106 -0
- endoreg_db/config/settings/__init__.py +6 -0
- endoreg_db/config/settings/base.py +148 -0
- endoreg_db/config/settings/case_gen.py +32 -0
- endoreg_db/config/settings/dev.py +108 -0
- endoreg_db/config/settings/keycloak.py +177 -0
- endoreg_db/config/settings/prod.py +66 -0
- endoreg_db/config/settings/test.py +72 -0
- endoreg_db/data/__init__.py +135 -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/polyp_classification.yaml +52 -0
- endoreg_db/data/ai_model_label/label-set/data.yaml +40 -0
- endoreg_db/data/ai_model_label/label-set/polyp_classifications.yaml +25 -0
- endoreg_db/data/ai_model_label/label-type/data.yaml +7 -0
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +27 -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 +99 -0
- endoreg_db/data/center_resource/green_endoscopy_dashboard_CenterResource.yaml +144 -0
- endoreg_db/data/center_shift/ukw.yaml +9 -0
- endoreg_db/data/center_waste/green_endoscopy_dashboard_CenterWaste.yaml +48 -0
- endoreg_db/data/contraindication/bleeding.yaml +11 -0
- endoreg_db/data/db_summary.csv +58 -0
- endoreg_db/data/db_summary.xlsx +0 -0
- endoreg_db/data/disease/cardiovascular.yaml +37 -0
- endoreg_db/data/disease/hepatology.yaml +5 -0
- endoreg_db/data/disease/misc.yaml +5 -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 +50 -0
- endoreg_db/data/event/cardiology.yaml +15 -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/event_classification/data.yaml +4 -0
- endoreg_db/data/event_classification_choice/data.yaml +9 -0
- endoreg_db/data/examination/examinations/data.yaml +172 -0
- endoreg_db/data/examination/time/data.yaml +48 -0
- endoreg_db/data/examination/time-type/data.yaml +5 -0
- endoreg_db/data/examination/type/data.yaml +17 -0
- endoreg_db/data/examination_indication/endoscopy.yaml +359 -0
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +90 -0
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +97 -0
- endoreg_db/data/examination_requirement_set/colonoscopy.yaml +15 -0
- endoreg_db/data/finding/00_generic.yaml +35 -0
- endoreg_db/data/finding/00_generic_complication.yaml +9 -0
- endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
- endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
- endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
- endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
- endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
- endoreg_db/data/finding_classification/00_generic.yaml +44 -0
- endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
- endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
- endoreg_db/data/finding_classification/02_colonoscopy_baseline.yaml +83 -0
- endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
- endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
- endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
- endoreg_db/data/finding_classification_choice/00_generic.yaml +15 -0
- endoreg_db/data/finding_classification_choice/00_generic_baseline.yaml +23 -0
- endoreg_db/data/finding_classification_choice/00_generic_complication.yaml +15 -0
- endoreg_db/data/finding_classification_choice/00_generic_histology.yaml +21 -0
- endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_bowel_preparation.yaml +49 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_generic.yaml +19 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_histology.yaml +20 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_location.yaml +248 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_morphology.yaml +75 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
- endoreg_db/data/finding_classification_type/00_generic.yaml +53 -0
- endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
- endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
- endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
- endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
- endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/finding_type/data.yaml +39 -0
- endoreg_db/data/gender/data.yaml +42 -0
- endoreg_db/data/information_source/annotation.yaml +6 -0
- endoreg_db/data/information_source/data.yaml +30 -0
- endoreg_db/data/information_source/endoscopy_guidelines.yaml +7 -0
- endoreg_db/data/information_source/medication.yaml +6 -0
- endoreg_db/data/information_source/prediction.yaml +7 -0
- endoreg_db/data/information_source_type/data.yaml +8 -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 +76 -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 +54 -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 +46 -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/qualification/endoscopy.yaml +36 -0
- endoreg_db/data/qualification/m2.yaml +39 -0
- endoreg_db/data/qualification/outpatient_clinic.yaml +35 -0
- endoreg_db/data/qualification/sonography.yaml +36 -0
- endoreg_db/data/qualification_type/base.yaml +29 -0
- endoreg_db/data/reference_product/green_endoscopy_dashboard_ReferenceProduct.yaml +55 -0
- endoreg_db/data/report_reader_flag/rkh-histology-generic.yaml +10 -0
- endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +30 -0
- endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +24 -0
- endoreg_db/data/requirement/01_patient_data.yaml +93 -0
- endoreg_db/data/requirement/old/colon_polyp_intervention.yaml +49 -0
- endoreg_db/data/requirement/old/colonoscopy_baseline_austria.yaml +45 -0
- endoreg_db/data/requirement/old/coloreg_colon_polyp.yaml +49 -0
- endoreg_db/data/requirement/old/disease_cardiovascular.yaml +79 -0
- endoreg_db/data/requirement/old/disease_classification_choice_cardiovascular.yaml +41 -0
- endoreg_db/data/requirement/old/disease_hepatology.yaml +12 -0
- endoreg_db/data/requirement/old/disease_misc.yaml +12 -0
- endoreg_db/data/requirement/old/disease_renal.yaml +96 -0
- endoreg_db/data/requirement/old/endoscopy_bleeding_risk.yaml +59 -0
- endoreg_db/data/requirement/old/event_cardiology.yaml +251 -0
- endoreg_db/data/requirement/old/event_requirements.yaml +145 -0
- endoreg_db/data/requirement/old/finding_colon_polyp.yaml +50 -0
- endoreg_db/data/requirement/old/gender.yaml +0 -0
- endoreg_db/data/requirement/old/lab_value.yaml +441 -0
- endoreg_db/data/requirement/old/medication.yaml +93 -0
- endoreg_db/data/requirement_operator/_old/age.yaml +13 -0
- endoreg_db/data/requirement_operator/_old/lab_operators.yaml +129 -0
- endoreg_db/data/requirement_operator/_old/model_operators.yaml +96 -0
- endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +65 -0
- endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
- endoreg_db/data/requirement_set/02_endoscopy_bleeding_risk.yaml +46 -0
- endoreg_db/data/requirement_set/90_coloreg.yaml +190 -0
- endoreg_db/data/requirement_set/_old_ +109 -0
- endoreg_db/data/requirement_set/colonoscopy_austria_screening.yaml +57 -0
- endoreg_db/data/requirement_set_type/data.yaml +41 -0
- endoreg_db/data/requirement_type/requirement_types.yaml +165 -0
- endoreg_db/data/resource/green_endoscopy_dashboard_Resource.yaml +15 -0
- endoreg_db/data/risk/bleeding.yaml +26 -0
- endoreg_db/data/risk/thrombosis.yaml +37 -0
- endoreg_db/data/risk_type/data.yaml +27 -0
- endoreg_db/data/setup_config.yaml +38 -0
- endoreg_db/data/shift/endoscopy.yaml +21 -0
- endoreg_db/data/shift/m2.yaml +0 -0
- endoreg_db/data/shift_type/base.yaml +35 -0
- endoreg_db/data/tag/requirement_set_tags.yaml +32 -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 +115 -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 +48 -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/exceptions.py +24 -0
- endoreg_db/export/frames/export.py +6 -0
- endoreg_db/export/frames/export_frames_with_labels.py +616 -0
- endoreg_db/factories/__init__.py +0 -0
- endoreg_db/forms/__init__.py +4 -0
- endoreg_db/forms/examination_form.py +12 -0
- endoreg_db/forms/patient_finding_intervention_form.py +40 -0
- endoreg_db/forms/patient_form.py +23 -0
- endoreg_db/forms/questionnaires/__init__.py +1 -0
- endoreg_db/forms/questionnaires/tto_questionnaire.py +23 -0
- endoreg_db/forms/settings/__init__.py +11 -0
- endoreg_db/forms/unit.py +7 -0
- endoreg_db/helpers/__init__.py +0 -0
- endoreg_db/helpers/count_db.py +48 -0
- endoreg_db/helpers/data_loader.py +280 -0
- endoreg_db/helpers/default_objects.py +414 -0
- endoreg_db/helpers/download_segmentation_model.py +32 -0
- endoreg_db/helpers/interact.py +1 -0
- endoreg_db/helpers/test_video_helper.py +127 -0
- endoreg_db/import_files/__init__.py +27 -0
- endoreg_db/import_files/context/__init__.py +7 -0
- endoreg_db/import_files/context/default_sensitive_meta.py +83 -0
- endoreg_db/import_files/context/ensure_center.py +17 -0
- endoreg_db/import_files/context/file_lock.py +66 -0
- endoreg_db/import_files/context/import_context.py +42 -0
- endoreg_db/import_files/context/validate_directories.py +57 -0
- endoreg_db/import_files/file_storage/__init__.py +15 -0
- endoreg_db/import_files/file_storage/create_report_file.py +99 -0
- endoreg_db/import_files/file_storage/create_video_file.py +104 -0
- endoreg_db/import_files/file_storage/sensitive_meta_storage.py +42 -0
- endoreg_db/import_files/file_storage/state_management.py +463 -0
- endoreg_db/import_files/file_storage/storage.py +42 -0
- endoreg_db/import_files/import_service.md +26 -0
- endoreg_db/import_files/processing/__init__.py +11 -0
- endoreg_db/import_files/processing/report_processing/report_anonymization.py +99 -0
- endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
- endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
- endoreg_db/import_files/pseudonymization/__init__.py +0 -0
- endoreg_db/import_files/pseudonymization/fake.py +52 -0
- endoreg_db/import_files/pseudonymization/k_anonymity.py +181 -0
- endoreg_db/import_files/pseudonymization/k_pseudonymity.py +139 -0
- endoreg_db/import_files/pseudonymization/pseudonymize.py +0 -0
- endoreg_db/import_files/report_import_service.py +147 -0
- endoreg_db/import_files/video_import_service.py +154 -0
- endoreg_db/logger_conf.py +156 -0
- endoreg_db/management/__init__.py +1 -0
- endoreg_db/management/commands/__init__.py +1 -0
- endoreg_db/management/commands/anonymize_video.py +0 -0
- endoreg_db/management/commands/check_auth.py +132 -0
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +177 -0
- endoreg_db/management/commands/create_multilabel_model_meta.py +419 -0
- endoreg_db/management/commands/export_frame_annot.py +196 -0
- endoreg_db/management/commands/fix_missing_patient_data.py +206 -0
- endoreg_db/management/commands/fix_video_paths.py +186 -0
- endoreg_db/management/commands/import_report.py +361 -0
- endoreg_db/management/commands/list_routes.py +20 -0
- endoreg_db/management/commands/load_ai_model_data.py +83 -0
- endoreg_db/management/commands/load_ai_model_label_data.py +60 -0
- endoreg_db/management/commands/load_base_db_data.py +63 -0
- endoreg_db/management/commands/load_center_data.py +68 -0
- endoreg_db/management/commands/load_contraindication_data.py +39 -0
- endoreg_db/management/commands/load_disease_classification_choices_data.py +38 -0
- endoreg_db/management/commands/load_disease_classification_data.py +38 -0
- endoreg_db/management/commands/load_disease_data.py +59 -0
- endoreg_db/management/commands/load_distribution_data.py +63 -0
- endoreg_db/management/commands/load_endoscope_data.py +58 -0
- endoreg_db/management/commands/load_event_data.py +39 -0
- endoreg_db/management/commands/load_examination_data.py +78 -0
- endoreg_db/management/commands/load_examination_indication_data.py +85 -0
- endoreg_db/management/commands/load_finding_data.py +115 -0
- endoreg_db/management/commands/load_gender_data.py +37 -0
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +142 -0
- endoreg_db/management/commands/load_information_source.py +46 -0
- endoreg_db/management/commands/load_lab_value_data.py +52 -0
- endoreg_db/management/commands/load_legacy_data.py +303 -0
- endoreg_db/management/commands/load_medication_data.py +104 -0
- endoreg_db/management/commands/load_name_data.py +36 -0
- endoreg_db/management/commands/load_organ_data.py +39 -0
- endoreg_db/management/commands/load_pdf_type_data.py +58 -0
- endoreg_db/management/commands/load_profession_data.py +40 -0
- endoreg_db/management/commands/load_qualification_data.py +56 -0
- endoreg_db/management/commands/load_report_reader_flag_data.py +40 -0
- endoreg_db/management/commands/load_requirement_data.py +207 -0
- endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
- endoreg_db/management/commands/load_risk_data.py +57 -0
- endoreg_db/management/commands/load_shift_data.py +57 -0
- endoreg_db/management/commands/load_tag_data.py +54 -0
- endoreg_db/management/commands/load_unit_data.py +40 -0
- endoreg_db/management/commands/load_user_groups.py +26 -0
- endoreg_db/management/commands/model_input.py +169 -0
- endoreg_db/management/commands/register_ai_model.py +70 -0
- endoreg_db/management/commands/setup_endoreg_db.py +459 -0
- endoreg_db/management/commands/start_filewatcher.py +115 -0
- endoreg_db/management/commands/storage_management.py +622 -0
- endoreg_db/management/commands/summarize_db_content.py +280 -0
- endoreg_db/management/commands/train_image_multilabel_model.py +144 -0
- endoreg_db/management/commands/validate_video_files.py +189 -0
- endoreg_db/management/commands/video_validation.py +20 -0
- endoreg_db/mermaid/Overall_flow_patient_finding_intervention.md +10 -0
- endoreg_db/mermaid/anonymized_image_annotation.md +20 -0
- endoreg_db/mermaid/binary_classification_annotation.md +50 -0
- endoreg_db/mermaid/classification.md +8 -0
- endoreg_db/mermaid/examination.md +8 -0
- endoreg_db/mermaid/findings.md +7 -0
- endoreg_db/mermaid/image_classification.md +28 -0
- endoreg_db/mermaid/interventions.md +8 -0
- endoreg_db/mermaid/morphology.md +8 -0
- endoreg_db/mermaid/patient_creation.md +14 -0
- endoreg_db/mermaid/video_segmentation_annotation.md +17 -0
- endoreg_db/migrations/0001_initial.py +1953 -0
- endoreg_db/migrations/__init__.py +0 -0
- endoreg_db/models/__init__.py +322 -0
- endoreg_db/models/administration/__init__.py +95 -0
- endoreg_db/models/administration/ai/__init__.py +9 -0
- endoreg_db/models/administration/ai/active_model.py +35 -0
- endoreg_db/models/administration/ai/ai_model.py +180 -0
- endoreg_db/models/administration/ai/model_type.py +42 -0
- endoreg_db/models/administration/case/__init__.py +5 -0
- endoreg_db/models/administration/case/case.py +114 -0
- endoreg_db/models/administration/case/case_template/__init__.py +3 -0
- endoreg_db/models/administration/case/case_template/case_template.py +3 -0
- endoreg_db/models/administration/case/case_template/case_template_rule.py +3 -0
- endoreg_db/models/administration/case/case_template/case_template_rule_value.py +3 -0
- endoreg_db/models/administration/case/case_template/case_template_type.py +3 -0
- endoreg_db/models/administration/center/__init__.py +13 -0
- endoreg_db/models/administration/center/center.py +85 -0
- endoreg_db/models/administration/center/center_product.py +67 -0
- endoreg_db/models/administration/center/center_resource.py +69 -0
- endoreg_db/models/administration/center/center_shift.py +94 -0
- endoreg_db/models/administration/center/center_waste.py +42 -0
- endoreg_db/models/administration/person/__init__.py +26 -0
- endoreg_db/models/administration/person/employee/__init__.py +3 -0
- endoreg_db/models/administration/person/employee/employee.py +40 -0
- endoreg_db/models/administration/person/employee/employee_qualification.py +44 -0
- endoreg_db/models/administration/person/employee/employee_type.py +50 -0
- endoreg_db/models/administration/person/examiner/__init__.py +4 -0
- endoreg_db/models/administration/person/examiner/examiner.py +64 -0
- endoreg_db/models/administration/person/names/__init__.py +0 -0
- endoreg_db/models/administration/person/names/first_name.py +20 -0
- endoreg_db/models/administration/person/names/last_name.py +20 -0
- endoreg_db/models/administration/person/patient/__init__.py +7 -0
- endoreg_db/models/administration/person/patient/patient.py +488 -0
- endoreg_db/models/administration/person/patient/patient_external_id.py +36 -0
- endoreg_db/models/administration/person/person.py +35 -0
- endoreg_db/models/administration/person/profession/__init__.py +28 -0
- endoreg_db/models/administration/person/user/__init__.py +5 -0
- endoreg_db/models/administration/person/user/portal_user_information.py +41 -0
- endoreg_db/models/administration/product/__init__.py +15 -0
- endoreg_db/models/administration/product/product.py +106 -0
- endoreg_db/models/administration/product/product_group.py +41 -0
- endoreg_db/models/administration/product/product_material.py +60 -0
- endoreg_db/models/administration/product/product_weight.py +51 -0
- endoreg_db/models/administration/product/reference_product.py +147 -0
- endoreg_db/models/administration/qualification/__init__.py +7 -0
- endoreg_db/models/administration/qualification/qualification.py +43 -0
- endoreg_db/models/administration/qualification/qualification_type.py +39 -0
- endoreg_db/models/administration/shift/__init__.py +9 -0
- endoreg_db/models/administration/shift/scheduled_days.py +72 -0
- endoreg_db/models/administration/shift/shift.py +57 -0
- endoreg_db/models/administration/shift/shift_type.py +108 -0
- endoreg_db/models/aidataset/__init__.py +5 -0
- endoreg_db/models/aidataset/aidataset.py +193 -0
- endoreg_db/models/label/__init__.py +23 -0
- endoreg_db/models/label/annotation/__init__.py +12 -0
- endoreg_db/models/label/annotation/image_classification.py +85 -0
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +61 -0
- endoreg_db/models/label/label.py +91 -0
- endoreg_db/models/label/label_set.py +68 -0
- endoreg_db/models/label/label_type.py +29 -0
- endoreg_db/models/label/label_video_segment/__init__.py +3 -0
- endoreg_db/models/label/label_video_segment/_create_from_video.py +42 -0
- endoreg_db/models/label/label_video_segment/label_video_segment.py +611 -0
- endoreg_db/models/label/video_segmentation_label.py +35 -0
- endoreg_db/models/label/video_segmentation_labelset.py +28 -0
- endoreg_db/models/media/__init__.py +23 -0
- endoreg_db/models/media/frame/__init__.py +3 -0
- endoreg_db/models/media/frame/frame.py +137 -0
- endoreg_db/models/media/pdf/__init__.py +12 -0
- endoreg_db/models/media/pdf/raw_pdf.py +764 -0
- endoreg_db/models/media/pdf/report_file.py +162 -0
- endoreg_db/models/media/pdf/report_reader/__init__.py +7 -0
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +85 -0
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +46 -0
- endoreg_db/models/media/video/__init__.py +9 -0
- endoreg_db/models/media/video/create_from_file.py +402 -0
- endoreg_db/models/media/video/pipe_1.py +258 -0
- endoreg_db/models/media/video/pipe_2.py +129 -0
- endoreg_db/models/media/video/video_file.py +907 -0
- endoreg_db/models/media/video/video_file_ai.py +828 -0
- endoreg_db/models/media/video/video_file_anonymize.py +524 -0
- endoreg_db/models/media/video/video_file_frames/__init__.py +49 -0
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +25 -0
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +23 -0
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +126 -0
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +233 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +36 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +13 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +24 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +40 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +44 -0
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +30 -0
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +205 -0
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +228 -0
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +107 -0
- endoreg_db/models/media/video/video_file_io.py +272 -0
- endoreg_db/models/media/video/video_file_meta/__init__.py +22 -0
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +58 -0
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +62 -0
- endoreg_db/models/media/video/video_file_meta/get_fps.py +183 -0
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +198 -0
- endoreg_db/models/media/video/video_file_meta/text_meta.py +178 -0
- endoreg_db/models/media/video/video_file_meta/video_meta.py +105 -0
- endoreg_db/models/media/video/video_file_segments.py +317 -0
- endoreg_db/models/media/video/video_metadata.py +67 -0
- endoreg_db/models/media/video/video_processing.py +192 -0
- endoreg_db/models/medical/__init__.py +136 -0
- endoreg_db/models/medical/contraindication/README.md +1 -0
- endoreg_db/models/medical/contraindication/__init__.py +29 -0
- endoreg_db/models/medical/disease.py +174 -0
- endoreg_db/models/medical/event.py +154 -0
- endoreg_db/models/medical/examination/__init__.py +20 -0
- endoreg_db/models/medical/examination/examination.py +183 -0
- endoreg_db/models/medical/examination/examination_indication.py +229 -0
- endoreg_db/models/medical/examination/examination_time.py +68 -0
- endoreg_db/models/medical/examination/examination_time_type.py +44 -0
- endoreg_db/models/medical/examination/examination_type.py +47 -0
- endoreg_db/models/medical/finding/__init__.py +20 -0
- endoreg_db/models/medical/finding/finding.py +113 -0
- endoreg_db/models/medical/finding/finding_classification.py +131 -0
- endoreg_db/models/medical/finding/finding_intervention.py +68 -0
- endoreg_db/models/medical/finding/finding_type.py +38 -0
- endoreg_db/models/medical/hardware/__init__.py +8 -0
- endoreg_db/models/medical/hardware/endoscope.py +77 -0
- endoreg_db/models/medical/hardware/endoscopy_processor.py +182 -0
- endoreg_db/models/medical/laboratory/__init__.py +5 -0
- endoreg_db/models/medical/laboratory/lab_value.py +490 -0
- endoreg_db/models/medical/medication/__init__.py +23 -0
- endoreg_db/models/medical/medication/medication.py +45 -0
- endoreg_db/models/medical/medication/medication_indication.py +78 -0
- endoreg_db/models/medical/medication/medication_indication_type.py +58 -0
- endoreg_db/models/medical/medication/medication_intake_time.py +58 -0
- endoreg_db/models/medical/medication/medication_schedule.py +58 -0
- endoreg_db/models/medical/organ/__init__.py +38 -0
- endoreg_db/models/medical/patient/__init__.py +48 -0
- endoreg_db/models/medical/patient/medication_examples.py +56 -0
- endoreg_db/models/medical/patient/patient_disease.py +72 -0
- endoreg_db/models/medical/patient/patient_event.py +80 -0
- endoreg_db/models/medical/patient/patient_examination.py +280 -0
- endoreg_db/models/medical/patient/patient_examination_indication.py +57 -0
- endoreg_db/models/medical/patient/patient_finding.py +416 -0
- endoreg_db/models/medical/patient/patient_finding_classification.py +231 -0
- endoreg_db/models/medical/patient/patient_finding_intervention.py +37 -0
- endoreg_db/models/medical/patient/patient_lab_sample.py +157 -0
- endoreg_db/models/medical/patient/patient_lab_value.py +247 -0
- endoreg_db/models/medical/patient/patient_medication.py +111 -0
- endoreg_db/models/medical/patient/patient_medication_schedule.py +152 -0
- endoreg_db/models/medical/risk/__init__.py +7 -0
- endoreg_db/models/medical/risk/risk.py +73 -0
- endoreg_db/models/medical/risk/risk_type.py +54 -0
- endoreg_db/models/metadata/__init__.py +19 -0
- endoreg_db/models/metadata/model_meta.py +266 -0
- endoreg_db/models/metadata/model_meta_logic.py +485 -0
- endoreg_db/models/metadata/pdf_meta.py +96 -0
- endoreg_db/models/metadata/sensitive_meta.py +345 -0
- endoreg_db/models/metadata/sensitive_meta_logic.py +1161 -0
- endoreg_db/models/metadata/video_meta.py +459 -0
- endoreg_db/models/metadata/video_prediction_logic.py +232 -0
- endoreg_db/models/metadata/video_prediction_meta.py +319 -0
- endoreg_db/models/operation_log.py +63 -0
- endoreg_db/models/other/__init__.py +40 -0
- endoreg_db/models/other/distribution/__init__.py +46 -0
- endoreg_db/models/other/distribution/base_value_distribution.py +22 -0
- endoreg_db/models/other/distribution/date_value_distribution.py +163 -0
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +50 -0
- endoreg_db/models/other/distribution/numeric_value_distribution.py +211 -0
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +23 -0
- endoreg_db/models/other/emission/__init__.py +5 -0
- endoreg_db/models/other/emission/emission_factor.py +110 -0
- endoreg_db/models/other/gender.py +32 -0
- endoreg_db/models/other/information_source.py +190 -0
- endoreg_db/models/other/material.py +34 -0
- endoreg_db/models/other/resource.py +24 -0
- endoreg_db/models/other/tag.py +32 -0
- endoreg_db/models/other/transport_route.py +40 -0
- endoreg_db/models/other/unit.py +40 -0
- endoreg_db/models/other/waste.py +28 -0
- endoreg_db/models/report/__init__.py +0 -0
- endoreg_db/models/report/images.py +0 -0
- endoreg_db/models/report/report.py +5 -0
- endoreg_db/models/requirement/__init__.py +11 -0
- endoreg_db/models/requirement/requirement.py +792 -0
- endoreg_db/models/requirement/requirement_error.py +84 -0
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +6 -0
- endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
- endoreg_db/models/requirement/requirement_evaluation/get_values.py +40 -0
- endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +6 -0
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +137 -0
- endoreg_db/models/requirement/requirement_operator.py +187 -0
- endoreg_db/models/requirement/requirement_set.py +327 -0
- endoreg_db/models/state/__init__.py +13 -0
- endoreg_db/models/state/abstract.py +11 -0
- endoreg_db/models/state/anonymization.py +30 -0
- endoreg_db/models/state/audit_ledger.py +155 -0
- endoreg_db/models/state/label_video_segment.py +31 -0
- endoreg_db/models/state/processing_history/__init__.py +3 -0
- endoreg_db/models/state/processing_history/processing_history.py +136 -0
- endoreg_db/models/state/raw_pdf.py +219 -0
- endoreg_db/models/state/sensitive_meta.py +50 -0
- endoreg_db/models/state/video.py +251 -0
- endoreg_db/models/upload_job.py +100 -0
- endoreg_db/models/utils.py +138 -0
- endoreg_db/queries/__init__.py +3 -0
- endoreg_db/queries/annotations/__init__.py +1 -0
- endoreg_db/queries/annotations/legacy.py +169 -0
- endoreg_db/queries/sanity/__init_.py +0 -0
- endoreg_db/root_urls.py +27 -0
- endoreg_db/schemas/__init__.py +0 -0
- endoreg_db/schemas/examination_evaluation.py +30 -0
- endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +861 -0
- endoreg_db/serializers/__init__.py +104 -0
- endoreg_db/serializers/administration/__init__.py +13 -0
- endoreg_db/serializers/administration/ai/__init__.py +9 -0
- endoreg_db/serializers/administration/ai/active_model.py +12 -0
- endoreg_db/serializers/administration/ai/ai_model.py +20 -0
- endoreg_db/serializers/administration/ai/model_type.py +12 -0
- endoreg_db/serializers/administration/center.py +14 -0
- endoreg_db/serializers/administration/gender.py +11 -0
- endoreg_db/serializers/anonymization.py +77 -0
- endoreg_db/serializers/evaluation/examination_evaluation.py +0 -0
- endoreg_db/serializers/examination/__init__.py +10 -0
- endoreg_db/serializers/examination/base.py +45 -0
- endoreg_db/serializers/examination/dropdown.py +20 -0
- endoreg_db/serializers/examination_serializer.py +9 -0
- endoreg_db/serializers/finding/__init__.py +5 -0
- endoreg_db/serializers/finding/finding.py +61 -0
- endoreg_db/serializers/finding_classification/__init__.py +7 -0
- endoreg_db/serializers/finding_classification/choice.py +19 -0
- endoreg_db/serializers/finding_classification/classification.py +11 -0
- endoreg_db/serializers/label_video_segment/__init__.py +9 -0
- endoreg_db/serializers/label_video_segment/image_classification_annotation.py +62 -0
- endoreg_db/serializers/label_video_segment/label/__init__.py +6 -0
- endoreg_db/serializers/label_video_segment/label/label.py +15 -0
- endoreg_db/serializers/label_video_segment/label_video_segment.py +427 -0
- endoreg_db/serializers/meta/__init__.py +13 -0
- endoreg_db/serializers/meta/sensitive_meta_detail.py +122 -0
- endoreg_db/serializers/meta/sensitive_meta_update.py +153 -0
- endoreg_db/serializers/meta/sensitive_meta_verification.py +62 -0
- endoreg_db/serializers/meta/video_meta.py +39 -0
- endoreg_db/serializers/misc/__init__.py +14 -0
- endoreg_db/serializers/misc/file_overview.py +72 -0
- endoreg_db/serializers/misc/sensitive_patient_data.py +144 -0
- endoreg_db/serializers/misc/stats.py +35 -0
- endoreg_db/serializers/misc/translatable_field_mix_in.py +44 -0
- endoreg_db/serializers/misc/upload_job.py +74 -0
- endoreg_db/serializers/patient/__init__.py +12 -0
- endoreg_db/serializers/patient/patient.py +103 -0
- endoreg_db/serializers/patient/patient_dropdown.py +35 -0
- endoreg_db/serializers/patient_examination/__init__.py +7 -0
- endoreg_db/serializers/patient_examination/patient_examination.py +168 -0
- endoreg_db/serializers/patient_finding/__init__.py +15 -0
- endoreg_db/serializers/patient_finding/patient_finding.py +32 -0
- endoreg_db/serializers/patient_finding/patient_finding_classification.py +47 -0
- endoreg_db/serializers/patient_finding/patient_finding_detail.py +62 -0
- endoreg_db/serializers/patient_finding/patient_finding_intervention.py +28 -0
- endoreg_db/serializers/patient_finding/patient_finding_list.py +40 -0
- endoreg_db/serializers/patient_finding/patient_finding_write.py +135 -0
- endoreg_db/serializers/pdf/__init__.py +3 -0
- endoreg_db/serializers/pdf/anony_text_validation.py +101 -0
- endoreg_db/serializers/requirements/requirement_schema.py +20 -0
- endoreg_db/serializers/requirements/requirement_sets.py +99 -0
- endoreg_db/serializers/sensitive_meta_serializer.py +301 -0
- endoreg_db/serializers/video/__init__.py +7 -0
- endoreg_db/serializers/video/video_file.py +283 -0
- endoreg_db/serializers/video/video_file_brief.py +14 -0
- endoreg_db/serializers/video/video_file_detail.py +96 -0
- endoreg_db/serializers/video/video_file_list.py +100 -0
- endoreg_db/serializers/video/video_processing_history.py +172 -0
- endoreg_db/serializers/video_examination.py +198 -0
- endoreg_db/services/__init__.py +5 -0
- endoreg_db/services/anonymization.py +274 -0
- endoreg_db/services/examination_evaluation.py +172 -0
- endoreg_db/services/finding_description_service.py +0 -0
- endoreg_db/services/lookup_service.py +424 -0
- endoreg_db/services/lookup_store.py +266 -0
- endoreg_db/services/model_meta_from_hf.py +76 -0
- endoreg_db/services/pdf_import.py +0 -0
- endoreg_db/services/polling_coordinator.py +319 -0
- endoreg_db/services/pseudonym_service.py +94 -0
- endoreg_db/services/report_import.py +13 -0
- endoreg_db/services/segment_sync.py +171 -0
- endoreg_db/services/video_import.py +9 -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/urls/__init__.py +56 -0
- endoreg_db/urls/ai.py +14 -0
- endoreg_db/urls/anonymization.py +78 -0
- endoreg_db/urls/auth.py +16 -0
- endoreg_db/urls/classification.py +34 -0
- endoreg_db/urls/examination.py +63 -0
- endoreg_db/urls/media.py +251 -0
- endoreg_db/urls/patient.py +23 -0
- endoreg_db/urls/requirements.py +15 -0
- endoreg_db/urls/root_urls.py +28 -0
- endoreg_db/urls/stats.py +54 -0
- endoreg_db/urls/upload.py +12 -0
- endoreg_db/urls.py +9 -0
- endoreg_db/utils/__init__.py +97 -0
- endoreg_db/utils/ai/__init__.py +9 -0
- endoreg_db/utils/ai/data_loader_for_model_input.py +262 -0
- endoreg_db/utils/ai/data_loader_for_model_training.py +262 -0
- endoreg_db/utils/ai/get.py +6 -0
- endoreg_db/utils/ai/inference_dataset.py +51 -0
- endoreg_db/utils/ai/model_training/config.py +117 -0
- endoreg_db/utils/ai/model_training/dataset.py +74 -0
- endoreg_db/utils/ai/model_training/losses.py +68 -0
- endoreg_db/utils/ai/model_training/metrics.py +78 -0
- endoreg_db/utils/ai/model_training/model_backbones.py +155 -0
- endoreg_db/utils/ai/model_training/model_gastronet_resnet.py +118 -0
- endoreg_db/utils/ai/model_training/trainer_gastronet_multilabel.py +771 -0
- endoreg_db/utils/ai/multilabel_classification_net.py +270 -0
- endoreg_db/utils/ai/postprocess.py +63 -0
- endoreg_db/utils/ai/predict.py +293 -0
- endoreg_db/utils/ai/preprocess.py +76 -0
- endoreg_db/utils/calc_duration_seconds.py +24 -0
- endoreg_db/utils/case_generator/__init__.py +3 -0
- endoreg_db/utils/case_generator/lab_sample_factory.py +32 -0
- endoreg_db/utils/check_video_files.py +175 -0
- endoreg_db/utils/cropping.py +30 -0
- endoreg_db/utils/dataloader.py +285 -0
- endoreg_db/utils/dates.py +59 -0
- endoreg_db/utils/defaults/set_default_center.py +33 -0
- endoreg_db/utils/env.py +37 -0
- endoreg_db/utils/extract_specific_frames.py +87 -0
- endoreg_db/utils/file_operations.py +70 -0
- endoreg_db/utils/fix_video_path_direct.py +157 -0
- endoreg_db/utils/frame_anonymization_utils.py +463 -0
- endoreg_db/utils/hashs.py +138 -0
- endoreg_db/utils/links/__init__.py +0 -0
- endoreg_db/utils/links/requirement_link.py +237 -0
- endoreg_db/utils/mime_types.py +0 -0
- endoreg_db/utils/names.py +82 -0
- endoreg_db/utils/ocr.py +195 -0
- endoreg_db/utils/operation_log.py +87 -0
- endoreg_db/utils/parse_and_generate_yaml.py +45 -0
- endoreg_db/utils/paths.py +159 -0
- endoreg_db/utils/permissions.py +160 -0
- endoreg_db/utils/pipelines/Readme.md +235 -0
- endoreg_db/utils/pipelines/__init__.py +0 -0
- endoreg_db/utils/pipelines/process_video_dir.py +144 -0
- endoreg_db/utils/product/__init__.py +0 -0
- endoreg_db/utils/product/sum_emissions.py +22 -0
- endoreg_db/utils/product/sum_weights.py +20 -0
- endoreg_db/utils/pydantic_models/__init__.py +5 -0
- endoreg_db/utils/pydantic_models/db_config.py +57 -0
- endoreg_db/utils/requirement_helpers.py +0 -0
- endoreg_db/utils/requirement_operator_logic/__init__.py +0 -0
- endoreg_db/utils/requirement_operator_logic/_old/lab_value_operators.py +678 -0
- endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +842 -0
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +114 -0
- endoreg_db/utils/setup_config.py +196 -0
- endoreg_db/utils/storage.py +117 -0
- endoreg_db/utils/translation.py +31 -0
- endoreg_db/utils/uuid.py +5 -0
- endoreg_db/utils/validate_endo_roi.py +33 -0
- endoreg_db/utils/validate_subcategory_dict.py +93 -0
- endoreg_db/utils/validate_video_detailed.py +415 -0
- endoreg_db/utils/video/__init__.py +30 -0
- endoreg_db/utils/video/extract_frames.py +100 -0
- endoreg_db/utils/video/ffmpeg_wrapper.py +996 -0
- endoreg_db/utils/video/names.py +47 -0
- endoreg_db/utils/video/streaming_processor.py +386 -0
- endoreg_db/utils/video/video_splitter.py +105 -0
- endoreg_db/versioning.md +79 -0
- endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +247 -0
- endoreg_db/views/__init__.py +157 -0
- endoreg_db/views/anonymization/__init__.py +31 -0
- endoreg_db/views/anonymization/media_management.py +486 -0
- endoreg_db/views/anonymization/overview.py +307 -0
- endoreg_db/views/anonymization/validate.py +310 -0
- endoreg_db/views/auth/__init__.py +13 -0
- endoreg_db/views/auth/keycloak.py +146 -0
- endoreg_db/views/examination/__init__.py +30 -0
- endoreg_db/views/examination/examination.py +37 -0
- endoreg_db/views/examination/examination_manifest_cache.py +26 -0
- endoreg_db/views/examination/get_finding_classification_choices.py +62 -0
- endoreg_db/views/examination/get_finding_classifications.py +38 -0
- endoreg_db/views/examination/get_findings.py +39 -0
- endoreg_db/views/examination/get_instruments.py +19 -0
- endoreg_db/views/examination/get_interventions.py +14 -0
- endoreg_db/views/finding/__init__.py +9 -0
- endoreg_db/views/finding/finding.py +116 -0
- endoreg_db/views/finding/get_classifications.py +14 -0
- endoreg_db/views/finding/get_interventions.py +17 -0
- endoreg_db/views/finding_classification/__init__.py +13 -0
- endoreg_db/views/finding_classification/base.py +0 -0
- endoreg_db/views/finding_classification/finding_classification.py +41 -0
- endoreg_db/views/finding_classification/get_classification_choices.py +54 -0
- endoreg_db/views/media/__init__.py +32 -0
- endoreg_db/views/media/pdf_media.py +411 -0
- endoreg_db/views/media/sensitive_metadata.py +372 -0
- endoreg_db/views/media/video_media.py +275 -0
- endoreg_db/views/meta/__init__.py +7 -0
- endoreg_db/views/meta/sensitive_meta_list.py +102 -0
- endoreg_db/views/meta/sensitive_meta_verification.py +74 -0
- endoreg_db/views/misc/__init__.py +29 -0
- endoreg_db/views/misc/center.py +14 -0
- endoreg_db/views/misc/csrf.py +8 -0
- endoreg_db/views/misc/gender.py +15 -0
- endoreg_db/views/misc/stats.py +255 -0
- endoreg_db/views/misc/upload_views.py +241 -0
- endoreg_db/views/patient/__init__.py +3 -0
- endoreg_db/views/patient/patient.py +253 -0
- endoreg_db/views/patient_examination/__init__.py +11 -0
- endoreg_db/views/patient_examination/patient_examination.py +141 -0
- endoreg_db/views/patient_examination/patient_examination_create.py +58 -0
- endoreg_db/views/patient_examination/patient_examination_detail.py +63 -0
- endoreg_db/views/patient_examination/patient_examination_list.py +72 -0
- endoreg_db/views/patient_examination/video.py +228 -0
- endoreg_db/views/patient_finding/__init__.py +7 -0
- endoreg_db/views/patient_finding/base.py +0 -0
- endoreg_db/views/patient_finding/patient_finding.py +71 -0
- endoreg_db/views/patient_finding/patient_finding_optimized.py +291 -0
- endoreg_db/views/patient_finding_classification/__init__.py +5 -0
- endoreg_db/views/patient_finding_classification/pfc_create.py +75 -0
- endoreg_db/views/report/__init__.py +7 -0
- endoreg_db/views/report/reimport.py +177 -0
- endoreg_db/views/report/report_stream.py +191 -0
- endoreg_db/views/requirement/__init__.py +11 -0
- endoreg_db/views/requirement/evaluate.py +278 -0
- endoreg_db/views/requirement/lookup.py +380 -0
- endoreg_db/views/requirement/lookup_store.py +183 -0
- endoreg_db/views/requirement/requirement_utils.py +87 -0
- endoreg_db/views/requirement_lookup/lookup.py +0 -0
- endoreg_db/views/requirement_lookup/lookup_store.py +0 -0
- endoreg_db/views/stats/__init__.py +13 -0
- endoreg_db/views/stats/stats_views.py +266 -0
- endoreg_db/views/video/__init__.py +49 -0
- endoreg_db/views/video/ai/__init__.py +8 -0
- endoreg_db/views/video/ai/label.py +159 -0
- endoreg_db/views/video/correction.py +529 -0
- endoreg_db/views/video/reimport.py +230 -0
- endoreg_db/views/video/segments_crud.py +709 -0
- endoreg_db/views/video/video_apply_mask.py +49 -0
- endoreg_db/views/video/video_correction.py +22 -0
- endoreg_db/views/video/video_download_processed.py +58 -0
- endoreg_db/views/video/video_examination_viewset.py +242 -0
- endoreg_db/views/video/video_metadata.py +101 -0
- endoreg_db/views/video/video_processing_history.py +25 -0
- endoreg_db/views/video/video_remove_frames.py +49 -0
- endoreg_db/views/video/video_stream.py +334 -0
- endoreg_db-0.8.9.32.dist-info/METADATA +404 -0
- endoreg_db-0.8.9.32.dist-info/RECORD +787 -0
- endoreg_db-0.8.9.32.dist-info/WHEEL +4 -0
- endoreg_db-0.8.9.32.dist-info/licenses/LICENSE +674 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from rest_framework import serializers
|
|
4
|
+
|
|
5
|
+
from ...models import VideoFile
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
import cv2
|
|
9
|
+
except ImportError:
|
|
10
|
+
cv2 = None
|
|
11
|
+
# from django.conf import settings
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
13
|
+
|
|
14
|
+
from django.conf import settings
|
|
15
|
+
from rest_framework.exceptions import ValidationError
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from endoreg_db.models import VideoFile
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class VideoFileSerializer(serializers.ModelSerializer):
|
|
22
|
+
"""
|
|
23
|
+
Serializer that dynamically handles video retrieval and streaming.
|
|
24
|
+
Ensures file returns the relative file path (not MEDIA_URL)
|
|
25
|
+
Computes full_video_path using the correct storage path (/home/admin/test-data)-need to change make it dynamic
|
|
26
|
+
Returns video_url for frontend integration
|
|
27
|
+
Serves the video file when needed
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
video_url = serializers.SerializerMethodField()
|
|
32
|
+
full_video_path = serializers.SerializerMethodField()
|
|
33
|
+
file = serializers.SerializerMethodField() # Override file to remove incorrect MEDIA_URL behavior,otherwise:Django's FileField automatically generates a URL based on MEDIA_URL
|
|
34
|
+
# Video dropdown field for frontend selection (currently shows video ID, but can be changed later)
|
|
35
|
+
video_selection_field = serializers.SerializerMethodField()
|
|
36
|
+
# classification_data = serializers.SerializerMethodField() #data from database (smooth prediction values but currently hardcoded one)
|
|
37
|
+
# The Meta class tells Django what data to include when serializing a RawVideoFile object.
|
|
38
|
+
sequences = serializers.SerializerMethodField()
|
|
39
|
+
label_names = serializers.SerializerMethodField()
|
|
40
|
+
# Convert selected label frames into time segments (seconds)
|
|
41
|
+
label_time_segments = serializers.SerializerMethodField()
|
|
42
|
+
# label_predictions = serializers.SerializerMethodField()
|
|
43
|
+
original_file_name = serializers.CharField(read_only=True)
|
|
44
|
+
duration = serializers.SerializerMethodField()
|
|
45
|
+
|
|
46
|
+
class Meta:
|
|
47
|
+
model = VideoFile
|
|
48
|
+
# he fields list defines which data should be included in the API response.
|
|
49
|
+
fields = [
|
|
50
|
+
"id",
|
|
51
|
+
"original_file_name",
|
|
52
|
+
"file",
|
|
53
|
+
"duration",
|
|
54
|
+
"video_url",
|
|
55
|
+
"full_video_path",
|
|
56
|
+
"video_selection_field",
|
|
57
|
+
"label_names",
|
|
58
|
+
"sequences",
|
|
59
|
+
"label_time_segments",
|
|
60
|
+
] # Ensure computed fields are included
|
|
61
|
+
|
|
62
|
+
# @staticmethod #using @staticmethod makes it reusable without needing to create a serializer instance.
|
|
63
|
+
# Without @staticmethod, you would need to instantiate the serializer before calling the method, which is unnecessary her
|
|
64
|
+
def get_video_selection_field(self, obj: "VideoFile"):
|
|
65
|
+
"""
|
|
66
|
+
Return the UUID of the video for use as a selection value in frontend dropdowns.
|
|
67
|
+
|
|
68
|
+
Parameters:
|
|
69
|
+
obj (Video): The video instance being serialized.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
str: The UUID of the video.
|
|
73
|
+
"""
|
|
74
|
+
return obj.video_hash
|
|
75
|
+
|
|
76
|
+
def get_video_url(
|
|
77
|
+
self, obj
|
|
78
|
+
): # when we serialize a RawVideoFile object (video metadata), the get_video_url method is automatically invoked by DRF
|
|
79
|
+
"""
|
|
80
|
+
Return the absolute API URL for accessing the video file.
|
|
81
|
+
|
|
82
|
+
If the video ID is invalid or the request context is missing, returns a dictionary with an error message.
|
|
83
|
+
"""
|
|
84
|
+
if not obj.id:
|
|
85
|
+
return {"error": "Invalid video ID"}
|
|
86
|
+
|
|
87
|
+
request = self.context.get(
|
|
88
|
+
"request"
|
|
89
|
+
) # Gets the request object (provided by DRF).
|
|
90
|
+
if request:
|
|
91
|
+
return request.build_absolute_uri(
|
|
92
|
+
f"/api/video/{obj.id}/"
|
|
93
|
+
) # Added api/ prefix
|
|
94
|
+
|
|
95
|
+
return {"error": "Video URL not available"}
|
|
96
|
+
|
|
97
|
+
def get_duration(self, obj: "VideoFile"):
|
|
98
|
+
"""
|
|
99
|
+
Return the duration of the video in seconds, using the stored value if available or extracting it dynamically with OpenCV.
|
|
100
|
+
|
|
101
|
+
If the duration is not present in the database, the method opens the video file, retrieves its frame count and frames per second (FPS), and calculates the duration. Returns `None` if the video cannot be opened or FPS is zero.
|
|
102
|
+
"""
|
|
103
|
+
if hasattr(obj, "duration") and obj.duration:
|
|
104
|
+
return (
|
|
105
|
+
obj.duration
|
|
106
|
+
) # If duration is stored in the database, return it directly.
|
|
107
|
+
|
|
108
|
+
# Dynamically extract duration if not stored
|
|
109
|
+
video_path = obj.active_file.path
|
|
110
|
+
|
|
111
|
+
cap = cv2.VideoCapture(video_path)
|
|
112
|
+
try:
|
|
113
|
+
if not cap.isOpened():
|
|
114
|
+
return None # Error handling if video can't be opened
|
|
115
|
+
|
|
116
|
+
fps = cap.get(cv2.CAP_PROP_FPS)
|
|
117
|
+
total_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
round(total_frames / fps, 2) if fps > 0 else None
|
|
121
|
+
) # Return duration in seconds
|
|
122
|
+
finally:
|
|
123
|
+
cap.release()
|
|
124
|
+
|
|
125
|
+
def get_file(self, obj: "VideoFile"):
|
|
126
|
+
"""
|
|
127
|
+
Returns the relative file path of the active video file, or an error message if the file is missing or invalid.
|
|
128
|
+
|
|
129
|
+
Parameters:
|
|
130
|
+
obj (Video): The video instance whose file path is to be retrieved.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
str or dict: The relative file path as a string, or a dictionary with an error message if the file is missing or invalid.
|
|
134
|
+
"""
|
|
135
|
+
if not obj.active_file:
|
|
136
|
+
return {"error": "No file associated with this entry"}
|
|
137
|
+
# obj.active_file.name is an attribute of FieldFile that returns the file path as a string and name is not the database attribute, it is an attribute of Django’s FieldFile object that holds the file path as a string.
|
|
138
|
+
if not hasattr(obj.active_file, "name") or not obj.active_file.name.strip():
|
|
139
|
+
return {"error": "Invalid file name"}
|
|
140
|
+
|
|
141
|
+
return str(
|
|
142
|
+
obj.active_file.name
|
|
143
|
+
).strip() # Only return the file path, no URL,#obj.active_file returning a FieldFile object instead of a string
|
|
144
|
+
|
|
145
|
+
def get_full_video_path(self, obj: "VideoFile"):
|
|
146
|
+
"""
|
|
147
|
+
Return the absolute filesystem path to the video's active file.
|
|
148
|
+
|
|
149
|
+
If the file does not exist or an error occurs during path construction, returns a dictionary with an error message.
|
|
150
|
+
"""
|
|
151
|
+
if not obj.active_file:
|
|
152
|
+
return {"error": "No video file associated with this entry"}
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
# Use the active_file_path property which handles both processed and raw files
|
|
156
|
+
if hasattr(obj, "active_file_path") and obj.active_file_path:
|
|
157
|
+
full_path = obj.active_file_path
|
|
158
|
+
return (
|
|
159
|
+
str(full_path)
|
|
160
|
+
if full_path.exists()
|
|
161
|
+
else {"error": f"file not found at: {full_path}"}
|
|
162
|
+
)
|
|
163
|
+
else:
|
|
164
|
+
# Fallback: construct path manually
|
|
165
|
+
video_relative_path = str(obj.active_file.name).strip()
|
|
166
|
+
if not video_relative_path:
|
|
167
|
+
return {"error": "Video file path is empty or invalid"}
|
|
168
|
+
|
|
169
|
+
# Construct the path using the file's actual path
|
|
170
|
+
full_path = obj.active_file.path
|
|
171
|
+
return (
|
|
172
|
+
str(full_path)
|
|
173
|
+
if Path(full_path).exists()
|
|
174
|
+
else {"error": f"file not found at: {full_path}"}
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
except Exception as e:
|
|
178
|
+
return {"error": f"Error constructing file path: {str(e)}"}
|
|
179
|
+
|
|
180
|
+
def get_sequences(self, obj: "VideoFile"):
|
|
181
|
+
"""
|
|
182
|
+
Retrieve frame sequences for each label from the video object.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
dict: A mapping of label names to lists of frame ranges, or an error message if no sequences are found.
|
|
186
|
+
"""
|
|
187
|
+
return obj.sequences or {
|
|
188
|
+
"error": "no sequence found, check database first"
|
|
189
|
+
} # Get from sequences, return {} if missing
|
|
190
|
+
|
|
191
|
+
def get_label_names(self, obj: "VideoFile"):
|
|
192
|
+
"""
|
|
193
|
+
Return a list of label names present in the video's frame sequences.
|
|
194
|
+
|
|
195
|
+
Parameters:
|
|
196
|
+
obj (Video): The video instance to extract label names from.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
list[str]: List of label names, or an empty list if no sequences are found.
|
|
200
|
+
"""
|
|
201
|
+
sequences = self.get_sequences(obj)
|
|
202
|
+
return list(sequences.keys()) if sequences else []
|
|
203
|
+
|
|
204
|
+
def get_label_time_segments(self, obj: "VideoFile"):
|
|
205
|
+
"""
|
|
206
|
+
Convert frame sequences for each label into time segments with frame-level metadata.
|
|
207
|
+
|
|
208
|
+
For each label in the video, this method generates a list of time segments based on frame index ranges, converting them to seconds using the video's FPS. Each segment includes the raw frame indices, start and end times in seconds, and detailed information for each frame in the segment, such as filename, full file path, and a placeholder for predictions.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
dict: A dictionary mapping each label to its list of time segments and associated frame metadata.
|
|
212
|
+
"""
|
|
213
|
+
|
|
214
|
+
fps = getattr(obj, "fps", None)
|
|
215
|
+
if fps is None and hasattr(obj, "get_fps"):
|
|
216
|
+
fps = obj.get_fps()
|
|
217
|
+
|
|
218
|
+
if not fps or fps <= 0:
|
|
219
|
+
# Strict by default — only use fallback if explicitly enabled and > 0
|
|
220
|
+
if (
|
|
221
|
+
getattr(settings, "VIDEO_ALLOW_FPS_FALLBACK", False)
|
|
222
|
+
and getattr(settings, "VIDEO_DEFAULT_FPS", 0) > 0
|
|
223
|
+
):
|
|
224
|
+
fps = settings.VIDEO_DEFAULT_FPS
|
|
225
|
+
else:
|
|
226
|
+
raise ValidationError(
|
|
227
|
+
{
|
|
228
|
+
"label_time_segments": "FPS unavailable — cannot calculate time segments",
|
|
229
|
+
"video_id": getattr(obj, "id", None),
|
|
230
|
+
}
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
sequences = self.get_sequences(obj) # Fetch sequence data
|
|
234
|
+
frame_dir = Path(obj.frame_dir) # Get the correct directory from the model
|
|
235
|
+
time_segments = {} # Dictionary to store converted times and frame predictions
|
|
236
|
+
|
|
237
|
+
for label, frame_ranges in sequences.items():
|
|
238
|
+
label_times = [] # Stores time segments
|
|
239
|
+
frame_predictions = {} # Ensure frame_predictions is properly initialized for each label #TODO Currently always emty?
|
|
240
|
+
|
|
241
|
+
for frame_range in frame_ranges:
|
|
242
|
+
if len(frame_range) != 2:
|
|
243
|
+
continue # Skip invalid frame ranges
|
|
244
|
+
|
|
245
|
+
start_frame, end_frame = frame_range # Raw frame indices from DB
|
|
246
|
+
start_time = start_frame / fps # Convert frame index to seconds
|
|
247
|
+
end_time = end_frame / fps # Convert frame index to seconds
|
|
248
|
+
|
|
249
|
+
frame_data = {} # Store frame-wise info
|
|
250
|
+
|
|
251
|
+
# Fetch predictions for frames within this range
|
|
252
|
+
for frame_num in range(start_frame, end_frame + 1):
|
|
253
|
+
frame_filename = (
|
|
254
|
+
f"frame_{str(frame_num).zfill(7)}.jpg" # Frame filename format
|
|
255
|
+
)
|
|
256
|
+
frame_path = frame_dir / frame_filename # Full path to the frame
|
|
257
|
+
|
|
258
|
+
frame_data[frame_num] = {
|
|
259
|
+
"frame_filename": frame_filename,
|
|
260
|
+
"frame_file_path": str(frame_path),
|
|
261
|
+
"predictions": None,
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
# Append the converted time segment
|
|
265
|
+
label_times.append(
|
|
266
|
+
{
|
|
267
|
+
"segment_start": start_frame, # Raw start frame (not divided by FPS)
|
|
268
|
+
"segment_end": end_frame, # Raw end frame (not divided by FPS)
|
|
269
|
+
"start_time": round(
|
|
270
|
+
start_time, 2
|
|
271
|
+
), # Converted start time in seconds
|
|
272
|
+
"end_time": round(end_time, 2), # Converted end time in seconds
|
|
273
|
+
"frames": frame_data, # Attach frame details
|
|
274
|
+
}
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
# Store time segments and frame_predictions under the label
|
|
278
|
+
time_segments[label] = {
|
|
279
|
+
"time_ranges": label_times,
|
|
280
|
+
"frame_predictions": frame_predictions, # Ensure frame_predictions is correctly assigned
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return time_segments
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from endoreg_db.models import VideoFile
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from rest_framework import serializers
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class VideoBriefSerializer(serializers.ModelSerializer):
|
|
8
|
+
class Meta:
|
|
9
|
+
model = VideoFile
|
|
10
|
+
fields = [
|
|
11
|
+
"id",
|
|
12
|
+
"original_file_name",
|
|
13
|
+
"sensitive_meta_id",
|
|
14
|
+
] # for tables/overview
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from rest_framework import serializers
|
|
2
|
+
from django.conf import settings
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from endoreg_db.models.media.video.video_file import VideoFile
|
|
6
|
+
from endoreg_db.serializers.video.video_file_brief import VideoBriefSerializer
|
|
7
|
+
from ...utils.calc_duration_seconds import _calc_duration_vf
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class VideoDetailSerializer(VideoBriefSerializer):
|
|
11
|
+
# pull selected fields from SensitiveMeta (READ-ONLY) - using SerializerMethodField to handle datetime->date conversion
|
|
12
|
+
patient_first_name = serializers.CharField(
|
|
13
|
+
source="sensitive_meta.patient_first_name", read_only=True
|
|
14
|
+
)
|
|
15
|
+
patient_last_name = serializers.CharField(
|
|
16
|
+
source="sensitive_meta.patient_last_name", read_only=True
|
|
17
|
+
)
|
|
18
|
+
patient_dob = serializers.SerializerMethodField()
|
|
19
|
+
examination_date = serializers.SerializerMethodField()
|
|
20
|
+
|
|
21
|
+
file = serializers.SerializerMethodField()
|
|
22
|
+
full_path = serializers.SerializerMethodField()
|
|
23
|
+
duration = serializers.SerializerMethodField()
|
|
24
|
+
video_url = serializers.SerializerMethodField()
|
|
25
|
+
|
|
26
|
+
class Meta(VideoBriefSerializer.Meta):
|
|
27
|
+
fields = VideoBriefSerializer.Meta.fields + [
|
|
28
|
+
"file",
|
|
29
|
+
"full_path",
|
|
30
|
+
"video_url",
|
|
31
|
+
"patient_first_name",
|
|
32
|
+
"patient_last_name",
|
|
33
|
+
"patient_dob",
|
|
34
|
+
"examination_date",
|
|
35
|
+
"duration",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
# ---------- helpers ---------- #
|
|
39
|
+
def get_file(self, obj):
|
|
40
|
+
f = obj.processed_file or obj.raw_file
|
|
41
|
+
return f.name if f else None
|
|
42
|
+
|
|
43
|
+
def get_full_path(self, obj):
|
|
44
|
+
f = obj.processed_file or obj.raw_file
|
|
45
|
+
return str(Path(settings.MEDIA_ROOT) / f.name) if f else None
|
|
46
|
+
|
|
47
|
+
def get_video_url(self, obj):
|
|
48
|
+
"""
|
|
49
|
+
Return the absolute URL for accessing the video streaming resource.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
str or None: The absolute URL to the video streaming endpoint if a request context is available; otherwise, None.
|
|
53
|
+
"""
|
|
54
|
+
request = self.context.get("request")
|
|
55
|
+
# Use video streaming endpoint (VideoStreamView)
|
|
56
|
+
return (
|
|
57
|
+
request.build_absolute_uri(f"/api/media/videos/{obj.pk}/")
|
|
58
|
+
if request
|
|
59
|
+
else None
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def get_duration(self, obj: VideoFile):
|
|
63
|
+
"""
|
|
64
|
+
Return the duration of the video, using the stored value if available or calculating it if not.
|
|
65
|
+
|
|
66
|
+
Parameters:
|
|
67
|
+
obj (VideoFile): The video file instance.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
float or None: Duration of the video in seconds, or None if unavailable.
|
|
71
|
+
"""
|
|
72
|
+
return obj.duration or _calc_duration_vf(obj)
|
|
73
|
+
|
|
74
|
+
def get_patient_dob(self, obj):
|
|
75
|
+
"""
|
|
76
|
+
Returns the patient's date of birth as a date object if available, or None if not present.
|
|
77
|
+
|
|
78
|
+
Extracts the date part from the patient's date of birth field in the sensitive metadata, handling both datetime and date types.
|
|
79
|
+
"""
|
|
80
|
+
if obj.sensitive_meta and obj.sensitive_meta.patient_dob:
|
|
81
|
+
# If it's a datetime, extract the date part
|
|
82
|
+
dob = obj.sensitive_meta.patient_dob
|
|
83
|
+
return dob.date() if hasattr(dob, "date") else dob
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def get_examination_date(self, obj):
|
|
87
|
+
"""
|
|
88
|
+
Returns the examination date as a date object from the sensitive metadata, or None if unavailable.
|
|
89
|
+
|
|
90
|
+
If the examination date is a datetime, only the date part is returned.
|
|
91
|
+
"""
|
|
92
|
+
if obj.sensitive_meta and obj.sensitive_meta.examination_date:
|
|
93
|
+
# If it's a datetime, extract the date part
|
|
94
|
+
exam_date = obj.sensitive_meta.examination_date
|
|
95
|
+
return exam_date.date() if hasattr(exam_date, "date") else exam_date
|
|
96
|
+
return None
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# endoreg_db/serializers/video/video_file_list.py
|
|
2
|
+
from typing import Literal
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from rest_framework import serializers
|
|
6
|
+
|
|
7
|
+
from endoreg_db.models import VideoFile
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class VideoFileListSerializer(serializers.ModelSerializer):
|
|
13
|
+
"""
|
|
14
|
+
Minimal serializer to return only basic video information
|
|
15
|
+
for the video selection dropdown in Vue.js.
|
|
16
|
+
|
|
17
|
+
Convention:
|
|
18
|
+
- Serializer methods must NOT raise if video state is missing or invalid.
|
|
19
|
+
- They return safe defaults and log what went wrong.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
# Add computed fields for video status
|
|
23
|
+
status = serializers.SerializerMethodField()
|
|
24
|
+
assignedUser = serializers.SerializerMethodField()
|
|
25
|
+
anonymized = serializers.SerializerMethodField()
|
|
26
|
+
|
|
27
|
+
class Meta:
|
|
28
|
+
model = VideoFile
|
|
29
|
+
fields = ["id", "original_file_name", "status", "assignedUser", "anonymized"]
|
|
30
|
+
|
|
31
|
+
# --- internal helper -------------------------------------------------
|
|
32
|
+
def _get_video_state(self, obj: VideoFile):
|
|
33
|
+
"""
|
|
34
|
+
Best-effort accessor for obj.state.
|
|
35
|
+
|
|
36
|
+
Serializer layer must never raise here; it only logs and returns None
|
|
37
|
+
if the state cannot be loaded for any reason.
|
|
38
|
+
"""
|
|
39
|
+
try:
|
|
40
|
+
return getattr(obj, "state", None)
|
|
41
|
+
except (
|
|
42
|
+
Exception
|
|
43
|
+
) as exc: # pragma: no cover - type of error is DB/backend-specific
|
|
44
|
+
logger.warning(
|
|
45
|
+
"VideoFileListSerializer: unable to access state for VideoFile(id=%s): %s",
|
|
46
|
+
getattr(obj, "id", "unknown"),
|
|
47
|
+
exc,
|
|
48
|
+
)
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
# --- public serializer fields ----------------------------------------
|
|
52
|
+
def get_status(
|
|
53
|
+
self, obj: VideoFile
|
|
54
|
+
) -> Literal["completed", "in_progress", "available"]:
|
|
55
|
+
"""
|
|
56
|
+
Determine the processing status of a video file as 'completed',
|
|
57
|
+
'in_progress', or 'available'.
|
|
58
|
+
|
|
59
|
+
Contract:
|
|
60
|
+
- Never raises.
|
|
61
|
+
- Missing or invalid state -> treated as 'available'.
|
|
62
|
+
"""
|
|
63
|
+
state = self._get_video_state(obj)
|
|
64
|
+
|
|
65
|
+
if not state:
|
|
66
|
+
return "available"
|
|
67
|
+
|
|
68
|
+
# Use getattr with defaults to tolerate partially populated state objects
|
|
69
|
+
anonymized = getattr(state, "anonymized", False)
|
|
70
|
+
frames_extracted = getattr(state, "frames_extracted", False)
|
|
71
|
+
|
|
72
|
+
if anonymized:
|
|
73
|
+
return "completed"
|
|
74
|
+
if frames_extracted:
|
|
75
|
+
return "in_progress"
|
|
76
|
+
return "available"
|
|
77
|
+
|
|
78
|
+
def get_assignedUser(self, obj: VideoFile):
|
|
79
|
+
"""
|
|
80
|
+
Returns the user assigned to the video, or None if no user is assigned.
|
|
81
|
+
|
|
82
|
+
Currently always returns None as user assignment is not implemented.
|
|
83
|
+
"""
|
|
84
|
+
# For now return None, can be extended when user assignment is implemented
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
def get_anonymized(self, obj: VideoFile) -> bool:
|
|
88
|
+
"""
|
|
89
|
+
Determine whether the video has been anonymized.
|
|
90
|
+
|
|
91
|
+
Contract:
|
|
92
|
+
- Never raises.
|
|
93
|
+
- Returns False if state does not exist or cannot be loaded.
|
|
94
|
+
"""
|
|
95
|
+
state = self._get_video_state(obj)
|
|
96
|
+
if not state:
|
|
97
|
+
return False
|
|
98
|
+
|
|
99
|
+
# getattr to be robust against partially/populated state
|
|
100
|
+
return bool(getattr(state, "anonymized", False))
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Video Processing History Serializer
|
|
3
|
+
|
|
4
|
+
Serializes VideoProcessingHistory model for API responses.
|
|
5
|
+
Created as part of Phase 1.1: Video Correction API Endpoints.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from collections.abc import Mapping
|
|
9
|
+
|
|
10
|
+
from rest_framework import serializers
|
|
11
|
+
|
|
12
|
+
from endoreg_db.models import VideoProcessingHistory
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class VideoProcessingHistorySerializer(serializers.ModelSerializer):
|
|
16
|
+
"""
|
|
17
|
+
Serializer for VideoProcessingHistory model.
|
|
18
|
+
|
|
19
|
+
Provides operation audit trail (masking, frame removal, analysis)
|
|
20
|
+
with download URLs for processed files.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
download_url = serializers.SerializerMethodField()
|
|
24
|
+
operation_display = serializers.SerializerMethodField()
|
|
25
|
+
status_display = serializers.SerializerMethodField()
|
|
26
|
+
duration = serializers.ReadOnlyField()
|
|
27
|
+
is_complete = serializers.ReadOnlyField()
|
|
28
|
+
|
|
29
|
+
class Meta:
|
|
30
|
+
model = VideoProcessingHistory
|
|
31
|
+
fields = [
|
|
32
|
+
"id",
|
|
33
|
+
"video",
|
|
34
|
+
"operation",
|
|
35
|
+
"operation_display",
|
|
36
|
+
"status",
|
|
37
|
+
"status_display",
|
|
38
|
+
"config",
|
|
39
|
+
"output_file",
|
|
40
|
+
"download_url",
|
|
41
|
+
"details",
|
|
42
|
+
"task_id",
|
|
43
|
+
"created_at",
|
|
44
|
+
"completed_at",
|
|
45
|
+
"duration",
|
|
46
|
+
"is_complete",
|
|
47
|
+
]
|
|
48
|
+
read_only_fields = ["id", "created_at", "completed_at"]
|
|
49
|
+
|
|
50
|
+
def get_download_url(self, obj) -> str | None:
|
|
51
|
+
"""
|
|
52
|
+
Generate download URL for processed video file.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
obj: VideoProcessingHistory instance
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
str: URL to download processed file, or None if not available
|
|
59
|
+
"""
|
|
60
|
+
if not obj.output_file or obj.status != VideoProcessingHistory.STATUS_SUCCESS:
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
# Build URL to download endpoint (to be implemented)
|
|
64
|
+
# Format: /api/media/processed-videos/{video_id}/{history_id}/
|
|
65
|
+
context = self.context if isinstance(self.context, Mapping) else None
|
|
66
|
+
request = context.get("request") if context else None
|
|
67
|
+
if request:
|
|
68
|
+
return request.build_absolute_uri(
|
|
69
|
+
f"/api/media/processed-videos/{obj.video.id}/{obj.id}/"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
return f"/api/media/processed-videos/{obj.video.id}/{obj.id}/"
|
|
73
|
+
|
|
74
|
+
def get_operation_display(self, obj) -> str:
|
|
75
|
+
display = getattr(obj, "get_operation_display", None)
|
|
76
|
+
result = display() if callable(display) else obj.operation
|
|
77
|
+
return str(result)
|
|
78
|
+
|
|
79
|
+
def get_status_display(self, obj) -> str:
|
|
80
|
+
display = getattr(obj, "get_status_display", None)
|
|
81
|
+
result = display() if callable(display) else obj.status
|
|
82
|
+
return str(result)
|
|
83
|
+
|
|
84
|
+
def validate_operation(self, value):
|
|
85
|
+
"""
|
|
86
|
+
Validate operation is one of the defined choices.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
value: Operation type
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
str: Validated operation
|
|
93
|
+
|
|
94
|
+
Raises:
|
|
95
|
+
ValidationError: If operation is invalid
|
|
96
|
+
"""
|
|
97
|
+
valid_operations = [
|
|
98
|
+
choice[0] for choice in VideoProcessingHistory.OPERATION_CHOICES
|
|
99
|
+
]
|
|
100
|
+
if value not in valid_operations:
|
|
101
|
+
raise serializers.ValidationError(
|
|
102
|
+
f"Invalid operation. Must be one of: {', '.join(valid_operations)}"
|
|
103
|
+
)
|
|
104
|
+
return value
|
|
105
|
+
|
|
106
|
+
def validate_status(self, value):
|
|
107
|
+
"""
|
|
108
|
+
Validate status is one of the defined choices.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
value: Status type
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
str: Validated status
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
ValidationError: If status is invalid
|
|
118
|
+
"""
|
|
119
|
+
valid_statuses = [choice[0] for choice in VideoProcessingHistory.STATUS_CHOICES]
|
|
120
|
+
if value not in valid_statuses:
|
|
121
|
+
raise serializers.ValidationError(
|
|
122
|
+
f"Invalid status. Must be one of: {', '.join(valid_statuses)}"
|
|
123
|
+
)
|
|
124
|
+
return value
|
|
125
|
+
|
|
126
|
+
def validate_config(self, value):
|
|
127
|
+
"""
|
|
128
|
+
Validate config based on operation type.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
value: Config dictionary
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
dict: Validated config
|
|
135
|
+
|
|
136
|
+
Raises:
|
|
137
|
+
ValidationError: If config is invalid for operation
|
|
138
|
+
"""
|
|
139
|
+
if not isinstance(value, dict):
|
|
140
|
+
raise serializers.ValidationError("config must be a dictionary")
|
|
141
|
+
|
|
142
|
+
initial = self.initial_data if isinstance(self.initial_data, Mapping) else {}
|
|
143
|
+
operation = initial.get("operation")
|
|
144
|
+
|
|
145
|
+
# Validate masking config
|
|
146
|
+
if operation == VideoProcessingHistory.OPERATION_MASKING:
|
|
147
|
+
required_fields = ["mask_type"]
|
|
148
|
+
if "mask_type" not in value:
|
|
149
|
+
raise serializers.ValidationError(
|
|
150
|
+
f"Masking config must include: {', '.join(required_fields)}"
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# If device mask, require device_name
|
|
154
|
+
if value["mask_type"] == "device" and "device_name" not in value:
|
|
155
|
+
raise serializers.ValidationError(
|
|
156
|
+
"Device mask requires 'device_name' in config"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# If custom ROI, require roi coordinates
|
|
160
|
+
if value["mask_type"] == "custom" and "roi" not in value:
|
|
161
|
+
raise serializers.ValidationError(
|
|
162
|
+
"Custom mask requires 'roi' coordinates in config"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Validate frame removal config
|
|
166
|
+
elif operation == VideoProcessingHistory.OPERATION_FRAME_REMOVAL:
|
|
167
|
+
if "frame_list" not in value and "detection_method" not in value:
|
|
168
|
+
raise serializers.ValidationError(
|
|
169
|
+
"Frame removal config must include 'frame_list' (manual) or 'detection_method' (automatic)"
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
return value
|