source: trunk/src/PlotHelper.cpp @ 2951

Last change on this file since 2951 was 2951, checked in by Kana Sugimoto, 10 years ago

New Development: No

JIRA Issue: Yes (CAS-5870)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: sdplot with plottype='grid' and polaverage=True

Put in Release Notes: No

Module(s): sdplot, PlotHelper?

Description: Fixed a bug reported by Shinya. There was an issue in auto center and cell size resolution when scantable has only one pointing.


File size: 14.3 KB
Line 
1//
2// C++ Interface: PlotHelper
3//
4// Description:
5//    A small helper class to handle direction coordinate in asapplotter
6//
7// Author: Kana Sugimoto <kana.sugi@nao.ac.jp>, (C) 2012
8//
9// Copyright: See COPYING file that comes with this distribution
10//
11//
12
13// casacore
14#include <casa/Arrays/Vector.h>
15#include <casa/Quanta/Quantum.h>
16#include <casa/Quanta/QuantumHolder.h>
17#include <casa/Quanta/MVAngle.h>
18#include <casa/Logging/LogIO.h>
19
20#include <measures/Measures/MDirection.h>
21#include <tables/Tables/TableRecord.h>
22
23
24#include "PlotHelper.h"
25
26#define SMALL_ANGLE 1.0e-7
27
28// #ifndef KS_DEBUG
29// #define KS_DEBUG
30// #endif
31
32using namespace std ;
33using namespace casa ;
34using namespace asap ;
35
36namespace asap {
37
38PlotHelper::PlotHelper() : dircoord_p(0)
39{
40#ifdef KS_DEBUG
41  cout << "Default constructor nrow = " << data_p->nrow() << endl;
42#endif
43};
44
45PlotHelper::PlotHelper( const ScantableWrapper &s) : dircoord_p(0)
46{
47#ifdef KS_DEBUG
48  cout << "Constructing PlotHelper with scantable wrapper" << endl;
49#endif
50  setScantable(s);
51};
52
53PlotHelper::~PlotHelper(){
54#ifdef KS_DEBUG
55  cout << "Called PlotHelper destructor" << endl;
56#endif
57  if (dircoord_p){
58#ifdef KS_DEBUG
59    cout << "Destructing dircoord_p" << endl;
60#endif
61    delete dircoord_p;
62    dircoord_p = 0;
63  }
64};
65
66void PlotHelper::setScantable( const ScantableWrapper &s )
67{
68#ifdef KS_DEBUG
69  cout << "Setting scantable" << endl;
70#endif
71  data_p = s.getCP();
72};
73
74
75DirectionCoordinate PlotHelper::getSTCoord(const int nx, const int ny,
76                                           const Projection::Type ptype)
77{
78  LogIO os(LogOrigin("PlotHelper","getSTCoord()", WHERE));
79  os << "Getting pointing information of the scantable." << LogIO::POST;
80  if (data_p->nrow() < 1)
81    throw AipsError("Scantable is not set. Please set a scantable first.");
82
83  // First, generate rough direction coordinate.
84  DirectionCoordinate coord;
85  Double incx, incy;
86  MDirection::Types mdt;
87  ROArrayColumn<Double> dircol;
88  Double xmax, xmin, ymax, ymin;
89  Double centx, centy;
90  Matrix<Double> xform(2,2);
91  xform = 0.0;
92  xform.diagonal() = 1.0;
93  // Rough estimates of center and cell from scantable DIRECTIONs.
94  dircol.attach( data_p->table(), "DIRECTION" );
95  const Vector<String> udir = dircol.keywordSet().asArrayString("QuantumUnits");
96  const Matrix<Double> direction = dircol.getColumn();
97  minMax(xmin, xmax, direction.row(0));
98  minMax(ymin, ymax, direction.row(1));
99  if (!MDirection::getType(mdt, data_p->getDirectionRefString()))
100    throw AipsError("Failed to get direction reference from scantable.");
101  centx = 0.5 * (xmin + xmax);
102  centy = 0.5 * (ymin + ymax);
103  incx = abs(xmax - xmin) / (double) nx * cos(centy);
104  incy = abs(ymax - ymin) / (double) ny;
105  // Direction coordinate seems not work well with inc=0. set very small value.
106  if (incx == 0.) incx = SMALL_ANGLE;
107  if (incy == 0.) incy = SMALL_ANGLE;
108  // Generate a temporal direction coordinte
109  coord = DirectionCoordinate(mdt, ptype,
110                                centx, centy, incx, incy, xform,
111                                0.5*Double(nx), 0.5*Double(ny));
112  coord.setWorldAxisUnits(udir);
113#ifdef KS_DEBUG
114  {//Debug outputs
115    cout << "Generated a temporal direction coordinate of a scantable: " << endl;
116    Vector<String> units = coord.worldAxisUnits();
117    Vector<Double> refv = coord.referenceValue();
118    cout <<"- Reference: " << MDirection::showType(coord.directionType()) << " " << refv[0] << units[0] << " " << refv[1] << units[1]  << endl;
119    Vector<Double> refpix = coord.referencePixel();
120    cout <<"- Reference Pixel: [" << refpix[0] << ", " << refpix[1] << "]" << endl;
121    Vector<Double> inc = coord.increment();
122    cout <<"- Increments: [" << inc[0] << ", " << inc[1] << "]" << endl;
123    cout <<"- Projection: " << coord.projection().name() << endl;
124  }
125#endif
126  return coord;
127}
128
129void PlotHelper::setGridParam(const int nx, const int ny,
130                              const string cellx, const string celly,
131                              string center, const string projname)
132{
133  LogIO os(LogOrigin("PlotHelper","setGridParam()", WHERE));
134  // Value check of nx and ny
135  if (nx < 1)
136    throw(AipsError("nx should be > 0"));
137  if (ny < 1)
138    throw(AipsError("ny should be > 0"));
139  // Destroy old coord
140  if (dircoord_p){
141#ifdef KS_DEBUG
142    cout << "Destructing old dircoord_p" << endl;
143#endif
144    delete dircoord_p;
145    dircoord_p = 0;
146  }
147
148  // Check for availability of data_p
149  const bool stset = ((data_p->nrow() > 0) ? true : false);
150  const bool needst = center.empty() || (cellx.empty() && celly.empty());
151  if (needst && !stset)
152    throw AipsError("Could not resolve grid parameters. Please set a scantable first.");
153
154  // projection
155  Projection::Type projtype(Projection::type(String(projname)));
156
157  // Calculate projected map center (in world coordinate)
158  // and extent (in pixel coordinate) from scantable DIRECIONs (if necessary).
159  MDirection stcent;
160  Double stxmax, stxmin, stymax, stymin;
161  MDirection::Types stdt;
162  DirectionCoordinate stcoord;
163  Quantum<Double> stincx, stincy;
164  if (needst && stset) {
165    stcoord = getSTCoord(nx, ny, projtype);
166    Vector<Double> inc = stcoord.increment();
167    Vector<String> units = stcoord.worldAxisUnits();
168    stincx = Quantum<Double>(inc[0], units[0]);
169    stincy = Quantum<Double>(inc[1], units[0]);
170    stdt = stcoord.directionType();
171    // Get the extent of directions in Pixel coordinate
172    ROArrayColumn<Double> dircol;
173    dircol.attach( data_p->table(), "DIRECTION" );
174    const Matrix<Double> direction = dircol.getColumn();
175    Matrix<Double> dirpix;
176    Vector<Bool> failures;
177    if (!stcoord.toPixelMany(dirpix, direction, failures))
178      throw AipsError("Failed to get directions in pixel coordinate.");
179    minMax(stxmin, stxmax, dirpix.row(0));
180    minMax(stymin, stymax, dirpix.row(1));
181    // Get the direction center in World coordinate.
182    Vector<Double> centpix(2);
183    centpix[0] = 0.5 * (stxmin + stxmax);
184    centpix[1] = 0.5 * (stymin + stymax);
185    stcoord.toWorld(stcent, centpix);
186#ifdef KS_DEBUG
187    {//Debug output
188      Quantum< Vector<Double> > qcent;
189      cout << "Got the center and map extent of scantable." << endl;
190      qcent = stcent.getAngle();
191      cout << "- Center of DIRECTIONs: " << stcent.getRefString() << " "
192           << qcent.getValue()[0] << qcent.getUnit() << " "
193           << qcent.getValue()[1] << qcent.getUnit() << endl;
194      cout << "- Map extent: [" << (stxmax-stxmin)*stincx.getValue() << ", "
195           << (stymax-stymin)*stincy.getValue() << "] ( " << stincx.getUnit() << ")" << endl;
196    }
197#endif
198  }
199
200  os << "Setting grid parameters" << LogIO::POST;
201  // Now, define direction coordinate from input parameters (in radian)
202  Double incx, incy;
203  Double centx, centy;
204  MDirection::Types mdt;
205  // center
206  if (center.empty()){
207    os << "center is not specified. Using pointing center of the scantable." << LogIO::POST;
208    if (!stset)
209      throw AipsError("Scantable is not set. Could not resolve map center.");
210
211    centx = stcent.getAngle("rad").getValue()[0];
212    centy = stcent.getAngle("rad").getValue()[1];
213    mdt = stdt;
214  } else {
215    os << "Using user defined center" << LogIO::POST;
216    // Parse center string
217    string::size_type pos0 = center.find(" ");
218   
219    if (pos0 == string::npos)
220      throw AipsError("bad string format in center direction");
221
222    string::size_type pos1 = center.find(" ", pos0+1);
223    String sepoch, sra, sdec;
224    if (pos1 != string::npos) {
225      sepoch = center.substr(0, pos0);
226      sra = center.substr(pos0+1, pos1-pos0);
227      sdec = center.substr(pos1+1);
228    } else {
229      sepoch = "J2000";
230      sra = center.substr(0, pos0);
231      sdec = center.substr(pos0+1);
232    }
233    if (!MDirection::getType(mdt,sepoch))
234      throw AipsError("Invalid direction reference in center");
235    if (stset){
236      if ( !needst &&
237           !MDirection::getType( stdt, data_p->getDirectionRefString() ) )
238        throw AipsError("Failed to get direction reference from scantable.");
239      if (mdt != stdt)
240        throw AipsError("Direction reference of center should be the same as input scantable");
241    }
242    QuantumHolder qh ;
243    String err ;
244    qh.fromString(err, sra);
245    Quantum<Double> ra  = qh.asQuantumDouble();
246    qh.fromString(err, sdec) ;
247    Quantum<Double> dec = qh.asQuantumDouble();
248    centx = ra.getValue("rad");
249    centy = dec.getValue("rad");
250    // rotaion
251    if (stset) {
252      Double stcentx = stcent.getAngle("rad").getValue()[0];
253      Double rotnum = round( abs(centx - stcentx) / (C::_2pi) );
254      if (centx < stcentx) rotnum *= -1;
255      centx -= (rotnum * C::_2pi);
256    }
257  }
258  os << "Grid center: ( "  << centx  << " rad , " << centy << " rad ) " << LogIO::POST;
259
260  // cell
261  if (cellx.empty() && celly.empty()){
262    os << "cell size is not specified. Using cell size to cover all pointings in the scantable." << LogIO::POST;
263    if (!stset)
264      throw AipsError("Scantable is not set. Could not resolve cell size.");
265
266    Vector<Double> centpix;
267    MDirection centmd = MDirection(Quantum<Double>(centx, "rad"),
268                                   Quantum<Double>(centy, "rad"), mdt);
269    stcoord.toPixel(centpix, centmd);
270#ifdef KS_DEBUG
271    cout << "- got centpix [" << centpix[0] << ", " << centpix[1] << "]" <<endl;
272#endif
273    // Direction coordinate seems not work well with inc=0. set very small value.
274    Double wx = max( max( abs(stxmax-centpix[0]), abs(stxmin-centpix[0]) ), 0.5 )
275      * 2 * stincx.getValue("rad");
276    Double wy = max( max( abs(stymax-centpix[1]), abs(stymin-centpix[1]) ), 0.5 )
277      * 2 * stincy.getValue("rad");
278    incx = wx / max(nx - 1., 1.);
279    incy = wy / max(ny - 1., 1.);
280  } else {
281    os << "Using user defined cell size" << LogIO::POST;
282    Quantum<Double> qcellx, qcelly;
283    if (!cellx.empty() && !celly.empty()){
284      readQuantity(qcellx, String(cellx));
285      readQuantity(qcelly, String(celly));
286    } else if (celly.empty()) {
287      readQuantity(qcellx, String(cellx));
288      qcelly = qcellx;
289    } else { //only celly is defined
290      readQuantity(qcelly, String(celly));
291      qcellx = qcelly;
292    }
293    incx = qcellx.getValue("rad");
294    incy = qcelly.getValue("rad");
295  }
296  // inc should be negative to transpose plot
297  incx = -abs(incx);
298  incy = -abs(incy);
299
300  os << "Spacing: ( " << abs(incx) << " rad , " << abs(incy) << " rad )" <<endl;
301
302  setupCoord(mdt, projtype, centx, centy, incx, incy,
303             0.5*Double(nx), 0.5*Double(ny)) ; // pixel at center)
304
305};
306
307void PlotHelper::setGridParamVal(const int nx, const int ny,
308                                 const double cellx, const double celly,
309                                 const double centx, const double centy,
310                                 const string epoch, const string projname){
311  LogIO os(LogOrigin("PlotHelper","setGridParamVal()", WHERE));
312  // Value check of nx and ny
313  if (nx < 1)
314    throw(AipsError("nx should be > 0"));
315  if (ny < 1)
316    throw(AipsError("ny should be > 0"));
317  // Destroy old coord
318  if (dircoord_p){
319#ifdef KS_DEBUG
320    cout << "Destructing old dircoord_p" << endl;
321#endif
322    delete dircoord_p;
323    dircoord_p = 0;
324  }
325
326  // center (in rad)
327  Double centX(centx), centY(centy);
328  // cell size (in rad)
329  Double incX(cellx), incY(celly);
330  // epoch
331  MDirection::Types mdt;
332  MDirection::getType(mdt, String(epoch));
333  // projection
334  Projection::Type projType(Projection::type(String(projname)));
335
336  setupCoord(mdt, projType, centX, centY, incX, incY,
337             0.5*Double(nx), 0.5*Double(ny)) ; // pixel at center
338//           0.5*Double(nx-1), 0.5*Double(ny-1)) ; // pixel at grid
339
340};
341
342
343void PlotHelper::setupCoord(const MDirection::Types mdt,
344                            const Projection::Type pjt,
345                            const Double centx, const Double centy,
346                            const Double incx, const Double incy,
347                            const Double refx, const Double refy)
348{
349  LogIO os(LogOrigin("PlotHelper","setupCoord()", WHERE));
350  // Destroy old coord
351  if (dircoord_p){
352#ifdef KS_DEBUG
353    cout << "Destructing old dircoord_p" << endl;
354#endif
355    delete dircoord_p;
356    dircoord_p = 0;
357  }
358
359  Matrix<Double> xform(2,2) ;
360  xform = 0.0 ;
361  xform.diagonal() = 1.0 ;
362  dircoord_p = new DirectionCoordinate(mdt, pjt, centx, centy, incx, incy,
363                                      xform, refx, refy);
364  {//Summary
365    os << "Successfully generated grid coordinate:" << LogIO::POST;
366    Vector<String> units = dircoord_p->worldAxisUnits();
367    Vector<Double> refv = dircoord_p->referenceValue();
368    os <<"- Reference Direction : "
369       << MDirection::showType(dircoord_p->directionType())
370       << " " << refv[0] << units[0] << " " << refv[1] << units[1] << LogIO::POST;
371    Vector<Double> refpix = dircoord_p->referencePixel();
372    os <<"- Reference Pixel     : [" << refpix[0] << ", " << refpix[1] << "]" << LogIO::POST;
373    Vector<Double> inc = dircoord_p->increment();
374    os <<"- Increments          : [" << inc[0] << ", " << inc[1] << "]" << LogIO::POST;
375    os <<"- Projection Type     : " << dircoord_p->projection().name() << LogIO::POST;
376  }
377};
378
379vector<double>  PlotHelper::getGridPixel(const int whichrow)
380{
381  if (data_p->nrow() < 1)
382    throw AipsError("Scantable is not set. Could not get direction.");
383  else if (whichrow > int(data_p->nrow()) - 1)
384    throw AipsError("Row index out of range.");
385  if (!dircoord_p)
386    throw AipsError("Direction coordinate is not defined.");
387
388  Vector<Double> pixel;
389  MDirection world;
390  vector<double> outvec;
391  world = data_p->getDirection(whichrow);
392#ifdef KS_DEBUG
393  cout << "searching pixel position (world = " << data_p->getDirectionString(whichrow) << " = [" << world.getAngle("rad").getValue()[0] << ", " << world.getAngle("rad").getValue()[1] << "])" << endl;
394#endif
395  dircoord_p->toPixel(pixel, world);
396#ifdef KS_DEBUG
397  cout << "got pixel = [" << pixel[0] << ", " << pixel[1] << "]" << endl;
398#endif
399  // convert pixel to std vector
400  pixel.tovector(outvec);
401  return outvec;
402};
403
404string PlotHelper::getGridRef()
405{
406  if (!dircoord_p)
407    throw AipsError("Direction coordinate is not defined. Please set it first.");
408
409  string outref;
410
411  Vector<String> units = dircoord_p->worldAxisUnits();
412  Vector<Double> refv = dircoord_p->referenceValue();
413  MVAngle lon( Quantum<Double>(refv[0], units[0]) );
414  MVAngle lat ( Quantum<Double>(refv[1], units[1]) );
415  outref = MDirection::showType(dircoord_p->directionType()) + " "
416    + lon(0.0).string(MVAngle::TIME, 9) + " "
417    + lat.string(MVAngle::ANGLE+MVAngle::DIG2, 9);
418
419  return outref;
420};
421
422vector<double>  PlotHelper::getGridCellVal()
423{
424  if (!dircoord_p)
425    throw AipsError("Direction coordinate is not defined. Please set it first.");
426
427  vector<double> outinc(2);
428  Vector<Double> inc = dircoord_p->increment();
429  Vector<String> units = dircoord_p->worldAxisUnits();
430  MVAngle qincx( Quantum<Double>(inc[0], units[0]) );
431  MVAngle qincy( Quantum<Double>(inc[1], units[1]) );
432  outinc[0] = (double) abs(qincx.radian());
433  outinc[1] = (double) abs(qincy.radian());
434
435  return outinc;
436};
437
438
439} //namespace asap
Note: See TracBrowser for help on using the repository browser.