source: trunk/src/SDMath.cc @ 171

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

implement insitu version of Hanning smoothing

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.1 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)
394//
395// Hanning smooth each row
396// Should Tsys be smoothed ?
397//
398{
399  SDMemTable* pTabOut = new SDMemTable(in,True);
400
401// Loop over rows in Table
402
403  for (uInt ri=0; ri < in.nRow(); ++ri) {
404
405// Get data
406   
407    const MaskedArray<Float>& marr(in.rowAsMaskedArray(ri));
408    Array<Float> arr = marr.getArray();
409    Array<Bool> barr = marr.getMask();
410
411// Smooth along the channels axis
412
413    uInt axis = 3;
414    VectorIterator<Float> itData(arr, axis);
415    VectorIterator<Bool> itMask(barr, axis);
416    Vector<Float> outv;
417    Vector<Bool> outm;
418    while (!itData.pastEnd()) {
419       mathutil::hanning(outv, outm, itData.vector(), itMask.vector());
420       itData.vector() = outv;                                                 
421       itMask.vector() = outm;
422//
423       itData.next();
424       itMask.next();
425    }
426
427// Create and put back
428
429    SDContainer sc = in.getSDContainer(ri);
430    putDataInSDC (sc, arr, barr);
431//
432    pTabOut->putSDContainer(sc);
433  }
434//
435  return pTabOut;
436}
437
438
439
440
441std::vector<float> SDMath::statistic (const CountedPtr<SDMemTable>& in,
442                                       const std::vector<bool>& mask,
443                                       const std::string& which)
444//
445// Perhaps iteration over pol/beam/if should be in here
446// and inside the nrow iteration ?
447//
448{
449  const uInt nRow = in->nRow();
450  std::vector<float> result(nRow);
451  Vector<Bool> msk(mask);
452
453// Specify cursor location
454
455  IPosition start, end;
456  getCursorLocation (start, end, *in);
457
458// Loop over rows
459
460  const uInt nEl = msk.nelements();
461  for (uInt ii=0; ii < in->nRow(); ++ii) {
462
463// Get row and deconstruct
464
465     MaskedArray<Float> marr(in->rowAsMaskedArray(ii));
466     Array<Float> arr = marr.getArray();
467     Array<Bool> barr = marr.getMask();
468
469// Access desired piece of data
470
471     Array<Float> v((arr(start,end)).nonDegenerate());
472     Array<Bool> m((barr(start,end)).nonDegenerate());
473
474// Apply OTF mask
475
476     MaskedArray<Float> tmp;
477     if (m.nelements()==nEl) {
478       tmp.setData(v,m&&msk);
479     } else {
480       tmp.setData(v,m);
481     }
482
483// Get statistic
484
485     result[ii] = mathutil::statistics(which, tmp);
486  }
487//
488  return result;
489}
490
491
492SDMemTable* SDMath::bin (const SDMemTable& in, Int width)
493{
494  SDHeader sh = in.getSDHeader();
495  SDMemTable* pTabOut = new SDMemTable(in, True);
496
497// Bin up SpectralCoordinates
498
499  IPosition factors(1);
500  factors(0) = width;
501  for (uInt j=0; j<in.nCoordinates(); ++j) {
502    CoordinateSystem cSys;
503    cSys.addCoordinate(in.getCoordinate(j));
504    CoordinateSystem cSysBin =
505      CoordinateUtil::makeBinnedCoordinateSystem (factors, cSys, False);
506//
507    SpectralCoordinate sCBin = cSysBin.spectralCoordinate(0);
508    pTabOut->setCoordinate(sCBin, j);
509  }
510
511// Use RebinLattice to find shape
512
513  IPosition shapeIn(1,sh.nchan);
514  IPosition shapeOut = RebinLattice<Float>::rebinShape (shapeIn, factors);
515  sh.nchan = shapeOut(0);
516  pTabOut->putSDHeader(sh);
517
518
519// Loop over rows and bin along channel axis
520 
521  const uInt axis = 3;
522  for (uInt i=0; i < in.nRow(); ++i) {
523    SDContainer sc = in.getSDContainer(i);
524//
525    Array<Float> tSys(sc.getTsys());                           // Get it out before sc changes shape
526
527// Bin up spectrum
528
529    MaskedArray<Float> marr(in.rowAsMaskedArray(i));
530    MaskedArray<Float> marrout;
531    LatticeUtilities::bin(marrout, marr, axis, width);
532
533// Put back the binned data and flags
534
535    IPosition ip2 = marrout.shape();
536    sc.resize(ip2);
537//
538    putDataInSDC (sc, marrout.getArray(), marrout.getMask());
539
540// Bin up Tsys. 
541
542    Array<Bool> allGood(tSys.shape(),True);
543    MaskedArray<Float> tSysIn(tSys, allGood, True);
544//
545    MaskedArray<Float> tSysOut;   
546    LatticeUtilities::bin(tSysOut, tSysIn, axis, width);
547    sc.putTsys(tSysOut.getArray());
548//
549    pTabOut->putSDContainer(sc);
550  }
551  return pTabOut;
552}
553
554SDMemTable* SDMath::simpleOperate (const SDMemTable& in, Float val, Bool doAll,
555                                   uInt what)
556//
557// what = 0   Multiply
558//        1   Add
559{
560   SDMemTable* pOut = new SDMemTable(in,False);
561   const Table& tOut = pOut->table();
562   ArrayColumn<Float> spec(tOut,"SPECTRA"); 
563//
564   if (doAll) {
565      for (uInt i=0; i < tOut.nrow(); i++) {
566
567// Get
568
569         MaskedArray<Float> marr(pOut->rowAsMaskedArray(i));
570
571// Operate
572
573         if (what==0) {
574            marr *= val;
575         } else if (what==1) {
576            marr += val;
577         }
578
579// Put
580
581         spec.put(i, marr.getArray());
582      }
583   } else {
584
585// Get cursor location
586
587      IPosition start, end;
588      getCursorLocation (start, end, in);
589//
590      for (uInt i=0; i < tOut.nrow(); i++) {
591
592// Get
593
594         MaskedArray<Float> dataIn(pOut->rowAsMaskedArray(i));
595
596// Modify. More work than we would like to deal with the mask
597
598         Array<Float>& values = dataIn.getRWArray();
599         Array<Bool> mask(dataIn.getMask());
600//
601         Array<Float> values2 = values(start,end);
602         Array<Bool> mask2 = mask(start,end);
603         MaskedArray<Float> t(values2,mask2);
604         if (what==0) {
605            t *= val;
606         } else if (what==1) {
607            t += val;
608         }
609         values(start, end) = t.getArray();     // Write back into 'dataIn'
610
611// Put
612         spec.put(i, dataIn.getArray());
613      }
614   }
615//
616   return pOut;
617}
618
619
620
621SDMemTable* SDMath::averagePol (const SDMemTable& in, const Vector<Bool>& mask)
622//
623// Average all polarizations together, weighted by variance
624//
625{
626//   WeightType wtType = NONE;
627//   convertWeightString (wtType, weight);
628
629   const uInt nRows = in.nRow();
630   const uInt polAxis = 2;                     // Polarization axis
631   const uInt chanAxis = 3;                    // Spectrum axis
632
633// Create output Table and reshape number of polarizations
634
635  Bool clear=True;
636  SDMemTable* pTabOut = new SDMemTable(in, clear);
637  SDHeader header = pTabOut->getSDHeader();
638  header.npol = 1;
639  pTabOut->putSDHeader(header);
640
641// Shape of input and output data
642
643  const IPosition& shapeIn = in.rowAsMaskedArray(0u, False).shape();
644  IPosition shapeOut(shapeIn);
645  shapeOut(polAxis) = 1;                          // Average all polarizations
646//
647  const uInt nChan = shapeIn(chanAxis);
648  const IPosition vecShapeOut(4,1,1,1,nChan);     // A multi-dim form of a Vector shape
649  IPosition start(4), end(4);
650
651// Output arrays
652
653  Array<Float> outData(shapeOut, 0.0);
654  Array<Bool> outMask(shapeOut, True);
655  const IPosition axes(2, 2, 3);              // pol-channel plane
656//
657  const Bool useMask = (mask.nelements() == shapeIn(chanAxis));
658
659// Loop over rows
660
661   for (uInt iRow=0; iRow<nRows; iRow++) {
662
663// Get data for this row
664
665      MaskedArray<Float> marr(in.rowAsMaskedArray(iRow));
666      Array<Float>& arr = marr.getRWArray();
667      const Array<Bool>& barr = marr.getMask();
668
669// Make iterators to iterate by pol-channel planes
670
671      ReadOnlyArrayIterator<Float> itDataPlane(arr, axes);
672      ReadOnlyArrayIterator<Bool> itMaskPlane(barr, axes);
673
674// Accumulations
675
676      Float fac = 1.0;
677      Vector<Float> vecSum(nChan,0.0);
678
679// Iterate through data by pol-channel planes
680
681      while (!itDataPlane.pastEnd()) {
682
683// Iterate through plane by polarization  and accumulate Vectors
684
685        Vector<Float> t1(nChan); t1 = 0.0;
686        Vector<Bool> t2(nChan); t2 = True;
687        MaskedArray<Float> vecSum(t1,t2);
688        Float varSum = 0.0;
689        {
690           ReadOnlyVectorIterator<Float> itDataVec(itDataPlane.array(), 1);
691           ReadOnlyVectorIterator<Bool> itMaskVec(itMaskPlane.array(), 1);
692           while (!itDataVec.pastEnd()) {     
693
694// Create MA of data & mask (optionally including OTF mask) and  get variance
695
696              if (useMask) {
697                 const MaskedArray<Float> spec(itDataVec.vector(),mask&&itMaskVec.vector());
698                 fac = 1.0 / variance(spec);
699              } else {
700                 const MaskedArray<Float> spec(itDataVec.vector(),itMaskVec.vector());
701                 fac = 1.0 / variance(spec);
702              }
703
704// Normalize spectrum (without OTF mask) and accumulate
705
706              const MaskedArray<Float> spec(fac*itDataVec.vector(), itMaskVec.vector());
707              vecSum += spec;
708              varSum += fac;
709
710// Next
711
712              itDataVec.next();
713              itMaskVec.next();
714           }
715        }
716
717// Normalize summed spectrum
718
719        vecSum /= varSum;
720
721// FInd position in input data array.  We are iterating by pol-channel
722// plane so all that will change is beam and IF and that's what we want.
723
724        IPosition pos = itDataPlane.pos();
725
726// Write out data. This is a bit messy. We have to reform the Vector
727// accumulator into an Array of shape (1,1,1,nChan)
728
729        start = pos;
730        end = pos;
731        end(chanAxis) = nChan-1;
732        outData(start,end) = vecSum.getArray().reform(vecShapeOut);
733        outMask(start,end) = vecSum.getMask().reform(vecShapeOut);
734
735// Step to next beam/IF combination
736
737        itDataPlane.next();
738        itMaskPlane.next();
739      }
740
741// Generate output container and write it to output table
742
743      SDContainer sc = in.getSDContainer();
744      sc.resize(shapeOut);
745//
746      putDataInSDC (sc, outData, outMask);
747      pTabOut->putSDContainer(sc);
748   }
749//
750  return pTabOut;
751}
752
753
754
755
756// 'private' functions
757
758void SDMath::fillSDC (SDContainer& sc,
759                      const Array<Bool>& mask,
760                      const Array<Float>& data,
761                      const Array<Float>& tSys,
762                      Int scanID, Double timeStamp,
763                      Double interval, const String& sourceName,
764                      const Vector<uInt>& freqID)
765{
766// Data and mask
767
768  putDataInSDC (sc, data, mask);
769
770// TSys
771
772  sc.putTsys(tSys);
773
774// Time things
775
776  sc.timestamp = timeStamp;
777  sc.interval = interval;
778  sc.scanid = scanID;
779//
780  sc.sourcename = sourceName;
781  sc.putFreqMap(freqID);
782}
783
784void SDMath::normalize (MaskedArray<Float>& sum,
785                        const Array<Float>& sumSq,
786                        const Array<Float>& nPts,
787                        WeightType wtType, Int axis,
788                        Int nAxesSub)
789{
790   IPosition pos2(nAxesSub,0);
791//
792   if (wtType==NONE) {
793
794// We just average by the number of points accumulated.
795// We need to make a MA out of nPts so that no divide by
796// zeros occur
797
798      MaskedArray<Float> t(nPts, (nPts>Float(0.0)));
799      sum /= t;
800   } else if (wtType==VAR) {
801
802// Normalize each spectrum by sum(1/var) where the variance
803// is worked out for each spectrum
804
805      Array<Float>& data = sum.getRWArray();
806      VectorIterator<Float> itData(data, axis);
807      while (!itData.pastEnd()) {
808         pos2 = itData.pos().getFirst(nAxesSub);
809         itData.vector() /= sumSq(pos2);
810         itData.next();
811      }
812   } else if (wtType==TSYS) {
813   }
814}
815
816
817void SDMath::accumulate (Double& timeSum, Double& intSum, Int& nAccum,
818                         MaskedArray<Float>& sum, Array<Float>& sumSq,
819                         Array<Float>& nPts, Array<Float>& tSysSum,
820                         const Array<Float>& tSys, const Array<Float>& nInc,
821                         const Vector<Bool>& mask, Double time, Double interval,
822                         const Block<CountedPtr<SDMemTable> >& in,
823                         uInt iTab, uInt iRow, uInt axis,
824                         uInt nAxesSub, Bool useMask,
825                         WeightType wtType)
826{
827
828// Get data
829
830   MaskedArray<Float> dataIn(in[iTab]->rowAsMaskedArray(iRow));
831   Array<Float>& valuesIn = dataIn.getRWArray();           // writable reference
832   const Array<Bool>& maskIn = dataIn.getMask();          // RO reference
833//
834   if (wtType==NONE) {
835      const MaskedArray<Float> n(nInc,dataIn.getMask());
836      nPts += n;                               // Only accumulates where mask==T
837   } else if (wtType==VAR) {
838
839// We are going to average the data, weighted by the noise for each pol, beam and IF.
840// So therefore we need to iterate through by spectrum (axis 3)
841
842      VectorIterator<Float> itData(valuesIn, axis);
843      ReadOnlyVectorIterator<Bool> itMask(maskIn, axis);
844      Float fac = 1.0;
845      IPosition pos(nAxesSub,0); 
846//
847      while (!itData.pastEnd()) {
848
849// Make MaskedArray of Vector, optionally apply OTF mask, and find scaling factor
850
851        if (useMask) {
852           MaskedArray<Float> tmp(itData.vector(),mask&&itMask.vector());
853           fac = 1.0/variance(tmp);
854        } else {
855           MaskedArray<Float> tmp(itData.vector(),itMask.vector());
856           fac = 1.0/variance(tmp);
857        }
858
859// Scale data
860
861        itData.vector() *= fac;     // Writes back into 'dataIn'
862//
863// Accumulate variance per if/pol/beam averaged over spectrum
864// This method to get pos2 from itData.pos() is only valid
865// because the spectral axis is the last one (so we can just
866// copy the first nAXesSub positions out)
867
868        pos = itData.pos().getFirst(nAxesSub);
869        sumSq(pos) += fac;
870//
871        itData.next();
872        itMask.next();
873      }
874   } else if (wtType==TSYS) {
875   }
876
877// Accumulate sum of (possibly scaled) data
878
879   sum += dataIn;
880
881// Accumulate Tsys, time, and interval
882
883   tSysSum += tSys;
884   timeSum += time;
885   intSum += interval;
886   nAccum += 1;
887}
888
889
890
891
892void SDMath::getCursorLocation (IPosition& start, IPosition& end,
893                                const SDMemTable& in)
894{
895  const uInt nDim = 4;
896  const uInt i = in.getBeam();
897  const uInt j = in.getIF();
898  const uInt k = in.getPol();
899  const uInt n = in.nChan();
900//
901  start.resize(nDim);
902  start(0) = i;
903  start(1) = j;
904  start(2) = k;
905  start(3) = 0;
906//
907  end.resize(nDim);
908  end(0) = i;
909  end(1) = j;
910  end(2) = k;
911  end(3) = n-1;
912}
913
914
915void SDMath::convertWeightString (WeightType& wtType, const std::string& weightStr)
916{
917  String tStr(weightStr);
918  tStr.upcase();
919  if (tStr.contains(String("NONE"))) {
920     wtType = NONE;
921  } else if (tStr.contains(String("VAR"))) {
922     wtType = VAR;
923  } else if (tStr.contains(String("TSYS"))) {
924     wtType = TSYS;
925     throw (AipsError("T_sys weighting not yet implemented"));
926  } else {
927    throw (AipsError("Unrecognized weighting type"));
928  }
929}
930
931void SDMath::putDataInSDC (SDContainer& sc, const Array<Float>& data,
932                           const Array<Bool>& mask)
933{
934    sc.putSpectrum(data);
935//
936    Array<uChar> outflags(data.shape());
937    convertArray(outflags,!mask);
938    sc.putFlags(outflags);
939}
940
941
Note: See TracBrowser for help on using the repository browser.