Search in sources :

Example 41 with Observation

use of org.hl7.fhir.r5.model.Observation in project BridgeServer2 by Sage-Bionetworks.

the class CRCControllerTest method operationWrongIdentifier.

@Test(expectedExceptions = BadRequestException.class, expectedExceptionsMessageRegExp = "Could not find Bridge user ID.")
public void operationWrongIdentifier() throws Exception {
    when(mockRequest.getHeader(AUTHORIZATION)).thenReturn(AUTHORIZATION_HEADER_VALUE);
    when(mockAccountService.authenticate(any(), any())).thenReturn(account);
    when(mockAccountService.getAccount(ACCOUNT_ID)).thenReturn(Optional.of(account));
    Identifier identifier = new Identifier();
    identifier.setSystem("wrong-system");
    identifier.setValue(TEST_USER_ID);
    Observation observation = new Observation();
    observation.addIdentifier(identifier);
    String json = FHIR_CONTEXT.newJsonParser().encodeResourceToString(observation);
    mockRequestBody(mockRequest, json);
    controller.postObservation();
}
Also used : Identifier(org.hl7.fhir.dstu3.model.Identifier) Observation(org.hl7.fhir.dstu3.model.Observation) Test(org.testng.annotations.Test)

Example 42 with Observation

use of org.hl7.fhir.r5.model.Observation in project quality-measure-and-cohort-service by Alvearie.

the class MeasureSupplementalDataEvaluationTest method testProcessAccumulators_notSDESex.

@Test
public void testProcessAccumulators_notSDESex() {
    /* 
		 * Jill - I don't like how this part of the code works.  The code grabs everything after (and including) the "-", 
		 * and then looks for that to exist as an extension on the Patient resource.  This works for race and ethnicity 
		 * on the US-core patient profile, but since we already calculated this in the populate SDE accumulator method
		 * the only reason it's "recalculating" is because the system and display aren't on the passed in map.
		 * Plus, it's coded assuming there is a list of extensions within the extension (which is how US-Core handles race and eth) 
		 * and it magically grabs the first one... so if you have multiple this doesn't match all of them.
		*/
    Code white = new Code();
    white.setCode(WHITE_CODE);
    Map<String, Map<String, Integer>> sdeAccumulators = getSDEAccumulators(SDE_RACE, null, white, new HashMap<>());
    MeasureReport report = new MeasureReport();
    Patient mockPatient = mockPatient();
    Extension raceExtension = new Extension();
    // This can be anything as long as it includes "-race"
    raceExtension.setUrl("something-race");
    // This example was stolen from https://www.hl7.org/fhir/us/core/Patient-example.xml.html
    Extension valueExtension = new Extension();
    valueExtension.setUrl("ombCategory");
    valueExtension.setValue(getWhiteCoding());
    raceExtension.setExtension(Arrays.asList(valueExtension));
    Mockito.when(mockPatient.getExtension()).thenReturn(Arrays.asList(raceExtension));
    MeasureSupplementalDataEvaluation.processAccumulators(report, sdeAccumulators, true, Arrays.asList(mockPatient));
    assertNotNull(report);
    // EvaluatedResource should contain a reference to an observation record created for supplemental data
    assertEquals(1, report.getEvaluatedResource().size());
    // The observation record mentioned previously should exist within the contained resources of the measure report
    assertEquals(1, report.getContained().size());
    assertTrue(report.getContained().get(0) instanceof Observation);
    Observation obs = (Observation) report.getContained().get(0);
    // For a single patient, the code of the observation should be the supplemental data text
    assertEquals(SDE_RACE, obs.getCode().getText());
    // For a single patient, the value of the observation should be the result of the appropriate define
    assertTrue(obs.getValue() instanceof CodeableConcept);
    assertEquals(WHITE_CODE, ((CodeableConcept) obs.getValue()).getCoding().get(0).getCode());
}
Also used : Extension(org.hl7.fhir.r4.model.Extension) Observation(org.hl7.fhir.r4.model.Observation) Patient(org.hl7.fhir.r4.model.Patient) MeasureReport(org.hl7.fhir.r4.model.MeasureReport) Code(org.opencds.cqf.cql.engine.runtime.Code) HashMap(java.util.HashMap) Map(java.util.Map) CodeableConcept(org.hl7.fhir.r4.model.CodeableConcept) Test(org.junit.Test)

Example 43 with Observation

use of org.hl7.fhir.r5.model.Observation in project quality-measure-and-cohort-service by Alvearie.

the class MeasureSupplementalDataEvaluationTest method testProcessAccumulators.

