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-99 Indicators HIV.IND.37-HIV.IND.45 and Refactoring of Indicator Logic #43

Closed
wants to merge 13 commits into from
6 changes: 3 additions & 3 deletions input/cql/HIVB9DTLogic.cql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
@DecisionID: HIV.B9.DT
@DecisionID: HIV.B9.DT Logic
@BusinessRule: HIV restesting recommendations
@Trigger: HIV.B9 Determine recommended services
@HitPolicy: Rule order
Expand Down Expand Up @@ -79,7 +79,7 @@ define "HIV burden of setting is low HIV burden setting":
@pseudocode: "Key population member" = TRUE
*/
define "Key population member":
exists(Elements."Key population member* B.DE49 Observation" O
exists(Elements."Key population member B.DE49 Observation" O
where O.value is true)

/*
Expand All @@ -95,7 +95,7 @@ define "Currently pregnant":
*/
define "TB diagnosis result is diagnosed TB":
exists(Elements."TB diagnosis result Observation" O
where O.value ~ HCx."Diagnosed TB" or)
where O.value ~ HCx."Diagnosed TB")

/*
@input: "Presumptive TB"
Expand Down
201 changes: 14 additions & 187 deletions input/cql/HIVCommon.cql
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ include WHOCommon called WCom
//include FHIRCommon called FC
include HIVConcepts called HC
include HIVConceptsCustom called HCC
include HIVElements called HE
include HIVIndicatorElements called HIE


parameter "Measurement Period" Interval<Date> default Interval[@2020-01-01, @2020-12-31]
parameter "Measurement Date" Date default @2020-01-01
Expand All @@ -18,7 +15,6 @@ parameter "Intervention Interval" System.Quantity default 7 days

context Patient


//VERIFIED

define "routine viral load sample collection":
Expand All @@ -32,148 +28,6 @@ define "viral load sample collection":
where P.status = 'completed'
and P.code ~ HCC."viral load test"


define "First On ART":
(First(HE."On ART D.DE38"))

define "Viral load tests received after ART intitiation":
HE."Viral load test result D.DE387" O
where start of O.issued.toInterval() after start of "First On ART".effective.toInterval()
sort by start of issued.toInterval()

define "Elevated Viral load test during Measurement Period":
HE."Viral load test result D.DE387" VL
with "viral load sample collection" P
such that VL.partOf.references(P) and P.performed.toInterval() during "Measurement Period"
where VL.value > 1000 'copies/ml'
sort by start of effective.toInterval()


define "Negative Tests within Measurement Period":
HE."HIV-negative B.DE113" O
with HE."At elevated risk for HIV acquisition B.DE225" HIV
such that O.hasMember.references(HIV)
where O.effective.toInterval() starts during "Measurement Period"
sort by start of effective.toInterval()

define "First Negative Test within Measurement Period":
(First("Negative Tests within Measurement Period"))

define "Negative Tests after First Negative Test":
HE."HIV-negative B.DE113" O
with HE."At elevated risk for HIV acquisition B.DE225" HIV
such that O.hasMember.references(HIV)
where O.effective.toInterval() starts after start of "First Negative Test within Measurement Period".effective.toInterval()
and O.effective.toInterval() starts before (start of "First Negative Test within Measurement Period".effective.toInterval() + "Testing Interval")
sort by start of effective.toInterval()

define patientGroups:
List<String>{
if HIE."Sex worker B.DE51" then 'SW' else null,
if HIE."Men who have sex with men" then 'MSM' else null,
if HIE."Trans and gender-diverse people B.DE53" then 'Trans' else null,
if HIE."People who inject drugs B.DE54" then 'PWID' else null,
if HIE."People living in prisons and other closed settings" then 'Prisoner' else null
}

define "Treatment outcome category":
List<String>{
if HIE."Lost to follow-up" then 'LTFU' else null,
if HIE."Transferred out" then 'Transfer Out' else null,
if HIE."Death documented" then 'Death' else null,
if HIE."Refused stopped treatment" then 'Stopped' else null,
if HIE."On ART H.DE47" then 'On ART' else null
}


/*
* By Age Stratifiers
* (0–4, 5–9, 10–14, 15–19, 20–24, 25–29, 30–34, 35–39, 40–44, 45–49, 50+ years)
*
*/
define "By Age Stratifier":
case
when HIE."Age In Years" <= 4 then '0-4'
when HIE."Age In Years" <= 9 then '5-9'
when HIE."Age In Years" <= 14 then '10–14'
when HIE."Age In Years" <= 19 then '15–19'
when HIE."Age In Years" <= 24 then '20–24'
when HIE."Age In Years" <= 29 then '25–29'
when HIE."Age In Years" <= 34 then '30–34'
when HIE."Age In Years" <= 39 then '35–39'
when HIE."Age In Years" <= 44 then '40–44'
when HIE."Age In Years" <= 49 then '45–49'
when HIE."Age In Years" >= 50 then '50+'
else null
end

