Search in sources :

Example 36 with Group

use of org.hl7.fhir.r4.model.Group in project cqf-ruler by DBCG.

the class Session method resolveDefinition.

private Resource resolveDefinition(RequestDetails theRequest, Session session, PlanDefinition.PlanDefinitionActionComponent action) {
    Resource result = null;
    if (action.hasDefinition()) {
        logger.debug("Resolving definition: {}", action.getDefinition().getReference());
        Reference definition = action.getDefinition();
        if (definition.getId().contains(session.getPlanDefinition().fhirType())) {
            IdType id = new IdType(definition.getId());
            CarePlan plan;
            try {
                plan = applyPlanDefinition(theRequest, id, session.getPatientId(), session.getEncounterId(), session.getPractitionerId(), session.getOrganizationId(), session.getUserType(), session.getUserLanguage(), session.getUserTaskContext(), session.getSetting(), session.getSettingContext());
                if (plan.getId() == null) {
                    plan.setId(UUID.randomUUID().toString());
                }
                // Add an action to the request group which points to this CarePlan
                session.getRequestGroupBuilder().buildContained(plan).addAction(new RequestGroupActionBuilder().buildResource(new Reference("#" + plan.getId())).build());
                for (Reference r : plan.getDefinition()) {
                    session.getCarePlanBuilder().buildDefinition(r);
                }
                result = plan;
            } catch (IOException e) {
                e.printStackTrace();
                logger.error("nested plan failed");
            }
        } else {
            try {
                if (action.getDefinition().getReferenceElement().getIdPart().startsWith("#")) {
                    result = this.activityDefinitionApplyProvider.resolveActivityDefinition((ActivityDefinition) resolveContained(session.getPlanDefinition(), action.getDefinition().getReferenceElement().getIdPart()), session.getPatientId(), session.getPractitionerId(), session.getOrganizationId(), theRequest);
                } else {
                    result = this.activityDefinitionApplyProvider.apply(theRequest, new IdType(action.getDefinition().getReferenceElement().getIdPart()), session.getPatientId(), session.getEncounterId(), session.getPractitionerId(), session.getOrganizationId(), null, session.getUserLanguage(), session.getUserTaskContext(), session.getSetting(), session.getSettingContext());
                }
                if (result.getId() == null) {
                    logger.warn("ActivityDefinition {} returned resource with no id, setting one", action.getDefinition().getReferenceElement().getIdPart());
                    result.setId(UUID.randomUUID().toString());
                }
                session.getRequestGroupBuilder().buildContained(result).addAction(new RequestGroupActionBuilder().buildResource(new Reference("#" + result.getId())).build());
            } catch (Exception e) {
                logger.error("ERROR: ActivityDefinition {} could not be applied and threw exception {}", action.getDefinition(), e.toString());
            }
        }
    }
    return result;
}
Also used : RequestGroupActionBuilder(org.opencds.cqf.ruler.cr.dstu3.builder.RequestGroupActionBuilder) CarePlan(org.hl7.fhir.dstu3.model.CarePlan) Reference(org.hl7.fhir.dstu3.model.Reference) DomainResource(org.hl7.fhir.dstu3.model.DomainResource) Resource(org.hl7.fhir.dstu3.model.Resource) IOException(java.io.IOException) IOException(java.io.IOException) FHIRException(org.hl7.fhir.exceptions.FHIRException) IdType(org.hl7.fhir.dstu3.model.IdType) ActivityDefinition(org.hl7.fhir.dstu3.model.ActivityDefinition)

Example 37 with Group

use of org.hl7.fhir.r4.model.Group in project cqf-ruler by DBCG.

the class Session method applyPlanDefinition.

