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
@@ -0,0 +1,94 @@
1
+ from django.db import models
2
+ from typing import List
3
+ # Class to represent the LocationClassifications of a Finding
4
+
5
+ class FindingLocationClassificationManager(models.Manager):
6
+ def get_by_natural_key(self, name):
7
+ return self.get(name=name)
8
+
9
+ class FindingLocationClassification(models.Model):
10
+ name = models.CharField(max_length=100, unique=True)
11
+ name_de = models.CharField(max_length=100, blank=True, null=True)
12
+ name_en = models.CharField(max_length=100, blank=True, null=True)
13
+ description = models.TextField(blank=True, null=True)
14
+ description_de = models.TextField(blank=True, null=True)
15
+ description_en = models.TextField(blank=True, null=True)
16
+
17
+ # Many to many relationships:
18
+ findings = models.ManyToManyField('Finding', blank=True, related_name='location_classifications')
19
+ examinations = models.ManyToManyField('Examination', blank=True, related_name='location_classifications')
20
+ finding_types = models.ManyToManyField('FindingType', blank=True, related_name='location_classifications')
21
+ choices = models.ManyToManyField('FindingLocationClassificationChoice', blank=True, related_name='location_classifications')
22
+
23
+ objects = FindingLocationClassificationManager()
24
+
25
+ def natural_key(self):
26
+ return (self.name,)
27
+
28
+ def __str__(self):
29
+ return self.name
30
+
31
+ def get_available_findings(self):
32
+ from endoreg_db.models import Finding
33
+ available_findings:List[Finding] = [_ for _ in self.findings.all()]
34
+ return available_findings
35
+
36
+ def remove_unavailable_findings(
37
+ self,
38
+ findings
39
+ ):
40
+ """
41
+ Returns a list of findings that are in the input list but not available for this location classification.
42
+ """
43
+ from endoreg_db.models import Finding
44
+ for _ in findings:
45
+ assert isinstance(_, Finding)
46
+ available_findings:List['Finding'] = self.get_available_findings()
47
+ available_finding_names = [
48
+ finding.name for finding in available_findings
49
+ ]
50
+
51
+ filtered_findings = []
52
+
53
+ for finding in findings:
54
+ if finding.name in available_finding_names:
55
+ filtered_findings.append(finding)
56
+
57
+ return filtered_findings
58
+
59
+ def get_choices(self):
60
+ return self.choices.all()
61
+
62
+ class FindingLocationClassificationChoiceManager(models.Manager):
63
+ def get_by_natural_key(self, name):
64
+ return self.get(name=name)
65
+
66
+ class FindingLocationClassificationChoice(models.Model):
67
+ name = models.CharField(max_length=100, unique=True)
68
+ name_de = models.CharField(max_length=100, blank=True, null=True)
69
+ name_en = models.CharField(max_length=100, blank=True, null=True)
70
+ description = models.TextField(blank=True, null=True)
71
+ description_de = models.TextField(blank=True, null=True)
72
+ description_en = models.TextField(blank=True, null=True)
73
+
74
+ # Foreign key relationships: # migrated to organs
75
+ # organs = models.ManyToManyField('Organ', blank=True, related_name='location_choices')
76
+
77
+ # Optional Descriptors:
78
+ # subcategories_str is a List of strings with names of categorical descriptors
79
+ subcategories = models.JSONField(blank=True, null=True)
80
+ numerical_descriptors = models.JSONField(blank=True, null=True)
81
+
82
+ objects = FindingLocationClassificationChoiceManager()
83
+
84
+ def natural_key(self):
85
+ return (self.name,)
86
+
87
+ def __str__(self):
88
+ return self.name
89
+
90
+ def get_subcategories(self)->dict:
91
+ return self.subcategories
92
+
93
+ def get_numerical_descriptors(self)->dict:
94
+ return self.numerical_descriptors
@@ -0,0 +1,89 @@
1
+ from django.db import models
2
+ from typing import List
3
+
4
+ class FindingMorphologyClassificationTypeManager(models.Manager):
5
+ def get_by_natural_key(self, name):
6
+ return self.get(name=name)
7
+
8
+ class FindingMorphologyClassificationType(models.Model):
9
+ name = models.CharField(max_length=255, unique=True)
10
+ name_de = models.CharField(max_length=255, blank=True)
11
+ name_en = models.CharField(max_length=255, blank=True)
12
+ description = models.TextField(blank=True)
13
+
14
+ objects = FindingMorphologyClassificationTypeManager()
15
+
16
+ def natural_key(self):
17
+ return (self.name,)
18
+
19
+ def __str__(self):
20
+ return self.name
21
+
22
+ @classmethod
23
+ def get_required_classifications_for_finding(cls, finding):
24
+ """
25
+ Returns all required morphology classification types for a given finding.
26
+ """
27
+ from endoreg_db.models import FindingMorphologyClassificationType
28
+ required_classification_types:List[FindingMorphologyClassificationType] = [
29
+ _ for _ in finding.required_morphology_classification_types.all()
30
+ ]
31
+ return required_classification_types
32
+
33
+ class FindingMorphologyClassificationManager(models.Manager):
34
+ def get_by_natural_key(self, name):
35
+ return self.get(name=name)
36
+
37
+ class FindingMorphologyClassification(models.Model):
38
+ name = models.CharField(max_length=255, unique=True)
39
+ name_de = models.CharField(max_length=255, blank=True)
40
+ name_en = models.CharField(max_length=255, blank=True)
41
+ description = models.TextField(blank=True)
42
+ classification_type = models.ForeignKey(FindingMorphologyClassificationType, on_delete=models.CASCADE)
43
+
44
+ objects = FindingMorphologyClassificationManager()
45
+
46
+ def natural_key(self):
47
+ return (self.name,)
48
+
49
+ def __str__(self):
50
+ return self.name
51
+
52
+ def get_choices(self):
53
+ choices: List[FindingMorphologyClassificationChoice] = [_ for _ in self.choices.all()]
54
+ return choices
55
+
56
+ class FindingMorphologyClassificationChoiceManager(models.Manager):
57
+ def get_by_natural_key(self, name):
58
+ return self.get(name=name)
59
+
60
+ class FindingMorphologyClassificationChoice(models.Model):
61
+ name = models.CharField(max_length=255, unique=True)
62
+ name_de = models.CharField(max_length=255, blank=True)
63
+ name_en = models.CharField(max_length=255, blank=True)
64
+ description = models.TextField(blank=True)
65
+ classification = models.ForeignKey(
66
+ FindingMorphologyClassification,
67
+ on_delete=models.CASCADE,
68
+ related_name='choices'
69
+ )
70
+
71
+ subcategories = models.JSONField(
72
+ default = dict
73
+ )
74
+
75
+ numerical_descriptors = models.JSONField(
76
+ default = dict
77
+ )
78
+
79
+ objects = FindingMorphologyClassificationChoiceManager()
80
+
81
+ def natural_key(self):
82
+ return (self.name,)
83
+
84
+ def __str__(self):
85
+ _str = f"{self.name} ({self.classification})"
86
+ return _str
87
+
88
+
89
+
@@ -0,0 +1,22 @@
1
+ from django.db import models
2
+
3
+
4
+ class FindingTypeManager(models.Manager):
5
+ def get_by_natural_key(self, name):
6
+ return self.get(name=name)
7
+
8
+ class FindingType(models.Model):
9
+ name = models.CharField(max_length=100, unique=True)
10
+ name_de = models.CharField(max_length=100, blank=True, null=True)
11
+ name_en = models.CharField(max_length=100, blank=True, null=True)
12
+ description = models.TextField(blank=True, null=True)
13
+ description_de = models.TextField(blank=True, null=True)
14
+ description_en = models.TextField(blank=True, null=True)
15
+
16
+ objects = FindingTypeManager()
17
+
18
+ def natural_key(self):
19
+ return (self.name,)
20
+
21
+ def __str__(self):
22
+ return self.name
@@ -8,7 +8,23 @@ class Endoscope(models.Model):
8
8
  objects = EndoscopeManager()
