← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 1370: Changed from regresion to interpolation for dataentry history popup.

 

------------------------------------------------------------
revno: 1370
committer: Lars Helge Oeverland <larshelge@xxxxxxxxx>
branch nick: trunk
timestamp: Fri 2010-01-29 10:05:27 +0100
message:
  Changed from regresion to interpolation for dataentry history popup.
added:
  dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/ConversionUtilsTest.java
  dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/GetHistoryChartAction.java
modified:
  dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/chart/impl/DefaultChartService.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ConversionUtils.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/MathUtils.java
  dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/MathUtilsTest.java
  dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/StreamUtilsTest.java
  dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/org/hisp/dhis/de/i18n_module.properties
  dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/history.vm


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription.
=== modified file 'dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/chart/impl/DefaultChartService.java'
--- dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/chart/impl/DefaultChartService.java	2010-01-28 23:08:44 +0000
+++ dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/chart/impl/DefaultChartService.java	2010-01-29 09:05:27 +0000
@@ -33,14 +33,21 @@
 import static org.hisp.dhis.chart.Chart.TYPE_BAR;
 import static org.hisp.dhis.chart.Chart.TYPE_LINE;
 
+import static org.hisp.dhis.system.util.ConversionUtils.*;
+
 import java.awt.Color;
 import java.awt.Font;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import org.apache.commons.math.MathException;
+import org.apache.commons.math.analysis.SplineInterpolator;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.apache.commons.math.analysis.UnivariateRealInterpolator;
 import org.apache.commons.math.stat.regression.SimpleRegression;
 import org.hisp.dhis.chart.Chart;
 import org.hisp.dhis.chart.ChartService;
@@ -197,12 +204,14 @@
 
         MinMaxDataElement minMax = minMaxDataElementService.getMinMaxDataElement( organisationUnit, dataElement, categoryOptionCombo );
         
-        SimpleRegression regression = new SimpleRegression();
+        UnivariateRealInterpolator interpolator = new SplineInterpolator();
         
-        int periodCount = 0;
+        Integer periodCount = 0;
+        List<Double> x = new ArrayList<Double>();
+        List<Double> y = new ArrayList<Double>();
         
         // ---------------------------------------------------------------------
-        // DataSets
+        // DataValue, MinValue and MaxValue DataSets
         // ---------------------------------------------------------------------
 
         DefaultCategoryDataset dataValueDataSet = new DefaultCategoryDataset();
@@ -210,6 +219,8 @@
                 
         for ( Period period : periods )
         {
+            ++periodCount;
+            
             period.setName( format.formatPeriod( period ) );
             
             DataValue dataValue = dataValueService.getDataValue( organisationUnit, dataElement, period, categoryOptionCombo );
@@ -220,7 +231,8 @@
             {
                 value = Double.parseDouble( dataValue.getValue() );
                 
-                regression.addData( ++periodCount, value );
+                x.add( periodCount.doubleValue() );
+                y.add( value );
             }
             
             dataValueDataSet.addValue( value, dataElement.getShortName(), period.getName() );
@@ -231,12 +243,36 @@
                 metaDataSet.addValue( minMax.getMax(), "Max value", period.getName() );
             }
         }
-        
-        periodCount = 0;
-        
-        for ( Period period : periods )
+
+        // ---------------------------------------------------------------------
+        // Interpolation DataSet
+        // ---------------------------------------------------------------------
+
+        if ( x.size() >= 3 ) // minimum 3 data points required for interpolation
         {
-            metaDataSet.addValue( regression.predict( ++periodCount ), "Regression value", period.getName() );
+            periodCount = 0;
+
+            double[] xa = getArray( x );
+            
+            int min = MathUtils.getMin( xa ).intValue();
+            int max = MathUtils.getMax( xa ).intValue();
+            
+            try
+            {
+                UnivariateRealFunction function = interpolator.interpolate( xa, getArray( y ) );
+                    
+                for ( Period period : periods )
+                {
+                    if ( ++periodCount >= min && periodCount <= max )
+                    {
+                        metaDataSet.addValue( function.value( periodCount ), "Regression value", period.getName() );
+                    }
+                }
+            }
+            catch ( MathException ex )
+            {
+                throw new RuntimeException( "Failed to interpolate", ex );
+            }
         }
 
         // ---------------------------------------------------------------------

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ConversionUtils.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ConversionUtils.java	2009-11-25 15:56:24 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ConversionUtils.java	2010-01-29 09:05:27 +0000
@@ -206,4 +206,24 @@
         
         return map;
     }
