casa
$Rev:20696$
|
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