MirFiller.h

Go to the documentation of this file.
00001 //# MirFiller.h: defines the MirFiller class for filling Miriad data
00002 //# Copyright (C) 2000,2001,2002
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 //#
00027 //# $Id: MirFiller.h,v 1.2 2009/09/03 23:28:32 pteuben Exp $
00028 
00029 #ifndef BIMA_MIRFILLER_H
00030 #define BIMA_MIRFILLER_H
00031 
00032 #include <casa/Containers/List.h>
00033 #include <casa/Arrays/Vector.h>
00034 #include <casa/Arrays/Cube.h>
00035 #include <casa/Arrays/Matrix.h>
00036 #include <casa/Logging/LogIO.h>
00037 
00038 #include <miriad/Filling/MirVarHandler.h>
00039 #include <miriad/Filling/MirVisReader.h>
00040 
00041 #include <casa/namespace.h>
00042 //# Forward Declarations
00043 namespace casa { //# NAMESPACE CASA - BEGIN
00044 class Record;
00045 class String;
00046 class AipsError;
00047 class MeasurementSet;
00048 //class FillMetadata;
00049 //class GlishRecord;
00050 } //# NAMESPACE CASA - END
00051 
00052 class MirPol;
00053 class MirSource;
00054 class MirFreqSetup;
00055 class UnavailableMiriadDataSelectionError;
00056 
00057 class FillMetadata;
00058 
00059 // <summary>
00060 // BIMA MIRIAD dataset to MeasurementSet2 filler
00061 // </summary>
00062 // 
00063 // <use visibility=export>
00064 // 
00065 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
00066 // </reviewed>
00067 // 
00068 // <prerequisite>
00069 //   <li> <linkto class="Record">Record</linkto> -- for holding options
00070 // </prerequisite>
00071 //
00072 // <etymology>
00073 // MirFiller is the successor to the BimaFiller (class and application).  
00074 // It attempts to be more general in its filling of Miriad data while still 
00075 // retaining special functionality for BIMA data specifically.  
00076 // </etymology>
00077 //
00078 // <synopsis>
00079 // MirFiller converts an input Miriad dataset into an output MeasurementSet 
00080 // (ver. 2).  It is attached to its Miriad dataset at construction; it can 
00081 // subsequently be used to fill several output MSes, perhaps with different 
00082 // data from the input dataset, in sequence (i.e. it is not thread-safe).  
00083 //
00084 // Default use of this class would be to construct an instance attached to 
00085 // a Miriad dataset, and then call its <src>fill()</src> method, passing 
00086 // it the output measurement set name.  This will load all data found in 
00087 // the input dataset into the measurement set.  Restricting the filling to 
00088 // specific spectral windows can be controled via the <src>select()</src> 
00089 // function.  
00090 //
00091 // <h3>Miriad Dataset Spectral Layout and 
00092 // its Mapping to the Measurement Set</h3>
00093 // 
00094 // Each record in a Miriad dataset organizes its correlation data by
00095 // spectral windows and so-called wideband channels.  Each Miriad
00096 // spectral window contains data from a band of frequencies, broken up
00097 // into some number of channels.  (Because each channel, then, is
00098 // fairly narrow in bandwidth, these correlations are often referred
00099 // to as "narrow-band" data.)  The wideband channels, in general,
00100 // contain single correlations, averaged over some band at potentially
00101 // arbitrary frequencies; that is, they are bolometer-like
00102 // measurements.
00103 //
00104 // With BIMA Miriad datasets, the wideband channels are used to store
00105 // wide-band averages of the spectral windows.  More specifically, the
00106 // first wideband channel contains the average of all spectral windows
00107 // channels associated with the lower sideband (the first Nwin/2
00108 // windows), and the second wideband channel contains the average of
00109 // the upper sideband windows.  The remaining wideband channels
00110 // contain the averages of each of the spectral windows (in the same
00111 // order).  Thus, if the BIMA Miriad dataset contains Nwin spectral windows, 
00112 // there will be Nwin+2 wideband channels.  The first Nwin/2 windows will
00113 // be from the lower sideband, and the rest, from the upper sideband.  
00114 // 
00115 // When the Miriad data is converted to an MS, each spectral window and each 
00116 // wideband channel is loaded into a separate MS spectral window.  Thus, for
00117 // a BIMA dataset with Nwin windows, the output MS (by default) will contain 
00118 // Nwin*2+2 spectral windows.  The <src>select()</src> function can be used
00119 // to restrict the windows that get written.
00120 //
00121 // <h3>Polarization</h3>
00122 // 
00123 // Miriad datasets stores correlations for different polarizations in
00124 // separate records, even if they were observed simultaneously.
00125 // (Thus, it is up to the Miriad I/O software to properly combine
00126 // records to form new Stokes correlations.)  This is in contrast to
00127 // AIPS++ which can store polarizations observed at the same time in the 
00128 // same record.  Furthermore, BIMA can only observe one polarization at 
00129 // a time.  Thus, how polarizations should be loaded from a Miriad dataset
00130 // into an AIPS++ Measurment Set depends in part on whether the 
00131 // polarizations were (effectively) observed simultaneously.  It might 
00132 // also depend on whether polarization calibration is needed and how it 
00133 // should be done.  
00134 //
00135 // The standard recipe for handling raw BIMA polarization data calls for 
00136 // the sampling of the polarizations to be loaded into separate records.  
00137 // This makes time-based editing easier.  Once the polarization gains are
00138 // applied, one usually time-averages the data over several polarization
00139 // switching cycles; in effect, then, one can consider the polarizations 
00140 // as having been observed simultaneously.  Thus, in this time-averaging
00141 // step, one collapses the different polarizations into single records for
00142 // standard handling by the imaging tools.  (Note: the software to support 
00143 // this operation is still in development as of this writing.)
00144 //
00145 // The "joinpol" option (set with setOptions()) allows one to control 
00146 // whether an attempt is made to load polarizations into the same record.  
00147 // If joinpol is false, all polarizations are loaded into different records;
00148 // each record will point to a different polarization setup in the 
00149 // POLARIZATION table (with each setup containing only one correlation type).
00150 // If joinpol is true, then fill() will look for polarizations with the same 
00151 // time stamp and load them into the same record; the POLARIZATION table will
00152 // then only have one setup containing all correlations.  Any polarizations 
00153 // that are not found are set to zero.  Thus, for a raw BIMA data 
00154 // containing multiple polarizations, joinpol equal to true will produce a
00155 // much large dataset than joinpol equal to false because of all the extra
00156 // zero visibilities that get loaded in.  
00157 // </synopsis>
00158 //
00159 // <example>
00160 // <srcblock>
00161 //    // open Miriad dataset 3c273 for filling
00162 //    MirFiller filler('3c273');
00163 //
00164 //    // if needed, set some options
00165 //    Record opts = filler.getOptions();
00166 //    RecordFieldPtr<Double>(opts, "scanlim").define(600);
00167 //    RecordFieldPtr<Bool>(opts, "verbose").define(True);
00168 //    filler.setOptions(opts);
00169 //
00170 //    // if desired, chose the windows to write
00171 //    Vector<Int> wide(0)    // do not write out any wideband channels
00172 //    Vector<Int> splwin(filler.nspect());
00173 //    for(Int i=0; i < splwin.nelements(); i++) splwin(i) = i;
00174 //    filler.select(wide, splwin);
00175 //
00176 //    // fill the output MS
00177 //    filler.fill('3c273.ms');
00178 // </srcblock>
00179 // </example>
00180 //
00181 // <motivation>
00182 // The important features of this class are:
00183 // <ul>
00184 //    <li> Input spectral windows are loaded into separate output windows.
00185 //         This allows windows to have different rest frequencies associated
00186 //         with them.  It also allows channels within a window to be 
00187 //         contiguous in frequency and having the same width.
00188 //    <li> Wideband channels are each placed in their own window.  This is 
00189 //         particularly important for the sideband averages, which are used
00190 //         to calculate the G-Jones which can be applied to the spectral 
00191 //         windows.
00192 //    <li> Associations are set to connect spectral windows and their averages.
00193 //         This allows the averages to be recalculated if necessary (e.g.
00194 //         after flagging).
00195 //    <li> Different polarizations are by default loaded into separate 
00196 //         records as is appropriate for raw BIMA data; however, if 
00197 //         simultaneously measured polarizations exist, an option can be
00198 //         set to join them into a single record.  
00199 // </ul>
00200 // </motivation>
00201 //
00202 // <thrown>
00203 //    <li> <linkto class="AipsError">AipsError</linkto> -- if the input
00204 //         dataset is not in Miriad format or cannot be opened.
00205 //    <li> <linkto class="MiriadFormatError">MiriadFormatError</linkto>
00206 //         -- if an illegal format condition is found in the input
00207 //         Miriad dataset.
00208 //    <li> <linkto class="UnavailableMiriadDataSelectionError">
00209 //         UnavailableMiriadDataSelectionError</linkto> -- if the data
00210 //         selection is known to be out of range.
00211 // </thrown>
00212 //
00213 // <todo asof="2001/03/01">
00214 //   <li> load planet source models
00215 //   <li> a splitWindows option may be needed
00216 //   <li> a more sophisticated handling of multiple polarization setups
00217 //        may be needed
00218 //   <li> system temperatures are currently loaded into the SYSCAL as 
00219 //        single-element arrays, regardless of the "official" number of 
00220 //        polarization receptors.  This is not strictly in compliance with 
00221 //        the MS2 spec, so it should be fixed.
00222 //   <li> change getOptions() interface to get output from user (?)
00223 // </todo>
00224 
00225 class MirFiller : public MirVarHandler {
00226 private:
00227     uInt debug;  // debugging level
00228 
00229 public:
00230 
00231     // create the filler, attaching it to a Miriad dataset.  <src>mirfile</src>
00232     // is the dataset filename, and <src>dbg</src> is the debug level (see 
00233     // <linkto class="MirFiller:setDebug"><src>setDebugLevel()</src></linkto>).
00234     MirFiller(const String& mirfile, Bool scan=True, Int dbg=0);
00235 
00236     // destruct this filler
00237     virtual ~MirFiller();
00238 
00239     // set the debugging level which controls the amount of debugging 
00240     // messages that are printed to the terminal (as opposed to the logger).  
00241     // A value of zero or less will cause no extra messages to be printed; 
00242     // increasing values will increase the amount of messages.
00243     void setDebugLevel(Int level) { 
00244         debug = (level < 0) ? 0 : (uInt) level; 
00245         rdr_p.setDebugLevel(debug);
00246     }
00247 
00248     // set the debugging level which controls the amount of debugging 
00249     // messages that are printed to the terminal.  A value of zero or less 
00250     // means that no extra messages will be printed; increasing values will 
00251     // increase the amount of messages.
00252     Int getDebugLevel() const { return debug; }
00253 
00254     // return true if the debugging level is at least as high as a given 
00255     // level.
00256     Bool Debug(Int level) { return (((uInt) level) <= debug); }
00257 
00258     // return true if this filler should be verbose in its messages.  This
00259     // will be true if the verbose option is enabled or the debug level is
00260     // greater than 1.
00261     Bool verbose() { return (verbose_p || debug > 1); }
00262 
00263     // return basic characteristics of the input dataset as a GlishRecord.  If
00264     // scan is True (the default), the entire file will be (re-) scanned 
00265     // using the current values for the obslim and scanlim options.
00266     // If verbose is true (the 
00267     // default), send a description to the logger.
00268     //GlishRecord summary(Bool verbose=True, Bool scan=True);
00269 
00270     // fill the output MS according to the current selections and options
00271     // msfile is the output name to use; it should not already exist.
00272     void fill(const String& msfile) {
00273         if (joinpol_p) 
00274             joinFill(msfile);
00275         else 
00276             noJoinFill(msfile);
00277     }
00278 
00279     // select spectral data from the input Miriad dataset.  wideChans is a 
00280     // list of one-based channel indices.  narrowWins is a list of one-based
00281     // window indices.  The default is to choose all available wide channels
00282     // and windows.  polsel is a polarization selection: only the correlation
00283     // types present will be loaded; a NULL value means take all polarizations
00284     // found.  (See also the joinpol option under setOptions().)
00285     void selectSpectra(const Vector<Int>& wideChans, 
00286                        const Vector<Int>& narrowWins);
00287 //      throw(UnavailableMiriadDataSelectionError);
00288 
00289     // select the polarizations to load.  An empty setup means by default 
00290     // take all polarizations found in the dataset.
00291     void selectPols(ConstMirPolSetup &polsel);
00292 
00293     // set the options for filling.  The options are set via a Record object
00294     // for which the following keys are recognized:
00295     // <pre>
00296     // scanlim  the scan time jump limit, in seconds.  If the jump in
00297     //          time between two consecutive Miriad records is greater 
00298     //          than this limit the scan number that gets written out
00299     //          for that record will be incremented.  A change in source
00300     //          will always increment the scan number unless scanlim is
00301     //          negative; in this case, all records are forced to have
00302     //          the same scan number.  The default is 5 minutes.
00303     // 
00304     // obslim   the observation ID time jump limit, in seconds.  The 
00305     //          observation ID is meant to delimit two tracks that might
00306     //          appear in the same file.  If the jump in time 
00307     //          between two consecutive Miriad records is greater than 
00308     //          this limit the scan number that gets written out for 
00309     //          that record will be incremented.  The ID will always be
00310     //          incremented if there is a change in telescope or array
00311     //          configuration unless obslim is negative, in which case,
00312     //          all records will be forced to have the same observation
00313     //          ID.  The default is 4 hours.
00314     // 
00315     // tilesize the tiling size to use (in channels?) for storing data
00316     //          in the MS using the TiledStorageManager.  If the value 
00317     //          is <= 0, the standard (non-tiled) storage manager will
00318     //          be used.  The default is 32.
00319     // 
00320     // wideconv the convention to use for interpreting the wideband channels.
00321     //          The allowed values are "bima" and "none".  In the "bima" 
00322     //          convention, the first two wideband channels are the lower & 
00323     //          upper sideband averages and the remaining channels represent 
00324     //          averages of each of the spectral line windows.  Currently,
00325     //          this option only affects the writing out of window 
00326     //          associations: if wideconv="bima", the associations linking 
00327     //          wideband windows to spectral line windows will be written
00328     //          according to the convention.  
00329     // 
00330     // joinpol  If true, multiple polarizations are loaded as a single 
00331     //          polarization setup.  Which polarizations are included
00332     //          depend on the polarization selections.  If false (the 
00333     //          default), each polarization is loaded as a separate setup.
00334     // 
00335     // tsyswt   If true (the default), the SIGMA and WEIGHT columns will
00336     //          be filled with values based on the system temperatures, if 
00337     //          found.  If false, these columns will be filled with values=1.
00338     //          The SYSCAL table will be filled if system temperatures are
00339     //          present, regardless of the value of this option.
00340     //
00341     // planetfit  The maximum fit order to use when fitting the direction of a 
00342     //          planet-tracking field.  The actual order used may be less than
00343     //          this if there is insufficient data.  The default is 3.
00344         // updmodelint  This is the amount of time to wait before updating the
00345         //              model.  By default this is 8 hours.
00346     //
00347     // movfield if true, exact field positions tracking a moving object will
00348     //          be written to subtable called BIMA_MOVING_FIELDS.
00349     //
00350     // compress if true, selected columns will be compressed using scaled
00351     //          integers.  This limits the dynamic range to about 65000:1.
00352     //          The default is true.
00353     //
00354     // verbose  if true, send extra messages to the logger
00355     // </pre>
00356     void setOptions(const Record &opts);
00357 
00358     // get the current filling options
00359     Record getOptions();
00360 
00361     // handle an update to the integration time; 
00362     // this is a callback routine that is part of the MirVarHandler 
00363     // interface which must be implemented.  This implementation does
00364     // nothing.
00365     virtual void updateIntTime(FillMetadata &fm, Double time);
00366 
00367     // handle an update to the observatory; 
00368     // this is a callback routine that is part of the MirVarHandler 
00369     // interface which must be implemented.  This implementation flushes
00370     // records for the FEED subtable for the last observatory, and adds
00371     // a PROCESSOR subtable record for the next table.
00372     virtual void updateObservatory(FillMetadata &fm, Double time);
00373 
00374     // handle an update to the array configuration; 
00375     // this is a callback routine that is part of the MirVarHandler 
00376     // interface which must be implemented
00377     virtual void updateArray(FillMetadata &fm, Double time);
00378 
00379         // handle an update to the SOURCE_MODEL column of the SOURCE subtable.
00380         // Maybe that this gets incorporated into updateSource at sometime, have
00381         // to examine logistics.  REWRITEME. dgoscha
00382     virtual void updateSourceModel(FillMetadata &fm, Double time);
00383 
00384     // handle an update to the array configuration; 
00385     // this is a callback routine that is part of the MirVarHandler 
00386     // interface which must be implemented
00387     virtual void updatePolSetup(FillMetadata &fm, Double time);
00388 
00389     // handle an update to the source; 
00390     // this is a callback routine that is part of the MirVarHandler 
00391     // interface which must be implemented
00392     virtual void updateSource(FillMetadata &fm, Double time);
00393 
00394     // handle an update to the observing field; 
00395     // this is a callback routine that is part of the MirVarHandler 
00396     // interface which must be implemented
00397     virtual void updateField(FillMetadata &fm, Double time);
00398 
00399     // handle an update to the frequency setup; 
00400     // this is a callback routine that is part of the MirVarHandler 
00401     // interface which must be implemented
00402     virtual void updateFreqSetup(FillMetadata &fm, Double time);
00403 
00404     // handle an update to system temperatures
00405     // this is a callback routine that is part of the MirVarHandler 
00406     // interface which must be implemented
00407     virtual void updateTsys(FillMetadata &fm, Double time);
00408 
00409 private:
00410 
00411     // open and setup the output MS.  This includes all initialization that 
00412     // can be done without reading any data from the input Miriad dataset.
00413     MeasurementSet *setupMS(const String& msfile, Int tileSize=0,
00414                             Bool needSrcModel=True);
00415 
00416     // initialize the output MS.  This is called after the first input record 
00417     // is read in from the input Miriad dataset.  It will initialize certain
00418     // subtables (currently, POINTING, PROCESSOR, HISTORY, FEED, and 
00419     // POLARIZATION) based on static or otherwise non-tracked variable 
00420     // information.
00421     void initMS(::FillMetadata& fm);
00422 
00423     void noJoinFill(const String& msfile);
00424     void joinFill(const String& msfile);
00425 
00426     Bool nearAbs(Double a, Double b, Double tol) {
00427         return (abs(a-b) < tol);
00428     }
00429 
00430     // add the current observation information as a new record to the
00431     // output ms's OBSERVATION subtable
00432     void flushObsRecord(FillMetadata& fm, Double time);
00433 
00434     // add the records to the FEED subtable for the current set of antennas
00435     // and polarizations
00436     void flushFeedRecords(FillMetadata& fm, Double time);
00437 
00438     // check for moving objects in source list and adjust FIELD subtable
00439     // accordingly
00440     void flushMovingFields(FillMetadata& fm, Double time);
00441 
00442     // add the records to the POINTING subtable for the current set of antennas
00443     void flushPointingRecords(FillMetadata& fm, Double time);
00444 
00445     // add a new set of antenna positions
00446     void addAntennaPositions(FillMetadata &fm, Double time);
00447 
00448     // add the current source to the SOURCE subtable
00449     uInt addSource(FillMetadata &fm, double time);
00450 
00451     // add the current field to the FIELD subtable
00452     void addField(FillMetadata &fm, double time);
00453 
00454     // add subtable records for the current correlator setup
00455     void addCorrelatorSetup(FillMetadata &fm, double time);
00456 
00457     // add a POLARIZATION record for the current polarization type.
00458     void addPolarization(FillMetadata &fm, Bool addCurrentOnly=False);
00459 
00460     // add DATA_DESCRIPTION records for the current polarization
00461     // and frequency setup
00462     void addDataDesc(FillMetadata &fm);
00463 
00464     // write out the miriad history into the HISTORY table
00465     void flushHistory(FillMetadata &fm);
00466 
00467     // copy the history from a given HISTORY table
00468     void copyHistoryFrom(FillMetadata &fm, String tablename);
00469 
00470     // add a processor record for the current frequency setup
00471     void addProcessor(FillMetadata &fm);
00472 
00473     // add a filler message to the HISTORY table
00474     void addHistoryMessage(FillMetadata &fm, String priority, 
00475                            String origin, String msg);
00476 
00477     // add a record to the SysCal table
00478     void addTsysRecords(FillMetadata &fm, Double time, Cube<Float>& tsys);
00479 
00480     // initialize the STATE table
00481     void initState(FillMetadata &fm);
00482 
00483     // create a polynomial fit for the direction to a moving source 
00484     //PJT
00485     Bool fitskymotion(Matrix<Double> &dirfit, const Vector<Double> &time, 
00486                       const Vector<Double> &ra, const Vector<Double> &dec);
00487 
00488     // info that doesn't change during life of filler
00489     MirVisReader rdr_p;
00490     LogIO log_p;
00491 
00492     // selection info
00493     Vector<Bool> widesel_p, winsel_p;
00494     Int nwinsel_p, nwidesel_p;
00495     ConstMirPolSetup *defpolsel_p;
00496 
00497     // options
00498     String histbl_p;
00499     Double scanlim_p, obslim_p;
00500     Int tilesize_p, planetfit_p;
00501     Bool verbose_p, joinpol_p, tsyswt_p, movfield_p, compress_p;
00502 
00503     enum wideConventions { NONE=0, BIMA, MIRIAD, NCONV };
00504     static String wideconvnames[];
00505     wideConventions wideconv_p;
00506 
00507     Double updmodelint_p;
00508 };
00509 
00510 
00511 #endif
00512 
00513 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1