@Test
public void testProcessAccumulators() {
    Map<String, Map<String, Integer>> sdeAccumulators = getSexSDEAccumulators();
    MeasureReport report = new MeasureReport();
    MeasureSupplementalDataEvaluation.processAccumulators(report, sdeAccumulators, true, new ArrayList<>());
    assertNotNull(report);
    // EvaluatedResource should contain a reference to an observation record created for supplemental data
    assertEquals(1, report.getEvaluatedResource().size());
    // The observation record mentioned previously should exist within the contained resources of the measure report
    assertEquals(1, report.getContained().size());
    assertTrue(report.getContained().get(0) instanceof Observation);
    Observation obs = (Observation) report.getContained().get(0);
    // For a single patient, the code of the observation should be the supplemental data text
    assertEquals(MeasureSupplementalDataEvaluation.SDE_SEX, obs.getCode().getText());
    // For a single patient, the value of the observation should be the result of the appropriate define
    assertTrue(obs.getValue() instanceof CodeableConcept);
    assertEquals(MALE_CODE, ((CodeableConcept) obs.getValue()).getCoding().get(0).getCode());
    // Within the observation, there should be 1 extension, with two further nested extensions
    Extension obsExt = obs.getExtensionByUrl(MeasureSupplementalDataEvaluation.CQF_MEASUREINFO_URL);
    assertNotNull(obsExt);
    assertEquals(2, obsExt.getExtension().size());
    Extension measureNestedExt = obsExt.getExtensionByUrl(MeasureSupplementalDataEvaluation.MEASURE);
    assertTrue(measureNestedExt.getValue() instanceof CanonicalType);
    assertEquals(MeasureSupplementalDataEvaluation.CQFMEASURES_URL + report.getMeasure(), ((CanonicalType) measureNestedExt.getValue()).asStringValue());
    Extension populationNestedExt = obsExt.getExtensionByUrl(MeasureSupplementalDataEvaluation.POPULATION_ID);
    assertEquals(MeasureSupplementalDataEvaluation.SDE_SEX, ((StringType) populationNestedExt.getValue()).asStringValue());
}
Also used : Extension(org.hl7.fhir.r4.model.Extension) Observation(org.hl7.fhir.r4.model.Observation) MeasureReport(org.hl7.fhir.r4.model.MeasureReport) HashMap(java.util.HashMap) Map(java.util.Map) CanonicalType(org.hl7.fhir.r4.model.CanonicalType) CodeableConcept(org.hl7.fhir.r4.model.CodeableConcept) Test(org.junit.Test)

Example 44 with Observation

use of org.hl7.fhir.r5.model.Observation in project quality-measure-and-cohort-service by Alvearie.

the class MeasureEvaluatorTest method in_populations_supplemental_data.

@Test
public void in_populations_supplemental_data() throws Exception {
    CapabilityStatement metadata = getCapabilityStatement();
    mockFhirResourceRetrieval("/metadata?_format=json", metadata);
    Patient patient = getPatient("123", AdministrativeGender.MALE, "1970-10-10");
    mockFhirResourceRetrieval(patient);
    Library library = setupDefineReturnLibrary();
    expressionsByPopulationType.clear();
    expressionsByPopulationType.put(MeasurePopulationType.INITIALPOPULATION, INITIAL_POPULATION);
    expressionsByPopulationType.put(MeasurePopulationType.DENOMINATOR, DENOMINATOR);
    expressionsByPopulationType.put(MeasurePopulationType.NUMERATOR, NUMERATOR);
    Measure measure = getProportionMeasure("ProportionMeasureName", library, expressionsByPopulationType);
    measure.setSupplementalData(Arrays.asList(createSupplementalDataComponent("SDE Sex", MeasureSupplementalDataEvaluation.SDE_SEX)));
    mockFhirResourceRetrieval(measure);
    MeasureReport report = evaluator.evaluatePatientMeasure(measure.getId(), patient.getId(), null, new MeasureEvidenceOptions());
    assertNotNull(report);
    // EvaluatedResource should contain a reference to an observation record created for supplemental data, despite the evidence options indicating returning no evaluatedResources
    assertEquals(1, report.getEvaluatedResource().size());
// See MeasureSupplementalDataEvaluationTest for more details on what is returned here
}
Also used : CapabilityStatement(org.hl7.fhir.r4.model.CapabilityStatement) Measure(org.hl7.fhir.r4.model.Measure) Patient(org.hl7.fhir.r4.model.Patient) MeasureReport(org.hl7.fhir.r4.model.MeasureReport) Library(org.hl7.fhir.r4.model.Library) MeasureEvidenceOptions(com.ibm.cohort.engine.measure.evidence.MeasureEvidenceOptions) Test(org.junit.Test)

