source: trunk/src/SDMath.cc @ 169

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

moev functionality from SDMath to SDMathWrapper (adding SDMathWrapper.cc in
the process). This removes an unnecessary layer from SDMath

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