Displaying differences for changeset
 
display as  

src/java/cfa/CDPHE_lowFlowStats.java

@@ -6,7 +6,7 @@
 import java.util.Calendar;
 
 /**
-* Last Updated: 20-January-2015
+* Last Updated: 30-January-2015
 * @author Tyler Wible
 * @since 16-December-2014
 */
@@ -370,15 +370,87 @@
     public double CDPHE_HumanHealth(String[][] flowData) throws IOException, ParseException{
         DoubleMath doubleMath = new DoubleMath();
         
+        //Calculate design flows
+        double[] flowOnlyData = convertSecondColumn(flowData);
+        double designFlow = doubleMath.round(doubleMath.meanHarmonic(flowOnlyData), 3);
+        
+        return designFlow;
+    }
+    /**
+     * Convert a string[][] array's second column to a double[] array, 
+     * aka pull out the flow values from flowData
+     * @param flowData  flow data, column1 = dates (format yyyy-mm-dd), column2 = flow values
+     * @return 
+     */
+    private double[] convertSecondColumn(String[][] flowData){
         //Pull data
         double[] flowOnlyData = new double[flowData.length];
         for(int i=0; i<flowData.length; i++){
             flowOnlyData[i] = Double.parseDouble(flowData[i][1]);
         }
         
-        //Calculate design flows
-        double designFlow = doubleMath.round(doubleMath.meanHarmonic(flowOnlyData), 3);
+        return flowOnlyData;
+    }
+    /**
+     * 
+     * @param flowData  a String[][] of flow data, column1 = dates (format yyyy-mm-dd), column2 = flow values
+     * @return
+     * @throws IOException
+     * @throws ParseException 
+     */
+    public String CDPHE_REG31(String[][] flowData) throws IOException, ParseException{
+        //Calculate acute biologically based low flows (1-day 3-year)
+        System.out.println("Calcualting Reg. 31 1E3 Acute Monthly Low Flows...");
+        double[] monthlyBiologically_1day = CDPHE_Biological(flowData, 1, 3, 120, 5);
         
-        return designFlow;
+        //Calculate chronic biologically based low flows (7-day 3-year)
+        System.out.println("Calcualting Reg. 31 7E3 Chronic Monthly Low Flows...");
+        double[] monthlyBiologically_7day = CDPHE_Biological(flowData, 7, 3, 120, 5);
+        
+        //Calculate chronic biologically based low flows (30-day 3-year)
+        System.out.println("Calcualting Reg. 31 30E3 Chronic Monthly Low Flows...");
+        double[] monthlyBiologically_30day = CDPHE_Biological(flowData, 30, 3, 120, 5);
+        
+        //Calculate annual median of data with a 5-year return period
+        System.out.println("Calcualting Reg. 31 1E5 Annual Median of Daily Average Flows...");
+        double median_R_yearFlow = annualMedianReturnPeriod(flowData, 5);
+        
+        //Format the results into a summary table
+        String summaryTable = "Month\t1E3 Acute Monthly Low Flows\t7E3 Chronic Monthly Low Flows\t30E3 Chronic Monthly Low Flows";
+        String[] months = {"Entire Record", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
+        for(int i=0; i<13; i++){
+            summaryTable = summaryTable + "\r\n" + months[i] + "\t" + monthlyBiologically_1day[i] + "\t" + monthlyBiologically_7day[i] + "\t" + monthlyBiologically_30day[i];
+        }
+        summaryTable = summaryTable + "\r\n" + median_R_yearFlow;
+        
+        return summaryTable;
+    }
+    private double annualMedianReturnPeriod(String[][] flowData, int R){
+        //Calculate the annual median of daily average flow values with a recurrance intervale of 1 in "R" years
+        DoubleArray doubleArray =  new DoubleArray();
+        DoubleMath doubleMath =  new DoubleMath();
+        
+        //Calculate mediant for each year in time period
+        ArrayList<Double> medianFlows = new ArrayList<Double>();
+        boolean moreYears = flowData.length > 0;
+        String currentYear = flowData[0][0].substring(0,4);
+        String finalYear = flowData[flowData.length - 1][0].substring(0,4);
+        while(moreYears){
+            //Get current year's data and calculate it's statistics
+            String[][] partialData = doubleArray.getYearsData(flowData, currentYear);
+            double[] flowOnlyData = convertSecondColumn(partialData);
+            medianFlows.add(doubleMath.Median(flowOnlyData));
+            
+            int nextYear = Integer.parseInt(currentYear) + 1;
+            if(finalYear.compareToIgnoreCase(String.valueOf(nextYear)) >= 0){
+                currentYear = String.valueOf(nextYear);
+            }else{
+                moreYears = false;
+            }
+        }
+        
+        //Calculate return period of data
+        double median_RyearFlow = doubleArray.calculateReturnPeriod(medianFlows, R);
+        return median_RyearFlow;
     }
 }

