Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WSG-88-HIV-indicators-13-18 #34

Merged
merged 1 commit into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 225 additions & 5 deletions input/cql/HIVCommon.cql
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ using FHIR version '4.0.1'

include FHIRHelpers version '4.0.1'
include WHOCommon called WCom
include FHIRCommon called FC
//include FHIRCommon called FC
include HIVConcepts called HC
include HIVConceptsCustom called HCC

parameter "Measurement Period" Interval<Date> default Interval[@2020-01-01, @2020-12-31]
parameter "Measurement Date" Date default @2020-01-01

context Patient

Expand Down Expand Up @@ -123,12 +124,58 @@ define "Needle Syringe Dispensed":
and O.value ~ HC."People who inject drugs - HIV.B.DE54"
where DUS.status = 'completed'

define PWID_person:
[Observation: HC."Key population member* - HIV.E.DE113"] O
where O.status in { 'final', 'amended', 'corrected' }
define PWID_person:
[Observation: HC."Key population member* - HIV.E.DE113"] O
where O.status in { 'final', 'amended', 'corrected' }
and exists(O.category OC where OC ~ HCC."social-history")
and O.value ~ HC."People who inject drugs - HIV.B.DE54"

define "OAMT_initiated":
exists(
[EpisodeOfCare] EOC
where exists(EOC.type T where T ~ HC."OAMT")
and (exists (
EOC.statusHistory H
where H.period starts after start of "Measurement Period"
and H.period starts before end of "Measurement Period"
)
or (
EOC.period starts after start of "Measurement Period"
and EOC.period starts before end of "Measurement Period"
)
)
)

define "OAMT_retained":
exists(
[EpisodeOfCare] EOC
where exists(EOC.type T where T ~ HC."OAMT")
and (exists (
EOC.statusHistory H
where H.period starts after start of "Measurement Period"
and H.period starts before end of "Measurement Period"
and H.period ends after (end of "Measurement Period" + 6 months)
)
or (
EOC.period starts after start of "Measurement Period"
and EOC.period starts before end of "Measurement Period"
and (EOC.period ends after (end of "Measurement Period" + 6 months)
or end of EOC.period is null)
)
)
)

define "methadone_prescribed":
[MedicationRequest] MR
where MR.status = 'completed'
and MR.intent = 'order'
and MR.medication ~ HCC."methadone"

define "buprenorphine_prescribed":
[MedicationRequest] MR
where MR.status = 'completed'
and MR.intent = 'order'
and MR.medication ~ HCC."buprenorphine"

define "Patient Deceased before end of Measurement Period":
case
Expand Down Expand Up @@ -237,6 +284,13 @@ define "By Administrative Gender Stratifier":
else HC."Other - HIV.A.DE23"
end

define "HIV Status":
case
when exists("HIV Positive Condition" C where C.onset before end of "Measurement Period") then HC."HIV-positive - HIV.B.DE116"
when not exists("HIV Positive Condition" C where C.onset before end of "Measurement Period") and exists("HIV Negative Observation" O where O.issued before end of "Measurement Period") then HC."HIV-negative - HIV.B.DE117"
else HC."Unknown - HIV.B.DE118"
end

/*
* Key populations (men who have sex with men, people living in prisons and other closed settings, people who inject drugs, sex workers, trans and gender diverse people)
*/
Expand Down Expand Up @@ -579,4 +633,170 @@ define function "Prescription Relevant Period"(prescription FHIR.MedicationReque
date from prescription.authoredOn,
date from prescription.authoredOn + System.Quantity{ value: GetDurationInDays(prescription.dispenseRequest.expectedSupplyDuration), unit: 'days' }
]
else null
else null