/*
* By Age Stratifiers
* Age (0–4, 5–9, 10–14, 15–19, 20–24, 25–49, 50+ years)
*
*/
define "By Age Stratifier 2":
case
when HIE."Age In Years" <= 4 then '0-4'
when HIE."Age In Years" <= 9 then '5-9'
when HIE."Age In Years" <= 14 then '10–14'
when HIE."Age In Years" <= 19 then '15–19'
when HIE."Age In Years" <= 24 then '20–24'
when HIE."Age In Years" <= 49 then '25–49'
when HIE."Age In Years" >= 50 then '50+'
else null
end

define "By Age Stratifier 3":
case
when HIE."Age In Years" >= 15 and HIE."Age In Years"<= 19 then '15-19'
when HIE."Age In Years" <= 24 then '20-24'
when HIE."Age In Years" <= 49 then '25–49'
when HIE."Age In Years" >= 50 then '50+'
else null
end

/*
* By state stratifier
*/

define "By Geographic Region Stratifier":
First(Patient.address A where A.use in { 'home' }).state

/*
* By Administrative Gender of Patient Stratifier
* Need to expand codes
*/

define "By Administrative Gender Stratifier":
case
when Patient.gender = 'male' then HC."Male"
when Patient.gender = 'female' then HC."Female"
when Patient.gender = 'transgender female' then HC."Transgender female"
when Patient.gender = 'transgender male' then HC."Transgender male"
else HC."Other - HIV.A.DE23"
end


define "HIV status of partner or contact":
case
when HIE."Already knew positive" then HC."Already knew positive"
when HIE."Newly diagnosed" then HC."Newly diagnosed"
when HIE."Negative H.DE37" then HC."Negative - HIV.H.DE37"
else null
end

//(including PrEP, OAMT, NSP, STI services, VMMC)
define "HIV prevention intervention":
List<String>{
if HIE."PrEP service" then 'PrEP' else null,
if HIE."OAMT" then 'OAMT' else null,
if HIE."NSP" then 'NSP' else null,
if HIE."STI services" then 'STI services' else null,
if HIE."VMMC" then 'VMMC' else null,
if HIE."Other PRV.DE8" then 'other prevention' else null
}

//DRAFT
define "Patient Deceased during Measurement Period":
case
Expand All @@ -182,16 +36,6 @@ define "Patient Deceased during Measurement Period":
else false
end

define "HIV Positive Condition":
[Condition] C
where C.clinicalStatus ~ HCC."active"
and exists(C.category CC where CC ~ HCC."encounter-diagnosis")
and C.code ~ HC."HIV-positive - HIV.B.DE116"
sort by start of onset.toInterval()

define "First HIV Positive Condition":
First("HIV Positive Condition")

define "HIV Positive Observation":
[Observation] O
where O.status in {'final', 'amended'}
Expand Down Expand Up @@ -335,24 +179,6 @@ define "buprenorphine_prescribed":
where MR.status = 'completed'
and MR.intent = 'order'
and MR.medication ~ HCC."buprenorphine"





define "Lost to Follow Up during the measurement period":
exists(HE."On ART H.DE47" H
where H.effective starts before end of "Measurement Period"
and H.effective ends after start of "Measurement Period"
and not (H.effective ends after (end of "Measurement Period" - 28 days))
)

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 @@ -878,19 +704,6 @@ define "VMMC_adverse_event_Postoperative":
and exists(O.category OC where OC ~ HCC."social-history")
and O.code ~ HC."Sexual partner - HIV.B.DE11"


define "First HIV Treatment":
First(HE."On ART H.DE47")


define "Time to start ART":
case
when difference in days between start of "First HIV Treatment".effective.toInterval() and start of "First HIV Positive Condition".onset.toInterval() <= 7 then HC."Within 7 days of HIV diagnosis"
when difference in days between start of "First HIV Treatment".effective.toInterval() and start of "First HIV Positive Condition".onset.toInterval() <= 30 then HC."Within 30 days of HIV diagnosis"
when difference in days between start of "First HIV Treatment".effective.toInterval() and start of "First HIV Positive Condition".onset.toInterval() <= 90 then HC."Within 90 days of HIV diagnosis"
else null
end

//HIV status of partner or contact (already known positive, newly diagnosed positive, negative)

define "already known positive":
Expand Down Expand Up @@ -920,5 +733,19 @@ define "VMMC_adverse_event_Postoperative":
and P.code ~ HC."STI testing and treatment services"


/**
* @description Takes a choice between a Medication and a CodeableConcept and returns just the code of the medication
*/
define function ExtractMedicationCode(choice Choice<FHIR.CodeableConcept, FHIR.Reference>):
case
when choice is FHIR.CodeableConcept then
choice as FHIR.CodeableConcept
when choice is FHIR.Reference then
First([Medication] M
where M.id = Last(Split(choice.reference, '/'))
return M.code as FHIR.CodeableConcept)
else
Message(null as FHIR.CodeableConcept, true, '1', 'Error', 'Cannot compute a medication code') // TODO: I'm sure that this is supported somehow?
end


Loading
Loading