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.

Files changed (268) hide show
  1. endoreg_db/admin.py +90 -1
  2. endoreg_db/case_generator/case_generator.py +159 -0
  3. endoreg_db/case_generator/lab_sample_factory.py +33 -0
  4. endoreg_db/case_generator/utils.py +30 -0
  5. endoreg_db/data/__init__.py +50 -4
  6. endoreg_db/data/ai_model/data.yaml +7 -0
  7. endoreg_db/data/{label → ai_model_label}/label/data.yaml +27 -1
  8. endoreg_db/data/ai_model_label/label-set/data.yaml +21 -0
  9. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +5 -0
  10. endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml +176 -0
  11. endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml +20 -0
  12. endoreg_db/data/center/data.yaml +35 -5
  13. endoreg_db/data/contraindication/bleeding.yaml +11 -0
  14. endoreg_db/data/distribution/numeric/data.yaml +14 -0
  15. endoreg_db/data/endoscope/data.yaml +93 -0
  16. endoreg_db/data/examination_indication/endoscopy.yaml +8 -0
  17. endoreg_db/data/examination_indication_classification/endoscopy.yaml +8 -0
  18. endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +101 -0
  19. endoreg_db/data/finding/data.yaml +141 -0
  20. endoreg_db/data/finding_intervention/endoscopy.yaml +138 -0
  21. endoreg_db/data/finding_intervention_type/endoscopy.yaml +15 -0
  22. endoreg_db/data/finding_location_classification/colonoscopy.yaml +46 -0
  23. endoreg_db/data/finding_location_classification_choice/colonoscopy.yaml +240 -0
  24. endoreg_db/data/finding_morphology_classification/colonoscopy.yaml +48 -0
  25. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_circularity_default.yaml +34 -0
  26. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_nice.yaml +20 -0
  27. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_paris.yaml +65 -0
  28. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_planarity_default.yaml +56 -0
  29. endoreg_db/data/finding_morphology_classification_choice/colon_lesion_surface_intact_default.yaml +39 -0
  30. endoreg_db/data/finding_morphology_classification_choice/colonoscopy_size.yaml +57 -0
  31. endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +79 -0
  32. endoreg_db/data/finding_type/data.yaml +30 -0
  33. endoreg_db/data/gender/data.yaml +17 -0
  34. endoreg_db/data/lab_value/cardiac_enzymes.yaml +7 -1
  35. endoreg_db/data/lab_value/coagulation.yaml +6 -1
  36. endoreg_db/data/lab_value/electrolytes.yaml +39 -1
  37. endoreg_db/data/lab_value/gastrointestinal_function.yaml +12 -0
  38. endoreg_db/data/lab_value/hematology.yaml +17 -2
  39. endoreg_db/data/lab_value/hormones.yaml +6 -0
  40. endoreg_db/data/lab_value/lipids.yaml +12 -3
  41. endoreg_db/data/lab_value/misc.yaml +5 -2
  42. endoreg_db/data/lab_value/renal_function.yaml +2 -1
  43. endoreg_db/data/lx_client_tag/base.yaml +54 -0
  44. endoreg_db/data/lx_client_type/base.yaml +30 -0
  45. endoreg_db/data/lx_permission/base.yaml +24 -0
  46. endoreg_db/data/lx_permission/endoreg.yaml +52 -0
  47. endoreg_db/data/medication_indication/anticoagulation.yaml +44 -49
  48. endoreg_db/data/names_first/first_names.yaml +51 -0
  49. endoreg_db/data/names_last/last_names.yaml +51 -0
  50. endoreg_db/data/network_device/data.yaml +30 -0
  51. endoreg_db/data/organ/data.yaml +29 -0
  52. endoreg_db/data/pdf_type/data.yaml +2 -1
  53. endoreg_db/data/report_reader_flag/ukw-examination-generic.yaml +4 -0
  54. endoreg_db/forms/__init__.py +3 -1
  55. endoreg_db/forms/examination_form.py +11 -0
  56. endoreg_db/forms/patient_finding_intervention_form.py +19 -0
  57. endoreg_db/forms/patient_form.py +26 -0
  58. endoreg_db/management/commands/__init__.py +0 -0
  59. endoreg_db/management/commands/load_ai_model_data.py +57 -23
  60. endoreg_db/management/commands/load_ai_model_label_data.py +59 -0
  61. endoreg_db/management/commands/load_base_db_data.py +160 -118
  62. endoreg_db/management/commands/{load_endoscope_type_data.py → load_contraindication_data.py} +3 -7
  63. endoreg_db/management/commands/load_disease_data.py +29 -7
  64. endoreg_db/management/commands/load_endoscope_data.py +68 -0
  65. endoreg_db/management/commands/load_examination_indication_data.py +65 -0
  66. endoreg_db/management/commands/load_finding_data.py +171 -0
  67. endoreg_db/management/commands/load_lab_value_data.py +3 -3
  68. endoreg_db/management/commands/load_lx_data.py +64 -0
  69. endoreg_db/management/commands/load_medication_data.py +83 -21
  70. endoreg_db/management/commands/load_name_data.py +37 -0
  71. endoreg_db/management/commands/{load_endoscopy_processor_data.py → load_organ_data.py} +7 -9
  72. endoreg_db/migrations/0001_initial.py +1206 -728
  73. endoreg_db/migrations/0002_alter_frame_image_alter_rawframe_image.py +23 -0
  74. endoreg_db/migrations/0003_alter_frame_image_alter_rawframe_image.py +23 -0
  75. endoreg_db/migrations/0004_alter_rawvideofile_file_alter_video_file.py +25 -0
  76. endoreg_db/migrations/0005_rawvideofile_frame_count_and_more.py +33 -0
  77. endoreg_db/migrations/0006_frame_extracted_rawframe_extracted.py +23 -0
  78. endoreg_db/migrations/0007_rename_pseudo_patient_video_patient_and_more.py +24 -0
  79. endoreg_db/migrations/0008_remove_reportfile_patient_examination_and_more.py +48 -0
  80. endoreg_db/models/__init__.py +331 -28
  81. endoreg_db/models/ai_model/__init__.py +1 -0
  82. endoreg_db/models/ai_model/ai_model.py +103 -0
  83. endoreg_db/models/ai_model/lightning/__init__.py +3 -0
  84. endoreg_db/models/ai_model/lightning/inference_dataset.py +53 -0
  85. endoreg_db/models/ai_model/lightning/multilabel_classification_net.py +155 -0
  86. endoreg_db/models/ai_model/lightning/postprocess.py +53 -0
  87. endoreg_db/models/ai_model/lightning/predict.py +172 -0
  88. endoreg_db/models/ai_model/lightning/prediction_visualizer.py +55 -0
  89. endoreg_db/models/ai_model/lightning/preprocess.py +68 -0
  90. endoreg_db/models/ai_model/lightning/run_visualizer.py +21 -0
  91. endoreg_db/models/ai_model/model_meta.py +232 -6
  92. endoreg_db/models/ai_model/model_type.py +13 -3
  93. endoreg_db/models/annotation/__init__.py +31 -2
  94. endoreg_db/models/annotation/anonymized_image_annotation.py +73 -18
  95. endoreg_db/models/annotation/binary_classification_annotation_task.py +94 -57
  96. endoreg_db/models/annotation/image_classification.py +73 -14
  97. endoreg_db/models/annotation/video_segmentation_annotation.py +52 -0
  98. endoreg_db/models/annotation/video_segmentation_labelset.py +20 -0
  99. endoreg_db/models/case/__init__.py +1 -0
  100. endoreg_db/models/{persons/patient/case → case}/case.py +4 -0
  101. endoreg_db/models/case_template/__init__.py +10 -1
  102. endoreg_db/models/case_template/case_template.py +57 -13
  103. endoreg_db/models/case_template/case_template_rule.py +5 -5
  104. endoreg_db/models/case_template/case_template_rule_value.py +19 -4
  105. endoreg_db/models/center/__init__.py +7 -0
  106. endoreg_db/models/center/center.py +31 -5
  107. endoreg_db/models/center/center_product.py +0 -1
  108. endoreg_db/models/center/center_resource.py +16 -2
  109. endoreg_db/models/center/center_waste.py +6 -1
  110. endoreg_db/models/contraindication/__init__.py +21 -0
  111. endoreg_db/models/data_file/__init__.py +38 -5
  112. endoreg_db/models/data_file/base_classes/__init__.py +6 -1
  113. endoreg_db/models/data_file/base_classes/abstract_frame.py +64 -15
  114. endoreg_db/models/data_file/base_classes/abstract_pdf.py +136 -0
  115. endoreg_db/models/data_file/base_classes/abstract_video.py +744 -138
  116. endoreg_db/models/data_file/base_classes/frame_helpers.py +17 -0
  117. endoreg_db/models/data_file/base_classes/prepare_bulk_frames.py +19 -0
  118. endoreg_db/models/data_file/base_classes/utils.py +80 -0
  119. endoreg_db/models/data_file/frame.py +22 -38
  120. endoreg_db/models/data_file/import_classes/__init__.py +4 -18
  121. endoreg_db/models/data_file/import_classes/raw_pdf.py +162 -90
  122. endoreg_db/models/data_file/import_classes/raw_video.py +239 -294
  123. endoreg_db/models/data_file/metadata/__init__.py +10 -0
  124. endoreg_db/models/data_file/metadata/pdf_meta.py +4 -0
  125. endoreg_db/models/data_file/metadata/sensitive_meta.py +265 -6
  126. endoreg_db/models/data_file/metadata/video_meta.py +116 -50
  127. endoreg_db/models/data_file/report_file.py +30 -63
  128. endoreg_db/models/data_file/video/__init__.py +6 -2
  129. endoreg_db/models/data_file/video/video.py +187 -16
  130. endoreg_db/models/data_file/video_segment.py +162 -55
  131. endoreg_db/models/disease.py +25 -2
  132. endoreg_db/models/emission/__init__.py +5 -1
  133. endoreg_db/models/emission/emission_factor.py +71 -6
  134. endoreg_db/models/event.py +51 -0
  135. endoreg_db/models/examination/__init__.py +6 -1
  136. endoreg_db/models/examination/examination.py +53 -12
  137. endoreg_db/models/examination/examination_indication.py +170 -0
  138. endoreg_db/models/examination/examination_time.py +31 -5
  139. endoreg_db/models/examination/examination_time_type.py +28 -4
  140. endoreg_db/models/examination/examination_type.py +28 -6
  141. endoreg_db/models/finding/__init__.py +11 -0
  142. endoreg_db/models/finding/finding.py +75 -0
  143. endoreg_db/models/finding/finding_intervention.py +60 -0
  144. endoreg_db/models/finding/finding_location_classification.py +94 -0
  145. endoreg_db/models/finding/finding_morphology_classification.py +89 -0
  146. endoreg_db/models/finding/finding_type.py +22 -0
  147. endoreg_db/models/hardware/endoscope.py +16 -0
  148. endoreg_db/models/hardware/endoscopy_processor.py +31 -19
  149. endoreg_db/models/label/label.py +35 -7
  150. endoreg_db/models/laboratory/lab_value.py +12 -3
  151. endoreg_db/models/logging/__init__.py +8 -1
  152. endoreg_db/models/lx/__init__.py +4 -0
  153. endoreg_db/models/lx/client.py +57 -0
  154. endoreg_db/models/lx/identity.py +34 -0
  155. endoreg_db/models/lx/permission.py +18 -0
  156. endoreg_db/models/lx/user.py +16 -0
  157. endoreg_db/models/medication/__init__.py +19 -1
  158. endoreg_db/models/medication/medication.py +7 -122
  159. endoreg_db/models/medication/medication_indication.py +50 -0
  160. endoreg_db/models/medication/medication_indication_type.py +34 -0
  161. endoreg_db/models/medication/medication_intake_time.py +26 -0
  162. endoreg_db/models/medication/medication_schedule.py +37 -0
  163. endoreg_db/models/network/__init__.py +7 -1
  164. endoreg_db/models/network/network_device.py +13 -8
  165. endoreg_db/models/organ/__init__.py +38 -0
  166. endoreg_db/models/other/__init__.py +19 -1
  167. endoreg_db/models/other/distribution/__init__.py +44 -0
  168. endoreg_db/models/other/distribution/base_value_distribution.py +20 -0
  169. endoreg_db/models/other/distribution/date_value_distribution.py +91 -0
  170. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +32 -0
  171. endoreg_db/models/other/distribution/numeric_value_distribution.py +97 -0
  172. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +22 -0
  173. endoreg_db/models/other/distribution.py +1 -211
  174. endoreg_db/models/other/material.py +4 -0
  175. endoreg_db/models/other/transport_route.py +2 -1
  176. endoreg_db/models/patient/__init__.py +24 -0
  177. endoreg_db/models/patient/patient_examination.py +182 -0
  178. endoreg_db/models/patient/patient_finding.py +143 -0
  179. endoreg_db/models/patient/patient_finding_intervention.py +26 -0
  180. endoreg_db/models/patient/patient_finding_location.py +120 -0
  181. endoreg_db/models/patient/patient_finding_morphology.py +166 -0
  182. endoreg_db/models/persons/__init__.py +29 -2
  183. endoreg_db/models/persons/examiner/examiner.py +48 -4
  184. endoreg_db/models/persons/patient/__init__.py +1 -1
  185. endoreg_db/models/persons/patient/patient.py +227 -54
  186. endoreg_db/models/persons/patient/patient_disease.py +6 -0
  187. endoreg_db/models/persons/patient/patient_event.py +31 -1
  188. endoreg_db/models/persons/patient/patient_examination_indication.py +32 -0
  189. endoreg_db/models/persons/patient/patient_lab_sample.py +4 -2
  190. endoreg_db/models/persons/patient/patient_lab_value.py +37 -16
  191. endoreg_db/models/persons/patient/patient_medication.py +27 -12
  192. endoreg_db/models/persons/patient/patient_medication_schedule.py +62 -2
  193. endoreg_db/models/prediction/__init__.py +7 -1
  194. endoreg_db/models/prediction/image_classification.py +20 -6
  195. endoreg_db/models/prediction/video_prediction_meta.py +151 -89
  196. endoreg_db/models/product/__init__.py +10 -1
  197. endoreg_db/models/product/product.py +15 -2
  198. endoreg_db/models/product/product_group.py +8 -0
  199. endoreg_db/models/product/product_material.py +4 -0
  200. endoreg_db/models/product/product_weight.py +12 -0
  201. endoreg_db/models/product/reference_product.py +19 -3
  202. endoreg_db/models/quiz/__init__.py +8 -1
  203. endoreg_db/models/report_reader/__init__.py +6 -1
  204. endoreg_db/serializers/__init__.py +1 -1
  205. endoreg_db/serializers/annotation.py +2 -5
  206. endoreg_db/serializers/frame.py +1 -5
  207. endoreg_db/serializers/patient.py +26 -3
  208. endoreg_db/serializers/prediction.py +2 -7
  209. endoreg_db/serializers/raw_video_meta_validation.py +13 -0
  210. endoreg_db/serializers/video.py +6 -13
  211. endoreg_db/serializers/video_segmentation.py +492 -0
  212. endoreg_db/templates/admin/patient_finding_intervention.html +253 -0
  213. endoreg_db/templates/admin/start_examination.html +12 -0
  214. endoreg_db/templates/timeline.html +176 -0
  215. endoreg_db/urls.py +173 -0
  216. endoreg_db/utils/__init__.py +36 -1
  217. endoreg_db/utils/dataloader.py +45 -19
  218. endoreg_db/utils/dates.py +39 -0
  219. endoreg_db/utils/hashs.py +122 -4
  220. endoreg_db/utils/names.py +74 -0
  221. endoreg_db/utils/parse_and_generate_yaml.py +46 -0
  222. endoreg_db/utils/pydantic_models/__init__.py +6 -0
  223. endoreg_db/utils/pydantic_models/db_config.py +57 -0
  224. endoreg_db/utils/validate_endo_roi.py +19 -0
  225. endoreg_db/utils/validate_subcategory_dict.py +91 -0
  226. endoreg_db/utils/video/__init__.py +13 -0
  227. endoreg_db/utils/video/extract_frames.py +121 -0
  228. endoreg_db/utils/video/transcode_videofile.py +111 -0
  229. endoreg_db/views/__init__.py +2 -0
  230. endoreg_db/views/csrf.py +7 -0
  231. endoreg_db/views/patient_views.py +90 -0
  232. endoreg_db/views/raw_video_meta_validation_views.py +38 -0
  233. endoreg_db/views/report_views.py +96 -0
  234. endoreg_db/views/video_segmentation_views.py +149 -0
  235. endoreg_db/views/views_for_timeline.py +46 -0
  236. endoreg_db/views.py +0 -3
  237. endoreg_db-0.6.1.dist-info/METADATA +151 -0
  238. endoreg_db-0.6.1.dist-info/RECORD +420 -0
  239. {endoreg_db-0.5.3.dist-info → endoreg_db-0.6.1.dist-info}/WHEEL +1 -1
  240. endoreg_db/data/active_model/data.yaml +0 -3
  241. endoreg_db/data/label/label-set/data.yaml +0 -18
  242. endoreg_db/management/commands/delete_legacy_images.py +0 -19
  243. endoreg_db/management/commands/delete_legacy_videos.py +0 -17
  244. endoreg_db/management/commands/extract_legacy_video_frames.py +0 -18
  245. endoreg_db/management/commands/import_legacy_images.py +0 -94
  246. endoreg_db/management/commands/import_legacy_videos.py +0 -76
  247. endoreg_db/management/commands/load_label_data.py +0 -67
  248. endoreg_db/migrations/0002_anonymizedimagelabel_anonymousimageannotation_and_more.py +0 -55
  249. endoreg_db/migrations/0003_anonymousimageannotation_original_image_url_and_more.py +0 -39
  250. endoreg_db/migrations/0004_alter_rawpdffile_file.py +0 -20
  251. endoreg_db/migrations/0005_uploadedfile_alter_rawpdffile_file_anonymizedfile.py +0 -40
  252. endoreg_db/migrations/0006_alter_rawpdffile_file.py +0 -20
  253. endoreg_db/migrations/0007_networkdevicelogentry_datetime_and_more.py +0 -43
  254. endoreg_db/migrations/0008_networkdevicelogentry_aglnet_ip_and_more.py +0 -28
  255. endoreg_db/migrations/0009_alter_networkdevicelogentry_vpn_service_status.py +0 -18
  256. endoreg_db/migrations/0010_remove_networkdevicelogentry_hostname.py +0 -17
  257. endoreg_db/models/legacy_data/__init__.py +0 -3
  258. endoreg_db/models/legacy_data/image.py +0 -34
  259. endoreg_db/models/patient_examination/__init__.py +0 -35
  260. endoreg_db/utils/video_metadata.py +0 -87
  261. endoreg_db-0.5.3.dist-info/METADATA +0 -28
  262. endoreg_db-0.5.3.dist-info/RECORD +0 -319
  263. /endoreg_db/{models/persons/patient/case → case_generator}/__init__.py +0 -0
  264. /endoreg_db/data/{label → ai_model_label}/label-type/data.yaml +0 -0
  265. /endoreg_db/data/{model_type → ai_model_type}/data.yaml +0 -0
  266. /endoreg_db/{data/distribution/numeric/.init → management/__init__.py} +0 -0
  267. /endoreg_db/management/commands/{load_report_reader_flag.py → load_report_reader_flag_data.py} +0 -0
  268. {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', related_name='patient_medication_schedules'
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 LegacyVideoPredictionMeta, VideoPredictionMeta
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
- label = models.ForeignKey("Label", on_delete=models.CASCADE, related_name="image_classification_predictions")
15
- frame = models.ForeignKey("Frame", on_delete=models.CASCADE, blank=True, null=True, related_name="image_classification_predictions")
16
- legacy_frame = models.ForeignKey("LegacyFrame", on_delete=models.CASCADE, blank=True, null=True, related_name="image_classification_predictions")
17
- legacy_image = models.ForeignKey("LegacyImage", on_delete=models.CASCADE, blank=True, null=True, related_name="image_classification_predictions")
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("ModelMeta", on_delete=models.CASCADE, related_name="image_classification_predictions")
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 = ('label', 'frame', 'model_meta')
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 LegacyVideo, Video
5
- from ..data_file.frame import LegacyFrame, Frame
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.video_segment import LegacyLabelVideoSegment, LabelVideoSegment, find_segments_in_prediction_array
8
- from ..information_source import get_prediction_information_source
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 = ('model_meta', 'video')
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
- return self.model_meta.labelset
34
-
58
+ if self.is_raw:
59
+ return self.model_meta.labelset
60
+
35
61
  def get_video_model(self):
36
- assert 1 == 2, "This method should be overridden in derived classes"
62
+ if self.is_raw:
63
+ return RawVideoFile
64
+
65
+ return Video
37
66
 
38
67
  def get_frame_model(self):
39
- assert 1 == 2, "This method should be overridden in derived classes"
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 get_video_segment_model(self):
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
- running_mean_array = np.zeros(confidence_array.shape)
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(confidence_array, (pad_size, pad_size), 'constant', constant_values=(0.5, 0.5))
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='same')
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
- def create_video_segments_for_label(self, segments, label):
118
- """
119
- Creates video segments for the given label and segments.
120
- Segments is a list of tuples (start_frame_number, end_frame_number).
121
- Labels is a Label object.
122
- """
123
- video = self.video
124
- video_segment_model = self.get_video_segment_model()
125
- information_source = get_prediction_information_source()
126
-
127
- for segment in segments:
128
- start_frame_number, end_frame_number = segment
129
-
130
- video_segment = video_segment_model(
131
- video=video,
132
- prediction_meta=self,
133
- start_frame_number=start_frame_number,
134
- end_frame_number=end_frame_number,
135
- source=information_source,
136
- label=label,
137
- )
138
- video_segment.save()
139
-
140
- def create_video_segments(self, segment_length_threshold_in_s:float=None):
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
- def get_video_model(self):
171
- return Video
172
-
173
- def get_frame_model(self):
174
- return Frame
175
-
176
- def get_video_segment_model(self):
177
- return LabelVideoSegment
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(label=label, frame__video=video, model_meta=model_meta).order_by('frame__frame_number')
192
- confidences = np.array([prediction.confidence for prediction in predictions])
193
- smooth_confidences = self.apply_running_mean(confidences, window_size_in_seconds)
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 LegacyVideoPredictionMeta(AbstractVideoPredictionMeta):
204
- video = models.OneToOneField("LegacyVideo", on_delete=models.CASCADE, related_name="video_prediction_meta")
205
-
206
- def get_video_model(self):
207
- return LegacyVideo
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 get_frame_model(self):
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:LegacyVideo = self.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(label=label, legacy_frame__video=video, model_meta=model_meta).order_by('legacy_frame__frame_number')
228
- confidences = np.array([prediction.confidence for prediction in predictions])
229
- smooth_confidences = self.apply_running_mean(confidences, window_size_in_seconds)
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("ProductGroup", on_delete=models.SET_NULL, null=True)
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
- return self.name
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("EmissionFactor", on_delete=models.SET_NULL, null=True, blank = True)
13
- emission_factor_package = models.ForeignKey("EmissionFactor", on_delete=models.SET_NULL, null=True, related_name="reference_product_package")
14
- emission_factor_product = models.ForeignKey("EmissionFactor", on_delete=models.SET_NULL, null=True, related_name="reference_product_product")
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,2 +1,7 @@
1
1
  from .report_reader_config import ReportReaderConfig
2
- from .report_reader_flag import ReportReaderFlag
2
+ from .report_reader_flag import ReportReaderFlag
3
+
4
+ __all__ = [
5
+ 'ReportReaderConfig',
6
+ 'ReportReaderFlag',
7
+ ]
@@ -7,4 +7,4 @@ from .hardware import *
7
7
  from .label import *
8
8
  from .patient import *
9
9
  from .report_file import *
10
- from .video import *
10
+ from .video import *
@@ -1,10 +1,7 @@
1
1
  from rest_framework import serializers
2
- from endoreg_db.models import LegacyBinaryClassificationAnnotationTask, BinaryClassificationAnnotationTask, ImageClassificationAnnotation
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:
@@ -1,13 +1,9 @@
1
1
  from rest_framework import serializers
2
- from endoreg_db.models import Frame, LegacyFrame
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