source: trunk/src/SDMath.cc @ 144

Last change on this file since 144 was 144, checked in by kil064, 19 years ago

merge functions 'average' and 'averages' into one that averages
in time, can do scan averages and apply various weighting schemes.
Break some functionality into other functrions

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.0 KB
Line 
1//#---------------------------------------------------------------------------
2//# SDMath.cc: A collection of single dish mathematical operations
3//#---------------------------------------------------------------------------
4//# Copyright (C) 2004
5//# ATNF
6//#
7//# This program is free software; you can redistribute it and/or modify it
8//# under the terms of the GNU General Public License as published by the Free
9//# Software Foundation; either version 2 of the License, or (at your option)
10//# any later version.
11//#
12//# This program is distributed in the hope that it will be useful, but
13//# WITHOUT ANY WARRANTY; without even the implied warranty of
14//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15//# Public License for more details.
16//#
17//# You should have received a copy of the GNU General Public License along
18//# with this program; if not, write to the Free Software Foundation, Inc.,
19//# 675 Massachusetts Ave, Cambridge, MA 02139, USA.
20//#
21//# Correspondence concerning this software should be addressed as follows:
22//#        Internet email: Malte.Marquarding@csiro.au
23//#        Postal address: Malte Marquarding,
24//#                        Australia Telescope National Facility,
25//#                        P.O. Box 76,
26//#                        Epping, NSW, 2121,
27//#                        AUSTRALIA
28//#
29//# $Id:
30//#---------------------------------------------------------------------------
31#include <vector>
32
33#include <casa/aips.h>
34#include <casa/BasicSL/String.h>
35#include <casa/Arrays/IPosition.h>
36#include <casa/Arrays/Array.h>
37#include <casa/Arrays/ArrayIter.h>
38#include <casa/Arrays/VectorIter.h>
39#include <casa/Arrays/ArrayMath.h>
40#include <casa/Arrays/ArrayLogical.h>
41#include <casa/Arrays/MaskedArray.h>
42#include <casa/Arrays/MaskArrMath.h>
43#include <casa/Arrays/MaskArrLogi.h>
44#include <casa/Exceptions.h>
45
46#include <tables/Tables/Table.h>
47#include <tables/Tables/ScalarColumn.h>
48#include <tables/Tables/ArrayColumn.h>
49
50#include <lattices/Lattices/LatticeUtilities.h>
51#include <lattices/Lattices/RebinLattice.h>
52#include <coordinates/Coordinates/SpectralCoordinate.h>
53#include <coordinates/Coordinates/CoordinateSystem.h>
54#include <coordinates/Coordinates/CoordinateUtil.h>
55
56#include "MathUtils.h"
57#include "SDContainer.h"
58#include "SDMemTable.h"
59
60#include "SDMath.h"
61
62using namespace casa;
63using namespace asap;
64//using namespace asap::SDMath;
65
66CountedPtr<SDMemTable> SDMath::average (const Block<CountedPtr<SDMemTable> >& in,
67                                        const Vector<Bool>& mask, bool scanAv,
68                                        const std::string& weightStr)
69//
70// Weighted averaging of spectra from one or more Tables.
71//
72{
73  weightType wtType = NONE;
74  String tStr(weightStr);
75  tStr.upcase();
76  if (tStr.contains(String("NONE"))) {
77     wtType = NONE;
78  } else if (tStr.contains(String("VAR"))) {
79     wtType = VAR;
80  } else if (tStr.contains(String("TSYS"))) {
81     wtType = TSYS;
82     throw (AipsError("T_sys weighting not yet implemented"));
83  } else {
84    throw (AipsError("Unrecognized weighting type"));
85  }
86
87// Create output Table by cloning from the first table
88
89  SDMemTable* pTabOut = new SDMemTable(*in[0],True);
90
91// Setup
92
93  const uInt axis = 3;                                     // Spectral axis
94  IPosition shp = in[0]->rowAsMaskedArray(0).shape();      // Must not change
95  Array<Float> arr(shp);
96  Array<Bool> barr(shp);
97  const Bool useMask = (mask.nelements() == shp(axis));
98
99// Columns from Tables
100
101  ROArrayColumn<Float> tSysCol;
102  ROScalarColumn<Double> mjdCol;
103  ROScalarColumn<String> srcNameCol;
104  ROScalarColumn<Double> intCol;
105  ROArrayColumn<uInt> fqIDCol;
106
107// Create accumulation MaskedArray. We accumulate for each channel,if,pol,beam
108// Note that the mask of the accumulation array will ALWAYS remain ALL True.
109// The MA is only used so that when data which is masked Bad is added to it,
110// that data does not contribute.
111
112  Array<Float> zero(shp);
113  zero=0.0;
114  Array<Bool> good(shp);
115  good = True;
116  MaskedArray<Float> sum(zero,good);
117
118// Counter arrays
119
120  Array<Float> nPts(shp);             // Number of points
121  nPts = 0.0;
122  Array<Float> nInc(shp);             // Increment
123  nInc = 1.0;
124
125// Create accumulation Array for variance. We accumulate for
126// each if,pol,beam, but average over channel.  So we need
127// a shape with one less axis dropping channels.
128
129  const uInt nAxesSub = shp.nelements() - 1;
130  IPosition shp2(nAxesSub);
131  for (uInt i=0,j=0; i<(nAxesSub+1); i++) {
132     if (i!=axis) {
133       shp2(j) = shp(i);
134       j++;
135     }
136  }
137  Array<Float> sumSq(shp2);
138  sumSq = 0.0;
139  IPosition pos2(nAxesSub,0);                        // For indexing
140
141// Time-related accumulators
142
143  Double time;
144  Double timeSum = 0.0;
145  Double intSum = 0.0;
146  Double interval = 0.0;
147
148// To get the right shape for the Tsys accumulator we need to
149// access a column from the first table.  The shape of this
150// array must not change
151
152  Array<Float> tSysSum;
153  {
154    const Table& tabIn = in[0]->table();
155    tSysCol.attach(tabIn,"TSYS");
156    tSysSum.resize(tSysCol.shape(0));
157  }
158  tSysSum =0.0;
159  Array<Float> tSys;
160
161// Scan and row tracking
162
163  Int oldScanID = 0;
164  Int outScanID = 0;
165  Int scanID = 0;
166  Int rowStart = 0;
167  Int nAccum = 0;
168  Int tableStart = 0;
169
170// Source and FreqID
171
172  String sourceName, oldSourceName, sourceNameStart;
173  Vector<uInt> freqID, freqIDStart, oldFreqID;
174
175// Loop over tables
176
177  Float fac = 1.0;
178  const uInt nTables = in.nelements();
179  for (uInt iTab=0; iTab<nTables; iTab++) {
180
181// Attach columns to Table
182
183     const Table& tabIn = in[iTab]->table();
184     tSysCol.attach(tabIn, "TSYS");
185     mjdCol.attach(tabIn, "TIME");
186     srcNameCol.attach(tabIn, "SRCNAME");
187     intCol.attach(tabIn, "INTERVAL");
188     fqIDCol.attach(tabIn, "FREQID");
189
190// Loop over rows in Table
191
192     const uInt nRows = in[iTab]->nRow();
193     for (uInt iRow=0; iRow<nRows; iRow++) {
194
195// Check conformance
196
197        IPosition shp2 = in[iTab]->rowAsMaskedArray(iRow).shape();
198        if (!shp.isEqual(shp2)) {
199           throw (AipsError("Shapes for all rows must be the same"));
200        }
201
202// If we are not doing scan averages, make checks for source and
203// frequency setup and warn if averaging across them
204
205// Get copy of Scan Container for this row
206
207        SDContainer sc = in[iTab]->getSDContainer(iRow);
208        scanID = sc.scanid;
209
210// Get quantities from columns
211
212        srcNameCol.getScalar(iRow, sourceName);
213        mjdCol.get(iRow, time);
214        tSysCol.get(iRow, tSys);
215        intCol.get(iRow, interval);
216        fqIDCol.get(iRow, freqID);
217
218// Initialize first source and freqID
219
220        if (iRow==0 && iTab==0) {
221          sourceNameStart = sourceName;
222          freqIDStart = freqID;
223        }
224
225// If we are doing scan averages, see if we are at the end of an
226// accumulation period (scan).  We must check soutce names too,
227// since we might have two tables with one scan each but different
228// source names; we shouldn't average different sources together
229
230        if (scanAv && ( (scanID != oldScanID)  ||
231                        (iRow==0 && iTab>0 && sourceName!=oldSourceName))) {
232
233// Normalize data in 'sum' accumulation array according to weighting scheme
234
235           normalize (sum, sumSq, nPts, wtType, axis, nAxesSub);
236
237// Fill scan container. The source and freqID come from the
238// first row of the first table that went into this average (
239// should be the same for all rows in the scan average)
240
241           Float nR(nAccum);
242           fillSDC (sc, sum.getMask(), sum.getArray(), tSysSum/nR, outScanID,
243                    timeSum/nR, intSum, sourceNameStart, freqIDStart);
244
245// Write container out to Table
246
247           pTabOut->putSDContainer(sc);
248
249// Reset accumulators
250
251           sum = 0.0;
252           sumSq = 0.0;
253           nAccum = 0;
254//
255           tSysSum =0.0;
256           timeSum = 0.0;
257           intSum = 0.0;
258
259// Increment
260
261           rowStart = iRow;              // First row for next accumulation
262           tableStart = iTab;            // First table for next accumulation
263           sourceNameStart = sourceName; // First source name for next accumulation
264           freqIDStart = freqID;         // First FreqID for next accumulation
265//
266           oldScanID = scanID;
267           outScanID += 1;               // Scan ID for next accumulation period
268        }
269
270// Accumulation step. First get data and deconstruct
271
272        MaskedArray<Float> dataIn(in[iTab]->rowAsMaskedArray(iRow));
273        Array<Float>& valuesIn = dataIn.getRWArray();           // writable reference
274        const Array<Bool>& maskIn = dataIn.getMask();          // RO reference
275//
276        if (wtType==NONE) {
277           const MaskedArray<Float> n(nInc,dataIn.getMask());
278           nPts += n;                               // Only accumulates where mask==T
279        } else if (wtType==VAR) {
280
281// We are going to average the data, weighted by the noise for each pol, beam and IF.
282// So therefore we need to iterate through by spectrum (axis 3)
283
284           VectorIterator<Float> itData(valuesIn, axis);
285           ReadOnlyVectorIterator<Bool> itMask(maskIn, axis);
286           while (!itData.pastEnd()) {
287
288// Make MaskedArray of Vector, optionally apply OTF mask, and find scaling factor
289
290             if (useMask) {
291                MaskedArray<Float> tmp(itData.vector(),mask&&itMask.vector());
292                fac = 1.0/variance(tmp);
293             } else {
294                MaskedArray<Float> tmp(itData.vector(),itMask.vector());
295                fac = 1.0/variance(tmp);
296             }
297
298// Scale data
299
300             itData.vector() *= fac;     // Writes back into 'dataIn'
301//
302// Accumulate variance per if/pol/beam averaged over spectrum
303// This method to get pos2 from itData.pos() is only valid
304// because the spectral axis is the last one (so we can just
305// copy the first nAXesSub positions out)
306
307             pos2 = itData.pos().getFirst(nAxesSub);
308             sumSq(pos2) += fac;
309//
310             itData.next();
311             itMask.next();
312           }
313        } else if (wtType==TSYS) {
314        }
315
316// Accumulate sum of (possibly scaled) data
317
318       sum += dataIn;
319
320// Accumulate Tsys, time, and interval
321
322       tSysSum += tSys;
323       timeSum += time;
324       intSum += interval;
325
326// Number of rows in accumulation
327
328       nAccum += 1;
329       oldSourceName = sourceName;
330       oldFreqID = freqID;
331    }
332  }
333
334// OK at this point we have accumulation data which is either
335//   - accumulated from all tables into one row
336// or
337//   - accumulated from the last scan average
338//
339// Normalize data in 'sum' accumulation array according to weighting scheme
340
341  normalize (sum, sumSq, nPts, wtType, axis, nAxesSub);
342
343// Create and fill container.  The container we clone will be from
344// the last Table and the first row that went into the current
345// accumulation.  It probably doesn't matter that much really...
346
347  Float nR(nAccum);
348  SDContainer sc = in[tableStart]->getSDContainer(rowStart);
349  fillSDC (sc, sum.getMask(), sum.getArray(), tSysSum/nR, outScanID,
350           timeSum/nR, intSum, sourceNameStart, freqIDStart);
351//
352  pTabOut->putSDContainer(sc);
353/*
354   cout << endl;
355   cout << "Last accumulation for output scan ID " << outScanID << endl;
356   cout << "   The first row in this accumulation is " << rowStart << endl;
357   cout << "   The number of rows accumulated is " << nAccum << endl;
358   cout << "   The first table in this accumulation is " << tableStart << endl;
359   cout << "   The first source in this accumulation is " << sourceNameStart << endl;
360   cout << "   The first freqID in this accumulation is " << freqIDStart << endl;
361   cout  << "   Average time stamp = " << timeSum/nR << endl;
362   cout << "   Integrated time = " << intSum << endl;
363*/
364  return CountedPtr<SDMemTable>(pTabOut);
365}
366
367
368
369CountedPtr<SDMemTable>
370SDMath::quotient(const CountedPtr<SDMemTable>& on,
371                 const CountedPtr<SDMemTable>& off)
372//
373// Compute quotient spectrum
374//
375{
376  const uInt nRows = on->nRow();
377  if (off->nRow() != nRows) {
378     throw (AipsError("Input Scan Tables must have the same number of rows"));
379  }
380
381// Input Tables and columns
382
383  Table ton = on->table();
384  Table toff = off->table();
385  ROArrayColumn<Float> tsys(toff, "TSYS");
386  ROScalarColumn<Double> mjd(ton, "TIME");
387  ROScalarColumn<Double> integr(ton, "INTERVAL");
388  ROScalarColumn<String> srcn(ton, "SRCNAME");
389  ROArrayColumn<uInt> freqidc(ton, "FREQID");
390
391// Output Table cloned from input
392
393  SDMemTable* sdmt = new SDMemTable(*on, True);
394
395// Loop over rows
396
397  for (uInt i=0; i<nRows; i++) {
398     MaskedArray<Float> mon(on->rowAsMaskedArray(i));
399     MaskedArray<Float> moff(off->rowAsMaskedArray(i));
400     IPosition ipon = mon.shape();
401     IPosition ipoff = moff.shape();
402//
403     Array<Float> tsarr; 
404     tsys.get(i, tsarr);
405     if (ipon != ipoff && ipon != tsarr.shape()) {
406       throw(AipsError("on/off not conformant"));
407     }
408
409// Compute quotient
410
411     MaskedArray<Float> tmp = (mon-moff);
412     Array<Float> out(tmp.getArray());
413     out /= moff;
414     out *= tsarr;
415     Array<Bool> outflagsb = !(mon.getMask() && moff.getMask());
416     Array<uChar> outflags(outflagsb.shape());
417     convertArray(outflags,outflagsb);
418
419// Fill container for this row
420
421     SDContainer sc = on->getSDContainer();
422     sc.putTsys(tsarr);
423     sc.scanid = 0;
424     sc.putSpectrum(out);
425     sc.putFlags(outflags);
426
427// Put new row in output Table
428
429     sdmt->putSDContainer(sc);
430  }
431//
432  return CountedPtr<SDMemTable>(sdmt);
433}
434
435void SDMath::multiplyInSitu(SDMemTable* in, Float factor) {
436  SDMemTable* sdmt = new SDMemTable(*in);
437  Table t = sdmt->table();
438  ArrayColumn<Float> spec(t,"SPECTRA"); 
439  for (uInt i=0; i < t.nrow(); i++) {
440    MaskedArray<Float> marr(sdmt->rowAsMaskedArray(i));
441    marr *= factor;
442    spec.put(i, marr.getArray());
443  }
444  in = sdmt;
445  delete sdmt;sdmt=0;
446}
447
448CountedPtr<SDMemTable>
449SDMath::multiply(const CountedPtr<SDMemTable>& in, Float factor)
450//
451// Multiply values by factor
452//
453{
454  SDMemTable* sdmt = new SDMemTable(*in);
455  Table t = sdmt->table();
456  ArrayColumn<Float> spec(t,"SPECTRA");
457
458  for (uInt i=0; i < t.nrow(); i++) {
459    MaskedArray<Float> marr(sdmt->rowAsMaskedArray(i));
460    marr *= factor;
461    spec.put(i, marr.getArray());
462  }
463  return CountedPtr<SDMemTable>(sdmt);
464}
465
466CountedPtr<SDMemTable>
467SDMath::add(const CountedPtr<SDMemTable>& in, Float offset)
468//
469// Add offset to values
470//
471{
472  SDMemTable* sdmt = new SDMemTable(*in);
473
474  Table t = sdmt->table();
475  ArrayColumn<Float> spec(t,"SPECTRA");
476
477  for (uInt i=0; i < t.nrow(); i++) {
478    MaskedArray<Float> marr(sdmt->rowAsMaskedArray(i));
479    marr += offset;
480    spec.put(i, marr.getArray());
481  }
482  return CountedPtr<SDMemTable>(sdmt);
483}
484
485
486CountedPtr<SDMemTable>
487SDMath::hanning(const CountedPtr<SDMemTable>& in)
488//
489// Hanning smooth each row
490// Should Tsys be smoothed ?
491//
492{
493  SDMemTable* sdmt = new SDMemTable(*in,True);
494
495// Loop over rows in Table
496
497  for (uInt ri=0; ri < in->nRow(); ++ri) {
498
499// Get data
500   
501    const MaskedArray<Float>& marr(in->rowAsMaskedArray(ri));
502    Array<Float> arr = marr.getArray();
503    Array<Bool> barr = marr.getMask();
504
505// Smooth along the channels axis
506
507    uInt axis = 3;
508    VectorIterator<Float> itData(arr, axis);
509    VectorIterator<Bool> itMask(barr, axis);
510    Vector<Float> outv;
511    Vector<Bool> outm;
512    while (!itData.pastEnd()) {
513       mathutil::hanning(outv, outm, itData.vector(), itMask.vector());
514       itData.vector() = outv;                                                 
515       itMask.vector() = outm;
516//
517       itData.next();
518       itMask.next();
519    }
520
521// Create and put back
522
523    Array<uChar> outflags(barr.shape());
524    convertArray(outflags,!barr);
525    SDContainer sc = in->getSDContainer(ri);
526    sc.putSpectrum(arr);
527    sc.putFlags(outflags);
528    sdmt->putSDContainer(sc);
529  }
530  return CountedPtr<SDMemTable>(sdmt);
531}
532
533
534
535
536CountedPtr<SDMemTable>
537SDMath::averagePol(const CountedPtr<SDMemTable>& in,
538                   const Vector<Bool>& mask)
539{
540   const uInt nRows = in->nRow();
541   const uInt axis = 3;                        // Spectrum
542   const IPosition axes(2, 2, 3);              // pol-channel plane
543
544// Create output Table
545
546  SDMemTable* sdmt = new SDMemTable(*in, True);
547
548// Loop over rows
549
550   for (uInt iRow=0; iRow<nRows; iRow++) {
551
552// Get data for this row
553
554      MaskedArray<Float> marr(in->rowAsMaskedArray(iRow));
555      Array<Float>& arr = marr.getRWArray();
556      const Array<Bool>& barr = marr.getMask();
557//
558      IPosition shp = marr.shape();
559      const Bool useMask = (mask.nelements() == shp(axis));
560      const uInt nChan = shp(axis);
561
562// Make iterators to iterate by pol-channel planes
563
564     ArrayIterator<Float> itDataPlane(arr, axes);
565     ReadOnlyArrayIterator<Bool> itMaskPlane(barr, axes);
566
567// Accumulations
568
569     Float fac = 0.0;
570     Vector<Float> vecSum(nChan,0.0);
571
572// Iterate by plane
573
574     while (!itDataPlane.pastEnd()) {
575
576// Iterate through pol-channel plane by spectrum
577
578        Vector<Float> t1(nChan); t1 = 0.0;
579        Vector<Bool> t2(nChan); t2 = True;
580        MaskedArray<Float> vecSum(t1,t2);
581        Float varSum = 0.0;
582        {
583           ReadOnlyVectorIterator<Float> itDataVec(itDataPlane.array(), 1);
584           ReadOnlyVectorIterator<Bool> itMaskVec(itMaskPlane.array(), 1);
585           while (!itDataVec.pastEnd()) {     
586
587// Create MA of data & mask (optionally including OTF mask) and  get variance
588
589              if (useMask) {
590                 const MaskedArray<Float> spec(itDataVec.vector(),mask&&itMaskVec.vector());
591                 fac = 1.0 / variance(spec);
592              } else {
593                 const MaskedArray<Float> spec(itDataVec.vector(),itMaskVec.vector());
594                 fac = 1.0 / variance(spec);
595              }
596
597// Normalize spectrum (without OTF mask) and accumulate
598
599              const MaskedArray<Float> spec(fac*itDataVec.vector(), itMaskVec.vector());
600              vecSum += spec;
601              varSum += fac;
602
603// Next
604
605              itDataVec.next();
606              itMaskVec.next();
607           }
608        }
609
610// Normalize summed spectrum
611
612        vecSum /= varSum;
613
614// We have formed the weighted averaged spectrum from all polarizations
615// for this beam and IF.  Now replicate the spectrum to all polarizations
616
617        {
618           VectorIterator<Float> itDataVec(itDataPlane.array(), 1);  // Writes back into 'arr'
619           const Vector<Float>& vecSumData = vecSum.getArray();      // It *is* a Vector
620//
621           while (!itDataVec.pastEnd()) {     
622              itDataVec.vector() = vecSumData;
623              itDataVec.next();
624           }
625        }
626
627// Step to next beam/IF combination
628
629        itDataPlane.next();
630        itMaskPlane.next();
631     }
632
633// Generate output container and write it to output table
634
635     SDContainer sc = in->getSDContainer();
636     Array<uChar> outflags(barr.shape());
637     convertArray(outflags,!barr);
638     sc.putSpectrum(arr);
639     sc.putFlags(outflags);
640     sdmt->putSDContainer(sc);
641   }
642//
643  return CountedPtr<SDMemTable>(sdmt);
644}
645
646
647CountedPtr<SDMemTable> SDMath::bin(const CountedPtr<SDMemTable>& in,
648                                   Int width)
649{
650  SDHeader sh = in->getSDHeader();
651  SDMemTable* sdmt = new SDMemTable(*in,True);
652
653// Bin up SpectralCoordinates
654
655  IPosition factors(1);
656  factors(0) = width;
657  for (uInt j=0; j<in->nCoordinates(); ++j) {
658    CoordinateSystem cSys;
659    cSys.addCoordinate(in->getCoordinate(j));
660    CoordinateSystem cSysBin =
661      CoordinateUtil::makeBinnedCoordinateSystem (factors, cSys, False);
662//
663    SpectralCoordinate sCBin = cSysBin.spectralCoordinate(0);
664    sdmt->setCoordinate(sCBin, j);
665  }
666
667// Use RebinLattice to find shape
668
669  IPosition shapeIn(1,sh.nchan);
670  IPosition shapeOut = RebinLattice<Float>::rebinShape (shapeIn, factors);
671  sh.nchan = shapeOut(0);
672  sdmt->putSDHeader(sh);
673
674
675// Loop over rows and bin along channel axis
676 
677  const uInt axis = 3;
678  for (uInt i=0; i < in->nRow(); ++i) {
679    SDContainer sc = in->getSDContainer(i);
680//
681    Array<Float> tSys(sc.getTsys());                           // Get it out before sc changes shape
682
683// Bin up spectrum
684
685    MaskedArray<Float> marr(in->rowAsMaskedArray(i));
686    MaskedArray<Float> marrout;
687    LatticeUtilities::bin(marrout, marr, axis, width);
688
689// Put back the binned data and flags
690
691    IPosition ip2 = marrout.shape();
692    sc.resize(ip2);
693    sc.putSpectrum(marrout.getArray());
694//
695    Array<uChar> outflags(ip2);
696    convertArray(outflags,!(marrout.getMask()));
697    sc.putFlags(outflags);
698
699// Bin up Tsys. 
700
701    Array<Bool> allGood(tSys.shape(),True);
702    MaskedArray<Float> tSysIn(tSys, allGood, True);
703//
704    MaskedArray<Float> tSysOut;   
705    LatticeUtilities::bin(tSysOut, tSysIn, axis, width);
706    sc.putTsys(tSysOut.getArray());
707    sdmt->putSDContainer(sc);
708  }
709  return CountedPtr<SDMemTable>(sdmt);
710}
711
712
713
714std::vector<float> SDMath::statistic (const CountedPtr<SDMemTable>& in,
715                                       const std::vector<bool>& mask,
716                                       const std::string& which)
717//
718// Perhaps iteration over pol/beam/if should be in here
719// and inside the nrow iteration ?
720//
721{
722  const uInt nRow = in->nRow();
723  std::vector<float> result(nRow);
724  Vector<Bool> msk(mask);
725
726// Specify cursor location
727
728  uInt i = in->getBeam();
729  uInt j = in->getIF();
730  uInt k = in->getPol();
731  IPosition start(4,i,j,k,0);
732  IPosition end(4,i,j,k,in->nChan()-1);
733
734// Loop over rows
735
736  const uInt nEl = msk.nelements();
737  for (uInt ii=0; ii < in->nRow(); ++ii) {
738
739// Get row and deconstruct
740
741     MaskedArray<Float> marr(in->rowAsMaskedArray(ii));
742     Array<Float> arr = marr.getArray();
743     Array<Bool> barr = marr.getMask();
744
745// Access desired piece of data
746
747     Array<Float> v((arr(start,end)).nonDegenerate());
748     Array<Bool> m((barr(start,end)).nonDegenerate());
749
750// Apply OTF mask
751
752     MaskedArray<Float> tmp;
753     if (m.nelements()==nEl) {
754       tmp.setData(v,m&&msk);
755     } else {
756       tmp.setData(v,m);
757     }
758
759// Get statistic
760
761     result[ii] = mathutil::statistics(which, tmp);
762  }
763//
764  return result;
765}
766
767void SDMath::fillSDC (SDContainer& sc,
768                      const Array<Bool>& mask,
769                      const Array<Float>& data,
770                      const Array<Float>& tSys,
771                      Int scanID, Double timeStamp,
772                      Double interval, const String& sourceName,
773                      const Vector<uInt>& freqID)
774{
775  sc.putSpectrum(data);
776//
777  Array<uChar> outflags(mask.shape());
778  convertArray(outflags,!mask);
779  sc.putFlags(outflags);
780//
781  sc.putTsys(tSys);
782
783// Time things
784
785  sc.timestamp = timeStamp;
786  sc.interval = interval;
787  sc.scanid = scanID;
788//
789  sc.sourcename = sourceName;
790  sc.putFreqMap(freqID);
791}
792
793void SDMath::normalize (MaskedArray<Float>& sum,
794                        const Array<Float>& sumSq,
795                        const Array<Float>& nPts,
796                        weightType wtType, Int axis,
797                        Int nAxesSub)
798{
799   IPosition pos2(nAxesSub,0);
800//
801   if (wtType==NONE) {
802
803// We just average by the number of points accumulated.
804// We need to make a MA out of nPts so that no divide by
805// zeros occur
806
807      MaskedArray<Float> t(nPts, (nPts>Float(0.0)));
808      sum /= t;
809   } else if (wtType==VAR) {
810
811// Normalize each spectrum by sum(1/var) where the variance
812// is worked out for each spectrum
813
814      Array<Float>& data = sum.getRWArray();
815      VectorIterator<Float> itData(data, axis);
816      while (!itData.pastEnd()) {
817         pos2 = itData.pos().getFirst(nAxesSub);
818         itData.vector() /= sumSq(pos2);
819         itData.next();
820      }
821   } else if (wtType==TSYS) {
822   }
823}
824
Note: See TracBrowser for help on using the repository browser.