source: trunk/src/STApplyCal.cpp@ 2779

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

New Development: No

JIRA Issue: Yes CAS-4770

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: test_sdcal2

Put in Release Notes: No

Module(s): Module Names change impacts.

Description: Describe your changes here...

  • Throw exception when empty string is specified in STApplyTable::save().
  • Use TSYS in the data when Tsys calibration is not done.


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