source: trunk/src/STApplyCal.cpp @ 2752

Last change on this file since 2752 was 2750, checked in by Takeshi Nakazato, 11 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: List test programs

Put in Release Notes: Yes/No?

Module(s): Module Names change impacts.

Description: Describe your changes here...

Various fixes to avoid segmentation fault, and a few updates on
python interface.


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