casa  $Rev:20696$
MsPlotConvert.h
Go to the documentation of this file.
00001 //# MsPlotConvert.h: Defines the convert classes used by MsPlot.  These
00002 //#                  classes are called by TablePlot when the data points
00003 //#                  being plotted need to be changed -- good for supporting
00004 //#                  different units
00005 //# Copyright (C) 2003
00006 //# Associated Universities, Inc. Washington DC, USA.
00007 //#
00008 //# This library is free software; you can redistribute it and/or modify it
00009 //# under the terms of the GNU Library General Public License as published by
00010 //# the Free Software Foundation; either version 2 of the License, or (at your
00011 //# option) any later version.
00012 //#
00013 //# This library is distributed in the hope that it will be useful, but WITHOUT
00014 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00016 //# License for more details.
00017 //#
00018 //# You should have received a copy of the GNU Library General Public License
00019 //# along with this library; if not, write to the Free Software Foundation,
00020 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00021 //#
00022 //# Correspondence concerning AIPS++ should be addressed as follows:
00023 //#        Internet email: aips2-request@nrao.edu.
00024 //#        Postal address: AIPS++ Project Office
00025 //#                        National Radio Astronomy Observatory
00026 //#                        520 Edgemont Road
00027 //#                        Charlottesville, VA 22903-2475 USA
00028 //#
00029 //#
00030 //# $Id:$
00031 //#
00032 //# -------------------------------------------------------------------------
00033 //# Change Log
00034 //# Date   Name       Description
00035 //# 11/14/2007  S. Jaeger   Fixed up the message handling.
00036 
00037 
00038 #if !defined CASA_MSPLOT_CONVERT_H
00039 #define CASA_MSPLOT_CONVERT_H
00040 
00041 
00042 //# General CASA includes
00043 #include <casa/BasicSL/String.h>
00044 
00045 //# Measurement and table related includes
00046 #include <ms/MeasurementSets/MSColumns.h>
00047 #include <ms/MeasurementSets/MSAntennaColumns.h>
00048 #include <ms/MeasurementSets/MSSpWindowColumns.h>
00049 #include <ms/MeasurementSets/MSDerivedValues.h>
00050 
00051 #include <measures/Measures/MeasTable.h>
00052 
00053 #include <tableplot/TablePlot/SLog.h>
00054 
00055 //# How frequently we display debugging message, we've set it at every
00056 //# 500 000 points.
00057 #define CASA_MPC_DBG_FREQ 50000
00058 
00059 
00060 //#!//////////////////////////////////////////////////////////////////////////
00061 //#! 
00062 //#!       CONVERSION CLASSES - All classes used with TablePlot to convert 
00063 //#!                            point values when plotting.
00064 //#! 
00065 //#!//////////////////////////////////////////////////////////////////////////
00066 
00067 // Some method parameters are only used when LOG0 is set to one which means that
00068 // normally they generate compile warnings.  This macro will comment outthe enclosed
00069 // parameter when LOG0 is not one and will leave it alone when LOG0 == 1. (jjacobs)
00070 
00071 #if LOG0
00072 #    define IfLOG0(x)\
00073     x
00074 #else
00075 #    define IfLOG0(x)\
00076     /*x*/
00077 #endif
00078 
00079 namespace casa { //# NAMESPACE CASA - BEGIN
00080 
00081 
00083 //#! All the wonderful docs, that will show up in the user reference
00084 //#! manual for this class.
00085     
00086 //#!//////////////////////////////////////////////////////////////////////////
00087 //#! All the wonderful docs, that will show up in the user reference
00088 //#! manual for this class.
00089 //#!    
00090 // <summary>
00091 // Class used by TablePlot. The Xconvert and Yconvert methods are called
00092 // for each data point that is plotted.  This class is used when plotting
00093 // the "azimuth" plot of a measurement set.
00094 // </summary>
00095 //#!
00096 //#! <use visibility=local>   or   <use visibility=export>
00097 // <use visibility=local>    
00098 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
00099 //#! for example:
00100 //#!  <reviewed reviewer="pshannon@nrao.edu" date="1994/10/10" tests="tMyClass, t1MyClass" demos="dMyClass, d1MyClass">
00101 //#!  </reviewed>
00102 // </reviewed>
00103 //#!
00104 //#! Classes or concepts you should understand before using this class.
00105 // <prerequisite>
00106 // <ul>    
00107 //   <li> <linkto class="MSPlot">MSPlot</linkto>class,     
00108 //   <li> <linkto class="TablePlot">TablePlot</linkto>class,
00109 //   <li> What an azimuth plot is plotting,
00110 //   <li> <linkto class="MeasurementSet:description">Measurement Set
00111 //        </linkto> class,
00112 //#!    
00113 //   <li> <linkto class="Table">Table</linkto> class,
00114 //       in particular TaQL expressions
00115 //   in with the table code.
00116 // </ul>    
00117 // </prerequisite>
00118 //#!        
00119 // <etymology>
00120 // The conversion class that takes points from a Measuremen Set's TIME
00121 // column and converts them to azimuth angless.
00122 // </etymology>
00123 //#!
00124 // <synopsis>
00125 // </synopsis>
00126 //#!
00127 //<example>    
00128 //<example>
00129 //#!
00130 // <motivation>
00131 // Provide a plot of azimuth values to the user doing the conversion
00132 // for them; the conversion could be done with the facilities provided
00133 // in Python as well as the <linkto class="Table">Table</linkto> class.    
00134 // </motivation>
00135 //#!
00136 // <thrown>
00137 //    <li> AIPSError
00138 //    <li> TableError
00139 // </thrown>
00140 //#!
00141 // <todo asof="2007/12/12">
00142 //   <li> Make it more efficient by having the
00143 //        <linkto class="TablePlot">TablePlot</linkto> class send
00144 //        a full row of data rather then a single point. This will reduce
00145 //        the number of calculations substantially and speed things up!   
00146 //   </li>
00147 // </todo>
00148 //#!    
00149 //#! End of documentation.    
00150 //#!///////////////////////////////////////////////////////////////////////////
00151     
00152 class MSPlotConvertAzimuth : public TPConvertBase
00153 {
00154     public: 
00155    // Constructor
00156    MSPlotConvertAzimuth( MSDerivedValues * derived,
00157                ROMSColumns * columns,
00158                Bool onXaxis )
00159         {
00160             log = SLog::slog();
00161        // For some reason message loggin, even when its not being
00162        // displayed really slows things -- the Logger needs to do
00163        // things a little faster.
00164        numPlotted = 0;
00165        String fnname =  "MSPlotConvertAzimuth";
00166        log->FnEnter(fnname, clname);
00167        
00168        // Determine wether the converted value is along the x or
00169        // y axis.
00170        convertOnX = onXaxis;
00171 
00172        // Store the data bits we need.  We could get away with
00173        // keeping less info around.  It's the old speed versus
00174        // space trade of.
00175        itsMsDerived = derived;
00176        itsFieldIds = columns->fieldId().getColumn();
00177        itsColumns = columns;
00178        // We keep track of the lastFieldId seen by these class.
00179        // This saves us some calculation time, if the current one
00180        // is the same as the last we use the stored value rather
00181        // then recalculate.
00182        lastFieldId = -1;
00183 
00184        log->FnExit(fnname, clname);
00185    };
00186    
00187    // Destructor
00188    ~MSPlotConvertAzimuth() {
00189        String fnname = "~MSPlotConvertAzimuth";
00190        log->FnEnter(fnname, clname);
00191 
00192        log->FnExit(fnname, clname);
00193    };
00194    
00195    // Conversion along the Xaxis
00196    Double Xconvert( Double x, Int row, Int tblNum )
00197    {
00198        String fnname = "Xconvert";
00199        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {
00200            log->FnEnter(fnname + "(x, row, tblNum)", clname);
00201            log->out(String("Value: ") + String::toString(x)
00202               + " Row= " + String::toString(row)
00203               + " Table Counter=" + String::toString(tblNum),
00204               fnname, clname, LogMessage::DEBUG1); 
00205        }
00206        
00207        if ( convertOnX ) {
00208            numPlotted++;
00209            if ( row >= 0 && itsFieldIds.nelements() > (uInt)row )
00210            {
00211                if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00212                    log->FnExit(fnname, clname);
00213                return findValue( x, row );
00214            } else {
00215                String err =  String( "Internal Error: Unable to convert" )
00216                    + String( "azimuth value, row value was: " )
00217                    + String::toString( row )
00218                    + String( ". Row values need to be between 0 and "  )
00219                    + String::toString( itsFieldIds.nelements() );
00220                log->out( err, fnname, clname, LogMessage::SEVERE, True );
00221                // Should never get here, and exception occurs in logMessage()
00222                return x;   
00223            }
00224        } else {
00225            if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00226                log->FnExit(fnname, clname);
00227            return x;
00228        }
00229    };
00230    
00231 
00232    // Conversion along the Yaxis
00233    Double Yconvert( Double y, Int row, Int tblNum )
00234    {
00235        String fnname = "Yconvert";
00236        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {
00237            log->FnEnter(fnname + "(y, row, tblNum)", clname);
00238            log->out(String("Value: ") + String::toString(y)
00239                    + " Row= " + String::toString(row)
00240                    + " Table Counter=" + String::toString(tblNum),
00241                    fnname, clname, LogMessage::DEBUG1); 
00242        }        
00243        
00244        if ( !convertOnX ) {
00245            numPlotted++;
00246            if ( row >= 0 && itsFieldIds.nelements() > (uInt)row )
00247            {
00248                if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00249                    log->FnExit(fnname, clname);
00250                return findValue( y, row );
00251            } else {
00252                String err =  String( "Internal Error: Unable to convert" )
00253                    + String( "azimuth value, row value was: " )
00254                    + String::toString( row )
00255                    + String( ". Row values need to be between 0 and "  )
00256                    + String::toString( itsFieldIds.nelements() );
00257                log->out( err, fnname, clname, LogMessage::SEVERE, True );
00258                // Should never get here, and exception occurs in logMessage()
00259                return y;
00260            }
00261        } else {
00262            if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00263                log->FnExit(fnname, clname);
00264            return y;
00265        }
00266    };
00267   
00268    Double findValue( Double value, Int row )
00269    {
00270        String fnname = "findValue";
00271        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00272            log->FnEnter(fnname, clname);
00273        
00274        curFieldId = itsFieldIds( row );    
00275        if ( curFieldId < 0 ||
00276                (uInt)curFieldId >= itsColumns->field().numPoly().getColumn().nelements() )
00277        {
00278            String err = String( "Internal Error: Current field ID, " )
00279                + String::toString( curFieldId )
00280                + String( " is greater then the size of fields polygon column" );
00281            log->out( err, fnname, clname, LogMessage::SEVERE, True );
00282        }
00283        if ( curFieldId != lastFieldId )
00284        {
00285            if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00286                log->out( String( "Field ID: ")+String::toString(curFieldId));
00287            
00288            if ( itsColumns->field().numPoly()(curFieldId) == 0 )
00289                itsMsDerived->setFieldCenter( itsColumns->field().phaseDirMeas( curFieldId ) );
00290            if ( itsColumns->field().numPoly()( curFieldId ) > 0 )
00291                itsMsDerived->setFieldCenter( itsColumns->field().phaseDirMeas( curFieldId, value ) );
00292             }   
00293        Quantity qt( value, "s" );
00294        MEpoch mep( qt );
00295        itsMsDerived->setEpoch( mep );
00296        
00297        lastFieldId = curFieldId;
00298        
00299        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 )
00300            log->FnExit(fnname, clname);
00301        return itsMsDerived->azel().getAngle("deg").getValue("deg") (0);
00302    };
00303    
00304 
00305  private:
00306         // Variables
00307         Bool convertOnX;
00308         MSDerivedValues * itsMsDerived;
00309         Int curFieldId, lastFieldId;
00310         Vector<Int> itsFieldIds;
00311         ROMSColumns * itsColumns;
00312         
00313         // Message logger
00314         SLog* log;
00315         static const String clname;
00316         // A counter for messaging.  We really don't need to display
00317         // millions of messages for debugging purposes.  This seems
00318         // to slow things down a lot if we do anyway -- even if they
00319         // aren't printed to the logger.
00320         uInt numPlotted;
00321 };
00322 
00323 const String MSPlotConvertAzimuth::clname = "MSPlotConvertAzimuth"; 
00324 
00326 // Class used by TablePlot. The Xconvert and Yconvert methods are called
00327 // for each data point that is plotted.  This class is used when doing the
00328 // "elevation" plot
00329 
00330 class MSPlotConvertElevation : public TPConvertBase
00331 {
00332     public: 
00333    // Constructor
00334    MSPlotConvertElevation( MSDerivedValues * derived,
00335                ROMSColumns * columns,
00336                Bool onXaxis )
00337         {
00338             log = SLog::slog();
00339             String fnname = "MSPlotConvertElevation";
00340        numPlotted = 0;
00341        log->FnEnter(fnname + "(derived, columns, onXaxis)", clname);
00342        
00343        // Determine wether the converted value is along the x or
00344        // y axis.
00345        convertOnX = onXaxis;
00346 
00347        // Store the data bits we need.  We could get away with
00348        // keeping less info around.  It's the old speed versus
00349        // space trade of.
00350        itsMsDerived = derived;
00351        itsFieldIds = columns->fieldId().getColumn();
00352        itsColumns = columns;
00353 
00354        // We keep track of the lastFieldId seen by these class.
00355        // This saves us some calculation time, if the current one
00356        // is the same as the last we use the stored value rather
00357        // then recalculate.
00358        lastFieldId = -1;
00359        log->FnExit(fnname, clname);
00360    };
00361    
00362    // Destructor
00363    ~MSPlotConvertElevation() {
00364             String fnname = "~MSPlotConvertElevation";
00365        log->FnEnter(fnname, clname);
00366 
00367        log->FnExit(fnname, clname);
00368    };
00369    
00370    // Conversion along the Xaxis
00371    Double Xconvert( Double x, Int row, Int tblNum )
00372         {
00373        //cout << "NUM PLOTTED: " << numPlotted << endl;
00374        //cout << "mod value is: " << numPlotted % CASA_MPC_DBG_FREQ << endl;
00375             String fnname = "Xconvert";
00376        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {
00377        //cout << "SENDING LOG MESSAGE" << endl;
00378       log->FnEnter(fnname + "(x, row, tblNum)", clname );
00379       log->out(String("Value: ") + String::toString(x)
00380                       + " Row= " + String::toString(row)
00381                       + " Table Counter=" + String::toString(tblNum),
00382                       fnname, clname, LogMessage::DEBUG1); 
00383        }
00384        
00385        if ( convertOnX ) {
00386       numPlotted++;
00387       if ( row >= 0 && itsFieldIds.nelements() > (uInt)row ) 
00388       {
00389           if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00390          log->FnExit(fnname, clname);
00391           return findValue( x, row );
00392       } else {
00393           String err =  String( "Internal Error: Unable to convert" )
00394          + String( "elevation value, row value was: " )
00395          + String::toString( row )
00396          + String( ". Row values need to be between 0 and "  )
00397          + String::toString( itsFieldIds.nelements() );
00398           log->out( err, fnname, clname, LogMessage::SEVERE, True );
00399           // Should never get here, and exception occurs in logMessage()
00400           return x;   
00401       }
00402        } else{
00403       if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00404           log->FnExit(fnname, clname);
00405       return x;
00406        }
00407    };
00408    
00409 
00410    // Conversion along the Yaxis
00411    Double Yconvert( Double y, Int row, Int tblNum )
00412         {
00413        //cout << "NUM PLOTTED: " << numPlotted << endl;
00414        //cout << "mod value is: " << numPlotted % CASA_MPC_DBG_FREQ << endl;
00415             String fnname = "Yconvert";
00416        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {
00417       //cout << "SENDING LOG MESSAGE" << endl;
00418       log->FnEnter(fnname, clname);
00419       log->out(String("Value: ") + String::toString(y)
00420                       + " Row= " + String::toString(row)
00421                       + " Table Counter=" + String::toString(tblNum),
00422                       fnname, clname, LogMessage::DEBUG1); 
00423        }
00424        
00425        if ( !convertOnX ) {
00426       numPlotted++;
00427       if ( row >= 0 && itsFieldIds.nelements() > (uInt)row )
00428       {
00429           if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00430          log->FnExit(fnname, clname);
00431           return findValue( y, row );
00432       } else {
00433           String err =  String( "Internal Error: Unable to convert" )
00434          + String( "elevation value, row value was: " )
00435          + String::toString( row )
00436          + String( ". Row values need to be between 0 and "  )
00437          + String::toString( itsFieldIds.nelements() );
00438           log->out( err, fnname, clname, LogMessage::SEVERE, True );
00439           // Should never get here, and exception occurs in logMessage()
00440           return y;
00441       }
00442        } else {
00443       if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00444           log->FnExit(fnname, clname);
00445       return y;
00446        }
00447    };
00448 
00449     protected:
00450         Double findValue( Double value, Int row )
00451         {
00452             String fnname = "findValue";
00453        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00454       log->FnEnter(fnname + "(value, row)", clname);
00455 
00456        curFieldId = itsFieldIds( row );
00457        if ( curFieldId < 0 ||
00458           (uInt)curFieldId >= itsColumns->field().numPoly().getColumn().nelements() )
00459        {
00460       String err = String( "Internal Error: Current field ID, " )
00461           + String::toString( curFieldId )
00462           + String( " is greater then the size of fields polygon column" );
00463       log->out( err, fnname, clname, LogMessage::SEVERE, True );
00464          }
00465          if ( curFieldId != lastFieldId )
00466          {
00467         if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00468             log->out( String( "Field ID: ")+String::toString(curFieldId));
00469         if ( itsColumns->field().numPoly()(curFieldId) == 0 )
00470             itsMsDerived->setFieldCenter( itsColumns->field().phaseDirMeas( curFieldId ) );
00471         if ( itsColumns->field().numPoly()( curFieldId ) > 0 )
00472             itsMsDerived->setFieldCenter( itsColumns->field().phaseDirMeas( curFieldId, value ) );
00473          }
00474          Quantity qt( value, "s" );
00475          MEpoch mep( qt );
00476          itsMsDerived->setEpoch( mep );
00477         
00478          lastFieldId = curFieldId;
00479 
00480          if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00481         log->FnExit(fnname, clname);
00482          return itsMsDerived->azel().getAngle("deg").getValue("deg")(1);
00483    }
00484 
00485      private:
00486    // Variables
00487         Bool convertOnX;
00488    MSDerivedValues * itsMsDerived;
00489         Int curFieldId, lastFieldId;
00490         Vector<Int> itsFieldIds;
00491         ROMSColumns * itsColumns;
00492 
00493    // Message logger
00494    SLog* log;
00495         const static String clname;
00496    // A counter for messaging.  We really don't need to display
00497    // millions of messages for debugging purposes.  This seems
00498    // to slow things down a lot if we do anyway -- even if they
00499    // aren't printed to the logger.
00500    uInt numPlotted;
00501 };
00502 
00503 const String MSPlotConvertElevation::clname = "MSPlotConvertElevation";
00504 
00506 // Class used by TablePlot. The Xconvert and Yconvert methods are called
00507 // for each data point that is plotted.  This class is used when plotting
00508 // the Hourangle plot.
00509 
00510 class MSPlotConvertHourangle : public TPConvertBase
00511 {
00512     public: 
00513    // Constructor
00514    MSPlotConvertHourangle( MSDerivedValues * derived,
00515             ROMSColumns * columns,
00516             Bool onXaxis )
00517         {
00518             log = SLog::slog();
00519        numPlotted = 0;
00520        String fnname = "MSPlotConvertHourangle";
00521        log->FnEnter(fnname, clname);
00522        // Determine wether the converted value is along the x or
00523        // y axis.
00524        convertOnX = onXaxis;
00525 
00526        // Store the data bits we need.  We could get away with
00527        // keeping less info around.  It's the old speed versus
00528        // space trade of.
00529        itsMsDerived = derived;
00530        itsColumns = columns;
00531        
00532        // Set the antenna info in the MS Derived
00533        const ROMSAntennaColumns & antColumns = itsColumns->antenna();
00534 
00535        // this is the average of all antennas. Use observatory 
00536        // position instead?
00537        itsMsDerived->setAntennas( antColumns ); 
00538 
00539        // the following block is needed by parAngle()
00540        Int numAnts = antColumns.nrow();
00541        Vector<String> mount( numAnts );
00542        for (Int i=0; i < numAnts; i++) {
00543          mount(i) = antColumns.mount()(i);
00544        }
00545        itsMsDerived->setAntennaMount( mount );
00546 
00547        itsFieldIds = columns->fieldId().getColumn();
00548 
00549        lastFieldId = -1;
00550        log->FnExit(fnname, clname);
00551    };
00552    
00553    // Destructor
00554    ~MSPlotConvertHourangle() {
00555             String fnname = "~MSPlotConvertHourangle";
00556        log->FnEnter(fnname, clname);
00557 
00558        log->FnExit(fnname, clname);
00559    };
00560    
00561    // Conversion along the Xaxis
00562    Double Xconvert( Double x, Int row, Int tblNum )
00563         {
00564             String fnname = "Xconver";
00565        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {
00566       log->FnEnter(fnname + "(x, row, tblNum)", clname);   
00567       log->out(String("Value: ") + String::toString(x)
00568                       + " Row= " + String::toString(row)
00569                       + " Table Counter=" + String::toString(tblNum),
00570                       fnname, clname, LogMessage::DEBUG1); 
00571        }
00572        
00573        if ( convertOnX ) {
00574       numPlotted++;
00575       if ( row >= 0 && itsFieldIds.nelements() > (uInt)row )
00576       {
00577           if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00578          log->FnExit(fnname, clname);
00579           return findValue( x, row );
00580       } else {
00581           String err =  String( "Internal Error: Unable to convert" )
00582          + String( "hourangle value, row value was: " )
00583          + String::toString( row )
00584          + String( ". Row values need to be between 0 and "  )
00585          + String::toString( itsFieldIds.nelements() );
00586           log->out( err, fnname, clname, LogMessage::SEVERE, True );
00587           // Should never get here, and exception occurs in logMessage()
00588           return x;   
00589       }
00590        } else {
00591       if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00592           log->FnExit(fnname, clname);
00593       return x;
00594        }
00595    };
00596    
00597 
00598    // Conversion along the Yaxis
00599    Double Yconvert( Double y, Int row, Int tblNum )
00600         {
00601             String fnname = "Yconvert";
00602        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {
00603       log->FnEnter(fnname + "(y, row, tblNum)", clname );
00604       log->out(String("Value: ") + String::toString(y)
00605                       + " Row= " + String::toString(row)
00606                       + " Table Counter=" + String::toString(tblNum),
00607                       fnname, clname, LogMessage::DEBUG1); 
00608        }
00609        
00610 
00611        if ( !convertOnX )
00612       if ( row >= 0 && itsFieldIds.nelements() > (uInt)row )
00613       {
00614           if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00615          log->FnExit(fnname, clname);
00616           return findValue( y, row );
00617       } else {
00618           String err =  String( "Internal Error: Unable to convert" )
00619          + String( "hourangle value, row value was: " )
00620          + String::toString( row )
00621          + String( ". Row values need to be between 0 and "  )
00622          + String::toString( itsFieldIds.nelements() );
00623           log->out( err, fnname, clname, LogMessage::SEVERE, True );
00624           // Should never get here, and exception occurs in logMessage()
00625           return y;
00626       }
00627        else {
00628       if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00629           log->FnExit(fnname, clname);
00630       return y;
00631        }
00632    };
00633   
00634 
00635     protected:
00636         Double findValue( Double value, Int row )
00637    {
00638             String fnname = "findValue";
00639        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00640       log->FnEnter(fnname + "(value, row)", clname);
00641        curFieldId = itsFieldIds( row );
00642        if ( curFieldId < 0 ||
00643           (uInt)curFieldId >= itsColumns->field().numPoly().getColumn().nelements() )
00644        {
00645       String err = String( "Internal Error: Current field ID, " )
00646           + String::toString( curFieldId )
00647           + String( " is greater then the size of fields polygon column" );
00648       log->out( err, fnname, clname, LogMessage::SEVERE, True );
00649        }
00650        if ( curFieldId != lastFieldId )
00651        {
00652       if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00653           log->out( String( "Field ID: ")+String::toString(curFieldId));
00654       if ( itsColumns->field().numPoly()(curFieldId) == 0 )
00655           itsMsDerived->setFieldCenter( itsColumns->field().phaseDirMeas( curFieldId ) );
00656       if ( itsColumns->field().numPoly()( curFieldId ) > 0 )
00657           itsMsDerived->setFieldCenter( itsColumns->field().phaseDirMeas( curFieldId, value ) );
00658        }
00659        Quantity qt( value, "s" );
00660        MEpoch mep( qt );
00661        itsMsDerived->setEpoch( mep );
00662        
00663        lastFieldId = curFieldId;
00664 
00665        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00666       log->FnExit(fnname, clname);
00667        // itsMsDerived->hourAngle()/C::_2pi*C::day;
00668        return itsMsDerived->hourAngle()*360.0/C::_2pi;  
00669    }
00670 
00671      private:
00672    // Variables
00673         Bool convertOnX;
00674    MSDerivedValues * itsMsDerived;
00675         Int curFieldId, lastFieldId;
00676         Vector<Int> itsFieldIds;
00677         ROMSColumns * itsColumns;
00678 
00679    // Message logger
00680    SLog* log;
00681         const static String clname;
00682    // A counter for messaging.  We really don't need to display
00683    // millions of messages for debugging purposes.  This seems
00684    // to slow things down a lot if we do anyway -- even if they
00685    // aren't printed to the logger.
00686    uInt numPlotted;
00687 };
00688 
00689 const String MSPlotConvertHourangle::clname = "MSPlotConvertHourangle";
00691 // Class used by TablePlot. The Xconvert and Yconvert methods are called
00692 // for each data point that is plotted.  This class use used with the
00693 // "parallacticangle" plot.
00694 //
00695 // The values are plotted in degrees.
00696 
00697 class MSPlotConvertParallacticangle : public TPConvertBase
00698 {
00699     public: 
00700    // Constructor
00701    MSPlotConvertParallacticangle( MSDerivedValues * derived,
00702                ROMSColumns * columns,
00703                Bool onXaxis )
00704         {
00705             log = SLog::slog();
00706             String fnname = "MSPlotConvertParallacticangle";
00707        numPlotted=0;
00708        log->FnEnter(fnname + "(derived, columns, onXaxis)", clname );
00709        
00710        // Determine wether the converted value is along the x or
00711        // y axis.
00712        convertOnX = onXaxis;
00713 
00714        // Store the data bits we need.  We could get away with
00715        // keeping less info around.  It's the old speed versus
00716        // space trade of.
00717        itsMsDerived = derived;
00718        itsFieldIds = columns->fieldId().getColumn();
00719        itsColumns = columns;
00720 
00721        // We keep track of the lastFieldId seen by these class.
00722        // This saves us some calculation time, if the current one
00723        // is the same as the last we use the stored value rather
00724        // then recalculate.
00725        lastFieldId = -1;
00726 
00727        // Set the antenna info in the MS Derived
00728        const ROMSAntennaColumns & antColumns = itsColumns->antenna();
00729 
00730        // this is the average of all antennas. Use observatory 
00731        // position instead?
00732        itsMsDerived->setAntennas( antColumns ); 
00733 
00734        // the following block is needed by parAngle()
00735        Int numAnts = antColumns.nrow();
00736        Vector<String> mount( numAnts );
00737        for (Int i=0; i < numAnts; i++) {
00738          mount(i) = antColumns.mount()(i);
00739        }
00740        itsMsDerived->setAntennaMount( mount );
00741 
00742        log->FnExit(fnname, clname);
00743    };
00744    
00745    // Destructor
00746    ~MSPlotConvertParallacticangle() {
00747             String fnname = "~MSPlotConvertParallacticangle";
00748        log->FnEnter(fnname, clname);
00749 
00750        log->FnExit(fnname, clname);
00751    };
00752 
00753    // Conversion along the Xaxis
00754    Double Xconvert( Double x, Int row, Int tblNum )
00755         {
00756             String fnname = "Xconvert";
00757        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {
00758       log->FnEnter(fnname + "(x, row, tableNum)", clname );
00759                 log->out( "Value=" + String::toString(x) +
00760                           + " Row=" + String::toString(row)
00761                 + " Table Counter=" + String::toString(tblNum),
00762                  fnname, clname, LogMessage::DEBUG1); 
00763        }
00764        
00765 
00766        if ( convertOnX ) {
00767       numPlotted++;      
00768       if ( row >=  0 && itsFieldIds.nelements() > (uInt)row ) 
00769       {
00770           if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00771          log->FnExit(fnname, clname);          
00772           return findValue( x, row );
00773       } else {
00774           String err =  String( "Internal Error: Unable to convert" )
00775          + String( "parallacticangle   value, row value was: " )
00776          + String::toString( row )
00777          + String( ". Row values need to be between 0 and "  )
00778          + String::toString( itsFieldIds.nelements() );
00779           log->out( err, fnname, clname, LogMessage::SEVERE, True );
00780           // Should never get here, and exception occurs in logMessage()
00781           return x;   
00782       }
00783        } else {
00784       if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00785           log->FnExit(fnname, clname);      
00786       return x;
00787        }
00788    };
00789    
00790 
00791    // Conversion along the Yaxis
00792    Double Yconvert( Double y, Int row, Int tblNum )
00793         {
00794             String fnname = "Yconvert";
00795        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {      
00796       log->FnEnter(fnname + "(y, row, tblNum)", clname );
00797                 log->out( "Value=" + String::toString(y) +
00798                           + " Row=" + String::toString(row)
00799                 + " Table Counter=" + String::toString(tblNum),
00800                  fnname, clname, LogMessage::DEBUG1); 
00801        }
00802        
00803        if ( !convertOnX ) {
00804       numPlotted++;       
00805       if ( row >= 0 && itsFieldIds.nelements() > (uInt)row )
00806       {
00807           if ( numPlotted % CASA_MPC_DBG_FREQ == 0 )       
00808          log->FnExit(fnname, clname);          
00809           return findValue( y, row );
00810       } else {        
00811           String err =  String( "Internal Error: Unable to convert" )
00812          + String( "parallacticangle   value, row value was: " )
00813          + String::toString( row )
00814          + String( ". Row values need to be between 0 and "  )
00815          + String::toString( itsFieldIds.nelements() );
00816           log->out( err, fnname, clname, LogMessage::SEVERE, True );
00817           // Should never get here, and exception occurs in logMessage()
00818           return y;          
00819       }
00820        } else {
00821       if ( numPlotted % CASA_MPC_DBG_FREQ == 0 )       
00822           log->FnExit(fnname, clname);      
00823       return y;
00824        }
00825    };
00826 
00827     protected:
00828         Double findValue( Double value, Int row )
00829         {
00830             String fnname = "findValue";
00831        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 )       
00832       log->FnEnter( "findValue", "findValue( value, row )" );
00833        if ( itsColumns != NULL )
00834       curFieldId = itsFieldIds( row );
00835        if ( curFieldId < 0 ||
00836           (uInt)curFieldId >= itsColumns->field().numPoly().getColumn().nelements() )
00837        {
00838       String err = String( "Internal Error: Current field ID, " )
00839           + String::toString( curFieldId )
00840           + String( " is greater then the size of fields polygon column, " )
00841           + String::toString( itsColumns->field().numPoly().getColumn().nelements() );
00842       log->out(err, fnname, clname, LogMessage::SEVERE, True );
00843        }
00844          
00845        if ( curFieldId != lastFieldId )
00846        {
00847       if ( itsColumns->field().numPoly()(curFieldId) == 0 )
00848           itsMsDerived->setFieldCenter( itsColumns->field().phaseDirMeas( curFieldId ) );
00849       if ( itsColumns->field().numPoly()( curFieldId ) > 0 )
00850           itsMsDerived->setFieldCenter( itsColumns->field().phaseDirMeas( curFieldId, value ) );
00851        }
00852        Quantity qt( value, "s" );
00853        MEpoch mep( qt );
00854        itsMsDerived->setEpoch( mep );
00855         
00856        lastFieldId = curFieldId;
00857 
00858        // itsMsDerived->parAngle()/C::_2pi*C::day;
00859        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00860       log->FnExit(fnname, clname);       
00861        return itsMsDerived->parAngle()*360.0/C::_2pi; 
00862    }
00863    
00864 
00865      private:
00866    // Variables
00867         Bool convertOnX;
00868         MSDerivedValues * itsMsDerived;
00869         Int curFieldId, lastFieldId;
00870         Vector<Int> itsFieldIds;
00871         ROMSColumns * itsColumns;
00872 
00873    // Message logger
00874    SLog* log;
00875         const static String clname;
00876    // A counter for messaging.  We really don't need to display
00877    // millions of messages for debugging purposes.  This seems
00878    // to slow things down a lot if we do anyway -- even if they
00879    // aren't printed to the logger.
00880    uInt numPlotted;
00881 };
00882 
00883 const String MSPlotConvertParallacticangle::clname = 
00884              "MSPlotConvertParallacticangle";
00886 // Class used by TablePlot. The Xconvert and Yconvert methods are called
00887 // for each data point that is plotted.
00888 //
00889 // This class converts values from geocentric to topcentric frame for
00890 // the antenna position (array) plot.  The conversion routine logic
00891 // is based on Gary Li's original implementation of the MsPlot class,
00892 // although it wasn't done in a Covert class then.
00893 //
00894 // The values are plotted in meters, note if we wish to change this
00895 // to handle kilometers then just divide the results by 1000.
00896 
00897 
00898 class MSPlotConvertArrayPositions : public TPConvertBase
00899 {
00900     public: 
00901    // Constructor
00902    MSPlotConvertArrayPositions( ROMSColumns * msColumn )
00903         {
00904             log = SLog::slog();            
00905        numPlotted=0;
00906        String fnname = "MSPlotConvertArrayPositions";
00907        log->FnEnter(fnname, clname);
00908        
00909        // Calculate the converted X and Y values that will 
00910        // replace those stored in the table.
00911        itsMsColumn = msColumn;
00912        getTopocentricAnts( msColumn );
00913 
00914        log->FnExit(fnname, clname);       
00915    };
00916    
00917    // Destructor
00918    ~MSPlotConvertArrayPositions() {
00919             String fnname = "~MSPlotConvertParallacticangle";
00920        log->FnEnter(fnname, clname);
00921        
00922        delete itsMsColumn; itsMsColumn = NULL;
00923 
00924        log->FnExit(fnname, clname);       
00925    };
00926    
00927    // Conversion along the Xaxis
00928    Double Xconvert( Double x, Int row, Int tblNum )
00929         {
00930             String fnname = "Xconvert";
00931        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {
00932       log->FnEnter(fnname + "(x, row, tblNum)", clname );
00933       log->out(String("Value: ") + String::toString(x)
00934                       + " Row= " + String::toString(row)
00935                       + " Table Counter=" + String::toString(tblNum),
00936                       fnname, clname, LogMessage::DEBUG1); 
00937        }
00938               
00939        if ( (uInt)row >= itsXValues.nelements() )
00940        {
00941       String err = String( "Internal Error: Invalid array row value: " )
00942           + String::toString( row )
00943           + String( ". Expected a value less then ")
00944           + String::toString( itsXValues.nelements() );
00945           log->out( err, fnname, clname, LogMessage::SEVERE, True );
00946           // Should never get here, and exception occurs in logMessage()
00947           return x;   
00948        }
00949 
00950        numPlotted++;
00951        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00952       log->FnExit(fnname, clname);
00953        return itsXValues[ row ];
00954    };
00955 
00956 
00957    // Conversion along the Yaxis
00958    Double Yconvert( Double y, Int row, Int tblNum )
00959         {
00960             String fnname = "Yconvert";
00961        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {
00962       log->FnEnter(fnname + "(y, row, tblNum)", clname);
00963       log->out(String("Value: ") + String::toString(y)
00964                       + " Row= " + String::toString(row)
00965                       + " Table Counter=" + String::toString(tblNum),
00966                       fnname, clname, LogMessage::DEBUG1); 
00967        }
00968        
00969        
00970        if ( (uInt)row >= itsYValues.nelements() )
00971        {
00972       String err = String( "Internal Error: Invalid array row value: " )
00973           + String::toString( row )
00974           + String( ". Expected a value less then ")
00975           + String::toString( itsYValues.nelements() );
00976       log->out( err, fnname, clname, LogMessage::SEVERE, True );
00977       // Should never get here, and exception occurs in logMessage()
00978       return y;                
00979        }
00980        
00981        numPlotted++;
00982        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00983       log->FnExit(fnname, clname);             
00984        return itsYValues[ row ];
00985    };
00986   
00987 
00988     protected:
00989    MPosition 
00990    getObservatory( ROMSColumns * msColumn )
00991         {
00992             String fnname = "getObservatory";
00993        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
00994       log->FnEnter(fnname, clname);
00995        MPosition retValue;
00996        
00997        // Get the observatory details from the telescope information.
00998        String telescope = msColumn->observation().telescopeName()(0);
00999        if ( MeasTable::Observatory( retValue, telescope ) )
01000        {
01001       if ( retValue.type() != MPosition::ITRF )
01002       {
01003           MPosition::Convert toItrf( retValue, MPosition::ITRF );
01004           retValue = toItrf( retValue );
01005       }
01006        }  else {
01007          String err = String( "Error: Unable to plot telescope array" );
01008          if (telescope.length()<=0)
01009            err += String( " the name of the telescope is not stored in " )
01010              + String( " the measurement set. " );
01011          else
01012            err += String(" - ")+telescope+String(" unknown to CASA.  Please contact the helpdesk");
01013       log->out( err, fnname, clname, LogMessage::SEVERE, True );
01014       // Should never get here, and exception occurs in logMessage()
01015       return retValue;          
01016        }
01017        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01018       log->FnExit(fnname, clname);      
01019             return retValue;
01020    }
01021    
01022    Vector<MPosition>
01023    getAntennas( ROMSColumns * msColumn )
01024    {
01025             String fnname = "getAntennas";
01026        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01027       log->FnEnter(fnname, clname);
01028        
01029        Vector<MPosition> retValue( msColumn->antenna().nrow() );
01030        for( uInt i=0; i < retValue.nelements(); i++ )
01031       //retValue[i] = antPositions(i);   
01032       retValue[i] = msColumn->antenna().positionMeas()(i);   
01033 
01034        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01035       log->FnExit(fnname, clname);             
01036        return retValue;
01037    }
01038        
01039    void
01040    getTopocentricAnts( ROMSColumns * msColumn )
01041         {
01042             String fnname = "getTopocentricAnts";
01043        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01044       log->FnEnter(fnname, clname);
01045        // Get the observatory information.
01046        MPosition observatory = getObservatory( msColumn );
01047 
01048        // Get the anenna information.
01049        Vector<MPosition> antPositions = getAntennas( msColumn );
01050        
01051        // Resize the vectors we need to store the values in.
01052        uInt numAnts = antPositions.nelements();
01053        itsXValues.resize( numAnts );
01054        itsYValues.resize( numAnts );
01055        
01056        // Define some storage variables used in the loop
01057        Vector<Double> xTrans(numAnts), yTrans(numAnts), zTrans(numAnts);
01058        Vector<Double> antXYZ(3);
01059        Vector<Double> obsXYZ = observatory.get("m").getValue();
01060 
01061        // Store the cos and sin of both the longitude and
01062        // latitude of the observatory.  This is needed to 
01063        // rotate the antenna positions.
01064        Vector<Double> angles    = observatory.getAngle("rad").getValue();
01065        Double obsLongitude      = angles[0];
01066        Double obsLatitude       = angles[1];
01067        Double obsCosLongitude   = cos( obsLongitude );
01068        Double obsSinLongitude   = sin( obsLongitude );
01069        //Double obsCosLatitude    = cos( obsLatitude );
01070        Double obsSinLatitude    = sin( obsLatitude );
01071 
01072        //       cout << endl << "observatory: " << observatory << endl << 
01073        //        "lonlat = " << obsLongitude*180/3.1415 << " , " << obsLatitude*180/3.1415 << endl;
01074        //       cout << "obsXYZ = " << obsXYZ << endl;
01075        
01076        // Now do the conversion.
01077        for( uInt i=0; i < numAnts; i++ )
01078        {
01079          //      if (i<3)
01080          //        cout << i << ": " << antPositions[i] << " from " <<  (MPosition::Types)antPositions[i].type() << " to " << observatory.type() << ": ";
01081 
01082       if ( antPositions[i].type() != observatory.type() )
01083           antPositions[i] = MPosition::Convert( antPositions[i],
01084                      (MPosition::Types)observatory.type() )();
01085        
01086       // Translate the global coords to local components
01087       // without rotating.
01088       antXYZ = antPositions[i].get("m").getValue();
01089       xTrans[i] = antXYZ[0] - obsXYZ[0];
01090       yTrans[i] = antXYZ[1] - obsXYZ[1];
01091       zTrans[i] = antXYZ[2] - obsXYZ[2];
01092       
01093       //      if (i<3) cout << "Trans = " << xTrans[i] << "," << yTrans[i] << "," << zTrans[i] << endl;
01094 
01095       // Now rotate and store the new position information
01096       itsXValues[i] = ( -obsSinLongitude * xTrans[i] )
01097           + ( obsCosLongitude * yTrans[i] );
01098       itsYValues[i] = ( -obsSinLatitude * obsCosLongitude * xTrans[i] )
01099           - ( obsSinLatitude * obsSinLongitude * yTrans[i] )
01100           + zTrans[i];
01101        }
01102 
01103        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01104       log->FnExit(fnname, clname);      
01105    }
01106    
01107      private:
01108    // Variables
01109    ROMSColumns * itsMsColumn;
01110         Bool convertOnX;
01111    Vector<Double> itsXValues;
01112    Vector<Double> itsYValues;
01113 
01114    // Message logger
01115    SLog* log;
01116         static const String clname;
01117 
01118    // A counter for messaging.  We really don't need to display
01119    // millions of messages for debugging purposes.  This seems
01120    // to slow things down a lot if we do anyway -- even if they
01121    // aren't printed to the logger.
01122    uInt numPlotted;
01123 };
01124 
01125 const String MSPlotConvertArrayPositions::clname = "MSPlotConvertArrayPositions";
01126 
01128 // Class used by TablePlot. The Xconvert and Yconvert methods are called
01129 // for each data point that is plotted.
01130 //
01131 // This class converts channel indices (0-based) to frequency.
01132 //
01133 // Note that if the values coming to the convert functions are non-integer
01134 // this means that we've done some averaging and we need to average the
01135 // frequencies for this value. The values could be integers as well,
01136 // with averaging if choosen correctly
01137 //
01138 // The values are plotted in GHz,
01139 
01140 class MSPlotConvertChanToFreq : public TPConvertBase
01141 {
01142     public: 
01143    // Constructor
01144    MSPlotConvertChanToFreq( Vector<Int> inIds,
01145       MsPlot *inMsPlot,
01146       Bool inAveOn,
01147       Vector< Vector<Int> > &inStartChans,
01148       Vector< Vector<Int> > &inEndChans,
01149       Vector< Vector<Int> > &inStepChans,
01150       Bool onXAxis )
01151         {
01152             log = SLog::slog();
01153        numPlotted=0;
01154        String fnname = "MSPlotConvertChanToFreq";
01155        log->FnEnter(fnname + 
01156               "(Ids, MS, average, startChans, endChans, stepChans)", clname);
01157        // Store the list of Ids for each table locally.
01158        // The Ids are currently SPWs, but in the future
01159        // the will be Data Desc Ids.
01160        itsSpwIds = inIds;
01161 
01162        // Store the Measurement Set data locally
01163        itsMsPlot = inMsPlot;
01164 
01165        // Store the channel averaging information.
01166        itsAveragingOn = inAveOn;
01167        itsStartChans = inStartChans;
01168        itsEndChans = inEndChans;
01169        itsStepChans = inStepChans;
01170        
01171        // Store which axis we are converting on.
01172        convertOnX = onXAxis;
01173        
01174        //showConverter();
01175        log->FnExit(fnname, clname);
01176    };
01177 
01178    void showConverter() {
01179        cout << "itsSpwIds=" << itsSpwIds << endl;
01180        cout << "itsAveragingOn=" << itsAveragingOn << endl;
01181        for (uInt i = 0; i < itsStartChans.nelements(); i++) {
01182           cout << "itsStartChans=" << itsStartChans(i) << endl;
01183           cout << "itsEndChans=" << itsEndChans(i) << endl;
01184           cout << "itsStepChans=" << itsStepChans(i) << endl;
01185        }
01186        cout << "convertOnX=" << convertOnX;
01187    }
01188    
01189    // Destructor
01190    ~MSPlotConvertChanToFreq() {
01191             String fnname = "~MSPlotConvertChanToFreq";
01192        log->FnEnter(fnname, clname);
01193 
01194        log->FnExit(fnname, clname);
01195    };
01196 
01197    // This is a MAJOR HACK to support multiple spws!!!
01198    // Just a word of warning that this really needs to
01199    // be cleaned up at some point.
01200    void setSpwIds( Vector<Int> inIds )  { itsSpwIds = inIds; };
01201    
01202    
01203    // Conversion along the Xaxis
01204    Double
01205    Xconvert_col( Double x, Int row, Int tblnum )
01206    {
01207       String fnname = "Xconvert_col";
01208 
01209        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 )
01210           log->FnEnter(fnname + "(x, row, tblnum)", clname );
01211        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {      
01212            log->out(String("Value=") + String::toString(x) +
01213                    " Row=" + String::toString(row) +
01214                    " Table Counter=" + String::toString(tblnum),
01215                    fnname, clname, LogMessage::DEBUG1);   
01216        }
01217        
01218        if ( ! convertOnX )
01219        {
01220            if ( numPlotted % CASA_MPC_DBG_FREQ == 0 )
01221                log->FnExit(fnname, clname);
01222            return x;
01223        } else {
01224            numPlotted++;      
01225            // Check table number with our list of SPW Ids and get the
01226            // spwId for the table
01227            Int spwId = getSpwId( tblnum );
01228 
01229            if ( ! itsAveragingOn )
01230            {
01231                // Look up the frequency from our stored information.
01232                if ( numPlotted % CASA_MPC_DBG_FREQ == 0 )
01233                    log->FnExit(fnname, clname);
01234 
01235                return itsMsPlot->getChanFrequency( spwId, Int(x) ) / 1.0e9;
01236            } else {
01237                // If channels are averaged then
01238                
01239                if ( numPlotted % CASA_MPC_DBG_FREQ == 0 )
01240                    log->FnExit(fnname, clname);
01241                Vector<Int> chanRange = getChannelRange( x, spwId );
01242                return getAveFreq( chanRange, tblnum );
01243            }
01244        }
01245    };
01246 
01247 
01248    // Conversion along the Yaxis
01249    Double
01250    Yconvert_col( Double y, Int row, Int tblnum )
01251    {
01252        String fnname = "Yconvert";
01253        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01254            log->FnEnter(fnname, clname);
01255        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {
01256            log->out(String("Value=") + String::toString(y) +
01257                    " Row=" + String::toString(row) +
01258                    " Table Counter=" + String::toString(tblnum),
01259                    fnname, clname, LogMessage::DEBUG1);   
01260        }
01261                 
01262        
01263        if ( convertOnX )
01264        {
01265            if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01266                log->FnExit(fnname, clname);
01267            return y;
01268        } else {
01269            numPlotted++;      
01270            // Check table number with our list of SPW Ids and get the
01271            // spwId for the table
01272            Int spwId = getSpwId( tblnum );
01273       
01274            if ( ! itsAveragingOn )
01275            {
01276                // Look up the frequency from our stored information.
01277                if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01278                    log->FnExit(fnname, clname);
01279                return itsMsPlot->getChanFrequency( spwId, Int(y) ) / 1.0e9;
01280            } else {
01281                // If channels are averaged then
01282                Vector<Int> chanRange = getChannelRange( y, spwId );
01283                if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01284                    log->FnExit(fnname, clname);
01285                return getAveFreq( chanRange, tblnum );
01286            }
01287        }
01288    };
01289   
01290 
01291     protected:
01292    // Check if the supplied table ID is smaller then our
01293    // list of Ids.  If it's larger and exception is thrown.
01294    Int
01295    getSpwId( Int tblNum )
01296    {
01297        String fnname = "getSpwId";
01298        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01299                 log->FnEnter(fnname, clname);
01300 
01301        Int retValue = -1;
01302 
01303        // Check that our tblNum is with in range.
01304        if ( tblNum < 0 || (uInt)tblNum > itsSpwIds.nelements() )
01305        {
01306            String err = String( "Internal Error: Invalid table number: " )
01307                + String::toString( tblNum )
01308                + String( " given to MsPlotConvertChanToFreq.\n" )
01309                + String( " Expected values are from 0 to " )
01310                + String::toString( itsSpwIds.nelements() );
01311            log->out( err, fnname, clname, LogMessage::SEVERE, True);
01312            // Should never get here, and exception occurs in logMessage()
01313            return retValue;                      
01314        }
01315        
01316              
01317        // If we are here all is good, and we can simply look up the
01318        // Spw ID from our Id list.
01319             // What?-----------------
01320        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01321            log->FnExit(fnname, clname);
01322        retValue = itsSpwIds[tblNum];
01323 
01324        return retValue;
01325    };
01326 
01327    // If the averaging is on then the channel value passed in
01328    // is an averaged channel value.  We need to find the channel
01329    // range that this value came from, ie. the value is between
01330    // the start and end values.
01331    //
01332    // Comment, it might be useful to pre-compute the averaged values
01333    // in the constructor.  They could be computed if the start, end,
01334    // and step values are given.  Then we'd just need to search for
01335    // the matching number.  However, this may not work if we compute
01336    // the average differently then TablePlot.
01337    Vector<Int>
01338    getChannelRange( Double aveChanValue, Int spwId )
01339    {
01340        String fnname = "getChannelRange";
01341        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01342       log->FnEnter(fnname + "(aveChanValue, spwId)", clname);
01343        
01344        Vector<int> retValue;
01345 
01346        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01347       log->out(String(" Finding a freqency range for: ")
01348                          +String::toString(aveChanValue));
01349 
01350        // Loop through your list of channel start and end values
01351        // looking for an averaging range that our channel value is
01352        // between.
01353        // TODO deal with min/max values.  ie. if there is no
01354        // start or end value.
01355        // TODO if stepchan < 2 then we aren't averaging, may want
01356        // to make this a special case.
01357        Int start=-1; Int end=-1;
01358        for ( uInt i=0; i < itsEndChans[spwId].nelements(); i++ )
01359        {
01360       if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) { 
01361          ostringstream os;
01362          os  << "Checking " << i << " set of channel info: "
01363          << itsStartChans[spwId][i]
01364          << "~" << itsEndChans[spwId][i]
01365          << "^"  << itsStepChans[spwId][i];
01366                     log->out(os, fnname, clname, LogMessage::DEBUG1);
01367                 }
01368       
01369       for ( Int chan = itsStartChans[spwId][i];
01370             chan < itsEndChans[spwId][i];
01371             chan += itsStepChans[spwId][i] )
01372       {
01373           if ( chan < 0 )
01374          chan = 0;
01375           if ( chan <= aveChanValue
01376              && chan+itsStepChans[spwId][i] >= aveChanValue )
01377           {
01378          start = chan;
01379          end = chan + itsStepChans[spwId][i];
01380          break;
01381           }
01382       }
01383        }
01384        
01385 
01386        if ( start < 0 && end < 0 )
01387       start = end = Int( aveChanValue );
01388 
01389        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01390       log->out(String("Averaging range is from ") + 
01391                       String::toString(start)
01392           + String(" to ") + String::toString(end), 
01393                     fnname, clname, LogMessage::DEBUG1 );
01394        retValue.resize( end - start + 1 );
01395        for( uInt i=0; i < (uInt)(end-start+1); i++ )
01396       retValue[i] = start + i;
01397 
01398        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01399       log->FnExit(fnname, clname);
01400        return retValue;
01401    };
01402 
01403    // Get the averaged frequency for the averaged channel
01404    // value.
01405    Double
01406    getAveFreq( Vector<Int> chanRange, Int tblNum )
01407    {
01408             String fnname = "getAveFreq";
01409        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01410       log->FnEnter(fnname + "(chanRange, tblNum)", clname);
01411        
01412        Double sum = 0.0;
01413 
01414        for ( uInt i=0; i < chanRange.nelements(); i++ )
01415        {
01416            //sum += getFreq( chanRange[i], tblNum );
01417            sum += 
01418                itsMsPlot->getChanFrequency( tblNum, chanRange[i] ) / 1.0e9;
01419        }
01420 
01421        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01422       log->FnExit(fnname, clname);
01423        return sum / chanRange.nelements();
01424    };
01425 
01426 
01427    // Get the frequency associated with this channel
01428    // Routine based on demo4 in tTablePlot.cc, written by
01429    // Urvashi R.V.
01430    Double
01431    getFreq( Int channel, Int spwId )
01432    {
01433        String fnname = "getFreq";
01434        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01435            log->FnEnter(fnname + "(channel, spwId)", clname);
01436        
01437        return itsMsPlot->getChanFrequency( spwId, channel ) / 1.0e9;
01438    };
01439    
01440      private:
01441    // Measurement set the data belongs to.
01442    MsPlot *itsMsPlot;
01443 
01444    // List of Ids assoc. with each table given to TablePlot.
01445    // May not need this,  Its needed if different tables passed
01446    // in have different channel ranges.  Not that index 0, is
01447    // the SPW ID of table 0, ...
01448    Vector<Int> itsSpwIds;
01449 
01450    // Averaging information, the list of averaged ranges in
01451    // two lists.  The list in which each range starts on and
01452    // the list each range ends on.
01453    Bool itsAveragingOn;
01454    Vector< Vector< Int > > itsStartChans;
01455    Vector< Vector< Int > > itsStepChans;
01456    Vector< Vector< Int > > itsEndChans;
01457 
01458    // Indicate if we are averaging on the X or Y axis.
01459    Bool convertOnX;
01460 
01461    // Message logger
01462    SLog* log;
01463         static const String clname;
01464    // A counter for messaging.  We really don't need to display
01465    // millions of messages for debugging purposes.  This seems
01466    // to slow things down a lot if we do anyway -- even if they
01467    // aren't printed to the logger.
01468    uInt numPlotted;
01469 };
01470 
01471 
01473 // Class used by TablePlot. The Xconvert and Yconvert methods are called
01474 // for each data point that is plotted.
01475 //
01476 // This class converts channel indices (0-based) to velocity (km/s).
01477 //
01478 // Note that if the values coming to the convert functions are non-integer
01479 // this means that we've done some averaging and we need to average the
01480 // frequencies for this value. The values could be integers as well,
01481 // with averaging if choosen correctly
01482 //
01483 // The values are plotted in Km/s,
01484 
01485 class MSPlotConvertChanToVelocity : public TPConvertBase
01486 {
01487     public: 
01488     // Constructor
01489     MSPlotConvertChanToVelocity( Vector<Int> inSpwIds, ROMSColumns * columns,
01490            MsPlot *inMsPlot, Bool onXAxis )
01491    {
01492        log = SLog::slog();
01493        numPlotted=0;
01494        String fnname = "MSPlotConvertChanToVelocity";
01495        log->FnEnter(fnname + 
01496               "(Ids, MS, average, startChans, endChans, stepChans)", clname);
01497 
01498        // Store the list of Ids for each table locally.
01499        // The Ids are currently SPWs, but in the future
01500        // the will be Data Desc Ids.
01501        itsSpwIds = inSpwIds;
01502 
01503 
01504        // Store the list of field Ids for each table row locally.
01505        // If in the future we have DATA DESC IDs we can likely
01506        // retrieve this using the measurement set.
01507        itsFieldIds = columns->fieldId().getColumn();
01508 
01509        // Store the Measurement Set data locally
01510        itsMsPlot = inMsPlot;
01511 
01512        // Store which axis we are converting on.
01513        convertOnX = onXAxis;
01514        
01515        log->FnExit(fnname, clname);
01516    };
01517    
01518    // Destructor
01519    ~MSPlotConvertChanToVelocity() {
01520        String fnname = "~MSPlotConvertChanToVelocity";
01521        log->FnEnter(fnname, clname);
01522 
01523        log->FnExit(fnname, clname);
01524    };
01525 
01526    // This is a MAJOR HACK to support multiple spws!!!
01527    // Just a word of warning that this really needs to
01528    // be cleaned up at some point.
01529    void setSpwIds( Vector<Int> inIds )  { itsSpwIds = inIds; };
01530    
01531    // Conversion along the Xaxis
01532    Double
01533    Xconvert_col( Double x, Int row, Int tblnum )
01534    {
01535        String fnname = "Xconvert_col";
01536 
01537        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 )
01538            log->FnEnter(fnname + "(x, row, tblnum)", clname );
01539        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {      
01540            log->out(String("Value=") + String::toString(x) +
01541                    " Row=" + String::toString(row) +
01542                    " Table Counter=" + String::toString(tblnum),
01543                    fnname, clname, LogMessage::DEBUG1);   
01544        }
01545 
01546        numPlotted++;      
01547        if ( ! convertOnX )
01548        {
01549            if ( numPlotted % CASA_MPC_DBG_FREQ == 0 )
01550                log->FnExit(fnname, clname);
01551            return x;
01552        } else {
01553            // Check table number with our list of SPW Ids and get the
01554            // spwId for the table
01555            Int spwId = getSpwId( tblnum );
01556 
01557            // Find the field Number associated with this Row of data.
01558            Int fieldId = getFieldId( row );
01559 
01560            // Look up the frequency from our stored information.
01561            if ( numPlotted % CASA_MPC_DBG_FREQ == 0 )
01562                log->FnExit(fnname, clname);
01563 
01564            return itsMsPlot->getChanVelocity( spwId, fieldId, uInt(x) );
01565        }
01566    };
01567 
01568 
01569    // Conversion along the Yaxis
01570    Double
01571    Yconvert_col( Double y, Int row, Int tblnum )
01572    {
01573        String fnname = "Yconvert";
01574        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01575            log->FnEnter(fnname, clname);
01576        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) {
01577            log->out(String("Value=") + String::toString(y) +
01578                    " Row=" + String::toString(row) +
01579                    " Table Counter=" + String::toString(tblnum),
01580                    fnname, clname, LogMessage::DEBUG1);   
01581        }
01582                 
01583        numPlotted++;      
01584        if ( convertOnX )
01585        {
01586            if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01587                log->FnExit(fnname, clname);
01588            return y;
01589        } else {
01590            // Check table number with our list of SPW Ids and get the
01591            // spwId for the table
01592            Int spwId = getSpwId( tblnum );
01593 
01594            // Find the field Number associated with this Row of data.
01595            Int fieldId = getFieldId( row );
01596 
01597            // Look up the frequency from our stored information.
01598            if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01599                log->FnExit(fnname, clname);
01600            return itsMsPlot->getChanVelocity( spwId, fieldId, uInt(y) );
01601        }
01602    };
01603 
01604  protected:
01605    // Check if the supplied table ID is smaller then our
01606    // list of Ids.  If it's larger and exception is thrown.
01607    Int
01608    getSpwId( Int tblNum )
01609    {
01610        String fnname = "getSpwId";
01611        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01612                 log->FnEnter(fnname, clname);
01613 
01614        Int retValue = -1;
01615 
01616        // Check that our tblNum is with in range.
01617        if ( tblNum < 0 || (uInt)tblNum > itsSpwIds.nelements() )
01618        {
01619            String err = String( "Internal Error: Invalid table number: " )
01620                + String::toString( tblNum )
01621                + String( " given to MsPlotConvertChanToVelocity.\n" )
01622                + String( " Expected values are from 0 to " )
01623                + String::toString( itsSpwIds.nelements() );
01624            log->out( err, fnname, clname, LogMessage::SEVERE, True);
01625            // Should never get here, and exception occurs in logMessage()
01626            return retValue;                      
01627        }
01628        
01629              
01630        // If we are here all is good, and we can simply look up the
01631        // Spw ID from our stored list.
01632        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01633            log->FnExit(fnname, clname);
01634        retValue = itsSpwIds[tblNum];
01635 
01636        return retValue;
01637    };
01638 
01639 
01640    // Check if the supplied row number and if valid then get
01641    // the field ID.
01642    Int
01643    getFieldId( Int rowNum )
01644    {
01645        String fnname = "getFieldId";
01646        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01647                 log->FnEnter(fnname, clname);
01648 
01649        Int retValue = -1;
01650 
01651        // Check that our rowNum is with in range.
01652        if ( rowNum < 0 || (uInt)rowNum > itsFieldIds.nelements() )
01653        {
01654            String err = String( "Internal Error: Invalid row number: " )
01655                + String::toString( rowNum )
01656                + String( " given to MsPlotConvertChanToVelocity.\n" )
01657                + String( " Expected values are from 0 to " )
01658                + String::toString( itsFieldIds.nelements() );
01659            log->out( err, fnname, clname, LogMessage::SEVERE, True);
01660            // Should never get here, and exception occurs in logMessage()
01661            return retValue;                      
01662        }
01663        
01664              
01665        // If we are here all is good, and we can simply look up the
01666        // Field ID from our stored list.
01667        if ( numPlotted % CASA_MPC_DBG_FREQ == 0 ) 
01668            log->FnExit(fnname, clname);
01669        retValue = itsFieldIds[rowNum];
01670 
01671        return retValue;
01672    };
01673 
01674  private:
01675    // Measurement set the data belongs to.
01676    MsPlot *itsMsPlot;
01677 
01678    // List of Ids assoc. with each table given to TablePlot.
01679    // May not need this,  Its needed if different tables passed
01680    // in have different channel ranges.  Not that index 0, is
01681    // the SPW ID of table 0, ...
01682    Vector<Int> itsSpwIds;
01683 
01684 
01685    // List of Field Ids assoc. with each row of data given to TablePlot.
01686    Vector<Int> itsFieldIds;
01687 
01688    // Averaging information, the list of averaged ranges in
01689    // two lists.  The list in which each range starts on and
01690    // the list each range ends on.
01691    Bool itsAveragingOn;
01692    Vector< Vector< Int > > itsStartChans;
01693    Vector< Vector< Int > > itsStepChans;
01694    Vector< Vector< Int > > itsEndChans;
01695 
01696    // Indicate if we are averaging on the X or Y axis.
01697    Bool convertOnX;
01698 
01699    // Message logger
01700    SLog* log;
01701    static const String clname;
01702    
01703    // A counter for messaging.  We really don't need to display
01704    // millions of messages for debugging purposes.  This seems
01705    // to slow things down a lot if we do anyway -- even if they
01706    // aren't printed to the logger.
01707    uInt numPlotted;
01708 };
01709 
01710 
01711 const String MSPlotConvertChanToVelocity::clname = "MSPlotConvertChanToVelocity";
01712 const String MSPlotConvertChanToFreq::clname = "MSPlotConvertChanToFreq";
01713 
01715 class MSPlotConvertAveChanToFreq : public TPConvertBase
01716 {
01717    public: 
01718    //It would be ideal to calculate the chanFreq in the averager
01719    //and pass the map to here. However, in the setupPlotxy,
01720    //setConverFn is before setInputTable (because a conversion
01721    //function change may require a reread of the ms), then
01722    //we have to reset conversion function after averager
01723    //
01724    MSPlotConvertAveChanToFreq(MeasurementSet &inMS, 
01725                              Matrix<Double> &chanFreq, Bool onXAxis) {
01726    
01727       log = SLog::slog();
01728       String fnname = "MSPlotConvertAveChanToFreq";
01729        
01730       itsMS = inMS;
01731       itsChanFreq = chanFreq;
01732 
01733       //cout << "itsChanFreq=" << itsChanFreq << endl;
01734       convertOnX = onXAxis;
01735    };
01736 
01737    
01738    ~MSPlotConvertAveChanToFreq() {
01739       //String fnname = "~MSPlotConvertAveChanToFreq";
01740    };
01741 
01742    // Conversion along the Xaxis
01743    Double Xconvert_col(Double x, Int IfLOG0(row), Int IfLOG0(tableId)) {
01744       String fnname = "Xconvert_col";
01745 #if LOG0
01746       static int a = 0;
01747       String fncall = String("Value=") + String::toString(x) +
01748                " Row=" + String::toString(row) +
01749                " Table Counter=" + String::toString(tableId);
01750       if (x != 0 && a < 10) {
01751          log->FnPass(fnname + fncall, clname);
01752          a++;
01753       }
01754 #endif
01755        
01756       if (!convertOnX) {
01757           return x;
01758       } 
01759       else {
01760          Int chn = max(0, Int(x)); 
01761          chn = min(chn, Int(itsChanFreq.nrow() - 1));
01762          return itsChanFreq(chn, 1);
01763       }
01764    };
01765 
01766    // Conversion along the Yaxis
01767    Double Yconvert_col(Double y, Int IfLOG0(row), Int IfLOG0(tableId)) {
01768       String fnname = "Yconvert";
01769 #if LOG0
01770       static int b = 0;
01771       String fncall = String("Value=") + String::toString(y) +
01772                " Row=" + String::toString(row) +
01773                " Table Counter=" + String::toString(tableId);
01774       if (b < 10 &&  y != 0) {
01775          log->FnPass(fnname + fncall, clname);
01776          b++;
01777       }
01778 #endif
01779                 
01780       if (convertOnX) {
01781          return y;
01782       } 
01783       else {
01784          Int chn = max(0, Int(y)); 
01785          chn = min(chn, Int(itsChanFreq.nrow() - 1));
01786          return itsChanFreq(chn, 1);
01787       }
01788    };
01789   
01790    private:
01791 
01792       //not used. the frequency calculation is done in the averager.
01793       MeasurementSet itsMS;
01794 
01795       //itsChanFreq is of nAveChan x 2. The first column stores
01796       //the averaged channel Id (hence is equal to the position index.)
01797       //The second column store averaged frequencies corresponding to
01798       //the averaged channel Id. 
01799       //The first column can be used to store the spwids in the future. 
01800       Matrix<Double> itsChanFreq;
01801 
01802       // Indicate if we are averaging on the X or Y axis.
01803       Bool convertOnX;
01804 
01805       SLog* log;
01806       static const String clname;
01807 };
01808 
01809 const String MSPlotConvertAveChanToFreq::clname = "MSPlotConverAveChanToFreq";
01810 
01812 class MSPlotConvertAveChanToChan : public TPConvertBase
01813 {
01814    public: 
01815    MSPlotConvertAveChanToChan(MeasurementSet &inMS, 
01816                              Matrix<Int> &chanFreq, Bool onXAxis) {
01817    
01818       log = SLog::slog();
01819       String fnname = "MSPlotConvertAveChanToChan";
01820        
01821       itsMS = inMS;
01822 
01823       Int nChan = chanFreq.nrow();
01824       //cout << "chanFreq=" << chanFreq << endl;
01825       //cout << "nChan=" << nChan << endl;
01826       itsChanMap.resize(nChan);
01827       //cout << "itsChanMap.shape()[0]=" << itsChanMap.shape()[0] << endl;
01828       for (Int k = 0; k < nChan; k++) {
01829          itsChanMap(k) = (chanFreq(k, 1) + chanFreq(k, 2) - 1) / 2;
01830       }
01831       //cout << "itsChanMap=" << itsChanMap << endl;
01832 
01833       convertOnX = onXAxis;
01834    };
01835 
01836    
01837    ~MSPlotConvertAveChanToChan() {
01838       //String fnname = "~MSPlotConvertAveChanToChan";
01839    };
01840 
01841    // Conversion along the Xaxis
01842    Double Xconvert_col(Double x, Int IfLOG0(row), Int IfLOG0(tableId)) {
01843       String fnname = "Xconvert";
01844 #if LOG0
01845       static int a = 0;
01846       String fncall = String("Value=") + String::toString(x) +
01847                " Row=" + String::toString(row) +
01848                " Table Counter=" + String::toString(tableId);
01849       if (x != 0 && a < 10) {
01850          log->FnPass(fnname + fncall, clname);
01851          a++;
01852       }
01853 #endif
01854        
01855       if (!convertOnX) {
01856           return x;
01857       } 
01858       else {
01859          Int chn = max(0, Int(x)); 
01860          chn = min(chn, Int(itsChanMap.shape()[0] - 1));
01861          cout << " " << itsChanMap(chn);
01862          return itsChanMap(chn);
01863       }
01864    };
01865 
01866    // Conversion along the Yaxis
01867    Double Yconvert_col(Double y, Int IfLOG0(row), Int IfLOG0(tableId)) {
01868       String fnname = "Yconvert";
01869 #if LOG0
01870       static int b = 0;
01871       String fncall = String("Value=") + String::toString(y) +
01872                " Row=" + String::toString(row) +
01873                " Table Counter=" + String::toString(tableId);
01874       if (b < 10 &&  y != 0) {
01875          log->FnPass(fnname + fncall, clname);
01876          b++;
01877       }
01878 #endif
01879                 
01880       if (convertOnX) {
01881          return y;
01882       } 
01883       else {
01884          Int chn = max(0, Int(y)); 
01885          chn = min(chn, Int(itsChanMap.shape()[0] - 1));
01886          return itsChanMap(chn);
01887       }
01888    };
01889   
01890    private:
01891 
01892       //not used. the frequency calculation is done in the averager.
01893       MeasurementSet itsMS;
01894 
01895       Vector<Int> itsChanMap;
01896 
01897       // Indicate if we are averaging on the X or Y axis.
01898       Bool convertOnX;
01899 
01900       SLog* log;
01901       static const String clname;
01902 };
01903 
01904 const String MSPlotConvertAveChanToChan::clname = "MSPlotConverAveChanToChan";
01905 
01906 };
01907 #endif //CASA_MSPLOT__CONVERT_H
01908 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines