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,241 @@
|
|
|
1
|
+
import mimetypes
|
|
2
|
+
|
|
3
|
+
from django.http import Http404
|
|
4
|
+
from django.urls import reverse
|
|
5
|
+
from django.utils.decorators import method_decorator
|
|
6
|
+
from django.views.decorators.csrf import csrf_exempt
|
|
7
|
+
from rest_framework import status
|
|
8
|
+
from rest_framework.parsers import FormParser, MultiPartParser
|
|
9
|
+
from rest_framework.permissions import AllowAny
|
|
10
|
+
from rest_framework.response import Response
|
|
11
|
+
from rest_framework.views import APIView
|
|
12
|
+
|
|
13
|
+
# Try to import python-magic, but provide fallback if not available
|
|
14
|
+
try:
|
|
15
|
+
import magic
|
|
16
|
+
|
|
17
|
+
MAGIC_AVAILABLE = True
|
|
18
|
+
except ImportError:
|
|
19
|
+
MAGIC_AVAILABLE = False
|
|
20
|
+
|
|
21
|
+
from endoreg_db.models.upload_job import UploadJob
|
|
22
|
+
from endoreg_db.serializers.misc.upload_job import UploadJobStatusSerializer
|
|
23
|
+
|
|
24
|
+
# Try to import celery task, but provide fallback
|
|
25
|
+
try:
|
|
26
|
+
from endoreg_db.tasks.upload_tasks import process_upload_job
|
|
27
|
+
|
|
28
|
+
CELERY_AVAILABLE = True
|
|
29
|
+
except ImportError:
|
|
30
|
+
CELERY_AVAILABLE = False
|
|
31
|
+
|
|
32
|
+
# Define a dummy function for development
|
|
33
|
+
def process_upload_job(job_id):
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@method_decorator(csrf_exempt, name="dispatch")
|
|
38
|
+
class UploadFileView(APIView):
|
|
39
|
+
"""
|
|
40
|
+
Handle file uploads (POST /api/upload/).
|
|
41
|
+
|
|
42
|
+
Accepts multipart/form-data with a 'file' field containing report or video files.
|
|
43
|
+
Creates an UploadJob and starts asynchronous processing.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
201 Created: {"upload_id": "<uuid>", "status_url": "/api/upload/<uuid>/status/"}
|
|
47
|
+
400 Bad Request: File validation errors
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
parser_classes = [MultiPartParser, FormParser]
|
|
51
|
+
permission_classes = [AllowAny] # Adjust based on your auth requirements
|
|
52
|
+
|
|
53
|
+
# Maximum file size (1 GiB)
|
|
54
|
+
MAX_FILE_SIZE = 1024 * 1024 * 1024 # 1 GiB in bytes
|
|
55
|
+
|
|
56
|
+
# Allowed MIME types
|
|
57
|
+
ALLOWED_MIME_TYPES = {
|
|
58
|
+
"application/pdf",
|
|
59
|
+
"video/mp4",
|
|
60
|
+
"video/avi",
|
|
61
|
+
"video/quicktime",
|
|
62
|
+
"video/x-msvideo",
|
|
63
|
+
"video/x-ms-wmv",
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
def post(self, request, *args, **kwargs):
|
|
67
|
+
"""
|
|
68
|
+
Handle file upload and create processing job.
|
|
69
|
+
"""
|
|
70
|
+
# Validate file presence
|
|
71
|
+
if "file" not in request.FILES:
|
|
72
|
+
return Response(
|
|
73
|
+
{
|
|
74
|
+
"error": 'No file provided. Please include a file in the "file" field.'
|
|
75
|
+
},
|
|
76
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
uploaded_file = request.FILES["file"]
|
|
80
|
+
|
|
81
|
+
# Validate file is not empty
|
|
82
|
+
if not uploaded_file or uploaded_file.size == 0:
|
|
83
|
+
return Response(
|
|
84
|
+
{"error": "Uploaded file is empty. Please select a valid file."},
|
|
85
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Validate file size
|
|
89
|
+
if uploaded_file.size > self.MAX_FILE_SIZE:
|
|
90
|
+
return Response(
|
|
91
|
+
{
|
|
92
|
+
"error": f"File too large. Maximum size is {self.MAX_FILE_SIZE // (1024**3)} GB."
|
|
93
|
+
},
|
|
94
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Validate filename
|
|
98
|
+
if not uploaded_file.name or uploaded_file.name.strip() == "":
|
|
99
|
+
return Response(
|
|
100
|
+
{"error": "Invalid filename. Please ensure the file has a valid name."},
|
|
101
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Detect MIME type
|
|
105
|
+
try:
|
|
106
|
+
content_type = self._detect_mime_type(uploaded_file)
|
|
107
|
+
except Exception as e:
|
|
108
|
+
return Response(
|
|
109
|
+
{"error": f"Could not determine file type: {str(e)}"},
|
|
110
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Validate MIME type
|
|
114
|
+
if content_type not in self.ALLOWED_MIME_TYPES:
|
|
115
|
+
return Response(
|
|
116
|
+
{
|
|
117
|
+
"error": f"Unsupported file type: {content_type}. Allowed types: report, MP4, AVI, MOV, WMV."
|
|
118
|
+
},
|
|
119
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
# Create upload job
|
|
124
|
+
upload_job = UploadJob.objects.create(
|
|
125
|
+
file=uploaded_file, content_type=content_type
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Start asynchronous processing if Celery is available
|
|
129
|
+
if CELERY_AVAILABLE:
|
|
130
|
+
try:
|
|
131
|
+
process_upload_job.delay(str(upload_job.id))
|
|
132
|
+
except Exception as e:
|
|
133
|
+
# If Celery task fails to start, mark job as failed
|
|
134
|
+
upload_job.mark_failed(f"Failed to start processing: {str(e)}")
|
|
135
|
+
return Response(
|
|
136
|
+
{"error": f"Failed to start processing: {str(e)}"},
|
|
137
|
+
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
138
|
+
)
|
|
139
|
+
else:
|
|
140
|
+
# For development without Celery, mark as processing immediately
|
|
141
|
+
upload_job.mark_processing()
|
|
142
|
+
# In production, this would be handled by Celery
|
|
143
|
+
# For now, just leave it in processing state
|
|
144
|
+
|
|
145
|
+
# Prepare response
|
|
146
|
+
status_url = reverse("upload_status", kwargs={"id": upload_job.id})
|
|
147
|
+
response_data = {
|
|
148
|
+
"upload_id": str(upload_job.id), # Ensure UUID is converted to string
|
|
149
|
+
"status_url": status_url,
|
|
150
|
+
"message": "Upload job created successfully",
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
# Return the response data directly since serializer fields are read-only
|
|
154
|
+
return Response(response_data, status=status.HTTP_201_CREATED)
|
|
155
|
+
|
|
156
|
+
except Exception as e:
|
|
157
|
+
return Response(
|
|
158
|
+
{"error": f"Failed to create upload job: {str(e)}"},
|
|
159
|
+
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
def _detect_mime_type(self, uploaded_file) -> str:
|
|
163
|
+
"""
|
|
164
|
+
Detect MIME type using python-magic as primary method,
|
|
165
|
+
fallback to mimetypes module.
|
|
166
|
+
"""
|
|
167
|
+
try:
|
|
168
|
+
# Reset file pointer
|
|
169
|
+
uploaded_file.seek(0)
|
|
170
|
+
|
|
171
|
+
# Try python-magic first (more reliable) if available
|
|
172
|
+
if MAGIC_AVAILABLE:
|
|
173
|
+
try:
|
|
174
|
+
# Read first chunk for magic detection
|
|
175
|
+
chunk = uploaded_file.read(2048)
|
|
176
|
+
uploaded_file.seek(0) # Reset again
|
|
177
|
+
|
|
178
|
+
mime_type = magic.from_buffer(chunk, mime=True)
|
|
179
|
+
if mime_type and mime_type != "application/octet-stream":
|
|
180
|
+
return mime_type
|
|
181
|
+
except Exception:
|
|
182
|
+
pass # Fall back to mimetypes
|
|
183
|
+
|
|
184
|
+
# Fallback to mimetypes module
|
|
185
|
+
mime_type, _ = mimetypes.guess_type(uploaded_file.name)
|
|
186
|
+
if mime_type:
|
|
187
|
+
return mime_type
|
|
188
|
+
|
|
189
|
+
# Last resort - check file extension
|
|
190
|
+
if uploaded_file.name.lower().endswith(".pdf"):
|
|
191
|
+
return "application/pdf"
|
|
192
|
+
elif uploaded_file.name.lower().endswith((".mp4", ".m4v")):
|
|
193
|
+
return "video/mp4"
|
|
194
|
+
elif uploaded_file.name.lower().endswith(".avi"):
|
|
195
|
+
return "video/avi"
|
|
196
|
+
elif uploaded_file.name.lower().endswith((".mov", ".qt")):
|
|
197
|
+
return "video/quicktime"
|
|
198
|
+
elif uploaded_file.name.lower().endswith(".wmv"):
|
|
199
|
+
return "video/x-ms-wmv"
|
|
200
|
+
|
|
201
|
+
raise ValueError("Could not determine file type")
|
|
202
|
+
|
|
203
|
+
finally:
|
|
204
|
+
# Ensure file pointer is reset
|
|
205
|
+
uploaded_file.seek(0)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class UploadStatusView(APIView):
|
|
209
|
+
"""
|
|
210
|
+
Get upload job status (GET /api/upload/<uuid>/status/).
|
|
211
|
+
|
|
212
|
+
Returns current processing status and relevant metadata.
|
|
213
|
+
Should be polled every 2 seconds by the frontend.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
200 OK: Status information
|
|
217
|
+
404 Not Found: Upload job not found
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
permission_classes = [AllowAny] # Adjust based on your auth requirements
|
|
221
|
+
|
|
222
|
+
def get(self, request, id, *args, **kwargs):
|
|
223
|
+
"""
|
|
224
|
+
Return the current status of an upload job.
|
|
225
|
+
"""
|
|
226
|
+
try:
|
|
227
|
+
# Look up upload job by UUID
|
|
228
|
+
upload_job = UploadJob.objects.select_related("sensitive_meta").get(id=id)
|
|
229
|
+
|
|
230
|
+
# Serialize the response
|
|
231
|
+
serializer = UploadJobStatusSerializer(upload_job)
|
|
232
|
+
|
|
233
|
+
return Response(serializer.data, status=status.HTTP_200_OK)
|
|
234
|
+
|
|
235
|
+
except UploadJob.DoesNotExist:
|
|
236
|
+
raise Http404("Upload job not found")
|
|
237
|
+
except Exception as e:
|
|
238
|
+
return Response(
|
|
239
|
+
{"error": f"Failed to get upload status: {str(e)}"},
|
|
240
|
+
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
241
|
+
)
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
from django.shortcuts import render
|
|
2
|
+
from django.contrib.admin.views.decorators import staff_member_required
|
|
3
|
+
from django.db import transaction
|
|
4
|
+
|
|
5
|
+
from rest_framework import viewsets, status, serializers
|
|
6
|
+
from rest_framework.response import Response
|
|
7
|
+
from rest_framework.decorators import action
|
|
8
|
+
|
|
9
|
+
from endoreg_db.authz.permissions import PolicyPermission
|
|
10
|
+
from endoreg_db.models import Patient
|
|
11
|
+
from endoreg_db.serializers.patient import PatientSerializer
|
|
12
|
+
from endoreg_db.models.medical.patient.patient_examination import PatientExamination
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@staff_member_required # Ensures only staff members can access the page
|
|
16
|
+
def start_examination(request):
|
|
17
|
+
return render(request, "admin/start_examination.html") # Loads the simple HTML page
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# TODO Review this view
|
|
21
|
+
class PatientViewSet(viewsets.ModelViewSet):
|
|
22
|
+
"""API endpoint for managing patients."""
|
|
23
|
+
|
|
24
|
+
queryset = Patient.objects.all()
|
|
25
|
+
serializer_class = PatientSerializer
|
|
26
|
+
permission_classes = [PolicyPermission]
|
|
27
|
+
# permission_classes = [PolicyPermission]
|
|
28
|
+
|
|
29
|
+
def perform_create(self, serializer):
|
|
30
|
+
"""Erweiterte Validierung beim Erstellen eines Patienten"""
|
|
31
|
+
try:
|
|
32
|
+
# Zusätzliche Validierung falls nötig
|
|
33
|
+
patient = serializer.save()
|
|
34
|
+
return patient
|
|
35
|
+
except Exception as e:
|
|
36
|
+
raise serializers.ValidationError(
|
|
37
|
+
f"Fehler beim Erstellen des Patienten: {str(e)}"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def update(self, request, *args, **kwargs):
|
|
41
|
+
"""Erweiterte Logik für das Aktualisieren von Patienten"""
|
|
42
|
+
try:
|
|
43
|
+
return super().update(request, *args, **kwargs)
|
|
44
|
+
except Exception as e:
|
|
45
|
+
return Response(
|
|
46
|
+
{"error": f"Fehler beim Aktualisieren des Patienten: {str(e)}"},
|
|
47
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def destroy(self, request, *args, **kwargs):
|
|
51
|
+
"""
|
|
52
|
+
Delete a patient with proper error handling and cascade protection.
|
|
53
|
+
"""
|
|
54
|
+
patient = self.get_object()
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
with transaction.atomic():
|
|
58
|
+
# Check if patient has related examinations
|
|
59
|
+
examination_count = (
|
|
60
|
+
patient.patient_examinations.count()
|
|
61
|
+
if hasattr(patient, "patient_examinations")
|
|
62
|
+
else 0
|
|
63
|
+
)
|
|
64
|
+
finding_count = 0
|
|
65
|
+
|
|
66
|
+
if examination_count > 0:
|
|
67
|
+
finding_count = sum(
|
|
68
|
+
exam.patient_findings.count()
|
|
69
|
+
if hasattr(exam, "patient_findings")
|
|
70
|
+
else 0
|
|
71
|
+
for exam in patient.patient_examinations.all()
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
return Response(
|
|
75
|
+
{
|
|
76
|
+
"error": "Patient cannot be deleted",
|
|
77
|
+
"reason": f"Patient has {examination_count} examination(s) and {finding_count} finding(s).",
|
|
78
|
+
"detail": "Please remove all related examinations and findings before deleting the patient.",
|
|
79
|
+
},
|
|
80
|
+
status=status.HTTP_409_CONFLICT,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Check if this is a real person (additional protection)
|
|
84
|
+
if hasattr(patient, "is_real_person") and patient.is_real_person:
|
|
85
|
+
return Response(
|
|
86
|
+
{
|
|
87
|
+
"error": "Cannot delete real patient",
|
|
88
|
+
"reason": "This patient is marked as a real person.",
|
|
89
|
+
"detail": "Real patient data cannot be deleted for data protection reasons.",
|
|
90
|
+
},
|
|
91
|
+
status=status.HTTP_403_FORBIDDEN,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Perform the deletion
|
|
95
|
+
patient_name = f"{patient.first_name} {patient.last_name}"
|
|
96
|
+
patient.delete()
|
|
97
|
+
|
|
98
|
+
return Response(
|
|
99
|
+
{
|
|
100
|
+
"message": f'Patient "{patient_name}" has been successfully deleted.'
|
|
101
|
+
},
|
|
102
|
+
status=status.HTTP_200_OK,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
except Exception as e:
|
|
106
|
+
return Response(
|
|
107
|
+
{
|
|
108
|
+
"error": "Patient deletion failed",
|
|
109
|
+
"reason": "Patient has protected related objects.",
|
|
110
|
+
"detail": str(e),
|
|
111
|
+
},
|
|
112
|
+
status=status.HTTP_409_CONFLICT,
|
|
113
|
+
)
|
|
114
|
+
except Exception as e:
|
|
115
|
+
return Response(
|
|
116
|
+
{"error": f"Fehler beim Löschen des Patienten: {str(e)}"},
|
|
117
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
def check_pe_exist(self, request, pk=None):
|
|
121
|
+
"""Check if a patient examination exists.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
request (id): pk of the PatientExamination
|
|
125
|
+
pk (int, optional): _description_. Defaults to None.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
_type_: _description_
|
|
129
|
+
"""
|
|
130
|
+
try:
|
|
131
|
+
PatientExamination.objects.get(pk=pk)
|
|
132
|
+
return Response({"exists": True}, status=status.HTTP_200_OK)
|
|
133
|
+
except PatientExamination.DoesNotExist:
|
|
134
|
+
return Response({"exists": False}, status=status.HTTP_404_NOT_FOUND)
|
|
135
|
+
|
|
136
|
+
@action(detail=True, methods=["get"])
|
|
137
|
+
def check_deletion_safety(self, request, pk=None):
|
|
138
|
+
"""
|
|
139
|
+
Check if a patient can be safely deleted.
|
|
140
|
+
Returns information about related objects.
|
|
141
|
+
"""
|
|
142
|
+
patient = self.get_object()
|
|
143
|
+
|
|
144
|
+
examination_count = (
|
|
145
|
+
patient.patient_examinations.count()
|
|
146
|
+
if hasattr(patient, "patient_examinations")
|
|
147
|
+
else 0
|
|
148
|
+
)
|
|
149
|
+
examinations = (
|
|
150
|
+
patient.patient_examinations.all()
|
|
151
|
+
if hasattr(patient, "patient_examinations")
|
|
152
|
+
else []
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
finding_count = sum(
|
|
156
|
+
exam.patient_findings.count() if hasattr(exam, "patient_findings") else 0
|
|
157
|
+
for exam in examinations
|
|
158
|
+
)
|
|
159
|
+
video_count = sum(
|
|
160
|
+
1 for exam in examinations if hasattr(exam, "video") and exam.video
|
|
161
|
+
)
|
|
162
|
+
report_count = sum(
|
|
163
|
+
exam.raw_pdf_files.count() if hasattr(exam, "raw_pdf_files") else 0
|
|
164
|
+
for exam in examinations
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
is_real_person = hasattr(patient, "is_real_person") and patient.is_real_person
|
|
168
|
+
can_delete = examination_count == 0 and not is_real_person
|
|
169
|
+
|
|
170
|
+
warnings = []
|
|
171
|
+
if is_real_person:
|
|
172
|
+
warnings.append("This patient is marked as a real person")
|
|
173
|
+
if examination_count > 0:
|
|
174
|
+
warnings.append(f"Patient has {examination_count} examination(s)")
|
|
175
|
+
if finding_count > 0:
|
|
176
|
+
warnings.append(f"Patient has {finding_count} finding(s)")
|
|
177
|
+
|
|
178
|
+
return Response(
|
|
179
|
+
{
|
|
180
|
+
"can_delete": can_delete,
|
|
181
|
+
"is_real_person": is_real_person,
|
|
182
|
+
"related_objects": {
|
|
183
|
+
"examinations": examination_count,
|
|
184
|
+
"findings": finding_count,
|
|
185
|
+
"videos": video_count,
|
|
186
|
+
"reports": report_count,
|
|
187
|
+
},
|
|
188
|
+
"warnings": warnings,
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
@action(detail=False, methods=["get"])
|
|
193
|
+
def patient_count(self, request):
|
|
194
|
+
"""Gibt die Anzahl der Patienten zurück"""
|
|
195
|
+
count = Patient.objects.count()
|
|
196
|
+
return Response({"count": count})
|
|
197
|
+
|
|
198
|
+
@action(detail=True, methods=["post"], url_path="pseudonym")
|
|
199
|
+
def generate_pseudonym(self, request, pk=None):
|
|
200
|
+
"""
|
|
201
|
+
Generate a pseudonym hash for an existing patient.
|
|
202
|
+
|
|
203
|
+
This endpoint generates a deterministic hash based on the patient's
|
|
204
|
+
personal data (name, dob, center) using server-side logic without
|
|
205
|
+
exposing any secrets to the frontend.
|
|
206
|
+
"""
|
|
207
|
+
from endoreg_db.services.pseudonym_service import (
|
|
208
|
+
generate_patient_pseudonym,
|
|
209
|
+
validate_patient_for_pseudonym,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
patient = self.get_object()
|
|
213
|
+
|
|
214
|
+
try:
|
|
215
|
+
# Validate that patient has required fields
|
|
216
|
+
missing_fields = validate_patient_for_pseudonym(patient)
|
|
217
|
+
if missing_fields:
|
|
218
|
+
return Response(
|
|
219
|
+
{
|
|
220
|
+
"error": "Missing required fields for pseudonym generation",
|
|
221
|
+
"missing_fields": missing_fields,
|
|
222
|
+
"detail": f"Please provide: {', '.join(missing_fields)}",
|
|
223
|
+
},
|
|
224
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
# Generate the pseudonym
|
|
228
|
+
patient_hash, persisted = generate_patient_pseudonym(patient)
|
|
229
|
+
|
|
230
|
+
return Response(
|
|
231
|
+
{
|
|
232
|
+
"patient_id": patient.id,
|
|
233
|
+
"patient_hash": patient_hash,
|
|
234
|
+
"source": "server",
|
|
235
|
+
"persisted": persisted,
|
|
236
|
+
"message": "Pseudonym generated successfully",
|
|
237
|
+
},
|
|
238
|
+
status=status.HTTP_200_OK,
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
except ValueError as e:
|
|
242
|
+
return Response(
|
|
243
|
+
{"error": "Pseudonym generation failed", "detail": str(e)},
|
|
244
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
245
|
+
)
|
|
246
|
+
except Exception as e:
|
|
247
|
+
return Response(
|
|
248
|
+
{
|
|
249
|
+
"error": "Internal server error during pseudonym generation",
|
|
250
|
+
"detail": str(e),
|
|
251
|
+
},
|
|
252
|
+
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
253
|
+
)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from .patient_examination_create import ExaminationCreateView
|
|
2
|
+
from .patient_examination_detail import PatientExaminationDetailView
|
|
3
|
+
from .patient_examination_list import PatientExaminationListView
|
|
4
|
+
from .patient_examination import PatientExaminationViewSet
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"ExaminationCreateView",
|
|
8
|
+
"PatientExaminationDetailView",
|
|
9
|
+
"PatientExaminationListView",
|
|
10
|
+
"PatientExaminationViewSet",
|
|
11
|
+
]
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
from rest_framework import viewsets, status
|
|
2
|
+
from rest_framework.decorators import action
|
|
3
|
+
from rest_framework.response import Response
|
|
4
|
+
from endoreg_db.models import PatientExamination, Patient, Examination
|
|
5
|
+
from endoreg_db.serializers.patient.patient_dropdown import PatientDropdownSerializer
|
|
6
|
+
from endoreg_db.serializers.patient_examination import (
|
|
7
|
+
PatientExaminationSerializer,
|
|
8
|
+
)
|
|
9
|
+
from endoreg_db.serializers.examination import ExaminationDropdownSerializer
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PatientExaminationViewSet(viewsets.ModelViewSet):
|
|
13
|
+
"""
|
|
14
|
+
ViewSet für PatientExamination mit vollständiger CRUD-Unterstützung
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
queryset = PatientExamination.objects.all().select_related("patient", "examination")
|
|
18
|
+
serializer_class = PatientExaminationSerializer
|
|
19
|
+
|
|
20
|
+
def get_queryset(self):
|
|
21
|
+
"""Optimierte Abfrage mit besserer Performance"""
|
|
22
|
+
return (
|
|
23
|
+
PatientExamination.objects.select_related("patient", "examination")
|
|
24
|
+
.prefetch_related("patient_findings", "indications")
|
|
25
|
+
.order_by("-date_start", "-id")
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
def get_patient_examination_ids(self):
|
|
29
|
+
"""Hilfsmethode zum Abrufen mehrerer PatientExamination IDs"""
|
|
30
|
+
return PatientExamination.objects.filter(all=True).values_list("id", flat=True)
|
|
31
|
+
|
|
32
|
+
def get_patient_examination_by_id(self, pk):
|
|
33
|
+
"""Hilfsmethode zum Abrufen einer PatientExamination nach ID"""
|
|
34
|
+
if not PatientExamination.objects.filter(pk=pk).exists():
|
|
35
|
+
return None
|
|
36
|
+
else:
|
|
37
|
+
return PatientExamination.objects.select_related(
|
|
38
|
+
"patient", "examination"
|
|
39
|
+
).get(pk=pk)
|
|
40
|
+
|
|
41
|
+
@action(detail=False, methods=["get"])
|
|
42
|
+
def patients_dropdown(self, request):
|
|
43
|
+
"""
|
|
44
|
+
Endpoint für Patient-Dropdown-Daten
|
|
45
|
+
GET /api/patient-examinations/patients_dropdown/
|
|
46
|
+
"""
|
|
47
|
+
patients = Patient.objects.all().order_by("first_name", "last_name")
|
|
48
|
+
serializer = PatientDropdownSerializer(patients, many=True)
|
|
49
|
+
return Response(serializer.data)
|
|
50
|
+
|
|
51
|
+
@action(detail=False, methods=["get"])
|
|
52
|
+
def examinations_dropdown(self, request):
|
|
53
|
+
"""
|
|
54
|
+
Endpoint für Examination-Dropdown-Daten
|
|
55
|
+
GET /api/patient-examinations/examinations_dropdown/
|
|
56
|
+
"""
|
|
57
|
+
examinations = Examination.objects.all().order_by("name")
|
|
58
|
+
serializer = ExaminationDropdownSerializer(examinations, many=True)
|
|
59
|
+
return Response(serializer.data)
|
|
60
|
+
|
|
61
|
+
@action(detail=False, methods=["get"])
|
|
62
|
+
def recent(self, request):
|
|
63
|
+
"""
|
|
64
|
+
Endpoint für die letzten PatientExaminations
|
|
65
|
+
GET /api/patient-examinations/recent/
|
|
66
|
+
"""
|
|
67
|
+
limit = int(request.query_params.get("limit", 10))
|
|
68
|
+
recent_examinations = self.get_queryset()[:limit]
|
|
69
|
+
serializer = self.get_serializer(recent_examinations, many=True)
|
|
70
|
+
return Response(serializer.data)
|
|
71
|
+
|
|
72
|
+
@action(detail=True, methods=["get"])
|
|
73
|
+
def details(self, request, pk=None):
|
|
74
|
+
"""
|
|
75
|
+
Detaillierte Informationen über eine PatientExamination
|
|
76
|
+
GET /api/patient-examinations/{id}/details/
|
|
77
|
+
"""
|
|
78
|
+
examination = self.get_object()
|
|
79
|
+
data = {
|
|
80
|
+
"examination": PatientExaminationSerializer(examination).data,
|
|
81
|
+
"findings": examination.get_findings().count(),
|
|
82
|
+
"indications": examination.get_indications().count(),
|
|
83
|
+
"patient_age_at_examination": examination.get_patient_age_at_examination()
|
|
84
|
+
if examination.date_start
|
|
85
|
+
else None,
|
|
86
|
+
}
|
|
87
|
+
return Response(data)
|
|
88
|
+
|
|
89
|
+
def create(self, request, *args, **kwargs):
|
|
90
|
+
"""
|
|
91
|
+
Überschreibt die create-Methode für bessere Fehlerbehandlung
|
|
92
|
+
"""
|
|
93
|
+
serializer = self.get_serializer(data=request.data)
|
|
94
|
+
if serializer.is_valid():
|
|
95
|
+
try:
|
|
96
|
+
self.perform_create(serializer)
|
|
97
|
+
headers = self.get_success_headers(serializer.data)
|
|
98
|
+
return Response(
|
|
99
|
+
serializer.data, status=status.HTTP_201_CREATED, headers=headers
|
|
100
|
+
)
|
|
101
|
+
except Exception as e:
|
|
102
|
+
return Response(
|
|
103
|
+
{"error": f"Fehler beim Erstellen der Untersuchung: {str(e)}"},
|
|
104
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
105
|
+
)
|
|
106
|
+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
107
|
+
|
|
108
|
+
def update(self, request, *args, **kwargs):
|
|
109
|
+
"""
|
|
110
|
+
Überschreibt die update-Methode für bessere Fehlerbehandlung
|
|
111
|
+
"""
|
|
112
|
+
partial = kwargs.pop("partial", False)
|
|
113
|
+
instance = self.get_object()
|
|
114
|
+
serializer = self.get_serializer(instance, data=request.data, partial=partial)
|
|
115
|
+
|
|
116
|
+
if serializer.is_valid():
|
|
117
|
+
try:
|
|
118
|
+
self.perform_update(serializer)
|
|
119
|
+
return Response(serializer.data)
|
|
120
|
+
except Exception as e:
|
|
121
|
+
return Response(
|
|
122
|
+
{"error": f"Fehler beim Aktualisieren der Untersuchung: {str(e)}"},
|
|
123
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
124
|
+
)
|
|
125
|
+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
126
|
+
|
|
127
|
+
def get_findings_for_examination(self, request, pk=None):
|
|
128
|
+
"""
|
|
129
|
+
Endpoint to retrieve findings for a specific PatientExamination
|
|
130
|
+
GET /api/patient-examinations/{pk}/findings/
|
|
131
|
+
"""
|
|
132
|
+
examination = self.get_patient_examination_by_id(pk)
|
|
133
|
+
if not examination:
|
|
134
|
+
return Response(
|
|
135
|
+
{"error": "PatientExamination nicht gefunden"},
|
|
136
|
+
status=status.HTTP_404_NOT_FOUND,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
findings = PatientExaminationSerializer.get_
|
|
140
|
+
finding_data = [{"id": f.id, "name": str(f)} for f in findings]
|
|
141
|
+
return Response(finding_data)
|