Example 45 with Observation

use of org.hl7.fhir.r5.model.Observation in project quality-measure-and-cohort-service by Alvearie.

the class MeasureEvaluation method evaluate.

protected MeasureReport evaluate(Measure measure, Context context, List<Patient> patients, MeasureReport.MeasureReportType type, boolean isSingle, boolean includeEvaluatedResources) {
    MeasureReportBuilder reportBuilder = new MeasureReportBuilder();
    reportBuilder.buildStatus("complete");
    reportBuilder.buildType(type);
    reportBuilder.buildMeasureReference(measure.getIdElement().getResourceType() + "/" + measure.getIdElement().getIdPart());
    if (type == MeasureReport.MeasureReportType.INDIVIDUAL && CollectionUtils.isNotEmpty(patients)) {
        IdType patientId = patients.get(0).getIdElement();
        reportBuilder.buildPatientReference(patientId.getResourceType() + "/" + patientId.getIdPart());
    }
    reportBuilder.buildPeriod(measurementPeriod);
    MeasureReport report = reportBuilder.build();
    Map<String, Resource> resources = new HashMap<>();
    Map<String, Set<String>> codeToResourceMap = new HashMap<>();
    MeasureScoring measureScoring = MeasureScoring.fromCode(measure.getScoring().getCodingFirstRep().getCode());
    if (measureScoring == null) {
        throw new RuntimeException("Measure scoring is required in order to calculate.");
    }
    List<Measure.MeasureSupplementalDataComponent> sde = measure.getSupplementalData();
    Map<String, Map<String, Integer>> sdeAccumulators = new HashMap<>();
    for (Measure.MeasureGroupComponent group : measure.getGroup()) {
        MeasureReport.MeasureReportGroupComponent reportGroup = new MeasureReport.MeasureReportGroupComponent();
        reportGroup.setId(group.getId());
        report.getGroup().add(reportGroup);
        // Declare variables to avoid a hash lookup on every patient
        // TODO: Isn't quite right, there may be multiple initial populations for a
        // ratio measure...
        Measure.MeasureGroupPopulationComponent initialPopulationCriteria = null;
        Measure.MeasureGroupPopulationComponent numeratorCriteria = null;
        Measure.MeasureGroupPopulationComponent numeratorExclusionCriteria = null;
        Measure.MeasureGroupPopulationComponent denominatorCriteria = null;
        Measure.MeasureGroupPopulationComponent denominatorExclusionCriteria = null;
        Measure.MeasureGroupPopulationComponent denominatorExceptionCriteria = null;
        Map<String, Resource> initialPopulation = null;
        Map<String, Resource> numerator = null;
        Map<String, Resource> numeratorExclusion = null;
        Map<String, Resource> denominator = null;
        Map<String, Resource> denominatorExclusion = null;
        Map<String, Resource> denominatorException = null;
        Map<String, Patient> initialPopulationPatients = null;
        Map<String, Patient> numeratorPatients = null;
        Map<String, Patient> numeratorExclusionPatients = null;
        Map<String, Patient> denominatorPatients = null;
        Map<String, Patient> denominatorExclusionPatients = null;
        Map<String, Patient> denominatorExceptionPatients = null;
        for (Measure.MeasureGroupPopulationComponent pop : group.getPopulation()) {
            MeasurePopulationType populationType = MeasurePopulationType.fromCode(pop.getCode().getCodingFirstRep().getCode());
            if (populationType != null) {
                switch(populationType) {
                    case INITIALPOPULATION:
                        initialPopulationCriteria = pop;
                        initialPopulation = new HashMap<>();
                        if (type == MeasureReport.MeasureReportType.SUBJECTLIST) {
                            initialPopulationPatients = new HashMap<>();
                        }
                        break;
                    case NUMERATOR:
                        numeratorCriteria = pop;
                        numerator = new HashMap<>();
                        if (type == MeasureReport.MeasureReportType.SUBJECTLIST) {
                            numeratorPatients = new HashMap<>();
                        }
                        break;
                    case NUMERATOREXCLUSION:
                        numeratorExclusionCriteria = pop;
                        numeratorExclusion = new HashMap<>();
                        if (type == MeasureReport.MeasureReportType.SUBJECTLIST) {
                            numeratorExclusionPatients = new HashMap<>();
                        }
                        break;
                    case DENOMINATOR:
                        denominatorCriteria = pop;
                        denominator = new HashMap<>();
                        if (type == MeasureReport.MeasureReportType.SUBJECTLIST) {
                            denominatorPatients = new HashMap<>();
                        }
                        break;
                    case DENOMINATOREXCLUSION:
                        denominatorExclusionCriteria = pop;
                        denominatorExclusion = new HashMap<>();
                        if (type == MeasureReport.MeasureReportType.SUBJECTLIST) {
                            denominatorExclusionPatients = new HashMap<>();
                        }
                        break;
                    case DENOMINATOREXCEPTION:
                        denominatorExceptionCriteria = pop;
                        denominatorException = new HashMap<>();
                        if (type == MeasureReport.MeasureReportType.SUBJECTLIST) {
                            denominatorExceptionPatients = new HashMap<>();
                        }
                        break;
                    default:
                        throw new UnsupportedOperationException("Measure population, observation and measure population exclusion are used for continuous-variable scoring measures which are not supported");
                }
            }
        }
        switch(measureScoring) {
            case PROPORTION:
            case RATIO:
                {
                    // For each patient in the initial population
                    for (Patient patient : patients) {
                        // Are they in the initial population?
                        boolean inInitialPopulation = evaluatePopulationCriteria(context, patient, initialPopulationCriteria, initialPopulation, initialPopulationPatients, null, null, null);
                        populateResourceMap(context, MeasurePopulationType.INITIALPOPULATION, resources, codeToResourceMap, includeEvaluatedResources);
                        if (inInitialPopulation) {
                            // Are they in the denominator?
                            boolean inDenominator = evaluatePopulationCriteria(context, patient, denominatorCriteria, denominator, denominatorPatients, denominatorExclusionCriteria, denominatorExclusion, denominatorExclusionPatients);
                            populateResourceMap(context, MeasurePopulationType.DENOMINATOR, resources, codeToResourceMap, includeEvaluatedResources);
                            if (inDenominator) {
                                // Are they in the numerator?
                                boolean inNumerator = evaluatePopulationCriteria(context, patient, numeratorCriteria, numerator, numeratorPatients, numeratorExclusionCriteria, numeratorExclusion, numeratorExclusionPatients);
                                populateResourceMap(context, MeasurePopulationType.NUMERATOR, resources, codeToResourceMap, includeEvaluatedResources);
                                if (!inNumerator && inDenominator && (denominatorExceptionCriteria != null)) {
                                    // Are they in the denominator exception?
                                    boolean inException = false;
                                    for (Resource resource : evaluateCriteria(context, patient, denominatorExceptionCriteria)) {
                                        inException = true;
                                        denominatorException.put(resource.getIdElement().getIdPart(), resource);
                                        denominator.remove(resource.getIdElement().getIdPart());
                                        populateResourceMap(context, MeasurePopulationType.DENOMINATOREXCEPTION, resources, codeToResourceMap, includeEvaluatedResources);
                                    }
                                    if (inException) {
                                        if (denominatorExceptionPatients != null) {
                                            denominatorExceptionPatients.put(patient.getIdElement().getIdPart(), patient);
                                        }
                                        if (denominatorPatients != null) {
                                            denominatorPatients.remove(patient.getIdElement().getIdPart());
                                        }
                                    }
                                }
                            }
                        }
                        MeasureSupplementalDataEvaluation.populateSDEAccumulators(context, patient, sdeAccumulators, sde);
                    }
                    // Calculate actual measure score, Count(numerator) / Count(denominator)
                    if (numerator != null && MapUtils.isNotEmpty(denominator)) {
                        reportGroup.setMeasureScore(new Quantity(numerator.size() / (double) denominator.size()));
                    }
                    break;
                }
            case COHORT:
                {
                    // For each patient in the patient list
                    for (Patient patient : patients) {
                        evaluatePopulationCriteria(context, patient, initialPopulationCriteria, initialPopulation, initialPopulationPatients, null, null, null);
                        populateResourceMap(context, MeasurePopulationType.INITIALPOPULATION, resources, codeToResourceMap, includeEvaluatedResources);
                        MeasureSupplementalDataEvaluation.populateSDEAccumulators(context, patient, sdeAccumulators, sde);
                    }
                    break;
                }
            case CONTINUOUSVARIABLE:
                throw new UnsupportedOperationException("Scoring type CONTINUOUSVARIABLE is not supported");
        }
        // Add population reports for each group
        addPopulationCriteriaReport(report, reportGroup, initialPopulationCriteria, initialPopulation != null ? initialPopulation.size() : 0, initialPopulationPatients != null ? initialPopulationPatients.values() : null);
        addPopulationCriteriaReport(report, reportGroup, numeratorCriteria, numerator != null ? numerator.size() : 0, numeratorPatients != null ? numeratorPatients.values() : null);
        addPopulationCriteriaReport(report, reportGroup, numeratorExclusionCriteria, numeratorExclusion != null ? numeratorExclusion.size() : 0, numeratorExclusionPatients != null ? numeratorExclusionPatients.values() : null);
        addPopulationCriteriaReport(report, reportGroup, denominatorCriteria, denominator != null ? denominator.size() : 0, denominatorPatients != null ? denominatorPatients.values() : null);
        addPopulationCriteriaReport(report, reportGroup, denominatorExclusionCriteria, denominatorExclusion != null ? denominatorExclusion.size() : 0, denominatorExclusionPatients != null ? denominatorExclusionPatients.values() : null);
        addPopulationCriteriaReport(report, reportGroup, denominatorExceptionCriteria, denominatorException != null ? denominatorException.size() : 0, denominatorExceptionPatients != null ? denominatorExceptionPatients.values() : null);
    }
    for (Entry<String, Set<String>> entry : codeToResourceMap.entrySet()) {
        ListResource list = new ListResource();
        for (String element : entry.getValue()) {
            ListResource.ListEntryComponent comp = new ListEntryComponent();
            comp.setItem(new Reference('#' + element));
            list.addEntry(comp);
        }
        if (!list.isEmpty()) {
            list.setId(UUID.randomUUID().toString());
            list.setTitle(entry.getKey());
            resources.put(list.getId(), list);
        }
    }
    if (MapUtils.isNotEmpty(resources)) {
        List<Reference> evaluatedResourceIds = new ArrayList<>();
        resources.forEach((key, resource) -> {
            evaluatedResourceIds.add(new Reference(resource.getId()));
        });
        report.setEvaluatedResource(evaluatedResourceIds);
    }
    if (MapUtils.isNotEmpty(sdeAccumulators)) {
        report = MeasureSupplementalDataEvaluation.processAccumulators(report, sdeAccumulators, isSingle, patients);
    }
    return report;
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) MeasureScoring(org.opencds.cqf.common.evaluation.MeasureScoring) ListEntryComponent(org.hl7.fhir.r4.model.ListResource.ListEntryComponent) Measure(org.hl7.fhir.r4.model.Measure) ListEntryComponent(org.hl7.fhir.r4.model.ListResource.ListEntryComponent) Reference(org.hl7.fhir.r4.model.Reference) MeasureReportBuilder(com.ibm.cohort.engine.r4.builder.MeasureReportBuilder) ListResource(org.hl7.fhir.r4.model.ListResource) Resource(org.hl7.fhir.r4.model.Resource) Patient(org.hl7.fhir.r4.model.Patient) Quantity(org.hl7.fhir.r4.model.Quantity) MeasureReport(org.hl7.fhir.r4.model.MeasureReport) IdType(org.hl7.fhir.r4.model.IdType) ListResource(org.hl7.fhir.r4.model.ListResource) HashMap(java.util.HashMap) Map(java.util.Map) MeasurePopulationType(org.opencds.cqf.common.evaluation.MeasurePopulationType)

