@@ -1529,6 +1529,63 @@ |
} |
return leapYear; |
} |
+ /** |
+ * Loops through and finds "m-day" consecutive values and takes the arithmetic average of them |
+ * @param flowData a string[][] containing: column1 = dates, column2 = flowValues |
+ * @param numDays an integer representing the number (m) of consecutive days to be desired for analysis |
+ * @returns an ArrayList containing an ArrayList of each set of "m-day" consecutive set of flows for analysis (min, max, average, etc) |
+ * @throws IOException |
+ */ |
+ public Object[] getMdayData(String[][] flowData, int numDays) throws IOException{ |
+ DoubleMath doubleMath = new DoubleMath(); |
+ |
+ //Loop through flow data and find "m"-day consecutive flows |
+ ArrayList<String> allDate = new ArrayList<String>(); |
+ ArrayList<Double> allData = new ArrayList<Double>(); |
+ try{ |
+ for(int i=0; i<flowData.length; i++){ |
+ ArrayList<String> mDayDate = new ArrayList<String>(); |
+ ArrayList<Double> mDayData = new ArrayList<Double>(); |
+ int ctr = i; |
+ for(int j=0; j<numDays; j++){ |
+ if(j==0){ |
+ //Keep the first day |
+ mDayDate.add(flowData[ctr][0]); |
+ mDayData.add(Double.parseDouble(flowData[ctr][1])); |
+ }else{ |
+ //Compare the current day to the previous day for consecutive-ness |
+ boolean checkNextDate = checkSubsequentDates(flowData[ctr-1][0], flowData[ctr][0]); |
+ if(checkNextDate){ |
+ mDayDate.add(flowData[ctr][0]); |
+ mDayData.add(Double.parseDouble(flowData[ctr][1])); |
+ }else{ |
+ //If not consecutive days, break out of the loop and move to the next date for flowData |
+ mDayDate.clear(); |
+ mDayData.clear(); |
+ i = ctr - 1;//Skip to newest date since there is a break in the consecutive day data |
+ break; |
+ } |
+ } |
+ ctr++; |
+ } |
+ if(mDayData.size() == numDays){ |
+ //Add this m-consecutive day set of data to the all data array list for statistics later |
+ String startDate = mDayDate.get(0); |
+ String endDate = mDayDate.get(numDays - 1); |
+ allDate.add(startDate + " to " + endDate); |
+ allData.add(doubleMath.meanArithmetic(mDayData)); |
+ } |
+ } |
+ }catch(ArrayIndexOutOfBoundsException e){ |
+ //If the consecutive day counter (ctr) goes beyond the length of data available, |
+ //stop the subroutine and return the existing results |
+ Object[] returnArray = {allDate, allData}; |
+ return returnArray; |
+ } |
+ |
+ Object[] returnArray = {allDate, allData}; |
+ return returnArray; |
+ } |
// /** |
// * Reduces all data to just that within the specified date range |
// * @param allData all water quality data for the earlier provided date range and station ID (column1 = date, column2 = value) |
@@ -187,8 +187,8 @@ |
} |
/** |
* Calculates the arithmetic mean of the provided double[] array |
- * @param data the double[] array of which the average is desired |
- * @return the double value of the average of the data array |
+ * @param data the double[] array of which the arithmetic mean is desired |
+ * @return the double value of the arithmetic mean of the data array |
*/ |
public double meanArithmetic(double[] data){ |
//Calculates the average of a double array |
@@ -203,8 +203,8 @@ |
} |
/** |
* Calculates the arithmetic mean of the provided ArrayList<Double> |
- * @param data the ArrayList<Double> of which the average is desired |
- * @return the double value of the average of the data array |
+ * @param data the ArrayList<Double> of which the arithmetic mean is desired |
+ * @return the double value of the arithmetic mean of the data array |
*/ |
public double meanArithmetic(ArrayList<Double> data){ |
//Calculates the average of a double array |
@@ -215,6 +215,32 @@ |
return average; |
} |
/** |
+ * Calculates the harmonic mean of the provided double[] array, |
+ * only calculates for real positive values. |
+ * |
+ * Note that the final estimate of the harmonic mean is a weighted average |
+ * of the harmonic mean of the non-zero elements and zero. |
+ * @param data the double[] array of which the harmonic mean is desired |
+ * @return the double value of the harmonic mean of the data array |
+ */ |
+ public double meanHarmonic(double[] data){ |
+ //Calculate properties of harmonic mean |
+ double reciprocalSum = 0, nZeros = 0, nNonZeros = 0; |
+ for(int i=0; i<data.length; i++){ |
+ if(data[i] > 0){ |
+ reciprocalSum = reciprocalSum + (1/data[i]);//sum of reciprocals |
+ }else{ |
+ nZeros++; |
+ } |
+ nNonZeros++; |
+ } |
+ |
+ //Compute harmonic mean (with correction for the number of zero items in the array) |
+ double meanHarmonic = (nNonZeros - nZeros) / (reciprocalSum * ((nNonZeros - nZeros)/nNonZeros)); |
+ |
+ return meanHarmonic; |
+ } |
+ /** |
* Finds the average of the Log10 of a double[] array |
* @param data the double[] array that the average is desired for |
* @return the double value of the average of the Log10 of the data array |
@@ -74,7 +74,7 @@ |
String period3End) throws IOException, ParseException{ |
//Get today's date for output purposes |
Date currentDate = new Date(); |
- SimpleDateFormat desiredDateFormat = new SimpleDateFormat("yyyy-MM-dd"); |
+ SimpleDateFormat desiredDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); |
String today = desiredDateFormat.format(currentDate); |
stationName = stationName.replace(",", ""); |
|
@@ -253,8 +253,8 @@ |
statsSummaryTable[165][0] = "December (Coefficient of Variation)"; |
} |
statsSummaryTable[statsSummaryTable.length - 4][0] = "Flow Statistics based on Indicators of Hydrologic Alteration from:"; |
- statsSummaryTable[statsSummaryTable.length - 3][0] = "B.D. Richter; J.V. Baumgartner; J. Powell; D.P. Braun. 1996. 'A Method For Assessing Hydrologic Aleration Within Ecosystems.' Conservation Biology 10(4): 1163-1174.\t"; |
- statsSummaryTable[statsSummaryTable.length - 2][0] = "B.D. Richter; J.V. Baumgartner; R. Wigington; D.P Braun. 1997. 'How Much Water Does A River Need?' Freshwater Biology. 37: 231-249.\t"; |
+ statsSummaryTable[statsSummaryTable.length - 3][0] = "B.D. Richter; J.V. Baumgartner; J. Powell; D.P. Braun. 1996. 'A Method For Assessing Hydrologic Aleration Within Ecosystems.' Conservation Biology 10(4): 1163-1174."; |
+ statsSummaryTable[statsSummaryTable.length - 2][0] = "B.D. Richter; J.V. Baumgartner; R. Wigington; D.P Braun. 1997. 'How Much Water Does A River Need?' Freshwater Biology. 37: 231-249."; |
statsSummaryTable[statsSummaryTable.length - 1][0] = "B.D. Richter; J.V. Baumgartner; D.P. Braun; J. Powell. 1998. 'A Spatial Assessment Of Hydrologic Alteration Within A River Network.' Regul. Rivers: Res. Mgmt. 14: 329-340."; |
|
//Calculate all data statistics |
@@ -446,17 +446,21 @@ |
return returnArray; |
} |
/** |
- * |
- * @param statsSummaryTable |
- * @param flowData |
- * @param highPercentile |
- * @param lowPercentile |
- * @param m |
- * @param dataHeader |
- * @param showMonthlyTF |
- * @param seasonBegin |
- * @param seasonEnd |
- * @return |
+ * calculates flow statistics for the provided flowData and appends the column |
+ * of results to the statsSummaryTable under the provided header |
+ * @param statsSummaryTable the summary table to add to |
+ * @param flowData the String[][] containing sorted data for the time series |
+ * (column 1 = dates (yyyy-mm-dd) column 2 = value |
+ * @param highPercentile the percentile value for defining a "high flow pulse" |
+ * typically greater than 75% = 0.75 |
+ * @param lowPercentile the percentile value for defining a "low flow pulse" |
+ * typically lower than 25% = 0.25 |
+ * @param m used to calculate an "m-day-average" minimum flow |
+ * @param dataHeader the text header for this column of result statistics in the statsSummaryTable (i.e. 'All Data' or '1998') |
+ * @param showMonthlyTF a flag to show monthly statistics (min/max/etc.) or not (which reduces the total output of the tool) |
+ * @param seasonBegin the month and date (MM-dd) of the start of a seasonal analysis to be averaged over the period of data |
+ * @param seasonEnd the month and date (MM-dd) of the end of a seasonal analysis to be averaged over the period of data |
+ * @return an Object[] containing the updated statsSummaryTable at returnObject[0] and the m-day-average minimum-flow at returnObject[1] |
* @throws IOException |
*/ |
private Object[] calculateFlowStatistics(String[][] statsSummaryTable, |
@@ -596,7 +600,7 @@ |
double centroid = centroidSum / sum; |
|
//Calculate 3-day statistics |
- Object[] resultArray = getMdayData(flowData, 3); |
+ Object[] resultArray = doubleArray.getMdayData(flowData, 3); |
ArrayList<String> average_3day_date = (ArrayList<String>) resultArray[0]; |
ArrayList<Double> average_3day = (ArrayList<Double>) resultArray[1]; |
double max_3day = doubleMath.max(average_3day); |
@@ -605,7 +609,7 @@ |
String min_3day_date = getDateOfValue(average_3day_date, average_3day, min_3day); |
|
//Calculate 7-day statistics |
- resultArray = getMdayData(flowData, 7); |
+ resultArray = doubleArray.getMdayData(flowData, 7); |
ArrayList<String> average_7day_date = (ArrayList<String>) resultArray[0]; |
ArrayList<Double> average_7day = (ArrayList<Double>) resultArray[1]; |
double max_7day = doubleMath.max(average_7day); |
@@ -615,7 +619,7 @@ |
String min_7day_date = getDateOfValue(average_7day_date, average_7day, min_7day); |
|
//Calculate 30-day statistics |
- resultArray = getMdayData(flowData, 30); |
+ resultArray = doubleArray.getMdayData(flowData, 30); |
ArrayList<String> average_30day_date = (ArrayList<String>) resultArray[0]; |
ArrayList<Double> average_30day = (ArrayList<Double>) resultArray[1]; |
double max_30day = doubleMath.max(average_30day); |
@@ -624,7 +628,7 @@ |
String min_30day_date = getDateOfValue(average_30day_date, average_30day, min_30day); |
|
//Calculate 90-day statistics |
- resultArray = getMdayData(flowData, 90); |
+ resultArray = doubleArray.getMdayData(flowData, 90); |
ArrayList<String> average_90day_date = (ArrayList<String>) resultArray[0]; |
ArrayList<Double> average_90day = (ArrayList<Double>) resultArray[1]; |
double max_90day = doubleMath.max(average_90day); |
@@ -635,7 +639,7 @@ |
//Calculate mQn (7Q10)Statistics |
double min_Mday = 0; |
if(m != 0){ |
- resultArray = getMdayData(flowData, m); |
+ resultArray = doubleArray.getMdayData(flowData, m); |
ArrayList<Double> average_Mday = (ArrayList<Double>) resultArray[1]; |
min_Mday = doubleMath.min(average_Mday); |
} |
@@ -853,64 +857,6 @@ |
return returnArray; |
} |
/** |
- * Loops through and finds "m-day" consecutive values and takes the average of them |
- * @param flowData a string[][] containing: column1 = dates, column2 = flowValues |
- * @param numDays an integer representing the number (m) of consecutive days to be desired for analysis |
- * @returns an ArrayList containing an ArrayList of each set of "m-day" consecutive set of flows for analysis (min, max, average, etc) |
- * @throws IOException |
- */ |
- private Object[] getMdayData(String[][] flowData, int numDays) throws IOException{ |
- DoubleMath doubleMath = new DoubleMath(); |
- DoubleArray doubleArray = new DoubleArray(); |
- |
- //Loop through flow data and find "m"-day consecutive flows |
- ArrayList<String> allDate = new ArrayList<String>(); |
- ArrayList<Double> allData = new ArrayList<Double>(); |
- try{ |
- for(int i=0; i<flowData.length; i++){ |
- ArrayList<String> mDayDate = new ArrayList<String>(); |
- ArrayList<Double> mDayData = new ArrayList<Double>(); |
- int ctr = i; |
- for(int j=0; j<numDays; j++){ |
- if(j==0){ |
- //Keep the first day |
- mDayDate.add(flowData[ctr][0]); |
- mDayData.add(Double.parseDouble(flowData[ctr][1])); |
- }else{ |
- //Compare the current day to the previous day for consecutive-ness |
- boolean checkNextDate = doubleArray.checkSubsequentDates(flowData[ctr-1][0], flowData[ctr][0]); |
- if(checkNextDate){ |
- mDayDate.add(flowData[ctr][0]); |
- mDayData.add(Double.parseDouble(flowData[ctr][1])); |
- }else{ |
- //If not consecutive days, break out of the loop and move to the next date for flowData |
- mDayDate.clear(); |
- mDayData.clear(); |
- i = ctr - 1;//Skip to newest date since there is a break in the consecutive day data |
- break; |
- } |
- } |
- ctr++; |
- } |
- if(mDayData.size() == numDays){ |
- //Add this m-consecutive day set of data to the all data array list for statistics later |
- String startDate = mDayDate.get(0); |
- String endDate = mDayDate.get(numDays - 1); |
- allDate.add(startDate + " to " + endDate); |
- allData.add(doubleMath.meanArithmetic(mDayData)); |
- } |
- } |
- }catch(ArrayIndexOutOfBoundsException e){ |
- //If the consecutive day counter (ctr) goes beyond the length of data available, |
- //stop the subroutine and return the existing results |
- Object[] returnArray = {allDate, allData}; |
- return returnArray; |
- } |
- |
- Object[] returnArray = {allDate, allData}; |
- return returnArray; |
- } |
- /** |
* Loop through the provided data array and gets the corresponding index to 'value' and returns that index from the dates array |
* @param dates a list of dates |
* @param data a list of values corresponding to the dates in the above list |
@@ -53,6 +53,7 @@ |
String period3End = ""; |
double highPercentile = 0.75; |
double lowPercentile = 0.25; |
+ boolean showMonthlyStatsTF = false; |
String mQnPeriod = "false";//"7Q10";// |
String userData = "";//"Date\tFlow\n1999-04-29\t8.3\n1999-05-09\t60.2\n1999-05-29\t20.1$$Date\t00600\n1999-04-29\t8.3\n1999-05-09\t60.2\n1999-05-29\t20.1";//"Date\tFlow\n1999-04-29\t8.3\n1999-05-09\t60.2\n1999-05-29\t20.1";// |
boolean mergeDatasets = false;//true;// |
@@ -201,6 +202,9 @@ |
public void setLowPercentile(double lowPercentile) { |
this.lowPercentile = lowPercentile; |
} |
+ public void setShowMonthlyStatsTF(boolean showMonthlyStatsTF) { |
+ this.showMonthlyStatsTF = showMonthlyStatsTF; |
+ } |
public void setMQNperiod(String mQnPeriod) { |
this.mQnPeriod = mQnPeriod; |
} |
@@ -292,7 +296,7 @@ |
|
//Calculate the flow stats file |
FlowStatistics flowStats = new FlowStatistics(); |
- Object[] returnValue = flowStats.calculateAllStatisticsSummaries(mainFolder, stationID, stationName, sortedData_combined, highPercentile, lowPercentile, m, n, true, |
+ Object[] returnValue = flowStats.calculateAllStatisticsSummaries(mainFolder, stationID, stationName, sortedData_combined, highPercentile, lowPercentile, m, n, showMonthlyStatsTF, |
seasonBegin, seasonEnd, period1Begin, period1End, period2Begin, period2End, period3Begin, period3End); |
double mQn = (Double) returnValue[0]; |
String MQNmessage = (String) returnValue[1]; |
@@ -677,7 +681,7 @@ |
|
//Calculate the flow stats file |
FlowStatistics flowStats = new FlowStatistics(); |
- Object[] returnValue = flowStats.calculateAllStatisticsSummaries(mainFolder, stationID, stationName, sortedData_combined, highPercentile, lowPercentile, m, n, true, |
+ Object[] returnValue = flowStats.calculateAllStatisticsSummaries(mainFolder, stationID, stationName, sortedData_combined, highPercentile, lowPercentile, m, n, showMonthlyStatsTF, |
seasonBegin, seasonEnd, period1Begin, period1End, period2Begin, period2End, period3Begin, period3End); |
double mQn = (Double) returnValue[0]; |
String MQNmessage = (String) returnValue[1]; |
@@ -69,6 +69,7 @@ |
boolean medianTF = false; |
double highPercentile = 0.75; |
double lowPercentile = 0.25; |
+ boolean showMonthlyStatsTF = false; |
String userData = "";//"Date\tFlow\n1999-04-29\t8.3\n1999-05-09\t60.2\n1999-05-29\t20.1";// |
boolean mergeDatasets = false;//true;// |
String mergeMethod = "user";//"public";//"max";//"average";//"min";// |
@@ -413,6 +414,9 @@ |
public void setLowPercentile(double lowPercentile) { |
this.lowPercentile = lowPercentile; |
} |
+ public void setShowMonthlyStatsTF(boolean showMonthlyStatsTF) { |
+ this.showMonthlyStatsTF = showMonthlyStatsTF; |
+ } |
public void setUserData(String userData) { |
this.userData = userData; |
} |
@@ -1828,7 +1832,7 @@ |
FlowStatistics flowStats = new FlowStatistics(); |
if(wqTest.equalsIgnoreCase("flow")){ |
//Calculate Hydrologic Indicators of Alteration |
- flowStats.calculateAllStatisticsSummaries(mainFolder, stationID, stationName, sortedData_combined, highPercentile, lowPercentile, 0, 0, true, |
+ flowStats.calculateAllStatisticsSummaries(mainFolder, stationID, stationName, sortedData_combined, highPercentile, lowPercentile, 0, 0, showMonthlyStatsTF, |
seasonBegin, seasonEnd, period1Begin, period1End, period2Begin, period2End, period3Begin, period3End); |
}else{ |
//Report that there cannot be flow statistics for water quality data |