source: trunk/src/SDMath.cc @ 183

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

add destructor

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