22from django .utils .translation import gettext_lazy as _
33from django .contrib .postgres .indexes import GinIndex
44
5+ import datetime
6+
57class StandardFlag (models .TextChoices ):
68 """
79 See `standard_concept` column of `CONCEPT` table found in `OHDSI docs`_.
@@ -11,6 +13,7 @@ class StandardFlag(models.TextChoices):
1113 STANDARD = 'S' , _ ('Standard Concept' )
1214 CLASSIFICATION = 'C' , _ ('Classification Concept' )
1315
16+
1417class InvalidFlag (models .TextChoices ):
1518 """
1619 See `invalid_reason` column of `CONCEPT` table found in `OHDSI docs`_.
@@ -20,106 +23,181 @@ class InvalidFlag(models.TextChoices):
2023 DEPRECATED = 'D' , _ ('Deprecated' )
2124 UPGRADED = 'U' , _ ('Upgraded' )
2225
26+
2327class OMOP_CODES (models .Model ):
24- """
25- Represents a standardised `OMOP`_ code from its Common Data Model, related to :model:`clinicalcode.CodingSystem`.
26-
27- Version
28- -------
29- Vocabulary version: `v20250827`
30-
31- Reference
32- ---------
33- See `OHDSI Single-page docs`_.
34-
35- Mapping
36- ----------
37- | Attribute | Table->Column |
38- |:---------------------|:---------------------------------|
39- | `code` | `CONCEPT->concept_id` |
40- | `description` | `CONCEPT->concept_name` |
41- | `is_code` | `N/A` |
42- | `is_valid` | `N/A` |
43- | `standard_concept` | `CONCEPT->standard_concept` |
44- | `coding_name` | `N/A` |
45- | `coding_system_id` | `N/A` |
46- | `domain_name` | `CONCEPT->domain_id` |
47- | `class_name` | `CONCEPT->concept_class_id` |
48- | `vocabulary_name` | `CONCEPT->vocabulary_id` |
49- | `vocabulary_code` | `CONCEPT->concept_code` |
50- | `vocabulary_version` | `VOCABULARY->vocabulary_version` |
51- | `valid_start_date` | `CONCEPT->valid_start_date` |
52- | `valid_end_date` | `CONCEPT->valid_end_date` |
53- | `invalid_reason` | `CONCEPT->invalid_reason` |
54- | `created` | `N/A` |
55- | `modified` | `N/A` |
56-
57- .. _OMOP: https://www.ohdsi.org/data-standardization/
58- .. _OHDSI Single-page docs: https://www.ohdsi.org/web/wiki/doku.php?id=documentation:cdm:single-page
59- """
60- id = models .BigAutoField (auto_created = True , primary_key = True )
61- code = models .CharField (max_length = 64 , null = True , blank = True , unique = True , default = '' )
62- description = models .CharField (max_length = 256 , null = True , blank = True , default = '' )
63- is_code = models .BooleanField (null = False , default = True )
64- is_valid = models .BooleanField (null = False , default = True )
65- standard_concept = models .CharField (
66- # 'S', 'C' or NULL
67- null = True ,
68- blank = True ,
69- choices = StandardFlag .choices ,
70- default = None ,
71- max_length = 1 ,
72- )
73- coding_name = models .CharField (max_length = 256 , null = True , blank = True , default = '' )
74- coding_system = models .ForeignKey (
75- 'clinicalcode.CodingSystem' ,
76- on_delete = models .SET_NULL ,
77- null = True ,
78- blank = True ,
79- default = None ,
80- related_name = 'omop_code'
81- )
82- domain_name = models .CharField (max_length = 256 , null = True , blank = True , default = '' )
83- class_name = models .CharField (max_length = 256 , null = True , blank = True , default = '' )
84- vocabulary_name = models .CharField (max_length = 64 , null = True , blank = True , default = '' )
85- vocabulary_code = models .CharField (max_length = 64 , null = True , blank = True , default = '' )
86- vocabulary_version = models .CharField (max_length = 256 , null = True , blank = True , default = '' )
87- valid_start_date = models .DateField (null = True , blank = True )
88- valid_end_date = models .DateField (null = True , blank = True )
89- invalid_reason = models .CharField (
90- # 'D', 'U' or NULL
91- null = True ,
92- blank = True ,
93- choices = InvalidFlag .choices ,
94- default = None ,
95- max_length = 1 ,
96- )
97- created = models .DateTimeField (auto_now_add = True , editable = True )
98- modified = models .DateTimeField (auto_now_add = True , editable = True )
99-
100- class Meta :
101- ordering = ('id' ,)
102- indexes = [
103- models .Index (fields = ['id' ]),
104- models .Index (fields = ['created' ]),
105- GinIndex (
106- name = 'omop_cd_trgm_idx' ,
107- fields = ['code' ],
108- opclasses = ['gin_trgm_ops' ]
109- ),
110- GinIndex (
111- name = 'omop_desc_trgm_idx' ,
112- fields = ['description' ],
113- opclasses = ['gin_trgm_ops' ]
114- ),
115- GinIndex (
116- name = 'omop_cs_trgm_idx' ,
117- fields = ['coding_name' ],
118- opclasses = ['gin_trgm_ops' ]
119- ),
120- GinIndex (
121- name = 'omop_vscd_trgm_idx' ,
122- fields = ['vocabulary_code' ],
123- opclasses = ['gin_trgm_ops' ]
124- ),
125- ]
28+ """
29+ Represents a standardised `OMOP`_ code from its Common Data Model, related to :model:`clinicalcode.CodingSystem`.
30+
31+ Version
32+ -------
33+ Vocabulary version: `v20250827`
34+
35+ Reference
36+ ---------
37+ See `OHDSI Single-page docs`_.
38+
39+ Mapping
40+ -------
41+ | Attribute | Table->Column |
42+ |:---------------------|:---------------------------------|
43+ | `code` | `CONCEPT->concept_id` |
44+ | `description` | `CONCEPT->concept_name` |
45+ | `is_code` | `N/A` |
46+ | `is_valid` | `N/A` |
47+ | `standard_concept` | `CONCEPT->standard_concept` |
48+ | `coding_name` | `N/A` |
49+ | `coding_system_id` | `N/A` |
50+ | `domain_name` | `CONCEPT->domain_id` |
51+ | `class_name` | `CONCEPT->concept_class_id` |
52+ | `vocabulary_name` | `CONCEPT->vocabulary_id` |
53+ | `vocabulary_code` | `CONCEPT->concept_code` |
54+ | `vocabulary_version` | `VOCABULARY->vocabulary_version` |
55+ | `valid_start_date` | `CONCEPT->valid_start_date` |
56+ | `valid_end_date` | `CONCEPT->valid_end_date` |
57+ | `invalid_reason` | `CONCEPT->invalid_reason` |
58+ | `created` | `N/A` |
59+ | `modified` | `N/A` |
60+
61+ .. _OMOP: https://www.ohdsi.org/data-standardization/
62+ .. _OHDSI Single-page docs: https://www.ohdsi.org/web/wiki/doku.php?id=documentation:cdm:single-page
63+ """
64+ id = models .BigAutoField (auto_created = True , primary_key = True )
65+ code = models .CharField (max_length = 64 , null = True , blank = True , unique = True , default = '' )
66+ description = models .CharField (max_length = 256 , null = True , blank = True , default = '' )
67+ is_code = models .BooleanField (null = False , default = True )
68+ is_valid = models .BooleanField (null = False , default = True )
69+ standard_concept = models .CharField (
70+ # 'S', 'C' or NULL
71+ null = True ,
72+ blank = True ,
73+ choices = StandardFlag .choices ,
74+ default = None ,
75+ max_length = 1 ,
76+ )
77+ coding_name = models .CharField (max_length = 256 , null = True , blank = True , default = '' )
78+ coding_system = models .ForeignKey (
79+ 'clinicalcode.CodingSystem' ,
80+ on_delete = models .SET_NULL ,
81+ null = True ,
82+ blank = True ,
83+ default = None ,
84+ related_name = 'omop_code'
85+ )
86+ domain_name = models .CharField (max_length = 256 , null = True , blank = True , default = '' )
87+ class_name = models .CharField (max_length = 256 , null = True , blank = True , default = '' )
88+ vocabulary_name = models .CharField (max_length = 64 , null = True , blank = True , default = '' )
89+ vocabulary_code = models .CharField (max_length = 64 , null = True , blank = True , default = '' )
90+ vocabulary_version = models .CharField (max_length = 256 , null = True , blank = True , default = '' )
91+ valid_start_date = models .DateField (blank = True , null = True )
92+ valid_end_date = models .DateField (blank = True , default = datetime .date (2099 ,12 ,31 ))
93+ invalid_reason = models .CharField (
94+ # 'D', 'U' or NULL
95+ null = True ,
96+ blank = True ,
97+ choices = InvalidFlag .choices ,
98+ default = None ,
99+ max_length = 1 ,
100+ )
101+ created = models .DateTimeField (auto_now_add = True , editable = True )
102+ modified = models .DateTimeField (auto_now_add = True , editable = True )
103+
104+ class Meta :
105+ ordering = ('id' ,)
106+ indexes = [
107+ models .Index (fields = ['id' ]),
108+ models .Index (fields = ['created' ]),
109+ GinIndex (
110+ name = 'omop_cd_trgm_idx' ,
111+ fields = ['code' ],
112+ opclasses = ['gin_trgm_ops' ]
113+ ),
114+ GinIndex (
115+ name = 'omop_desc_trgm_idx' ,
116+ fields = ['description' ],
117+ opclasses = ['gin_trgm_ops' ]
118+ ),
119+ GinIndex (
120+ name = 'omop_cs_trgm_idx' ,
121+ fields = ['coding_name' ],
122+ opclasses = ['gin_trgm_ops' ]
123+ ),
124+ GinIndex (
125+ name = 'omop_vscd_trgm_idx' ,
126+ fields = ['vocabulary_code' ],
127+ opclasses = ['gin_trgm_ops' ]
128+ ),
129+ ]
130+
131+
132+ class OMOPRelationships (models .Model ):
133+ """
134+ Represents the edges, or `relationships`_, between OMOP concepts stored in :model:`clinicalcode.OMOP_CODES`.
135+
136+ Version
137+ -------
138+ Vocabulary version: `v20250827`
139+
140+ Reference
141+ ---------
142+ See:
143+ - `Concept Relationship Data Model Conventions`_.
144+ - `CONCEPT_RELATIONSHIP table`_.
145+
146+ Mapping
147+ -------
148+ | Attribute | Table->Column |
149+ |:---------------------|:-----------------------------------------|
150+ | `code0_id` | `CONCEPT_RELATIONSHIP->concept_id_1` |
151+ | `code1_id` | `CONCEPT_RELATIONSHIP->concept_id_2` |
152+ | `relationship` | `CONCEPT_RELATIONSHIP->relationship_id` |
153+ | `valid_start_date` | `CONCEPT_RELATIONSHIP->valid_start_date` |
154+ | `valid_end_date` | `CONCEPT_RELATIONSHIP->valid_end_date` |
155+ | `invalid_reason` | `CONCEPT_RELATIONSHIP->invalid_reason` |
156+
157+ .. _relationships: https://www.ohdsi.org/web/wiki/doku.php?id=documentation:cdm:concept_relationship
158+ .. _Concept Relationship Data Model Conventions: https://ohdsi.github.io/CommonDataModel/dataModelConventions.html#Concept_Relationships
159+ .. _CONCEPT_RELATIONSHIP table: https://www.ohdsi.org/web/wiki/doku.php?id=documentation:cdm:concept_relationship
160+ """
161+ id = models .BigAutoField (auto_created = True , primary_key = True )
162+ code0 = models .ForeignKey (
163+ to = 'OMOP_CODES' ,
164+ to_field = 'code' ,
165+ related_name = f'source_relationships' ,
166+ on_delete = models .CASCADE ,
167+ )
168+ code1 = models .ForeignKey (
169+ to = 'OMOP_CODES' ,
170+ to_field = 'code' ,
171+ related_name = f'destination_relationships' ,
172+ on_delete = models .CASCADE ,
173+ )
174+ relationship = models .CharField (max_length = 64 )
175+ valid_start_date = models .DateField (blank = True , auto_now_add = True )
176+ valid_end_date = models .DateField (blank = True , default = datetime .date (2099 ,12 ,31 ))
177+ invalid_reason = models .CharField (
178+ # 'D', 'U' or NULL
179+ null = True ,
180+ blank = True ,
181+ choices = InvalidFlag .choices ,
182+ default = None ,
183+ max_length = 1 ,
184+ )
185+
186+ class Meta :
187+ unique_together = ('code0' , 'code1' , 'relationship' ,)
188+ indexes = [
189+ models .Index (fields = ['code0' ]),
190+ models .Index (fields = ['code1' ]),
191+ models .Index (fields = ['code0' , 'code1' ]),
192+ models .Index (fields = ['code0' , 'relationship' , 'invalid_reason' ]),
193+ GinIndex (
194+ name = 'omop_e0_trgm_idx' ,
195+ fields = ['code0' ],
196+ opclasses = ['gin_trgm_ops' ]
197+ ),
198+ GinIndex (
199+ name = 'omop_e0t_tgbt_idx' ,
200+ fields = ['code0' , 'relationship' , 'invalid_reason' ],
201+ opclasses = ['' , 'gin_trgm_ops' , '' ]
202+ ),
203+ ]
0 commit comments