source: trunk/src/SDMath.cc @ 177

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

remove function 'hanning'
add function 'smooth' (includes hanning)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.9 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/Utilities/Assert.h>
45#include <casa/Exceptions.h>
46
47#include <scimath/Mathematics/VectorKernel.h>
48#include <scimath/Mathematics/Convolver.h>
49
50#include <tables/Tables/Table.h>
51#include <tables/Tables/ScalarColumn.h>
52#include <tables/Tables/ArrayColumn.h>
53
54#include <lattices/Lattices/LatticeUtilities.h>
55#include <lattices/Lattices/RebinLattice.h>
56#include <coordinates/Coordinates/SpectralCoordinate.h>
57#include <coordinates/Coordinates/CoordinateSystem.h>
58#include <coordinates/Coordinates/CoordinateUtil.h>
59
60#include "MathUtils.h"
61#include "SDContainer.h"
62#include "SDMemTable.h"
63
64#include "SDMath.h"
65
66using namespace casa;
67using namespace asap;
68
69
70SDMath::SDMath()
71{;}
72
73SDMath::SDMath (const SDMath& other)
74{
75
76// No state
77
78}
79
80SDMath& SDMath::operator=(const SDMath& other)
81{
82  if (this != &other) {
83// No state
84  }
85  return *this;
86}
87
88
89CountedPtr<SDMemTable> SDMath::average (const Block<CountedPtr<SDMemTable> >& in,
90                                        const Vector<Bool>& mask, Bool scanAv,
91                                        const std::string& weightStr)
92//
93// Weighted averaging of spectra from one or more Tables.
94//
95{
96
97// Convert weight type
98 
99  WeightType wtType = NONE;
100  convertWeightString (wtType, weightStr);
101
102// Create output Table by cloning from the first table
103
104  SDMemTable* pTabOut = new SDMemTable(*in[0],True);
105
106// Setup
107
108  const uInt axis = 3;                                     // Spectral axis
109  IPosition shp = in[0]->rowAsMaskedArray(0).shape();      // Must not change
110  Array<Float> arr(shp);
111  Array<Bool> barr(shp);
112  const Bool useMask = (mask.nelements() == shp(axis));
113
114// Columns from Tables
115
116  ROArrayColumn<Float> tSysCol;
117  ROScalarColumn<Double> mjdCol;
118  ROScalarColumn<String> srcNameCol;
119  ROScalarColumn<Double> intCol;
120  ROArrayColumn<uInt> fqIDCol;
121
122// Create accumulation MaskedArray. We accumulate for each channel,if,pol,beam
123// Note that the mask of the accumulation array will ALWAYS remain ALL True.
124// The MA is only used so that when data which is masked Bad is added to it,
125// that data does not contribute.
126
127  Array<Float> zero(shp);
128  zero=0.0;
129  Array<Bool> good(shp);
130  good = True;
131  MaskedArray<Float> sum(zero,good);
132
133// Counter arrays
134
135  Array<Float> nPts(shp);             // Number of points
136  nPts = 0.0;
137  Array<Float> nInc(shp);             // Increment
138  nInc = 1.0;
139
140// Create accumulation Array for variance. We accumulate for
141// each if,pol,beam, but average over channel.  So we need
142// a shape with one less axis dropping channels.
143
144  const uInt nAxesSub = shp.nelements() - 1;
145  IPosition shp2(nAxesSub);
146  for (uInt i=0,j=0; i<(nAxesSub+1); i++) {
147     if (i!=axis) {
148       shp2(j) = shp(i);
149       j++;
150     }
151  }
152  Array<Float> sumSq(shp2);
153  sumSq = 0.0;
154  IPosition pos2(nAxesSub,0);                        // For indexing
155
156// Time-related accumulators
157
158  Double time;
159  Double timeSum = 0.0;
160  Double intSum = 0.0;
161  Double interval = 0.0;
162
163// To get the right shape for the Tsys accumulator we need to
164// access a column from the first table.  The shape of this
165// array must not change
166
167  Array<Float> tSysSum;
168  {
169    const Table& tabIn = in[0]->table();
170    tSysCol.attach(tabIn,"TSYS");
171    tSysSum.resize(tSysCol.shape(0));
172  }
173  tSysSum =0.0;
174  Array<Float> tSys;
175
176// Scan and row tracking
177
178  Int oldScanID = 0;
179  Int outScanID = 0;
180  Int scanID = 0;
181  Int rowStart = 0;
182  Int nAccum = 0;
183  Int tableStart = 0;
184
185// Source and FreqID
186
187  String sourceName, oldSourceName, sourceNameStart;
188  Vector<uInt> freqID, freqIDStart, oldFreqID;
189
190// Loop over tables
191
192  Float fac = 1.0;
193  const uInt nTables = in.nelements();
194  for (uInt iTab=0; iTab<nTables; iTab++) {
195
196// Attach columns to Table
197
198     const Table& tabIn = in[iTab]->table();
199     tSysCol.attach(tabIn, "TSYS");
200     mjdCol.attach(tabIn, "TIME");
201     srcNameCol.attach(tabIn, "SRCNAME");
202     intCol.attach(tabIn, "INTERVAL");
203     fqIDCol.attach(tabIn, "FREQID");
204
205// Loop over rows in Table
206
207     const uInt nRows = in[iTab]->nRow();
208     for (uInt iRow=0; iRow<nRows; iRow++) {
209
210// Check conformance
211
212        IPosition shp2 = in[iTab]->rowAsMaskedArray(iRow).shape();
213        if (!shp.isEqual(shp2)) {
214           throw (AipsError("Shapes for all rows must be the same"));
215        }
216
217// If we are not doing scan averages, make checks for source and
218// frequency setup and warn if averaging across them
219
220// Get copy of Scan Container for this row
221
222        SDContainer sc = in[iTab]->getSDContainer(iRow);
223        scanID = sc.scanid;
224
225// Get quantities from columns
226
227        srcNameCol.getScalar(iRow, sourceName);
228        mjdCol.get(iRow, time);
229        tSysCol.get(iRow, tSys);
230        intCol.get(iRow, interval);
231        fqIDCol.get(iRow, freqID);
232
233// Initialize first source and freqID
234
235        if (iRow==0 && iTab==0) {
236          sourceNameStart = sourceName;
237          freqIDStart = freqID;
238        }
239
240// If we are doing scan averages, see if we are at the end of an
241// accumulation period (scan).  We must check soutce names too,
242// since we might have two tables with one scan each but different
243// source names; we shouldn't average different sources together
244
245        if (scanAv && ( (scanID != oldScanID)  ||
246                        (iRow==0 && iTab>0 && sourceName!=oldSourceName))) {
247
248// Normalize data in 'sum' accumulation array according to weighting scheme
249
250           normalize (sum, sumSq, nPts, wtType, axis, nAxesSub);
251
252// Fill scan container. The source and freqID come from the
253// first row of the first table that went into this average (
254// should be the same for all rows in the scan average)
255
256           Float nR(nAccum);
257           fillSDC (sc, sum.getMask(), sum.getArray(), tSysSum/nR, outScanID,
258                    timeSum/nR, intSum, sourceNameStart, freqIDStart);
259
260// Write container out to Table
261
262           pTabOut->putSDContainer(sc);
263
264// Reset accumulators
265
266           sum = 0.0;
267           sumSq = 0.0;
268           nAccum = 0;
269//
270           tSysSum =0.0;
271           timeSum = 0.0;
272           intSum = 0.0;
273
274// Increment
275
276           rowStart = iRow;              // First row for next accumulation
277           tableStart = iTab;            // First table for next accumulation
278           sourceNameStart = sourceName; // First source name for next accumulation
279           freqIDStart = freqID;         // First FreqID for next accumulation
280//
281           oldScanID = scanID;
282           outScanID += 1;               // Scan ID for next accumulation period
283        }
284
285// Accumulate
286
287        accumulate (timeSum, intSum, nAccum, sum, sumSq, nPts, tSysSum,
288                    tSys, nInc, mask, time, interval, in, iTab, iRow, axis,
289                    nAxesSub, useMask, wtType);
290//
291       oldSourceName = sourceName;
292       oldFreqID = freqID;
293    }
294  }
295
296// OK at this point we have accumulation data which is either
297//   - accumulated from all tables into one row
298// or
299//   - accumulated from the last scan average
300//
301// Normalize data in 'sum' accumulation array according to weighting scheme
302
303  normalize (sum, sumSq, nPts, wtType, axis, nAxesSub);
304
305// Create and fill container.  The container we clone will be from
306// the last Table and the first row that went into the current
307// accumulation.  It probably doesn't matter that much really...
308
309  Float nR(nAccum);
310  SDContainer sc = in[tableStart]->getSDContainer(rowStart);
311  fillSDC (sc, sum.getMask(), sum.getArray(), tSysSum/nR, outScanID,
312           timeSum/nR, intSum, sourceNameStart, freqIDStart);
313//
314  pTabOut->putSDContainer(sc);
315/*
316   cout << endl;
317   cout << "Last accumulation for output scan ID " << outScanID << endl;
318   cout << "   The first row in this accumulation is " << rowStart << endl;
319   cout << "   The number of rows accumulated is " << nAccum << endl;
320   cout << "   The first table in this accumulation is " << tableStart << endl;
321   cout << "   The first source in this accumulation is " << sourceNameStart << endl;
322   cout << "   The first freqID in this accumulation is " << freqIDStart << endl;
323   cout  << "   Average time stamp = " << timeSum/nR << endl;
324   cout << "   Integrated time = " << intSum << endl;
325*/
326  return CountedPtr<SDMemTable>(pTabOut);
327}
328
329
330
331CountedPtr<SDMemTable>
332SDMath::quotient(const CountedPtr<SDMemTable>& on,
333                 const CountedPtr<SDMemTable>& off)
334//
335// Compute quotient spectrum
336//
337{
338  const uInt nRows = on->nRow();
339  if (off->nRow() != nRows) {
340     throw (AipsError("Input Scan Tables must have the same number of rows"));
341  }
342
343// Input Tables and columns
344
345  Table ton = on->table();
346  Table toff = off->table();
347  ROArrayColumn<Float> tsys(toff, "TSYS");
348  ROScalarColumn<Double> mjd(ton, "TIME");
349  ROScalarColumn<Double> integr(ton, "INTERVAL");
350  ROScalarColumn<String> srcn(ton, "SRCNAME");
351  ROArrayColumn<uInt> freqidc(ton, "FREQID");
352
353// Output Table cloned from input
354
355  SDMemTable* pTabOut = new SDMemTable(*on, True);
356
357// Loop over rows
358
359  for (uInt i=0; i<nRows; i++) {
360     MaskedArray<Float> mon(on->rowAsMaskedArray(i));
361     MaskedArray<Float> moff(off->rowAsMaskedArray(i));
362     IPosition ipon = mon.shape();
363     IPosition ipoff = moff.shape();
364//
365     Array<Float> tsarr; 
366     tsys.get(i, tsarr);
367     if (ipon != ipoff && ipon != tsarr.shape()) {
368       throw(AipsError("on/off not conformant"));
369     }
370
371// Compute quotient
372
373     MaskedArray<Float> tmp = (mon-moff);
374     Array<Float> out(tmp.getArray());
375     out /= moff;
376     out *= tsarr;
377     Array<Bool> outflagsb = mon.getMask() && moff.getMask();
378
379// Fill container for this row
380
381     SDContainer sc = on->getSDContainer();
382//
383     putDataInSDC (sc, out, outflagsb);
384     sc.putTsys(tsarr);
385     sc.scanid = 0;
386
387// Put new row in output Table
388
389     pTabOut->putSDContainer(sc);
390  }
391//
392  return CountedPtr<SDMemTable>(pTabOut);
393}
394
395
396
397std::vector<float> SDMath::statistic (const CountedPtr<SDMemTable>& in,
398                                      const std::vector<bool>& mask,
399                                      const String& which)
400//
401// Perhaps iteration over pol/beam/if should be in here
402// and inside the nrow iteration ?
403//
404{
405  const uInt nRow = in->nRow();
406  std::vector<float> result(nRow);
407  Vector<Bool> msk(mask);
408
409// Specify cursor location
410
411  IPosition start, end;
412  getCursorLocation (start, end, *in);
413
414// Loop over rows
415
416  const uInt nEl = msk.nelements();
417  for (uInt ii=0; ii < in->nRow(); ++ii) {
418
419// Get row and deconstruct
420
421     MaskedArray<Float> marr(in->rowAsMaskedArray(ii));
422     Array<Float> arr = marr.getArray();
423     Array<Bool> barr = marr.getMask();
424
425// Access desired piece of data
426
427     Array<Float> v((arr(start,end)).nonDegenerate());
428     Array<Bool> m((barr(start,end)).nonDegenerate());
429
430// Apply OTF mask
431
432     MaskedArray<Float> tmp;
433     if (m.nelements()==nEl) {
434       tmp.setData(v,m&&msk);
435     } else {
436       tmp.setData(v,m);
437     }
438
439// Get statistic
440
441     result[ii] = mathutil::statistics(which, tmp);
442  }
443//
444  return result;
445}
446
447
448SDMemTable* SDMath::bin (const SDMemTable& in, Int width)
449{
450  SDHeader sh = in.getSDHeader();
451  SDMemTable* pTabOut = new SDMemTable(in, True);
452
453// Bin up SpectralCoordinates
454
455  IPosition factors(1);
456  factors(0) = width;
457  for (uInt j=0; j<in.nCoordinates(); ++j) {
458    CoordinateSystem cSys;
459    cSys.addCoordinate(in.getCoordinate(j));
460    CoordinateSystem cSysBin =
461      CoordinateUtil::makeBinnedCoordinateSystem (factors, cSys, False);
462//
463    SpectralCoordinate sCBin = cSysBin.spectralCoordinate(0);
464    pTabOut->setCoordinate(sCBin, j);
465  }
466
467// Use RebinLattice to find shape
468
469  IPosition shapeIn(1,sh.nchan);
470  IPosition shapeOut = RebinLattice<Float>::rebinShape (shapeIn, factors);
471  sh.nchan = shapeOut(0);
472  pTabOut->putSDHeader(sh);
473
474
475// Loop over rows and bin along channel axis
476 
477  const uInt axis = 3;
478  for (uInt i=0; i < in.nRow(); ++i) {
479    SDContainer sc = in.getSDContainer(i);
480//
481    Array<Float> tSys(sc.getTsys());                           // Get it out before sc changes shape
482
483// Bin up spectrum
484
485    MaskedArray<Float> marr(in.rowAsMaskedArray(i));
486    MaskedArray<Float> marrout;
487    LatticeUtilities::bin(marrout, marr, axis, width);
488
489// Put back the binned data and flags
490
491    IPosition ip2 = marrout.shape();
492    sc.resize(ip2);
493//
494    putDataInSDC (sc, marrout.getArray(), marrout.getMask());
495
496// Bin up Tsys. 
497
498    Array<Bool> allGood(tSys.shape(),True);
499    MaskedArray<Float> tSysIn(tSys, allGood, True);
500//
501    MaskedArray<Float> tSysOut;   
502    LatticeUtilities::bin(tSysOut, tSysIn, axis, width);
503    sc.putTsys(tSysOut.getArray());
504//
505    pTabOut->putSDContainer(sc);
506  }
507  return pTabOut;
508}
509
510SDMemTable* SDMath::simpleOperate (const SDMemTable& in, Float val, Bool doAll,
511                                   uInt what)
512//
513// what = 0   Multiply
514//        1   Add
515{
516   SDMemTable* pOut = new SDMemTable(in,False);
517   const Table& tOut = pOut->table();
518   ArrayColumn<Float> spec(tOut,"SPECTRA"); 
519//
520   if (doAll) {
521      for (uInt i=0; i < tOut.nrow(); i++) {
522
523// Get
524
525         MaskedArray<Float> marr(pOut->rowAsMaskedArray(i));
526
527// Operate
528
529         if (what==0) {
530            marr *= val;
531         } else if (what==1) {
532            marr += val;
533         }
534
535// Put
536
537         spec.put(i, marr.getArray());
538      }
539   } else {
540
541// Get cursor location
542
543      IPosition start, end;
544      getCursorLocation (start, end, in);
545//
546      for (uInt i=0; i < tOut.nrow(); i++) {
547
548// Get
549
550         MaskedArray<Float> dataIn(pOut->rowAsMaskedArray(i));
551
552// Modify. More work than we would like to deal with the mask
553
554         Array<Float>& values = dataIn.getRWArray();
555         Array<Bool> mask(dataIn.getMask());
556//
557         Array<Float> values2 = values(start,end);
558         Array<Bool> mask2 = mask(start,end);
559         MaskedArray<Float> t(values2,mask2);
560         if (what==0) {
561            t *= val;
562         } else if (what==1) {
563            t += val;
564         }
565         values(start, end) = t.getArray();     // Write back into 'dataIn'
566
567// Put
568         spec.put(i, dataIn.getArray());
569      }
570   }
571//
572   return pOut;
573}
574
575
576
577SDMemTable* SDMath::averagePol (const SDMemTable& in, const Vector<Bool>& mask)
578//
579// Average all polarizations together, weighted by variance
580//
581{
582//   WeightType wtType = NONE;
583//   convertWeightString (wtType, weight);
584
585   const uInt nRows = in.nRow();
586   const uInt polAxis = 2;                     // Polarization axis
587   const uInt chanAxis = 3;                    // Spectrum axis
588
589// Create output Table and reshape number of polarizations
590
591  Bool clear=True;
592  SDMemTable* pTabOut = new SDMemTable(in, clear);
593  SDHeader header = pTabOut->getSDHeader();
594  header.npol = 1;
595  pTabOut->putSDHeader(header);
596
597// Shape of input and output data
598
599  const IPosition& shapeIn = in.rowAsMaskedArray(0u, False).shape();
600  IPosition shapeOut(shapeIn);
601  shapeOut(polAxis) = 1;                          // Average all polarizations
602//
603  const uInt nChan = shapeIn(chanAxis);
604  const IPosition vecShapeOut(4,1,1,1,nChan);     // A multi-dim form of a Vector shape
605  IPosition start(4), end(4);
606
607// Output arrays
608
609  Array<Float> outData(shapeOut, 0.0);
610  Array<Bool> outMask(shapeOut, True);
611  const IPosition axes(2, 2, 3);              // pol-channel plane
612//
613  const Bool useMask = (mask.nelements() == shapeIn(chanAxis));
614
615// Loop over rows
616
617   for (uInt iRow=0; iRow<nRows; iRow++) {
618
619// Get data for this row
620
621      MaskedArray<Float> marr(in.rowAsMaskedArray(iRow));
622      Array<Float>& arr = marr.getRWArray();
623      const Array<Bool>& barr = marr.getMask();
624
625// Make iterators to iterate by pol-channel planes
626
627      ReadOnlyArrayIterator<Float> itDataPlane(arr, axes);
628      ReadOnlyArrayIterator<Bool> itMaskPlane(barr, axes);
629
630// Accumulations
631
632      Float fac = 1.0;
633      Vector<Float> vecSum(nChan,0.0);
634
635// Iterate through data by pol-channel planes
636
637      while (!itDataPlane.pastEnd()) {
638
639// Iterate through plane by polarization  and accumulate Vectors
640
641        Vector<Float> t1(nChan); t1 = 0.0;
642        Vector<Bool> t2(nChan); t2 = True;
643        MaskedArray<Float> vecSum(t1,t2);
644        Float varSum = 0.0;
645        {
646           ReadOnlyVectorIterator<Float> itDataVec(itDataPlane.array(), 1);
647           ReadOnlyVectorIterator<Bool> itMaskVec(itMaskPlane.array(), 1);
648           while (!itDataVec.pastEnd()) {     
649
650// Create MA of data & mask (optionally including OTF mask) and  get variance
651
652              if (useMask) {
653                 const MaskedArray<Float> spec(itDataVec.vector(),mask&&itMaskVec.vector());
654                 fac = 1.0 / variance(spec);
655              } else {
656                 const MaskedArray<Float> spec(itDataVec.vector(),itMaskVec.vector());
657                 fac = 1.0 / variance(spec);
658              }
659
660// Normalize spectrum (without OTF mask) and accumulate
661
662              const MaskedArray<Float> spec(fac*itDataVec.vector(), itMaskVec.vector());
663              vecSum += spec;
664              varSum += fac;
665
666// Next
667
668              itDataVec.next();
669              itMaskVec.next();
670           }
671        }
672
673// Normalize summed spectrum
674
675        vecSum /= varSum;
676
677// FInd position in input data array.  We are iterating by pol-channel
678// plane so all that will change is beam and IF and that's what we want.
679
680        IPosition pos = itDataPlane.pos();
681
682// Write out data. This is a bit messy. We have to reform the Vector
683// accumulator into an Array of shape (1,1,1,nChan)
684
685        start = pos;
686        end = pos;
687        end(chanAxis) = nChan-1;
688        outData(start,end) = vecSum.getArray().reform(vecShapeOut);
689        outMask(start,end) = vecSum.getMask().reform(vecShapeOut);
690
691// Step to next beam/IF combination
692
693        itDataPlane.next();
694        itMaskPlane.next();
695      }
696
697// Generate output container and write it to output table
698
699      SDContainer sc = in.getSDContainer();
700      sc.resize(shapeOut);
701//
702      putDataInSDC (sc, outData, outMask);
703      pTabOut->putSDContainer(sc);
704   }
705//
706  return pTabOut;
707}
708
709
710SDMemTable* SDMath::smooth (const SDMemTable& in, const casa::String& kernelType,
711                            casa::Float width, Bool doAll)
712{
713
714// Number of channels
715
716   const uInt chanAxis = 3;                                     // Spectral axis
717   SDHeader sh = in.getSDHeader();
718   const uInt nChan = sh.nchan;
719
720// Generate Kernel
721
722   VectorKernel::KernelTypes type = VectorKernel::toKernelType (kernelType);
723   Vector<Float> kernel = VectorKernel::make(type, width, nChan, True, False);
724
725// Generate Convolver
726
727   IPosition shape(1,nChan);
728   Convolver<Float> conv(kernel, shape);
729
730// New Table
731
732   SDMemTable* pTabOut = new SDMemTable(in,True);
733
734// Get cursor location
735         
736  IPosition start, end;
737  getCursorLocation (start, end, in);
738//
739  IPosition shapeOut(4,1);
740
741// Output Vectors
742
743  Vector<Float> valuesOut(nChan);
744  Vector<Bool> maskOut(nChan);
745
746// Loop over rows in Table
747
748  for (uInt ri=0; ri < in.nRow(); ++ri) {
749
750// Get copy of data
751   
752    const MaskedArray<Float>& dataIn(in.rowAsMaskedArray(ri));
753    AlwaysAssert(dataIn.shape()(chanAxis)==nChan, AipsError);
754//
755    Array<Float> valuesIn = dataIn.getArray();
756    Array<Bool> maskIn = dataIn.getMask();
757
758// Branch depending on whether we smooth all locations or just
759// those pointed at by the current selection cursor
760
761    if (doAll) {
762       uInt axis = 3;
763       VectorIterator<Float> itValues(valuesIn, axis);
764       VectorIterator<Bool> itMask(maskIn, axis);
765       while (!itValues.pastEnd()) {
766
767// Smooth
768          if (kernelType==VectorKernel::HANNING) {
769             mathutil::hanning(valuesOut, maskOut, itValues.vector(), itMask.vector());
770             itMask.vector() = maskOut;
771          } else {
772             mathutil::replaceMaskByZero(itValues.vector(), itMask.vector());
773             conv.linearConv(valuesOut, itValues.vector());
774          }
775//
776          itValues.vector() = valuesOut;
777//
778          itValues.next();
779          itMask.next();
780       }
781    } else {
782
783// Set multi-dim Vector shape
784
785       shapeOut(chanAxis) = valuesIn.shape()(chanAxis);
786
787// Stuff about with shapes so that we don't have conformance run-time errors
788
789       Vector<Float> valuesIn2 = valuesIn(start,end).nonDegenerate();
790       Vector<Bool> maskIn2 = maskIn(start,end).nonDegenerate();
791
792// Smooth
793
794       if (kernelType==VectorKernel::HANNING) {
795          mathutil::hanning(valuesOut, maskOut, valuesIn2, maskIn2);
796          maskIn(start,end) = maskOut.reform(shapeOut);
797       } else {
798          mathutil::replaceMaskByZero(valuesIn2, maskIn2);
799          conv.linearConv(valuesOut, valuesIn2);
800       }
801//
802       valuesIn(start,end) = valuesOut.reform(shapeOut);
803    }
804
805// Create and put back
806
807    SDContainer sc = in.getSDContainer(ri);
808    putDataInSDC (sc, valuesIn, maskIn);
809//
810    pTabOut->putSDContainer(sc);
811  }
812//
813  return pTabOut;
814}
815
816
817
818
819
820// 'private' functions
821
822void SDMath::fillSDC (SDContainer& sc,
823                      const Array<Bool>& mask,
824                      const Array<Float>& data,
825                      const Array<Float>& tSys,
826                      Int scanID, Double timeStamp,
827                      Double interval, const String& sourceName,
828                      const Vector<uInt>& freqID)
829{
830// Data and mask
831
832  putDataInSDC (sc, data, mask);
833
834// TSys
835
836  sc.putTsys(tSys);
837
838// Time things
839
840  sc.timestamp = timeStamp;
841  sc.interval = interval;
842  sc.scanid = scanID;
843//
844  sc.sourcename = sourceName;
845  sc.putFreqMap(freqID);
846}
847
848void SDMath::normalize (MaskedArray<Float>& sum,
849                        const Array<Float>& sumSq,
850                        const Array<Float>& nPts,
851                        WeightType wtType, Int axis,
852                        Int nAxesSub)
853{
854   IPosition pos2(nAxesSub,0);
855//
856   if (wtType==NONE) {
857
858// We just average by the number of points accumulated.
859// We need to make a MA out of nPts so that no divide by
860// zeros occur
861
862      MaskedArray<Float> t(nPts, (nPts>Float(0.0)));
863      sum /= t;
864   } else if (wtType==VAR) {
865
866// Normalize each spectrum by sum(1/var) where the variance
867// is worked out for each spectrum
868
869      Array<Float>& data = sum.getRWArray();
870      VectorIterator<Float> itData(data, axis);
871      while (!itData.pastEnd()) {
872         pos2 = itData.pos().getFirst(nAxesSub);
873         itData.vector() /= sumSq(pos2);
874         itData.next();
875      }
876   } else if (wtType==TSYS) {
877   }
878}
879
880
881void SDMath::accumulate (Double& timeSum, Double& intSum, Int& nAccum,
882                         MaskedArray<Float>& sum, Array<Float>& sumSq,
883                         Array<Float>& nPts, Array<Float>& tSysSum,
884                         const Array<Float>& tSys, const Array<Float>& nInc,
885                         const Vector<Bool>& mask, Double time, Double interval,
886                         const Block<CountedPtr<SDMemTable> >& in,
887                         uInt iTab, uInt iRow, uInt axis,
888                         uInt nAxesSub, Bool useMask,
889                         WeightType wtType)
890{
891
892// Get data
893
894   MaskedArray<Float> dataIn(in[iTab]->rowAsMaskedArray(iRow));
895   Array<Float>& valuesIn = dataIn.getRWArray();           // writable reference
896   const Array<Bool>& maskIn = dataIn.getMask();          // RO reference
897//
898   if (wtType==NONE) {
899      const MaskedArray<Float> n(nInc,dataIn.getMask());
900      nPts += n;                               // Only accumulates where mask==T
901   } else if (wtType==VAR) {
902
903// We are going to average the data, weighted by the noise for each pol, beam and IF.
904// So therefore we need to iterate through by spectrum (axis 3)
905
906      VectorIterator<Float> itData(valuesIn, axis);
907      ReadOnlyVectorIterator<Bool> itMask(maskIn, axis);
908      Float fac = 1.0;
909      IPosition pos(nAxesSub,0); 
910//
911      while (!itData.pastEnd()) {
912
913// Make MaskedArray of Vector, optionally apply OTF mask, and find scaling factor
914
915        if (useMask) {
916           MaskedArray<Float> tmp(itData.vector(),mask&&itMask.vector());
917           fac = 1.0/variance(tmp);
918        } else {
919           MaskedArray<Float> tmp(itData.vector(),itMask.vector());
920           fac = 1.0/variance(tmp);
921        }
922
923// Scale data
924
925        itData.vector() *= fac;     // Writes back into 'dataIn'
926//
927// Accumulate variance per if/pol/beam averaged over spectrum
928// This method to get pos2 from itData.pos() is only valid
929// because the spectral axis is the last one (so we can just
930// copy the first nAXesSub positions out)
931
932        pos = itData.pos().getFirst(nAxesSub);
933        sumSq(pos) += fac;
934//
935        itData.next();
936        itMask.next();
937      }
938   } else if (wtType==TSYS) {
939   }
940
941// Accumulate sum of (possibly scaled) data
942
943   sum += dataIn;
944
945// Accumulate Tsys, time, and interval
946
947   tSysSum += tSys;
948   timeSum += time;
949   intSum += interval;
950   nAccum += 1;
951}
952
953
954
955
956void SDMath::getCursorLocation (IPosition& start, IPosition& end,
957                                const SDMemTable& in)
958{
959  const uInt nDim = 4;
960  const uInt i = in.getBeam();
961  const uInt j = in.getIF();
962  const uInt k = in.getPol();
963  const uInt n = in.nChan();
964//
965  start.resize(nDim);
966  start(0) = i;
967  start(1) = j;
968  start(2) = k;
969  start(3) = 0;
970//
971  end.resize(nDim);
972  end(0) = i;
973  end(1) = j;
974  end(2) = k;
975  end(3) = n-1;
976}
977
978
979void SDMath::convertWeightString (WeightType& wtType, const std::string& weightStr)
980{
981  String tStr(weightStr);
982  tStr.upcase();
983  if (tStr.contains(String("NONE"))) {
984     wtType = NONE;
985  } else if (tStr.contains(String("VAR"))) {
986     wtType = VAR;
987  } else if (tStr.contains(String("TSYS"))) {
988     wtType = TSYS;
989     throw (AipsError("T_sys weighting not yet implemented"));
990  } else {
991    throw (AipsError("Unrecognized weighting type"));
992  }
993}
994
995void SDMath::putDataInSDC (SDContainer& sc, const Array<Float>& data,
996                           const Array<Bool>& mask)
997{
998    sc.putSpectrum(data);
999//
1000    Array<uChar> outflags(data.shape());
1001    convertArray(outflags,!mask);
1002    sc.putFlags(outflags);
1003}
Note: See TracBrowser for help on using the repository browser.