9
9
 
10
10
  name = models.CharField(max_length=255)
11
+ name_de = models.CharField(max_length=255, blank=True, null=True)
12
+ name_en = models.CharField(max_length=255, blank=True, null=True)
11
13
  sn = models.CharField(max_length=255)
14
+ center = models.ForeignKey(
15
+ 'Center',
16
+ blank=True,
17
+ null=True,
18
+ on_delete=models.CASCADE,
19
+ related_name='endoscopes'
20
+ )
21
+ endoscope_type = models.ForeignKey(
22
+ 'EndoscopeType',
23
+ blank=True,
24
+ null=True,
25
+ on_delete=models.CASCADE,
26
+ related_name='endoscopes'
27
+ )
12
28
 
13
29
  def natural_key(self):
14
30
  return (self.name, self.sn)
@@ -1,12 +1,20 @@
1
1
  from django.db import models
2
2
 
3
+
3
4
  class EndoscopyProcessorManager(models.Manager):
4
5
  def get_by_natural_key(self, name):
5
6
  return self.get(name=name)
6
7
 
8
+
7
9
  class EndoscopyProcessor(models.Model):
8
10
  objects = EndoscopyProcessorManager()
9
11
 
12
+ centers = models.ManyToManyField(
13
+ "Center",
14
+ blank=True,
15
+ related_name="endoscopy_processors",
16
+ )
17
+
10
18
  name = models.CharField(max_length=255)
