endoreg-db 0.4.5__py3-none-any.whl → 0.8.6.3__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.
- endoreg_db/admin.py +90 -1
- endoreg_db/api_urls.py +4 -0
- endoreg_db/apps.py +12 -0
- endoreg_db/assets/dummy_model.ckpt +1 -0
- endoreg_db/codemods/readme.md +88 -0
- endoreg_db/codemods/rename_datetime_fields.py +92 -0
- endoreg_db/config/env.py +101 -0
- endoreg_db/data/__init__.py +76 -4
- endoreg_db/data/ai_model/data.yaml +7 -0
- endoreg_db/data/{label → ai_model_label}/label/data.yaml +27 -1
- endoreg_db/data/ai_model_label/label/polyp_classification.yaml +52 -0
- endoreg_db/data/ai_model_label/label-set/data.yaml +40 -0
- endoreg_db/data/ai_model_label/label-set/polyp_classifications.yaml +25 -0
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +27 -0
- endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml +176 -0
- endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml +20 -0
- endoreg_db/data/center/data.yaml +40 -9
- endoreg_db/data/center_shift/ukw.yaml +9 -0
- endoreg_db/data/contraindication/bleeding.yaml +11 -0
- endoreg_db/data/db_summary.csv +58 -0
- endoreg_db/data/db_summary.xlsx +0 -0
- endoreg_db/data/disease/misc.yaml +1 -2
- endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +2 -2
- endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +6 -6
- endoreg_db/data/distribution/numeric/data.yaml +14 -0
- endoreg_db/data/endoscope/data.yaml +93 -0
- endoreg_db/data/endoscopy_processor/data.yaml +3 -0
- endoreg_db/data/event/cardiology.yaml +0 -13
- endoreg_db/data/examination/examinations/data.yaml +34 -28
- endoreg_db/data/examination/type/data.yaml +12 -0
- endoreg_db/data/examination_indication/endoscopy.yaml +424 -0
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +160 -0
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
- endoreg_db/data/examination_requirement_set/colonoscopy.yaml +15 -0
- endoreg_db/data/finding/anatomy_colon.yaml +128 -0
- endoreg_db/data/finding/colonoscopy.yaml +40 -0
- endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +56 -0
- endoreg_db/data/finding/complication.yaml +16 -0
- endoreg_db/data/finding/data.yaml +105 -0
- endoreg_db/data/finding/examination_setting.yaml +16 -0
- endoreg_db/data/finding/medication_related.yaml +18 -0
- endoreg_db/data/finding/outcome.yaml +12 -0
- endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +95 -0
- endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +22 -0
- endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +25 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +68 -0
- endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +80 -0
- endoreg_db/data/finding_classification/colonoscopy_lst.yaml +21 -0
- endoreg_db/data/finding_classification/colonoscopy_nice.yaml +20 -0
- endoreg_db/data/finding_classification/colonoscopy_paris.yaml +26 -0
- endoreg_db/data/finding_classification/colonoscopy_sano.yaml +22 -0
- endoreg_db/data/finding_classification/colonoscopy_summary.yaml +53 -0
- endoreg_db/data/finding_classification/complication_generic.yaml +25 -0
- endoreg_db/data/finding_classification/examination_setting_generic.yaml +40 -0
- endoreg_db/data/finding_classification/histology_colo.yaml +51 -0
- endoreg_db/data/finding_classification/intervention_required.yaml +26 -0
- endoreg_db/data/finding_classification/medication_related.yaml +23 -0
- endoreg_db/data/finding_classification/visualized.yaml +33 -0
- endoreg_db/data/finding_classification_choice/bowel_preparation.yaml +78 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +32 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +15 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +17 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_paris.yaml +57 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +49 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +14 -0
- endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +36 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_location.yaml +229 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +82 -0
- endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
- endoreg_db/data/finding_classification_choice/complication_generic_types.yaml +15 -0
- endoreg_db/data/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
- endoreg_db/data/finding_classification_choice/histology.yaml +24 -0
- endoreg_db/data/finding_classification_choice/histology_polyp.yaml +20 -0
- endoreg_db/data/finding_classification_choice/outcome.yaml +19 -0
- endoreg_db/data/finding_classification_choice/yes_no_na.yaml +11 -0
- endoreg_db/data/finding_classification_type/colonoscopy_basic.yaml +48 -0
- endoreg_db/data/finding_intervention/endoscopy.yaml +43 -0
- endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +168 -0
- endoreg_db/data/finding_intervention/endoscopy_egd.yaml +128 -0
- endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +32 -0
- endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +9 -0
- endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +36 -0
- endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
- endoreg_db/data/finding_type/data.yaml +43 -0
- endoreg_db/data/gender/data.yaml +24 -0
- endoreg_db/data/information_source/annotation.yaml +6 -0
- endoreg_db/data/information_source/endoscopy_guidelines.yaml +7 -0
- endoreg_db/data/information_source/prediction.yaml +7 -0
- endoreg_db/data/information_source_type/data.yaml +8 -0
- endoreg_db/data/lab_value/cardiac_enzymes.yaml +7 -1
- endoreg_db/data/lab_value/coagulation.yaml +6 -1
- endoreg_db/data/lab_value/electrolytes.yaml +39 -1
- endoreg_db/data/lab_value/gastrointestinal_function.yaml +12 -0
- endoreg_db/data/lab_value/hematology.yaml +17 -2
- endoreg_db/data/lab_value/hormones.yaml +6 -0
- endoreg_db/data/lab_value/lipids.yaml +12 -3
- endoreg_db/data/lab_value/misc.yaml +48 -2
- endoreg_db/data/lab_value/renal_function.yaml +2 -1
- endoreg_db/data/lx_client_tag/base.yaml +54 -0
- endoreg_db/data/lx_client_type/base.yaml +30 -0
- endoreg_db/data/lx_permission/base.yaml +24 -0
- endoreg_db/data/lx_permission/endoreg.yaml +52 -0
- endoreg_db/data/medication/anticoagulation.yaml +5 -5
- endoreg_db/data/medication/tah.yaml +5 -5
- endoreg_db/data/medication_indication/anticoagulation.yaml +48 -53
- endoreg_db/data/medication_intake_time/base.yaml +4 -4
- endoreg_db/data/names_first/first_names.yaml +54 -0
- endoreg_db/data/names_last/last_names.yaml +51 -0
- endoreg_db/data/network_device/data.yaml +30 -0
- endoreg_db/data/organ/data.yaml +29 -0
- endoreg_db/data/pdf_type/data.yaml +27 -9
- endoreg_db/data/qualification/endoscopy.yaml +36 -0
- endoreg_db/data/qualification/m2.yaml +39 -0
- endoreg_db/data/qualification/outpatient_clinic.yaml +35 -0
- endoreg_db/data/qualification/sonography.yaml +36 -0
- endoreg_db/data/qualification_type/base.yaml +29 -0
- endoreg_db/data/report_reader_flag/rkh-histology-generic.yaml +10 -0
- endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +4 -0
- endoreg_db/data/report_reader_flag/ukw-histology-generic.yaml +5 -0
- endoreg_db/data/requirement/age.yaml +26 -0
- endoreg_db/data/requirement/colonoscopy_baseline_austria.yaml +45 -0
- endoreg_db/data/requirement/disease_cardiovascular.yaml +79 -0
- endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +41 -0
- endoreg_db/data/requirement/disease_hepatology.yaml +12 -0
- endoreg_db/data/requirement/disease_misc.yaml +12 -0
- endoreg_db/data/requirement/disease_renal.yaml +96 -0
- endoreg_db/data/requirement/endoscopy_bleeding_risk.yaml +59 -0
- endoreg_db/data/requirement/event_cardiology.yaml +251 -0
- endoreg_db/data/requirement/event_requirements.yaml +145 -0
- endoreg_db/data/requirement/finding_colon_polyp.yaml +50 -0
- endoreg_db/data/requirement/gender.yaml +25 -0
- endoreg_db/data/requirement/lab_value.yaml +441 -0
- endoreg_db/data/requirement/medication.yaml +93 -0
- endoreg_db/data/requirement_operator/age.yaml +13 -0
- endoreg_db/data/requirement_operator/lab_operators.yaml +129 -0
- endoreg_db/data/requirement_operator/model_operators.yaml +96 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +48 -0
- endoreg_db/data/requirement_set/colonoscopy_austria_screening.yaml +57 -0
- endoreg_db/data/requirement_set/endoscopy_bleeding_risk.yaml +52 -0
- endoreg_db/data/requirement_set_type/data.yaml +20 -0
- endoreg_db/data/requirement_type/requirement_types.yaml +165 -0
- endoreg_db/data/risk/bleeding.yaml +26 -0
- endoreg_db/data/risk/thrombosis.yaml +37 -0
- endoreg_db/data/risk_type/data.yaml +27 -0
- endoreg_db/data/setup_config.yaml +38 -0
- endoreg_db/data/shift/endoscopy.yaml +21 -0
- endoreg_db/data/shift_type/base.yaml +35 -0
- endoreg_db/data/tag/requirement_set_tags.yaml +11 -0
- endoreg_db/data/unit/concentration.yaml +23 -0
- endoreg_db/data/unit/time.yaml +36 -1
- endoreg_db/exceptions.py +19 -0
- endoreg_db/forms/__init__.py +3 -1
- endoreg_db/forms/examination_form.py +11 -0
- endoreg_db/forms/patient_finding_intervention_form.py +18 -0
- endoreg_db/forms/patient_form.py +27 -0
- endoreg_db/forms/questionnaires/__init__.py +1 -1
- endoreg_db/forms/questionnaires/tto_questionnaire.py +19 -19
- endoreg_db/helpers/count_db.py +45 -0
- endoreg_db/helpers/data_loader.py +208 -0
- endoreg_db/helpers/default_objects.py +378 -0
- endoreg_db/helpers/download_segmentation_model.py +31 -0
- endoreg_db/helpers/interact.py +6 -0
- endoreg_db/helpers/test_video_helper.py +119 -0
- endoreg_db/logger_conf.py +140 -0
- endoreg_db/management/__init__.py +1 -0
- endoreg_db/management/commands/__init__.py +1 -0
- endoreg_db/management/commands/anonymize_video.py +0 -0
- endoreg_db/management/commands/check_auth.py +125 -0
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +115 -0
- endoreg_db/management/commands/create_multilabel_model_meta.py +214 -0
- endoreg_db/management/commands/fix_missing_patient_data.py +172 -0
- endoreg_db/management/commands/fix_video_paths.py +165 -0
- endoreg_db/management/commands/import_fallback_video.py +203 -0
- endoreg_db/management/commands/import_report.py +298 -0
- endoreg_db/management/commands/import_video.py +423 -0
- endoreg_db/management/commands/import_video_with_classification.py +367 -0
- endoreg_db/management/commands/init_default_ai_model.py +112 -0
- endoreg_db/management/commands/load_ai_model_data.py +58 -26
- endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
- endoreg_db/management/commands/load_base_db_data.py +174 -118
- endoreg_db/management/commands/load_center_data.py +46 -21
- endoreg_db/management/commands/{load_logging_data.py → load_contraindication_data.py} +4 -2
- endoreg_db/management/commands/load_disease_data.py +29 -7
- endoreg_db/management/commands/{load_endoscope_type_data.py → load_endoscope_data.py} +30 -7
- endoreg_db/management/commands/load_examination_indication_data.py +86 -0
- endoreg_db/management/commands/load_finding_data.py +128 -0
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +0 -1
- endoreg_db/management/commands/load_information_source.py +13 -7
- endoreg_db/management/commands/load_lab_value_data.py +3 -3
- endoreg_db/management/commands/load_medication_data.py +83 -21
- endoreg_db/management/commands/load_name_data.py +37 -0
- endoreg_db/management/commands/{load_medication_intake_time_data.py → load_organ_data.py} +7 -5
- endoreg_db/management/commands/load_qualification_data.py +59 -0
- endoreg_db/management/commands/load_requirement_data.py +180 -0
- endoreg_db/management/commands/load_risk_data.py +56 -0
- endoreg_db/management/commands/load_shift_data.py +60 -0
- endoreg_db/management/commands/load_tag_data.py +57 -0
- endoreg_db/management/commands/register_ai_model.py +1 -1
- endoreg_db/management/commands/setup_endoreg_db.py +381 -0
- endoreg_db/management/commands/start_filewatcher.py +106 -0
- endoreg_db/management/commands/storage_management.py +548 -0
- endoreg_db/management/commands/summarize_db_content.py +189 -0
- endoreg_db/management/commands/validate_video.py +204 -0
- endoreg_db/management/commands/validate_video_files.py +161 -0
- endoreg_db/management/commands/video_validation.py +22 -0
- endoreg_db/mermaid/Overall_flow_patient_finding_intervention.md +10 -0
- endoreg_db/mermaid/anonymized_image_annotation.md +20 -0
- endoreg_db/mermaid/binary_classification_annotation.md +50 -0
- endoreg_db/mermaid/classification.md +8 -0
- endoreg_db/mermaid/examination.md +8 -0
- endoreg_db/mermaid/findings.md +7 -0
- endoreg_db/mermaid/image_classification.md +28 -0
- endoreg_db/mermaid/interventions.md +8 -0
- endoreg_db/mermaid/morphology.md +8 -0
- endoreg_db/mermaid/patient_creation.md +14 -0
- endoreg_db/mermaid/video_segmentation_annotation.md +17 -0
- endoreg_db/migrations/0001_initial.py +1234 -944
- endoreg_db/migrations/0002_add_video_correction_models.py +52 -0
- endoreg_db/migrations/0003_add_center_display_name.py +30 -0
- endoreg_db/models/__init__.py +339 -53
- endoreg_db/models/administration/__init__.py +116 -0
- endoreg_db/models/administration/ai/__init__.py +9 -0
- endoreg_db/models/administration/ai/active_model.py +35 -0
- endoreg_db/models/administration/ai/ai_model.py +156 -0
- endoreg_db/models/{ai_model → administration/ai}/model_type.py +19 -4
- endoreg_db/models/administration/case/__init__.py +19 -0
- endoreg_db/models/administration/case/case.py +114 -0
- endoreg_db/models/{case_template → administration/case/case_template}/__init__.py +10 -1
- endoreg_db/models/{case_template → administration/case/case_template}/case_template.py +60 -16
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_rule.py +6 -13
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_rule_value.py +21 -8
- endoreg_db/models/{case_template → administration/case/case_template}/case_template_type.py +1 -3
- endoreg_db/models/{center → administration/center}/__init__.py +9 -0
- endoreg_db/models/administration/center/center.py +67 -0
- endoreg_db/models/administration/center/center_product.py +64 -0
- endoreg_db/models/administration/center/center_resource.py +49 -0
- endoreg_db/models/administration/center/center_shift.py +88 -0
- endoreg_db/models/administration/center/center_waste.py +30 -0
- endoreg_db/models/administration/permissions/__init__.py +44 -0
- endoreg_db/models/administration/person/__init__.py +24 -0
- endoreg_db/models/administration/person/employee/__init__.py +3 -0
- endoreg_db/models/administration/person/employee/employee.py +35 -0
- endoreg_db/models/administration/person/employee/employee_qualification.py +39 -0
- endoreg_db/models/administration/person/employee/employee_type.py +42 -0
- endoreg_db/models/administration/person/examiner/__init__.py +4 -0
- endoreg_db/models/administration/person/examiner/examiner.py +54 -0
- endoreg_db/models/administration/person/names/__init__.py +0 -0
- endoreg_db/models/{persons → administration/person/names}/first_name.py +1 -1
- endoreg_db/models/{persons → administration/person/names}/last_name.py +2 -3
- endoreg_db/models/administration/person/patient/__init__.py +5 -0
- endoreg_db/models/administration/person/patient/patient.py +460 -0
- endoreg_db/models/administration/person/profession/__init__.py +24 -0
- endoreg_db/models/administration/person/user/__init__.py +5 -0
- endoreg_db/models/administration/person/user/portal_user_information.py +37 -0
- endoreg_db/models/administration/product/__init__.py +14 -0
- endoreg_db/models/administration/product/product.py +97 -0
- endoreg_db/models/administration/product/product_group.py +39 -0
- endoreg_db/models/administration/product/product_material.py +54 -0
- endoreg_db/models/{product → administration/product}/product_weight.py +21 -0
- endoreg_db/models/{product → administration/product}/reference_product.py +44 -13
- endoreg_db/models/administration/qualification/__init__.py +7 -0
- endoreg_db/models/administration/qualification/qualification.py +37 -0
- endoreg_db/models/administration/qualification/qualification_type.py +35 -0
- endoreg_db/models/administration/shift/__init__.py +9 -0
- endoreg_db/models/administration/shift/scheduled_days.py +69 -0
- endoreg_db/models/administration/shift/shift.py +51 -0
- endoreg_db/models/administration/shift/shift_type.py +108 -0
- endoreg_db/models/label/__init__.py +24 -1
- endoreg_db/models/label/annotation/__init__.py +12 -0
- endoreg_db/models/label/annotation/image_classification.py +84 -0
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +66 -0
- endoreg_db/models/label/label.py +53 -54
- endoreg_db/models/label/label_set.py +53 -0
- endoreg_db/models/label/label_type.py +29 -0
- endoreg_db/models/label/label_video_segment/__init__.py +3 -0
- endoreg_db/models/label/label_video_segment/_create_from_video.py +41 -0
- endoreg_db/models/label/label_video_segment/label_video_segment.py +511 -0
- endoreg_db/models/label/video_segmentation_label.py +31 -0
- endoreg_db/models/label/video_segmentation_labelset.py +27 -0
- endoreg_db/models/media/__init__.py +16 -0
- endoreg_db/models/media/frame/__init__.py +3 -0
- endoreg_db/models/media/frame/frame.py +111 -0
- endoreg_db/models/media/pdf/__init__.py +11 -0
- endoreg_db/models/media/pdf/raw_pdf.py +757 -0
- endoreg_db/models/media/pdf/report_file.py +162 -0
- endoreg_db/models/media/pdf/report_reader/__init__.py +7 -0
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +77 -0
- endoreg_db/models/media/video/__init__.py +8 -0
- endoreg_db/models/media/video/create_from_file.py +358 -0
- endoreg_db/models/media/video/pipe_1.py +213 -0
- endoreg_db/models/media/video/pipe_2.py +105 -0
- endoreg_db/models/media/video/refactor_plan.md +0 -0
- endoreg_db/models/media/video/video_file.py +825 -0
- endoreg_db/models/media/video/video_file_ai.py +443 -0
- endoreg_db/models/media/video/video_file_anonymize.py +349 -0
- endoreg_db/models/media/video/video_file_frames/__init__.py +47 -0
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +22 -0
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +23 -0
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +104 -0
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +174 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +28 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +20 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +34 -0
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +27 -0
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +129 -0
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +141 -0
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +65 -0
- endoreg_db/models/media/video/video_file_frames.py +0 -0
- endoreg_db/models/media/video/video_file_io.py +168 -0
- endoreg_db/models/media/video/video_file_meta/__init__.py +22 -0
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +45 -0
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +39 -0
- endoreg_db/models/media/video/video_file_meta/get_fps.py +147 -0
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +143 -0
- endoreg_db/models/media/video/video_file_meta/text_meta.py +134 -0
- endoreg_db/models/media/video/video_file_meta/video_meta.py +70 -0
- endoreg_db/models/media/video/video_file_segments.py +209 -0
- endoreg_db/models/media/video/video_metadata.py +65 -0
- endoreg_db/models/media/video/video_processing.py +152 -0
- endoreg_db/models/medical/__init__.py +146 -0
- endoreg_db/models/medical/contraindication/__init__.py +17 -0
- endoreg_db/models/medical/disease.py +156 -0
- endoreg_db/models/medical/event.py +137 -0
- endoreg_db/models/medical/examination/__init__.py +9 -0
- endoreg_db/models/medical/examination/examination.py +148 -0
- endoreg_db/models/medical/examination/examination_indication.py +278 -0
- endoreg_db/models/medical/examination/examination_time.py +49 -0
- endoreg_db/models/medical/examination/examination_time_type.py +41 -0
- endoreg_db/models/medical/examination/examination_type.py +48 -0
- endoreg_db/models/medical/finding/__init__.py +18 -0
- endoreg_db/models/medical/finding/finding.py +96 -0
- endoreg_db/models/medical/finding/finding_classification.py +142 -0
- endoreg_db/models/medical/finding/finding_intervention.py +52 -0
- endoreg_db/models/medical/finding/finding_type.py +35 -0
- endoreg_db/models/medical/hardware/__init__.py +8 -0
- endoreg_db/models/medical/hardware/endoscope.py +65 -0
- endoreg_db/models/{hardware → medical/hardware}/endoscopy_processor.py +68 -29
- endoreg_db/models/medical/laboratory/__init__.py +5 -0
- endoreg_db/models/medical/laboratory/lab_value.py +419 -0
- endoreg_db/models/medical/medication/__init__.py +19 -0
- endoreg_db/models/medical/medication/medication.py +31 -0
- endoreg_db/models/medical/medication/medication_indication.py +50 -0
- endoreg_db/models/medical/medication/medication_indication_type.py +39 -0
- endoreg_db/models/medical/medication/medication_intake_time.py +44 -0
- endoreg_db/models/medical/medication/medication_schedule.py +45 -0
- endoreg_db/models/medical/organ/__init__.py +35 -0
- endoreg_db/models/medical/patient/__init__.py +56 -0
- endoreg_db/models/medical/patient/medication_examples.py +38 -0
- endoreg_db/models/medical/patient/patient_disease.py +63 -0
- endoreg_db/models/medical/patient/patient_event.py +75 -0
- endoreg_db/models/medical/patient/patient_examination.py +249 -0
- endoreg_db/models/medical/patient/patient_examination_indication.py +44 -0
- endoreg_db/models/medical/patient/patient_finding.py +357 -0
- endoreg_db/models/medical/patient/patient_finding_classification.py +207 -0
- endoreg_db/models/medical/patient/patient_finding_intervention.py +40 -0
- endoreg_db/models/medical/patient/patient_lab_sample.py +148 -0
- endoreg_db/models/{persons → medical}/patient/patient_lab_value.py +68 -22
- endoreg_db/models/medical/patient/patient_medication.py +104 -0
- endoreg_db/models/medical/patient/patient_medication_schedule.py +136 -0
- endoreg_db/models/medical/risk/__init__.py +7 -0
- endoreg_db/models/medical/risk/risk.py +72 -0
- endoreg_db/models/medical/risk/risk_type.py +51 -0
- endoreg_db/models/metadata/__init__.py +19 -0
- endoreg_db/models/metadata/frame_ocr_result.py +0 -0
- endoreg_db/models/metadata/model_meta.py +206 -0
- endoreg_db/models/metadata/model_meta_logic.py +343 -0
- endoreg_db/models/{data_file/metadata → metadata}/pdf_meta.py +32 -13
- endoreg_db/models/metadata/sensitive_meta.py +288 -0
- endoreg_db/models/metadata/sensitive_meta_logic.py +1048 -0
- endoreg_db/models/metadata/video_meta.py +332 -0
- endoreg_db/models/metadata/video_prediction_logic.py +190 -0
- endoreg_db/models/metadata/video_prediction_meta.py +270 -0
- endoreg_db/models/other/__init__.py +36 -1
- endoreg_db/models/other/distribution/__init__.py +44 -0
- endoreg_db/models/other/distribution/base_value_distribution.py +20 -0
- endoreg_db/models/other/distribution/date_value_distribution.py +89 -0
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
- endoreg_db/models/other/distribution/numeric_value_distribution.py +125 -0
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
- endoreg_db/models/other/emission/__init__.py +5 -0
- endoreg_db/models/other/emission/emission_factor.py +94 -0
- endoreg_db/models/{persons → other}/gender.py +8 -3
- endoreg_db/models/other/information_source.py +159 -0
- endoreg_db/models/other/material.py +14 -2
- endoreg_db/models/other/resource.py +6 -2
- endoreg_db/models/other/tag.py +27 -0
- endoreg_db/models/other/transport_route.py +15 -3
- endoreg_db/models/{unit.py → other/unit.py} +16 -6
- endoreg_db/models/other/waste.py +10 -3
- endoreg_db/models/requirement/__init__.py +11 -0
- endoreg_db/models/requirement/requirement.py +767 -0
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +6 -0
- endoreg_db/models/requirement/requirement_evaluation/get_values.py +40 -0
- endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +9 -0
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +95 -0
- endoreg_db/models/requirement/requirement_operator.py +176 -0
- endoreg_db/models/requirement/requirement_set.py +287 -0
- endoreg_db/models/rule/__init__.py +13 -0
- endoreg_db/models/{rules → rule}/rule.py +6 -3
- endoreg_db/models/{rules → rule}/rule_attribute_dtype.py +0 -2
- endoreg_db/models/{rules → rule}/rule_type.py +0 -2
- endoreg_db/models/{rules → rule}/ruleset.py +0 -2
- endoreg_db/models/state/__init__.py +12 -0
- endoreg_db/models/state/abstract.py +11 -0
- endoreg_db/models/state/audit_ledger.py +150 -0
- endoreg_db/models/state/label_video_segment.py +22 -0
- endoreg_db/models/state/raw_pdf.py +187 -0
- endoreg_db/models/state/sensitive_meta.py +46 -0
- endoreg_db/models/state/video.py +232 -0
- endoreg_db/models/upload_job.py +99 -0
- endoreg_db/models/utils.py +135 -0
- endoreg_db/renames.yml +8 -0
- endoreg_db/root_urls.py +9 -0
- endoreg_db/schemas/__init__.py +0 -0
- endoreg_db/schemas/examination_evaluation.py +27 -0
- endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +775 -0
- endoreg_db/serializers/__init__.py +118 -10
- endoreg_db/serializers/_old/raw_pdf_meta_validation.py +223 -0
- endoreg_db/serializers/_old/raw_video_meta_validation.py +179 -0
- endoreg_db/serializers/_old/video.py +71 -0
- endoreg_db/serializers/administration/__init__.py +14 -0
- endoreg_db/serializers/administration/ai/__init__.py +10 -0
- endoreg_db/serializers/administration/ai/active_model.py +10 -0
- endoreg_db/serializers/administration/ai/ai_model.py +18 -0
- endoreg_db/serializers/administration/ai/model_type.py +10 -0
- endoreg_db/serializers/administration/center.py +9 -0
- endoreg_db/serializers/administration/gender.py +9 -0
- endoreg_db/serializers/anonymization.py +69 -0
- endoreg_db/serializers/evaluation/examination_evaluation.py +1 -0
- endoreg_db/serializers/examination/__init__.py +10 -0
- endoreg_db/serializers/examination/base.py +46 -0
- endoreg_db/serializers/examination/dropdown.py +21 -0
- endoreg_db/serializers/examination_serializer.py +12 -0
- endoreg_db/serializers/finding/__init__.py +5 -0
- endoreg_db/serializers/finding/finding.py +54 -0
- endoreg_db/serializers/finding_classification/__init__.py +7 -0
- endoreg_db/serializers/finding_classification/choice.py +19 -0
- endoreg_db/serializers/finding_classification/classification.py +13 -0
- endoreg_db/serializers/label/__init__.py +7 -0
- endoreg_db/serializers/label/image_classification_annotation.py +62 -0
- endoreg_db/serializers/label/label.py +15 -0
- endoreg_db/serializers/label_video_segment/__init__.py +7 -0
- endoreg_db/serializers/label_video_segment/_lvs_create.py +149 -0
- endoreg_db/serializers/label_video_segment/_lvs_update.py +138 -0
- endoreg_db/serializers/label_video_segment/_lvs_validate.py +149 -0
- endoreg_db/serializers/label_video_segment/label_video_segment.py +344 -0
- endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +99 -0
- endoreg_db/serializers/label_video_segment/label_video_segment_update.py +163 -0
- endoreg_db/serializers/meta/__init__.py +19 -0
- endoreg_db/serializers/meta/pdf_file_meta_extraction.py +115 -0
- endoreg_db/serializers/meta/report_meta.py +53 -0
- endoreg_db/serializers/meta/sensitive_meta_detail.py +162 -0
- endoreg_db/serializers/meta/sensitive_meta_update.py +148 -0
- endoreg_db/serializers/meta/sensitive_meta_verification.py +59 -0
- endoreg_db/serializers/meta/video_meta.py +39 -0
- endoreg_db/serializers/misc/__init__.py +14 -0
- endoreg_db/serializers/misc/file_overview.py +182 -0
- endoreg_db/serializers/misc/sensitive_patient_data.py +120 -0
- endoreg_db/serializers/misc/stats.py +33 -0
- endoreg_db/serializers/misc/translatable_field_mix_in.py +44 -0
- endoreg_db/serializers/misc/upload_job.py +71 -0
- endoreg_db/serializers/patient/__init__.py +11 -0
- endoreg_db/serializers/patient/patient.py +86 -0
- endoreg_db/serializers/patient/patient_dropdown.py +27 -0
- endoreg_db/serializers/patient_examination/__init__.py +7 -0
- endoreg_db/serializers/patient_examination/patient_examination.py +141 -0
- endoreg_db/serializers/patient_finding/__init__.py +15 -0
- endoreg_db/serializers/patient_finding/patient_finding.py +31 -0
- endoreg_db/serializers/patient_finding/patient_finding_classification.py +39 -0
- endoreg_db/serializers/patient_finding/patient_finding_detail.py +53 -0
- endoreg_db/serializers/patient_finding/patient_finding_intervention.py +26 -0
- endoreg_db/serializers/patient_finding/patient_finding_list.py +41 -0
- endoreg_db/serializers/patient_finding/patient_finding_write.py +126 -0
- endoreg_db/serializers/pdf/__init__.py +5 -0
- endoreg_db/serializers/pdf/anony_text_validation.py +85 -0
- endoreg_db/serializers/report/__init__.py +9 -0
- endoreg_db/serializers/report/mixins.py +45 -0
- endoreg_db/serializers/report/report.py +105 -0
- endoreg_db/serializers/report/report_list.py +22 -0
- endoreg_db/serializers/report/secure_file_url.py +26 -0
- endoreg_db/serializers/requirements/requirement_schema.py +25 -0
- endoreg_db/serializers/requirements/requirement_sets.py +29 -0
- endoreg_db/serializers/sensitive_meta_serializer.py +282 -0
- endoreg_db/serializers/video/__init__.py +7 -0
- endoreg_db/serializers/video/segmentation.py +263 -0
- endoreg_db/serializers/video/video_file_brief.py +10 -0
- endoreg_db/serializers/video/video_file_detail.py +83 -0
- endoreg_db/serializers/video/video_file_list.py +67 -0
- endoreg_db/serializers/video/video_metadata.py +105 -0
- endoreg_db/serializers/video/video_processing_history.py +153 -0
- endoreg_db/serializers/video_examination.py +198 -0
- endoreg_db/services/__init__.py +5 -0
- endoreg_db/services/anonymization.py +223 -0
- endoreg_db/services/examination_evaluation.py +149 -0
- endoreg_db/services/finding_description_service.py +0 -0
- endoreg_db/services/lookup_service.py +411 -0
- endoreg_db/services/lookup_store.py +266 -0
- endoreg_db/services/pdf_import.py +1382 -0
- endoreg_db/services/polling_coordinator.py +288 -0
- endoreg_db/services/pseudonym_service.py +89 -0
- endoreg_db/services/requirements_object.py +147 -0
- endoreg_db/services/segment_sync.py +155 -0
- endoreg_db/services/storage_aware_video_processor.py +344 -0
- endoreg_db/services/video_import.py +1259 -0
- endoreg_db/tasks/upload_tasks.py +207 -0
- endoreg_db/tasks/video_ingest.py +157 -0
- endoreg_db/tasks/video_processing_tasks.py +327 -0
- endoreg_db/templates/admin/patient_finding_intervention.html +253 -0
- endoreg_db/templates/admin/start_examination.html +12 -0
- endoreg_db/templates/timeline.html +176 -0
- endoreg_db/urls/__init__.py +83 -0
- endoreg_db/urls/anonymization.py +32 -0
- endoreg_db/urls/auth.py +16 -0
- endoreg_db/urls/classification.py +39 -0
- endoreg_db/urls/examination.py +54 -0
- endoreg_db/urls/files.py +6 -0
- endoreg_db/urls/label_video_segment_validate.py +33 -0
- endoreg_db/urls/label_video_segments.py +46 -0
- endoreg_db/urls/media.py +227 -0
- endoreg_db/urls/patient.py +19 -0
- endoreg_db/urls/report.py +48 -0
- endoreg_db/urls/requirements.py +13 -0
- endoreg_db/urls/sensitive_meta.py +0 -0
- endoreg_db/urls/stats.py +46 -0
- endoreg_db/urls/upload.py +20 -0
- endoreg_db/urls/video.py +61 -0
- endoreg_db/urls.py +9 -0
- endoreg_db/utils/__init__.py +88 -1
- endoreg_db/utils/ai/__init__.py +9 -0
- endoreg_db/{models/ai_model/utils.py → utils/ai/get.py} +1 -4
- endoreg_db/utils/ai/inference_dataset.py +52 -0
- endoreg_db/utils/ai/multilabel_classification_net.py +159 -0
- endoreg_db/utils/ai/postprocess.py +63 -0
- endoreg_db/utils/ai/predict.py +291 -0
- endoreg_db/utils/ai/preprocess.py +68 -0
- endoreg_db/utils/calc_duration_seconds.py +24 -0
- endoreg_db/utils/case_generator/__init__.py +0 -0
- endoreg_db/utils/case_generator/case_generator.py +159 -0
- endoreg_db/utils/case_generator/lab_sample_factory.py +33 -0
- endoreg_db/utils/case_generator/utils.py +30 -0
- endoreg_db/utils/check_video_files.py +148 -0
- endoreg_db/utils/dataloader.py +118 -35
- endoreg_db/utils/dates.py +60 -0
- endoreg_db/utils/env.py +33 -0
- endoreg_db/utils/extract_specific_frames.py +72 -0
- endoreg_db/utils/file_operations.py +29 -1
- endoreg_db/utils/fix_video_path_direct.py +141 -0
- endoreg_db/utils/frame_anonymization_utils.py +463 -0
- endoreg_db/utils/hashs.py +123 -4
- endoreg_db/utils/links/__init__.py +0 -0
- endoreg_db/utils/links/requirement_link.py +193 -0
- endoreg_db/utils/mime_types.py +0 -0
- endoreg_db/utils/names.py +76 -0
- endoreg_db/utils/parse_and_generate_yaml.py +46 -0
- endoreg_db/utils/paths.py +95 -0
- endoreg_db/utils/permissions.py +143 -0
- endoreg_db/utils/pipelines/Readme.md +235 -0
- endoreg_db/utils/pipelines/__init__.py +0 -0
- endoreg_db/utils/pipelines/process_video_dir.py +120 -0
- endoreg_db/utils/product/__init__.py +0 -0
- endoreg_db/utils/product/sum_emissions.py +20 -0
- endoreg_db/utils/product/sum_weights.py +18 -0
- endoreg_db/utils/pydantic_models/__init__.py +6 -0
- endoreg_db/utils/pydantic_models/db_config.py +57 -0
- endoreg_db/utils/requirement_helpers.py +0 -0
- endoreg_db/utils/requirement_operator_logic/__init__.py +0 -0
- endoreg_db/utils/requirement_operator_logic/lab_value_operators.py +578 -0
- endoreg_db/utils/requirement_operator_logic/model_evaluators.py +368 -0
- endoreg_db/utils/setup_config.py +177 -0
- endoreg_db/utils/translation.py +27 -0
- endoreg_db/utils/validate_endo_roi.py +19 -0
- endoreg_db/utils/validate_subcategory_dict.py +91 -0
- endoreg_db/utils/validate_video_detailed.py +357 -0
- endoreg_db/utils/video/__init__.py +26 -0
- endoreg_db/utils/video/extract_frames.py +88 -0
- endoreg_db/utils/video/ffmpeg_wrapper.py +835 -0
- endoreg_db/utils/video/names.py +42 -0
- endoreg_db/utils/video/streaming_processor.py +312 -0
- endoreg_db/utils/video/video_splitter.py +94 -0
- endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +238 -0
- endoreg_db/views/__init__.py +274 -0
- endoreg_db/views/anonymization/__init__.py +27 -0
- endoreg_db/views/anonymization/media_management.py +454 -0
- endoreg_db/views/anonymization/overview.py +216 -0
- endoreg_db/views/anonymization/validate.py +107 -0
- endoreg_db/views/auth/__init__.py +13 -0
- endoreg_db/views/auth/keycloak.py +113 -0
- endoreg_db/views/examination/__init__.py +33 -0
- endoreg_db/views/examination/examination.py +37 -0
- endoreg_db/views/examination/examination_manifest_cache.py +26 -0
- endoreg_db/views/examination/get_finding_classification_choices.py +59 -0
- endoreg_db/views/examination/get_finding_classifications.py +36 -0
- endoreg_db/views/examination/get_findings.py +41 -0
- endoreg_db/views/examination/get_instruments.py +18 -0
- endoreg_db/views/examination/get_interventions.py +14 -0
- endoreg_db/views/finding/__init__.py +9 -0
- endoreg_db/views/finding/finding.py +112 -0
- endoreg_db/views/finding/get_classifications.py +14 -0
- endoreg_db/views/finding/get_interventions.py +17 -0
- endoreg_db/views/finding_classification/__init__.py +13 -0
- endoreg_db/views/finding_classification/base.py +0 -0
- endoreg_db/views/finding_classification/finding_classification.py +42 -0
- endoreg_db/views/finding_classification/get_classification_choices.py +55 -0
- endoreg_db/views/label/__init__.py +5 -0
- endoreg_db/views/label/label.py +15 -0
- endoreg_db/views/label_video_segment/__init__.py +16 -0
- endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +44 -0
- endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +50 -0
- endoreg_db/views/label_video_segment/label_video_segment.py +77 -0
- endoreg_db/views/label_video_segment/label_video_segment_by_label.py +174 -0
- endoreg_db/views/label_video_segment/label_video_segment_detail.py +73 -0
- endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +46 -0
- endoreg_db/views/label_video_segment/validate.py +226 -0
- endoreg_db/views/media/__init__.py +45 -0
- endoreg_db/views/media/pdf_media.py +388 -0
- endoreg_db/views/media/segments.py +71 -0
- endoreg_db/views/media/sensitive_metadata.py +314 -0
- endoreg_db/views/media/video_media.py +272 -0
- endoreg_db/views/media/video_segments.py +524 -0
- endoreg_db/views/meta/__init__.py +15 -0
- endoreg_db/views/meta/available_files_list.py +146 -0
- endoreg_db/views/meta/report_meta.py +53 -0
- endoreg_db/views/meta/sensitive_meta_detail.py +148 -0
- endoreg_db/views/meta/sensitive_meta_list.py +104 -0
- endoreg_db/views/meta/sensitive_meta_verification.py +71 -0
- endoreg_db/views/misc/__init__.py +63 -0
- endoreg_db/views/misc/center.py +13 -0
- endoreg_db/views/misc/csrf.py +7 -0
- endoreg_db/views/misc/gender.py +14 -0
- endoreg_db/views/misc/secure_file_serving_view.py +80 -0
- endoreg_db/views/misc/secure_file_url_view.py +84 -0
- endoreg_db/views/misc/secure_url_validate.py +79 -0
- endoreg_db/views/misc/stats.py +220 -0
- endoreg_db/views/misc/translation.py +182 -0
- endoreg_db/views/misc/upload_views.py +240 -0
- endoreg_db/views/patient/__init__.py +5 -0
- endoreg_db/views/patient/patient.py +210 -0
- endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +164 -0
- endoreg_db/views/patient_examination/__init__.py +11 -0
- endoreg_db/views/patient_examination/patient_examination.py +140 -0
- endoreg_db/views/patient_examination/patient_examination_create.py +63 -0
- endoreg_db/views/patient_examination/patient_examination_detail.py +66 -0
- endoreg_db/views/patient_examination/patient_examination_list.py +68 -0
- endoreg_db/views/patient_examination/video.py +194 -0
- endoreg_db/views/patient_finding/__init__.py +7 -0
- endoreg_db/views/patient_finding/base.py +0 -0
- endoreg_db/views/patient_finding/patient_finding.py +64 -0
- endoreg_db/views/patient_finding/patient_finding_optimized.py +259 -0
- endoreg_db/views/patient_finding_classification/__init__.py +5 -0
- endoreg_db/views/patient_finding_classification/pfc_create.py +67 -0
- endoreg_db/views/patient_finding_location/__init__.py +5 -0
- endoreg_db/views/patient_finding_location/pfl_create.py +70 -0
- endoreg_db/views/patient_finding_morphology/__init__.py +5 -0
- endoreg_db/views/patient_finding_morphology/pfm_create.py +70 -0
- endoreg_db/views/pdf/__init__.py +8 -0
- endoreg_db/views/pdf/pdf_stream.py +187 -0
- endoreg_db/views/pdf/reimport.py +177 -0
- endoreg_db/views/report/__init__.py +9 -0
- endoreg_db/views/report/report_list.py +112 -0
- endoreg_db/views/report/report_with_secure_url.py +28 -0
- endoreg_db/views/report/start_examination.py +7 -0
- endoreg_db/views/requirement/__init__.py +10 -0
- endoreg_db/views/requirement/evaluate.py +279 -0
- endoreg_db/views/requirement/lookup.py +367 -0
- endoreg_db/views/requirement/lookup_store.py +252 -0
- endoreg_db/views/requirement_lookup/lookup.py +0 -0
- endoreg_db/views/requirement_lookup/lookup_store.py +0 -0
- endoreg_db/views/stats/__init__.py +13 -0
- endoreg_db/views/stats/stats_views.py +229 -0
- endoreg_db/views/video/__init__.py +59 -0
- endoreg_db/views/video/correction.py +530 -0
- endoreg_db/views/video/reimport.py +195 -0
- endoreg_db/views/video/segmentation.py +274 -0
- endoreg_db/views/video/task_status.py +49 -0
- endoreg_db/views/video/timeline.py +46 -0
- endoreg_db/views/video/video_analyze.py +52 -0
- endoreg_db/views/video/video_apply_mask.py +48 -0
- endoreg_db/views/video/video_correction.py +21 -0
- endoreg_db/views/video/video_download_processed.py +58 -0
- endoreg_db/views/video/video_examination_viewset.py +242 -0
- endoreg_db/views/video/video_meta.py +29 -0
- endoreg_db/views/video/video_processing_history.py +24 -0
- endoreg_db/views/video/video_remove_frames.py +48 -0
- endoreg_db/views/video/video_stream.py +306 -0
- endoreg_db/views.py +0 -3
- endoreg_db-0.8.6.3.dist-info/METADATA +383 -0
- endoreg_db-0.8.6.3.dist-info/RECORD +793 -0
- {endoreg_db-0.4.5.dist-info → endoreg_db-0.8.6.3.dist-info}/WHEEL +1 -1
- endoreg_db/data/active_model/data.yaml +0 -3
- endoreg_db/data/agl_service/data.yaml +0 -19
- endoreg_db/data/label/label-set/data.yaml +0 -18
- endoreg_db/management/commands/_load_model_template.py +0 -41
- endoreg_db/management/commands/delete_all.py +0 -18
- endoreg_db/management/commands/delete_legacy_images.py +0 -19
- endoreg_db/management/commands/delete_legacy_videos.py +0 -17
- endoreg_db/management/commands/extract_legacy_video_frames.py +0 -18
- endoreg_db/management/commands/fetch_legacy_image_dataset.py +0 -32
- endoreg_db/management/commands/fix_auth_permission.py +0 -20
- endoreg_db/management/commands/import_legacy_images.py +0 -94
- endoreg_db/management/commands/import_legacy_videos.py +0 -76
- endoreg_db/management/commands/load_active_model_data.py +0 -45
- endoreg_db/management/commands/load_endoscopy_processor_data.py +0 -45
- endoreg_db/management/commands/load_g_play_data.py +0 -113
- endoreg_db/management/commands/load_label_data.py +0 -67
- endoreg_db/management/commands/load_medication_indication_data.py +0 -63
- endoreg_db/management/commands/load_medication_indication_type_data.py +0 -41
- endoreg_db/management/commands/load_medication_schedule_data.py +0 -55
- endoreg_db/management/commands/load_network_data.py +0 -57
- endoreg_db/migrations/0002_anonymizedimagelabel_anonymousimageannotation_and_more.py +0 -55
- endoreg_db/migrations/0003_anonymousimageannotation_original_image_url_and_more.py +0 -39
- endoreg_db/migrations/0004_alter_rawpdffile_file.py +0 -20
- endoreg_db/migrations/0005_uploadedfile_alter_rawpdffile_file_anonymizedfile.py +0 -40
- endoreg_db/migrations/0006_alter_rawpdffile_file.py +0 -20
- endoreg_db/migrations/0007_networkdevicelogentry_datetime_and_more.py +0 -43
- endoreg_db/models/ai_model/__init__.py +0 -3
- endoreg_db/models/ai_model/active_model.py +0 -9
- endoreg_db/models/ai_model/model_meta.py +0 -24
- endoreg_db/models/annotation/__init__.py +0 -3
- endoreg_db/models/annotation/anonymized_image_annotation.py +0 -60
- endoreg_db/models/annotation/binary_classification_annotation_task.py +0 -80
- endoreg_db/models/annotation/image_classification.py +0 -27
- endoreg_db/models/center/center.py +0 -25
- endoreg_db/models/center/center_product.py +0 -34
- endoreg_db/models/center/center_resource.py +0 -19
- endoreg_db/models/center/center_waste.py +0 -11
- endoreg_db/models/data_file/__init__.py +0 -6
- endoreg_db/models/data_file/base_classes/__init__.py +0 -2
- endoreg_db/models/data_file/base_classes/abstract_frame.py +0 -51
- endoreg_db/models/data_file/base_classes/abstract_video.py +0 -201
- endoreg_db/models/data_file/frame.py +0 -45
- endoreg_db/models/data_file/import_classes/__init__.py +0 -32
- endoreg_db/models/data_file/import_classes/processing_functions/__init__.py +0 -35
- endoreg_db/models/data_file/import_classes/processing_functions/pdf.py +0 -28
- endoreg_db/models/data_file/import_classes/processing_functions/video.py +0 -260
- endoreg_db/models/data_file/import_classes/raw_pdf.py +0 -188
- endoreg_db/models/data_file/import_classes/raw_video.py +0 -343
- endoreg_db/models/data_file/metadata/__init__.py +0 -3
- endoreg_db/models/data_file/metadata/sensitive_meta.py +0 -31
- endoreg_db/models/data_file/metadata/video_meta.py +0 -133
- endoreg_db/models/data_file/report_file.py +0 -89
- endoreg_db/models/data_file/video/__init__.py +0 -7
- endoreg_db/models/data_file/video/import_meta.py +0 -25
- endoreg_db/models/data_file/video/video.py +0 -25
- endoreg_db/models/data_file/video_segment.py +0 -107
- endoreg_db/models/disease.py +0 -56
- endoreg_db/models/emission/__init__.py +0 -1
- endoreg_db/models/emission/emission_factor.py +0 -20
- endoreg_db/models/event.py +0 -22
- endoreg_db/models/examination/__init__.py +0 -4
- endoreg_db/models/examination/examination.py +0 -26
- endoreg_db/models/examination/examination_time.py +0 -27
- endoreg_db/models/examination/examination_time_type.py +0 -24
- endoreg_db/models/examination/examination_type.py +0 -18
- endoreg_db/models/hardware/__init__.py +0 -2
- endoreg_db/models/hardware/endoscope.py +0 -44
- endoreg_db/models/information_source.py +0 -29
- endoreg_db/models/laboratory/__init__.py +0 -1
- endoreg_db/models/laboratory/lab_value.py +0 -102
- endoreg_db/models/legacy_data/__init__.py +0 -3
- endoreg_db/models/legacy_data/image.py +0 -34
- endoreg_db/models/logging/__init__.py +0 -4
- endoreg_db/models/logging/agl_service.py +0 -19
- endoreg_db/models/logging/base.py +0 -22
- endoreg_db/models/logging/log_type.py +0 -23
- endoreg_db/models/logging/network_device.py +0 -24
- endoreg_db/models/medication/__init__.py +0 -1
- endoreg_db/models/medication/medication.py +0 -148
- endoreg_db/models/network/__init__.py +0 -3
- endoreg_db/models/network/agl_service.py +0 -38
- endoreg_db/models/network/network_device.py +0 -53
- endoreg_db/models/network/network_device_type.py +0 -23
- endoreg_db/models/other/distribution.py +0 -215
- endoreg_db/models/patient_examination/__init__.py +0 -35
- endoreg_db/models/permissions/__init__.py +0 -44
- endoreg_db/models/persons/__init__.py +0 -7
- endoreg_db/models/persons/examiner/__init__.py +0 -2
- endoreg_db/models/persons/examiner/examiner.py +0 -16
- endoreg_db/models/persons/examiner/examiner_type.py +0 -2
- endoreg_db/models/persons/patient/__init__.py +0 -8
- endoreg_db/models/persons/patient/case/case.py +0 -30
- endoreg_db/models/persons/patient/patient.py +0 -216
- endoreg_db/models/persons/patient/patient_disease.py +0 -16
- endoreg_db/models/persons/patient/patient_event.py +0 -22
- endoreg_db/models/persons/patient/patient_lab_sample.py +0 -106
- endoreg_db/models/persons/patient/patient_medication.py +0 -44
- endoreg_db/models/persons/patient/patient_medication_schedule.py +0 -28
- endoreg_db/models/persons/portal_user_information.py +0 -27
- endoreg_db/models/prediction/__init__.py +0 -2
- endoreg_db/models/prediction/image_classification.py +0 -37
- endoreg_db/models/prediction/video_prediction_meta.py +0 -244
- endoreg_db/models/product/__init__.py +0 -5
- endoreg_db/models/product/product.py +0 -97
- endoreg_db/models/product/product_group.py +0 -19
- endoreg_db/models/product/product_material.py +0 -24
- endoreg_db/models/questionnaires/__init__.py +0 -114
- endoreg_db/models/quiz/__init__.py +0 -2
- endoreg_db/models/quiz/quiz_answer.py +0 -41
- endoreg_db/models/quiz/quiz_question.py +0 -54
- endoreg_db/models/report_reader/__init__.py +0 -2
- endoreg_db/models/report_reader/report_reader_config.py +0 -53
- endoreg_db/models/rules/__init__.py +0 -5
- endoreg_db/queries/get/__init__.py +0 -6
- endoreg_db/queries/get/center.py +0 -42
- endoreg_db/queries/get/model.py +0 -13
- endoreg_db/queries/get/patient.py +0 -14
- endoreg_db/queries/get/patient_examination.py +0 -20
- endoreg_db/queries/get/report_file.py +0 -33
- endoreg_db/queries/get/video.py +0 -31
- endoreg_db/serializers/ai_model.py +0 -19
- endoreg_db/serializers/annotation.py +0 -17
- endoreg_db/serializers/center.py +0 -11
- endoreg_db/serializers/examination.py +0 -33
- endoreg_db/serializers/frame.py +0 -13
- endoreg_db/serializers/hardware.py +0 -21
- endoreg_db/serializers/label.py +0 -22
- endoreg_db/serializers/patient.py +0 -10
- endoreg_db/serializers/prediction.py +0 -15
- endoreg_db/serializers/report_file.py +0 -7
- endoreg_db/serializers/video.py +0 -27
- endoreg_db/tests.py +0 -3
- endoreg_db/utils/legacy_ocr.py +0 -201
- endoreg_db/utils/video_metadata.py +0 -87
- endoreg_db-0.4.5.dist-info/METADATA +0 -34
- endoreg_db-0.4.5.dist-info/RECORD +0 -316
- /endoreg_db/{data/distribution/numeric/.init → api/serializers/finding_descriptions.py} +0 -0
- /endoreg_db/{models/persons/patient/case/__init__.py → api/views/finding_descriptions.py} +0 -0
- /endoreg_db/{queries/get/annotation.py → config/__init__.py} +0 -0
- /endoreg_db/data/{label → ai_model_label}/label-type/data.yaml +0 -0
- /endoreg_db/data/{model_type → ai_model_type}/data.yaml +0 -0
- /endoreg_db/{queries/get/prediction.py → data/shift/m2.yaml} +0 -0
- /endoreg_db/{queries/get/video_import_meta.py → factories/__init__.py} +0 -0
- /endoreg_db/{queries/get/video_prediction_meta.py → helpers/__init__.py} +0 -0
- /endoreg_db/management/commands/{load_report_reader_flag.py → load_report_reader_flag_data.py} +0 -0
- /endoreg_db/models/{persons → administration/person}/person.py +0 -0
- /endoreg_db/models/{report_reader → media/pdf/report_reader}/report_reader_flag.py +0 -0
- /endoreg_db/models/{rules → rule}/rule_applicator.py +0 -0
- {endoreg_db-0.4.5.dist-info → endoreg_db-0.8.6.3.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,775 @@
|
|
|
1
|
+
from endoreg_db.utils.extract_specific_frames import extract_selected_frames
|
|
2
|
+
from rest_framework import serializers
|
|
3
|
+
from endoreg_db.models import Label, LabelVideoSegment
|
|
4
|
+
from itertools import combinations
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from django.conf import settings
|
|
7
|
+
# === CONFIGURABLE PARAMETERS - ForNiceClassificationSerializer ===
|
|
8
|
+
POLYP_LABEL_NAME = "polyp"
|
|
9
|
+
CHROMO_LABEL_NAMES = ["digital_chromo_endoscopy", "nbi"]
|
|
10
|
+
FPS = 50 # Frames per second- should fetch dynamically from videofile table
|
|
11
|
+
# Sequence-level filtering
|
|
12
|
+
MIN_SEQUENCE_GAP_SECONDS = 0.5 # Enforce diversity between sequences
|
|
13
|
+
MIN_SEQUENCE_GAP_FRAMES = FPS * MIN_SEQUENCE_GAP_SECONDS # Convert to frame count
|
|
14
|
+
# Minimum length of a segment in seconds
|
|
15
|
+
MIN_SEGMENT_LENGTH_SECONDS = 0.5
|
|
16
|
+
MIN_SEGMENT_LENGTH_FRAMES = FPS * MIN_SEGMENT_LENGTH_SECONDS
|
|
17
|
+
|
|
18
|
+
# Frame-level selection within a sequence
|
|
19
|
+
MIN_FRAME_GAP_SECONDS = 1 # Minimum gap between selected frames in seconds
|
|
20
|
+
MIN_FRAME_GAP_IN_SEQUENCE = FPS * MIN_FRAME_GAP_SECONDS # Convert to frame count
|
|
21
|
+
FRAMES_PER_SEQUENCE = 3 # Number of frames to select per matched sequence
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# === Frame Filtering Rules ===
|
|
25
|
+
# All rules must return True to accept the frame
|
|
26
|
+
FRAME_SELECTION_RULES = [
|
|
27
|
+
lambda pred: pred.get("low_quality", 1.0) < 0.1,
|
|
28
|
+
lambda pred: pred.get("outside", 1.0) < 0.1,
|
|
29
|
+
lambda pred: pred.get("snare", 1.0) < 0.1,
|
|
30
|
+
|
|
31
|
+
# Add more rules easily here
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
REQUIRED_FRAME_KEYS = ["low_quality", "outside", "snare"] # need tp update when adding rules
|
|
35
|
+
|
|
36
|
+
POLYP_CONFIDENCE_THRESHOLDS = [0.9, 0.8, 0.7] # basically this is the prediction value/score, we are using for frame selection
|
|
37
|
+
INSTRUMENT_LABEL_NAMES = ["instrument", "snare", "needle"] # Add more as needed later
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class BaseClassificationSerializer(serializers.Serializer):
|
|
41
|
+
"""
|
|
42
|
+
Base class for NICE and PARIS serializers.
|
|
43
|
+
Handles label lookup, chromo/instrument segment filtering, and shared utilities.
|
|
44
|
+
"""
|
|
45
|
+
#TODO add create method
|
|
46
|
+
#TODO add update method
|
|
47
|
+
LABEL_NAME = "polyp" # default (can be overridden)
|
|
48
|
+
INSTRUMENT_LABEL_NAME = "instrument" #TODO @Hamzaukw we should define frequently used labels in a utils file
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_label_id_by_name(self, label_name):
|
|
52
|
+
"""
|
|
53
|
+
Get the ID of a label by its name.
|
|
54
|
+
Raises a validation error if not found.
|
|
55
|
+
"""
|
|
56
|
+
try:
|
|
57
|
+
label = Label.objects.get(name=label_name)
|
|
58
|
+
return label.id
|
|
59
|
+
except Label.DoesNotExist:
|
|
60
|
+
raise serializers.ValidationError({
|
|
61
|
+
"error": f"Label with name '{label_name}' does not exist."
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
def get_label_ids_by_names(self, label_names):
|
|
65
|
+
"""
|
|
66
|
+
Get a list of label IDs for a given list of label names.
|
|
67
|
+
Ensures all names exist in the database.
|
|
68
|
+
"""
|
|
69
|
+
labels = Label.objects.filter(name__in=label_names)
|
|
70
|
+
label_map = {label.name: label.id for label in labels}
|
|
71
|
+
|
|
72
|
+
missing = set(label_names) - set(label_map.keys())
|
|
73
|
+
if missing:
|
|
74
|
+
raise serializers.ValidationError({
|
|
75
|
+
"error": f"Labels not found: {', '.join(missing)}"
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return list(label_map.values())
|
|
79
|
+
|
|
80
|
+
def get_chromo_segments(self, video_id):
|
|
81
|
+
"""
|
|
82
|
+
Fetch all segments that match chromo-like labels (e.g., chromo or NBI).
|
|
83
|
+
Used in both NICE and PARIS, but interpreted differently:
|
|
84
|
+
- NICE: chromo overlap is required
|
|
85
|
+
- PARIS: chromo overlap is disqualifying
|
|
86
|
+
"""
|
|
87
|
+
chromo_label_ids = self.get_label_ids_by_names(CHROMO_LABEL_NAMES)
|
|
88
|
+
return LabelVideoSegment.objects.filter(label_id__in=chromo_label_ids, video_file_id=video_id)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def get_filtered_polyp_segments(self, video_id):
|
|
93
|
+
"""
|
|
94
|
+
Return polyp segments that do NOT overlap with 'instrument' segments.
|
|
95
|
+
"""
|
|
96
|
+
polyp_label_id = self.get_label_id_by_name(self.LABEL_NAME)
|
|
97
|
+
instrument_label_id = self.get_label_id_by_name(self.INSTRUMENT_LABEL_NAME)
|
|
98
|
+
|
|
99
|
+
print("polyp label id is :-", polyp_label_id,"and - instrument_label_id is ,", instrument_label_id)
|
|
100
|
+
|
|
101
|
+
polyp_segments = LabelVideoSegment.objects.filter(
|
|
102
|
+
label_id=polyp_label_id, video_file_id=video_id
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
instrument_segments = LabelVideoSegment.objects.filter(
|
|
106
|
+
label_id=instrument_label_id, video_file_id=video_id
|
|
107
|
+
)
|
|
108
|
+
print("------------------------ --------------------------------- -------------------------------")
|
|
109
|
+
print("polyp label id is :-", polyp_label_id,"and - instrument_label_id is ,", instrument_label_id)
|
|
110
|
+
print("polyp segments are",polyp_segments , "instrument_segments are", instrument_segments)
|
|
111
|
+
|
|
112
|
+
def overlaps(seg1, seg2):
|
|
113
|
+
return seg1.start_frame_number <= seg2.end_frame_number and seg1.end_frame_number >= seg2.start_frame_number
|
|
114
|
+
|
|
115
|
+
filtered_polyp_segments = []
|
|
116
|
+
for polyp_seg in polyp_segments:
|
|
117
|
+
if not any(overlaps(polyp_seg, instr_seg) for instr_seg in instrument_segments):
|
|
118
|
+
filtered_polyp_segments.append(polyp_seg)
|
|
119
|
+
|
|
120
|
+
return filtered_polyp_segments
|
|
121
|
+
|
|
122
|
+
def get_polyp_segments(self, video_id):
|
|
123
|
+
polyp_label_id = self.get_label_id_by_name(self.LABEL_NAME)
|
|
124
|
+
return LabelVideoSegment.objects.filter(label_id=polyp_label_id, video_file_id=video_id)
|
|
125
|
+
|
|
126
|
+
def apply_sequence_diversity(self, matching_segments):
|
|
127
|
+
if not matching_segments:
|
|
128
|
+
return []
|
|
129
|
+
|
|
130
|
+
matching_segments.sort(key=lambda seg: seg['polyp'].start_frame_number)
|
|
131
|
+
|
|
132
|
+
valid_segments = [
|
|
133
|
+
seg for seg in matching_segments
|
|
134
|
+
if (seg['polyp'].end_frame_number - seg['polyp'].start_frame_number) >= MIN_SEGMENT_LENGTH_FRAMES
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
if len(valid_segments) < 3:
|
|
138
|
+
valid_segments.sort(
|
|
139
|
+
key=lambda seg: seg['polyp'].end_frame_number - seg['polyp'].start_frame_number,
|
|
140
|
+
reverse=True
|
|
141
|
+
)
|
|
142
|
+
return valid_segments[:3]
|
|
143
|
+
|
|
144
|
+
best_combo = None
|
|
145
|
+
best_gap_sum = -1
|
|
146
|
+
|
|
147
|
+
for combo in combinations(valid_segments, 3):
|
|
148
|
+
sorted_combo = sorted(combo, key=lambda seg: seg['polyp'].start_frame_number)
|
|
149
|
+
s1, s2, s3 = sorted_combo
|
|
150
|
+
s1_end = s1['polyp'].end_frame_number
|
|
151
|
+
s2_start = s2['polyp'].start_frame_number
|
|
152
|
+
s2_end = s2['polyp'].end_frame_number
|
|
153
|
+
s3_start = s3['polyp'].start_frame_number
|
|
154
|
+
gap1 = s2_start - s1_end
|
|
155
|
+
gap2 = s3_start - s2_end
|
|
156
|
+
|
|
157
|
+
if gap1 >= MIN_SEQUENCE_GAP_FRAMES and gap2 >= MIN_SEQUENCE_GAP_FRAMES:
|
|
158
|
+
total_gap = gap1 + gap2
|
|
159
|
+
if total_gap > best_gap_sum:
|
|
160
|
+
best_gap_sum = total_gap
|
|
161
|
+
best_combo = sorted_combo
|
|
162
|
+
|
|
163
|
+
if best_combo:
|
|
164
|
+
return list(best_combo)
|
|
165
|
+
|
|
166
|
+
valid_segments.sort(
|
|
167
|
+
key=lambda seg: seg['polyp'].end_frame_number - seg['polyp'].start_frame_number,
|
|
168
|
+
reverse=True
|
|
169
|
+
)
|
|
170
|
+
return valid_segments[:3]
|
|
171
|
+
|
|
172
|
+
def select_frames_for_sequence(self, sequence):
|
|
173
|
+
"""
|
|
174
|
+
Selects evenly spaced representative frames from a polyp segment.
|
|
175
|
+
|
|
176
|
+
Frames are chosen from the segment's frame range, ensuring a minimum gap between selected frames. Returns a list of dictionaries containing frame numbers and their corresponding file paths. If the video's frame directory is unavailable, returns an empty list.
|
|
177
|
+
"""
|
|
178
|
+
polyp_sequence = sequence['polyp']
|
|
179
|
+
video = polyp_sequence.video_file
|
|
180
|
+
|
|
181
|
+
start_frame = polyp_sequence.start_frame_number
|
|
182
|
+
end_frame = polyp_sequence.end_frame_number
|
|
183
|
+
|
|
184
|
+
frame_dir = getattr(video, "frame_dir", "")
|
|
185
|
+
|
|
186
|
+
if not frame_dir:
|
|
187
|
+
return []
|
|
188
|
+
|
|
189
|
+
# Just create frames assuming predictions aren't available
|
|
190
|
+
segment_frames = [
|
|
191
|
+
{
|
|
192
|
+
"frame_number": idx,
|
|
193
|
+
"frame_path": f"{frame_dir}/frame_{str(idx).zfill(7)}.png"
|
|
194
|
+
}
|
|
195
|
+
for idx in range(start_frame, end_frame + 1)
|
|
196
|
+
]
|
|
197
|
+
|
|
198
|
+
selected_frames = []
|
|
199
|
+
last_selected_frame = -float('inf')
|
|
200
|
+
|
|
201
|
+
for frame in segment_frames:
|
|
202
|
+
if len(selected_frames) >= FRAMES_PER_SEQUENCE:
|
|
203
|
+
break
|
|
204
|
+
|
|
205
|
+
if frame["frame_number"] - last_selected_frame >= MIN_FRAME_GAP_IN_SEQUENCE:
|
|
206
|
+
selected_frames.append({
|
|
207
|
+
"frame_number": frame["frame_number"],
|
|
208
|
+
"frame_path": frame["frame_path"]
|
|
209
|
+
})
|
|
210
|
+
last_selected_frame = frame["frame_number"]
|
|
211
|
+
|
|
212
|
+
return selected_frames
|
|
213
|
+
|
|
214
|
+
def extract_and_save_selected_frames(self, video, frame_numbers, classification_type: str):
|
|
215
|
+
"""
|
|
216
|
+
Extract specific frames from the original video file and save them
|
|
217
|
+
into a structured folder path based on the classification type.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
video (VideoFile): Video object with `original_file_name` and `frame_dir`.
|
|
221
|
+
frame_numbers (List[int]): List of frame numbers to extract.
|
|
222
|
+
classification_type (str): Either "nice" or "paris".
|
|
223
|
+
"""
|
|
224
|
+
# Resolve the path to the original video
|
|
225
|
+
original_path = Path(video.original_file_name)
|
|
226
|
+
if not original_path.is_absolute():
|
|
227
|
+
base_video_dir = settings.BASE_DIR.parent.parent / "production_test" / "endoreg-db" / "data" / "coloreg_first_test_batch"
|
|
228
|
+
original_path = base_video_dir / original_path
|
|
229
|
+
|
|
230
|
+
# Define output directory based on classification and video ID
|
|
231
|
+
output_path = Path(video.frame_dir) / classification_type / f"video_{video.id}"
|
|
232
|
+
|
|
233
|
+
# Extract frames using the shared utility
|
|
234
|
+
extract_selected_frames(
|
|
235
|
+
video_path=original_path,
|
|
236
|
+
frame_numbers=frame_numbers,
|
|
237
|
+
output_dir=output_path,
|
|
238
|
+
fps=FPS
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
''' # # If any error occurs in this function, use the commented one below(fallback:select_frames_for_sequence).
|
|
243
|
+
def select_frames_for_sequence(self, sequence):
|
|
244
|
+
# Extract the polyp segment from the current sequence
|
|
245
|
+
polyp_sequence = sequence['polyp']
|
|
246
|
+
video = polyp_sequence.video
|
|
247
|
+
|
|
248
|
+
# Get the start and end frame numbers of the segment/sequence
|
|
249
|
+
start_frame = polyp_sequence.start_frame_number
|
|
250
|
+
end_frame = polyp_sequence.end_frame_number
|
|
251
|
+
|
|
252
|
+
# here we aregetting the predictions and frame directory from the video object
|
|
253
|
+
predictions = getattr(video, "readable_predictions", [])
|
|
254
|
+
frame_dir = getattr(video, "frame_dir", "") #need to check
|
|
255
|
+
|
|
256
|
+
# If either predictions or frame_dir is missing, return an empty list
|
|
257
|
+
if not predictions or not frame_dir:
|
|
258
|
+
return []
|
|
259
|
+
|
|
260
|
+
# Build a list of prediction dictionaries for each frame in the segment
|
|
261
|
+
# Each entry includes frame number, selected prediction keys, path, and full prediction
|
|
262
|
+
segment_predictions = [
|
|
263
|
+
{
|
|
264
|
+
"frame_number": idx,
|
|
265
|
+
**{key: pred.get(key, 1.0) for key in REQUIRED_FRAME_KEYS + ["polyp"]},
|
|
266
|
+
"frame_path": f"{frame_dir}/frame_{str(idx).zfill(7)}.jpg",
|
|
267
|
+
"prediction": pred
|
|
268
|
+
}
|
|
269
|
+
for idx, pred in enumerate(predictions[start_frame:end_frame + 1], start=start_frame)
|
|
270
|
+
if isinstance(pred, dict)
|
|
271
|
+
]
|
|
272
|
+
|
|
273
|
+
# Sort the frames by lowest 'low_quality' value first,# for higher quality images// changeable,
|
|
274
|
+
segment_predictions.sort(key=lambda x: x["low_quality"])
|
|
275
|
+
|
|
276
|
+
# Try frame selection with decreasing polyp confidence thresholds
|
|
277
|
+
#for polyp_threshold in [0.9, 0.8, 0.7]:
|
|
278
|
+
for polyp_threshold in POLYP_CONFIDENCE_THRESHOLDS:
|
|
279
|
+
|
|
280
|
+
# Filter frames that meet the current polyp threshold
|
|
281
|
+
candidate_frames = [
|
|
282
|
+
frame for frame in segment_predictions
|
|
283
|
+
if frame["prediction"].get("polyp", 0.0) > polyp_threshold
|
|
284
|
+
]
|
|
285
|
+
|
|
286
|
+
# If no candidates at this threshold, try the next lower threshold
|
|
287
|
+
if not candidate_frames:
|
|
288
|
+
continue
|
|
289
|
+
|
|
290
|
+
# Initialize list of selected frames and track last selected frame number
|
|
291
|
+
selected_frames = []
|
|
292
|
+
last_selected_frame = -float('inf')
|
|
293
|
+
|
|
294
|
+
# Iterate through the candidate frames
|
|
295
|
+
for frame in candidate_frames:
|
|
296
|
+
# Stop if we've already selected enough frames
|
|
297
|
+
if len(selected_frames) >= FRAMES_PER_SEQUENCE:
|
|
298
|
+
break
|
|
299
|
+
|
|
300
|
+
# Apply the standard filtering rules and spacing condition
|
|
301
|
+
if (
|
|
302
|
+
frame["prediction"].get("low_quality", 1.0) < 0.1 and
|
|
303
|
+
frame["prediction"].get("outside", 1.0) < 0.1 and
|
|
304
|
+
frame["prediction"].get("snare", 1.0) < 0.1 and
|
|
305
|
+
frame["frame_number"] - last_selected_frame >= MIN_FRAME_GAP_IN_SEQUENCE
|
|
306
|
+
):
|
|
307
|
+
# Frame passes all filters and spacing rule, so select it
|
|
308
|
+
selected_frames.append({
|
|
309
|
+
"frame_number": frame["frame_number"],
|
|
310
|
+
"low_quality": frame["low_quality"],
|
|
311
|
+
"polyp_score": frame["prediction"]["polyp"],
|
|
312
|
+
"frame_path": frame["frame_path"]
|
|
313
|
+
})
|
|
314
|
+
last_selected_frame = frame["frame_number"]
|
|
315
|
+
|
|
316
|
+
# If we found enough valid frames at this threshold, return them
|
|
317
|
+
if len(selected_frames) >= FRAMES_PER_SEQUENCE:
|
|
318
|
+
return selected_frames
|
|
319
|
+
|
|
320
|
+
# If no threshold yielded enough frames, return what was found in the last attempt (could be empty)
|
|
321
|
+
return selected_frames if selected_frames else []'''
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
# fallback:select_frames_for_sequence
|
|
325
|
+
'''
|
|
326
|
+
def select_frames_for_sequence(self, sequence):
|
|
327
|
+
print("----------------------in selected_frames fro sequnces funtion ----------------------------------------")
|
|
328
|
+
polyp_sequence = sequence['polyp']
|
|
329
|
+
video = polyp_sequence.video
|
|
330
|
+
start_frame = polyp_sequence.start_frame_number
|
|
331
|
+
end_frame = polyp_sequence.end_frame_number
|
|
332
|
+
predictions = getattr(video, "readable_predictions", [])
|
|
333
|
+
frame_dir = getattr(video, "frame_dir", "")
|
|
334
|
+
|
|
335
|
+
if not predictions or not frame_dir:
|
|
336
|
+
return []
|
|
337
|
+
|
|
338
|
+
segment_predictions = [
|
|
339
|
+
{
|
|
340
|
+
"frame_number": idx,
|
|
341
|
+
**{key: pred.get(key, 1.0) for key in REQUIRED_FRAME_KEYS},
|
|
342
|
+
"frame_path": f"{frame_dir}/frame_{str(idx).zfill(7)}.jpg",
|
|
343
|
+
"prediction": pred
|
|
344
|
+
}
|
|
345
|
+
for idx, pred in enumerate(predictions[start_frame:end_frame + 1], start=start_frame)
|
|
346
|
+
if isinstance(pred, dict)
|
|
347
|
+
]
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
segment_predictions.sort(key=lambda x: x["low_quality"])
|
|
351
|
+
|
|
352
|
+
selected_frames = []
|
|
353
|
+
last_selected_frame = -float('inf')
|
|
354
|
+
|
|
355
|
+
for frame in segment_predictions:
|
|
356
|
+
if len(selected_frames) >= FRAMES_PER_SEQUENCE:
|
|
357
|
+
break
|
|
358
|
+
|
|
359
|
+
if all(rule(frame["prediction"]) for rule in FRAME_SELECTION_RULES):
|
|
360
|
+
if frame["frame_number"] - last_selected_frame >= MIN_FRAME_GAP_IN_SEQUENCE:
|
|
361
|
+
selected_frames.append({
|
|
362
|
+
"frame_number": frame["frame_number"],
|
|
363
|
+
"low_quality": frame["low_quality"],
|
|
364
|
+
"frame_path": frame["frame_path"]
|
|
365
|
+
})
|
|
366
|
+
last_selected_frame = frame["frame_number"]
|
|
367
|
+
|
|
368
|
+
return selected_frames'''
|
|
369
|
+
class ForNiceClassificationSerializer(BaseClassificationSerializer):
|
|
370
|
+
"""
|
|
371
|
+
NICE classification logic:
|
|
372
|
+
- Requires polyp segments
|
|
373
|
+
- Filters out any overlap with instrument labels
|
|
374
|
+
- Requires overlap with chromo-like labels (chromo/NBI)
|
|
375
|
+
- Selects diverse sequences and representative frames from each
|
|
376
|
+
"""
|
|
377
|
+
def get_matching_sequences(self, video_id):
|
|
378
|
+
"""
|
|
379
|
+
1. Fetch all polyp segments in a video
|
|
380
|
+
2. Remove parts overlapping with any instrument-type labels
|
|
381
|
+
3. Keep only parts that still overlap with chromo/NBI
|
|
382
|
+
4. Trim segments accordingly and return valid subsegments
|
|
383
|
+
"""
|
|
384
|
+
polyp_label_id = self.get_label_id_by_name(self.LABEL_NAME)
|
|
385
|
+
instrument_label_ids = self.get_label_ids_by_names(INSTRUMENT_LABEL_NAMES)
|
|
386
|
+
#chromo_label_id = self.get_label_id_by_name(CHROMO_LABEL_NAME)
|
|
387
|
+
chromo_segments = self.get_chromo_segments(video_id)
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
polyp_segments = LabelVideoSegment.objects.filter(label_id=polyp_label_id, video_file_id=video_id)
|
|
391
|
+
instrument_segments = LabelVideoSegment.objects.filter(label_id__in=instrument_label_ids, video_file_id=video_id)
|
|
392
|
+
|
|
393
|
+
#chromo_segments = LabelVideoSegment.objects.filter(label_id=chromo_label_id, video_file_id=video_id)
|
|
394
|
+
print("polyp_label_id is", polyp_label_id, "and ployp_segment is ", polyp_segments)
|
|
395
|
+
print("instrument_segments is", instrument_segments)
|
|
396
|
+
#print("chromo_segments is ",chromo_segments)
|
|
397
|
+
|
|
398
|
+
def overlaps(seg1, seg2):
|
|
399
|
+
return seg1.start_frame_number <= seg2.end_frame_number and seg1.end_frame_number >= seg2.start_frame_number
|
|
400
|
+
|
|
401
|
+
def subtract_overlap(seg, overlaps):
|
|
402
|
+
start = seg.start_frame_number
|
|
403
|
+
end = seg.end_frame_number
|
|
404
|
+
blocks = [(o.start_frame_number, o.end_frame_number) for o in overlaps]
|
|
405
|
+
blocks.sort()
|
|
406
|
+
|
|
407
|
+
safe_ranges = []
|
|
408
|
+
curr = start
|
|
409
|
+
|
|
410
|
+
for o_start, o_end in blocks:
|
|
411
|
+
if o_end < curr:
|
|
412
|
+
continue
|
|
413
|
+
if o_start > end:
|
|
414
|
+
break
|
|
415
|
+
if o_start > curr:
|
|
416
|
+
safe_ranges.append((curr, min(o_start - 1, end)))
|
|
417
|
+
curr = max(curr, o_end + 1)
|
|
418
|
+
|
|
419
|
+
if curr <= end:
|
|
420
|
+
safe_ranges.append((curr, end))
|
|
421
|
+
|
|
422
|
+
return safe_ranges
|
|
423
|
+
|
|
424
|
+
matching_segments = []
|
|
425
|
+
|
|
426
|
+
for polyp in polyp_segments:
|
|
427
|
+
overlapping_instr = [seg for seg in instrument_segments if overlaps(polyp, seg)]
|
|
428
|
+
safe_ranges = subtract_overlap(polyp, overlapping_instr)
|
|
429
|
+
|
|
430
|
+
for start, end in safe_ranges:
|
|
431
|
+
if end - start + 1 < MIN_SEGMENT_LENGTH_FRAMES:
|
|
432
|
+
continue
|
|
433
|
+
|
|
434
|
+
for chromo in chromo_segments:
|
|
435
|
+
if chromo.start_frame_number <= end and chromo.end_frame_number >= start:
|
|
436
|
+
overlap_start = max(start, chromo.start_frame_number)
|
|
437
|
+
overlap_end = min(end, chromo.end_frame_number)
|
|
438
|
+
|
|
439
|
+
if overlap_end - overlap_start + 1 >= MIN_SEGMENT_LENGTH_FRAMES:
|
|
440
|
+
overlapping_segment = LabelVideoSegment(
|
|
441
|
+
video_file=polyp.video_file,
|
|
442
|
+
start_frame_number=overlap_start,
|
|
443
|
+
end_frame_number=overlap_end
|
|
444
|
+
)
|
|
445
|
+
matching_segments.append({'polyp': overlapping_segment})
|
|
446
|
+
|
|
447
|
+
return matching_segments
|
|
448
|
+
|
|
449
|
+
def to_representation(self, videos):
|
|
450
|
+
"""
|
|
451
|
+
Processes a list of videos:
|
|
452
|
+
- Applies NICE/PARIS rules to find segments
|
|
453
|
+
- Applies sequence diversity logic
|
|
454
|
+
- Selects frames per segment
|
|
455
|
+
- Extracts all frames for a video in a single call
|
|
456
|
+
- Returns structured output with messages per video
|
|
457
|
+
"""
|
|
458
|
+
results = []
|
|
459
|
+
|
|
460
|
+
for video in videos:
|
|
461
|
+
try:
|
|
462
|
+
video_id = video.id
|
|
463
|
+
print("video-id is", video_id)
|
|
464
|
+
|
|
465
|
+
matching_segments = self.get_matching_sequences(video_id)
|
|
466
|
+
print("matching_segments are", matching_segments)
|
|
467
|
+
if not matching_segments:
|
|
468
|
+
results.append({
|
|
469
|
+
"video_id": video_id,
|
|
470
|
+
"message": "No valid polyp segments overlapping with chromo and not overlapping with instrument."
|
|
471
|
+
})
|
|
472
|
+
continue
|
|
473
|
+
|
|
474
|
+
diverse_segments = self.apply_sequence_diversity(matching_segments)
|
|
475
|
+
if not diverse_segments:
|
|
476
|
+
results.append({
|
|
477
|
+
"video_id": video_id,
|
|
478
|
+
"message": "No diverse NICE sequences found — either too short or too close together."
|
|
479
|
+
})
|
|
480
|
+
continue
|
|
481
|
+
|
|
482
|
+
# Collect all frame numbers to extract only once per video
|
|
483
|
+
all_frames = []
|
|
484
|
+
segment_results = []
|
|
485
|
+
|
|
486
|
+
for segment in diverse_segments:
|
|
487
|
+
frames = self.select_frames_for_sequence(segment)
|
|
488
|
+
|
|
489
|
+
if not frames:
|
|
490
|
+
segment_results.append({
|
|
491
|
+
"video_id": video_id,
|
|
492
|
+
"segment_start": segment['polyp'].start_frame_number,
|
|
493
|
+
"segment_end": segment['polyp'].end_frame_number,
|
|
494
|
+
"message": "No valid frames passed filtering rules (low_quality, outside, snare)."
|
|
495
|
+
})
|
|
496
|
+
else:
|
|
497
|
+
segment_results.append({
|
|
498
|
+
"video_id": video_id,
|
|
499
|
+
"segment_start": segment['polyp'].start_frame_number,
|
|
500
|
+
"segment_end": segment['polyp'].end_frame_number,
|
|
501
|
+
"frames": frames
|
|
502
|
+
})
|
|
503
|
+
all_frames.extend(frames)
|
|
504
|
+
|
|
505
|
+
# Extract once per video
|
|
506
|
+
if all_frames:
|
|
507
|
+
unique_frame_numbers = sorted({f["frame_number"] for f in all_frames})
|
|
508
|
+
classification_type = "nice" if isinstance(self, ForNiceClassificationSerializer) else "paris"
|
|
509
|
+
self.extract_and_save_selected_frames(video, unique_frame_numbers, classification_type)
|
|
510
|
+
|
|
511
|
+
results.extend(segment_results)
|
|
512
|
+
|
|
513
|
+
except Exception as e:
|
|
514
|
+
results.append({
|
|
515
|
+
"video_id": video.id,
|
|
516
|
+
"error": str(e)
|
|
517
|
+
})
|
|
518
|
+
|
|
519
|
+
if not results:
|
|
520
|
+
return [{
|
|
521
|
+
"message": "No classification data generated for any videos."
|
|
522
|
+
}]
|
|
523
|
+
|
|
524
|
+
return {
|
|
525
|
+
"message": "NICE classification data generated." if isinstance(self, ForNiceClassificationSerializer)
|
|
526
|
+
else "PARIS classification data generated.",
|
|
527
|
+
"data": results
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
class ForParisClassificationSerializer(BaseClassificationSerializer):
|
|
535
|
+
"""
|
|
536
|
+
PARIS classification logic:
|
|
537
|
+
- Requires polyp segments
|
|
538
|
+
- Excludes any region overlapping with instruments or chromo/NBI
|
|
539
|
+
- Keeps remaining 'clean' subsegments
|
|
540
|
+
- Enforces minimum length and sequence diversity
|
|
541
|
+
- Selects frames from each valid segment
|
|
542
|
+
"""
|
|
543
|
+
|
|
544
|
+
def get_filtered_polyp_segments(self, video_id):
|
|
545
|
+
"""
|
|
546
|
+
1. Fetch all polyp segments
|
|
547
|
+
2. Subtract any overlap with chromo or instrument segments
|
|
548
|
+
3. Keep only trimmed segments longer than the minimum threshold
|
|
549
|
+
"""
|
|
550
|
+
|
|
551
|
+
polyp_label_id = self.get_label_id_by_name(self.LABEL_NAME)
|
|
552
|
+
instrument_label_ids = self.get_label_ids_by_names(INSTRUMENT_LABEL_NAMES)
|
|
553
|
+
#chromo_label_id = self.get_label_id_by_name(CHROMO_LABEL_NAME)
|
|
554
|
+
|
|
555
|
+
polyp_segments = LabelVideoSegment.objects.filter(label_id=polyp_label_id, video_file_id=video_id)
|
|
556
|
+
instrument_segments = LabelVideoSegment.objects.filter(label_id__in=instrument_label_ids, video_file_id=video_id)
|
|
557
|
+
#chromo_segments = LabelVideoSegment.objects.filter(label_id=chromo_label_id, video_file_id=video_id)
|
|
558
|
+
chromo_segments = self.get_chromo_segments(video_id)
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
def overlaps(seg1, seg2):
|
|
562
|
+
return seg1.start_frame_number <= seg2.end_frame_number and seg1.end_frame_number >= seg2.start_frame_number
|
|
563
|
+
|
|
564
|
+
def subtract_overlap(seg, overlaps):
|
|
565
|
+
"""
|
|
566
|
+
Given a base segment and list of overlapping segments,
|
|
567
|
+
returns list of non-overlapping sub-segments.
|
|
568
|
+
"""
|
|
569
|
+
start = seg.start_frame_number
|
|
570
|
+
end = seg.end_frame_number
|
|
571
|
+
blocks = [(o.start_frame_number, o.end_frame_number) for o in overlaps]
|
|
572
|
+
blocks.sort()
|
|
573
|
+
|
|
574
|
+
safe_ranges = []
|
|
575
|
+
curr = start
|
|
576
|
+
|
|
577
|
+
for o_start, o_end in blocks:
|
|
578
|
+
if o_end < curr:
|
|
579
|
+
continue
|
|
580
|
+
if o_start > end:
|
|
581
|
+
break
|
|
582
|
+
if o_start > curr:
|
|
583
|
+
safe_ranges.append((curr, min(o_start - 1, end)))
|
|
584
|
+
curr = max(curr, o_end + 1)
|
|
585
|
+
|
|
586
|
+
if curr <= end:
|
|
587
|
+
safe_ranges.append((curr, end))
|
|
588
|
+
|
|
589
|
+
return safe_ranges
|
|
590
|
+
|
|
591
|
+
# Final valid sub-segments
|
|
592
|
+
trimmed_segments = []
|
|
593
|
+
|
|
594
|
+
for polyp_seg in polyp_segments:
|
|
595
|
+
# Collect all overlapping regions with instrument or chromo
|
|
596
|
+
overlapping = [
|
|
597
|
+
seg for seg in (list(instrument_segments) + list(chromo_segments))
|
|
598
|
+
if overlaps(polyp_seg, seg)
|
|
599
|
+
]
|
|
600
|
+
|
|
601
|
+
safe_ranges = subtract_overlap(polyp_seg, overlapping)
|
|
602
|
+
|
|
603
|
+
for start, end in safe_ranges:
|
|
604
|
+
if end - start + 1 >= MIN_SEGMENT_LENGTH_FRAMES:
|
|
605
|
+
trimmed_segments.append(LabelVideoSegment(
|
|
606
|
+
video_file=polyp_seg.video_file,
|
|
607
|
+
start_frame_number=start,
|
|
608
|
+
end_frame_number=end
|
|
609
|
+
))
|
|
610
|
+
|
|
611
|
+
return trimmed_segments
|
|
612
|
+
|
|
613
|
+
filtered_segments = []
|
|
614
|
+
for polyp_seg in polyp_segments:
|
|
615
|
+
if not any(overlaps(polyp_seg, instr_seg) for instr_seg in instrument_segments) and \
|
|
616
|
+
not any(overlaps(polyp_seg, chromo_seg) for chromo_seg in chromo_segments):
|
|
617
|
+
filtered_segments.append(polyp_seg)
|
|
618
|
+
|
|
619
|
+
return filtered_segments
|
|
620
|
+
|
|
621
|
+
def get_matching_sequences(self, video_id):
|
|
622
|
+
"""
|
|
623
|
+
Wraps all valid polyp subsegments into a uniform data structure.
|
|
624
|
+
This is needed for consistent downstream processing.
|
|
625
|
+
"""
|
|
626
|
+
segments = self.get_filtered_polyp_segments(video_id)
|
|
627
|
+
return [{'polyp': seg} for seg in segments]
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
def to_representation(self, videos):
|
|
631
|
+
"""
|
|
632
|
+
Processes videos for PARIS classification.
|
|
633
|
+
Filters segments, selects diverse sequences, and picks valid frames.
|
|
634
|
+
Extracts all selected frames once per video.
|
|
635
|
+
Returns detailed per-video feedback or results.
|
|
636
|
+
"""
|
|
637
|
+
results = []
|
|
638
|
+
|
|
639
|
+
for video in videos:
|
|
640
|
+
try:
|
|
641
|
+
video_id = video.id
|
|
642
|
+
matching_segments = self.get_matching_sequences(video_id)
|
|
643
|
+
|
|
644
|
+
if not matching_segments:
|
|
645
|
+
results.append({
|
|
646
|
+
"video_id": video_id,
|
|
647
|
+
"message": "No matching polyp segments found — possibly filtered due to overlap with 'instrument' label."
|
|
648
|
+
})
|
|
649
|
+
continue
|
|
650
|
+
|
|
651
|
+
diverse_segments = self.apply_sequence_diversity(matching_segments)
|
|
652
|
+
if not diverse_segments:
|
|
653
|
+
results.append({
|
|
654
|
+
"video_id": video_id,
|
|
655
|
+
"message": "No diverse sequences found — either too short or too close to each other."
|
|
656
|
+
})
|
|
657
|
+
continue
|
|
658
|
+
|
|
659
|
+
all_frames = []
|
|
660
|
+
segment_results = []
|
|
661
|
+
|
|
662
|
+
for segment in diverse_segments:
|
|
663
|
+
frames = self.select_frames_for_sequence(segment)
|
|
664
|
+
|
|
665
|
+
if not frames:
|
|
666
|
+
segment_results.append({
|
|
667
|
+
"video_id": video_id,
|
|
668
|
+
"segment_start": segment['polyp'].start_frame_number,
|
|
669
|
+
"segment_end": segment['polyp'].end_frame_number,
|
|
670
|
+
"message": "No valid frames selected due to prediction rules (e.g., quality, outside, snare)."
|
|
671
|
+
})
|
|
672
|
+
else:
|
|
673
|
+
segment_results.append({
|
|
674
|
+
"video_id": video_id,
|
|
675
|
+
"segment_start": segment['polyp'].start_frame_number,
|
|
676
|
+
"segment_end": segment['polyp'].end_frame_number,
|
|
677
|
+
"frames": frames
|
|
678
|
+
})
|
|
679
|
+
all_frames.extend(frames)
|
|
680
|
+
|
|
681
|
+
if all_frames:
|
|
682
|
+
unique_frame_numbers = sorted({f["frame_number"] for f in all_frames})
|
|
683
|
+
self.extract_and_save_selected_frames(video, unique_frame_numbers, classification_type="paris")
|
|
684
|
+
|
|
685
|
+
results.extend(segment_results)
|
|
686
|
+
|
|
687
|
+
except Exception as e:
|
|
688
|
+
results.append({
|
|
689
|
+
"video_id": video.id,
|
|
690
|
+
"error": str(e)
|
|
691
|
+
})
|
|
692
|
+
|
|
693
|
+
if not results:
|
|
694
|
+
return [{
|
|
695
|
+
"message": "No valid classification results could be generated for any video."
|
|
696
|
+
}]
|
|
697
|
+
|
|
698
|
+
return {
|
|
699
|
+
"message": "PARIS classification data generated.",
|
|
700
|
+
"data": results
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
"""
|
|
706
|
+
NICE Classification Serializer
|
|
707
|
+
------------------------------
|
|
708
|
+
|
|
709
|
+
This serializer identifies clean polyp segments for NICE classification:
|
|
710
|
+
- Filters out segments overlapping with instruments
|
|
711
|
+
- Requires overlap with digital chromo or NBI
|
|
712
|
+
- Applies sequence diversity and selects clean frames
|
|
713
|
+
|
|
714
|
+
Configurable via:
|
|
715
|
+
- INSTRUMENT_LABEL_NAMES: defines what tools to exclude
|
|
716
|
+
- CHROMO_LABEL_NAMES: defines what chromo types to include
|
|
717
|
+
|
|
718
|
+
Returns:
|
|
719
|
+
{
|
|
720
|
+
"video_id": int,
|
|
721
|
+
"segment_start": int,
|
|
722
|
+
"segment_end": int,
|
|
723
|
+
"frames": [{ frame_number, frame_path }]
|
|
724
|
+
}
|
|
725
|
+
"""
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
"""
|
|
729
|
+
PARIS Classification Serializer
|
|
730
|
+
-------------------------------
|
|
731
|
+
|
|
732
|
+
This serializer identifies clean polyp segments for PARIS classification:
|
|
733
|
+
- Filters out segments that overlap with any instrument-type labels
|
|
734
|
+
- Also excludes any segments that overlap with digital chromo or NBI imaging
|
|
735
|
+
- Trims overlapping regions and returns only clean, usable subsegments
|
|
736
|
+
- Applies sequence diversity to avoid redundant or closely positioned segments
|
|
737
|
+
- Selects clean, representative frames from each remaining valid segment
|
|
738
|
+
|
|
739
|
+
Configurable via:
|
|
740
|
+
- INSTRUMENT_LABEL_NAMES: defines all instrument labels that must be excluded (e.g., 'instrument', 'snare', 'needle')
|
|
741
|
+
- CHROMO_LABEL_NAMES: defines chromo-like labels that should also be excluded (e.g., 'digital_chromo_endoscopy', 'nbi')
|
|
742
|
+
|
|
743
|
+
Returns:
|
|
744
|
+
{
|
|
745
|
+
"video_id": int,
|
|
746
|
+
"segment_start": int,
|
|
747
|
+
"segment_end": int,
|
|
748
|
+
"frames": [{ frame_number: int, frame_path: str }]
|
|
749
|
+
}
|
|
750
|
+
"""
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
'''
|
|
757
|
+
await import('https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js');
|
|
758
|
+
const fetchNiceClassification = async () => {
|
|
759
|
+
try {
|
|
760
|
+
const response = await axios.get("http://localhost:8000/videos/nice-classification/", {
|
|
761
|
+
headers: { "Accept": "application/json" }
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
console.log(" NICE Classification Response:", response.data);
|
|
765
|
+
alert("NICE Classification data fetched!");
|
|
766
|
+
return response.data;
|
|
767
|
+
} catch (error) {
|
|
768
|
+
console.error(" Error fetching NICE classification:", error.response?.data || error);
|
|
769
|
+
alert("Failed to fetch NICE classification data.");
|
|
770
|
+
return error.response?.data || { error: "Unknown error" };
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
|
|
774
|
+
fetchNiceClassification().then(data => console.log("Final Output:", data));
|
|
775
|
+
'''
|