source: trunk/src/SDMath.cc @ 146

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

rework 'multiply' and 'multiplyInSitu' to use one common
'localMultiply' function behind the scenes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.5 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// Accumulate
271
272        accumulate (timeSum, intSum, nAccum, sum, sumSq, nPts, tSysSum,
273                    tSys, nInc, mask, time, interval, in, iTab, iRow, axis,
274                    nAxesSub, useMask, wtType);
275//
276       oldSourceName = sourceName;
277       oldFreqID = freqID;
278    }
279  }
280
281// OK at this point we have accumulation data which is either
282//   - accumulated from all tables into one row
283// or
284//   - accumulated from the last scan average
285//
286// Normalize data in 'sum' accumulation array according to weighting scheme
287
288  normalize (sum, sumSq, nPts, wtType, axis, nAxesSub);
289
290// Create and fill container.  The container we clone will be from
291// the last Table and the first row that went into the current
292// accumulation.  It probably doesn't matter that much really...
293
294  Float nR(nAccum);
295  SDContainer sc = in[tableStart]->getSDContainer(rowStart);
296  fillSDC (sc, sum.getMask(), sum.getArray(), tSysSum/nR, outScanID,
297           timeSum/nR, intSum, sourceNameStart, freqIDStart);
298//
299  pTabOut->putSDContainer(sc);
300/*
301   cout << endl;
302   cout << "Last accumulation for output scan ID " << outScanID << endl;
303   cout << "   The first row in this accumulation is " << rowStart << endl;
304   cout << "   The number of rows accumulated is " << nAccum << endl;
305   cout << "   The first table in this accumulation is " << tableStart << endl;
306   cout << "   The first source in this accumulation is " << sourceNameStart << endl;
307   cout << "   The first freqID in this accumulation is " << freqIDStart << endl;
308   cout  << "   Average time stamp = " << timeSum/nR << endl;
309   cout << "   Integrated time = " << intSum << endl;
310*/
311  return CountedPtr<SDMemTable>(pTabOut);
312}
313
314
315
316CountedPtr<SDMemTable>
317SDMath::quotient(const CountedPtr<SDMemTable>& on,
318                 const CountedPtr<SDMemTable>& off)
319//
320// Compute quotient spectrum
321//
322{
323  const uInt nRows = on->nRow();
324  if (off->nRow() != nRows) {
325     throw (AipsError("Input Scan Tables must have the same number of rows"));
326  }
327
328// Input Tables and columns
329
330  Table ton = on->table();
331  Table toff = off->table();
332  ROArrayColumn<Float> tsys(toff, "TSYS");
333  ROScalarColumn<Double> mjd(ton, "TIME");
334  ROScalarColumn<Double> integr(ton, "INTERVAL");
335  ROScalarColumn<String> srcn(ton, "SRCNAME");
336  ROArrayColumn<uInt> freqidc(ton, "FREQID");
337
338// Output Table cloned from input
339
340  SDMemTable* sdmt = new SDMemTable(*on, True);
341
342// Loop over rows
343
344  for (uInt i=0; i<nRows; i++) {
345     MaskedArray<Float> mon(on->rowAsMaskedArray(i));
346     MaskedArray<Float> moff(off->rowAsMaskedArray(i));
347     IPosition ipon = mon.shape();
348     IPosition ipoff = moff.shape();
349//
350     Array<Float> tsarr; 
351     tsys.get(i, tsarr);
352     if (ipon != ipoff && ipon != tsarr.shape()) {
353       throw(AipsError("on/off not conformant"));
354     }
355
356// Compute quotient
357
358     MaskedArray<Float> tmp = (mon-moff);
359     Array<Float> out(tmp.getArray());
360     out /= moff;
361     out *= tsarr;
362     Array<Bool> outflagsb = !(mon.getMask() && moff.getMask());
363     Array<uChar> outflags(outflagsb.shape());
364     convertArray(outflags,outflagsb);
365
366// Fill container for this row
367
368     SDContainer sc = on->getSDContainer();
369     sc.putTsys(tsarr);
370     sc.scanid = 0;
371     sc.putSpectrum(out);
372     sc.putFlags(outflags);
373
374// Put new row in output Table
375
376     sdmt->putSDContainer(sc);
377  }
378//
379  return CountedPtr<SDMemTable>(sdmt);
380}
381
382
383
384void SDMath::multiplyInSitu(SDMemTable* pIn, Float factor)
385{
386  SDMemTable* pOut = localMultiply (*pIn, factor);
387  *pIn = *pOut;
388   delete pOut;
389
390
391
392CountedPtr<SDMemTable>
393SDMath::multiply(const CountedPtr<SDMemTable>& in, Float factor)
394{
395  return CountedPtr<SDMemTable>(localMultiply(*in,factor));
396}
397
398CountedPtr<SDMemTable>
399SDMath::add(const CountedPtr<SDMemTable>& in, Float offset)
400//
401// Add offset to values
402//
403{
404  SDMemTable* sdmt = new SDMemTable(*in,False);
405  Table t = sdmt->table();
406  ArrayColumn<Float> spec(t,"SPECTRA");
407
408  for (uInt i=0; i < t.nrow(); i++) {
409    MaskedArray<Float> marr(sdmt->rowAsMaskedArray(i));
410    marr += offset;
411    spec.put(i, marr.getArray());
412  }
413  return CountedPtr<SDMemTable>(sdmt);
414}
415
416
417CountedPtr<SDMemTable>
418SDMath::hanning(const CountedPtr<SDMemTable>& in)
419//
420// Hanning smooth each row
421// Should Tsys be smoothed ?
422//
423{
424  SDMemTable* sdmt = new SDMemTable(*in,True);
425
426// Loop over rows in Table
427
428  for (uInt ri=0; ri < in->nRow(); ++ri) {
429
430// Get data
431   
432    const MaskedArray<Float>& marr(in->rowAsMaskedArray(ri));
433    Array<Float> arr = marr.getArray();
434    Array<Bool> barr = marr.getMask();
435
436// Smooth along the channels axis
437
438    uInt axis = 3;
439    VectorIterator<Float> itData(arr, axis);
440    VectorIterator<Bool> itMask(barr, axis);
441    Vector<Float> outv;
442    Vector<Bool> outm;
443    while (!itData.pastEnd()) {
444       mathutil::hanning(outv, outm, itData.vector(), itMask.vector());
445       itData.vector() = outv;                                                 
446       itMask.vector() = outm;
447//
448       itData.next();
449       itMask.next();
450    }
451
452// Create and put back
453
454    Array<uChar> outflags(barr.shape());
455    convertArray(outflags,!barr);
456    SDContainer sc = in->getSDContainer(ri);
457    sc.putSpectrum(arr);
458    sc.putFlags(outflags);
459    sdmt->putSDContainer(sc);
460  }
461  return CountedPtr<SDMemTable>(sdmt);
462}
463
464
465
466
467CountedPtr<SDMemTable>
468SDMath::averagePol(const CountedPtr<SDMemTable>& in,
469                   const Vector<Bool>& mask)
470{
471   const uInt nRows = in->nRow();
472   const uInt axis = 3;                        // Spectrum
473   const IPosition axes(2, 2, 3);              // pol-channel plane
474
475// Create output Table
476
477  SDMemTable* sdmt = new SDMemTable(*in, True);
478
479// Loop over rows
480
481   for (uInt iRow=0; iRow<nRows; iRow++) {
482
483// Get data for this row
484
485      MaskedArray<Float> marr(in->rowAsMaskedArray(iRow));
486      Array<Float>& arr = marr.getRWArray();
487      const Array<Bool>& barr = marr.getMask();
488//
489      IPosition shp = marr.shape();
490      const Bool useMask = (mask.nelements() == shp(axis));
491      const uInt nChan = shp(axis);
492
493// Make iterators to iterate by pol-channel planes
494
495     ArrayIterator<Float> itDataPlane(arr, axes);
496     ReadOnlyArrayIterator<Bool> itMaskPlane(barr, axes);
497
498// Accumulations
499
500     Float fac = 0.0;
501     Vector<Float> vecSum(nChan,0.0);
502
503// Iterate by plane
504
505     while (!itDataPlane.pastEnd()) {
506
507// Iterate through pol-channel plane by spectrum
508
509        Vector<Float> t1(nChan); t1 = 0.0;
510        Vector<Bool> t2(nChan); t2 = True;
511        MaskedArray<Float> vecSum(t1,t2);
512        Float varSum = 0.0;
513        {
514           ReadOnlyVectorIterator<Float> itDataVec(itDataPlane.array(), 1);
515           ReadOnlyVectorIterator<Bool> itMaskVec(itMaskPlane.array(), 1);
516           while (!itDataVec.pastEnd()) {     
517
518// Create MA of data & mask (optionally including OTF mask) and  get variance
519
520              if (useMask) {
521                 const MaskedArray<Float> spec(itDataVec.vector(),mask&&itMaskVec.vector());
522                 fac = 1.0 / variance(spec);
523              } else {
524                 const MaskedArray<Float> spec(itDataVec.vector(),itMaskVec.vector());
525                 fac = 1.0 / variance(spec);
526              }
527
528// Normalize spectrum (without OTF mask) and accumulate
529
530              const MaskedArray<Float> spec(fac*itDataVec.vector(), itMaskVec.vector());
531              vecSum += spec;
532              varSum += fac;
533
534// Next
535
536              itDataVec.next();
537              itMaskVec.next();
538           }
539        }
540
541// Normalize summed spectrum
542
543        vecSum /= varSum;
544
545// We have formed the weighted averaged spectrum from all polarizations
546// for this beam and IF.  Now replicate the spectrum to all polarizations
547
548        {
549           VectorIterator<Float> itDataVec(itDataPlane.array(), 1);  // Writes back into 'arr'
550           const Vector<Float>& vecSumData = vecSum.getArray();      // It *is* a Vector
551//
552           while (!itDataVec.pastEnd()) {     
553              itDataVec.vector() = vecSumData;
554              itDataVec.next();
555           }
556        }
557
558// Step to next beam/IF combination
559
560        itDataPlane.next();
561        itMaskPlane.next();
562     }
563
564// Generate output container and write it to output table
565
566     SDContainer sc = in->getSDContainer();
567     Array<uChar> outflags(barr.shape());
568     convertArray(outflags,!barr);
569     sc.putSpectrum(arr);
570     sc.putFlags(outflags);
571     sdmt->putSDContainer(sc);
572   }
573//
574  return CountedPtr<SDMemTable>(sdmt);
575}
576
577
578CountedPtr<SDMemTable> SDMath::bin(const CountedPtr<SDMemTable>& in,
579                                   Int width)
580{
581  SDHeader sh = in->getSDHeader();
582  SDMemTable* sdmt = new SDMemTable(*in,True);
583
584// Bin up SpectralCoordinates
585
586  IPosition factors(1);
587  factors(0) = width;
588  for (uInt j=0; j<in->nCoordinates(); ++j) {
589    CoordinateSystem cSys;
590    cSys.addCoordinate(in->getCoordinate(j));
591    CoordinateSystem cSysBin =
592      CoordinateUtil::makeBinnedCoordinateSystem (factors, cSys, False);
593//
594    SpectralCoordinate sCBin = cSysBin.spectralCoordinate(0);
595    sdmt->setCoordinate(sCBin, j);
596  }
597
598// Use RebinLattice to find shape
599
600  IPosition shapeIn(1,sh.nchan);
601  IPosition shapeOut = RebinLattice<Float>::rebinShape (shapeIn, factors);
602  sh.nchan = shapeOut(0);
603  sdmt->putSDHeader(sh);
604
605
606// Loop over rows and bin along channel axis
607 
608  const uInt axis = 3;
609  for (uInt i=0; i < in->nRow(); ++i) {
610    SDContainer sc = in->getSDContainer(i);
611//
612    Array<Float> tSys(sc.getTsys());                           // Get it out before sc changes shape
613
614// Bin up spectrum
615
616    MaskedArray<Float> marr(in->rowAsMaskedArray(i));
617    MaskedArray<Float> marrout;
618    LatticeUtilities::bin(marrout, marr, axis, width);
619
620// Put back the binned data and flags
621
622    IPosition ip2 = marrout.shape();
623    sc.resize(ip2);
624    sc.putSpectrum(marrout.getArray());
625//
626    Array<uChar> outflags(ip2);
627    convertArray(outflags,!(marrout.getMask()));
628    sc.putFlags(outflags);
629
630// Bin up Tsys. 
631
632    Array<Bool> allGood(tSys.shape(),True);
633    MaskedArray<Float> tSysIn(tSys, allGood, True);
634//
635    MaskedArray<Float> tSysOut;   
636    LatticeUtilities::bin(tSysOut, tSysIn, axis, width);
637    sc.putTsys(tSysOut.getArray());
638    sdmt->putSDContainer(sc);
639  }
640  return CountedPtr<SDMemTable>(sdmt);
641}
642
643
644
645std::vector<float> SDMath::statistic (const CountedPtr<SDMemTable>& in,
646                                       const std::vector<bool>& mask,
647                                       const std::string& which)
648//
649// Perhaps iteration over pol/beam/if should be in here
650// and inside the nrow iteration ?
651//
652{
653  const uInt nRow = in->nRow();
654  std::vector<float> result(nRow);
655  Vector<Bool> msk(mask);
656
657// Specify cursor location
658
659  uInt i = in->getBeam();
660  uInt j = in->getIF();
661  uInt k = in->getPol();
662  IPosition start(4,i,j,k,0);
663  IPosition end(4,i,j,k,in->nChan()-1);
664
665// Loop over rows
666
667  const uInt nEl = msk.nelements();
668  for (uInt ii=0; ii < in->nRow(); ++ii) {
669
670// Get row and deconstruct
671
672     MaskedArray<Float> marr(in->rowAsMaskedArray(ii));
673     Array<Float> arr = marr.getArray();
674     Array<Bool> barr = marr.getMask();
675
676// Access desired piece of data
677
678     Array<Float> v((arr(start,end)).nonDegenerate());
679     Array<Bool> m((barr(start,end)).nonDegenerate());
680
681// Apply OTF mask
682
683     MaskedArray<Float> tmp;
684     if (m.nelements()==nEl) {
685       tmp.setData(v,m&&msk);
686     } else {
687       tmp.setData(v,m);
688     }
689
690// Get statistic
691
692     result[ii] = mathutil::statistics(which, tmp);
693  }
694//
695  return result;
696}
697
698
699
700// 'private' functions
701
702void SDMath::fillSDC (SDContainer& sc,
703                      const Array<Bool>& mask,
704                      const Array<Float>& data,
705                      const Array<Float>& tSys,
706                      Int scanID, Double timeStamp,
707                      Double interval, const String& sourceName,
708                      const Vector<uInt>& freqID)
709{
710  sc.putSpectrum(data);
711//
712  Array<uChar> outflags(mask.shape());
713  convertArray(outflags,!mask);
714  sc.putFlags(outflags);
715//
716  sc.putTsys(tSys);
717
718// Time things
719
720  sc.timestamp = timeStamp;
721  sc.interval = interval;
722  sc.scanid = scanID;
723//
724  sc.sourcename = sourceName;
725  sc.putFreqMap(freqID);
726}
727
728void SDMath::normalize (MaskedArray<Float>& sum,
729                        const Array<Float>& sumSq,
730                        const Array<Float>& nPts,
731                        weightType wtType, Int axis,
732                        Int nAxesSub)
733{
734   IPosition pos2(nAxesSub,0);
735//
736   if (wtType==NONE) {
737
738// We just average by the number of points accumulated.
739// We need to make a MA out of nPts so that no divide by
740// zeros occur
741
742      MaskedArray<Float> t(nPts, (nPts>Float(0.0)));
743      sum /= t;
744   } else if (wtType==VAR) {
745
746// Normalize each spectrum by sum(1/var) where the variance
747// is worked out for each spectrum
748
749      Array<Float>& data = sum.getRWArray();
750      VectorIterator<Float> itData(data, axis);
751      while (!itData.pastEnd()) {
752         pos2 = itData.pos().getFirst(nAxesSub);
753         itData.vector() /= sumSq(pos2);
754         itData.next();
755      }
756   } else if (wtType==TSYS) {
757   }
758}
759
760
761void SDMath::accumulate (Double& timeSum, Double& intSum, Int& nAccum,
762                         MaskedArray<Float>& sum, Array<Float>& sumSq,
763                         Array<Float>& nPts, Array<Float>& tSysSum,
764                         const Array<Float>& tSys, const Array<Float>& nInc,
765                         const Vector<Bool>& mask, Double time, Double interval,
766                         const Block<CountedPtr<SDMemTable> >& in,
767                         uInt iTab, uInt iRow, uInt axis,
768                         uInt nAxesSub, Bool useMask,
769                         weightType wtType)
770{
771
772// Get data
773
774   MaskedArray<Float> dataIn(in[iTab]->rowAsMaskedArray(iRow));
775   Array<Float>& valuesIn = dataIn.getRWArray();           // writable reference
776   const Array<Bool>& maskIn = dataIn.getMask();          // RO reference
777//
778   if (wtType==NONE) {
779      const MaskedArray<Float> n(nInc,dataIn.getMask());
780      nPts += n;                               // Only accumulates where mask==T
781   } else if (wtType==VAR) {
782
783// We are going to average the data, weighted by the noise for each pol, beam and IF.
784// So therefore we need to iterate through by spectrum (axis 3)
785
786      VectorIterator<Float> itData(valuesIn, axis);
787      ReadOnlyVectorIterator<Bool> itMask(maskIn, axis);
788      Float fac = 1.0;
789      IPosition pos(nAxesSub,0); 
790//
791      while (!itData.pastEnd()) {
792
793// Make MaskedArray of Vector, optionally apply OTF mask, and find scaling factor
794
795        if (useMask) {
796           MaskedArray<Float> tmp(itData.vector(),mask&&itMask.vector());
797           fac = 1.0/variance(tmp);
798        } else {
799           MaskedArray<Float> tmp(itData.vector(),itMask.vector());
800           fac = 1.0/variance(tmp);
801        }
802
803// Scale data
804
805        itData.vector() *= fac;     // Writes back into 'dataIn'
806//
807// Accumulate variance per if/pol/beam averaged over spectrum
808// This method to get pos2 from itData.pos() is only valid
809// because the spectral axis is the last one (so we can just
810// copy the first nAXesSub positions out)
811
812        pos = itData.pos().getFirst(nAxesSub);
813        sumSq(pos) += fac;
814//
815        itData.next();
816        itMask.next();
817      }
818   } else if (wtType==TSYS) {
819   }
820
821// Accumulate sum of (possibly scaled) data
822
823   sum += dataIn;
824
825// Accumulate Tsys, time, and interval
826
827   tSysSum += tSys;
828   timeSum += time;
829   intSum += interval;
830   nAccum += 1;
831}
832
833SDMemTable* SDMath::localMultiply (const SDMemTable& in, Float factor)
834{
835  SDMemTable* pOut = new SDMemTable(in,False);
836  const Table& tOut = pOut->table();
837  ArrayColumn<Float> spec(tOut,"SPECTRA"); 
838//
839  for (uInt i=0; i < tOut.nrow(); i++) {
840    MaskedArray<Float> marr(pOut->rowAsMaskedArray(i));
841    marr *= factor;
842    spec.put(i, marr.getArray());
843  }
844   return pOut;
845}
846
847
Note: See TracBrowser for help on using the repository browser.