| 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 |  | 
|---|
| 62 | using namespace casa; | 
|---|
| 63 | using namespace asap; | 
|---|
| 64 |  | 
|---|
| 65 |  | 
|---|
| 66 | SDMath::SDMath() | 
|---|
| 67 | {;} | 
|---|
| 68 |  | 
|---|
| 69 | SDMath::SDMath (const SDMath& other) | 
|---|
| 70 | { | 
|---|
| 71 |  | 
|---|
| 72 | // No state | 
|---|
| 73 |  | 
|---|
| 74 | } | 
|---|
| 75 |  | 
|---|
| 76 | SDMath& SDMath::operator=(const SDMath& other) | 
|---|
| 77 | { | 
|---|
| 78 | if (this != &other) { | 
|---|
| 79 | // No state | 
|---|
| 80 | } | 
|---|
| 81 | return *this; | 
|---|
| 82 | } | 
|---|
| 83 |  | 
|---|
| 84 |  | 
|---|
| 85 | CountedPtr<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 |  | 
|---|
| 327 | CountedPtr<SDMemTable> | 
|---|
| 328 | SDMath::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 |  | 
|---|
| 393 | SDMemTable* 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 |  | 
|---|
| 441 | std::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 |  | 
|---|
| 492 | SDMemTable* 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 |  | 
|---|
| 554 | SDMemTable* 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 |  | 
|---|
| 621 | SDMemTable* 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 |  | 
|---|
| 758 | void 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 |  | 
|---|
| 784 | void 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 |  | 
|---|
| 817 | void 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 |  | 
|---|
| 892 | void 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 |  | 
|---|
| 915 | void 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 |  | 
|---|
| 931 | void 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 |  | 
|---|