//System.Integer
define function ToDaily(frequency System.Integer, period System.Quantity):
case period.unit
when 'h' then frequency * (24.0 / period.value)
when 'min' then frequency * (24.0 / period.value) * 60
when 's' then frequency * (24.0 / period.value) * 60 * 60
when 'd' then frequency * (24.0 / period.value) / 24
when 'wk' then frequency * (24.0 / period.value) / (24 * 7)
when 'mo' then frequency * (24.0 / period.value) / (24 * 30) /* assuming 30 days in month */
when 'a' then frequency * (24.0 / period.value) / (24 * 365) /* assuming 365 days in year */
when 'hour' then frequency * (24.0 / period.value)
when 'minute' then frequency * (24.0 / period.value) * 60
when 'second' then frequency * (24.0 / period.value) * 60 * 60
when 'day' then frequency * (24.0 / period.value) / 24
when 'week' then frequency * (24.0 / period.value) / (24 * 7)
when 'month' then frequency * (24.0 / period.value) / (24 * 30) /* assuming 30 days in month */
when 'year' then frequency * (24.0 / period.value) / (24 * 365) /* assuming 365 days in year */
when 'hours' then frequency * (24.0 / period.value)
when 'minutes' then frequency * (24.0 / period.value) * 60
when 'seconds' then frequency * (24.0 / period.value) * 60 * 60
when 'days' then frequency * (24.0 / period.value) / 24
when 'weeks' then frequency * (24.0 / period.value) / (24 * 7)
when 'months' then frequency * (24.0 / period.value) / (24 * 30) /* assuming 30 days in month */
when 'years' then frequency * (24.0 / period.value) / (24 * 365) /* assuming 365 days in year */
else null
end

define function "HasEnd"(period Interval<DateTime> ):
not (end of period is null
or end of period = maximum DateTime
)

define function MedicationRequestPeriod(Request "MedicationRequest"):
Request R
let
dosage: singleton from R.dosageInstruction,
doseAndRate: singleton from dosage.doseAndRate,
doseRange: doseAndRate.dose as Range,
doseQuantity: doseAndRate.dose as SimpleQuantity,
dose: Coalesce(end of doseRange, doseQuantity),
timing: dosage.timing,
frequency: Coalesce(timing.repeat.frequencyMax, timing.repeat.frequency),
period: System.Quantity { value: timing.repeat.period, unit: timing.repeat.periodUnit.value },
dosesPerDay: Coalesce(ToDaily(FHIRHelpers.ToInteger(frequency), period), Count(timing.repeat.timeOfDay), 1.0),
boundsPeriod: timing.repeat.bounds as Period,
daysSupply: R.dispenseRequest.expectedSupplyDuration,
quantity: R.dispenseRequest.quantity,
refills: Coalesce(R.dispenseRequest.numberOfRepeatsAllowed, 0),
startDate:
Coalesce(
start of boundsPeriod,
start of R.dispenseRequest.validityPeriod,
R.authoredOn
)
return
if HasEnd(boundsPeriod) then
Interval[startDate, end of boundsPeriod]
else
(
Coalesce(daysSupply, quantity / (dose * dosesPerDay))
* (1 + refills)
) durationInDays
return Interval[startDate, startDate + durationInDays]


define function "DosesPerDay"(frequency Code):
/*Calculates the cumulative dose per day for each prescription*/
case
when frequency ~ HCC."Once daily (qualifier value)" then 1.0
when frequency ~ HCC."Twice a day (qualifier value)" then 2.0
when frequency ~ HCC."Three times daily (qualifier value)" then 3.0
when frequency ~ HCC."Four times daily (qualifier value)" then 4.0
when frequency ~ HCC."Every twenty four hours (qualifier value)" then 1.0
when frequency ~ HCC."Every twelve hours (qualifier value)" then 2.0
when frequency ~ HCC."Every thirty six hours (qualifier value)" then 0.67
when frequency ~ HCC."Every eight hours (qualifier value)" then 3.0
when frequency ~ HCC."Every four hours (qualifier value)" then 6.0
when frequency ~ HCC."Every six hours (qualifier value)" then 4.0
when frequency ~ HCC."Every seventy two hours (qualifier value)" then 0.34
when frequency ~ HCC."Every forty eight hours (qualifier value)" then 0.5
when frequency ~ HCC."Every eight to twelve hours (qualifier value)" then 2.0
when frequency ~ HCC."Every six to eight hours (qualifier value)" then 3.0
when frequency ~ HCC."Every three to four hours (qualifier value)" then 6.0
when frequency ~ HCC."Every three to six hours (qualifier value)" then 4.0
when frequency ~ HCC."Every two to four hours (qualifier value)" then 6.0
when frequency ~ HCC."One to four times a day (qualifier value)" then 4.0
when frequency ~ HCC."One to three times a day (qualifier value)" then 3.0
when frequency ~ HCC."One to two times a day (qualifier value)" then 2.0
else null
end

//define function "GetMedicationDailyDose"(dosage Quantity, dosesPerDay Decimal):
//dosage * Quantity { value: dosesPerDay, unit: '/d' }


