source: trunk/src/STApplyCal.cpp@ 2731

Last change on this file since 2731 was 2727, checked in by Takeshi Nakazato, 12 years ago

New Development: No

JIRA Issue: Yes CAS-4770, CAS-4774

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Updated STApplyCal to be able to specify interpolation method.
The method can be specified in time and frequency axes independently.
Possible options are nearest, linear (default), (natural) cubic spline,
and polynomial with arbitrary order.

File size: 15.7 KB
Line 
1//
2// C++ Implementation: STApplyCal
3//
4// Description:
5//
6//
7// Author: Takeshi Nakazato <takeshi.nakazato@nao.ac.jp> (C) 2012
8//
9// Copyright: See COPYING file that comes with this distribution
10//
11//
12#include <assert.h>
13
14#include <casa/Arrays/Array.h>
15#include <casa/Arrays/Vector.h>
16#include <casa/Arrays/Matrix.h>
17#include <casa/Arrays/ArrayIO.h>
18#include <casa/Arrays/ArrayMath.h>
19#include <casa/BasicSL/String.h>
20#include <casa/Logging/LogIO.h>
21#include <casa/Exceptions/Error.h>
22#include <casa/Utilities/CountedPtr.h>
23#include <casa/Utilities/Sort.h>
24#include <tables/Tables/Table.h>
25
26#include "Scantable.h"
27#include "STApplyCal.h"
28#include "STApplyTable.h"
29#include "STCalTsysTable.h"
30#include "STCalSkyTable.h"
31#include "STCalEnum.h"
32#include "STIdxIter.h"
33#include "Calibrator.h"
34#include "PSAlmaCalibrator.h"
35#include "NearestInterpolator1D.h"
36#include "BufferedLinearInterpolator1D.h"
37#include "PolynomialInterpolator1D.h"
38#include "CubicSplineInterpolator1D.h"
39#include <atnf/PKSIO/SrcType.h>
40
41
42using namespace casa;
43using namespace std;
44
45namespace asap {
46
47STApplyCal::STApplyCal()
48{
49 init();
50}
51
52STApplyCal::STApplyCal(CountedPtr<Scantable> target)
53 : target_(target)
54{
55 init();
56}
57
58STApplyCal::~STApplyCal()
59{
60}
61
62void STApplyCal::init()
63{
64 caltype_ = STCalEnum::NoType;
65 doTsys_ = False;
66 interp_.resize((int)STCalEnum::NumAxis);
67 // default is linear interpolation
68 for (unsigned int i = 0; i < interp_.size(); i++) {
69 interp_[i] = STCalEnum::LinearInterpolation;
70 }
71}
72
73void STApplyCal::setTarget(CountedPtr<Scantable> target)
74{
75 target_ = target;
76}
77
78void STApplyCal::setTarget(const String &name)
79{
80 // always create PlainTable
81 target_ = new Scantable(name, Table::Plain);
82}
83
84void STApplyCal::push(STCalSkyTable *table)
85{
86 skytable_.push_back(table);
87 STCalEnum::CalType caltype = STApplyTable::getCalType(table);
88 os_ << "caltype=" << caltype << LogIO::POST;
89 if (caltype_ == STCalEnum::NoType ||
90 caltype_ == STCalEnum::DefaultType ||
91 caltype_ == STCalEnum::CalTsys) {
92 caltype_ = caltype;
93 }
94 os_ << "caltype_=" << caltype_ << LogIO::POST;
95}
96
97void STApplyCal::push(STCalTsysTable *table)
98{
99 tsystable_.push_back(table);
100 doTsys_ = True;
101}
102
103void STApplyCal::setInterpolation(STCalEnum::InterpolationAxis axis, STCalEnum::InterpolationType itype, Int order)
104{
105 interp_[(int)axis] = itype;
106 order_ = order;
107}
108
109void STApplyCal::setTsysTransfer(uInt from, Vector<uInt> to)
110{
111 os_ << "from=" << from << ", to=" << to << LogIO::POST;
112 map<uInt, Vector<uInt> >::iterator i = spwmap_.find(from);
113 if (i == spwmap_.end()) {
114 spwmap_.insert(pair<uInt, Vector<uInt> >(from, to));
115 }
116 else {
117 Vector<uInt> toNew = i->second;
118 spwmap_.erase(i);
119 uInt k = toNew.nelements();
120 toNew.resize(k+to.nelements(), True);
121 for (uInt i = 0; i < to.nelements(); i++)
122 toNew[i+k] = to[i];
123 spwmap_.insert(pair<uInt, Vector<uInt> >(from, toNew));
124 }
125}
126
127void STApplyCal::apply(Bool insitu)
128{
129 // calibrator
130 if (caltype_ == STCalEnum::CalPSAlma)
131 calibrator_ = new PSAlmaCalibrator();
132
133 // interpolator
134 initInterpolator();
135
136 // select data
137 sel_.reset();
138 if (caltype_ == STCalEnum::CalPSAlma ||
139 caltype_ == STCalEnum::CalPS) {
140 sel_.setTypes(vector<int>(1,(int)SrcType::PSON));
141 }
142 target_->setSelection(sel_);
143
144 os_ << "sel_.print()=" << sel_.print() << LogIO::POST;
145
146 // working data
147 if (insitu)
148 work_ = target_;
149 else
150 work_ = new Scantable(*target_, false);
151
152 os_ << "work_->nrow()=" << work_->nrow() << LogIO::POST;
153
154 // list of apply tables for sky calibration
155 Vector<uInt> skycalList;
156 uInt numSkyCal = 0;
157 uInt nrowSky = 0;
158 // list of apply tables for Tsys calibration
159// Vector<uInt> tsyscalList;
160
161 for (uInt i = 0 ; i < skytable_.size(); i++) {
162 STCalEnum::CalType caltype = STApplyTable::getCalType(skytable_[i]);
163 if (caltype == caltype_) {
164 skycalList.resize(numSkyCal+1, True);
165 skycalList[numSkyCal] = i;
166 numSkyCal++;
167 nrowSky += skytable_[i]->nrow();
168 }
169 }
170
171
172 vector<string> cols( 3 ) ;
173 cols[0] = "BEAMNO" ;
174 cols[1] = "POLNO" ;
175 cols[2] = "IFNO" ;
176 CountedPtr<STIdxIter> iter = new STIdxIterAcc(work_, cols) ;
177 while (!iter->pastEnd()) {
178 Vector<uInt> ids = iter->current();
179 Vector<uInt> rows = iter->getRows(SHARE);
180 os_ << "ids=" << ids << LogIO::POST;
181 if (rows.nelements() > 0)
182 doapply(ids[0], ids[2], ids[1], rows, skycalList);
183 iter->next();
184 }
185
186 target_->unsetSelection();
187}
188
189void STApplyCal::doapply(uInt beamno, uInt ifno, uInt polno,
190 Vector<uInt> &rows,
191 Vector<uInt> &skylist)
192{
193 os_ << "skylist=" << skylist << LogIO::POST;
194 os_ << "rows=" << rows << LogIO::POST;
195 Bool doTsys = doTsys_;
196
197 //STSelector sel = sel_;
198 STSelector sel;
199 vector<int> id(1);
200 id[0] = beamno;
201 sel.setBeams(id);
202 id[0] = ifno;
203 sel.setIFs(id);
204 id[0] = polno;
205 sel.setPolarizations(id);
206 os_ << "sel=" << sel.print() << LogIO::POST;
207
208 // apply selection to apply tables
209 uInt nrowSky = 0;
210 uInt nrowTsys = 0;
211 for (uInt i = 0; i < skylist.nelements(); i++) {
212 skytable_[skylist[i]]->setSelection(sel);
213 nrowSky += skytable_[skylist[i]]->nrow();
214 os_ << "nrowSky=" << nrowSky << LogIO::POST;
215 }
216 uInt nchanTsys = 0;
217 Vector<Double> ftsys;
218 uInt tsysifno = getIFForTsys(ifno);
219 os_ << "tsysifno=" << tsysifno << LogIO::POST;
220 if (tsystable_.size() == 0) {
221 os_.origin(LogOrigin("STApplyTable", "doapply", WHERE));
222 os_ << "No Tsys tables are given. Skip Tsys calibratoin." << LogIO::POST;
223 doTsys = False;
224 }
225 else if (tsysifno == (uInt)-1) {
226 os_.origin(LogOrigin("STApplyTable", "doapply", WHERE));
227 os_ << "No corresponding Tsys for IFNO " << ifno << ". Skip Tsys calibration" << LogIO::POST;
228 doTsys = False;
229 }
230 else {
231 nchanTsys = tsystable_[0]->nchan(tsysifno);
232 ftsys = tsystable_[0]->getBaseFrequency(0);
233 interpolatorF_->setX(ftsys.data(), nchanTsys);
234 os_ << "nchanTsys=" << nchanTsys << LogIO::POST;
235 id[0] = (int)tsysifno;
236 sel.setIFs(id);
237 for (uInt i = 0; i < tsystable_.size() ; i++) {
238 tsystable_[i]->setSelection(sel);
239 nrowTsys += tsystable_[i]->nrow();
240 os_ << "nrowTsys=" << nrowTsys << LogIO::POST;
241 }
242 }
243
244 uInt nchanSp = skytable_[skylist[0]]->nchan(ifno);
245 os_ << "nchanSp = " << nchanSp << LogIO::POST;
246 Vector<Double> timeSky(nrowSky);
247 Matrix<Float> spoff(nchanSp, nrowSky);
248 Vector<Float> iOff(nchanSp);
249 nrowSky = 0;
250 os_ << "spoff.shape()=" << spoff.shape() << LogIO::POST;
251 for (uInt i = 0 ; i < skylist.nelements(); i++) {
252 STCalSkyTable *p = skytable_[skylist[i]];
253 os_ << "table " << i << ": nrow=" << p->nrow() << LogIO::POST;
254 Vector<Double> t = p->getTime();
255 Matrix<Float> sp = p->getSpectra();
256 os_ << "sp.shape()=" << sp.shape() << LogIO::POST;
257 os_ << "t.nelements()=" << t.nelements() << LogIO::POST;
258 for (uInt j = 0; j < t.nelements(); j++) {
259 timeSky[nrowSky] = t[j];
260 os_ << "timeSky[" << nrowSky << "]-timeSky[0]=" << timeSky[nrowSky] - timeSky[0] << LogIO::POST;
261 spoff.column(nrowSky) = sp.column(j);
262 nrowSky++;
263 }
264 }
265 os_ << "timeSky-timeSky[0]=" << timeSky-timeSky[0] << LogIO::POST;
266
267 Vector<uInt> skyIdx = timeSort(timeSky);
268 os_ << "skyIdx = " << skyIdx << LogIO::POST;
269
270 double *xa = new double[skyIdx.nelements()];
271 float *ya = new float[skyIdx.nelements()];
272 IPosition ipos(1, skyIdx.nelements());
273 Vector<double> timeSkySorted(ipos, xa, TAKE_OVER);
274 Vector<Float> tmpOff(ipos, ya, TAKE_OVER);
275 for (uInt i = 0 ; i < skyIdx.nelements(); i++) {
276 timeSkySorted[i] = (double)timeSky[skyIdx[i]];
277 os_ << "timeSkySorted[" << i << "]-timeSkySorted[0]=" << timeSkySorted[i] - timeSkySorted[0] << LogIO::POST;
278 }
279 os_ << "timeSkySorted-timeSkySorted[0]=" << timeSkySorted-timeSkySorted[0] << LogIO::POST;
280
281 interpolatorS_->setX(xa, skyIdx.nelements());
282
283 os_ << "doTsys = " << doTsys << LogIO::POST;
284 Vector<uInt> tsysIdx;
285 Vector<Double> timeTsys(nrowTsys);
286 Matrix<Float> tsys;
287 Vector<double> timeTsysSorted;
288 Vector<Float> tmpTsys;
289 if (doTsys) {
290 os_ << "doTsys" << LogIO::POST;
291 timeTsys.resize(nrowTsys);
292 tsys.resize(nchanTsys, nrowTsys);
293 nrowTsys = 0;
294 for (uInt i = 0 ; i < tsystable_.size(); i++) {
295 STCalTsysTable *p = tsystable_[i];
296 os_ << "p->nrow()=" << p->nrow() << LogIO::POST;
297 Vector<Double> t = p->getTime();
298 os_ << "t=" << t << LogIO::POST;
299 Matrix<Float> ts = p->getTsys();
300 for (uInt j = 0; j < t.nelements(); j++) {
301 timeTsys[nrowTsys] = t[j];
302 tsys.column(nrowTsys) = ts.column(j);
303 nrowTsys++;
304 }
305 }
306 tsysIdx = timeSort(timeTsys);
307 os_ << "tsysIdx = " << tsysIdx << LogIO::POST;
308
309 double *xb = new double[tsysIdx.nelements()];
310 float *yb = new float[tsysIdx.nelements()];
311 IPosition ipos(1, tsysIdx.nelements());
312 timeTsysSorted.takeStorage(ipos, xb, TAKE_OVER);
313 tmpTsys.takeStorage(ipos, yb, TAKE_OVER);
314 for (uInt i = 0 ; i < tsysIdx.nelements(); i++) {
315 timeTsysSorted[i] = (double)timeTsys[tsysIdx[i]];
316 os_ << "timeTsysSorted[" << i << "]-timeTsysSorted[0]=" << timeTsysSorted[i] - timeTsysSorted[0] << LogIO::POST;
317 }
318 os_ << "timeTsysSorted=" << timeTsysSorted << LogIO::POST;
319 interpolatorT_->setX(xb, tsysIdx.nelements());
320 }
321
322 Table tab = work_->table();
323 ArrayColumn<Float> spCol(tab, "SPECTRA");
324 ScalarColumn<Double> timeCol(tab, "TIME");
325 Vector<Float> on;
326 for (uInt i = 0; i < rows.nelements(); i++) {
327 os_ << "start row " << i << LogIO::POST;
328 uInt irow = rows[i];
329
330 // target spectral data
331 on = spCol(irow);
332 calibrator_->setSource(on);
333
334 // interpolation
335 double t0 = (double)timeCol(irow);
336 for (uInt ichan = 0; ichan < nchanSp; ichan++) {
337 Vector<Float> spOffSlice = spoff.row(ichan);
338 //os_ << "spOffSlice = " << spOffSlice << LogIO::POST;
339 for (uInt j = 0; j < skyIdx.nelements(); j++) {
340 tmpOff[j] = (float)spOffSlice[skyIdx[j]];
341 }
342 interpolatorS_->setY(ya, skyIdx.nelements());
343 iOff[ichan] = interpolatorS_->interpolate(t0);
344 }
345 //os_ << "iOff=" << iOff << LogIO::POST;
346 calibrator_->setReference(iOff);
347
348 Float *Y = new Float[nchanSp];
349 Vector<Float> iTsys(IPosition(1,nchanSp), Y, TAKE_OVER);
350 if (doTsys) {
351 // Tsys correction
352 float *yt = new float[nchanTsys];
353 Vector<Float> iTsysT(IPosition(1,nchanTsys), yt, TAKE_OVER);
354 float *yb = tmpTsys.data();
355 for (uInt ichan = 0; ichan < nchanTsys; ichan++) {
356 Vector<Float> tsysSlice = tsys.row(ichan);
357 for (uInt j = 0; j < tsysIdx.nelements(); j++) {
358 tmpTsys[j] = (float)tsysSlice[tsysIdx[j]];
359 }
360 interpolatorT_->setY(yb, tsysIdx.nelements());
361 iTsysT[ichan] = interpolatorT_->interpolate(t0);
362 }
363 os_ << "iTsysT=" << iTsysT << LogIO::POST;
364 if (nchanSp == 1) {
365 // take average
366 iTsys[0] = mean(iTsysT);
367 }
368 else {
369 // interpolation on frequency axis
370 os_ << "getBaseFrequency for target" << LogIO::POST;
371 Vector<Double> fsp = getBaseFrequency(rows[i]);
372 os_ << "fsp = " << fsp << LogIO::POST;
373 interpolatorF_->setY(yt, nchanTsys);
374 for (uInt ichan = 0; ichan < nchanSp; ichan++) {
375 iTsys[ichan] = (Float)interpolatorF_->interpolate(fsp[ichan]);
376 }
377 }
378 }
379 else {
380 iTsys = 1.0;
381 }
382 os_ << "iTsys=" << iTsys << LogIO::POST;
383 calibrator_->setScaler(iTsys);
384
385 // do calibration
386 calibrator_->calibrate();
387
388 // update table
389 os_ << "calibrated=" << calibrator_->getCalibrated() << LogIO::POST;
390 spCol.put(irow, calibrator_->getCalibrated());
391
392 }
393
394
395 // reset selection on apply tables
396 for (uInt i = 0; i < skylist.nelements(); i++)
397 skytable_[i]->unsetSelection();
398 for (uInt i = 0; i < tsystable_.size(); i++)
399 tsystable_[i]->unsetSelection();
400
401
402 // reset interpolator
403 interpolatorS_->reset();
404 interpolatorF_->reset();
405 interpolatorT_->reset();
406}
407
408Vector<uInt> STApplyCal::timeSort(Vector<Double> &t)
409{
410 Sort sort;
411 sort.sortKey(&t[0], TpDouble, 0, Sort::Ascending);
412 Vector<uInt> idx;
413 sort.sort(idx, t.nelements(), Sort::QuickSort|Sort::NoDuplicates);
414 return idx;
415}
416
417uInt STApplyCal::getIFForTsys(uInt to)
418{
419 for (map<casa::uInt, Vector<uInt> >::iterator i = spwmap_.begin();
420 i != spwmap_.end(); i++) {
421 Vector<uInt> tolist = i->second;
422 os_ << i->first << ": tolist=" << tolist << LogIO::POST;
423 for (uInt j = 0; j < tolist.nelements(); j++) {
424 if (tolist[j] == to)
425 return i->first;
426 }
427 }
428 return (uInt)-1;
429}
430
431void STApplyCal::save(const String &name)
432{
433 if (work_.null())
434 return;
435
436 work_->setSelection(sel_);
437 work_->makePersistent(name);
438 work_->unsetSelection();
439}
440
441Vector<Double> STApplyCal::getBaseFrequency(uInt whichrow)
442{
443 assert(whichrow <= (uInt)work_->nrow());
444 ROTableColumn col(work_->table(), "IFNO");
445 uInt ifno = col.asuInt(whichrow);
446 col.attach(work_->table(), "FREQ_ID");
447 uInt freqid = col.asuInt(whichrow);
448 uInt nc = work_->nchan(ifno);
449 STFrequencies ftab = work_->frequencies();
450 Double rp, rf, inc;
451 ftab.getEntry(rp, rf, inc, freqid);
452 Vector<Double> r(nc);
453 indgen(r, rf-rp*inc, inc);
454 return r;
455}
456
457void STApplyCal::initInterpolator()
458{
459 int ta = (int)STCalEnum::TimeAxis;
460 int fa = (int)STCalEnum::FrequencyAxis;
461 int order = (order_ > 0) ? order_ : 1;
462 switch (interp_[ta]) {
463 case STCalEnum::NearestInterpolation:
464 {
465 os_ << "use NearestInterpolator in time axis" << LogIO::POST;
466 interpolatorS_ = new NearestInterpolator1D();
467 interpolatorT_ = new NearestInterpolator1D();
468 break;
469 }
470 case STCalEnum::LinearInterpolation:
471 {
472 os_ << "use BufferedLinearInterpolator in time axis" << LogIO::POST;
473 interpolatorS_ = new BufferedLinearInterpolator1D();
474 interpolatorT_ = new BufferedLinearInterpolator1D();
475 break;
476 }
477 case STCalEnum::CubicSplineInterpolation:
478 {
479 os_ << "use CubicSplineInterpolator in time axis" << LogIO::POST;
480 interpolatorS_ = new CubicSplineInterpolator1D();
481 interpolatorT_ = new CubicSplineInterpolator1D();
482 break;
483 }
484 case STCalEnum::PolynomialInterpolation:
485 {
486 os_ << "use PolynomialInterpolator in time axis" << LogIO::POST;
487 if (order == 0) {
488 interpolatorS_ = new NearestInterpolator1D();
489 interpolatorT_ = new NearestInterpolator1D();
490 }
491 else {
492 interpolatorS_ = new PolynomialInterpolator1D();
493 interpolatorT_ = new PolynomialInterpolator1D();
494 interpolatorS_->setOrder(order);
495 interpolatorT_->setOrder(order);
496 }
497 break;
498 }
499 default:
500 {
501 os_ << "use BufferedLinearInterpolator in time axis" << LogIO::POST;
502 interpolatorS_ = new BufferedLinearInterpolator1D();
503 interpolatorT_ = new BufferedLinearInterpolator1D();
504 break;
505 }
506 }
507
508 switch (interp_[fa]) {
509 case STCalEnum::NearestInterpolation:
510 {
511 os_ << "use NearestInterpolator in frequency axis" << LogIO::POST;
512 interpolatorF_ = new NearestInterpolator1D();
513 break;
514 }
515 case STCalEnum::LinearInterpolation:
516 {
517 os_ << "use BufferedLinearInterpolator in frequency axis" << LogIO::POST;
518 interpolatorF_ = new BufferedLinearInterpolator1D();
519 break;
520 }
521 case STCalEnum::CubicSplineInterpolation:
522 {
523 os_ << "use CubicSplineInterpolator in frequency axis" << LogIO::POST;
524 interpolatorF_ = new CubicSplineInterpolator1D();
525 break;
526 }
527 case STCalEnum::PolynomialInterpolation:
528 {
529 os_ << "use PolynomialInterpolator in frequency axis" << LogIO::POST;
530 if (order == 0) {
531 interpolatorF_ = new NearestInterpolator1D();
532 }
533 else {
534 interpolatorF_ = new PolynomialInterpolator1D();
535 interpolatorF_->setOrder(order);
536 }
537 break;
538 }
539 default:
540 {
541 os_ << "use LinearInterpolator in frequency axis" << LogIO::POST;
542 interpolatorF_ = new BufferedLinearInterpolator1D();
543 break;
544 }
545 }
546}
547}
Note: See TracBrowser for help on using the repository browser.