source: trunk/src/STApplyCal.cpp @ 2733

Last change on this file since 2733 was 2733, checked in by Takeshi Nakazato, 11 years ago

New Development: No

JIRA Issue: Yes CAS-4770

Ready for Test: Yes

Interface Changes: Yes/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...

Redefined Interpolator1D and derived classes as template class.


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