define "methadone_prescribed at date":
[MedicationRequest] MR
where MR.status = 'completed'
and MR.intent = 'order'
and MR.medication ~ HCC."methadone"
//and "GetMedicationDailyDose"(MR.dosageInstruction, "DosesPerDay"(singleton from MR.dosageInstruction.timing.repeat.frequencyMax)) >= 60 'mg/d'
and MedicationRequestPeriod(MR) starts before "Measurement Date"
and MedicationRequestPeriod(MR) ends after "Measurement Date"

define "VMMC_done":
[Procedure] P
where P.status = 'completed'
and P.code ~ HC."Voluntary medical male circumcision VMMC"

define "VMMC_adverse_event":
[AdverseEvent] AE
with [Procedure] P
such that AE.suspectEntity.instance.references(P) and P.status = 'completed'
and P.code ~ HC."Voluntary medical male circumcision VMMC"
and P.performed after start of "Measurement Period"
and P.performed before end of "Measurement Period"
and AE.date <= (P.performed + 30 days)
and AE.date >= (P.performed)
where AE.actuality = 'actual'

define "VMMC_adverse_event_type":
case
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Abnormal pain") then HC."Abnormal pain"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Anaesthesia-related effects") then HC."Anaesthesia-related effects"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Damage to the penis") then HC."Damage to the penis"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Difficulty urinating") then HC."Difficulty urinating"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Excessive bleeding") then HC."Excessive bleeding"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Excessive skin removal") then HC."Excessive skin removal"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Excessive swelling") then HC."Excessive swelling"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Haematoma") then HC."Haematoma"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Infection") then HC."Infection"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Injury to glans") then HC."Injury to glans"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Scar or disfigurement") then HC."Scar or disfigurement"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Sharps injury to personnel") then HC."Sharps injury to personnel"
when exists("VMMC_adverse_event" AE where AE.event ~ HC."Wound disruption") then HC."Wound disruption"
else HC."Other - HIV.B.DE222"
end

define "VMMC_adverse_event_Intraoperative":
[AdverseEvent] AE
with [Procedure] P
such that AE.suspectEntity.instance.references(P) and P.status = 'completed'
and P.code ~ HC."Voluntary medical male circumcision VMMC"
and P.performed after start of "Measurement Period"
and P.performed before end of "Measurement Period"
and AE.date = P.performed
where AE.actuality = 'actual'

define "VMMC_adverse_event_Postoperative":
[AdverseEvent] AE
with [Procedure] P
such that AE.suspectEntity.instance.references(P) and P.status = 'completed'
and P.code ~ HC."Voluntary medical male circumcision VMMC"
and P.performed after start of "Measurement Period"
and P.performed before end of "Measurement Period"
and AE.date <= (P.performed + 30 days)
and AE.date > (P.performed)
where AE.actuality = 'actual'

define "VMMC_adverse_event_timing":
case
when exists(VMMC_adverse_event_Intraoperative) then HC."Intraoperative"
when exists(VMMC_adverse_event_Postoperative) then HC."Postoperative"
else null
end
34 changes: 34 additions & 0 deletions input/cql/HIVConceptsCustom.cql
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ codesystem "ConditionClinicalStatusCodes": 'http://terminology.hl7.org/CodeSyste
codesystem "ObservationCategoryCodes": 'http://terminology.hl7.org/CodeSystem/observation-category'
codesystem "missing concepts": 'missing concepts'
codesystem "Devicestatement-status": 'http://hl7.org/fhir/ValueSet/device-statement-status'
codesystem "SNOMEDCT:2018-03": 'urn:oid:2.16.840.1.113883.6.96' version 'urn:hl7:version:2018-03'
codesystem "SNOMEDCT": 'urn:oid:2.16.840.1.113883.6.96'
codesystem "AdverseEventSeverity": 'http://hl7.org/fhir/ValueSet/adverse-event-severity'

code "encounter-diagnosis": 'encounter-diagnosis' from "ConditionCategoryCodes" display 'Encounter Diagnosis'

Expand All @@ -22,6 +25,37 @@ code "social-history": 'social-history' from "ObservationCategoryCodes" display
//Device statement status
code "completed": 'completed' from "Devicestatement-status"

//adverse event severity
code "mild": 'mild' from "AdverseEventSeverity"
code "moderate": 'moderate' from "AdverseEventSeverity"
code "severe": 'severe' from "AdverseEventSeverity"

