Displaying differences for changeset
 
display as  

src/java/cfa/CDPHE_lowFlowStats.java

@@ -6,7 +6,7 @@
 import java.util.Calendar;
 
 /**
-* Last Updated: 2-February-2015
+* Last Updated: 3-February-2015
 * @author Tyler Wible
 * @since 16-December-2014
 */
@@ -106,7 +106,7 @@
         double designFlow = Math.exp(U + K*S);
         
         //Call file writer for outputs fo flow statistics
-        designFlow = doubleMath.round(designFlow, 3);
+        designFlow = doubleMath.round(designFlow, 2);
         
         return designFlow;
     }
@@ -114,7 +114,7 @@
      * Calculate the CDPHE "biologically-based" design flow (see DFLOW user manual) 
      * which is an 'm'-day harmonic average low flow based on a certain excursion count (exceedance?), 
      * performs this calculation for the entire flow record as well as each month of the year
-     * @param data_all  a String[][] of flow data, column1 = dates (format yyyy-mm-dd), column2 = flow values
+     * @param flowData  a String[][] of flow data, column1 = dates (format yyyy-mm-dd), column2 = flow values
      * @param m  the number of days to average for annual low flow analysis (m-day average)
      * @param R  the desired return period of the m-day low flow (in years)
      * @param clusterLength  the length of time for the definition of a 'cluster' of excursion 
@@ -126,7 +126,7 @@
      * @throws IOException
      * @throws ParseException 
      */
-    public double[] CDPHE_Biological(String[][] data_all,
+    public double[] CDPHE_Biological(String[][] flowData,
                                    int m,
                                    int R,
                                    int clusterLength,
@@ -134,38 +134,58 @@
         DoubleArray doubleArray =  new DoubleArray();
         DoubleMath doubleMath = new DoubleMath();
         
-        //Pull data
-        String[][] data_jan = doubleArray.getSeasonalData(data_all, "01-01", "01-31");
-        String[][] data_feb = doubleArray.getSeasonalData(data_all, "02-01", "02-28");
-        if(m == 30){
-            data_feb = doubleArray.getSeasonalData(data_all, "02-01", "03-03");
+        //Calculate annual design low flow
+        double DFLOW_annual = CDPHE_Biological_calcs(flowData, m, R, clusterLength, clusterCountMax);
+        
+        //Calculate monthly design low flows
+        double DFLOW_jan = -9999, DFLOW_feb = -9999, DFLOW_mar = -9999, DFLOW_apr = -9999, DFLOW_may = -9999, DFLOW_jun = -9999;
+        double DFLOW_jul = -9999, DFLOW_aug = -9999, DFLOW_sep = -9999, DFLOW_oct = -9999, DFLOW_nov = -9999, DFLOW_dec = -9999;
+        if(m == 30 && R == 3){
+            //If the design flow is 30E3, follow the special provisions set out by reg31
+            double[] monthlyDFLOWs = calc30E3(flowData, DFLOW_annual);
+            DFLOW_jan = monthlyDFLOWs[0];
+            DFLOW_feb = monthlyDFLOWs[1];
+            DFLOW_mar = monthlyDFLOWs[2];
+            DFLOW_apr = monthlyDFLOWs[3];
+            DFLOW_may = monthlyDFLOWs[4];
+            DFLOW_jun = monthlyDFLOWs[5];
+            DFLOW_jul = monthlyDFLOWs[6];
+            DFLOW_aug = monthlyDFLOWs[7];
+            DFLOW_sep = monthlyDFLOWs[8];
+            DFLOW_oct = monthlyDFLOWs[9];
+            DFLOW_nov = monthlyDFLOWs[10];
+            DFLOW_dec = monthlyDFLOWs[11];
+        }else{
+            //Otherwise treat it as a normal biological flow
+            DFLOW_jan = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "01-01", "01-31"), m, R, clusterLength, clusterCountMax);
+            DFLOW_feb = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "02-01", "02-28"), m, R, clusterLength, clusterCountMax);
+            DFLOW_mar = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "03-01", "03-31"), m, R, clusterLength, clusterCountMax);
+            DFLOW_apr = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "04-01", "04-30"), m, R, clusterLength, clusterCountMax);
+            DFLOW_may = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "05-01", "05-31"), m, R, clusterLength, clusterCountMax);
+            DFLOW_jun = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "06-01", "06-30"), m, R, clusterLength, clusterCountMax);
+            DFLOW_jul = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "07-01", "07-31"), m, R, clusterLength, clusterCountMax);
+            DFLOW_aug = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "08-01", "08-31"), m, R, clusterLength, clusterCountMax);
+            DFLOW_sep = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "09-01", "09-30"), m, R, clusterLength, clusterCountMax);
+            DFLOW_oct = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "10-01", "10-31"), m, R, clusterLength, clusterCountMax);
+            DFLOW_nov = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "11-01", "11-30"), m, R, clusterLength, clusterCountMax);
+            DFLOW_dec = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "12-01", "12-31"), m, R, clusterLength, clusterCountMax);
         }