11
19
  image_width = models.IntegerField()
12
20
  image_height = models.IntegerField()
@@ -62,74 +70,78 @@ class EndoscopyProcessor(models.Model):
62
70
 
63
71
  def natural_key(self):
64
72
  return (self.name,)
65
-
73
+
74
+ @classmethod
75
+ def get_by_name(self, name):
76
+ return self.objects.get(name=name)
77
+
66
78
  def __str__(self):
67
79
  return self.name
68
-
80
+
69
81
  def get_roi_endoscope_image(self):
70
82
  return {
71
83
  "x": self.endoscope_image_x,
72
84
  "y": self.endoscope_image_y,
73
85
  "width": self.endoscope_image_width,
74
- "height": self.endoscope_image_height
86
+ "height": self.endoscope_image_height,
75
87
  }
76
-
88
+
77
89
  def get_roi_examination_date(self):
78
90
  return {
79
91
  "x": self.examination_date_x,
80
92
  "y": self.examination_date_y,
81
93
  "width": self.examination_date_width,
82
- "height": self.examination_date_height
94
+ "height": self.examination_date_height,
83
95
  }
84
-
96
+
85
97
  def get_roi_examination_time(self):
86
98
  return {
87
99
  "x": self.examination_time_x,
88
100
  "y": self.examination_time_y,
89
101
  "width": self.examination_time_width,
90
- "height": self.examination_time_height
102
+ "height": self.examination_time_height,
91
103
  }
92
-
104
+
93
105
  def get_roi_patient_last_name(self):
94
106
  return {
95
107
  "x": self.patient_last_name_x,
96
108
  "y": self.patient_last_name_y,
97
109
  "width": self.patient_last_name_width,
98
- "height": self.patient_last_name_height
110
+ "height": self.patient_last_name_height,
99
111
  }
100
-
112
+
101
113
  def get_roi_patient_first_name(self):
102
114
  return {
103
115
  "x": self.patient_first_name_x,
104
116
  "y": self.patient_first_name_y,
105
117
  "width": self.patient_first_name_width,
106
- "height": self.patient_first_name_height
118
+ "height": self.patient_first_name_height,
107
119
  }
108
-
120
+
109
121
  def get_roi_patient_dob(self):
110
122
  return {
111
123
  "x": self.patient_dob_x,
112
124
  "y": self.patient_dob_y,
113
125
  "width": self.patient_dob_width,
114
- "height": self.patient_dob_height
126
+ "height": self.patient_dob_height,
115
127
  }
116
-
128
+
117
129
  def get_roi_endoscope_type(self):
118
130
  return {
119
131
  "x": self.endoscope_type_x,
120
132
  "y": self.endoscope_type_y,
121
133
  "width": self.endoscope_type_width,
122
- "height": self.endoscope_type_height
134
+ "height": self.endoscope_type_height,
123
135
  }
