Advertisement
Guest User

my groovy file

a guest
Jul 16th, 2018
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Groovy 20.74 KB | None | 0 0
  1. import org.apache.commons.lang.StringUtils
  2. import org.hibernate.Query
  3. import org.hibernate.SessionFactory;
  4. import org.openmrs.Obs;
  5. import org.openmrs.Patient;
  6. import org.openmrs.Concept;
  7. import org.openmrs.Encounter;
  8. import org.openmrs.module.bahmniemrapi.encountertransaction.contract.BahmniObservation
  9. import org.openmrs.util.OpenmrsUtil;
  10. import org.openmrs.api.context.Context;
  11. import org.openmrs.module.bahmniemrapi.obscalculator.ObsValueCalculator;
  12. import org.openmrs.module.bahmniemrapi.encountertransaction.contract.BahmniEncounterTransaction
  13. import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction;
  14.  
  15. import org.joda.time.LocalDate;
  16. import org.joda.time.Months;
  17.  
  18. public class BahmniObsValueCalculator implements ObsValueCalculator {
  19.  
  20.     static Double BMI_VERY_SEVERELY_UNDERWEIGHT = 16.0;
  21.     static Double BMI_SEVERELY_UNDERWEIGHT = 17.0;
  22.     static Double BMI_UNDERWEIGHT = 18.5;
  23.     static Double BMI_NORMAL = 25.0;
  24.     static Double BMI_OVERWEIGHT = 30.0;
  25.     static Double BMI_OBESE = 35.0;
  26.     static Double BMI_SEVERELY_OBESE = 40.0;
  27.     static Double ZERO = 0.0;
  28.     static Map<BahmniObservation, BahmniObservation> obsParentMap = new HashMap<BahmniObservation, BahmniObservation>();
  29.  
  30.     public static enum BmiStatus {
  31.         VERY_SEVERELY_UNDERWEIGHT("Very Severely Underweight"),
  32.         SEVERELY_UNDERWEIGHT("Severely Underweight"),
  33.         UNDERWEIGHT("Underweight"),
  34.         NORMAL("Normal"),
  35.         OVERWEIGHT("Overweight"),
  36.         OBESE("Obese"),
  37.         SEVERELY_OBESE("Severely Obese"),
  38.         VERY_SEVERELY_OBESE("Very Severely Obese");
  39.  
  40.         private String status;
  41.  
  42.         BmiStatus(String status) {
  43.             this.status = status
  44.         }
  45.  
  46.         @Override
  47.         public String toString() {
  48.             return status;
  49.         }
  50.     }
  51.  
  52.  
  53.     public void run(BahmniEncounterTransaction bahmniEncounterTransaction) {
  54.         calculateAndAdd(bahmniEncounterTransaction);
  55.         calculateDiffOffSurgTimeInAndTimeOut(bahmniEncounterTransaction);
  56.         def file11 = new File(OpenmrsUtil.getApplicationDataDirectory() + "obscalculator/groovy_debug.txt")
  57.         file11.append '\ndebugging statement:';
  58.     }
  59.     static def calculateDiffOffSurgTimeInAndTimeOut(bahmniEncounterTransaction bahmniEncounterTransaction){
  60.         Collection<BahmniObservation> observations = bahmniEncounterTransaction.getObservations()
  61.         BahmniObservation surgicalTimeInObservation = find("Surgical Time In", observations, null);
  62.         BahmniObservation surgicalTimeOutObservation = find("Surgical Time Out", observations, null);
  63.         BahmniObservation surgicalTotalTimeObservation = find("Surgical Total Time", observations, null);
  64.         if(!hasValueDate(surgicalTimeInObservation)|| !hasValueDate(surgicalTimeOutObservation)){
  65.             return
  66.         }
  67.  
  68.         def duration = groovy.time.TimeCategory.minus(
  69.           new Date(surgicalTimeOutObservation.getValue()),
  70.           new Date(surgicalTimeInObservation.getValue())
  71.           );
  72.         def values = [
  73.         "min: " + duration.minutes,
  74.         "hours: " + duration.hours,
  75.         "days: " + duration.days,
  76.         "ago: " + duration.ago,
  77.         ];
  78.         surgicalTotalTimeObservation.setValue(values);
  79.         def file11 = new File(OpenmrsUtil.getApplicationDataDirectory() + "obscalculator/groovy_debug.txt")
  80.         file11.append '\ndebugging statement:'+" "+values;
  81.         return;
  82.     }
  83.  
  84.     static def calculateAndAdd(BahmniEncounterTransaction bahmniEncounterTransaction) {
  85.         Collection<BahmniObservation> observations = bahmniEncounterTransaction.getObservations()
  86.         def nowAsOfEncounter = bahmniEncounterTransaction.getEncounterDateTime() != null ? bahmniEncounterTransaction.getEncounterDateTime() : new Date();
  87.  
  88.         BahmniObservation heightObservation = find("Height", observations, null)
  89.         BahmniObservation weightObservation = find("Weight", observations, null)
  90.         BahmniObservation parent = null;
  91.  
  92.         if (hasValue(heightObservation) || hasValue(weightObservation)) {
  93.             def heightObs = null, weightObs = null;
  94.             Encounter encounter = Context.getEncounterService().getEncounterByUuid(bahmniEncounterTransaction.getEncounterUuid());
  95.             if (encounter != null) {
  96.                 Set<Obs> latestObsOfEncounter = encounter.getObsAtTopLevel(true);
  97.                 latestObsOfEncounter.each { Obs latestObs ->
  98.                     for (Obs groupMember : latestObs.groupMembers) {
  99.                         heightObs = heightObs ? heightObs : (groupMember.concept.getName().name.equalsIgnoreCase("HEIGHT") ? groupMember : null);
  100.                         weightObs = weightObs ? weightObs : (groupMember.concept.getName().name.equalsIgnoreCase("WEIGHT") ? groupMember : null);
  101.                     }
  102.                 }
  103.                 if (isSameObs(heightObservation, heightObs) && isSameObs(weightObservation, weightObs)) {
  104.                     return;
  105.                 }
  106.             }
  107.  
  108.  
  109.             BahmniObservation bmiDataObservation = find("BMI Data", observations, null)
  110.             BahmniObservation bmiObservation = find("BMI", bmiDataObservation ? [bmiDataObservation] : [], null)
  111.             BahmniObservation bmiAbnormalObservation = find("BMI Abnormal", bmiDataObservation ? [bmiDataObservation]: [], null)
  112.  
  113.             BahmniObservation bmiStatusDataObservation = find("BMI Status Data", observations, null)
  114.             BahmniObservation bmiStatusObservation = find("BMI Status", bmiStatusDataObservation ? [bmiStatusDataObservation] : [], null)
  115.             BahmniObservation bmiStatusAbnormalObservation = find("BMI Status Abnormal", bmiStatusDataObservation ? [bmiStatusDataObservation]: [], null)
  116.  
  117.             Patient patient = Context.getPatientService().getPatientByUuid(bahmniEncounterTransaction.getPatientUuid())
  118.             def patientAgeInMonthsAsOfEncounter = Months.monthsBetween(new LocalDate(patient.getBirthdate()), new LocalDate(nowAsOfEncounter)).getMonths()
  119.  
  120.             parent = obsParent(heightObservation, parent)
  121.             parent = obsParent(weightObservation, parent)
  122.  
  123.             if ((heightObservation && heightObservation.voided) && (weightObservation && weightObservation.voided)) {
  124.                 voidObs(bmiDataObservation);
  125.                 voidObs(bmiObservation);
  126.                 voidObs(bmiStatusDataObservation);
  127.                 voidObs(bmiStatusObservation);
  128.                 voidObs(bmiAbnormalObservation);
  129.                 return
  130.             }
  131.  
  132.             def previousHeightValue = fetchLatestValue("Height", bahmniEncounterTransaction.getPatientUuid(), heightObservation, nowAsOfEncounter)
  133.             def previousWeightValue = fetchLatestValue("Weight", bahmniEncounterTransaction.getPatientUuid(), weightObservation, nowAsOfEncounter)
  134.  
  135.             Double height = hasValue(heightObservation) && !heightObservation.voided ? heightObservation.getValue() as Double : previousHeightValue
  136.             Double weight = hasValue(weightObservation) && !weightObservation.voided ? weightObservation.getValue() as Double : previousWeightValue
  137.             Date obsDatetime = getDate(weightObservation) != null ? getDate(weightObservation) : getDate(heightObservation)
  138.  
  139.             if (height == null || weight == null) {
  140.                 voidObs(bmiDataObservation)
  141.                 voidObs(bmiObservation)
  142.                 voidObs(bmiStatusDataObservation)
  143.                 voidObs(bmiStatusObservation)
  144.                 voidObs(bmiAbnormalObservation)
  145.                 return
  146.             }
  147.  
  148.             if(encounter != null) {
  149.                 voidPreviousBMIObs(encounter.getObsAtTopLevel(false));
  150.                 voidPreviousBMIObs(encounter.getObs());
  151.             }
  152.  
  153.             bmiDataObservation = bmiDataObservation ?: createObs("BMI Data", null, bahmniEncounterTransaction, obsDatetime) as BahmniObservation
  154.             bmiStatusDataObservation = bmiStatusDataObservation ?: createObs("BMI Status Data", null, bahmniEncounterTransaction, obsDatetime) as BahmniObservation
  155.  
  156.             def bmi = bmi(height, weight)
  157.             bmiObservation = bmiObservation ?: createObs("BMI", bmiDataObservation, bahmniEncounterTransaction, obsDatetime) as BahmniObservation;
  158.             bmiObservation.setValue(bmi);
  159.  
  160.             def bmiStatus = bmiStatus(bmi, patientAgeInMonthsAsOfEncounter, patient.getGender());
  161.             bmiStatusObservation = bmiStatusObservation ?: createObs("BMI Status", bmiStatusDataObservation, bahmniEncounterTransaction, obsDatetime) as BahmniObservation;
  162.             bmiStatusObservation.setValue(bmiStatus);
  163.  
  164.             def bmiAbnormal = bmiAbnormal(bmiStatus);
  165.             bmiAbnormalObservation =  bmiAbnormalObservation ?: createObs("BMI Abnormal", bmiDataObservation, bahmniEncounterTransaction, obsDatetime) as BahmniObservation;
  166.             bmiAbnormalObservation.setValue(bmiAbnormal);
  167.  
  168.             bmiStatusAbnormalObservation =  bmiStatusAbnormalObservation ?: createObs("BMI Status Abnormal", bmiStatusDataObservation, bahmniEncounterTransaction, obsDatetime) as BahmniObservation;
  169.             bmiStatusAbnormalObservation.setValue(bmiAbnormal);
  170.  
  171.             return
  172.         }
  173.  
  174.         BahmniObservation waistCircumferenceObservation = find("Waist Circumference", observations, null)
  175.         BahmniObservation hipCircumferenceObservation = find("Hip Circumference", observations, null)
  176.         if (hasValue(waistCircumferenceObservation) && hasValue(hipCircumferenceObservation)) {
  177.             def calculatedConceptName = "Waist/Hip Ratio"
  178.             BahmniObservation calculatedObs = find(calculatedConceptName, observations, null)
  179.             parent = obsParent(waistCircumferenceObservation, null)
  180.  
  181.             Date obsDatetime = getDate(waistCircumferenceObservation)
  182.             def waistCircumference = waistCircumferenceObservation.getValue() as Double
  183.             def hipCircumference = hipCircumferenceObservation.getValue() as Double
  184.             def waistByHipRatio = waistCircumference/hipCircumference
  185.             if (calculatedObs == null)
  186.                 calculatedObs = createObs(calculatedConceptName, parent, bahmniEncounterTransaction, obsDatetime) as BahmniObservation
  187.  
  188.             calculatedObs.setValue(waistByHipRatio)
  189.             return
  190.         }
  191.  
  192.         BahmniObservation lmpObservation = find("Obstetrics, Last Menstrual Period", observations, null)
  193.         def calculatedConceptName = "Estimated Date of Delivery"
  194.         if (hasValue(lmpObservation)) {
  195.             parent = obsParent(lmpObservation, null)
  196.             def calculatedObs = find(calculatedConceptName, observations, null)
  197.  
  198.             Date obsDatetime = getDate(lmpObservation)
  199.  
  200.             LocalDate edd = new LocalDate(lmpObservation.getValue()).plusMonths(9).plusWeeks(1)
  201.             if (calculatedObs == null)
  202.                 calculatedObs = createObs(calculatedConceptName, parent, bahmniEncounterTransaction, obsDatetime) as BahmniObservation
  203.             calculatedObs.setValue(edd)
  204.             return
  205.         } else {
  206.             def calculatedObs = find(calculatedConceptName, observations, null)
  207.             if (hasValue(calculatedObs)) {
  208.                 voidObs(calculatedObs)
  209.             }
  210.         }
  211.     }
  212.  
  213.     private static BahmniObservation obsParent(BahmniObservation child, BahmniObservation parent) {
  214.         if (parent != null) return parent;
  215.  
  216.         if(child != null) {
  217.             return obsParentMap.get(child)
  218.         }
  219.     }
  220.  
  221.     private static Date getDate(BahmniObservation observation) {
  222.         return hasValue(observation) && !observation.voided ? observation.getObservationDateTime() : null;
  223.     }
  224.  
  225.     private static boolean isSameObs(BahmniObservation observation, Obs editedObs) {
  226.         if(observation && editedObs) {
  227.             return  (editedObs.uuid == observation.encounterTransactionObservation.uuid && editedObs.valueNumeric == observation.value);
  228.         } else if(observation == null && editedObs == null) {
  229.             return true;
  230.         }
  231.         return false;
  232.     }
  233.  
  234.     private static boolean hasValue(BahmniObservation observation) {
  235.         return observation != null && observation.getValue() != null && !StringUtils.isEmpty(observation.getValue().toString());
  236.     }
  237.     private static boolean hasValueDate(BahmniObservation observation) {
  238.         return observation != null && observation.getValue() != null;
  239.     }
  240.  
  241.     private static void voidObs(BahmniObservation bmiObservation) {
  242.         if (hasValue(bmiObservation)) {
  243.             bmiObservation.voided = true
  244.         }
  245.     }
  246.  
  247.     private static void voidPreviousBMIObs(Set<Obs> bmiObs) {
  248.         if(bmiObs) {
  249.             bmiObs.each { Obs obs ->
  250.                 Concept concept = Context.getConceptService().getConceptByUuid(obs.getConcept().uuid);
  251.                 if (concept.getName().name.equalsIgnoreCase("BMI Data") || concept.getName().name.equalsIgnoreCase("BMI") ||
  252.                         concept.getName().name.equalsIgnoreCase("BMI ABNORMAL") || concept.getName().name.equalsIgnoreCase("BMI Status Data")
  253.                         || concept.getName().name.equalsIgnoreCase("BMI STATUS") || concept.getName().name.equalsIgnoreCase("BMI STATUS ABNORMAL")) {
  254.  
  255.                     obs.voided = true;
  256.                     obs.setVoidReason("Replaced with a new one because it was changed");
  257.                     Context.getObsService().saveObs(obs, "Replaced with a new one because it was changed");
  258.                 }
  259.             }
  260.         }
  261.     }
  262.  
  263.     static BahmniObservation createObs(String conceptName, BahmniObservation parent, BahmniEncounterTransaction encounterTransaction, Date obsDatetime) {
  264.         def concept = Context.getConceptService().getConceptByName(conceptName)
  265.         BahmniObservation newObservation = new BahmniObservation()
  266.         newObservation.setConcept(new EncounterTransaction.Concept(concept.getUuid(), conceptName))
  267.         newObservation.setObservationDateTime(obsDatetime);
  268.         parent == null ? encounterTransaction.addObservation(newObservation) : parent.addGroupMember(newObservation)
  269.         return newObservation
  270.     }
  271.  
  272.     static def bmi(Double height, Double weight) {
  273.         if (height == ZERO) {
  274.             throw new IllegalArgumentException("Please enter Height greater than zero")
  275.         } else if (weight == ZERO) {
  276.             throw new IllegalArgumentException("Please enter Weight greater than zero")
  277.         }
  278.         Double heightInMeters = height / 100;
  279.         Double value = weight / (heightInMeters * heightInMeters);
  280.         return new BigDecimal(value).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
  281.     };
  282.  
  283.     static def bmiStatus(Double bmi, Integer ageInMonth, String gender) {
  284.         BMIChart bmiChart = readCSV(OpenmrsUtil.getApplicationDataDirectory() + "obscalculator/BMI_chart.csv");
  285.         def bmiChartLine = bmiChart.get(gender, ageInMonth);
  286.         if(bmiChartLine != null ) {
  287.             return bmiChartLine.getStatus(bmi);
  288.         }
  289.  
  290.         if (bmi < BMI_VERY_SEVERELY_UNDERWEIGHT) {
  291.             return BmiStatus.VERY_SEVERELY_UNDERWEIGHT;
  292.         }
  293.         if (bmi < BMI_SEVERELY_UNDERWEIGHT) {
  294.             return BmiStatus.SEVERELY_UNDERWEIGHT;
  295.         }
  296.         if (bmi < BMI_UNDERWEIGHT) {
  297.             return BmiStatus.UNDERWEIGHT;
  298.         }
  299.         if (bmi < BMI_NORMAL) {
  300.             return BmiStatus.NORMAL;
  301.         }
  302.         if (bmi < BMI_OVERWEIGHT) {
  303.             return BmiStatus.OVERWEIGHT;
  304.         }
  305.         if (bmi < BMI_OBESE) {
  306.             return BmiStatus.OBESE;
  307.         }
  308.         if (bmi < BMI_SEVERELY_OBESE) {
  309.             return BmiStatus.SEVERELY_OBESE;
  310.         }
  311.         if (bmi >= BMI_SEVERELY_OBESE) {
  312.             return BmiStatus.VERY_SEVERELY_OBESE;
  313.         }
  314.         return null
  315.     }
  316.  
  317.     static def bmiAbnormal(BmiStatus status) {
  318.         return status != BmiStatus.NORMAL;
  319.     };
  320.  
  321.     static Double fetchLatestValue(String conceptName, String patientUuid, BahmniObservation excludeObs, Date tillDate) {
  322.         SessionFactory sessionFactory = Context.getRegisteredComponents(SessionFactory.class).get(0)
  323.         def excludedObsIsSaved = excludeObs != null && excludeObs.uuid != null
  324.         String excludeObsClause = excludedObsIsSaved ? " and obs.uuid != :excludeObsUuid" : ""
  325.         Query queryToGetObservations = sessionFactory.getCurrentSession()
  326.                 .createQuery("select obs " +
  327.                 " from Obs as obs, ConceptName as cn " +
  328.                 " where obs.person.uuid = :patientUuid " +
  329.                 " and cn.concept = obs.concept.conceptId " +
  330.                 " and cn.name = :conceptName " +
  331.                 " and obs.voided = false" +
  332.                 " and obs.obsDatetime <= :till" +
  333.                 excludeObsClause +
  334.                 " order by obs.obsDatetime desc ");
  335.         queryToGetObservations.setString("patientUuid", patientUuid);
  336.         queryToGetObservations.setParameterList("conceptName", conceptName);
  337.         queryToGetObservations.setParameter("till", tillDate);
  338.         if (excludedObsIsSaved) {
  339.             queryToGetObservations.setString("excludeObsUuid", excludeObs.uuid)
  340.         }
  341.         queryToGetObservations.setMaxResults(1);
  342.         List<Obs> observations = queryToGetObservations.list();
  343.         if (observations.size() > 0) {
  344.             return observations.get(0).getValueNumeric();
  345.         }
  346.         return null
  347.     }
  348.  
  349.     static BahmniObservation find(String conceptName, Collection<BahmniObservation> observations, BahmniObservation parent) {
  350.         for (BahmniObservation observation : observations) {
  351.             if (conceptName.equalsIgnoreCase(observation.getConcept().getName())) {
  352.                 obsParentMap.put(observation, parent);
  353.                 return observation;
  354.             }
  355.             BahmniObservation matchingObservation = find(conceptName, observation.getGroupMembers(), observation)
  356.             if (matchingObservation) return matchingObservation;
  357.         }
  358.         return null
  359.     }
  360.  
  361.     static BMIChart readCSV(String fileName) {
  362.         def chart = new BMIChart();
  363.         try {
  364.             new File(fileName).withReader { reader ->
  365.                 def header = reader.readLine();
  366.                 reader.splitEachLine(",") { tokens ->
  367.                     chart.add(new BMIChartLine(tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]));
  368.                 }
  369.             }
  370.         } catch (FileNotFoundException e) {
  371.         }
  372.         return chart;
  373.     }
  374.  
  375.     static class BMIChartLine {
  376.         public String gender;
  377.         public Integer ageInMonth;
  378.         public Double third;
  379.         public Double fifteenth;
  380.         public Double eightyFifth;
  381.         public Double ninetySeventh;
  382.  
  383.         BMIChartLine(String gender, String ageInMonth, String third, String fifteenth, String eightyFifth, String ninetySeventh) {
  384.             this.gender = gender
  385.             this.ageInMonth = ageInMonth.toInteger();
  386.             this.third = third.toDouble();
  387.             this.fifteenth = fifteenth.toDouble();
  388.             this.eightyFifth = eightyFifth.toDouble();
  389.             this.ninetySeventh = ninetySeventh.toDouble();
  390.         }
  391.  
  392.         public BmiStatus getStatus(Double bmi) {
  393.             if(bmi < third) {
  394.                 return BmiStatus.SEVERELY_UNDERWEIGHT
  395.             } else if(bmi < fifteenth) {
  396.                 return BmiStatus.UNDERWEIGHT
  397.             } else if(bmi < eightyFifth) {
  398.                 return BmiStatus.NORMAL
  399.             } else if(bmi < ninetySeventh) {
  400.                 return BmiStatus.OVERWEIGHT
  401.             } else {
  402.                 return BmiStatus.OBESE
  403.             }
  404.         }
  405.     }
  406.  
  407.     static class BMIChart {
  408.         List<BMIChartLine> lines;
  409.         Map<BMIChartLineKey, BMIChartLine> map = new HashMap<BMIChartLineKey, BMIChartLine>();
  410.  
  411.         public add(BMIChartLine line) {
  412.             def key = new BMIChartLineKey(line.gender, line.ageInMonth);
  413.             map.put(key, line);
  414.         }
  415.  
  416.         public BMIChartLine get(String gender, Integer ageInMonth) {
  417.             def key = new BMIChartLineKey(gender, ageInMonth);
  418.             return map.get(key);
  419.         }
  420.     }
  421.  
  422.     static class BMIChartLineKey {
  423.         public String gender;
  424.         public Integer ageInMonth;
  425.  
  426.         BMIChartLineKey(String gender, Integer ageInMonth) {
  427.             this.gender = gender
  428.             this.ageInMonth = ageInMonth
  429.         }
  430.  
  431.         boolean equals(o) {
  432.             if (this.is(o)) return true
  433.             if (getClass() != o.class) return false
  434.  
  435.             BMIChartLineKey bmiKey = (BMIChartLineKey) o
  436.  
  437.             if (ageInMonth != bmiKey.ageInMonth) return false
  438.             if (gender != bmiKey.gender) return false
  439.  
  440.             return true
  441.         }
  442.  
  443.         int hashCode() {
  444.             int result
  445.             result = (gender != null ? gender.hashCode() : 0)
  446.             result = 31 * result + (ageInMonth != null ? ageInMonth.hashCode() : 0)
  447.             return result
  448.         }
  449.     }
  450. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement