org.openmrs.module.kenyaemr.calculation.library.hiv.art.PatientPreArtOutComeCalculation.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.kenyaemr.calculation.library.hiv.art.PatientPreArtOutComeCalculation.java

Source

/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.module.kenyaemr.calculation.library.hiv.art;

import org.joda.time.DateTime;
import org.joda.time.Days;
import org.openmrs.Concept;
import org.openmrs.Encounter;
import org.openmrs.Obs;
import org.openmrs.PatientProgram;
import org.openmrs.Program;
import org.openmrs.Visit;
import org.openmrs.api.context.Context;
import org.openmrs.calculation.patient.PatientCalculationContext;
import org.openmrs.calculation.result.CalculationResultMap;
import org.openmrs.calculation.result.SimpleResult;
import org.openmrs.module.kenyacore.CoreUtils;
import org.openmrs.module.kenyacore.calculation.AbstractPatientCalculation;
import org.openmrs.module.kenyacore.calculation.CalculationUtils;
import org.openmrs.module.kenyacore.calculation.Calculations;
import org.openmrs.module.kenyacore.calculation.Filters;
import org.openmrs.module.kenyaemr.Dictionary;
import org.openmrs.module.kenyaemr.HivConstants;
import org.openmrs.module.kenyaemr.calculation.EmrCalculationUtils;
import org.openmrs.module.kenyaemr.calculation.library.rdqa.DateOfDeathCalculation;
import org.openmrs.module.kenyaemr.metadata.HivMetadata;
import org.openmrs.module.metadatadeploy.MetadataUtils;
import org.openmrs.module.reporting.common.DateUtil;
import org.openmrs.module.reporting.common.DurationUnit;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * Calculate possible patient outcomes at the end of the cohort period
 */
public class PatientPreArtOutComeCalculation extends AbstractPatientCalculation {

