endoreg-db 0.8.4.4__py3-none-any.whl → 0.8.8.0__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/authz/auth.py +74 -0
- endoreg_db/authz/backends.py +168 -0
- endoreg_db/authz/management/commands/list_routes.py +18 -0
- endoreg_db/authz/middleware.py +83 -0
- endoreg_db/authz/permissions.py +127 -0
- endoreg_db/authz/policy.py +218 -0
- endoreg_db/authz/views_auth.py +66 -0
- endoreg_db/config/env.py +13 -8
- endoreg_db/data/__init__.py +8 -31
- endoreg_db/data/_examples/disease.yaml +55 -0
- endoreg_db/data/_examples/disease_classification.yaml +13 -0
- endoreg_db/data/_examples/disease_classification_choice.yaml +62 -0
- endoreg_db/data/_examples/event.yaml +64 -0
- endoreg_db/data/_examples/examination.yaml +72 -0
- endoreg_db/data/_examples/finding/anatomy_colon.yaml +128 -0
- endoreg_db/data/_examples/finding/colonoscopy.yaml +40 -0
- endoreg_db/data/_examples/finding/colonoscopy_bowel_prep.yaml +56 -0
- endoreg_db/data/_examples/finding/complication.yaml +16 -0
- endoreg_db/data/_examples/finding/data.yaml +105 -0
- endoreg_db/data/_examples/finding/examination_setting.yaml +16 -0
- endoreg_db/data/_examples/finding/medication_related.yaml +18 -0
- endoreg_db/data/_examples/finding/outcome.yaml +12 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_bowel_preparation.yaml +68 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_jnet.yaml +22 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_kudo.yaml +25 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_size.yaml +68 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_location.yaml +80 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lst.yaml +21 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_nice.yaml +20 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_paris.yaml +26 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_sano.yaml +22 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_summary.yaml +53 -0
- endoreg_db/data/_examples/finding_classification/complication_generic.yaml +25 -0
- endoreg_db/data/_examples/finding_classification/examination_setting_generic.yaml +40 -0
- endoreg_db/data/_examples/finding_classification/histology_colo.yaml +51 -0
- endoreg_db/data/_examples/finding_classification/intervention_required.yaml +26 -0
- endoreg_db/data/_examples/finding_classification/medication_related.yaml +23 -0
- endoreg_db/data/_examples/finding_classification/visualized.yaml +33 -0
- endoreg_db/data/_examples/finding_classification_choice/bowel_preparation.yaml +78 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_circularity_default.yaml +32 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_lst.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_nice.yaml +17 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_paris.yaml +57 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_planarity_default.yaml +49 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_sano.yaml +14 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_surface_intact_default.yaml +36 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_location.yaml +229 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_size.yaml +82 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/complication_generic_types.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/histology.yaml +24 -0
- endoreg_db/data/_examples/finding_classification_choice/histology_polyp.yaml +20 -0
- endoreg_db/data/_examples/finding_classification_choice/outcome.yaml +19 -0
- endoreg_db/data/_examples/finding_classification_choice/yes_no_na.yaml +11 -0
- endoreg_db/data/_examples/finding_classification_type/colonoscopy_basic.yaml +48 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy.yaml +43 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_colonoscopy.yaml +168 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_egd.yaml +128 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_ercp.yaml +32 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_eus_lower.yaml +9 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_eus_upper.yaml +36 -0
- endoreg_db/data/_examples/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/_examples/finding_type/data.yaml +43 -0
- endoreg_db/data/_examples/requirement/age.yaml +26 -0
- endoreg_db/data/_examples/requirement/colonoscopy_baseline_austria.yaml +45 -0
- endoreg_db/data/_examples/requirement/disease_cardiovascular.yaml +79 -0
- endoreg_db/data/_examples/requirement/disease_classification_choice_cardiovascular.yaml +41 -0
- endoreg_db/data/_examples/requirement/disease_hepatology.yaml +12 -0
- endoreg_db/data/_examples/requirement/disease_misc.yaml +12 -0
- endoreg_db/data/_examples/requirement/disease_renal.yaml +96 -0
- endoreg_db/data/_examples/requirement/endoscopy_bleeding_risk.yaml +59 -0
- endoreg_db/data/_examples/requirement/event_cardiology.yaml +251 -0
- endoreg_db/data/_examples/requirement/event_requirements.yaml +145 -0
- endoreg_db/data/_examples/requirement/finding_colon_polyp.yaml +50 -0
- endoreg_db/data/_examples/requirement/gender.yaml +25 -0
- endoreg_db/data/_examples/requirement/lab_value.yaml +441 -0
- endoreg_db/data/_examples/requirement/medication.yaml +93 -0
- endoreg_db/data/_examples/requirement_operator/age.yaml +13 -0
- endoreg_db/data/_examples/requirement_operator/lab_operators.yaml +129 -0
- endoreg_db/data/_examples/requirement_operator/model_operators.yaml +96 -0
- endoreg_db/data/_examples/requirement_set/01_endoscopy_generic.yaml +48 -0
- endoreg_db/data/_examples/requirement_set/colonoscopy_austria_screening.yaml +57 -0
- endoreg_db/data/_examples/yaml_examples.xlsx +0 -0
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +4 -3
- endoreg_db/data/event_classification/data.yaml +4 -0
- endoreg_db/data/event_classification_choice/data.yaml +9 -0
- endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +43 -70
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +22 -52
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +31 -62
- endoreg_db/data/finding_classification/histology_colo.yaml +28 -36
- endoreg_db/data/requirement/colon_polyp_intervention.yaml +49 -0
- endoreg_db/data/requirement/coloreg_colon_polyp.yaml +49 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +31 -12
- 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 +178 -0
- endoreg_db/data/requirement_set/_old_ +109 -0
- endoreg_db/data/requirement_set_type/data.yaml +21 -0
- endoreg_db/data/setup_config.yaml +4 -4
- endoreg_db/data/tag/requirement_set_tags.yaml +21 -0
- endoreg_db/exceptions.py +5 -2
- endoreg_db/helpers/data_loader.py +1 -1
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +21 -10
- endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
- endoreg_db/management/commands/import_video.py +9 -10
- endoreg_db/management/commands/import_video_with_classification.py +1 -1
- endoreg_db/management/commands/init_default_ai_model.py +1 -1
- endoreg_db/management/commands/list_routes.py +18 -0
- endoreg_db/management/commands/load_ai_model_data.py +2 -1
- endoreg_db/management/commands/load_center_data.py +12 -12
- endoreg_db/management/commands/load_requirement_data.py +60 -31
- endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
- endoreg_db/management/commands/setup_endoreg_db.py +14 -10
- endoreg_db/management/commands/storage_management.py +271 -203
- endoreg_db/migrations/0001_initial.py +1799 -1300
- endoreg_db/migrations/0002_requirementset_depends_on.py +18 -0
- endoreg_db/migrations/_old/0001_initial.py +1857 -0
- endoreg_db/migrations/_old/0004_employee_city_employee_post_code_employee_street_and_more.py +68 -0
- endoreg_db/migrations/_old/0004_remove_casetemplate_rules_and_more.py +77 -0
- endoreg_db/migrations/_old/0005_merge_20251111_1003.py +14 -0
- endoreg_db/migrations/_old/0006_sensitivemeta_anonymized_text_and_more.py +68 -0
- endoreg_db/migrations/_old/0007_remove_rule_attribute_dtype_remove_rule_rule_type_and_more.py +89 -0
- endoreg_db/migrations/_old/0008_remove_event_event_classification_and_more.py +27 -0
- endoreg_db/migrations/_old/0009_alter_modelmeta_options_and_more.py +21 -0
- endoreg_db/models/__init__.py +78 -123
- endoreg_db/models/administration/__init__.py +21 -42
- endoreg_db/models/administration/ai/active_model.py +2 -2
- endoreg_db/models/administration/ai/ai_model.py +7 -6
- endoreg_db/models/administration/case/__init__.py +1 -15
- endoreg_db/models/administration/case/case.py +3 -3
- endoreg_db/models/administration/case/case_template/__init__.py +2 -14
- endoreg_db/models/administration/case/case_template/case_template.py +2 -124
- endoreg_db/models/administration/case/case_template/case_template_rule.py +2 -268
- endoreg_db/models/administration/case/case_template/case_template_rule_value.py +2 -85
- endoreg_db/models/administration/case/case_template/case_template_type.py +2 -25
- endoreg_db/models/administration/center/center.py +33 -19
- endoreg_db/models/administration/center/center_product.py +12 -9
- endoreg_db/models/administration/center/center_resource.py +25 -19
- endoreg_db/models/administration/center/center_shift.py +21 -17
- endoreg_db/models/administration/center/center_waste.py +16 -8
- endoreg_db/models/administration/person/__init__.py +2 -0
- endoreg_db/models/administration/person/employee/employee.py +10 -5
- endoreg_db/models/administration/person/employee/employee_qualification.py +9 -4
- endoreg_db/models/administration/person/employee/employee_type.py +12 -6
- endoreg_db/models/administration/person/examiner/examiner.py +13 -11
- endoreg_db/models/administration/person/patient/__init__.py +2 -0
- endoreg_db/models/administration/person/patient/patient.py +103 -100
- endoreg_db/models/administration/person/patient/patient_external_id.py +37 -0
- endoreg_db/models/administration/person/person.py +4 -0
- endoreg_db/models/administration/person/profession/__init__.py +8 -4
- endoreg_db/models/administration/person/user/portal_user_information.py +11 -7
- endoreg_db/models/administration/product/product.py +20 -15
- endoreg_db/models/administration/product/product_material.py +17 -18
- endoreg_db/models/administration/product/product_weight.py +12 -8
- endoreg_db/models/administration/product/reference_product.py +23 -55
- endoreg_db/models/administration/qualification/qualification.py +7 -3
- endoreg_db/models/administration/qualification/qualification_type.py +7 -3
- endoreg_db/models/administration/shift/scheduled_days.py +8 -5
- endoreg_db/models/administration/shift/shift.py +16 -12
- endoreg_db/models/administration/shift/shift_type.py +23 -31
- endoreg_db/models/label/__init__.py +7 -8
- endoreg_db/models/label/annotation/image_classification.py +10 -9
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +8 -5
- endoreg_db/models/label/label.py +15 -15
- endoreg_db/models/label/label_set.py +19 -6
- endoreg_db/models/label/label_type.py +1 -1
- endoreg_db/models/label/label_video_segment/_create_from_video.py +5 -8
- endoreg_db/models/label/label_video_segment/label_video_segment.py +76 -102
- endoreg_db/models/label/video_segmentation_label.py +4 -0
- endoreg_db/models/label/video_segmentation_labelset.py +4 -3
- endoreg_db/models/media/frame/frame.py +22 -22
- endoreg_db/models/media/pdf/raw_pdf.py +249 -177
- endoreg_db/models/media/pdf/report_file.py +25 -29
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +30 -46
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
- endoreg_db/models/media/video/__init__.py +1 -0
- endoreg_db/models/media/video/create_from_file.py +48 -56
- endoreg_db/models/media/video/pipe_1.py +30 -33
- endoreg_db/models/media/video/pipe_2.py +8 -9
- endoreg_db/models/media/video/video_file.py +359 -204
- endoreg_db/models/media/video/video_file_ai.py +288 -74
- endoreg_db/models/media/video/video_file_anonymize.py +38 -38
- endoreg_db/models/media/video/video_file_frames/__init__.py +3 -1
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +7 -9
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +9 -8
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +38 -45
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +4 -18
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +7 -6
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +15 -25
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +26 -23
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +23 -14
- endoreg_db/models/media/video/video_file_io.py +109 -62
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +3 -3
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +5 -3
- endoreg_db/models/media/video/video_file_meta/get_fps.py +37 -34
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +19 -25
- endoreg_db/models/media/video/video_file_meta/text_meta.py +41 -38
- endoreg_db/models/media/video/video_file_meta/video_meta.py +14 -7
- endoreg_db/models/media/video/video_file_segments.py +24 -17
- endoreg_db/models/media/video/video_metadata.py +19 -35
- endoreg_db/models/media/video/video_processing.py +96 -95
- endoreg_db/models/medical/contraindication/__init__.py +13 -3
- endoreg_db/models/medical/disease.py +22 -16
- endoreg_db/models/medical/event.py +31 -18
- endoreg_db/models/medical/examination/__init__.py +13 -6
- endoreg_db/models/medical/examination/examination.py +17 -18
- endoreg_db/models/medical/examination/examination_indication.py +26 -25
- endoreg_db/models/medical/examination/examination_time.py +16 -6
- endoreg_db/models/medical/examination/examination_time_type.py +9 -6
- endoreg_db/models/medical/examination/examination_type.py +3 -4
- endoreg_db/models/medical/finding/finding.py +38 -39
- endoreg_db/models/medical/finding/finding_classification.py +37 -48
- endoreg_db/models/medical/finding/finding_intervention.py +27 -22
- endoreg_db/models/medical/finding/finding_type.py +13 -12
- endoreg_db/models/medical/hardware/endoscope.py +20 -26
- endoreg_db/models/medical/hardware/endoscopy_processor.py +2 -2
- endoreg_db/models/medical/laboratory/lab_value.py +62 -91
- endoreg_db/models/medical/medication/medication.py +22 -10
- endoreg_db/models/medical/medication/medication_indication.py +29 -3
- endoreg_db/models/medical/medication/medication_indication_type.py +25 -14
- endoreg_db/models/medical/medication/medication_intake_time.py +31 -19
- endoreg_db/models/medical/medication/medication_schedule.py +27 -16
- endoreg_db/models/medical/organ/__init__.py +15 -12
- endoreg_db/models/medical/patient/medication_examples.py +1 -5
- endoreg_db/models/medical/patient/patient_disease.py +20 -23
- endoreg_db/models/medical/patient/patient_event.py +19 -22
- endoreg_db/models/medical/patient/patient_examination.py +48 -54
- endoreg_db/models/medical/patient/patient_examination_indication.py +16 -14
- endoreg_db/models/medical/patient/patient_finding.py +122 -139
- endoreg_db/models/medical/patient/patient_finding_classification.py +44 -49
- endoreg_db/models/medical/patient/patient_finding_intervention.py +8 -19
- endoreg_db/models/medical/patient/patient_lab_sample.py +28 -23
- endoreg_db/models/medical/patient/patient_lab_value.py +82 -89
- endoreg_db/models/medical/patient/patient_medication.py +27 -38
- endoreg_db/models/medical/patient/patient_medication_schedule.py +28 -36
- endoreg_db/models/medical/risk/risk.py +7 -6
- endoreg_db/models/medical/risk/risk_type.py +8 -5
- endoreg_db/models/metadata/model_meta.py +60 -29
- endoreg_db/models/metadata/model_meta_logic.py +139 -18
- endoreg_db/models/metadata/pdf_meta.py +19 -24
- endoreg_db/models/metadata/sensitive_meta.py +102 -85
- endoreg_db/models/metadata/sensitive_meta_logic.py +383 -43
- endoreg_db/models/metadata/video_meta.py +51 -31
- endoreg_db/models/metadata/video_prediction_logic.py +16 -23
- endoreg_db/models/metadata/video_prediction_meta.py +29 -33
- endoreg_db/models/other/distribution/date_value_distribution.py +89 -29
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +21 -5
- endoreg_db/models/other/distribution/numeric_value_distribution.py +114 -53
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +4 -3
- endoreg_db/models/other/emission/emission_factor.py +18 -8
- endoreg_db/models/other/gender.py +10 -5
- endoreg_db/models/other/information_source.py +25 -25
- endoreg_db/models/other/material.py +9 -5
- endoreg_db/models/other/resource.py +6 -4
- endoreg_db/models/other/tag.py +10 -5
- endoreg_db/models/other/transport_route.py +13 -8
- endoreg_db/models/other/unit.py +10 -6
- endoreg_db/models/other/waste.py +6 -5
- endoreg_db/models/requirement/requirement.py +580 -272
- endoreg_db/models/requirement/requirement_error.py +85 -0
- endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
- endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +3 -6
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +90 -64
- endoreg_db/models/requirement/requirement_operator.py +36 -33
- endoreg_db/models/requirement/requirement_set.py +74 -57
- endoreg_db/models/state/__init__.py +4 -4
- endoreg_db/models/state/abstract.py +2 -2
- endoreg_db/models/state/anonymization.py +12 -0
- endoreg_db/models/state/audit_ledger.py +46 -47
- endoreg_db/models/state/label_video_segment.py +9 -0
- endoreg_db/models/state/raw_pdf.py +40 -46
- endoreg_db/models/state/sensitive_meta.py +6 -2
- endoreg_db/models/state/video.py +58 -53
- endoreg_db/models/upload_job.py +32 -55
- endoreg_db/models/utils.py +1 -2
- endoreg_db/root_urls.py +21 -2
- endoreg_db/serializers/__init__.py +26 -57
- endoreg_db/serializers/anonymization.py +18 -10
- endoreg_db/serializers/meta/report_meta.py +1 -1
- endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
- endoreg_db/serializers/misc/__init__.py +1 -1
- endoreg_db/serializers/misc/file_overview.py +33 -91
- endoreg_db/serializers/misc/{vop_patient_data.py → sensitive_patient_data.py} +1 -1
- endoreg_db/serializers/requirements/requirement_sets.py +92 -22
- endoreg_db/serializers/video/segmentation.py +2 -1
- endoreg_db/serializers/video/video_processing_history.py +20 -5
- endoreg_db/serializers/video_examination.py +198 -0
- endoreg_db/services/anonymization.py +75 -73
- endoreg_db/services/lookup_service.py +256 -73
- endoreg_db/services/lookup_store.py +174 -30
- endoreg_db/services/pdf_import.py +711 -310
- endoreg_db/services/storage_aware_video_processor.py +140 -114
- endoreg_db/services/video_import.py +266 -117
- endoreg_db/urls/__init__.py +27 -27
- endoreg_db/urls/label_video_segments.py +2 -0
- endoreg_db/urls/media.py +108 -66
- endoreg_db/urls/root_urls.py +29 -0
- endoreg_db/utils/__init__.py +15 -5
- endoreg_db/utils/ai/multilabel_classification_net.py +116 -20
- endoreg_db/utils/case_generator/__init__.py +3 -0
- endoreg_db/utils/dataloader.py +88 -16
- endoreg_db/utils/defaults/set_default_center.py +32 -0
- endoreg_db/utils/names.py +22 -16
- endoreg_db/utils/permissions.py +2 -1
- endoreg_db/utils/pipelines/process_video_dir.py +1 -1
- endoreg_db/utils/requirement_operator_logic/model_evaluators.py +414 -127
- endoreg_db/utils/setup_config.py +8 -5
- endoreg_db/utils/storage.py +115 -0
- endoreg_db/utils/validate_endo_roi.py +8 -2
- endoreg_db/utils/video/ffmpeg_wrapper.py +184 -188
- endoreg_db/views/__init__.py +5 -12
- endoreg_db/views/anonymization/media_management.py +198 -163
- endoreg_db/views/anonymization/overview.py +4 -1
- endoreg_db/views/anonymization/validate.py +174 -40
- endoreg_db/views/media/__init__.py +2 -0
- endoreg_db/views/media/pdf_media.py +131 -150
- endoreg_db/views/media/sensitive_metadata.py +46 -6
- endoreg_db/views/media/video_media.py +89 -82
- endoreg_db/views/media/video_segments.py +187 -260
- endoreg_db/views/meta/sensitive_meta_detail.py +0 -63
- endoreg_db/views/patient/patient.py +5 -4
- endoreg_db/views/pdf/__init__.py +5 -8
- endoreg_db/views/pdf/pdf_stream.py +186 -0
- endoreg_db/views/pdf/pdf_stream_views.py +0 -127
- endoreg_db/views/pdf/reimport.py +86 -91
- endoreg_db/views/requirement/evaluate.py +188 -187
- endoreg_db/views/requirement/lookup.py +186 -288
- endoreg_db/views/requirement/requirement_utils.py +89 -0
- endoreg_db/views/video/__init__.py +0 -4
- endoreg_db/views/video/correction.py +2 -2
- endoreg_db/views/video/video_examination_viewset.py +202 -289
- {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/METADATA +7 -3
- {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/RECORD +350 -255
- endoreg_db/models/administration/permissions/__init__.py +0 -44
- endoreg_db/models/media/video/refactor_plan.md +0 -0
- endoreg_db/models/media/video/video_file_frames.py +0 -0
- endoreg_db/models/metadata/frame_ocr_result.py +0 -0
- endoreg_db/models/rule/__init__.py +0 -13
- endoreg_db/models/rule/rule.py +0 -27
- endoreg_db/models/rule/rule_applicator.py +0 -224
- endoreg_db/models/rule/rule_attribute_dtype.py +0 -17
- endoreg_db/models/rule/rule_type.py +0 -20
- endoreg_db/models/rule/ruleset.py +0 -17
- endoreg_db/serializers/video/video_metadata.py +0 -105
- endoreg_db/urls/report.py +0 -48
- endoreg_db/urls/video.py +0 -61
- endoreg_db/utils/case_generator/case_generator.py +0 -159
- endoreg_db/utils/case_generator/utils.py +0 -30
- endoreg_db/views/pdf/pdf_media.py +0 -239
- endoreg_db/views/report/__init__.py +0 -9
- endoreg_db/views/report/report_list.py +0 -112
- endoreg_db/views/report/report_with_secure_url.py +0 -28
- endoreg_db/views/report/start_examination.py +0 -7
- endoreg_db/views/video/video_media.py +0 -158
- endoreg_db/views.py +0 -0
- /endoreg_db/data/{requirement_set → _examples/requirement_set}/endoscopy_bleeding_risk.yaml +0 -0
- /endoreg_db/migrations/{0002_add_video_correction_models.py → _old/0002_add_video_correction_models.py} +0 -0
- /endoreg_db/migrations/{0003_add_center_display_name.py → _old/0003_add_center_display_name.py} +0 -0
- {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/WHEEL +0 -0
- {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,44 +1,56 @@
|
|
|
1
|
-
|
|
1
|
+
"""Model for medication intake time"""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
2
5
|
from django.db import models
|
|
3
6
|
|
|
4
7
|
|
|
5
8
|
class MedicationIntakeTimeManager(models.Manager):
|
|
6
|
-
|
|
9
|
+
"""Manager for the medication intake time model."""
|
|
10
|
+
|
|
7
11
|
def get_by_natural_key(self, name):
|
|
8
|
-
|
|
12
|
+
"""Retrieve a medication intake time by its natural key."""
|
|
9
13
|
return self.get(name=name)
|
|
10
|
-
|
|
14
|
+
|
|
15
|
+
|
|
11
16
|
class MedicationIntakeTime(models.Model):
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
"""Model representing a medication intake time."""
|
|
18
|
+
|
|
19
|
+
name = models.CharField(max_length=255, unique=True) # Made unique=True
|
|
20
|
+
repeats = models.CharField(max_length=20, default="daily")
|
|
15
21
|
time = models.TimeField()
|
|
16
22
|
|
|
17
23
|
objects = MedicationIntakeTimeManager()
|
|
18
24
|
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from endoreg_db.models import MedicationSchedule
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def medication_schedules(self) -> "models.manager.RelatedManager[MedicationSchedule]": ...
|
|
30
|
+
|
|
19
31
|
@classmethod
|
|
20
32
|
def dm(cls):
|
|
21
|
-
|
|
22
|
-
return cls.objects.get(name=
|
|
23
|
-
|
|
33
|
+
"""Return the daily morning intake time object."""
|
|
34
|
+
return cls.objects.get(name="daily-morning")
|
|
35
|
+
|
|
24
36
|
@classmethod
|
|
25
37
|
def dno(cls):
|
|
26
|
-
|
|
27
|
-
return cls.objects.get(name=
|
|
38
|
+
"""Return the daily noon intake time object."""
|
|
39
|
+
return cls.objects.get(name="daily-noon")
|
|
28
40
|
|
|
29
41
|
@classmethod
|
|
30
42
|
def de(cls):
|
|
31
|
-
|
|
32
|
-
return cls.objects.get(name=
|
|
33
|
-
|
|
43
|
+
"""Return the daily evening intake time object."""
|
|
44
|
+
return cls.objects.get(name="daily-evening")
|
|
45
|
+
|
|
34
46
|
@classmethod
|
|
35
47
|
def dn(cls):
|
|
36
|
-
|
|
37
|
-
return cls.objects.get(name=
|
|
48
|
+
"""Return the daily night intake time object."""
|
|
49
|
+
return cls.objects.get(name="daily-night")
|
|
38
50
|
|
|
39
51
|
def natural_key(self):
|
|
40
|
-
|
|
52
|
+
"""Return the natural key for the medication intake time."""
|
|
41
53
|
return (self.name,)
|
|
42
|
-
|
|
54
|
+
|
|
43
55
|
def __str__(self):
|
|
44
56
|
return self.name + " at " + str(self.time) + " (" + self.repeats + ")"
|
|
@@ -1,45 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"""Model for the medication schedule."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, List, cast
|
|
4
|
+
|
|
3
5
|
from django.db import models
|
|
4
6
|
|
|
5
7
|
if TYPE_CHECKING:
|
|
6
|
-
from endoreg_db.models import MedicationIntakeTime
|
|
8
|
+
from endoreg_db.models import Medication, MedicationIntakeTime, Unit
|
|
9
|
+
|
|
10
|
+
|
|
7
11
|
class MedicationScheduleManager(models.Manager):
|
|
8
|
-
|
|
12
|
+
"""Manager for the medication schedule model."""
|
|
13
|
+
|
|
9
14
|
def get_by_natural_key(self, name):
|
|
10
15
|
"""
|
|
11
16
|
Retrieve a MedicationSchedule instance by its name.
|
|
12
|
-
|
|
17
|
+
|
|
13
18
|
Parameters:
|
|
14
19
|
name (str): The name of the medication schedule to retrieve.
|
|
15
|
-
|
|
20
|
+
|
|
16
21
|
Returns:
|
|
17
22
|
MedicationSchedule: The matching medication schedule instance.
|
|
18
23
|
"""
|
|
19
24
|
return self.get(name=name)
|
|
20
|
-
|
|
25
|
+
|
|
26
|
+
|
|
21
27
|
class MedicationSchedule(models.Model):
|
|
22
|
-
|
|
23
|
-
|
|
28
|
+
"""Model representing a medication schedule."""
|
|
29
|
+
|
|
30
|
+
name = models.CharField(max_length=255, unique=True)
|
|
24
31
|
description = models.TextField(blank=True, null=True)
|
|
25
32
|
medication = models.ForeignKey("Medication", on_delete=models.CASCADE)
|
|
26
33
|
unit = models.ForeignKey("Unit", on_delete=models.CASCADE)
|
|
27
34
|
therapy_duration_d = models.FloatField(blank=True, null=True)
|
|
28
35
|
dose = models.FloatField()
|
|
29
36
|
intake_times = models.ManyToManyField(
|
|
30
|
-
"MedicationIntakeTime",
|
|
37
|
+
"MedicationIntakeTime",
|
|
31
38
|
)
|
|
32
39
|
|
|
33
40
|
objects = MedicationScheduleManager()
|
|
34
41
|
|
|
42
|
+
if TYPE_CHECKING:
|
|
43
|
+
unit: models.ForeignKey["Unit"]
|
|
44
|
+
medication: models.ForeignKey["Medication"]
|
|
45
|
+
intake_times = cast("models.manager.RelatedManager[MedicationIntakeTime]", intake_times)
|
|
46
|
+
|
|
35
47
|
def natural_key(self):
|
|
36
|
-
|
|
48
|
+
"""Return the natural key for the medication schedule."""
|
|
37
49
|
return (self.name,)
|
|
38
|
-
|
|
50
|
+
|
|
39
51
|
def __str__(self):
|
|
40
52
|
return str(self.name)
|
|
41
|
-
|
|
53
|
+
|
|
42
54
|
def get_intake_times(self) -> List["MedicationIntakeTime"]:
|
|
43
|
-
|
|
44
|
-
return [_ for _ in self.intake_times.all()]
|
|
45
|
-
|
|
55
|
+
"""Return a list of all intake times for this medication schedule."""
|
|
56
|
+
return [_ for _ in self.intake_times.all()]
|
|
@@ -1,35 +1,38 @@
|
|
|
1
1
|
"""Module for Organ models."""
|
|
2
|
+
|
|
2
3
|
from django.db import models
|
|
3
4
|
|
|
5
|
+
|
|
4
6
|
class OrganManager(models.Manager):
|
|
5
7
|
"""Manager for Organ model."""
|
|
6
8
|
|
|
7
9
|
def get_by_natural_key(self, name):
|
|
8
10
|
"""Retrieve an Organ by its natural key."""
|
|
9
11
|
return self.get(name=name)
|
|
10
|
-
|
|
12
|
+
|
|
11
13
|
def all_names(self):
|
|
12
14
|
"""Return a list of all organ names."""
|
|
13
|
-
return list(self.all().values_list(
|
|
14
|
-
|
|
15
|
+
return list(self.all().values_list("name", flat=True))
|
|
16
|
+
|
|
17
|
+
|
|
15
18
|
class Organ(models.Model):
|
|
16
19
|
"""Model representing an organ."""
|
|
17
|
-
|
|
18
|
-
name = models.CharField(max_length=100, unique=True)
|
|
20
|
+
|
|
21
|
+
name = models.CharField(max_length=100, unique=True)
|
|
19
22
|
description = models.TextField(blank=True, null=True)
|
|
20
23
|
|
|
21
24
|
# Deprecated
|
|
22
|
-
location_choices = models.ManyToManyField(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
)
|
|
25
|
+
# location_choices = models.ManyToManyField(
|
|
26
|
+
# 'FindingClassificationChoice',
|
|
27
|
+
# blank=True, related_name='organs'
|
|
28
|
+
# )
|
|
26
29
|
|
|
27
30
|
objects = OrganManager()
|
|
28
|
-
|
|
31
|
+
|
|
29
32
|
def natural_key(self):
|
|
30
33
|
"""Return the natural key for the organ."""
|
|
31
34
|
return (self.name,)
|
|
32
|
-
|
|
35
|
+
|
|
33
36
|
def __str__(self):
|
|
34
37
|
"""Return string representation of the organ."""
|
|
35
|
-
return str(self.name)
|
|
38
|
+
return str(self.name)
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
from endoreg_db.models import (
|
|
2
|
-
Patient,
|
|
3
|
-
PatientMedication,
|
|
4
|
-
PatientMedicationSchedule,
|
|
5
2
|
Medication,
|
|
6
3
|
MedicationIndication,
|
|
7
4
|
MedicationIndicationType,
|
|
8
|
-
MedicationIntakeTime
|
|
9
|
-
MedicationSchedule
|
|
5
|
+
MedicationIntakeTime
|
|
10
6
|
)
|
|
11
7
|
from endoreg_db.helpers.default_objects import generate_patient
|
|
12
8
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, cast # Added List
|
|
2
|
+
|
|
1
3
|
from django.db import models
|
|
2
|
-
from typing import TYPE_CHECKING # Added List
|
|
3
4
|
|
|
4
5
|
if TYPE_CHECKING:
|
|
6
|
+
from endoreg_db.utils.links.requirement_link import RequirementLinks # Added RequirementLinks
|
|
7
|
+
|
|
5
8
|
from ...administration.person.patient.patient import Patient
|
|
6
9
|
from ..disease import Disease, DiseaseClassificationChoice
|
|
7
|
-
from endoreg_db.utils.links.requirement_link import RequirementLinks # Added RequirementLinks
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class PatientDisease(models.Model):
|
|
@@ -14,14 +16,9 @@ class PatientDisease(models.Model):
|
|
|
14
16
|
Links a patient to a disease type, optional classification choices, start/end dates,
|
|
15
17
|
and stores associated subcategory values and numerical descriptors.
|
|
16
18
|
"""
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
)
|
|
21
|
-
disease = models.ForeignKey(
|
|
22
|
-
"Disease", on_delete=models.CASCADE,
|
|
23
|
-
related_name="patient_diseases"
|
|
24
|
-
)
|
|
19
|
+
|
|
20
|
+
patient = models.ForeignKey("Patient", on_delete=models.CASCADE, related_name="diseases")
|
|
21
|
+
disease = models.ForeignKey("Disease", on_delete=models.CASCADE, related_name="patient_diseases")
|
|
25
22
|
classification_choices = models.ManyToManyField("DiseaseClassificationChoice")
|
|
26
23
|
start_date = models.DateField(blank=True, null=True)
|
|
27
24
|
end_date = models.DateField(blank=True, null=True)
|
|
@@ -31,33 +28,33 @@ class PatientDisease(models.Model):
|
|
|
31
28
|
last_update = models.DateTimeField(auto_now=True)
|
|
32
29
|
|
|
33
30
|
if TYPE_CHECKING:
|
|
34
|
-
patient: "Patient"
|
|
35
|
-
disease: "Disease"
|
|
36
|
-
|
|
31
|
+
patient: models.ForeignKey["Patient"]
|
|
32
|
+
disease: models.ForeignKey["Disease"]
|
|
33
|
+
|
|
34
|
+
classification_choices = cast(
|
|
35
|
+
"models.manager.RelatedManager[DiseaseClassificationChoice]",
|
|
36
|
+
classification_choices,
|
|
37
|
+
)
|
|
37
38
|
|
|
38
39
|
def __str__(self):
|
|
39
40
|
"""Returns a string representation including the patient and disease name."""
|
|
40
41
|
return f"{self.patient} - {self.disease}"
|
|
41
|
-
|
|
42
|
+
|
|
42
43
|
@property
|
|
43
44
|
def links(self) -> "RequirementLinks":
|
|
44
|
-
from endoreg_db.utils.links.requirement_link import RequirementLinks
|
|
45
|
+
from endoreg_db.utils.links.requirement_link import RequirementLinks # Added RequirementLinks
|
|
45
46
|
|
|
46
47
|
"""
|
|
47
48
|
Aggregates and returns related model instances relevant for requirement evaluation
|
|
48
49
|
as a RequirementLinks object.
|
|
49
50
|
"""
|
|
50
|
-
links_data = {
|
|
51
|
-
"patient_diseases": [self],
|
|
52
|
-
"diseases": [],
|
|
53
|
-
"disease_classification_choices": list(self.classification_choices.all())
|
|
54
|
-
}
|
|
51
|
+
links_data = {"patient_diseases": [self], "diseases": [], "disease_classification_choices": list(self.classification_choices.all())}
|
|
55
52
|
if self.disease:
|
|
56
53
|
links_data["diseases"].append(self.disease)
|
|
57
|
-
|
|
54
|
+
|
|
58
55
|
return RequirementLinks(**links_data)
|
|
59
56
|
|
|
60
57
|
class Meta:
|
|
61
58
|
# unique_together = ('patient', 'disease', 'start_date')
|
|
62
|
-
verbose_name =
|
|
63
|
-
verbose_name_plural =
|
|
59
|
+
verbose_name = "Patient Disease"
|
|
60
|
+
verbose_name_plural = "Patient Diseases"
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
from django.db import models
|
|
2
1
|
from typing import TYPE_CHECKING
|
|
3
2
|
|
|
3
|
+
from django.db import models
|
|
4
|
+
|
|
4
5
|
if TYPE_CHECKING:
|
|
5
6
|
from ...administration.person.patient.patient import Patient
|
|
6
7
|
from ..event import Event, EventClassificationChoice
|
|
7
8
|
|
|
9
|
+
|
|
8
10
|
class PatientEvent(models.Model):
|
|
9
11
|
"""
|
|
10
12
|
Represents a specific event occurrence for a patient, potentially with classification details.
|
|
@@ -12,26 +14,24 @@ class PatientEvent(models.Model):
|
|
|
12
14
|
Links a patient to an event type, dates, description, and optional classification choices,
|
|
13
15
|
subcategories, and numerical descriptors.
|
|
14
16
|
"""
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
)
|
|
19
|
-
event:models.ForeignKey["Event"] = models.ForeignKey(
|
|
20
|
-
"Event", on_delete=models.CASCADE,
|
|
21
|
-
related_name="patient_events"
|
|
22
|
-
)
|
|
17
|
+
|
|
18
|
+
patient: models.ForeignKey["Patient"] = models.ForeignKey("Patient", on_delete=models.CASCADE, related_name="events")
|
|
19
|
+
event: models.ForeignKey["Event"] = models.ForeignKey("Event", on_delete=models.CASCADE, related_name="patient_events")
|
|
23
20
|
date_start = models.DateField()
|
|
24
21
|
date_end = models.DateField(blank=True, null=True)
|
|
25
22
|
description = models.TextField(blank=True, null=True)
|
|
26
|
-
classification_choice
|
|
27
|
-
"EventClassificationChoice", on_delete=models.CASCADE, blank=True, null=True
|
|
28
|
-
)
|
|
23
|
+
classification_choice = models.ForeignKey("EventClassificationChoice", on_delete=models.CASCADE, blank=True, null=True)
|
|
29
24
|
|
|
30
25
|
subcategories = models.JSONField(default=dict)
|
|
31
26
|
numerical_descriptors = models.JSONField(default=dict)
|
|
32
27
|
|
|
33
28
|
last_update = models.DateTimeField(auto_now=True)
|
|
34
29
|
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
patient: models.ForeignKey["Patient"]
|
|
32
|
+
event: models.ForeignKey["Event"]
|
|
33
|
+
classification_choice: models.ForeignKey["EventClassificationChoice|None"]
|
|
34
|
+
|
|
35
35
|
@property
|
|
36
36
|
def links(self):
|
|
37
37
|
"""
|
|
@@ -39,12 +39,9 @@ class PatientEvent(models.Model):
|
|
|
39
39
|
Currently, it only includes the patient and event.
|
|
40
40
|
"""
|
|
41
41
|
from endoreg_db.utils.links.requirement_link import RequirementLinks
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
events=[self.event]
|
|
46
|
-
)
|
|
47
|
-
|
|
42
|
+
|
|
43
|
+
return RequirementLinks(patient_events=[self], events=[self.event])
|
|
44
|
+
|
|
48
45
|
@property
|
|
49
46
|
def date(self):
|
|
50
47
|
"""
|
|
@@ -57,19 +54,19 @@ class PatientEvent(models.Model):
|
|
|
57
54
|
Returns a string representation of the event's start date and name.
|
|
58
55
|
"""
|
|
59
56
|
return str(self.date_start) + ": " + self.event.name
|
|
60
|
-
|
|
57
|
+
|
|
61
58
|
def set_subcategories_from_classification_choice(self):
|
|
62
59
|
"""Copies subcategory definitions from the linked classification choice."""
|
|
63
60
|
if self.classification_choice:
|
|
64
61
|
self.subcategories = self.classification_choice.subcategories
|
|
65
62
|
self.save()
|
|
66
|
-
|
|
63
|
+
|
|
67
64
|
return self.subcategories
|
|
68
|
-
|
|
65
|
+
|
|
69
66
|
def set_numerical_descriptors_from_classification_choice(self):
|
|
70
67
|
"""Copies numerical descriptor definitions from the linked classification choice."""
|
|
71
68
|
if self.classification_choice:
|
|
72
69
|
self.numerical_descriptors = self.classification_choice.numerical_descriptors
|
|
73
70
|
self.save()
|
|
74
|
-
|
|
71
|
+
|
|
75
72
|
return self.numerical_descriptors
|
|
@@ -1,48 +1,51 @@
|
|
|
1
|
-
from django.db import models
|
|
2
1
|
from typing import TYPE_CHECKING, List, Optional
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
from django.db import models
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from endoreg_db.utils.links.requirement_link import RequirementLinks
|
|
7
|
+
|
|
5
8
|
from ...administration.person.patient import Patient
|
|
9
|
+
from ...media import AnonymExaminationReport, AnonymHistologyReport, RawPdfFile, VideoFile
|
|
10
|
+
from ..examination import Examination, ExaminationIndication, ExaminationIndicationClassificationChoice
|
|
6
11
|
from ..finding import Finding
|
|
7
|
-
from .patient_finding import PatientFinding
|
|
8
|
-
from ..examination import Examination
|
|
9
|
-
from ...media import VideoFile, RawPdfFile, AnonymExaminationReport, AnonymHistologyReport
|
|
10
12
|
from .patient_examination_indication import PatientExaminationIndication
|
|
11
|
-
from
|
|
12
|
-
|
|
13
|
+
from .patient_finding import PatientFinding
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
class PatientExamination(models.Model):
|
|
15
|
-
patient = models.ForeignKey(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
examination = models.ForeignKey( # type: ignore[assignment]
|
|
19
|
-
"Examination", on_delete=models.CASCADE, null=True, blank=True
|
|
20
|
-
)
|
|
21
|
-
video = models.OneToOneField( # type: ignore[assignment]
|
|
17
|
+
patient = models.ForeignKey("Patient", on_delete=models.CASCADE, related_name="patient_examinations")
|
|
18
|
+
examination = models.ForeignKey("Examination", on_delete=models.CASCADE, null=True, blank=True)
|
|
19
|
+
video = models.OneToOneField(
|
|
22
20
|
"VideoFile",
|
|
23
21
|
on_delete=models.CASCADE,
|
|
24
22
|
null=True,
|
|
25
23
|
blank=True,
|
|
26
24
|
related_name="patient_examination",
|
|
27
25
|
)
|
|
28
|
-
|
|
26
|
+
|
|
29
27
|
objects = models.Manager()
|
|
30
|
-
|
|
28
|
+
|
|
31
29
|
date_start = models.DateField(null=True, blank=True)
|
|
32
30
|
date_end = models.DateField(null=True, blank=True)
|
|
33
31
|
hash = models.CharField(max_length=255, unique=True)
|
|
34
|
-
|
|
35
32
|
|
|
36
33
|
if TYPE_CHECKING:
|
|
37
34
|
patient: "models.ForeignKey[Patient]"
|
|
38
|
-
examination: "models.ForeignKey[Examination]"
|
|
39
|
-
video: "models.OneToOneField[VideoFile]"
|
|
35
|
+
examination: "models.ForeignKey[Examination|None]"
|
|
36
|
+
video: "models.OneToOneField[VideoFile|None]"
|
|
40
37
|
patient_findings: models.QuerySet["PatientFinding"]
|
|
41
38
|
indications: models.QuerySet["PatientExaminationIndication"]
|
|
42
39
|
raw_pdf_files: models.QuerySet["RawPdfFile"]
|
|
43
40
|
anonymexaminationreport_set: models.QuerySet["AnonymExaminationReport"]
|
|
44
41
|
anonymhistologyreport_set: models.QuerySet["AnonymHistologyReport"]
|
|
45
42
|
|
|
43
|
+
@property
|
|
44
|
+
def examination_safe(self):
|
|
45
|
+
if self.examination is None:
|
|
46
|
+
raise ValueError("Examination is not set for this PatientExamination.")
|
|
47
|
+
return self.examination
|
|
48
|
+
|
|
46
49
|
# report_files
|
|
47
50
|
class Meta:
|
|
48
51
|
verbose_name = "Patient Examination"
|
|
@@ -61,12 +64,8 @@ class PatientExamination(models.Model):
|
|
|
61
64
|
|
|
62
65
|
created = False
|
|
63
66
|
|
|
64
|
-
if PatientExamination.objects.filter(
|
|
65
|
-
patient__patient_hash=patient_hash, hash=examination_hash
|
|
66
|
-
).exists():
|
|
67
|
-
return PatientExamination.objects.get(
|
|
68
|
-
patient__patient_hash=patient_hash, hash=examination_hash
|
|
69
|
-
), created
|
|
67
|
+
if PatientExamination.objects.filter(patient__patient_hash=patient_hash, hash=examination_hash).exists():
|
|
68
|
+
return PatientExamination.objects.get(patient__patient_hash=patient_hash, hash=examination_hash), created
|
|
70
69
|
|
|
71
70
|
patient, created = Patient.get_or_create_pseudo_patient_by_hash(patient_hash)
|
|
72
71
|
if examination_name is not None:
|
|
@@ -74,9 +73,7 @@ class PatientExamination(models.Model):
|
|
|
74
73
|
else:
|
|
75
74
|
examination = None
|
|
76
75
|
|
|
77
|
-
patient_examination = cls.objects.create(
|
|
78
|
-
patient=patient, examination=examination, hash=examination_hash
|
|
79
|
-
)
|
|
76
|
+
patient_examination = cls.objects.create(patient=patient, examination=examination, hash=examination_hash)
|
|
80
77
|
|
|
81
78
|
patient_examination.save()
|
|
82
79
|
|
|
@@ -94,9 +91,7 @@ class PatientExamination(models.Model):
|
|
|
94
91
|
import random
|
|
95
92
|
import string
|
|
96
93
|
|
|
97
|
-
_hash = "DEFAULT_HASH_" + "".join(
|
|
98
|
-
random.choices(string.ascii_uppercase + string.digits, k=10)
|
|
99
|
-
)
|
|
94
|
+
_hash = "DEFAULT_HASH_" + "".join(random.choices(string.ascii_uppercase + string.digits, k=10))
|
|
100
95
|
|
|
101
96
|
return _hash
|
|
102
97
|
|
|
@@ -114,6 +109,8 @@ class PatientExamination(models.Model):
|
|
|
114
109
|
patient: Patient = self.patient
|
|
115
110
|
dob = patient.get_dob()
|
|
116
111
|
date_start = self.date_start
|
|
112
|
+
assert dob is not None
|
|
113
|
+
assert date_start is not None
|
|
117
114
|
return (date_start - dob).days // 365
|
|
118
115
|
|
|
119
116
|
def get_available_findings(self):
|
|
@@ -121,6 +118,7 @@ class PatientExamination(models.Model):
|
|
|
121
118
|
Returns all findings that are associated with the examination of this patient examination.
|
|
122
119
|
"""
|
|
123
120
|
|
|
121
|
+
assert self.examination is not None
|
|
124
122
|
return self.examination.get_available_findings()
|
|
125
123
|
|
|
126
124
|
def get_findings(self) -> models.QuerySet["PatientFinding"]:
|
|
@@ -139,13 +137,11 @@ class PatientExamination(models.Model):
|
|
|
139
137
|
def get_indication_choices(self) -> List["ExaminationIndicationClassificationChoice"]:
|
|
140
138
|
"""
|
|
141
139
|
Returns a list of indication choices associated with this patient examination.
|
|
142
|
-
|
|
140
|
+
|
|
143
141
|
Only includes indication choices that are not None.
|
|
144
142
|
"""
|
|
145
143
|
|
|
146
|
-
choices = [
|
|
147
|
-
_.indication_choice for _ in self.get_indications() if _.indication_choice is not None
|
|
148
|
-
]
|
|
144
|
+
choices = [_.indication_choice for _ in self.get_indications() if _.indication_choice is not None]
|
|
149
145
|
return choices
|
|
150
146
|
|
|
151
147
|
def get_or_create_patient_examination_by_id(self, pk: int) -> Optional["PatientExamination"]:
|
|
@@ -153,14 +149,14 @@ class PatientExamination(models.Model):
|
|
|
153
149
|
if not self.objects.filter(pk=pk).exists():
|
|
154
150
|
return None
|
|
155
151
|
else:
|
|
156
|
-
return self.objects.filter(pk=pk)
|
|
152
|
+
return self.objects.filter(pk=pk).first()
|
|
157
153
|
|
|
158
154
|
@property
|
|
159
155
|
def links(self) -> "RequirementLinks":
|
|
160
156
|
"""
|
|
161
157
|
Aggregates and returns all related model instances relevant for requirement evaluation
|
|
162
158
|
as a RequirementLinks object.
|
|
163
|
-
|
|
159
|
+
|
|
164
160
|
This includes:
|
|
165
161
|
- All findings associated with this examination
|
|
166
162
|
- All classifications and choices from those findings
|
|
@@ -168,12 +164,12 @@ class PatientExamination(models.Model):
|
|
|
168
164
|
- Examination indications and their choices
|
|
169
165
|
- Patient lab values
|
|
170
166
|
"""
|
|
171
|
-
from endoreg_db.utils.links.requirement_link import RequirementLinks
|
|
172
167
|
from endoreg_db.models.medical.patient.patient_lab_value import PatientLabValue
|
|
173
|
-
|
|
168
|
+
from endoreg_db.utils.links.requirement_link import RequirementLinks
|
|
169
|
+
|
|
174
170
|
# Get all PatientExaminationIndication instances linked to this PatientExamination
|
|
175
|
-
patient_exam_indications = self.indications.all()
|
|
176
|
-
|
|
171
|
+
patient_exam_indications = self.indications.all()
|
|
172
|
+
|
|
177
173
|
examination_indications_list: List["ExaminationIndication"] = []
|
|
178
174
|
indication_choices_list: List["ExaminationIndicationClassificationChoice"] = []
|
|
179
175
|
|
|
@@ -189,37 +185,37 @@ class PatientExamination(models.Model):
|
|
|
189
185
|
patient_lab_values = list(PatientLabValue.objects.filter(patient=self.patient))
|
|
190
186
|
|
|
191
187
|
current_examination = [self.examination] if self.examination else []
|
|
192
|
-
|
|
188
|
+
|
|
193
189
|
# Now aggregate findings data from all PatientFinding instances
|
|
194
190
|
findings_list = []
|
|
195
191
|
finding_classifications_list = []
|
|
196
192
|
finding_classification_choices_list = []
|
|
197
193
|
finding_interventions_list = []
|
|
198
194
|
patient_findings_list = []
|
|
199
|
-
|
|
195
|
+
|
|
200
196
|
for patient_finding in self.patient_findings.all():
|
|
201
197
|
# Add the PatientFinding itself
|
|
202
198
|
patient_findings_list.append(patient_finding)
|
|
203
|
-
|
|
199
|
+
|
|
204
200
|
# Add the base Finding
|
|
205
201
|
if patient_finding.finding:
|
|
206
202
|
findings_list.append(patient_finding.finding)
|
|
207
|
-
|
|
203
|
+
|
|
208
204
|
# Add all active classifications and their choices from this PatientFinding
|
|
209
205
|
for pf_classification in patient_finding.active_classifications:
|
|
210
206
|
if pf_classification.classification:
|
|
211
207
|
finding_classifications_list.append(pf_classification.classification)
|
|
212
208
|
if pf_classification.classification_choice:
|
|
213
209
|
finding_classification_choices_list.append(pf_classification.classification_choice)
|
|
214
|
-
|
|
215
|
-
# Add all active interventions from this PatientFinding
|
|
210
|
+
|
|
211
|
+
# Add all active interventions from this PatientFinding
|
|
216
212
|
for pf_intervention in patient_finding.active_interventions:
|
|
217
213
|
if pf_intervention.intervention:
|
|
218
214
|
finding_interventions_list.append(pf_intervention.intervention)
|
|
219
215
|
|
|
220
216
|
return RequirementLinks(
|
|
221
217
|
patient_examinations=[self], # Add the instance itself
|
|
222
|
-
examinations=current_examination,
|
|
218
|
+
examinations=current_examination, # Add the related Examination model
|
|
223
219
|
examination_indications=examination_indications_list,
|
|
224
220
|
examination_indication_classification_choices=indication_choices_list,
|
|
225
221
|
patient_lab_values=patient_lab_values,
|
|
@@ -231,18 +227,16 @@ class PatientExamination(models.Model):
|
|
|
231
227
|
finding_interventions=finding_interventions_list,
|
|
232
228
|
)
|
|
233
229
|
|
|
234
|
-
def create_finding(self, finding:"Finding") -> "PatientFinding":
|
|
230
|
+
def create_finding(self, finding: "Finding") -> "PatientFinding":
|
|
235
231
|
"""
|
|
236
232
|
Adds a finding to this patient examination.
|
|
237
233
|
"""
|
|
238
234
|
from .patient_finding import PatientFinding
|
|
239
235
|
|
|
240
|
-
examination
|
|
241
|
-
assert examination
|
|
236
|
+
examination = self.examination
|
|
237
|
+
assert examination is not None
|
|
242
238
|
|
|
243
|
-
patient_finding = PatientFinding.objects.create(
|
|
244
|
-
patient_examination=self, finding=finding
|
|
245
|
-
)
|
|
239
|
+
patient_finding = PatientFinding.objects.create(patient_examination=self, finding=finding)
|
|
246
240
|
|
|
247
241
|
patient_finding.save()
|
|
248
242
|
|