-        String[][] data_mar = doubleArray.getSeasonalData(data_all, "03-01", "03-31");
-        String[][] data_apr = doubleArray.getSeasonalData(data_all, "04-01", "04-30");
-        String[][] data_may = doubleArray.getSeasonalData(data_all, "05-01", "05-31");
-        String[][] data_jun = doubleArray.getSeasonalData(data_all, "06-01", "06-30");
-        String[][] data_jul = doubleArray.getSeasonalData(data_all, "07-01", "07-31");
-        String[][] data_aug = doubleArray.getSeasonalData(data_all, "08-01", "08-31");
-        String[][] data_sep = doubleArray.getSeasonalData(data_all, "09-01", "09-30");
-        String[][] data_oct = doubleArray.getSeasonalData(data_all, "10-01", "10-31");
-        String[][] data_nov = doubleArray.getSeasonalData(data_all, "11-01", "11-30");
-        String[][] data_dec = doubleArray.getSeasonalData(data_all, "12-01", "12-31");
         
         //Calculate design flows
         double[] designFlows = new double[13];
-        designFlows[0] = doubleMath.round(CDPHE_Biological_calcs(data_all, m, R, clusterLength, clusterCountMax), 3);   //entire record
-        designFlows[1] = doubleMath.round(CDPHE_Biological_calcs(data_jan, m, R, clusterLength, clusterCountMax), 3);   //January
-        designFlows[2] = doubleMath.round(CDPHE_Biological_calcs(data_feb, m, R, clusterLength, clusterCountMax), 3);   //February
-        designFlows[3] = doubleMath.round(CDPHE_Biological_calcs(data_mar, m, R, clusterLength, clusterCountMax), 3);   //March
-        designFlows[4] = doubleMath.round(CDPHE_Biological_calcs(data_apr, m, R, clusterLength, clusterCountMax), 3);   //April
-        designFlows[5] = doubleMath.round(CDPHE_Biological_calcs(data_may, m, R, clusterLength, clusterCountMax), 3);   //May
-        designFlows[6] = doubleMath.round(CDPHE_Biological_calcs(data_jun, m, R, clusterLength, clusterCountMax), 3);   //June
-        designFlows[7] = doubleMath.round(CDPHE_Biological_calcs(data_jul, m, R, clusterLength, clusterCountMax), 3);   //July
-        designFlows[8] = doubleMath.round(CDPHE_Biological_calcs(data_aug, m, R, clusterLength, clusterCountMax), 3);   //August
-        designFlows[9] = doubleMath.round(CDPHE_Biological_calcs(data_sep, m, R, clusterLength, clusterCountMax), 3);   //September
-        designFlows[10] = doubleMath.round(CDPHE_Biological_calcs(data_oct, m, R, clusterLength, clusterCountMax), 3);  //October
-        designFlows[11] = doubleMath.round(CDPHE_Biological_calcs(data_nov, m, R, clusterLength, clusterCountMax), 3);  //November
-        designFlows[12] = doubleMath.round(CDPHE_Biological_calcs(data_dec, m, R, clusterLength, clusterCountMax), 3);  //December
+        designFlows[0] = doubleMath.round(DFLOW_annual, 2);   //entire record
+        designFlows[1] = doubleMath.round(DFLOW_jan, 2);   //January
+        designFlows[2] = doubleMath.round(DFLOW_feb, 2);   //February
+        designFlows[3] = doubleMath.round(DFLOW_mar, 2);   //March
+        designFlows[4] = doubleMath.round(DFLOW_apr, 2);   //April
+        designFlows[5] = doubleMath.round(DFLOW_may, 2);   //May
+        designFlows[6] = doubleMath.round(DFLOW_jun, 2);   //June
+        designFlows[7] = doubleMath.round(DFLOW_jul, 2);   //July
+        designFlows[8] = doubleMath.round(DFLOW_aug, 2);   //August
+        designFlows[9] = doubleMath.round(DFLOW_sep, 2);   //September
+        designFlows[10] = doubleMath.round(DFLOW_oct, 2);  //October
+        designFlows[11] = doubleMath.round(DFLOW_nov, 2);  //November
+        designFlows[12] = doubleMath.round(DFLOW_dec, 2);  //December
         
         return designFlows;
     }
