guiTimeseries_Model.java [src/java/m/cfa/timeseries] Revision: e17730f1469a79c99933dd778e05aa78d3cdb062 Date: Fri Feb 12 15:27:46 MST 2016
package m.cfa.timeseries;
import cfa.FlowStatistics;
import cfa.Data;
import cfa.DoubleArray;
import cfa.DoubleMath;
import cfa.Graphing;
import cfa.User_Data;
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;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
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.AxisLocation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.LogarithmicAxis;
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: 12-February-2016
* @author Tyler Wible
* @since 24-June-2011
*/
public class guiTimeseries_Model {
//Inputs
String mainFolder = "C:/Projects/TylerWible/CodeDirectories/NetBeans/data/CFA/Timeseries";
String database = "USGS";//"CDWR";//"STORET";//"UserData";//
String organizationID = "n/a";//"n/a";//"21COL001";
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 = "";
String endDate = "";
String timeStep = "Daily";//"Yearly";//"Monthly";//
String method = "Max";//"Min";//"Average";//"Total";//
int numBins = 10;
boolean logarithmicBinsTF = true;
String seasonBegin = "06-01";//"MM-dd"
String seasonEnd = "09-30";//"MM-dd"
String period1Begin = "";
String period1End = "";
String period2Begin = "";
String period2End = "";
String period3Begin = "";
String period3End = "";
boolean medianTF = false;
boolean envelopeTF = true;
boolean rasterTF = true;
boolean rasterLogarithmicBinsTF = true;
double highPercentile = 0.75;
double lowPercentile = 0.25;
boolean showMonthlyStatsTF = false;
boolean calcFlowStatisticsFileTF = 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"
String CDPHE_waterYearBegin = "04-01";//"MM-dd" //only used if CDPHE_lowFlowType == "all" or "extreme-value"
int CDPHE_clusterLength = 120; //only used if CDPHE_lowFlowType == "all" or "biological"
int CDPHE_clusterCountMax = 5; //only used if CDPHE_lowFlowType == "all" or "biological"
boolean mergeDatasets = false;//true;//
String mergeMethod = "user";//"public";//"max";//"average";//"min";//
String userData = "";//"Date\tFlow\n1999-04-29\t8.3\n1999-05-09\t60.2\n1999-05-29\t20.1";//
//Outputs
String len = "-1";
String start = "?";
String end = "?";
String units = "?";
String dataSource = "?";
double extremeValueDFLOW = -1;
double biologicalDFLOW_all = -1;
double biologicalDFLOW_jan = -1;
double biologicalDFLOW_feb = -1;
double biologicalDFLOW_mar = -1;
double biologicalDFLOW_apr = -1;
double biologicalDFLOW_may = -1;
double biologicalDFLOW_jun = -1;
double biologicalDFLOW_jul = -1;
double biologicalDFLOW_aug = -1;
double biologicalDFLOW_sep = -1;
double biologicalDFLOW_oct = -1;
double biologicalDFLOW_nov = -1;
double biologicalDFLOW_dec = -1;
double humanHealthDFLOW = -1;
String reg31DFLOWsummary = "?";
double max = -1;
double min = -1;
double upperQuartile = -1;
double lowerQuartile = -1;
double median = -1;
double mean = -1;
double standardDeviation = -1;
double variance = -1;
double skew = -1;
double coeffvar = -1;
double kendallCorlCoeff = -1;
String len_seasonal = "-1";
double max_seasonal = -1;
double min_seasonal = -1;
double upperQuartile_seasonal = -1;
double lowerQuartile_seasonal = -1;
double median_seasonal = -1;
double mean_seasonal = -1;
double standardDeviation_seasonal = -1;
double variance_seasonal = -1;
double skew_seasonal = -1;
double coeffvar_seasonal = -1;
double kendallCorlCoeff_seasonal = -1;
String len_period1 = "-1";
double max_period1 = -1;
double min_period1 = -1;
double upperQuartile_period1 = -1;
double lowerQuartile_period1 = -1;
double median_period1 = -1;
double mean_period1 = -1;
double standardDeviation_period1 = -1;
double variance_period1 = -1;
double skew_period1 = -1;
double coeffvar_period1 = -1;
double kendallCorlCoeff_period1 = -1;
String len_period2 = "-1";
double max_period2 = -1;
double min_period2 = -1;
double upperQuartile_period2 = -1;
double lowerQuartile_period2 = -1;
double median_period2 = -1;
double mean_period2 = -1;
double standardDeviation_period2 = -1;
double variance_period2 = -1;
double skew_period2 = -1;
double coeffvar_period2 = -1;
double kendallCorlCoeff_period2 = -1;
String len_period3 = "-1";
double max_period3 = -1;
double min_period3 = -1;
double upperQuartile_period3 = -1;
double lowerQuartile_period3 = -1;
double median_period3 = -1;
double mean_period3 = -1;
double standardDeviation_period3 = -1;
double variance_period3 = -1;
double skew_period3 = -1;
double coeffvar_period3 = -1;
double kendallCorlCoeff_period3 = -1;
//Gets
public File getParagraph() {
return new File(mainFolder, "timeseries_summary.txt");
}
public File getFlowStatistics_summary() {
FlowStatistics flowStats = new FlowStatistics();
return new File(mainFolder, flowStats.getFlowStatistics_summary());
}
public File getTimeseriesOutput(){
//This output file is for use with JSHighCharts
return new File(mainFolder, "timeseries_graph.out");
}
public File getBoxplotOutput(){
//This output file is for use with JSHighCharts
return new File(mainFolder, "timeseries_boxplot.out");
}
public File getMonthlyTimeseriesOutput(){
//This output file is for use with JSHighCharts
return new File(mainFolder, "timeseries_monthlygraph.out");
}
// public File getMonthlyBoxplotOutput(){
// //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");
//Note that this file has a different extension as a flag for eRAMS to parse the first column as strings not numbers
}
public File getCDFoutput(){
//This output file is for use with JSHighCharts
return new File(mainFolder, "timeseries_cdf.out");
}
public String getGraph() {
return "timeseries_graph.jpg";
}
public String getBoxplot() {
return "timeseries_boxplot.jpg";
}
public String getTimeseriesEnvelope() {
return "timeseries_envelope.jpg";
}
public String getTimeseriesRaster() {
return "timeseries_raster.jpg";
}
public String getMonthlyGraph() {
return "timeseries_monthlygraph.jpg";
}
public String getHistogram() {
return "timeseries_histogram.jpg";
}
public String getCDF() {
return "timeseries_cdf.jpg";
}
public String getLen(){
return len;
}
public String getStart(){
return start;
}
public String getEnd(){
return end;
}
public String getUnits(){
return units;
}
public String getDataSource(){
return dataSource;
}
public String getCDPHE_ExtremeValueDFLOW(){
return String.valueOf(extremeValueDFLOW);
}
public String getCDPHE_BiologicalDFLOW_all(){
return String.valueOf(biologicalDFLOW_all);
}
public String getCDPHE_BiologicalDFLOW_jan(){
return String.valueOf(biologicalDFLOW_jan);
}
public String getCDPHE_BiologicalDFLOW_feb(){
return String.valueOf(biologicalDFLOW_feb);
}
public String getCDPHE_BiologicalDFLOW_mar(){
return String.valueOf(biologicalDFLOW_mar);
}
public String getCDPHE_BiologicalDFLOW_apr(){
return String.valueOf(biologicalDFLOW_apr);
}
public String getCDPHE_BiologicalDFLOW_may(){
return String.valueOf(biologicalDFLOW_may);
}
public String getCDPHE_BiologicalDFLOW_jun(){
return String.valueOf(biologicalDFLOW_jun);
}
public String getCDPHE_BiologicalDFLOW_jul(){
return String.valueOf(biologicalDFLOW_jul);
}
public String getCDPHE_BiologicalDFLOW_aug(){
return String.valueOf(biologicalDFLOW_aug);
}
public String getCDPHE_BiologicalDFLOW_sep(){
return String.valueOf(biologicalDFLOW_sep);
}
public String getCDPHE_BiologicalDFLOW_oct(){
return String.valueOf(biologicalDFLOW_oct);
}
public String getCDPHE_BiologicalDFLOW_nov(){
return String.valueOf(biologicalDFLOW_nov);
}
public String getCDPHE_BiologicalDFLOW_dec(){
return String.valueOf(biologicalDFLOW_dec);
}
public String getCDPHE_HumanHealthDFLOW(){
return String.valueOf(humanHealthDFLOW);
}
public String getCDPHE_Reg31DFLOWsummary(){
return String.valueOf(reg31DFLOWsummary);
}
public String getMax(){
return String.valueOf(max);
}
public String getMin(){
return String.valueOf(min);
}
public String getUpperQuartile(){
return String.valueOf(upperQuartile);
}
public String getLowerQuartile(){
return String.valueOf(lowerQuartile);
}
public String getMedian(){
return String.valueOf(median);
}
public String getMean(){
return String.valueOf(mean);
}
public String getStandardDeviation(){
return String.valueOf(standardDeviation);
}
public String getVariance(){
return String.valueOf(variance);
}
public String getSkewness(){
return String.valueOf(skew);
}
public String getCoefficientOfVariation(){
return String.valueOf(coeffvar);
}
public String getKendallCorrelationCoefficient(){
return String.valueOf(kendallCorlCoeff);
}
public String getLen_seasonal(){
return len_seasonal;
}
public String getMax_seasonal(){
return String.valueOf(max_seasonal);
}
public String getMin_seasonal(){
return String.valueOf(min_seasonal);
}
public String getUpperQuartile_seasonal(){
return String.valueOf(upperQuartile_seasonal);
}
public String getLowerQuartile_seasonal(){
return String.valueOf(lowerQuartile_seasonal);
}
public String getMedian_seasonal(){
return String.valueOf(median_seasonal);
}
public String getMean_seasonal(){
return String.valueOf(mean_seasonal);
}
public String getStandardDeviation_seasonal(){
return String.valueOf(standardDeviation_seasonal);
}
public String getVariance_seasonal(){
return String.valueOf(variance_seasonal);
}
public String getSkewness_seasonal(){
return String.valueOf(skew_seasonal);
}
public String getCoefficientOfVariation_seasonal(){
return String.valueOf(coeffvar_seasonal);
}
public String getKendallCorrelationCoefficient_seasonal(){
return String.valueOf(kendallCorlCoeff_seasonal);
}
public String getLen_period1(){
return len_period1;
}
public String getMax_period1(){
return String.valueOf(max_period1);
}
public String getMin_period1(){
return String.valueOf(min_period1);
}
public String getUpperQuartile_period1(){
return String.valueOf(upperQuartile_period1);
}
public String getLowerQuartile_period1(){
return String.valueOf(lowerQuartile_period1);
}
public String getMedian_period1(){
return String.valueOf(median_period1);
}
public String getMean_period1(){
return String.valueOf(mean_period1);
}
public String getStandardDeviation_period1(){
return String.valueOf(standardDeviation_period1);
}
public String getVariance_period1(){
return String.valueOf(variance_period1);
}
public String getSkewness_period1(){
return String.valueOf(skew_period1);
}
public String getCoefficientOfVariation_period1(){
return String.valueOf(coeffvar_period1);
}
public String getKendallCorrelationCoefficient_period1(){
return String.valueOf(kendallCorlCoeff_period1);
}
public String getLen_period2(){
return len_period2;
}
public String getMax_period2(){
return String.valueOf(max_period2);
}
public String getMin_period2(){
return String.valueOf(min_period2);
}
public String getUpperQuartile_period2(){
return String.valueOf(upperQuartile_period2);
}
public String getLowerQuartile_period2(){
return String.valueOf(lowerQuartile_period2);
}
public String getMedian_period2(){
return String.valueOf(median_period2);
}
public String getMean_period2(){
return String.valueOf(mean_period2);
}
public String getStandardDeviation_period2(){
return String.valueOf(standardDeviation_period2);
}
public String getVariance_period2(){
return String.valueOf(variance_period2);
}
public String getSkewness_period2(){
return String.valueOf(skew_period2);
}
public String getCoefficientOfVariation_period2(){
return String.valueOf(coeffvar_period2);
}
public String getKendallCorrelationCoefficient_period2(){
return String.valueOf(kendallCorlCoeff_period2);
}
public String getLen_period3(){
return len_period3;
}
public String getMax_period3(){
return String.valueOf(max_period3);
}
public String getMin_period3(){
return String.valueOf(min_period3);
}
public String getUpperQuartile_period3(){
return String.valueOf(upperQuartile_period3);
}
public String getLowerQuartile_period3(){
return String.valueOf(lowerQuartile_period3);
}
public String getMedian_period3(){
return String.valueOf(median_period3);
}
public String getMean_period3(){
return String.valueOf(mean_period3);
}
public String getStandardDeviation_period3(){
return String.valueOf(standardDeviation_period3);
}
public String getVariance_period3(){
return String.valueOf(variance_period3);
}
public String getSkewness_period3(){
return String.valueOf(skew_period3);
}
public String getCoefficientOfVariation_period3(){
return String.valueOf(coeffvar_period3);
}
public String getKendallCorrelationCoefficient_period3(){
return String.valueOf(kendallCorlCoeff_period3);
}
//Sets
public void setMainFolder(String mainFolder) {
this.mainFolder = mainFolder;
}
public void setDatabase(String database) {
this.database = database;
}
public void setOrganizationID(String organizationID) {
this.organizationID = organizationID;
}
public void setBeginDate(String beginDate) {
this.beginDate = beginDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public void setStationName(String stationName) {
this.stationName = stationName;
}
public void setStationID(String stationID) {
this.stationID = stationID;
}
public void setWQtest(String wqTest) {
this.wqTest = wqTest;
}
public void setTimeStep(String timeStep) {
this.timeStep = timeStep;
}
public void setMethod(String method) {
this.method = method;
}
public void setNumberOfBins(int numBins) {
this.numBins = numBins;
}
public void setLogarithmicHistogramBins(boolean logarithmicBinsTF) {
this.logarithmicBinsTF = logarithmicBinsTF;
}
public void setSeasonBegin(String seasonBegin) {
this.seasonBegin = seasonBegin;
}
public void setSeasonEnd(String seasonEnd) {
this.seasonEnd = seasonEnd;
}
public void setPeriod1Begin(String period1Begin) {
this.period1Begin = period1Begin;
}
public void setPeriod1End(String period1End) {
this.period1End = period1End;
}
public void setPeriod2Begin(String period2Begin) {
this.period2Begin = period2Begin;
}
public void setPeriod2End(String period2End) {
this.period2End = period2End;
}
public void setPeriod3Begin(String period3Begin) {
this.period3Begin = period3Begin;
}
public void setPeriod3End(String period3End) {
this.period3End = period3End;
}
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 setRasterLogarithmicBinsTF(boolean rasterLogarithmicBinsTF) {
this.rasterLogarithmicBinsTF = rasterLogarithmicBinsTF;
}
public void setHighPercentile(double highPercentile) {
this.highPercentile = highPercentile;
}
public void setLowPercentile(double lowPercentile) {
this.lowPercentile = lowPercentile;
}
public void setShowMonthlyStatsTF(boolean showMonthlyStatsTF) {
this.showMonthlyStatsTF = showMonthlyStatsTF;
}
public void setCalcFlowStatisticsFileTF(boolean calcFlowStatisticsFileTF) {
this.calcFlowStatisticsFileTF = calcFlowStatisticsFileTF;
}
public void setCalcCDPHElowflowTF(boolean calcCDPHElowflowTF) {
this.calcCDPHElowflowTF = calcCDPHElowflowTF;
}
public void setCDPHE_lowFlowType(String CDPHE_lowFlowType) {
this.CDPHE_lowFlowType = CDPHE_lowFlowType;
}
public void setCDPHE_m(int CDPHE_m) {
this.CDPHE_m = CDPHE_m;
}
public void setCDPHE_R(int CDPHE_R) {
this.CDPHE_R = CDPHE_R;
}
public void setCDPHE_waterYearBegin(String CDPHE_waterYearBegin) {
this.CDPHE_waterYearBegin = CDPHE_waterYearBegin;
}
public void setCDPHE_clusterLength(int CDPHE_clusterLength) {
this.CDPHE_clusterLength = CDPHE_clusterLength;
}
public void setCDPHE_clusterCountMax(int CDPHE_clusterCountMax) {
this.CDPHE_clusterCountMax = CDPHE_clusterCountMax;
}
public void setMergeDatasets(boolean mergeDatasets) {
this.mergeDatasets = mergeDatasets;
}
public void setMergeMethod(String mergeMethod) {
this.mergeMethod = mergeMethod;
}
public void setUserData(String userData) {
this.userData = userData;
}
/**
* Main statistics function calls other functions to calculate each statistic value then stores the results as global variables
* @param dataList data on which statistical values are desired
* @param flag a flag for which results the statistics will be stored to, either "all", "period1", "period2", or "period3"
*/
private void CalculateStatistics(String[][] data, String flag) {
//Convert into double list
ArrayList<Double> dataList = new ArrayList<Double>();
for(int i=0; i<data.length; i++){
dataList.add(Double.parseDouble(data[i][1]));
}
//Calculate statistics
DoubleMath doubleMath = new DoubleMath();
double temp1 = doubleMath.round(doubleMath.max(dataList),3);//Call Max function
double temp2 = doubleMath.round(doubleMath.min(dataList),3);//Call Min function
double temp3 = doubleMath.round(doubleMath.Percentile_function(dataList,0.75),3);//Call Upper Quartile function
double temp4 = doubleMath.round(doubleMath.Percentile_function(dataList,0.25),3);//Call Lower Quartile function
double temp5 = doubleMath.round(doubleMath.median(dataList),3);//Call Median function
double temp6 = doubleMath.round(doubleMath.meanArithmetic(dataList),3);//Call Mean function
double temp7 = doubleMath.round(doubleMath.StandardDeviationSample(dataList),3);//Call standard deviation function
double temp8 = doubleMath.round(doubleMath.VarianceSample(dataList),3);//Call variance function
double temp9 = doubleMath.round(doubleMath.SkewnessSample(dataList),8);//Call skewness function
double temp10 = doubleMath.round(doubleMath.CoefficientOfVariation(dataList),3);//call coefficient of variation function
double temp11 = doubleMath.round(doubleMath.KendallCorrelationCoefficient(dataList), 4);
if(flag.equalsIgnoreCase("all")){
max = temp1;
min = temp2;
upperQuartile = temp3;
lowerQuartile = temp4;
median = temp5;
mean = temp6;
standardDeviation = temp7;
variance = temp8;
skew = temp9;
coeffvar = temp10;
kendallCorlCoeff = temp11;
}else if(flag.equalsIgnoreCase("seasonal")){
len_seasonal = String.valueOf(data.length);
max_seasonal = temp1;
min_seasonal = temp2;
upperQuartile_seasonal = temp3;
lowerQuartile_seasonal = temp4;
median_seasonal = temp5;
mean_seasonal = temp6;
standardDeviation_seasonal = temp7;
variance_seasonal = temp8;
skew_seasonal = temp9;
coeffvar_seasonal = temp10;
kendallCorlCoeff_seasonal = temp11;
}else if(flag.equalsIgnoreCase("period1")){
max_period1 = temp1;
min_period1 = temp2;
upperQuartile_period1 = temp3;
lowerQuartile_period1 = temp4;
median_period1 = temp5;
mean_period1 = temp6;
standardDeviation_period1 = temp7;
variance_period1 = temp8;
skew_period1 = temp9;
coeffvar_period1 = temp10;
kendallCorlCoeff_period1 = temp11;
}else if(flag.equalsIgnoreCase("period2")){
max_period2 = temp1;
min_period2 = temp2;
upperQuartile_period2 = temp3;
lowerQuartile_period2 = temp4;
median_period2 = temp5;
mean_period2 = temp6;
standardDeviation_period2 = temp7;
variance_period2 = temp8;
skew_period2 = temp9;
coeffvar_period2 = temp10;
kendallCorlCoeff_period2 = temp11;
}else if(flag.equalsIgnoreCase("period3")){
max_period3 = temp1;
min_period3 = temp2;
upperQuartile_period3 = temp3;
lowerQuartile_period3 = temp4;
median_period3 = temp5;
mean_period3 = temp6;
standardDeviation_period3 = temp7;
variance_period3 = temp8;
skew_period3 = temp9;
coeffvar_period3 = temp10;
kendallCorlCoeff_period3 = temp11;
}
}
/**
* Graph 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
* (column 1 = dates (yyyy-mm-dd if timeStep = "daily", yyyy-mm if
* timeStep = "monthly", yyyy if timeStep = "yearly") column 2 = value
* @param sortedData_user the String[][] containing sorted user data for the
* time series (column 1 = dates (yyyy-mm-dd if timeStep = "daily", yyyy-mm
* if timeStep = "monthly", yyyy if timeStep = "yearly") column 2 = value
* @param period1Data the String[][] containing sorted data for the time
* series contained by period1 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param period2Data the String[][] containing sorted data for the time
* series contained by period2 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param period3Data the String[][] containing sorted data for the time
* series contained by period3 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param color the color of the merged dataset (Java.Color)
* @param color2 the color of the user dataset (Java.Color)
* @param showLine a boolean, if true lines will be shown on the graph, if false only shapes for the data
* @param yAxisTitle the String label for the y axis of the graph
* @param units the units of the current graph to be used in labeling for the legend
* @param medianTF if true then the median value will be plotted for period analyses, if false the mean (average) will be used
*/
private void createTimeseriesGraph(String[][] sortedData,
String[][] sortedData_user,
String[][] period1Data,
String[][] period2Data,
String[][] period3Data,
Color color,
Color color2,
boolean showLine,
String yAxisTitle,
String units,
boolean medianTF) throws ParseException {
//Create TimeSeries graph of merged data
Graphing graphing = new Graphing();
XYPlot plotTime = new XYPlot();
boolean showLegend = false;
TimeSeries series = createTimeSeriesFromData(sortedData, stationID + ": Data", timeStep);
TimeSeries series2 = createTimeSeriesFromData(sortedData_user, stationID + ": User Data", timeStep);
//Create user data points
if(sortedData_user.length != 0){//only show user points if it is not zero
plotTime = graphing.addTimeseriesData(plotTime, series, showLine, color, false, false, false, true, 0);
plotTime = graphing.addTimeseriesData(plotTime, series2, showLine, color2, false, false, false, true, 1);
showLegend = true;
}else{
plotTime = graphing.addTimeseriesData(plotTime, series, showLine, color, false, false, false, true, 0);
}
//Create period analysis average lines
if(period1Data.length > 0){
this.len_period1 = String.valueOf(period1Data.length);
double value = mean_period1;
String label = "Average";
if(medianTF){
value = median_period1;
label = "Median";
}
TimeSeries periodSeries = new TimeSeries("Period 1 " + label + ": " + value + " " + units);
//Set Start Point
double d = Double.parseDouble(period1Begin.substring(8));
double m = Double.parseDouble(period1Begin.substring(5,7));
double y = Double.parseDouble(period1Begin.substring(0,4));
int day = (int)d;
int month = (int)m;
int year = (int)y;
if(year >= 1900){//artificial limit for JFreeCharts' "Day" class
Day date = new Day(day,month,year);//day,month,year
periodSeries.add(date, value);
}
//Set End Point
d = Double.parseDouble(period1End.substring(8));
m = Double.parseDouble(period1End.substring(5,7));
y = Double.parseDouble(period1End.substring(0,4));
day = (int)d;
month = (int)m;
year = (int)y;
if(year >= 1900){//artificial limit for JFreeCharts' "Day" class
Day date = new Day(day,month,year);//day,month,year
periodSeries.add(date, value);
}
plotTime = graphing.addTimeseriesData(plotTime, periodSeries, true, Color.red, false, false, true, true, 2);
showLegend = true;
}
if(period2Data.length > 0){
this.len_period2 = String.valueOf(period2Data.length);
double value = mean_period2;
String label = "Average";
if(medianTF){
value = median_period2;
label = "Median";
}
TimeSeries periodSeries = new TimeSeries("Period 2 " + label + ": " + value + " " + units);
//Set Start Point
double d = Double.parseDouble(period2Begin.substring(8));
double m = Double.parseDouble(period2Begin.substring(5,7));
double y = Double.parseDouble(period2Begin.substring(0,4));
int day = (int)d;
int month = (int)m;
int year = (int)y;
if(year >= 1900){//artificial limit for JFreeCharts' "Day" class
Day date = new Day(day,month,year);//day,month,year
periodSeries.add(date, value);
}
//Set End Point
d = Double.parseDouble(period2End.substring(8));
m = Double.parseDouble(period2End.substring(5,7));
y = Double.parseDouble(period2End.substring(0,4));
day = (int)d;
month = (int)m;
year = (int)y;
if(year >= 1900){//artificial limit for JFreeCharts' "Day" class
Day date = new Day(day,month,year);//day,month,year
periodSeries.add(date, value);
}
plotTime = graphing.addTimeseriesData(plotTime, periodSeries, true, new Color(255, 135, 0), false, false, true, true, 3);//gold
showLegend = true;
}
if(period3Data.length > 0){
this.len_period3 = String.valueOf(period3Data.length);
double value = mean_period3;
String label = "Average";
if(medianTF){
value = median_period3;
label = "Median";
}
TimeSeries periodSeries = new TimeSeries("Period 3 " + label + ": " + value + " " + units);
//Set Start Point
double d = Double.parseDouble(period3Begin.substring(8));
double m = Double.parseDouble(period3Begin.substring(5,7));
double y = Double.parseDouble(period3Begin.substring(0,4));
int day = (int)d;
int month = (int)m;
int year = (int)y;
if(year >= 1900){//artificial limit for JFreeCharts' "Day" class
Day date = new Day(day,month,year);//day,month,year
periodSeries.add(date, value);
}
//Set End Point
d = Double.parseDouble(period3End.substring(8));
m = Double.parseDouble(period3End.substring(5,7));
y = Double.parseDouble(period3End.substring(0,4));
day = (int)d;
month = (int)m;
year = (int)y;
if(year >= 1900){//artificial limit for JFreeCharts' "Day" class
Day date = new Day(day,month,year);//day,month,year
periodSeries.add(date, value);
}
plotTime = graphing.addTimeseriesData(plotTime, periodSeries, true, Color.green, false, false, true, true, 4);
showLegend = true;
}
//Create Y Axis
ValueAxis rangeTime = new NumberAxis(yAxisTitle);
plotTime.setRangeAxis(0, rangeTime);
//Create X Axis
DateAxis domainTime = new DateAxis("Date");
domainTime.setLowerMargin(0.05);
domainTime.setUpperMargin(0.05);
plotTime.setDomainAxis(0, domainTime);
//Set extra plot preferences
plotTime = graphing.setTimeAxisPreferences(plotTime);
//Create the chart with the plot and a legend
String graphTitle = "Time Series for " + database + " Station: " + stationID + "; " + stationName;
JFreeChart chart = new JFreeChart(graphTitle, graphing.titleFont, plotTime, showLegend);
//Set legend Font
if(showLegend){
LegendTitle legendTitle = chart.getLegend();
legendTitle.setItemFont(graphing.masterFont);
}
//Save resulting graph for use later
try{
String path = mainFolder + File.separator + getGraph();
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.");
}
}
/**
* Create a JFreeChart TimeSeries out of the provided time series data
* @param data the String[][] containing data for the
* time series (column 1 = dates (yyyy-mm-dd if timeStep = "daily", yyyy-mm
* if timeStep = "monthly", yyyy if timeStep = "yearly") column 2 = value
* @param title the title of the TimeSeries to appear in the legend
* @return a JFreeChart TimeSeries
*/
private TimeSeries createTimeSeriesFromData(String[][] data, String title, String timeStep){
//Create TimeSeries graph of merged data
TimeSeries series = new TimeSeries(title);
for(int i=0; i < data.length; i++) {
double value = Double.parseDouble(data[i][1]);
String tmpStr = data[i][0];
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;
if(year >= 1900){//artificial limit for JFreeCharts' "Day" class
Day date = new Day(day,month,year);//day,month,year
series.add(date, value);
}
}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;
if(year >= 1900){//artificial limit for JFreeCharts' "Day" class
Month date = new Month(month,year);//month,year
series.add(date, value);
}
}else if(timeStep.equalsIgnoreCase("yearly")){
double y = Double.parseDouble(tmpStr.substring(0,4));
int year = (int)y;
if(year >= 1900){//artificial limit for JFreeCharts' "Day" class
Year date = new Year(year);//year
series.add(date, value);
}
}
}
return series;
}
/**
* Creates a boxplot of the timeseries data to be displayed next to a summary of the statistics of the timeseries data
* @param yAxisTitle a String of the title for the Y axis of the boxplot
*/
private void createTimeseriesBoxplot(String[][] data, String yAxisTitle){
Graphing graphing = new Graphing();
//Create boxplot of the timeseries data
XYPlot plot = new XYPlot();
//Create X Axis
ValueAxis xAxis = new NumberAxis("");
xAxis.setRange(0, 10);
xAxis.setLabelFont(graphing.masterFont);
xAxis.setTickLabelFont(graphing.masterFont);
xAxis.setTickLabelsVisible(false);
plot.setDomainAxis(0, xAxis);
ValueAxis yAxis = new NumberAxis(yAxisTitle);
yAxis.setLabelFont(graphing.masterFont);
yAxis.setTickLabelFont(graphing.masterFont);
plot.setRangeAxis(0, yAxis);
//Calculate and add Median to dataset
XYSeries median_series = new XYSeries("Median");
median_series.add(5, median);
//Create median Line
XYDataset median_scatter = new XYSeriesCollection(median_series);
XYItemRenderer renderer_median = new XYLineAndShapeRenderer(false, true);
renderer_median.setSeriesShape(0, new Rectangle2D.Double(-4.0, 0.0, 8.0, 1));//new Ellipse2D.Double(-4, -4, 8, 8));
renderer_median.setSeriesPaint(0, Color.red);
renderer_median.setSeriesVisibleInLegend(0, false);
plot.setDataset(0, median_scatter);
plot.setRenderer(0, renderer_median);
//Create quartile Box shapes for the box plot
//Create XYSeries for the box shape
XYSeries shapeSeries = new XYSeries("Shape");
shapeSeries.add(5, lowerQuartile);
shapeSeries.add(5, upperQuartile);
//Create the quartile rectangle shape
XYDataset shapeDataset = new XYSeriesCollection(shapeSeries);
XYItemRenderer renderer_shape = new XYLineAndShapeRenderer(true, false);
Stroke thickness = new BasicStroke(10, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);
renderer_shape.setSeriesStroke(0, thickness);
renderer_shape.setSeriesPaint(0, Color.blue);
renderer_shape.setSeriesVisibleInLegend(0, false);
plot.setDataset(1, shapeDataset);
plot.setRenderer(1, renderer_shape);
//Creates 1.5 * Interquartile Range (IQR) lines
//Create XYSeries for the min-max lines
double IQR = upperQuartile - lowerQuartile;
double lowerLimit = lowerQuartile - 1.5*IQR;
double upperLimit = upperQuartile + 1.5*IQR;
if(lowerLimit < min){
lowerLimit = min;
}
if(upperLimit > max){
upperLimit = max;
}
XYSeries lineSeries = new XYSeries("Line");
lineSeries.add(5, lowerLimit);
lineSeries.add(5, upperLimit);
//Create the 1.5*IQR lines
XYDataset lineDataset = new XYSeriesCollection(lineSeries);
XYItemRenderer lineRenderer = new XYLineAndShapeRenderer(true, true);
Stroke thickness2 = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);
lineRenderer.setSeriesStroke(0, thickness2);
lineRenderer.setSeriesShape(0, new Rectangle2D.Double(-10.0, 0.0, 20.0, 1));
lineRenderer.setSeriesPaint(0, Color.black);
lineRenderer.setSeriesVisibleInLegend(0, false);
plot.setDataset(2, lineDataset);
plot.setRenderer(2, lineRenderer);
//Calculate and create Outliers (# < lowerQuartile - 1.5*IQR or # > upperQuartile + 1.5*IQR)
//Calculate and create Extreme Outliers (# < lowerQuartile - 3*IQR or # > upperQuartile + 3*IQR)
XYSeries outliers = new XYSeries("Outliers");
XYSeries extremeOutliers = new XYSeries("Extreme Outliers");
for(int i=0; i<data.length; i++){
double value = Double.parseDouble(data[i][1]);
//Lower outliers
if(value < (lowerQuartile - 1.5*IQR) && value > (lowerQuartile - 3*IQR)){
outliers.add(5, value);
}
//Upper outliers
if(value > (upperQuartile + 1.5*IQR) && value < (lowerQuartile + 3*IQR)){
outliers.add(5, value);
}
//Extreme Lower outliers
if(value < (lowerQuartile - 3*IQR)){
extremeOutliers.add(5, value);
}
//Extreme Upper outliers
if(value > (lowerQuartile + 3*IQR)){
extremeOutliers.add(5, value);
}
}
//Create outlier scatter
XYDataset outlier_scatter = new XYSeriesCollection(outliers);
XYItemRenderer renderer_outlier = new XYLineAndShapeRenderer(false, true);
renderer_outlier.setSeriesShape(0, new Ellipse2D.Double(-2.0, 2.0, 4.0, 4.0));
renderer_outlier.setSeriesPaint(0, Color.darkGray);
if(outliers.isEmpty()){
renderer_outlier.setSeriesVisibleInLegend(0, false);
}
plot.setDataset(3, outlier_scatter);
plot.setRenderer(3, renderer_outlier);
//Create extreme outlier scatter
XYDataset extremeOutlier_scatter = new XYSeriesCollection(extremeOutliers);
XYItemRenderer renderer_ExtremeOutlier = new XYLineAndShapeRenderer(false, true);
renderer_ExtremeOutlier.setSeriesShape(0, new Ellipse2D.Double(-2.0, 2.0, 4.0, 4.0));
renderer_ExtremeOutlier.setSeriesPaint(0, Color.red);
if(extremeOutliers.isEmpty()){
renderer_ExtremeOutlier.setSeriesVisibleInLegend(0, false);
}
plot.setDataset(4, extremeOutlier_scatter);
plot.setRenderer(4, renderer_ExtremeOutlier);
//Put the line on the first Domain and first Range
plot.mapDatasetToDomainAxis(0, 0);
plot.mapDatasetToRangeAxis(0, 0);
//Set extra plot preferences
plot.setOutlinePaint(Color.black);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.black);
//Create the chart with the plot and a legend
JFreeChart chart = new JFreeChart("Boxplot of Timeseries Data", graphing.titleFont, plot, true);
//Save resulting graph for use later
try{
String path = mainFolder + File.separator + getBoxplot();
ChartUtilities.saveChartAsJPEG(new File(path), chart, 200, 400);
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 quantile plot CDF of the time series 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 if timeStep = "daily", yyyy-mm if
* timeStep = "monthly", yyyy if timeStep = "yearly") column 2 = value
* @param sortedData_user the String[][] containing sorted user data for the
* time series (column 1 = dates (yyyy-mm-dd if timeStep = "daily", yyyy-mm
* if timeStep = "monthly", yyyy if timeStep = "yearly") column 2 = value
* @param period1Data the String[][] containing sorted data for the time
* series contained by period1 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param period2Data the String[][] containing sorted data for the time
* series contained by period2 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param period3Data the String[][] containing sorted data for the time
* series contained by period3 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param color the color of the merged dataset (Java.Color)
* @param color2 the color of the user dataset (Java.Color)
* @param xAxisTitle the String label for the x axis of the graph
*/
private void createTimeseriesCDF(String[][] sortedData,
String[][] sortedData_user,
String[][] period1Data,
String[][] period2Data,
String[][] period3Data,
Color color,
Color color2,
String xAxisTitle) throws ParseException, IOException {
DoubleArray doubleArray = new DoubleArray();
double[][] xyRanks = doubleArray.weibullPlottingPosition(sortedData);
double[][] xyRanks_user = doubleArray.weibullPlottingPosition(sortedData_user);
double[][] xyRanks_period1 = doubleArray.weibullPlottingPosition(period1Data);
double[][] xyRanks_period2 = doubleArray.weibullPlottingPosition(period2Data);
double[][] xyRanks_period3 = doubleArray.weibullPlottingPosition(period3Data);
//Calculate cdf for the entire dataset
XYSeries series = new XYSeries(stationID + ": Data");
XYSeries series_user = new XYSeries(stationID + ": User Data");
XYSeries period1_series = new XYSeries(stationID + ": Period 1");
XYSeries period2_series = new XYSeries(stationID + ": Period 2");
XYSeries period3_series = new XYSeries(stationID + ": Period 3");
String[][] cdfData = new String[xyRanks.length][8];
for(int i=0; i<xyRanks.length; i++){
double x = xyRanks[i][1]; //flow
double y = 1 - (xyRanks[i][0]/100); //rank
series.add(x, y);
cdfData[i][0] = String.valueOf(x);
cdfData[i][1] = String.valueOf(y);
//Add user data (if any)
if(i < xyRanks_user.length){
x = xyRanks_user[i][1]; //flow
y = 1 - (xyRanks_user[i][0]/100); //rank
series_user.add(x, y);
}
//Add period 1 data (if any)
if(i < xyRanks_period1.length){
x = xyRanks_period1[i][1]; //flow
y = 1 - (xyRanks_period1[i][0]/100); //rank
period1_series.add(x, y);
cdfData[i][2] = String.valueOf(x);
cdfData[i][3] = String.valueOf(y);
}else{
cdfData[i][2] = "-1";
cdfData[i][3] = "-1";
}
//Add period 2 data (if any)
if(i < xyRanks_period2.length){
x = xyRanks_period2[i][1]; //flow
y = 1 - (xyRanks_period2[i][0]/100); //rank
period2_series.add(x, y);
cdfData[i][4] = String.valueOf(x);
cdfData[i][5] = String.valueOf(y);
}else{
cdfData[i][4] = "-1";
cdfData[i][5] = "-1";
}
//Add period 3 data (if any)
if(i < xyRanks_period3.length){
x = xyRanks_period3[i][1]; //flow
y = 1 - (xyRanks_period3[i][0]/100); //rank
period3_series.add(x, y);
cdfData[i][6] = String.valueOf(x);
cdfData[i][7] = String.valueOf(y);
}else{
cdfData[i][6] = "-1";
cdfData[i][7] = "-1";
}
}
//Save cdf data for JHighCharts
doubleArray.writeXYseries(mainFolder, cdfData, getCDFoutput().getName());
//Create renderer, and axis for timeseries graph
XYPlot plot = new XYPlot();
XYDataset xyDataset = new XYSeriesCollection(series);
XYDataset xyDataset_user = new XYSeriesCollection(series_user);
XYDataset xyDataset_period1 = new XYSeriesCollection(period1_series);
XYDataset xyDataset_period2 = new XYSeriesCollection(period2_series);
XYDataset xyDataset_period3 = new XYSeriesCollection(period3_series);
XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
renderer.setSeriesPaint(0, color);
//Set the line data, renderer, and axis into plot
plot.setDataset(0, xyDataset);
plot.setRenderer(0, renderer);
boolean legendTF = false;
if(sortedData_user.length > 0){
XYItemRenderer renderer_user = new XYLineAndShapeRenderer(true, false);
renderer_user.setSeriesPaint(0, color2);
plot.setDataset(1, xyDataset_user);
plot.setRenderer(1, renderer_user);
legendTF = true;
}
if(period1Data.length > 0){
XYItemRenderer renderer_period1 = new XYLineAndShapeRenderer(true, false);
renderer_period1.setSeriesPaint(0, Color.red);
plot.setDataset(2, xyDataset_period1);
plot.setRenderer(2, renderer_period1);
legendTF = true;
}
if(period2Data.length > 0){
XYItemRenderer renderer_period2 = new XYLineAndShapeRenderer(true, false);
renderer_period2.setSeriesPaint(0, new Color(255, 135, 0));//gold
plot.setDataset(3, xyDataset_period2);
plot.setRenderer(3, renderer_period2);
legendTF = true;
}
if(period3Data.length > 0){
XYItemRenderer renderer_period3 = new XYLineAndShapeRenderer(true, false);
renderer_period3.setSeriesPaint(0, Color.green);
plot.setDataset(4, xyDataset_period3);
plot.setRenderer(4, renderer_period3);
legendTF = true;
}
//Map the line to the first Domain and first Range
plot.mapDatasetToDomainAxis(0, 0);
plot.mapDatasetToRangeAxis(0, 0);
//Create Y Axis
ValueAxis rangeAxis = new NumberAxis("Non-Exceedance");
rangeAxis.setRange(0, 1);
plot.setRangeAxis(0, rangeAxis);
//Create X Axis
LogarithmicAxis xAxis = new LogarithmicAxis(xAxisTitle);
xAxis.setAllowNegativesFlag(true);
plot.setDomainAxis(0, xAxis);
//Set extra plot preferences
Graphing graphing = new Graphing();
plot = graphing.setLogXaxisPreferences(plot);
//Create the charts out of the plots
String graphTitle = "CDF for " + database + " Station: " + stationID + "; " + stationName;
JFreeChart chart = new JFreeChart(graphTitle, graphing.titleFont, plot, legendTF);
//Set legend Font
if(legendTF){
LegendTitle legendTitle = chart.getLegend();
legendTitle.setItemFont(graphing.masterFont);
}
//Save monthly timeseries graph for use later
try{
String path = mainFolder + File.separator + getCDF();
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 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,
boolean logYaxis_TF) throws IOException {
DoubleArray doubleArray = new DoubleArray();
DoubleMath doubleMath = new DoubleMath();
Graphing graphing = new Graphing();
//Initialize variables
int currentYear = Integer.parseInt(end.substring(0,4));
int firstYear = Integer.parseInt(start.substring(0,4));
int lastYear = Integer.parseInt(end.substring(0,4));
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 average_TS = 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 = doubleMath.meanArithmetic(dateData);
if(medianTF){
dayValue = doubleMath.median(dateData);
}
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, 2000);
average_TS.add(graphDay, dayValue);
graphData[j-1][0] = String.valueOf(j);
graphData[j-1][1] = String.valueOf(dayValue);
}
//Create renderer, and axis for timeseries graph
graphing.addTimeseriesData(plot, average_TS, true, Color.gray, false, false, true, true, seriesIndex);
seriesIndex++;
seriesIndex++;//Increase series so the most recent month can be plotted second
//Graph a line for each year of monthly data in time period
boolean moreYears = sortedData.length > 0;
String[][] mostRecentYearData = new String[0][2];
while(moreYears){
//Get current year's data and graph it
String[][] partialData = doubleArray.getYearsData(sortedData, String.valueOf(currentYear));
for(int i=0; i<partialData.length; i++){
String month_day = partialData[i][0].substring(5);
partialData[i][0] = "2000-" + month_day;
}
TimeSeries currentYear_TS = createTimeSeriesFromData(partialData, "temp", "daily");
graphing.addTimeseriesData(plot, currentYear_TS, true, Color.lightGray, false, false, false, false, seriesIndex);
seriesIndex++;
if(currentYear == lastYear){
mostRecentYearData = partialData;
}
//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 previousYear = currentYear - 1;
if(firstYear <= previousYear){
currentYear = previousYear;
}else{
moreYears = false;
}
}
//Re-add the most recent year to the graph so it renders on top
TimeSeries finalYear_TS = createTimeSeriesFromData(mostRecentYearData, String.valueOf(lastYear), "daily");
graphing.addTimeseriesData(plot, finalYear_TS, true, Color.red, false, false, true, true, 1);
//Output monthly boxplot and timeseries data for use with JHighCharts
doubleArray.writeXYseries(mainFolder, graphData, getTimeseriesEnvelopeOutput().getName());
//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>();
ArrayList<Double> tempData_noZeros = 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);
if(value > 0){
tempData_noZeros.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);
}
double tempMin = doubleMath.min(tempData_value);
double tempMax = doubleMath.max(tempData_value);
//Renderer
XYZDataset xyzRasterData = new XYZArrayDataset(rasterData);
XYBlockRenderer renderer = new XYBlockRenderer();
LookupPaintScale paintScale = new LookupPaintScale(tempMin, tempMax, Color.lightGray);
Paint[] contourColors = getFullRainBowScale(170);
//Color Scale
double value = tempMax;
double delta = (tempMax - tempMin)/(contourColors.length -1);
if(rasterLogarithmicBinsTF){
value = Math.log(tempMax);
delta = (Math.log(tempMax) - Math.log(tempMin))/(contourColors.length -1);
if(tempMin == 0){
delta = (Math.log(tempMax) - Math.log(doubleMath.min(tempData_noZeros)))/(contourColors.length -1);
}
}
for(int i=0; i<contourColors.length; i++){
if(rasterLogarithmicBinsTF){
paintScale.add(Math.exp(value), contourColors[i]);
}else{
paintScale.add(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
ValueAxis domainAxis = new NumberAxis("Day of Calendar 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 = "Raster Graph for " + database + " Station: " + stationID + "; " + stationName;
JFreeChart chart = new JFreeChart(graphTitle, graphing.titleFont, plot, false);
//Add scale/legend
NumberAxis scaleAxis = new NumberAxis(zAxisTitle);
if(rasterLogarithmicBinsTF){
scaleAxis = new LogarithmicAxis(zAxisTitle);
}
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 + getTimeseriesRaster();
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.");
}
}
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(double colorValue){
// 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.));
float x = (float) (1./(ncolor + colorValue));
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
* (column 1 = dates (yyyy-mm-dd if timeStep = "daily", yyyy-mm if
* timeStep = "monthly", yyyy if timeStep = "yearly") column 2 = value
* @param sortedData_user the String[][] containing sorted user data for the
* time series (column 1 = dates (yyyy-mm-dd if timeStep = "daily", yyyy-mm
* if timeStep = "monthly", yyyy if timeStep = "yearly") column 2 = value
* @param period1Data the String[][] containing sorted data for the time
* series contained by period1 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param period2Data the String[][] containing sorted data for the time
* series contained by period2 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param period3Data the String[][] containing sorted data for the time
* series contained by period3 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param color the color of the graph for flow (blue) or water quality (magenta)
* @param xAxisTitle the String label for the y axis of the graph
*/
private void createTimeseriesHistogram(String[][] sortedData,
String[][] sortedData_user,
String[][] period1Data,
String[][] period2Data,
String[][] period3Data,
Color color,
String xAxisTitle) throws IOException{
//Initialize other classes
Graphing graphing = new Graphing();
DoubleMath doubleMath = new DoubleMath();
//Determine bin type (arithmetic/logarithmic) and then range
double[] lowerLimit = new double[numBins];
double[] upperLimit = new double[numBins];
if(logarithmicBinsTF){
if(min != 0){
double exponent = (Math.log10(max) - Math.log10(min)) / numBins;
for(int i=0; i<numBins; i++){
if(i == 0){
lowerLimit[i] = 0;
}else{
lowerLimit[i] = upperLimit[i-1];
}
upperLimit[i] = min * Math.pow(10, exponent * (i+1));
}
}else{
double exponent = Math.log10(max) / numBins;
for(int i=0; i<numBins; i++){
if(i == 0){
lowerLimit[i] = 0;
}else{
lowerLimit[i] = upperLimit[i-1];
}
upperLimit[i] = Math.pow(10, exponent * (i+1));
}
}
}else{
double interval = (max - min) / numBins;
for(int i=0; i<numBins; i++){
lowerLimit[i] = min + i*interval;
upperLimit[i] = min + (i+1)*interval;
}
}
//Create TimeSeries graph
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
String[][] histogramData = new String[numBins][5];
boolean legendTF = false;
for(int j=0; j<numBins; j++){
//Count data within the bin range
int count = 0;
for(int i=0; i < sortedData.length; i++) {
double value = Double.parseDouble(sortedData[i][1]);
if(value > lowerLimit[j] && value <= upperLimit[j]){
count++;
}
}
String categoryTitle = String.valueOf(doubleMath.round(lowerLimit[j],1)) + " to " + String.valueOf(doubleMath.round(upperLimit[j],1));
dataset.addValue(count, "All Data", categoryTitle);
histogramData[j][0] = categoryTitle;
histogramData[j][1] = String.valueOf(count);
//Count user data within the bin range
if(sortedData_user.length > 0){
count = 0;
for(int i=0; i < sortedData_user.length; i++) {
double value = Double.parseDouble(sortedData_user[i][1]);
if(value > lowerLimit[j] && value <= upperLimit[j]){
count++;
}
}
dataset.addValue(count, "User Data", categoryTitle);
}
//Count period 1 data within the bin range
if(period1Data.length > 0){
count = 0;
for(int i=0; i < period1Data.length; i++) {
double value = Double.parseDouble(period1Data[i][1]);
if(value > lowerLimit[j] && value <= upperLimit[j]){
count++;
}
}
dataset.addValue(count, "Period 1 Data", categoryTitle);
histogramData[j][2] = String.valueOf(count);
legendTF = true;
}else{
histogramData[j][2] = "-1";
}
//Count period 2 data within the bin range
if(period2Data.length > 0){
count = 0;
for(int i=0; i < period2Data.length; i++) {
double value = Double.parseDouble(period2Data[i][1]);
if(value > lowerLimit[j] && value <= upperLimit[j]){
count++;
}
}
dataset.addValue(count, "Period 2 Data", categoryTitle);
histogramData[j][3] = String.valueOf(count);
legendTF = true;
}else{
histogramData[j][3] = "-1";
}
//Count period 3 data within the bin range
if (period3Data.length > 0) {
count = 0;
for (int i = 0; i < period3Data.length; i++) {
double value = Double.parseDouble(period3Data[i][1]);
if (value > lowerLimit[j] && value <= upperLimit[j]) {
count++;
}
}
dataset.addValue(count, "Period 3 Data", categoryTitle);
histogramData[j][4] = String.valueOf(count);
legendTF = true;
}else{
histogramData[j][4] = "-1";
}
}
//Save histogram data for JHighCharts
DoubleArray doubleArray = new DoubleArray();
doubleArray.writeXYseries(mainFolder, histogramData, getHistogramOutput().getName());
//Define renderer properties for bar graph
int seriesIndex = 0;
BarRenderer renderer = new BarRenderer();
renderer.setDrawBarOutline(false);
renderer.setSeriesPaint(seriesIndex, color);
seriesIndex++;
if(sortedData_user.length > 0){
renderer.setSeriesPaint(seriesIndex, Color.gray);
seriesIndex++;
}
if(period1Data.length > 0){
renderer.setSeriesPaint(seriesIndex, Color.red);
seriesIndex++;
}
if(period2Data.length > 0){
renderer.setSeriesPaint(seriesIndex, new Color(255, 135, 0));//gold
seriesIndex++;
}
if(period3Data.length > 0){
renderer.setSeriesPaint(seriesIndex, Color.green);
seriesIndex++;
}
//Define axis and properties
NumberAxis yAxis = new NumberAxis("Count");
CategoryAxis xAxis = new CategoryAxis(xAxisTitle);
xAxis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);
//Graph the dataset using the renderer and create a chart
CategoryPlot plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
//Set extra plot preferences
graphing.setCategoryAxisPreferences(plot);
//Create the chart with the plot
String graphTitle = "Histogram for " + database + " Station: " + stationID + "; " + stationName;
JFreeChart chart = new JFreeChart(graphTitle, graphing.titleFont, plot, legendTF);
//Set legend Font
if(legendTF){
LegendTitle legendTitle = chart.getLegend();
legendTitle.setItemFont(graphing.masterFont);
}
//Save resulting graph for use later
try{
String path = mainFolder + File.separator + getHistogram();
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
* (column 1 = dates (yyyy-mm-dd if timeStep = "daily", yyyy-mm if
* timeStep = "monthly", yyyy if timeStep = "yearly") column 2 = value
* @param period1Data the String[][] containing sorted data for the time
* series contained by period1 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param period2Data the String[][] containing sorted data for the time
* series contained by period2 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param period3Data the String[][] containing sorted data for the time
* series contained by period3 (column 1 = dates (yyyy-mm-dd if timeStep =
* "daily", yyyy-mm if timeStep = "monthly", yyyy if timeStep = "yearly")
* column 2 = value
* @param yAxisTitle the String label for the y axis of the graph
*/
private void createTimeseriesMonthlyGraph(String[][] sortedData,
String[][] period1Data,
String[][] period2Data,
String[][] period3Data,
String yAxisTitle) throws IOException {
//Convert sortedData to monthly data
DoubleArray doubleArray = new DoubleArray();
sortedData = doubleArray.computeFlowMethod(sortedData, "Monthly", "Average", false);
period1Data = doubleArray.computeFlowMethod(period1Data, "Monthly", "Average", false);
period2Data = doubleArray.computeFlowMethod(period2Data, "Monthly", "Average", false);
period3Data = doubleArray.computeFlowMethod(period3Data, "Monthly", "Average", false);
//Calculate monthly averages for the entire dataset
XYPlot plot = new XYPlot();
Graphing graphing = new Graphing();
XYSeries series = new XYSeries(stationID + ": Data");
XYSeries period1_series = new XYSeries(stationID + ": Period 1 Data");
XYSeries period2_series = new XYSeries(stationID + ": Period 2 Data");
XYSeries period3_series = new XYSeries(stationID + ": Period 3 Data");
// ArrayList<ArrayList<Double>> boxplotOutliers = new ArrayList<ArrayList<Double>>();
// double[][] boxplotData = new double[5][12];
String[][] monthXYdata = new String[12][8];
boolean showOutliers = false, showExtremeOutliers = false;
int seriesIndex = 0;
for(int j=1; j<=12; j++){
ArrayList<Double> monthlyData = new ArrayList<Double>();
double flow = 0, flow1 = 0, flow2 = 0, flow3 = 0;
double ctr = 0, ctr1 = 0, ctr2 = 0, ctr3 = 0;
for(int i=0; i<sortedData.length; i++){
double month = Double.parseDouble(sortedData[i][0].substring(5));
double value = Double.parseDouble(sortedData[i][1]);
int month_int = (int) month;
if(month_int == j){
monthlyData.add(value);
flow = flow + value;
ctr = ctr + 1;
}
if(i < period1Data.length){
month_int = (int) Double.parseDouble(period1Data[i][0].substring(5));
value = Double.parseDouble(period1Data[i][1]);
if(month_int == j){
flow1 = flow1 + value;
ctr1 = ctr1 + 1;
}
}
if(i < period2Data.length){
month_int = (int) Double.parseDouble(period2Data[i][0].substring(5));
value = Double.parseDouble(period2Data[i][1]);
if(month_int == j){
flow2 = flow2 + value;
ctr2 = ctr2 + 1;
}
}
if(i < period3Data.length){
month_int = (int) Double.parseDouble(period3Data[i][0].substring(5));
value = Double.parseDouble(period3Data[i][1]);
if(month_int == j){
flow3 = flow3 + value;
ctr3 = ctr3 + 1;
}
}
}
//Calculate monthly average
if(ctr == 0){ctr = 1;} //prevent divide by zero problems
series.add(j, flow/ctr);
monthXYdata[j-1][0] = String.valueOf(j);
monthXYdata[j-1][1] = String.valueOf(flow/ctr);
monthXYdata[j-1][2] = String.valueOf(j);
monthXYdata[j-1][3] = "-1";
monthXYdata[j-1][4] = String.valueOf(j);
monthXYdata[j-1][5] = "-1";
monthXYdata[j-1][6] = String.valueOf(j);
monthXYdata[j-1][7] = "-1";
//Check for period data
if(period1Data.length > 0){
if(ctr1 == 0){ctr1 = 1;} //prevent divide by zero problems
period1_series.add(j, flow1/ctr1);
monthXYdata[j-1][3] = String.valueOf(flow1/ctr1);
}
if(period2Data.length > 0){
if(ctr2 == 0){ctr2 = 1;} //prevent divide by zero problems
period2_series.add(j, flow2/ctr2);
monthXYdata[j-1][5] = String.valueOf(flow2/ctr2);
}
if(period3Data.length > 0){
if(ctr3 == 0){ctr3 = 1;} //prevent divide by zero problems
period3_series.add(j, flow3/ctr3);
monthXYdata[j-1][7] = String.valueOf(flow3/ctr3);
}
//Create Monthly boxplot
if(monthlyData.size() > 4){
//Create quartile rectangle, min-max line, and median line
Object[] returnArray = graphing.boxplot_shapes(plot, j, monthlyData, seriesIndex, showOutliers, showExtremeOutliers);
plot = (XYPlot) returnArray[0];
showOutliers = (boolean) returnArray[1];
showExtremeOutliers = (boolean) returnArray[2];
seriesIndex = (int) returnArray[3];
// ArrayList<Double> outliers = (ArrayList<Double>) returnArray[4];
// double[] currentBoxplotData = (double[]) returnArray[5];
//
// //Store additional results for use with JHighCharts
// boxplotOutliers.add(outliers);
// boxplotData[0][j-1] = currentBoxplotData[0];
// boxplotData[1][j-1] = currentBoxplotData[1];
// boxplotData[2][j-1] = currentBoxplotData[2];
// boxplotData[3][j-1] = currentBoxplotData[3];
// boxplotData[4][j-1] = currentBoxplotData[4];
}
}
// //Check to show legend on boxplot graph
// boolean showBoxplotLegend = false;
// if(showOutliers || showExtremeOutliers){
// showBoxplotLegend = true;
// }
//Create renderer, and axis for timeseries graph
XYDataset xyDataset = new XYSeriesCollection(series);
XYDataset xyDataset_period1 = new XYSeriesCollection(period1_series);
XYDataset xyDataset_period2 = new XYSeriesCollection(period2_series);
XYDataset xyDataset_period3 = new XYSeriesCollection(period3_series);
XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
renderer.setSeriesPaint(0, Color.black);
renderer.setSeriesStroke(0,
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, xyDataset);
plot.setRenderer(seriesIndex, renderer);
boolean legendTF = false;
seriesIndex++;
//Add period data (if any)
if(period1Data.length > 0){
XYItemRenderer renderer_period1 = new XYLineAndShapeRenderer(true, false);
renderer_period1.setSeriesPaint(0, Color.red);
plot.setDataset(seriesIndex, xyDataset_period1);
plot.setRenderer(seriesIndex, renderer_period1);
legendTF = true;
seriesIndex++;
}
if(period2Data.length > 0){
XYItemRenderer renderer_period2 = new XYLineAndShapeRenderer(true, false);
renderer_period2.setSeriesPaint(0, new Color(255, 135, 0));//gold
plot.setDataset(seriesIndex, xyDataset_period2);
plot.setRenderer(seriesIndex, renderer_period2);
legendTF = true;
seriesIndex++;
}
if(period3Data.length > 0){
XYItemRenderer renderer_period3 = new XYLineAndShapeRenderer(true, false);
renderer_period3.setSeriesPaint(0, Color.green);
plot.setDataset(seriesIndex, xyDataset_period3);
plot.setRenderer(seriesIndex, renderer_period3);
legendTF = true;
seriesIndex++;
}
//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
String[] monthList = {"1","2","3","4","5","6","7","8","9","10","11","12"};
String currentYear = start.substring(0,4);
String finalYear = end.substring(0,4);
boolean moreYears = sortedData.length > 0;
while(moreYears){
//Get current year's data and graph it
String[][] partialData = doubleArray.getYearsData(sortedData, currentYear);
double[][] currentYearData = new double[partialData.length][2];
for(int i=0; i<partialData.length; i++){
currentYearData[i][0] = Double.parseDouble(partialData[i][0].substring(5));//month
currentYearData[i][1] = Double.parseDouble(partialData[i][1]);//value
}
graphing.addXYSeries(plot, currentYearData, Color.lightGray, seriesIndex);
seriesIndex++;
//Save results for output for JHighCharts
String[] partialMonthData = new String[12];
int ctr = 0;
for(int i=0; i<12; i++){
partialMonthData[i] = "-1";//value
try{
double month = Double.parseDouble(partialData[ctr][0].substring(5));//month
int month_int = (int) month;
if(month_int == (i+1)){
partialMonthData[i] = partialData[ctr][1];//value
ctr++;
}
}catch(IndexOutOfBoundsException e){
//do nothing as it already has a -1 value
}
}
monthXYdata = doubleArray.appendcolumn_Matrix(monthXYdata, monthList);//Add list of months (aka x points)
monthXYdata = doubleArray.appendcolumn_Matrix(monthXYdata, partialMonthData);//Add month 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{
moreYears = false;
}
}
//Output monthly boxplot and timeseries data for use with JHighCharts
doubleArray.writeXYseries(mainFolder, monthXYdata, getMonthlyTimeseriesOutput().getName());
// doubleArray.writeBoxplot(mainFolder, boxplotOutliers, boxplotData, getMonthlyBoxplotOutput().getName());
//Create Y Axis
ValueAxis rangeAxis = new NumberAxis(yAxisTitle);
plot.setRangeAxis(0, rangeAxis);
//Create X Axis
NumberTickUnit temp = new NumberTickUnit(1);
NumberAxis domainAxis = new NumberAxis("Calendar Month");
domainAxis.setRange(0.75, 12.25);
domainAxis.setTickUnit(temp);
plot.setDomainAxis(0, domainAxis);
//Set extra plot preferences
plot = graphing.setAxisPreferences(plot);
//Create the charts out of the plots
String graphTitle = "Monthly Averages for " + database + " Station: " + stationID + "; " + stationName;
JFreeChart chart = new JFreeChart(graphTitle, graphing.titleFont, plot, legendTF);
//Set legend Font
if(legendTF){
LegendTitle legendTitle = chart.getLegend();
legendTitle.setItemFont(graphing.masterFont);
}
//Save monthly timeseries graph for use later
try{
String path = mainFolder + File.separator + getMonthlyGraph();
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 calendar day (1-366) verses the year 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 createTimeseriesRasterGraph(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 average_TS = 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 = doubleMath.meanArithmetic(dateData);
if(medianTF){
dayValue = doubleMath.median(dateData);
}
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, 2000);
average_TS.add(graphDay, dayValue);
graphData[j-1][0] = String.valueOf(j);
graphData[j-1][1] = String.valueOf(dayValue);
}
//Create renderer, and axis for timeseries graph
graphing.addTimeseriesData(plot, average_TS, true, Color.gray, false, false, true, true, seriesIndex);
seriesIndex++;
seriesIndex++;//Increase series so the most recent month can be plotted second
//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] = "2000-" + month_day;
}
TimeSeries currentYear_TS = createTimeSeriesFromData(partialData, "temp", "daily");
graphing.addTimeseriesData(plot, currentYear_TS, true, Color.lightGray, false, false, false, false, seriesIndex);
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
TimeSeries finalYear_TS = createTimeSeriesFromData(partialData, finalYear, "daily");
graphing.addTimeseriesData(plot, finalYear_TS, true, Color.red, false, false, true, true, 1);
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);
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.");
}
}
/**
* Writes out the error message, if any, for finding the file and then exits the program
* @param error string array to be written as each line of an error message
* @throws IOException
*/
public void writeError(ArrayList<String> error) throws IOException{
//Output data to text file
String errorContents = error.get(0);
for(int i=1; i<error.size(); i++){
errorContents = errorContents + "\n" + error.get(i);
}
throw new IOException("Error encountered. Please see the following message for details: \n" + errorContents);
}
/**
* Primary TimeSeries
* It calls the subfunctions based on user selection/inputs.
* Calls STORET or USGS database queries and their respective subfunctions
* @throws IOException
* @throws InterruptedException
*/
public void run(File storetResourceFile) throws IOException, InterruptedException, ParseException, Exception {
//If no date input, make it the maximum of available data
if(beginDate == null || beginDate.equalsIgnoreCase("")){
beginDate = "1850-01-01";
}
if(endDate == null || endDate.equalsIgnoreCase("")){
// Pull current date for upper limit of data search
DateFormat desiredDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date currentDate = new Date();
endDate = desiredDateFormat.format(currentDate);
}
//Initialize graph variables
String yAxisTitle = "y axis";
String monthlyYaxisTitle = "y axis";
String WQlabel = "??";
String graphUnits = "??";
Color color = Color.black, color2 = Color.black;
boolean showLine = true;
Data data = new Data();
String[][] sortableData = new String[0][2];
if(wqTest.equalsIgnoreCase("flow")){
//Check if any flow data exists
sortableData = data.extractFlowData(mainFolder, storetResourceFile, database, organizationID, stationID, beginDate, endDate, userData);
//Define other graph information
graphUnits = "cfs";
if(timeStep.equalsIgnoreCase("Daily")){
yAxisTitle = timeStep + " Flow [" + graphUnits + "]";
}else{
yAxisTitle = timeStep + " " + method + " Flow [" + graphUnits + "]";
}
monthlyYaxisTitle = "Monthly Average Flow [" + graphUnits + "]";
color = Color.blue;
color2 = Color.darkGray;
showLine = true;
}else{
//Search for WQ data
Object[] returnArray = data.extractWQdata(mainFolder, storetResourceFile, database, organizationID, stationID, beginDate, endDate, wqTest, userData);
sortableData = (String[][]) returnArray[0];
graphUnits = (String) returnArray[1];
WQlabel = (String) returnArray[2];
//Define other graph information
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;
showLine = false;
}
//Check if merging the datasets is desired, if so get the user data
String[][] sortableData_user = new String[0][0];
if(mergeDatasets){
User_Data user_Data = new User_Data();
sortableData_user = user_Data.readUserFile("UserData", stationID, userData, wqTest, beginDate, endDate);
}
//Sort the Data by date to remove duplicate date entries
DoubleArray doubleArray = new DoubleArray();
String[][] sortedData = doubleArray.removeDuplicateDates(sortableData);
String[][] sortedData_user = doubleArray.removeDuplicateDates(sortableData_user);
//Merge the two datasets (if user data is empty nothing will be merged)
String[][] sortedData_combined = doubleArray.mergeData(sortedData, sortedData_user, mergeMethod);
if(sortedData_combined.length == 0){
ArrayList<String> errorMessage = new ArrayList<String>();
if(sortableData.length == 0){
errorMessage.add("There is no available " + wqTest + " data in the " + database + " database for station '" + stationID + "' and the specified date range.");
if(database.equalsIgnoreCase("CDWR")){
errorMessage.add("The CDWR database is sensitive to the begin date used, try specifying a later begin date");
}
}
if(sortedData_user.length == 0){
errorMessage.add("There is no available uploaded data for station '" + stationID + "' and the specified date range");
}
writeError(errorMessage);
}
//Save analysis results
this.start = sortedData_combined[0][0];
this.end = sortedData_combined[sortedData_combined.length - 1][0];
//Get period data for analyses
String[][] period1Data = doubleArray.getPeriodData(sortedData_combined, period1Begin, period1End);
String[][] period2Data = doubleArray.getPeriodData(sortedData_combined, period2Begin, period2End);
String[][] period3Data = doubleArray.getPeriodData(sortedData_combined, period3Begin, period3End);
String[][] seasonalData = doubleArray.getSeasonalData(sortedData_combined, seasonBegin, seasonEnd);
//Perform operations on daily data before it is converted to the user desired timeStep
createTimeseriesMonthlyGraph(sortedData_combined, period1Data, period2Data, period3Data, monthlyYaxisTitle);
FlowStatistics flowStats = new FlowStatistics();
if(wqTest.equalsIgnoreCase("flow")){
//Create Envelope Graph
if(envelopeTF || rasterTF){
createTimeseriesEnvelopeGraph(sortedData_combined, yAxisTitle, true);
}
//Calculate Hydrologic Indicators of Alteration
if(calcFlowStatisticsFileTF){
flowStats.calculateAllStatisticsSummaries(mainFolder, stationID, stationName, sortedData_combined, highPercentile, lowPercentile, 0, 0, showMonthlyStatsTF,
seasonBegin, seasonEnd, period1Begin, period1End, period2Begin, period2End, period3Begin, period3End);
}
//Calculate CDPHE design low flow
if(calcCDPHElowflowTF){
CDPHE_lowFlowStats cdphe_lowflow = new CDPHE_lowFlowStats();
if(CDPHE_lowFlowType.equalsIgnoreCase("extreme-value")){
//Calculate the Extreme-value based design flow:
this.extremeValueDFLOW = cdphe_lowflow.CDPHE_ExtremeValue(sortedData_combined, CDPHE_m, CDPHE_R, CDPHE_waterYearBegin);
}else if(CDPHE_lowFlowType.equalsIgnoreCase("biological")){
//Calculate the Biologically based design flow:
double[] biologial_flows = cdphe_lowflow.CDPHE_Biological(sortedData_combined, CDPHE_m, CDPHE_R, CDPHE_clusterLength, CDPHE_clusterCountMax);
this.biologicalDFLOW_all = biologial_flows[0];
this.biologicalDFLOW_jan = biologial_flows[1];
this.biologicalDFLOW_feb = biologial_flows[2];
this.biologicalDFLOW_mar = biologial_flows[3];
this.biologicalDFLOW_apr = biologial_flows[4];
this.biologicalDFLOW_may = biologial_flows[5];
this.biologicalDFLOW_jun = biologial_flows[6];
this.biologicalDFLOW_jul = biologial_flows[7];
this.biologicalDFLOW_aug = biologial_flows[8];
this.biologicalDFLOW_sep = biologial_flows[9];
this.biologicalDFLOW_oct = biologial_flows[10];
this.biologicalDFLOW_nov = biologial_flows[11];
this.biologicalDFLOW_dec = biologial_flows[12];
}else if(CDPHE_lowFlowType.equalsIgnoreCase("human-health")){
//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
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];
this.biologicalDFLOW_jan = biologial_flows[1];
this.biologicalDFLOW_feb = biologial_flows[2];
this.biologicalDFLOW_mar = biologial_flows[3];
this.biologicalDFLOW_apr = biologial_flows[4];
this.biologicalDFLOW_may = biologial_flows[5];
this.biologicalDFLOW_jun = biologial_flows[6];
this.biologicalDFLOW_jul = biologial_flows[7];
this.biologicalDFLOW_aug = biologial_flows[8];
this.biologicalDFLOW_sep = biologial_flows[9];
this.biologicalDFLOW_oct = biologial_flows[10];
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{
//Report that there cannot be flow statistics for water quality data
String[][] errorMessage = {{"Error"," Cannot compute flow statistics as indicators of hydrologic alteration using water quality data."},{"This output is only applicable for flow analysis.",""}};
flowStats.writeStatsSummaryFile(mainFolder, errorMessage);
}
//Perform analysis method on data
sortedData_combined = doubleArray.computeFlowMethod(sortedData_combined, timeStep, method, false);
sortedData_user = doubleArray.computeFlowMethod(sortedData_user, timeStep, method, false);
period1Data = doubleArray.computeFlowMethod(period1Data, timeStep, method, false);
period2Data = doubleArray.computeFlowMethod(period2Data, timeStep, method, false);
period3Data = doubleArray.computeFlowMethod(period3Data, timeStep, method, false);
seasonalData = doubleArray.computeFlowMethod(seasonalData, timeStep, method, false);
//CalculateStatistics
CalculateStatistics(sortedData_combined, "all");
CalculateStatistics(period1Data, "period1");
CalculateStatistics(period2Data, "period2");
CalculateStatistics(period3Data, "period3");
CalculateStatistics(seasonalData, "seasonal");
//Graph the timeseries data
createTimeseriesGraph(sortedData_combined, sortedData_user, period1Data, period2Data, period3Data, color, color2, showLine, yAxisTitle, graphUnits, medianTF);
createTimeseriesBoxplot(sortedData_combined, yAxisTitle);
createTimeseriesHistogram(sortedData_combined, sortedData_user, period1Data, period2Data, period3Data, color, yAxisTitle);
createTimeseriesCDF(sortedData_combined, sortedData_user, period1Data, period2Data, period3Data, color, color2, yAxisTitle);
//Re-Format graphing data for output for use with JHighChart
SimpleDateFormat desiredDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date period1Begin_date = new Date();
Date period1End_date = new Date();
Date period2Begin_date = new Date();
Date period2End_date = new Date();
Date period3Begin_date = new Date();
Date period3End_date = new Date();
if(!period1Begin.isEmpty() && !period1End.isEmpty()){
period1Begin_date = desiredDateFormat.parse(period1Begin);
period1End_date = desiredDateFormat.parse(period1End);
}
if(!period2Begin.isEmpty() && !period2End.isEmpty()){
period2Begin_date = desiredDateFormat.parse(period2Begin);
period2End_date = desiredDateFormat.parse(period2End);
}
if(!period3Begin.isEmpty() && !period3End.isEmpty()){
period3Begin_date = desiredDateFormat.parse(period3Begin);
period3End_date = desiredDateFormat.parse(period3End);
}
String[][] graphData = new String[sortedData_combined.length][5];
SimpleDateFormat dataDateFormat = new SimpleDateFormat("yyyy-MM-dd");
if(timeStep.equalsIgnoreCase("Monthly")){
dataDateFormat = new SimpleDateFormat("yyyy-MM");
}else if(timeStep.equalsIgnoreCase("Yearly")){
dataDateFormat = new SimpleDateFormat("yyyy");
}
for(int i=0; i<sortedData_combined.length; i++){
Date newDate = dataDateFormat.parse(sortedData_combined[i][0]);
graphData[i][0] = sortedData_combined[i][0];
graphData[i][1] = sortedData_combined[i][1];
//Period1
if(newDate.compareTo(period1Begin_date) >= 0 && newDate.compareTo(period1End_date) <= 0){
if(medianTF){
graphData[i][2] = String.valueOf(median_period1);
}else{
graphData[i][2] = String.valueOf(mean_period1);
}
}else{
graphData[i][2] = "-1";
}
//Period2
if(newDate.compareTo(period2Begin_date) >= 0 && newDate.compareTo(period2End_date) <= 0){
if(medianTF){
graphData[i][3] = String.valueOf(median_period2);
}else{
graphData[i][3] = String.valueOf(mean_period2);
}
}else{
graphData[i][3] = "-1";
}
//Period3
if(newDate.compareTo(period3Begin_date) >= 0 && newDate.compareTo(period3End_date) <= 0){
if(medianTF){
graphData[i][4] = String.valueOf(median_period3);
}else{
graphData[i][4] = String.valueOf(mean_period3);
}
}else{
graphData[i][4] = "-1";
}
}
//Prep. boxplot data for output function
ArrayList<ArrayList<Double>> boxplotOutliers = new ArrayList<ArrayList<Double>>();
ArrayList<Double> outliers = new ArrayList<Double>();// Get daily outliers
double IQR = upperQuartile - lowerQuartile;// Find IQR
for (int i = 0; i < sortedData_combined.length; i++){
double value = Double.parseDouble(sortedData_combined[i][1]);
if(value < (lowerQuartile - 1.5 * IQR) || value > (upperQuartile + 1.5 * IQR)){
outliers.add(value);
}
}
boxplotOutliers.add(outliers);
double[][] boxplotData = {{max},{upperQuartile},{median},{lowerQuartile},{min}};
//Write output for JHighChart boxplot and timeseries for use on eRAMS
//output for JHighChart's monthly boxplot is performed during the JFreeChart graphing of monthly boxplot
Arrays.sort(graphData, new cfa.DateComparator());
doubleArray.writeTimeSeries(mainFolder, graphData, timeStep, getTimeseriesOutput().getName(), false);
doubleArray.writeBoxplot(mainFolder, boxplotOutliers, boxplotData, getBoxplotOutput().getName());
//Get today's date for the source reference
Date currentDate = new Date();
SimpleDateFormat sourceDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String today = sourceDateFormat.format(currentDate);
if(database.equalsIgnoreCase("USGS")){
this.dataSource = "Stream flow data and water quality test data retrieved from the U.S. Geological Survey, National Water Information System: Web Interface. http://waterdata.usgs.gov/nwis, accessed: " + today;
}else if(database.equalsIgnoreCase("STORET")){
this.dataSource = "Stream flow data and water quality test data retrieved from the U.S. Environmental Protection Agency, STORET. http://www.epa.gov/storet/index.html accessed: " + today;
}else if(database.equalsIgnoreCase("CDWR")){
this.dataSource = "Stream flow data retrieved from the Colorado Division of Water Resources, CDWR. http://www.dwr.state.co.us accessed: " + today;
}else{
this.dataSource = "Stream flow data provided by the user. Flow analysis accessed: " + today;
}
this.len = String.valueOf(sortedData_combined.length);
this.units = graphUnits;
}
public static void main(String[] args) throws IOException, InterruptedException, Exception {
//Run model
guiTimeseries_Model timeseries_Model = new guiTimeseries_Model();
timeseries_Model.run(null);
}
}