source: trunk/src/SDMath.cc@ 153

Last change on this file since 153 was 152, checked in by kil064, 20 years ago

function 'add' and 'multiply' now take arg. doAll to
indicate whether operation to be applied to
all spectral or cursor selection only.

Combine functions 'localMultiply' and 'localAdd' into
'localOperate'

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