Aggregations

Observation (org.hl7.fhir.r4.model.Observation)237 Test (org.junit.Test)235 MockHttpServletResponse (org.springframework.mock.web.MockHttpServletResponse)114 Test (org.junit.jupiter.api.Test)107 IBaseResource (org.hl7.fhir.instance.model.api.IBaseResource)106 Observation (org.hl7.fhir.dstu3.model.Observation)94 Bundle (org.hl7.fhir.r4.model.Bundle)88 IBundleProvider (ca.uhn.fhir.rest.api.server.IBundleProvider)64 ArrayList (java.util.ArrayList)62 BundleEntryComponent (org.hl7.fhir.r4.model.Bundle.BundleEntryComponent)59 Resource (org.hl7.fhir.r4.model.Resource)55 Bundle (org.hl7.fhir.dstu3.model.Bundle)53 CodeableConcept (org.hl7.fhir.r4.model.CodeableConcept)47 Coding (org.hl7.fhir.r4.model.Coding)46 Reference (org.hl7.fhir.r4.model.Reference)41 TokenAndListParam (ca.uhn.fhir.rest.param.TokenAndListParam)37 TokenParam (ca.uhn.fhir.rest.param.TokenParam)37 Date (java.util.Date)34 ReferenceAndListParam (ca.uhn.fhir.rest.param.ReferenceAndListParam)32 ReferenceOrListParam (ca.uhn.fhir.rest.param.ReferenceOrListParam)32