Skip to content

Instantly share code, notes, and snippets.

@clarkevans
Created February 28, 2018 21:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save clarkevans/681daa7bb366c69404b4dd16572ef133 to your computer and use it in GitHub Desktop.
Save clarkevans/681daa7bb366c69404b4dd16572ef133 to your computer and use it in GitHub Desktop.
Implementing CMS165v6: Controlling High Blood Pressure
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Implementing CMS165v6."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook demonstrates how _CMS165v6_ eCQM is calculated for 12 synthetic patients derived from the Cypress project encoded using FHIR and serialized with XML.\n",
"```\n",
"Measure: CMS165v5\n",
"Title: Controlling High Blood Pressure\n",
"Description: Percentage of patients 18-85 years \n",
" of age who had a diagnosis of hypertension and \n",
" whose blood pressure was adequately controlled \n",
" (<140/90mmHg) during the measurement period\n",
"```\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"cd(\"src\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"WARNING: Method definition cse(RBT.Query) in module RBT at /home/cce/.julia/v0.5/RBT/src/cse.jl:3 overwritten in module Main at /home/cce/ihm-fhir-ri/src/querycombinators.jl:84.\n"
]
},
{
"data": {
"text/plain": [
"\"Data and source code loaded\""
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"include(\"querycombinators.jl\") # ignore redefinition of \"cse\" warning\n",
"include(\"load-fhir.jl\") \n",
"include(\"interval.jl\")\n",
"include(\"load-valueset.jl\")\n",
"\"Data and source code loaded\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First we need to define the ValueSets used in the measure. If one was implementing all the measures, you could do this independently. The ``ValueSet`` combinator here converts the identifier into a Vector of Concepts to be used in various calculations."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"RBT.Combinator(RBT.#201)"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"OfficeVisit = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.101.12.1001\")\n",
"FaceToFaceInteraction = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.101.12.1048\")\n",
"PreventiveCareServicesEstablishedOfficeVisit18AndUp = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.101.12.1025\")\n",
"PreventiveCareServicesInitialOfficeVisit18AndUp = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.101.12.1023\")\n",
"HomeHealthcareServices = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.101.12.1016\")\n",
"AnnualWellnessVisit = \n",
" ValueSet(\"2.16.840.1.113883.3.526.3.1240\")\n",
"\n",
"EssentialHypertension = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.104.12.1011\")\n",
"\n",
"Pregnancy = \n",
" ValueSet(\"2.16.840.1.113883.3.526.3.378\")\n",
"EndStageRenalDisease = \n",
" ValueSet(\"2.16.840.1.113883.3.526.3.353\")\n",
"ChronicKidneyDiseaseStage5 = \n",
" ValueSet(\"2.16.840.1.113883.3.526.3.1002\")\n",
"VascularAccessForDialysis = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.109.12.1011\")\n",
"ESRDMonthlyOutpatientServices = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.109.12.1014\")\n",
"KidneyTransplant = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.109.12.1012\")\n",
"DialysisEducation = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.109.12.1016\")\n",
"DialysisServices = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.109.12.1013\")\n",
"OtherServicesRelatedToDialysis = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.109.12.1015\")\n",
"\n",
"# new in v6\n",
"HospiceCareAmbulatory = \n",
" ValueSet(\"2.16.840.1.113762.1.4.1108.1\")\n",
"EncounterInpatient = \n",
" ValueSet(\"2.16.840.1.113883.3.666.5.307\")\n",
"DischargedHospiceHome =\n",
" ValueSet(\"2.16.840.1.113883.3.117.1.7.1.209\")\n",
"DischargedHospiceFacility = \n",
" ValueSet(\"2.16.840.1.113883.3.117.1.7.1.207\")\n",
" \n",
"AdultOutpatientVisit = \n",
" ValueSet(\"2.16.840.1.113883.3.464.1003.101.12.1065\")\n",
"SystolicBloodPressure = \n",
" ValueSet(\"2.16.840.1.113883.3.526.3.1032\")\n",
"DiastolicBloodPressure = \n",
" ValueSet(\"2.16.840.1.113883.3.526.3.1033\")\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The measure period for this sample data is 2016. Let's first define an *Interval* called measure period and define a few useful predicates which test an entry period against the measure period."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"RBT.Combinator(RBT.#201)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"MeasurePeriod = MakeInterval(\"2016-01-01T00:00\", \"2016-12-31T23:59:59\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, let's compute an ``AgeTest`` to translate the following logic:\n",
"\n",
"```\n",
"Population Criteria:\n",
" Initial Population =\n",
" AND: Age>= 18 year(s) at: \"Measurement Period\"\n",
" AND: Age< 85 year(s) at: \"Measurement Period\"\n",
"```\n",
"\n",
"We need to first retrieve the ``BirthDate`` from the sample data. Then, we use ``AgeAt`` which computes the number of years between a date provided and start of the interval. In a reusable module, ``BirthDate`` could be defined once and used as needed. As we can see by testing this query fragment independently, all of the sample patients in our database pass the age test."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"12-element composite vector of {String, DateTime, Int64, Bool}:\n",
" (\"2_N_GP_Adult\",1981-05-29T01:56:00,34,true) \n",
" (\"A_Heart_Adult\",1946-02-01T11:30:00,69,true) \n",
" (\"B_Heart_Adult\",1946-02-01T15:00:00,69,true) \n",
" (\"C_N_GP_Adult\",1941-01-02T15:30:00,74,true) \n",
" (\"Z14_N_GP_Adult\",1968-02-14T15:25:00,47,true) \n",
" (\"Z1_Pregnancy_Adult\",1992-10-01T15:00:00,23,true)\n",
" (\"Z2_N_Heart_Adult\",1946-02-01T11:30:00,69,true) \n",
" (\"Z4_Heart_Adult\",1946-02-01T15:00:00,69,true) \n",
" (\"Z5_Heart_Adult\",1969-08-26T15:30:00,46,true) \n",
" (\"Z6_N_Heart_Adult\",1967-01-24T00:00:00,48,true) \n",
" (\"Z7_Heart_Adult\",1959-01-26T00:00:00,56,true) \n",
" (\"Z9_GP_Geriatric\",1941-02-07T15:30:00,74,true) "
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"BirthDateConcept = ToConcept(\"SNOMED-CT\",\"184099003\")\n",
"BirthDate = (\n",
" Frame(\n",
" Observation\n",
" >> ThenFilter(AnyOf(Observable .== BirthDateConcept))\n",
" >> Initiation\n",
" >> ThenUnique\n",
" ) >> ThenExpectOne)\n",
"\n",
"AgeFrom(young, old) = (\n",
" AgeAt(BirthDate, MeasurePeriod) .>= Const(young) &\n",
" AgeAt(BirthDate, MeasurePeriod) .< Const(old)\n",
")\n",
"\n",
"query_ihm(\n",
" Patient \n",
" >> ThenSelect(\n",
" Handle,\n",
" BirthDate,\n",
" AgeAt(BirthDate, MeasurePeriod),\n",
" AgeFrom(18,85)\n",
" )\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's create a ``VisitTest`` that computes the following:\n",
"\n",
"```\n",
"Initial Population =\n",
" ...\n",
" AND: Union of:\n",
" \"Encounter, Performed: Office Visit\"\n",
" \"Encounter, Performed: Face-to-Face Interaction\"\n",
" \"Encounter, Performed: Preventive Care Services -\n",
" Established Office Visit, 18 and Up\"\n",
" \"Encounter, Performed: Preventive Care Services -\n",
" Initial Office Visit, 18 and Up\"\n",
" \"Encounter, Performed: Home Healthcare Services\"\n",
" \"Encounter, Performed: Annual Wellness Visit\"\n",
" during \"Measurement Period\"\n",
"```\n",
"\n",
"As we'll see, all 12 sample patients meet this criteria as well. "
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"12-element composite vector of {String, Int64, Date*}:\n",
" (\"2_N_GP_Adult\",2,Date[2016-04-03,2016-06-23]) \n",
" (\"A_Heart_Adult\",3,Date[2016-03-01,2016-07-01,2016-12-20])\n",
" (\"B_Heart_Adult\",2,Date[2016-03-01,2016-12-20]) \n",
" (\"C_N_GP_Adult\",3,Date[2016-03-01,2016-07-01,2016-10-01]) \n",
" (\"Z14_N_GP_Adult\",1,Date[2016-03-05]) \n",
" (\"Z1_Pregnancy_Adult\",2,Date[2016-02-11,2016-03-08]) \n",
" (\"Z2_N_Heart_Adult\",2,Date[2016-03-01,2016-06-10]) \n",
" (\"Z4_Heart_Adult\",2,Date[2016-03-01,2016-12-20]) \n",
" (\"Z5_Heart_Adult\",1,Date[2016-02-12]) \n",
" (\"Z6_N_Heart_Adult\",2,Date[2016-03-04,2016-05-01]) \n",
" (\"Z7_Heart_Adult\",2,Date[2016-03-04,2016-05-01]) \n",
" (\"Z9_GP_Geriatric\",2,Date[2016-01-07,2016-07-10]) "
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"EntryMatching(EntryKind, Temporality, \n",
" TheInterval, Sets...) = (\n",
" EntryKind\n",
" >> ThenFilter(\n",
" AnyOf(Category .== Merge(Sets...)))\n",
" >> ThenFilter(Temporality(TheInterval))\n",
")\n",
"\n",
"Interactions = EntryMatching(\n",
" Encounter, During, MeasurePeriod,\n",
" OfficeVisit,\n",
" FaceToFaceInteraction, \n",
" PreventiveCareServicesEstablishedOfficeVisit18AndUp,\n",
" PreventiveCareServicesInitialOfficeVisit18AndUp,\n",
" HomeHealthcareServices,\n",
" AnnualWellnessVisit)\n",
"\n",
"query_ihm(\n",
" Patient \n",
" >> ThenFilter(Exists(Interactions))\n",
" >> ThenSelect(\n",
" Handle,\n",
" Count(Interactions),\n",
" Interactions >> PeriodStart >> AsDate\n",
" )\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we need to define a particular *Occurance* of a diagnosis that is used later on to compare against exams and other encounters. Logically, the test below could be reframed more simply, that the Entry overlaps the ``FirstSixMonths`` of the measure period.\n",
"\n",
"```\n",
"Initial Population =\n",
" ...\n",
" AND: \"Occurrence A of Diagnosis: Essential Hypertension\" \n",
" satisfies any:\n",
" < 6 month(s) starts after start of \"Measurement Period\"\n",
" satisfies all:\n",
" starts before start of \"Measurement Period\"\n",
" overlaps \"Measurement Period\"\n",
"```\n",
"\n",
"Unsurprisingly, all 12 synthetic patients (which were designed to be in the denominator) match this criteria as well."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"12-element composite vector of {String, Int64, Date*}:\n",
" (\"2_N_GP_Adult\",1,Date[2003-06-03]) \n",
" (\"A_Heart_Adult\",1,Date[2016-03-01]) \n",
" (\"B_Heart_Adult\",1,Date[2016-03-01]) \n",
" (\"C_N_GP_Adult\",1,Date[2015-03-01]) \n",
" (\"Z14_N_GP_Adult\",1,Date[2016-03-05]) \n",
" (\"Z1_Pregnancy_Adult\",1,Date[2015-04-03])\n",
" (\"Z2_N_Heart_Adult\",1,Date[2016-03-01]) \n",
" (\"Z4_Heart_Adult\",1,Date[2016-03-01]) \n",
" (\"Z5_Heart_Adult\",1,Date[2015-08-01]) \n",
" (\"Z6_N_Heart_Adult\",1,Date[2008-08-07]) \n",
" (\"Z7_Heart_Adult\",1,Date[2008-08-07]) \n",
" (\"Z9_GP_Geriatric\",1,Date[1991-03-02]) "
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"FirstSixMonths = ToInterval(\n",
" MeasurePeriod >> ThenLeft,\n",
" MeasurePeriod >> ThenLeft \n",
" .+ Const(Dates.Month(6)) \n",
" .- Const(Dates.Second(1)))\n",
"\n",
"HypertensionDx = EntryMatching(\n",
" Observation, Overlaps, FirstSixMonths,\n",
" EssentialHypertension)\n",
"\n",
"query_ihm(\n",
" Patient \n",
" >> ThenFilter(Exists(HypertensionDx))\n",
" >> ThenSelect(\n",
" Handle,\n",
" Count(HypertensionDx),\n",
" HypertensionDx >> Initiation >> AsDate\n",
" )\n",
")\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Putting these together, we get our Denominator.\n",
"\n",
"```\n",
"Initial Population = \n",
" AND: <age-test as above>\n",
" AND: <occurance-of-diagnosis as above>\n",
" AND: <has-office-visit as above>\n",
"Denominator =\n",
" AND: Initial Population\n",
"```\n",
"\n",
"Since each of the 3 criteria above match, the overall denominator; as each patient in our test deck satisfies all 3 criteria, our whole test deck is in the denominator."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"12-element Array{String,1}:\n",
" \"2_N_GP_Adult\" \n",
" \"A_Heart_Adult\" \n",
" \"B_Heart_Adult\" \n",
" \"C_N_GP_Adult\" \n",
" \"Z14_N_GP_Adult\" \n",
" \"Z1_Pregnancy_Adult\"\n",
" \"Z2_N_Heart_Adult\" \n",
" \"Z4_Heart_Adult\" \n",
" \"Z5_Heart_Adult\" \n",
" \"Z6_N_Heart_Adult\" \n",
" \"Z7_Heart_Adult\" \n",
" \"Z9_GP_Geriatric\" "
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"InPopulation = (\n",
" AgeFrom(18, 85) & \n",
" Exists(Interactions) & \n",
" Exists(HypertensionDx)\n",
")\n",
"\n",
"InDenominator = InPopulation\n",
"\n",
"query_ihm(\n",
" Patient\n",
" >> ThenFilter(InDenominator)\n",
" >> Handle\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The measure also defines a set of exclusions which do not count against the Physican even though they may fail the numerator (positive outcome) test.\n",
"\n",
"```\n",
"Denominator Exclusions =\n",
"OR: \"Encounter, Performed: Encounter Inpatient (discharge \n",
" status: Discharged to Home for Hospice Care)\" \n",
" ends during \"Measurement Period\"\n",
"OR: \"Encounter, Performed: Encounter Inpatient (discharge \n",
" status: Discharged to Health Care Facility for Hospice Care)\" \n",
" ends during \"Measurement Period\"\n",
"OR: Union of:\n",
" \"Intervention, Order: Hospice care ambulatory\"\n",
" \"Intervention, Performed: Hospice care ambulatory\"\n",
" overlaps \"Measurement Period\"\n",
"OR: Union of:\n",
" \"Diagnosis: Pregnancy\"\n",
" \"Diagnosis: End Stage Renal Disease\"\n",
" \"Diagnosis: Chronic Kidney Disease, Stage 5\"\n",
" overlaps \"Measurement Period\"\n",
"OR: Union of:\n",
" \"Procedure, Performed: Vascular Access for Dialysis\"\n",
" \"Encounter, Performed: ESRD Monthly Outpatient Services\"\n",
" \"Procedure, Performed: Kidney Transplant\"\n",
" \"Procedure, Performed: Dialysis Services\"\n",
" starts before end of \"Measurement Period\" \n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6-element Array{String,1}:\n",
" \"2_N_GP_Adult\" \n",
" \"C_N_GP_Adult\" \n",
" \"Z1_Pregnancy_Adult\"\n",
" \"Z5_Heart_Adult\" \n",
" \"Z6_N_Heart_Adult\" \n",
" \"Z7_Heart_Adult\" "
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"InDenominatorExclusions = InDenominator & Exists(\n",
" Merge(\n",
" EntryMatching(\n",
" Encounter, EndsDuring, MeasurePeriod,\n",
" EncounterInpatient)\n",
" >> ThenFilter( Const(true)\n",
" # These didn't make it into the FHIR data?\n",
" # AnyOf(Discharge .== DischargedHospiceHome)\n",
" # | AnyOf(Discharge .== DischargedHospiceFacility)),\n",
" ),\n",
" EntryMatching(\n",
" Observation, Overlaps, MeasurePeriod,\n",
" Pregnancy, EndStageRenalDisease,\n",
" ChronicKidneyDiseaseStage5),\n",
" EntryMatching(\n",
" Action, StartsBeforeEndOf, MeasurePeriod,\n",
" HospiceCareAmbulatory),\n",
" EntryMatching(\n",
" Request, StartsBeforeEndOf, MeasurePeriod,\n",
" HospiceCareAmbulatory),\n",
" EntryMatching(\n",
" Encounter, StartsBeforeEndOf, MeasurePeriod,\n",
" ESRDMonthlyOutpatientServices), \n",
" EntryMatching(\n",
" Action, StartsBeforeEndOf, MeasurePeriod,\n",
" DialysisEducation, \n",
" OtherServicesRelatedToDialysis),\n",
" EntryMatching(\n",
" Action, StartsBeforeEndOf, MeasurePeriod,\n",
" KidneyTransplant, VascularAccessForDialysis, \n",
" DialysisServices)\n",
"))\n",
" \n",
"query_ihm(\n",
" Patient\n",
" >> ThenFilter(InDenominatorExclusions)\n",
" >> Handle\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The numerator condition identifies a successful outcome. This is a two stage criteria. First, it specifies that we're looking at only the most recent qualifying encounter where a physical exams were performed. Second, it tests the results of those exams.\n",
"```\n",
"Numerator =\n",
" AND: Most Recent:\n",
" \"Occurrence A of Encounter, Performed: Adult Outpatient Visit\"\n",
" satisfies all:\n",
" overlaps \"Occurrence A of Diagnosis: Essential Hypertension\"\n",
" during \"Measurement Period\"\n",
" overlaps \"Physical Exam, Performed: Diastolic Blood Pressure (result)\"\n",
" overlaps \"Physical Exam, Performed: Systolic Blood Pressure (result)\"\n",
" ...\n",
"```\n",
"\n",
"This is essentially a 4-way product of entries: the encounter, the diagnosis, and two physical exam records. We're after the latest encounter during the measure period that has these characteristics. In our context-sensitive language, we create sets of 3 time periods for the diagnosis and exams. Then we search for encounters that overlap. \n",
"\n",
"In this prototype, there is a current complication with this multi-pass query. We need effectively 4 cursors through the data and the normal combinator path is restricted to just one. The ``Using`` combinator permits 3 of the 4 to be given a name and referenced in the 4th. The ``Gnisu`` function simply retrives the cursor defined in the ``Using``. Further, only constants (ie, ``Interval``) can easily be used. In subsequent versions of this impementation a more elegant approach will be explored. "
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4-element composite vector of {String, DateTime*}:\n",
" (\"A_Heart_Adult\",DateTime[2016-03-01T17:00:00]) \n",
" (\"B_Heart_Adult\",DateTime[2016-12-20T17:00:00]) \n",
" (\"Z14_N_GP_Adult\",DateTime[2016-03-05T08:00:00])\n",
" (\"Z4_Heart_Adult\",DateTime[2016-12-20T17:00:00])"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"DiastolicExam = (\n",
" EntryMatching(\n",
" Observation, During, MeasurePeriod,\n",
" DiastolicBloodPressure)\n",
" >> ThenFilter(Exists(Result)))\n",
"\n",
"SystolicExam = (\n",
" EntryMatching(\n",
" Observation, During, MeasurePeriod,\n",
" SystolicBloodPressure)\n",
" >> ThenFilter(Exists(Result)))\n",
"\n",
"ThenMostRecent = (\n",
" ThenSort(PeriodStart) \n",
" >> ThenSkip(-1)\n",
")\n",
"\n",
"ExamVisit = WithThisPatient(\n",
" EntryMatching(\n",
" Encounter, During, MeasurePeriod,\n",
" AdultOutpatientVisit)\n",
" >> ThenFilter(\n",
" AnyOf(Overlaps(ThisPatient >> HypertensionDx)) &\n",
" AnyOf(Overlaps(ThisPatient >> DiastolicExam)) &\n",
" AnyOf(Overlaps(ThisPatient >> SystolicExam)))\n",
" >> ThenMostRecent\n",
")\n",
"\n",
"query_ihm(\n",
" Patient\n",
" >> ThenFilter(Exists(ExamVisit))\n",
" >> ThenSelect(\n",
" Handle,\n",
" ExamVisit >> PeriodStart)\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that we have the target visit, let's extract the blood pressure readings."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4-element composite vector of {String, Int64?, Int64?}:\n",
" (\"A_Heart_Adult\",150,90) \n",
" (\"B_Heart_Adult\",130,60) \n",
" (\"Z14_N_GP_Adult\",194,102)\n",
" (\"Z4_Heart_Adult\",130,60) "
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"GetReading(ExamType) = WithThisPatient(\n",
" ExamType\n",
" >> ThenFilter(\n",
" AnyOf(During(ThisPatient >> ExamVisit)))\n",
" >> ThenMostRecent\n",
" >> Result\n",
" >> Scalar\n",
" >> ThenExpectAtMostOne\n",
")\n",
"\n",
"query_ihm(\n",
" Patient\n",
" >> ThenFilter(Exists(ExamVisit))\n",
" >> ThenSelect(\n",
" Handle,\n",
" GetReading(SystolicExam),\n",
" GetReading(DiastolicExam))\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then, it's time to finish the Numerator.\n",
"\n",
"```\n",
"Numerator =\n",
" ... \n",
" AND: \"Physical Exam, Performed: Diastolic Blood Pressure\"\n",
" satisfies all:\n",
" Most Recent:\n",
" during \"Occurrence A of Encounter, Performed: Adult Outpatient Visit\"\n",
" (result < 90 mmHg)\n",
" AND: \"Physical Exam, Performed: Systolic Blood Pressure\"\n",
" satisfies all:\n",
" Most Recent:\n",
" during \"Occurrence A of Encounter, Performed: Adult Outpatient Visit\"\n",
" (result < 140 mmHg)\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"12-element composite vector of {String, Bool, Bool, Bool}:\n",
" (\"2_N_GP_Adult\",false,true,true) \n",
" (\"A_Heart_Adult\",false,true,false) \n",
" (\"B_Heart_Adult\",true,true,false) \n",
" (\"C_N_GP_Adult\",false,true,true) \n",
" (\"Z14_N_GP_Adult\",false,true,false) \n",
" (\"Z1_Pregnancy_Adult\",false,true,true)\n",
" (\"Z2_N_Heart_Adult\",false,true,false) \n",
" (\"Z4_Heart_Adult\",true,true,false) \n",
" (\"Z5_Heart_Adult\",false,true,true) \n",
" (\"Z6_N_Heart_Adult\",false,true,true) \n",
" (\"Z7_Heart_Adult\",false,true,true) \n",
" (\"Z9_GP_Geriatric\",false,true,false) "
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"InNumerator = (\n",
" InDenominator &\n",
" ~InDenominatorExclusions &\n",
" AnyOf(GetReading(SystolicExam) .< 140) &\n",
" AnyOf(GetReading(DiastolicExam) .< 90)\n",
")\n",
"\n",
"query_ihm(\n",
" Patient \n",
" >> ThenSelect(\n",
" Handle,\n",
" InNumerator, \n",
" InDenominator,\n",
" InDenominatorExclusions)\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Offical Results**\n",
"```\n",
"+--------------------------------------------------------+\n",
"|*Patient* |*Numerator*|*Denominator*|*Exclusion*|\n",
"|2_N_GP_Adult |false |true |true |\n",
"|A_Heart_Adult |false |true |false |\n",
"|B_Heart_Adult |true |true |false |\n",
"|C_N_GP_Adult |false |true |true |\n",
"|Z14_N_GP_Adult |false |true |false |\n",
"|Z1_Pregnancy_Adult|false |true |true |\n",
"|Z2_N_Heart_Adult |false |true |false |\n",
"|Z4_Heart_Adult |true |true |false |\n",
"|Z5_Heart_Adult |false |true |true |\n",
"|Z6_N_Heart_Adult |false |true |true |\n",
"|Z7_Heart_Adult |false |true |true |\n",
"|Z9_GP_Geriatric |false |true |false |\n",
"+--------------------------------------------------------+\n",
"```"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 0.5.2",
"language": "julia",
"name": "julia-0.5"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "0.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment