endoreg-db 0.8.5.1__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/admin.py +92 -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 +18 -0
- endoreg_db/assets/dummy_model.ckpt +1 -0
- endoreg_db/codemods/readme.md +88 -0
- endoreg_db/codemods/rename_datetime_fields.py +92 -0
- endoreg_db/config/__init__.py +0 -0
- endoreg_db/config/env.py +101 -0
- endoreg_db/data/__init__.py +144 -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 +91 -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/examination/examinations/data.yaml +72 -0
- endoreg_db/data/examination/time/data.yaml +48 -0
- endoreg_db/data/examination/time-type/data.yaml +8 -0
- endoreg_db/data/examination/type/data.yaml +17 -0
- endoreg_db/data/examination_indication/endoscopy.yaml +424 -0
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +160 -0
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
- endoreg_db/data/examination_requirement_set/colonoscopy.yaml +15 -0
- endoreg_db/data/finding/anatomy_colon.yaml +128 -0
- endoreg_db/data/finding/colonoscopy.yaml +40 -0
- endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +56 -0
- endoreg_db/data/finding/complication.yaml +16 -0
- endoreg_db/data/finding/data.yaml +105 -0
- endoreg_db/data/finding/examination_setting.yaml +16 -0
- endoreg_db/data/finding/medication_related.yaml +18 -0
- endoreg_db/data/finding/outcome.yaml +12 -0
- endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +95 -0
- endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +22 -0
- endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +25 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +68 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +80 -0
- endoreg_db/data/finding_classification/colonoscopy_lst.yaml +21 -0
- endoreg_db/data/finding_classification/colonoscopy_nice.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_paris.yaml +26 -0
- endoreg_db/data/finding_classification/colonoscopy_sano.yaml +22 -0
- endoreg_db/data/finding_classification/colonoscopy_summary.yaml +53 -0
- endoreg_db/data/finding_classification/complication_generic.yaml +25 -0
- endoreg_db/data/finding_classification/examination_setting_generic.yaml +40 -0
- endoreg_db/data/finding_classification/histology_colo.yaml +51 -0
- endoreg_db/data/finding_classification/intervention_required.yaml +26 -0
- endoreg_db/data/finding_classification/medication_related.yaml +23 -0
- endoreg_db/data/finding_classification/visualized.yaml +33 -0
- endoreg_db/data/finding_classification_choice/bowel_preparation.yaml +78 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +32 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +15 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +17 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_paris.yaml +57 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +49 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +14 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +36 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_location.yaml +229 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +82 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
- endoreg_db/data/finding_classification_choice/complication_generic_types.yaml +15 -0
- endoreg_db/data/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
- endoreg_db/data/finding_classification_choice/histology.yaml +24 -0
- endoreg_db/data/finding_classification_choice/histology_polyp.yaml +20 -0
- endoreg_db/data/finding_classification_choice/outcome.yaml +19 -0
- endoreg_db/data/finding_classification_choice/yes_no_na.yaml +11 -0
- endoreg_db/data/finding_classification_type/colonoscopy_basic.yaml +48 -0
- endoreg_db/data/finding_intervention/endoscopy.yaml +43 -0
- endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +168 -0
- endoreg_db/data/finding_intervention/endoscopy_egd.yaml +128 -0
- endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +32 -0
- endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +9 -0
- endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +36 -0
- endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
- endoreg_db/data/finding_type/data.yaml +43 -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/age.yaml +26 -0
- endoreg_db/data/requirement/colonoscopy_baseline_austria.yaml +45 -0
- endoreg_db/data/requirement/disease_cardiovascular.yaml +79 -0
- endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +41 -0
- endoreg_db/data/requirement/disease_hepatology.yaml +12 -0
- endoreg_db/data/requirement/disease_misc.yaml +12 -0
- endoreg_db/data/requirement/disease_renal.yaml +96 -0
- endoreg_db/data/requirement/endoscopy_bleeding_risk.yaml +59 -0
- endoreg_db/data/requirement/event_cardiology.yaml +251 -0
- endoreg_db/data/requirement/event_requirements.yaml +145 -0
- endoreg_db/data/requirement/finding_colon_polyp.yaml +50 -0
- endoreg_db/data/requirement/gender.yaml +25 -0
- endoreg_db/data/requirement/lab_value.yaml +441 -0
- endoreg_db/data/requirement/medication.yaml +93 -0
- endoreg_db/data/requirement_operator/age.yaml +13 -0
- endoreg_db/data/requirement_operator/lab_operators.yaml +129 -0
- endoreg_db/data/requirement_operator/model_operators.yaml +96 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +48 -0
- endoreg_db/data/requirement_set/colonoscopy_austria_screening.yaml +57 -0
- endoreg_db/data/requirement_set/endoscopy_bleeding_risk.yaml +52 -0
- endoreg_db/data/requirement_set_type/data.yaml +20 -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 +11 -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 +19 -0
- endoreg_db/factories/__init__.py +0 -0
- endoreg_db/forms/__init__.py +5 -0
- endoreg_db/forms/examination_form.py +11 -0
- endoreg_db/forms/patient_finding_intervention_form.py +18 -0
- endoreg_db/forms/patient_form.py +27 -0
- endoreg_db/forms/questionnaires/__init__.py +1 -0
- endoreg_db/forms/questionnaires/tto_questionnaire.py +23 -0
- endoreg_db/forms/settings/__init__.py +8 -0
- endoreg_db/forms/unit.py +6 -0
- endoreg_db/helpers/__init__.py +0 -0
- endoreg_db/helpers/count_db.py +45 -0
- endoreg_db/helpers/data_loader.py +208 -0
- endoreg_db/helpers/default_objects.py +378 -0
- endoreg_db/helpers/download_segmentation_model.py +31 -0
- endoreg_db/helpers/interact.py +6 -0
- endoreg_db/helpers/test_video_helper.py +119 -0
- endoreg_db/logger_conf.py +140 -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 +125 -0
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +115 -0
- endoreg_db/management/commands/create_multilabel_model_meta.py +214 -0
- endoreg_db/management/commands/fix_missing_patient_data.py +172 -0
- endoreg_db/management/commands/fix_video_paths.py +165 -0
- endoreg_db/management/commands/import_fallback_video.py +203 -0
- endoreg_db/management/commands/import_report.py +298 -0
- endoreg_db/management/commands/import_video.py +423 -0
- endoreg_db/management/commands/import_video_with_classification.py +367 -0
- endoreg_db/management/commands/init_default_ai_model.py +112 -0
- endoreg_db/management/commands/load_ai_model_data.py +77 -0
- endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
- endoreg_db/management/commands/load_base_db_data.py +192 -0
- endoreg_db/management/commands/load_center_data.py +68 -0
- endoreg_db/management/commands/load_contraindication_data.py +41 -0
- endoreg_db/management/commands/load_disease_classification_choices_data.py +41 -0
- endoreg_db/management/commands/load_disease_classification_data.py +41 -0
- endoreg_db/management/commands/load_disease_data.py +62 -0
- endoreg_db/management/commands/load_distribution_data.py +66 -0
- endoreg_db/management/commands/load_endoscope_data.py +68 -0
- endoreg_db/management/commands/load_event_data.py +41 -0
- endoreg_db/management/commands/load_examination_data.py +75 -0
- endoreg_db/management/commands/load_examination_indication_data.py +86 -0
- endoreg_db/management/commands/load_finding_data.py +128 -0
- endoreg_db/management/commands/load_gender_data.py +44 -0
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +132 -0
- endoreg_db/management/commands/load_information_source.py +51 -0
- endoreg_db/management/commands/load_lab_value_data.py +50 -0
- endoreg_db/management/commands/load_medication_data.py +103 -0
- endoreg_db/management/commands/load_name_data.py +37 -0
- endoreg_db/management/commands/load_organ_data.py +43 -0
- endoreg_db/management/commands/load_pdf_type_data.py +61 -0
- endoreg_db/management/commands/load_profession_data.py +44 -0
- endoreg_db/management/commands/load_qualification_data.py +59 -0
- endoreg_db/management/commands/load_report_reader_flag_data.py +46 -0
- endoreg_db/management/commands/load_requirement_data.py +180 -0
- endoreg_db/management/commands/load_risk_data.py +56 -0
- endoreg_db/management/commands/load_shift_data.py +60 -0
- endoreg_db/management/commands/load_tag_data.py +57 -0
- endoreg_db/management/commands/load_unit_data.py +46 -0
- endoreg_db/management/commands/load_user_groups.py +28 -0
- endoreg_db/management/commands/register_ai_model.py +64 -0
- endoreg_db/management/commands/reset_celery_schedule.py +9 -0
- endoreg_db/management/commands/setup_endoreg_db.py +381 -0
- endoreg_db/management/commands/start_filewatcher.py +106 -0
- endoreg_db/management/commands/storage_management.py +548 -0
- endoreg_db/management/commands/summarize_db_content.py +189 -0
- endoreg_db/management/commands/validate_video.py +204 -0
- endoreg_db/management/commands/validate_video_files.py +161 -0
- endoreg_db/management/commands/video_validation.py +22 -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 +1857 -0
- endoreg_db/migrations/0002_add_video_correction_models.py +52 -0
- endoreg_db/migrations/0003_add_center_display_name.py +30 -0
- endoreg_db/migrations/__init__.py +0 -0
- endoreg_db/models/__init__.py +359 -0
- endoreg_db/models/administration/__init__.py +116 -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 +156 -0
- endoreg_db/models/administration/ai/model_type.py +41 -0
- endoreg_db/models/administration/case/__init__.py +19 -0
- endoreg_db/models/administration/case/case.py +114 -0
- endoreg_db/models/administration/case/case_template/__init__.py +15 -0
- endoreg_db/models/administration/case/case_template/case_template.py +125 -0
- endoreg_db/models/administration/case/case_template/case_template_rule.py +269 -0
- endoreg_db/models/administration/case/case_template/case_template_rule_value.py +86 -0
- endoreg_db/models/administration/case/case_template/case_template_type.py +26 -0
- endoreg_db/models/administration/center/__init__.py +13 -0
- endoreg_db/models/administration/center/center.py +67 -0
- endoreg_db/models/administration/center/center_product.py +64 -0
- endoreg_db/models/administration/center/center_resource.py +49 -0
- endoreg_db/models/administration/center/center_shift.py +88 -0
- endoreg_db/models/administration/center/center_waste.py +30 -0
- endoreg_db/models/administration/permissions/__init__.py +44 -0
- endoreg_db/models/administration/person/__init__.py +24 -0
- endoreg_db/models/administration/person/employee/__init__.py +3 -0
- endoreg_db/models/administration/person/employee/employee.py +35 -0
- endoreg_db/models/administration/person/employee/employee_qualification.py +39 -0
- endoreg_db/models/administration/person/employee/employee_type.py +42 -0
- endoreg_db/models/administration/person/examiner/__init__.py +4 -0
- endoreg_db/models/administration/person/examiner/examiner.py +54 -0
- endoreg_db/models/administration/person/names/__init__.py +0 -0
- endoreg_db/models/administration/person/names/first_name.py +18 -0
- endoreg_db/models/administration/person/names/last_name.py +19 -0
- endoreg_db/models/administration/person/patient/__init__.py +5 -0
- endoreg_db/models/administration/person/patient/patient.py +460 -0
- endoreg_db/models/administration/person/person.py +31 -0
- endoreg_db/models/administration/person/profession/__init__.py +24 -0
- endoreg_db/models/administration/person/user/__init__.py +5 -0
- endoreg_db/models/administration/person/user/portal_user_information.py +37 -0
- endoreg_db/models/administration/product/__init__.py +14 -0
- endoreg_db/models/administration/product/product.py +97 -0
- endoreg_db/models/administration/product/product_group.py +39 -0
- endoreg_db/models/administration/product/product_material.py +54 -0
- endoreg_db/models/administration/product/product_weight.py +47 -0
- endoreg_db/models/administration/product/reference_product.py +130 -0
- endoreg_db/models/administration/qualification/__init__.py +7 -0
- endoreg_db/models/administration/qualification/qualification.py +37 -0
- endoreg_db/models/administration/qualification/qualification_type.py +35 -0
- endoreg_db/models/administration/shift/__init__.py +9 -0
- endoreg_db/models/administration/shift/scheduled_days.py +69 -0
- endoreg_db/models/administration/shift/shift.py +51 -0
- endoreg_db/models/administration/shift/shift_type.py +108 -0
- endoreg_db/models/label/__init__.py +24 -0
- endoreg_db/models/label/annotation/__init__.py +12 -0
- endoreg_db/models/label/annotation/image_classification.py +84 -0
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +66 -0
- endoreg_db/models/label/label.py +83 -0
- endoreg_db/models/label/label_set.py +53 -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 +41 -0
- endoreg_db/models/label/label_video_segment/label_video_segment.py +511 -0
- endoreg_db/models/label/video_segmentation_label.py +31 -0
- endoreg_db/models/label/video_segmentation_labelset.py +27 -0
- endoreg_db/models/media/__init__.py +16 -0
- endoreg_db/models/media/frame/__init__.py +3 -0
- endoreg_db/models/media/frame/frame.py +111 -0
- endoreg_db/models/media/pdf/__init__.py +11 -0
- endoreg_db/models/media/pdf/raw_pdf.py +613 -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 +77 -0
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +20 -0
- endoreg_db/models/media/video/__init__.py +8 -0
- endoreg_db/models/media/video/create_from_file.py +358 -0
- endoreg_db/models/media/video/pipe_1.py +213 -0
- endoreg_db/models/media/video/pipe_2.py +105 -0
- endoreg_db/models/media/video/refactor_plan.md +0 -0
- endoreg_db/models/media/video/video_file.py +699 -0
- endoreg_db/models/media/video/video_file_ai.py +443 -0
- endoreg_db/models/media/video/video_file_anonymize.py +349 -0
- endoreg_db/models/media/video/video_file_frames/__init__.py +47 -0
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +22 -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 +104 -0
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +174 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +28 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +20 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +34 -0
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +129 -0
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +141 -0
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +65 -0
- endoreg_db/models/media/video/video_file_frames.py +0 -0
- endoreg_db/models/media/video/video_file_io.py +168 -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 +45 -0
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +39 -0
- endoreg_db/models/media/video/video_file_meta/get_fps.py +147 -0
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +143 -0
- endoreg_db/models/media/video/video_file_meta/text_meta.py +134 -0
- endoreg_db/models/media/video/video_file_meta/video_meta.py +70 -0
- endoreg_db/models/media/video/video_file_segments.py +209 -0
- endoreg_db/models/media/video/video_metadata.py +65 -0
- endoreg_db/models/media/video/video_processing.py +152 -0
- endoreg_db/models/medical/__init__.py +146 -0
- endoreg_db/models/medical/contraindication/__init__.py +17 -0
- endoreg_db/models/medical/disease.py +156 -0
- endoreg_db/models/medical/event.py +137 -0
- endoreg_db/models/medical/examination/__init__.py +9 -0
- endoreg_db/models/medical/examination/examination.py +148 -0
- endoreg_db/models/medical/examination/examination_indication.py +278 -0
- endoreg_db/models/medical/examination/examination_time.py +49 -0
- endoreg_db/models/medical/examination/examination_time_type.py +41 -0
- endoreg_db/models/medical/examination/examination_type.py +48 -0
- endoreg_db/models/medical/finding/__init__.py +18 -0
- endoreg_db/models/medical/finding/finding.py +96 -0
- endoreg_db/models/medical/finding/finding_classification.py +142 -0
- endoreg_db/models/medical/finding/finding_intervention.py +52 -0
- endoreg_db/models/medical/finding/finding_type.py +35 -0
- endoreg_db/models/medical/hardware/__init__.py +8 -0
- endoreg_db/models/medical/hardware/endoscope.py +65 -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 +419 -0
- endoreg_db/models/medical/medication/__init__.py +19 -0
- endoreg_db/models/medical/medication/medication.py +31 -0
- endoreg_db/models/medical/medication/medication_indication.py +50 -0
- endoreg_db/models/medical/medication/medication_indication_type.py +39 -0
- endoreg_db/models/medical/medication/medication_intake_time.py +44 -0
- endoreg_db/models/medical/medication/medication_schedule.py +45 -0
- endoreg_db/models/medical/organ/__init__.py +35 -0
- endoreg_db/models/medical/patient/__init__.py +56 -0
- endoreg_db/models/medical/patient/medication_examples.py +38 -0
- endoreg_db/models/medical/patient/patient_disease.py +63 -0
- endoreg_db/models/medical/patient/patient_event.py +75 -0
- endoreg_db/models/medical/patient/patient_examination.py +249 -0
- endoreg_db/models/medical/patient/patient_examination_indication.py +44 -0
- endoreg_db/models/medical/patient/patient_finding.py +357 -0
- endoreg_db/models/medical/patient/patient_finding_classification.py +207 -0
- endoreg_db/models/medical/patient/patient_finding_intervention.py +40 -0
- endoreg_db/models/medical/patient/patient_lab_sample.py +148 -0
- endoreg_db/models/medical/patient/patient_lab_value.py +222 -0
- endoreg_db/models/medical/patient/patient_medication.py +104 -0
- endoreg_db/models/medical/patient/patient_medication_schedule.py +136 -0
- endoreg_db/models/medical/risk/__init__.py +7 -0
- endoreg_db/models/medical/risk/risk.py +72 -0
- endoreg_db/models/medical/risk/risk_type.py +51 -0
- endoreg_db/models/metadata/__init__.py +19 -0
- endoreg_db/models/metadata/frame_ocr_result.py +0 -0
- endoreg_db/models/metadata/model_meta.py +206 -0
- endoreg_db/models/metadata/model_meta_logic.py +343 -0
- endoreg_db/models/metadata/pdf_meta.py +89 -0
- endoreg_db/models/metadata/sensitive_meta.py +288 -0
- endoreg_db/models/metadata/sensitive_meta_logic.py +730 -0
- endoreg_db/models/metadata/video_meta.py +332 -0
- endoreg_db/models/metadata/video_prediction_logic.py +190 -0
- endoreg_db/models/metadata/video_prediction_meta.py +270 -0
- endoreg_db/models/other/__init__.py +40 -0
- endoreg_db/models/other/distribution/__init__.py +44 -0
- endoreg_db/models/other/distribution/base_value_distribution.py +20 -0
- endoreg_db/models/other/distribution/date_value_distribution.py +89 -0
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
- endoreg_db/models/other/distribution/numeric_value_distribution.py +125 -0
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
- endoreg_db/models/other/emission/__init__.py +5 -0
- endoreg_db/models/other/emission/emission_factor.py +94 -0
- endoreg_db/models/other/gender.py +27 -0
- endoreg_db/models/other/information_source.py +159 -0
- endoreg_db/models/other/material.py +28 -0
- endoreg_db/models/other/resource.py +22 -0
- endoreg_db/models/other/tag.py +27 -0
- endoreg_db/models/other/transport_route.py +33 -0
- endoreg_db/models/other/unit.py +32 -0
- endoreg_db/models/other/waste.py +27 -0
- endoreg_db/models/requirement/__init__.py +11 -0
- endoreg_db/models/requirement/requirement.py +767 -0
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +6 -0
- endoreg_db/models/requirement/requirement_evaluation/get_values.py +40 -0
- endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +9 -0
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +95 -0
- endoreg_db/models/requirement/requirement_operator.py +176 -0
- endoreg_db/models/requirement/requirement_set.py +287 -0
- endoreg_db/models/rule/__init__.py +13 -0
- endoreg_db/models/rule/rule.py +27 -0
- endoreg_db/models/rule/rule_applicator.py +224 -0
- endoreg_db/models/rule/rule_attribute_dtype.py +17 -0
- endoreg_db/models/rule/rule_type.py +20 -0
- endoreg_db/models/rule/ruleset.py +17 -0
- endoreg_db/models/state/__init__.py +12 -0
- endoreg_db/models/state/abstract.py +11 -0
- endoreg_db/models/state/audit_ledger.py +150 -0
- endoreg_db/models/state/label_video_segment.py +22 -0
- endoreg_db/models/state/raw_pdf.py +187 -0
- endoreg_db/models/state/sensitive_meta.py +46 -0
- endoreg_db/models/state/video.py +232 -0
- endoreg_db/models/upload_job.py +99 -0
- endoreg_db/models/utils.py +135 -0
- endoreg_db/queries/__init__.py +5 -0
- endoreg_db/queries/annotations/__init__.py +3 -0
- endoreg_db/queries/annotations/legacy.py +158 -0
- endoreg_db/queries/sanity/__init_.py +0 -0
- endoreg_db/renames.yml +8 -0
- endoreg_db/root_urls.py +9 -0
- endoreg_db/schemas/__init__.py +0 -0
- endoreg_db/schemas/examination_evaluation.py +27 -0
- endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +775 -0
- endoreg_db/serializers/__init__.py +147 -0
- endoreg_db/serializers/_old/raw_pdf_meta_validation.py +223 -0
- endoreg_db/serializers/_old/raw_video_meta_validation.py +179 -0
- endoreg_db/serializers/_old/video.py +71 -0
- endoreg_db/serializers/administration/__init__.py +14 -0
- endoreg_db/serializers/administration/ai/__init__.py +10 -0
- endoreg_db/serializers/administration/ai/active_model.py +10 -0
- endoreg_db/serializers/administration/ai/ai_model.py +18 -0
- endoreg_db/serializers/administration/ai/model_type.py +10 -0
- endoreg_db/serializers/administration/center.py +9 -0
- endoreg_db/serializers/administration/gender.py +9 -0
- endoreg_db/serializers/anonymization.py +69 -0
- endoreg_db/serializers/evaluation/examination_evaluation.py +1 -0
- endoreg_db/serializers/examination/__init__.py +10 -0
- endoreg_db/serializers/examination/base.py +46 -0
- endoreg_db/serializers/examination/dropdown.py +21 -0
- endoreg_db/serializers/examination_serializer.py +12 -0
- endoreg_db/serializers/finding/__init__.py +5 -0
- endoreg_db/serializers/finding/finding.py +54 -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 +13 -0
- endoreg_db/serializers/label/__init__.py +7 -0
- endoreg_db/serializers/label/image_classification_annotation.py +62 -0
- endoreg_db/serializers/label/label.py +15 -0
- endoreg_db/serializers/label_video_segment/__init__.py +7 -0
- endoreg_db/serializers/label_video_segment/_lvs_create.py +149 -0
- endoreg_db/serializers/label_video_segment/_lvs_update.py +138 -0
- endoreg_db/serializers/label_video_segment/_lvs_validate.py +149 -0
- endoreg_db/serializers/label_video_segment/label_video_segment.py +344 -0
- endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +99 -0
- endoreg_db/serializers/label_video_segment/label_video_segment_update.py +163 -0
- endoreg_db/serializers/meta/__init__.py +19 -0
- endoreg_db/serializers/meta/pdf_file_meta_extraction.py +115 -0
- endoreg_db/serializers/meta/report_meta.py +53 -0
- endoreg_db/serializers/meta/sensitive_meta_detail.py +162 -0
- endoreg_db/serializers/meta/sensitive_meta_update.py +148 -0
- endoreg_db/serializers/meta/sensitive_meta_verification.py +59 -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 +152 -0
- endoreg_db/serializers/misc/stats.py +33 -0
- endoreg_db/serializers/misc/translatable_field_mix_in.py +44 -0
- endoreg_db/serializers/misc/upload_job.py +71 -0
- endoreg_db/serializers/misc/vop_patient_data.py +120 -0
- endoreg_db/serializers/patient/__init__.py +11 -0
- endoreg_db/serializers/patient/patient.py +86 -0
- endoreg_db/serializers/patient/patient_dropdown.py +27 -0
- endoreg_db/serializers/patient_examination/__init__.py +7 -0
- endoreg_db/serializers/patient_examination/patient_examination.py +141 -0
- endoreg_db/serializers/patient_finding/__init__.py +15 -0
- endoreg_db/serializers/patient_finding/patient_finding.py +31 -0
- endoreg_db/serializers/patient_finding/patient_finding_classification.py +39 -0
- endoreg_db/serializers/patient_finding/patient_finding_detail.py +53 -0
- endoreg_db/serializers/patient_finding/patient_finding_intervention.py +26 -0
- endoreg_db/serializers/patient_finding/patient_finding_list.py +41 -0
- endoreg_db/serializers/patient_finding/patient_finding_write.py +126 -0
- endoreg_db/serializers/pdf/__init__.py +5 -0
- endoreg_db/serializers/pdf/anony_text_validation.py +85 -0
- endoreg_db/serializers/report/__init__.py +9 -0
- endoreg_db/serializers/report/mixins.py +45 -0
- endoreg_db/serializers/report/report.py +105 -0
- endoreg_db/serializers/report/report_list.py +22 -0
- endoreg_db/serializers/report/secure_file_url.py +26 -0
- endoreg_db/serializers/requirements/requirement_schema.py +25 -0
- endoreg_db/serializers/requirements/requirement_sets.py +29 -0
- endoreg_db/serializers/sensitive_meta_serializer.py +282 -0
- endoreg_db/serializers/video/__init__.py +7 -0
- endoreg_db/serializers/video/segmentation.py +263 -0
- endoreg_db/serializers/video/video_file_brief.py +10 -0
- endoreg_db/serializers/video/video_file_detail.py +83 -0
- endoreg_db/serializers/video/video_file_list.py +67 -0
- endoreg_db/serializers/video/video_metadata.py +105 -0
- endoreg_db/serializers/video/video_processing_history.py +153 -0
- endoreg_db/services/__init__.py +5 -0
- endoreg_db/services/anonymization.py +223 -0
- endoreg_db/services/examination_evaluation.py +149 -0
- endoreg_db/services/finding_description_service.py +0 -0
- endoreg_db/services/lookup_service.py +241 -0
- endoreg_db/services/lookup_store.py +122 -0
- endoreg_db/services/pdf_import.py +1159 -0
- endoreg_db/services/polling_coordinator.py +288 -0
- endoreg_db/services/pseudonym_service.py +89 -0
- endoreg_db/services/requirements_object.py +147 -0
- endoreg_db/services/segment_sync.py +155 -0
- endoreg_db/services/storage_aware_video_processor.py +344 -0
- endoreg_db/services/video_import.py +1258 -0
- endoreg_db/tasks/upload_tasks.py +207 -0
- endoreg_db/tasks/video_ingest.py +157 -0
- endoreg_db/tasks/video_processing_tasks.py +327 -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 +70 -0
- endoreg_db/urls/anonymization.py +32 -0
- endoreg_db/urls/auth.py +16 -0
- endoreg_db/urls/classification.py +39 -0
- endoreg_db/urls/examination.py +54 -0
- endoreg_db/urls/files.py +6 -0
- endoreg_db/urls/label_video_segment_validate.py +33 -0
- endoreg_db/urls/label_video_segments.py +44 -0
- endoreg_db/urls/media.py +226 -0
- endoreg_db/urls/patient.py +19 -0
- endoreg_db/urls/report.py +48 -0
- endoreg_db/urls/requirements.py +13 -0
- endoreg_db/urls/sensitive_meta.py +0 -0
- endoreg_db/urls/stats.py +46 -0
- endoreg_db/urls/upload.py +20 -0
- endoreg_db/urls/video.py +61 -0
- endoreg_db/urls.py +9 -0
- endoreg_db/utils/__init__.py +88 -0
- endoreg_db/utils/ai/__init__.py +9 -0
- endoreg_db/utils/ai/get.py +5 -0
- endoreg_db/utils/ai/inference_dataset.py +52 -0
- endoreg_db/utils/ai/multilabel_classification_net.py +159 -0
- endoreg_db/utils/ai/postprocess.py +63 -0
- endoreg_db/utils/ai/predict.py +291 -0
- endoreg_db/utils/ai/preprocess.py +68 -0
- endoreg_db/utils/calc_duration_seconds.py +24 -0
- endoreg_db/utils/case_generator/__init__.py +0 -0
- endoreg_db/utils/case_generator/case_generator.py +159 -0
- endoreg_db/utils/case_generator/lab_sample_factory.py +33 -0
- endoreg_db/utils/case_generator/utils.py +30 -0
- endoreg_db/utils/check_video_files.py +148 -0
- endoreg_db/utils/cropping.py +29 -0
- endoreg_db/utils/dataloader.py +175 -0
- endoreg_db/utils/dates.py +60 -0
- endoreg_db/utils/env.py +33 -0
- endoreg_db/utils/extract_specific_frames.py +72 -0
- endoreg_db/utils/file_operations.py +58 -0
- endoreg_db/utils/fix_video_path_direct.py +141 -0
- endoreg_db/utils/frame_anonymization_utils.py +463 -0
- endoreg_db/utils/hashs.py +153 -0
- endoreg_db/utils/links/__init__.py +0 -0
- endoreg_db/utils/links/requirement_link.py +193 -0
- endoreg_db/utils/mime_types.py +0 -0
- endoreg_db/utils/names.py +76 -0
- endoreg_db/utils/ocr.py +190 -0
- endoreg_db/utils/parse_and_generate_yaml.py +46 -0
- endoreg_db/utils/paths.py +95 -0
- endoreg_db/utils/permissions.py +143 -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 +120 -0
- endoreg_db/utils/product/__init__.py +0 -0
- endoreg_db/utils/product/sum_emissions.py +20 -0
- endoreg_db/utils/product/sum_weights.py +18 -0
- endoreg_db/utils/pydantic_models/__init__.py +6 -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/lab_value_operators.py +578 -0
- endoreg_db/utils/requirement_operator_logic/model_evaluators.py +368 -0
- endoreg_db/utils/setup_config.py +177 -0
- endoreg_db/utils/translation.py +27 -0
- endoreg_db/utils/uuid.py +4 -0
- endoreg_db/utils/validate_endo_roi.py +19 -0
- endoreg_db/utils/validate_subcategory_dict.py +91 -0
- endoreg_db/utils/validate_video_detailed.py +357 -0
- endoreg_db/utils/video/__init__.py +26 -0
- endoreg_db/utils/video/extract_frames.py +88 -0
- endoreg_db/utils/video/ffmpeg_wrapper.py +835 -0
- endoreg_db/utils/video/names.py +42 -0
- endoreg_db/utils/video/streaming_processor.py +312 -0
- endoreg_db/utils/video/video_splitter.py +94 -0
- endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +238 -0
- endoreg_db/views/__init__.py +272 -0
- endoreg_db/views/anonymization/__init__.py +27 -0
- endoreg_db/views/anonymization/media_management.py +454 -0
- endoreg_db/views/anonymization/overview.py +216 -0
- endoreg_db/views/anonymization/validate.py +107 -0
- endoreg_db/views/auth/__init__.py +13 -0
- endoreg_db/views/auth/keycloak.py +113 -0
- endoreg_db/views/examination/__init__.py +33 -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 +59 -0
- endoreg_db/views/examination/get_finding_classifications.py +36 -0
- endoreg_db/views/examination/get_findings.py +41 -0
- endoreg_db/views/examination/get_instruments.py +18 -0
- endoreg_db/views/examination/get_interventions.py +14 -0
- endoreg_db/views/finding/__init__.py +9 -0
- endoreg_db/views/finding/finding.py +112 -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 +42 -0
- endoreg_db/views/finding_classification/get_classification_choices.py +55 -0
- endoreg_db/views/label/__init__.py +5 -0
- endoreg_db/views/label/label.py +15 -0
- endoreg_db/views/label_video_segment/__init__.py +16 -0
- endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +44 -0
- endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +50 -0
- endoreg_db/views/label_video_segment/label_video_segment.py +77 -0
- endoreg_db/views/label_video_segment/label_video_segment_by_label.py +174 -0
- endoreg_db/views/label_video_segment/label_video_segment_detail.py +73 -0
- endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +46 -0
- endoreg_db/views/label_video_segment/validate.py +226 -0
- endoreg_db/views/media/__init__.py +45 -0
- endoreg_db/views/media/pdf_media.py +386 -0
- endoreg_db/views/media/segments.py +71 -0
- endoreg_db/views/media/sensitive_metadata.py +314 -0
- endoreg_db/views/media/video_media.py +272 -0
- endoreg_db/views/media/video_segments.py +524 -0
- endoreg_db/views/meta/__init__.py +15 -0
- endoreg_db/views/meta/available_files_list.py +146 -0
- endoreg_db/views/meta/report_meta.py +53 -0
- endoreg_db/views/meta/sensitive_meta_detail.py +148 -0
- endoreg_db/views/meta/sensitive_meta_list.py +104 -0
- endoreg_db/views/meta/sensitive_meta_verification.py +71 -0
- endoreg_db/views/misc/__init__.py +63 -0
- endoreg_db/views/misc/center.py +13 -0
- endoreg_db/views/misc/csrf.py +7 -0
- endoreg_db/views/misc/gender.py +14 -0
- endoreg_db/views/misc/secure_file_serving_view.py +80 -0
- endoreg_db/views/misc/secure_file_url_view.py +84 -0
- endoreg_db/views/misc/secure_url_validate.py +79 -0
- endoreg_db/views/misc/stats.py +220 -0
- endoreg_db/views/misc/translation.py +182 -0
- endoreg_db/views/misc/upload_views.py +240 -0
- endoreg_db/views/patient/__init__.py +5 -0
- endoreg_db/views/patient/patient.py +210 -0
- endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +164 -0
- endoreg_db/views/patient_examination/__init__.py +11 -0
- endoreg_db/views/patient_examination/patient_examination.py +140 -0
- endoreg_db/views/patient_examination/patient_examination_create.py +63 -0
- endoreg_db/views/patient_examination/patient_examination_detail.py +66 -0
- endoreg_db/views/patient_examination/patient_examination_list.py +68 -0
- endoreg_db/views/patient_examination/video.py +194 -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 +64 -0
- endoreg_db/views/patient_finding/patient_finding_optimized.py +259 -0
- endoreg_db/views/patient_finding_classification/__init__.py +5 -0
- endoreg_db/views/patient_finding_classification/pfc_create.py +67 -0
- endoreg_db/views/patient_finding_location/__init__.py +5 -0
- endoreg_db/views/patient_finding_location/pfl_create.py +70 -0
- endoreg_db/views/patient_finding_morphology/__init__.py +5 -0
- endoreg_db/views/patient_finding_morphology/pfm_create.py +70 -0
- endoreg_db/views/pdf/__init__.py +11 -0
- endoreg_db/views/pdf/pdf_media.py +239 -0
- endoreg_db/views/pdf/pdf_stream_views.py +127 -0
- endoreg_db/views/pdf/reimport.py +161 -0
- endoreg_db/views/report/__init__.py +9 -0
- endoreg_db/views/report/report_list.py +112 -0
- endoreg_db/views/report/report_with_secure_url.py +28 -0
- endoreg_db/views/report/start_examination.py +7 -0
- endoreg_db/views/requirement/__init__.py +10 -0
- endoreg_db/views/requirement/evaluate.py +279 -0
- endoreg_db/views/requirement/lookup.py +483 -0
- endoreg_db/views/requirement/lookup_store.py +252 -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 +229 -0
- endoreg_db/views/video/__init__.py +61 -0
- endoreg_db/views/video/correction.py +530 -0
- endoreg_db/views/video/reimport.py +195 -0
- endoreg_db/views/video/segmentation.py +274 -0
- endoreg_db/views/video/task_status.py +49 -0
- endoreg_db/views/video/timeline.py +46 -0
- endoreg_db/views/video/video_analyze.py +52 -0
- endoreg_db/views/video/video_apply_mask.py +48 -0
- endoreg_db/views/video/video_correction.py +21 -0
- endoreg_db/views/video/video_download_processed.py +58 -0
- endoreg_db/views/video/video_examination_viewset.py +329 -0
- endoreg_db/views/video/video_media.py +158 -0
- endoreg_db/views/video/video_meta.py +29 -0
- endoreg_db/views/video/video_processing_history.py +24 -0
- endoreg_db/views/video/video_remove_frames.py +48 -0
- endoreg_db/views/video/video_stream.py +306 -0
- endoreg_db/views.py +0 -0
- endoreg_db-0.8.5.1.dist-info/METADATA +383 -0
- endoreg_db-0.8.5.1.dist-info/RECORD +794 -0
- endoreg_db-0.8.5.1.dist-info/WHEEL +4 -0
- endoreg_db-0.8.5.1.dist-info/licenses/LICENSE +674 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
from django.http import FileResponse, Http404, StreamingHttpResponse
|
|
2
|
+
import mimetypes
|
|
3
|
+
import os
|
|
4
|
+
import logging
|
|
5
|
+
import re
|
|
6
|
+
from ...models import RawPdfFile
|
|
7
|
+
from ...serializers._old.raw_pdf_meta_validation import PDFFileForMetaSerializer, SensitiveMetaUpdateSerializer
|
|
8
|
+
from rest_framework.views import APIView
|
|
9
|
+
from rest_framework.response import Response
|
|
10
|
+
from rest_framework import status
|
|
11
|
+
from ...models import SensitiveMeta
|
|
12
|
+
from django.views.decorators.clickjacking import xframe_options_sameorigin
|
|
13
|
+
from django.utils.decorators import method_decorator
|
|
14
|
+
from django.db import transaction
|
|
15
|
+
from django.urls import reverse
|
|
16
|
+
from django.utils.encoding import iri_to_uri
|
|
17
|
+
from endoreg_db.utils.paths import PDF_DIR, STORAGE_DIR
|
|
18
|
+
from .pdf_stream_views import ClosingFileWrapper
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
_RANGE_RE = re.compile(r"bytes=(\d+)-(\d*)")
|
|
22
|
+
|
|
23
|
+
class PDFMediaView(APIView):
|
|
24
|
+
"""
|
|
25
|
+
Unified API for PDFs to support frontend flows:
|
|
26
|
+
- Without `id`: returns next PDF metadata (including anonymized_text) and stream URLs
|
|
27
|
+
- With `id`: streams the PDF (original by default; `?variant=anonymized` for anonymized)
|
|
28
|
+
- Integrates with Media Management expectations (clean deletion after validation is handled elsewhere)
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def get(self, request):
|
|
32
|
+
"""
|
|
33
|
+
Handles both:
|
|
34
|
+
- Fetching PDF metadata (if `id` is NOT provided)
|
|
35
|
+
- Streaming the actual PDF file (if `id` is provided)
|
|
36
|
+
"""
|
|
37
|
+
pdf_id = request.GET.get("id")
|
|
38
|
+
last_id = request.GET.get("last_id")
|
|
39
|
+
|
|
40
|
+
if pdf_id:
|
|
41
|
+
return self.serve_pdf_file(pdf_id)
|
|
42
|
+
else:
|
|
43
|
+
return self.fetch_pdf_metadata(last_id)
|
|
44
|
+
|
|
45
|
+
def fetch_pdf_metadata(self, last_id):
|
|
46
|
+
"""
|
|
47
|
+
Fetches the first or next available PDF metadata and provides stream URLs.
|
|
48
|
+
"""
|
|
49
|
+
pdf_entry = PDFFileForMetaSerializer.get_next_pdf(last_id)
|
|
50
|
+
if pdf_entry is None:
|
|
51
|
+
return Response({"error": "No more PDFs available."}, status=status.HTTP_404_NOT_FOUND)
|
|
52
|
+
|
|
53
|
+
serialized_pdf = PDFFileForMetaSerializer(pdf_entry, context={'request': self.request})
|
|
54
|
+
|
|
55
|
+
# Build stream URLs pointing to this unified endpoint
|
|
56
|
+
try:
|
|
57
|
+
media_url = reverse('pdf_media')
|
|
58
|
+
except Exception:
|
|
59
|
+
media_url = "/api/pdf/media/"
|
|
60
|
+
stream_url = f"{media_url}?id={pdf_entry.id}"
|
|
61
|
+
anon_stream_url = f"{media_url}?id={pdf_entry.id}&variant=anonymized"
|
|
62
|
+
|
|
63
|
+
data = dict(serialized_pdf.data)
|
|
64
|
+
data.update({
|
|
65
|
+
'stream_url': iri_to_uri(self.request.build_absolute_uri(stream_url)),
|
|
66
|
+
'anonymized_stream_url': iri_to_uri(self.request.build_absolute_uri(anon_stream_url)),
|
|
67
|
+
'pdf_id': pdf_entry.id,
|
|
68
|
+
'has_anonymized': bool(getattr(pdf_entry, 'anonymized_file', None) and getattr(pdf_entry.anonymized_file, 'name', None)),
|
|
69
|
+
})
|
|
70
|
+
return Response(data, status=status.HTTP_200_OK)
|
|
71
|
+
|
|
72
|
+
@method_decorator(xframe_options_sameorigin)
|
|
73
|
+
def serve_pdf_file(self, pdf_id):
|
|
74
|
+
"""
|
|
75
|
+
Streams the actual PDF file (original or anonymized) with Range support.
|
|
76
|
+
Query param `variant=anonymized` selects anonymized file; default is original.
|
|
77
|
+
"""
|
|
78
|
+
variant = (self.request.GET.get('variant') or 'original').lower()
|
|
79
|
+
range_header = self.request.headers.get("Range")
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
pdf_entry = RawPdfFile.objects.get(id=pdf_id)
|
|
83
|
+
except RawPdfFile.DoesNotExist:
|
|
84
|
+
return Response({"error": "Invalid PDF ID."}, status=status.HTTP_400_BAD_REQUEST)
|
|
85
|
+
|
|
86
|
+
# Choose file according to variant
|
|
87
|
+
file_field = None
|
|
88
|
+
if variant == 'anonymized' and getattr(pdf_entry, 'anonymized_file', None):
|
|
89
|
+
file_field = pdf_entry.anonymized_file
|
|
90
|
+
else:
|
|
91
|
+
file_field = pdf_entry.file
|
|
92
|
+
|
|
93
|
+
if not file_field:
|
|
94
|
+
return Response({"error": "PDF file not found."}, status=status.HTTP_404_NOT_FOUND)
|
|
95
|
+
|
|
96
|
+
# Resolve path and attempt self-heal for originals
|
|
97
|
+
try:
|
|
98
|
+
file_path = file_field.path
|
|
99
|
+
except Exception:
|
|
100
|
+
file_path = None
|
|
101
|
+
|
|
102
|
+
if not file_path or not os.path.exists(file_path):
|
|
103
|
+
if variant != 'anonymized':
|
|
104
|
+
# Try to self-heal original reference to sensitive storage
|
|
105
|
+
sensitive_path = os.path.join(str(PDF_DIR), "sensitive", f"{pdf_entry.pdf_hash}.pdf")
|
|
106
|
+
if os.path.exists(sensitive_path):
|
|
107
|
+
try:
|
|
108
|
+
relative_name = os.path.relpath(sensitive_path, str(STORAGE_DIR))
|
|
109
|
+
if getattr(pdf_entry.file, 'name', None) != relative_name:
|
|
110
|
+
pdf_entry.file.name = relative_name
|
|
111
|
+
pdf_entry.save(update_fields=['file'])
|
|
112
|
+
logger.info("Self-healed PDF file reference for ID %s -> %s", pdf_entry.id, pdf_entry.file.path)
|
|
113
|
+
file_path = sensitive_path
|
|
114
|
+
except Exception as e:
|
|
115
|
+
logger.error("Failed to self-heal file path for PDF %s: %s", pdf_entry.id, e)
|
|
116
|
+
file_path = sensitive_path
|
|
117
|
+
# If still missing (or anonymized missing), fail
|
|
118
|
+
if not file_path or not os.path.exists(file_path):
|
|
119
|
+
raise Http404("PDF file not found on server.")
|
|
120
|
+
|
|
121
|
+
# Prepare headers
|
|
122
|
+
safe_filename = os.path.basename(getattr(file_field, 'name', None) or f"document_{pdf_id}.pdf")
|
|
123
|
+
if not safe_filename.endswith('.pdf'):
|
|
124
|
+
safe_filename += '.pdf'
|
|
125
|
+
|
|
126
|
+
file_size = os.path.getsize(file_path)
|
|
127
|
+
|
|
128
|
+
# Range support
|
|
129
|
+
if range_header:
|
|
130
|
+
match = _RANGE_RE.match(range_header)
|
|
131
|
+
if match:
|
|
132
|
+
start = int(match.group(1))
|
|
133
|
+
end = int(match.group(2) or file_size - 1)
|
|
134
|
+
|
|
135
|
+
if start < 0 or start >= file_size:
|
|
136
|
+
raise Http404("Invalid range")
|
|
137
|
+
if end >= file_size:
|
|
138
|
+
end = file_size - 1
|
|
139
|
+
|
|
140
|
+
chunk_size = end - start + 1
|
|
141
|
+
try:
|
|
142
|
+
fh = open(file_path, 'rb')
|
|
143
|
+
fh.seek(start)
|
|
144
|
+
resp = StreamingHttpResponse(
|
|
145
|
+
ClosingFileWrapper(fh, blksize=8192),
|
|
146
|
+
status=206,
|
|
147
|
+
content_type="application/pdf",
|
|
148
|
+
)
|
|
149
|
+
resp["Content-Length"] = str(chunk_size)
|
|
150
|
+
resp["Content-Range"] = f"bytes {start}-{end}/{file_size}"
|
|
151
|
+
resp["Accept-Ranges"] = "bytes"
|
|
152
|
+
resp["Content-Disposition"] = f'inline; filename="{safe_filename}"'
|
|
153
|
+
return resp
|
|
154
|
+
except (OSError, IOError) as e:
|
|
155
|
+
logger.error(f"Error opening PDF file for range request: {e}")
|
|
156
|
+
raise Http404("Error accessing PDF file")
|
|
157
|
+
|
|
158
|
+
# Fallback: serve full file
|
|
159
|
+
mime_type, _ = mimetypes.guess_type(file_path)
|
|
160
|
+
try:
|
|
161
|
+
fh = open(file_path, 'rb')
|
|
162
|
+
response = FileResponse(fh, content_type=mime_type or "application/pdf")
|
|
163
|
+
response["Content-Length"] = str(file_size)
|
|
164
|
+
response["Accept-Ranges"] = "bytes"
|
|
165
|
+
response["Content-Disposition"] = f'inline; filename="{safe_filename}"'
|
|
166
|
+
return response
|
|
167
|
+
except (OSError, IOError) as e:
|
|
168
|
+
logger.error(f"Error opening PDF file: {e}")
|
|
169
|
+
raise Http404("Error accessing PDF file")
|
|
170
|
+
|
|
171
|
+
class UpdateSensitiveMetaView(APIView):
|
|
172
|
+
"""
|
|
173
|
+
API endpoint to update patient details in the SensitiveMeta table.
|
|
174
|
+
Handles partial updates (only edited fields) and raw file deletion after validation acceptance.
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
@transaction.atomic
|
|
178
|
+
def patch(self, request, *args, **kwargs):
|
|
179
|
+
"""
|
|
180
|
+
Updates the provided fields for a specific patient record.
|
|
181
|
+
Only updates fields that are sent in the request.
|
|
182
|
+
Automatically deletes raw PDF files when validation is accepted.
|
|
183
|
+
"""
|
|
184
|
+
sensitive_meta_id = request.data.get("sensitive_meta_id")
|
|
185
|
+
|
|
186
|
+
if not sensitive_meta_id:
|
|
187
|
+
return Response({"error": "sensitive_meta_id is required."}, status=status.HTTP_400_BAD_REQUEST)
|
|
188
|
+
|
|
189
|
+
try:
|
|
190
|
+
sensitive_meta = SensitiveMeta.objects.get(id=sensitive_meta_id)
|
|
191
|
+
except SensitiveMeta.DoesNotExist:
|
|
192
|
+
return Response({"error": "Patient record not found."}, status=status.HTTP_404_NOT_FOUND)
|
|
193
|
+
|
|
194
|
+
is_accepting_validation = request.data.get("is_verified", False)
|
|
195
|
+
delete_raw_files = request.data.get("delete_raw_files", False)
|
|
196
|
+
if is_accepting_validation:
|
|
197
|
+
delete_raw_files = True
|
|
198
|
+
logger.info(f"Validation accepted for PDF SensitiveMeta {sensitive_meta_id}, marking raw files for deletion")
|
|
199
|
+
|
|
200
|
+
serializer = SensitiveMetaUpdateSerializer(sensitive_meta, data=request.data, partial=True)
|
|
201
|
+
|
|
202
|
+
if serializer.is_valid():
|
|
203
|
+
updated_sm = serializer.save()
|
|
204
|
+
if delete_raw_files and updated_sm.is_verified:
|
|
205
|
+
try:
|
|
206
|
+
pdf_file = RawPdfFile.objects.filter(sensitive_meta=updated_sm).first()
|
|
207
|
+
if pdf_file:
|
|
208
|
+
self._schedule_raw_file_deletion(pdf_file)
|
|
209
|
+
logger.info(f"Scheduled raw file deletion for PDF {pdf_file.id}")
|
|
210
|
+
else:
|
|
211
|
+
logger.warning(f"No PDF file found for SensitiveMeta {sensitive_meta_id}")
|
|
212
|
+
except Exception as e:
|
|
213
|
+
logger.error(f"Error scheduling raw file deletion for PDF SensitiveMeta {sensitive_meta_id}: {e}")
|
|
214
|
+
return Response({"message": "Patient information updated successfully.", "updated_data": serializer.data}, status=status.HTTP_200_OK)
|
|
215
|
+
|
|
216
|
+
return Response({"error": "Invalid data.", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
|
|
217
|
+
|
|
218
|
+
def _schedule_raw_file_deletion(self, pdf_file):
|
|
219
|
+
"""
|
|
220
|
+
Schedule deletion of raw PDF file after validation acceptance.
|
|
221
|
+
Deletes the original (sensitive) file but keeps anonymized_file for frontend.
|
|
222
|
+
"""
|
|
223
|
+
try:
|
|
224
|
+
def cleanup_raw_files():
|
|
225
|
+
try:
|
|
226
|
+
if pdf_file.file and getattr(pdf_file.file, 'path', None) and os.path.exists(pdf_file.file.path):
|
|
227
|
+
logger.info(f"Deleting original (sensitive) PDF file: {pdf_file.file.path}")
|
|
228
|
+
os.remove(pdf_file.file.path)
|
|
229
|
+
pdf_file.file = None
|
|
230
|
+
pdf_file.save(update_fields=['file'])
|
|
231
|
+
logger.info(f"Successfully deleted original file for PDF {pdf_file.id}")
|
|
232
|
+
else:
|
|
233
|
+
logger.info(f"Original file already deleted or not found for PDF {pdf_file.id}")
|
|
234
|
+
except Exception as e:
|
|
235
|
+
logger.error(f"Error during raw file cleanup for PDF {pdf_file.id}: {e}")
|
|
236
|
+
transaction.on_commit(cleanup_raw_files)
|
|
237
|
+
except Exception as e:
|
|
238
|
+
logger.error(f"Error scheduling raw file deletion for PDF {pdf_file.id}: {e}")
|
|
239
|
+
raise
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import logging
|
|
3
|
+
from django.http import FileResponse, StreamingHttpResponse, Http404
|
|
4
|
+
from rest_framework.views import APIView
|
|
5
|
+
from ...utils.permissions import EnvironmentAwarePermission
|
|
6
|
+
from endoreg_db.models import RawPdfFile
|
|
7
|
+
import os
|
|
8
|
+
from django.views.decorators.clickjacking import xframe_options_sameorigin
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
_RANGE_RE = re.compile(r"bytes=(\d+)-(\d*)")
|
|
12
|
+
|
|
13
|
+
class ClosingFileWrapper:
|
|
14
|
+
"""Custom file wrapper that ensures file is closed after streaming"""
|
|
15
|
+
def __init__(self, file_handle, blksize=8192):
|
|
16
|
+
self.file_handle = file_handle
|
|
17
|
+
self.blksize = blksize
|
|
18
|
+
|
|
19
|
+
def __iter__(self):
|
|
20
|
+
return self
|
|
21
|
+
|
|
22
|
+
def __next__(self):
|
|
23
|
+
data = self.file_handle.read(self.blksize)
|
|
24
|
+
if not data:
|
|
25
|
+
self.file_handle.close()
|
|
26
|
+
raise StopIteration
|
|
27
|
+
return data
|
|
28
|
+
|
|
29
|
+
def close(self):
|
|
30
|
+
if hasattr(self.file_handle, 'close'):
|
|
31
|
+
self.file_handle.close()
|
|
32
|
+
|
|
33
|
+
class PDFStreamView(APIView):
|
|
34
|
+
"""
|
|
35
|
+
Streams a PDF file with correct HTTP range support and proper file handle management.
|
|
36
|
+
"""
|
|
37
|
+
permission_classes = [EnvironmentAwarePermission]
|
|
38
|
+
|
|
39
|
+
@xframe_options_sameorigin
|
|
40
|
+
def get(self, request, pdf_id: int, *args, **kwargs):
|
|
41
|
+
try:
|
|
42
|
+
pdf_obj = RawPdfFile.objects.filter(pk=pdf_id).first()
|
|
43
|
+
if not pdf_obj or not pdf_obj.file:
|
|
44
|
+
logger.warning(f"PDF not found: ID {pdf_id}")
|
|
45
|
+
raise Http404("PDF not found")
|
|
46
|
+
|
|
47
|
+
# Check if file exists on filesystem
|
|
48
|
+
try:
|
|
49
|
+
file_path = pdf_obj.file.path
|
|
50
|
+
if not os.path.exists(file_path):
|
|
51
|
+
logger.error(f"PDF file does not exist on filesystem: {file_path}")
|
|
52
|
+
raise Http404("PDF file not found on filesystem")
|
|
53
|
+
|
|
54
|
+
file_size = os.path.getsize(file_path)
|
|
55
|
+
except (OSError, IOError, AttributeError) as e:
|
|
56
|
+
logger.error(f"Error accessing PDF file {pdf_id}: {e}")
|
|
57
|
+
raise Http404("PDF file not accessible")
|
|
58
|
+
|
|
59
|
+
# Generate safe filename
|
|
60
|
+
safe_filename = os.path.basename(pdf_obj.file.name) if pdf_obj.file.name else f"document_{pdf_id}.pdf"
|
|
61
|
+
if not safe_filename.endswith('.pdf'):
|
|
62
|
+
safe_filename += '.pdf'
|
|
63
|
+
|
|
64
|
+
# Handle Range requests
|
|
65
|
+
range_header = request.headers.get("Range")
|
|
66
|
+
if range_header:
|
|
67
|
+
logger.debug(f"Range request for PDF {pdf_id}: {range_header}")
|
|
68
|
+
match = _RANGE_RE.match(range_header)
|
|
69
|
+
if match:
|
|
70
|
+
start = int(match.group(1))
|
|
71
|
+
end = int(match.group(2) or file_size - 1)
|
|
72
|
+
|
|
73
|
+
# Validate range
|
|
74
|
+
if start >= file_size or start < 0:
|
|
75
|
+
logger.warning(f"Invalid range start {start} for file size {file_size}")
|
|
76
|
+
raise Http404("Invalid range")
|
|
77
|
+
|
|
78
|
+
if end >= file_size:
|
|
79
|
+
end = file_size - 1
|
|
80
|
+
|
|
81
|
+
chunk_size = end - start + 1
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
file_handle = open(file_path, "rb")
|
|
85
|
+
file_handle.seek(start)
|
|
86
|
+
|
|
87
|
+
logger.debug(f"Serving PDF {pdf_id} range {start}-{end}/{file_size}")
|
|
88
|
+
|
|
89
|
+
response = StreamingHttpResponse(
|
|
90
|
+
ClosingFileWrapper(file_handle, blksize=8192),
|
|
91
|
+
status=206,
|
|
92
|
+
content_type="application/pdf",
|
|
93
|
+
)
|
|
94
|
+
response["Content-Length"] = str(chunk_size)
|
|
95
|
+
response["Content-Range"] = f"bytes {start}-{end}/{file_size}"
|
|
96
|
+
response["Accept-Ranges"] = "bytes"
|
|
97
|
+
response["Content-Disposition"] = f'inline; filename="{safe_filename}"'
|
|
98
|
+
|
|
99
|
+
return response
|
|
100
|
+
except (OSError, IOError) as e:
|
|
101
|
+
logger.error(f"Error opening PDF file for range request: {e}")
|
|
102
|
+
raise Http404("Error accessing PDF file")
|
|
103
|
+
else:
|
|
104
|
+
logger.warning(f"Invalid Range header format: {range_header}")
|
|
105
|
+
|
|
106
|
+
# Serve entire file using FileResponse (automatically handles file closing)
|
|
107
|
+
logger.debug(f"Serving full PDF {pdf_id} ({file_size} bytes)")
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
file_handle = open(file_path, "rb")
|
|
111
|
+
response = FileResponse(
|
|
112
|
+
file_handle,
|
|
113
|
+
content_type="application/pdf"
|
|
114
|
+
)
|
|
115
|
+
response["Content-Length"] = str(file_size)
|
|
116
|
+
response["Accept-Ranges"] = "bytes"
|
|
117
|
+
response["Content-Disposition"] = f'inline; filename="{safe_filename}"'
|
|
118
|
+
|
|
119
|
+
# FileResponse will take ownership of file_handle and close it after response
|
|
120
|
+
return response
|
|
121
|
+
except (OSError, IOError) as e:
|
|
122
|
+
logger.error(f"Error opening PDF file: {e}")
|
|
123
|
+
raise Http404("Error accessing PDF file")
|
|
124
|
+
|
|
125
|
+
except Exception as e:
|
|
126
|
+
logger.error(f"Unexpected error streaming PDF {pdf_id}: {e}", exc_info=True)
|
|
127
|
+
raise Http404("Error streaming PDF")
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from rest_framework.views import APIView
|
|
2
|
+
from rest_framework.response import Response
|
|
3
|
+
from rest_framework import status
|
|
4
|
+
import logging
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from django.db import transaction
|
|
7
|
+
from ...models import RawPdfFile, SensitiveMeta
|
|
8
|
+
from ...services.pdf_import import PdfImportService
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
class PdfReimportView(APIView):
|
|
12
|
+
"""
|
|
13
|
+
API endpoint to re-import a pdf file and regenerate metadata.
|
|
14
|
+
This is useful when OCR failed or metadata is incomplete.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, **kwargs):
|
|
18
|
+
super().__init__(**kwargs)
|
|
19
|
+
self.pdf_service = PdfImportService()
|
|
20
|
+
|
|
21
|
+
def post(self, request, pk):
|
|
22
|
+
"""
|
|
23
|
+
Re-import a pdf file to regenerate SensitiveMeta and other metadata.
|
|
24
|
+
Instead of creating a new pdf, this updates the existing one.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
request: HTTP request object
|
|
28
|
+
pk: PDF primary key (ID)
|
|
29
|
+
"""
|
|
30
|
+
pdf_id = pk # Align with media framework naming convention
|
|
31
|
+
|
|
32
|
+
# Validate pdf_id parameter
|
|
33
|
+
if not pdf_id or not isinstance(pdf_id, int):
|
|
34
|
+
return Response(
|
|
35
|
+
{"error": "Invalid PDF ID provided."},
|
|
36
|
+
status=status.HTTP_400_BAD_REQUEST
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
pdf = RawPdfFile.objects.get(id=pdf_id)
|
|
41
|
+
logger.info(f"Found PDF {pdf.uuid} (ID: {pdf_id}) for re-import")
|
|
42
|
+
except RawPdfFile.DoesNotExist:
|
|
43
|
+
logger.warning(f"PDF with ID {pdf_id} not found")
|
|
44
|
+
return Response(
|
|
45
|
+
{"error": f"PDF with ID {pdf_id} not found."},
|
|
46
|
+
status=status.HTTP_404_NOT_FOUND
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# Check if the raw file actually exists on disk
|
|
52
|
+
raw_file_path = Path(pdf.file.path)
|
|
53
|
+
if not raw_file_path.exists():
|
|
54
|
+
logger.error(f"Raw file not found on disk: {raw_file_path}")
|
|
55
|
+
return Response(
|
|
56
|
+
{"error": f"PDF file not found on server: {raw_file_path.name}"},
|
|
57
|
+
status=status.HTTP_400_BAD_REQUEST
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Check if PDF has required relationships
|
|
61
|
+
if not pdf.center:
|
|
62
|
+
logger.warning(f"PDF {pdf.uuid} has no associated center")
|
|
63
|
+
return Response(
|
|
64
|
+
{"error": "Video has no associated center."},
|
|
65
|
+
status=status.HTTP_400_BAD_REQUEST
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
logger.info(f"Starting in-place re-import for pdf {pdf.uuid} (ID: {pdf_id})")
|
|
70
|
+
|
|
71
|
+
with transaction.atomic():
|
|
72
|
+
# Clear existing metadata to force regeneration
|
|
73
|
+
old_meta_id = None
|
|
74
|
+
if pdf.sensitive_meta:
|
|
75
|
+
old_meta_id = pdf.sensitive_meta.id
|
|
76
|
+
logger.info(f"Clearing existing SensitiveMeta {old_meta_id} for pdf {pdf.uuid}")
|
|
77
|
+
pdf.sensitive_meta = None
|
|
78
|
+
pdf.save(update_fields=['sensitive_meta'])
|
|
79
|
+
|
|
80
|
+
# Delete the old SensitiveMeta record
|
|
81
|
+
try:
|
|
82
|
+
SensitiveMeta.objects.filter(id=old_meta_id).delete()
|
|
83
|
+
logger.info(f"Deleted old SensitiveMeta {old_meta_id}")
|
|
84
|
+
except Exception as e:
|
|
85
|
+
logger.warning(f"Could not delete old SensitiveMeta {old_meta_id}: {e}")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# Ensure minimum patient data is available
|
|
92
|
+
logger.info(f"Ensuring minimum patient data for {pdf.uuid}")
|
|
93
|
+
self.pdf_service._ensure_default_patient_data(pdf)
|
|
94
|
+
|
|
95
|
+
# Refresh from database to get updated data
|
|
96
|
+
pdf.refresh_from_db()
|
|
97
|
+
|
|
98
|
+
# Use VideoImportService for anonymization
|
|
99
|
+
try:
|
|
100
|
+
|
|
101
|
+
logger.info(f"Starting anonymization using VideoImportService for {pdf.uuid}")
|
|
102
|
+
self.pdf_service.import_and_anonymize(
|
|
103
|
+
file_path=raw_file_path,
|
|
104
|
+
center_name=pdf.center.name,
|
|
105
|
+
processor_name=pdf.processor.name if pdf.processor else "Unknown",
|
|
106
|
+
save_video=True,
|
|
107
|
+
delete_source=False
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
logger.info(f"VideoImportService anonymization completed for {pdf.uuid}")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
return Response({
|
|
114
|
+
"message": "Video re-import with VideoImportService completed successfully.",
|
|
115
|
+
"pdf_id": pdf_id,
|
|
116
|
+
"uuid": str(pdf.uuid),
|
|
117
|
+
"frame_cleaning_applied": True,
|
|
118
|
+
"sensitive_meta_created": pdf.sensitive_meta is not None,
|
|
119
|
+
"sensitive_meta_id": pdf.sensitive_meta.id if pdf.sensitive_meta else None,
|
|
120
|
+
"updated_in_place": True,
|
|
121
|
+
"status": "done"
|
|
122
|
+
}, status=status.HTTP_200_OK)
|
|
123
|
+
|
|
124
|
+
except Exception as e:
|
|
125
|
+
logger.exception(f"VideoImportService anonymization failed for pdf {pdf.uuid}: {e}")
|
|
126
|
+
logger.warning("Continuing without anonymization due to error")
|
|
127
|
+
|
|
128
|
+
# Refresh from database to get final state
|
|
129
|
+
pdf.refresh_from_db()
|
|
130
|
+
|
|
131
|
+
return Response({
|
|
132
|
+
"message": "PDF re-import completed successfully.",
|
|
133
|
+
"pdf_id": pdf_id,
|
|
134
|
+
"uuid": str(pdf.uuid),
|
|
135
|
+
"sensitive_meta_created": pdf.sensitive_meta is not None,
|
|
136
|
+
"sensitive_meta_id": pdf.sensitive_meta.id if pdf.sensitive_meta else None,
|
|
137
|
+
"updated_in_place": True,
|
|
138
|
+
"status": "done"
|
|
139
|
+
}, status=status.HTTP_200_OK)
|
|
140
|
+
|
|
141
|
+
except Exception as e:
|
|
142
|
+
logger.error(f"Failed to re-import pdf {pdf.uuid}: {str(e)}", exc_info=True)
|
|
143
|
+
|
|
144
|
+
# Handle specific error types
|
|
145
|
+
error_msg = str(e)
|
|
146
|
+
if any(phrase in error_msg.lower() for phrase in ["insufficient storage", "no space left", "disk full"]):
|
|
147
|
+
# Storage error - return specific error message
|
|
148
|
+
return Response({
|
|
149
|
+
"error": f"Storage error during re-import: {error_msg}",
|
|
150
|
+
"error_type": "storage_error",
|
|
151
|
+
"pdf_id": pdf_id,
|
|
152
|
+
"uuid": str(pdf.uuid)
|
|
153
|
+
}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
|
|
154
|
+
else:
|
|
155
|
+
# Other errors
|
|
156
|
+
return Response({
|
|
157
|
+
"error": f"Re-import failed: {error_msg}",
|
|
158
|
+
"error_type": "processing_error",
|
|
159
|
+
"pdf_id": pdf_id,
|
|
160
|
+
"uuid": str(pdf.uuid)
|
|
161
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
from endoreg_db.models import RawPdfFile
|
|
2
|
+
from endoreg_db.serializers.report.report_list import ReportListSerializer
|
|
3
|
+
|
|
4
|
+
from django.core.paginator import Paginator
|
|
5
|
+
from django.db.models import Q
|
|
6
|
+
from rest_framework import status
|
|
7
|
+
from rest_framework.response import Response
|
|
8
|
+
from rest_framework.views import APIView
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
class ReportListView(APIView):
|
|
14
|
+
"""
|
|
15
|
+
API-Endpunkt für paginierte Report-Listen mit optionaler Filterung
|
|
16
|
+
GET /api/reports/
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def get(self, request):
|
|
20
|
+
try:
|
|
21
|
+
# Query-Parameter abrufen
|
|
22
|
+
page = int(request.GET.get('page', 1))
|
|
23
|
+
page_size = min(int(request.GET.get('page_size', 20)), 100) # Max 100 pro Seite
|
|
24
|
+
|
|
25
|
+
# Filter-Parameter
|
|
26
|
+
file_type_filter = request.GET.get('file_type')
|
|
27
|
+
patient_name_filter = request.GET.get('patient_name')
|
|
28
|
+
casenumber_filter = request.GET.get('casenumber')
|
|
29
|
+
date_from = request.GET.get('date_from')
|
|
30
|
+
date_to = request.GET.get('date_to')
|
|
31
|
+
|
|
32
|
+
# Base QuerySet mit related data
|
|
33
|
+
queryset = RawPdfFile.objects.select_related('sensitive_meta').all()
|
|
34
|
+
|
|
35
|
+
# Filter anwenden
|
|
36
|
+
if patient_name_filter:
|
|
37
|
+
queryset = queryset.filter(
|
|
38
|
+
Q(sensitive_meta__patient_first_name__icontains=patient_name_filter) |
|
|
39
|
+
Q(sensitive_meta__patient_last_name__icontains=patient_name_filter)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
if casenumber_filter:
|
|
43
|
+
queryset = queryset.filter(
|
|
44
|
+
sensitive_meta__case_number__icontains=casenumber_filter
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
if file_type_filter:
|
|
48
|
+
# Filter basierend auf Dateiendung
|
|
49
|
+
queryset = queryset.filter(file__endswith=f'.{file_type_filter}')
|
|
50
|
+
|
|
51
|
+
if date_from:
|
|
52
|
+
queryset = queryset.filter(created_at__gte=date_from)
|
|
53
|
+
|
|
54
|
+
if date_to:
|
|
55
|
+
queryset = queryset.filter(created_at__lte=date_to)
|
|
56
|
+
|
|
57
|
+
# Sortierung (neueste zuerst)
|
|
58
|
+
queryset = queryset.order_by('-created_at')
|
|
59
|
+
|
|
60
|
+
# Paginierung
|
|
61
|
+
paginator = Paginator(queryset, page_size)
|
|
62
|
+
|
|
63
|
+
if page > paginator.num_pages:
|
|
64
|
+
return Response({
|
|
65
|
+
'count': paginator.count,
|
|
66
|
+
'next': None,
|
|
67
|
+
'previous': None,
|
|
68
|
+
'results': []
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
page_obj = paginator.get_page(page)
|
|
72
|
+
|
|
73
|
+
# Serialisierung
|
|
74
|
+
serializer = ReportListSerializer(
|
|
75
|
+
page_obj.object_list,
|
|
76
|
+
many=True,
|
|
77
|
+
context={'request': request}
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# URLs für Paginierung
|
|
81
|
+
next_url = None
|
|
82
|
+
previous_url = None
|
|
83
|
+
|
|
84
|
+
if page_obj.has_next():
|
|
85
|
+
next_url = request.build_absolute_uri(
|
|
86
|
+
f"?page={page_obj.next_page_number()}&page_size={page_size}"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
if page_obj.has_previous():
|
|
90
|
+
previous_url = request.build_absolute_uri(
|
|
91
|
+
f"?page={page_obj.previous_page_number()}&page_size={page_size}"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
return Response({
|
|
95
|
+
'count': paginator.count,
|
|
96
|
+
'next': next_url,
|
|
97
|
+
'previous': previous_url,
|
|
98
|
+
'results': serializer.data
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
except ValueError as e:
|
|
102
|
+
logger.error("Ungültige Parameter in ReportListView: %s", str(e))
|
|
103
|
+
return Response(
|
|
104
|
+
{"error": "Ungültige Parameter"},
|
|
105
|
+
status=status.HTTP_400_BAD_REQUEST
|
|
106
|
+
)
|
|
107
|
+
except (AttributeError, TypeError, OSError) as e:
|
|
108
|
+
logger.error("Fehler in ReportListView: %s", str(e))
|
|
109
|
+
return Response(
|
|
110
|
+
{"error": "Fehler beim Laden der Reports"},
|
|
111
|
+
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
112
|
+
)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from endoreg_db.models import RawPdfFile
|
|
2
|
+
from endoreg_db.serializers.report.report import ReportDataSerializer
|
|
3
|
+
|
|
4
|
+
from django.shortcuts import get_object_or_404
|
|
5
|
+
from rest_framework import status
|
|
6
|
+
from rest_framework.response import Response
|
|
7
|
+
from rest_framework.views import APIView
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
class ReportWithSecureUrlView(APIView):
|
|
13
|
+
"""
|
|
14
|
+
API-Endpunkt für Reports mit sicherer URL-Generierung
|
|
15
|
+
GET /api/reports/{report_id}/with-secure-url/
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def get(self, request, report_id):
|
|
19
|
+
try:
|
|
20
|
+
report = get_object_or_404(RawPdfFile, id=report_id)
|
|
21
|
+
serializer = ReportDataSerializer(report, context={'request': request})
|
|
22
|
+
return Response(serializer.data)
|
|
23
|
+
except (ValueError, TypeError) as e:
|
|
24
|
+
logger.error("Fehler beim Laden des Reports %s: %s", report_id, str(e))
|
|
25
|
+
return Response(
|
|
26
|
+
{"error": "Report konnte nicht geladen werden"},
|
|
27
|
+
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
28
|
+
)
|