124
-
136
+
125
137
  def get_roi_endoscopy_sn(self):
126
138
  return {
127
139
  "x": self.endoscope_sn_x,
128
140
  "y": self.endoscope_sn_y,
129
141
  "width": self.endoscope_sn_width,
130
- "height": self.endoscope_sn_height
142
+ "height": self.endoscope_sn_height,
131
143
  }
132
-
144
+
133
145
  def get_rois(self):
134
146
  return {
135
147
  "endoscope_image": self.get_roi_endoscope_image(),
@@ -139,5 +151,5 @@ class EndoscopyProcessor(models.Model):
139
151
  "patient_last_name": self.get_roi_patient_last_name(),
140
152
  "patient_dob": self.get_roi_patient_dob(),
141
153
  "endoscope_type": self.get_roi_endoscope_type(),
142
- "endoscope_sn": self.get_roi_endoscopy_sn()
154
+ "endoscope_sn": self.get_roi_endoscopy_sn(),
143
155
  }
@@ -1,9 +1,11 @@
1
1
  from django.db import models
2
2
 
3
+
3
4
  class LabelTypeManager(models.Manager):
4
5
  def get_by_natural_key(self, name):
5
6
  return self.get(name=name)
6
7
 
8
+
7
9
  class LabelType(models.Model):
8
10
  """
9
11
  A class representing a label type.
@@ -13,22 +15,28 @@ class LabelType(models.Model):
13
15
  description (str): A description of the label type.
14
16
 
15
17
  """
18
+
16
19
  name = models.CharField(max_length=255)
17
20
  description = models.TextField(blank=True, null=True)
18
21
 
19
22
  objects = LabelTypeManager()
20
23
 
21
24
  def natural_key(self):
25
+ """Return the natural key of this label type"""
22
26
  return (self.name,)
23
27
 
24
28
  def __str__(self):
25
- return self.name
29
+ return str(self.name)
26
30
 
27
31
 
28
32
  class LabelManager(models.Manager):
33
+ """Manager class for handling Label model operations."""
34
+
29
35
  def get_by_natural_key(self, name):
36
+ """Retrieves a Label instance by its natural key (name)."""
30
37
  return self.get(name=name)
31
38
 
39
+
32
40
  class Label(models.Model):
33
41
  """
34
42
  A class representing a label.
@@ -39,22 +47,37 @@ class Label(models.Model):
39
47
  description (str): A description of the label.
40
48
 
41
49
  """
50
+
42
51
  name = models.CharField(max_length=255)
43
- label_type = models.ForeignKey("LabelType", on_delete=models.CASCADE, related_name="labels")
52
+ label_type = models.ForeignKey(
53
+ "LabelType", on_delete=models.CASCADE, related_name="labels"
54
+ )
44
55
  description = models.TextField(blank=True, null=True)
45
56
 
46
57
  objects = LabelManager()
47
58
 
48
59
  def natural_key(self):
60
+ """Return the natural key of this label"""
49
61
  return (self.name,)
50
62
 
51
63
  def __str__(self):
52
- return self.name
64
+ return str(self.name)
65
+
53
66
 
54
67
  class LabelSetManager(models.Manager):
68
+ """
69
+ Manager class for handling LabelSet model operations.
70
+ Methods
71
+ -------
72
+ get_by_natural_key(name)
73
+
74
+ """
75
+
55
76
  def get_by_natural_key(self, name):
77
+ """Retrieves a LabelSet instance by its natural key (name)."""
56
78
  return self.get(name=name)
57
79
 
80
+
58
81
  class LabelSet(models.Model):
59
82
  """
60
83
  A class representing a label set.
@@ -64,21 +87,26 @@ class LabelSet(models.Model):
64
87
  description (str): A description of the label set.
65
88
 
66
89
  """
90
+
67
91
  name = models.CharField(max_length=255)
68
92
  description = models.TextField(blank=True, null=True)
69
93
  version = models.IntegerField()
70
94
  labels = models.ManyToManyField("Label", related_name="labels")
71
-
95
+
72
96
  objects = LabelSetManager()
