@@ -16,8 +16,11 @@ |
import org.jfree.chart.plot.XYPlot; |
import org.jfree.chart.renderer.xy.XYItemRenderer; |
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; |
+import org.jfree.data.time.Day; |
+import org.jfree.data.time.Month; |
import org.jfree.data.time.TimeSeries; |
import org.jfree.data.time.TimeSeriesCollection; |
+import org.jfree.data.time.Year; |
import org.jfree.data.xy.XYDataset; |
import org.jfree.data.xy.XYSeries; |
import org.jfree.data.xy.XYSeriesCollection; |
@@ -26,7 +29,7 @@ |
import org.jfree.ui.TextAnchor; |
|
/** |
-* Last Updated: 5-June-2014 |
+* Last Updated: 18-June-2014 |
* @author Tyler Wible |
* @since 3-February-2014 |
*/ |
@@ -246,6 +249,82 @@ |
return plot; |
} |
/** |
+ * Graphs the provided "series" as an XY series with x as the first column y as the second column in the provided color |
+ * on the provided XYPlot, this series is not visible in the legend |
+ * @param plot the XYPlot to add the "series" to |
+ * @param series a String[][] array with series[all][0] = dates in yyyy-MM-dd format, series[all][1] = y-values |
+ * @param timeStep a flag for what data is being graphed ("Daily", "Monthly", or "Yearly") |
+ * @param seriesName the name of the series to appear in the legend (if showInLegend is true) |
+ * @param lineColor the color of the line to be graphed |
+ * @param seriesIndex the graph index of the series to be plotted |
+ * @param showInLegend a flag to show this series in the legend (true) or not (false) |
+ * @param leapYearTF a flag to check if the main dataset is a leap year or not so that if graphing data repeatedly for one year (see timeseries envelope graph) Feb. 29th does or doesnot get plotted |
+ * @return the provided XYPlot with the series added to it with the above properties |
+ */ |
+ public XYPlot graphSeries(XYPlot plot, |
+ String[][] series, |
+ String timeStep, |
+ String seriesName, |
+ Color lineColor, |
+ int seriesIndex, |
+ boolean showInLegend, |
+ boolean leapYearTF){ |
+ TimeSeries timeSeries = new TimeSeries(seriesName); |
+ for(int i=0; i<series.length; i++){ |
+ String tmpStr = series[i][0]; |
+ double value = Double.parseDouble(series[i][1]); |
+ |
+ if(timeStep.equalsIgnoreCase("daily")){ |
+ double d = Double.parseDouble(tmpStr.substring(8)); |
+ double m = Double.parseDouble(tmpStr.substring(5,7)); |
+ double y = Double.parseDouble(tmpStr.substring(0,4)); |
+ int day = (int)d; |
+ int month = (int)m; |
+ int year = (int)y; |
+ try{ |
+ Day date = new Day(day,month,year);//day,month,year |
+ timeSeries.add(date, value); |
+ }catch(IllegalArgumentException e){ |
+ //If there is an error with the date and it is not due to trying |
+ //to plot Feb. 29th in a non-leap year then throw the error |
+ if(!leapYearTF && month!=2 && day!=29){ |
+ throw new IllegalArgumentException (e); |
+ } |
+ } |
+ |
+ }else if(timeStep.equalsIgnoreCase("monthly")){ |
+ double m = Double.parseDouble(tmpStr.substring(5,7)); |
+ double y = Double.parseDouble(tmpStr.substring(0,4)); |
+ int month = (int)m; |
+ int year = (int)y; |
+ Month date = new Month(month,year);//month,year |
+ timeSeries.add(date, value); |
+ |
+ }else if(timeStep.equalsIgnoreCase("yearly")){ |
+ double y = Double.parseDouble(tmpStr.substring(0,4)); |
+ int year = (int)y; |
+ Year date = new Year(year);//year |
+ timeSeries.add(date, value); |
+ } |
+ } |
+ |
+ //Create a graph with the line |
+ TimeSeriesCollection currentDataset = new TimeSeriesCollection(timeSeries); |
+ XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false); |
+ renderer.setSeriesPaint(0, lineColor); |
+ renderer.setSeriesVisibleInLegend(0, showInLegend); |
+ |
+ //Set the line data, renderer, and axis into plot |
+ plot.setDataset(seriesIndex, currentDataset); |
+ plot.setRenderer(seriesIndex, renderer); |
+ |
+ //Map the line to the first Domain and first Range |
+ plot.mapDatasetToDomainAxis(0, 0); |
+ plot.mapDatasetToRangeAxis(0, 0); |
+ |
+ return plot; |
+ } |
+ /** |
* Graphs the TimeSeries on to the provided plot with the below properties for rendering, color, series index |
* @param plot The XYPlot to graph the XYSeries on |
* @param currentLine the XYSeries containing the x,y points of the current line series |
@@ -305,7 +384,7 @@ |
)); |
} |
|
- //Put the LDC line data, renderer, and axis into plot |
+ //Put the line data, renderer, and axis into plot |
plot.setDataset(graphIndex, currentDataset); |
plot.setRenderer(graphIndex, currentRenderer); |
|
@@ -13,7 +13,9 @@ |
import java.text.SimpleDateFormat; |
import java.util.ArrayList; |
import java.util.Arrays; |
+import java.util.Calendar; |
import java.util.Date; |
+import java.util.GregorianCalendar; |
import org.jfree.chart.ChartUtilities; |
import org.jfree.chart.JFreeChart; |
import org.jfree.chart.axis.CategoryAxis; |
@@ -33,13 +35,14 @@ |
import org.jfree.data.time.Day; |
import org.jfree.data.time.Month; |
import org.jfree.data.time.TimeSeries; |
+import org.jfree.data.time.TimeSeriesCollection; |
import org.jfree.data.time.Year; |
import org.jfree.data.xy.XYDataset; |
import org.jfree.data.xy.XYSeries; |
import org.jfree.data.xy.XYSeriesCollection; |
|
/** |
-* Last Updated: 9-July-2014 |
+* Last Updated: 18-July-2014 |
* @author Tyler Wible |
* @since 24-June-2011 |
*/ |
@@ -150,6 +153,10 @@ |
//This output file is for use with JSHighCharts |
return new File(mainFolder, "timeseries_monthlyboxplot.out"); |
} |
+ public File getTimeseriesEnvelopeOutput(){ |
+ //This output file is for use with JSHighCharts |
+ return new File(mainFolder, "timeseries_envelope.out"); |
+ } |
public File getHistogramOutput(){ |
//This output file is for use with JSHighCharts |
return new File(mainFolder, "timeseries_histogram.outt"); |
@@ -165,12 +172,15 @@ |
public String getBoxplot() { |
return "timeseries_boxplot.jpg"; |
} |
- public String getHistogram() { |
- return "timeseries_histogram.jpg"; |
+ public String getTimeseriesEnvelope() { |
+ return "timeseries_envelope.jpg"; |
} |
public String getMonthlyGraph() { |
return "timeseries_monthlygraph.jpg"; |
} |
+ public String getHistogram() { |
+ return "timeseries_histogram.jpg"; |
+ } |
public String getCDF() { |
return "timeseries_cdf.jpg"; |
} |
@@ -1012,6 +1022,182 @@ |
} |
} |
/** |
+ * Graph the time series verses the month/day for each year and long term average/median |
+ * and user data and save the resulting graph to the specified location. |
+ * @param sortedData the String[][] containing sorted data for the time series |
+ * (column 1 = dates (yyyy-mm-dd), column 2 = value |
+ * @param yAxisTitle the String label for the y axis of the graph |
+ */ |
+ private void createTimeseriesEnvelopeGraph(String[][] sortedData, |
+ String yAxisTitle) throws IOException { |
+ DoubleArray doubleArray = new DoubleArray(); |
+ DoubleMath doubleMath = new DoubleMath(); |
+ Graphing graphing = new Graphing(); |
+ |
+ //Initialize variables |
+ String currentYear = start.substring(0,4); |
+ String finalYear = end.substring(0,4); |
+ boolean leapYearTF = doubleArray.getLeapYearTF(Integer.parseInt(finalYear)); |
+ String[][] graphData = new String[366][2]; |
+ String[] dayList = new String[366]; |
+ int seriesIndex = 0; |
+ |
+ //Plot each year and the long term average and the most recent year |
+ XYPlot plot = new XYPlot(); |
+ String longTermSeriesName = "Average"; |
+ if(medianTF) longTermSeriesName = "Median"; |
+ TimeSeries timeSeries = new TimeSeries(longTermSeriesName); |
+ for(int j=1; j<=366; j++){ |
+ ArrayList<Double> dateData = new ArrayList<Double>(); |
+ dayList[j-1] = String.valueOf(j); |
+ |
+ for(int i=0; i<sortedData.length; i++){ |
+ double value = Double.parseDouble(sortedData[i][1]); |
+ double d = Double.parseDouble(sortedData[i][0].substring(8)); |
+ double m = Double.parseDouble(sortedData[i][0].substring(5,7)); |
+ double y = Double.parseDouble(sortedData[i][0].substring(0,4)); |
+ int day = (int)d; |
+ int month = (int)m; |
+ int year = (int)y; |
+ Calendar currentDate = new GregorianCalendar(year,month - 1, day); |
+ if(currentDate.get(Calendar.DAY_OF_YEAR) == j){ |
+ dateData.add(value); |
+ } |
+ } |
+ //Calculate average/median |
+ double dayValue = 0; |
+ if(medianTF){ |
+ dayValue = doubleMath.Median(dateData); |
+ }else{ |
+ dayValue = doubleMath.Average(dateData); |
+ } |
+ |
+ //Save the results for this day of the year |
+ if(leapYearTF){ |
+ Calendar currentDate = new GregorianCalendar(2000, 0, 1); |
+ currentDate.set(Calendar.DAY_OF_YEAR, j); |
+ Day graphDay = new Day(currentDate.get(Calendar.DAY_OF_MONTH), currentDate.get(Calendar.MONTH) + 1, Integer.parseInt(finalYear)); |
+ timeSeries.add(graphDay, dayValue); |
+ graphData[j-1][0] = String.valueOf(j); |
+ graphData[j-1][1] = String.valueOf(dayValue); |
+ }else{ |
+ if(j !=366){ |
+ Calendar currentDate = new GregorianCalendar(2001, 0, 1); |
+ currentDate.set(Calendar.DAY_OF_YEAR, j); |
+ Day graphDay = new Day(currentDate.get(Calendar.DAY_OF_MONTH), currentDate.get(Calendar.MONTH) + 1, Integer.parseInt(finalYear)); |
+ timeSeries.add(graphDay, dayValue); |
+ graphData[j-1][0] = String.valueOf(j); |
+ graphData[j-1][1] = String.valueOf(dayValue); |
+ } |
+ } |
+ } |
+ |
+ //Create renderer, and axis for timeseries graph |
+ TimeSeriesCollection currentDataset = new TimeSeriesCollection(timeSeries); |
+ XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false); |
+ renderer.setSeriesPaint(seriesIndex, Color.BLACK); |
+ renderer.setSeriesStroke(seriesIndex, |
+ new BasicStroke( |
+ 3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, |
+ 1.0f, new float[] {6.0f, 0.0f}, 0.0f |
+ )); |
+ |
+ //Set the line data, renderer, and axis into plot |
+ plot.setDataset(seriesIndex, currentDataset); |
+ plot.setRenderer(seriesIndex, renderer); |
+ seriesIndex++; |
+ seriesIndex++;//Increase series so the most recent month can be plotted second |
+ |
+ //Map the line to the first Domain and first Range |
+ plot.mapDatasetToDomainAxis(0, 0); |
+ plot.mapDatasetToRangeAxis(0, 0); |
+ |
+ //Graph a line for each year of monthly data in time period |
+ boolean moreYears = sortedData.length > 0; |
+ while(moreYears){ |
+ //Get current year's data and graph it |
+ String[][] partialData = doubleArray.getYearsData(sortedData, currentYear); |
+ for(int i=0; i<partialData.length; i++){ |
+ String month_day = partialData[i][0].substring(5); |
+ partialData[i][0] = finalYear + "-" + month_day; |
+ } |
+ graphing.graphSeries(plot, partialData, "daily", "", Color.lightGray, seriesIndex, false, leapYearTF); |
+ seriesIndex++; |
+ |
+ //Save results for output for JHighCharts |
+ String[] partialDayData = new String[dayList.length]; |
+ int ctr = 0; |
+ for(int i=0; i<dayList.length; i++){ |
+ partialDayData[i] = "-1";//value |
+ try{ |
+ double d = Double.parseDouble(partialData[ctr][0].substring(8)); |
+ double m = Double.parseDouble(partialData[ctr][0].substring(5,7)); |
+ double y = Double.parseDouble(partialData[ctr][0].substring(0,4)); |
+ int day = (int)d; |
+ int month = (int)m; |
+ int year = (int)y; |
+ Calendar currentDate = new GregorianCalendar(year,month - 1, day); |
+ if(currentDate.get(Calendar.DAY_OF_YEAR) == (i+1)){ |
+ partialDayData[i] = partialData[ctr][1];//value |
+ ctr++; |
+ } |
+ }catch(IndexOutOfBoundsException e){ |
+ //do nothing as it already has a -1 value |
+ } |
+ } |
+ graphData = doubleArray.appendcolumn_Matrix(graphData, dayList);//Add list of days (aka x points) |
+ graphData = doubleArray.appendcolumn_Matrix(graphData, partialDayData);//Add day values (aka y points) |
+ |
+ //Determine the next data year to continue looping over |
+ int nextYear = Integer.parseInt(currentYear) + 1; |
+ if(finalYear.compareToIgnoreCase(String.valueOf(nextYear)) >= 0){ |
+ currentYear = String.valueOf(nextYear); |
+ }else{ |
+ //Re-add the most recent year to the graph so it renders on top |
+ graphing.graphSeries(plot, partialData, "daily", finalYear, Color.red, 1, true, leapYearTF); |
+ moreYears = false; |
+ } |
+ } |
+ |
+ //Output monthly boxplot and timeseries data for use with JHighCharts |
+ doubleArray.writeXYseries(mainFolder, graphData, getTimeseriesEnvelopeOutput().getName()); |
+ |
+ //Create Y Axis |
+// ValueAxis rangeAxis = new NumberAxis(yAxisTitle); |
+ LogarithmicAxis rangeAxis = new LogarithmicAxis("Discharge [cfs]"); |
+ rangeAxis.setAllowNegativesFlag(true); |
+ plot.setRangeAxis(0, rangeAxis); |
+ |
+ //Create X Axis |
+ DateAxis domainTime = new DateAxis("Date"); |
+ domainTime.setLowerMargin(0.05); |
+ domainTime.setUpperMargin(0.05); |
+ SimpleDateFormat xlabelDateFormat = new SimpleDateFormat("MMM"); |
+ domainTime.setDateFormatOverride(xlabelDateFormat); |
+ plot.setDomainAxis(0, domainTime); |
+ |
+ //Set extra plot preferences |
+ plot = graphing.setAxisPreferences(plot); |
+ |
+ //Create the charts out of the plots |
+ String graphTitle = "Time Series Range for " + database + " Station: " + stationID + "; " + stationName; |
+ JFreeChart chart = new JFreeChart(graphTitle, graphing.titleFont, plot, true); |
+ |
+ //Set legend Font |
+ LegendTitle legendTitle = chart.getLegend(); |
+ legendTitle.setItemFont(graphing.masterFont); |
+ |
+ //Save monthly timeseries graph for use later |
+ try{ |
+ String path = mainFolder + File.separator + getTimeseriesEnvelope(); |
+ ChartUtilities.saveChartAsJPEG(new File(path), chart, 1280, 800); |
+ System.out.println("JFreeChart created properly at: " + path); |
+ |
+ }catch(IOException e){ |
+ System.err.println("A problem occurred while trying to creating the chart."); |
+ } |
+ } |
+ /** |
* Graph the monthly average time series and user data and save the resulting graph to the specified location. |
* Also creates a boxplot for each month's data in a new graph |
* @param sortedData the String[][] containing sorted data for the time series |
@@ -1356,7 +1542,11 @@ |
|
//Define other graph information |
graphUnits = "cfs"; |
- yAxisTitle = timeStep + " " + method + " Flow [" + graphUnits + "]"; |
+ if(timeStep.equalsIgnoreCase("Daily")){ |
+ yAxisTitle = timeStep + " Flow [" + graphUnits + "]"; |
+ }else{ |
+ yAxisTitle = timeStep + " " + method + " Flow [" + graphUnits + "]"; |
+ } |
monthlyYaxisTitle = "Monthly Average Flow [" + graphUnits + "]"; |
color = Color.blue; |
color2 = Color.DARK_GRAY; |
@@ -1369,7 +1559,11 @@ |
WQlabel = (String) returnArray[2]; |
|
//Define other graph information |
- yAxisTitle = timeStep + " " + method + " " + WQlabel + " [" + graphUnits + "]"; |
+ if(timeStep.equalsIgnoreCase("Daily")){ |
+ yAxisTitle = timeStep + " " + WQlabel + " [" + graphUnits + "]"; |
+ }else{ |
+ yAxisTitle = timeStep + " " + method + " " + WQlabel + " [" + graphUnits + "]"; |
+ } |
monthlyYaxisTitle = "Monthly Average " + WQlabel + " [" + graphUnits + "]"; |
color = Color.magenta; |
color2 = Color.BLUE; |
@@ -1410,6 +1604,7 @@ |
|
//Perform operations on daily data before it is converted to the user desired timeStep |
createTimeseriesMonthlyGraph(sortedData_combined, monthlyYaxisTitle); |
+ createTimeseriesEnvelopeGraph(sortedData_combined, yAxisTitle); |
FlowStatistics flowStats = new FlowStatistics(); |
if(wqTest.equalsIgnoreCase("flow")){ |
//Calculate Hydrologic Indicators of Alteration |