SimFeed.h

Go to the documentation of this file.
00001 //# SimFeed.h: container for containing feed descriptions in memory
00002 //# Copyright (C) 2002,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$
00027 
00028 #ifndef SIMULATORS_SIMFEED_H
00029 #define SIMULATORS_SIMFEED_H
00030 
00031 #include <casa/BasicSL/String.h>
00032 #include <casa/Arrays/Vector.h>
00033 #include <casa/Arrays/Matrix.h>
00034 #include <measures/Measures/MPosition.h>
00035 #include <measures/Measures/Stokes.h>
00036 #include <casa/Exceptions/Error.h>
00037 
00038 namespace casa { //# NAMESPACE CASA - BEGIN
00039 
00040 class MSFeed;
00041 class MSFeedColumns;
00042 
00043 // <summary> a container for data destined for an MS FEED record </summary>
00044 
00045 // <use visibility=export>
00046 
00047 // <reviewed reviewer="" date="" tests="" demos="">
00048 
00049 // <prerequisite>
00050 //   <li> <linkto class="SimTelescope">SimTelescope</linkto>
00051 // </prerequisite>
00052 //
00053 // <etymology>
00054 // This is a container for data describing a signal feed for a simulated
00055 // telescope.
00056 // </etymology>
00057 //
00058 // <synopsis> 
00059 // This class describes a feed in terms of the data that make up a record
00060 // in the FEED table.  In the MS data 
00061 // model, a feed can carry the signals for one or more polarizations.  This
00062 // class records those types as well as more complex characteristics of the
00063 // feed.  
00064 // This container is used to define simulated observations.  Simulators would
00065 // not normally create these objects directly but rather implicitly via the
00066 // <linkto class="SimTelescope">SimTelescope</linkto> class.  <p>
00067 // 
00068 // The most important part of the feed description is the set of 
00069 // polarization types.  These are set at construction time or with 
00070 // setPolTypes().  The "key" is a set of data that uniquely identifies this
00071 // feed within a set of records in a FEED table and is made up of a time 
00072 // stamp, a time interval, and a set of IDs; these are all set simultaneously
00073 // with setKey().  Currently with this class, a feed is restricted to be 
00074 // associated with either a single antenna (and/or window) or all antennas
00075 // currently defined.  The more complex information, such as the feed postion 
00076 // and beam offset, can also be set after construction, via various set 
00077 // functions. <p>
00078 //
00079 // A row marker, set with setRow(), is used by 
00080 // <linkto class="SimFeedList">SimFeedList</linkto> to indicate that this 
00081 // SimFeed has been written out to a FEED table.  In general, a single 
00082 // SimFeed will be written out as a series of rows in the FEED table, usually 
00083 // one for each antenna.  Thus, the row marker represents the first row 
00084 // associated with this SimFeed. <p>
00085 //
00086 // Although this class has several non-const functions that update the 
00087 // internal data, it is not intended that the data be changed arbitrarily 
00088 // at any time.  The complexity of the data (and the fact that much of it
00089 // is optional) makes setting it via update functions more convenient than
00090 // via a constructor.  Care should be taken to avoid updating the object
00091 // after it has been copied to disk (by the 
00092 // <linkto class="SimFeedList">SimFeedList</linkto> class).  A negative
00093 // value returned from getRow() indicates that the item has not yet been
00094 // written out. <p>
00095 // </synopsis> 
00096 //
00097 // <motivation>
00098 // This container provides an simplified in-memory representation of 
00099 // feeds that will ultimately be written to a FEED table.  
00100 // The interface is oriented toward what is typical with current instruments
00101 // and thus is simpler than the interface provided by the MS FEED 
00102 // table.
00103 // </motivation>
00104 //
00105 // <todo asof="03/03/25">
00106 //   <li> loading from an existing MS needs more testing.
00107 //   <li> It would probably be helpful to have a common base classes for 
00108 //        all Sim* and Sim*List classes that are managed by SimTelescope
00109 //        and SimObservations
00110 //   <li> Because this class was written first, it behaves a little different
00111 //        from the other Sim* classes; it should probably be homogenized a 
00112 //        bit.
00113 // </todo>
00114 class SimFeed {
00115 public:
00116 
00117     // create the record container.  
00118     //   nrec is the number of receptors associated with this feed.
00119     //   types is a String containing the polarization codes for each 
00120     //      receptor in their proper order (with no intervening spaces); 
00121     //      the length of the string must either be 0 (to be set later 
00122     //      with setPolTypes()) or equal to number of receptors.
00123     //   ant is the ID for the antenna associated with this feed; a value of -1 
00124     //      means this applies to all antennae.
00125     //   spw is the ID for the spectral window associated with this feed; a 
00126     //      value of -1 means that this applies to all windows.
00127     SimFeed(uInt nrec=2, String types="", Int ant=-1, Int spw=-1) : 
00128         nrecp_p(nrec), antId_p(ant), spwId_p(spw), beamId_p(-1), row_p(-1), 
00129         pols_p(), position_p(0), beamOff_p(0), polResp_p(0), angle_p(0) 
00130     { 
00131         if (types.length() > 0) setPolTypes(types);
00132     }
00133 
00134     // make a copy of the record
00135     SimFeed(const SimFeed& f) : nrecp_p(f.nrecp_p), 
00136         antId_p(f.antId_p), spwId_p(f.spwId_p), beamId_p(f.beamId_p), row_p(-1),
00137         pols_p(f.pols_p), position_p(f.position_p), beamOff_p(f.beamOff_p), 
00138         polResp_p(f.polResp_p), angle_p(f.angle_p) 
00139     { }
00140 
00141     SimFeed& operator=(const SimFeed& f);
00142 
00143     virtual ~SimFeed() { deletePointers(); }
00144 
00145     // set the values that make up the lookup key for this feed.  Negative 
00146     // values for ant and spw mean the record applies to all antennae and 
00147     // windows, respectively.  A value of 0 for time defaults to the start
00148     // time.
00149     void setKey(uInt feed, Int ant=-1, Int spw=-1, 
00150                 Double time=0, Double interval=0) 
00151     {
00152         feedId_p = feed;
00153         antId_p = ant;
00154         spwId_p = spw;
00155         time_p = time;
00156         intv_p = interval;
00157 //      beamId_p = beam;
00158     }
00159 
00160     uInt numReceptors() const { return nrecp_p; }
00161     uInt feedId() const { return feedId_p; }
00162     Int antId() const { return antId_p; }
00163     Int spwId() const { return spwId_p; }
00164     Int beamId() const { return beamId_p; }
00165     Double time() const { return time_p; }
00166     Double interval() const { return intv_p; }
00167 
00168     uInt nrows(uInt nants) const { return ((antId_p < 0) ? nants : 1); }
00169 
00170     void setPolTypes(const String &types) {
00171         if (types.length() < nrecp_p) 
00172             throw AipsError(String("Insufficient no. of pols passed in '") 
00173                             + types + "'; expected " + nrecp_p + ", got " + 
00174                             types.length());
00175         pols_p = types;
00176     }
00177 
00178     const String& getPolTypes() const { return pols_p; }
00179 
00180     // set the Beam ID
00181     void setBeamID(Int id) { beamId_p = id; }
00182 
00183     Matrix<Double>& beamOffset() {
00184         if (! beamOff_p) beamOff_p = new Matrix<Double>(2, nrecp_p, 0.0);
00185         return *beamOff_p;
00186     }
00187 
00188     Matrix<Complex>& polResponse() {
00189         if (! polResp_p) {
00190             polResp_p = new Matrix<Complex>(nrecp_p, nrecp_p);
00191             polResp_p->diagonal() = Complex(1.0, 0.0);
00192         }
00193         return *polResp_p;
00194     }
00195 
00196     void setPosition(const MPosition &pos) { position_p = new MPosition(pos); }
00197 
00198     Vector<Double>& receptorAngle() {
00199         if (! angle_p) angle_p = new Vector<Double>(nrecp_p, 0.0);
00200         return *angle_p;
00201     }
00202     
00203     // get and set the row ID, the row of the first record with this feedID.  
00204     // An ID less than zero means that this record has not yet been recorded.
00205     // <group>
00206     Int getRow() const { return row_p; }
00207     void setRow(Int id) { row_p = id; }
00208     // </group>
00209 
00210     uInt write(MSFeed& msf, MSFeedColumns& msfc, uInt nant=0);
00211 
00212 protected:
00213     
00214 private:
00215     void deletePointers() {
00216         if (beamOff_p) { delete beamOff_p; beamOff_p = 0; }
00217         if (polResp_p) { delete polResp_p; polResp_p = 0; }
00218         if (position_p) { delete position_p; position_p = 0; }
00219         if (angle_p) { delete angle_p; angle_p = 0; }
00220     }
00221 
00222     uInt feedId_p, nrecp_p;
00223     Int antId_p, spwId_p, beamId_p, row_p;
00224     Double time_p, intv_p;
00225 
00226     String pols_p;
00227 
00228     MPosition *position_p;
00229     Matrix<Double> *beamOff_p;
00230     Matrix<Complex> *polResp_p;
00231     Vector<Double> *angle_p;
00232 };
00233 
00234 // <summary> a container for data destined for an MS FEED table </summary>
00235 
00236 // <use visibility=local>
00237 
00238 // <reviewed reviewer="" date="" tests="" demos="">
00239 
00240 // <prerequisite>
00241 //   <li> <linkto class="SimFeed">SimFeed</linkto>
00242 //   <li> <linkto class="SimTelescope">SimTelescope</linkto>
00243 // </prerequisite>
00244 //
00245 // <etymology>
00246 // This class holds a list of <linkto class="SimFeed">SimFeed</linkto> 
00247 // objects.
00248 // </etymology>
00249 //
00250 // <synopsis> 
00251 // This class holds a list of <linkto class="SimFeed">SimFeed</linkto> 
00252 // instances which, as a group, describes a spectrometer set-up (typical
00253 // of correlation spectrometers).  
00254 // When using this class, one does not create SimFeed objects directly,
00255 // but rather implicitly via the addFeed() function.
00256 // The ultimate purpose of this container is to support simulated 
00257 // observations.  Simulators would not normally create these objects 
00258 // directly but rather implicitly via the 
00259 // <linkto class="SimTelescope">SimTelescope</linkto> class.  <p>
00260 //
00261 // An important function handled by this class is the recording of the 
00262 // feed descriptions to a Measurement Set.  This is done with the flush()
00263 // function.  When it writes the data from a SimFeed in its list to the MS,
00264 // it sets the row number of the first feed record via setRow();
00265 // this is used as a flag indicating that the SimFeed as been flushed.  This
00266 // allows one to later add additional feeds to the list; when flush() is 
00267 // called again, only the new SimFeed data are written out.  This, of course, 
00268 // assumes that the same output MSFeed is passed to the flush() 
00269 // function each time.  If you want to write all the data to a new 
00270 // FEED table, you can call clearIds() to clear all the row 
00271 // markers.  <p>
00272 // 
00273 // A set of feeds can be read in from a FEED table as well using 
00274 // the initFrom() method or the SimFeedList(const MSFeed&, ...) 
00275 // constructor.  These will implicitly set the row markers from the input 
00276 // table.  This allows one to add new feeds to the already recorded set.
00277 // </synopsis> 
00278 //
00279 // <motivation>
00280 // This container provides an simplified in-memory representation of 
00281 // feeds that will ultimately be written to a FEED table.
00282 // The interface is oriented toward what is typical with current instruments
00283 // and thus is simpler than the interface provided by the MS FEED
00284 // table.
00285 // </motivation>
00286 //
00287 // <todo asof="03/03/25">
00288 //   <li> loading from an existing MS needs more testing.
00289 //   <li> It would probably be helpful to have a common base classes for 
00290 //        all Sim* and Sim*List classes that are managed by SimTelescope
00291 //        and SimObservations
00292 // </todo>
00293 class SimFeedList {
00294 public:
00295     // create an empty list
00296     SimFeedList(uInt initsz=2, uInt stepsz=4) 
00297         : n_p(0), chnk_p(stepsz), recs_p(initsz, 0) { }
00298 
00299     // create a copy of another list
00300     // <group>
00301     SimFeedList(const SimFeedList& f, uInt stepsz=4) 
00302         : n_p(0), chnk_p(stepsz), recs_p(f.recs_p.nelements(), 0) 
00303     {
00304         for(uInt i=0; i < recs_p.nelements(); i++)
00305             recs_p[i] = new SimFeed(*(f.recs_p[i]));
00306     }
00307     SimFeedList& operator=(const SimFeedList& f);
00308     // </group>
00309 
00310     // load the feeds described in the given FEED table
00311     SimFeedList(const MSFeed& fdt, uInt stepsz=4);
00312 
00313     virtual ~SimFeedList() { deleteRecs(); }
00314 
00315     // count the number of rows assuming a given number of antennae
00316     uInt countRows(uInt nants, Bool unflushed=False) const {
00317         uInt nrows = 0;
00318         for(uInt i=0; i < recs_p.nelements(); i++) {
00319             if (unflushed || recs_p[i]->getRow() >= 0) 
00320                 nrows += recs_p[i]->nrows(nants);
00321         }
00322         return nrows;
00323     }
00324 
00325     // return the number of feeds described in this list
00326     uInt numFeeds() const { return n_p; }
00327 
00328     // return True if all feeds have the same number of receptors on them
00329     Bool uniform() const {
00330         if (recs_p.nelements() == 0) return True;
00331         Bool nr = recs_p[0]->numReceptors();
00332         for(uInt i=1; i < recs_p.nelements(); i++) {
00333             if (nr != recs_p[i]->numReceptors()) return False;
00334         }
00335         return True;
00336     }
00337 
00338     // add a feed to this list.  nrecp is the number of receptors attached to 
00339     // the feed.  types lists polarizations for the receptors.  The length
00340     // of the string is equal to nrecp, and the values are taken from "RLXY".
00341     SimFeed& addFeed(uInt nrecp, String types) {
00342         SimFeed *out = new SimFeed(nrecp);
00343         out->setPolTypes(types);
00344         add(out);
00345         return *out;
00346     }
00347 
00348     // access the i-th SimFeed object in this list.  
00349     // <group>
00350     SimFeed& operator[](Int i) { return get(i); }
00351     const SimFeed& operator[](Int i) const { return get(i); }
00352     // </group>
00353 
00354     // reset all the row markers used to flag the SimFeed members that 
00355     // have been recorded to a Measurement Set already.  Thus, the next call 
00356     // to flush() will record all SimFeeds to the FEED table.  
00357     // This should be used when writing to a new FEED table, 
00358     // different from one previously read from or written to.  
00359     void clearIds() {
00360         for(uInt i=0; i < n_p; i++) 
00361             recs_p[i]->setRow(-1);
00362     }
00363 
00364     // add feed descriptions from a Measurement set 
00365     void initFrom(const MSFeed& fdt);
00366 
00367     // write out the FEED table assuming a given number of antennae
00368     // <group>
00369     uInt write(MSFeed &msf, uInt nants) const;
00370     uInt flush(MSFeed& msf, uInt nants=0) const;
00371     // </group>
00372 
00373 private:
00374     void deleteRecs() {
00375         for(uInt i=0; i < recs_p.nelements(); i++) {
00376             if (recs_p[i]) delete recs_p[i];
00377         }
00378     }
00379 
00380     SimFeed& get(Int i) const {
00381         if (i < 0 || i >= static_cast<Int>(n_p)) throwOutOfRange(n_p-1, i);
00382         return *(recs_p[i]);
00383     }
00384 
00385     void throwOutOfRange(uInt legallength, Int index) const;
00386 
00387     void add(SimFeed *feed) {
00388         if (n_p == recs_p.nelements()) {
00389             recs_p.resize(n_p+chnk_p);
00390             for(uInt i=n_p; i < recs_p.nelements(); i++) recs_p[i] = 0;
00391         }
00392         recs_p[n_p++] = feed;
00393     }
00394 
00395     uInt n_p, chnk_p;
00396     Block<SimFeed*> recs_p;
00397 };
00398 
00399 
00400 } //# NAMESPACE CASA - END
00401 
00402 #endif

Generated on Thu Aug 27 21:08:48 2009 for NRAOCASA by  doxygen 1.5.1