src/java/cfa/DoubleArray.java

@@ -49,7 +49,7 @@
     }
 }
 /**
-* Last Updated: 6-January-2015
+* Last Updated: 29-January-2015
 * @author Tyler Wible
 * @since 21-June-2012
 */
@@ -899,6 +899,48 @@
         return SeasonalData;
     }
     /**
+     * Calculate the flow associated with the n-year return period from the set of annual data
+     * @param nYearFlows  a list of annual flow values (aka one value per year)
+     * @param n  the n-year return period for the desired flow
+     * @return 
+     */
+    public double calculateReturnPeriod(ArrayList<Double> nYearFlows, int n){
+        DoubleArray doubleArray = new DoubleArray();
+        
+        //Remove non-values
+        int ctr = 0;
+        for(int i=0; i<nYearFlows.size(); i++){
+            if(nYearFlows.get(i) != Double.NaN){
+                ctr++;
+            }
+        }
+        String[][] nYearData = new String[ctr][2];
+        ctr=0;
+        for(int i=0; i<nYearFlows.size(); i++){
+            if(nYearFlows.get(i) != Double.NaN){
+                nYearData[ctr][0] = String.valueOf(ctr);
+                nYearData[ctr][1] = String.valueOf(nYearFlows.get(i));
+                ctr++;
+            }
+        }
+        
+        //Get ranks for remaining annual data
+        double[][] nYearRanks = doubleArray.weibullPlottingPosition(nYearData);
+
+        //Find the "n" recurrence interval and return its corresponding flow as the n-year Flow
+        double n_yearFlow = 0;
+        double target = (double) n/10;
+        for(int i=0; i<(nYearRanks.length - 1); i++){
+            if(n < nYearRanks[i][0] && n > nYearRanks[i+1][0]){
+                //Linear interpolation for flow value for "n" recurrence interval
+                n_yearFlow = ((target - nYearRanks[i+1][0])/(nYearRanks[i][0] - nYearRanks[i+1][0]))*(nYearRanks[i][1] - nYearRanks[i+1][1]) + nYearRanks[i+1][1];
+            }else if(n == nYearRanks[i][0]){
+                n_yearFlow = nYearRanks[i][1];
+            }
+        }
+        return n_yearFlow;
+    }
+    /**
      * 
      * @param sortedData  the String[][] containing sorted data for the time series 
      * (column 1 = dates (yyyy-mm-dd format) column 2 = value

src/java/cfa/FlowStatistics.java

@@ -13,7 +13,7 @@
 import java.util.GregorianCalendar;
 
 /**
-* Last Updated: 6-January-2015
+* Last Updated: 29-January-2015
 * @author Tyler Wible
 * @since 29-June-2011
 */
