//# PlotData.h: Classes to represent data for plots. //# Copyright (C) 2008 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id: $ #ifndef PLOTDATA_H_ #define PLOTDATA_H_ #include <graphics/GenericPlotter/PlotOptions.h> #include <casacore/casa/Arrays/Matrix.h> #include <casacore/casa/Arrays/Vector.h> #include <casacore/casa/BasicSL/String.h> #include <casacore/casa/Utilities/CountedPtr.h> #include <casacore/casa/BasicMath/Math.h> namespace casa { // Typedef for a point, which is two doubles (x and y). typedef std::pair<double, double> ppoint_t; ////////////////////// // ABSTRACT CLASSES // ////////////////////// // Deliberately vague to be general enough to allow for many different types // of data, but is it too vague to be useful? Since the interface is meant // to be a simple plotter, it may be better to restrict PlotData to be more // like PlotPointData, which would eliminate possibilities for data like // functions but would also eliminate a lot of vaguery. class PlotData { public: PlotData() { } virtual ~PlotData() { } // ABSTRACT METHODS // // Returns whether the contained data is valid or not. virtual bool isValid() const = 0; // Returns whether this object will delete its underlying data structures // upon deconstruction or not. virtual bool willDeleteData() const = 0; // Sets whether this object will delete its underlying data structures upon // deconstruction or not. virtual void setDeleteData(bool del = true) = 0; }; typedef casacore::CountedPtr<PlotData> PlotDataPtr; // A single source of data that basically provides indexing of its values. class PlotSingleData : public virtual PlotData { public: PlotSingleData() { } virtual ~PlotSingleData() { } // ABSTRACT METHODS // // Returns the number of points. virtual unsigned int size() const = 0; // Returns the value at given index. virtual double at(unsigned int i) const = 0; // Gets the minimum and maximum values. Returns false for error. virtual bool minMax(double& min, double& max) = 0; }; INHERITANCE_POINTER2(PlotSingleData, PlotSingleDataPtr, PlotData, PlotDataPtr) // A source of data used to supply x and y values. Basically consists of // indexing its values. class PlotPointData : public virtual PlotData { public: PlotPointData() { } virtual ~PlotPointData() { } // ABSTRACT METHODS // // Returns the number of points. virtual unsigned int size() const = 0; // Returns the x value at the given index. virtual double xAt(unsigned int i) const = 0; // Returns the y value at the given index. virtual double yAt(unsigned int i) const = 0; // Gets the minimum and maximum values. Returns false for error. virtual bool minsMaxes(double& xMin, double& xMax, double& yMin, double& yMax) = 0; // IMPLEMENTED METHODS // // Gets the x and y values at the given index. Default implementation // just calls xAt and yAt, but in subclasses where performance could be // gained, this method should be overridden. Implementations for plots // that use PlotPointData should use this method by default in case there // are performance gains. virtual void xAndYAt(unsigned int index, double& x, double& y) const; }; INHERITANCE_POINTER2(PlotPointData, PlotPointDataPtr, PlotData, PlotDataPtr) // casacore::Data that adds masking functionality on top of normal point data. class PlotMaskedPointData : public virtual PlotPointData { public: PlotMaskedPointData() { } virtual ~PlotMaskedPointData() { } // ABSTRACT METHODS // // Returns the number of masked points. virtual unsigned int sizeMasked() const = 0; // Returns the number of unmasked points. virtual unsigned int sizeUnmasked() const = 0; // Returns whether the data is masked at the given point or not. virtual bool maskedAt(unsigned int index) const = 0; // Gets the mins/maxes for just the masked points. virtual bool maskedMinsMaxes(double& xMin, double& xMax, double& yMin, double& yMax) = 0; // Gets the mins/maxes for just the unmasked points. virtual bool unmaskedMinsMaxes(double& xMin, double& xMax, double& yMin, double& yMax) = 0; // Returns whether data is plotted in reverse order (right to left), // needed when connecting points virtual bool reverseConnect(unsigned int index) const = 0; // Returns whether to plot conjugate data (e.g. UV plots) virtual bool plotConjugates() const = 0; // IMPLEMENTED METHODS // // Gets the x and y values and the mask at the given index. See // PlotPointData::xAndYAt(). virtual void xyAndMaskAt(unsigned int index, double& x, double& y, bool& mask) const; }; INHERITANCE_POINTER(PlotMaskedPointData, PlotMaskedPointDataPtr, PlotPointData, PlotPointDataPtr, PlotData, PlotDataPtr) // casacore::Data that adds error functionality on top of normal plot data. class PlotErrorData : public virtual PlotPointData { public: PlotErrorData() { } virtual ~PlotErrorData() { } // ABSTRACT METHODS // // Returns the "left" error for x at the given index. virtual double xLeftErrorAt(unsigned int i) const = 0; // Returns the "right" error for x at the given index. virtual double xRightErrorAt(unsigned int i) const = 0; // Returns the "bottom" error for y at the given index. virtual double yBottomErrorAt(unsigned int i) const = 0; // Returns the "top" error for y at the given index. virtual double yTopErrorAt(unsigned int i) const = 0; // Gets the maximum errors for the four sides. virtual bool errorMaxes(double& xLeft, double& xRight, double& yBottom, double& yTop) = 0; // IMPLEMENTED METHODS // // Gets the x and y values and error data at the given index. See // PlotPointData::xAndYAt(). virtual void xyAndErrorsAt(unsigned int index, double& x, double& y, double& xLeftError, double& xRightError, double& yBottomError, double& yTopError) const; }; INHERITANCE_POINTER(PlotErrorData, PlotErrorDataPtr, PlotPointData, PlotDataPtr, PlotData, PlotDataPtr) // casacore::Data that differentiates different points into different "bins" on top of // normal point data functionality. class PlotBinnedData : public virtual PlotPointData { public: // Constructor. PlotBinnedData() { } // Destructor. virtual ~PlotBinnedData() { } // ABSTRACT METHODS // // Returns the total number of bins that the data is in. virtual unsigned int numBins() const = 0; // Returns the bin index number for the given index. MUST be between 0 and // numBins(). virtual unsigned int binAt(unsigned int i) const = 0; virtual unsigned int connectBinAt(unsigned int i) const { return binAt(i); }; // Return map of colorized values to color, and whether all plots use the same color list virtual std::map<std::string, std::string> getColorizeMap(bool& shared_colormap) const = 0; // IMPLEMENTED METHODS // // Returns true if the data is binned, false otherwise. virtual bool isBinned() const { return numBins() > 1; } }; INHERITANCE_POINTER(PlotBinnedData, PlotBinnedDataPtr, PlotPointData, PlotDataPtr, PlotData, PlotDataPtr) // casacore::Data for raster plots, which can be thought of as three-dimensional. Used // for images, with the values being in one of the givne formats. class PlotRasterData : public virtual PlotData { public: // casacore::Format that the data is in enum Format { RGB32, // data is an RBG integer, like 0x60A0C0 ARGB32, // data is an ARGB integer, like 0xFF60A0C0 SPECTROGRAM // data is meant for a spectrogram, not specific colors }; // Origin point of the data - in other words, where (0,0) is located // visually on the canvas. Default is LLEFT. enum Origin { LLEFT, LRIGHT, ULEFT, URIGHT }; PlotRasterData() { } virtual ~PlotRasterData() { } // ABSTRACT METHODS // // Returns the data origin. virtual Origin origin() const = 0; // Sets the data origin. virtual void setOrigin(Origin o) = 0; // Returns the range of x. virtual prange_t xRange() const = 0; // Returns the range of y. virtual prange_t yRange() const = 0; // Sets the range of x. virtual void setXRange(double from, double to) = 0; // Sets the range of y. virtual void setYRange(double from, double to) = 0; // Returns the range of the data values. virtual prange_t valueRange() const = 0; // Returns the data value at the given (x,y) coordinate. virtual double valueAt(double x, double y) const = 0; // Gets color bar values. virtual std::vector<double>* colorBarValues(unsigned int max = 1000) const = 0; }; INHERITANCE_POINTER2(PlotRasterData, PlotRasterDataPtr, PlotData, PlotDataPtr) ///////////////////////////// // DEFAULT IMPLEMENTATIONS // ///////////////////////////// // Default implementation of PlotSingleData that supports raw arrays, vectors, // and CASA Vectors. The class is templated, but since data sources are // expected in doubles it should be a numeric type that can be casted to a // double. template <class T> class PlotSingleDataImpl : public virtual PlotSingleData { public: // Invalid data constructor. PlotSingleDataImpl(): m_vector(NULL), m_cvector(NULL), m_array(NULL), m_arraySize(0), m_shouldDelete(false) { } // casacore::Data using different standard containers. // <group> PlotSingleDataImpl(std::vector<T>& value, bool shouldDelete = false): m_vector(&value), m_cvector(NULL), m_array(NULL), m_arraySize(0), m_shouldDelete(shouldDelete) { recalculateMinMax(); } PlotSingleDataImpl(casacore::Vector<T>& value, bool shouldDelete = false): m_vector(NULL), m_cvector(&value), m_array(NULL), m_arraySize(0), m_shouldDelete(shouldDelete) { recalculateMinMax(); } PlotSingleDataImpl(T*& value, unsigned int size, bool shouldDelete= false): m_vector(NULL), m_cvector(NULL), m_array(value), m_arraySize(size), m_shouldDelete(shouldDelete) { recalculateMinMax(); } // </group> // Destructor. ~PlotSingleDataImpl() { if(m_shouldDelete) { if(m_vector != NULL) delete m_vector; if(m_cvector != NULL) delete m_cvector; if(m_array != NULL) delete m_array; } } // Implements PlotData::isValid(). bool isValid() const { return m_vector != NULL || m_cvector != NULL || m_array != NULL; } // Implements PlotData::willDeleteData(). bool willDeleteData() const { return m_shouldDelete; } // Implements PlotData::setDeleteData(). void setDeleteData(bool del = true) { m_shouldDelete = del; } // Implements PlotSingleData::size(). unsigned int size() const { if(m_vector != NULL) return m_vector->size(); if(m_cvector != NULL) return m_cvector->size(); if(m_array != NULL) return m_arraySize; return 0; } // Implements PlotSingleData::at(). double at(unsigned int i) const { if(m_vector != NULL) return (double)(*m_vector)[i]; if(m_cvector != NULL) return (double)(*m_cvector)[i]; if(m_array != NULL) return (double)m_array[i]; return 0; } // Implements PlotSingleData::minMax(). bool minMax(double& min, double& max) { if(!isValid() || size() == 0) return false; min = m_min; max = m_max; return true; } // Recalculates the cached min and max. Should be used if the underlying // data structure changes. void recalculateMinMax() { if(!isValid()) return; unsigned int n = size(); if(n == 0) return; double temp = (double)at(0); m_min = m_max = temp; if(m_vector != NULL) { for(unsigned int i = 1; i < n; i++) { temp = (double)(*m_vector)[i]; if(temp < m_min) m_min = temp; if(temp > m_max) m_max = temp; } } else if(m_cvector != NULL) { for(unsigned int i = 1; i < n; i++) { temp = (double)(*m_cvector)[i]; if(temp < m_min) m_min = temp; if(temp > m_max) m_max = temp; } } else if(m_array != NULL) { for(unsigned int i = 1; i < n; i++) { temp = (double)m_array[i]; if(temp < m_min) m_min = temp; if(temp > m_max) m_max = temp; } } } private: std::vector<T>* m_vector; casacore::Vector<T>* m_cvector; T* m_array; unsigned int m_arraySize; bool m_shouldDelete; double m_min, m_max; }; typedef PlotSingleDataImpl<int> PlotSingleIntData; typedef PlotSingleDataImpl<unsigned int> PlotSingleUIntData; typedef PlotSingleDataImpl<float> PlotSingleFloatData; typedef PlotSingleDataImpl<double> PlotSingleDoubleData; // Default implementation of PlotPointData that supports raw arrays, vectors, // and CASA Vectors. The class is templated, but since data sources are // expected in doubles it should be a numeric type that can be casted to a // double. It can either be both x and y data, or just y data (where x is the // index). template <class T> class PlotPointDataImpl : public virtual PlotPointData { public: // X/Y constructors. // <group> PlotPointDataImpl(std::vector<T>& x, std::vector<T>& y, bool shouldDelete = false) : m_xData(x, shouldDelete), m_yData(y, shouldDelete) { } PlotPointDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, bool shouldDelete = false) : m_xData(x, shouldDelete), m_yData(y, shouldDelete) { } PlotPointDataImpl(T*& x, T*& y, unsigned int size, bool shouldDel = false): m_xData(x, size, shouldDel), m_yData(y, size, shouldDel) { } // </group> // Y constructors. // <group> PlotPointDataImpl(std::vector<T>& y, bool shouldDelete = false) : m_yData(y, shouldDelete) { } PlotPointDataImpl(casacore::Vector<T>& y, bool shouldDelete = false) : m_yData(y, shouldDelete) { } PlotPointDataImpl(T*& y, unsigned int size, bool shouldDel = false): m_yData(y, size, shouldDel) { } // </group> virtual ~PlotPointDataImpl() { } // Implements PlotData::isValid(). bool isValid() const { return m_yData.isValid(); } // Implements PlotData::willDeleteData(). virtual bool willDeleteData() const { return (m_yData.isValid() && m_yData.willDeleteData()) && (!m_xData.isValid() || m_xData.willDeleteData()); } // Implements PlotData::setDeleteData(). virtual void setDeleteData(bool del = true) { if(m_xData.isValid()) m_xData.setDeleteData(del); if(m_yData.isValid()) m_yData.setDeleteData(del); } // Implements PlotPointData::size(). unsigned int size() const { if(!m_xData.isValid()) return m_yData.size(); else return casacore::min(m_xData.size(), m_yData.size()); } // Implements PlotPointData::xAt(). If no x data is given, the index is // returned. double xAt(unsigned int i) const { if(m_xData.isValid()) return m_xData.at(i); else return i; } // Implements PlotPointData::yAt(). double yAt(unsigned int i) const { return m_yData.at(i); } // Implements PlotPointData::minsMaxes(). bool minsMaxes(double& xMin, double& xMax, double& yMin, double& yMax) { if(!m_xData.isValid()) { xMin = 0; xMax = m_yData.size(); return m_yData.minMax(yMin, yMax); } else { return m_xData.minMax(xMin, xMax) && m_yData.minMax(yMin, yMax); } } private: PlotSingleDataImpl<T> m_xData; PlotSingleDataImpl<T> m_yData; }; typedef PlotPointDataImpl<int> PlotPointIntData; typedef PlotPointDataImpl<unsigned int> PlotPointUIntData; typedef PlotPointDataImpl<float> PlotPointFloatData; typedef PlotPointDataImpl<double> PlotPointDoubleData; // Specialized subclass of PlotPointData that creates histogram data from // single point data. A histogram divides up the data into a number of "bins" // and then counts the number of data that falls into each bin. This class can // act as both an interface for specializations or a concrete subclass of // PlotPointData in itself. class PlotHistogramData : public virtual PlotPointData { public: // Constructor which takes data and number of bins. PlotHistogramData(PlotSingleDataPtr data, unsigned int numBins); // Destructor. virtual ~PlotHistogramData(); // Implements PlotData::isValid(). virtual bool isValid() const; // Implements PlotData::willDeleteData(). virtual bool willDeleteData() const; // Implements PlotData::setDeleteData(). virtual void setDeleteData(bool del = true); // Implements PlotPointData::size(). virtual unsigned int size() const { return numBins(); } // Implements PlotPointData::xAt(). virtual double xAt(unsigned int i) const; // Implements PlotPointData::yAt(). virtual double yAt(unsigned int i) const; // Implements PlotPointData::minsMaxes(). virtual bool minsMaxes(double& xMin, double& xMax, double& yMin, double& yMax); // Recalculates the histogram data into the given number of bins. virtual void recalculateBins(unsigned int numBins); // Returns the current number of histogram bins. virtual unsigned int numBins() const; // Returns the range at the given index. virtual prange_t rangeAt(unsigned int i) const; private: PlotSingleDataPtr m_data; // Data. std::vector<unsigned int> m_bins; // Bins with count. std::vector<prange_t> m_ranges; // Cached bin ranges. unsigned int m_max; // Highest bin count. }; // Default implementation of PlotMaskedPointData using default containers. template <class T> class PlotMaskedPointDataImpl : public virtual PlotMaskedPointData, public PlotPointDataImpl<T> { public: // X/Y constructors. // <group> PlotMaskedPointDataImpl(std::vector<T>& x, std::vector<T>& y, std::vector<bool>& mask, bool shouldDelete = false) : PlotPointDataImpl<T>(x, y, shouldDelete), m_maskVector(&mask), m_maskCVector(NULL), m_maskArray(NULL), m_maskArraySize(0), m_shouldDeleteMask(shouldDelete) { } PlotMaskedPointDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, casacore::Vector<bool>& mask, bool shouldDelete = false) : PlotPointDataImpl<T>(x, y, shouldDelete), m_maskVector(NULL), m_maskCVector(&mask), m_maskArray(NULL), m_maskArraySize(0), m_shouldDeleteMask(shouldDelete) { } PlotMaskedPointDataImpl(T*& x, T*& y, bool*& mask, unsigned int size, bool shouldDel = false) : PlotPointDataImpl<T>(x, y, size, shouldDel), m_maskVector(NULL), m_maskCVector(NULL), m_maskArray(mask), m_maskArraySize(size), m_shouldDeleteMask(shouldDel) { } // </group> // Y constructors. // <group> PlotMaskedPointDataImpl(std::vector<T>& y, std::vector<bool>& mask, bool shouldDelete = false) : PlotPointDataImpl<T>(y, shouldDelete), m_maskVector(&mask), m_maskCVector(NULL), m_maskArray(NULL), m_maskArraySize(0), m_shouldDeleteMask(shouldDelete) { } PlotMaskedPointDataImpl(casacore::Vector<T>& y, casacore::Vector<bool>& mask, bool shouldDelete = false) : PlotPointDataImpl<T>(y, shouldDelete), m_maskVector(NULL), m_maskCVector(&mask), m_maskArray(NULL), m_maskArraySize(0), m_shouldDeleteMask(shouldDelete) { } PlotMaskedPointDataImpl(T*& y, bool*& mask, unsigned int size, bool shouldDel = false) : PlotPointDataImpl<T>(y, size, shouldDel), m_maskVector(NULL), m_maskCVector(NULL), m_maskArray(mask), m_maskArraySize(size), m_shouldDeleteMask(shouldDel) { } // </group> // Destructor. ~PlotMaskedPointDataImpl() { if(m_shouldDeleteMask) { if(m_maskVector != NULL) delete m_maskVector; if(m_maskCVector != NULL) delete m_maskCVector; if(m_maskArray != NULL) delete m_maskArray; } } virtual bool reverseConnect(unsigned int /*index*/) const { return false; }; virtual bool plotConjugates() const { return false; }; // Overrides PlotPointDataImpl::willDeleteData(). bool willDeleteData() const { return PlotPointDataImpl<T>::willDeleteData() && m_shouldDeleteMask; } // Overrides PlotPointDataImpl::setDeleteData(). void setDeleteData(bool del = true) { PlotPointDataImpl<T>::setDeleteData(del); m_shouldDeleteMask = del; } // Implements PlotMaskedPointData::sizeMasked(). unsigned int sizeMasked() const { return sizeMaskedOrUnmasked(true); } // Implements PlotMaskedPointData::sizeUnmasked(). unsigned int sizeUnmasked() const { return sizeMaskedOrUnmasked(false); } // Implements PlotMaskedPointData::maskedAt(). bool maskedAt(unsigned int index) const { if(m_maskVector != NULL) return (*m_maskVector)[index]; if(m_maskCVector != NULL) return (*m_maskCVector)[index]; if(m_maskArray != NULL) return m_maskArray[index]; return false; } // Implements PlotMaskedPointData::maskedMinsMaxes(). bool maskedMinsMaxes(double& xMin, double& xMax, double& yMin, double& yMax) { return getMaskedOrUnmaskedMinsMaxes(xMin, xMax, yMin, yMax, true); } // Implements PlotMaskedPointData::unmaskedMinsMaxes(). bool unmaskedMinsMaxes(double& xMin, double& xMax, double& yMin, double& yMax) { return getMaskedOrUnmaskedMinsMaxes(xMin, xMax, yMin, yMax, false); } private: std::vector<bool>* m_maskVector; casacore::Vector<bool>* m_maskCVector; bool* m_maskArray; unsigned int m_maskArraySize; bool m_shouldDeleteMask; // Helper for size. unsigned int sizeMaskedOrUnmasked(bool masked) const { unsigned int n = size(); unsigned int count = 0; if(m_maskArray != NULL) { for(unsigned int i = 0; i < m_maskArraySize; i++) if(m_maskArray[i]) count++; } else if(m_maskVector != NULL) { for(unsigned int i = 0; i < m_maskVector->size(); i++) if((*m_maskVector)[i]) count++; } else if(m_maskCVector != NULL) { for(unsigned int i = 0; i < m_maskCVector->size(); i++) if((*m_maskCVector)[i]) count++; } else return n; if(masked) return casacore::min(count, n); else return casacore::min(n - count, n); } // Helper for mins/maxes. bool getMaskedOrUnmaskedMinsMaxes(double& xMin, double& xMax, double& yMin, double& yMax, bool masked) { if(!isValid()) return false; unsigned int n = size(); if(n == 0) return false; if(m_maskArray == NULL && m_maskVector == NULL && m_maskCVector == NULL) return minsMaxes(xMin, xMax, yMin, yMax); unsigned int i = 0; bool m; for(; i < n; i++) { m = maskedAt(i); if((masked && m) || (!masked && !m)) { xMin = xMax = xAt(i); yMin = yMax = yAt(i); break; } } if(i == n) return false; double temp; for(; i < n; i++) { m = maskedAt(i); if((masked && m) || (!masked && !m)) { temp = xAt(i); if(temp < xMin) xMin = temp; if(temp > xMax) xMax = temp; temp = yAt(i); if(temp < yMin) yMin = temp; if(temp > yMax) yMax = temp; } } return true; } }; typedef PlotMaskedPointDataImpl<int> PlotMaskedPointIntData; typedef PlotMaskedPointDataImpl<unsigned int> PlotMaskedPointUIntData; typedef PlotMaskedPointDataImpl<float> PlotMaskedPointFloatData; typedef PlotMaskedPointDataImpl<double> PlotMaskedPointDoubleData; // Default implementation of PlotErrorData using standard containers, plus // scalars for the four errors. template <class T> class PlotScalarErrorDataImpl : public virtual PlotErrorData, public PlotPointDataImpl<T> { public: // Scalar error for top, bottom, left, and right. // <group> PlotScalarErrorDataImpl(std::vector<T>& x, std::vector<T>& y, T xLeftError, T xRightError, T yBottomError, T yTopError, bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete), m_xLeftError(xLeftError), m_xRightError(xRightError), m_yBottomError(yBottomError), m_yTopError(yTopError) { } PlotScalarErrorDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, T xLeftError, T xRightError, T yBottomError, T yTopError, bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete), m_xLeftError(xLeftError), m_xRightError(xRightError), m_yBottomError(yBottomError), m_yTopError(yTopError) { } PlotScalarErrorDataImpl(T*& x, T*& y, unsigned int size, T xLeftError, T xRightError, T yBottomError, T yTopError, bool shouldDelete = false) : PlotPointDataImpl<T>(x, y, size, shouldDelete), m_xLeftError(xLeftError), m_xRightError(xRightError), m_yBottomError(yBottomError), m_yTopError(yTopError) { } // </group> // Single error for x and y. // <group> PlotScalarErrorDataImpl(std::vector<T>& x, std::vector<T>& y, T xError, T yError, bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete), m_xLeftError(xError), m_xRightError(xError), m_yBottomError(yError), m_yTopError(yError) { } PlotScalarErrorDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, T xError, T yError, bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete), m_xLeftError(xError), m_xRightError(xError), m_yBottomError(yError), m_yTopError(yError) { } PlotScalarErrorDataImpl(T*& x, T*& y,unsigned int size, T xError, T yError, bool shouldDelete = false) : PlotPointDataImpl<T>(x, y, size, shouldDelete), m_xLeftError(xError), m_xRightError(xError), m_yBottomError(yError), m_yTopError(yError) { } // </group> // Single error for all values. // <group> PlotScalarErrorDataImpl(std::vector<T>& x, std::vector<T>& y, T error, bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete), m_xLeftError(error), m_xRightError(error), m_yBottomError(error), m_yTopError(error) { } PlotScalarErrorDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, T error, bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete), m_xLeftError(error), m_xRightError(error), m_yBottomError(error), m_yTopError(error) { } PlotScalarErrorDataImpl(T*& x, T*& y, unsigned int size, T error, bool shouldDelete = false) : PlotPointDataImpl<T>(x, y, size, shouldDelete), m_xLeftError(error), m_xRightError(error), m_yBottomError(error), m_yTopError(error) { } // </group> // Destructor. ~PlotScalarErrorDataImpl() { } // Implements PlotErrorData getter methods. // <group> double xLeftErrorAt(unsigned int ) const { return m_xLeftError; } double xRightErrorAt(unsigned int ) const { return m_xRightError; } double yBottomErrorAt(unsigned int ) const { return m_yBottomError; } double yTopErrorAt(unsigned int ) const { return m_yTopError; } // </group> // Implements PlotErrorData::errorMaxes(). bool errorMaxes(double& xLeft, double& xRight, double& yBottom, double& yTop) { xLeft = m_xLeftError; xRight = m_xRightError; yBottom = m_yBottomError; yTop = m_yTopError; return true; } private: T m_xLeftError, m_xRightError, m_yBottomError, m_yTopError; }; typedef PlotScalarErrorDataImpl<int> PlotScalarErrorIntData; typedef PlotScalarErrorDataImpl<unsigned int> PlotScalarErrorUIntData; typedef PlotScalarErrorDataImpl<float> PlotScalarErrorFloatData; typedef PlotScalarErrorDataImpl<double> PlotScalarErrorDoubleData; // Default implementation of PlotErrorData using standard containers, plus // PlotPointDataImpls for the errors. template <class T> class PlotErrorDataImpl : public virtual PlotErrorData, public PlotPointDataImpl<T> { public: // Symmetric error constructors. // <group> PlotErrorDataImpl(T*& x, T*& y, T*& xError, T*& yError, unsigned int size, bool shouldDelete = true) : PlotPointDataImpl<T>(x, y, size, shouldDelete), m_xError(xError, xError, size, shouldDelete), m_yError(yError, yError, size, shouldDelete) { } PlotErrorDataImpl(std::vector<T>& x, std::vector<T>& y, std::vector<T>& xError, std::vector<T>& yError, bool shouldDelete = false) : PlotPointDataImpl<T>(x, y, shouldDelete), m_xError(xError, xError, shouldDelete), m_yError(yError, yError, shouldDelete) { } PlotErrorDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, casacore::Vector<T>& xError, casacore::Vector<T>& yError, bool shouldDelete = false) : PlotPointDataImpl<T>(x, y, shouldDelete), m_xError(xError, xError, shouldDelete), m_yError(yError, yError, shouldDelete) { } // </group> // Asymmetric error constructors. // <group> PlotErrorDataImpl(T*& x, T*& y, T*& xLeftError, T*& xRightError, T*& yBottomError, T*& yTopError, unsigned int size, bool shouldDelete = true) : PlotPointDataImpl<T>(x, y, size, shouldDelete), m_xError(xLeftError, xRightError, size, shouldDelete), m_yError(yBottomError, yTopError, size, shouldDelete) { } PlotErrorDataImpl(std::vector<T>& x, std::vector<T>& y, std::vector<T>& xLeftError, std::vector<T>& xRightError, std::vector<T>& yBottomError, std::vector<T>& yTopError, bool shouldDelete = false) : PlotPointDataImpl<T>(x, y, shouldDelete), m_xError(xLeftError, xRightError, shouldDelete), m_yError(yBottomError, yTopError, shouldDelete) { } PlotErrorDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, casacore::Vector<T>& xLeftError, casacore::Vector<T>& xRightError, casacore::Vector<T>& yBottomError, casacore::Vector<T>& yTopError, bool shouldDelete = false) : PlotPointDataImpl<T>(x, y, shouldDelete), m_xError(xLeftError, xRightError, shouldDelete), m_yError(yBottomError, yTopError, shouldDelete) { } // </group> ~PlotErrorDataImpl() { } // Overrides PlotPointDataImpl::willDeleteData(). bool willDeleteData() const { return PlotPointDataImpl<T>::willDeleteData() && m_xError.willDeleteData() && m_yError.willDeleteData(); } // Overrides PlotPointDataImpl::setDeleteData(). void setDeleteData(bool del = true) { m_xError.setDeleteData(del); m_yError.setDeleteData(del); PlotPointDataImpl<T>::setDeleteData(del); } // Implements PlotErrorData getter methods. // <group> double xLeftErrorAt(unsigned int i) const { return m_xError.xAt(i); } double xRightErrorAt(unsigned int i) const { return m_xError.yAt(i); } double yBottomErrorAt(unsigned int i) const { return m_yError.xAt(i); } double yTopErrorAt(unsigned int i) const { return m_yError.yAt(i); } // </group> // Implements PlotErrorData::errorMaxes(). bool errorMaxes(double& xLeft, double& xRight, double& yBottom, double& yTop) { double temp; return m_xError.minsMaxes(temp, xLeft, temp, xRight) && m_yError.minsMaxes(temp, yBottom, temp, yTop); } private: PlotPointDataImpl<T> m_xError, m_yError; }; typedef PlotErrorDataImpl<int> PlotErrorIntData; typedef PlotErrorDataImpl<unsigned int> PlotErrorUIntData; typedef PlotErrorDataImpl<float> PlotErrorFloatData; typedef PlotErrorDataImpl<double> PlotErrorDoubleData; // Implementation of raster data using casa::Matrix. template <class T> class PlotRasterMatrixData : public virtual PlotRasterData { public: // Whether the indexing is (row,col) or (x,y). Default is (row,col). enum Indexing { ROW_COL, X_Y }; PlotRasterMatrixData(casacore::Matrix<T>& data, bool shouldDelete = false) : m_data(&data), m_origin(LLEFT), m_indexing(ROW_COL), m_shouldDelete(shouldDelete) { casacore::IPosition shape = data.shape(); unsigned int n0 = shape[0] - 1, n1 = shape[1] - 1; m_0From = 0; m_0To = n0 + 1; m_1From = 0; m_1To = n1 + 1; m_0Pieces = (n0 + 1) / (m_0To - m_0From); m_1Pieces = (n1 + 1) / (m_1To - m_1From); double val = static_cast<double>(data(0, 0)); m_valFrom = m_valTo = val; for(casacore::uInt i = 0; i < data.nrow(); i++) { for(casacore::uInt j = 0; j < data.ncolumn(); j++) { val = static_cast<double>(data(i, j)); if(val < m_valFrom) m_valFrom = val; if(val > m_valTo) m_valTo = val; } } } ~PlotRasterMatrixData() { if(m_shouldDelete) delete m_data; } // Implements PlotData::isValid(). bool isValid() const { return true; } // Implements PlotData::willDeleteData(). bool willDeleteData() const { return m_shouldDelete; } // Implements PlotData::setDeleteData(). void setDeleteData(bool del = true) { m_shouldDelete = del; } // Implements PlotRasterData::origin(). Origin origin() const { return m_origin; } // Implements PlotRasterData::setOrigin(). void setOrigin(Origin o) { if(m_origin != o) { m_origin = o; } } // Implements PlotRasterData::xRange(). prange_t xRange() const { if(m_indexing == X_Y) return prange_t(m_0From, m_0To); else return prange_t(m_1From, m_1To); } // Implements PlotRasterData::yRange(). prange_t yRange() const { if(m_indexing == X_Y) return prange_t(m_1From, m_1To); else return prange_t(m_0From, m_0To); } // Implements PlotRasterData::setXRange(). void setXRange(double from, double to) { if(from == to) return; if(from > to) { double temp = from; from = to; to = temp; } if(m_indexing == X_Y) { m_0From = from; m_0To = to; m_0Pieces = (m_data->shape()[0]) / (m_0To - m_0From); } else { m_1From = from; m_1To = to; m_1Pieces = (m_data->shape()[1]) / (m_1To - m_1From); } } // Implements PlotRasterData::setYRange(). void setYRange(double from, double to) { if(from == to) return; if(from > to) { double temp = from; from = to; to = temp; } if(m_indexing == X_Y) { m_1From = from; m_1To = to; m_1Pieces = (m_data->shape()[1]) / (m_1To - m_1From); } else { m_0From = from; m_0To = to; m_0Pieces = (m_data->shape()[0]) / (m_0To - m_0From); } } // Implements PlotRasterData::valueRange(). prange_t valueRange() const { return prange_t(m_valFrom, m_valTo); } // Implements PlotRasterData::valueAt(). double valueAt(double x, double y) const { if(m_indexing == X_Y) { if(x < m_0From || x > m_0To || y < m_1From || y > m_1To) return 0; int xi = (int)((x - m_0From) * m_0Pieces); int yi = (int)((y - m_1From) * m_1Pieces); if(xi >= m_data->shape()[0]) xi = m_data->shape()[0] - 1; if(yi >= m_data->shape()[1]) yi = m_data->shape()[1] - 1; return static_cast<double>((*m_data)(xi, yi)); } else { if(x < m_1From || x > m_1To || y < m_0From || y > m_0To) return 0; int xi = (int)((x - m_1From) * m_1Pieces); int yi = (int)((y - m_0From) * m_0Pieces); if(xi >= m_data->shape()[1]) xi = m_data->shape()[1] - 1; if(yi >= m_data->shape()[0]) yi = m_data->shape()[0] - 1; return static_cast<double>((*m_data)(yi, xi)); } } // Implements PlotRasterData::colorBarValues(). std::vector<double>* colorBarValues(unsigned int max = 1000) const { std::vector<double>* v = new std::vector<double>(); double val; bool found; for(unsigned int i = 0; i < m_data->nrow() && v->size() <= max; i++) { for(unsigned int j = 0; j < m_data->ncolumn() && v->size() <= max; j++) { val = static_cast<double>((*m_data)(i, j)); found = false; for(unsigned int k = 0; k < v->size() && !found; k++) if(v->at(k) == val) found = true; if(!found) v->push_back(val); } } return v; } // Gets/sets the indexing used for the matrix. // <group> Indexing indexing() const { return m_indexing; } void setIndexing(Indexing i) { m_indexing = i; } // </group> // Gets/sets the matrix. // <group> casacore::Matrix<T>* matrix() { return m_data; } void setMatrix(casacore::Matrix<T>* m, bool shouldDelete = true) { if(m_shouldDelete) delete m_data; m_data = m; m_shouldDelete = shouldDelete; } // </group> private: casacore::Matrix<T>* m_data; double m_0From, m_0To; double m_1From, m_1To; double m_0Pieces, m_1Pieces; double m_valFrom, m_valTo; Origin m_origin; Indexing m_indexing; bool m_shouldDelete; }; } #endif /*PLOTDATA_H_*/