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;
}
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));
}
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;
}
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;
}
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;
}
Aggregations