@@ -418,33 +418,7 @@
         //Calculate mQn (7Q10) Statistics
         double mQnFlow = 0;
         if(m != 0 && n != 0){
-            int ctr = 0;
-            for(int i=0; i<mQnFlows.size(); i++){
-                if(mQnFlows.get(i) != Double.NaN){
-                    ctr++;
-                }
-            }
-            String[][] mQnData = new String[ctr][2];
-            ctr=0;
-            for(int i=0; i<mQnFlows.size(); i++){
-                if(mQnFlows.get(i) != Double.NaN){
-                    mQnData[ctr][0] = String.valueOf(ctr);
-                    mQnData[ctr][1] = String.valueOf(mQnFlows.get(i));
-                    ctr++;
-                }
-            }
-            double[][] mQnRanks = doubleArray.weibullPlottingPosition(mQnData);
-
-            //Find the "n" recurrence interval and return its corresponding flow as the mQnFlow
-            double target = (double) n/10;
-            for(int i=0; i<(mQnRanks.length - 1); i++){
-                if(n < mQnRanks[i][0] && n > mQnRanks[i+1][0]){
-                    //Linear interpolation for flow value for "n" recurrence interval
-                    mQnFlow = ((target - mQnRanks[i+1][0])/(mQnRanks[i][0] - mQnRanks[i+1][0]))*(mQnRanks[i][1] - mQnRanks[i+1][1]) + mQnRanks[i+1][1];
-                }else if(n == mQnRanks[i][0]){
-                    mQnFlow = mQnRanks[i][1];
-                }
-            }
+            mQnFlow = doubleArray.calculateReturnPeriod(mQnFlows, n);
         }
         String errorMessage = "";
         if(mQnFlow == 0){

src/java/cfa/guiTimeseries_Model.java

@@ -40,7 +40,7 @@
 import org.jfree.data.xy.XYSeriesCollection;
 
 /**
-* Last Updated: 26-January-2015
+* Last Updated: 30-January-2015
 * @author Tyler Wible
 * @since 24-June-2011
 */
@@ -72,7 +72,7 @@
     boolean showMonthlyStatsTF = false;
     boolean calcFlowStatisticsFileTF = true;
     boolean calcCDPHElowflowTF = true;
-    String CDPHE_lowFlowType = "all";//"extreme-value";//"biological";//"human-health";//
+    String CDPHE_lowFlowType = "all";//"extreme-value";//"biological";//"human-health";//"reg31";//
     int CDPHE_m = 4;//m-day average                          //only used if CDPHE_lowFlowType == "all" or "extreme-value" or "biological"
     int CDPHE_R = 10;//R-year return period for cdphe flows  //only used if CDPHE_lowFlowType == "all" or "extreme-value" or "biological"
     String CDPHE_waterYearBegin = "04-01";//"MM-dd"          //only used if CDPHE_lowFlowType == "all" or "extreme-value"
@@ -105,6 +105,7 @@
     double biologicalDFLOW_nov = -1;
     double biologicalDFLOW_dec = -1;
     double humanHealthDFLOW = -1;
+    String reg31DFLOWsummary = "?";
     double max = -1;
     double min = -1;
     double upperQuartile = -1;
@@ -275,6 +276,9 @@
     public String getCDPHE_HumanHealthDFLOW(){
         return String.valueOf(humanHealthDFLOW);
     }
+    public String getCDPHE_Reg31DFLOWsummary(){
+        return String.valueOf(reg31DFLOWsummary);
+    }
     public String getMax(){
         return String.valueOf(max);
     }
@@ -1991,8 +1995,12 @@
                     //Calculate the Human-health based design flow:
                     this.humanHealthDFLOW = cdphe_lowflow.CDPHE_HumanHealth(sortedData_combined);
                     
+                }else if(CDPHE_lowFlowType.equalsIgnoreCase("reg31")){
+                    //Calcualte the Regulation 31 summary of design flows:
+                    this.reg31DFLOWsummary = cdphe_lowflow.CDPHE_REG31(sortedData_combined);
+                    
                 }else if(CDPHE_lowFlowType.equalsIgnoreCase("all")){
-                    //Calculate all design flows
+                    //Calculate all design flows
                     this.extremeValueDFLOW = cdphe_lowflow.CDPHE_ExtremeValue(sortedData_combined, CDPHE_m, CDPHE_R, CDPHE_waterYearBegin);
                     double[] biologial_flows = cdphe_lowflow.CDPHE_Biological(sortedData_combined, CDPHE_m, CDPHE_R, CDPHE_clusterLength, CDPHE_clusterCountMax);
                     this.biologicalDFLOW_all = biologial_flows[0];
@@ -2009,6 +2017,7 @@
                     this.biologicalDFLOW_nov = biologial_flows[11];
                     this.biologicalDFLOW_dec = biologial_flows[12];
                     this.humanHealthDFLOW = cdphe_lowflow.CDPHE_HumanHealth(sortedData_combined);
+                    this.reg31DFLOWsummary = cdphe_lowflow.CDPHE_REG31(sortedData_combined);
                 }
             }
         }else{

src/java/m/cfa/Timeseries_V1_0.java

@@ -132,6 +132,7 @@
         result.put(JSONUtils.data("cdphe_biologicalDFLOW_nov", model.getCDPHE_BiologicalDFLOW_nov()));
         result.put(JSONUtils.data("cdphe_biologicalDFLOW_dec", model.getCDPHE_BiologicalDFLOW_dec()));
         result.put(JSONUtils.data("cdphe_humanHealthDFLOW", model.getCDPHE_HumanHealthDFLOW()));
+        result.put(JSONUtils.data("cdphe_reg31DFLOWsummary", model.getCDPHE_Reg31DFLOWsummary()));
         //Get all data results
         result.put(JSONUtils.data("max", model.getMax()));
         result.put(JSONUtils.data("min", model.getMin()));

src/java/m/cfa/Timeseries_V1_0Req.json

@@ -130,7 +130,7 @@
     },
     {
       "name": "CDPHE_lowFlowType",
-      "description": "The type of CDPHE low flow to be calculated, 'all' performs all the low flow calculations (all | extreme-value | biological | human-health). Only used if calcCDPHElowflowTF is True.",
+      "description": "The type of CDPHE low flow to be calculated, 'all' performs all the low flow calculations (all | extreme-value | biological | human-health | reg31). Only used if calcCDPHElowflowTF is True.",
       "value": "all"
     },
     {