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

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