source: trunk/src/SDMath.cc@ 145

Last change on this file since 145 was 144, checked in by kil064, 20 years ago

merge functions 'average' and 'averages' into one that averages
in time, can do scan averages and apply various weighting schemes.
Break some functionality into other functrions

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.0 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//using namespace asap::SDMath;
65
66CountedPtr<SDMemTable> SDMath::average (const Block<CountedPtr<SDMemTable> >& in,
67 const Vector<Bool>& mask, bool scanAv,
68 const std::string& weightStr)
69//
70// Weighted averaging of spectra from one or more Tables.
71//
72{
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 }
86
87// Create output Table by cloning from the first table
88
89 SDMemTable* pTabOut = new SDMemTable(*in[0],True);
90
91// Setup
92
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));
98
99// Columns from Tables
100
101 ROArrayColumn<Float> tSysCol;
102 ROScalarColumn<Double> mjdCol;
103 ROScalarColumn<String> srcNameCol;
104 ROScalarColumn<Double> intCol;
105 ROArrayColumn<uInt> fqIDCol;
106
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 }
136 }
137 Array<Float> sumSq(shp2);
138 sumSq = 0.0;
139 IPosition pos2(nAxesSub,0); // For indexing
140
141// Time-related accumulators
142
143 Double time;
144 Double timeSum = 0.0;
145 Double intSum = 0.0;
146 Double interval = 0.0;
147
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
151
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
270// Accumulation step. First get data and deconstruct
271
272 MaskedArray<Float> dataIn(in[iTab]->rowAsMaskedArray(iRow));
273 Array<Float>& valuesIn = dataIn.getRWArray(); // writable reference
274 const Array<Bool>& maskIn = dataIn.getMask(); // RO reference
275//
276 if (wtType==NONE) {
277 const MaskedArray<Float> n(nInc,dataIn.getMask());
278 nPts += n; // Only accumulates where mask==T
279 } else if (wtType==VAR) {
280
281// We are going to average the data, weighted by the noise for each pol, beam and IF.
282// So therefore we need to iterate through by spectrum (axis 3)
283
284 VectorIterator<Float> itData(valuesIn, axis);
285 ReadOnlyVectorIterator<Bool> itMask(maskIn, axis);
286 while (!itData.pastEnd()) {
287
288// Make MaskedArray of Vector, optionally apply OTF mask, and find scaling factor
289
290 if (useMask) {
291 MaskedArray<Float> tmp(itData.vector(),mask&&itMask.vector());
292 fac = 1.0/variance(tmp);
293 } else {
294 MaskedArray<Float> tmp(itData.vector(),itMask.vector());
295 fac = 1.0/variance(tmp);
296 }
297
298// Scale data
299
300 itData.vector() *= fac; // Writes back into 'dataIn'
301//
302// Accumulate variance per if/pol/beam averaged over spectrum
303// This method to get pos2 from itData.pos() is only valid
304// because the spectral axis is the last one (so we can just
305// copy the first nAXesSub positions out)
306
307 pos2 = itData.pos().getFirst(nAxesSub);
308 sumSq(pos2) += fac;
309//
310 itData.next();
311 itMask.next();
312 }
313 } else if (wtType==TSYS) {
314 }
315
316// Accumulate sum of (possibly scaled) data
317
318 sum += dataIn;
319
320// Accumulate Tsys, time, and interval
321
322 tSysSum += tSys;
323 timeSum += time;
324 intSum += interval;
325
326// Number of rows in accumulation
327
328 nAccum += 1;
329 oldSourceName = sourceName;
330 oldFreqID = freqID;
331 }
332 }
333
334// OK at this point we have accumulation data which is either
335// - accumulated from all tables into one row
336// or
337// - accumulated from the last scan average
338//
339// Normalize data in 'sum' accumulation array according to weighting scheme
340
341 normalize (sum, sumSq, nPts, wtType, axis, nAxesSub);
342
343// Create and fill container. The container we clone will be from
344// the last Table and the first row that went into the current
345// accumulation. It probably doesn't matter that much really...
346
347 Float nR(nAccum);
348 SDContainer sc = in[tableStart]->getSDContainer(rowStart);
349 fillSDC (sc, sum.getMask(), sum.getArray(), tSysSum/nR, outScanID,
350 timeSum/nR, intSum, sourceNameStart, freqIDStart);
351//
352 pTabOut->putSDContainer(sc);
353/*
354 cout << endl;
355 cout << "Last accumulation for output scan ID " << outScanID << endl;
356 cout << " The first row in this accumulation is " << rowStart << endl;
357 cout << " The number of rows accumulated is " << nAccum << endl;
358 cout << " The first table in this accumulation is " << tableStart << endl;
359 cout << " The first source in this accumulation is " << sourceNameStart << endl;
360 cout << " The first freqID in this accumulation is " << freqIDStart << endl;
361 cout << " Average time stamp = " << timeSum/nR << endl;
362 cout << " Integrated time = " << intSum << endl;
363*/
364 return CountedPtr<SDMemTable>(pTabOut);
365}
366
367
368
369CountedPtr<SDMemTable>
370SDMath::quotient(const CountedPtr<SDMemTable>& on,
371 const CountedPtr<SDMemTable>& off)
372//
373// Compute quotient spectrum
374//
375{
376 const uInt nRows = on->nRow();
377 if (off->nRow() != nRows) {
378 throw (AipsError("Input Scan Tables must have the same number of rows"));
379 }
380
381// Input Tables and columns
382
383 Table ton = on->table();
384 Table toff = off->table();
385 ROArrayColumn<Float> tsys(toff, "TSYS");
386 ROScalarColumn<Double> mjd(ton, "TIME");
387 ROScalarColumn<Double> integr(ton, "INTERVAL");
388 ROScalarColumn<String> srcn(ton, "SRCNAME");
389 ROArrayColumn<uInt> freqidc(ton, "FREQID");
390
391// Output Table cloned from input
392
393 SDMemTable* sdmt = new SDMemTable(*on, True);
394
395// Loop over rows
396
397 for (uInt i=0; i<nRows; i++) {
398 MaskedArray<Float> mon(on->rowAsMaskedArray(i));
399 MaskedArray<Float> moff(off->rowAsMaskedArray(i));
400 IPosition ipon = mon.shape();
401 IPosition ipoff = moff.shape();
402//
403 Array<Float> tsarr;
404 tsys.get(i, tsarr);
405 if (ipon != ipoff && ipon != tsarr.shape()) {
406 throw(AipsError("on/off not conformant"));
407 }
408
409// Compute quotient
410
411 MaskedArray<Float> tmp = (mon-moff);
412 Array<Float> out(tmp.getArray());
413 out /= moff;
414 out *= tsarr;
415 Array<Bool> outflagsb = !(mon.getMask() && moff.getMask());
416 Array<uChar> outflags(outflagsb.shape());
417 convertArray(outflags,outflagsb);
418
419// Fill container for this row
420
421 SDContainer sc = on->getSDContainer();
422 sc.putTsys(tsarr);
423 sc.scanid = 0;
424 sc.putSpectrum(out);
425 sc.putFlags(outflags);
426
427// Put new row in output Table
428
429 sdmt->putSDContainer(sc);
430 }
431//
432 return CountedPtr<SDMemTable>(sdmt);
433}
434
435void SDMath::multiplyInSitu(SDMemTable* in, Float factor) {
436 SDMemTable* sdmt = new SDMemTable(*in);
437 Table t = sdmt->table();
438 ArrayColumn<Float> spec(t,"SPECTRA");
439 for (uInt i=0; i < t.nrow(); i++) {
440 MaskedArray<Float> marr(sdmt->rowAsMaskedArray(i));
441 marr *= factor;
442 spec.put(i, marr.getArray());
443 }
444 in = sdmt;
445 delete sdmt;sdmt=0;
446}
447
448CountedPtr<SDMemTable>
449SDMath::multiply(const CountedPtr<SDMemTable>& in, Float factor)
450//
451// Multiply values by factor
452//
453{
454 SDMemTable* sdmt = new SDMemTable(*in);
455 Table t = sdmt->table();
456 ArrayColumn<Float> spec(t,"SPECTRA");
457
458 for (uInt i=0; i < t.nrow(); i++) {
459 MaskedArray<Float> marr(sdmt->rowAsMaskedArray(i));
460 marr *= factor;
461 spec.put(i, marr.getArray());
462 }
463 return CountedPtr<SDMemTable>(sdmt);
464}
465
466CountedPtr<SDMemTable>
467SDMath::add(const CountedPtr<SDMemTable>& in, Float offset)
468//
469// Add offset to values
470//
471{
472 SDMemTable* sdmt = new SDMemTable(*in);
473
474 Table t = sdmt->table();
475 ArrayColumn<Float> spec(t,"SPECTRA");
476
477 for (uInt i=0; i < t.nrow(); i++) {
478 MaskedArray<Float> marr(sdmt->rowAsMaskedArray(i));
479 marr += offset;
480 spec.put(i, marr.getArray());
481 }
482 return CountedPtr<SDMemTable>(sdmt);
483}
484
485
486CountedPtr<SDMemTable>
487SDMath::hanning(const CountedPtr<SDMemTable>& in)
488//
489// Hanning smooth each row
490// Should Tsys be smoothed ?
491//
492{
493 SDMemTable* sdmt = new SDMemTable(*in,True);
494
495// Loop over rows in Table
496
497 for (uInt ri=0; ri < in->nRow(); ++ri) {
498
499// Get data
500
501 const MaskedArray<Float>& marr(in->rowAsMaskedArray(ri));
502 Array<Float> arr = marr.getArray();
503 Array<Bool> barr = marr.getMask();
504
505// Smooth along the channels axis
506
507 uInt axis = 3;
508 VectorIterator<Float> itData(arr, axis);
509 VectorIterator<Bool> itMask(barr, axis);
510 Vector<Float> outv;
511 Vector<Bool> outm;
512 while (!itData.pastEnd()) {
513 mathutil::hanning(outv, outm, itData.vector(), itMask.vector());
514 itData.vector() = outv;
515 itMask.vector() = outm;
516//
517 itData.next();
518 itMask.next();
519 }
520
521// Create and put back
522
523 Array<uChar> outflags(barr.shape());
524 convertArray(outflags,!barr);
525 SDContainer sc = in->getSDContainer(ri);
526 sc.putSpectrum(arr);
527 sc.putFlags(outflags);
528 sdmt->putSDContainer(sc);
529 }
530 return CountedPtr<SDMemTable>(sdmt);
531}
532
533
534
535
536CountedPtr<SDMemTable>
537SDMath::averagePol(const CountedPtr<SDMemTable>& in,
538 const Vector<Bool>& mask)
539{
540 const uInt nRows = in->nRow();
541 const uInt axis = 3; // Spectrum
542 const IPosition axes(2, 2, 3); // pol-channel plane
543
544// Create output Table
545
546 SDMemTable* sdmt = new SDMemTable(*in, True);
547
548// Loop over rows
549
550 for (uInt iRow=0; iRow<nRows; iRow++) {
551
552// Get data for this row
553
554 MaskedArray<Float> marr(in->rowAsMaskedArray(iRow));
555 Array<Float>& arr = marr.getRWArray();
556 const Array<Bool>& barr = marr.getMask();
557//
558 IPosition shp = marr.shape();
559 const Bool useMask = (mask.nelements() == shp(axis));
560 const uInt nChan = shp(axis);
561
562// Make iterators to iterate by pol-channel planes
563
564 ArrayIterator<Float> itDataPlane(arr, axes);
565 ReadOnlyArrayIterator<Bool> itMaskPlane(barr, axes);
566
567// Accumulations
568
569 Float fac = 0.0;
570 Vector<Float> vecSum(nChan,0.0);
571
572// Iterate by plane
573
574 while (!itDataPlane.pastEnd()) {
575
576// Iterate through pol-channel plane by spectrum
577
578 Vector<Float> t1(nChan); t1 = 0.0;
579 Vector<Bool> t2(nChan); t2 = True;
580 MaskedArray<Float> vecSum(t1,t2);
581 Float varSum = 0.0;
582 {
583 ReadOnlyVectorIterator<Float> itDataVec(itDataPlane.array(), 1);
584 ReadOnlyVectorIterator<Bool> itMaskVec(itMaskPlane.array(), 1);
585 while (!itDataVec.pastEnd()) {
586
587// Create MA of data & mask (optionally including OTF mask) and get variance
588
589 if (useMask) {
590 const MaskedArray<Float> spec(itDataVec.vector(),mask&&itMaskVec.vector());
591 fac = 1.0 / variance(spec);
592 } else {
593 const MaskedArray<Float> spec(itDataVec.vector(),itMaskVec.vector());
594 fac = 1.0 / variance(spec);
595 }
596
597// Normalize spectrum (without OTF mask) and accumulate
598
599 const MaskedArray<Float> spec(fac*itDataVec.vector(), itMaskVec.vector());
600 vecSum += spec;
601 varSum += fac;
602
603// Next
604
605 itDataVec.next();
606 itMaskVec.next();
607 }
608 }
609
610// Normalize summed spectrum
611
612 vecSum /= varSum;
613
614// We have formed the weighted averaged spectrum from all polarizations
615// for this beam and IF. Now replicate the spectrum to all polarizations
616
617 {
618 VectorIterator<Float> itDataVec(itDataPlane.array(), 1); // Writes back into 'arr'
619 const Vector<Float>& vecSumData = vecSum.getArray(); // It *is* a Vector
620//
621 while (!itDataVec.pastEnd()) {
622 itDataVec.vector() = vecSumData;
623 itDataVec.next();
624 }
625 }
626
627// Step to next beam/IF combination
628
629 itDataPlane.next();
630 itMaskPlane.next();
631 }
632
633// Generate output container and write it to output table
634
635 SDContainer sc = in->getSDContainer();
636 Array<uChar> outflags(barr.shape());
637 convertArray(outflags,!barr);
638 sc.putSpectrum(arr);
639 sc.putFlags(outflags);
640 sdmt->putSDContainer(sc);
641 }
642//
643 return CountedPtr<SDMemTable>(sdmt);
644}
645
646
647CountedPtr<SDMemTable> SDMath::bin(const CountedPtr<SDMemTable>& in,
648 Int width)
649{
650 SDHeader sh = in->getSDHeader();
651 SDMemTable* sdmt = new SDMemTable(*in,True);
652
653// Bin up SpectralCoordinates
654
655 IPosition factors(1);
656 factors(0) = width;
657 for (uInt j=0; j<in->nCoordinates(); ++j) {
658 CoordinateSystem cSys;
659 cSys.addCoordinate(in->getCoordinate(j));
660 CoordinateSystem cSysBin =
661 CoordinateUtil::makeBinnedCoordinateSystem (factors, cSys, False);
662//
663 SpectralCoordinate sCBin = cSysBin.spectralCoordinate(0);
664 sdmt->setCoordinate(sCBin, j);
665 }
666
667// Use RebinLattice to find shape
668
669 IPosition shapeIn(1,sh.nchan);
670 IPosition shapeOut = RebinLattice<Float>::rebinShape (shapeIn, factors);
671 sh.nchan = shapeOut(0);
672 sdmt->putSDHeader(sh);
673
674
675// Loop over rows and bin along channel axis
676
677 const uInt axis = 3;
678 for (uInt i=0; i < in->nRow(); ++i) {
679 SDContainer sc = in->getSDContainer(i);
680//
681 Array<Float> tSys(sc.getTsys()); // Get it out before sc changes shape
682
683// Bin up spectrum
684
685 MaskedArray<Float> marr(in->rowAsMaskedArray(i));
686 MaskedArray<Float> marrout;
687 LatticeUtilities::bin(marrout, marr, axis, width);
688
689// Put back the binned data and flags
690
691 IPosition ip2 = marrout.shape();
692 sc.resize(ip2);
693 sc.putSpectrum(marrout.getArray());
694//
695 Array<uChar> outflags(ip2);
696 convertArray(outflags,!(marrout.getMask()));
697 sc.putFlags(outflags);
698
699// Bin up Tsys.
700
701 Array<Bool> allGood(tSys.shape(),True);
702 MaskedArray<Float> tSysIn(tSys, allGood, True);
703//
704 MaskedArray<Float> tSysOut;
705 LatticeUtilities::bin(tSysOut, tSysIn, axis, width);
706 sc.putTsys(tSysOut.getArray());
707 sdmt->putSDContainer(sc);
708 }
709 return CountedPtr<SDMemTable>(sdmt);
710}
711
712
713
714std::vector<float> SDMath::statistic (const CountedPtr<SDMemTable>& in,
715 const std::vector<bool>& mask,
716 const std::string& which)
717//
718// Perhaps iteration over pol/beam/if should be in here
719// and inside the nrow iteration ?
720//
721{
722 const uInt nRow = in->nRow();
723 std::vector<float> result(nRow);
724 Vector<Bool> msk(mask);
725
726// Specify cursor location
727
728 uInt i = in->getBeam();
729 uInt j = in->getIF();
730 uInt k = in->getPol();
731 IPosition start(4,i,j,k,0);
732 IPosition end(4,i,j,k,in->nChan()-1);
733
734// Loop over rows
735
736 const uInt nEl = msk.nelements();
737 for (uInt ii=0; ii < in->nRow(); ++ii) {
738
739// Get row and deconstruct
740
741 MaskedArray<Float> marr(in->rowAsMaskedArray(ii));
742 Array<Float> arr = marr.getArray();
743 Array<Bool> barr = marr.getMask();
744
745// Access desired piece of data
746
747 Array<Float> v((arr(start,end)).nonDegenerate());
748 Array<Bool> m((barr(start,end)).nonDegenerate());
749
750// Apply OTF mask
751
752 MaskedArray<Float> tmp;
753 if (m.nelements()==nEl) {
754 tmp.setData(v,m&&msk);
755 } else {
756 tmp.setData(v,m);
757 }
758
759// Get statistic
760
761 result[ii] = mathutil::statistics(which, tmp);
762 }
763//
764 return result;
765}
766
767void SDMath::fillSDC (SDContainer& sc,
768 const Array<Bool>& mask,
769 const Array<Float>& data,
770 const Array<Float>& tSys,
771 Int scanID, Double timeStamp,
772 Double interval, const String& sourceName,
773 const Vector<uInt>& freqID)
774{
775 sc.putSpectrum(data);
776//
777 Array<uChar> outflags(mask.shape());
778 convertArray(outflags,!mask);
779 sc.putFlags(outflags);
780//
781 sc.putTsys(tSys);
782
783// Time things
784
785 sc.timestamp = timeStamp;
786 sc.interval = interval;
787 sc.scanid = scanID;
788//
789 sc.sourcename = sourceName;
790 sc.putFreqMap(freqID);
791}
792
793void SDMath::normalize (MaskedArray<Float>& sum,
794 const Array<Float>& sumSq,
795 const Array<Float>& nPts,
796 weightType wtType, Int axis,
797 Int nAxesSub)
798{
799 IPosition pos2(nAxesSub,0);
800//
801 if (wtType==NONE) {
802
803// We just average by the number of points accumulated.
804// We need to make a MA out of nPts so that no divide by
805// zeros occur
806
807 MaskedArray<Float> t(nPts, (nPts>Float(0.0)));
808 sum /= t;
809 } else if (wtType==VAR) {
810
811// Normalize each spectrum by sum(1/var) where the variance
812// is worked out for each spectrum
813
814 Array<Float>& data = sum.getRWArray();
815 VectorIterator<Float> itData(data, axis);
816 while (!itData.pastEnd()) {
817 pos2 = itData.pos().getFirst(nAxesSub);
818 itData.vector() /= sumSq(pos2);
819 itData.next();
820 }
821 } else if (wtType==TSYS) {
822 }
823}
824
Note: See TracBrowser for help on using the repository browser.