@@ -1,6 +1,7 @@ |
package cfa; |
import java.awt.BasicStroke; |
import java.awt.Color; |
+import java.awt.Paint; |
import java.awt.Stroke; |
import java.awt.geom.Ellipse2D; |
import java.awt.geom.Rectangle2D; |
@@ -16,6 +17,7 @@ |
import java.util.GregorianCalendar; |
import org.jfree.chart.ChartUtilities; |
import org.jfree.chart.JFreeChart; |
+import org.jfree.chart.axis.AxisLocation; |
import org.jfree.chart.axis.CategoryAxis; |
import org.jfree.chart.axis.CategoryLabelPositions; |
import org.jfree.chart.axis.DateAxis; |
@@ -23,23 +25,31 @@ |
import org.jfree.chart.axis.NumberAxis; |
import org.jfree.chart.axis.NumberTickUnit; |
import org.jfree.chart.axis.ValueAxis; |
+import org.jfree.chart.block.BlockBorder; |
import org.jfree.chart.plot.CategoryPlot; |
import org.jfree.chart.plot.XYPlot; |
+import org.jfree.chart.renderer.LookupPaintScale; |
import org.jfree.chart.renderer.category.BarRenderer; |
+import org.jfree.chart.renderer.xy.XYBlockRenderer; |
import org.jfree.chart.renderer.xy.XYItemRenderer; |
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; |
import org.jfree.chart.title.LegendTitle; |
+import org.jfree.chart.title.PaintScaleLegend; |
import org.jfree.data.category.DefaultCategoryDataset; |
import org.jfree.data.time.Day; |
import org.jfree.data.time.Month; |
import org.jfree.data.time.TimeSeries; |
import org.jfree.data.time.Year; |
+import org.jfree.data.xy.AbstractXYZDataset; |
import org.jfree.data.xy.XYDataset; |
import org.jfree.data.xy.XYSeries; |
import org.jfree.data.xy.XYSeriesCollection; |
+import org.jfree.data.xy.XYZDataset; |
+import org.jfree.ui.RectangleEdge; |
+import org.jfree.ui.RectangleInsets; |
|
/** |
-* Last Updated: 10-November-2015 |
+* Last Updated: 8-January-2016 |
* @author Tyler Wible |
* @since 24-June-2011 |
*/ |
@@ -48,7 +58,7 @@ |
String mainFolder = "C:/Projects/TylerWible/CodeDirectories/NetBeans/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 = "06764880";//"CLAGRECO";//"000028";// |
+ String stationID = "10328000";//"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 = ""; |
@@ -66,11 +76,13 @@ |
String period3Begin = ""; |
String period3End = ""; |
boolean medianTF = false; |
+ boolean envelopeTF = true; |
+ boolean rasterTF = true; |
double highPercentile = 0.75; |
double lowPercentile = 0.25; |
boolean showMonthlyStatsTF = false; |
boolean calcFlowStatisticsFileTF = true; |
- boolean calcCDPHElowflowTF = true; |
+ boolean calcCDPHElowflowTF = false; |
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" |
@@ -216,6 +228,9 @@ |
public String getTimeseriesEnvelope() { |
return "timeseries_envelope.jpg"; |
} |
+ public String getTimeseriesRaster() { |
+ return "timeseries_raster.jpg"; |
+ } |
public String getMonthlyGraph() { |
return "timeseries_monthlygraph.jpg"; |
} |
@@ -530,6 +545,12 @@ |
public void setMedianTF(boolean medianTF) { |
this.medianTF = medianTF; |
} |
+ public void setEnvelopeTF(boolean envelopeTF) { |
+ this.envelopeTF = envelopeTF; |
+ } |
+ public void setRasterTF(boolean rasterTF) { |
+ this.rasterTF = rasterTF; |
+ } |
public void setHighPercentile(double highPercentile) { |
this.highPercentile = highPercentile; |
} |
@@ -1362,38 +1383,144 @@ |
//Output monthly boxplot and timeseries data for use with JHighCharts |
doubleArray.writeXYseries(mainFolder, graphData, getTimeseriesEnvelopeOutput().getName()); |
|
- //Create Y Axis |
- if(logYaxis_TF){ |
- LogarithmicAxis rangeAxis = new LogarithmicAxis(yAxisTitle); |
- rangeAxis.setAllowNegativesFlag(true); |
- plot.setRangeAxis(0, rangeAxis); |
- }else{ |
- ValueAxis rangeAxis = new NumberAxis(yAxisTitle); |
- plot.setRangeAxis(0, rangeAxis); |
+ //Check if the user desires a raster graph |
+ if(rasterTF){ |
+ createRasterGraph(graphData, yAxisTitle); |
} |
|
+ //Check if the user desires an envelope graph |
+ if(envelopeTF){ |
+ //Create Y Axis |
+ if(logYaxis_TF){ |
+ LogarithmicAxis rangeAxis = new LogarithmicAxis(yAxisTitle); |
+ rangeAxis.setAllowNegativesFlag(true); |
+ plot.setRangeAxis(0, rangeAxis); |
+ }else{ |
+ ValueAxis rangeAxis = new NumberAxis(yAxisTitle); |
+ 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 time series (z) verses the month/day (x) per each year (y) |
+ * and save the resulting graph to the specified location. |
+ */ |
+ private void createRasterGraph(String[][] envelopePlotData, String zAxisTitle) throws IOException { |
+ DoubleMath doubleMath = new DoubleMath(); |
+ Graphing graphing = new Graphing(); |
+ |
+ //Manipulate envelope plot data into raster plot data format |
+ ArrayList<Double> tempData_dayOfYear = new ArrayList<Double>(); |
+ ArrayList<Double> tempData_year = new ArrayList<Double>(); |
+ ArrayList<Double> tempData_value = new ArrayList<Double>(); |
+ double currentYear = Double.parseDouble(end.substring(0,4)); |
+ for(int j=3; j< envelopePlotData[0].length; j=j+2){//skip the first 'average' data |
+ for(int i=0; i<366; i++){//day loop |
+ double value = Double.parseDouble(envelopePlotData[i][j]); |
+ if(value > -1){ |
+ tempData_dayOfYear.add((double) i+1); |
+ tempData_year.add(currentYear); |
+ tempData_value.add(value); |
+ } |
+ } |
+ currentYear--; |
+ } |
+ double[][] rasterData = new double[tempData_dayOfYear.size()][3]; |
+ for(int i=0; i<tempData_dayOfYear.size(); i++){ |
+ rasterData[i][0] = tempData_dayOfYear.get(i); |
+ rasterData[i][1] = tempData_year.get(i); |
+ rasterData[i][2] = tempData_value.get(i); |
+ } |
+ |
+ //Renderer |
+ XYZDataset xyzRasterData = new XYZArrayDataset(rasterData); |
+ XYBlockRenderer renderer = new XYBlockRenderer(); |
+ LookupPaintScale paintScale = new LookupPaintScale(doubleMath.min(tempData_value),doubleMath.max(tempData_value),Color.lightGray); |
+ Paint [] contourColors = getFullRainBowScale(); |
+ double delta = (Math.log(doubleMath.max(tempData_value)) - Math.log(doubleMath.min(tempData_value) + 0.001))/(contourColors.length -1); |
+ double value = Math.log(doubleMath.max(tempData_value)); |
+ for(int i=0; i<contourColors.length; i++){ |
+ paintScale.add(Math.exp(value), contourColors[i]); |
+ value = value - delta; |
+ } |
+ paintScale.add(0, Color.blue); |
+ renderer.setPaintScale(paintScale); |
+ |
+ //Put the line data, renderer, and axis into plot |
+ XYPlot plot = new XYPlot(); |
+ plot.setDataset(0, xyzRasterData); |
+ plot.setRenderer(0, renderer); |
+ |
+ //Put the line on the first Domain and first Range |
+ plot.mapDatasetToDomainAxis(0, 0); |
+ plot.mapDatasetToRangeAxis(0, 0); |
+ |
+ //Create Y Axis |
+ ValueAxis rangeAxis = new NumberAxis("Year"); |
+ rangeAxis.setRange(Double.parseDouble(start.substring(0,4)), Double.parseDouble(end.substring(0,4))); |
+ rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); |
+ 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); |
+ ValueAxis domainAxis = new NumberAxis("Day of Year"); |
+ domainAxis.setLowerMargin(0.0); |
+ domainAxis.setUpperMargin(0.0); |
+ plot.setDomainAxis(0, domainAxis); |
|
//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); |
+ String graphTitle = "Raster Graph for " + database + " Station: " + stationID + "; " + stationName; |
+ JFreeChart chart = new JFreeChart(graphTitle, graphing.titleFont, plot, false); |
|
- //Set legend Font |
- LegendTitle legendTitle = chart.getLegend(); |
- legendTitle.setItemFont(graphing.masterFont); |
+ //Add scale/legend |
+ LogarithmicAxis scaleAxis = new LogarithmicAxis(zAxisTitle);//NumberAxis scaleAxis = new NumberAxis("Scale"); |
+ scaleAxis.setAxisLinePaint(Color.white); |
+ scaleAxis.setTickMarkPaint(Color.white); |
+ scaleAxis.setTickLabelFont(graphing.masterFont); |
+ scaleAxis.setLabelFont(graphing.masterFont); |
+ PaintScaleLegend legend = new PaintScaleLegend(paintScale, scaleAxis); |
+ legend.setAxisLocation(AxisLocation.BOTTOM_OR_LEFT); |
+ legend.setAxisOffset(5.0); |
+ legend.setMargin(new RectangleInsets(5, 5, 5, 5)); |
+ legend.setFrame(new BlockBorder(Color.black)); |
+ legend.setPadding(new RectangleInsets(10, 10, 10, 10)); |
+ legend.setPosition(RectangleEdge.RIGHT); |
+ chart.addSubtitle(legend); |
|
//Save monthly timeseries graph for use later |
try{ |
- String path = mainFolder + File.separator + getTimeseriesEnvelope(); |
+ String path = mainFolder + File.separator + getTimeseriesRaster(); |
ChartUtilities.saveChartAsJPEG(new File(path), chart, 1280, 800); |
System.out.println("JFreeChart created properly at: " + path); |
|
@@ -1401,6 +1528,60 @@ |
System.err.println("A problem occurred while trying to creating the chart."); |
} |
} |
+ private static class XYZArrayDataset extends AbstractXYZDataset{ |
+ double[][] data; //{{x1, y1, z1}, {x2, y2, z2}, ...{xN, yN, zN}} |
+ int rowCount = 0; |
+ int columnCount = 0; |
+ |
+ XYZArrayDataset(double[][] data){ |
+ this.data = data; |
+ rowCount = data.length; |
+ columnCount = data[0].length; |
+ } |
+ public int getSeriesCount(){ |
+ return 1; |
+ } |
+ public Comparable getSeriesKey(int series){ |
+ return "serie"; |
+ } |
+ public int getItemCount(int series){ |
+ return rowCount; |
+ } |
+ public double getXValue(int series,int item){ |
+ return data[item][0]; |
+ } |
+ public double getYValue(int series,int item){ |
+ return data[item][1]; |
+ } |
+ public double getZValue(int series,int item){ |
+ return data[item][2]; |
+ } |
+ public Number getX(int series,int item){ |
+ return data[item][0]; |
+ } |
+ public Number getY(int series,int item){ |
+ return data[item][1]; |
+ } |
+ public Number getZ(int series,int item){ |
+ return data[item][2]; |
+ } |
+ } |
+ private static Paint[] getFullRainBowScale(){ |
+ // minimum of about 200 to not have perceptible steps in color scale |
+ // whether or not perceptible color gradients show depend upon the |
+ // legend size and the monitor settings |
+ int ncolor = 360; |
+ Color [] rainbow = new Color[ncolor]; |
+ // divide the color wheel up into more than ncolor pieces |
+ // but don't go all of the way around the wheel, or the first color |
+ // will repeat. The 60 value is about a minimum of 40, or the |
+ // red color will repeat. Too large a value, and there will be no magenta. |
+ float x = (float) (1./(ncolor + 170.)); |
+ for (int i=0; i < rainbow.length; i++){ |
+ rainbow[i] = new Color( Color.HSBtoRGB((i)*x,1.0F,1.0F)); |
+ } |
+ return rainbow; |
+ } |
/** |
* Graph a histogram of the time series and user data and save the resulting graph to the specified location |
* @param sortedData the String[][] containing sorted data for the time series |
@@ -2151,7 +2332,9 @@ |
FlowStatistics flowStats = new FlowStatistics(); |
if(wqTest.equalsIgnoreCase("flow")){ |
//Create Envelope Graph |
- createTimeseriesEnvelopeGraph(sortedData_combined, yAxisTitle, true); |
+ if(envelopeTF || rasterTF){ |
+ createTimeseriesEnvelopeGraph(sortedData_combined, yAxisTitle, true); |
+ } |
|
//Calculate Hydrologic Indicators of Alteration |
if(calcFlowStatisticsFileTF){ |