Line data Source code
1 : //# PlotData.h: Classes to represent data for plots.
2 : //# Copyright (C) 2008
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //#
5 : //# This library is free software; you can redistribute it and/or modify it
6 : //# under the terms of the GNU Library General Public License as published by
7 : //# the Free Software Foundation; either version 2 of the License, or (at your
8 : //# option) any later version.
9 : //#
10 : //# This library is distributed in the hope that it will be useful, but WITHOUT
11 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 : //# License for more details.
14 : //#
15 : //# You should have received a copy of the GNU Library General Public License
16 : //# along with this library; if not, write to the Free Software Foundation,
17 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 : //#
19 : //# Correspondence concerning AIPS++ should be addressed as follows:
20 : //# Internet email: casa-feedback@nrao.edu.
21 : //# Postal address: AIPS++ Project Office
22 : //# National Radio Astronomy Observatory
23 : //# 520 Edgemont Road
24 : //# Charlottesville, VA 22903-2475 USA
25 : //#
26 : //# $Id: $
27 : #ifndef PLOTDATA_H_
28 : #define PLOTDATA_H_
29 :
30 : #include <graphics/GenericPlotter/PlotOptions.h>
31 :
32 : #include <casacore/casa/Arrays/Matrix.h>
33 : #include <casacore/casa/Arrays/Vector.h>
34 :
35 : #include <casacore/casa/BasicSL/String.h>
36 : #include <casacore/casa/Utilities/CountedPtr.h>
37 : #include <casacore/casa/BasicMath/Math.h>
38 :
39 : namespace casa {
40 :
41 : // Typedef for a point, which is two doubles (x and y).
42 : typedef std::pair<double, double> ppoint_t;
43 :
44 : //////////////////////
45 : // ABSTRACT CLASSES //
46 : //////////////////////
47 :
48 : // Deliberately vague to be general enough to allow for many different types
49 : // of data, but is it too vague to be useful? Since the interface is meant
50 : // to be a simple plotter, it may be better to restrict PlotData to be more
51 : // like PlotPointData, which would eliminate possibilities for data like
52 : // functions but would also eliminate a lot of vaguery.
53 : class PlotData {
54 : public:
55 0 : PlotData() { }
56 :
57 0 : virtual ~PlotData() { }
58 :
59 :
60 : // ABSTRACT METHODS //
61 :
62 : // Returns whether the contained data is valid or not.
63 : virtual bool isValid() const = 0;
64 :
65 : // Returns whether this object will delete its underlying data structures
66 : // upon deconstruction or not.
67 : virtual bool willDeleteData() const = 0;
68 :
69 : // Sets whether this object will delete its underlying data structures upon
70 : // deconstruction or not.
71 : virtual void setDeleteData(bool del = true) = 0;
72 : };
73 : typedef casacore::CountedPtr<PlotData> PlotDataPtr;
74 :
75 :
76 : // A single source of data that basically provides indexing of its values.
77 : class PlotSingleData : public virtual PlotData {
78 : public:
79 0 : PlotSingleData() { }
80 :
81 0 : virtual ~PlotSingleData() { }
82 :
83 :
84 : // ABSTRACT METHODS //
85 :
86 : // Returns the number of points.
87 : virtual unsigned int size() const = 0;
88 :
89 : // Returns the value at given index.
90 : virtual double at(unsigned int i) const = 0;
91 :
92 : // Gets the minimum and maximum values. Returns false for error.
93 : virtual bool minMax(double& min, double& max) = 0;
94 : };
95 0 : INHERITANCE_POINTER2(PlotSingleData, PlotSingleDataPtr, PlotData, PlotDataPtr)
96 :
97 :
98 : // A source of data used to supply x and y values. Basically consists of
99 : // indexing its values.
100 : class PlotPointData : public virtual PlotData {
101 : public:
102 0 : PlotPointData() { }
103 :
104 0 : virtual ~PlotPointData() { }
105 :
106 :
107 : // ABSTRACT METHODS //
108 :
109 : // Returns the number of points.
110 : virtual unsigned int size() const = 0;
111 :
112 : // Returns the x value at the given index.
113 : virtual double xAt(unsigned int i) const = 0;
114 :
115 : // Returns the y value at the given index.
116 : virtual double yAt(unsigned int i) const = 0;
117 :
118 : // Gets the minimum and maximum values. Returns false for error.
119 : virtual bool minsMaxes(double& xMin, double& xMax, double& yMin,
120 : double& yMax) = 0;
121 :
122 :
123 : // IMPLEMENTED METHODS //
124 :
125 : // Gets the x and y values at the given index. Default implementation
126 : // just calls xAt and yAt, but in subclasses where performance could be
127 : // gained, this method should be overridden. Implementations for plots
128 : // that use PlotPointData should use this method by default in case there
129 : // are performance gains.
130 : virtual void xAndYAt(unsigned int index, double& x, double& y) const;
131 : };
132 0 : INHERITANCE_POINTER2(PlotPointData, PlotPointDataPtr, PlotData, PlotDataPtr)
133 :
134 :
135 : // casacore::Data that adds masking functionality on top of normal point data.
136 : class PlotMaskedPointData : public virtual PlotPointData {
137 : public:
138 0 : PlotMaskedPointData() { }
139 :
140 0 : virtual ~PlotMaskedPointData() { }
141 :
142 :
143 : // ABSTRACT METHODS //
144 :
145 : // Returns the number of masked points.
146 : virtual unsigned int sizeMasked() const = 0;
147 :
148 : // Returns the number of unmasked points.
149 : virtual unsigned int sizeUnmasked() const = 0;
150 :
151 : // Returns whether the data is masked at the given point or not.
152 : virtual bool maskedAt(unsigned int index) const = 0;
153 :
154 : // Gets the mins/maxes for just the masked points.
155 : virtual bool maskedMinsMaxes(double& xMin, double& xMax, double& yMin,
156 : double& yMax) = 0;
157 :
158 : // Gets the mins/maxes for just the unmasked points.
159 : virtual bool unmaskedMinsMaxes(double& xMin, double& xMax, double& yMin,
160 : double& yMax) = 0;
161 :
162 : // Returns whether data is plotted in reverse order (right to left),
163 : // needed when connecting points
164 : virtual bool reverseConnect(unsigned int index) const = 0;
165 :
166 : // Returns whether to plot conjugate data (e.g. UV plots)
167 : virtual bool plotConjugates() const = 0;
168 :
169 : // IMPLEMENTED METHODS //
170 :
171 : // Gets the x and y values and the mask at the given index. See
172 : // PlotPointData::xAndYAt().
173 : virtual void xyAndMaskAt(unsigned int index, double& x, double& y,
174 : bool& mask) const;
175 : };
176 0 : INHERITANCE_POINTER(PlotMaskedPointData, PlotMaskedPointDataPtr, PlotPointData,
177 : PlotPointDataPtr, PlotData, PlotDataPtr)
178 :
179 :
180 : // casacore::Data that adds error functionality on top of normal plot data.
181 : class PlotErrorData : public virtual PlotPointData {
182 : public:
183 0 : PlotErrorData() { }
184 :
185 0 : virtual ~PlotErrorData() { }
186 :
187 :
188 : // ABSTRACT METHODS //
189 :
190 : // Returns the "left" error for x at the given index.
191 : virtual double xLeftErrorAt(unsigned int i) const = 0;
192 :
193 : // Returns the "right" error for x at the given index.
194 : virtual double xRightErrorAt(unsigned int i) const = 0;
195 :
196 : // Returns the "bottom" error for y at the given index.
197 : virtual double yBottomErrorAt(unsigned int i) const = 0;
198 :
199 : // Returns the "top" error for y at the given index.
200 : virtual double yTopErrorAt(unsigned int i) const = 0;
201 :
202 : // Gets the maximum errors for the four sides.
203 : virtual bool errorMaxes(double& xLeft, double& xRight, double& yBottom,
204 : double& yTop) = 0;
205 :
206 :
207 : // IMPLEMENTED METHODS //
208 :
209 : // Gets the x and y values and error data at the given index. See
210 : // PlotPointData::xAndYAt().
211 : virtual void xyAndErrorsAt(unsigned int index, double& x, double& y,
212 : double& xLeftError, double& xRightError, double& yBottomError,
213 : double& yTopError) const;
214 : };
215 0 : INHERITANCE_POINTER(PlotErrorData, PlotErrorDataPtr, PlotPointData,
216 : PlotDataPtr, PlotData, PlotDataPtr)
217 :
218 :
219 : // casacore::Data that differentiates different points into different "bins" on top of
220 : // normal point data functionality.
221 : class PlotBinnedData : public virtual PlotPointData {
222 : public:
223 : // Constructor.
224 : PlotBinnedData() { }
225 :
226 : // Destructor.
227 : virtual ~PlotBinnedData() { }
228 :
229 :
230 : // ABSTRACT METHODS //
231 :
232 : // Returns the total number of bins that the data is in.
233 : virtual unsigned int numBins() const = 0;
234 :
235 : // Returns the bin index number for the given index. MUST be between 0 and
236 : // numBins().
237 : virtual unsigned int binAt(unsigned int i) const = 0;
238 : virtual unsigned int connectBinAt(unsigned int i) const {
239 : return binAt(i); };
240 :
241 : // Return map of colorized values to color, and whether all plots use the same color list
242 : virtual std::map<std::string, std::string> getColorizeMap(bool& shared_colormap) const = 0;
243 :
244 : // IMPLEMENTED METHODS //
245 :
246 : // Returns true if the data is binned, false otherwise.
247 : virtual bool isBinned() const { return numBins() > 1; }
248 : };
249 : INHERITANCE_POINTER(PlotBinnedData, PlotBinnedDataPtr, PlotPointData,
250 : PlotDataPtr, PlotData, PlotDataPtr)
251 :
252 :
253 : // casacore::Data for raster plots, which can be thought of as three-dimensional. Used
254 : // for images, with the values being in one of the givne formats.
255 : class PlotRasterData : public virtual PlotData {
256 : public:
257 : // casacore::Format that the data is in
258 : enum Format {
259 : RGB32, // data is an RBG integer, like 0x60A0C0
260 : ARGB32, // data is an ARGB integer, like 0xFF60A0C0
261 : SPECTROGRAM // data is meant for a spectrogram, not specific colors
262 : };
263 :
264 : // Origin point of the data - in other words, where (0,0) is located
265 : // visually on the canvas. Default is LLEFT.
266 : enum Origin {
267 : LLEFT, LRIGHT, ULEFT, URIGHT
268 : };
269 :
270 :
271 0 : PlotRasterData() { }
272 :
273 0 : virtual ~PlotRasterData() { }
274 :
275 :
276 : // ABSTRACT METHODS //
277 :
278 : // Returns the data origin.
279 : virtual Origin origin() const = 0;
280 :
281 : // Sets the data origin.
282 : virtual void setOrigin(Origin o) = 0;
283 :
284 : // Returns the range of x.
285 : virtual prange_t xRange() const = 0;
286 :
287 : // Returns the range of y.
288 : virtual prange_t yRange() const = 0;
289 :
290 : // Sets the range of x.
291 : virtual void setXRange(double from, double to) = 0;
292 :
293 : // Sets the range of y.
294 : virtual void setYRange(double from, double to) = 0;
295 :
296 : // Returns the range of the data values.
297 : virtual prange_t valueRange() const = 0;
298 :
299 : // Returns the data value at the given (x,y) coordinate.
300 : virtual double valueAt(double x, double y) const = 0;
301 :
302 : // Gets color bar values.
303 : virtual std::vector<double>* colorBarValues(unsigned int max = 1000) const = 0;
304 : };
305 0 : INHERITANCE_POINTER2(PlotRasterData, PlotRasterDataPtr, PlotData, PlotDataPtr)
306 :
307 :
308 : /////////////////////////////
309 : // DEFAULT IMPLEMENTATIONS //
310 : /////////////////////////////
311 :
312 : // Default implementation of PlotSingleData that supports raw arrays, vectors,
313 : // and CASA Vectors. The class is templated, but since data sources are
314 : // expected in doubles it should be a numeric type that can be casted to a
315 : // double.
316 : template <class T>
317 : class PlotSingleDataImpl : public virtual PlotSingleData {
318 : public:
319 : // Invalid data constructor.
320 0 : PlotSingleDataImpl(): m_vector(NULL), m_cvector(NULL), m_array(NULL),
321 0 : m_arraySize(0), m_shouldDelete(false) { }
322 :
323 : // casacore::Data using different standard containers.
324 : // <group>
325 0 : PlotSingleDataImpl(std::vector<T>& value, bool shouldDelete = false):
326 0 : m_vector(&value), m_cvector(NULL), m_array(NULL), m_arraySize(0),
327 0 : m_shouldDelete(shouldDelete) {
328 0 : recalculateMinMax(); }
329 0 : PlotSingleDataImpl(casacore::Vector<T>& value, bool shouldDelete = false):
330 0 : m_vector(NULL), m_cvector(&value), m_array(NULL), m_arraySize(0),
331 0 : m_shouldDelete(shouldDelete) {
332 0 : recalculateMinMax(); }
333 0 : PlotSingleDataImpl(T*& value, unsigned int size, bool shouldDelete= false):
334 0 : m_vector(NULL), m_cvector(NULL), m_array(value), m_arraySize(size),
335 0 : m_shouldDelete(shouldDelete) {
336 0 : recalculateMinMax(); }
337 : // </group>
338 :
339 : // Destructor.
340 0 : ~PlotSingleDataImpl() {
341 0 : if(m_shouldDelete) {
342 0 : if(m_vector != NULL) delete m_vector;
343 0 : if(m_cvector != NULL) delete m_cvector;
344 0 : if(m_array != NULL) delete m_array;
345 : }
346 0 : }
347 :
348 :
349 : // Implements PlotData::isValid().
350 0 : bool isValid() const {
351 0 : return m_vector != NULL || m_cvector != NULL || m_array != NULL; }
352 :
353 : // Implements PlotData::willDeleteData().
354 0 : bool willDeleteData() const { return m_shouldDelete; }
355 :
356 : // Implements PlotData::setDeleteData().
357 0 : void setDeleteData(bool del = true) { m_shouldDelete = del; }
358 :
359 : // Implements PlotSingleData::size().
360 0 : unsigned int size() const {
361 0 : if(m_vector != NULL) return m_vector->size();
362 0 : if(m_cvector != NULL) return m_cvector->size();
363 0 : if(m_array != NULL) return m_arraySize;
364 0 : return 0;
365 : }
366 :
367 : // Implements PlotSingleData::at().
368 0 : double at(unsigned int i) const {
369 0 : if(m_vector != NULL) return (double)(*m_vector)[i];
370 0 : if(m_cvector != NULL) return (double)(*m_cvector)[i];
371 0 : if(m_array != NULL) return (double)m_array[i];
372 0 : return 0;
373 : }
374 :
375 : // Implements PlotSingleData::minMax().
376 0 : bool minMax(double& min, double& max) {
377 0 : if(!isValid() || size() == 0) return false;
378 0 : min = m_min; max = m_max;
379 0 : return true;
380 : }
381 :
382 : // Recalculates the cached min and max. Should be used if the underlying
383 : // data structure changes.
384 0 : void recalculateMinMax() {
385 0 : if(!isValid()) return;
386 0 : unsigned int n = size();
387 0 : if(n == 0) return;
388 0 : double temp = (double)at(0);
389 0 : m_min = m_max = temp;
390 0 : if(m_vector != NULL) {
391 0 : for(unsigned int i = 1; i < n; i++) {
392 0 : temp = (double)(*m_vector)[i];
393 0 : if(temp < m_min) m_min = temp;
394 0 : if(temp > m_max) m_max = temp;
395 : }
396 0 : } else if(m_cvector != NULL) {
397 0 : for(unsigned int i = 1; i < n; i++) {
398 0 : temp = (double)(*m_cvector)[i];
399 0 : if(temp < m_min) m_min = temp;
400 0 : if(temp > m_max) m_max = temp;
401 : }
402 0 : } else if(m_array != NULL) {
403 0 : for(unsigned int i = 1; i < n; i++) {
404 0 : temp = (double)m_array[i];
405 0 : if(temp < m_min) m_min = temp;
406 0 : if(temp > m_max) m_max = temp;
407 : }
408 : }
409 : }
410 :
411 : private:
412 : std::vector<T>* m_vector;
413 : casacore::Vector<T>* m_cvector;
414 : T* m_array;
415 : unsigned int m_arraySize;
416 : bool m_shouldDelete;
417 : double m_min, m_max;
418 : };
419 :
420 : typedef PlotSingleDataImpl<int> PlotSingleIntData;
421 : typedef PlotSingleDataImpl<unsigned int> PlotSingleUIntData;
422 : typedef PlotSingleDataImpl<float> PlotSingleFloatData;
423 : typedef PlotSingleDataImpl<double> PlotSingleDoubleData;
424 :
425 :
426 : // Default implementation of PlotPointData that supports raw arrays, vectors,
427 : // and CASA Vectors. The class is templated, but since data sources are
428 : // expected in doubles it should be a numeric type that can be casted to a
429 : // double. It can either be both x and y data, or just y data (where x is the
430 : // index).
431 : template <class T>
432 : class PlotPointDataImpl : public virtual PlotPointData {
433 : public:
434 : // X/Y constructors.
435 : // <group>
436 0 : PlotPointDataImpl(std::vector<T>& x, std::vector<T>& y, bool shouldDelete = false) :
437 0 : m_xData(x, shouldDelete), m_yData(y, shouldDelete) { }
438 0 : PlotPointDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, bool shouldDelete = false) :
439 0 : m_xData(x, shouldDelete), m_yData(y, shouldDelete) { }
440 0 : PlotPointDataImpl(T*& x, T*& y, unsigned int size, bool shouldDel = false):
441 0 : m_xData(x, size, shouldDel), m_yData(y, size, shouldDel) { }
442 : // </group>
443 :
444 : // Y constructors.
445 : // <group>
446 0 : PlotPointDataImpl(std::vector<T>& y, bool shouldDelete = false) :
447 0 : m_yData(y, shouldDelete) { }
448 0 : PlotPointDataImpl(casacore::Vector<T>& y, bool shouldDelete = false) :
449 0 : m_yData(y, shouldDelete) { }
450 0 : PlotPointDataImpl(T*& y, unsigned int size, bool shouldDel = false):
451 0 : m_yData(y, size, shouldDel) { }
452 : // </group>
453 :
454 0 : virtual ~PlotPointDataImpl() { }
455 :
456 :
457 : // Implements PlotData::isValid().
458 0 : bool isValid() const { return m_yData.isValid(); }
459 :
460 : // Implements PlotData::willDeleteData().
461 0 : virtual bool willDeleteData() const {
462 0 : return (m_yData.isValid() && m_yData.willDeleteData()) &&
463 0 : (!m_xData.isValid() || m_xData.willDeleteData());
464 : }
465 :
466 : // Implements PlotData::setDeleteData().
467 0 : virtual void setDeleteData(bool del = true) {
468 0 : if(m_xData.isValid()) m_xData.setDeleteData(del);
469 0 : if(m_yData.isValid()) m_yData.setDeleteData(del);
470 0 : }
471 :
472 : // Implements PlotPointData::size().
473 0 : unsigned int size() const {
474 0 : if(!m_xData.isValid()) return m_yData.size();
475 0 : else return casacore::min(m_xData.size(), m_yData.size());
476 : }
477 :
478 : // Implements PlotPointData::xAt(). If no x data is given, the index is
479 : // returned.
480 0 : double xAt(unsigned int i) const {
481 0 : if(m_xData.isValid()) return m_xData.at(i);
482 0 : else return i;
483 : }
484 :
485 : // Implements PlotPointData::yAt().
486 0 : double yAt(unsigned int i) const { return m_yData.at(i); }
487 :
488 : // Implements PlotPointData::minsMaxes().
489 0 : bool minsMaxes(double& xMin, double& xMax, double& yMin, double& yMax) {
490 0 : if(!m_xData.isValid()) {
491 0 : xMin = 0;
492 0 : xMax = m_yData.size();
493 0 : return m_yData.minMax(yMin, yMax);
494 : } else {
495 0 : return m_xData.minMax(xMin, xMax) && m_yData.minMax(yMin, yMax);
496 : }
497 : }
498 :
499 : private:
500 : PlotSingleDataImpl<T> m_xData;
501 : PlotSingleDataImpl<T> m_yData;
502 : };
503 :
504 : typedef PlotPointDataImpl<int> PlotPointIntData;
505 : typedef PlotPointDataImpl<unsigned int> PlotPointUIntData;
506 : typedef PlotPointDataImpl<float> PlotPointFloatData;
507 : typedef PlotPointDataImpl<double> PlotPointDoubleData;
508 :
509 :
510 : // Specialized subclass of PlotPointData that creates histogram data from
511 : // single point data. A histogram divides up the data into a number of "bins"
512 : // and then counts the number of data that falls into each bin. This class can
513 : // act as both an interface for specializations or a concrete subclass of
514 : // PlotPointData in itself.
515 : class PlotHistogramData : public virtual PlotPointData {
516 : public:
517 : // Constructor which takes data and number of bins.
518 : PlotHistogramData(PlotSingleDataPtr data, unsigned int numBins);
519 :
520 : // Destructor.
521 : virtual ~PlotHistogramData();
522 :
523 :
524 : // Implements PlotData::isValid().
525 : virtual bool isValid() const;
526 :
527 : // Implements PlotData::willDeleteData().
528 : virtual bool willDeleteData() const;
529 :
530 : // Implements PlotData::setDeleteData().
531 : virtual void setDeleteData(bool del = true);
532 :
533 :
534 : // Implements PlotPointData::size().
535 0 : virtual unsigned int size() const { return numBins(); }
536 :
537 : // Implements PlotPointData::xAt().
538 : virtual double xAt(unsigned int i) const;
539 :
540 : // Implements PlotPointData::yAt().
541 : virtual double yAt(unsigned int i) const;
542 :
543 : // Implements PlotPointData::minsMaxes().
544 : virtual bool minsMaxes(double& xMin, double& xMax, double& yMin,
545 : double& yMax);
546 :
547 :
548 : // Recalculates the histogram data into the given number of bins.
549 : virtual void recalculateBins(unsigned int numBins);
550 :
551 : // Returns the current number of histogram bins.
552 : virtual unsigned int numBins() const;
553 :
554 : // Returns the range at the given index.
555 : virtual prange_t rangeAt(unsigned int i) const;
556 :
557 : private:
558 : PlotSingleDataPtr m_data; // Data.
559 : std::vector<unsigned int> m_bins; // Bins with count.
560 : std::vector<prange_t> m_ranges; // Cached bin ranges.
561 : unsigned int m_max; // Highest bin count.
562 : };
563 :
564 :
565 : // Default implementation of PlotMaskedPointData using default containers.
566 : template <class T>
567 : class PlotMaskedPointDataImpl : public virtual PlotMaskedPointData,
568 : public PlotPointDataImpl<T> {
569 : public:
570 : // X/Y constructors.
571 : // <group>
572 0 : PlotMaskedPointDataImpl(std::vector<T>& x, std::vector<T>& y, std::vector<bool>& mask,
573 : bool shouldDelete = false) :
574 0 : PlotPointDataImpl<T>(x, y, shouldDelete), m_maskVector(&mask),
575 0 : m_maskCVector(NULL), m_maskArray(NULL), m_maskArraySize(0),
576 0 : m_shouldDeleteMask(shouldDelete) { }
577 0 : PlotMaskedPointDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, casacore::Vector<bool>& mask,
578 : bool shouldDelete = false) :
579 0 : PlotPointDataImpl<T>(x, y, shouldDelete), m_maskVector(NULL),
580 0 : m_maskCVector(&mask), m_maskArray(NULL), m_maskArraySize(0),
581 0 : m_shouldDeleteMask(shouldDelete) { }
582 0 : PlotMaskedPointDataImpl(T*& x, T*& y, bool*& mask, unsigned int size,
583 : bool shouldDel = false) :
584 0 : PlotPointDataImpl<T>(x, y, size, shouldDel), m_maskVector(NULL),
585 0 : m_maskCVector(NULL), m_maskArray(mask), m_maskArraySize(size),
586 0 : m_shouldDeleteMask(shouldDel) { }
587 : // </group>
588 :
589 : // Y constructors.
590 : // <group>
591 : PlotMaskedPointDataImpl(std::vector<T>& y, std::vector<bool>& mask,
592 : bool shouldDelete = false) :
593 : PlotPointDataImpl<T>(y, shouldDelete), m_maskVector(&mask),
594 : m_maskCVector(NULL), m_maskArray(NULL), m_maskArraySize(0),
595 : m_shouldDeleteMask(shouldDelete) { }
596 : PlotMaskedPointDataImpl(casacore::Vector<T>& y, casacore::Vector<bool>& mask,
597 : bool shouldDelete = false) :
598 : PlotPointDataImpl<T>(y, shouldDelete), m_maskVector(NULL),
599 : m_maskCVector(&mask), m_maskArray(NULL), m_maskArraySize(0),
600 : m_shouldDeleteMask(shouldDelete) { }
601 : PlotMaskedPointDataImpl(T*& y, bool*& mask, unsigned int size,
602 : bool shouldDel = false) :
603 : PlotPointDataImpl<T>(y, size, shouldDel), m_maskVector(NULL),
604 : m_maskCVector(NULL), m_maskArray(mask), m_maskArraySize(size),
605 : m_shouldDeleteMask(shouldDel) { }
606 : // </group>
607 :
608 : // Destructor.
609 0 : ~PlotMaskedPointDataImpl() {
610 0 : if(m_shouldDeleteMask) {
611 0 : if(m_maskVector != NULL) delete m_maskVector;
612 0 : if(m_maskCVector != NULL) delete m_maskCVector;
613 0 : if(m_maskArray != NULL) delete m_maskArray;
614 : }
615 0 : }
616 :
617 0 : virtual bool reverseConnect(unsigned int /*index*/) const { return false; };
618 0 : virtual bool plotConjugates() const { return false; };
619 :
620 : // Overrides PlotPointDataImpl::willDeleteData().
621 0 : bool willDeleteData() const {
622 0 : return PlotPointDataImpl<T>::willDeleteData() && m_shouldDeleteMask; }
623 :
624 : // Overrides PlotPointDataImpl::setDeleteData().
625 0 : void setDeleteData(bool del = true) {
626 0 : PlotPointDataImpl<T>::setDeleteData(del);
627 0 : m_shouldDeleteMask = del;
628 0 : }
629 :
630 : // Implements PlotMaskedPointData::sizeMasked().
631 0 : unsigned int sizeMasked() const { return sizeMaskedOrUnmasked(true); }
632 :
633 : // Implements PlotMaskedPointData::sizeUnmasked().
634 0 : unsigned int sizeUnmasked() const { return sizeMaskedOrUnmasked(false); }
635 :
636 : // Implements PlotMaskedPointData::maskedAt().
637 0 : bool maskedAt(unsigned int index) const {
638 0 : if(m_maskVector != NULL) return (*m_maskVector)[index];
639 0 : if(m_maskCVector != NULL) return (*m_maskCVector)[index];
640 0 : if(m_maskArray != NULL) return m_maskArray[index];
641 0 : return false;
642 : }
643 :
644 : // Implements PlotMaskedPointData::maskedMinsMaxes().
645 0 : bool maskedMinsMaxes(double& xMin, double& xMax, double& yMin,
646 : double& yMax) {
647 0 : return getMaskedOrUnmaskedMinsMaxes(xMin, xMax, yMin, yMax, true); }
648 :
649 : // Implements PlotMaskedPointData::unmaskedMinsMaxes().
650 0 : bool unmaskedMinsMaxes(double& xMin, double& xMax, double& yMin,
651 : double& yMax) {
652 0 : return getMaskedOrUnmaskedMinsMaxes(xMin, xMax, yMin, yMax, false); }
653 :
654 : private:
655 : std::vector<bool>* m_maskVector;
656 : casacore::Vector<bool>* m_maskCVector;
657 : bool* m_maskArray;
658 : unsigned int m_maskArraySize;
659 : bool m_shouldDeleteMask;
660 :
661 : // Helper for size.
662 0 : unsigned int sizeMaskedOrUnmasked(bool masked) const {
663 0 : unsigned int n = size();
664 0 : unsigned int count = 0;
665 0 : if(m_maskArray != NULL) {
666 0 : for(unsigned int i = 0; i < m_maskArraySize; i++)
667 0 : if(m_maskArray[i]) count++;
668 0 : } else if(m_maskVector != NULL) {
669 0 : for(unsigned int i = 0; i < m_maskVector->size(); i++)
670 0 : if((*m_maskVector)[i]) count++;
671 0 : } else if(m_maskCVector != NULL) {
672 0 : for(unsigned int i = 0; i < m_maskCVector->size(); i++)
673 0 : if((*m_maskCVector)[i]) count++;
674 0 : } else return n;
675 0 : if(masked) return casacore::min(count, n);
676 0 : else return casacore::min(n - count, n);
677 : }
678 :
679 : // Helper for mins/maxes.
680 0 : bool getMaskedOrUnmaskedMinsMaxes(double& xMin, double& xMax, double& yMin,
681 : double& yMax, bool masked) {
682 0 : if(!isValid()) return false;
683 0 : unsigned int n = size();
684 0 : if(n == 0) return false;
685 0 : if(m_maskArray == NULL && m_maskVector == NULL &&
686 0 : m_maskCVector == NULL) return minsMaxes(xMin, xMax, yMin, yMax);
687 :
688 0 : unsigned int i = 0;
689 : bool m;
690 0 : for(; i < n; i++) {
691 0 : m = maskedAt(i);
692 0 : if((masked && m) || (!masked && !m)) {
693 0 : xMin = xMax = xAt(i);
694 0 : yMin = yMax = yAt(i);
695 0 : break;
696 : }
697 : }
698 0 : if(i == n) return false;
699 : double temp;
700 0 : for(; i < n; i++) {
701 0 : m = maskedAt(i);
702 0 : if((masked && m) || (!masked && !m)) {
703 0 : temp = xAt(i);
704 0 : if(temp < xMin) xMin = temp;
705 0 : if(temp > xMax) xMax = temp;
706 0 : temp = yAt(i);
707 0 : if(temp < yMin) yMin = temp;
708 0 : if(temp > yMax) yMax = temp;
709 : }
710 : }
711 0 : return true;
712 : }
713 : };
714 :
715 : typedef PlotMaskedPointDataImpl<int> PlotMaskedPointIntData;
716 : typedef PlotMaskedPointDataImpl<unsigned int> PlotMaskedPointUIntData;
717 : typedef PlotMaskedPointDataImpl<float> PlotMaskedPointFloatData;
718 : typedef PlotMaskedPointDataImpl<double> PlotMaskedPointDoubleData;
719 :
720 :
721 : // Default implementation of PlotErrorData using standard containers, plus
722 : // scalars for the four errors.
723 : template <class T>
724 : class PlotScalarErrorDataImpl : public virtual PlotErrorData,
725 : public PlotPointDataImpl<T> {
726 : public:
727 : // Scalar error for top, bottom, left, and right.
728 : // <group>
729 0 : PlotScalarErrorDataImpl(std::vector<T>& x, std::vector<T>& y, T xLeftError,
730 : T xRightError, T yBottomError, T yTopError,
731 : bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete),
732 0 : m_xLeftError(xLeftError), m_xRightError(xRightError),
733 0 : m_yBottomError(yBottomError), m_yTopError(yTopError) { }
734 0 : PlotScalarErrorDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, T xLeftError,
735 : T xRightError, T yBottomError, T yTopError,
736 : bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete),
737 0 : m_xLeftError(xLeftError), m_xRightError(xRightError),
738 0 : m_yBottomError(yBottomError), m_yTopError(yTopError) { }
739 0 : PlotScalarErrorDataImpl(T*& x, T*& y, unsigned int size, T xLeftError,
740 : T xRightError, T yBottomError, T yTopError,
741 : bool shouldDelete = false) :
742 : PlotPointDataImpl<T>(x, y, size, shouldDelete),
743 0 : m_xLeftError(xLeftError), m_xRightError(xRightError),
744 0 : m_yBottomError(yBottomError), m_yTopError(yTopError) { }
745 : // </group>
746 :
747 : // Single error for x and y.
748 : // <group>
749 : PlotScalarErrorDataImpl(std::vector<T>& x, std::vector<T>& y, T xError, T yError,
750 : bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete),
751 : m_xLeftError(xError), m_xRightError(xError),
752 : m_yBottomError(yError), m_yTopError(yError) { }
753 : PlotScalarErrorDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, T xError, T yError,
754 : bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete),
755 : m_xLeftError(xError), m_xRightError(xError),
756 : m_yBottomError(yError), m_yTopError(yError) { }
757 : PlotScalarErrorDataImpl(T*& x, T*& y,unsigned int size, T xError, T yError,
758 : bool shouldDelete = false) :
759 : PlotPointDataImpl<T>(x, y, size, shouldDelete),
760 : m_xLeftError(xError), m_xRightError(xError),
761 : m_yBottomError(yError), m_yTopError(yError) { }
762 : // </group>
763 :
764 : // Single error for all values.
765 : // <group>
766 : PlotScalarErrorDataImpl(std::vector<T>& x, std::vector<T>& y, T error,
767 : bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete),
768 : m_xLeftError(error), m_xRightError(error), m_yBottomError(error),
769 : m_yTopError(error) { }
770 : PlotScalarErrorDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, T error,
771 : bool shouldDelete=false): PlotPointDataImpl<T>(x, y, shouldDelete),
772 : m_xLeftError(error), m_xRightError(error), m_yBottomError(error),
773 : m_yTopError(error) { }
774 : PlotScalarErrorDataImpl(T*& x, T*& y, unsigned int size, T error,
775 : bool shouldDelete = false) :
776 : PlotPointDataImpl<T>(x, y, size, shouldDelete),
777 : m_xLeftError(error), m_xRightError(error), m_yBottomError(error),
778 : m_yTopError(error) { }
779 : // </group>
780 :
781 : // Destructor.
782 0 : ~PlotScalarErrorDataImpl() { }
783 :
784 : // Implements PlotErrorData getter methods.
785 : // <group>
786 0 : double xLeftErrorAt(unsigned int ) const { return m_xLeftError; }
787 0 : double xRightErrorAt(unsigned int ) const { return m_xRightError; }
788 0 : double yBottomErrorAt(unsigned int ) const { return m_yBottomError; }
789 0 : double yTopErrorAt(unsigned int ) const { return m_yTopError; }
790 : // </group>
791 :
792 : // Implements PlotErrorData::errorMaxes().
793 0 : bool errorMaxes(double& xLeft, double& xRight, double& yBottom,
794 : double& yTop) {
795 0 : xLeft = m_xLeftError;
796 0 : xRight = m_xRightError;
797 0 : yBottom = m_yBottomError;
798 0 : yTop = m_yTopError;
799 0 : return true;
800 : }
801 :
802 : private:
803 : T m_xLeftError, m_xRightError, m_yBottomError, m_yTopError;
804 : };
805 :
806 : typedef PlotScalarErrorDataImpl<int> PlotScalarErrorIntData;
807 : typedef PlotScalarErrorDataImpl<unsigned int> PlotScalarErrorUIntData;
808 : typedef PlotScalarErrorDataImpl<float> PlotScalarErrorFloatData;
809 : typedef PlotScalarErrorDataImpl<double> PlotScalarErrorDoubleData;
810 :
811 :
812 : // Default implementation of PlotErrorData using standard containers, plus
813 : // PlotPointDataImpls for the errors.
814 : template <class T>
815 : class PlotErrorDataImpl : public virtual PlotErrorData,
816 : public PlotPointDataImpl<T> {
817 : public:
818 : // Symmetric error constructors.
819 : // <group>
820 : PlotErrorDataImpl(T*& x, T*& y, T*& xError, T*& yError, unsigned int size,
821 : bool shouldDelete = true) :
822 : PlotPointDataImpl<T>(x, y, size, shouldDelete),
823 : m_xError(xError, xError, size, shouldDelete),
824 : m_yError(yError, yError, size, shouldDelete) { }
825 : PlotErrorDataImpl(std::vector<T>& x, std::vector<T>& y, std::vector<T>& xError,
826 : std::vector<T>& yError, bool shouldDelete = false) :
827 : PlotPointDataImpl<T>(x, y, shouldDelete),
828 : m_xError(xError, xError, shouldDelete),
829 : m_yError(yError, yError, shouldDelete) { }
830 : PlotErrorDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, casacore::Vector<T>& xError,
831 : casacore::Vector<T>& yError, bool shouldDelete = false) :
832 : PlotPointDataImpl<T>(x, y, shouldDelete),
833 : m_xError(xError, xError, shouldDelete),
834 : m_yError(yError, yError, shouldDelete) { }
835 : // </group>
836 :
837 : // Asymmetric error constructors.
838 : // <group>
839 0 : PlotErrorDataImpl(T*& x, T*& y, T*& xLeftError, T*& xRightError,
840 : T*& yBottomError, T*& yTopError, unsigned int size,
841 : bool shouldDelete = true) :
842 : PlotPointDataImpl<T>(x, y, size, shouldDelete),
843 0 : m_xError(xLeftError, xRightError, size, shouldDelete),
844 0 : m_yError(yBottomError, yTopError, size, shouldDelete) { }
845 0 : PlotErrorDataImpl(std::vector<T>& x, std::vector<T>& y, std::vector<T>& xLeftError,
846 : std::vector<T>& xRightError, std::vector<T>& yBottomError,
847 : std::vector<T>& yTopError, bool shouldDelete = false) :
848 : PlotPointDataImpl<T>(x, y, shouldDelete),
849 0 : m_xError(xLeftError, xRightError, shouldDelete),
850 0 : m_yError(yBottomError, yTopError, shouldDelete) { }
851 0 : PlotErrorDataImpl(casacore::Vector<T>& x, casacore::Vector<T>& y, casacore::Vector<T>& xLeftError,
852 : casacore::Vector<T>& xRightError, casacore::Vector<T>& yBottomError,
853 : casacore::Vector<T>& yTopError, bool shouldDelete = false) :
854 : PlotPointDataImpl<T>(x, y, shouldDelete),
855 0 : m_xError(xLeftError, xRightError, shouldDelete),
856 0 : m_yError(yBottomError, yTopError, shouldDelete) { }
857 : // </group>
858 :
859 0 : ~PlotErrorDataImpl() { }
860 :
861 : // Overrides PlotPointDataImpl::willDeleteData().
862 0 : bool willDeleteData() const {
863 0 : return PlotPointDataImpl<T>::willDeleteData() &&
864 0 : m_xError.willDeleteData() && m_yError.willDeleteData();
865 : }
866 :
867 : // Overrides PlotPointDataImpl::setDeleteData().
868 0 : void setDeleteData(bool del = true) {
869 0 : m_xError.setDeleteData(del);
870 0 : m_yError.setDeleteData(del);
871 0 : PlotPointDataImpl<T>::setDeleteData(del);
872 0 : }
873 :
874 : // Implements PlotErrorData getter methods.
875 : // <group>
876 0 : double xLeftErrorAt(unsigned int i) const { return m_xError.xAt(i); }
877 0 : double xRightErrorAt(unsigned int i) const { return m_xError.yAt(i); }
878 0 : double yBottomErrorAt(unsigned int i) const { return m_yError.xAt(i); }
879 0 : double yTopErrorAt(unsigned int i) const { return m_yError.yAt(i); }
880 : // </group>
881 :
882 : // Implements PlotErrorData::errorMaxes().
883 0 : bool errorMaxes(double& xLeft, double& xRight, double& yBottom,
884 : double& yTop) {
885 : double temp;
886 0 : return m_xError.minsMaxes(temp, xLeft, temp, xRight) &&
887 0 : m_yError.minsMaxes(temp, yBottom, temp, yTop);
888 : }
889 :
890 : private:
891 : PlotPointDataImpl<T> m_xError, m_yError;
892 : };
893 :
894 : typedef PlotErrorDataImpl<int> PlotErrorIntData;
895 : typedef PlotErrorDataImpl<unsigned int> PlotErrorUIntData;
896 : typedef PlotErrorDataImpl<float> PlotErrorFloatData;
897 : typedef PlotErrorDataImpl<double> PlotErrorDoubleData;
898 :
899 :
900 : // Implementation of raster data using casa::Matrix.
901 : template <class T>
902 : class PlotRasterMatrixData : public virtual PlotRasterData {
903 : public:
904 : // Whether the indexing is (row,col) or (x,y). Default is (row,col).
905 : enum Indexing {
906 : ROW_COL, X_Y
907 : };
908 :
909 0 : PlotRasterMatrixData(casacore::Matrix<T>& data, bool shouldDelete = false) :
910 0 : m_data(&data), m_origin(LLEFT), m_indexing(ROW_COL),
911 0 : m_shouldDelete(shouldDelete) {
912 0 : casacore::IPosition shape = data.shape();
913 0 : unsigned int n0 = shape[0] - 1, n1 = shape[1] - 1;
914 :
915 0 : m_0From = 0;
916 0 : m_0To = n0 + 1;
917 0 : m_1From = 0;
918 0 : m_1To = n1 + 1;
919 0 : m_0Pieces = (n0 + 1) / (m_0To - m_0From);
920 0 : m_1Pieces = (n1 + 1) / (m_1To - m_1From);
921 :
922 0 : double val = static_cast<double>(data(0, 0));
923 0 : m_valFrom = m_valTo = val;
924 0 : for(casacore::uInt i = 0; i < data.nrow(); i++) {
925 0 : for(casacore::uInt j = 0; j < data.ncolumn(); j++) {
926 0 : val = static_cast<double>(data(i, j));
927 0 : if(val < m_valFrom) m_valFrom = val;
928 0 : if(val > m_valTo) m_valTo = val;
929 : }
930 : }
931 0 : }
932 :
933 0 : ~PlotRasterMatrixData() { if(m_shouldDelete) delete m_data; }
934 :
935 : // Implements PlotData::isValid().
936 0 : bool isValid() const { return true; }
937 :
938 : // Implements PlotData::willDeleteData().
939 0 : bool willDeleteData() const { return m_shouldDelete; }
940 :
941 : // Implements PlotData::setDeleteData().
942 0 : void setDeleteData(bool del = true) { m_shouldDelete = del; }
943 :
944 : // Implements PlotRasterData::origin().
945 0 : Origin origin() const { return m_origin; }
946 :
947 : // Implements PlotRasterData::setOrigin().
948 0 : void setOrigin(Origin o) {
949 0 : if(m_origin != o) {
950 0 : m_origin = o;
951 : }
952 0 : }
953 :
954 : // Implements PlotRasterData::xRange().
955 0 : prange_t xRange() const {
956 0 : if(m_indexing == X_Y) return prange_t(m_0From, m_0To);
957 0 : else return prange_t(m_1From, m_1To);
958 : }
959 :
960 : // Implements PlotRasterData::yRange().
961 0 : prange_t yRange() const {
962 0 : if(m_indexing == X_Y) return prange_t(m_1From, m_1To);
963 0 : else return prange_t(m_0From, m_0To);
964 : }
965 :
966 : // Implements PlotRasterData::setXRange().
967 0 : void setXRange(double from, double to) {
968 0 : if(from == to) return;
969 0 : if(from > to) {
970 0 : double temp = from;
971 0 : from = to;
972 0 : to = temp;
973 : }
974 :
975 0 : if(m_indexing == X_Y) {
976 0 : m_0From = from;
977 0 : m_0To = to;
978 0 : m_0Pieces = (m_data->shape()[0]) / (m_0To - m_0From);
979 : } else {
980 0 : m_1From = from;
981 0 : m_1To = to;
982 0 : m_1Pieces = (m_data->shape()[1]) / (m_1To - m_1From);
983 : }
984 : }
985 :
986 : // Implements PlotRasterData::setYRange().
987 0 : void setYRange(double from, double to) {
988 0 : if(from == to) return;
989 0 : if(from > to) {
990 0 : double temp = from;
991 0 : from = to;
992 0 : to = temp;
993 : }
994 :
995 0 : if(m_indexing == X_Y) {
996 0 : m_1From = from;
997 0 : m_1To = to;
998 0 : m_1Pieces = (m_data->shape()[1]) / (m_1To - m_1From);
999 : } else {
1000 0 : m_0From = from;
1001 0 : m_0To = to;
1002 0 : m_0Pieces = (m_data->shape()[0]) / (m_0To - m_0From);
1003 : }
1004 : }
1005 :
1006 : // Implements PlotRasterData::valueRange().
1007 0 : prange_t valueRange() const { return prange_t(m_valFrom, m_valTo); }
1008 :
1009 : // Implements PlotRasterData::valueAt().
1010 0 : double valueAt(double x, double y) const {
1011 0 : if(m_indexing == X_Y) {
1012 0 : if(x < m_0From || x > m_0To || y < m_1From || y > m_1To) return 0;
1013 :
1014 0 : int xi = (int)((x - m_0From) * m_0Pieces);
1015 0 : int yi = (int)((y - m_1From) * m_1Pieces);
1016 0 : if(xi >= m_data->shape()[0]) xi = m_data->shape()[0] - 1;
1017 0 : if(yi >= m_data->shape()[1]) yi = m_data->shape()[1] - 1;
1018 :
1019 0 : return static_cast<double>((*m_data)(xi, yi));
1020 :
1021 : } else {
1022 0 : if(x < m_1From || x > m_1To || y < m_0From || y > m_0To) return 0;
1023 :
1024 0 : int xi = (int)((x - m_1From) * m_1Pieces);
1025 0 : int yi = (int)((y - m_0From) * m_0Pieces);
1026 0 : if(xi >= m_data->shape()[1]) xi = m_data->shape()[1] - 1;
1027 0 : if(yi >= m_data->shape()[0]) yi = m_data->shape()[0] - 1;
1028 :
1029 0 : return static_cast<double>((*m_data)(yi, xi));
1030 : }
1031 : }
1032 :
1033 : // Implements PlotRasterData::colorBarValues().
1034 0 : std::vector<double>* colorBarValues(unsigned int max = 1000) const {
1035 0 : std::vector<double>* v = new std::vector<double>();
1036 :
1037 : double val;
1038 : bool found;
1039 0 : for(unsigned int i = 0; i < m_data->nrow() && v->size() <= max; i++) {
1040 0 : for(unsigned int j = 0; j < m_data->ncolumn() && v->size() <= max;
1041 : j++) {
1042 0 : val = static_cast<double>((*m_data)(i, j));
1043 0 : found = false;
1044 0 : for(unsigned int k = 0; k < v->size() && !found; k++)
1045 0 : if(v->at(k) == val) found = true;
1046 0 : if(!found) v->push_back(val);
1047 : }
1048 : }
1049 :
1050 0 : return v;
1051 : }
1052 :
1053 : // Gets/sets the indexing used for the matrix.
1054 : // <group>
1055 : Indexing indexing() const { return m_indexing; }
1056 : void setIndexing(Indexing i) { m_indexing = i; }
1057 : // </group>
1058 :
1059 : // Gets/sets the matrix.
1060 : // <group>
1061 : casacore::Matrix<T>* matrix() { return m_data; }
1062 : void setMatrix(casacore::Matrix<T>* m, bool shouldDelete = true) {
1063 : if(m_shouldDelete) delete m_data;
1064 : m_data = m;
1065 : m_shouldDelete = shouldDelete;
1066 : }
1067 : // </group>
1068 :
1069 : private:
1070 : casacore::Matrix<T>* m_data;
1071 : double m_0From, m_0To;
1072 : double m_1From, m_1To;
1073 : double m_0Pieces, m_1Pieces;
1074 : double m_valFrom, m_valTo;
1075 : Origin m_origin;
1076 : Indexing m_indexing;
1077 : bool m_shouldDelete;
1078 : };
1079 :
1080 : }
1081 :
1082 : #endif /*PLOTDATA_H_*/
|