source: trunk/src/PlotHelper.cpp@ 2717

Last change on this file since 2717 was 2717, checked in by Kana Sugimoto, 13 years ago

New Development: Yes

JIRA Issue: No

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: added a new method, set_grid(), in plothelper class.

Test Programs: test_sdplot[sdplot_gridTest]

Put in Release Notes: Yes

Module(s): asapplotter, sdplot(plottype='grid')

Description:

The method, asapplotter.plotgrid(), considers tangential projection
effects when getting grid center and extents from a scantable.
This affects behavior of plottype='grid' in sdplot task of CASA.

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