source: trunk/src/SDMath.cc@ 172

Last change on this file since 172 was 171, checked in by kil064, 20 years ago

implement insitu version of Hanning smoothing

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