endoreg-db 0.8.6.1__py3-none-any.whl → 0.8.8.9__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 +2 -11
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +3 -3
- 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 +114 -14
- endoreg_db/data/examination/time-type/data.yaml +0 -3
- endoreg_db/data/examination_indication/endoscopy.yaml +108 -173
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +0 -70
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +33 -37
- 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/{yes_no_na.yaml → 00_generic.yaml} +5 -1
- endoreg_db/data/finding_classification_choice/{examination_setting_generic_types.yaml → 00_generic_baseline.yaml} +10 -2
- endoreg_db/data/finding_classification_choice/{complication_generic_types.yaml → 00_generic_complication.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{histology.yaml → 00_generic_histology.yaml} +1 -4
- endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
- endoreg_db/data/finding_classification_choice/{bowel_preparation.yaml → 02_colonoscopy_bowel_preparation.yaml} +1 -30
- endoreg_db/data/finding_classification_choice/{colonoscopy_not_complete_reason.yaml → 02_colonoscopy_generic.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{histology_polyp.yaml → 02_colonoscopy_histology.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{colonoscopy_location.yaml → 02_colonoscopy_location.yaml} +23 -4
- 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/{colon_lesion_paris.yaml → 02_colonoscopy_polyp_morphology.yaml} +26 -8
- endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
- endoreg_db/data/finding_classification_type/{colonoscopy_basic.yaml → 00_generic.yaml} +18 -13
- 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_type/data.yaml +8 -12
- 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/coloreg_colon_polyp.yaml +49 -0
- endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +29 -12
- endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
- endoreg_db/data/requirement_set/{endoscopy_bleeding_risk.yaml → 02_endoscopy_bleeding_risk.yaml} +0 -6
- endoreg_db/data/requirement_set/90_coloreg.yaml +190 -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 +4 -2
- endoreg_db/forms/examination_form.py +1 -1
- endoreg_db/helpers/data_loader.py +125 -53
- endoreg_db/helpers/default_objects.py +116 -81
- 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 +81 -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 +43 -0
- endoreg_db/import_files/context/validate_directories.py +56 -0
- endoreg_db/import_files/file_storage/__init__.py +15 -0
- endoreg_db/import_files/file_storage/create_report_file.py +76 -0
- endoreg_db/import_files/file_storage/create_video_file.py +75 -0
- endoreg_db/import_files/file_storage/sensitive_meta_storage.py +39 -0
- endoreg_db/import_files/file_storage/state_management.py +400 -0
- endoreg_db/import_files/file_storage/storage.py +36 -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 +94 -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/processing/video_processing/video_cleanup_on_error.py +119 -0
- endoreg_db/import_files/pseudonymization/fake.py +52 -0
- endoreg_db/import_files/pseudonymization/k_anonymity.py +182 -0
- endoreg_db/import_files/pseudonymization/k_pseudonymity.py +128 -0
- endoreg_db/import_files/report_import_service.py +141 -0
- endoreg_db/import_files/video_import_service.py +150 -0
- 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_report.py +130 -65
- endoreg_db/management/commands/import_video.py +9 -10
- endoreg_db/management/commands/import_video_with_classification.py +2 -2
- endoreg_db/management/commands/list_routes.py +18 -0
- endoreg_db/management/commands/load_ai_model_data.py +5 -5
- endoreg_db/management/commands/load_ai_model_label_data.py +9 -7
- endoreg_db/management/commands/load_base_db_data.py +5 -134
- endoreg_db/management/commands/load_center_data.py +12 -12
- endoreg_db/management/commands/load_contraindication_data.py +14 -16
- endoreg_db/management/commands/load_disease_classification_choices_data.py +15 -18
- endoreg_db/management/commands/load_disease_classification_data.py +15 -18
- endoreg_db/management/commands/load_disease_data.py +25 -28
- endoreg_db/management/commands/load_endoscope_data.py +20 -27
- endoreg_db/management/commands/load_event_data.py +14 -16
- endoreg_db/management/commands/load_examination_data.py +31 -44
- endoreg_db/management/commands/load_examination_indication_data.py +20 -21
- endoreg_db/management/commands/load_finding_data.py +52 -80
- endoreg_db/management/commands/load_information_source.py +21 -23
- endoreg_db/management/commands/load_lab_value_data.py +17 -26
- endoreg_db/management/commands/load_medication_data.py +13 -12
- endoreg_db/management/commands/load_organ_data.py +15 -19
- endoreg_db/management/commands/load_pdf_type_data.py +19 -18
- endoreg_db/management/commands/load_profession_data.py +14 -17
- endoreg_db/management/commands/load_qualification_data.py +20 -23
- endoreg_db/management/commands/load_report_reader_flag_data.py +17 -19
- endoreg_db/management/commands/load_requirement_data.py +62 -39
- endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
- endoreg_db/management/commands/load_risk_data.py +7 -6
- endoreg_db/management/commands/load_shift_data.py +20 -23
- endoreg_db/management/commands/load_tag_data.py +8 -11
- endoreg_db/management/commands/load_unit_data.py +17 -19
- endoreg_db/management/commands/setup_endoreg_db.py +3 -3
- endoreg_db/management/commands/start_filewatcher.py +46 -37
- endoreg_db/management/commands/storage_management.py +271 -203
- endoreg_db/management/commands/validate_video_files.py +1 -5
- endoreg_db/migrations/0001_initial.py +297 -250
- 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 +129 -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 +8 -9
- endoreg_db/models/label/annotation/image_classification.py +10 -9
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +23 -28
- 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 +98 -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 +194 -194
- endoreg_db/models/media/pdf/report_file.py +25 -29
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +55 -47
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
- endoreg_db/models/media/processing_history/__init__.py +5 -0
- endoreg_db/models/media/processing_history/processing_history.py +96 -0
- endoreg_db/models/media/video/__init__.py +1 -0
- endoreg_db/models/media/video/create_from_file.py +139 -77
- endoreg_db/models/media/video/pipe_2.py +8 -9
- endoreg_db/models/media/video/video_file.py +174 -112
- 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 +113 -61
- 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/README.md +1 -0
- 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 +39 -20
- endoreg_db/models/medical/examination/examination_indication.py +30 -95
- endoreg_db/models/medical/examination/examination_time.py +23 -8
- 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 +32 -40
- endoreg_db/models/medical/finding/finding_classification.py +42 -72
- endoreg_db/models/medical/finding/finding_intervention.py +25 -22
- endoreg_db/models/medical/finding/finding_type.py +13 -12
- endoreg_db/models/medical/hardware/endoscope.py +26 -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 +6 -6
- 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 +125 -18
- endoreg_db/models/metadata/pdf_meta.py +31 -24
- endoreg_db/models/metadata/sensitive_meta.py +105 -85
- endoreg_db/models/metadata/sensitive_meta_logic.py +198 -103
- 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 +50 -29
- 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/report/report.py +6 -0
- endoreg_db/models/requirement/requirement.py +329 -361
- 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 +103 -112
- 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 +49 -51
- endoreg_db/models/state/label_video_segment.py +9 -0
- endoreg_db/models/state/raw_pdf.py +101 -68
- endoreg_db/models/state/sensitive_meta.py +6 -2
- endoreg_db/models/state/video.py +110 -90
- endoreg_db/models/upload_job.py +35 -34
- endoreg_db/models/utils.py +28 -25
- endoreg_db/queries/__init__.py +3 -1
- endoreg_db/root_urls.py +21 -2
- endoreg_db/schemas/examination_evaluation.py +1 -1
- endoreg_db/serializers/__init__.py +2 -10
- endoreg_db/serializers/anonymization.py +18 -10
- endoreg_db/serializers/label_video_segment/label_video_segment.py +2 -29
- endoreg_db/serializers/meta/__init__.py +1 -6
- endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
- endoreg_db/serializers/misc/file_overview.py +11 -99
- endoreg_db/serializers/misc/sensitive_patient_data.py +50 -26
- endoreg_db/serializers/patient_examination/patient_examination.py +3 -3
- endoreg_db/serializers/pdf/anony_text_validation.py +39 -23
- endoreg_db/serializers/requirements/requirement_sets.py +92 -22
- endoreg_db/serializers/video/segmentation.py +2 -1
- endoreg_db/serializers/video/video_file_list.py +65 -34
- endoreg_db/serializers/video/video_processing_history.py +20 -5
- endoreg_db/services/__old/pdf_import.py +1487 -0
- endoreg_db/services/__old/video_import.py +1306 -0
- endoreg_db/services/anonymization.py +128 -89
- endoreg_db/services/lookup_service.py +65 -52
- endoreg_db/services/lookup_store.py +2 -2
- endoreg_db/services/pdf_import.py +0 -1382
- endoreg_db/services/report_import.py +10 -0
- endoreg_db/services/video_import.py +6 -1255
- endoreg_db/tasks/upload_tasks.py +79 -70
- endoreg_db/tasks/video_ingest.py +8 -4
- endoreg_db/urls/__init__.py +5 -32
- endoreg_db/urls/ai.py +32 -0
- endoreg_db/urls/media.py +121 -83
- 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 +142 -40
- endoreg_db/utils/defaults/set_default_center.py +32 -0
- endoreg_db/utils/names.py +22 -16
- endoreg_db/utils/paths.py +110 -46
- endoreg_db/utils/permissions.py +2 -1
- endoreg_db/utils/pipelines/Readme.md +1 -1
- endoreg_db/utils/pipelines/process_video_dir.py +1 -1
- endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +655 -0
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +97 -0
- 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 +85 -183
- endoreg_db/views/ai/__init__.py +8 -0
- endoreg_db/views/ai/label.py +155 -0
- endoreg_db/views/anonymization/media_management.py +202 -166
- endoreg_db/views/anonymization/overview.py +99 -67
- endoreg_db/views/anonymization/validate.py +182 -44
- endoreg_db/views/media/__init__.py +7 -20
- endoreg_db/views/media/pdf_media.py +197 -174
- endoreg_db/views/media/sensitive_metadata.py +193 -138
- endoreg_db/views/media/video_media.py +89 -82
- endoreg_db/views/meta/__init__.py +0 -8
- endoreg_db/views/misc/__init__.py +1 -7
- endoreg_db/views/misc/upload_views.py +94 -93
- endoreg_db/views/patient/patient.py +5 -4
- endoreg_db/views/report/__init__.py +5 -7
- endoreg_db/views/{pdf → report}/reimport.py +22 -22
- endoreg_db/views/{pdf/pdf_stream.py → report/report_stream.py} +46 -39
- endoreg_db/views/requirement/evaluate.py +188 -187
- endoreg_db/views/requirement/lookup.py +17 -3
- endoreg_db/views/requirement/lookup_store.py +22 -90
- endoreg_db/views/requirement/requirement_utils.py +89 -0
- endoreg_db/views/video/__init__.py +23 -24
- endoreg_db/views/video/correction.py +201 -172
- endoreg_db/views/video/reimport.py +1 -1
- endoreg_db/views/{media/video_segments.py → video/segments_crud.py} +77 -40
- endoreg_db/views/video/{video_meta.py → video_meta_stats.py} +2 -2
- endoreg_db/views/video/video_stream.py +7 -8
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/METADATA +7 -3
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/RECORD +391 -413
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/WHEEL +1 -1
- endoreg_db/data/finding/anatomy_colon.yaml +0 -128
- endoreg_db/data/finding/colonoscopy.yaml +0 -40
- endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +0 -56
- endoreg_db/data/finding/complication.yaml +0 -16
- endoreg_db/data/finding/data.yaml +0 -105
- endoreg_db/data/finding/examination_setting.yaml +0 -16
- endoreg_db/data/finding/medication_related.yaml +0 -18
- endoreg_db/data/finding/outcome.yaml +0 -12
- endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +0 -95
- endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +0 -22
- endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +0 -25
- endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +0 -68
- endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +0 -80
- endoreg_db/data/finding_classification/colonoscopy_lst.yaml +0 -21
- endoreg_db/data/finding_classification/colonoscopy_nice.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_paris.yaml +0 -26
- endoreg_db/data/finding_classification/colonoscopy_sano.yaml +0 -22
- endoreg_db/data/finding_classification/colonoscopy_summary.yaml +0 -53
- endoreg_db/data/finding_classification/complication_generic.yaml +0 -25
- endoreg_db/data/finding_classification/examination_setting_generic.yaml +0 -40
- endoreg_db/data/finding_classification/histology_colo.yaml +0 -51
- endoreg_db/data/finding_classification/intervention_required.yaml +0 -26
- endoreg_db/data/finding_classification/medication_related.yaml +0 -23
- endoreg_db/data/finding_classification/visualized.yaml +0 -33
- endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
- endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
- endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
- endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +0 -15
- endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +0 -17
- endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
- endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +0 -14
- endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
- endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +0 -82
- endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
- endoreg_db/data/finding_classification_choice/outcome.yaml +0 -19
- endoreg_db/data/finding_intervention/endoscopy.yaml +0 -43
- endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
- endoreg_db/data/finding_intervention/endoscopy_egd.yaml +0 -128
- endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +0 -32
- endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +0 -9
- endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +0 -36
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +0 -79
- endoreg_db/data/requirement/age.yaml +0 -26
- endoreg_db/data/requirement/gender.yaml +0 -25
- endoreg_db/management/commands/init_default_ai_model.py +0 -112
- endoreg_db/management/commands/reset_celery_schedule.py +0 -9
- endoreg_db/management/commands/validate_video.py +0 -204
- endoreg_db/migrations/0002_add_video_correction_models.py +0 -52
- endoreg_db/migrations/0003_add_center_display_name.py +0 -30
- endoreg_db/models/administration/permissions/__init__.py +0 -44
- 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/renames.yml +0 -8
- endoreg_db/serializers/_old/raw_pdf_meta_validation.py +0 -223
- endoreg_db/serializers/_old/raw_video_meta_validation.py +0 -179
- endoreg_db/serializers/_old/video.py +0 -71
- endoreg_db/serializers/meta/pdf_file_meta_extraction.py +0 -115
- endoreg_db/serializers/meta/report_meta.py +0 -53
- endoreg_db/serializers/report/__init__.py +0 -9
- endoreg_db/serializers/report/mixins.py +0 -45
- endoreg_db/serializers/report/report.py +0 -105
- endoreg_db/serializers/report/report_list.py +0 -22
- endoreg_db/serializers/report/secure_file_url.py +0 -26
- endoreg_db/serializers/video/video_metadata.py +0 -105
- endoreg_db/services/requirements_object.py +0 -147
- endoreg_db/services/storage_aware_video_processor.py +0 -344
- endoreg_db/urls/files.py +0 -6
- endoreg_db/urls/label_video_segment_validate.py +0 -33
- endoreg_db/urls/label_video_segments.py +0 -46
- 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/utils/requirement_operator_logic/model_evaluators.py +0 -368
- endoreg_db/views/label/__init__.py +0 -5
- endoreg_db/views/label/label.py +0 -15
- endoreg_db/views/label_video_segment/__init__.py +0 -16
- endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +0 -44
- endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +0 -50
- endoreg_db/views/label_video_segment/label_video_segment.py +0 -77
- endoreg_db/views/label_video_segment/label_video_segment_by_label.py +0 -174
- endoreg_db/views/label_video_segment/label_video_segment_detail.py +0 -73
- endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +0 -46
- endoreg_db/views/label_video_segment/validate.py +0 -226
- endoreg_db/views/media/segments.py +0 -71
- endoreg_db/views/meta/available_files_list.py +0 -146
- endoreg_db/views/meta/report_meta.py +0 -53
- endoreg_db/views/meta/sensitive_meta_detail.py +0 -148
- endoreg_db/views/misc/secure_file_serving_view.py +0 -80
- endoreg_db/views/misc/secure_file_url_view.py +0 -84
- endoreg_db/views/misc/secure_url_validate.py +0 -79
- endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +0 -164
- endoreg_db/views/patient_finding_location/__init__.py +0 -5
- endoreg_db/views/patient_finding_location/pfl_create.py +0 -70
- endoreg_db/views/patient_finding_morphology/__init__.py +0 -5
- endoreg_db/views/patient_finding_morphology/pfm_create.py +0 -70
- endoreg_db/views/pdf/__init__.py +0 -8
- 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/segmentation.py +0 -274
- endoreg_db/views/video/task_status.py +0 -49
- endoreg_db/views/video/timeline.py +0 -46
- endoreg_db/views/video/video_analyze.py +0 -52
- endoreg_db/views.py +0 -0
- /endoreg_db/data/requirement/{colonoscopy_baseline_austria.yaml → old/colonoscopy_baseline_austria.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_cardiovascular.yaml → old/disease_cardiovascular.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_classification_choice_cardiovascular.yaml → old/disease_classification_choice_cardiovascular.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_hepatology.yaml → old/disease_hepatology.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_misc.yaml → old/disease_misc.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_renal.yaml → old/disease_renal.yaml} +0 -0
- /endoreg_db/data/requirement/{endoscopy_bleeding_risk.yaml → old/endoscopy_bleeding_risk.yaml} +0 -0
- /endoreg_db/data/requirement/{event_cardiology.yaml → old/event_cardiology.yaml} +0 -0
- /endoreg_db/data/requirement/{event_requirements.yaml → old/event_requirements.yaml} +0 -0
- /endoreg_db/data/requirement/{finding_colon_polyp.yaml → old/finding_colon_polyp.yaml} +0 -0
- /endoreg_db/{migrations/__init__.py → data/requirement/old/gender.yaml} +0 -0
- /endoreg_db/data/requirement/{lab_value.yaml → old/lab_value.yaml} +0 -0
- /endoreg_db/data/requirement/{medication.yaml → old/medication.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{age.yaml → _old/age.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{lab_operators.yaml → _old/lab_operators.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{model_operators.yaml → _old/model_operators.yaml} +0 -0
- /endoreg_db/{models/media/video/refactor_plan.md → import_files/pseudonymization/__init__.py} +0 -0
- /endoreg_db/{models/media/video/video_file_frames.py → import_files/pseudonymization/pseudonymize.py} +0 -0
- /endoreg_db/models/{metadata/frame_ocr_result.py → report/__init__.py} +0 -0
- /endoreg_db/{urls/sensitive_meta.py → models/report/images.py} +0 -0
- /endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py} +0 -0
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
from django.db import models
|
|
3
|
-
from faker import Faker
|
|
1
|
+
import logging
|
|
4
2
|
import random
|
|
5
|
-
from datetime import datetime
|
|
3
|
+
from datetime import date, datetime
|
|
6
4
|
from typing import TYPE_CHECKING, List, Optional # Added List
|
|
7
|
-
|
|
5
|
+
|
|
6
|
+
from django.db import models
|
|
8
7
|
from django.utils import timezone # Add this import
|
|
8
|
+
from faker import Faker
|
|
9
|
+
|
|
10
|
+
from ..person import Person
|
|
9
11
|
|
|
10
12
|
# Import RequirementLinks and Disease for the links property
|
|
11
13
|
|
|
@@ -13,23 +15,22 @@ logger = logging.getLogger("patient")
|
|
|
13
15
|
|
|
14
16
|
if TYPE_CHECKING:
|
|
15
17
|
from endoreg_db.models import (
|
|
18
|
+
AnonymExaminationReport,
|
|
19
|
+
AnonymHistologyReport,
|
|
20
|
+
Center,
|
|
16
21
|
ExaminationIndication,
|
|
17
|
-
PatientEvent, PatientDisease,
|
|
18
22
|
Gender,
|
|
23
|
+
PatientDisease,
|
|
24
|
+
PatientEvent,
|
|
19
25
|
PatientExamination,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
AnonymHistologyReport, RawPdfFile,
|
|
23
|
-
# Added for links property
|
|
24
|
-
Medication,
|
|
26
|
+
PatientExternalID,
|
|
27
|
+
PatientLabValue,
|
|
25
28
|
PatientMedication,
|
|
26
|
-
|
|
27
|
-
MedicationIntakeTime,
|
|
28
|
-
PatientLabValue, # Assuming self.lab_values are PatientLabValue instances
|
|
29
|
-
LabValue # If RequirementLinks expects actual LabValue instances
|
|
29
|
+
RawPdfFile,
|
|
30
30
|
)
|
|
31
31
|
from endoreg_db.utils.links.requirement_link import RequirementLinks
|
|
32
32
|
|
|
33
|
+
|
|
33
34
|
class Patient(Person):
|
|
34
35
|
"""
|
|
35
36
|
A class representing a patient.
|
|
@@ -44,31 +45,55 @@ class Patient(Person):
|
|
|
44
45
|
|
|
45
46
|
"""
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
gender = models.ForeignKey( # type: ignore[assignment]
|
|
48
|
+
first_name = models.CharField(max_length=100)
|
|
49
|
+
last_name = models.CharField(max_length=100)
|
|
50
|
+
dob = models.DateField(null=True, blank=True)
|
|
51
|
+
gender = models.ForeignKey(
|
|
52
52
|
"Gender", on_delete=models.SET_NULL, null=True, blank=True
|
|
53
53
|
)
|
|
54
|
-
center = models.ForeignKey(
|
|
54
|
+
center = models.ForeignKey(
|
|
55
55
|
"Center", on_delete=models.SET_NULL, null=True, blank=True
|
|
56
56
|
)
|
|
57
57
|
patient_hash = models.CharField(max_length=255, blank=True, null=True)
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
objects = models.Manager() # Default manager
|
|
60
60
|
|
|
61
61
|
if TYPE_CHECKING:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
62
|
+
from django.db.models.manager import RelatedManager
|
|
63
|
+
|
|
64
|
+
first_name: models.CharField[str]
|
|
65
|
+
last_name: models.CharField[str]
|
|
66
|
+
dob: models.DateField[date | None]
|
|
67
|
+
gender: models.ForeignKey["Gender | None"]
|
|
68
|
+
center: models.ForeignKey["Center | None"]
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def events(self) -> RelatedManager[PatientEvent]: ...
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def diseases(self) -> RelatedManager[PatientDisease]: ...
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def patient_examinations(self) -> RelatedManager[PatientExamination]: ...
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def anonymexaminationreport_set(
|
|
81
|
+
self,
|
|
82
|
+
) -> RelatedManager[AnonymExaminationReport]: ...
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def anonymhistologyreport_set(
|
|
86
|
+
self,
|
|
87
|
+
) -> RelatedManager[AnonymHistologyReport]: ...
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def external_ids(self) -> RelatedManager[PatientExternalID]: ...
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def patientmedication_set(self) -> RelatedManager[PatientMedication]: ...
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def lab_values(self) -> RelatedManager[PatientLabValue]: ...
|
|
72
97
|
|
|
73
98
|
def __str__(self):
|
|
74
99
|
return f"{self.first_name} {self.last_name} ({self.dob})"
|
|
@@ -77,12 +102,13 @@ class Patient(Person):
|
|
|
77
102
|
def get_or_create_pseudo_patient_by_hash(
|
|
78
103
|
cls,
|
|
79
104
|
patient_hash: str,
|
|
80
|
-
center: "Center" = None,
|
|
81
|
-
gender: "Gender | str" = None, # Allow string type hint
|
|
82
|
-
birth_month: int = None,
|
|
83
|
-
birth_year: int = None,
|
|
105
|
+
center: Optional["Center"] = None,
|
|
106
|
+
gender: Optional["Gender | str"] = None, # Allow string type hint
|
|
107
|
+
birth_month: Optional[int] = None,
|
|
108
|
+
birth_year: Optional[int] = None,
|
|
84
109
|
):
|
|
85
|
-
from endoreg_db.utils import
|
|
110
|
+
from endoreg_db.utils import create_mock_patient_name, random_day_by_year
|
|
111
|
+
|
|
86
112
|
from ....other import Gender # Import Gender model
|
|
87
113
|
|
|
88
114
|
created = False
|
|
@@ -130,9 +156,8 @@ class Patient(Person):
|
|
|
130
156
|
|
|
131
157
|
return patient, created
|
|
132
158
|
|
|
133
|
-
def get_dob(self) ->
|
|
134
|
-
|
|
135
|
-
return dob
|
|
159
|
+
def get_dob(self) -> date | None:
|
|
160
|
+
return self.dob
|
|
136
161
|
|
|
137
162
|
def get_patient_examinations(self): # field: self.patient_examinations
|
|
138
163
|
"""Returns all patient examinations for this patient ordered by date (most recent is first)."""
|
|
@@ -146,10 +171,9 @@ class Patient(Person):
|
|
|
146
171
|
save: bool = True,
|
|
147
172
|
) -> "PatientExamination":
|
|
148
173
|
"""Creates a patient examination for this patient."""
|
|
174
|
+
from ....medical import Examination, PatientExamination
|
|
149
175
|
|
|
150
176
|
if examination_name_str:
|
|
151
|
-
from ....medical import Examination, PatientExamination
|
|
152
|
-
|
|
153
177
|
examination = Examination.objects.get(name=examination_name_str)
|
|
154
178
|
patient_examination = PatientExamination(
|
|
155
179
|
patient=self,
|
|
@@ -168,42 +192,16 @@ class Patient(Person):
|
|
|
168
192
|
|
|
169
193
|
return patient_examination
|
|
170
194
|
|
|
171
|
-
def create_examination_by_indication(
|
|
172
|
-
self, indication: "ExaminationIndication", date_start: datetime = None, date_end: datetime = None
|
|
173
|
-
):
|
|
174
|
-
from ....medical import (
|
|
175
|
-
PatientExaminationIndication,
|
|
176
|
-
PatientExamination,
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
examination = indication.get_examination()
|
|
180
|
-
|
|
181
|
-
patient_examination = PatientExamination.objects.create(
|
|
182
|
-
patient=self,
|
|
183
|
-
examination=examination,
|
|
184
|
-
date_start=date_start,
|
|
185
|
-
date_end=date_end,
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
patient_examination.save()
|
|
189
|
-
|
|
190
|
-
patient_examination_indication = PatientExaminationIndication.objects.create(
|
|
191
|
-
patient_examination=patient_examination, examination_indication=indication
|
|
192
|
-
)
|
|
193
|
-
patient_examination_indication.save()
|
|
194
|
-
|
|
195
|
-
return patient_examination, patient_examination_indication
|
|
196
|
-
|
|
197
195
|
def create_event(
|
|
198
196
|
self,
|
|
199
197
|
event_name_str: str,
|
|
200
|
-
date_start: datetime = None,
|
|
201
|
-
date_end: datetime = None,
|
|
202
|
-
description: str = None,
|
|
198
|
+
date_start: Optional[datetime] = None,
|
|
199
|
+
date_end: Optional[datetime] = None,
|
|
200
|
+
description: Optional[str] = None,
|
|
203
201
|
):
|
|
204
202
|
"""
|
|
205
203
|
Creates a patient event with the specified event name and start date.
|
|
206
|
-
|
|
204
|
+
|
|
207
205
|
If no start date is provided, the current datetime is used. Returns the created PatientEvent instance.
|
|
208
206
|
"""
|
|
209
207
|
from ....medical import Event, PatientEvent
|
|
@@ -223,17 +221,18 @@ class Patient(Person):
|
|
|
223
221
|
|
|
224
222
|
def create_examination_by_pdf(self, pdf: "RawPdfFile"):
|
|
225
223
|
"""
|
|
226
|
-
Creates a patient examination and associates it with the provided
|
|
227
|
-
|
|
228
|
-
The examination is created for this patient, saved, and linked to the given RawPdfFile instance. The
|
|
229
|
-
|
|
224
|
+
Creates a patient examination and associates it with the provided report report file.
|
|
225
|
+
|
|
226
|
+
The examination is created for this patient, saved, and linked to the given RawPdfFile instance. The report's examination field is updated and saved. Returns the created examination instance.
|
|
227
|
+
|
|
230
228
|
Args:
|
|
231
229
|
pdf: The RawPdfFile to associate with the new examination.
|
|
232
|
-
|
|
230
|
+
|
|
233
231
|
Returns:
|
|
234
232
|
The created PatientExamination instance.
|
|
235
233
|
"""
|
|
236
234
|
from ....medical import PatientExamination
|
|
235
|
+
|
|
237
236
|
patient_examination = PatientExamination(patient=self)
|
|
238
237
|
patient_examination.save()
|
|
239
238
|
pdf.examination = patient_examination
|
|
@@ -346,11 +345,17 @@ class Patient(Person):
|
|
|
346
345
|
last_name=last_name,
|
|
347
346
|
dob=dob,
|
|
348
347
|
gender=gender,
|
|
349
|
-
center=center_obj,
|
|
348
|
+
center=center_obj, # Assign the center object
|
|
350
349
|
)
|
|
351
350
|
# No need to call save() again after create()
|
|
352
351
|
return patient
|
|
353
352
|
|
|
353
|
+
@property
|
|
354
|
+
def age_safe(self) -> int:
|
|
355
|
+
age = self.age()
|
|
356
|
+
assert age is not None, "Patient age is not set."
|
|
357
|
+
return age
|
|
358
|
+
|
|
354
359
|
def age(self) -> int | None:
|
|
355
360
|
"""
|
|
356
361
|
Get the age of the patient.
|
|
@@ -358,7 +363,9 @@ class Patient(Person):
|
|
|
358
363
|
:return: The age of the patient.
|
|
359
364
|
"""
|
|
360
365
|
# calculate correct age based on current date including day and month
|
|
361
|
-
current_date =
|
|
366
|
+
current_date = (
|
|
367
|
+
timezone.now().date()
|
|
368
|
+
) # Use timezone.now() here too for consistency
|
|
362
369
|
dob = self.dob
|
|
363
370
|
# Ensure dob is not None before calculation
|
|
364
371
|
if dob:
|
|
@@ -385,7 +392,9 @@ class Patient(Person):
|
|
|
385
392
|
date = timezone.now() # Use timezone.now() instead of datetime.now()
|
|
386
393
|
# Ensure the provided date is timezone-aware if it's not None
|
|
387
394
|
elif timezone.is_naive(date):
|
|
388
|
-
logger.warning(
|
|
395
|
+
logger.warning(
|
|
396
|
+
f"Received naive datetime {date} for PatientLabSample. Making it timezone-aware using current timezone."
|
|
397
|
+
)
|
|
389
398
|
date = timezone.make_aware(date, timezone.get_current_timezone())
|
|
390
399
|
|
|
391
400
|
if isinstance(sample_type, str):
|
|
@@ -411,50 +420,70 @@ class Patient(Person):
|
|
|
411
420
|
as a RequirementLinks object. For a Patient, this includes their diseases, associated classification choices,
|
|
412
421
|
all their lab values, and medication information.
|
|
413
422
|
"""
|
|
414
|
-
from endoreg_db.
|
|
415
|
-
|
|
416
|
-
|
|
423
|
+
from endoreg_db.models.medical.disease import (
|
|
424
|
+
Disease,
|
|
425
|
+
DiseaseClassificationChoice,
|
|
426
|
+
)
|
|
427
|
+
|
|
417
428
|
# Imports for medication related models
|
|
418
429
|
from endoreg_db.models.medical.medication.medication import Medication
|
|
419
|
-
from endoreg_db.models.medical.medication.medication_indication import
|
|
420
|
-
|
|
430
|
+
from endoreg_db.models.medical.medication.medication_indication import (
|
|
431
|
+
MedicationIndication,
|
|
432
|
+
)
|
|
433
|
+
from endoreg_db.models.medical.medication.medication_intake_time import (
|
|
434
|
+
MedicationIntakeTime,
|
|
435
|
+
)
|
|
436
|
+
from endoreg_db.utils.links.requirement_link import RequirementLinks
|
|
437
|
+
|
|
421
438
|
# PatientMedication objects are retrieved via self.patientmedication_set
|
|
422
439
|
# PatientLabValue objects are retrieved via self.lab_values
|
|
423
440
|
|
|
424
|
-
patient_disease_instances = list(
|
|
441
|
+
patient_disease_instances = list(
|
|
442
|
+
self.diseases.all()
|
|
443
|
+
) # These are PatientDisease model instances
|
|
425
444
|
actual_diseases: List[Disease] = []
|
|
426
445
|
all_classification_choices: List[DiseaseClassificationChoice] = []
|
|
427
446
|
|
|
428
447
|
for pd_instance in patient_disease_instances:
|
|
429
|
-
if pd_instance.disease:
|
|
448
|
+
if pd_instance.disease: # pd_instance.disease is a Disease instance
|
|
430
449
|
actual_diseases.append(pd_instance.disease)
|
|
431
|
-
all_classification_choices.extend(
|
|
432
|
-
|
|
450
|
+
all_classification_choices.extend(
|
|
451
|
+
list(pd_instance.classification_choices.all())
|
|
452
|
+
)
|
|
453
|
+
|
|
433
454
|
# Assuming self.lab_values is a related manager for PatientLabValue instances
|
|
434
|
-
patient_lab_value_instances = list(
|
|
455
|
+
patient_lab_value_instances = list(
|
|
456
|
+
self.lab_values.all()
|
|
457
|
+
) # These are PatientLabValue model instances
|
|
435
458
|
|
|
436
459
|
# Medication information
|
|
437
460
|
# self.patientmedication_set gives a QuerySet of PatientMedication
|
|
438
|
-
patient_medication_instances = list(self.patientmedication_set.all())
|
|
439
|
-
|
|
461
|
+
patient_medication_instances = list(self.patientmedication_set.all())
|
|
462
|
+
|
|
440
463
|
actual_medications: List[Medication] = []
|
|
441
464
|
med_indications: List[MedicationIndication] = []
|
|
442
465
|
med_intake_times: List[MedicationIntakeTime] = []
|
|
443
466
|
|
|
444
467
|
for pm_instance in patient_medication_instances:
|
|
445
|
-
if
|
|
468
|
+
if (
|
|
469
|
+
pm_instance.medication
|
|
470
|
+
): # pm_instance.medication is a Medication instance
|
|
446
471
|
actual_medications.append(pm_instance.medication)
|
|
447
|
-
if
|
|
472
|
+
if (
|
|
473
|
+
pm_instance.medication_indication
|
|
474
|
+
): # pm_instance.medication_indication is a MedicationIndication instance
|
|
448
475
|
med_indications.append(pm_instance.medication_indication)
|
|
449
|
-
med_intake_times.extend(
|
|
476
|
+
med_intake_times.extend(
|
|
477
|
+
list(pm_instance.intake_times.all())
|
|
478
|
+
) # pm_instance.intake_times is a ManyRelatedManager for MedicationIntakeTime
|
|
450
479
|
|
|
451
480
|
return RequirementLinks(
|
|
452
|
-
diseases=list(set(actual_diseases)),
|
|
453
|
-
patient_diseases=patient_disease_instances,
|
|
454
|
-
disease_classification_choices=list(set(all_classification_choices)),
|
|
481
|
+
diseases=list(set(actual_diseases)),
|
|
482
|
+
patient_diseases=patient_disease_instances,
|
|
483
|
+
disease_classification_choices=list(set(all_classification_choices)),
|
|
455
484
|
patient_lab_values=patient_lab_value_instances,
|
|
456
|
-
medications=list(set(actual_medications)),
|
|
485
|
+
medications=list(set(actual_medications)),
|
|
457
486
|
patient_medications=patient_medication_instances,
|
|
458
487
|
medication_indications=list(set(med_indications)),
|
|
459
|
-
medication_intake_times=list(set(med_intake_times))
|
|
488
|
+
medication_intake_times=list(set(med_intake_times)),
|
|
460
489
|
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
from django.db import models # Add this import
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from endoreg_db.models import (
|
|
7
|
+
Patient,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PatientExternalID(models.Model):
|
|
12
|
+
"""
|
|
13
|
+
A class representing the identifier of external datasources.
|
|
14
|
+
Attributes:
|
|
15
|
+
external_id (str): The external ID value.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
external_id: models.CharField = models.CharField(max_length=255)
|
|
19
|
+
patient = models.ForeignKey(
|
|
20
|
+
"Patient",
|
|
21
|
+
on_delete=models.CASCADE,
|
|
22
|
+
related_name="external_ids",
|
|
23
|
+
)
|
|
24
|
+
origin = models.CharField(max_length=255)
|
|
25
|
+
|
|
26
|
+
class Meta:
|
|
27
|
+
constraints = [
|
|
28
|
+
models.UniqueConstraint(
|
|
29
|
+
fields=("origin", "external_id"),
|
|
30
|
+
name="uniq_patient_external_id_per_origin",
|
|
31
|
+
)
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
patient: models.ForeignKey["Patient"]
|
|
36
|
+
origin: models.CharField[str]
|
|
37
|
+
|
|
@@ -22,6 +22,10 @@ class Person(models.Model):
|
|
|
22
22
|
phone = models.CharField(max_length=255, blank=True, null=True)
|
|
23
23
|
is_real_person = models.BooleanField(default=True)
|
|
24
24
|
|
|
25
|
+
post_code = models.CharField(max_length=20, blank=True, null=True)
|
|
26
|
+
city = models.CharField(max_length=255, blank=True, null=True)
|
|
27
|
+
street = models.CharField(max_length=255, blank=True, null=True)
|
|
28
|
+
|
|
25
29
|
@abstractmethod
|
|
26
30
|
def __str__(self):
|
|
27
31
|
pass
|
|
@@ -1,24 +1,28 @@
|
|
|
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 endoreg_db.models import PortalUserInfo
|
|
6
7
|
|
|
8
|
+
|
|
7
9
|
class ProfessionManager(models.Manager):
|
|
8
10
|
def get_by_natural_key(self, name):
|
|
9
11
|
return self.get(name=name)
|
|
10
12
|
|
|
13
|
+
|
|
11
14
|
class Profession(models.Model):
|
|
12
15
|
objects = ProfessionManager()
|
|
13
16
|
name = models.CharField(max_length=100)
|
|
14
17
|
description = models.TextField(blank=True, null=True)
|
|
15
18
|
|
|
16
|
-
|
|
17
19
|
if TYPE_CHECKING:
|
|
18
|
-
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def portal_user_infos(self) -> models.QuerySet["PortalUserInfo"]: ...
|
|
19
23
|
|
|
20
24
|
def __str__(self):
|
|
21
25
|
"""
|
|
22
26
|
Return the profession's name as its string representation.
|
|
23
27
|
"""
|
|
24
|
-
return str(self.name)
|
|
28
|
+
return str(self.name)
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
from django.db import models
|
|
2
1
|
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
from django.db import models
|
|
4
|
+
|
|
3
5
|
# models.py in your main app
|
|
4
6
|
|
|
5
7
|
if TYPE_CHECKING:
|
|
6
|
-
from ..profession import Profession
|
|
7
|
-
from endoreg_db.models import Examiner
|
|
8
8
|
from django.contrib.auth.models import User
|
|
9
9
|
|
|
10
|
+
from endoreg_db.models import Examiner
|
|
11
|
+
|
|
12
|
+
from ..profession import Profession
|
|
13
|
+
|
|
10
14
|
|
|
11
15
|
class PortalUserInfo(models.Model):
|
|
12
16
|
user = models.OneToOneField("auth.User", on_delete=models.CASCADE)
|
|
13
17
|
profession = models.ForeignKey(
|
|
14
|
-
|
|
18
|
+
"endoreg_db.Profession",
|
|
15
19
|
on_delete=models.CASCADE,
|
|
16
20
|
blank=True,
|
|
17
21
|
null=True,
|
|
@@ -29,9 +33,9 @@ class PortalUserInfo(models.Model):
|
|
|
29
33
|
)
|
|
30
34
|
|
|
31
35
|
if TYPE_CHECKING:
|
|
32
|
-
user: "User"
|
|
33
|
-
profession: "Profession"
|
|
34
|
-
examiner: "Examiner"
|
|
36
|
+
user: models.OneToOneField["User"]
|
|
37
|
+
profession: models.ForeignKey["Profession|None"]
|
|
38
|
+
examiner: models.OneToOneField["Examiner|None"]
|
|
35
39
|
|
|
36
40
|
def __str__(self):
|
|
37
41
|
return self.user.username
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
from django.db import models
|
|
2
1
|
from typing import TYPE_CHECKING
|
|
3
2
|
|
|
3
|
+
from django.db import models
|
|
4
|
+
|
|
4
5
|
from endoreg_db.utils.product.sum_emissions import sum_emissions
|
|
5
6
|
from endoreg_db.utils.product.sum_weights import sum_weights
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from ...other.transport_route import TransportRoute
|
|
9
10
|
from .product_group import ProductGroup
|
|
10
|
-
from .reference_product import ReferenceProduct
|
|
11
11
|
from .product_material import ProductMaterial
|
|
12
|
+
from .reference_product import ReferenceProduct
|
|
12
13
|
# from .product_weight import ProductWeight
|
|
13
14
|
|
|
15
|
+
|
|
14
16
|
class ProductManager(models.Manager):
|
|
15
17
|
def get_by_natural_key(self, name):
|
|
16
18
|
return self.get(name=name)
|
|
17
|
-
|
|
19
|
+
|
|
20
|
+
|
|
18
21
|
class Product(models.Model):
|
|
19
22
|
objects = ProductManager()
|
|
20
23
|
|
|
@@ -29,15 +32,14 @@ class Product(models.Model):
|
|
|
29
32
|
)
|
|
30
33
|
|
|
31
34
|
if TYPE_CHECKING:
|
|
32
|
-
transport_route: "TransportRoute"
|
|
33
|
-
product_group: "ProductGroup"
|
|
35
|
+
transport_route: models.ForeignKey["TransportRoute|None"]
|
|
36
|
+
product_group: models.ForeignKey["ProductGroup|None"]
|
|
34
37
|
reference_products: models.QuerySet["ReferenceProduct"]
|
|
35
38
|
product_product_materials: models.QuerySet["ProductMaterial"]
|
|
36
39
|
|
|
37
|
-
|
|
38
40
|
def natural_key(self):
|
|
39
41
|
return (self.name,)
|
|
40
|
-
|
|
42
|
+
|
|
41
43
|
def __str__(self):
|
|
42
44
|
result = f"{self.name}"
|
|
43
45
|
if self.product_group:
|
|
@@ -49,41 +51,44 @@ class Product(models.Model):
|
|
|
49
51
|
result += f"{self.transport_route})"
|
|
50
52
|
else:
|
|
51
53
|
result += "no transport route)"
|
|
52
|
-
|
|
54
|
+
|
|
53
55
|
return result
|
|
54
|
-
|
|
56
|
+
|
|
55
57
|
def _calculate_material_metric(self, component: str, calculation_func):
|
|
56
58
|
"""Helper method to calculate weight or emission for materials of a specific component."""
|
|
57
|
-
from .product_material import ProductMaterial
|
|
59
|
+
from .product_material import ProductMaterial # Import locally to avoid circular dependency issues at module level
|
|
60
|
+
|
|
58
61
|
materials = ProductMaterial.objects.filter(product=self, component=component)
|
|
59
62
|
return calculation_func(materials)
|
|
60
63
|
|
|
61
64
|
def get_product_weight(self):
|
|
62
65
|
"""Get the product weight, prioritizing material definitions."""
|
|
63
66
|
from .product_material import ProductMaterial
|
|
67
|
+
|
|
64
68
|
# Check if there are specific material definitions for the product component
|
|
65
69
|
if ProductMaterial.objects.filter(product=self, component="product").exists():
|
|
66
70
|
return self.get_product_material_weight()
|
|
67
|
-
|
|
71
|
+
|
|
68
72
|
# Fallback: check if there is a direct product weight defined (Not implemented yet)
|
|
69
73
|
# TODO: Implement logic for ProductWeight lookup
|
|
70
|
-
return None
|
|
74
|
+
return None # Or appropriate default/error
|
|
71
75
|
|
|
72
76
|
def get_package_weight(self):
|
|
73
77
|
"""Get the package weight, prioritizing material definitions."""
|
|
74
78
|
from .product_material import ProductMaterial
|
|
79
|
+
|
|
75
80
|
# Check if there are specific material definitions for the package component
|
|
76
81
|
if ProductMaterial.objects.filter(product=self, component="package").exists():
|
|
77
82
|
return self.get_package_material_weight()
|
|
78
|
-
|
|
83
|
+
|
|
79
84
|
# Fallback: check if there is a direct package weight defined (Not implemented yet)
|
|
80
85
|
# TODO: Implement logic for PackageWeight lookup (if different from ProductWeight)
|
|
81
|
-
return None
|
|
86
|
+
return None # Or appropriate default/error
|
|
82
87
|
|
|
83
88
|
def get_product_material_weight(self):
|
|
84
89
|
"""Calculate the total weight based on defined product materials."""
|
|
85
90
|
return self._calculate_material_metric("product", sum_weights)
|
|
86
|
-
|
|
91
|
+
|
|
87
92
|
def get_package_material_weight(self):
|
|
88
93
|
"""Calculate the total weight based on defined package materials."""
|
|
89
94
|
return self._calculate_material_metric("package", sum_weights)
|
|
@@ -1,54 +1,53 @@
|
|
|
1
|
-
from django.db import models
|
|
2
1
|
from typing import TYPE_CHECKING
|
|
3
2
|
|
|
3
|
+
from django.db import models
|
|
4
|
+
|
|
4
5
|
from endoreg_db.models.other.unit import Unit
|
|
5
6
|
|
|
6
7
|
if TYPE_CHECKING:
|
|
7
|
-
from ...other.
|
|
8
|
+
from ...other.material import Material
|
|
8
9
|
from ...other.unit import Unit
|
|
9
10
|
from .product import Product
|
|
10
|
-
|
|
11
|
+
|
|
11
12
|
|
|
12
13
|
class ProductMaterial(models.Model):
|
|
13
14
|
component = models.CharField(max_length=255)
|
|
14
15
|
material = models.ForeignKey(
|
|
15
16
|
"Material",
|
|
16
17
|
on_delete=models.CASCADE,
|
|
17
|
-
related_name="material_product_materials",
|
|
18
|
+
related_name="material_product_materials", # Changed related_name
|
|
18
19
|
)
|
|
19
20
|
product = models.ForeignKey(
|
|
20
21
|
"Product",
|
|
21
22
|
on_delete=models.CASCADE,
|
|
22
|
-
related_name="product_product_materials"
|
|
23
|
+
related_name="product_product_materials", # Changed related_name
|
|
23
24
|
)
|
|
24
25
|
unit = models.ForeignKey(
|
|
25
26
|
"Unit",
|
|
26
27
|
on_delete=models.CASCADE,
|
|
27
|
-
related_name="unit_product_materials",
|
|
28
|
+
related_name="unit_product_materials", # Changed related_name
|
|
28
29
|
)
|
|
29
30
|
quantity = models.FloatField()
|
|
30
31
|
|
|
31
32
|
if TYPE_CHECKING:
|
|
32
|
-
product: "Product"
|
|
33
|
-
material: "Material"
|
|
34
|
-
unit: "Unit"
|
|
35
|
-
emission_factor: "EmissionFactor"
|
|
33
|
+
product: models.ForeignKey["Product"]
|
|
34
|
+
material: models.ForeignKey["Material"]
|
|
35
|
+
unit: models.ForeignKey["Unit"]
|
|
36
36
|
|
|
37
37
|
def get_emission(self) -> tuple[float, Unit]:
|
|
38
38
|
emission_factor = self.material.emission_factor
|
|
39
39
|
if emission_factor is None:
|
|
40
40
|
raise Exception("No emission factor for material " + self.material.name + " found.")
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
# make sure product_material.unit is the same as emission_factor.unit
|
|
43
|
-
if self.unit
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
if self.unit is not None and emission_factor.unit is not None:
|
|
44
|
+
if self.unit != emission_factor.unit:
|
|
45
|
+
raise Exception("Unit mismatch: " + self.unit.name + " != " + emission_factor.unit.name)
|
|
46
|
+
|
|
46
47
|
emmision_value = emission_factor.value * self.quantity
|
|
48
|
+
assert isinstance(emission_factor.unit, Unit)
|
|
47
49
|
emission_unit = emission_factor.unit
|
|
48
50
|
return emmision_value, emission_unit
|
|
49
|
-
|
|
51
|
+
|
|
50
52
|
def __str__(self) -> str:
|
|
51
53
|
return f"{self.product.name} - {self.material.name} - {self.quantity} {self.unit.name}"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|