casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
MSAsRaster.h
Go to the documentation of this file.
00001 //# MSAsRaster.h: DisplayData (drawing layer) for raster displays of an MS
00002 //# Copyright (C) 2000,2001,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 //#
00027 //# $Id$
00028 
00029 #ifndef TRIALDISPLAY_MSASRASTER_H
00030 #define TRIALDISPLAY_MSASRASTER_H
00031 
00032 
00033 #include <casa/aips.h>
00034 #include <display/DisplayDatas/ActiveCaching2dDD.h>
00035 #include <ms/MeasurementSets.h>
00036 #include <images/Images/PagedImage.h>
00037 #include <casa/Arrays/Vector.h>
00038 #include <casa/Quanta/Unit.h>
00039 #include <casa/BasicSL/String.h>
00040 #include <display/Display/DParameterChoice.h>
00041 #include <display/Display/DParameterRange.h>
00042 #include <display/Display/DParameterString.h>
00043 #include <display/Display/DParameterButton.h>
00044 #include <display/DisplayCanvas/WCPowerScaleHandler.h>
00045 #include <synthesis/MSVis/VisibilityIterator.h>
00046 #include <display/DisplayDatas/WorldAxesDD.h>
00047 #include <display/Display/DisplayEnums.h>
00048 #include <display/Display/WorldCanvasHolder.h>
00049 #include <display/DisplayDatas/CachingDisplayMethod.h>
00050 #include <display/DisplayDatas/DisplayDataOptions.h>
00051 #include <display/Display/Colormap.h>
00052 #include <display/region/Region.qo.h>
00053 
00054 namespace casa { //# NAMESPACE CASA - BEGIN
00055 
00056 class MSAsRasterDM;
00057 
00058 
00059 // <summary>
00060 // Class for displaying data within an MS as a raster (gridded) image.
00061 // </summary>
00062 
00063 // <prerequisite>
00064 //   <li> CachingDisplayData
00065 //   <li> WorldCanvas[Holder]
00066 //   <li> MeasurementSet
00067 //   <li> CoordinateSystem
00068 //   <li> Array
00069 // </prerequisite>
00070 
00071 // <etymology>
00072 // "MSAsRaster" is a implementation of a <linkto class=ActiveCaching2dDD>
00073 // ActiveCaching2dDD </linkto> which provides for the display of Measurement 
00074 // Set data (visibilities) as a raster image.
00075 // </etymology>
00076 
00077 // <synopsis>
00078 // MSAsRaster displays Measurement Set data which can be presented as a
00079 // regular grid, on a WorldCanvas (data which is sparse and
00080 // irregular on its display axes would typically be plotted using MSAsXY
00081 // instead).  Display or iteration axes include time, baseline,
00082 // channels and polarizations.  Visibilities of the selected slice are drawn
00083 // as a Raster image.
00084 //
00085 // Unlike many DDs, MSAsRaster has _two_ levels of underlying data: the source 
00086 // MS, and a hypercube of visibility data, which is extracted from the MS and
00087 // gridded onto 5 main axes: time, baseline, spectral window, frequency and
00088 // polarization.  Extracting the data is a more time-consuming operation 
00089 // than display of various portions of gridded data, and is triggered only
00090 // through the extract_() method.  Data selection options do not take effect 
00091 // until triggered in this way.  In contrast, many options affecting display
00092 // of the extracted data (such as zooms, and colormapping) affect
00093 // the display immediately, as with most DDs.  Setting new display axes will 
00094 // trigger extract_() if the current extracted hypercube does not fill them.
00095 //
00096 // </synopsis>
00097 
00098 // <example>
00099 // <srcblock>
00100 //    MSAsRaster *mar = new MSAsRaster("filename_of.ms");
00101 //    wcHolder->addDisplayData(mar);
00102 // </srcblock>
00103 // </example>
00104 //
00105 // <motivation>
00106 // To move compute-intensive tasks of data handling
00107 // for Measurement Set display out of glish into C++
00108 // </motivation>
00109 
00110 // <todo asof="2001/02/01">
00111 //
00112 // The current user interface for triggering extract_ is the 'Apply' button,
00113 // which is detected internally when setOptions() is called with more than
00114 // one user option field to be updated.  This is not entirely satisfactory;
00115 // User interface could use improvement.
00116 //
00117 // Major items among other things left to to:
00118 //
00119 // * MS Selection and averaging.
00120 //
00121 // * World coordinates in axis labelling, position tracking and slice
00122 //   selection
00123 //
00124 // * Alternative orderings, especially along baseline and time axes
00125 //
00126 // </todo>
00127 
00128 class MSAsRaster: public ActiveCaching2dDD {
00129 
00130  public:
00131 
00132   // constructor
00133   // from the filename of an MS
00134   MSAsRaster( const String msname, const viewer::DisplayDataOptions &ddo );
00135 
00136   //# from an MS object
00137   //# MSAsRaster(MeasurementSet* ms);
00138   //#unneeded?--prefer to control permissions...
00139 
00140   // Destructor
00141   virtual ~MSAsRaster();
00142 
00143 
00144   // Apply option values stored in <src>rec</src> to the DisplayData.  A
00145   // return value of <src>True</src> means a refresh is needed.
00146   // <src>recOut</src> contains any fields which were implicitly 
00147   // changed as a result of the call to this function.  
00148   // Parameters from the 'adjust' gui are sent through here,
00149   // controlling and triggering many of
00150   // MSAsRaster's actions.  (Other input is via the mouse on the
00151   // canvas, which affects the object through the event handlers).
00152   virtual Bool setOptions(Record &rec, Record &recOut);
00153 
00154   // Retrieve the current options.  In addition to the values themselves, the
00155   // returned record contains meta-information (prompts, help text,
00156   // choices, defaults, etc.) useful in constructing gui elements to
00157   // control the DD settings.
00158   // Note: If the user interface is to be zero-based, you should call
00159   // setUIBase(0) _before_ using this routine -- see setUIBase().
00160   virtual Record getOptions();
00161 
00162   // set all options to default values (unused so far; incomplete
00163   // support in base classes...incomplete here as well).
00164   virtual void setDefaultOptions();
00165 
00166 
00167   // Return the current options of this DisplayData as a 'restrictions'
00168   // AttributeBuffer (only options that affect the way the image would
00169   // be drawn are returned).  It is used to determine which (if any) of
00170   // the cached drawings can be used to satisfy the current draw request.
00171   virtual AttributeBuffer optionsAsAttributes();
00172 
00173 
00174   // Determine whether DD is compatible with the WC[H]'s current
00175   // world coordinates.  MSAsRaster DDs must be in charge (the CS master),
00176   // Otherwise they will not respond.  Multiple MSARs on one canvas
00177   // (blinking, etc.) is not supported, because of possible confusion
00178   // about which one(s) should respond to flagging edits.
00179   virtual Bool conformsToCS(const WorldCanvas& wc) {
00180     csConformed_ = wc.isCSmaster(this);
00181     return csConformed_;  }
00182 
00183   // Format the data value at the given world position.
00184   // Call setActiveImage(zindex) with the desired animator position
00185   // before calling this routine.
00186   virtual String showValue(const Vector<Double> &world);
00187 
00188   // Format the position of the cursor.  Also requires previous call to
00189   // setActiveImage(zindex); also used for position tracking.
00190   virtual String showPosition(const Vector<Double> &world,
00191                               const Bool &displayAxesOnly = False);
00192   bool showPosition( viewer::RegionInfo::stats_t &stat_list, const Vector<Double> &world,
00193                      const Bool& displayAxesOnly = False);
00194 
00195   // get the Unit for displayed data values (visibilities)
00196   virtual const Unit dataUnit() const;
00197   const IPosition dataShape() const { return IPosition( ); }
00198   const uInt dataDim() const { return 0; }
00199   std::vector<int> displayAxes( ) const { return std::vector<int>( ); }
00200 
00201 
00202   // Return the type of this DisplayData.
00203   virtual Display::DisplayDataType classType()
00204     { return Display::Raster; }
00205   // Pure virtual function from DisplayData...
00206   String dataType() const { return "ms"; }
00207 
00208 
00209   // return the size of the animation axis.
00210   // <group>
00211   virtual const uInt nelements() const {
00212         return msShape_[axisOn_(Z)];  }
00213   virtual const uInt nelements(const WorldCanvasHolder &) const {
00214         return msShape_[axisOn_(Z)];  }
00215   // </group>
00216 
00217   // Handle axis labelling.
00218   virtual Bool labelAxes(const WCRefreshEvent &ev);
00219 
00220   // Needed to enable or destroy drawlists and colormaps on corresp. canvas.
00221   // (Only to be called by the relevant WCH).
00222   // <group>
00223   virtual void notifyRegister(WorldCanvasHolder *wch) ;
00224   virtual void notifyUnregister(WorldCanvasHolder& wch,
00225                                 Bool ignoreRefresh = False) ;
00226   // </group>
00227 
00228   // handle flagging region selection events, via new-style (1/02)
00229   // interface.
00230   virtual void handleEvent(DisplayEvent& ev);
00231   
00232   // Return the animator position setting preferred if this DD
00233   // about to be registered on a new DisplayPanel.
00234   virtual Bool zIndexHint(Int& preferredZIndex) const;
00235 
00236   // Empty cache completely.
00237   virtual void purgeCache() {
00238     ActiveCaching2dDD::purgeCache();
00239     itsAxisLabeller.purgeCache();  }            //# (include our labeller)
00240 
00241   // Empty cache of all DMs for a given WCH.
00242   virtual void purgeCache(const WorldCanvasHolder& wch) {
00243     ActiveCaching2dDD::purgeCache(wch);
00244     itsAxisLabeller.purgeCache(wch);  }         //# (include our labeller)
00245 
00246   // DD 'Absolute Pixel Coordinates', e.g. channel numbers, are internally
00247   // 0-based (they begin numbering at 0), but certain external user-interface
00248   // methods (e.g. showPosition(), used for position tracking) have
00249   // produced 1-based output traditionally for the glish-based viewer.
00250   // uiBase_, and related methods uiBase() and setUIBase(), allow newer
00251   // (python/Qt-based) code to cause external ui functions like showValue()
00252   // to report 0-based values instead.  Unless setUIBase(0) is called, the
00253   // traditional 1-based reporting behavior is retained by default.
00254   // For this DD, in addition to tracking, this setting affects labelling,
00255   // slider-based position setting, and MS selection on Field or Sp. Window.
00256   //
00257   // If you are using 0-basing in the user interface, you should call
00258   // setUIBase(0) right after constructing this DisplayData, before other
00259   // user interface operations such as getOptions(); the method has not
00260   // been tested other than for a one-time setUIBase(0) call directly after
00261   // DD construction.
00262   virtual void setUIBase(Int uibase) {
00263     Int oldUIBase = uiBase();
00264     ActiveCaching2dDD::setUIBase(uibase);
00265     if(oldUIBase != uiBase()) {
00266       setCS_();         // fixes axis labelling, among other things...
00267       purgeCache();  }  }
00268         // In case it helps; the method should probably be called
00269         // only before we've had a chance to cache anything though....
00270 
00271 
00272 
00273   virtual const String &name( ) const { return msName_; }
00274 
00275   // added to allow flagging control from mouse tools... <drs>
00276   bool flag( WorldCanvas *wc, double blc_x, double blc_y, double trc_x, double trc_y );
00277 
00278  protected:
00279 
00280   // This routine is called to inform the DD of the current canvas's
00281   // animator index.  Used by confromsTo() and related methods.
00282   // Return value indicates whether the index is within the data's range.
00283   virtual Bool setActiveZIndex_(Int zindex) {
00284     activeZIndex_ = zindex;
00285         // activeZIndex_ and zIndexConformed_ protected on the DD
00286         // base level; they are intended to be set only by these
00287         // [protected] setActiveZIndex_() methods, which are in turn
00288         // called by DD::conformsToZIndex().
00289     zIndexConformed_ = ( activeZIndex_>=0 && activeZIndex_<Int(nelements()) );
00290     return zIndexConformed_;  }
00291 
00292   // Construct and destroy the user option DisplayParameters.
00293   // To be used by constructors/destructor only.
00294   // <group>
00295   void constructParameters_();
00296   void deleteParameters_();
00297   // </group>
00298 
00299   // return a new MSAsRasterDM for the given WorldCanvas.
00300   virtual CachingDisplayMethod *newDisplayMethod(WorldCanvas *worldCanvas,
00301                                          AttributeBuffer *wchAttributes,
00302                                          AttributeBuffer *ddAttributes,
00303                                          CachingDisplayData *dd);
00304 
00305   // Helper functions.
00306   //# gcc-3.4.2 cannot distinguish between the 2 functions in complex.
00307   // <group>
00308   static Float real (const Complex& val)
00309     { return val.real(); }
00310   static Float imag (const Complex& val)
00311     { return val.imag(); }
00312   // </group>
00313 
00314  private:
00315 
00316 
00317   // Constructs position information for non-deviation display
00318   // state averaging...
00319   String avgPos( const String &dim, int v );
00320 
00321   // The (multiple) DMs which this DD creates just hold drawlist handles.
00322   // They send the actual drawing chores back to MSAsRaster::draw_().
00323   // The friend designation is so that draw_() can be made private.
00324   friend class MSAsRasterDM;
00325 
00326   // Default and copy constructors, and the assignment operator, are 
00327   // non-functional and should not be used.  Do not make copies of
00328   // DisplayData objects, or pass them by value;
00329   // use references or pointers instead.
00330   // <group>
00331   MSAsRaster(): mspos_(this) {  }
00332   MSAsRaster(const MSAsRaster &other): ActiveCaching2dDD(other), mspos_(this) {  }
00333   MSAsRaster& operator=(const MSAsRaster &/*other*/) { return *this;  }
00334   // </group>
00335 
00336   // Initialization common to all useful constructors
00337   void initMSAR_( const viewer::DisplayDataOptions &ddo );
00338 
00339   // set/restore default option values on this level only.  (Not implemented).
00340   void setDefaultMSAROptions_();
00341 
00342 
00343   //#-------------------------------------------------------------------
00344   //# The Workhorses--steps in producing the display from the MS and the
00345   //# the user input settings.  (Most of the control logic is elsewhere).
00346 
00347   // prepare the selection MS and its VisSet.
00348   void selectVS_( const viewer::DisplayDataOptions &ddo=viewer::DisplayDataOptions( ) );
00349 
00350   // find the ranges of the MS selection (VisSet) for the 5 hypercube axes
00351   void findRanges_();
00352 
00353   // update/set the (2d--canvas) coordinate system from the current MS
00354   // selection and display axes.
00355   void setCS_();
00356 
00357   // Extract the hypercube buffer of visibilities for the requested
00358   // MS selection and axis settings (the most time-consuming operation).
00359   void extract_();
00360 
00361   // retrieve (2D) slice data Matrix, and corresponding mask/flag
00362   // matrices, to send to the display canvas.
00363   void createDisplaySlice_();
00364 
00365   // Actually do the drawing.
00366   // The return value indicates whether the DD was able to draw.
00367   Bool draw_(Display::RefreshReason reason,
00368              WorldCanvasHolder &wch, WorldCanvas &wc);
00369 
00370 
00371              
00372   //#------baseline reordering routines-------------------------------------
00373   
00374   // Called from findRanges_(), computes translation matrices between
00375   // antenna1,antenna2 and baseline index  (a1A_, a2A_, a1L_, a2L_,
00376   // bslA_, bslL_).
00377   void computeBaselineSorts_();
00378 
00379     
00380   // Set the baseline index translation Arrays a1_, a2_ and bsl_ by
00381   // copying as appropriate according to the current sort.  (Source Arrays
00382   // should already have been created by computeBaselineSorts_(), above).
00383   // also sets total number of baselines, nbsl_, which becomes
00384   // msShape_[BASELN] except in single dish case.
00385   void setBslSort_();
00386 
00387 
00388   // Shuffle vis_ into new baseline order, per user request for sort change.
00389   // (Information needed to do this should already have been set up by
00390   // the previous two routines).
00391   void reSortVis_();
00392   
00393   
00394   
00395   //#-----small helper routines.-----------------------------------------
00396 
00397   // Return baseline index (for the ant1-ant2 sort _only_) from
00398   // antenna numbers.  Input must have 0 <= a1 <= a2 < nAnt_.
00399   // Mapping leaves room for autocorrelations plus a 1-pixel gap between
00400   // successive antenna1 groups.
00401   //
00402   //# (Crude--needs improvement:  *Wasteful if some antennas have ANTENNA
00403   //# table entries but don't appear in the visibility data.  *The gaps
00404   //# really should appear only in the final display Matrix, when needed.
00405   //# *Slots for autocorrs should also be inserted only if the selected
00406   //# data includes them.  *Other baseline ordering options should exist).
00407   Int bsln_(Int a1, Int a2) const {
00408     return a1*(nAnt_+2) - a1*(a1+1)/2 + a2-a1;  }
00409 
00410   // A corresponding inverse, this handles non-integer 'baseline indices'.
00411   // Set abase to 1 to number ant1 and ant2 from 1.  (The baseline index
00412   // bsl is always numbered from 0, internally).  The version with the
00413   // Double return value returns a1 + a2/a1mult_() (for labelling --
00414   // example: for baseline index corresp. to 13-24, returns 13.024).
00415   // <group>
00416   void a1a2_(Double& a1, Double& a2,  Double bsl, Int abase=0) const;
00417   Double a1a2_(Double bsl, Int abase=0);
00418   // </group>
00419 
00420   // Subsidiary routine for above, determines (in effect) how many decimal
00421   // places are needed for an antenna number (including one leading zero). 
00422   // Returns 1000 for 10-99 antennas, 10000 for 100-999 antennas, etc.
00423   Double a1mult_() { 
00424     Double m=10.; 
00425     while(m <= nAnt_-1+uiBase()) m*=10.; 
00426     return 10*m;  }
00427 
00428   
00429   // A small routine to return the label for the "Visibility Memory"
00430   // slider widget.  The label includes feedback on the selected MS's
00431   // total size, and is updated when that changes.
00432   String visMbLabel_();
00433 
00434   
00435   // Reset Block of relevant Spectral window IDs, and return
00436   // correponding Vectors of channel frequencies.  freq_ is used for display
00437   // of frequencies in position tracking.  spwId_ translates spw 'index'
00438   // into the actual spectral window ID.
00439   void resetFreq_() {
00440     for(uInt s=0; s<freq_.nelements(); s++) {
00441       delete static_cast<Vector<Double>*>(freq_[s]);  }
00442     freq_.resize(0, True);
00443     spwId_.resize(0, True);  }
00444     
00445   // Translate actual spectral window ID into the 'spw' index (zero-based
00446   // pixel coordinate) along the spectral window axis.  Because the
00447   // user can select specific spectral windows, these two may not be the same.
00448   // Returns -1 if the spectral window ID is not in the selected MS data.
00449   Int spw_(Int spwid) {
00450     Int nspw=spwId_.nelements();
00451     for(Int spw=0; spw<nspw; spw++) if(spwId_[spw]==spwid) return spw;
00452     return -1;  }
00453 
00454   // Compute vis_ array dimensions which fit into allowed memory.
00455   // visShpA is the actual shape to be allocated to vis_; visShp is the
00456   // portion which will actually be used at present; it may be smaller on the
00457   // BASELN axis if baselines are currently sorted by length (no 'gaps').
00458   void computeVisShape_(Block<Int>& visShp, Block<Int>& visShpA);
00459 
00460   // Return how many of the given (sorted) animation frames
00461   // can be displayed from a given window (strtfrm, nfrms) on that axis.
00462   // In cases where nframes>0, margin will be the minimum padding on either
00463   // side, from the edges of the interval to the frames of interest.
00464   Int nframes_(const Block<Int>& frames, Int strtfrm, Int nfrms, Int& margin);
00465 
00466   // Return the maximum number of the given (sorted) animation frames that
00467   // can be displayed from a window or interval of a given size (nfrms).
00468   // also returns where that interval should start (strtfrm).
00469   Int maxframes_(const Block<Int>& frames, Int& strtfrm, Int nfrms);
00470 
00471   // Reset data scaling DParameters to newly-computed data ranges.
00472   void resetMinMax_();
00473 
00474 
00475   //#------flagging routines----------------------------------------------
00476 
00477   // Return or set a flag within the bitmapped flags_ vector, as if it were
00478   // a 5-axis Array<Bool> corresponding in dimensions to vis_.
00479   // (Note: flags_ is an internal array corresponding to the current state of
00480   // flags in the MS, but these routines in themselves do not read or write
00481   // any flags to disk).
00482   // <group>
00483   Bool flag_(IPosition& slot);
00484   void setFlag_(IPosition& slot, Bool flag);
00485   // </group>
00486 
00487   // Add the edit request that just came in (from the mouse, via handleEvent)
00488   // to the flagEdits_ List, then cause the display to be updated.
00489   void addEdit_(WorldCanvas* wc, Int xStart, Int xShape,
00490                                  Int yStart, Int yShape);
00491                                 
00492   // Assure that the display matrices are up-to-date with the flagging edits
00493   // list, to provide visual feedback of the edits.
00494   void postEditsToDisp_();
00495 
00496   // Undo unsaved edits.  Return value indicates whether there were any
00497   // edits to undo.  extent=="all" means undo all, else just the last one.
00498   // If feedback==True, a warning message will be printed about discarded
00499   // edits.
00500   Bool undoEdits_(String extent="all", Bool feedback=False);
00501 
00502   // Save all edits permanently to the MS.  The return value indicates
00503   // whether there were any edits to save.
00504   Bool saveEdits_();
00505 
00506 
00507   //#------visibility deviation (difference, RMS) routines----------------
00508 
00509   // compute the lsTime_ and leTime_ vectors, which define the
00510   // 'local neighborhoods' around each given time slot, for
00511   // computing running averages.
00512   void computeTimeBoxcars_();
00513 
00514   // Return a single visibility point from vis_ or disp_, as a function
00515   // of time slot only.  The row of times and mode must be predetermined by
00516   // setting useVis_, dPos_, axlTm_ and flgdDev_ (below).  goodData_ is set
00517   // True by this routine if the data exists, is loaded and is not flagged
00518   // (False otherwise).
00519   Float v_(Int t);
00520 
00521   // Phase deviations are calculated both for the original phases
00522   // (in [-180,180]), and for the phases 180 degrees opposite
00523   // (also expressed within [-180,180]); the minimum result is displayed.
00524   // This is so that phases clustered around +-180 do not show
00525   // artificially high deviations.  (remainder(x,360) (from math.h)
00526   // is always in [-180,180] -- wierd, but usable for this purpose).
00527   Float vAlt_(Float v) { return remainder(v-180., 360.);  }
00528 
00529   // Return the visibility deviation for the time slot t.  visDev_
00530   // determines whether this is an RMS deviation or absolute
00531   // difference from the running mean.  Maintains state from the
00532   // prior calculation to speed things up in some cases.  Must be
00533   // initialized as for v_() above, and sT_ set to -1, at the
00534   // beginning of a new row of times.
00535   Float dev_(Int t);
00536 
00537   // Calculate deviations throughout range of vis_.  Used to set
00538   // data scaling sliders when visibility deviations are to be displayed.
00539   void computeDevRange_();
00540 
00541   // Create dispDev_ Matrix for displaying deviations.  Both this
00542   // routine and the one above initialize and use dev_() to calculate
00543   // individual deviations.
00544   void createDevSlice_();
00545 
00546 
00547 
00548 
00549 //===================    Data    ======================= (mostly) ========
00550 
00551 
00552 
00553   //------Main enums (and their conversions to strings)-------------------
00554 
00555   // (or, rather, they _used_ to be enums, until the compiler started
00556   // whining and moaning about their use as Ints, Vector/Array/Block
00557   // indices, etc.  (Strong typing: grrr...)
00558 
00559   static const Int INVALID;     // (==-1)  (fairly general purpose).
00560   
00561   // The visibility hypercube (vis_) has 5 axes, in this order.
00562   typedef Int Axis;
00563   static const Axis TIME=0, BASELN=1, CHAN=2, POL=3, SP_W=4,
00564                     NAXES=5,  INVALID_AXIS=-1;
00565 
00566   // Each axis can placed on the canvas display (X or Y), the animator (Z),
00567   // or on one of 2 auxiliary slider controls (SL0, SL1)
00568   typedef Int AxisLoc;
00569   static const AxisLoc X=0, Y=1, Z=2, SL0=3, SL1=4,   NLOCS=5;
00570 
00571   typedef Int VisType;
00572   static const VisType OBSERVED=VisibilityIterator::Observed,
00573                        CORRECTED=VisibilityIterator::Corrected,
00574                        MODEL=VisibilityIterator::Model,
00575                        RESIDUAL=3,  // RATIO=4,
00576                        NTYPES=4,   INVALID_VT=-1;
00577 
00578   typedef Int VisComp;
00579   static const VisComp AMPLITUDE=0, PHASE=1, REAL=2, IMAGINARY=3,
00580                        NCOMPS=4,        // # of actual components (above)
00581                        AMPDIFF=4, AMPRMS=5, PHDIFF=6, PHRMS=7,
00582                        NCOMPNAMES=8,    // Number of choices in the
00583         // GUI choice box (itsVisComp).  itsVisComp is split into visComp_
00584         // (which must be one of the first four values above) and visDev_.
00585         // (see visDev_ below, and also setOptions()).
00586                        INVALID_VC=-1;
00587 
00588   typedef Int VisDev;
00589   static const VisDev  NORMAL=0, DIFF=1, RMS=2,  INVALID_VD=-1;
00590 
00591   // Generic string-to-index converter...
00592   static Int ind_(const String& name, const Vector<String>& names) {
00593     for(uInt i=0; i<names.nelements(); i++) if(names(i)==name) return i;
00594     return -1;  }
00595 
00596   // ...applied to 3 of the 'enums' used internally.
00597   // <group>
00598   Axis axisNum_(const String& axisName) const {
00599     return Axis(ind_(axisName, axisName_));  }
00600 
00601   VisType visTypeNum_(const String& visTypeName) const {
00602     return VisType(ind_(visTypeName, visTypeName_));  }
00603 
00604   VisComp visCompNum_(const String& visCompName) const {
00605     return VisComp(ind_(visCompName, visCompName_));  }
00606   // </group>
00607 
00608 
00609  //-----more constants and statics ----------------------------------------
00610 
00611   // These should be static const, but there's no way to initialize them.
00612   // Print strings, corresponding to Axis, VisType and VisComp enums above.
00613   Vector<String> axisName_;
00614   Vector<String> visTypeName_;
00615   Vector<String> visCompName_;
00616 
00617   static const Float NO_DATA;           // Arbitrary value commandeered
00618         // to stand for 'no data in the selected MS at this position in
00619         // the visibility cube'.  vis_ is initialized to this value before
00620         // data is extracted into it from the selected MS.  After extract_,
00621         // elements left with this value will be masked out during display.
00622   static const Float NOT_LOADED;
00623         // Very similar, but used only in the disp_ array, for data
00624         // which is not loaded into memory (vis_) at present.
00625   static const Float INSUF_DATA;
00626         // Also similar.  Returned by dev_() when there are less than 2
00627         // values in the local neighborhood from which to compute a
00628         // meaningful deviation, or if the data is flagged.
00629 
00630   // NB: The values above are large negative numbers which will not
00631   // correspond to legitimate data values in the data arrays
00632   // where they appear.  The dispFlags_ overlay matrix uses different
00633   // values (NODATA, NOTLOAED, below) to indicate these same two
00634   // conditions--small enum-like sequential integers which can be mapped to
00635   // definite colors easily.
00636 
00637   // dispFlags_ and the flagCM_ custom colormap use the following coding:
00638 
00639   static const Float NOTLOADED,  // not in vis_ memory buffer (grey)
00640                         NODATA,  // no data in the MS selection (black)
00641                        OLDFLAG,  // old flag, from the MS file (medium blue)
00642                        NEWFLAG;  // newly edited, unsaved flag (lighter blue)
00643   static const Int   NCOLORS=4;  // number of colors above.
00644 
00645   //-----primary user input data-------------------------------------------
00646 
00647   //  Passed in through constructors and setOpts parameters.
00648 
00649   String msName_;               // MS filename.
00650 
00651   // User option DisplayParameters specific to MSAsRaster
00652 
00653 
00654   // Maximum memory to use for vis_ buffer.
00655   DParameterRange<Int> *itsVisMb;
00656 
00657   // Which axes will be on X, Y, Animator.  Chosen from
00658   // time, baseline, channel, polarization and spectral window.
00659   DParameterChoice *itsXAxis;
00660   DParameterChoice *itsYAxis;
00661   DParameterChoice *itsZAxis;
00662 
00663   // Which slice to display, for the other two axes.
00664   // The _label_ of the sliders (and the axes they control) vary. 
00665   // They control the slice position of the axes not selected above.
00666   // Animator position is determined externally by WCH restriction 'zIndex'.
00667   DParameterRange<Int> *itsSL0Pos;
00668   DParameterRange<Int> *itsSL1Pos;
00669 
00670   // Baseline sort (antenna1-antenna2 vs. baseline length).
00671   DParameterChoice *itsBslnSort;
00672 
00673   // Sent to scale handler for scaling data to color within these limits.
00674   DParameterRange<Float> *itsDataMin;
00675   DParameterRange<Float> *itsDataMax;
00676 
00677   // Axis Labelling? (Yes/No).
00678   DParameterChoice *itsAxisLabelling;
00679 
00680   // changes to these options require data extraction:
00681 
00682   //#  // the MS selections record:
00683   //#  DParameterRecord (or DParameterMSSelect) *itsSelections;
00684 
00685   // Observed, Corrected, Model, etc.
00686   DParameterChoice *itsVisType;
00687 
00688   //Which real visibiliy component to display: Real, Imag, Amp, Phase.
00689   DParameterChoice *itsVisComp;
00690 
00691   // how many values to use (ideally) in moving averages.
00692   DParameterRange<Int> *itsNAvg;
00693 
00694 
00695   //----derived from above: what is now requested-----------------------
00696 
00697   Vector<Int> axisOn_;  // the axis on each location.  This will be any
00698   // permutation of (TIME, BASELN, CHAN, POL, SP_W), corresponding to the
00699   // axis to display or control on X, Y, Z, SL0, and SL1, in that order.
00700 
00701   Block<Int> pos_;      // The position setting on the animator and sliders.
00702         // Zero-based (although the user sees 1-based values).
00703         // pos_ is indexed by Axis (TIME, BASELN, etc).  For axes being
00704         // displayed, the position is not immediately relevant, but serves
00705         // as a memory of the last setting and is restored to a slice control
00706         // whenever the axis moves off the display.  Corresponds somewhat to
00707         // itsFixedPosition in PrincipalAxesDD.
00708 
00709   VisType visType_;     // enums corresp. to strings in itsVisType/Comp
00710   VisComp visComp_;     // and in sync with them.
00711   VisDev  visDev_;      // (12/02) itsVisComp now maps into _two_ 'enums':
00712                         // visComp_ and visDev_.
00713                         // visComp_ is _only_ AMP, PHASE, REAL or IMAGINARY
00714                         // (above is what is stored in large vis_ Array)
00715                         // and visDev_ tells whether to display the
00716                         // straight vis component (NORMAL), a difference
00717                         // from a running average (DIFF) or a running
00718                         // RMS (RMS).
00719 
00720   Int nDAvg_;           // RMS/Diff average value in itsNAvg (above).
00721   Int nPAvg_;           // number of planes to average
00722 
00723   Vector<Int> fieldIds_;        // user-selected field IDs and
00724   Vector<Int> spwIds_;          // spectral window IDs (0-based).
00725 
00726 
00727   //----current state of main internal data: what is already computed----
00728 
00729   // (These are set (successively) in initMSAR_, selectVS_, findRanges_,
00730   //  extract_, createDisplaySlice_, and createDevSlice_).
00731   
00732   
00733       // The original, unselected MS
00734 
00735   MeasurementSet *itsMS;                // The (unselected) MS to be displayed.
00736   VisibilityIterator* vs_;              // VisSet of (unselected) itsMS
00737   Bool msValid_;                        // valid, writable, non-null (unselected) MS?
00738                                         // (should be set True (permanently) during
00739                                         // construction, or this object will be useless,
00740                                         // and do nothing).
00741   ROMSColumns* msCols_;                 // utility object for (unselected) itsMS.
00742   Int nFieldIds_;                       // Total number of fields, spectral windows,
00743   Int nSpwIds_;                         // in the (unselected) MS.
00744   Vector<Int> nChan_;                   // Number of channels, by Spectral window ID.
00745   Bool dish_;                           // true if the MS is 'single-dish' (has FLOAT_DATA,
00746                                         // which will then be used instead of the DATA column).
00747  
00748                              
00749       // The selected MS.
00750 
00751   MS* mssel_;                           // the selected MS and its VisSet--kept in sync
00752   VisibilityIterator* wvi_p;            // with user input (itsMS, fieldIds_, spwIds_).
00753   Bool msselValid_;                     // mssel_ and vssel_ are valid and non-null.  We will
00754                                         // not draw until this is set True (in selectVS_).
00755   
00756   Int nAnt_;                            // # rows in antenna table (for now).  Later: size
00757                                         // of the set of antennas appearing in mssel_
00758                                         // main data rows.  
00759                                         // NB: nAnt_==1 is tested, rather than dish_ (which
00760                                         // should be equivalent), to determine whether feeds
00761                                         // are displayed instead of baselines.
00762 
00763   Block<Int> msShape_;                  // shape of visibilites of the whole selected MS
00764                                         // = {nTime, nBsln, nChan, nPol, nSpw}.
00765                                         // msShape_[BASELN] reflects the size requirement for
00766                                         // the baseline sort in use (see antSort_, below).
00767   Block<Int> msShapeA_;                 // Identical to msShape_, except possibly on BASELN
00768                                         // axis when baselines are sorted by length
00769                                         // (antSort==False).  In that case, msShapeA_[BASELN]
00770                                         // is the number of baseline slots that _would_ be 
00771                                         // required if the antenna sort were used, including
00772                                         // 1-element 'gaps' where antenna1 changes.
00773                                         // msShape_[BASELN] is the number of actual baselines
00774                                         // needed; the gaps are not needed when displaying the
00775                                         // sort by baseline length.  However, when able to fit
00776                                         // into memory, vis_ is sized according to the larger
00777                                         // msShapeA_[BASELN] in any case, so that switching
00778                                         // between sorts does not require resizing or
00779                                         // reloading vis_, but only reshuffling of the
00780                                         // baseline planes in memory.
00781   
00782   Bool antSort_;                        // True (the default) means baselines are (to be)
00783                                         // sorted by antenna1-antenna2.  False means sorting
00784                                         // by (unprojected, uvw) baseline length.
00785   
00786   Matrix<Double> bLen_;                 // (Unprojected) baseline lengths, indexed by antenna
00787                                         // numbers (symmetric, 0 along diagonal).  Used to
00788                                         // order baselines by length on request.
00789   
00790   Vector<Int> a1_, a2_,                 // These Arrays provide quick conversions between
00791              a1A_, a2A_,                // (antenna1,antenna2) and baseline index.  Of course
00792              a1L_, a2L_,                // arguments ( a1_(bsl), a2_(bsl),  bsl_(a1, a2) )
00793     len2ant_, ant2len_;                 // must be Ints within range; their values are
00794   Matrix<Int> bsl_,                     // according to the _current_ baseline sort
00795        bslA_, bslL_;                    // (antSort_).  (In contrast, methods a1a2_() and
00796   Int         nbsl_,                    // bsln_() may take Float arguments, but convert
00797       nbslA_, nbslL_;                   // _only_ according to the Antenna1-Antenna2 sort).
00798                                         // The A and L versions are for antenna and length
00799                                         // sorts, respectively; they are copied into a1_, a2_,
00800                                         // and bsl_ in accordance with the current sort.
00801                                         // len2ant_ and ant2len_ provide conversion between
00802                                         // baseline indices for the two sorts.  nbsl* give
00803                                         // the number of baselines for the applicable case
00804                                         // (if sgl dish, they will be 1, but irrelevant;
00805                                         // msShape_[BASELN] will be set to number of feeds
00806                                         // instead).
00807 
00808   
00809   Vector<Double> time_;                 // sorted vector of actual times in mssel_
00810                                         // only first msShape_[TIME] ( <= time_.shape() )
00811                                         // are valid.
00812   Vector<Int> field_;                   // vector for field ids corresponding to time slots;
00813                                         // indexed as time_ is, above.  For now, field id
00814                                         // is assumed to be unique for a given time.  Used
00815                                         // to avoid computing running averages across
00816                                         // field boundaries.
00817   Vector<Int> scan_;                    // same as above, for scan numbers.
00818   Vector<String> fieldName_;            // Names corresponding to field_ above.
00819 
00820   Block<Int> spwId_;                    // Spectral window index-to-ID translation.
00821                                         // The user can select the spectral windows to
00822                                         // view.  This Block holds the (sorted) spectral
00823                                         // windows actually found in the selected MS--usually
00824                                         // it will be identical to the user selection (spwIds_,
00825                                         // above).  Its length is the size of the Spectral
00826                                         // Window axis (msShape_[SP_W]). 
00827                                         // Note that throughout the code, the variable 'spw'
00828                                         // refers to the _index_ into this block, not the
00829                                         // Spectral window ID itself.  Actual IDs will have
00830                                         // 'Id' in the variable name.
00831   Block<void*> freq_;                   // *freq_[spw] is really a Vector<Double>.  
00832                                         // (*freq_[spw])[chan] holds the CHAN_FREQ for 
00833                                         // the given spw index and channel (in Hz).
00834 
00835   // The following translate pol ID and the polarization index within a cell
00836   // of data in the MS, to the 'pol' index within the internal visibility
00837   // cube.  There is no 'polID axis' separate from the pol axis internally or
00838   // for the display; it is flattened to a single pol axis, using these
00839   // tables.  They are set up in findRanges_.
00840   Int nPolIds_;                         // Number of rows in the POLARIZATION subtable
00841                                         // (and the size of the next two vectors).
00842   Vector<Int> nPolsIn_;                 // number of correlations in each polId.
00843   Vector<Int> pidBase_;                 // difference between a visibility's 'pol' index
00844                                         // within msShape_[POL] and its index within
00845                                         // the MS table's visibility data cell, for given
00846                                         // polId (or -1, if the polID is not in the 
00847                                         // selected data).
00848         // The following 2 vectors will have sizes = msShape_[POL], and
00849         // are indexed according to the internal polarization 'data pixel
00850         // number' (generally referred to as 'pol').
00851   Vector<Int> polId_;                   // polarizationId for given pol.
00852   Vector<String> polName_;              // name of the pol.
00853 
00854 
00855       // The visibility hypercube.
00856 
00857   Array<Float> vis_;                    // the (large) memory buffer: 5-axis hypercube of
00858                                         // gridded MS visibilities (for t, bsl, chan, pol, spw, in that
00859                                         // order).  Conceptually, this is a (contiguous, hyper-rectangular)
00860                                         // 'window' or 'cursor' into the whole gridded ms as characterized
00861                                         // by msShape_ above.  It _will_ be the whole thing, if it fits
00862                                         // into memory; in any case, the two display axes will be full size.
00863   Bool visValid_;                       // Is vis_ valid for current selected MS?
00864   Block<Int> visShape_;                 // shape of extracted vis_ Array (used*) and
00865   Block<Int> visStart_;                 // start of extracted vis_ Array, within msShape_
00866 
00867   Block<Int> visShapeA_;                // *Identical to visShape_ except possibly on the
00868                                         // BASELN axis, and then only when computeVisShape_()
00869                                         // determines that the entire msShapeA_[BASELN]
00870                                         // will fit into memory, and the length sort
00871                                         // is also in effect.  In that case,
00872                                         // visShapeA_[BASELN] == msShapeA_[BASELN] and
00873                                         // visShape_[BASELN] == msShape_[BASELN] (which is
00874                                         // msShapeA_[BASELN] - (nAnt_-1) ).
00875                                         // vis_ is actually sized according to visShapeA_.
00876   
00877   VisType curVisType_;
00878   VisComp curVisComp_;                  // type and component of current vis_.
00879 
00880   Float dataRngMin_, dataRngMax_;       // The 'data ranges' for vis_.
00881                                         // Used (only) for scaling data values to colors; they are
00882                                         // too expensive to compute except during extract_().
00883                                         // Not the actual min/max of the data in general, since they
00884                                         // may be sampled and/or clipped to 3-sigma limits.
00885   Float devRngMin_, devRngMax_;         // same thing, for the case when
00886                                         // visibility deviations are being displayed.  Both types
00887                                         // of ranges are kept, in case the user switches from one
00888                                         // type ot display to the other.  devRngMin_ is set to
00889                                         // NO_DATA if these haven't been computed yet.
00890                                         // computeDevRange_() is called from extract_ or
00891                                         // setOptions to compute these when needed.
00892 
00893   
00894       // The display matrices which are drawn on the canvas.
00895 
00896   Matrix<Float> disp_;                  // Matrix of data values actually passed to the
00897                                         // display canvas.
00898   Axis dispX_, dispY_;                  // displayed axes that disp_ represents.
00899   Block<Int> dispPos_;                  // non-display axis ('slice') positions disp_
00900                                         // represents, by Axis.  Settings for display axes,
00901                                         // (i.e. dispPos_[dispX_] and dispPos_[dispY_]),
00902                                         // are irrelevant).
00903   Bool dispValid_;                      // Has disp_ been created since extract_ was
00904                                         // called?
00905   Bool dispNotLoaded_;                  // Is the entire disp_ Matrix set to the
00906                                         // NOT_LOADED value?
00907 
00908   Matrix<Float> dispDev_;               // Similar to disp_, but for visibility deviation
00909                                         // data displays.  (Filled by createDevSlice_()).
00910   Bool dispDevValid_;                   // Is dispDev_ valid for current disp_ and
00911                                         // (if necessary) the state of flag edits?
00912   VisDev dispDevType_;                  // Type of deviation (RMS or DIFF) that dispDev_
00913                                         // represents.
00914   Int dispDevNAvg_;                     // Nominal number of values in running averages
00915                                         // in effect when dispDev_ was last computed.
00916 
00917 
00918 
00919 
00920   //---------------additional control state----------------------------------
00921   //  ...for communication of control logic between various methods (mainly
00922   //  setOptions, draw_ and extract_)
00923 
00924   Bool visDataChg_;     // means that MS selection, visType_ or visComp_
00925                         // do not reflect current state of vis_.  Set by
00926                         // setOptions.  Indicates to extract_ that it should
00927                         // completely recalculate data ranges (and set
00928                         // the actual dataMin/Max_ sent to the scale handler
00929                         // accordingly).  setOptions also uses it to help
00930                         // determine whether it should call extract_.
00931 
00932   Bool postDataRng_;    // A kind of reply to the above; set True after
00933                         // extract_ has recalculated data ranges from
00934                         // scratch (as opposed to merely expanding them).
00935                         // When True, setOptions will return these new
00936                         // ranges unaltered to the gui, via recOut.
00937 
00938                         
00939   //----translation between MS values and internal hypercube indices---------
00940   
00941   struct MSpos_;
00942   friend struct MSpos_;
00943   struct MSpos_ {
00944 
00945     // An MSpos_ holds information about a given position of interest within
00946     // the main MS visibility Table.  Its data members are the values at
00947     // that position as actually stored in the MS (times, antennas, etc.);
00948     // these can be freely set and queried by MSAsRaster, the only user of
00949     // this struct.  It provides translation between these values and the
00950     // hypercube indices (pos_) used internally.  It was time to quit
00951     // performing these translations ad hoc and consolidate them here (3/04).
00952     // (Still to do: use this instead of old ad hoc methods in, e.g.,
00953     // showPosition()).
00954     
00955     // When MS selection changes, MSAsRaster::findRanges_() computes several
00956     // tables (time_, spwId_, freq_, polId_, nAnt_, etc.) which [re-]define
00957     // the correspondence of MS data to hypercube positions.  An MSpos_
00958     // set up prior to this change can be queried afterward as to the data's
00959     // position (if any) in the new hypercube.  It is also useful in
00960     // determining whether flagging edits (which are stored in terms of
00961     // hypercube positions) apply to MS data beyond what is currently
00962     // selected.
00963     
00964     // Below is the real content of an MSpos_: data for a position within
00965     // an MS in terms of the values actually stored there.  
00966     // Note that, in its current version, MSAsRaster assumes that this
00967     // data uniquely determines a visibility-and-flag within the MS (and
00968     // feed is not considered either, when there is more than one antenna).
00969     
00970     Double time;
00971     Int ant1, ant2, feed, spwId, polId, chan;
00972     String polName;
00973     
00974     // IMO, a _nested_ struct/class should have visibility (and access
00975     // permission(?)) into the nesting class, but it doesn't (except, rather
00976     // oddly, for the static consts of MSAsRaster: TIME, NAXES, etc.,
00977     // which are directly in scope and accessible here).   Hence the
00978     // need to have a pointer to the nesting object and for it to declare
00979     // this class a friend.  The nesting class's 'this' should be
00980     // available implicitly to this class instead.  As is, it's
00981     // rather clumsy to implement classes/structs that are purely in support
00982     // of another class....
00983     
00984     const MSAsRaster* m;        // parent dd, needed for access to the
00985                                 //  MSAsRaster tables which it set up in
00986                                 // findRanges_: nAnt_, time_, spwId_, freq_,
00987                                 // polId_, etc.
00988 
00989     Int ts, te;         // Ancillary output of t() (in terms of hypercube
00990                         // time-slot indices).  When t() returns INVALID (time
00991                         // not found) they are the bracketing time slots, i.e.
00992                         // ts+1==te and (where ts or te are in timeslot range)
00993                         // time_[ts] < time < time_[te].
00994 
00995 
00996     // Construct MSpos_ with no valid values set (yet).
00997     
00998     MSpos_(const MSAsRaster* msar):
00999       time(INVALID), ant1(INVALID), ant2(INVALID), feed(INVALID),
01000       spwId(INVALID), polId(INVALID), chan(INVALID), polName("Invalid"),
01001       m(msar), ts(INVALID), te(INVALID) {   }
01002     
01003           
01004     // Construct MSpos_ according to 5-element Block corresponding to a
01005     // position within the internal hypercube.
01006     
01007     MSpos_(const MSAsRaster* msar, const Block<Int>& pos): m(msar) {
01008       set(pos);  }
01009     
01010               
01011     // Translation methods (for times, baselines, channels, 
01012     // spectral windows, and polarizations).  All but the last seven
01013     // set MSpos_ state to the appropriate values as stored in the MS.
01014     
01015     // hypercube indices to MS values
01016     
01017     void set(const Block<Int>& pos) {
01018       sett(pos[TIME]); setb(pos[BASELN]); sets(pos[SP_W]);
01019       setc(pos[CHAN]); setp(pos[POL]);  }
01020     
01021     void sett(Int t);  void setb(Int b);  void sets(Int s);
01022     void setc(Int c);  void setp(Int p);
01023              
01024     // MS values to hypercube indices.      
01025     
01026     Int t(Double tm) { time=tm; return t();  }
01027     Int b(Int a1, Int a2) { ant1=a1; ant2=a2; feed=INVALID; return b();  }
01028     Int b(Int fd) { feed=fd; ant1=ant2=INVALID; return b();  }
01029     Int s(Int sid) { spwId=sid; return s();  }
01030     Int c(Int ch) { chan=ch; return c();  }
01031     Int c(Int sid, Int ch) { spwId=sid; chan=ch; return c();  }
01032     Int p(Int pid, Int pnm) { polId=pid; polName=pnm; return p();  }
01033     Int p0(Int pid) { polId=pid; return p0();  }
01034     
01035     Int p0() { 
01036       if(polId<0 || polId>=Int(m->pidBase_.nelements())) return INVALID;
01037       return m->pidBase_[polId];  }  
01038           
01039     Int operator[](Axis ax) {
01040       switch(ax) {
01041         case   TIME: return t();   case BASELN: return b();
01042         case   SP_W: return s();   case   CHAN: return c();
01043         case    POL: return p();       default: return INVALID;  }  }
01044         
01045     Int t();  Int b();  Int s();  Int c();  Int p();  };
01046 
01047     
01048             
01049   MSpos_ mspos_;        // used by findRanges_() to maintain the MS 'slice'
01050                         // position being viewed as much as possible when
01051                         // MS selection is changed--e.g., to remain on the
01052                         // same time (if it is still in the selected MS),
01053                         // even though its time-slot index (slice position)
01054                         // may have changed.
01055  
01056   
01057   //----flagging state-------------------------------------------------------
01058 
01059   DParameterChoice *itsFlagColor;
01060   Bool flagsInClr_;     // equivalent to  itsFlagColor->value()=="In Color"
01061 
01062   DParameterChoice *itsUnflag;
01063   Bool unflag_;         // equivalent to  itsUnflag->value()=="Unflag"
01064 
01065   Block<Bool> flagAll_;    // from UI checkboxes for each axis (there is
01066                            // no checkbox-type DParameter yet)..
01067 
01068   DParameterChoice *itsEntireAnt;
01069                           // choice box for applying edits to entire antenna.
01070   Bool entireAnt_;        // equivalent to  itsEntireAnt->value()=="Yes"
01071 
01072   DParameterButton *itsUndoOne;
01073                            // defines the button for undoing one edit.
01074   DParameterButton *itsUndoAll;
01075                            // defines the button for undoing all edits.
01076   DParameterChoice *itsEditEntireMS;
01077                            // choice box for using entire MS (vs. selected
01078                            // MS only) when saving edits.
01079   DParameterButton *itsSaveEdits;
01080                            // defines the button for saving all edits.
01081   
01082   Vector<uInt> flags_;     // Bitmapped storage for flags retrieved
01083                            // from the MS (only); not for new, unsaved flags.
01084                            // Virtually, this has the same shape as vis_.
01085 
01086   Matrix<Bool> dispMask_;  // Mask for disp_ or dispFlags_.  Distinguishes
01087                            // good data from flagged/missing data.  Which
01088                            // is True and which False depends on flagsInClr_.
01089   Matrix<Float> dispFlags_;  // For the (slower) 'color flags' option, this
01090                              // will overlay the main data array to show
01091                              // flags in color.
01092   Bool dispFlagsInClr_;      // Are the current display matrices set up to
01093                              // draw flags in color?
01094   uInt dispNEdits_;          // Number of flag edits already reflected
01095                              // in display matrices and masks.
01096 
01097 
01098 
01099   // FlagEdit_ holds information about a single
01100   // (new, unsaved) flagging edit command.
01101   
01102   struct FlagEdit_;
01103   friend struct FlagEdit_;
01104   struct FlagEdit_ {
01105 
01106 
01107     MSAsRaster* msar;   // parent dd, needed for access to its members.
01108 
01109     // All 3 of these Blocks are indexed by Axis, and have NAXES elements.
01110     Block<Bool> all;    // all[axis]==T: apply edit to entire axis.
01111     Block<Int> start;   // all[axis]==F: apply edit from start[axis] up to
01112     Block<Int> shape;   // (but not including) start[axis]+shape[axis].
01113     
01114                         // Note that all[axis] will imply start[axis]==0 &&
01115                         // shape[axis]==msShape_[axis], but _not vice-versa_.
01116                         // all[axis] has the _additional_ meaning that the
01117                         // edit should extend beyond hypercube (selected
01118                         // MS) boundaries, to the _entire_ MS, when saving
01119                         // flags (if itsEditEntireMS is turned on).
01120 
01121 
01122     Bool unflag;        // T=unflag  F=flag
01123 
01124     Bool entireAnt;     // T=apply to all baselines with Antenna1 of selection.
01125     
01126     // The following are set by appliesToChunk(spw, nChan, pol0, nPol) at
01127     // the beginning of each chunk, within saveEdits_().
01128     // A given chunk has a fixed polId and spwId, which imply a given
01129     // shape (nPol, nChan) of visibilities and flags as actually stored in
01130     // the MS.
01131 
01132     Bool appChunk;      // Does the edit apply to the spectral window and
01133                         // at least some of the pols and channels implied by
01134                         // the chunk's data description ID?
01135     Int sPol,ePol, sChan,eChan;         // If appChunk is True, (and the
01136                 // edit applies to the row's time and baseline -- tested
01137                 // elsewhere), then the visibilities in the MS row where
01138                 // the edit applies have pol and channel index ranges
01139                 // [sPol,ePol) and [sChan,eChan).  (Note that these are
01140                 // _different_ index ranges from those determined by 
01141                 // start & shape, above, which are relative to the
01142                 // _internal hypercube_ shape, msShape_).
01143         
01144     FlagEdit_(MSAsRaster* m):           // constructor.
01145       msar(m),
01146       all(NAXES, False), start(NAXES), shape(NAXES, 1),
01147       unflag(False), entireAnt(False),
01148       appChunk(False), sPol(0),ePol(0), sChan(0),eChan(0) {   }
01149 
01150     // Return the range (half-open interval) over which the edit definitely
01151     // applies*, on the given axis.  This is the range selected with the
01152     // mouse or (when edit.all[ax]==True) the entire axis range.
01153     // 
01154     // * Exception: when antenna-based editing is on (entireAnt==True),
01155     // baselines of only one antenna will be edited regardless -- see
01156     // appliesTo(Int bsln).  The interval returned is still as stated
01157     // above, however).
01158     void getSureRange(Axis ax,  Int& strt, Int& fin) {
01159       strt=start[ax]; fin=strt+shape[ax];  }
01160 
01161     // Is the given position within the range above, on the given axis?
01162     Bool inSureRange(Axis ax, Int pos) {
01163       return start[ax]<=pos && pos<start[ax]+shape[ax];  }
01164 
01165     // Retrieve ranges for loops.  Same as getSureRange(), except for
01166     // antenna-based baseline testing, when the entire baseline range
01167     // of the selected MS is returned.  In that case, applicability
01168     // of the edit to the individual baselines must still be tested
01169     // within the loop, with edit.appliesTo(bsln).
01170     void getLoopRange(Int ax,  Int& strt, Int& fin) {
01171       if(entireAnt && ax==BASELN) { strt=0; fin=msar->msShape_[ax];  }
01172       else getSureRange(ax, strt,fin);  }
01173 
01174     // Is the given position in the 'loop range' on the given axis?
01175     Bool inLoopRange(Int ax, Int pos) {
01176       Int strt, fin; getLoopRange(ax, strt,fin);
01177       return (strt<=pos && pos<fin);  }
01178 
01179     // Does edit apply to given hypercube position (relative to
01180     // entire MS)?  (pos must be NAXES in size).
01181     Bool appliesTo(IPosition pos) {
01182       for(Axis ax=0; ax<NAXES; ax++) if(!appliesTo(ax, pos(ax))) return False;
01183       return True;  }
01184 
01185     // Does edit apply to given position on given axis?
01186     Bool appliesTo(Axis ax, Int pos) {
01187       return inLoopRange(ax, pos) && applies2(ax, pos);  }
01188 
01189     // Same as above, but for use (only) where inLoopRange(ax, pos)
01190     // is already known to be true.  This one is used within loops,
01191     // for efficiency.
01192     Bool applies2(Axis ax, Int pos) {
01193       return ax!=BASELN || !entireAnt || appliesTo(pos);  }
01194 
01195     // Does edit apply to the given baseline?  (Also for use only where
01196     // inLoopRange(BASELN, bsln) is already known to be True).  This is
01197     // used mainly for testing baselines against antenna-based edits.
01198     Bool appliesTo(Int bsln);
01199 
01200     // Does the edit apply to the current MS iteration chunk?
01201     Bool appliesToChunk(Int pol0, Int nPol, Int spw, Int nChan);
01202     
01203     // Does the edit apply to a given (raw) time?
01204     Bool appliesTo(Double time);
01205     
01206     Bool operator==(FlagEdit_& other);  };
01207 
01208     
01209   
01210   
01211   List<void*> flagEdits_;       // List of all the (so-far-unsaved) edits.
01212     // (<void*> rather than <FlagEdit_*> just to avoid the extra templates)
01213 
01214 
01215   //---state for computing [RMS] deviation from local visibility average---
01216   // (Not very object-oriented--more like Fortran common.  Sorry, pressed
01217   // for time.  To be reworked into object(s) sometime, if it can be
01218   // done efficiently).
01219 
01220   Vector<Int> lsTime_, leTime_,  lsvTime_, levTime_;
01221         // Beginning and (1 beyond) ending time index defining the 'boxcar'
01222         // or local neighborhood over which averages are computed, for given
01223         // time slot.  (Note that, for now, these are assumed to be only a
01224         // function of time.  Later, these may become Matrices, indexed
01225         // also by Array ID or baseline).  Recomputed (computeTimeBoxcars_)
01226         // when nAvg_ changes, and after extract_.
01227         // lsv, lev versions are for vis_, i.e relative to visStart_[TIME],
01228         // and of length visShape_[TIME].
01229 
01230   Bool useVis_; IPosition dPos_; AxisLoc axlTm_; Bool flgdDev_;
01231         // Initializing input to dev_(t) and its subsidiary routine v_(t).
01232         // These create something similar to an ArrayAccessor, in that
01233         // vis_ (or disp_, depending on useVis_) can be accessed by giving
01234         // only the value along the time axis.  dPos_ fixes the row of times
01235         // to use within vis_ or disp_; axlTm_ gives the location of the
01236         // time axis within dPos_.  The value of the index along that
01237         // axis (only) will be varied as needed, by dev_() and v_().
01238 
01239         // flgdDev_ should usually be set False, causing dev_ simply to
01240         // return INSUF_DATA for flagged points.  In one obscure case, it
01241         // is set True to request dev_ to calculate deviations even for
01242         // the flagged points.
01243 
01244   Bool goodData_;
01245         // This really should be a return value from v_(); placed here for
01246         // 'efficiency'.  Set after each call to v_(): True iff the data
01247         // existed, was loaded, and was not flagged.
01248 
01249   Int sT_, eT_; Double sumv_, sumv2_, sumva_, sumv2a_; Int nValid_; Float d_;
01250         // Saved state from the last call to dev_().  When moving along
01251         // a time axis, it sometimes saves time to have these previous
01252         // results handy.  d_ is the most recently computed deviation.
01253         // sT_ (boxcar start time slot) must be set to -1 when starting to
01254         // compute deviations on a new line of times, indicating that
01255         // none of this 'saved state' is valid yet.
01256 
01257 
01258 
01259 
01260   //----------helper objects and their control data-----------
01261 
01262   // This does data scaling for WorldCanvas
01263   WCPowerScaleHandler itsPowerScaleHandler;
01264 
01265   // This labels the axes.  An actual CachingDisplayData itself, contained
01266   // within MSAsRaster and controlled through it.  MSAsRaster propagates
01267   // getOptions and setOptions calls and draw commands to it, and sets the
01268   // WC CoordinateSystem which it uses.
01269   WorldAxesDD itsAxisLabeller;
01270 
01271   // A private internal colormap for showing colors for various conditions
01272   // (flagged, no data, data not loaded).  This is not the colormap set
01273   // by the user for mapping data values.  It has rigid single colors
01274   // for the different conditions.
01275   Colormap flagCM_;
01276 
01277 private:
01278 
01279   bool adjustAvgRange( VisDev newstate, Record &outrec, bool force=false );
01280 
01281 };
01282 
01283 
01284 
01285 //#----------MSAsRasterDM----------------------------------------------------
01286 
01287 // <summary>
01288 // (Minimal) DisplayMethod for MSAsRaster.
01289 // </summary>
01290 
01291 // <prerequisite>
01292 //   <li> MSAsRaster
01293 //   <li> CachingDisplayMethod
01294 // </prerequisite>
01295 
01296 // <etymology>
01297 // "MSAsRasterDM" is a implementation of a <linkto class=CachingDisplayMethod>
01298 // CachingDisplayMethod </linkto> for <linkto class=MSAsRaster>
01299 // MSAsRaster </linkto>.
01300 // </etymology>
01301 
01302 // <synopsis>
01303 // MSAsRasterDM a minimal skeleton; it is implemented
01304 // in its entirety here.  Its only purpose is to hold the cached drawlist
01305 // and use it when appropriate via the mechanism and data structure
01306 // implemented on the CachingDisplayMethod level.  MSAsRasterDM just
01307 // turns the draw request back over to MSAsRaster, since that's where
01308 // the necessary data is.
01309 
01310 // This 'minimal' CachingDisplayMethod could be adapted and reused by any
01311 // other CachingDisplayData that wanted to do its own drawing.
01312 
01313 // </synopsis>
01314 
01315 class MSAsRasterDM : public CachingDisplayMethod {
01316 
01317  public:
01318 
01319   // Constructor.  The parameters contain state that determines
01320   // what should be drawn.
01321   MSAsRasterDM(WorldCanvas *wc, AttributeBuffer *wchAttrs,
01322                AttributeBuffer *ddAttrs, CachingDisplayData *dd):
01323                CachingDisplayMethod(wc, wchAttrs, ddAttrs, dd) {  }
01324   
01325   // Destructor.
01326   virtual ~MSAsRasterDM() {  }
01327   
01328  protected:
01329   
01330   // The base CachingDM takes care of using any cached drawlist.
01331   // When this method is called, we know that no drawlist applies,
01332   // and that we must actually send drawing commands to the WC (though
01333   // technically, they might _not_ actually be going into a drawlist).  
01334   // This skeleton DM just hands the drawing task back to the DD,
01335   // where all the data has been created and maintained anyway.
01336 
01337   virtual Bool drawIntoList(Display::RefreshReason reason,
01338                             WorldCanvasHolder &wcHolder) {
01339     MSAsRaster *msar = dynamic_cast<MSAsRaster *>(parentDisplayData());
01340     if (!msar) throw(AipsError("invalid parent of MSAsRasterDM"));
01341 
01342     return msar->draw_(reason, wcHolder, *(worldCanvas()) );  }
01343 
01344  
01345  private:
01346 
01347   // Default and copy constructors, and the assignment operator, are 
01348   // mon-functional and should not be used.  Do not make copies of
01349   // DisplayMethod objects, or pass them by value;
01350   // use references or pointers instead.
01351   // <group>
01352   MSAsRasterDM() {  }
01353   MSAsRasterDM(const MSAsRasterDM &other) : CachingDisplayMethod(other) {  }
01354   MSAsRasterDM& operator=(const MSAsRasterDM &/*other*/) { return *this;  }
01355   // </group>
01356   
01357 };
01358 
01359 
01360 } //# NAMESPACE CASA - END
01361 
01362 #endif
01363