//# Copyright (C) 1998,1999,2000,2001 //# 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 //# #ifndef ANNOTATIONS_ANNOTATIONBASE_H #define ANNOTATIONS_ANNOTATIONBASE_H #include <casacore/coordinates/Coordinates/CoordinateSystem.h> #include <casacore/casa/Utilities/Regex.h> #include <casacore/measures/Measures/Stokes.h> #include <list> namespace casa { // <summary>Base class for annotations</summary> // <use visibility=export> // <reviewed reviewer="" date="yyyy/mm/dd"> // </reviewed> // <synopsis> // Base class for annotations // In order to minimize maintainability, many parameters are not // set in the constructor but can be set by mutator methods. // // casacore::Input directions will be converted to the reference frame of the // input coordinate system upon construction if necessary. The coordinate // system specified in the constructor should be that associated with the // image to which the region/annotation is being applied. // </synopsis> class AnnotationBase { public: using RGB = std::vector<float>; // The pairs have longitude as the first member and latitude as the second using Direction = casacore::Vector<std::pair<casacore::Quantity,casacore::Quantity> >; enum Type { // annotations only LINE, VECTOR, TEXT, SYMBOL, // regions RECT_BOX, CENTER_BOX, ROTATED_BOX, POLYGON, POLYLINE, CIRCLE, ANNULUS, ELLIPSE }; enum Keyword { COORD, RANGE, FRAME, CORR, VELTYPE, RESTFREQ, LINEWIDTH, LINESTYLE, SYMSIZE, SYMTHICK, COLOR, FONT, FONTSIZE, FONTSTYLE, USETEX, LABEL, LABELCOLOR, LABELPOS, LABELOFF, UNKNOWN_KEYWORD, N_KEYS }; enum LineStyle { SOLID, DASHED, DOT_DASHED, DOTTED }; enum FontStyle { NORMAL, BOLD, ITALIC, ITALIC_BOLD }; static const RGB BLACK; static const RGB BLUE; static const RGB CYAN; static const RGB GRAY; static const RGB GREEN; static const RGB MAGENTA; static const RGB ORANGE; static const RGB RED; static const RGB WHITE; static const RGB YELLOW; static const casacore::String DEFAULT_LABEL; static const RGB DEFAULT_COLOR; static const LineStyle DEFAULT_LINESTYLE; static const casacore::uInt DEFAULT_LINEWIDTH; static const casacore::uInt DEFAULT_SYMBOLSIZE; static const casacore::uInt DEFAULT_SYMBOLTHICKNESS; static const casacore::String DEFAULT_FONT; static const casacore::uInt DEFAULT_FONTSIZE; static const FontStyle DEFAULT_FONTSTYLE; static const casacore::Bool DEFAULT_USETEX; static const RGB DEFAULT_LABELCOLOR; static const casacore::String DEFAULT_LABELPOS; static const std::vector<casacore::Int> DEFAULT_LABELOFF; static const casacore::Regex rgbHexRegex; virtual ~AnnotationBase(); Type getType() const; static LineStyle lineStyleFromString(const casacore::String& ls); // Given a string, return the corresponding annotation type or throw // an error if the string does not correspond to an allowed type. static Type typeFromString(const casacore::String& type); static casacore::String typeToString(const Type type); static casacore::String keywordToString(const Keyword key); static casacore::String lineStyleToString(const LineStyle linestyle); static FontStyle fontStyleFromString(const casacore::String& fs); static casacore::String fontStyleToString(const FontStyle fs); void setLabel(const casacore::String& label); casacore::String getLabel() const; // <src>color</src> must either be a recognized color name or // a valid rgb hex string, else an expection is thrown void setColor(const casacore::String& color); // color must have three elements all with values between 0 and 255 inclusive // or an exception is thrown. void setColor(const RGB& color); // returns the color name if it is recognized or its rgb hex string casacore::String getColorString() const; static casacore::String colorToString(const RGB& color); // get the color associated with this object RGB getColor() const; void setLineStyle(const LineStyle lineStyle); LineStyle getLineStyle() const; void setLineWidth(const casacore::uInt linewidth); casacore::uInt getLineWidth() const; void setSymbolSize(const casacore::uInt symbolsize); casacore::uInt getSymbolSize() const; void setSymbolThickness(const casacore::uInt symbolthickness); casacore::uInt getSymbolThickness() const; void setFont(const casacore::String& font); casacore::String getFont() const; void setFontSize(const casacore::uInt fontsize); casacore::uInt getFontSize() const; void setFontStyle(const FontStyle& fontstyle); FontStyle getFontStyle() const; void setUseTex(const casacore::Bool usetex); casacore::Bool isUseTex() const; // is the object a region? virtual casacore::Bool isRegion() const; // is the object only an annotation? Can only be false if the object // is a region inline virtual casacore::Bool isAnnotationOnly() const { return true; } // set "pix" as valid unit. This should be called externally // before creating quantities which have pixel units. static void unitInit(); // <src>color</src> must either be a recognized color name or // a valid rgb hex string, else an expection is thrown void setLabelColor(const casacore::String& color); // color must have three elements all with values between 0 and 255 inclusive // or an exception is thrown. void setLabelColor(const RGB& color); // returns the color name if it is recognized or its rgb hex string casacore::String getLabelColorString() const; // get the color associated with this object's label RGB getLabelColor() const; // returns one of top, bottom, left, or right. casacore::String getLabelPosition() const; // <src>position</src> must have a value in top, bottom, left, or right. // case is ignored. void setLabelPosition(const casacore::String& position); // <src>offset</src> must have two elements void setLabelOffset(const std::vector<casacore::Int>& offset); std::vector<casacore::Int> getLabelOffset() const; virtual std::ostream& print(std::ostream &os) const = 0; // These parameters are included at the global scope. Multiple runs // on the same object are cumulative; if a key exists in the current // settings but not in <src>globalKeys</src> that key will still exist // in the globals after setGlobals has run. void setGlobals(const casacore::Vector<Keyword>& globalKeys); // print a set of keyword value pairs static std::ostream& print( std::ostream& os, const std::map<Keyword, casacore::String>& params ); // print a line style representation static std::ostream& print( std::ostream& os, const LineStyle ls ); // print a font style representation static std::ostream& print( std::ostream& os, const FontStyle fs ); static std::ostream& print( std::ostream& os, const Direction d ); // Get a list of the user-friendly color names supported static std::list<std::string> colorChoices(); // get the coordinate system associated with this object. // This is the same coordinate system used to construct the object. inline const casacore::CoordinateSystem& getCsys() const { return _csys; } // DEPRECATED Please use getConvertedDirections() // the pair elements have longitude as the first member and latitude as the second. // FIXME make this return of vector of MVDirections // Returns the same angles as getConvertedDirections() Direction getDirections() const; // get the frequency limits converted to the spectral frame of the coordinate // system of this object. An empty casacore::Vector implies all applicable frequencies // have been selected. casacore::Vector<casacore::MFrequency> getFrequencyLimits() const; // Get the stokes for which the selection applies. An empty casacore::Vector implies // all applicable stokes have been selected. casacore::Vector<casacore::Stokes::StokesTypes> getStokes() const; // if freqRefFrame=="" -> use the reference frame of the coordinate system // if dopplerString=="" -> use the doppler system associated with the coordinate system // if restfreq=casacore::Quantity(0, "Hz") -> use the rest frequency associated with the coordinate system // Tacitly does nothing if the coordinate system has no spectral axis. // Returns true if frequencies actually need to be set and were set. virtual casacore::Bool setFrequencyLimits( const casacore::Quantity& beginFreq, const casacore::Quantity& endFreq, const casacore::String& freqRefFrame, const casacore::String& dopplerString, const casacore::Quantity& restfreq ); // same as getDirections, only returns proper MDirections inline const casacore::Vector<casacore::MDirection>& getConvertedDirections() const { return _convertedDirections; } protected: // <group> // if <src>freqRefFrame</src> or <src>dopplerString</src> are empty, // the values from the spectral coordinate of csys will be used, if one // exists. if restfreq=casacore::Quantity(0, "Hz") -> use the rest frequency // associated with the coordinate system. // The provided coordinate system should be that of the image to which // the region/annotation is being applied. AnnotationBase( const Type type, const casacore::String& dirRefFrameString, const casacore::CoordinateSystem& csys, const casacore::Quantity& beginFreq, const casacore::Quantity& endFreq, const casacore::String& freqRefFrame, const casacore::String& dopplerString, const casacore::Quantity& restfreq, const casacore::Vector<casacore::Stokes::StokesTypes>& stokes ); // use only if the frame of the input directions is the // same as the frame of the coordinate system. All frequencies // are used. AnnotationBase( const Type type, const casacore::CoordinateSystem& csys, const casacore::Vector<casacore::Stokes::StokesTypes>& stokes ); // <group> // assignment operator AnnotationBase& operator= (const AnnotationBase& other); static void _checkMixed( const casacore::String& origin, const Direction& dirs ); casacore::MDirection _directionFromQuantities( const casacore::Quantity& q0, const casacore::Quantity& q1 ); void _checkAndConvertDirections( const casacore::String& origin, const Direction& dirs ); virtual void _printPairs(std::ostream& os) const; inline const casacore::IPosition& _getDirectionAxes() const { return _directionAxes; } // direction to string, precision of 0.1 mas // ra and dec in sexigesimal format, non-equatorial coords in degrees casacore::String _printDirection( const casacore::Quantity& longitude, const casacore::Quantity& latitude ) const; // convert angle to arcsec, precision 0.1 mas static casacore::String _toArcsec(const casacore::Quantity& angle); // convert angle to degrees, precision 0.1 mas static casacore::String _toDeg(const casacore::Quantity& angle); inline void _setParam(const Keyword k, const casacore::String& s) { _params[k] = s; } // return a string representing a pixel value, precision 1. static casacore::String _printPixel(const casacore::Double& d); casacore::MDirection::Types _getDirectionRefFrame() const { return _directionRefFrame; } private: Type _type; casacore::MDirection::Types _directionRefFrame; casacore::CoordinateSystem _csys; casacore::IPosition _directionAxes; casacore::String _label, _font, _labelPos; RGB _color, _labelColor; FontStyle _fontstyle; LineStyle _linestyle; casacore::uInt _fontsize, _linewidth, _symbolsize, _symbolthickness; casacore::Bool _usetex; casacore::Vector<casacore::MDirection> _convertedDirections; casacore::Vector<casacore::MFrequency> _convertedFreqLimits; casacore::Quantity _beginFreq, _endFreq, _restFreq; casacore::Vector<casacore::Stokes::StokesTypes> _stokes; casacore::MFrequency::Types _freqRefFrame; casacore::MDoppler::Types _dopplerType; std::map<Keyword, casacore::Bool> _globals; std::map<Keyword, casacore::String> _params; casacore::Bool _printGlobals; std::vector<casacore::Int> _labelOff; static casacore::Bool _doneUnitInit, _doneColorInit; static std::map<casacore::String, LineStyle> _lineStyleMap; static std::map<casacore::String, Type> _typeMap; static std::map<string, RGB> _colors; static std::map<RGB, string> _rgbNameMap; static std::list<std::string> _colorNames; const static casacore::String _class; void _init(); void _initParams(); static void _initColors(); static RGB _colorStringToRGB(const casacore::String& s); static casacore::Bool _isRGB(const RGB& rgb); void _testConvertToPixel() const; static void _initTypeMap(); void _checkAndConvertFrequencies(); casacore::String _printFreqRange() const; static casacore::String _printFreq(const casacore::Quantity& freq); }; inline std::ostream &operator<<(std::ostream& os, const AnnotationBase& annotation) { return annotation.print(os); }; inline std::ostream &operator<<(std::ostream& os, const AnnotationBase::LineStyle& ls) { return AnnotationBase::print(os, ls); }; inline std::ostream &operator<<(std::ostream& os, const AnnotationBase::FontStyle& fs) { return AnnotationBase::print(os, fs); }; inline std::ostream &operator<<(std::ostream& os, const std::map<AnnotationBase::Keyword, casacore::String>& x) { return AnnotationBase::print(os, x); }; inline std::ostream &operator<<(std::ostream& os, const AnnotationBase::Direction x) { return AnnotationBase::print(os, x); }; // Just need a identifiable exception class for exception handling. class WorldToPixelConversionError : public casacore::AipsError { public: WorldToPixelConversionError(casacore::String msg) : casacore::AipsError(msg) {} }; } #endif