source: trunk/src/CalibrationHelper.h @ 2919

Last change on this file since 2919 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.