+    
+    /**
+     * Converts a List<Double> into a double[].
+     * 
+     * @param list the List.
+     * @return a double array.
+     */
+    public static double[] getArray( List<Double> list )
+    {
+        double[] array = new double[ list.size() ];
+        
+        int index = 0;
+        
+        for ( Double d : list )
+        {
+            array[ index++ ] = d;
+        }
+        
+        return array;
+    }
 }

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/MathUtils.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/MathUtils.java	2009-12-11 11:28:02 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/MathUtils.java	2010-01-29 09:05:27 +0000
@@ -195,4 +195,56 @@
     {
         return new Random().nextInt( 999 );
     }
+    
+    /**
+     * Returns the minimum value from the given array.
+     * 
+     * @param array the array of numbers.
+     * @return the minimum value.
+     */
+    public static Double getMin( double[] array )
+    {
+        if ( array == null || array.length == 0 )
+        {
+            return null;
+        }
+        
+        double min = array[ 0 ];
+        
+        for ( int i = 1; i < array.length; i++ )
+        {
+            if ( array[ i ] < min )
+            {
+                min = array[ i ];
+            }
+        }
+        
+        return min;
+    }
+    
+    /**
+     * Returns the maximum value from the given array.
+     * 
+     * @param array the array of numbers.
+     * @return the maximum value.
+     */
+    public static Double getMax( double[] array )
+    {
+        if ( array == null || array.length == 0 )
+        {
+            return null;
+        }
+        
+        double max = array[ 0 ];
+        
+        for ( int i = 1; i < array.length; i++ )
+        {
+            if ( array[ i ] > max )
+            {
+                max = array[ i ];
+            }
+        }
+        
+        return max;
+    }
 }

=== added file 'dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/ConversionUtilsTest.java'
--- dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/ConversionUtilsTest.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/ConversionUtilsTest.java	2010-01-29 09:05:27 +0000
@@ -0,0 +1,57 @@
+package org.hisp.dhis.system.util;
+
+/*
+ * Copyright (c) 2004-2007, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import static junit.framework.Assert.*;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class ConversionUtilsTest
+{
+    @Test
+    public void getArray()
+    {
+        List<Double> list = new ArrayList<Double>();
+        list.add( 1.0 );
+        list.add( 2.0 );
+        list.add( 3.0 );
+        
+        double[] array = ConversionUtils.getArray( list );
+        
+        assertEquals( 3, array.length );
+        assertEquals( 1.0, array[0] );
+        assertEquals( 2.0, array[1] );
+        assertEquals( 3.0, array[2] );
+    }
+}

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/MathUtilsTest.java'
--- dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/MathUtilsTest.java	2009-03-03 16:46:36 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/MathUtilsTest.java	2010-01-29 09:05:27 +0000
@@ -27,16 +27,18 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import junit.framework.TestCase;
-
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
 import static org.hisp.dhis.system.util.MathUtils.expressionIsTrue;
 
+import org.junit.Test;
+
 /**
  * @author Lars Helge Overland
  * @version $Id: MathUtil.java 4712 2008-03-12 10:32:45Z larshelg $
  */
 public class MathUtilsTest
