endoreg-db 0.5.3__py3-none-any.whl → 0.6.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of endoreg-db might be problematic. Click here for more details.
- endoreg_db/admin.py +90 -1
- endoreg_db/case_generator/case_generator.py +159 -0
- endoreg_db/case_generator/lab_sample_factory.py +33 -0
- endoreg_db/case_generator/utils.py +30 -0
- endoreg_db/data/__init__.py +50 -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-set/data.yaml +21 -0
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +5 -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 +35 -5
- endoreg_db/data/contraindication/bleeding.yaml +11 -0
- endoreg_db/data/distribution/numeric/data.yaml +14 -0
- endoreg_db/data/endoscope/data.yaml +93 -0
- endoreg_db/data/examination_indication/endoscopy.yaml +8 -0
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +8 -0
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
- endoreg_db/data/finding/data.yaml +141 -0
- endoreg_db/data/finding_intervention/endoscopy.yaml +138 -0
- endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/finding_location_classification/colonoscopy.yaml +46 -0
- endoreg_db/data/finding_location_classification_choice/colonoscopy.yaml +240 -0
- endoreg_db/data/finding_morphology_classification/colonoscopy.yaml +48 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_circularity_default.yaml +34 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_nice.yaml +20 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_paris.yaml +65 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_planarity_default.yaml +56 -0
- endoreg_db/data/finding_morphology_classification_choice/colon_lesion_surface_intact_default.yaml +39 -0
- endoreg_db/data/finding_morphology_classification_choice/colonoscopy_size.yaml +57 -0
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
- endoreg_db/data/finding_type/data.yaml +30 -0
- endoreg_db/data/gender/data.yaml +17 -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 +5 -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_indication/anticoagulation.yaml +44 -49
- endoreg_db/data/names_first/first_names.yaml +51 -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 +2 -1
- endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +4 -0
- endoreg_db/forms/__init__.py +3 -1
- endoreg_db/forms/examination_form.py +11 -0
- endoreg_db/forms/patient_finding_intervention_form.py +19 -0
- endoreg_db/forms/patient_form.py +26 -0
- endoreg_db/management/commands/__init__.py +0 -0
- endoreg_db/management/commands/load_ai_model_data.py +57 -23
- endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
- endoreg_db/management/commands/load_base_db_data.py +160 -118
- endoreg_db/management/commands/{load_endoscope_type_data.py → load_contraindication_data.py} +3 -7
- endoreg_db/management/commands/load_disease_data.py +29 -7
- endoreg_db/management/commands/load_endoscope_data.py +68 -0
- endoreg_db/management/commands/load_examination_indication_data.py +65 -0
- endoreg_db/management/commands/load_finding_data.py +171 -0
- endoreg_db/management/commands/load_lab_value_data.py +3 -3
- endoreg_db/management/commands/load_lx_data.py +64 -0
- 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_endoscopy_processor_data.py → load_organ_data.py} +7 -9
- endoreg_db/migrations/0001_initial.py +1206 -728
- endoreg_db/migrations/0002_alter_frame_image_alter_rawframe_image.py +23 -0
- endoreg_db/migrations/0003_alter_frame_image_alter_rawframe_image.py +23 -0
- endoreg_db/migrations/0004_alter_rawvideofile_file_alter_video_file.py +25 -0
- endoreg_db/migrations/0005_rawvideofile_frame_count_and_more.py +33 -0
- endoreg_db/migrations/0006_frame_extracted_rawframe_extracted.py +23 -0
- endoreg_db/migrations/0007_rename_pseudo_patient_video_patient_and_more.py +24 -0
- endoreg_db/migrations/0008_remove_reportfile_patient_examination_and_more.py +48 -0
- endoreg_db/models/__init__.py +331 -28
- endoreg_db/models/ai_model/__init__.py +1 -0
- endoreg_db/models/ai_model/ai_model.py +103 -0
- endoreg_db/models/ai_model/lightning/__init__.py +3 -0
- endoreg_db/models/ai_model/lightning/inference_dataset.py +53 -0
- endoreg_db/models/ai_model/lightning/multilabel_classification_net.py +155 -0
- endoreg_db/models/ai_model/lightning/postprocess.py +53 -0
- endoreg_db/models/ai_model/lightning/predict.py +172 -0
- endoreg_db/models/ai_model/lightning/prediction_visualizer.py +55 -0
- endoreg_db/models/ai_model/lightning/preprocess.py +68 -0
- endoreg_db/models/ai_model/lightning/run_visualizer.py +21 -0
- endoreg_db/models/ai_model/model_meta.py +232 -6
- endoreg_db/models/ai_model/model_type.py +13 -3
- endoreg_db/models/annotation/__init__.py +31 -2
- endoreg_db/models/annotation/anonymized_image_annotation.py +73 -18
- endoreg_db/models/annotation/binary_classification_annotation_task.py +94 -57
- endoreg_db/models/annotation/image_classification.py +73 -14
- endoreg_db/models/annotation/video_segmentation_annotation.py +52 -0
- endoreg_db/models/annotation/video_segmentation_labelset.py +20 -0
- endoreg_db/models/case/__init__.py +1 -0
- endoreg_db/models/{persons/patient/case → case}/case.py +4 -0
- endoreg_db/models/case_template/__init__.py +10 -1
- endoreg_db/models/case_template/case_template.py +57 -13
- endoreg_db/models/case_template/case_template_rule.py +5 -5
- endoreg_db/models/case_template/case_template_rule_value.py +19 -4
- endoreg_db/models/center/__init__.py +7 -0
- endoreg_db/models/center/center.py +31 -5
- endoreg_db/models/center/center_product.py +0 -1
- endoreg_db/models/center/center_resource.py +16 -2
- endoreg_db/models/center/center_waste.py +6 -1
- endoreg_db/models/contraindication/__init__.py +21 -0
- endoreg_db/models/data_file/__init__.py +38 -5
- endoreg_db/models/data_file/base_classes/__init__.py +6 -1
- endoreg_db/models/data_file/base_classes/abstract_frame.py +64 -15
- endoreg_db/models/data_file/base_classes/abstract_pdf.py +136 -0
- endoreg_db/models/data_file/base_classes/abstract_video.py +744 -138
- endoreg_db/models/data_file/base_classes/frame_helpers.py +17 -0
- endoreg_db/models/data_file/base_classes/prepare_bulk_frames.py +19 -0
- endoreg_db/models/data_file/base_classes/utils.py +80 -0
- endoreg_db/models/data_file/frame.py +22 -38
- endoreg_db/models/data_file/import_classes/__init__.py +4 -18
- endoreg_db/models/data_file/import_classes/raw_pdf.py +162 -90
- endoreg_db/models/data_file/import_classes/raw_video.py +239 -294
- endoreg_db/models/data_file/metadata/__init__.py +10 -0
- endoreg_db/models/data_file/metadata/pdf_meta.py +4 -0
- endoreg_db/models/data_file/metadata/sensitive_meta.py +265 -6
- endoreg_db/models/data_file/metadata/video_meta.py +116 -50
- endoreg_db/models/data_file/report_file.py +30 -63
- endoreg_db/models/data_file/video/__init__.py +6 -2
- endoreg_db/models/data_file/video/video.py +187 -16
- endoreg_db/models/data_file/video_segment.py +162 -55
- endoreg_db/models/disease.py +25 -2
- endoreg_db/models/emission/__init__.py +5 -1
- endoreg_db/models/emission/emission_factor.py +71 -6
- endoreg_db/models/event.py +51 -0
- endoreg_db/models/examination/__init__.py +6 -1
- endoreg_db/models/examination/examination.py +53 -12
- endoreg_db/models/examination/examination_indication.py +170 -0
- endoreg_db/models/examination/examination_time.py +31 -5
- endoreg_db/models/examination/examination_time_type.py +28 -4
- endoreg_db/models/examination/examination_type.py +28 -6
- endoreg_db/models/finding/__init__.py +11 -0
- endoreg_db/models/finding/finding.py +75 -0
- endoreg_db/models/finding/finding_intervention.py +60 -0
- endoreg_db/models/finding/finding_location_classification.py +94 -0
- endoreg_db/models/finding/finding_morphology_classification.py +89 -0
- endoreg_db/models/finding/finding_type.py +22 -0
- endoreg_db/models/hardware/endoscope.py +16 -0
- endoreg_db/models/hardware/endoscopy_processor.py +31 -19
- endoreg_db/models/label/label.py +35 -7
- endoreg_db/models/laboratory/lab_value.py +12 -3
- endoreg_db/models/logging/__init__.py +8 -1
- endoreg_db/models/lx/__init__.py +4 -0
- endoreg_db/models/lx/client.py +57 -0
- endoreg_db/models/lx/identity.py +34 -0
- endoreg_db/models/lx/permission.py +18 -0
- endoreg_db/models/lx/user.py +16 -0
- endoreg_db/models/medication/__init__.py +19 -1
- endoreg_db/models/medication/medication.py +7 -122
- endoreg_db/models/medication/medication_indication.py +50 -0
- endoreg_db/models/medication/medication_indication_type.py +34 -0
- endoreg_db/models/medication/medication_intake_time.py +26 -0
- endoreg_db/models/medication/medication_schedule.py +37 -0
- endoreg_db/models/network/__init__.py +7 -1
- endoreg_db/models/network/network_device.py +13 -8
- endoreg_db/models/organ/__init__.py +38 -0
- endoreg_db/models/other/__init__.py +19 -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 +91 -0
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
- endoreg_db/models/other/distribution/numeric_value_distribution.py +97 -0
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
- endoreg_db/models/other/distribution.py +1 -211
- endoreg_db/models/other/material.py +4 -0
- endoreg_db/models/other/transport_route.py +2 -1
- endoreg_db/models/patient/__init__.py +24 -0
- endoreg_db/models/patient/patient_examination.py +182 -0
- endoreg_db/models/patient/patient_finding.py +143 -0
- endoreg_db/models/patient/patient_finding_intervention.py +26 -0
- endoreg_db/models/patient/patient_finding_location.py +120 -0
- endoreg_db/models/patient/patient_finding_morphology.py +166 -0
- endoreg_db/models/persons/__init__.py +29 -2
- endoreg_db/models/persons/examiner/examiner.py +48 -4
- endoreg_db/models/persons/patient/__init__.py +1 -1
- endoreg_db/models/persons/patient/patient.py +227 -54
- endoreg_db/models/persons/patient/patient_disease.py +6 -0
- endoreg_db/models/persons/patient/patient_event.py +31 -1
- endoreg_db/models/persons/patient/patient_examination_indication.py +32 -0
- endoreg_db/models/persons/patient/patient_lab_sample.py +4 -2
- endoreg_db/models/persons/patient/patient_lab_value.py +37 -16
- endoreg_db/models/persons/patient/patient_medication.py +27 -12
- endoreg_db/models/persons/patient/patient_medication_schedule.py +62 -2
- endoreg_db/models/prediction/__init__.py +7 -1
- endoreg_db/models/prediction/image_classification.py +20 -6
- endoreg_db/models/prediction/video_prediction_meta.py +151 -89
- endoreg_db/models/product/__init__.py +10 -1
- endoreg_db/models/product/product.py +15 -2
- endoreg_db/models/product/product_group.py +8 -0
- endoreg_db/models/product/product_material.py +4 -0
- endoreg_db/models/product/product_weight.py +12 -0
- endoreg_db/models/product/reference_product.py +19 -3
- endoreg_db/models/quiz/__init__.py +8 -1
- endoreg_db/models/report_reader/__init__.py +6 -1
- endoreg_db/serializers/__init__.py +1 -1
- endoreg_db/serializers/annotation.py +2 -5
- endoreg_db/serializers/frame.py +1 -5
- endoreg_db/serializers/patient.py +26 -3
- endoreg_db/serializers/prediction.py +2 -7
- endoreg_db/serializers/raw_video_meta_validation.py +13 -0
- endoreg_db/serializers/video.py +6 -13
- endoreg_db/serializers/video_segmentation.py +492 -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.py +173 -0
- endoreg_db/utils/__init__.py +36 -1
- endoreg_db/utils/dataloader.py +45 -19
- endoreg_db/utils/dates.py +39 -0
- endoreg_db/utils/hashs.py +122 -4
- endoreg_db/utils/names.py +74 -0
- endoreg_db/utils/parse_and_generate_yaml.py +46 -0
- endoreg_db/utils/pydantic_models/__init__.py +6 -0
- endoreg_db/utils/pydantic_models/db_config.py +57 -0
- endoreg_db/utils/validate_endo_roi.py +19 -0
- endoreg_db/utils/validate_subcategory_dict.py +91 -0
- endoreg_db/utils/video/__init__.py +13 -0
- endoreg_db/utils/video/extract_frames.py +121 -0
- endoreg_db/utils/video/transcode_videofile.py +111 -0
- endoreg_db/views/__init__.py +2 -0
- endoreg_db/views/csrf.py +7 -0
- endoreg_db/views/patient_views.py +90 -0
- endoreg_db/views/raw_video_meta_validation_views.py +38 -0
- endoreg_db/views/report_views.py +96 -0
- endoreg_db/views/video_segmentation_views.py +149 -0
- endoreg_db/views/views_for_timeline.py +46 -0
- endoreg_db/views.py +0 -3
- endoreg_db-0.6.1.dist-info/METADATA +151 -0
- endoreg_db-0.6.1.dist-info/RECORD +420 -0
- {endoreg_db-0.5.3.dist-info → endoreg_db-0.6.1.dist-info}/WHEEL +1 -1
- endoreg_db/data/active_model/data.yaml +0 -3
- endoreg_db/data/label/label-set/data.yaml +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/import_legacy_images.py +0 -94
- endoreg_db/management/commands/import_legacy_videos.py +0 -76
- endoreg_db/management/commands/load_label_data.py +0 -67
- 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/migrations/0008_networkdevicelogentry_aglnet_ip_and_more.py +0 -28
- endoreg_db/migrations/0009_alter_networkdevicelogentry_vpn_service_status.py +0 -18
- endoreg_db/migrations/0010_remove_networkdevicelogentry_hostname.py +0 -17
- endoreg_db/models/legacy_data/__init__.py +0 -3
- endoreg_db/models/legacy_data/image.py +0 -34
- endoreg_db/models/patient_examination/__init__.py +0 -35
- endoreg_db/utils/video_metadata.py +0 -87
- endoreg_db-0.5.3.dist-info/METADATA +0 -28
- endoreg_db-0.5.3.dist-info/RECORD +0 -319
- /endoreg_db/{models/persons/patient/case → case_generator}/__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/{data/distribution/numeric/.init → management/__init__.py} +0 -0
- /endoreg_db/management/commands/{load_report_reader_flag.py → load_report_reader_flag_data.py} +0 -0
- {endoreg_db-0.5.3.dist-info → endoreg_db-0.6.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -3,7 +3,9 @@ from django.db import models
|
|
|
3
3
|
class PatientMedicationSchedule(models.Model):
|
|
4
4
|
patient = models.ForeignKey("Patient", on_delete= models.CASCADE)
|
|
5
5
|
medication = models.ManyToManyField(
|
|
6
|
-
'PatientMedication',
|
|
6
|
+
'PatientMedication',
|
|
7
|
+
related_name='patient_medication_schedules',
|
|
8
|
+
blank=True
|
|
7
9
|
)
|
|
8
10
|
|
|
9
11
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
@@ -25,4 +27,62 @@ class PatientMedicationSchedule(models.Model):
|
|
|
25
27
|
patient_medication_schedule.medication.add(patient_medication)
|
|
26
28
|
patient_medication_schedule.save()
|
|
27
29
|
|
|
28
|
-
return patient_medication_schedule
|
|
30
|
+
return patient_medication_schedule
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def create_by_patient_and_indication(cls, patient, medication_indication):
|
|
34
|
+
from endoreg_db.models import (
|
|
35
|
+
MedicationIndication, PatientMedication,
|
|
36
|
+
Patient
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
assert isinstance(medication_indication, MedicationIndication)
|
|
40
|
+
assert isinstance(patient, Patient)
|
|
41
|
+
patient_medication_schedule = cls.objects.create(patient=patient)
|
|
42
|
+
patient_medication_schedule.save()
|
|
43
|
+
|
|
44
|
+
patient_medication = PatientMedication.create_by_patient_and_indication(patient, medication_indication)
|
|
45
|
+
patient_medication_schedule.medication.add(patient_medication)
|
|
46
|
+
patient_medication_schedule.save()
|
|
47
|
+
|
|
48
|
+
return patient_medication_schedule
|
|
49
|
+
|
|
50
|
+
def create_patient_medication_from_medication_schedule(
|
|
51
|
+
self,
|
|
52
|
+
medication_schedule,
|
|
53
|
+
medication_indication=None,
|
|
54
|
+
start_date=None,
|
|
55
|
+
):
|
|
56
|
+
|
|
57
|
+
from endoreg_db.models import MedicationSchedule, PatientMedication
|
|
58
|
+
from datetime import datetime as dt
|
|
59
|
+
|
|
60
|
+
assert isinstance(medication_schedule, MedicationSchedule)
|
|
61
|
+
|
|
62
|
+
if not start_date:
|
|
63
|
+
start_date = dt.now()
|
|
64
|
+
|
|
65
|
+
drug = medication_schedule.medication
|
|
66
|
+
unit = medication_schedule.unit
|
|
67
|
+
dosage = medication_schedule.dose
|
|
68
|
+
intake_times = medication_schedule.get_intake_times()
|
|
69
|
+
|
|
70
|
+
patient_medication = PatientMedication.objects.create(
|
|
71
|
+
patient=self.patient,
|
|
72
|
+
medication=drug,
|
|
73
|
+
medication_indication=medication_indication,
|
|
74
|
+
unit=unit,
|
|
75
|
+
dosage=dosage
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
patient_medication.intake_times.set(intake_times)
|
|
79
|
+
patient_medication.save()
|
|
80
|
+
|
|
81
|
+
self.medication.add(patient_medication)
|
|
82
|
+
self.save()
|
|
83
|
+
|
|
84
|
+
return patient_medication
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def get_patient_medication(self):
|
|
88
|
+
return self.medication.all()
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
from .image_classification import ImageClassificationPrediction
|
|
2
|
-
from .video_prediction_meta import
|
|
2
|
+
from .video_prediction_meta import RawVideoPredictionMeta, VideoPredictionMeta
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"ImageClassificationPrediction",
|
|
6
|
+
"RawVideoPredictionMeta",
|
|
7
|
+
"VideoPredictionMeta",
|
|
8
|
+
]
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from django.db import models
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
class ImageClassificationPrediction(models.Model):
|
|
4
5
|
"""
|
|
5
6
|
A class representing an image classification prediction.
|
|
@@ -11,17 +12,30 @@ class ImageClassificationPrediction(models.Model):
|
|
|
11
12
|
date_created (datetime): The date the prediction was created.
|
|
12
13
|
|
|
13
14
|
"""
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
|
|
16
|
+
label = models.ForeignKey(
|
|
17
|
+
"Label",
|
|
18
|
+
on_delete=models.CASCADE,
|
|
19
|
+
related_name="image_classification_predictions",
|
|
20
|
+
)
|
|
21
|
+
frame = models.ForeignKey(
|
|
22
|
+
"Frame",
|
|
23
|
+
on_delete=models.CASCADE,
|
|
24
|
+
blank=True,
|
|
25
|
+
null=True,
|
|
26
|
+
related_name="image_classification_predictions",
|
|
27
|
+
)
|
|
18
28
|
value = models.BooleanField()
|
|
19
29
|
confidence = models.FloatField()
|
|
20
|
-
model_meta = models.ForeignKey(
|
|
30
|
+
model_meta = models.ForeignKey(
|
|
31
|
+
"ModelMeta",
|
|
32
|
+
on_delete=models.CASCADE,
|
|
33
|
+
related_name="image_classification_predictions",
|
|
34
|
+
)
|
|
21
35
|
date_created = models.DateTimeField(auto_now_add=True)
|
|
22
36
|
|
|
23
37
|
class Meta:
|
|
24
|
-
unique_together = (
|
|
38
|
+
unique_together = ("label", "frame", "model_meta")
|
|
25
39
|
|
|
26
40
|
def get_image_object(self):
|
|
27
41
|
"""
|
|
@@ -1,55 +1,88 @@
|
|
|
1
|
+
from typing import Union, TYPE_CHECKING
|
|
1
2
|
from django.db import models
|
|
2
3
|
|
|
3
4
|
from endoreg_db.models.label.label import LabelSet
|
|
4
|
-
from ..data_file.video import
|
|
5
|
-
from ..data_file.
|
|
5
|
+
from ..data_file.video import Video
|
|
6
|
+
from ..data_file.import_classes import RawVideoFile
|
|
7
|
+
from ..data_file.frame import Frame
|
|
6
8
|
from .image_classification import ImageClassificationPrediction
|
|
7
|
-
from ..data_file
|
|
8
|
-
|
|
9
|
+
from ..data_file import (
|
|
10
|
+
LabelVideoSegment,
|
|
11
|
+
find_segments_in_prediction_array,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
# from ..information_source import get_prediction_information_source
|
|
9
15
|
import numpy as np
|
|
10
16
|
import pickle
|
|
11
17
|
|
|
12
18
|
DEFAULT_WINDOW_SIZE_IN_SECONDS_FOR_RUNNING_MEAN = 1.5
|
|
13
19
|
DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S = 1.0
|
|
14
20
|
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from endoreg_db.models import ModelMeta
|
|
23
|
+
|
|
24
|
+
|
|
15
25
|
class AbstractVideoPredictionMeta(models.Model):
|
|
16
26
|
model_meta = models.ForeignKey("ModelMeta", on_delete=models.CASCADE)
|
|
17
27
|
date_created = models.DateTimeField(auto_now_add=True)
|
|
18
28
|
date_modified = models.DateTimeField(auto_now=True)
|
|
19
29
|
video = None # Placeholder for the video field, to be defined in derived classes
|
|
20
30
|
prediction_array = models.BinaryField(blank=True, null=True)
|
|
31
|
+
is_raw = models.BooleanField(default=False)
|
|
32
|
+
|
|
33
|
+
if TYPE_CHECKING:
|
|
34
|
+
model_meta: "ModelMeta"
|
|
35
|
+
video: Union["Video", "RawVideoFile"]
|
|
21
36
|
|
|
22
37
|
class Meta:
|
|
23
38
|
abstract = True
|
|
24
|
-
unique_together = (
|
|
39
|
+
unique_together = ("model_meta", "video")
|
|
40
|
+
|
|
41
|
+
def is_raw_video_prediction_meta(self):
|
|
42
|
+
if isinstance(self, RawVideoPredictionMeta):
|
|
43
|
+
return True
|
|
44
|
+
return False
|
|
25
45
|
|
|
26
46
|
def __str__(self):
|
|
27
47
|
return f"Video {self.video.id} - {self.model_meta.name}"
|
|
28
|
-
|
|
48
|
+
|
|
49
|
+
# override save method to set is_raw field
|
|
50
|
+
def save(self, *args, **kwargs):
|
|
51
|
+
self.is_raw = self.is_raw_video_prediction_meta()
|
|
52
|
+
super().save(*args, **kwargs)
|
|
53
|
+
|
|
29
54
|
def get_labelset(self):
|
|
30
55
|
"""
|
|
31
56
|
Get the labelset of the predictions.
|
|
32
57
|
"""
|
|
33
|
-
|
|
34
|
-
|
|
58
|
+
if self.is_raw:
|
|
59
|
+
return self.model_meta.labelset
|
|
60
|
+
|
|
35
61
|
def get_video_model(self):
|
|
36
|
-
|
|
62
|
+
if self.is_raw:
|
|
63
|
+
return RawVideoFile
|
|
64
|
+
|
|
65
|
+
return Video
|
|
37
66
|
|
|
38
67
|
def get_frame_model(self):
|
|
39
|
-
|
|
68
|
+
return Frame
|
|
69
|
+
|
|
70
|
+
def get_video_segment_model(self):
|
|
71
|
+
from endoreg_db.models import LabelRawVideoSegment
|
|
72
|
+
|
|
73
|
+
if self.is_raw:
|
|
74
|
+
return LabelRawVideoSegment
|
|
75
|
+
return LabelVideoSegment
|
|
40
76
|
|
|
41
77
|
def get_label_list(self):
|
|
42
78
|
"""
|
|
43
79
|
Get the label list of the predictions.
|
|
44
80
|
"""
|
|
45
|
-
labelset:LabelSet = self.get_labelset()
|
|
81
|
+
labelset: LabelSet = self.get_labelset()
|
|
46
82
|
label_list = labelset.get_labels_in_order()
|
|
47
83
|
return label_list
|
|
48
|
-
|
|
49
|
-
def
|
|
50
|
-
assert 1 == 2, "This method should be overridden in derived classes"
|
|
51
|
-
|
|
52
|
-
def save_prediction_array(self, prediction_array:np.array):
|
|
84
|
+
|
|
85
|
+
def save_prediction_array(self, prediction_array: np.array):
|
|
53
86
|
"""
|
|
54
87
|
Save the prediction array to the database.
|
|
55
88
|
"""
|
|
@@ -64,7 +97,7 @@ class AbstractVideoPredictionMeta(models.Model):
|
|
|
64
97
|
return None
|
|
65
98
|
else:
|
|
66
99
|
return pickle.loads(self.prediction_array)
|
|
67
|
-
|
|
100
|
+
|
|
68
101
|
def calculate_prediction_array(self):
|
|
69
102
|
assert 1 == 2, "This method should be overridden in derived classes"
|
|
70
103
|
|
|
@@ -97,47 +130,52 @@ class AbstractVideoPredictionMeta(models.Model):
|
|
|
97
130
|
window = np.ones(window_size_in_frames) / window_size_in_frames
|
|
98
131
|
|
|
99
132
|
# Create running mean array with the same shape as the confidence array
|
|
100
|
-
|
|
133
|
+
_running_mean_array = np.zeros(confidence_array.shape)
|
|
101
134
|
|
|
102
135
|
# Calculate the padding size
|
|
103
136
|
pad_size = window_size_in_frames // 2
|
|
104
137
|
|
|
105
138
|
# Pad the array with 0.5 on both sides
|
|
106
|
-
padded_confidences = np.pad(
|
|
107
|
-
|
|
139
|
+
padded_confidences = np.pad(
|
|
140
|
+
confidence_array,
|
|
141
|
+
(pad_size, pad_size),
|
|
142
|
+
"constant",
|
|
143
|
+
constant_values=(0.5, 0.5),
|
|
144
|
+
)
|
|
145
|
+
|
|
108
146
|
# Apply the running mean filter on the padded array
|
|
109
|
-
running_mean = np.convolve(padded_confidences, window, mode=
|
|
110
|
-
|
|
147
|
+
running_mean = np.convolve(padded_confidences, window, mode="same")
|
|
148
|
+
|
|
111
149
|
# Remove the padding from the result to match the original shape
|
|
112
150
|
running_mean = running_mean[pad_size:-pad_size]
|
|
113
151
|
|
|
114
152
|
return running_mean
|
|
115
|
-
|
|
116
153
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
154
|
+
# FIXME
|
|
155
|
+
# def create_video_segments_for_label(self, segments, label):
|
|
156
|
+
# """
|
|
157
|
+
# Creates video segments for the given label and segments.
|
|
158
|
+
# Segments is a list of tuples (start_frame_number, end_frame_number).
|
|
159
|
+
# Labels is a Label object.
|
|
160
|
+
# """
|
|
161
|
+
# video = self.video
|
|
162
|
+
# video_segment_model = self.get_video_segment_model()
|
|
163
|
+
# information_source = get_prediction_information_source()
|
|
164
|
+
|
|
165
|
+
# for segment in segments:
|
|
166
|
+
# start_frame_number, end_frame_number = segment
|
|
167
|
+
|
|
168
|
+
# video_segment = video_segment_model(
|
|
169
|
+
# video=video,
|
|
170
|
+
# prediction_meta=self,
|
|
171
|
+
# start_frame_number=start_frame_number,
|
|
172
|
+
# end_frame_number=end_frame_number,
|
|
173
|
+
# source=information_source,
|
|
174
|
+
# label=label,
|
|
175
|
+
# )
|
|
176
|
+
# video_segment.save()
|
|
177
|
+
|
|
178
|
+
def create_video_segments(self, segment_length_threshold_in_s: float = None):
|
|
141
179
|
if not segment_length_threshold_in_s:
|
|
142
180
|
segment_length_threshold_in_s = DEFAULT_VIDEO_SEGMENT_LENGTH_THRESHOLD_IN_S
|
|
143
181
|
|
|
@@ -146,7 +184,7 @@ class AbstractVideoPredictionMeta(models.Model):
|
|
|
146
184
|
min_frame_length = int(segment_length_threshold_in_s * fps)
|
|
147
185
|
|
|
148
186
|
label_list = self.get_label_list()
|
|
149
|
-
|
|
187
|
+
|
|
150
188
|
# if prediction array doesnt exist, create it
|
|
151
189
|
if self.prediction_array is None:
|
|
152
190
|
self.calculate_prediction_array()
|
|
@@ -163,24 +201,21 @@ class AbstractVideoPredictionMeta(models.Model):
|
|
|
163
201
|
# create video segments
|
|
164
202
|
self.create_video_segments_for_label(segments, label)
|
|
165
203
|
|
|
166
|
-
import numpy as np
|
|
167
|
-
class VideoPredictionMeta(AbstractVideoPredictionMeta):
|
|
168
|
-
video = models.OneToOneField("Video", on_delete=models.CASCADE, related_name="video_prediction_meta")
|
|
169
204
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
def calculate_prediction_array(self, window_size_in_seconds:int=None):
|
|
205
|
+
class RawVideoPredictionMeta(AbstractVideoPredictionMeta):
|
|
206
|
+
"""
|
|
207
|
+
Model for storing video predictions for a specific model and video.
|
|
208
|
+
"""
|
|
209
|
+
|
|
210
|
+
video = models.ForeignKey(
|
|
211
|
+
"RawVideoFile", on_delete=models.CASCADE, related_name="video_prediction_meta"
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
def calculate_prediction_array(self, window_size_in_seconds: int = None):
|
|
180
215
|
"""
|
|
181
216
|
Fetches all predictions for this video, labelset, and model meta.
|
|
182
217
|
"""
|
|
183
|
-
video:Video = self.video
|
|
218
|
+
video: Video = self.video
|
|
184
219
|
|
|
185
220
|
model_meta = self.model_meta
|
|
186
221
|
label_list = self.get_label_list()
|
|
@@ -188,9 +223,15 @@ class VideoPredictionMeta(AbstractVideoPredictionMeta):
|
|
|
188
223
|
prediction_array = np.zeros((video.get_frame_number, len(label_list)))
|
|
189
224
|
for i, label in enumerate(label_list):
|
|
190
225
|
# fetch all predictions for this label, video, and model meta ordered by ImageClassificationPrediction.frame.frame_number
|
|
191
|
-
predictions = ImageClassificationPrediction.objects.filter(
|
|
192
|
-
|
|
193
|
-
|
|
226
|
+
predictions = ImageClassificationPrediction.objects.filter(
|
|
227
|
+
label=label, frame__video=video, model_meta=model_meta
|
|
228
|
+
).order_by("frame__frame_number")
|
|
229
|
+
confidences = np.array(
|
|
230
|
+
[prediction.confidence for prediction in predictions]
|
|
231
|
+
)
|
|
232
|
+
smooth_confidences = self.apply_running_mean(
|
|
233
|
+
confidences, window_size_in_seconds
|
|
234
|
+
)
|
|
194
235
|
# calculate binary predictions
|
|
195
236
|
binary_predictions = smooth_confidences > 0.5
|
|
196
237
|
# add to prediction array
|
|
@@ -200,23 +241,46 @@ class VideoPredictionMeta(AbstractVideoPredictionMeta):
|
|
|
200
241
|
self.save_prediction_array(prediction_array)
|
|
201
242
|
|
|
202
243
|
|
|
203
|
-
class
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
244
|
+
class VideoPredictionMeta(AbstractVideoPredictionMeta):
|
|
245
|
+
"""
|
|
246
|
+
Model for storing video predictions for a specific model and video.
|
|
247
|
+
"""
|
|
248
|
+
|
|
249
|
+
video = models.ForeignKey(
|
|
250
|
+
"Video", on_delete=models.CASCADE, related_name="video_prediction_meta"
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
@classmethod
|
|
254
|
+
def from_raw(
|
|
255
|
+
cls, video: "Video", raw_video_prediction_meta: RawVideoPredictionMeta
|
|
256
|
+
):
|
|
257
|
+
"""
|
|
258
|
+
Create a new VideoPrediction from an existing RawVideoPredictionMeta.
|
|
259
|
+
"""
|
|
260
|
+
cls_dict = {
|
|
261
|
+
"video": video,
|
|
262
|
+
"model_meta": raw_video_prediction_meta.model_meta,
|
|
263
|
+
"date_created": raw_video_prediction_meta.date_created,
|
|
264
|
+
"date_modified": raw_video_prediction_meta.date_modified,
|
|
265
|
+
"prediction_array": raw_video_prediction_meta.prediction_array,
|
|
266
|
+
"is_raw": False,
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
# check if exists
|
|
270
|
+
if cls.objects.filter(
|
|
271
|
+
video=video, model_meta=raw_video_prediction_meta.model_meta
|
|
272
|
+
).exists():
|
|
273
|
+
return cls.objects.get(
|
|
274
|
+
video=video, model_meta=raw_video_prediction_meta.model_meta
|
|
275
|
+
)
|
|
276
|
+
else:
|
|
277
|
+
return cls.objects.create(**cls_dict)
|
|
208
278
|
|
|
209
|
-
def
|
|
210
|
-
return LegacyFrame
|
|
211
|
-
|
|
212
|
-
def get_video_segment_model(self):
|
|
213
|
-
return LegacyLabelVideoSegment
|
|
214
|
-
|
|
215
|
-
def calculate_prediction_array(self, window_size_in_seconds:int=None):
|
|
279
|
+
def calculate_prediction_array(self, window_size_in_seconds: int = None):
|
|
216
280
|
"""
|
|
217
281
|
Fetches all predictions for this video, labelset, and model meta.
|
|
218
282
|
"""
|
|
219
|
-
video:
|
|
283
|
+
video: Video = self.video
|
|
220
284
|
|
|
221
285
|
model_meta = self.model_meta
|
|
222
286
|
label_list = self.get_label_list()
|
|
@@ -224,9 +288,15 @@ class LegacyVideoPredictionMeta(AbstractVideoPredictionMeta):
|
|
|
224
288
|
prediction_array = np.zeros((video.get_frame_number, len(label_list)))
|
|
225
289
|
for i, label in enumerate(label_list):
|
|
226
290
|
# fetch all predictions for this label, video, and model meta ordered by ImageClassificationPrediction.frame.frame_number
|
|
227
|
-
predictions = ImageClassificationPrediction.objects.filter(
|
|
228
|
-
|
|
229
|
-
|
|
291
|
+
predictions = ImageClassificationPrediction.objects.filter(
|
|
292
|
+
label=label, frame__video=video, model_meta=model_meta
|
|
293
|
+
).order_by("frame__frame_number")
|
|
294
|
+
confidences = np.array(
|
|
295
|
+
[prediction.confidence for prediction in predictions]
|
|
296
|
+
)
|
|
297
|
+
smooth_confidences = self.apply_running_mean(
|
|
298
|
+
confidences, window_size_in_seconds
|
|
299
|
+
)
|
|
230
300
|
# calculate binary predictions
|
|
231
301
|
binary_predictions = smooth_confidences > 0.5
|
|
232
302
|
# add to prediction array
|
|
@@ -234,11 +304,3 @@ class LegacyVideoPredictionMeta(AbstractVideoPredictionMeta):
|
|
|
234
304
|
|
|
235
305
|
# save prediction array
|
|
236
306
|
self.save_prediction_array(prediction_array)
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
'''Module for product models'''
|
|
1
2
|
from .product import Product
|
|
2
3
|
from .product_material import ProductMaterial
|
|
3
4
|
from .product_group import ProductGroup
|
|
4
5
|
from .reference_product import ReferenceProduct
|
|
5
|
-
from .product_weight import ProductWeight
|
|
6
|
+
from .product_weight import ProductWeight
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
'Product',
|
|
10
|
+
'ProductMaterial',
|
|
11
|
+
'ProductGroup',
|
|
12
|
+
'ReferenceProduct',
|
|
13
|
+
'ProductWeight',
|
|
14
|
+
]
|
|
@@ -40,13 +40,26 @@ class Product(models.Model):
|
|
|
40
40
|
name_en = models.CharField(max_length=255, null=True)
|
|
41
41
|
|
|
42
42
|
transport_route = models.ForeignKey("TransportRoute", on_delete=models.SET_NULL, null=True)
|
|
43
|
-
product_group = models.ForeignKey(
|
|
43
|
+
product_group = models.ForeignKey(
|
|
44
|
+
"ProductGroup", on_delete=models.SET_NULL, null=True
|
|
45
|
+
)
|
|
44
46
|
|
|
45
47
|
def natural_key(self):
|
|
46
48
|
return (self.name,)
|
|
47
49
|
|
|
48
50
|
def __str__(self):
|
|
49
|
-
|
|
51
|
+
result = f"{self.name}"
|
|
52
|
+
if self.product_group:
|
|
53
|
+
result += f" ({self.product_group}, "
|
|
54
|
+
else:
|
|
55
|
+
result += " (no product group, "
|
|
56
|
+
|
|
57
|
+
if self.transport_route:
|
|
58
|
+
result += f"{self.transport_route})"
|
|
59
|
+
else:
|
|
60
|
+
result += "no transport route)"
|
|
61
|
+
|
|
62
|
+
return result
|
|
50
63
|
|
|
51
64
|
def get_product_weight(self):
|
|
52
65
|
# check if there is a product material weight
|
|
@@ -17,3 +17,11 @@ class ProductGroup(models.Model):
|
|
|
17
17
|
def __str__(self):
|
|
18
18
|
return self.name
|
|
19
19
|
|
|
20
|
+
def get_products(self):
|
|
21
|
+
from endoreg_db.models import Product
|
|
22
|
+
return Product.objects.filter(product_group=self)
|
|
23
|
+
|
|
24
|
+
def get_reference_product(self):
|
|
25
|
+
from endoreg_db.models import ReferenceProduct
|
|
26
|
+
return ReferenceProduct.objects.get(product_group=self)
|
|
27
|
+
|
|
@@ -20,5 +20,9 @@ class ProductMaterial(models.Model):
|
|
|
20
20
|
emmision_value = emission_factor.value * self.quantity
|
|
21
21
|
emission_unit = emission_factor.unit
|
|
22
22
|
return emmision_value, emission_unit
|
|
23
|
+
|
|
24
|
+
def __str__(self):
|
|
25
|
+
return f"{self.product.name} - {self.material.name} - {self.quantity} {self.unit.name}"
|
|
26
|
+
|
|
23
27
|
|
|
24
28
|
|
|
@@ -24,3 +24,15 @@ class ProductWeight(models.Model):
|
|
|
24
24
|
return self.manufacturer
|
|
25
25
|
else:
|
|
26
26
|
return None
|
|
27
|
+
|
|
28
|
+
def get_weight_source(self):
|
|
29
|
+
if not pd.isnull(self.verified):
|
|
30
|
+
return "verified"
|
|
31
|
+
elif not pd.isnull(self.measured):
|
|
32
|
+
return "measured"
|
|
33
|
+
elif not pd.isnull(self.manufacturer):
|
|
34
|
+
return "manufacturer"
|
|
35
|
+
else:
|
|
36
|
+
return None
|
|
37
|
+
def __str__(self):
|
|
38
|
+
return f"{self.product} - {self.get_weight()} {self.unit} (Source: {self.get_weight_source()})"
|
|
@@ -9,9 +9,25 @@ class ReferenceProduct(models.Model):
|
|
|
9
9
|
name = models.CharField(max_length=255)
|
|
10
10
|
product = models.ForeignKey("Product", on_delete=models.CASCADE)
|
|
11
11
|
product_group = models.OneToOneField("ProductGroup", on_delete=models.CASCADE, related_name="reference_product")
|
|
12
|
-
emission_factor_total = models.ForeignKey(
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
emission_factor_total = models.ForeignKey(
|
|
13
|
+
"EmissionFactor",
|
|
14
|
+
on_delete=models.SET_NULL,
|
|
15
|
+
null=True,
|
|
16
|
+
blank = True,
|
|
17
|
+
# related_name="reference_product_total"
|
|
18
|
+
)
|
|
19
|
+
emission_factor_package = models.ForeignKey(
|
|
20
|
+
"EmissionFactor",
|
|
21
|
+
on_delete=models.SET_NULL,
|
|
22
|
+
null=True,
|
|
23
|
+
related_name="reference_product_package"
|
|
24
|
+
)
|
|
25
|
+
emission_factor_product = models.ForeignKey(
|
|
26
|
+
"EmissionFactor",
|
|
27
|
+
on_delete=models.SET_NULL,
|
|
28
|
+
null=True,
|
|
29
|
+
related_name="reference_product_product"
|
|
30
|
+
)
|
|
15
31
|
|
|
16
32
|
objects = ReferenceProductManager()
|
|
17
33
|
|
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
from .quiz_answer import QuizAnswer, QuizAnswerType
|
|
2
|
-
from .quiz_question import QuizQuestion, QuizQuestionType
|
|
2
|
+
from .quiz_question import QuizQuestion, QuizQuestionType
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"QuizAnswer",
|
|
6
|
+
"QuizAnswerType",
|
|
7
|
+
"QuizQuestion",
|
|
8
|
+
"QuizQuestionType",
|
|
9
|
+
]
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
from rest_framework import serializers
|
|
2
|
-
from endoreg_db.models import
|
|
2
|
+
from endoreg_db.models import BinaryClassificationAnnotationTask, ImageClassificationAnnotation
|
|
3
|
+
|
|
3
4
|
|
|
4
|
-
class LegacyBinaryClassificationAnnotationTaskSerializer(serializers.ModelSerializer):
|
|
5
|
-
class Meta:
|
|
6
|
-
model = LegacyBinaryClassificationAnnotationTask
|
|
7
|
-
fields = '__all__'
|
|
8
5
|
|
|
9
6
|
class BinaryClassificationAnnotationTaskSerializer(serializers.ModelSerializer):
|
|
10
7
|
class Meta:
|
endoreg_db/serializers/frame.py
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
from rest_framework import serializers
|
|
2
|
-
from endoreg_db.models import Frame
|
|
2
|
+
from endoreg_db.models import Frame
|
|
3
3
|
|
|
4
4
|
class FrameSerializer(serializers.ModelSerializer):
|
|
5
5
|
class Meta:
|
|
6
6
|
model = Frame
|
|
7
7
|
fields = '__all__'
|
|
8
8
|
|
|
9
|
-
class LegacyFrameSerializer(serializers.ModelSerializer):
|
|
10
|
-
class Meta:
|
|
11
|
-
model = LegacyFrame
|
|
12
|
-
fields = '__all__'
|
|
13
9
|
|