Package gov.nasa.arc.mct.fastplot.bridge

Source Code of gov.nasa.arc.mct.fastplot.bridge.PlotDataSeries

/*******************************************************************************
* Mission Control Technologies, Copyright (c) 2009-2012, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* The MCT platform is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* MCT includes source code licensed under additional open source licenses. See
* the MCT Open Source Licenses file included with this distribution or the About
* MCT Licenses dialog available at runtime from the MCT Help menu for additional
* information.
*******************************************************************************/
package gov.nasa.arc.mct.fastplot.bridge;


import gov.nasa.arc.mct.fastplot.bridge.PlotConstants.AxisOrientationSetting;
import gov.nasa.arc.mct.fastplot.bridge.PlotConstants.PlotLineConnectionType;
import gov.nasa.arc.mct.fastplot.view.legend.AbstractLegendEntry;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.Stroke;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import plotter.DoubleData;
import plotter.xy.CompressingXYDataset;
import plotter.xy.CompressingXYDataset.MinMaxChangeListener;
import plotter.xy.DefaultCompressor;
import plotter.xy.LinearXYPlotLine;
import plotter.xy.LinearXYPlotLine.LineMode;
import plotter.xy.XYDimension;


/**
* Holds the information for a Quinn-Curtis data series representing a single
* entry on a plot. This includes, the data, the line plot representing it, the
* plotting color, the legend, and the code for compressing data as it is put
* into the buffers.
*/
class PlotDataSeries  implements MinMaxChangeListener, AbstractPlotDataSeries {
  public static final Stroke EMPTY_STROKE = new Stroke() {
    private final Shape EMPTY_SHAPE = new Polygon();
    @Override
    public Shape createStrokedShape(Shape p) {
      return EMPTY_SHAPE;
    }
  };

  private final static Logger logger = LoggerFactory
      .getLogger(PlotDataSeries.class);

  private PlotterPlot plot;
  CompressingXYDataset dataset;
  Color color;
  LinearXYPlotLine linePlot;
  LegendEntry legendEntry;
  LinearXYPlotLine regressionLine;
  private boolean updateRegressionLine = true;

  private String dataSetName;

  PlotDataSeries(PlotterPlot thePlot, String dataSetName, Color theColor) {
    plot = thePlot;
    color = theColor;
    this.dataSetName = dataSetName;
    setupLinePlot();
    setupDataSet(dataSetName);
  };


  /**
   * Resets the series' buffered data.
   */
  void resetData() {
    logger.debug("PlotDataSeries.resetData()");
    // remove the process variable for this item from the plot
    plot.getPlotView().getContents().remove(linePlot);
    if (regressionLine != null) {
      removeRegressionLine();
    }
    setupLinePlot();
    setupDataSet(dataSetName);
  }

  private void setupDataSet(String dataSetName) {

    assert plot.getPlotView() != null : "Plot Object not initalized";
    assert linePlot != null;

    dataset = new CompressingXYDataset(linePlot, new DefaultCompressor());
    // Listen for min/max changes on the non-time axis
    if(plot.getAxisOrientationSetting() == AxisOrientationSetting.X_AXIS_AS_TIME) {
      dataset.addYMinMaxChangeListener(this);
    } else {
      dataset.addXMinMaxChangeListener(this);
    }

    // add limit manager
    // Add alarms which under pin notifications for when data goes out of
    // range
    // and the limit triangles are put on the plot.
    plot.getLimitManager().addLimitAlarms(dataset);
   
  }

  private void setupLinePlot() {
    /* Note that once a LegendEntry acquires a plot line, it may
     * apply its own setup to it. */
   
    linePlot = new LinearXYPlotLineWrapper(plot.getPlotView().getXAxis(), plot.getPlotView().getYAxis(),
        plot.getAxisOrientationSetting() == AxisOrientationSetting.X_AXIS_AS_TIME ? XYDimension.X : XYDimension.Y);
    LineMode lineMode = LineMode.STEP_XY;
    if (plot.getPlotAbstraction().getPlotLineConnectionType() == PlotLineConnectionType.DIRECT) {
      lineMode = LineMode.STRAIGHT;
    }
    linePlot.setLineMode(lineMode);
    linePlot.setForeground(color);
   
    if (plot.getPlotAbstraction().getPlotLineDraw().drawMarkers()) {
      for (int i = 0; i < PlotConstants.MAX_NUMBER_OF_DATA_ITEMS_ON_A_PLOT; i++) {
        if (PlotLineColorPalette.getColor(i).getRGB() == color.getRGB()) {
          //linePlot.setPointFill(PlotLineShapePalette.getShape(i));
          linePlot.setPointIcon(new PlotMarkerIcon(PlotLineShapePalette.getShape(i)));
        }
      }
    }
   
        if (!plot.getPlotAbstraction().getPlotLineDraw().drawLine()) {
            linePlot.setStroke(EMPTY_STROKE);
        }
   
    plot.getPlotView().getContents().add(linePlot);
    if (legendEntry != null) {
      legendEntry.setPlot(linePlot);
    }
    if (legendEntry != null && legendEntry.hasRegressionLine()) {
      addRegressionLine();
    }
  }
 