73
97
 
74
98
  def natural_key(self):
99
+ """Return the natural key of this label set"""
75
100
  return (self.name,)
76
101
 
77
102
  def __str__(self):
78
- return self.name
79
-
103
+ return str(self.name)
104
+
80
105
  def get_labels_in_order(self):
81
106
  """
82
107
  Get all labels in this label set as list in the correct order.
108
+ Ordered by string representation (a is first).
83
109
  """
84
- return list(self.labels.all().order_by('id'))
110
+ labels = list(self.labels.all())
111
+ labels.sort(key=lambda x: x.name)
112
+ return labels
@@ -63,7 +63,11 @@ class LabValue(models.Model):
63
63
  warnings.warn("No default distribution set for lab value")
64
64
  return None
65
65
 
66
- def get_normal_range(self, age=None, gender=None):
66
+ def get_normal_range(self, age:int=None, gender=None):
67
+ from endoreg_db.models import Gender
68
+ assert isinstance(age, int) or age is None
69
+ assert isinstance(gender, Gender) or gender is None
70
+
67
71
  age_dependent = self.normal_range_age_dependent
68
72
  gender_dependent = self.normal_range_gender_dependent
69
73
  special_case = self.normal_range_special_case
@@ -90,7 +94,7 @@ class LabValue(models.Model):
90
94
  choices = ["male", "female"]
91
95
  gender = choice(choices)
92
96
 
93
- default_range_dict = self.default_normal_range.get(gender, {})
97
+ default_range_dict = self.default_normal_range.get(gender.name, {})
94
98
  min_value = default_range_dict.get('min', None)
95
99
  max_value = default_range_dict.get('max', None)
96
100
 
@@ -98,5 +102,10 @@ class LabValue(models.Model):
98
102
  # get normal range for special case
99
103
  warnings.warn("Special case normal range not implemented yet")
100
104
 
101
- return min_value, max_value
105
+ normal_range_dict = {
106
+ "min": min_value,
107
+ "max": max_value
108
+ }
109
+
110
+ return normal_range_dict
102
111
 
@@ -1,4 +1,11 @@
1
1
  from .base import AbstractLogEntry
2
2
  from .network_device import NetworkDeviceLogEntry
3
3
  from .log_type import LogType
