source: trunk/src/SDMath.cc@ 169

Last change on this file since 169 was 169, checked in by kil064, 20 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
RevLine 
[2]1//#---------------------------------------------------------------------------
2//# SDMath.cc: A collection of single dish mathematical operations
3//#---------------------------------------------------------------------------
4//# Copyright (C) 2004
[125]5//# ATNF
[2]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//#---------------------------------------------------------------------------
[38]31#include <vector>
32
[81]33#include <casa/aips.h>
34#include <casa/BasicSL/String.h>
35#include <casa/Arrays/IPosition.h>
36#include <casa/Arrays/Array.h>
[130]37#include <casa/Arrays/ArrayIter.h>
38#include <casa/Arrays/VectorIter.h>
[81]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>
[130]44#include <casa/Exceptions.h>
[2]45
[81]46#include <tables/Tables/Table.h>
47#include <tables/Tables/ScalarColumn.h>
48#include <tables/Tables/ArrayColumn.h>
[2]49
[130]50#include <lattices/Lattices/LatticeUtilities.h>
51#include <lattices/Lattices/RebinLattice.h>
[81]52#include <coordinates/Coordinates/SpectralCoordinate.h>
[130]53#include <coordinates/Coordinates/CoordinateSystem.h>
54#include <coordinates/Coordinates/CoordinateUtil.h>
[38]55
56#include "MathUtils.h"
[2]57#include "SDContainer.h"
58#include "SDMemTable.h"
59
60#include "SDMath.h"
61
[125]62using namespace casa;
[83]63using namespace asap;
[2]64
[144]65CountedPtr<SDMemTable> SDMath::average (const Block<CountedPtr<SDMemTable> >& in,
66 const Vector<Bool>& mask, bool scanAv,
67 const std::string& weightStr)
[130]68//
[144]69// Weighted averaging of spectra from one or more Tables.
[130]70//
71{
[2]72
[163]73// Convert weight type
74
75 WeightType wtType = NONE;
76 convertWeightString (wtType, weightStr);
77
[144]78// Create output Table by cloning from the first table
[2]79
[144]80 SDMemTable* pTabOut = new SDMemTable(*in[0],True);
[130]81
[144]82// Setup
[130]83
[144]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));
[130]89
[144]90// Columns from Tables
[130]91
[144]92 ROArrayColumn<Float> tSysCol;
93 ROScalarColumn<Double> mjdCol;
94 ROScalarColumn<String> srcNameCol;
95 ROScalarColumn<Double> intCol;
96 ROArrayColumn<uInt> fqIDCol;
[130]97
[144]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 }
[2]127 }
[144]128 Array<Float> sumSq(shp2);
129 sumSq = 0.0;
130 IPosition pos2(nAxesSub,0); // For indexing
[130]131
[144]132// Time-related accumulators
[130]133
[144]134 Double time;
135 Double timeSum = 0.0;
136 Double intSum = 0.0;
137 Double interval = 0.0;
[130]138
[144]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
[130]142
[144]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
[146]261// Accumulate
[144]262
[146]263 accumulate (timeSum, intSum, nAccum, sum, sumSq, nPts, tSysSum,
264 tSys, nInc, mask, time, interval, in, iTab, iRow, axis,
265 nAxesSub, useMask, wtType);
[144]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);
[2]303}
[9]304
[144]305
306
[85]307CountedPtr<SDMemTable>
308SDMath::quotient(const CountedPtr<SDMemTable>& on,
[130]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 }
[85]318
[130]319// Input Tables and columns
320
[9]321 Table ton = on->table();
322 Table toff = off->table();
[85]323 ROArrayColumn<Float> tsys(toff, "TSYS");
[9]324 ROScalarColumn<Double> mjd(ton, "TIME");
[15]325 ROScalarColumn<Double> integr(ton, "INTERVAL");
[9]326 ROScalarColumn<String> srcn(ton, "SRCNAME");
[38]327 ROArrayColumn<uInt> freqidc(ton, "FREQID");
328
[130]329// Output Table cloned from input
[85]330
[15]331 SDMemTable* sdmt = new SDMemTable(*on, True);
[130]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;
[163]353 Array<Bool> outflagsb = mon.getMask() && moff.getMask();
[130]354
355// Fill container for this row
356
357 SDContainer sc = on->getSDContainer();
[163]358//
359 putDataInSDC (sc, out, outflagsb);
[130]360 sc.putTsys(tsarr);
361 sc.scanid = 0;
362
363// Put new row in output Table
364
365 sdmt->putSDContainer(sc);
366 }
367//
[9]368 return CountedPtr<SDMemTable>(sdmt);
369}
[48]370
[146]371
372
[85]373CountedPtr<SDMemTable>
[130]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);
[107]381
[130]382// Loop over rows in Table
[48]383
[130]384 for (uInt ri=0; ri < in->nRow(); ++ri) {
[38]385
[130]386// Get data
[125]387
[130]388 const MaskedArray<Float>& marr(in->rowAsMaskedArray(ri));
[85]389 Array<Float> arr = marr.getArray();
390 Array<Bool> barr = marr.getMask();
[130]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();
[38]406 }
[130]407
408// Create and put back
409
[85]410 SDContainer sc = in->getSDContainer(ri);
[163]411 putDataInSDC (sc, arr, barr);
412//
[85]413 sdmt->putSDContainer(sc);
[38]414 }
415 return CountedPtr<SDMemTable>(sdmt);
416}
417
[163]418
[130]419
[48]420
[130]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
[152]435 IPosition start, end;
436 getCursorLocation (start, end, *in);
[130]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
[144]465 result[ii] = mathutil::statistics(which, tmp);
[130]466 }
467//
468 return result;
469}
470
[146]471
[169]472SDMemTable* SDMath::bin (const SDMemTable& in, Int width)
[144]473{
[169]474 SDHeader sh = in.getSDHeader();
475 SDMemTable* pTabOut = new SDMemTable(in, True);
[163]476
[169]477// Bin up SpectralCoordinates
[163]478
[169]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 }
[163]490
[169]491// Use RebinLattice to find shape
[130]492
[169]493 IPosition shapeIn(1,sh.nchan);
494 IPosition shapeOut = RebinLattice<Float>::rebinShape (shapeIn, factors);
495 sh.nchan = shapeOut(0);
496 pTabOut->putSDHeader(sh);
[144]497
498
[169]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);
[144]504//
[169]505 Array<Float> tSys(sc.getTsys()); // Get it out before sc changes shape
[144]506
[169]507// Bin up spectrum
[144]508
[169]509 MaskedArray<Float> marr(in.rowAsMaskedArray(i));
510 MaskedArray<Float> marrout;
511 LatticeUtilities::bin(marrout, marr, axis, width);
[144]512
[169]513// Put back the binned data and flags
[144]514
[169]515 IPosition ip2 = marrout.shape();
516 sc.resize(ip2);
[146]517//
[169]518 putDataInSDC (sc, marrout.getArray(), marrout.getMask());
[146]519
[169]520// Bin up Tsys.
[146]521
[169]522 Array<Bool> allGood(tSys.shape(),True);
523 MaskedArray<Float> tSysIn(tSys, allGood, True);
[146]524//
[169]525 MaskedArray<Float> tSysOut;
526 LatticeUtilities::bin(tSysOut, tSysIn, axis, width);
527 sc.putTsys(tSysOut.getArray());
[146]528//
[169]529 pTabOut->putSDContainer(sc);
530 }
531 return pTabOut;
[146]532}
533
[169]534SDMemTable* SDMath::simpleOperate (const SDMemTable& in, Float val, Bool doAll,
535 uInt what)
[152]536//
537// what = 0 Multiply
538// 1 Add
[146]539{
[152]540 SDMemTable* pOut = new SDMemTable(in,False);
541 const Table& tOut = pOut->table();
542 ArrayColumn<Float> spec(tOut,"SPECTRA");
[146]543//
[152]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//
[146]596 return pOut;
597}
598
599
[152]600
[169]601SDMemTable* SDMath::averagePol (const SDMemTable& in, const Vector<Bool>& mask)
[152]602//
[165]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}
[167]732
[169]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)
[167]745{
[169]746// Data and mask
[167]747
[169]748 putDataInSDC (sc, data, mask);
[167]749
[169]750// TSys
751
752 sc.putTsys(tSys);
753
754// Time things
755
756 sc.timestamp = timeStamp;
757 sc.interval = interval;
758 sc.scanid = scanID;
[167]759//
[169]760 sc.sourcename = sourceName;
761 sc.putFreqMap(freqID);
762}
[167]763
[169]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) {
[167]773
[169]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
[167]777
[169]778 MaskedArray<Float> t(nPts, (nPts>Float(0.0)));
779 sum /= t;
780 } else if (wtType==VAR) {
[167]781
[169]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
[167]813//
[169]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) {
[167]818
[169]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)
[167]821
[169]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()) {
[167]828
[169]829// Make MaskedArray of Vector, optionally apply OTF mask, and find scaling factor
[167]830
[169]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'
[167]842//
[169]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)
[167]847
[169]848 pos = itData.pos().getFirst(nAxesSub);
849 sumSq(pos) += fac;
850//
851 itData.next();
852 itMask.next();
853 }
854 } else if (wtType==TSYS) {
855 }
[167]856
[169]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();
[167]880//
[169]881 start.resize(nDim);
882 start(0) = i;
883 start(1) = j;
884 start(2) = k;
885 start(3) = 0;
[167]886//
[169]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"));
[167]908 }
909}
910
[169]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}
[167]920
[169]921
Note: See TracBrowser for help on using the repository browser.