source: branches/alma/src/STMath.cpp@ 1604

Last change on this file since 1604 was 1603, checked in by TakTsutsumi, 15 years ago

New Development: No, merge with asap2.3.1

JIRA Issue: Yes CAS-1450

Ready to Release: Yes/No

Interface Changes: Yes/No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes

Module(s): single dish

Description: Upgrade of alma branch based on ASAP2.2.0

(rev.1562) to ASAP2.3.1 (rev.1561)


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 92.4 KB
Line 
1//
2// C++ Implementation: STMath
3//
4// Description:
5//
6//
7// Author: Malte Marquarding <asap@atnf.csiro.au>, (C) 2006
8//
9// Copyright: See COPYING file that comes with this distribution
10//
11//
12
13#include <casa/iomanip.h>
14#include <casa/Exceptions/Error.h>
15#include <casa/Containers/Block.h>
16#include <casa/BasicSL/String.h>
17#include <casa/Arrays/MaskArrLogi.h>
18#include <casa/Arrays/MaskArrMath.h>
19#include <casa/Arrays/ArrayLogical.h>
20#include <casa/Arrays/ArrayMath.h>
21#include <casa/Arrays/Slice.h>
22#include <casa/Arrays/Slicer.h>
23#include <casa/Containers/RecordField.h>
24#include <tables/Tables/TableRow.h>
25#include <tables/Tables/TableVector.h>
26#include <tables/Tables/TabVecMath.h>
27#include <tables/Tables/ExprNode.h>
28#include <tables/Tables/TableRecord.h>
29#include <tables/Tables/TableParse.h>
30#include <tables/Tables/ReadAsciiTable.h>
31#include <tables/Tables/TableIter.h>
32#include <tables/Tables/TableCopy.h>
33#include <scimath/Mathematics/FFTServer.h>
34
35#include <lattices/Lattices/LatticeUtilities.h>
36
37#include <coordinates/Coordinates/SpectralCoordinate.h>
38#include <coordinates/Coordinates/CoordinateSystem.h>
39#include <coordinates/Coordinates/CoordinateUtil.h>
40#include <coordinates/Coordinates/FrequencyAligner.h>
41
42#include <scimath/Mathematics/VectorKernel.h>
43#include <scimath/Mathematics/Convolver.h>
44#include <scimath/Functionals/Polynomial.h>
45
46#include "MathUtils.h"
47#include "RowAccumulator.h"
48#include "STAttr.h"
49#include "STMath.h"
50#include "STSelector.h"
51
52using namespace casa;
53
54using namespace asap;
55
56STMath::STMath(bool insitu) :
57 insitu_(insitu)
58{
59}
60
61
62STMath::~STMath()
63{
64}
65
66CountedPtr<Scantable>
67STMath::average( const std::vector<CountedPtr<Scantable> >& in,
68 const std::vector<bool>& mask,
69 const std::string& weight,
70 const std::string& avmode)
71{
72 if ( avmode == "SCAN" && in.size() != 1 )
73 throw(AipsError("Can't perform 'SCAN' averaging on multiple tables.\n"
74 "Use merge first."));
75 WeightType wtype = stringToWeight(weight);
76
77 // output
78 // clone as this is non insitu
79 bool insitu = insitu_;
80 setInsitu(false);
81 CountedPtr< Scantable > out = getScantable(in[0], true);
82 setInsitu(insitu);
83 std::vector<CountedPtr<Scantable> >::const_iterator stit = in.begin();
84 ++stit;
85 while ( stit != in.end() ) {
86 out->appendToHistoryTable((*stit)->history());
87 ++stit;
88 }
89
90 Table& tout = out->table();
91
92 /// @todo check if all scantables are conformant
93
94 ArrayColumn<Float> specColOut(tout,"SPECTRA");
95 ArrayColumn<uChar> flagColOut(tout,"FLAGTRA");
96 ArrayColumn<Float> tsysColOut(tout,"TSYS");
97 ScalarColumn<Double> mjdColOut(tout,"TIME");
98 ScalarColumn<Double> intColOut(tout,"INTERVAL");
99 ScalarColumn<uInt> cycColOut(tout,"CYCLENO");
100 ScalarColumn<uInt> scanColOut(tout,"SCANNO");
101
102 // set up the output table rows. These are based on the structure of the
103 // FIRST scantable in the vector
104 const Table& baset = in[0]->table();
105
106 Block<String> cols(3);
107 cols[0] = String("BEAMNO");
108 cols[1] = String("IFNO");
109 cols[2] = String("POLNO");
110 if ( avmode == "SOURCE" ) {
111 cols.resize(4);
112 cols[3] = String("SRCNAME");
113 }
114 if ( avmode == "SCAN" && in.size() == 1) {
115 //cols.resize(4);
116 //cols[3] = String("SCANNO");
117 cols.resize(5);
118 cols[3] = String("SRCNAME");
119 cols[4] = String("SCANNO");
120 }
121 uInt outrowCount = 0;
122 TableIterator iter(baset, cols);
123 while (!iter.pastEnd()) {
124 Table subt = iter.table();
125 // copy the first row of this selection into the new table
126 tout.addRow();
127 TableCopy::copyRows(tout, subt, outrowCount, 0, 1);
128 // re-index to 0
129 if ( avmode != "SCAN" && avmode != "SOURCE" ) {
130 scanColOut.put(outrowCount, uInt(0));
131 }
132 ++outrowCount;
133 ++iter;
134 }
135 RowAccumulator acc(wtype);
136 Vector<Bool> cmask(mask);
137 acc.setUserMask(cmask);
138 ROTableRow row(tout);
139 ROArrayColumn<Float> specCol, tsysCol;
140 ROArrayColumn<uChar> flagCol;
141 ROScalarColumn<Double> mjdCol, intCol;
142 ROScalarColumn<Int> scanIDCol;
143
144 Vector<uInt> rowstodelete;
145
146 for (uInt i=0; i < tout.nrow(); ++i) {
147 for ( int j=0; j < int(in.size()); ++j ) {
148 const Table& tin = in[j]->table();
149 const TableRecord& rec = row.get(i);
150 ROScalarColumn<Double> tmp(tin, "TIME");
151 Double td;tmp.get(0,td);
152 Table basesubt = tin(tin.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
153 && tin.col("IFNO") == Int(rec.asuInt("IFNO"))
154 && tin.col("POLNO") == Int(rec.asuInt("POLNO")) );
155 Table subt;
156 if ( avmode == "SOURCE") {
157 subt = basesubt( basesubt.col("SRCNAME") == rec.asString("SRCNAME") );
158 } else if (avmode == "SCAN") {
159 //subt = basesubt( basesubt.col("SCANNO") == Int(rec.asuInt("SCANNO")) );
160 subt = basesubt( basesubt.col("SCANNO") == Int(rec.asuInt("SCANNO"))
161 && basesubt.col("SRCNAME") == rec.asString("SRCNAME") );
162 } else {
163 subt = basesubt;
164 }
165 specCol.attach(subt,"SPECTRA");
166 flagCol.attach(subt,"FLAGTRA");
167 tsysCol.attach(subt,"TSYS");
168 intCol.attach(subt,"INTERVAL");
169 mjdCol.attach(subt,"TIME");
170 Vector<Float> spec,tsys;
171 Vector<uChar> flag;
172 Double inter,time;
173 for (uInt k = 0; k < subt.nrow(); ++k ) {
174 flagCol.get(k, flag);
175 Vector<Bool> bflag(flag.shape());
176 convertArray(bflag, flag);
177 /*
178 if ( allEQ(bflag, True) ) {
179 continue;//don't accumulate
180 }
181 */
182 specCol.get(k, spec);
183 tsysCol.get(k, tsys);
184 intCol.get(k, inter);
185 mjdCol.get(k, time);
186 // spectrum has to be added last to enable weighting by the other values
187 acc.add(spec, !bflag, tsys, inter, time);
188 }
189 }
190 const Vector<Bool>& msk = acc.getMask();
191 if ( allEQ(msk, False) ) {
192 uint n = rowstodelete.nelements();
193 rowstodelete.resize(n+1, True);
194 rowstodelete[n] = i;
195 continue;
196 }
197 //write out
198 if (acc.state()) {
199 Vector<uChar> flg(msk.shape());
200 convertArray(flg, !msk);
201 flagColOut.put(i, flg);
202 specColOut.put(i, acc.getSpectrum());
203 tsysColOut.put(i, acc.getTsys());
204 intColOut.put(i, acc.getInterval());
205 mjdColOut.put(i, acc.getTime());
206 // we should only have one cycle now -> reset it to be 0
207 // frequency switched data has different CYCLENO for different IFNO
208 // which requires resetting this value
209 cycColOut.put(i, uInt(0));
210 } else {
211 ostringstream oss;
212 oss << "For output row="<<i<<", all input rows of data are flagged. no averaging" << endl;
213 pushLog(String(oss));
214 }
215 acc.reset();
216 }
217 if (rowstodelete.nelements() > 0) {
218 cout << rowstodelete << endl;
219 tout.removeRow(rowstodelete);
220 if (tout.nrow() == 0) {
221 throw(AipsError("Can't average fully flagged data."));
222 }
223 }
224 return out;
225}
226
227CountedPtr< Scantable >
228 STMath::averageChannel( const CountedPtr < Scantable > & in,
229 const std::string & mode,
230 const std::string& avmode )
231{
232 // clone as this is non insitu
233 bool insitu = insitu_;
234 setInsitu(false);
235 CountedPtr< Scantable > out = getScantable(in, true);
236 setInsitu(insitu);
237 Table& tout = out->table();
238 ArrayColumn<Float> specColOut(tout,"SPECTRA");
239 ArrayColumn<uChar> flagColOut(tout,"FLAGTRA");
240 ArrayColumn<Float> tsysColOut(tout,"TSYS");
241 ScalarColumn<uInt> scanColOut(tout,"SCANNO");
242 ScalarColumn<Double> intColOut(tout, "INTERVAL");
243 Table tmp = in->table().sort("BEAMNO");
244 Block<String> cols(3);
245 cols[0] = String("BEAMNO");
246 cols[1] = String("IFNO");
247 cols[2] = String("POLNO");
248 if ( avmode == "SCAN") {
249 cols.resize(4);
250 cols[3] = String("SCANNO");
251 }
252 uInt outrowCount = 0;
253 uChar userflag = 1 << 7;
254 TableIterator iter(tmp, cols);
255 while (!iter.pastEnd()) {
256 Table subt = iter.table();
257 ROArrayColumn<Float> specCol, tsysCol;
258 ROArrayColumn<uChar> flagCol;
259 ROScalarColumn<Double> intCol(subt, "INTERVAL");
260 specCol.attach(subt,"SPECTRA");
261 flagCol.attach(subt,"FLAGTRA");
262 tsysCol.attach(subt,"TSYS");
263 tout.addRow();
264 TableCopy::copyRows(tout, subt, outrowCount, 0, 1);
265 if ( avmode != "SCAN") {
266 scanColOut.put(outrowCount, uInt(0));
267 }
268 Vector<Float> tmp;
269 specCol.get(0, tmp);
270 uInt nchan = tmp.nelements();
271 // have to do channel by channel here as MaskedArrMath
272 // doesn't have partialMedians
273 Vector<uChar> flags = flagCol.getColumn(Slicer(Slice(0)));
274 Vector<Float> outspec(nchan);
275 Vector<uChar> outflag(nchan,0);
276 Vector<Float> outtsys(1);/// @fixme when tsys is channel based
277 for (uInt i=0; i<nchan; ++i) {
278 Vector<Float> specs = specCol.getColumn(Slicer(Slice(i)));
279 MaskedArray<Float> ma = maskedArray(specs,flags);
280 outspec[i] = median(ma);
281 if ( allEQ(ma.getMask(), False) )
282 outflag[i] = userflag;// flag data
283 }
284 outtsys[0] = median(tsysCol.getColumn());
285 specColOut.put(outrowCount, outspec);
286 flagColOut.put(outrowCount, outflag);
287 tsysColOut.put(outrowCount, outtsys);
288 Double intsum = sum(intCol.getColumn());
289 intColOut.put(outrowCount, intsum);
290 ++outrowCount;
291 ++iter;
292 }
293 return out;
294}
295
296CountedPtr< Scantable > STMath::getScantable(const CountedPtr< Scantable >& in,
297 bool droprows)
298{
299 if (insitu_) {
300 return in;
301 }
302 else {
303 // clone
304 return CountedPtr<Scantable>(new Scantable(*in, Bool(droprows)));
305 }
306}
307
308CountedPtr< Scantable > STMath::unaryOperate( const CountedPtr< Scantable >& in,
309 float val,
310 const std::string& mode,
311 bool tsys )
312{
313 CountedPtr< Scantable > out = getScantable(in, false);
314 Table& tab = out->table();
315 ArrayColumn<Float> specCol(tab,"SPECTRA");
316 ArrayColumn<Float> tsysCol(tab,"TSYS");
317 for (uInt i=0; i<tab.nrow(); ++i) {
318 Vector<Float> spec;
319 Vector<Float> ts;
320 specCol.get(i, spec);
321 tsysCol.get(i, ts);
322 if (mode == "MUL" || mode == "DIV") {
323 if (mode == "DIV") val = 1.0/val;
324 spec *= val;
325 specCol.put(i, spec);
326 if ( tsys ) {
327 ts *= val;
328 tsysCol.put(i, ts);
329 }
330 } else if ( mode == "ADD" || mode == "SUB") {
331 if (mode == "SUB") val *= -1.0;
332 spec += val;
333 specCol.put(i, spec);
334 if ( tsys ) {
335 ts += val;
336 tsysCol.put(i, ts);
337 }
338 }
339 }
340 return out;
341}
342
343CountedPtr<Scantable> STMath::binaryOperate(const CountedPtr<Scantable>& left,
344 const CountedPtr<Scantable>& right,
345 const std::string& mode)
346{
347 bool insitu = insitu_;
348 if ( ! left->conformant(*right) ) {
349 throw(AipsError("'left' and 'right' scantables are not conformant."));
350 }
351 setInsitu(false);
352 CountedPtr< Scantable > out = getScantable(left, false);
353 setInsitu(insitu);
354 Table& tout = out->table();
355 Block<String> coln(5);
356 coln[0] = "SCANNO"; coln[1] = "CYCLENO"; coln[2] = "BEAMNO";
357 coln[3] = "IFNO"; coln[4] = "POLNO";
358 Table tmpl = tout.sort(coln);
359 Table tmpr = right->table().sort(coln);
360 ArrayColumn<Float> lspecCol(tmpl,"SPECTRA");
361 ROArrayColumn<Float> rspecCol(tmpr,"SPECTRA");
362 ArrayColumn<uChar> lflagCol(tmpl,"FLAGTRA");
363 ROArrayColumn<uChar> rflagCol(tmpr,"FLAGTRA");
364
365 for (uInt i=0; i<tout.nrow(); ++i) {
366 Vector<Float> lspecvec, rspecvec;
367 Vector<uChar> lflagvec, rflagvec;
368 lspecvec = lspecCol(i); rspecvec = rspecCol(i);
369 lflagvec = lflagCol(i); rflagvec = rflagCol(i);
370 MaskedArray<Float> mleft = maskedArray(lspecvec, lflagvec);
371 MaskedArray<Float> mright = maskedArray(rspecvec, rflagvec);
372 if (mode == "ADD") {
373 mleft += mright;
374 } else if ( mode == "SUB") {
375 mleft -= mright;
376 } else if ( mode == "MUL") {
377 mleft *= mright;
378 } else if ( mode == "DIV") {
379 mleft /= mright;
380 } else {
381 throw(AipsError("Illegal binary operator"));
382 }
383 lspecCol.put(i, mleft.getArray());
384 }
385 return out;
386}
387
388
389
390MaskedArray<Float> STMath::maskedArray( const Vector<Float>& s,
391 const Vector<uChar>& f)
392{
393 Vector<Bool> mask;
394 mask.resize(f.shape());
395 convertArray(mask, f);
396 return MaskedArray<Float>(s,!mask);
397}
398
399Vector<uChar> STMath::flagsFromMA(const MaskedArray<Float>& ma)
400{
401 const Vector<Bool>& m = ma.getMask();
402 Vector<uChar> flags(m.shape());
403 convertArray(flags, !m);
404 return flags;
405}
406
407CountedPtr< Scantable > STMath::autoQuotient( const CountedPtr< Scantable >& in,
408 const std::string & mode,
409 bool preserve )
410{
411 /// @todo make other modes available
412 /// modes should be "nearest", "pair"
413 // make this operation non insitu
414 const Table& tin = in->table();
415 Table ons = tin(tin.col("SRCTYPE") == Int(0));
416 Table offs = tin(tin.col("SRCTYPE") == Int(1));
417 if ( offs.nrow() == 0 )
418 throw(AipsError("No 'off' scans present."));
419 // put all "on" scans into output table
420
421 bool insitu = insitu_;
422 setInsitu(false);
423 CountedPtr< Scantable > out = getScantable(in, true);
424 setInsitu(insitu);
425 Table& tout = out->table();
426
427 TableCopy::copyRows(tout, ons);
428 TableRow row(tout);
429 ROScalarColumn<Double> offtimeCol(offs, "TIME");
430 ArrayColumn<Float> outspecCol(tout, "SPECTRA");
431 ROArrayColumn<Float> outtsysCol(tout, "TSYS");
432 ArrayColumn<uChar> outflagCol(tout, "FLAGTRA");
433 for (uInt i=0; i < tout.nrow(); ++i) {
434 const TableRecord& rec = row.get(i);
435 Double ontime = rec.asDouble("TIME");
436 Table presel = offs(offs.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
437 && offs.col("IFNO") == Int(rec.asuInt("IFNO"))
438 && offs.col("POLNO") == Int(rec.asuInt("POLNO")) );
439 ROScalarColumn<Double> offtimeCol(presel, "TIME");
440
441 Double mindeltat = min(abs(offtimeCol.getColumn() - ontime));
442 // Timestamp may vary within a cycle ???!!!
443 // increase this by 0.01 sec in case of rounding errors...
444 // There might be a better way to do this.
445 // fix to this fix. TIME is MJD, so 1.0d not 1.0s
446 mindeltat += 0.01/24./60./60.;
447 Table sel = presel( abs(presel.col("TIME")-ontime) <= mindeltat);
448
449 if ( sel.nrow() < 1 ) {
450 throw(AipsError("No closest in time found... This could be a rounding "
451 "issue. Try quotient instead."));
452 }
453 TableRow offrow(sel);
454 const TableRecord& offrec = offrow.get(0);//should only be one row
455 RORecordFieldPtr< Array<Float> > specoff(offrec, "SPECTRA");
456 RORecordFieldPtr< Array<Float> > tsysoff(offrec, "TSYS");
457 RORecordFieldPtr< Array<uChar> > flagoff(offrec, "FLAGTRA");
458 /// @fixme this assumes tsys is a scalar not vector
459 Float tsysoffscalar = (*tsysoff)(IPosition(1,0));
460 Vector<Float> specon, tsyson;
461 outtsysCol.get(i, tsyson);
462 outspecCol.get(i, specon);
463 Vector<uChar> flagon;
464 outflagCol.get(i, flagon);
465 MaskedArray<Float> mon = maskedArray(specon, flagon);
466 MaskedArray<Float> moff = maskedArray(*specoff, *flagoff);
467 MaskedArray<Float> quot = (tsysoffscalar * mon / moff);
468 if (preserve) {
469 quot -= tsysoffscalar;
470 } else {
471 quot -= tsyson[0];
472 }
473 outspecCol.put(i, quot.getArray());
474 outflagCol.put(i, flagsFromMA(quot));
475 }
476 // renumber scanno
477 TableIterator it(tout, "SCANNO");
478 uInt i = 0;
479 while ( !it.pastEnd() ) {
480 Table t = it.table();
481 TableVector<uInt> vec(t, "SCANNO");
482 vec = i;
483 ++i;
484 ++it;
485 }
486 return out;
487}
488
489
490CountedPtr< Scantable > STMath::quotient( const CountedPtr< Scantable > & on,
491 const CountedPtr< Scantable > & off,
492 bool preserve )
493{
494 bool insitu = insitu_;
495 if ( ! on->conformant(*off) ) {
496 throw(AipsError("'on' and 'off' scantables are not conformant."));
497 }
498 setInsitu(false);
499 CountedPtr< Scantable > out = getScantable(on, false);
500 setInsitu(insitu);
501 Table& tout = out->table();
502 const Table& toff = off->table();
503 TableIterator sit(tout, "SCANNO");
504 TableIterator s2it(toff, "SCANNO");
505 while ( !sit.pastEnd() ) {
506 Table ton = sit.table();
507 TableRow row(ton);
508 Table t = s2it.table();
509 ArrayColumn<Float> outspecCol(ton, "SPECTRA");
510 ROArrayColumn<Float> outtsysCol(ton, "TSYS");
511 ArrayColumn<uChar> outflagCol(ton, "FLAGTRA");
512 for (uInt i=0; i < ton.nrow(); ++i) {
513 const TableRecord& rec = row.get(i);
514 Table offsel = t( t.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
515 && t.col("IFNO") == Int(rec.asuInt("IFNO"))
516 && t.col("POLNO") == Int(rec.asuInt("POLNO")) );
517 if ( offsel.nrow() == 0 )
518 throw AipsError("STMath::quotient: no matching off");
519 TableRow offrow(offsel);
520 const TableRecord& offrec = offrow.get(0);//should be ncycles - take first
521 RORecordFieldPtr< Array<Float> > specoff(offrec, "SPECTRA");
522 RORecordFieldPtr< Array<Float> > tsysoff(offrec, "TSYS");
523 RORecordFieldPtr< Array<uChar> > flagoff(offrec, "FLAGTRA");
524 Float tsysoffscalar = (*tsysoff)(IPosition(1,0));
525 Vector<Float> specon, tsyson;
526 outtsysCol.get(i, tsyson);
527 outspecCol.get(i, specon);
528 Vector<uChar> flagon;
529 outflagCol.get(i, flagon);
530 MaskedArray<Float> mon = maskedArray(specon, flagon);
531 MaskedArray<Float> moff = maskedArray(*specoff, *flagoff);
532 MaskedArray<Float> quot = (tsysoffscalar * mon / moff);
533 if (preserve) {
534 quot -= tsysoffscalar;
535 } else {
536 quot -= tsyson[0];
537 }
538 outspecCol.put(i, quot.getArray());
539 outflagCol.put(i, flagsFromMA(quot));
540 }
541 ++sit;
542 ++s2it;
543 // take the first off for each on scan which doesn't have a
544 // matching off scan
545 // non <= noff: matching pairs, non > noff matching pairs then first off
546 if ( s2it.pastEnd() ) s2it.reset();
547 }
548 return out;
549}
550
551// dototalpower (migration of GBTIDL procedure dototalpower.pro)
552// calibrate the CAL on-off pair. It calculate Tsys and average CAL on-off subintegrations
553// do it for each cycles in a specific scan.
554CountedPtr< Scantable > STMath::dototalpower( const CountedPtr< Scantable >& calon,
555 const CountedPtr< Scantable >& caloff, Float tcal )
556{
557if ( ! calon->conformant(*caloff) ) {
558 throw(AipsError("'CAL on' and 'CAL off' scantables are not conformant."));
559 }
560 setInsitu(false);
561 CountedPtr< Scantable > out = getScantable(caloff, false);
562 Table& tout = out->table();
563 const Table& tcon = calon->table();
564 Vector<Float> tcalout;
565 Vector<Float> tcalout2; //debug
566
567 if ( tout.nrow() != tcon.nrow() ) {
568 throw(AipsError("Mismatch in number of rows to form cal on - off pair."));
569 }
570 // iteration by scanno or cycle no.
571 TableIterator sit(tout, "SCANNO");
572 TableIterator s2it(tcon, "SCANNO");
573 while ( !sit.pastEnd() ) {
574 Table toff = sit.table();
575 TableRow row(toff);
576 Table t = s2it.table();
577 ScalarColumn<Double> outintCol(toff, "INTERVAL");
578 ArrayColumn<Float> outspecCol(toff, "SPECTRA");
579 ArrayColumn<Float> outtsysCol(toff, "TSYS");
580 ArrayColumn<uChar> outflagCol(toff, "FLAGTRA");
581 ROScalarColumn<uInt> outtcalIdCol(toff, "TCAL_ID");
582 ROScalarColumn<uInt> outpolCol(toff, "POLNO");
583 ROScalarColumn<Double> onintCol(t, "INTERVAL");
584 ROArrayColumn<Float> onspecCol(t, "SPECTRA");
585 ROArrayColumn<Float> ontsysCol(t, "TSYS");
586 ROArrayColumn<uChar> onflagCol(t, "FLAGTRA");
587 //ROScalarColumn<uInt> ontcalIdCol(t, "TCAL_ID");
588
589 for (uInt i=0; i < toff.nrow(); ++i) {
590 //skip these checks -> assumes the data order are the same between the cal on off pairs
591 //
592 Vector<Float> specCalon, specCaloff;
593 // to store scalar (mean) tsys
594 Vector<Float> tsysout(1);
595 uInt tcalId, polno;
596 Double offint, onint;
597 outpolCol.get(i, polno);
598 outspecCol.get(i, specCaloff);
599 onspecCol.get(i, specCalon);
600 Vector<uChar> flagCaloff, flagCalon;
601 outflagCol.get(i, flagCaloff);
602 onflagCol.get(i, flagCalon);
603 outtcalIdCol.get(i, tcalId);
604 outintCol.get(i, offint);
605 onintCol.get(i, onint);
606 // caluculate mean Tsys
607 uInt nchan = specCaloff.nelements();
608 // percentage of edge cut off
609 uInt pc = 10;
610 uInt bchan = nchan/pc;
611 uInt echan = nchan-bchan;
612
613 Slicer chansl(IPosition(1,bchan-1), IPosition(1,echan-1), IPosition(1,1),Slicer::endIsLast);
614 Vector<Float> testsubsp = specCaloff(chansl);
615 MaskedArray<Float> spoff = maskedArray( specCaloff(chansl),flagCaloff(chansl) );
616 MaskedArray<Float> spon = maskedArray( specCalon(chansl),flagCalon(chansl) );
617 MaskedArray<Float> spdiff = spon-spoff;
618 uInt noff = spoff.nelementsValid();
619 //uInt non = spon.nelementsValid();
620 uInt ndiff = spdiff.nelementsValid();
621 Float meantsys;
622
623/**
624 Double subspec, subdiff;
625 uInt usednchan;
626 subspec = 0;
627 subdiff = 0;
628 usednchan = 0;
629 for(uInt k=(bchan-1); k<echan; k++) {
630 subspec += specCaloff[k];
631 subdiff += static_cast<Double>(specCalon[k]-specCaloff[k]);
632 ++usednchan;
633 }
634**/
635 // get tcal if input tcal <= 0
636 String tcalt;
637 Float tcalUsed;
638 tcalUsed = tcal;
639 if ( tcal <= 0.0 ) {
640 caloff->tcal().getEntry(tcalt, tcalout, tcalId);
641 if (polno<=3) {
642 tcalUsed = tcalout[polno];
643 }
644 else {
645 tcalUsed = tcalout[0];
646 }
647 }
648
649 Float meanoff;
650 Float meandiff;
651 if (noff && ndiff) {
652 //Debug
653 //if(noff!=ndiff) cerr<<"noff and ndiff is not equal"<<endl;
654 meanoff = sum(spoff)/noff;
655 meandiff = sum(spdiff)/ndiff;
656 meantsys= (meanoff/meandiff )*tcalUsed + tcalUsed/2;
657 }
658 else {
659 meantsys=1;
660 }
661
662 tsysout[0] = Float(meantsys);
663 MaskedArray<Float> mcaloff = maskedArray(specCaloff, flagCaloff);
664 MaskedArray<Float> mcalon = maskedArray(specCalon, flagCalon);
665 MaskedArray<Float> sig = Float(0.5) * (mcaloff + mcalon);
666 //uInt ncaloff = mcaloff.nelementsValid();
667 //uInt ncalon = mcalon.nelementsValid();
668
669 outintCol.put(i, offint+onint);
670 outspecCol.put(i, sig.getArray());
671 outflagCol.put(i, flagsFromMA(sig));
672 outtsysCol.put(i, tsysout);
673 }
674 ++sit;
675 ++s2it;
676 }
677 return out;
678}
679
680//dosigref - migrated from GBT IDL's dosigref.pro, do calibration of position switch
681// observatiions.
682// input: sig and ref scantables, and an optional boxcar smoothing width(default width=0,
683// no smoothing).
684// output: resultant scantable [= (sig-ref/ref)*tsys]
685CountedPtr< Scantable > STMath::dosigref( const CountedPtr < Scantable >& sig,
686 const CountedPtr < Scantable >& ref,
687 int smoothref,
688 casa::Float tsysv,
689 casa::Float tau )
690{
691if ( ! ref->conformant(*sig) ) {
692 throw(AipsError("'sig' and 'ref' scantables are not conformant."));
693 }
694 setInsitu(false);
695 CountedPtr< Scantable > out = getScantable(sig, false);
696 CountedPtr< Scantable > smref;
697 if ( smoothref > 1 ) {
698 float fsmoothref = static_cast<float>(smoothref);
699 std::string inkernel = "boxcar";
700 smref = smooth(ref, inkernel, fsmoothref );
701 ostringstream oss;
702 oss<<"Applied smoothing of "<<fsmoothref<<" on the reference."<<endl;
703 pushLog(String(oss));
704 }
705 else {
706 smref = ref;
707 }
708 Table& tout = out->table();
709 const Table& tref = smref->table();
710 if ( tout.nrow() != tref.nrow() ) {
711 throw(AipsError("Mismatch in number of rows to form on-source and reference pair."));
712 }
713 // iteration by scanno? or cycle no.
714 TableIterator sit(tout, "SCANNO");
715 TableIterator s2it(tref, "SCANNO");
716 while ( !sit.pastEnd() ) {
717 Table ton = sit.table();
718 Table t = s2it.table();
719 ScalarColumn<Double> outintCol(ton, "INTERVAL");
720 ArrayColumn<Float> outspecCol(ton, "SPECTRA");
721 ArrayColumn<Float> outtsysCol(ton, "TSYS");
722 ArrayColumn<uChar> outflagCol(ton, "FLAGTRA");
723 ArrayColumn<Float> refspecCol(t, "SPECTRA");
724 ROScalarColumn<Double> refintCol(t, "INTERVAL");
725 ROArrayColumn<Float> reftsysCol(t, "TSYS");
726 ArrayColumn<uChar> refflagCol(t, "FLAGTRA");
727 ROScalarColumn<Float> refelevCol(t, "ELEVATION");
728 for (uInt i=0; i < ton.nrow(); ++i) {
729
730 Double onint, refint;
731 Vector<Float> specon, specref;
732 // to store scalar (mean) tsys
733 Vector<Float> tsysref;
734 outintCol.get(i, onint);
735 refintCol.get(i, refint);
736 outspecCol.get(i, specon);
737 refspecCol.get(i, specref);
738 Vector<uChar> flagref, flagon;
739 outflagCol.get(i, flagon);
740 refflagCol.get(i, flagref);
741 reftsysCol.get(i, tsysref);
742
743 Float tsysrefscalar;
744 if ( tsysv > 0.0 ) {
745 ostringstream oss;
746 Float elev;
747 refelevCol.get(i, elev);
748 oss << "user specified Tsys = " << tsysv;
749 // do recalc elevation if EL = 0
750 if ( elev == 0 ) {
751 throw(AipsError("EL=0, elevation data is missing."));
752 } else {
753 if ( tau <= 0.0 ) {
754 throw(AipsError("Valid tau is not supplied."));
755 } else {
756 tsysrefscalar = tsysv * exp(tau/elev);
757 }
758 }
759 oss << ", corrected (for El) tsys= "<<tsysrefscalar;
760 pushLog(String(oss));
761 }
762 else {
763 tsysrefscalar = tsysref[0];
764 }
765 //get quotient spectrum
766 MaskedArray<Float> mref = maskedArray(specref, flagref);
767 MaskedArray<Float> mon = maskedArray(specon, flagon);
768 MaskedArray<Float> specres = tsysrefscalar*((mon - mref)/mref);
769 Double resint = onint*refint*smoothref/(onint+refint*smoothref);
770
771 //Debug
772 //cerr<<"Tsys used="<<tsysrefscalar<<endl;
773 // fill the result, replay signal tsys by reference tsys
774 outintCol.put(i, resint);
775 outspecCol.put(i, specres.getArray());
776 outflagCol.put(i, flagsFromMA(specres));
777 outtsysCol.put(i, tsysref);
778 }
779 ++sit;
780 ++s2it;
781 }
782 return out;
783}
784
785CountedPtr< Scantable > STMath::donod(const casa::CountedPtr<Scantable>& s,
786 const std::vector<int>& scans,
787 int smoothref,
788 casa::Float tsysv,
789 casa::Float tau,
790 casa::Float tcal )
791
792{
793 setInsitu(false);
794 STSelector sel;
795 std::vector<int> scan1, scan2, beams;
796 std::vector< vector<int> > scanpair;
797 std::vector<string> calstate;
798 String msg;
799
800 CountedPtr< Scantable > s1b1on, s1b1off, s1b2on, s1b2off;
801 CountedPtr< Scantable > s2b1on, s2b1off, s2b2on, s2b2off;
802
803 std::vector< CountedPtr< Scantable > > sctables;
804 sctables.push_back(s1b1on);
805 sctables.push_back(s1b1off);
806 sctables.push_back(s1b2on);
807 sctables.push_back(s1b2off);
808 sctables.push_back(s2b1on);
809 sctables.push_back(s2b1off);
810 sctables.push_back(s2b2on);
811 sctables.push_back(s2b2off);
812
813 //check scanlist
814 int n=s->checkScanInfo(scans);
815 if (n==1) {
816 throw(AipsError("Incorrect scan pairs. "));
817 }
818
819 // Assume scans contain only a pair of consecutive scan numbers.
820 // It is assumed that first beam, b1, is on target.
821 // There is no check if the first beam is on or not.
822 if ( scans.size()==1 ) {
823 scan1.push_back(scans[0]);
824 scan2.push_back(scans[0]+1);
825 } else if ( scans.size()==2 ) {
826 scan1.push_back(scans[0]);
827 scan2.push_back(scans[1]);
828 } else {
829 if ( scans.size()%2 == 0 ) {
830 for (uInt i=0; i<scans.size(); i++) {
831 if (i%2 == 0) {
832 scan1.push_back(scans[i]);
833 }
834 else {
835 scan2.push_back(scans[i]);
836 }
837 }
838 } else {
839 throw(AipsError("Odd numbers of scans, cannot form pairs."));
840 }
841 }
842 scanpair.push_back(scan1);
843 scanpair.push_back(scan2);
844 calstate.push_back("*calon");
845 calstate.push_back("*[^calon]");
846 CountedPtr< Scantable > ws = getScantable(s, false);
847 uInt l=0;
848 while ( l < sctables.size() ) {
849 for (uInt i=0; i < 2; i++) {
850 for (uInt j=0; j < 2; j++) {
851 for (uInt k=0; k < 2; k++) {
852 sel.reset();
853 sel.setScans(scanpair[i]);
854 sel.setName(calstate[k]);
855 beams.clear();
856 beams.push_back(j);
857 sel.setBeams(beams);
858 ws->setSelection(sel);
859 sctables[l]= getScantable(ws, false);
860 l++;
861 }
862 }
863 }
864 }
865
866 // replace here by splitData or getData functionality
867 CountedPtr< Scantable > sig1;
868 CountedPtr< Scantable > ref1;
869 CountedPtr< Scantable > sig2;
870 CountedPtr< Scantable > ref2;
871 CountedPtr< Scantable > calb1;
872 CountedPtr< Scantable > calb2;
873
874 msg=String("Processing dototalpower for subset of the data");
875 ostringstream oss1;
876 oss1 << msg << endl;
877 pushLog(String(oss1));
878 // Debug for IRC CS data
879 //float tcal1=7.0;
880 //float tcal2=4.0;
881 sig1 = dototalpower(sctables[0], sctables[1], tcal=tcal);
882 ref1 = dototalpower(sctables[2], sctables[3], tcal=tcal);
883 ref2 = dototalpower(sctables[4], sctables[5], tcal=tcal);
884 sig2 = dototalpower(sctables[6], sctables[7], tcal=tcal);
885
886 // correction of user-specified tsys for elevation here
887
888 // dosigref calibration
889 msg=String("Processing dosigref for subset of the data");
890 ostringstream oss2;
891 oss2 << msg << endl;
892 pushLog(String(oss2));
893 calb1=dosigref(sig1,ref2,smoothref,tsysv,tau);
894 calb2=dosigref(sig2,ref1,smoothref,tsysv,tau);
895
896 // iteration by scanno or cycle no.
897 Table& tcalb1 = calb1->table();
898 Table& tcalb2 = calb2->table();
899 TableIterator sit(tcalb1, "SCANNO");
900 TableIterator s2it(tcalb2, "SCANNO");
901 while ( !sit.pastEnd() ) {
902 Table t1 = sit.table();
903 Table t2= s2it.table();
904 ArrayColumn<Float> outspecCol(t1, "SPECTRA");
905 ArrayColumn<Float> outtsysCol(t1, "TSYS");
906 ArrayColumn<uChar> outflagCol(t1, "FLAGTRA");
907 ScalarColumn<Double> outintCol(t1, "INTERVAL");
908 ArrayColumn<Float> t2specCol(t2, "SPECTRA");
909 ROArrayColumn<Float> t2tsysCol(t2, "TSYS");
910 ArrayColumn<uChar> t2flagCol(t2, "FLAGTRA");
911 ROScalarColumn<Double> t2intCol(t2, "INTERVAL");
912 for (uInt i=0; i < t1.nrow(); ++i) {
913 Vector<Float> spec1, spec2;
914 // to store scalar (mean) tsys
915 Vector<Float> tsys1, tsys2;
916 Vector<uChar> flag1, flag2;
917 Double tint1, tint2;
918 outspecCol.get(i, spec1);
919 t2specCol.get(i, spec2);
920 outflagCol.get(i, flag1);
921 t2flagCol.get(i, flag2);
922 outtsysCol.get(i, tsys1);
923 t2tsysCol.get(i, tsys2);
924 outintCol.get(i, tint1);
925 t2intCol.get(i, tint2);
926 // average
927 // assume scalar tsys for weights
928 Float wt1, wt2, tsyssq1, tsyssq2;
929 tsyssq1 = tsys1[0]*tsys1[0];
930 tsyssq2 = tsys2[0]*tsys2[0];
931 wt1 = Float(tint1)/tsyssq1;
932 wt2 = Float(tint2)/tsyssq2;
933 Float invsumwt=1/(wt1+wt2);
934 MaskedArray<Float> mspec1 = maskedArray(spec1, flag1);
935 MaskedArray<Float> mspec2 = maskedArray(spec2, flag2);
936 MaskedArray<Float> avspec = invsumwt * (wt1*mspec1 + wt2*mspec2);
937 //Array<Float> avtsys = Float(0.5) * (tsys1 + tsys2);
938 // cerr<< "Tsys1="<<tsys1<<" Tsys2="<<tsys2<<endl;
939 tsys1[0] = sqrt(tsyssq1 + tsyssq2);
940 Array<Float> avtsys = tsys1;
941
942 outspecCol.put(i, avspec.getArray());
943 outflagCol.put(i, flagsFromMA(avspec));
944 outtsysCol.put(i, avtsys);
945 }
946 ++sit;
947 ++s2it;
948 }
949 return calb1;
950}
951
952//GBTIDL version of frequency switched data calibration
953CountedPtr< Scantable > STMath::dofs( const CountedPtr< Scantable >& s,
954 const std::vector<int>& scans,
955 int smoothref,
956 casa::Float tsysv,
957 casa::Float tau,
958 casa::Float tcal )
959{
960
961
962 STSelector sel;
963 CountedPtr< Scantable > ws = getScantable(s, false);
964 CountedPtr< Scantable > sig, sigwcal, ref, refwcal;
965 CountedPtr< Scantable > calsig, calref, out, out1, out2;
966 Bool nofold=False;
967
968 //split the data
969 sel.setName("*_fs");
970 ws->setSelection(sel);
971 sig = getScantable(ws,false);
972 sel.reset();
973 sel.setName("*_fs_calon");
974 ws->setSelection(sel);
975 sigwcal = getScantable(ws,false);
976 sel.reset();
977 sel.setName("*_fsr");
978 ws->setSelection(sel);
979 ref = getScantable(ws,false);
980 sel.reset();
981 sel.setName("*_fsr_calon");
982 ws->setSelection(sel);
983 refwcal = getScantable(ws,false);
984
985 calsig = dototalpower(sigwcal, sig, tcal=tcal);
986 calref = dototalpower(refwcal, ref, tcal=tcal);
987
988 out1=dosigref(calsig,calref,smoothref,tsysv,tau);
989 out2=dosigref(calref,calsig,smoothref,tsysv,tau);
990
991 Table& tabout1=out1->table();
992 Table& tabout2=out2->table();
993 ROScalarColumn<uInt> freqidCol1(tabout1, "FREQ_ID");
994 ROScalarColumn<uInt> freqidCol2(tabout2, "FREQ_ID");
995 ROArrayColumn<Float> specCol(tabout2, "SPECTRA");
996 Vector<Float> spec; specCol.get(0, spec);
997 uInt nchan = spec.nelements();
998 uInt freqid1; freqidCol1.get(0,freqid1);
999 uInt freqid2; freqidCol2.get(0,freqid2);
1000 Double rp1, rp2, rv1, rv2, inc1, inc2;
1001 out1->frequencies().getEntry(rp1, rv1, inc1, freqid1);
1002 out2->frequencies().getEntry(rp2, rv2, inc2, freqid2);
1003 if (rp1==rp2) {
1004 Double foffset = rv1 - rv2;
1005 uInt choffset = static_cast<uInt>(foffset/abs(inc2));
1006 if (choffset >= nchan) {
1007 cerr<<"out-band frequency switching, no folding"<<endl;
1008 nofold = True;
1009 }
1010 }
1011
1012 if (nofold) {
1013 std::vector< CountedPtr< Scantable > > tabs;
1014 tabs.push_back(out1);
1015 tabs.push_back(out2);
1016 out = merge(tabs);
1017 }
1018 else { //folding is not implemented yet
1019 out = out1;
1020 }
1021
1022 return out;
1023}
1024
1025CountedPtr< Scantable > STMath::freqSwitch( const CountedPtr< Scantable >& in )
1026{
1027 // make copy or reference
1028 CountedPtr< Scantable > out = getScantable(in, false);
1029 Table& tout = out->table();
1030 Block<String> cols(4);
1031 cols[0] = String("SCANNO");
1032 cols[1] = String("CYCLENO");
1033 cols[2] = String("BEAMNO");
1034 cols[3] = String("POLNO");
1035 TableIterator iter(tout, cols);
1036 while (!iter.pastEnd()) {
1037 Table subt = iter.table();
1038 // this should leave us with two rows for the two IFs....if not ignore
1039 if (subt.nrow() != 2 ) {
1040 continue;
1041 }
1042 ArrayColumn<Float> specCol(subt, "SPECTRA");
1043 ArrayColumn<Float> tsysCol(subt, "TSYS");
1044 ArrayColumn<uChar> flagCol(subt, "FLAGTRA");
1045 Vector<Float> onspec,offspec, ontsys, offtsys;
1046 Vector<uChar> onflag, offflag;
1047 tsysCol.get(0, ontsys); tsysCol.get(1, offtsys);
1048 specCol.get(0, onspec); specCol.get(1, offspec);
1049 flagCol.get(0, onflag); flagCol.get(1, offflag);
1050 MaskedArray<Float> on = maskedArray(onspec, onflag);
1051 MaskedArray<Float> off = maskedArray(offspec, offflag);
1052 MaskedArray<Float> oncopy = on.copy();
1053
1054 on /= off; on -= 1.0f;
1055 on *= ontsys[0];
1056 off /= oncopy; off -= 1.0f;
1057 off *= offtsys[0];
1058 specCol.put(0, on.getArray());
1059 const Vector<Bool>& m0 = on.getMask();
1060 Vector<uChar> flags0(m0.shape());
1061 convertArray(flags0, !m0);
1062 flagCol.put(0, flags0);
1063
1064 specCol.put(1, off.getArray());
1065 const Vector<Bool>& m1 = off.getMask();
1066 Vector<uChar> flags1(m1.shape());
1067 convertArray(flags1, !m1);
1068 flagCol.put(1, flags1);
1069 ++iter;
1070 }
1071
1072 return out;
1073}
1074
1075std::vector< float > STMath::statistic( const CountedPtr< Scantable > & in,
1076 const std::vector< bool > & mask,
1077 const std::string& which )
1078{
1079
1080 Vector<Bool> m(mask);
1081 const Table& tab = in->table();
1082 ROArrayColumn<Float> specCol(tab, "SPECTRA");
1083 ROArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1084 std::vector<float> out;
1085 for (uInt i=0; i < tab.nrow(); ++i ) {
1086 Vector<Float> spec; specCol.get(i, spec);
1087 Vector<uChar> flag; flagCol.get(i, flag);
1088 MaskedArray<Float> ma = maskedArray(spec, flag);
1089 float outstat = 0.0;
1090 if ( spec.nelements() == m.nelements() ) {
1091 outstat = mathutil::statistics(which, ma(m));
1092 } else {
1093 outstat = mathutil::statistics(which, ma);
1094 }
1095 out.push_back(outstat);
1096 }
1097 return out;
1098}
1099
1100std::vector< int > STMath::minMaxChan( const CountedPtr< Scantable > & in,
1101 const std::vector< bool > & mask,
1102 const std::string& which )
1103{
1104
1105 Vector<Bool> m(mask);
1106 const Table& tab = in->table();
1107 ROArrayColumn<Float> specCol(tab, "SPECTRA");
1108 ROArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1109 std::vector<int> out;
1110 for (uInt i=0; i < tab.nrow(); ++i ) {
1111 Vector<Float> spec; specCol.get(i, spec);
1112 Vector<uChar> flag; flagCol.get(i, flag);
1113 MaskedArray<Float> ma = maskedArray(spec, flag);
1114 if (ma.ndim() != 1) {
1115 throw (ArrayError(
1116 "std::vector<int> STMath::minMaxChan("
1117 "ContedPtr<Scantable> &in, std::vector<bool> &mask, "
1118 " std::string &which)"
1119 " - MaskedArray is not 1D"));
1120 }
1121 IPosition outpos(1,0);
1122 if ( spec.nelements() == m.nelements() ) {
1123 outpos = mathutil::minMaxPos(which, ma(m));
1124 } else {
1125 outpos = mathutil::minMaxPos(which, ma);
1126 }
1127 out.push_back(outpos[0]);
1128 }
1129 return out;
1130}
1131
1132CountedPtr< Scantable > STMath::bin( const CountedPtr< Scantable > & in,
1133 int width )
1134{
1135 if ( !in->getSelection().empty() ) throw(AipsError("Can't bin subset of the data."));
1136 CountedPtr< Scantable > out = getScantable(in, false);
1137 Table& tout = out->table();
1138 out->frequencies().rescale(width, "BIN");
1139 ArrayColumn<Float> specCol(tout, "SPECTRA");
1140 ArrayColumn<uChar> flagCol(tout, "FLAGTRA");
1141 for (uInt i=0; i < tout.nrow(); ++i ) {
1142 MaskedArray<Float> main = maskedArray(specCol(i), flagCol(i));
1143 MaskedArray<Float> maout;
1144 LatticeUtilities::bin(maout, main, 0, Int(width));
1145 /// @todo implement channel based tsys binning
1146 specCol.put(i, maout.getArray());
1147 flagCol.put(i, flagsFromMA(maout));
1148 // take only the first binned spectrum's length for the deprecated
1149 // global header item nChan
1150 if (i==0) tout.rwKeywordSet().define(String("nChan"),
1151 Int(maout.getArray().nelements()));
1152 }
1153 return out;
1154}
1155
1156CountedPtr< Scantable > STMath::resample( const CountedPtr< Scantable >& in,
1157 const std::string& method,
1158 float width )
1159//
1160// Should add the possibility of width being specified in km/s. This means
1161// that for each freqID (SpectralCoordinate) we will need to convert to an
1162// average channel width (say at the reference pixel). Then we would need
1163// to be careful to make sure each spectrum (of different freqID)
1164// is the same length.
1165//
1166{
1167 //InterpolateArray1D<Double,Float>::InterpolationMethod interp;
1168 Int interpMethod(stringToIMethod(method));
1169
1170 CountedPtr< Scantable > out = getScantable(in, false);
1171 Table& tout = out->table();
1172
1173// Resample SpectralCoordinates (one per freqID)
1174 out->frequencies().rescale(width, "RESAMPLE");
1175 TableIterator iter(tout, "IFNO");
1176 TableRow row(tout);
1177 while ( !iter.pastEnd() ) {
1178 Table tab = iter.table();
1179 ArrayColumn<Float> specCol(tab, "SPECTRA");
1180 //ArrayColumn<Float> tsysCol(tout, "TSYS");
1181 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1182 Vector<Float> spec;
1183 Vector<uChar> flag;
1184 specCol.get(0,spec); // the number of channels should be constant per IF
1185 uInt nChanIn = spec.nelements();
1186 Vector<Float> xIn(nChanIn); indgen(xIn);
1187 Int fac = Int(nChanIn/width);
1188 Vector<Float> xOut(fac+10); // 10 to be safe - resize later
1189 uInt k = 0;
1190 Float x = 0.0;
1191 while (x < Float(nChanIn) ) {
1192 xOut(k) = x;
1193 k++;
1194 x += width;
1195 }
1196 uInt nChanOut = k;
1197 xOut.resize(nChanOut, True);
1198 // process all rows for this IFNO
1199 Vector<Float> specOut;
1200 Vector<Bool> maskOut;
1201 Vector<uChar> flagOut;
1202 for (uInt i=0; i < tab.nrow(); ++i) {
1203 specCol.get(i, spec);
1204 flagCol.get(i, flag);
1205 Vector<Bool> mask(flag.nelements());
1206 convertArray(mask, flag);
1207
1208 IPosition shapeIn(spec.shape());
1209 //sh.nchan = nChanOut;
1210 InterpolateArray1D<Float,Float>::interpolate(specOut, maskOut, xOut,
1211 xIn, spec, mask,
1212 interpMethod, True, True);
1213 /// @todo do the same for channel based Tsys
1214 flagOut.resize(maskOut.nelements());
1215 convertArray(flagOut, maskOut);
1216 specCol.put(i, specOut);
1217 flagCol.put(i, flagOut);
1218 }
1219 ++iter;
1220 }
1221
1222 return out;
1223}
1224
1225STMath::imethod STMath::stringToIMethod(const std::string& in)
1226{
1227 static STMath::imap lookup;
1228
1229 // initialize the lookup table if necessary
1230 if ( lookup.empty() ) {
1231 lookup["nearest"] = InterpolateArray1D<Double,Float>::nearestNeighbour;
1232 lookup["linear"] = InterpolateArray1D<Double,Float>::linear;
1233 lookup["cubic"] = InterpolateArray1D<Double,Float>::cubic;
1234 lookup["spline"] = InterpolateArray1D<Double,Float>::spline;
1235 }
1236
1237 STMath::imap::const_iterator iter = lookup.find(in);
1238
1239 if ( lookup.end() == iter ) {
1240 std::string message = in;
1241 message += " is not a valid interpolation mode";
1242 throw(AipsError(message));
1243 }
1244 return iter->second;
1245}
1246
1247WeightType STMath::stringToWeight(const std::string& in)
1248{
1249 static std::map<std::string, WeightType> lookup;
1250
1251 // initialize the lookup table if necessary
1252 if ( lookup.empty() ) {
1253 lookup["NONE"] = asap::NONE;
1254 lookup["TINT"] = asap::TINT;
1255 lookup["TINTSYS"] = asap::TINTSYS;
1256 lookup["TSYS"] = asap::TSYS;
1257 lookup["VAR"] = asap::VAR;
1258 }
1259
1260 std::map<std::string, WeightType>::const_iterator iter = lookup.find(in);
1261
1262 if ( lookup.end() == iter ) {
1263 std::string message = in;
1264 message += " is not a valid weighting mode";
1265 throw(AipsError(message));
1266 }
1267 return iter->second;
1268}
1269
1270CountedPtr< Scantable > STMath::gainElevation( const CountedPtr< Scantable >& in,
1271 const vector< float > & coeff,
1272 const std::string & filename,
1273 const std::string& method)
1274{
1275 // Get elevation data from Scantable and convert to degrees
1276 CountedPtr< Scantable > out = getScantable(in, false);
1277 Table& tab = out->table();
1278 ROScalarColumn<Float> elev(tab, "ELEVATION");
1279 Vector<Float> x = elev.getColumn();
1280 x *= Float(180 / C::pi); // Degrees
1281
1282 Vector<Float> coeffs(coeff);
1283 const uInt nc = coeffs.nelements();
1284 if ( filename.length() > 0 && nc > 0 ) {
1285 throw(AipsError("You must choose either polynomial coefficients or an ascii file, not both"));
1286 }
1287
1288 // Correct
1289 if ( nc > 0 || filename.length() == 0 ) {
1290 // Find instrument
1291 Bool throwit = True;
1292 Instrument inst =
1293 STAttr::convertInstrument(tab.keywordSet().asString("AntennaName"),
1294 throwit);
1295
1296 // Set polynomial
1297 Polynomial<Float>* ppoly = 0;
1298 Vector<Float> coeff;
1299 String msg;
1300 if ( nc > 0 ) {
1301 ppoly = new Polynomial<Float>(nc);
1302 coeff = coeffs;
1303 msg = String("user");
1304 } else {
1305 STAttr sdAttr;
1306 coeff = sdAttr.gainElevationPoly(inst);
1307 ppoly = new Polynomial<Float>(3);
1308 msg = String("built in");
1309 }
1310
1311 if ( coeff.nelements() > 0 ) {
1312 ppoly->setCoefficients(coeff);
1313 } else {
1314 delete ppoly;
1315 throw(AipsError("There is no known gain-elevation polynomial known for this instrument"));
1316 }
1317 ostringstream oss;
1318 oss << "Making polynomial correction with " << msg << " coefficients:" << endl;
1319 oss << " " << coeff;
1320 pushLog(String(oss));
1321 const uInt nrow = tab.nrow();
1322 Vector<Float> factor(nrow);
1323 for ( uInt i=0; i < nrow; ++i ) {
1324 factor[i] = 1.0 / (*ppoly)(x[i]);
1325 }
1326 delete ppoly;
1327 scaleByVector(tab, factor, true);
1328
1329 } else {
1330 // Read and correct
1331 pushLog("Making correction from ascii Table");
1332 scaleFromAsciiTable(tab, filename, method, x, true);
1333 }
1334 return out;
1335}
1336
1337void STMath::scaleFromAsciiTable(Table& in, const std::string& filename,
1338 const std::string& method,
1339 const Vector<Float>& xout, bool dotsys)
1340{
1341
1342// Read gain-elevation ascii file data into a Table.
1343
1344 String formatString;
1345 Table tbl = readAsciiTable(formatString, Table::Memory, filename, "", "", False);
1346 scaleFromTable(in, tbl, method, xout, dotsys);
1347}
1348
1349void STMath::scaleFromTable(Table& in,
1350 const Table& table,
1351 const std::string& method,
1352 const Vector<Float>& xout, bool dotsys)
1353{
1354
1355 ROScalarColumn<Float> geElCol(table, "ELEVATION");
1356 ROScalarColumn<Float> geFacCol(table, "FACTOR");
1357 Vector<Float> xin = geElCol.getColumn();
1358 Vector<Float> yin = geFacCol.getColumn();
1359 Vector<Bool> maskin(xin.nelements(),True);
1360
1361 // Interpolate (and extrapolate) with desired method
1362
1363 InterpolateArray1D<Double,Float>::InterpolationMethod interp = stringToIMethod(method);
1364
1365 Vector<Float> yout;
1366 Vector<Bool> maskout;
1367 InterpolateArray1D<Float,Float>::interpolate(yout, maskout, xout,
1368 xin, yin, maskin, interp,
1369 True, True);
1370
1371 scaleByVector(in, Float(1.0)/yout, dotsys);
1372}
1373
1374void STMath::scaleByVector( Table& in,
1375 const Vector< Float >& factor,
1376 bool dotsys )
1377{
1378 uInt nrow = in.nrow();
1379 if ( factor.nelements() != nrow ) {
1380 throw(AipsError("factors.nelements() != table.nelements()"));
1381 }
1382 ArrayColumn<Float> specCol(in, "SPECTRA");
1383 ArrayColumn<uChar> flagCol(in, "FLAGTRA");
1384 ArrayColumn<Float> tsysCol(in, "TSYS");
1385 for (uInt i=0; i < nrow; ++i) {
1386 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
1387 ma *= factor[i];
1388 specCol.put(i, ma.getArray());
1389 flagCol.put(i, flagsFromMA(ma));
1390 if ( dotsys ) {
1391 Vector<Float> tsys = tsysCol(i);
1392 tsys *= factor[i];
1393 tsysCol.put(i,tsys);
1394 }
1395 }
1396}
1397
1398CountedPtr< Scantable > STMath::convertFlux( const CountedPtr< Scantable >& in,
1399 float d, float etaap,
1400 float jyperk )
1401{
1402 CountedPtr< Scantable > out = getScantable(in, false);
1403 Table& tab = in->table();
1404 Unit fluxUnit(tab.keywordSet().asString("FluxUnit"));
1405 Unit K(String("K"));
1406 Unit JY(String("Jy"));
1407
1408 bool tokelvin = true;
1409 Double cfac = 1.0;
1410
1411 if ( fluxUnit == JY ) {
1412 pushLog("Converting to K");
1413 Quantum<Double> t(1.0,fluxUnit);
1414 Quantum<Double> t2 = t.get(JY);
1415 cfac = (t2 / t).getValue(); // value to Jy
1416
1417 tokelvin = true;
1418 out->setFluxUnit("K");
1419 } else if ( fluxUnit == K ) {
1420 pushLog("Converting to Jy");
1421 Quantum<Double> t(1.0,fluxUnit);
1422 Quantum<Double> t2 = t.get(K);
1423 cfac = (t2 / t).getValue(); // value to K
1424
1425 tokelvin = false;
1426 out->setFluxUnit("Jy");
1427 } else {
1428 throw(AipsError("Unrecognized brightness units in Table - must be consistent with Jy or K"));
1429 }
1430 // Make sure input values are converted to either Jy or K first...
1431 Float factor = cfac;
1432
1433 // Select method
1434 if (jyperk > 0.0) {
1435 factor *= jyperk;
1436 if ( tokelvin ) factor = 1.0 / jyperk;
1437 ostringstream oss;
1438 oss << "Jy/K = " << jyperk;
1439 pushLog(String(oss));
1440 Vector<Float> factors(tab.nrow(), factor);
1441 scaleByVector(tab,factors, false);
1442 } else if ( etaap > 0.0) {
1443 if (d < 0) {
1444 Instrument inst =
1445 STAttr::convertInstrument(tab.keywordSet().asString("AntennaName"),
1446 True);
1447 STAttr sda;
1448 d = sda.diameter(inst);
1449 }
1450 jyperk = STAttr::findJyPerK(etaap, d);
1451 ostringstream oss;
1452 oss << "Jy/K = " << jyperk;
1453 pushLog(String(oss));
1454 factor *= jyperk;
1455 if ( tokelvin ) {
1456 factor = 1.0 / factor;
1457 }
1458 Vector<Float> factors(tab.nrow(), factor);
1459 scaleByVector(tab, factors, False);
1460 } else {
1461
1462 // OK now we must deal with automatic look up of values.
1463 // We must also deal with the fact that the factors need
1464 // to be computed per IF and may be different and may
1465 // change per integration.
1466
1467 pushLog("Looking up conversion factors");
1468 convertBrightnessUnits(out, tokelvin, cfac);
1469 }
1470
1471 return out;
1472}
1473
1474void STMath::convertBrightnessUnits( CountedPtr<Scantable>& in,
1475 bool tokelvin, float cfac )
1476{
1477 Table& table = in->table();
1478 Instrument inst =
1479 STAttr::convertInstrument(table.keywordSet().asString("AntennaName"), True);
1480 TableIterator iter(table, "FREQ_ID");
1481 STFrequencies stfreqs = in->frequencies();
1482 STAttr sdAtt;
1483 while (!iter.pastEnd()) {
1484 Table tab = iter.table();
1485 ArrayColumn<Float> specCol(tab, "SPECTRA");
1486 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1487 ROScalarColumn<uInt> freqidCol(tab, "FREQ_ID");
1488 MEpoch::ROScalarColumn timeCol(tab, "TIME");
1489
1490 uInt freqid; freqidCol.get(0, freqid);
1491 Vector<Float> tmpspec; specCol.get(0, tmpspec);
1492 // STAttr.JyPerK has a Vector interface... change sometime.
1493 Vector<Float> freqs(1,stfreqs.getRefFreq(freqid, tmpspec.nelements()));
1494 for ( uInt i=0; i<tab.nrow(); ++i) {
1495 Float jyperk = (sdAtt.JyPerK(inst, timeCol(i), freqs))[0];
1496 Float factor = cfac * jyperk;
1497 if ( tokelvin ) factor = Float(1.0) / factor;
1498 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
1499 ma *= factor;
1500 specCol.put(i, ma.getArray());
1501 flagCol.put(i, flagsFromMA(ma));
1502 }
1503 ++iter;
1504 }
1505}
1506
1507CountedPtr< Scantable > STMath::opacity( const CountedPtr< Scantable > & in,
1508 float tau )
1509{
1510 CountedPtr< Scantable > out = getScantable(in, false);
1511
1512 Table tab = out->table();
1513 ROScalarColumn<Float> elev(tab, "ELEVATION");
1514 ArrayColumn<Float> specCol(tab, "SPECTRA");
1515 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1516 ArrayColumn<Float> tsysCol(tab, "TSYS");
1517 for ( uInt i=0; i<tab.nrow(); ++i) {
1518 Float zdist = Float(C::pi_2) - elev(i);
1519 Float factor = exp(tau/cos(zdist));
1520 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
1521 ma *= factor;
1522 specCol.put(i, ma.getArray());
1523 flagCol.put(i, flagsFromMA(ma));
1524 Vector<Float> tsys;
1525 tsysCol.get(i, tsys);
1526 tsys *= factor;
1527 tsysCol.put(i, tsys);
1528 }
1529 return out;
1530}
1531
1532CountedPtr< Scantable > STMath::smoothOther( const CountedPtr< Scantable >& in,
1533 const std::string& kernel,
1534 float width )
1535{
1536 CountedPtr< Scantable > out = getScantable(in, false);
1537 Table& table = out->table();
1538 ArrayColumn<Float> specCol(table, "SPECTRA");
1539 ArrayColumn<uChar> flagCol(table, "FLAGTRA");
1540 Vector<Float> spec;
1541 Vector<uChar> flag;
1542 for ( uInt i=0; i<table.nrow(); ++i) {
1543 specCol.get(i, spec);
1544 flagCol.get(i, flag);
1545 Vector<Bool> mask(flag.nelements());
1546 convertArray(mask, flag);
1547 Vector<Float> specout;
1548 Vector<Bool> maskout;
1549 if ( kernel == "hanning" ) {
1550 mathutil::hanning(specout, maskout, spec , !mask);
1551 convertArray(flag, !maskout);
1552 } else if ( kernel == "rmedian" ) {
1553 mathutil::runningMedian(specout, maskout, spec , mask, width);
1554 convertArray(flag, maskout);
1555 }
1556 flagCol.put(i, flag);
1557 specCol.put(i, specout);
1558 }
1559 return out;
1560}
1561
1562CountedPtr< Scantable > STMath::smooth( const CountedPtr< Scantable >& in,
1563 const std::string& kernel, float width )
1564{
1565 if (kernel == "rmedian" || kernel == "hanning") {
1566 return smoothOther(in, kernel, width);
1567 }
1568 CountedPtr< Scantable > out = getScantable(in, false);
1569 Table& table = out->table();
1570 VectorKernel::KernelTypes type = VectorKernel::toKernelType(kernel);
1571 // same IFNO should have same no of channels
1572 // this saves overhead
1573 TableIterator iter(table, "IFNO");
1574 while (!iter.pastEnd()) {
1575 Table tab = iter.table();
1576 ArrayColumn<Float> specCol(tab, "SPECTRA");
1577 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1578 Vector<Float> tmpspec; specCol.get(0, tmpspec);
1579 uInt nchan = tmpspec.nelements();
1580 Vector<Float> kvec = VectorKernel::make(type, width, nchan, True, False);
1581 Convolver<Float> conv(kvec, IPosition(1,nchan));
1582 Vector<Float> spec;
1583 Vector<uChar> flag;
1584 for ( uInt i=0; i<tab.nrow(); ++i) {
1585 specCol.get(i, spec);
1586 flagCol.get(i, flag);
1587 Vector<Bool> mask(flag.nelements());
1588 convertArray(mask, flag);
1589 Vector<Float> specout;
1590 mathutil::replaceMaskByZero(specout, mask);
1591 conv.linearConv(specout, spec);
1592 specCol.put(i, specout);
1593 }
1594 ++iter;
1595 }
1596 return out;
1597}
1598
1599CountedPtr< Scantable >
1600 STMath::merge( const std::vector< CountedPtr < Scantable > >& in )
1601{
1602 if ( in.size() < 2 ) {
1603 throw(AipsError("Need at least two scantables to perform a merge."));
1604 }
1605 std::vector<CountedPtr < Scantable > >::const_iterator it = in.begin();
1606 bool insitu = insitu_;
1607 setInsitu(false);
1608 CountedPtr< Scantable > out = getScantable(*it, false);
1609 setInsitu(insitu);
1610 Table& tout = out->table();
1611 ScalarColumn<uInt> freqidcol(tout,"FREQ_ID"), molidcol(tout, "MOLECULE_ID");
1612 ScalarColumn<uInt> scannocol(tout,"SCANNO"), focusidcol(tout,"FOCUS_ID");
1613 // Renumber SCANNO to be 0-based
1614 Vector<uInt> scannos = scannocol.getColumn();
1615 uInt offset = min(scannos);
1616 scannos -= offset;
1617 scannocol.putColumn(scannos);
1618 uInt newscanno = max(scannos)+1;
1619 ++it;
1620 while ( it != in.end() ){
1621 if ( ! (*it)->conformant(*out) ) {
1622 // non conformant.
1623 pushLog(String("Warning: Can't merge scantables as header info differs."));
1624 }
1625 out->appendToHistoryTable((*it)->history());
1626 const Table& tab = (*it)->table();
1627 TableIterator scanit(tab, "SCANNO");
1628 while (!scanit.pastEnd()) {
1629 TableIterator freqit(scanit.table(), "FREQ_ID");
1630 while ( !freqit.pastEnd() ) {
1631 Table thetab = freqit.table();
1632 uInt nrow = tout.nrow();
1633 tout.addRow(thetab.nrow());
1634 TableCopy::copyRows(tout, thetab, nrow, 0, thetab.nrow());
1635 ROTableRow row(thetab);
1636 for ( uInt i=0; i<thetab.nrow(); ++i) {
1637 uInt k = nrow+i;
1638 scannocol.put(k, newscanno);
1639 const TableRecord& rec = row.get(i);
1640 Double rv,rp,inc;
1641 (*it)->frequencies().getEntry(rp, rv, inc, rec.asuInt("FREQ_ID"));
1642 uInt id;
1643 id = out->frequencies().addEntry(rp, rv, inc);
1644 freqidcol.put(k,id);
1645 //String name,fname;Double rf;
1646 Vector<String> name,fname;Vector<Double> rf;
1647 (*it)->molecules().getEntry(rf, name, fname, rec.asuInt("MOLECULE_ID"));
1648 id = out->molecules().addEntry(rf, name, fname);
1649 molidcol.put(k, id);
1650 Float frot,fax,ftan,fhand,fmount,fuser, fxy, fxyp;
1651 (*it)->focus().getEntry(fax, ftan, frot, fhand,
1652 fmount,fuser, fxy, fxyp,
1653 rec.asuInt("FOCUS_ID"));
1654 id = out->focus().addEntry(fax, ftan, frot, fhand,
1655 fmount,fuser, fxy, fxyp);
1656 focusidcol.put(k, id);
1657 }
1658 ++freqit;
1659 }
1660 ++newscanno;
1661 ++scanit;
1662 }
1663 ++it;
1664 }
1665 return out;
1666}
1667
1668CountedPtr< Scantable >
1669 STMath::invertPhase( const CountedPtr < Scantable >& in )
1670{
1671 return applyToPol(in, &STPol::invertPhase, Float(0.0));
1672}
1673
1674CountedPtr< Scantable >
1675 STMath::rotateXYPhase( const CountedPtr < Scantable >& in, float phase )
1676{
1677 return applyToPol(in, &STPol::rotatePhase, Float(phase));
1678}
1679
1680CountedPtr< Scantable >
1681 STMath::rotateLinPolPhase( const CountedPtr < Scantable >& in, float phase )
1682{
1683 return applyToPol(in, &STPol::rotateLinPolPhase, Float(phase));
1684}
1685
1686CountedPtr< Scantable > STMath::applyToPol( const CountedPtr<Scantable>& in,
1687 STPol::polOperation fptr,
1688 Float phase )
1689{
1690 CountedPtr< Scantable > out = getScantable(in, false);
1691 Table& tout = out->table();
1692 Block<String> cols(4);
1693 cols[0] = String("SCANNO");
1694 cols[1] = String("BEAMNO");
1695 cols[2] = String("IFNO");
1696 cols[3] = String("CYCLENO");
1697 TableIterator iter(tout, cols);
1698 CountedPtr<STPol> stpol = STPol::getPolClass(out->factories_,
1699 out->getPolType() );
1700 while (!iter.pastEnd()) {
1701 Table t = iter.table();
1702 ArrayColumn<Float> speccol(t, "SPECTRA");
1703 ScalarColumn<uInt> focidcol(t, "FOCUS_ID");
1704 ScalarColumn<Float> parancol(t, "PARANGLE");
1705 Matrix<Float> pols(speccol.getColumn());
1706 try {
1707 stpol->setSpectra(pols);
1708 Float fang,fhand,parang;
1709 fang = in->focusTable_.getTotalFeedAngle(focidcol(0));
1710 fhand = in->focusTable_.getFeedHand(focidcol(0));
1711 parang = parancol(0);
1712 /// @todo re-enable this
1713 // disable total feed angle to support paralactifying Caswell style
1714 stpol->setPhaseCorrections(parang, -parang, fhand);
1715 // use a member function pointer in STPol. This only works on
1716 // the STPol pointer itself, not the Counted Pointer so
1717 // derefernce it.
1718 (&(*(stpol))->*fptr)(phase);
1719 speccol.putColumn(stpol->getSpectra());
1720 } catch (AipsError& e) {
1721 //delete stpol;stpol=0;
1722 throw(e);
1723 }
1724 ++iter;
1725 }
1726 //delete stpol;stpol=0;
1727 return out;
1728}
1729
1730CountedPtr< Scantable >
1731 STMath::swapPolarisations( const CountedPtr< Scantable > & in )
1732{
1733 CountedPtr< Scantable > out = getScantable(in, false);
1734 Table& tout = out->table();
1735 Table t0 = tout(tout.col("POLNO") == 0);
1736 Table t1 = tout(tout.col("POLNO") == 1);
1737 if ( t0.nrow() != t1.nrow() )
1738 throw(AipsError("Inconsistent number of polarisations"));
1739 ArrayColumn<Float> speccol0(t0, "SPECTRA");
1740 ArrayColumn<uChar> flagcol0(t0, "FLAGTRA");
1741 ArrayColumn<Float> speccol1(t1, "SPECTRA");
1742 ArrayColumn<uChar> flagcol1(t1, "FLAGTRA");
1743 Matrix<Float> s0 = speccol0.getColumn();
1744 Matrix<uChar> f0 = flagcol0.getColumn();
1745 speccol0.putColumn(speccol1.getColumn());
1746 flagcol0.putColumn(flagcol1.getColumn());
1747 speccol1.putColumn(s0);
1748 flagcol1.putColumn(f0);
1749 return out;
1750}
1751
1752CountedPtr< Scantable >
1753 STMath::averagePolarisations( const CountedPtr< Scantable > & in,
1754 const std::vector<bool>& mask,
1755 const std::string& weight )
1756{
1757 if (in->npol() < 2 )
1758 throw(AipsError("averagePolarisations can only be applied to two or more"
1759 "polarisations"));
1760 bool insitu = insitu_;
1761 setInsitu(false);
1762 CountedPtr< Scantable > pols = getScantable(in, true);
1763 setInsitu(insitu);
1764 Table& tout = pols->table();
1765 std::string taql = "SELECT FROM $1 WHERE POLNO IN [0,1]";
1766 Table tab = tableCommand(taql, in->table());
1767 if (tab.nrow() == 0 )
1768 throw(AipsError("Could not find any rows with POLNO==0 and POLNO==1"));
1769 TableCopy::copyRows(tout, tab);
1770 TableVector<uInt> vec(tout, "POLNO");
1771 vec = 0;
1772 pols->table_.rwKeywordSet().define("nPol", Int(1));
1773 //pols->table_.rwKeywordSet().define("POLTYPE", String("stokes"));
1774 pols->table_.rwKeywordSet().define("POLTYPE", in->getPolType());
1775 std::vector<CountedPtr<Scantable> > vpols;
1776 vpols.push_back(pols);
1777 CountedPtr< Scantable > out = average(vpols, mask, weight, "SCAN");
1778 return out;
1779}
1780
1781CountedPtr< Scantable >
1782 STMath::averageBeams( const CountedPtr< Scantable > & in,
1783 const std::vector<bool>& mask,
1784 const std::string& weight )
1785{
1786 bool insitu = insitu_;
1787 setInsitu(false);
1788 CountedPtr< Scantable > beams = getScantable(in, false);
1789 setInsitu(insitu);
1790 Table& tout = beams->table();
1791 // give all rows the same BEAMNO
1792 TableVector<uInt> vec(tout, "BEAMNO");
1793 vec = 0;
1794 beams->table_.rwKeywordSet().define("nBeam", Int(1));
1795 std::vector<CountedPtr<Scantable> > vbeams;
1796 vbeams.push_back(beams);
1797 CountedPtr< Scantable > out = average(vbeams, mask, weight, "SCAN");
1798 return out;
1799}
1800
1801
1802CountedPtr< Scantable >
1803 asap::STMath::frequencyAlign( const CountedPtr< Scantable > & in,
1804 const std::string & refTime,
1805 const std::string & method)
1806{
1807 // clone as this is not working insitu
1808 bool insitu = insitu_;
1809 setInsitu(false);
1810 CountedPtr< Scantable > out = getScantable(in, false);
1811 setInsitu(insitu);
1812 Table& tout = out->table();
1813 // Get reference Epoch to time of first row or given String
1814 Unit DAY(String("d"));
1815 MEpoch::Ref epochRef(in->getTimeReference());
1816 MEpoch refEpoch;
1817 if (refTime.length()>0) {
1818 Quantum<Double> qt;
1819 if (MVTime::read(qt,refTime)) {
1820 MVEpoch mv(qt);
1821 refEpoch = MEpoch(mv, epochRef);
1822 } else {
1823 throw(AipsError("Invalid format for Epoch string"));
1824 }
1825 } else {
1826 refEpoch = in->timeCol_(0);
1827 }
1828 MPosition refPos = in->getAntennaPosition();
1829
1830 InterpolateArray1D<Double,Float>::InterpolationMethod interp = stringToIMethod(method);
1831 /*
1832 // Comment from MV.
1833 // the following code has been commented out because different FREQ_IDs have to be aligned together even
1834 // if the frame doesn't change. So far, lack of this check didn't cause any problems.
1835 // test if user frame is different to base frame
1836 if ( in->frequencies().getFrameString(true)
1837 == in->frequencies().getFrameString(false) ) {
1838 throw(AipsError("Can't convert as no output frame has been set"
1839 " (use set_freqframe) or it is aligned already."));
1840 }
1841 */
1842 MFrequency::Types system = in->frequencies().getFrame();
1843 MVTime mvt(refEpoch.getValue());
1844 String epochout = mvt.string(MVTime::YMD) + String(" (") + refEpoch.getRefString() + String(")");
1845 ostringstream oss;
1846 oss << "Aligned at reference Epoch " << epochout
1847 << " in frame " << MFrequency::showType(system);
1848 pushLog(String(oss));
1849 // set up the iterator
1850 Block<String> cols(4);
1851 // select by constant direction
1852 cols[0] = String("SRCNAME");
1853 cols[1] = String("BEAMNO");
1854 // select by IF ( no of channels varies over this )
1855 cols[2] = String("IFNO");
1856 // select by restfrequency
1857 cols[3] = String("MOLECULE_ID");
1858 TableIterator iter(tout, cols);
1859 while ( !iter.pastEnd() ) {
1860 Table t = iter.table();
1861 MDirection::ROScalarColumn dirCol(t, "DIRECTION");
1862 TableIterator fiter(t, "FREQ_ID");
1863 // determine nchan from the first row. This should work as
1864 // we are iterating over BEAMNO and IFNO // we should have constant direction
1865
1866 ROArrayColumn<Float> sCol(t, "SPECTRA");
1867 const MDirection direction = dirCol(0);
1868 const uInt nchan = sCol(0).nelements();
1869
1870 // skip operations if there is nothing to align
1871 if (fiter.pastEnd()) {
1872 continue;
1873 }
1874
1875 Table ftab = fiter.table();
1876 // align all frequency ids with respect to the first encountered id
1877 ScalarColumn<uInt> freqidCol(ftab, "FREQ_ID");
1878 // get the SpectralCoordinate for the freqid, which we are iterating over
1879 SpectralCoordinate sC = in->frequencies().getSpectralCoordinate(freqidCol(0));
1880 FrequencyAligner<Float> fa( sC, nchan, refEpoch,
1881 direction, refPos, system );
1882 // realign the SpectralCoordinate and put into the output Scantable
1883 Vector<String> units(1);
1884 units = String("Hz");
1885 Bool linear=True;
1886 SpectralCoordinate sc2 = fa.alignedSpectralCoordinate(linear);
1887 sc2.setWorldAxisUnits(units);
1888 const uInt id = out->frequencies().addEntry(sc2.referencePixel()[0],
1889 sc2.referenceValue()[0],
1890 sc2.increment()[0]);
1891 while ( !fiter.pastEnd() ) {
1892 ftab = fiter.table();
1893 // spectral coordinate for the current FREQ_ID
1894 ScalarColumn<uInt> freqidCol2(ftab, "FREQ_ID");
1895 sC = in->frequencies().getSpectralCoordinate(freqidCol2(0));
1896 // create the "global" abcissa for alignment with same FREQ_ID
1897 Vector<Double> abc(nchan);
1898 for (uInt i=0; i<nchan; i++) {
1899 Double w;
1900 sC.toWorld(w,Double(i));
1901 abc[i] = w;
1902 }
1903 TableVector<uInt> tvec(ftab, "FREQ_ID");
1904 // assign new frequency id to all rows
1905 tvec = id;
1906 // cache abcissa for same time stamps, so iterate over those
1907 TableIterator timeiter(ftab, "TIME");
1908 while ( !timeiter.pastEnd() ) {
1909 Table tab = timeiter.table();
1910 ArrayColumn<Float> specCol(tab, "SPECTRA");
1911 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1912 MEpoch::ROScalarColumn timeCol(tab, "TIME");
1913 // use align abcissa cache after the first row
1914 // these rows should be just be POLNO
1915 bool first = true;
1916 for (int i=0; i<int(tab.nrow()); ++i) {
1917 // input values
1918 Vector<uChar> flag = flagCol(i);
1919 Vector<Bool> mask(flag.shape());
1920 Vector<Float> specOut, spec;
1921 spec = specCol(i);
1922 Vector<Bool> maskOut;Vector<uChar> flagOut;
1923 convertArray(mask, flag);
1924 // alignment
1925 Bool ok = fa.align(specOut, maskOut, abc, spec,
1926 mask, timeCol(i), !first,
1927 interp, False);
1928 // back into scantable
1929 flagOut.resize(maskOut.nelements());
1930 convertArray(flagOut, maskOut);
1931 flagCol.put(i, flagOut);
1932 specCol.put(i, specOut);
1933 // start abcissa caching
1934 first = false;
1935 }
1936 // next timestamp
1937 ++timeiter;
1938 }
1939 // next FREQ_ID
1940 ++fiter;
1941 }
1942 // next aligner
1943 ++iter;
1944 }
1945 // set this afterwards to ensure we are doing insitu correctly.
1946 out->frequencies().setFrame(system, true);
1947 return out;
1948}
1949
1950CountedPtr<Scantable>
1951 asap::STMath::convertPolarisation( const CountedPtr<Scantable>& in,
1952 const std::string & newtype )
1953{
1954 if (in->npol() != 2 && in->npol() != 4)
1955 throw(AipsError("Can only convert two or four polarisations."));
1956 if ( in->getPolType() == newtype )
1957 throw(AipsError("No need to convert."));
1958 if ( ! in->selector_.empty() )
1959 throw(AipsError("Can only convert whole scantable. Unset the selection."));
1960 bool insitu = insitu_;
1961 setInsitu(false);
1962 CountedPtr< Scantable > out = getScantable(in, true);
1963 setInsitu(insitu);
1964 Table& tout = out->table();
1965 tout.rwKeywordSet().define("POLTYPE", String(newtype));
1966
1967 Block<String> cols(4);
1968 cols[0] = "SCANNO";
1969 cols[1] = "CYCLENO";
1970 cols[2] = "BEAMNO";
1971 cols[3] = "IFNO";
1972 TableIterator it(in->originalTable_, cols);
1973 String basetype = in->getPolType();
1974 STPol* stpol = STPol::getPolClass(in->factories_, basetype);
1975 try {
1976 while ( !it.pastEnd() ) {
1977 Table tab = it.table();
1978 uInt row = tab.rowNumbers()[0];
1979 stpol->setSpectra(in->getPolMatrix(row));
1980 Float fang,fhand,parang;
1981 fang = in->focusTable_.getTotalFeedAngle(in->mfocusidCol_(row));
1982 fhand = in->focusTable_.getFeedHand(in->mfocusidCol_(row));
1983 parang = in->paraCol_(row);
1984 /// @todo re-enable this
1985 // disable total feed angle to support paralactifying Caswell style
1986 stpol->setPhaseCorrections(parang, -parang, fhand);
1987 Int npolout = 0;
1988 for (uInt i=0; i<tab.nrow(); ++i) {
1989 Vector<Float> outvec = stpol->getSpectrum(i, newtype);
1990 if ( outvec.nelements() > 0 ) {
1991 tout.addRow();
1992 TableCopy::copyRows(tout, tab, tout.nrow()-1, 0, 1);
1993 ArrayColumn<Float> sCol(tout,"SPECTRA");
1994 ScalarColumn<uInt> pCol(tout,"POLNO");
1995 sCol.put(tout.nrow()-1 ,outvec);
1996 pCol.put(tout.nrow()-1 ,uInt(npolout));
1997 npolout++;
1998 }
1999 }
2000 tout.rwKeywordSet().define("nPol", npolout);
2001 ++it;
2002 }
2003 } catch (AipsError& e) {
2004 delete stpol;
2005 throw(e);
2006 }
2007 delete stpol;
2008 return out;
2009}
2010
2011CountedPtr< Scantable >
2012 asap::STMath::mxExtract( const CountedPtr< Scantable > & in,
2013 const std::string & scantype )
2014{
2015 bool insitu = insitu_;
2016 setInsitu(false);
2017 CountedPtr< Scantable > out = getScantable(in, true);
2018 setInsitu(insitu);
2019 Table& tout = out->table();
2020 std::string taql = "SELECT FROM $1 WHERE BEAMNO != REFBEAMNO";
2021 if (scantype == "on") {
2022 taql = "SELECT FROM $1 WHERE BEAMNO == REFBEAMNO";
2023 }
2024 Table tab = tableCommand(taql, in->table());
2025 TableCopy::copyRows(tout, tab);
2026 if (scantype == "on") {
2027 // re-index SCANNO to 0
2028 TableVector<uInt> vec(tout, "SCANNO");
2029 vec = 0;
2030 }
2031 return out;
2032}
2033
2034CountedPtr< Scantable >
2035 asap::STMath::lagFlag( const CountedPtr< Scantable > & in,
2036 double frequency, double width )
2037{
2038 CountedPtr< Scantable > out = getScantable(in, false);
2039 Table& tout = out->table();
2040 TableIterator iter(tout, "FREQ_ID");
2041 FFTServer<Float,Complex> ffts;
2042 while ( !iter.pastEnd() ) {
2043 Table tab = iter.table();
2044 Double rp,rv,inc;
2045 ROTableRow row(tab);
2046 const TableRecord& rec = row.get(0);
2047 uInt freqid = rec.asuInt("FREQ_ID");
2048 out->frequencies().getEntry(rp, rv, inc, freqid);
2049 ArrayColumn<Float> specCol(tab, "SPECTRA");
2050 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
2051 for (int i=0; i<int(tab.nrow()); ++i) {
2052 Vector<Float> spec = specCol(i);
2053 Vector<uChar> flag = flagCol(i);
2054 Int lag0 = Int(spec.nelements()*abs(inc)/(frequency+width)+0.5);
2055 Int lag1 = Int(spec.nelements()*abs(inc)/(frequency-width)+0.5);
2056 for (int k=0; k < flag.nelements(); ++k ) {
2057 if (flag[k] > 0) {
2058 spec[k] = 0.0;
2059 }
2060 }
2061 Vector<Complex> lags;
2062 ffts.fft0(lags, spec);
2063 Int start = max(0, lag0);
2064 Int end = min(Int(lags.nelements()-1), lag1);
2065 if (start == end) {
2066 lags[start] = Complex(0.0);
2067 } else {
2068 for (int j=start; j <=end ;++j) {
2069 lags[j] = Complex(0.0);
2070 }
2071 }
2072 ffts.fft0(spec, lags);
2073 specCol.put(i, spec);
2074 }
2075 ++iter;
2076 }
2077 return out;
2078}
2079
2080// Averaging spectra with different channel/resolution
2081CountedPtr<Scantable>
2082STMath::new_average( const std::vector<CountedPtr<Scantable> >& in,
2083 const bool& compel,
2084 const std::vector<bool>& mask,
2085 const std::string& weight,
2086 const std::string& avmode )
2087 throw ( casa::AipsError )
2088{
2089 if ( avmode == "SCAN" && in.size() != 1 )
2090 throw(AipsError("Can't perform 'SCAN' averaging on multiple tables.\n"
2091 "Use merge first."));
2092
2093 CountedPtr<Scantable> out ; // processed result
2094 if ( compel ) {
2095 std::vector< CountedPtr<Scantable> > newin ; // input for average process
2096 uInt insize = in.size() ; // number of scantables
2097
2098 // TEST: do normal average in each table before IF grouping
2099 cout << "Do preliminary averaging" << endl ;
2100 vector< CountedPtr<Scantable> > tmpin( insize ) ;
2101 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2102 vector< CountedPtr<Scantable> > v( 1, in[itable] ) ;
2103 tmpin[itable] = average( v, mask, weight, avmode ) ;
2104 }
2105
2106 // warning
2107 cout << "Average spectra with different spectral resolution" << endl ;
2108 cout << endl ;
2109
2110 // temporarily set coordinfo
2111 vector<string> oldinfo( insize ) ;
2112 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2113 vector<string> coordinfo = in[itable]->getCoordInfo() ;
2114 oldinfo[itable] = coordinfo[0] ;
2115 coordinfo[0] = "Hz" ;
2116 tmpin[itable]->setCoordInfo( coordinfo ) ;
2117 }
2118
2119 // columns
2120 ScalarColumn<uInt> freqIDCol ;
2121 ScalarColumn<uInt> ifnoCol ;
2122 ScalarColumn<uInt> scannoCol ;
2123
2124
2125 // check IF frequency coverage
2126 //cout << "Check IF settings in each table" << endl ;
2127 vector< vector<uInt> > freqid( insize );
2128 vector< vector<double> > iffreq( insize ) ;
2129 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2130 uInt rows = tmpin[itable]->nrow() ;
2131 uInt freqnrows = tmpin[itable]->frequencies().table().nrow() ;
2132 for ( uInt irow = 0 ; irow < rows ; irow++ ) {
2133 if ( freqid[itable].size() == freqnrows ) {
2134 break ;
2135 }
2136 else {
2137 freqIDCol.attach( tmpin[itable]->table(), "FREQ_ID" ) ;
2138 ifnoCol.attach( tmpin[itable]->table(), "IFNO" ) ;
2139 uInt id = freqIDCol( irow ) ;
2140 if ( freqid[itable].size() == 0 || count( freqid[itable].begin(), freqid[itable].end(), id ) == 0 ) {
2141 //cout << "itable = " << itable << ": IF " << id << " is included in the list" << endl ;
2142 vector<double> abcissa = tmpin[itable]->getAbcissa( irow ) ;
2143 freqid[itable].push_back( id ) ;
2144 iffreq[itable].push_back( abcissa[0] - 0.5 * ( abcissa[1] - abcissa[0] ) ) ;
2145 iffreq[itable].push_back( abcissa[abcissa.size()-1] + 0.5 * ( abcissa[1] - abcissa[0] ) ) ;
2146 }
2147 }
2148 }
2149 }
2150
2151 // debug
2152 //cout << "IF settings summary:" << endl ;
2153 //for ( uInt i = 0 ; i < freqid.size() ; i++ ) {
2154 //cout << " Table" << i << endl ;
2155 //for ( uInt j = 0 ; j < freqid[i].size() ; j++ ) {
2156 //cout << " id = " << freqid[i][j] << " (min,max) = (" << iffreq[i][2*j] << "," << iffreq[i][2*j+1] << ")" << endl ;
2157 //}
2158 //}
2159 //cout << endl ;
2160
2161 // IF grouping based on their frequency coverage
2162 //cout << "IF grouping based on their frequency coverage" << endl ;
2163
2164 // IF group
2165 // ifgrp[numgrp][nummember*2]
2166 // ifgrp = [table00, freqrow00, table01, freqrow01, ...],
2167 // [table11, freqrow11, table11, freqrow11, ...],
2168 // ...
2169 // ifgfreq[numgrp*2]
2170 // ifgfreq = [min0, max0, min1, max1, ...]
2171 vector< vector<uInt> > ifgrp ;
2172 vector<double> ifgfreq ;
2173
2174 // parameter for IF grouping
2175 // groupmode = OR retrieve all region
2176 // AND only retrieve overlaped region
2177 //string groupmode = "AND" ;
2178 string groupmode = "OR" ;
2179 uInt sizecr = 0 ;
2180 if ( groupmode == "AND" )
2181 sizecr = 2 ;
2182 else if ( groupmode == "OR" )
2183 sizecr = 0 ;
2184
2185 vector<double> sortedfreq ;
2186 for ( uInt i = 0 ; i < iffreq.size() ; i++ ) {
2187 for ( uInt j = 0 ; j < iffreq[i].size() ; j++ ) {
2188 if ( count( sortedfreq.begin(), sortedfreq.end(), iffreq[i][j] ) == 0 )
2189 sortedfreq.push_back( iffreq[i][j] ) ;
2190 }
2191 }
2192 sort( sortedfreq.begin(), sortedfreq.end() ) ;
2193 for ( vector<double>::iterator i = sortedfreq.begin() ; i != sortedfreq.end()-1 ; i++ ) {
2194 ifgfreq.push_back( *i ) ;
2195 ifgfreq.push_back( *(i+1) ) ;
2196 }
2197 ifgrp.resize( ifgfreq.size()/2 ) ;
2198 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2199 for ( uInt iif = 0 ; iif < freqid[itable].size() ; iif++ ) {
2200 double range0 = iffreq[itable][2*iif] ;
2201 double range1 = iffreq[itable][2*iif+1] ;
2202 for ( uInt j = 0 ; j < ifgrp.size() ; j++ ) {
2203 double fmin = max( range0, ifgfreq[2*j] ) ;
2204 double fmax = min( range1, ifgfreq[2*j+1] ) ;
2205 if ( fmin < fmax ) {
2206 ifgrp[j].push_back( itable ) ;
2207 ifgrp[j].push_back( freqid[itable][iif] ) ;
2208 }
2209 }
2210 }
2211 }
2212 vector< vector<uInt> >::iterator fiter = ifgrp.begin() ;
2213 vector<double>::iterator giter = ifgfreq.begin() ;
2214 while( fiter != ifgrp.end() ) {
2215 if ( fiter->size() <= sizecr ) {
2216 fiter = ifgrp.erase( fiter ) ;
2217 giter = ifgfreq.erase( giter ) ;
2218 giter = ifgfreq.erase( giter ) ;
2219 }
2220 else {
2221 fiter++ ;
2222 advance( giter, 2 ) ;
2223 }
2224 }
2225
2226 // freqgrp[numgrp][nummember]
2227 // freqgrp = [ifgrp00, ifgrp01, ifgrp02, ...],
2228 // [ifgrp10, ifgrp11, ifgrp12, ...],
2229 // ...
2230 // freqrange[numgrp*2]
2231 // freqrange = [min0, max0, min1, max1, ...]
2232 vector< vector<uInt> > freqgrp ;
2233 double freqrange = 0.0 ;
2234 uInt grpnum = 0 ;
2235 for ( uInt i = 0 ; i < ifgrp.size() ; i++ ) {
2236 // Assumed that ifgfreq was sorted
2237 if ( grpnum != 0 && freqrange == ifgfreq[2*i] ) {
2238 freqgrp[grpnum-1].push_back( i ) ;
2239 }
2240 else {
2241 vector<uInt> grp0( 1, i ) ;
2242 freqgrp.push_back( grp0 ) ;
2243 grpnum++ ;
2244 }
2245 freqrange = ifgfreq[2*i+1] ;
2246 }
2247
2248
2249 // print IF groups
2250 cout << "IF Group summary: " << endl ;
2251 cout << " GROUP_ID [FREQ_MIN, FREQ_MAX]: (TABLE_ID, FREQ_ID)" << endl ;
2252 for ( uInt i = 0 ; i < ifgrp.size() ; i++ ) {
2253 cout << " GROUP " << setw( 2 ) << i << " [" << ifgfreq[2*i] << "," << ifgfreq[2*i+1] << "]: " ;
2254 for ( uInt j = 0 ; j < ifgrp[i].size()/2 ; j++ ) {
2255 cout << "(" << ifgrp[i][2*j] << "," << ifgrp[i][2*j+1] << ") " ;
2256 }
2257 cout << endl ;
2258 }
2259 cout << endl ;
2260
2261 // print frequency group
2262 cout << "Frequency Group summary: " << endl ;
2263 cout << " GROUP_ID [FREQ_MIN, FREQ_MAX]: IF_GROUP_ID" << endl ;
2264 for ( uInt i = 0 ; i < freqgrp.size() ; i++ ) {
2265 cout << " GROUP " << setw( 2 ) << i << " [" << ifgfreq[2*freqgrp[i][0]] << "," << ifgfreq[2*freqgrp[i][freqgrp[i].size()-1]+1] << "]: " ;
2266 for ( uInt j = 0 ; j < freqgrp[i].size() ; j++ ) {
2267 cout << freqgrp[i][j] << " " ;
2268 }
2269 cout << endl ;
2270 }
2271 cout << endl ;
2272
2273 // membership check
2274 // groups[numtable][numIF][nummembership]
2275 vector< vector< vector<uInt> > > groups( insize ) ;
2276 for ( uInt i = 0 ; i < insize ; i++ ) {
2277 groups[i].resize( freqid[i].size() ) ;
2278 }
2279 for ( uInt igrp = 0 ; igrp < ifgrp.size() ; igrp++ ) {
2280 for ( uInt imem = 0 ; imem < ifgrp[igrp].size()/2 ; imem++ ) {
2281 uInt tableid = ifgrp[igrp][2*imem] ;
2282 vector<uInt>::iterator iter = find( freqid[tableid].begin(), freqid[tableid].end(), ifgrp[igrp][2*imem+1] ) ;
2283 if ( iter != freqid[tableid].end() ) {
2284 uInt rowid = distance( freqid[tableid].begin(), iter ) ;
2285 groups[tableid][rowid].push_back( igrp ) ;
2286 }
2287 }
2288 }
2289
2290 // print membership
2291 //for ( uInt i = 0 ; i < insize ; i++ ) {
2292 //cout << "Table " << i << endl ;
2293 //for ( uInt j = 0 ; j < groups[i].size() ; j++ ) {
2294 //cout << " FREQ_ID " << setw( 2 ) << freqid[i][j] << ": " ;
2295 //for ( uInt k = 0 ; k < groups[i][j].size() ; k++ ) {
2296 //cout << setw( 2 ) << groups[i][j][k] << " " ;
2297 //}
2298 //cout << endl ;
2299 //}
2300 //}
2301
2302 // set back coordinfo
2303 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2304 vector<string> coordinfo = tmpin[itable]->getCoordInfo() ;
2305 coordinfo[0] = oldinfo[itable] ;
2306 tmpin[itable]->setCoordInfo( coordinfo ) ;
2307 }
2308
2309 // Create additional table if needed
2310 bool oldInsitu = insitu_ ;
2311 setInsitu( false ) ;
2312 vector< vector<uInt> > addrow( insize ) ;
2313 vector<uInt> addtable( insize, 0 ) ;
2314 vector<uInt> newtableids( insize ) ;
2315 vector<uInt> newifids( insize, 0 ) ;
2316 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2317 //cout << "Table " << setw(2) << itable << ": " ;
2318 for ( uInt ifrow = 0 ; ifrow < groups[itable].size() ; ifrow++ ) {
2319 addrow[itable].push_back( groups[itable][ifrow].size()-1 ) ;
2320 //cout << addrow[itable][ifrow] << " " ;
2321 }
2322 addtable[itable] = *max_element( addrow[itable].begin(), addrow[itable].end() ) ;
2323 //cout << "(" << addtable[itable] << ")" << endl ;
2324 }
2325 newin.resize( insize ) ;
2326 copy( tmpin.begin(), tmpin.end(), newin.begin() ) ;
2327 for ( uInt i = 0 ; i < insize ; i++ ) {
2328 newtableids[i] = i ;
2329 }
2330 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2331 for ( uInt iadd = 0 ; iadd < addtable[itable] ; iadd++ ) {
2332 CountedPtr<Scantable> add = getScantable( newin[itable], false ) ;
2333 vector<int> freqidlist ;
2334 for ( uInt i = 0 ; i < groups[itable].size() ; i++ ) {
2335 if ( groups[itable][i].size() > iadd + 1 ) {
2336 freqidlist.push_back( freqid[itable][i] ) ;
2337 }
2338 }
2339 stringstream taqlstream ;
2340 taqlstream << "SELECT FROM $1 WHERE FREQ_ID IN [" ;
2341 for ( uInt i = 0 ; i < freqidlist.size() ; i++ ) {
2342 taqlstream << i ;
2343 if ( i < freqidlist.size() - 1 )
2344 taqlstream << "," ;
2345 else
2346 taqlstream << "]" ;
2347 }
2348 string taql = taqlstream.str() ;
2349 //cout << "taql = " << taql << endl ;
2350 STSelector selector = STSelector() ;
2351 selector.setTaQL( taql ) ;
2352 add->setSelection( selector ) ;
2353 newin.push_back( add ) ;
2354 newtableids.push_back( itable ) ;
2355 newifids.push_back( iadd + 1 ) ;
2356 }
2357 }
2358
2359 // udpate ifgrp
2360 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2361 for ( uInt iadd = 0 ; iadd < addtable[itable] ; iadd++ ) {
2362 for ( uInt ifrow = 0 ; ifrow < groups[itable].size() ; ifrow++ ) {
2363 if ( groups[itable][ifrow].size() > iadd + 1 ) {
2364 uInt igrp = groups[itable][ifrow][iadd+1] ;
2365 for ( uInt imem = 0 ; imem < ifgrp[igrp].size()/2 ; imem++ ) {
2366 if ( ifgrp[igrp][2*imem] == newtableids[iadd+insize] && ifgrp[igrp][2*imem+1] == freqid[newtableids[iadd+insize]][ifrow] ) {
2367 ifgrp[igrp][2*imem] = insize + iadd ;
2368 }
2369 }
2370 }
2371 }
2372 }
2373 }
2374
2375 // print IF groups again for debug
2376 //cout << "IF Group summary: " << endl ;
2377 //cout << " GROUP_ID [FREQ_MIN, FREQ_MAX]: (TABLE_ID, FREQ_ID)" << endl ;
2378 //for ( uInt i = 0 ; i < ifgrp.size() ; i++ ) {
2379 //cout << " GROUP " << setw( 2 ) << i << " [" << ifgfreq[2*i] << "," << ifgfreq[2*i+1] << "]: " ;
2380 //for ( uInt j = 0 ; j < ifgrp[i].size()/2 ; j++ ) {
2381 //cout << "(" << ifgrp[i][2*j] << "," << ifgrp[i][2*j+1] << ") " ;
2382 //}
2383 //cout << endl ;
2384 //}
2385 //cout << endl ;
2386
2387 // reset SCANNO and IF: IF number is reset by the result of sortation
2388 cout << "All scan number is set to 0" << endl ;
2389 //cout << "All IF number is set to IF group index" << endl ;
2390 cout << endl ;
2391 insize = newin.size() ;
2392 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2393 uInt rows = newin[itable]->nrow() ;
2394 Table &tmpt = newin[itable]->table() ;
2395 freqIDCol.attach( tmpt, "FREQ_ID" ) ;
2396 scannoCol.attach( tmpt, "SCANNO" ) ;
2397 ifnoCol.attach( tmpt, "IFNO" ) ;
2398 for ( uInt irow=0 ; irow < rows ; irow++ ) {
2399 scannoCol.put( irow, 0 ) ;
2400 uInt freqID = freqIDCol( irow ) ;
2401 vector<uInt>::iterator iter = find( freqid[newtableids[itable]].begin(), freqid[newtableids[itable]].end(), freqID ) ;
2402 if ( iter != freqid[newtableids[itable]].end() ) {
2403 uInt index = distance( freqid[newtableids[itable]].begin(), iter ) ;
2404 ifnoCol.put( irow, groups[newtableids[itable]][index][newifids[itable]] ) ;
2405 }
2406 else {
2407 throw(AipsError("IF grouping was wrong in additional tables.")) ;
2408 }
2409 }
2410 }
2411 oldinfo.resize( insize ) ;
2412 setInsitu( oldInsitu ) ;
2413
2414 // temporarily set coordinfo
2415 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2416 vector<string> coordinfo = newin[itable]->getCoordInfo() ;
2417 oldinfo[itable] = coordinfo[0] ;
2418 coordinfo[0] = "Hz" ;
2419 newin[itable]->setCoordInfo( coordinfo ) ;
2420 }
2421
2422 // save column values in the vector
2423 vector< vector<uInt> > freqTableIdVec( insize ) ;
2424 vector< vector<uInt> > freqIdVec( insize ) ;
2425 vector< vector<uInt> > ifNoVec( insize ) ;
2426 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2427 ScalarColumn<uInt> freqIDs ;
2428 freqIDs.attach( newin[itable]->frequencies().table(), "ID" ) ;
2429 ifnoCol.attach( newin[itable]->table(), "IFNO" ) ;
2430 freqIDCol.attach( newin[itable]->table(), "FREQ_ID" ) ;
2431 for ( uInt irow = 0 ; irow < newin[itable]->frequencies().table().nrow() ; irow++ ) {
2432 freqTableIdVec[itable].push_back( freqIDs( irow ) ) ;
2433 }
2434 for ( uInt irow = 0 ; irow < newin[itable]->table().nrow() ; irow++ ) {
2435 freqIdVec[itable].push_back( freqIDCol( irow ) ) ;
2436 ifNoVec[itable].push_back( ifnoCol( irow ) ) ;
2437 }
2438 }
2439
2440 // reset spectra and flagtra: pick up common part of frequency coverage
2441 //cout << "Pick common frequency range and align resolution" << endl ;
2442 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2443 uInt rows = newin[itable]->nrow() ;
2444 int nminchan = -1 ;
2445 int nmaxchan = -1 ;
2446 vector<uInt> freqIdUpdate ;
2447 for ( uInt irow = 0 ; irow < rows ; irow++ ) {
2448 uInt ifno = ifNoVec[itable][irow] ; // IFNO is reset by group index
2449 double minfreq = ifgfreq[2*ifno] ;
2450 double maxfreq = ifgfreq[2*ifno+1] ;
2451 //cout << "frequency range: [" << minfreq << "," << maxfreq << "]" << endl ;
2452 vector<double> abcissa = newin[itable]->getAbcissa( irow ) ;
2453 int nchan = abcissa.size() ;
2454 double resol = abcissa[1] - abcissa[0] ;
2455 //cout << "abcissa range : [" << abcissa[0] << "," << abcissa[nchan-1] << "]" << endl ;
2456 if ( minfreq <= abcissa[0] )
2457 nminchan = 0 ;
2458 else {
2459 //double cfreq = ( minfreq - abcissa[0] ) / resol ;
2460 double cfreq = ( minfreq - abcissa[0] + 0.5 * resol ) / resol ;
2461 nminchan = int(cfreq) + ( ( cfreq - int(cfreq) <= 0.5 ) ? 0 : 1 ) ;
2462 }
2463 if ( maxfreq >= abcissa[abcissa.size()-1] )
2464 nmaxchan = abcissa.size() - 1 ;
2465 else {
2466 //double cfreq = ( abcissa[abcissa.size()-1] - maxfreq ) / resol ;
2467 double cfreq = ( abcissa[abcissa.size()-1] - maxfreq + 0.5 * resol ) / resol ;
2468 nmaxchan = abcissa.size() - 1 - int(cfreq) - ( ( cfreq - int(cfreq) >= 0.5 ) ? 1 : 0 ) ;
2469 }
2470 //cout << "channel range (" << irow << "): [" << nminchan << "," << nmaxchan << "]" << endl ;
2471 if ( nmaxchan > nminchan ) {
2472 newin[itable]->reshapeSpectrum( nminchan, nmaxchan, irow ) ;
2473 int newchan = nmaxchan - nminchan + 1 ;
2474 if ( count( freqIdUpdate.begin(), freqIdUpdate.end(), freqIdVec[itable][irow] ) == 0 && newchan < nchan )
2475 freqIdUpdate.push_back( freqIdVec[itable][irow] ) ;
2476 }
2477 else {
2478 throw(AipsError("Failed to pick up common part of frequency range.")) ;
2479 }
2480 }
2481 for ( uInt i = 0 ; i < freqIdUpdate.size() ; i++ ) {
2482 uInt freqId = freqIdUpdate[i] ;
2483 Double refpix ;
2484 Double refval ;
2485 Double increment ;
2486
2487 // update row
2488 newin[itable]->frequencies().getEntry( refpix, refval, increment, freqId ) ;
2489 refval = refval - ( refpix - nminchan ) * increment ;
2490 refpix = 0 ;
2491 newin[itable]->frequencies().setEntry( refpix, refval, increment, freqId ) ;
2492 }
2493 }
2494
2495
2496 // reset spectra and flagtra: align spectral resolution
2497 //cout << "Align spectral resolution" << endl ;
2498 vector<double> gmaxdnu( freqgrp.size(), 0.0 ) ;
2499 vector<uInt> gmemid( freqgrp.size(), 0 ) ;
2500 for ( uInt igrp = 0 ; igrp < ifgrp.size() ; igrp++ ) {
2501 double maxdnu = 0.0 ; // maximum (coarsest) frequency resolution
2502 int minchan = INT_MAX ; // minimum channel number
2503 Double refpixref = -1 ; // reference of 'reference pixel'
2504 Double refvalref = -1 ; // reference of 'reference frequency'
2505 Double refinc = -1 ; // reference frequency resolution
2506 uInt refreqid ;
2507 uInt reftable = INT_MAX;
2508 // process only if group member > 1
2509 if ( ifgrp[igrp].size() > 2 ) {
2510 // find minchan and maxdnu in each group
2511 for ( uInt imem = 0 ; imem < ifgrp[igrp].size()/2 ; imem++ ) {
2512 uInt tableid = ifgrp[igrp][2*imem] ;
2513 uInt rowid = ifgrp[igrp][2*imem+1] ;
2514 vector<uInt>::iterator iter = find( freqIdVec[tableid].begin(), freqIdVec[tableid].end(), rowid ) ;
2515 if ( iter != freqIdVec[tableid].end() ) {
2516 uInt index = distance( freqIdVec[tableid].begin(), iter ) ;
2517 vector<double> abcissa = newin[tableid]->getAbcissa( index ) ;
2518 int nchan = abcissa.size() ;
2519 double dnu = abcissa[1] - abcissa[0] ;
2520 //cout << "GROUP " << igrp << " (" << tableid << "," << rowid << "): nchan = " << nchan << " (minchan = " << minchan << ")" << endl ;
2521 if ( nchan < minchan ) {
2522 minchan = nchan ;
2523 maxdnu = dnu ;
2524 newin[tableid]->frequencies().getEntry( refpixref, refvalref, refinc, rowid ) ;
2525 refreqid = rowid ;
2526 reftable = tableid ;
2527 }
2528 }
2529 }
2530 // regrid spectra in each group
2531 cout << "GROUP " << igrp << endl ;
2532 cout << " Channel number is adjusted to " << minchan << endl ;
2533 cout << " Corresponding frequency resolution is " << maxdnu << "Hz" << endl ;
2534 for ( uInt imem = 0 ; imem < ifgrp[igrp].size()/2 ; imem++ ) {
2535 uInt tableid = ifgrp[igrp][2*imem] ;
2536 uInt rowid = ifgrp[igrp][2*imem+1] ;
2537 freqIDCol.attach( newin[tableid]->table(), "FREQ_ID" ) ;
2538 //cout << "tableid = " << tableid << " rowid = " << rowid << ": " << endl ;
2539 //cout << " regridChannel applied to " ;
2540 if ( tableid != reftable )
2541 refreqid = newin[tableid]->frequencies().addEntry( refpixref, refvalref, refinc ) ;
2542 for ( uInt irow = 0 ; irow < newin[tableid]->table().nrow() ; irow++ ) {
2543 uInt tfreqid = freqIdVec[tableid][irow] ;
2544 if ( tfreqid == rowid ) {
2545 //cout << irow << " " ;
2546 newin[tableid]->regridChannel( minchan, maxdnu, irow ) ;
2547 freqIDCol.put( irow, refreqid ) ;
2548 freqIdVec[tableid][irow] = refreqid ;
2549 }
2550 }
2551 //cout << endl ;
2552 }
2553 }
2554 else {
2555 uInt tableid = ifgrp[igrp][0] ;
2556 uInt rowid = ifgrp[igrp][1] ;
2557 vector<uInt>::iterator iter = find( freqIdVec[tableid].begin(), freqIdVec[tableid].end(), rowid ) ;
2558 if ( iter != freqIdVec[tableid].end() ) {
2559 uInt index = distance( freqIdVec[tableid].begin(), iter ) ;
2560 vector<double> abcissa = newin[tableid]->getAbcissa( index ) ;
2561 minchan = abcissa.size() ;
2562 maxdnu = abcissa[1] - abcissa[0] ;
2563 }
2564 }
2565 for ( uInt i = 0 ; i < freqgrp.size() ; i++ ) {
2566 if ( count( freqgrp[i].begin(), freqgrp[i].end(), igrp ) > 0 ) {
2567 if ( maxdnu > gmaxdnu[i] ) {
2568 gmaxdnu[i] = maxdnu ;
2569 gmemid[i] = igrp ;
2570 }
2571 break ;
2572 }
2573 }
2574 }
2575 cout << endl ;
2576
2577 // set back coordinfo
2578 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
2579 vector<string> coordinfo = newin[itable]->getCoordInfo() ;
2580 coordinfo[0] = oldinfo[itable] ;
2581 newin[itable]->setCoordInfo( coordinfo ) ;
2582 }
2583
2584 // accumulate all rows into the first table
2585 // NOTE: assumed in.size() = 1
2586 vector< CountedPtr<Scantable> > tmp( 1 ) ;
2587 if ( newin.size() == 1 )
2588 tmp[0] = newin[0] ;
2589 else
2590 tmp[0] = merge( newin ) ;
2591
2592 //return tmp[0] ;
2593
2594 // average
2595 CountedPtr<Scantable> tmpout = average( tmp, mask, weight, avmode ) ;
2596
2597 //return tmpout ;
2598
2599 // combine frequency group
2600 cout << "Combine spectra based on frequency grouping" << endl ;
2601 cout << "IFNO is renumbered as frequency group ID (see above)" << endl ;
2602 vector<string> coordinfo = tmpout->getCoordInfo() ;
2603 oldinfo[0] = coordinfo[0] ;
2604 coordinfo[0] = "Hz" ;
2605 tmpout->setCoordInfo( coordinfo ) ;
2606 // create proformas of output table
2607 stringstream taqlstream ;
2608 taqlstream << "SELECT FROM $1 WHERE IFNO IN [" ;
2609 for ( uInt i = 0 ; i < gmemid.size() ; i++ ) {
2610 taqlstream << gmemid[i] ;
2611 if ( i < gmemid.size() - 1 )
2612 taqlstream << "," ;
2613 else
2614 taqlstream << "]" ;
2615 }
2616 string taql = taqlstream.str() ;
2617 //cout << "taql = " << taql << endl ;
2618 STSelector selector = STSelector() ;
2619 selector.setTaQL( taql ) ;
2620 oldInsitu = insitu_ ;
2621 setInsitu( false ) ;
2622 out = getScantable( tmpout, false ) ;
2623 setInsitu( oldInsitu ) ;
2624 out->setSelection( selector ) ;
2625 // regrid rows
2626 ifnoCol.attach( tmpout->table(), "IFNO" ) ;
2627 for ( uInt irow = 0 ; irow < tmpout->table().nrow() ; irow++ ) {
2628 uInt ifno = ifnoCol( irow ) ;
2629 for ( uInt igrp = 0 ; igrp < freqgrp.size() ; igrp++ ) {
2630 if ( count( freqgrp[igrp].begin(), freqgrp[igrp].end(), ifno ) > 0 ) {
2631 vector<double> abcissa = tmpout->getAbcissa( irow ) ;
2632 double bw = ( abcissa[1] - abcissa[0] ) * abcissa.size() ;
2633 int nchan = (int)( bw / gmaxdnu[igrp] ) ;
2634 tmpout->regridChannel( nchan, gmaxdnu[igrp], irow ) ;
2635 break ;
2636 }
2637 }
2638 }
2639 // combine spectra
2640 ArrayColumn<Float> specColOut ;
2641 specColOut.attach( out->table(), "SPECTRA" ) ;
2642 ArrayColumn<uChar> flagColOut ;
2643 flagColOut.attach( out->table(), "FLAGTRA" ) ;
2644 ScalarColumn<uInt> ifnoColOut ;
2645 ifnoColOut.attach( out->table(), "IFNO" ) ;
2646 ScalarColumn<uInt> polnoColOut ;
2647 polnoColOut.attach( out->table(), "POLNO" ) ;
2648 ScalarColumn<uInt> freqidColOut ;
2649 freqidColOut.attach( out->table(), "FREQ_ID" ) ;
2650 Table &tab = tmpout->table() ;
2651 TableIterator iter( tab, "POLNO" ) ;
2652 vector< vector<uInt> > sizes( freqgrp.size() ) ;
2653 while( !iter.pastEnd() ) {
2654 vector< vector<Float> > specout( freqgrp.size() ) ;
2655 vector< vector<uChar> > flagout( freqgrp.size() ) ;
2656 ArrayColumn<Float> specCols ;
2657 specCols.attach( iter.table(), "SPECTRA" ) ;
2658 ArrayColumn<uChar> flagCols ;
2659 flagCols.attach( iter.table(), "FLAGTRA" ) ;
2660 ifnoCol.attach( iter.table(), "IFNO" ) ;
2661 ScalarColumn<uInt> polnos ;
2662 polnos.attach( iter.table(), "POLNO" ) ;
2663 uInt polno = polnos( 0 ) ;
2664 //cout << "POLNO iteration: " << polno << endl ;
2665 for ( uInt igrp = 0 ; igrp < freqgrp.size() ; igrp++ ) {
2666 sizes[igrp].resize( freqgrp[igrp].size() ) ;
2667 for ( uInt imem = 0 ; imem < freqgrp[igrp].size() ; imem++ ) {
2668 for ( uInt irow = 0 ; irow < iter.table().nrow() ; irow++ ) {
2669 uInt ifno = ifnoCol( irow ) ;
2670 if ( ifno == freqgrp[igrp][imem] ) {
2671 Vector<Float> spec = specCols( irow ) ;
2672 Vector<uChar> flag = flagCols( irow ) ;
2673 vector<Float> svec ;
2674 spec.tovector( svec ) ;
2675 vector<uChar> fvec ;
2676 flag.tovector( fvec ) ;
2677 //cout << "spec.size() = " << svec.size() << " fvec.size() = " << fvec.size() << endl ;
2678 specout[igrp].insert( specout[igrp].end(), svec.begin(), svec.end() ) ;
2679 flagout[igrp].insert( flagout[igrp].end(), fvec.begin(), fvec.end() ) ;
2680 //cout << "specout[" << igrp << "].size() = " << specout[igrp].size() << endl ;
2681 sizes[igrp][imem] = spec.nelements() ;
2682 }
2683 }
2684 }
2685 for ( uInt irow = 0 ; irow < out->table().nrow() ; irow++ ) {
2686 uInt ifout = ifnoColOut( irow ) ;
2687 uInt polout = polnoColOut( irow ) ;
2688 if ( ifout == gmemid[igrp] && polout == polno ) {
2689 // set SPECTRA and FRAGTRA
2690 Vector<Float> newspec( specout[igrp] ) ;
2691 Vector<uChar> newflag( flagout[igrp] ) ;
2692 specColOut.put( irow, newspec ) ;
2693 flagColOut.put( irow, newflag ) ;
2694 // IFNO renumbering
2695 ifnoColOut.put( irow, igrp ) ;
2696 }
2697 }
2698 }
2699 iter++ ;
2700 }
2701 // update FREQUENCIES subtable
2702 vector<bool> updated( freqgrp.size(), false ) ;
2703 for ( uInt igrp = 0 ; igrp < freqgrp.size() ; igrp++ ) {
2704 uInt index = 0 ;
2705 uInt pixShift = 0 ;
2706 while ( freqgrp[igrp][index] != gmemid[igrp] ) {
2707 pixShift += sizes[igrp][index++] ;
2708 }
2709 for ( uInt irow = 0 ; irow < out->table().nrow() ; irow++ ) {
2710 if ( ifnoColOut( irow ) == gmemid[igrp] && !updated[igrp] ) {
2711 uInt freqidOut = freqidColOut( irow ) ;
2712 //cout << "freqgrp " << igrp << " freqidOut = " << freqidOut << endl ;
2713 double refpix ;
2714 double refval ;
2715 double increm ;
2716 out->frequencies().getEntry( refpix, refval, increm, freqidOut ) ;
2717 refpix += pixShift ;
2718 out->frequencies().setEntry( refpix, refval, increm, freqidOut ) ;
2719 updated[igrp] = true ;
2720 }
2721 }
2722 }
2723
2724 //out = tmpout ;
2725
2726 coordinfo = tmpout->getCoordInfo() ;
2727 coordinfo[0] = oldinfo[0] ;
2728 tmpout->setCoordInfo( coordinfo ) ;
2729 }
2730 else {
2731 // simple average
2732 out = average( in, mask, weight, avmode ) ;
2733 }
2734
2735 return out ;
2736}
Note: See TracBrowser for help on using the repository browser.