cql_qdm_patientapi 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +46 -0
- data/.travis.yml +15 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +127 -0
- data/LICENSE +201 -0
- data/README.md +2 -0
- data/README.rdoc +2 -0
- data/Rakefile +32 -0
- data/app/assets/javascripts/cql_qdm_patientapi/.keep +0 -0
- data/app/assets/javascripts/cql_qdm_patientapi.js.coffee +3 -0
- data/app/assets/javascripts/cqlpatient.js.coffee +232 -0
- data/app/assets/javascripts/datatypes/adverseevent.js.coffee +70 -0
- data/app/assets/javascripts/datatypes/allergyintolerance.js.coffee +63 -0
- data/app/assets/javascripts/datatypes/assessment.js.coffee +159 -0
- data/app/assets/javascripts/datatypes/careexperience.js.coffee +47 -0
- data/app/assets/javascripts/datatypes/caregoal.js.coffee +60 -0
- data/app/assets/javascripts/datatypes/characteristic_birthdate.js.coffee +28 -0
- data/app/assets/javascripts/datatypes/communication.js.coffee +116 -0
- data/app/assets/javascripts/datatypes/datatype.js.coffee +44 -0
- data/app/assets/javascripts/datatypes/device.js.coffee +163 -0
- data/app/assets/javascripts/datatypes/diagnosis.js.coffee +67 -0
- data/app/assets/javascripts/datatypes/diagnosticstudy.js.coffee +215 -0
- data/app/assets/javascripts/datatypes/encounter.js.coffee +213 -0
- data/app/assets/javascripts/datatypes/familyhistory.js.coffee +37 -0
- data/app/assets/javascripts/datatypes/immunization.js.coffee +152 -0
- data/app/assets/javascripts/datatypes/intervention.js.coffee +164 -0
- data/app/assets/javascripts/datatypes/laboratorytest.js.coffee +243 -0
- data/app/assets/javascripts/datatypes/medication.js.coffee +486 -0
- data/app/assets/javascripts/datatypes/patient_characteristic.js.coffee +23 -0
- data/app/assets/javascripts/datatypes/patient_characteristic_expired.js.coffee +38 -0
- data/app/assets/javascripts/datatypes/patient_characteristic_payer.js.coffee +33 -0
- data/app/assets/javascripts/datatypes/patient_characteristic_sex.js.coffee +23 -0
- data/app/assets/javascripts/datatypes/physicalexam.js.coffee +223 -0
- data/app/assets/javascripts/datatypes/procedure.js.coffee +296 -0
- data/app/assets/javascripts/datatypes/substance.js.coffee +294 -0
- data/app/assets/javascripts/datatypes/symptom.js.coffee +49 -0
- data/app/assets/javascripts/types/component.js.coffee +71 -0
- data/app/assets/javascripts/types/facility.js.coffee +41 -0
- data/app/assets/javascripts/types/id.js.coffee +23 -0
- data/app/assets/javascripts/utils/helpers.js.coffee +101 -0
- data/bin/rails +12 -0
- data/coffeelint.json +135 -0
- data/cql_qdm_patientapi.gemspec +25 -0
- data/lib/cql_qdm_patientapi/engine.rb +6 -0
- data/lib/cql_qdm_patientapi/version.rb +3 -0
- data/lib/cql_qdm_patientapi.rb +4 -0
- data/vendor/assets/javascripts/cql4browsers.js +53992 -0
- metadata +133 -0
@@ -0,0 +1,232 @@
|
|
1
|
+
###
|
2
|
+
@namespace scoping into the CQL_QDM namespace (all classes and
|
3
|
+
their methods will be accessable through the CQL_QDM namespace)
|
4
|
+
###
|
5
|
+
@CQL_QDM ||= {}
|
6
|
+
|
7
|
+
|
8
|
+
###
|
9
|
+
Represents a patient. The interface aligns with QDM. The internals are
|
10
|
+
HDS mapped to the QDM representation.
|
11
|
+
|
12
|
+
Typical flow of usage:
|
13
|
+
1. Bonnie takes one of its patient records and creates a CQL_QDM.CQLPatient
|
14
|
+
for it.
|
15
|
+
1a. This class takes that patient record and checks for data criteria that
|
16
|
+
exist on it.
|
17
|
+
1b. When it finds a data criteria record, it creates an equivalent
|
18
|
+
CQL_QDM.QDMDatatype instance of that data criteria, and attaches it to
|
19
|
+
the instance of this patient. This process happens in the 'buildDatatypes'
|
20
|
+
method.
|
21
|
+
2. When the CQL execution engine comes across a retrieve statement (e.g.
|
22
|
+
["Encounter Performed"]), it will call 'findRecords' on this class with
|
23
|
+
the name of that profile. The 'findRecords' method will do some parsing,
|
24
|
+
and eventually return an array of CQL_QDM.QDMDatatype(s) that both
|
25
|
+
match that profile and exist on the instance of this patient.
|
26
|
+
3. The CQL_QDM.QDMDatatype directly represents a QDM datatype. The classes
|
27
|
+
that subclass this class (e.g. CQL_QDM.EncounterActive) provide methods
|
28
|
+
that represent the relevant QDM datatypes attributes (e.g.
|
29
|
+
CQL_QDM.EncounterActive.relevantPeriod).
|
30
|
+
4. When a CQL statement takes a data criteria and wants to check an attribute
|
31
|
+
of it, it calls the 'get' method of the CQL_QDM.QDMDatatype superclass with
|
32
|
+
the name of that attribute. This 'get' method takes that attribute and
|
33
|
+
calls the relevant attribute method on that data criteria.
|
34
|
+
5. Each attribute method of a CQL_QDM.QDMDatatype correctly converts the
|
35
|
+
Bonnie value for something into a form that the CQL execution engine
|
36
|
+
can understand.
|
37
|
+
###
|
38
|
+
class CQL_QDM.CQLPatient
|
39
|
+
constructor: (patient) ->
|
40
|
+
@_patient = patient
|
41
|
+
@_datatypes = @buildDatatypes()
|
42
|
+
|
43
|
+
###
|
44
|
+
@returns {String}
|
45
|
+
###
|
46
|
+
id: ->
|
47
|
+
@_patient.id
|
48
|
+
|
49
|
+
###
|
50
|
+
This method is called by the CQL execution engine on a CQLPatient when
|
51
|
+
the execution engine wants information on a record. A record could be patient
|
52
|
+
characteristic information about the patient, or it could be data criteria
|
53
|
+
that currently exist on this patient (data criteria you drag on a patient
|
54
|
+
in Bonnie's patient builder).
|
55
|
+
|
56
|
+
@param {String} profile - the data criteria requested by the execution engine
|
57
|
+
@returns {Object}
|
58
|
+
###
|
59
|
+
findRecords: (profile) ->
|
60
|
+
if profile == 'Patient'
|
61
|
+
# Requested generic patient info
|
62
|
+
@getPatientMetadata()
|
63
|
+
else if /PatientCharacteristic/.test profile
|
64
|
+
# Requested a patient characteristic
|
65
|
+
@getPatientCharacteristic(profile)
|
66
|
+
else if profile?
|
67
|
+
# Requested something else (probably a QDM data type).
|
68
|
+
|
69
|
+
# Strip model details from request. The requested profile string contains
|
70
|
+
# a lot of things we don't need or care about. Example, we might see
|
71
|
+
# something like:
|
72
|
+
# "{urn:healthit-gov:qdm:v5_0_draft}PatientCharacteristicEthnicity"
|
73
|
+
# Where we only care about: "PatientCharacteristicEthnicity".
|
74
|
+
profile = profile.replace(/ *\{[^)]*\} */g, '')
|
75
|
+
|
76
|
+
# Check and handle negation status
|
77
|
+
if /Positive/.test profile
|
78
|
+
profile = profile.replace /Positive/, ''
|
79
|
+
# Since the data criteria is 'Positive', it is not negated.
|
80
|
+
return @getNegatableDataCriteria(profile, false)
|
81
|
+
else if /Negative/.test profile
|
82
|
+
profile = profile.replace /Negative/, ''
|
83
|
+
# Since the data criteria is 'Negative', it is negated.
|
84
|
+
return @getNegatableDataCriteria(profile, true)
|
85
|
+
else
|
86
|
+
# No negation status, proceed normally
|
87
|
+
if @_datatypes[profile]? then return @_datatypes[profile] else []
|
88
|
+
else
|
89
|
+
[]
|
90
|
+
|
91
|
+
###
|
92
|
+
Handles requests for patient characteristic information (e.g. birthdate).
|
93
|
+
|
94
|
+
@param {String} profile - the data criteria requested by the execution engine
|
95
|
+
@returns {Array of Objects}
|
96
|
+
###
|
97
|
+
getPatientCharacteristic: (profile) ->
|
98
|
+
if /PatientCharacteristicSex/.test profile
|
99
|
+
# Requested sex
|
100
|
+
[new CQL_QDM.PatientCharacteristicSex(@_patient)]
|
101
|
+
else if /PatientCharacteristicBirthdate/.test profile
|
102
|
+
# Requested birthdate
|
103
|
+
[new CQL_QDM.PatientCharacteristicBirthdate(@_patient)]
|
104
|
+
else if /PatientCharacteristicExpired/.test profile
|
105
|
+
# Requested deathdate
|
106
|
+
[new CQL_QDM.PatientCharacteristicExpired(@_patient)]
|
107
|
+
else
|
108
|
+
# Check if there are PatientCharateristic qdm datatypes that can be returned
|
109
|
+
profile = profile.replace(/ *\{[^)]*\} */g, '')
|
110
|
+
@_datatypes[profile] || []
|
111
|
+
|
112
|
+
###
|
113
|
+
Searches the patient's history for data criteria that match the given
|
114
|
+
profile (keeping in mind negated status). Specifically, if we wanted
|
115
|
+
something that was negated, and we only have an instance of that thing
|
116
|
+
without a negation, we would not include it.
|
117
|
+
|
118
|
+
@param {String} profile - the data criteria requested by the execution engine
|
119
|
+
@param {Boolean} isNegated - the negated type of data criteria to look for
|
120
|
+
@returns {Array}
|
121
|
+
###
|
122
|
+
getNegatableDataCriteria: (profile, isNegated) ->
|
123
|
+
results = []
|
124
|
+
if @_datatypes[profile]?
|
125
|
+
for dataCriteria in @_datatypes[profile]
|
126
|
+
if isNegated
|
127
|
+
if dataCriteria._negationRationale != null && dataCriteria._negationRationale != undefined
|
128
|
+
results.push dataCriteria
|
129
|
+
else
|
130
|
+
if dataCriteria._negationRationale == null || dataCriteria._negationRationale == undefined
|
131
|
+
results.push dataCriteria
|
132
|
+
results
|
133
|
+
|
134
|
+
###
|
135
|
+
This method searches through the Bonnie patient for data criteria (i.e. the
|
136
|
+
data criteria that have been dragged on a patient in Bonnie's patient
|
137
|
+
builder). It then takes what it finds and creates CQL_QDM.QDMDatatype
|
138
|
+
versions of them for future lookups by the execution engine.
|
139
|
+
|
140
|
+
@returns {Object}
|
141
|
+
###
|
142
|
+
buildDatatypes: ->
|
143
|
+
# TODO: this datatypes scheme needs to be made more robust. It is too dependent
|
144
|
+
# on matching strings that don't always match.
|
145
|
+
|
146
|
+
# HDS based list that describe various QDM concepts.
|
147
|
+
# See lib/health-data-standards/models/record.rb in HDS for the origin
|
148
|
+
# of these types.
|
149
|
+
types = [
|
150
|
+
'adverse_events',
|
151
|
+
'assessments',
|
152
|
+
'allergies',
|
153
|
+
'care_goals',
|
154
|
+
'conditions',
|
155
|
+
'encounters',
|
156
|
+
'communications',
|
157
|
+
'family_history',
|
158
|
+
'immunizations',
|
159
|
+
'medical_equipment',
|
160
|
+
'medications',
|
161
|
+
'procedures',
|
162
|
+
'results',
|
163
|
+
'social_history',
|
164
|
+
'vital_signs',
|
165
|
+
'devices',
|
166
|
+
'diagnostic_studies',
|
167
|
+
'functional_statuses',
|
168
|
+
'interventions',
|
169
|
+
'laboratory_tests',
|
170
|
+
'physical_exams',
|
171
|
+
'risk_category_assessments',
|
172
|
+
'care_experiences',
|
173
|
+
'preferences',
|
174
|
+
'provider_characteristics',
|
175
|
+
'substances',
|
176
|
+
'system_characteristics',
|
177
|
+
'transfers'
|
178
|
+
]
|
179
|
+
data_types = {}
|
180
|
+
for type in types
|
181
|
+
data_criteria = @_patient.get(type)
|
182
|
+
if data_criteria
|
183
|
+
# Looks like this patient has at least one instance of this type of
|
184
|
+
# data criteria; loop over them and create CQL_QDM.QDMDatatype of them.
|
185
|
+
for dc in data_criteria
|
186
|
+
# Construct a classname from the data criteria
|
187
|
+
# e.g. "Encounter, Performed: Face-to-Face Interaction" becomes
|
188
|
+
# EncounterPerformed
|
189
|
+
# TODO: this needs to be modified to look at the HQMF template OID instead of the description
|
190
|
+
classname = dc.description.substr(0, dc.description.lastIndexOf(':'))
|
191
|
+
# remove commas, slashes, and colons
|
192
|
+
classname = classname.replace(/,/g, '').replace(/\//g, '').replace(/:/g, '')
|
193
|
+
# make all words start upper case
|
194
|
+
classname = classname.replace(/\w\S*/g, (txt) ->
|
195
|
+
txt.charAt(0).toUpperCase() + txt.substr(1))
|
196
|
+
# both 'discharge' and 'order' are present tense when positive and past tense when negative.
|
197
|
+
# need to make consistently present tense (this is what is in the model-info file).
|
198
|
+
classname = classname.replace(/Ordered$/g, "Order")
|
199
|
+
classname = classname.replace(/Discharged$/g, "Discharge")
|
200
|
+
# remove spaces
|
201
|
+
classname = classname.replace(/ /g, '')
|
202
|
+
unless data_types[classname]?
|
203
|
+
data_types[classname] = []
|
204
|
+
# Checks that the key 'classname' exists in the CQL_QDM object
|
205
|
+
# confirming that a QDM datatype profile has been selected.
|
206
|
+
if classname of CQL_QDM
|
207
|
+
cql_dc = new CQL_QDM[classname](dc)
|
208
|
+
# Keep track of the 'bonnie' type for use in the 'Learn CQL' tool
|
209
|
+
cql_dc['bonnie_type'] = type
|
210
|
+
data_types[classname].push cql_dc
|
211
|
+
data_types
|
212
|
+
|
213
|
+
###
|
214
|
+
Returns metadata information about this patient.
|
215
|
+
This metadata is composed of:
|
216
|
+
- birthDatetime (the birth date and time of the patient)
|
217
|
+
- gender (the sex of the patient)
|
218
|
+
|
219
|
+
@returns {Object}
|
220
|
+
###
|
221
|
+
getPatientMetadata: ->
|
222
|
+
# Note about 'gender' key:
|
223
|
+
# If the execution engine wants an attribute of the patient
|
224
|
+
# directly, it calls findRecord with a profile of Patient, and
|
225
|
+
# looks at that object for things. Other times CQL might treat
|
226
|
+
# things like gender/sex as a data criteria (i.e. PatientPatientCharacteristicSex),
|
227
|
+
# and calls things like getCode on them. The info['gender'] is for the
|
228
|
+
# former case.
|
229
|
+
info = {}
|
230
|
+
info['birthDatetime'] = CQL_QDM.Helpers.convertDateTime(@_patient.get('birthdate'))
|
231
|
+
info['gender'] = @_patient.get('gender')
|
232
|
+
[info]
|
@@ -0,0 +1,70 @@
|
|
1
|
+
###
|
2
|
+
@namespace scoping into the CQL_QDM namespace (all classes and
|
3
|
+
their methods will be accessable through the CQL_QDM namespace)
|
4
|
+
###
|
5
|
+
@CQL_QDM ||= {}
|
6
|
+
|
7
|
+
###
|
8
|
+
Data elements that meet criteria using this datatype should document the Adverse
|
9
|
+
Event and its corresponding value set.
|
10
|
+
###
|
11
|
+
class CQL_QDM.AdverseEvent extends CQL_QDM.QDMDatatype
|
12
|
+
###
|
13
|
+
@param {Object} entry - the HDS data criteria object to convert
|
14
|
+
###
|
15
|
+
constructor: (@entry) ->
|
16
|
+
super @entry
|
17
|
+
@_authorDatetime = CQL_QDM.Helpers.convertDateTime(@entry.start_time)
|
18
|
+
@_facilityLocation = @entry.facility
|
19
|
+
@_relevantPeriodLow = CQL_QDM.Helpers.convertDateTime(@entry.start_time)
|
20
|
+
if @entry.end_time
|
21
|
+
@_relevantPeriodHigh = CQL_QDM.Helpers.convertDateTime(@entry.end_time)
|
22
|
+
else
|
23
|
+
# No end time; high is set to infinity
|
24
|
+
@_relevantPeriodHigh = CQL_QDM.Helpers.infinityDateTime()
|
25
|
+
@_severity = @entry.severity
|
26
|
+
@_type = @entry.type
|
27
|
+
|
28
|
+
###
|
29
|
+
@returns {Date}
|
30
|
+
###
|
31
|
+
authorDatetime: ->
|
32
|
+
@_authorDatetime
|
33
|
+
|
34
|
+
###
|
35
|
+
@returns {FacilityLocation}
|
36
|
+
###
|
37
|
+
facilityLocation: ->
|
38
|
+
if @_facilityLocation?.values?[0]?
|
39
|
+
new CQL_QDM.FacilityLocation(@_facilityLocation.values[0])
|
40
|
+
else
|
41
|
+
null
|
42
|
+
|
43
|
+
###
|
44
|
+
@returns {Interval<Date>}
|
45
|
+
###
|
46
|
+
relevantPeriod: ->
|
47
|
+
low = @_relevantPeriodLow
|
48
|
+
high = @_relevantPeriodHigh
|
49
|
+
if low?
|
50
|
+
new cql.Interval(low, high)
|
51
|
+
else
|
52
|
+
null
|
53
|
+
|
54
|
+
###
|
55
|
+
@returns {Code}
|
56
|
+
###
|
57
|
+
severity: ->
|
58
|
+
if @_severity?
|
59
|
+
new cql.Code(@_severity.code, @_severity.code_system)
|
60
|
+
else
|
61
|
+
null
|
62
|
+
|
63
|
+
###
|
64
|
+
@returns {Code}
|
65
|
+
###
|
66
|
+
type: ->
|
67
|
+
if @_type?
|
68
|
+
new cql.Code(@_type.code, @_type.code_system)
|
69
|
+
else
|
70
|
+
null
|
@@ -0,0 +1,63 @@
|
|
1
|
+
###
|
2
|
+
@namespace scoping into the CQL_QDM namespace (all classes and
|
3
|
+
their methods will be accessable through the CQL_QDM namespace)
|
4
|
+
###
|
5
|
+
@CQL_QDM ||= {}
|
6
|
+
|
7
|
+
###
|
8
|
+
Data elements that meet criteria using this datatype should document the Allergy
|
9
|
+
or Intolerance and its corresponding value set.
|
10
|
+
|
11
|
+
Timing: The Prevalence Period references the time from the onset date to the
|
12
|
+
abatement date.
|
13
|
+
###
|
14
|
+
class CQL_QDM.AllergyIntolerance extends CQL_QDM.QDMDatatype
|
15
|
+
###
|
16
|
+
@param {Object} entry - the HDS data criteria object to convert
|
17
|
+
###
|
18
|
+
constructor: (@entry) ->
|
19
|
+
super @entry
|
20
|
+
@_authorDatetime = CQL_QDM.Helpers.convertDateTime(@entry.start_time)
|
21
|
+
@_prevalencePeriodLow = CQL_QDM.Helpers.convertDateTime(@entry.start_time)
|
22
|
+
if @entry.end_time
|
23
|
+
@_prevalencePeriodHigh = CQL_QDM.Helpers.convertDateTime(@entry.end_time)
|
24
|
+
else
|
25
|
+
# No end time; high is set to infinity
|
26
|
+
@_prevalencePeriodHigh = CQL_QDM.Helpers.infinityDateTime()
|
27
|
+
@_severity = @entry.severity
|
28
|
+
@_type = @entry.type
|
29
|
+
|
30
|
+
###
|
31
|
+
@returns {Date}
|
32
|
+
###
|
33
|
+
authorDatetime: ->
|
34
|
+
@_authorDatetime
|
35
|
+
|
36
|
+
###
|
37
|
+
@returns {Interval<Date>}
|
38
|
+
###
|
39
|
+
prevalencePeriod: ->
|
40
|
+
low = @_prevalencePeriodLow
|
41
|
+
high = @_prevalencePeriodHigh
|
42
|
+
if low?
|
43
|
+
new cql.Interval(low, high)
|
44
|
+
else
|
45
|
+
null
|
46
|
+
|
47
|
+
###
|
48
|
+
@returns {Code}
|
49
|
+
###
|
50
|
+
severity: ->
|
51
|
+
if @_severity?
|
52
|
+
new cql.Code(@_severity.code, @_severity.code_system)
|
53
|
+
else
|
54
|
+
null
|
55
|
+
|
56
|
+
###
|
57
|
+
@returns {Code}
|
58
|
+
###
|
59
|
+
type: ->
|
60
|
+
if @_type?
|
61
|
+
new cql.Code(@_type.code, @_type.code_system)
|
62
|
+
else
|
63
|
+
null
|
@@ -0,0 +1,159 @@
|
|
1
|
+
###
|
2
|
+
@namespace scoping into the CQL_QDM namespace (all classes and
|
3
|
+
their methods will be accessable through the CQL_QDM namespace)
|
4
|
+
###
|
5
|
+
@CQL_QDM ||= {}
|
6
|
+
|
7
|
+
|
8
|
+
###
|
9
|
+
Data elements that meet criteria using this datatype should document completion
|
10
|
+
of the assessment indicated by the QDM category and its corresponding value set.
|
11
|
+
|
12
|
+
Timing: The time the assessment is completed; author time.
|
13
|
+
###
|
14
|
+
class CQL_QDM.AssessmentPerformed extends CQL_QDM.QDMDatatype
|
15
|
+
###
|
16
|
+
@param {Object} entry - the HDS data criteria object to convert
|
17
|
+
###
|
18
|
+
constructor: (@entry) ->
|
19
|
+
super @entry
|
20
|
+
@_authorDatetime = CQL_QDM.Helpers.convertDateTime(@entry.start_time)
|
21
|
+
@_method = @entry.method
|
22
|
+
@_negationRationale = @entry.negationReason
|
23
|
+
@_reason = @entry.reason
|
24
|
+
if @entry.values? && @entry.values.length > 0
|
25
|
+
@_result = @entry.values?[0]
|
26
|
+
@_relatedTo = @entry.references
|
27
|
+
@_components = @entry.components
|
28
|
+
|
29
|
+
###
|
30
|
+
@returns {Date}
|
31
|
+
###
|
32
|
+
authorDatetime: ->
|
33
|
+
@_authorDatetime
|
34
|
+
|
35
|
+
###
|
36
|
+
@returns {Code}
|
37
|
+
###
|
38
|
+
method: ->
|
39
|
+
if @_method?
|
40
|
+
new cql.Code(@_method.code, @_method.code_system)
|
41
|
+
else
|
42
|
+
null
|
43
|
+
|
44
|
+
###
|
45
|
+
@returns {Code}
|
46
|
+
###
|
47
|
+
negationRationale: ->
|
48
|
+
if @_negationRationale?
|
49
|
+
new cql.Code(@_negationRationale.code, @_negationRationale.code_system)
|
50
|
+
else
|
51
|
+
null
|
52
|
+
|
53
|
+
###
|
54
|
+
@returns {Code}
|
55
|
+
###
|
56
|
+
reason: ->
|
57
|
+
if @_reason?
|
58
|
+
new cql.Code(@_reason.code, @_reason.code_system)
|
59
|
+
else
|
60
|
+
null
|
61
|
+
|
62
|
+
###
|
63
|
+
The model_info_file also lists Integer, Decimal, DateTime, Time, and Ratio.
|
64
|
+
Decimal and Integer are covered under Quantity with a nil unit.
|
65
|
+
Ratio is not yet supported with CQL although it appears in the QDM model.
|
66
|
+
Time and Datetime are covered by Date
|
67
|
+
@returns {Code|Quantity|Date}
|
68
|
+
###
|
69
|
+
result: ->
|
70
|
+
if @_result
|
71
|
+
# A PhysicalQuantity with unit UnixTime is a TimeStamp, set in bonnie /lib/measures/patient_builder.rb
|
72
|
+
if @_result.units == 'UnixTime'
|
73
|
+
CQL_QDM.Helpers.convertDateTime(@_result.scalar)
|
74
|
+
else
|
75
|
+
CQL_QDM.Helpers.formatResult(@_result)
|
76
|
+
else
|
77
|
+
null
|
78
|
+
|
79
|
+
###
|
80
|
+
@returns {Array}
|
81
|
+
###
|
82
|
+
relatedTo: ->
|
83
|
+
CQL_QDM.Helpers.relatedTo(@_relatedTo)
|
84
|
+
|
85
|
+
###
|
86
|
+
@returns {Array}
|
87
|
+
###
|
88
|
+
components: ->
|
89
|
+
CQL_QDM.Helpers.components(@_components)
|
90
|
+
|
91
|
+
|
92
|
+
###
|
93
|
+
Data elements that meet this criteria using this datatype should document a
|
94
|
+
recommendation for a request by a clinician or appropriately licensed care
|
95
|
+
provider to a patient or an appropriate provider or organization to perform an
|
96
|
+
assessment indicated by the QDM category and its corresponding value set.
|
97
|
+
Timing: The time the recommendation is authored (i.e., provided to the patient).
|
98
|
+
|
99
|
+
NOTE: Recommendations address the time that the recommendation occurs, a single
|
100
|
+
point in time. Vendors have expressed concerns that recommendations are not
|
101
|
+
necessarily captured or managed in a standard manner as part of structured data
|
102
|
+
capture in clinical workflow; many are documented as part of assessments in
|
103
|
+
narrative text. Measure developers should address feasibility of clinical
|
104
|
+
workflow to capture recommendations when evaluating measures.
|
105
|
+
###
|
106
|
+
class CQL_QDM.AssessmentRecommended extends CQL_QDM.QDMDatatype
|
107
|
+
###
|
108
|
+
@param {Object} entry - the HDS data criteria object to convert
|
109
|
+
###
|
110
|
+
constructor: (@entry) ->
|
111
|
+
super @entry
|
112
|
+
@_authorDatetime = CQL_QDM.Helpers.convertDateTime(@entry.start_time)
|
113
|
+
@_method = @entry.method
|
114
|
+
@_negationRationale = @entry.negationReasonv
|
115
|
+
@_reason = @entry.reason
|
116
|
+
if @entry.values? && @entry.values.length > 0
|
117
|
+
@_result = @entry.values?[0]
|
118
|
+
|
119
|
+
###
|
120
|
+
@returns {Date}
|
121
|
+
###
|
122
|
+
authorDatetime: ->
|
123
|
+
@_authorDatetime
|
124
|
+
|
125
|
+
###
|
126
|
+
@returns {Code}
|
127
|
+
###
|
128
|
+
method: ->
|
129
|
+
if @_method?
|
130
|
+
new cql.Code(@_method.code, @_method.code_system)
|
131
|
+
else
|
132
|
+
null
|
133
|
+
|
134
|
+
###
|
135
|
+
@returns {Code}
|
136
|
+
###
|
137
|
+
negationRationale: ->
|
138
|
+
if @_negationRationale?
|
139
|
+
new cql.Code(@_negationRationale.code, @_negationRationale.code_system)
|
140
|
+
else
|
141
|
+
null
|
142
|
+
|
143
|
+
###
|
144
|
+
@returns {Code}
|
145
|
+
###
|
146
|
+
reason: ->
|
147
|
+
if @_reason?
|
148
|
+
new cql.Code(@_reason.code, @_reason.code_system)
|
149
|
+
else
|
150
|
+
null
|
151
|
+
|
152
|
+
###
|
153
|
+
@returns {Code}
|
154
|
+
###
|
155
|
+
method: ->
|
156
|
+
if @_method?
|
157
|
+
new cql.Code(@_method.code, @_method.code_system)
|
158
|
+
else
|
159
|
+
null
|
@@ -0,0 +1,47 @@
|
|
1
|
+
###
|
2
|
+
@namespace scoping into the CQL_QDM namespace (all classes and
|
3
|
+
their methods will be accessable through the CQL_QDM namespace)
|
4
|
+
###
|
5
|
+
@CQL_QDM ||= {}
|
6
|
+
|
7
|
+
|
8
|
+
###
|
9
|
+
Data elements that meet this criterion indicate the patient’s care experience,
|
10
|
+
usually measured with a validated survey tool. The most common tool is the
|
11
|
+
Consumer Assessment of Healthcare Providers and Systems.
|
12
|
+
###
|
13
|
+
class CQL_QDM.PatientCareExperience extends CQL_QDM.QDMDatatype
|
14
|
+
###
|
15
|
+
@param {Object} entry - the HDS data criteria object to convert
|
16
|
+
###
|
17
|
+
constructor: (@entry) ->
|
18
|
+
super @entry
|
19
|
+
@_authorDatetime = CQL_QDM.Helpers.convertDateTime(@entry.start_time)
|
20
|
+
|
21
|
+
###
|
22
|
+
@returns {Date}
|
23
|
+
###
|
24
|
+
authorDatetime: ->
|
25
|
+
@_authorDatetime
|
26
|
+
|
27
|
+
|
28
|
+
###
|
29
|
+
Data elements that meet this criterion indicate the provider's experience
|
30
|
+
with availability of resources (e.g., scheduling, equipment, space, and
|
31
|
+
such consumables as medications). Provider care experience gauges provider
|
32
|
+
satisfaction with key structures, processes, and outcomes in the healthcare
|
33
|
+
delivery system.
|
34
|
+
###
|
35
|
+
class CQL_QDM.ProviderCareExperience extends CQL_QDM.QDMDatatype
|
36
|
+
###
|
37
|
+
@param {Object} entry - the HDS data criteria object to convert
|
38
|
+
###
|
39
|
+
constructor: (@entry) ->
|
40
|
+
super @entry
|
41
|
+
@_authorDatetime = CQL_QDM.Helpers.convertDateTime(@entry.start_time)
|
42
|
+
|
43
|
+
###
|
44
|
+
@returns {Date}
|
45
|
+
###
|
46
|
+
authorDatetime: ->
|
47
|
+
@_authorDatetime
|
@@ -0,0 +1,60 @@
|
|
1
|
+
###
|
2
|
+
@namespace scoping into the CQL_QDM namespace (all classes and
|
3
|
+
their methods will be accessable through the CQL_QDM namespace)
|
4
|
+
###
|
5
|
+
@CQL_QDM ||= {}
|
6
|
+
|
7
|
+
|
8
|
+
###
|
9
|
+
Unlike other QDM datatypes, the Care Goal datatype does not indicate a
|
10
|
+
specific context of use. Instead, to meet this criterion, there must be
|
11
|
+
documentation of a care goal as defined by the Care Goal QDM category and
|
12
|
+
its corresponding value set.
|
13
|
+
###
|
14
|
+
class CQL_QDM.CareGoal extends CQL_QDM.QDMDatatype
|
15
|
+
###
|
16
|
+
@param {Object} entry - the HDS data criteria object to convert
|
17
|
+
###
|
18
|
+
constructor: (@entry) ->
|
19
|
+
super @entry
|
20
|
+
@_authorDatetime = CQL_QDM.Helpers.convertDateTime(@entry.start_time)
|
21
|
+
@_relevantPeriodLow = CQL_QDM.Helpers.convertDateTime(@entry.start_time)
|
22
|
+
if @entry.end_time
|
23
|
+
@_relevantPeriodHigh = CQL_QDM.Helpers.convertDateTime(@entry.end_time)
|
24
|
+
else
|
25
|
+
# No end time; high is set to infinity
|
26
|
+
@_relevantPeriodHigh = CQL_QDM.Helpers.infinityDateTime()
|
27
|
+
@_relatedTo = @entry.references
|
28
|
+
@_targetOutcome = @entry.targetOutcome
|
29
|
+
|
30
|
+
###
|
31
|
+
@returns {Interval<Date>}
|
32
|
+
###
|
33
|
+
relevantPeriod: ->
|
34
|
+
low = @_relevantPeriodLow
|
35
|
+
high = @_relevantPeriodHigh
|
36
|
+
if low?
|
37
|
+
new cql.Interval(low, high)
|
38
|
+
else
|
39
|
+
null
|
40
|
+
|
41
|
+
###
|
42
|
+
@returns {Array}
|
43
|
+
###
|
44
|
+
relatedTo: ->
|
45
|
+
CQL_QDM.Helpers.relatedTo(@_relatedTo)
|
46
|
+
|
47
|
+
###
|
48
|
+
The model_info_file also lists Integer, Decimal, and Ratio.
|
49
|
+
Decimal and Integer are covered under Quantity with a nil unit.
|
50
|
+
Ratio is not yet supported with CQL although it appears in the QDM model.
|
51
|
+
@returns {Quantity | Code}
|
52
|
+
###
|
53
|
+
targetOutcome: ->
|
54
|
+
if @_targetOutcome?
|
55
|
+
if @_targetOutcome?['unit']?
|
56
|
+
new cql.Quantity({unit: @_targetOutcome['unit'], value: @_targetOutcome['value']})
|
57
|
+
else
|
58
|
+
new cql.Code(@_targetOutcome.code, @_targetOutcome.code_system)
|
59
|
+
else
|
60
|
+
null
|
@@ -0,0 +1,28 @@
|
|
1
|
+
###
|
2
|
+
@namespace scoping into the CQL_QDM namespace (all classes and
|
3
|
+
their methods will be accessable through the CQL_QDM namespace)
|
4
|
+
###
|
5
|
+
@CQL_QDM ||= {}
|
6
|
+
|
7
|
+
|
8
|
+
###
|
9
|
+
Used to represent a birthdate.
|
10
|
+
###
|
11
|
+
class CQL_QDM.PatientCharacteristicBirthdate extends CQL_QDM.QDMDatatype
|
12
|
+
###
|
13
|
+
@param {Object} patient - the HDS patient object to use
|
14
|
+
###
|
15
|
+
constructor: (@patient) ->
|
16
|
+
@_patient = @patient
|
17
|
+
|
18
|
+
###
|
19
|
+
@returns {Object}
|
20
|
+
###
|
21
|
+
getCode: ->
|
22
|
+
'21112-8' # LOINC code for birthdate
|
23
|
+
|
24
|
+
###
|
25
|
+
@returns {DateTime}
|
26
|
+
###
|
27
|
+
birthDatetime: ->
|
28
|
+
CQL_QDM.Helpers.convertDateTime(@_patient.get('birthdate'))
|