@Operation(name = "$apply", idempotent = true, type = PlanDefinition.class)
public CarePlan applyPlanDefinition(RequestDetails theRequest, @IdParam IdType theId, @OperationParam(name = "patient") String patientId, @OperationParam(name = "encounter") String encounterId, @OperationParam(name = "practitioner") String practitionerId, @OperationParam(name = "organization") String organizationId, @OperationParam(name = "userType") String userType, @OperationParam(name = "userLanguage") String userLanguage, @OperationParam(name = "userTaskContext") String userTaskContext, @OperationParam(name = "setting") String setting, @OperationParam(name = "settingContext") String settingContext) throws IOException, FHIRException {
    PlanDefinition planDefinition = this.planDefinitionDao.read(theId);
    if (planDefinition == null) {
        throw new IllegalArgumentException("Couldn't find PlanDefinition " + theId);
    }
    logger.info("Performing $apply operation on PlanDefinition/{}", theId);
    CarePlanBuilder builder = new CarePlanBuilder();
    builder.buildDefinition(new Reference(planDefinition.getIdElement().getIdPart())).buildSubject(new Reference(patientId)).buildStatus(CarePlan.CarePlanStatus.DRAFT);
    if (encounterId != null)
        builder.buildContext(new Reference(encounterId));
    if (practitionerId != null)
        builder.buildAuthor(new Reference(practitionerId));
    if (organizationId != null)
        builder.buildAuthor(new Reference(organizationId));
    if (userLanguage != null)
        builder.buildLanguage(userLanguage);
    // Each Group of actions shares a RequestGroup
    RequestGroupBuilder requestGroupBuilder = new RequestGroupBuilder().buildStatus().buildIntent();
    Session session = new Session(planDefinition, builder, patientId, encounterId, practitionerId, organizationId, userType, userLanguage, userTaskContext, setting, settingContext, requestGroupBuilder);
    return (CarePlan) ContainedHelper.liftContainedResourcesToParent(resolveActions(theRequest, session));
}
Also used : CarePlan(org.hl7.fhir.dstu3.model.CarePlan) CarePlanBuilder(org.opencds.cqf.ruler.cr.dstu3.builder.CarePlanBuilder) Reference(org.hl7.fhir.dstu3.model.Reference) RequestGroupBuilder(org.opencds.cqf.ruler.cr.dstu3.builder.RequestGroupBuilder) PlanDefinition(org.hl7.fhir.dstu3.model.PlanDefinition) Operation(ca.uhn.fhir.rest.annotation.Operation)

Example 38 with Group

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

the class MeasureTestBase method getCohortMeasure.

public Measure getCohortMeasure(String measureName, Library library, String expression) throws Exception {
    Measure measure = getTemplateMeasure(measureName, library, MeasureScoring.COHORT);
    Measure.MeasureGroupComponent group = new Measure.MeasureGroupComponent();
    addPopulations(group, Collections.singletonMap(MeasurePopulationType.INITIALPOPULATION, expression));
    measure.addGroup(group);
    return measure;
}
Also used : Measure(org.hl7.fhir.r4.model.Measure)

Example 39 with Group

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

the class MeasureTestBase method getProportionMeasure.

public Measure getProportionMeasure(String measureName, Library library, Map<MeasurePopulationType, String> expressionsByPopType) throws Exception {
    Measure measure = getTemplateMeasure(measureName, library, MeasureScoring.PROPORTION);
    Measure.MeasureGroupComponent group = new Measure.MeasureGroupComponent();
    addPopulations(group, expressionsByPopType);
    measure.addGroup(group);
    return measure;
}
Also used : Measure(org.hl7.fhir.r4.model.Measure)

Example 40 with Group

use of org.hl7.fhir.r4.model.Group 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

Test (org.junit.Test)106 Group (org.hl7.fhir.r4.model.Group)74 MockHttpServletResponse (org.springframework.mock.web.MockHttpServletResponse)59 ArrayList (java.util.ArrayList)57 BaseFhirIntegrationTest (org.openmrs.module.fhir2.BaseFhirIntegrationTest)50 Group (org.hl7.fhir.dstu3.model.Group)44 FHIRException (org.hl7.fhir.exceptions.FHIRException)37 Cohort (org.openmrs.Cohort)32 Test (org.junit.jupiter.api.Test)29 InputStream (java.io.InputStream)21 Reference (org.hl7.fhir.r4.model.Reference)21 List (java.util.List)16 Complex (org.hl7.fhir.dstu2016may.formats.RdfGenerator.Complex)16 DefinitionException (org.hl7.fhir.exceptions.DefinitionException)16 Coding (org.hl7.fhir.r4.model.Coding)16 Diagnosis (gov.cms.bfd.server.war.commons.Diagnosis)15 IOException (java.io.IOException)13 IdType (org.hl7.fhir.dstu3.model.IdType)13 OperationOutcome (org.hl7.fhir.r4.model.OperationOutcome)13 Complex (org.hl7.fhir.r4.utils.formats.Turtle.Complex)13