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,47 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_video_key(
|
|
5
|
+
examination_alias: str, content: str, is_anonymous: bool = False
|
|
6
|
+
) -> str:
|
|
7
|
+
"""
|
|
8
|
+
Generates a video key based on the examination alias, content, and anonymity status.
|
|
9
|
+
"""
|
|
10
|
+
if is_anonymous:
|
|
11
|
+
return f"{examination_alias}-{content}-anonymous"
|
|
12
|
+
else:
|
|
13
|
+
return f"{examination_alias}-{content}-non_anonymous"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def identify_video_key(video_key: str) -> str:
|
|
17
|
+
"""
|
|
18
|
+
Identifies the video key based on the provided string.
|
|
19
|
+
"""
|
|
20
|
+
split_key = video_key.split("-")
|
|
21
|
+
assert len(split_key) == 3, f"Invalid video key format: {video_key}"
|
|
22
|
+
examination_alias = split_key[0]
|
|
23
|
+
content = split_key[1]
|
|
24
|
+
is_anonymous = split_key[2] == "anonymous"
|
|
25
|
+
return examination_alias, content, is_anonymous
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_video_key_regex_by_examination_alias(
|
|
29
|
+
examination_alias: Optional[str] = None,
|
|
30
|
+
content: Optional[str] = None,
|
|
31
|
+
is_anonymous: Optional[bool] = None,
|
|
32
|
+
):
|
|
33
|
+
"""
|
|
34
|
+
Generates a regex pattern to match video keys based on examination alias, content, and anonymity status.
|
|
35
|
+
If any of the parameters are None, they will be ignored in the regex.
|
|
36
|
+
"""
|
|
37
|
+
pattern = ""
|
|
38
|
+
if examination_alias:
|
|
39
|
+
pattern += f"{examination_alias}-"
|
|
40
|
+
if content:
|
|
41
|
+
pattern += f"{content}-"
|
|
42
|
+
if is_anonymous is not None:
|
|
43
|
+
pattern += "anonymous" if is_anonymous else "non_anonymous"
|
|
44
|
+
else:
|
|
45
|
+
pattern += "(anonymous|non_anonymous)"
|
|
46
|
+
|
|
47
|
+
return f"^{pattern}$"
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import subprocess
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Optional, Iterator, Tuple
|
|
5
|
+
import tempfile
|
|
6
|
+
import shutil
|
|
7
|
+
|
|
8
|
+
from ...exceptions import InsufficientStorageError, VideoProcessingError
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class StreamingVideoProcessor:
|
|
14
|
+
"""
|
|
15
|
+
Streaming video processor for memory-efficient video anonymization.
|
|
16
|
+
Processes videos in chunks to reduce memory usage and improve performance.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, chunk_duration: int = 30, temp_dir: Optional[Path] = None):
|
|
20
|
+
"""
|
|
21
|
+
Initialize the streaming processor.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
chunk_duration: Duration of each chunk in seconds
|
|
25
|
+
temp_dir: Temporary directory for processing chunks
|
|
26
|
+
"""
|
|
27
|
+
self.chunk_duration = chunk_duration
|
|
28
|
+
self.temp_dir = (
|
|
29
|
+
Path(temp_dir)
|
|
30
|
+
if temp_dir
|
|
31
|
+
else Path(tempfile.gettempdir()) / "video_streaming"
|
|
32
|
+
)
|
|
33
|
+
self.temp_dir.mkdir(parents=True, exist_ok=True)
|
|
34
|
+
|
|
35
|
+
def check_ffmpeg_available(self) -> bool:
|
|
36
|
+
"""Check if FFmpeg is available in the system."""
|
|
37
|
+
try:
|
|
38
|
+
subprocess.run(
|
|
39
|
+
["ffmpeg", "-version"], capture_output=True, check=True, timeout=10
|
|
40
|
+
)
|
|
41
|
+
return True
|
|
42
|
+
except (
|
|
43
|
+
subprocess.CalledProcessError,
|
|
44
|
+
FileNotFoundError,
|
|
45
|
+
subprocess.TimeoutExpired,
|
|
46
|
+
):
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
def get_video_duration(self, video_path: Path) -> float:
|
|
50
|
+
"""Get video duration in seconds using FFprobe."""
|
|
51
|
+
try:
|
|
52
|
+
cmd = [
|
|
53
|
+
"ffprobe",
|
|
54
|
+
"-v",
|
|
55
|
+
"quiet",
|
|
56
|
+
"-show_entries",
|
|
57
|
+
"format=duration",
|
|
58
|
+
"-of",
|
|
59
|
+
"csv=p=0",
|
|
60
|
+
str(video_path),
|
|
61
|
+
]
|
|
62
|
+
result = subprocess.run(
|
|
63
|
+
cmd, capture_output=True, text=True, check=True, timeout=30
|
|
64
|
+
)
|
|
65
|
+
return float(result.stdout.strip())
|
|
66
|
+
except (
|
|
67
|
+
subprocess.CalledProcessError,
|
|
68
|
+
ValueError,
|
|
69
|
+
subprocess.TimeoutExpired,
|
|
70
|
+
) as e:
|
|
71
|
+
logger.error(f"Failed to get video duration for {video_path}: {e}")
|
|
72
|
+
raise VideoProcessingError(f"Could not determine video duration: {e}")
|
|
73
|
+
|
|
74
|
+
def split_video_chunks(
|
|
75
|
+
self, video_path: Path
|
|
76
|
+
) -> Iterator[Tuple[Path, float, float]]:
|
|
77
|
+
"""
|
|
78
|
+
Split video into chunks for streaming processing.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
video_path: Path to the input video
|
|
82
|
+
|
|
83
|
+
Yields:
|
|
84
|
+
Tuple of (chunk_path, start_time, end_time)
|
|
85
|
+
"""
|
|
86
|
+
if not self.check_ffmpeg_available():
|
|
87
|
+
raise VideoProcessingError("FFmpeg not available for video processing")
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
total_duration = self.get_video_duration(video_path)
|
|
91
|
+
logger.info(
|
|
92
|
+
f"Video duration: {total_duration:.2f}s, splitting into {self.chunk_duration}s chunks"
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
chunk_count = 0
|
|
96
|
+
for start_time in range(0, int(total_duration), self.chunk_duration):
|
|
97
|
+
end_time = min(start_time + self.chunk_duration, total_duration)
|
|
98
|
+
|
|
99
|
+
# Create chunk filename
|
|
100
|
+
chunk_filename = (
|
|
101
|
+
f"chunk_{chunk_count:04d}_{start_time}_{int(end_time)}.mp4"
|
|
102
|
+
)
|
|
103
|
+
chunk_path = self.temp_dir / chunk_filename
|
|
104
|
+
|
|
105
|
+
# Extract chunk using FFmpeg
|
|
106
|
+
cmd = [
|
|
107
|
+
"ffmpeg",
|
|
108
|
+
"-y", # Overwrite output files
|
|
109
|
+
"-ss",
|
|
110
|
+
str(start_time), # Start time
|
|
111
|
+
"-i",
|
|
112
|
+
str(video_path), # Input file
|
|
113
|
+
"-t",
|
|
114
|
+
str(end_time - start_time), # Duration
|
|
115
|
+
"-c",
|
|
116
|
+
"copy", # Copy streams without re-encoding for speed
|
|
117
|
+
"-avoid_negative_ts",
|
|
118
|
+
"make_zero", # Handle timestamp issues
|
|
119
|
+
str(chunk_path),
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
logger.debug(
|
|
124
|
+
f"Creating chunk {chunk_count}: {start_time}s-{end_time}s"
|
|
125
|
+
)
|
|
126
|
+
result = subprocess.run(
|
|
127
|
+
cmd, capture_output=True, text=True, check=True, timeout=300
|
|
128
|
+
) # 5 minute timeout per chunk
|
|
129
|
+
|
|
130
|
+
if chunk_path.exists() and chunk_path.stat().st_size > 0:
|
|
131
|
+
yield chunk_path, start_time, end_time
|
|
132
|
+
chunk_count += 1
|
|
133
|
+
else:
|
|
134
|
+
logger.warning(
|
|
135
|
+
f"Chunk {chunk_count} was not created or is empty"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
except subprocess.CalledProcessError as e:
|
|
139
|
+
logger.error(f"FFmpeg failed for chunk {chunk_count}: {e.stderr}")
|
|
140
|
+
# Skip this chunk but continue with others
|
|
141
|
+
continue
|
|
142
|
+
except subprocess.TimeoutExpired:
|
|
143
|
+
logger.error(f"FFmpeg timeout for chunk {chunk_count}")
|
|
144
|
+
continue
|
|
145
|
+
|
|
146
|
+
except Exception as e:
|
|
147
|
+
logger.error(f"Error in video chunking: {e}")
|
|
148
|
+
raise VideoProcessingError(f"Video chunking failed: {e}")
|
|
149
|
+
|
|
150
|
+
def process_chunk_anonymization(
|
|
151
|
+
self, chunk_path: Path, anonymizer_func, **kwargs
|
|
152
|
+
) -> Path:
|
|
153
|
+
"""
|
|
154
|
+
Process a single chunk with the anonymization function.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
chunk_path: Path to the video chunk
|
|
158
|
+
anonymizer_func: Function to anonymize the chunk
|
|
159
|
+
**kwargs: Additional arguments for the anonymizer
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
Path to the anonymized chunk
|
|
163
|
+
"""
|
|
164
|
+
try:
|
|
165
|
+
output_path = chunk_path.with_suffix(".anonymized.mp4")
|
|
166
|
+
|
|
167
|
+
# Call the anonymization function
|
|
168
|
+
result = anonymizer_func(chunk_path, output_path, **kwargs)
|
|
169
|
+
|
|
170
|
+
if isinstance(result, Path):
|
|
171
|
+
return result
|
|
172
|
+
elif result is True and output_path.exists():
|
|
173
|
+
return output_path
|
|
174
|
+
else:
|
|
175
|
+
raise VideoProcessingError(
|
|
176
|
+
f"Anonymization failed for chunk {chunk_path}"
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
except Exception as e:
|
|
180
|
+
logger.error(f"Chunk anonymization failed for {chunk_path}: {e}")
|
|
181
|
+
raise VideoProcessingError(f"Chunk processing failed: {e}")
|
|
182
|
+
|
|
183
|
+
def merge_chunks(self, chunk_paths: list[Path], output_path: Path) -> Path:
|
|
184
|
+
"""
|
|
185
|
+
Merge anonymized chunks back into a single video.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
chunk_paths: List of paths to anonymized chunks
|
|
189
|
+
output_path: Path for the final merged video
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
Path to the merged video
|
|
193
|
+
"""
|
|
194
|
+
if not chunk_paths:
|
|
195
|
+
raise VideoProcessingError("No chunks to merge")
|
|
196
|
+
|
|
197
|
+
try:
|
|
198
|
+
# Check storage space before merging
|
|
199
|
+
total_chunk_size = sum(
|
|
200
|
+
chunk.stat().st_size for chunk in chunk_paths if chunk.exists()
|
|
201
|
+
)
|
|
202
|
+
free_space = shutil.disk_usage(output_path.parent).free
|
|
203
|
+
|
|
204
|
+
if free_space < total_chunk_size * 1.2: # 20% safety margin
|
|
205
|
+
raise InsufficientStorageError(
|
|
206
|
+
f"Insufficient space for merging. Required: {total_chunk_size * 1.2 / 1e9:.1f} GB, "
|
|
207
|
+
f"Available: {free_space / 1e9:.1f} GB",
|
|
208
|
+
required_space=int(total_chunk_size * 1.2),
|
|
209
|
+
available_space=free_space,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# Create concat file for FFmpeg
|
|
213
|
+
concat_file = self.temp_dir / f"concat_{output_path.stem}.txt"
|
|
214
|
+
|
|
215
|
+
with open(concat_file, "w") as f:
|
|
216
|
+
for chunk_path in chunk_paths:
|
|
217
|
+
if chunk_path.exists():
|
|
218
|
+
# Use relative paths in concat file for better portability
|
|
219
|
+
f.write(f"file '{chunk_path.name}'\n")
|
|
220
|
+
|
|
221
|
+
# Merge using FFmpeg concat demuxer
|
|
222
|
+
cmd = [
|
|
223
|
+
"ffmpeg",
|
|
224
|
+
"-y", # Overwrite output
|
|
225
|
+
"-f",
|
|
226
|
+
"concat", # Use concat demuxer
|
|
227
|
+
"-safe",
|
|
228
|
+
"0", # Allow unsafe file paths
|
|
229
|
+
"-i",
|
|
230
|
+
str(concat_file), # Input concat file
|
|
231
|
+
"-c",
|
|
232
|
+
"copy", # Copy streams without re-encoding
|
|
233
|
+
str(output_path),
|
|
234
|
+
]
|
|
235
|
+
|
|
236
|
+
logger.info(f"Merging {len(chunk_paths)} chunks into {output_path}")
|
|
237
|
+
|
|
238
|
+
# Change working directory to temp_dir for relative paths
|
|
239
|
+
result = subprocess.run(
|
|
240
|
+
cmd,
|
|
241
|
+
cwd=str(self.temp_dir),
|
|
242
|
+
capture_output=True,
|
|
243
|
+
text=True,
|
|
244
|
+
check=True,
|
|
245
|
+
timeout=600,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
if not output_path.exists() or output_path.stat().st_size == 0:
|
|
249
|
+
raise VideoProcessingError("Merged video was not created or is empty")
|
|
250
|
+
|
|
251
|
+
logger.info(f"Successfully merged video: {output_path}")
|
|
252
|
+
|
|
253
|
+
# Clean up concat file
|
|
254
|
+
concat_file.unlink(missing_ok=True)
|
|
255
|
+
|
|
256
|
+
return output_path
|
|
257
|
+
|
|
258
|
+
except subprocess.CalledProcessError as e:
|
|
259
|
+
logger.error(f"FFmpeg merge failed: {e.stderr}")
|
|
260
|
+
raise VideoProcessingError(f"Video merging failed: {e.stderr}")
|
|
261
|
+
except subprocess.TimeoutExpired:
|
|
262
|
+
logger.error("FFmpeg merge timeout")
|
|
263
|
+
raise VideoProcessingError("Video merging timed out")
|
|
264
|
+
except Exception as e:
|
|
265
|
+
logger.error(f"Unexpected error during merge: {e}")
|
|
266
|
+
raise VideoProcessingError(f"Video merging failed: {e}")
|
|
267
|
+
|
|
268
|
+
def process_video_streaming(
|
|
269
|
+
self,
|
|
270
|
+
input_path: Path,
|
|
271
|
+
output_path: Path,
|
|
272
|
+
anonymizer_func,
|
|
273
|
+
progress_callback=None,
|
|
274
|
+
**kwargs,
|
|
275
|
+
) -> Path:
|
|
276
|
+
"""
|
|
277
|
+
Process a video using streaming approach for memory efficiency.
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
input_path: Path to input video
|
|
281
|
+
output_path: Path for output video
|
|
282
|
+
anonymizer_func: Function to anonymize video chunks
|
|
283
|
+
progress_callback: Optional callback for progress updates
|
|
284
|
+
**kwargs: Additional arguments for anonymizer
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
Path to the processed video
|
|
288
|
+
"""
|
|
289
|
+
processed_chunks = []
|
|
290
|
+
total_chunks = 0
|
|
291
|
+
|
|
292
|
+
try:
|
|
293
|
+
logger.info(
|
|
294
|
+
f"Starting streaming video processing: {input_path} -> {output_path}"
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
# First pass: count total chunks for progress tracking
|
|
298
|
+
chunk_list = list(self.split_video_chunks(input_path))
|
|
299
|
+
total_chunks = len(chunk_list)
|
|
300
|
+
|
|
301
|
+
if total_chunks == 0:
|
|
302
|
+
raise VideoProcessingError(
|
|
303
|
+
"No chunks were created from the input video"
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
logger.info(f"Processing {total_chunks} chunks")
|
|
307
|
+
|
|
308
|
+
# Process each chunk
|
|
309
|
+
for i, (chunk_path, start_time, end_time) in enumerate(chunk_list):
|
|
310
|
+
try:
|
|
311
|
+
logger.debug(
|
|
312
|
+
f"Processing chunk {i + 1}/{total_chunks}: {chunk_path}"
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
# Process the chunk
|
|
316
|
+
processed_chunk = self.process_chunk_anonymization(
|
|
317
|
+
chunk_path, anonymizer_func, **kwargs
|
|
318
|
+
)
|
|
319
|
+
processed_chunks.append(processed_chunk)
|
|
320
|
+
|
|
321
|
+
# Update progress
|
|
322
|
+
if progress_callback:
|
|
323
|
+
progress = int(
|
|
324
|
+
(i + 1) / total_chunks * 80
|
|
325
|
+
) # Reserve 20% for merging
|
|
326
|
+
progress_callback(
|
|
327
|
+
progress, f"Processed chunk {i + 1}/{total_chunks}"
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
# Clean up original chunk to save space
|
|
331
|
+
chunk_path.unlink(missing_ok=True)
|
|
332
|
+
|
|
333
|
+
except Exception as e:
|
|
334
|
+
logger.error(f"Failed to process chunk {i}: {e}")
|
|
335
|
+
# Clean up failed chunk
|
|
336
|
+
chunk_path.unlink(missing_ok=True)
|
|
337
|
+
# Continue with other chunks
|
|
338
|
+
continue
|
|
339
|
+
|
|
340
|
+
if not processed_chunks:
|
|
341
|
+
raise VideoProcessingError("No chunks were successfully processed")
|
|
342
|
+
|
|
343
|
+
# Update progress for merging phase
|
|
344
|
+
if progress_callback:
|
|
345
|
+
progress_callback(
|
|
346
|
+
80, f"Merging {len(processed_chunks)} processed chunks..."
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
# Merge processed chunks
|
|
350
|
+
final_output = self.merge_chunks(processed_chunks, output_path)
|
|
351
|
+
|
|
352
|
+
# Final progress update
|
|
353
|
+
if progress_callback:
|
|
354
|
+
progress_callback(100, "Video processing completed")
|
|
355
|
+
|
|
356
|
+
logger.info(f"Streaming video processing completed: {final_output}")
|
|
357
|
+
return final_output
|
|
358
|
+
|
|
359
|
+
except (InsufficientStorageError, VideoProcessingError):
|
|
360
|
+
# Re-raise these specific errors as-is
|
|
361
|
+
raise
|
|
362
|
+
except Exception as e:
|
|
363
|
+
logger.error(f"Streaming video processing failed: {e}")
|
|
364
|
+
raise VideoProcessingError(f"Streaming processing failed: {e}")
|
|
365
|
+
finally:
|
|
366
|
+
# Clean up all temporary chunks
|
|
367
|
+
self.cleanup_chunks(processed_chunks)
|
|
368
|
+
|
|
369
|
+
def cleanup_chunks(self, chunk_paths: list[Path]) -> None:
|
|
370
|
+
"""Clean up temporary chunk files."""
|
|
371
|
+
for chunk_path in chunk_paths:
|
|
372
|
+
if chunk_path and chunk_path.exists():
|
|
373
|
+
try:
|
|
374
|
+
chunk_path.unlink()
|
|
375
|
+
logger.debug(f"Cleaned up chunk: {chunk_path}")
|
|
376
|
+
except Exception as e:
|
|
377
|
+
logger.warning(f"Failed to clean up chunk {chunk_path}: {e}")
|
|
378
|
+
|
|
379
|
+
def cleanup_temp_dir(self) -> None:
|
|
380
|
+
"""Clean up the entire temporary directory."""
|
|
381
|
+
try:
|
|
382
|
+
if self.temp_dir.exists():
|
|
383
|
+
shutil.rmtree(self.temp_dir)
|
|
384
|
+
logger.debug(f"Cleaned up temp directory: {self.temp_dir}")
|
|
385
|
+
except Exception as e:
|
|
386
|
+
logger.warning(f"Failed to clean up temp directory {self.temp_dir}: {e}")
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import pathlib
|
|
3
|
+
import math
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
# Setup basic logging
|
|
7
|
+
logging.basicConfig(
|
|
8
|
+
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_video_duration(video_path: pathlib.Path) -> float:
|
|
13
|
+
"""Gets the duration of a video file using ffprobe."""
|
|
14
|
+
cmd = [
|
|
15
|
+
"ffprobe",
|
|
16
|
+
"-v",
|
|
17
|
+
"error",
|
|
18
|
+
"-show_entries",
|
|
19
|
+
"format=duration",
|
|
20
|
+
"-of",
|
|
21
|
+
"default=noprint_wrappers=1:nokey=1",
|
|
22
|
+
str(video_path),
|
|
23
|
+
]
|
|
24
|
+
try:
|
|
25
|
+
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
26
|
+
duration = float(result.stdout.strip())
|
|
27
|
+
return duration
|
|
28
|
+
except subprocess.CalledProcessError as e:
|
|
29
|
+
logging.error(f"Error getting duration for {video_path}: {e.stderr}")
|
|
30
|
+
raise
|
|
31
|
+
except ValueError:
|
|
32
|
+
logging.error(f"Could not parse duration from ffprobe output: {result.stdout}")
|
|
33
|
+
raise
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def split_video(input_path: str, interval: int):
|
|
37
|
+
"""
|
|
38
|
+
Splits a video into segments of a specified interval using ffmpeg.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
input_path: Path to the input MP4 video file.
|
|
42
|
+
interval: The desired duration of each segment in seconds.
|
|
43
|
+
"""
|
|
44
|
+
input_file = pathlib.Path(input_path)
|
|
45
|
+
if not input_file.is_file():
|
|
46
|
+
logging.error(f"Input file not found: {input_path}")
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
video_name = input_file.stem
|
|
50
|
+
output_dir = pathlib.Path("data/video_splitter") / video_name
|
|
51
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
52
|
+
logging.info(f"Created output directory: {output_dir}")
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
duration = get_video_duration(input_file)
|
|
56
|
+
logging.info(f"Video duration: {duration:.2f} seconds")
|
|
57
|
+
except Exception as e:
|
|
58
|
+
logging.error(f"Could not get video duration. Aborting split. Error: {e}")
|
|
59
|
+
return
|
|
60
|
+
|
|
61
|
+
num_segments = math.ceil(duration / interval)
|
|
62
|
+
logging.info(
|
|
63
|
+
f"Splitting into {num_segments} segments of approximately {interval} seconds each."
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
for i in range(num_segments):
|
|
67
|
+
start_time = i * interval
|
|
68
|
+
output_filename = output_dir / f"segment_{i + 1:03d}{input_file.suffix}"
|
|
69
|
+
|
|
70
|
+
# Use -t for interval duration. For the last segment, ffmpeg with -c copy
|
|
71
|
+
# might automatically stop at the end, or we could calculate exact duration.
|
|
72
|
+
# Using -t interval is simpler and usually works well with -c copy.
|
|
73
|
+
# If the last segment needs precise duration without relying on -c copy behavior:
|
|
74
|
+
# segment_duration = min(interval, duration - start_time)
|
|
75
|
+
# However, -t interval with -c copy is generally robust.
|
|
76
|
+
|
|
77
|
+
cmd = [
|
|
78
|
+
"ffmpeg",
|
|
79
|
+
"-i",
|
|
80
|
+
str(input_file),
|
|
81
|
+
"-ss",
|
|
82
|
+
str(start_time),
|
|
83
|
+
"-t",
|
|
84
|
+
str(interval),
|
|
85
|
+
"-c",
|
|
86
|
+
"copy", # Fast, lossless splitting
|
|
87
|
+
"-avoid_negative_ts",
|
|
88
|
+
"make_zero", # Avoids issues with negative timestamps
|
|
89
|
+
str(output_filename),
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
logging.info(f"Running command: {' '.join(cmd)}")
|
|
93
|
+
try:
|
|
94
|
+
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
95
|
+
logging.info(f"Successfully created segment: {output_filename}")
|
|
96
|
+
if result.stderr: # ffmpeg often outputs info to stderr
|
|
97
|
+
logging.debug(f"ffmpeg output for segment {i + 1}:\n{result.stderr}")
|
|
98
|
+
except subprocess.CalledProcessError as e:
|
|
99
|
+
logging.error(f"Error creating segment {i + 1}: {output_filename}")
|
|
100
|
+
logging.error(f"Command failed: {' '.join(cmd)}")
|
|
101
|
+
logging.error(f"ffmpeg stderr:\n{e.stderr}")
|
|
102
|
+
# Decide if you want to stop on error or continue
|
|
103
|
+
# return # Uncomment to stop on first error
|
|
104
|
+
|
|
105
|
+
logging.info("Video splitting completed.")
|
endoreg_db/versioning.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
### Dynamic Versioning with Hatch-VCS
|
|
2
|
+
|
|
3
|
+
This project uses `hatch-vcs` to automatically determine the package version based on Git tags. This ensures that PyPI releases always match the Git tag exactly, without manually editing version files.
|
|
4
|
+
|
|
5
|
+
#### How It Works
|
|
6
|
+
|
|
7
|
+
1. **Clean State:** If the commit matches a tag (e.g., `v1.0.0`) and the working directory is clean, the version is `1.0.0`.
|
|
8
|
+
2. **Dirty State:** If files are modified or uncommitted, `hatch` appends a local identifier (e.g., `1.0.1.dev0+g<hash>.d<date>`). **PyPI will reject these uploads.**
|
|
9
|
+
3. **Distance State:** If you are ahead of a tag by commits, it generates a dev version (e.g., `1.0.1.dev4+g<hash>`).
|
|
10
|
+
|
|
11
|
+
#### Release Workflow
|
|
12
|
+
|
|
13
|
+
1. **Prepare Changes:**
|
|
14
|
+
Make your code changes, update `pyproject.toml` dependencies if needed, and commit everything.
|
|
15
|
+
```bash
|
|
16
|
+
git add .
|
|
17
|
+
git commit -m "Update dependencies for release"
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
2. **Ensure Clean State:**
|
|
23
|
+
Verify there are no uncommitted changes (no "dirty" state).
|
|
24
|
+
```bash
|
|
25
|
+
git status
|
|
26
|
+
# Output must say: "nothing to commit, working tree clean"
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
*If you have untracked changes you don't want to commit yet, run `git stash`.*
|
|
32
|
+
3. **Tag the Release:**
|
|
33
|
+
Create an annotated tag for the new version.
|
|
34
|
+
```bash
|
|
35
|
+
git tag -a v0.8.9.16 -m "Release v0.8.9.16"
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
4. **Build:**
|
|
41
|
+
Generate the distribution packages.
|
|
42
|
+
```bash
|
|
43
|
+
rm -rf /dist #ensure empty dist
|
|
44
|
+
python -m build
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
*Check:* The filename in `dist/` should look like `endoreg_db-0.8.9.16.tar.gz` (clean version).
|
|
50
|
+
5. **Publish:**
|
|
51
|
+
Upload to PyPI.
|
|
52
|
+
```bash
|
|
53
|
+
python -m twine upload dist/*
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
6. **Push:**
|
|
59
|
+
Push the commit and the tag to the remote repository.
|
|
60
|
+
```bash
|
|
61
|
+
git push origin main --tags
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
#### Troubleshooting
|
|
68
|
+
|
|
69
|
+
**Problem:** `build` generates a version like `0.8.9.17.dev0+g...`
|
|
70
|
+
**Cause:** Your working directory is "dirty" (uncommitted changes).
|
|
71
|
+
**Fix:**
|
|
72
|
+
|
|
73
|
+
1. Run `git status` to identify modified files.
|
|
74
|
+
2. Commit them, add them to `.gitignore`, or stash them (`git stash`).
|
|
75
|
+
3. Re-run the build.
|
|
76
|
+
|
|
77
|
+
**Problem:** `HTTPError: 400 Bad Request ... use of local versions is not allowed`
|
|
78
|
+
**Cause:** You attempted to upload a "dirty" build to PyPI.
|
|
79
|
+
**Fix:** Delete `dist/`, clean your git state (stash/commit), rebuild, and upload again.
|