source: trunk/src/SDMath.cc@ 156

Last change on this file since 156 was 155, checked in by kil064, 20 years ago

doc cxhanges
previous entry should also have said that added 'insitu' capability
to function 'add' as well

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