source: trunk/src/SDMath.cc@ 178

Last change on this file since 178 was 177, checked in by kil064, 20 years ago

remove function 'hanning'
add function 'smooth' (includes hanning)

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