//frequency
code "Every eight hours (qualifier value)": '307469008' from "SNOMEDCT:2018-03" display 'Every eight hours (qualifier value)'
code "Every eight to twelve hours (qualifier value)": '396140003' from "SNOMEDCT" display 'Every eight to twelve hours (qualifier value)'
code "Every forty eight hours (qualifier value)": '396131002' from "SNOMEDCT:2018-03" display 'Every forty eight hours (qualifier value)'
code "Every four hours (qualifier value)": '225756002' from "SNOMEDCT" display 'Every four hours (qualifier value)'
code "Every seventy two hours (qualifier value)": '396143001' from "SNOMEDCT:2018-03" display 'Every seventy two hours (qualifier value)'
code "Every six hours (qualifier value)": '307468000' from "SNOMEDCT:2018-03" display 'Every six hours (qualifier value)'
code "Every six to eight hours (qualifier value)": '396139000' from "SNOMEDCT" display 'Every six to eight hours (qualifier value)'
code "Every thirty six hours (qualifier value)": '396126004' from "SNOMEDCT:2018-03" display 'Every thirty six hours (qualifier value)'
code "Every three to four hours (qualifier value)": '225754004' from "SNOMEDCT" display 'Every three to four hours (qualifier value)'
code "Every three to six hours (qualifier value)": '396127008' from "SNOMEDCT" display 'Every three to six hours (qualifier value)'
code "Every twelve hours (qualifier value)": '307470009' from "SNOMEDCT:2018-03" display 'Every twelve hours (qualifier value)'
code "Every twenty four hours (qualifier value)": '396125000' from "SNOMEDCT:2018-03" display 'Every twenty four hours (qualifier value)'
code "Every two to four hours (qualifier value)": '225752000' from "SNOMEDCT" display 'Every two to four hours (qualifier value)'
code "Four times daily (qualifier value)": '307439001' from "SNOMEDCT:2018-03" display 'Four times daily (qualifier value)'
code "Once daily (qualifier value)": '229797004' from "SNOMEDCT:2018-03" display 'Once daily (qualifier value)'
code "One to four times a day (qualifier value)": '396109005' from "SNOMEDCT" display 'One to four times a day (qualifier value)'
code "One to three times a day (qualifier value)": '396108002' from "SNOMEDCT" display 'One to three times a day (qualifier value)'
code "One to two times a day (qualifier value)": '396107007' from "SNOMEDCT" display 'One to two times a day (qualifier value)'
code "Three times daily (qualifier value)": '229798009' from "SNOMEDCT:2018-03" display 'Three times daily (qualifier value)'
code "Twice a day (qualifier value)": '229799001' from "SNOMEDCT:2018-03" display 'Twice a day (qualifier value)'
code "Two to four times a day (qualifier value)": '396111001' from "SNOMEDCT" display 'Two to four times a day (qualifier value)'


//not currently provided
code "needle-syringe": 'needle syringe' from "missing concepts"
code "methadone": 'methadone' from "missing concepts"
code "buprenorphine": 'buprenorphine' from "missing concepts"

32 changes: 29 additions & 3 deletions input/cql/HIVIND13Logic.cql
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ using FHIR version '4.0.1'

include HIVCommon version '0.0.1' called HIC
include FHIRHelpers version '4.0.1'
include FHIRCommon called FC
include WHOCommon called WCom

// Indicator Definition
Expand All @@ -78,7 +77,7 @@ define "Initial Population":
*/

define "Numerator":
true
HIC.OAMT_retained


/**
Expand All @@ -89,8 +88,35 @@ define "Numerator":
*/

define "Denominator":
true
HIC.OAMT_initiated


/* end Populations */

/*
* Disaggregators
*/

define "Administrative Gender Stratifier":
HIC."By Administrative Gender Stratifier"

define "Age Stratifier":
HIC."By Age Stratifier 3"

define "Geographic Region Stratifier":
HIC."By Geographic Region Stratifier"

define "patientGroups Stratifier":
HIC."patientGroups"

define "Setting":
HIC."setting"

//provider type not provided?

define "Stratification":
HIC."By Administrative Gender Stratifier".code
+ ':' + HIC."By Age Stratifier"
+ ':' + HIC."By Geographic Region Stratifier"
+ Combine(HIC.patientGroups, ':')
+ Combine(HIC.setting, ':')
1 change: 0 additions & 1 deletion input/cql/HIVIND14Logic.cql
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ using FHIR version '4.0.1'

include HIVCommon version '0.0.1' called HIC
include FHIRHelpers version '4.0.1'
include FHIRCommon called FC
include WHOCommon called WCom

// Indicator Definition
Expand Down
Loading
Loading