source: trunk/src/CalibrationHelper.h@ 2970

Last change on this file since 2970 was 2919, checked in by Takeshi Nakazato, 10 years ago

New Development: No

JIRA Issue: No

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

Refactoring.


File size: 13.2 KB
Line 
1#include <vector>
2
3#include <casa/Arrays/Vector.h>
4#include <casa/BasicSL/String.h>
5#include <casa/Utilities/CountedPtr.h>
6
7#include "Scantable.h"
8#include "STTcal.h"
9#include "STIdxIter.h"
10#include "STSelector.h"
11
12using namespace casa;
13using namespace asap;
14
15namespace {
16// Interpolation Helper
17class TcalData
18{
19public:
20 TcalData(CountedPtr<Scantable> s)
21 : table_(s)
22 {}
23 ~TcalData() {}
24 const String method_name() const {return "getTcalFromTime";}
25 uInt nrow() const {return table_->nrow();}
26 Vector<Float> GetEntry(int idx) const
27 {
28 String time;
29 uInt tcalid = table_->getTcalId(idx);
30 Vector<Float> return_value;
31 table_->tcal().getEntry(time, return_value, tcalid);
32 return return_value;
33 }
34private:
35 CountedPtr<Scantable> table_;
36};
37
38class TsysData
39{
40public:
41 TsysData(CountedPtr<Scantable> s)
42 : tsyscolumn_(s->table(), "TSYS")
43 {}
44 ~TsysData() {}
45 const String method_name() const {return "getTsysFromTime";}
46 uInt nrow() const {return tsyscolumn_.nrow();}
47 Vector<Float> GetEntry(int idx) const {return tsyscolumn_(idx);}
48private:
49 ROArrayColumn<Float> tsyscolumn_;
50};
51
52class SpectralData
53{
54public:
55 SpectralData(Matrix<Float> s)
56 : data_(s)
57 {}
58 ~SpectralData() {}
59 const String method_name() const {return "getSpectraFromTime";}
60 uInt nrow() const {return data_.ncolumn();}
61 Vector<Float> GetEntry(int idx) const {return data_.column(idx);}
62private:
63 Matrix<Float> data_;
64};
65
66
67vector<int> getRowIdFromTime(double reftime, const Vector<Double> &t)
68{
69 // double reft = reftime ;
70 double dtmin = 1.0e100 ;
71 double dtmax = -1.0e100 ;
72 // vector<double> dt ;
73 int just_before = -1 ;
74 int just_after = -1 ;
75 Vector<Double> dt = t - reftime ;
76 for ( unsigned int i = 0 ; i < dt.size() ; i++ ) {
77 if ( dt[i] > 0.0 ) {
78 // after reftime
79 if ( dt[i] < dtmin ) {
80 just_after = i ;
81 dtmin = dt[i] ;
82 }
83 }
84 else if ( dt[i] < 0.0 ) {
85 // before reftime
86 if ( dt[i] > dtmax ) {
87 just_before = i ;
88 dtmax = dt[i] ;
89 }
90 }
91 else {
92 // just a reftime
93 just_before = i ;
94 just_after = i ;
95 dtmax = 0 ;
96 dtmin = 0 ;
97 break ;
98 }
99 }
100
101 vector<int> v(2) ;
102 v[0] = just_before ;
103 v[1] = just_after ;
104
105 return v ;
106}
107
108template<class T>
109class SimpleInterpolationHelper
110{
111 public:
112 static Vector<Float> GetFromTime(double reftime,
113 const Vector<Double> &timeVec,
114 const vector<int> &idx,
115 const T &data,
116 const string mode)
117 {
118 Vector<Float> return_value;
119 LogIO os_;
120 LogIO os( LogOrigin( "STMath", data.method_name(), WHERE ) ) ;
121 if ( data.nrow() == 0 ) {
122 os << LogIO::SEVERE << "No row in the input scantable. Return empty tcal." << LogIO::POST ;
123 }
124 else if ( data.nrow() == 1 ) {
125 return_value = data.GetEntry(0);
126 }
127 else {
128 if ( mode == "before" ) {
129 int id = -1 ;
130 if ( idx[0] != -1 ) {
131 id = idx[0] ;
132 }
133 else if ( idx[1] != -1 ) {
134 os << LogIO::WARN << "Failed to find a scan before reftime. return a spectrum just after the reftime." << LogIO::POST ;
135 id = idx[1] ;
136 }
137
138 return_value = data.GetEntry(id);
139 }
140 else if ( mode == "after" ) {
141 int id = -1 ;
142 if ( idx[1] != -1 ) {
143 id = idx[1] ;
144 }
145 else if ( idx[0] != -1 ) {
146 os << LogIO::WARN << "Failed to find a scan after reftime. return a spectrum just before the reftime." << LogIO::POST ;
147 id = idx[1] ;
148 }
149
150 return_value = data.GetEntry(id);
151 }
152 else if ( mode == "nearest" ) {
153 int id = -1 ;
154 if ( idx[0] == -1 ) {
155 id = idx[1] ;
156 }
157 else if ( idx[1] == -1 ) {
158 id = idx[0] ;
159 }
160 else if ( idx[0] == idx[1] ) {
161 id = idx[0] ;
162 }
163 else {
164 double t0 = timeVec[idx[0]] ;
165 double t1 = timeVec[idx[1]] ;
166 if ( abs( t0 - reftime ) > abs( t1 - reftime ) ) {
167 id = idx[1] ;
168 }
169 else {
170 id = idx[0] ;
171 }
172 }
173 return_value = data.GetEntry(id);
174 }
175 else if ( mode == "linear" ) {
176 if ( idx[0] == -1 ) {
177 // use after
178 os << LogIO::WARN << "Failed to interpolate. return a spectrum just after the reftime." << LogIO::POST ;
179 int id = idx[1] ;
180 return_value = data.GetEntry(id);
181 }
182 else if ( idx[1] == -1 ) {
183 // use before
184 os << LogIO::WARN << "Failed to interpolate. return a spectrum just before the reftime." << LogIO::POST ;
185 int id = idx[0] ;
186 return_value = data.GetEntry(id);
187 }
188 else if ( idx[0] == idx[1] ) {
189 // use before
190 //os << "No need to interporate." << LogIO::POST ;
191 int id = idx[0] ;
192 return_value = data.GetEntry(id);
193 }
194 else {
195 // do interpolation
196
197 double t0 = timeVec[idx[0]] ;
198 double t1 = timeVec[idx[1]] ;
199 Vector<Float> value0 = data.GetEntry(idx[0]);
200 Vector<Float> value1 = data.GetEntry(idx[1]);
201 double tfactor = (reftime - t0) / (t1 - t0) ;
202 for ( unsigned int i = 0 ; i < value0.size() ; i++ ) {
203 value1[i] = ( value1[i] - value0[i] ) * tfactor + value0[i] ;
204 }
205 return_value = value1;
206 }
207 }
208 else {
209 os << LogIO::SEVERE << "Unknown mode" << LogIO::POST ;
210 }
211 }
212 return return_value ;
213 }
214};
215
216// Calibration Helper
217class CalibrationHelper
218{
219public:
220 static void CalibrateALMA( CountedPtr<Scantable>& out,
221 const CountedPtr<Scantable>& on,
222 const CountedPtr<Scantable>& off,
223 const Vector<uInt>& rows )
224 {
225 // 2012/05/22 TN
226 // Assume that out has empty SPECTRA column
227
228 // if rows is empty, just return
229 if ( rows.nelements() == 0 )
230 return ;
231
232 ROArrayColumn<Float> in_spectra_column(on->table(), "SPECTRA");
233 ROArrayColumn<Float> in_tsys_column(on->table(), "TSYS");
234 ROArrayColumn<uChar> in_flagtra_column(on->table(), "FLAGTRA");
235 ArrayColumn<Float> out_spectra_column(out->table(), "SPECTRA");
236 ArrayColumn<uChar> out_flagtra_column(out->table(), "FLAGTRA");
237
238 Vector<Double> timeVec = GetScalarColumn<Double>(off->table(), "TIME");
239 Vector<Double> refTimeVec = GetScalarColumn<Double>(on->table(), "TIME");
240 SpectralData offspectra(Matrix<Float>(GetArrayColumn<Float>(off->table(), "SPECTRA")));
241 unsigned int spsize = on->nchan( on->getIF(rows[0]) ) ;
242 vector<int> ids( 2 ) ;
243 for ( int irow = 0 ; irow < rows.nelements() ; irow++ ) {
244 uInt row = rows[irow];
245 double reftime = refTimeVec[row];
246 ids = getRowIdFromTime( reftime, timeVec ) ;
247 Vector<Float> spoff = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeVec, ids, offspectra, "linear");
248 Vector<Float> spec = in_spectra_column(row);
249 Vector<Float> tsys = in_tsys_column(row);
250 Vector<uChar> flag = in_flagtra_column(row);
251 // ALMA Calibration
252 //
253 // Ta* = Tsys * ( ON - OFF ) / OFF
254 //
255 // 2010/01/07 Takeshi Nakazato
256 unsigned int tsyssize = tsys.nelements() ;
257 for ( unsigned int j = 0 ; j < spsize ; j++ ) {
258 if ( spoff[j] == 0.0 ) {
259 spec[j] = 0.0 ;
260 flag[j] = (uChar)True;
261 }
262 else {
263 spec[j] = ( spec[j] - spoff[j] ) / spoff[j] ;
264 }
265 spec[j] *= (tsyssize == spsize) ? tsys[j] : tsys[0];
266 }
267 out_spectra_column.put(row, spec);
268 out_flagtra_column.put(row, flag);
269 }
270 }
271 static void CalibrateChopperWheel( CountedPtr<Scantable> &out,
272 const CountedPtr<Scantable>& on,
273 const CountedPtr<Scantable>& off,
274 const CountedPtr<Scantable>& sky,
275 const CountedPtr<Scantable>& hot,
276 const CountedPtr<Scantable>& cold,
277 const Vector<uInt> &rows )
278 {
279 // 2012/05/22 TN
280 // Assume that out has empty SPECTRA column
281
282 // if rows is empty, just return
283 if ( rows.nelements() == 0 )
284 return ;
285
286 string antenna_name = out->getAntennaName();
287 ROArrayColumn<Float> in_spectra_column(on->table(), "SPECTRA");
288 ROArrayColumn<uChar> in_flagtra_column(on->table(), "FLAGTRA");
289 ArrayColumn<Float> out_spectra_column(out->table(), "SPECTRA");
290 ArrayColumn<uChar> out_flagtra_column(out->table(), "FLAGTRA");
291 ArrayColumn<Float> out_tsys_column(out->table(), "TSYS");
292
293 Vector<Double> timeOff = GetScalarColumn<Double>(off->table(), "TIME");
294 Vector<Double> timeSky = GetScalarColumn<Double>(sky->table(), "TIME");
295 Vector<Double> timeHot = GetScalarColumn<Double>(hot->table(), "TIME");
296 Vector<Double> timeOn = GetScalarColumn<Double>(on->table(), "TIME");
297 SpectralData offspectra(Matrix<Float>(GetArrayColumn<Float>(off->table(), "SPECTRA")));
298 SpectralData skyspectra(Matrix<Float>(GetArrayColumn<Float>(sky->table(), "SPECTRA")));
299 SpectralData hotspectra(Matrix<Float>(GetArrayColumn<Float>(hot->table(), "SPECTRA")));
300 TcalData tcaldata(sky);
301 TsysData tsysdata(sky);
302 unsigned int spsize = on->nchan( on->getIF(rows[0]) ) ;
303 vector<int> ids( 2 ) ;
304 for ( int irow = 0 ; irow < rows.nelements() ; irow++ ) {
305 uInt row = rows[irow];
306 double reftime = timeOn[row];
307 ids = getRowIdFromTime( reftime, timeOff ) ;
308 Vector<Float> spoff = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeOff, ids, offspectra, "linear");
309 ids = getRowIdFromTime( reftime, timeSky ) ;
310 Vector<Float> spsky = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeSky, ids, skyspectra, "linear");
311 Vector<Float> tcal = SimpleInterpolationHelper<TcalData>::GetFromTime(reftime, timeSky, ids, tcaldata, "linear");
312 Vector<Float> tsys = SimpleInterpolationHelper<TsysData>::GetFromTime(reftime, timeSky, ids, tsysdata, "linear");
313 ids = getRowIdFromTime( reftime, timeHot ) ;
314 Vector<Float> sphot = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeHot, ids, hotspectra, "linear");
315 Vector<Float> spec = in_spectra_column(row);
316 Vector<uChar> flag = in_flagtra_column(row);
317 if ( antenna_name.find( "APEX" ) != String::npos ) {
318 // using gain array
319 for ( unsigned int j = 0 ; j < tcal.size() ; j++ ) {
320 if ( spoff[j] == 0.0 || (sphot[j]-spsky[j]) == 0.0 ) {
321 spec[j] = 0.0 ;
322 flag[j] = (uChar)True;
323 }
324 else {
325 spec[j] = ( ( spec[j] - spoff[j] ) / spoff[j] )
326 * ( spsky[j] / ( sphot[j] - spsky[j] ) ) * tcal[j] ;
327 }
328 }
329 }
330 else {
331 // Chopper-Wheel calibration (Ulich & Haas 1976)
332 for ( unsigned int j = 0 ; j < tcal.size() ; j++ ) {
333 if ( (sphot[j]-spsky[j]) == 0.0 ) {
334 spec[j] = 0.0 ;
335 flag[j] = (uChar)True;
336 }
337 else {
338 spec[j] = ( spec[j] - spoff[j] ) / ( sphot[j] - spsky[j] ) * tcal[j] ;
339 }
340 }
341 }
342 out_spectra_column.put(row, spec);
343 out_flagtra_column.put(row, flag);
344 out_tsys_column.put(row, tsys);
345 }
346 }
347 static void GetSelector(STSelector &sel, const vector<string> &names, const Record &values)
348 {
349 stringstream ss ;
350 ss << "SELECT FROM $1 WHERE ";
351 string separator = "";
352 for (vector<string>::const_iterator i = names.begin(); i != names.end(); ++i) {
353 ss << separator << *i << "==";
354 switch (values.dataType(*i)) {
355 case TpUInt:
356 ss << values.asuInt(*i);
357 break;
358 case TpInt:
359 ss << values.asInt(*i);
360 break;
361 case TpFloat:
362 ss << values.asFloat(*i);
363 break;
364 case TpDouble:
365 ss << values.asDouble(*i);
366 break;
367 case TpComplex:
368 ss << values.asComplex(*i);
369 break;
370 case TpString:
371 ss << values.asString(*i);
372 break;
373 default:
374 break;
375 }
376 separator = "&&";
377 }
378 sel.setTaQL(ss.str());
379 }
380private:
381 template<class T>
382 static Vector<T> GetScalarColumn(const Table &table, const String &name)
383 {
384 ROScalarColumn<T> column(table, name);
385 return column.getColumn();
386 }
387 template<class T>
388 static Array<T> GetArrayColumn(const Table &table, const String &name)
389 {
390 ROArrayColumn<T> column(table, name);
391 return column.getColumn();
392 }
393};
394
395class AlmaCalibrator
396{
397public:
398 AlmaCalibrator(CountedPtr<Scantable> &out,
399 const CountedPtr<Scantable> &on,
400 const CountedPtr<Scantable> &off)
401 : target_(out),
402 selector_(),
403 on_(on),
404 off_(off)
405 {}
406 ~AlmaCalibrator() {}
407 CountedPtr<Scantable> target() const {return target_;}
408 void Process(const vector<string> &cols, const Record &values, const Vector<uInt> &rows) {
409 CalibrationHelper::GetSelector(selector_, cols, values);
410 off_->setSelection(selector_);
411 CalibrationHelper::CalibrateALMA(target_, on_, off_, rows);
412 off_->unsetSelection();
413 }
414private:
415 CountedPtr<Scantable> target_;
416 STSelector selector_;
417 const CountedPtr<Scantable> on_;
418 const CountedPtr<Scantable> off_;
419};
420
421class ChopperWheelCalibrator
422{
423public:
424 ChopperWheelCalibrator(CountedPtr<Scantable> &out,
425 const CountedPtr<Scantable> &on,
426 const CountedPtr<Scantable> &sky,
427 const CountedPtr<Scantable> &off,
428 const CountedPtr<Scantable> &hot,
429 const CountedPtr<Scantable> &cold)
430 : target_(out),
431 selector_(),
432 on_(on),
433 off_(off),
434 sky_(sky),
435 hot_(hot),
436 cold_(cold)
437 {}
438 ~ChopperWheelCalibrator() {}
439 CountedPtr<Scantable> target() const {return target_;}
440 void Process(const vector<string> &cols, const Record &values, const Vector<uInt> &rows) {
441 CalibrationHelper::GetSelector(selector_, cols, values);
442 off_->setSelection(selector_);
443 sky_->setSelection(selector_);
444 hot_->setSelection(selector_);
445 CalibrationHelper::CalibrateChopperWheel(target_, on_, off_, sky_, hot_, cold_, rows);
446 off_->unsetSelection();
447 sky_->unsetSelection();
448 hot_->unsetSelection();
449 }
450private:
451 CountedPtr<Scantable> target_;
452 STSelector selector_;
453 const CountedPtr<Scantable> on_;
454 const CountedPtr<Scantable> off_;
455 const CountedPtr<Scantable> sky_;
456 const CountedPtr<Scantable> hot_;
457 const CountedPtr<Scantable> cold_;
458};
459
460} // anonymous namespace
Note: See TracBrowser for help on using the repository browser.