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
1.5.1