source: trunk/src/STApplyCal.cpp @ 2727

Last change on this file since 2727 was 2727, checked in by Takeshi Nakazato, 11 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.