4
- from .agl_service import AglServiceLogEntry
4
+ from .agl_service import AglServiceLogEntry
5
+
6
+ __all__ = [
7
+ "AbstractLogEntry",
8
+ "NetworkDeviceLogEntry",
9
+ "LogType",
10
+ "AglServiceLogEntry",
11
+ ]
@@ -0,0 +1,4 @@
1
+ from .client import LxClientType, LxClientTag, LxClient
2
+ from .identity import LxIdentity, LxIdentityType
3
+ from .permission import LxPermission
4
+ from .user import LxUser
@@ -0,0 +1,57 @@
1
+ # Insert models for Client, Client Type, Client Tag
2
+
3
+ from django.db import models
4
+
5
+ class LxClientTypeManager(models.Manager):
6
+ def get_by_natural_key(self, name):
7
+ return self.get(name=name)
8
+
9
+ #TODO implement base population for client Type
10
+
11
+ class LxClientType(models.Model):
12
+ name = models.CharField(max_length=100, unique=True)
13
+ abbreviation = models.CharField(max_length=10, unique=True) # New field
14
+ description = models.TextField(blank=True)
15
+ objects = LxClientTypeManager()
16
+
17
+ def __str__(self):
18
+ return self.name
19
+
20
+ def natural_key(self):
21
+ return (self.name,)
22
+
23
+
24
+ class LxClientTagManager(models.Manager):
25
+ def get_by_natural_key(self, name):
26
+ return self.get(name=name)
27
+
28
+ #TODO implement base population for client Tag
29
+
30
+ class LxClientTag(models.Model):
31
+ name = models.CharField(max_length=100, unique=True)
32
+ description = models.TextField(blank=True)
33
+ objects = LxClientTagManager()
34
+
35
+ # M2M relationship with LxPermission
36
+ permissions = models.ManyToManyField('LxPermission', blank=True, related_name="allowed_client_tags")
37
+
38
+ def __str__(self):
39
+ return self.name
40
+
41
+ def natural_key(self):
42
+ return (self.name,)
43
+
44
+ class LxClientManager(models.Manager):
45
+ def get_by_natural_key(self, name):
46
+ return self.get(name=name)
47
+
48
+ #TODO implement base population for client
49
+
50
+ class LxClient(models.Model):
51
+ name = models.CharField(max_length=100, unique=True)
52
+ description = models.TextField(blank=True)
53
+ client_type = models.ForeignKey(LxClientType, on_delete=models.CASCADE)
54
+ client_tags = models.ManyToManyField(LxClientTag, blank=True)
55
+ vpn_ip = models.GenericIPAddressField(blank=True, null=True)
56
+ objects = LxClientManager()
57
+
@@ -0,0 +1,34 @@
1
+ from django.db import models
2
+
3
+ class LxIdentityTypeManager(models.Manager):
4
+ def get_by_natural_key(self, name):
5
+ return self.get(name=name)
6
+
7
+ #TODO implement base population for identity Type
8
+ ## ed25519, rsa, ecdsa, dsa, etc
9
+
10
+ class LxIdentityType(models.Model):
11
+ name = models.CharField(max_length=100, unique=True)
12
+ description = models.TextField(blank=True)
13
+ objects = LxIdentityTypeManager()
14
+
15
+ def __str__(self):
16
+ return self.name
17
+
18
+ def natural_key(self):
19
+ return (self.name,)
20
+
21
+ class LxIdentity(models.Model):
22
+ name = models.CharField(max_length=100, unique=True)
23
+ description = models.TextField(blank=True)
24
+ identity_type = models.ForeignKey(LxIdentityType, on_delete=models.CASCADE)
25
+ objects = models.Manager()
26
+
27
+ # Foreign key to user, nullable
28
+ user = models.ForeignKey('LxUser', on_delete=models.CASCADE, null=True, blank=True)
29
+
30
+ def __str__(self):
31
+ return self.name
32
+
33
+ def natural_key(self):
34
+ return (self.name,)
@@ -0,0 +1,18 @@
1
+ from django.db import models
2
+
3
+ class LxPermissionManager(models.Manager):
4
+ def get_by_natural_key(self, name):
5
+ return self.get(name=name)
6
+
7
+ #TODO implement base population for permission
8
+
9
+ class LxPermission(models.Model):
10
+ name = models.CharField(max_length=100, unique=True)
11
+ description = models.TextField(blank=True)
12
+ objects = LxPermissionManager()
13
+
14
+ def __str__(self):
15
+ return self.name
16
+
17
+ def natural_key(self):
18
+ return (self.name,)
@@ -0,0 +1,16 @@
1
+ from django.db import models
2
+
3
+ class LxUserManager(models.Manager):
4
+ def get_by_natural_key(self, name):
5
+ return self.get(name=name)
6
+
7
+
8
+ class LxUser(models.Model):
9
+ name = models.CharField(max_length=100, unique=True)
10
+ description = models.TextField(blank=True)
11
+
12
+
13
+
14
+ # to be extended
15
+
16
+
@@ -1 +1,19 @@
1
- from .medication import *
1
+ """Medication models initialization module."""
2
+ from .medication import Medication, MedicationManager
3
+ from .medication_schedule import MedicationSchedule, MedicationScheduleManager
4
+ from .medication_intake_time import MedicationIntakeTime, MedicationIntakeTimeManager
5
+ from .medication_indication_type import MedicationIndicationType, MedicationIndicationTypeManager
6
+ from .medication_indication import MedicationIndication, MedicationIndicationManager
7
+
8
+ __all__ = [
9
+ "Medication",
10
+ "MedicationManager",
11
+ "MedicationSchedule",
12
+ "MedicationScheduleManager",
13
+ "MedicationIntakeTime",
14
+ "MedicationIntakeTimeManager",
15
+ "MedicationIndicationType",
16
+ "MedicationIndicationTypeManager",
17
+ "MedicationIndication",
18
+ "MedicationIndicationManager"
19
+ ]