-    extends TestCase
 {
     private static final String OPERATOR_EQUAL = "==";
     private static final String OPERATOR_NOT_EQUAL = "!=";
@@ -45,6 +47,7 @@
     private static final String OPERATOR_LESSER = "<";
     private static final String OPERATOR_LESSER_EQUAL = "<=";
     
+    @Test
     public void testExpressionIsTrue()
     {
         assertFalse( expressionIsTrue( 20.0, OPERATOR_EQUAL, 10.0 ) );
@@ -55,4 +58,20 @@
         assertTrue( expressionIsTrue( 40.0, OPERATOR_LESSER_EQUAL, 50.0 ) );
         assertFalse( expressionIsTrue( 0.0, OPERATOR_GREATER_EQUAL, 20.0 ) );
     }
+    
+    @Test
+    public void testGetMin()
+    {
+        double[] array = { 5.0, 2.0, 6.0, 12.0 };
+        
+        assertEquals( 2.0, MathUtils.getMin( array ) );
+    }
+
+    @Test
+    public void testGetMax()
+    {
+        double[] array = { 5.0, 2.0, 12.0, 6.0 };
+        
+        assertEquals( 12.0, MathUtils.getMax( array ) );
+    }
 }

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/StreamUtilsTest.java'
--- dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/StreamUtilsTest.java	2009-12-19 15:20:41 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/StreamUtilsTest.java	2010-01-29 09:05:27 +0000
@@ -28,11 +28,7 @@
  */
 
 import java.io.BufferedInputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+
 import junit.framework.TestCase;
 
 /**

=== added file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/GetHistoryChartAction.java'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/GetHistoryChartAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/GetHistoryChartAction.java	2010-01-29 09:05:27 +0000
@@ -0,0 +1,150 @@
+package org.hisp.dhis.de.action;
+
+/*
+ * Copyright (c) 2004-2007, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.hisp.dhis.chart.ChartService;
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
+import org.hisp.dhis.dataelement.DataElementCategoryService;
+import org.hisp.dhis.dataelement.DataElementService;
+import org.hisp.dhis.de.state.SelectedStateManager;
+import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.period.Period;
+import org.jfree.chart.JFreeChart;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class GetHistoryChartAction
+    implements Action
+{
+    private static final int HISTORY_LENGTH = 13;
+
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private ChartService chartService;
+    
+    public void setChartService( ChartService chartService )
+    {
+        this.chartService = chartService;
+    }
+
+    private DataElementService dataElementService;
+    
+    public void setDataElementService( DataElementService dataElementService )
+    {
+        this.dataElementService = dataElementService;
+    }
+
+    private DataElementCategoryService categoryService;
+
+    public void setCategoryService( DataElementCategoryService categoryService )
+    {
+        this.categoryService = categoryService;
+    }
+
+    private SelectedStateManager selectedStateManager;
+
+    public void setSelectedStateManager( SelectedStateManager selectedStateManager )
+    {
+        this.selectedStateManager = selectedStateManager;
+    }
+    
+    private I18nFormat format;
+
+    public void setFormat( I18nFormat format )
+    {
+        this.format = format;
+    }
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+
+    private Integer dataElementId;
+    
+    public void setDataElementId( Integer dataElementId )
+    {
+        this.dataElementId = dataElementId;
+    }
+
+    private Integer categoryOptionComboId;
+
+    public void setCategoryOptionComboId( Integer categoryOptionComboId )
+    {
+        this.categoryOptionComboId = categoryOptionComboId;
+    }
+
+
+    // -------------------------------------------------------------------------
+    // Output
+    // -------------------------------------------------------------------------
+
+    private JFreeChart chart;
+
+    public JFreeChart getChart()
+    {
+        return chart;
+    }
+
+    private int width = 525;
+
+    public int getWidth()
+    {
+        return width;
+    }
+
+    private int height = 330;
+
+    public int getHeight()
+    {
+        return height;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    public String execute()
+    {
+        DataElement dataElement = dataElementService.getDataElement( dataElementId );
+        DataElementCategoryOptionCombo categoryOptionCombo = categoryService.getDataElementCategoryOptionCombo( categoryOptionComboId );
+
+        Period period = selectedStateManager.getSelectedPeriod();
+        OrganisationUnit organisationUnit = selectedStateManager.getSelectedOrganisationUnit();
+        
+        chart = chartService.getJFreeChartHistory( dataElement, categoryOptionCombo, period, organisationUnit, HISTORY_LENGTH, format );
+        
+        return SUCCESS;
+    }
+}

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/org/hisp/dhis/de/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/org/hisp/dhis/de/i18n_module.properties	2010-01-28 23:08:44 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/org/hisp/dhis/de/i18n_module.properties	2010-01-29 09:05:27 +0000
@@ -112,4 +112,4 @@
 dv_deleted							= Deleted
 dv_added							= Added
 followup							= Follow-up
-regression_line						= Regression line
\ No newline at end of file
+interpolation						= Interpolation
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/history.vm'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/history.vm	2010-01-28 23:08:44 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/history.vm	2010-01-29 09:05:27 +0000
@@ -75,7 +75,7 @@
                 </tr>
                 <tr>
                     <td style="background-color:#75e077; height:26px">&nbsp;</td>
-                    <td>$encoder.htmlEncode( $i18n.getString( "regression_line" ) ) </td>
+                    <td>$encoder.htmlEncode( $i18n.getString( "interpolation" ) ) </td>
                     <td></td>
                 </tr>
             </table>