  /**
   *
   */
  private void addRegressionLine() {
    regressionLine = new LinearXYPlotLine(plot.getPlotView().getXAxis(), plot.getPlotView().getYAxis(),
        plot.getAxisOrientationSetting() == AxisOrientationSetting.X_AXIS_AS_TIME ? XYDimension.X : XYDimension.Y);
    regressionLine.setLineMode(LineMode.STRAIGHT);
    regressionLine.setForeground(color);
    regressionLine.setStroke(new BasicStroke(PlotConstants.SLOPE_LINE_WIDTH,
                BasicStroke.CAP_BUTT,
                BasicStroke.JOIN_MITER,
                10.0f, PlotConstants.dash1, 0.0f));
    plot.getPlotView().getContents().add(regressionLine);
    legendEntry.setHasRegressionLine(true);
    legendEntry.setRegressionLine(regressionLine);
  }
 
  private void removeRegressionLine() {
    plot.getPlotView().getContents().remove(regressionLine);
    plot.getPlotView().getContents().validate();
    plot.getPlotView().getContents().repaint();
    regressionLine = null;
  }

  /** Get the regression line for this data series
   * @return regressionLine
   */
  public LinearXYPlotLine getRegressionLine() {
    return regressionLine;
  }
 
  /** Set the regression line object for this data series
   * @param line a LinearXYPlotLine
   */
  public void setRegressionLine(LinearXYPlotLine line) {
    regressionLine = line;
  }

  public String getDataSetName() {
    return dataSetName;
  }

  void setPlottingColor(Color theColor) {
    color = theColor;
  }

  void setLegend(LegendEntry legend) {
    legendEntry = legend;
    legendEntry.setPlotLabelingAlgorithm(plot.plotLabelingAlgorithm);
  }

  void setLinePlot(LinearXYPlotLine thePlot) {
    linePlot = thePlot;
  }

  LinearXYPlotLine getPlot() {
    return linePlot;
  }

  public LegendEntry getLegendEntry() {
    return legendEntry;
  }

  Color getColor() {
    return color;
  }

  CompressingXYDataset getData() {
    return dataset;
  }

  /**
   * Compress data in local plot buffer by fifty percent.
   */
  public void compressByFiftyPercent() {
    // FIXME: Handle this in the dataset
  }

  /**
   * Search through the data set to identify the maximum value in the range
   *
   * @param maxTime
   *            upper bound on time range to search
   * @param minTime
   *            lower bound on the time range to search
   * @return minimum value in data set between max and max time (inclusive)
   */
  double[] getMaxValue(long maxTime, long minTime) {
    double max = -Double.MAX_VALUE;
    double time = 0;
    DoubleData nonTimeData = getNonTimeData(dataset);
    DoubleData timeData = getTimeData(dataset);

    if (timeData != null) {
      int n = timeData.getLength();
      for (int i = 0; i < n; i++) {
        double nonTime = nonTimeData.get(i);

          // System.out.println("min time " + minTime + " Max Time " +
          // maxTime + " timeData " + timeData[i] + " = " +
          // nonTimeData[i]);
          double time2 = timeData.get(i);
          if (time2 >= minTime && time2 <= maxTime) {
            if (nonTime > max) {
              max = nonTime;
              time = time2;
            }
          }
      }
    }
    double[] result = new double[2];
    result[0] = max;
    result[1] = time;
    return result;
  }

  /**
   * Search through the data set to identify the minimum value in the range
   *
   * @param maxTime
   *            upper bound on time range to search
   * @param minTime
   *            lower bound on the time range to search
   * @return minimum value in data set between min and max time (inclusive)
   */
  double[] getMinValue(long maxTime, long minTime) {
    double min = Double.MAX_VALUE;
    double time = 0;
    DoubleData nonTimeData = getNonTimeData(dataset);
    DoubleData timeData = getTimeData(dataset);
    if (timeData != null) {
      int n = timeData.getLength();
      for (int i = 0; i < n; i++) {
        double time2 = timeData.get(i);
          if (time2 >= minTime && time2 <= maxTime) {
            double nonTime = nonTimeData.get(i);
            if (nonTime < min) {
              min = nonTime;
              time = time2;
            }
          }
      }
    }
    double[] result = new double[2];
    result[0] = min;
    result[1] = time;
    return result;
  }

  DoubleData getNonTimeData(CompressingXYDataset dataSet) {
    if(plot.getAxisOrientationSetting() == AxisOrientationSetting.X_AXIS_AS_TIME) {
      return dataSet.getYData();
    } else {
      return dataSet.getXData();
    }
  }

