1 | C0SLAB ; GPL - Smart Lab Processing ;4/15/12 17:05
|
---|
2 | ;;1.0;VISTA SMART CONTAINER;;Sep 26, 2012;Build 5
|
---|
3 | ;Copyright 2012 George Lilly.
|
---|
4 | ;
|
---|
5 | ; This program is free software: you can redistribute it and/or modify
|
---|
6 | ; it under the terms of the GNU Affero General Public License as
|
---|
7 | ; published by the Free Software Foundation, either version 3 of the
|
---|
8 | ; License, or (at your option) any later version.
|
---|
9 | ;
|
---|
10 | ; This program is distributed in the hope that it will be useful,
|
---|
11 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
12 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
13 | ; GNU Affero General Public License for more details.
|
---|
14 | ;
|
---|
15 | ; You should have received a copy of the GNU Affero General Public License
|
---|
16 | ; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
---|
17 | ;
|
---|
18 | Q
|
---|
19 | ;
|
---|
20 | ; sample VistA NHIN lab result
|
---|
21 | ;
|
---|
22 | ;^TMP("C0STBL",32,"lab",8,"collected@value")=3110626.16
|
---|
23 | ;^TMP("C0STBL",32,"lab",8,"comment")="Report Released Date/Time: Jun 26, 2011@19:00"
|
---|
24 | ;^TMP("C0STBL",32,"lab",8,"comment@xml:space")="preserve"
|
---|
25 | ;^TMP("C0STBL",32,"lab",8,"facility@code")=100
|
---|
26 | ;^TMP("C0STBL",32,"lab",8,"facility@name")="VOE OFFICE INSTITUTION"
|
---|
27 | ;^TMP("C0STBL",32,"lab",8,"groupName@value")="CH 0626 47"
|
---|
28 | ;^TMP("C0STBL",32,"lab",8,"high@value")=" 101"
|
---|
29 | ;^TMP("C0STBL",32,"lab",8,"id@value")="CH;6889372.84;67003"
|
---|
30 | ;^TMP("C0STBL",32,"lab",8,"interpretation@value")="H"
|
---|
31 | ;^TMP("C0STBL",32,"lab",8,"labOrderID@value")=336
|
---|
32 | ;^TMP("C0STBL",32,"lab",8,"localName@value")="FBLDGLU"
|
---|
33 | ;^TMP("C0STBL",32,"lab",8,"loinc@value")="14771-0"
|
---|
34 | ;^TMP("C0STBL",32,"lab",8,"low@value")="69 "
|
---|
35 | ;^TMP("C0STBL",32,"lab",8,"orderID@value")=807
|
---|
36 | ;^TMP("C0STBL",32,"lab",8,"result@value")=178
|
---|
37 | ;^TMP("C0STBL",32,"lab",8,"resulted@value")=3110626.190006
|
---|
38 | ;^TMP("C0STBL",32,"lab",8,"sample@value")="SERUM"
|
---|
39 | ;^TMP("C0STBL",32,"lab",8,"specimen@code")="0X500"
|
---|
40 | ;^TMP("C0STBL",32,"lab",8,"specimen@name")="SERUM"
|
---|
41 | ;^TMP("C0STBL",32,"lab",8,"status@value")="completed"
|
---|
42 | ;^TMP("C0STBL",32,"lab",8,"test@value")="FASTING BLOOD GLUCOSE"
|
---|
43 | ;^TMP("C0STBL",32,"lab",8,"type@value")="CH"
|
---|
44 | ;^TMP("C0STBL",32,"lab",8,"units@value")="MG/DL"
|
---|
45 | ;^TMP("C0STBL",32,"lab",8,"vuid@value")=4656342
|
---|
46 | ;
|
---|
47 | ; sample Smart lab result triples
|
---|
48 | ;
|
---|
49 | ;G("loinc:29571-7","dcterms:identifier")="29571-7"
|
---|
50 | ;G("loinc:29571-7","dcterms:title")="Phe DBS Ql"
|
---|
51 | ;G("loinc:29571-7","rdf:type")="sp:Code"
|
---|
52 | ;G("loinc:29571-7","sp:system")="http://loinc.org/codes/"
|
---|
53 | ;G("loinc:38478-4","dcterms:identifier")="38478-4"
|
---|
54 | ;G("loinc:38478-4","dcterms:title")="Biotinidase DBS Ql"
|
---|
55 | ;G("loinc:38478-4","rdf:type")="sp:Code"
|
---|
56 | ;G("loinc:38478-4","sp:system")="http://loinc.org/codes/"
|
---|
57 | ;G("qqWZZIew993","rdf:type")="sp:Attribution"
|
---|
58 | ;G("qqWZZIew993","sp:startDate")="2007-04-21"
|
---|
59 | ;G("qqWZZIew994","rdf:type")="sp:NarrativeResult"
|
---|
60 | ;G("qqWZZIew994","sp:value")="Normal"
|
---|
61 | ;G("qqWZZIew995","dcterms:title")="Biotinidase DBS Ql"
|
---|
62 | ;G("qqWZZIew995","rdf:type")="sp:CodedValue"
|
---|
63 | ;G("qqWZZIew995","sp:code")="loinc:38478-4"
|
---|
64 | ;G("qqWZZIew997","rdf:type")="sp:Attribution"
|
---|
65 | ;G("qqWZZIew997","sp:startDate")="2007-09-08"
|
---|
66 | ;G("qqWZZIew998","rdf:type")="sp:NarrativeResult"
|
---|
67 | ;G("qqWZZIew998","sp:value")="Normal"
|
---|
68 | ;G("qqWZZIew999","dcterms:title")="Phe DBS Ql"
|
---|
69 | ;G("qqWZZIew999","rdf:type")="sp:CodedValue"
|
---|
70 | ;G("qqWZZIew999","sp:code")="loinc:29571-7"
|
---|
71 | ;G("smart:99912345/lab_results/3d9b39249193","rdf:type")="sp:LabResult"
|
---|
72 | ;G("smart:99912345/lab_results/3d9b39249193","sp:belongsTo")="smart:99912345"
|
---|
73 | ;G("smart:99912345/lab_results/3d9b39249193","sp:labName")="qqWZZIew995"
|
---|
74 | ;G("smart:99912345/lab_results/3d9b39249193","sp:narrativeResult")="qqWZZIew994"
|
---|
75 | ;G("smart:99912345/lab_results/3d9b39249193","sp:specimenCollected")="qqWZZIew993"
|
---|
76 | ;G("smart:99912345/lab_results/426c7adc4f54","rdf:type")="sp:LabResult"
|
---|
77 | ;G("smart:99912345/lab_results/426c7adc4f54","sp:belongsTo")="smart:99912345"
|
---|
78 | ;G("smart:99912345/lab_results/426c7adc4f54","sp:labName")="qqWZZIew999"
|
---|
79 | ;G("smart:99912345/lab_results/426c7adc4f54","sp:narrativeResult")="qqWZZIew998"
|
---|
80 | ;G("smart:99912345/lab_results/426c7adc4f54","sp:specimenCollected")="qqWZZIew997"
|
---|
81 | ;
|
---|
82 | ;
|
---|
83 | ; another Smart example, this one with sp:quantitativeResult
|
---|
84 | ;
|
---|
85 | ;G("loinc:786-4","dcterms:identifier")="786-4"
|
---|
86 | ;G("loinc:786-4","dcterms:title")="MCHC RBC Auto-mCnc"
|
---|
87 | ;G("loinc:786-4","rdf:type")="sp:Code"
|
---|
88 | ;G("loinc:786-4","sp:system")="http://loinc.org/codes/"
|
---|
89 | ;G("nodeID:4439","rdf:type")="sp:ValueAndUnit"
|
---|
90 | ;G("nodeID:4439","sp:unit")="g/dL"
|
---|
91 | ;G("nodeID:4439","sp:value")=36.6
|
---|
92 | ;G("nodeID:4613","rdf:type")="sp:ValueAndUnit"
|
---|
93 | ;G("nodeID:4613","sp:unit")="g/dL"
|
---|
94 | ;G("nodeID:4613","sp:value")=32
|
---|
95 | ;G("nodeID:4672","rdf:type")="sp:Attribution"
|
---|
96 | ;G("nodeID:4672","sp:startDate")="2005-03-10"
|
---|
97 | ;G("nodeID:4866","rdf:type")="sp:ValueAndUnit"
|
---|
98 | ;G("nodeID:4866","sp:unit")="g/dL"
|
---|
99 | ;G("nodeID:4866","sp:value")=36
|
---|
100 | ;G("nodeID:4871","dcterms:title")="MCHC RBC Auto-mCnc"
|
---|
101 | ;G("nodeID:4871","rdf:type")="sp:CodedValue"
|
---|
102 | ;G("nodeID:4871","sp:code")="loinc:786-4"
|
---|
103 | ;G("nodeID:5221","rdf:type")="sp:QuantitativeResult"
|
---|
104 | ;G("nodeID:5221","sp:normalRange")="nodeID:5282"
|
---|
105 | ;G("nodeID:5221","sp:valueAndUnit")="nodeID:4439"
|
---|
106 | ;G("nodeID:5282","rdf:type")="sp:ValueRange"
|
---|
107 | ;G("nodeID:5282","sp:maximum")="nodeID:4866"
|
---|
108 | ;G("nodeID:5282","sp:minimum")="nodeID:4613"
|
---|
109 | ;G("smart:1540505/lab_results/2fc100850766","rdf:type")="sp:LabResult"
|
---|
110 | ;G("smart:1540505/lab_results/2fc100850766","sp:belongsTo")="smart:1540505"
|
---|
111 | ;G("smart:1540505/lab_results/2fc100850766","sp:labName")="nodeID:4871"
|
---|
112 | ;G("smart:1540505/lab_results/2fc100850766","sp:quantitativeResult")="nodeID:5221"
|
---|
113 | ;G("smart:1540505/lab_results/2fc100850766","sp:specimenCollected")="nodeID:4672"
|
---|
114 | ;
|
---|
115 | LAB(GRTN,C0SARY) ; GRTN, passed by reference,
|
---|
116 | ; is the return name of the graph created. "" if none
|
---|
117 | ; C0SARY is passed in by reference and is the NHIN array of lab
|
---|
118 | ;
|
---|
119 | I $O(C0SARY("lab",""))="" D Q ;
|
---|
120 | . I $D(DEBUG) W !,"No Labs"
|
---|
121 | S GRTN="" ; default to no labs
|
---|
122 | N C0SGRF
|
---|
123 | S C0SGRF="vistaSmart:"_ZPATID_"/lab_results"
|
---|
124 | I $D(DEBUG) W !,"Processing ",C0SGRF
|
---|
125 | D DELGRAPH^C0XF2N(C0SGRF) ; delete the old graph
|
---|
126 | D INITFARY^C0XF2N("C0XFARY") ; which triple store to use
|
---|
127 | N FARY S FARY="C0XFARY"
|
---|
128 | D USEFARY^C0XF2N(FARY)
|
---|
129 | D VOCINIT^C0XUTIL
|
---|
130 | ;
|
---|
131 | D STARTADD^C0XF2N ; initialize to create triples
|
---|
132 | ;
|
---|
133 | N ZI S ZI=""
|
---|
134 | F S ZI=$O(C0SARY("lab",ZI)) Q:ZI="" D ;
|
---|
135 | . N LRN,ZR ; ZR is the local array for building the new triples
|
---|
136 | . S LRN=$NA(C0SARY("lab",ZI)) ; base for values in this lab result
|
---|
137 | . ;
|
---|
138 | . N RSLTID ; unique Id for this lab result
|
---|
139 | . S RSLTID=C0SGRF_"/"_$$LKY17^C0XF2N ; use a random number
|
---|
140 | . ;
|
---|
141 | . ; i don't like this because the same labs result gets a
|
---|
142 | . ; different ID every time it's reported. Can't trace it back to VistA
|
---|
143 | . ; I'd rather be using id@value ie "id@value")="CH;6889372.84;67003"
|
---|
144 | . ; .. either that or store an OID with the lab result - but that
|
---|
145 | . ; will have to wait for the redesign of file 60.. - gpl 4/16/2012
|
---|
146 | . ;
|
---|
147 | . N LOINC S LOINC=$G(@LRN@("loinc@value"))
|
---|
148 | . I LOINC="" D Q ;
|
---|
149 | . . I $D(DEBUG) W !,"NO LOINC VALUE, SKIPPING"
|
---|
150 | . N LABTST S LABTST=$G(@LRN@("test@value"))
|
---|
151 | . I $D(DEBUG) D ;
|
---|
152 | . . W !,"Processing Lab Result ",RSLTID
|
---|
153 | . . W !,"test: ",LABTST
|
---|
154 | . . W !,"loinc: ",LOINC
|
---|
155 | . ;
|
---|
156 | . ; first do the base result graph
|
---|
157 | . ;
|
---|
158 | . S ZR("rdf:type")="sp:LabResult"
|
---|
159 | . S ZR("sp:belongsTo")=C0SGRF ; the subject for this patient's lab results
|
---|
160 | . ; ie /vista/smart/99912345/lab_results
|
---|
161 | . ;
|
---|
162 | . N LABNAME S LABNAME=$$ANONS^C0XF2N ; new node for lab name
|
---|
163 | . S ZR("sp:labName")=LABNAME
|
---|
164 | . ;
|
---|
165 | . N NARRSLT S NARRSLT=$$ANONS^C0XF2N ; new node for narrative result
|
---|
166 | . S ZR("sp:narrativeResult")=NARRSLT
|
---|
167 | . ;
|
---|
168 | . N QNTRSLT S QNTRSLT=$$ANONS^C0XF2N ; new node for narrative result
|
---|
169 | . S ZR("sp:quantitativeResult")=QNTRSLT
|
---|
170 | . ;
|
---|
171 | . N SPECCOLL S SPECCOLL=$$ANONS^C0XF2N ; new node for specimen collected
|
---|
172 | . S ZR("sp:specimenCollected")=SPECCOLL
|
---|
173 | . ;
|
---|
174 | . D ADDINN^C0XF2N(C0SGRF,RSLTID,.ZR) ; addIfNotNull the triples
|
---|
175 | . K ZR ; clean up
|
---|
176 | . ;
|
---|
177 | . ; create the narrative result graph
|
---|
178 | . ;
|
---|
179 | . N IVAL S IVAL=$G(@LRN@("interpretation@value"))'="" D ; H OR L
|
---|
180 | . I IVAL'=""
|
---|
181 | . . S ZR("rdf:type")="sp:NarrativeResult"
|
---|
182 | . . S ZR("sp:value")=$G(@LRN@("interpretation@value")) ; H or L
|
---|
183 | . . I ZR("sp:value")="L" S ZR("sp:value")="abnormal"
|
---|
184 | . . I ZR("sp:value")="H" S ZR("sp:value")="abnormal"
|
---|
185 | . . I ZR("sp:value")="HH" S ZR("sp:value")="critical"
|
---|
186 | . . I ZR("sp:value")="LL" S ZR("sp:value")="critical"
|
---|
187 | . . D ADDINN^C0XF2N(C0SGRF,NARRSLT,.ZR)
|
---|
188 | . . K ZR
|
---|
189 | . ;
|
---|
190 | . ; create the quantitative result graph
|
---|
191 | . ;
|
---|
192 | . S ZR("rdf:type")="sp:QuantitativeResult"
|
---|
193 | . N NORMNM S NORMNM=$$ANONS^C0XF2N ; new node for normal range graph
|
---|
194 | . N VUNM S VUNM=$$ANONS^C0XF2N ; new node for value and unit graph
|
---|
195 | . N HASNORMAL S HASNORMAL=0
|
---|
196 | . I $G(@LRN@("high@value"))'="" S HASNORMAL=1
|
---|
197 | . I HASNORMAL S ZR("sp:normalRange")=NORMNM
|
---|
198 | . S ZR("sp:valueAndUnit")=VUNM
|
---|
199 | . D ADDINN^C0XF2N(C0SGRF,QNTRSLT,.ZR)
|
---|
200 | . K ZR
|
---|
201 | . ;
|
---|
202 | . ; create the normal range graph
|
---|
203 | . ;
|
---|
204 | . I HASNORMAL D ;
|
---|
205 | . . S ZR("rdf:type")="sp:ValueRange"
|
---|
206 | . . N MAXNM S MAXNM=$$ANONS^C0XF2N ; new node for maximum graph
|
---|
207 | . . N MINNM S MINNM=$$ANONS^C0XF2N ; new node for minimum graph
|
---|
208 | . . S ZR("sp:maximum")=MAXNM
|
---|
209 | . . S ZR("sp:minimum")=MINNM
|
---|
210 | . . D ADDINN^C0XF2N(C0SGRF,NORMNM,.ZR)
|
---|
211 | . . K ZR
|
---|
212 | . . ;
|
---|
213 | . . ; create the maximum graph
|
---|
214 | . . ;
|
---|
215 | . . S ZR("rdf:type")="sp:ValueAndUnit"
|
---|
216 | . . S ZR("sp:unit")=$G(@LRN@("units@value"))
|
---|
217 | . . S ZR("sp:value")=$G(@LRN@("high@value"))
|
---|
218 | . . D ADDINN^C0XF2N(C0SGRF,MAXNM,.ZR)
|
---|
219 | . . K ZR
|
---|
220 | . . ;
|
---|
221 | . . ; create the minimum graph
|
---|
222 | . . ;
|
---|
223 | . . S ZR("rdf:type")="sp:ValueAndUnit"
|
---|
224 | . . S ZR("sp:unit")=$G(@LRN@("units@value"))
|
---|
225 | . . S ZR("sp:value")=$G(@LRN@("low@value"))
|
---|
226 | . . D ADDINN^C0XF2N(C0SGRF,MINNM,.ZR)
|
---|
227 | . . K ZR
|
---|
228 | . ;
|
---|
229 | . ; create the value and unit graph
|
---|
230 | . ;
|
---|
231 | . S ZR("rdf:type")="sp:ValueAndUnit"
|
---|
232 | . S ZR("sp:unit")=$G(@LRN@("units@value"))
|
---|
233 | . I ZR("sp:unit")="" S ZR("sp:unit")="{unknown}" ; was $G(@LRN@("test@value")) gpl
|
---|
234 | . S ZR("sp:value")=$G(@LRN@("result@value"))
|
---|
235 | . D ADDINN^C0XF2N(C0SGRF,VUNM,.ZR)
|
---|
236 | . K ZR
|
---|
237 | . ;
|
---|
238 | . ; create specimen collected graph
|
---|
239 | . ;
|
---|
240 | . S ZR("rdf:type")="sp:Attribution"
|
---|
241 | . S ZR("sp:startDate")=$$SPDATE^C0SUTIL($G(@LRN@("collected@value")))
|
---|
242 | . D ADDINN^C0XF2N(C0SGRF,SPECCOLL,.ZR)
|
---|
243 | . K ZR
|
---|
244 | . ;
|
---|
245 | . ; create lab name graph - this contains the test name and code
|
---|
246 | . ;
|
---|
247 | . I LOINC'="" D ;
|
---|
248 | . . S ZR("rdf:type")="sp:CodedValue"
|
---|
249 | . . S ZR("dcterms:title")=LABTST
|
---|
250 | . . N LOINCNM S LOINCNM="loinc:"_LOINC
|
---|
251 | . . S ZR("sp:code")="loinc:"_LOINC
|
---|
252 | . . D ADDINN^C0XF2N(C0SGRF,LABNAME,.ZR)
|
---|
253 | . . K ZR
|
---|
254 | . . S ZR("dcterms:identifier")=LOINC
|
---|
255 | . . S ZR("dcterms:title")=LABTST
|
---|
256 | . . S ZR("rdf:type")="sp:Code"
|
---|
257 | . . S ZR("sp:system")="http://loinc.org/codes/"
|
---|
258 | . . D ADDINN^C0XF2N(C0SGRF,LOINCNM,.ZR)
|
---|
259 | . . K ZR
|
---|
260 | . ;
|
---|
261 | . ; that's all for now folks (there is more to do like reference ranges
|
---|
262 | . ; and result values)
|
---|
263 | . ;
|
---|
264 | D BULKLOAD^C0XF2N(.C0XFDA)
|
---|
265 | S GRTN=C0SGRF
|
---|
266 | Q
|
---|
267 | ;
|
---|
268 | SAMPLE ; import sample lab tests to the triplestore
|
---|
269 | N GN
|
---|
270 | S GN=$NA(^rdf("lab_results"))
|
---|
271 | D INSRDF^C0XF2N(GN,"/smart/lab/samples")
|
---|
272 | Q
|
---|
273 | ;
|
---|