source: trunk/src/STApplyCal.cpp@ 2720

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

New Development: Yes

JIRA Issue: Yes CAS-4770 and its sub-tickets

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...

First version of applycal for single dish calibration.
Added new classes for the operation (STApplyCal, Calibrator, PSAlmaCalibrator,
Locator, BisectionLocator, Interpolator1D, NearestInterpolator1D).
Also, modified existing classes to fit with implementation of applycal.


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