cql_qdm_patientapi 1.0.0
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.
- 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'))
|