source: trunk/src/SDMath.cc @ 175

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

Add cursor selection to function 'hanning' (arg. 'all')

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