    @Override
    public CalculationResultMap evaluate(Collection<Integer> cohort, Map<String, Object> params,
            PatientCalculationContext context) {

        Integer outcomePeriod = (params != null && params.containsKey("outcomePeriod"))
                ? (Integer) params.get("outcomePeriod")
                : null;

        Program hivProgram = MetadataUtils.existing(Program.class, HivMetadata._Program.HIV);

        CalculationResultMap enrolledHere = Calculations.firstEnrollments(hivProgram, cohort, context);

        if (outcomePeriod != null) {
            context.setNow(DateUtil.adjustDate(context.getNow(), outcomePeriod, DurationUnit.MONTHS));
        }

        CalculationResultMap onART = calculate(new InitialArtStartDateCalculation(), cohort, context);
        CalculationResultMap deadPatients = calculate(new DateOfDeathCalculation(), cohort, context);
        CalculationResultMap transferredOut = calculate(new TransferOutDateCalculation(), cohort, context);
        CalculationResultMap defaulted = defaultedMap(cohort, context, outcomePeriod);
        CalculationResultMap ltfu = ltfuMap(cohort, context, outcomePeriod);

        CalculationResultMap ret = new CalculationResultMap();

        for (Integer ptId : cohort) {
            String status = "Alive and not on ART";
            Date dateLost = null;
            TreeMap<Date, String> preArtOutcomes = new TreeMap<Date, String>();

            PatientProgram patientProgramDate = EmrCalculationUtils.resultForPatient(enrolledHere, ptId);

            if (patientProgramDate != null && outcomePeriod != null) {
                Date initialArtStart = EmrCalculationUtils.datetimeResultForPatient(onART, ptId);
                Date dod = EmrCalculationUtils.datetimeResultForPatient(deadPatients, ptId);
                Date dateTo = EmrCalculationUtils.datetimeResultForPatient(transferredOut, ptId);
                Date defaultedDate = EmrCalculationUtils.datetimeResultForPatient(defaulted, ptId);
                Date classifiedLTFU = EmrCalculationUtils.datetimeResultForPatient(ltfu, ptId);
                if (classifiedLTFU != null) {
                    dateLost = classifiedLTFU;
                }
                //get future date that would be used as a limit
                Date futureDate = DateUtil.adjustDate(DateUtil.adjustDate(patientProgramDate.getDateEnrolled(),
                        outcomePeriod, DurationUnit.MONTHS), 1, DurationUnit.DAYS);

                //start looping through to get outcomes
                if (initialArtStart != null && initialArtStart.before(futureDate)
                        && initialArtStart.after(patientProgramDate.getDateEnrolled())) {
                    preArtOutcomes.put(initialArtStart, "Initiated ART");
                }

                if (dod != null && dateTo != null && dod.before(dateTo) && dod.before(futureDate)
                        && dod.after(patientProgramDate.getDateEnrolled())) {
                    preArtOutcomes.put(dod, "Died");
                }
                if (dod != null && dateTo != null && dateTo.before(dod) && dateTo.before(futureDate)
                        && dateTo.after(patientProgramDate.getDateEnrolled())) {
                    preArtOutcomes.put(dateTo, "Transferred out");
                }

                if (dod != null && dod.before(futureDate) && dod.after(patientProgramDate.getDateEnrolled())) {
                    preArtOutcomes.put(dod, "Died");
                }
                try {
                    if (dateTo != null && dateTo.before(futureDate)
                            && (dateTo.after(patientProgramDate.getDateEnrolled())
                                    || dateOnlyDate(dateTo.toString()).equals(
                                            dateOnlyDate(patientProgramDate.getDateEnrolled().toString())))) {
                        preArtOutcomes.put(dateTo, "Transferred out");
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                if (defaultedDate != null && dateLost != null && defaultedDate.before(dateLost)
                        && defaultedDate.before(futureDate)
                        && defaultedDate.after(patientProgramDate.getDateEnrolled())) {
                    preArtOutcomes.put(defaultedDate, "Defaulted");
                }

                if (defaultedDate != null && dateLost != null && dateLost.before(defaultedDate)
                        && dateLost.before(futureDate) && dateLost.after(patientProgramDate.getDateEnrolled())
                        && dateLost.before(new Date())) {
                    preArtOutcomes.put(dateLost, "LTFU");
                }
                if (defaultedDate != null && defaultedDate.before(futureDate)
                        && defaultedDate.after(patientProgramDate.getDateEnrolled())
                        && defaultedDate.before(new Date())) {
                    preArtOutcomes.put(defaultedDate, "Defaulted");
                }

                if (dateLost != null && dateLost.before(futureDate)
                        && dateLost.after(patientProgramDate.getDateEnrolled()) && dateLost.before(new Date())) {
                    preArtOutcomes.put(dateLost, "LTFU");
                }
                if (initialArtStart != null && dateTo != null) {
                    preArtOutcomes.remove(initialArtStart);
                }
                //pick the last item in the tree map
                //check first if it is null
                if (preArtOutcomes.size() > 0) {
                    Map.Entry<Date, String> values = preArtOutcomes.lastEntry();
                    if (values != null) {
                        status = values.getValue();
                    }
                    if (preArtOutcomes.containsValue("Transferred out")) {
                        status = "Transferred out";
                    }
                    if (preArtOutcomes.containsValue("Died")) {
                        status = "Died";
                    }
                    if (preArtOutcomes.containsValue("Initiated ART")) {
                        status = "Initiated ART";
                    }
                }
                ret.put(ptId, new SimpleResult(status, this));
            }

        }
        return ret;
    }

    CalculationResultMap ltfuMap(Collection<Integer> cohort, PatientCalculationContext context, Integer period) {
        CalculationResultMap ret = new CalculationResultMap();
        CalculationResultMap resultMap = returnVisitDate(cohort, context, period);
        Set<Integer> isTransferOut = CalculationUtils
                .patientsThatPass(calculate(new IsTransferOutCalculation(), cohort, context));
        for (Integer ptId : cohort) {
            Date dateLost = null;
            SimpleResult lastScheduledReturnDateResults = (SimpleResult) resultMap.get(ptId);
            Date lastScheduledReturnDate = (Date) lastScheduledReturnDateResults.getValue();
            if (lastScheduledReturnDate != null && !(isTransferOut.contains(ptId))) {
                dateLost = DateUtil.adjustDate(lastScheduledReturnDate,
                        HivConstants.LOST_TO_FOLLOW_UP_THRESHOLD_DAYS, DurationUnit.DAYS);
            }
            ret.put(ptId, new SimpleResult(dateLost, this));
        }
        return ret;
    }

    CalculationResultMap returnVisitDate(Collection<Integer> cohort, PatientCalculationContext context,
            Integer period) {
        CalculationResultMap ret = new CalculationResultMap();

        Program hivProgram = MetadataUtils.existing(Program.class, HivMetadata._Program.HIV);
        CalculationResultMap enrolledHere = Calculations.firstEnrollments(hivProgram, cohort, context);
        CalculationResultMap dateLastSeen = dateLastSeen(cohort, context);

        Set<Integer> alive = Filters.alive(cohort, context);
        Concept RETURN_VISIT_DATE = Dictionary.getConcept(Dictionary.RETURN_VISIT_DATE);
        Set<Integer> transferredOut = CalculationUtils
                .patientsThatPass(calculate(new IsTransferOutCalculation(), cohort, context));
        for (Integer ptId : cohort) {
            PatientProgram patientProgram = EmrCalculationUtils.resultForPatient(enrolledHere, ptId);
            Date returnVisitDate = null;
            List<Visit> allVisits = Context.getVisitService()
                    .getVisitsByPatient(Context.getPatientService().getPatient(ptId));
            Date lastSeenDate = EmrCalculationUtils.datetimeResultForPatient(dateLastSeen, ptId);
            List<Visit> requiredVisits = new ArrayList<Visit>();
            if (alive.contains(ptId) && !(transferredOut.contains(ptId)) && period != null
                    && patientProgram != null) {
                Date futureDate = DateUtil.adjustDate(
                        DateUtil.adjustDate(patientProgram.getDateEnrolled(), period, DurationUnit.MONTHS), 1,
                        DurationUnit.DAYS);
                for (Visit visit : allVisits) {
                    if (visit.getStartDatetime().before(futureDate)) {
                        requiredVisits.add(visit);
                    }
                }
                if (requiredVisits.size() > 0) {

                    //pick the last visit
                    Set<Encounter> lastVisitEncounters = requiredVisits.get(0).getEncounters();
                    if (lastVisitEncounters.size() > 0) {
                        Set<Obs> allObs;
                        for (Encounter encounter : lastVisitEncounters) {
                            allObs = encounter.getAllObs();
                            for (Obs obs : allObs) {
                                if (obs.getConcept().equals(RETURN_VISIT_DATE)) {
                                    returnVisitDate = obs.getValueDatetime();
                                    break;
                                }
                            }
                        }
                        if (returnVisitDate != null && lastSeenDate != null
                                && returnVisitDate.before(lastSeenDate)) {
                            returnVisitDate = null;

                        }
                    }

                    if (returnVisitDate == null && requiredVisits.size() > 1) {
                        Date lastVisitDate = requiredVisits.get(0).getStartDatetime();
                        Date priorVisitDate1 = requiredVisits.get(1).getStartDatetime();
                        int dayDiff = daysBetweenDates(lastVisitDate, priorVisitDate1);
                        //get the prior visit
                        Set<Encounter> priorVisitEncounters = requiredVisits.get(1).getEncounters();
                        Date priorReturnDate1 = null;
                        if (priorVisitEncounters.size() > 0) {
                            Set<Obs> allObs;
                            for (Encounter encounter : priorVisitEncounters) {
                                allObs = encounter.getAllObs();
                                for (Obs obs : allObs) {
                                    if (obs.getConcept().equals(RETURN_VISIT_DATE)) {
                                        priorReturnDate1 = obs.getValueDatetime();
                                        break;
                                    }
                                }
                            }
                            if (priorReturnDate1 != null) {
                                returnVisitDate = DateUtil.adjustDate(priorReturnDate1, dayDiff, DurationUnit.DAYS);
                            }
                        }
                        if (returnVisitDate != null && lastSeenDate != null
                                && returnVisitDate.before(lastSeenDate)) {
                            returnVisitDate = DateUtil.adjustDate(lastSeenDate, 30, DurationUnit.DAYS);
                        }
                    }

                }
                if (returnVisitDate == null) {
                    returnVisitDate = DateUtil.adjustDate(lastSeenDate, 30, DurationUnit.DAYS);
                }
            }
            ret.put(ptId, new SimpleResult(returnVisitDate, this));
        }
        return ret;
    }

    CalculationResultMap defaultedMap(Collection<Integer> cohort, PatientCalculationContext context,
            Integer period) {
        CalculationResultMap ret = new CalculationResultMap();
        CalculationResultMap resultMap = returnVisitDate(cohort, context, period);
        Set<Integer> isTransferOut = CalculationUtils
                .patientsThatPass(calculate(new IsTransferOutCalculation(), cohort, context));
        for (Integer ptId : cohort) {
            Date dateDefaulted = null;
            SimpleResult lastScheduledReturnDateResults = (SimpleResult) resultMap.get(ptId);
            if (lastScheduledReturnDateResults != null) {
                Date lastScheduledReturnDate = (Date) lastScheduledReturnDateResults.getValue();
                if (lastScheduledReturnDate != null && !(isTransferOut.contains(ptId))) {
                    dateDefaulted = CoreUtils.dateAddDays(lastScheduledReturnDate, 30);
                }
            }

            ret.put(ptId, new SimpleResult(dateDefaulted, this));
        }
        return ret;
    }

    Date dateOnlyDate(String string) throws ParseException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return dateFormat.parse(string);

    }

    CalculationResultMap dateLastSeen(Collection<Integer> cohort, PatientCalculationContext context) {
        Program hivProgram = MetadataUtils.existing(Program.class, HivMetadata._Program.HIV);
        CalculationResultMap dateEnrolledMap = Calculations.firstEnrollments(hivProgram, cohort, context);

        CalculationResultMap lastEncounter = Calculations.lastEncounter(null, cohort, context);
        CalculationResultMap initialArtStart = calculate(new InitialArtStartDateCalculation(), cohort, context);

        CalculationResultMap result = new CalculationResultMap();
        for (Integer ptId : cohort) {
            Encounter encounter = EmrCalculationUtils.encounterResultForPatient(lastEncounter, ptId);
            PatientProgram patientProgram = EmrCalculationUtils.resultForPatient(dateEnrolledMap, ptId);
            Date artStartDate = EmrCalculationUtils.datetimeResultForPatient(initialArtStart, ptId);
            Date encounterDate = null;
            if (patientProgram != null) {
                if (encounter != null) {

                    if (artStartDate != null && artStartDate.after(encounter.getEncounterDatetime())) {
                        encounterDate = artStartDate;
                    } else {
                        encounterDate = encounter.getEncounterDatetime();
                    }
                }
                if (encounterDate == null && artStartDate != null) {
                    encounterDate = artStartDate;
                }

                if (encounterDate == null) {
                    encounterDate = patientProgram.getDateEnrolled();
                }
            }
            result.put(ptId, new SimpleResult(encounterDate, this));
        }
        return result;
    }

    int daysBetweenDates(Date d1, Date d2) {
        DateTime dateTime1 = new DateTime(d1.getTime());
        DateTime dateTime2 = new DateTime(d2.getTime());
        return Math.abs(Days.daysBetween(dateTime1, dateTime2).getDays());
    }

}