@@ -208,6 +228,7 @@
         double flow_lowerBound = 0, flow_upperBound = trialDFLOW, excursions_lowerBound = 0, excursions_upperBound = trialDFLOW_excursions;
         double designFlow = -1;
         boolean convergance = false;
+        int ctr = 0;
         while(!convergance){
             
             //Check for convergance
@@ -220,6 +241,10 @@
             }else if( Math.abs(A - excursions_upperBound) <= (0.005*A) ){
                 designFlow = flow_upperBound;
                 convergance = true;
+            }else if( ctr > 200 ){
+                designFlow = -9999;
+                convergance = true;
+                System.err.println("Did not converge to a solution after " + ctr + " iterations, current upper flow boundary: " + flow_upperBound+ ", current lower flow boundary: " + flow_lowerBound);
             }else{
                 //If convergance is not met, interpolate a new trial design flow and count it's excursions
                 trialDFLOW = flow_lowerBound + ( ((flow_upperBound - flow_lowerBound) * (A - excursions_lowerBound)) / (excursions_upperBound - excursions_lowerBound) );
@@ -232,6 +257,7 @@
                     excursions_upperBound = trialDFLOW_excursions;
                 }
             }
+            ctr++;
         }
         
         //Call file writer for outputs fo flow statistics
@@ -363,6 +389,84 @@
         return excursionLength;
     }
     /**
+     * Calculate the 30-day average low flow associated with a 3 year return period 
+     * using the special provisions set out in Regulation 31.9.3 "Streams with Rapid Flow Changes"
+     * @param flowData  flow data, column1 = dates (format yyyy-mm-dd), column2 = flow values
+     * @param DFLOW_annual  the biologically based 30E3 design flow for the period of record
+     * @return  a list of monthly low flows in order from January to December
+     * @throws IOException 
+     */
+    private double[] calc30E3(String[][] flowData, double DFLOW_annual) throws IOException{
+        DoubleArray doubleArray =  new DoubleArray();
+        DoubleMath doubleMath = new DoubleMath();
+        
+        //Calculate m-day statistics
+        Object[] resultArray = doubleArray.getMdayData(flowData, 30, "harmonic");
+        ArrayList<String> mDayAverage_dates = (ArrayList<String>) resultArray[0];
+        ArrayList<Double> mDayAverage = (ArrayList<Double>) resultArray[1];
+        
+        //Determine the year and 'month' of each m-day flow
+        ArrayList<String> mDayAverage_month = new ArrayList<String>();
+        for(int i=0; i<mDayAverage.size(); i++){
+            //Get the date for 14 days from the begin date, 
+            //aka a total of 15 days of data and check if this is still in the same month
+            String beginDate = mDayAverage_dates.get(i).substring(0,10);
+            String midDate = doubleArray.getDay(beginDate, 12);
+            
+            String beginMonth = beginDate.substring(5,7);
+            String midMonth = midDate.substring(5,7);
+            if(beginMonth.equalsIgnoreCase(midMonth)){
+                mDayAverage_month.add(convertMonth(Double.parseDouble(beginMonth)));
+            }else{
+                mDayAverage_month.add(convertMonth(Double.parseDouble(midMonth)));
+            }
+        }
+        
+        //Determine monthly low flows
+        String[] months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
+        double[] monthlyLowFlow = new double[12];
+        for(int j=0; j<12; j++){
+            //Get all flows for the current month
+            ArrayList<Double> currentMonthFlows = new ArrayList<Double>();
+            for(int i=0; i<mDayAverage.size(); i++){
+                if(mDayAverage_month.get(i).equalsIgnoreCase(months[j])){
+                    currentMonthFlows.add(mDayAverage.get(i));
+                }
+            }
+            
+            //Determine m-day minimum flow for this month
+            double mDayAveage_MonthlyMin = doubleMath.min(currentMonthFlows);
+            
+            //Check whether to return the annual 30E3 value or the monthly flow (Reg 31.9.3.e)
+            if(currentMonthFlows.isEmpty() || DFLOW_annual > mDayAveage_MonthlyMin){
+                mDayAveage_MonthlyMin = DFLOW_annual;
+            }
+            monthlyLowFlow[j] = mDayAveage_MonthlyMin;
+        }
+        
+        return monthlyLowFlow;
+    }
+    private String convertMonth(double monthDouble){
+        int monthInteger = (int) monthDouble;
+        String monthString = "?";
+        switch(monthInteger){
+            case 1:  monthString = "January"; break;
+            case 2:  monthString = "February"; break;
+            case 3:  monthString = "March"; break;
+            case 4:  monthString = "April"; break;
+            case 5:  monthString = "May"; break;
+            case 6:  monthString = "June"; break;
+            case 7:  monthString = "July"; break;
+            case 8:  monthString = "August"; break;
+            case 9:  monthString = "September"; break;
+            case 10: monthString = "October"; break;
+            case 11: monthString = "November"; break;
+            case 12: monthString = "December"; break;
+            default: monthString = "Not a valid month integer"; break;
+        }
+        return monthString;
+    }
+    /**
      * Calculate the CDPHE "human health" design flow (see DFLOW user manual) 
      * which is the harmonic mean of the flows
      * @param flowData  flow data, column1 = dates (format yyyy-mm-dd), column2 = flow values
@@ -375,7 +479,7 @@
         
         //Calculate design flows
         double[] flowOnlyData = convertSecondColumn(flowData);
-        double designFlow = doubleMath.round(doubleMath.meanHarmonic(flowOnlyData), 3);
+        double designFlow = doubleMath.round(doubleMath.meanHarmonic(flowOnlyData), 2);
         
         return designFlow;
     }
@@ -437,7 +541,7 @@
         //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);
-        median_R_yearFlow = doubleMath.round(median_R_yearFlow, 3);
+        median_R_yearFlow = doubleMath.round(median_R_yearFlow, 2);
         
         //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";

src/java/cfa/guiTimeseries_Model.java

@@ -49,7 +49,7 @@
     String mainFolder = "C:/Projects/TylerWible/CodeDirectories/NetBeans/CSIP/data/CFA/Timeseries";
     String database = "USGS";//"CDWR";//"STORET";//"UserData";//
     String organizationName = "USGS";//"Co. Division of Water Resources";//"Colorado Dept. of Public Health & Environment";//
-    String stationID = "06822000";//"06764880";//"CLAGRECO";//"000028";//
+    String stationID = "06764880";//"CLAGRECO";//"000028";//
     String stationName = "South Platte River at Roscoe, Nebr.";//"Cache La Poudre Near Greeley";//"BIG THOMPSON R NEAR MOUTH";//
     String wqTest = "flow";//"00600 Total nitrogen, water, unfiltered, milligrams per liter -- mg/L";//"00625 Ammonia-nitrogen as N -- mg/L";//
     String beginDate = "";