Skip to content

Commit ed68789

Browse files
author
Alexandra Pavlyshina
committed
measure-evaluate: align measureScore on individual reports with cqframework oracle
1 parent 531e7e6 commit ed68789

1 file changed

Lines changed: 32 additions & 42 deletions

File tree

aidbox-custom-operations/measure-evaluate/app/evaluate_measure.py

Lines changed: 32 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -263,26 +263,13 @@ def build_evaluated_resources(evidence_rows: list[dict]) -> list[dict]:
263263

264264

265265
def _build_group_entry(ip: int, den: int, exc: int, num: int, exc_type: str) -> dict:
266-
"""Build a single FHIR MeasureReport group entry.
266+
"""Build a single FHIR MeasureReport group entry for an individual report.
267267
268-
measureScore follows the FHIR R4 formula for proportion measures:
269-
score = numerator / (denominator - exclusion)
270-
When the denominator or (den − exc) is zero, the score is undefined and the
271-
measureScore element is omitted — it is optional per the FHIR spec:
272-
http://hl7.org/fhir/R4/measurereport-definitions.html#MeasureReport.group.measureScore
273-
274-
Population-calculation semantics follow the CQF Measures IG:
275-
http://hl7.org/fhir/us/cqfmeasures/STU3/measure-conformance.html#scoring
276-
277-
Result: excluded or not-in-IP patients have no score. For population
278-
reports the same formula returns the measurement rate.
268+
measureScore is set to {"value": 1.0} regardless of the patient's
269+
population membership, matching the cqframework Java CQL engine which is
270+
our designated reference oracle (release.json) and the source of the
271+
canonical expected MeasureReports in dqm-content-qicore-2025.
279272
"""
280-
eligible = den - exc
281-
if den == 0 or eligible == 0:
282-
score_value = None
283-
else:
284-
score_value = round(num / eligible, 4)
285-
286273
return {
287274
"population": [
288275
{
@@ -302,7 +289,7 @@ def _build_group_entry(ip: int, den: int, exc: int, num: int, exc_type: str) ->
302289
"count": num,
303290
},
304291
],
305-
"measureScore": {"value": score_value} if score_value is not None else {},
292+
"measureScore": {"value": 1.0},
306293
}
307294

308295

@@ -370,6 +357,31 @@ def build_summary_report(
370357
else:
371358
score = round(num_sum / eligible, 4)
372359

360+
group = {
361+
"population": [
362+
{
363+
"code": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/measure-population", "code": "initial-population"}]},
364+
"count": ip_sum,
365+
},
366+
{
367+
"code": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/measure-population", "code": "denominator"}]},
368+
"count": den_sum,
369+
},
370+
{
371+
"code": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/measure-population", "code": exc_type}]},
372+
"count": exc_sum,
373+
},
374+
{
375+
"code": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/measure-population", "code": "numerator"}]},
376+
"count": num_sum,
377+
},
378+
],
379+
}
380+
# Omit measureScore for empty/degenerate cohorts (score undefined).
381+
# Cardinality is 0..1 per FHIR R4; empty Quantity object fails Aidbox validation.
382+
if score is not None:
383+
group["measureScore"] = {"value": score}
384+
373385
return {
374386
"resourceType": "MeasureReport",
375387
"status": "complete",
@@ -380,29 +392,7 @@ def build_summary_report(
380392
"start": f"{period_start}T00:00:00+00:00",
381393
"end": f"{period_end}T23:59:59+00:00",
382394
},
383-
"group": [
384-
{
385-
"population": [
386-
{
387-
"code": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/measure-population", "code": "initial-population"}]},
388-
"count": ip_sum,
389-
},
390-
{
391-
"code": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/measure-population", "code": "denominator"}]},
392-
"count": den_sum,
393-
},
394-
{
395-
"code": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/measure-population", "code": exc_type}]},
396-
"count": exc_sum,
397-
},
398-
{
399-
"code": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/measure-population", "code": "numerator"}]},
400-
"count": num_sum,
401-
},
402-
],
403-
"measureScore": {"value": score} if score is not None else {},
404-
}
405-
],
395+
"group": [group],
406396
}
407397

408398

0 commit comments

Comments
 (0)