Displaying differences for changeset
 
display as  

src/java/cfa/Graphing.java

@@ -16,8 +16,11 @@
 import org.jfree.chart.plot.XYPlot;
 import org.jfree.chart.renderer.xy.XYItemRenderer;
 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.data.time.Day;
+import org.jfree.data.time.Month;
 import org.jfree.data.time.TimeSeries;
 import org.jfree.data.time.TimeSeriesCollection;
+import org.jfree.data.time.Year;
 import org.jfree.data.xy.XYDataset;
 import org.jfree.data.xy.XYSeries;
 import org.jfree.data.xy.XYSeriesCollection;
@@ -26,7 +29,7 @@
 import org.jfree.ui.TextAnchor;
 
 /**
-* Last Updated: 5-June-2014
+* Last Updated: 18-June-2014
 * @author Tyler Wible
 * @since 3-February-2014
 */
@@ -246,6 +249,82 @@
         return plot;
     }
     /**
+     * Graphs the provided "series" as an XY series with x as the first column y as the second column in the provided color
+     * on the provided XYPlot, this series is not visible in the legend
+     * @param plot  the XYPlot to add the "series" to
+     * @param series  a String[][] array with series[all][0] =  dates in yyyy-MM-dd format, series[all][1] = y-values
+     * @param timeStep  a flag for what data is being graphed ("Daily", "Monthly", or "Yearly")
+     * @param seriesName  the name of the series to appear in the legend (if showInLegend is true)
+     * @param lineColor  the color of the line to be graphed
+     * @param seriesIndex  the graph index of the series to be plotted
+     * @param showInLegend  a flag to show this series in the legend (true) or not (false)
+     * @param leapYearTF  a flag to check if the main dataset is a leap year or not so that if graphing data repeatedly for one year (see timeseries envelope graph) Feb. 29th does or doesnot get plotted
+     * @return the provided XYPlot with the series added to it with the above properties
+     */
+    public XYPlot graphSeries(XYPlot plot,
+                              String[][] series,
+                              String timeStep,
+                              String seriesName,
+                              Color lineColor,
+                              int seriesIndex,
+                              boolean showInLegend,
+                              boolean leapYearTF){
+        TimeSeries timeSeries = new TimeSeries(seriesName);
+        for(int i=0; i<series.length; i++){
+            String tmpStr = series[i][0];
+            double value = Double.parseDouble(series[i][1]);
+            
+            if(timeStep.equalsIgnoreCase("daily")){
+                double d = Double.parseDouble(tmpStr.substring(8));
+                double m = Double.parseDouble(tmpStr.substring(5,7));
+                double y = Double.parseDouble(tmpStr.substring(0,4));
+                int day =  (int)d;
+                int month = (int)m;
+                int year = (int)y;
+                try{
+                    Day date = new Day(day,month,year);//day,month,year
+                    timeSeries.add(date, value);
+                }catch(IllegalArgumentException e){
+                    //If there is an error with the date and it is not due to trying 
+                    //to plot Feb. 29th in a non-leap year then throw the error
+                    if(!leapYearTF && month!=2 && day!=29){
+                        throw new IllegalArgumentException (e);
+                    }
+                }
+                
+            }else if(timeStep.equalsIgnoreCase("monthly")){
+                double m = Double.parseDouble(tmpStr.substring(5,7));
+                double y = Double.parseDouble(tmpStr.substring(0,4));
+                int month = (int)m;
+                int year = (int)y;
+                Month date = new Month(month,year);//month,year
+                timeSeries.add(date, value);
+                
+            }else if(timeStep.equalsIgnoreCase("yearly")){
+                double y = Double.parseDouble(tmpStr.substring(0,4));
+                int year = (int)y;
+                Year date = new Year(year);//year
+                timeSeries.add(date, value);
+            }
+        }
+
+        //Create a graph with the line
+        TimeSeriesCollection currentDataset = new TimeSeriesCollection(timeSeries);
+        XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
+        renderer.setSeriesPaint(0, lineColor);
+        renderer.setSeriesVisibleInLegend(0, showInLegend);
+
+        //Set the line data, renderer, and axis into plot
+        plot.setDataset(seriesIndex, currentDataset);
+        plot.setRenderer(seriesIndex, renderer);
+
+        //Map the line to the first Domain and first Range
+        plot.mapDatasetToDomainAxis(0, 0);
+        plot.mapDatasetToRangeAxis(0, 0);
+
+        return plot;
+    }
+    /**
      * Graphs the TimeSeries on to the provided plot with the below properties for rendering, color, series index
      * @param plot  The XYPlot to graph the XYSeries on
      * @param currentLine  the XYSeries containing the x,y points of the current line series
@@ -305,7 +384,7 @@
                 ));
         }
         
-        //Put the LDC line data, renderer, and axis into plot
+        //Put the line data, renderer, and axis into plot
         plot.setDataset(graphIndex, currentDataset);
         plot.setRenderer(graphIndex, currentRenderer);
 

src/java/cfa/guiTimeseries_Model.java

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

src/java/m/cfa/Timeseries_V1_0.java

@@ -67,6 +67,7 @@
                                 model.getBoxplot(),
                                 model.getHistogram(),
                                 model.getMonthlyGraph(),
+                                //model.getTimeseriesEnvelope(),
                                 model.getCDF(),
                                 model.getFlowStatistics_summary().getName(),
                                 //Below are the result graph files for use by JHighCharts on eRAMS for duplicating the above graphs
@@ -74,6 +75,7 @@
                                 model.getBoxplotOutput().getName(),
                                 model.getMonthlyTimeseriesOutput().getName(),
                                 model.getMonthlyBoxplotOutput().getName(),
+                                //model.getTimeseriesEnvelopeOutput().getName(),
                                 model.getHistogramOutput().getName(),
                                 model.getCDFoutput().getName());
     }
@@ -140,12 +142,14 @@
         result.put(JSONUtils.data("histogram", model.getHistogram()));
         result.put(JSONUtils.data("cdf_graph", model.getCDF()));
         result.put(JSONUtils.data("monthlyAverage_graph", model.getMonthlyGraph()));
+        //result.put(JSONUtils.data("timeseries_envelope_graph", model.getTimeseriesEnvelope()));
         
         //Get result files for JSHighCharts
         String graphDataFiles = model.getTimeseriesOutput().getName() + "|" +  
                       model.getBoxplotOutput().getName() + "|" + 
                       model.getMonthlyTimeseriesOutput().getName() + "|" + 
                       model.getMonthlyBoxplotOutput().getName() + "|" +
+                      //model.getTimeseriesEnvelopeOutput().getName() + "|" +
                       model.getHistogramOutput().getName() + "|" +
                       model.getCDFoutput().getName();
         result.put(JSONUtils.data("graph_data_files", graphDataFiles));