casa
$Rev:20696$
|
00001 //# MeasureHolder.h: A holder for Measures to enable record conversions 00002 //# Copyright (C) 1998,1999,2000,2003 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id: MeasureHolder.h 21024 2011-03-01 11:46:18Z gervandiepen $ 00027 00028 #ifndef MEASURES_MEASUREHOLDER_H 00029 #define MEASURES_MEASUREHOLDER_H 00030 00031 //# Includes 00032 #include <casa/aips.h> 00033 #include <casa/Utilities/PtrHolder.h> 00034 #include <casa/Utilities/RecordTransformable.h> 00035 #include <casa/Containers/Block.h> 00036 00037 namespace casa { //# NAMESPACE CASA - BEGIN 00038 00039 //# Forward Declarations 00040 class Measure; 00041 class MDirection; 00042 class MDoppler; 00043 class MEpoch; 00044 class MFrequency; 00045 class MPosition; 00046 class MRadialVelocity; 00047 class Muvw; 00048 class MBaseline; 00049 class MEarthMagnetic; 00050 class MeasValue; 00051 00052 // <summary> A holder for Measures to enable record conversions </summary> 00053 00054 // <use visibility=export> 00055 00056 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tMeasureHolder" demos=""> 00057 // </reviewed> 00058 00059 // <prerequisite> 00060 // <li> <linkto class=RecordInterface>RecordInterface</linkto> class 00061 // <li> <linkto class=Measure>Measure</linkto> class 00062 // </prerequisite> 00063 // 00064 // <etymology> 00065 // A Holder of general Measures 00066 // </etymology> 00067 // 00068 // <synopsis> 00069 // This class can be used to handle heterogeneous collections of Measures, e.g. 00070 // as a <src>Vector<MeasureHolder></src>. With the aid of the 00071 // toRecord() and fromRecord() functions it can be used 00072 // to convert a Measure object into or from a record. 00073 // A MeasureHolder is created from a Measure, or can be empty. 00074 // 00075 // Checks on the contents can be made with functions like 00076 // <src>isMDirection</src> and the contents can be obtained with 00077 // functions like <src>asMDirection</src>. It is an error to try and 00078 // retrieve a measure of the wrong type and doing so will generate an 00079 // exception (AipsError). 00080 // 00081 // The MeasureHolder can, in addition to the Measure it is holding, also hold 00082 // a block of MeasValues. This is especially useful for intertask 00083 // communication (e.g. with Glish), for reasons of speed. In general the 00084 // additional values will be created when the record used to create 00085 // a Holder contains a <src>Quantity<Vector></src> rather than a quantity in 00086 // the m0, m1 and/or m2 fields. The <src>getMV()</src> method can be used to 00087 // access the <src>nelements()</src> additional information. They can be 00088 // (re-)set with the <src>setMV()</src> method (after a possible creation 00089 // of the extra block if not already there, or of the wrong length, 00090 // with <src>makeMV()</src>. If any value is set they will be used in 00091 // creating records, with the first value always overwriting the actual 00092 // Measure value. 00093 // 00094 // </synopsis> 00095 // 00096 // <example> 00097 // <srcblock> 00098 // TableRecord rec; 00099 // MDirection dir(MVDirection(Quantity(12.5, 'deg'), Quantity(-2, 'deg')), 00100 // MDirection::J2000); 00101 // String error; // error message 00102 // if (!MeasureHolder(dir).toRecord(error, rec)) { 00103 // cout << error << endl; 00104 // } 00105 // Record grec; // a Record 00106 // if (!MeasureHolder(dir).toRecord(error, grec)) { // make record 00107 // cout << error << endl; 00108 // } 00109 // // Note that for GlishRecords use can be made of the 00110 // // GlishRecord::to/fromrecord() methods. 00111 // </srcblock> 00112 // </example> 00113 // 00114 // <motivation> 00115 // To make general conversions between Measures and records, without knowing 00116 // the actual Measure being converted. 00117 // </motivation> 00118 00119 class MeasureHolder : public RecordTransformable { 00120 00121 public: 00122 00123 //# Friends 00124 00125 //# Enumerations 00126 00127 //# Constructors 00128 // Creates an empty holder 00129 MeasureHolder(); 00130 // Create from a Measure (copy made) 00131 MeasureHolder(const Measure &in); 00132 // Copy a holder (copy semantics) 00133 MeasureHolder(const MeasureHolder &other); 00134 //# Destructor 00135 ~MeasureHolder(); 00136 00137 //# Operators 00138 // Assignment (copy semantics) 00139 MeasureHolder &operator=(const MeasureHolder &other); 00140 00141 //# Member Functions 00142 // Check the the MeasureHolder holds the specified Measure type. Return 00143 // True if if does and False otherwise. 00144 // <group> 00145 Bool isEmpty() const; 00146 Bool isMeasure() const; 00147 Bool isMDirection() const; 00148 Bool isMDoppler() const; 00149 Bool isMEpoch() const; 00150 Bool isMFrequency() const; 00151 Bool isMPosition() const; 00152 Bool isMRadialVelocity() const; 00153 Bool isMBaseline() const; 00154 Bool isMuvw() const; 00155 Bool isMEarthMagnetic() const; 00156 // </group> 00157 00158 // Get a specific Measure from the holder (with lifetime as long 00159 // as holder exists). 00160 // <thrown> 00161 // <li> AipsError if holder empty 00162 // <li> AipsError if holder contains wrong Measure 00163 // </thrown> 00164 // <group> 00165 const Measure &asMeasure() const; 00166 const MDirection &asMDirection() const; 00167 const MDoppler &asMDoppler() const; 00168 const MEpoch &asMEpoch() const; 00169 const MFrequency &asMFrequency() const; 00170 const MPosition &asMPosition() const; 00171 const MRadialVelocity &asMRadialVelocity() const; 00172 const MBaseline &asMBaseline() const; 00173 const Muvw &asMuvw() const; 00174 const MEarthMagnetic &asMEarthMagnetic() const; 00175 // </group> 00176 // Create a Measure from a record. An error message is generated, and False 00177 // returned if an invalid record is given. A valid record will return True. 00178 // A valid record contains the following fields (any additional fields are 00179 // ignored): 00180 // <ul> 00181 // <li> type = TpString: type of Measure (direction, epoch, etc; case 00182 // insensitive) 00183 // <li> refer = TpString: reference type of Measure (case insensitive; 00184 // enough characters to be unique (e.g. J20, j200, utc, b1950, J2000); 00185 // unknown reference type will log an error message and translate into 00186 // the default type for the Measure. 00187 // <li> m0, m1, ... = TpRecord(Quantity): one or more Quantities giving 00188 // the value(s) for this Measure (e.g. longitude and latitude for a 00189 // direction). Each quantity can either be a scalar quantity or a 00190 // Quantum<Vector<Double> >. 00191 // <li> offset = TpRecord(Measure)--optional: an optional offset as a 00192 // Measure of the same type as the main Measure (e.g. an MEpoch for an 00193 // MEpoch) 00194 // </ul> 00195 // A Measure can be created from a string. In that case the string 00196 // will only indicate the type of measure (like direction), and will 00197 // create a default measure of that given type. In essence identical 00198 // to the fromType() method. 00199 // Error messages are postfixed to error. 00200 // <group> 00201 virtual Bool fromRecord(String &error, const RecordInterface &in); 00202 virtual Bool fromString(String &error, const String &in); 00203 // </group> 00204 // Create a record from a Measure. The return will be False and an error 00205 // message generated only if the MeasureHolder does not contain a Measure. 00206 // Error messages are postfixed to error. 00207 virtual Bool toRecord(String &error, RecordInterface &out) const; 00208 00209 // This version throws an exception if the conversion cannot 00210 // occur. It is meant for more allow more compact calling code for callers 00211 // that are content with just letting the exception proceed up the call stack 00212 // so they do not have to check a return status. This is, among other things, what 00213 // exceptions are for after all. 00214 // TODO. I'd rather return the RecordInterface, but since RecordInterface is abstract, 00215 // that means returning a pointer that is created internally. That really should be 00216 // done using a smart pointer, but other than our own PtrHolder (which I'd really rather 00217 // not use), auto_ptr is really the only thing that can be used at this point. auto_ptr 00218 // has its own issues and is frowned on by other casacore partners, so I don't want to 00219 // litter casacore code with that. unique_ptr is a much better solution, but as of now 00220 // that is still not available. When it becomes available this issue can be revisited. 00221 virtual void toRecord(RecordInterface& outRecord) const; 00222 00223 00224 // Create a default Measure or a record with only a type from a Measure 00225 00226 // <group> 00227 Bool toType(String &error, RecordInterface &out) const; 00228 Bool fromType(String &error, const RecordInterface &in); 00229 // </group> 00230 // Get identification of record 00231 virtual const String &ident() const; 00232 // Do we write MeasValues to record? 00233 Bool writeMV() const { return convertmv_p; } 00234 // Make a block of n MeasValues 00235 void makeMV(uInt n) { createMV(n); } 00236 // Get number of MeasValue pointers in block 00237 uInt nelements() const { return mvhold_p.nelements(); } 00238 // Set a measvalue at position pos (False if illegal pos) 00239 Bool setMV(uInt pos, const MeasValue &in); 00240 // Get a pointer to a MeasValue (or 0) 00241 MeasValue *getMV(uInt pos) const; 00242 00243 private: 00244 00245 //# Data Members 00246 // Pointer to a Measure 00247 PtrHolder<Measure> hold_p; 00248 // Block of pointers to measure values to make a faster interface 00249 Block<MeasValue *> mvhold_p; 00250 // Should the mvhold_p be converted into record? 00251 Bool convertmv_p; 00252 //# Member functions 00253 // Aid for to/from Record, String and Type 00254 // <group> 00255 Bool putType(String &error, RecordInterface &out) const; 00256 Bool getType(String &error, const RecordInterface &in); 00257 Bool getType(String &error, const String &in); 00258 // </group> 00259 // Make a MeasValue block of pointers of length n 00260 void createMV(uInt n); 00261 }; 00262 00263 00264 } //# NAMESPACE CASA - END 00265 00266 #endif