  DoubleData getTimeData(CompressingXYDataset dataSet) {
    if(plot.getAxisOrientationSetting() == AxisOrientationSetting.X_AXIS_AS_TIME) {
      return dataSet.getXData();
    } else {
      return dataSet.getYData();
    }
  }


  @Override
  public void minMaxChanged(CompressingXYDataset dataset, XYDimension dimension) {
    plot.minMaxChanged();
  }


  @Override
  public String toString() {
    int size = dataset.getPointCount();
    if(size == 0) {
      return "Full Data: Number data points 0\n";
    } else {
      return "Full Data: current value " + dataset.getYData().get(size - 1) + " Number data points " + size + "\n";
    }
  }
 
  public void updateRegressionLine() {
    if (!updateRegressionLine) {
      return;
    }
    if (getLegendEntry() != null) {
      if (getLegendEntry().hasRegressionLine()) {
        if (regressionLine == null) {
          addRegressionLine();
        }
      } else {
        if (regressionLine != null) {
          removeRegressionLine();
        }
        return;
      }
      regressionLine.removeAllPoints();
      // Not enough data for regression
      if (getData().getPointCount() < legendEntry.getNumberRegressionPoints()) {
        return;
      }
      double[] xRegData = new double[legendEntry.getNumberRegressionPoints()];
      double[] yRegData = new double[legendEntry.getNumberRegressionPoints()];
     
      int xDataLength = getData().getXData().getLength();
      int yDataLength = getData().getYData().getLength();
      int shift = 0;
      //Get last n x and y values that are valid values
      for (int i = legendEntry.getNumberRegressionPoints(); i > 0; i--) {
        if (((xDataLength - (legendEntry.getNumberRegressionPoints() - i) - 1 - shift) < 0) ||
            ((yDataLength - (legendEntry.getNumberRegressionPoints() - i) - 1 - shift) < 0)) { 
          // Not enough data for regression
          return;
        }
        while (
            Double.isNaN(getData().getXData().get(xDataLength - (legendEntry.getNumberRegressionPoints() - i) - 1 - shift)) ||
            Double.isNaN(getData().getYData().get(yDataLength - (legendEntry.getNumberRegressionPoints() - i) - 1 - shift))) {
          if ((yDataLength - (legendEntry.getNumberRegressionPoints() - i) - 1 - (shift + 1)) < 0 ||
              (xDataLength - (legendEntry.getNumberRegressionPoints() - i) - 1 - (shift + 1)) < 0) {
            // Not enough data for regression
            return;
          } else {
            shift++;
          }

        }
        xRegData[i-1] = getData().getXData().get(xDataLength - (legendEntry.getNumberRegressionPoints() - i) - 1 - shift);
        yRegData[i-1] = getData().getYData().get(yDataLength - (legendEntry.getNumberRegressionPoints() - i) - 1 - shift);
      }
      double x = xRegData[legendEntry.getNumberRegressionPoints() - 1],  y=yRegData[legendEntry.getNumberRegressionPoints() - 1];
      HighPrecisionLinearRegression lr = new HighPrecisionLinearRegression(xRegData, yRegData);
     
      if (lr.getSlopeAsBigDecimal() != null &&
          lr.getIntercept() != null &&
        !Double.isNaN(lr.getSlope()) &&
        !Double.isInfinite(lr.getSlope()) &&
        !Double.isInfinite(lr.getIntercept().doubleValue()) &&
        !Double.isNaN(lr.getIntercept().doubleValue())   
        ) {
        // Per Jira 3358 specs and customer discussions, translate regression line so that
        // origin is at last data point
        regressionLine.add(x, y); // Add origin of line
        if(linePlot.getIndependentDimension() == XYDimension.X) {       
          regressionLine.add(Long.valueOf(plot.getMaxTime()).doubleValue(),
              lr.calculateY(Long.valueOf(plot.getMaxTime()).doubleValue()) +
              (y - lr.calculateY(x))); // Add terminus of line
        }         else {
          regressionLine.add(lr.calculateX(Long.valueOf(plot.getMaxTime()).doubleValue()) +
              (x - lr.calculateX(y)),Long.valueOf(plot.getMaxTime()).doubleValue()); // Add terminus of line
        }

      }
    }
  }


  /** Get whether or not to update the prediction line (not updated if the
   * most recent data is not shown on a zoomed/panned plot.
   * @return updateRegressionLine
   */
  public boolean isUpdateRegressionLine() {
    return updateRegressionLine;
  }


  /** Set whether or not to update the prediction line (not updated if the
   * most recent data is not shown on a zoomed/panned plot.
   * @param updateRegressionLine boolean indicator
   */
  public void setUpdateRegressionLine(boolean updateRegressionLine) {
    this.updateRegressionLine = updateRegressionLine;
  }


  @Override
  public void setLegendEntry(AbstractLegendEntry entry) {
    // TODO Auto-generated method stub
   
  }
}
TOP

Related Classes of gov.nasa.arc.mct.fastplot.bridge.PlotDataSeries

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.