Line data Source code
1 : //# MSTransformManager.cc: This file contains the implementation of the MSTransformManager class.
2 : //#
3 : //# CASA - Common Astronomy Software Applications (http://casa.nrao.edu/)
4 : //# Copyright (C) Associated Universities, Inc. Washington DC, USA 2011, All rights reserved.
5 : //# Copyright (C) European Southern Observatory, 2011, All rights reserved.
6 : //#
7 : //# This library is free software; you can redistribute it and/or
8 : //# modify it under the terms of the GNU Lesser General Public
9 : //# License as published by the Free software Foundation; either
10 : //# version 2.1 of the License, or (at your option) any later version.
11 : //#
12 : //# This library is distributed in the hope that it will be useful,
13 : //# but WITHOUT ANY WARRANTY, without even the implied warranty of
14 : //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : //# Lesser General Public License for more details.
16 : //#
17 : //# You should have received a copy of the GNU Lesser General Public
18 : //# License along with this library; if not, write to the Free Software
19 : //# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 : //# MA 02111-1307 USA
21 : //# $Id: $
22 :
23 : #include <mstransform/MSTransform/MSTransformManager.h>
24 :
25 : #include <casacore/tables/Tables/TableUtil.h>
26 :
27 : #include <mstransform/TVI/PolAverageTVI.h>
28 : #include <mstransform/TVI/PointingInterpolationTVI.h>
29 : #include <mstransform/TVI/SDAtmosphereCorrectionTVI.h>
30 :
31 : #include <limits>
32 :
33 : using namespace casacore;
34 : namespace casa { //# NAMESPACE CASA - BEGIN
35 :
36 : /////////////////////////////////////////////
37 : ////// MS Transform Framework utilities /////
38 : /////////////////////////////////////////////
39 : namespace MSTransformations
40 : {
41 0 : Double wtToSigma(Double weight)
42 : {
43 0 : return weight > FLT_MIN ? 1.0 / std::sqrt (weight) : -1.0;
44 : }
45 :
46 0 : Double sigmaToWeight(Double sigma)
47 : {
48 0 : return sigma > FLT_MIN ? 1.0 / std::pow (sigma,2) : 0.0;
49 : }
50 :
51 : Unit Hz(String("Hz"));
52 : }
53 :
54 : /////////////////////////////////////////////
55 : /// MSTransformManager implementation ///
56 : /////////////////////////////////////////////
57 :
58 : // -----------------------------------------------------------------------
59 : // Default constructor
60 : // -----------------------------------------------------------------------
61 1922 : MSTransformManager::MSTransformManager()
62 : {
63 1922 : initialize();
64 1922 : return;
65 0 : }
66 :
67 :
68 : // -----------------------------------------------------------------------
69 : // Configuration constructor
70 : // -----------------------------------------------------------------------
71 0 : MSTransformManager::MSTransformManager(Record configuration)
72 : {
73 0 : initialize();
74 0 : configure(configuration);
75 0 : return;
76 0 : }
77 :
78 :
79 : // -----------------------------------------------------------------------
80 : // Default destructor
81 : // -----------------------------------------------------------------------
82 3084 : MSTransformManager::~MSTransformManager()
83 : {
84 : // Close the output MS in case the application layer does not do it
85 1922 : close();
86 :
87 1922 : if (channelSelector_p) delete channelSelector_p;
88 1922 : if (visibilityIterator_p and !factory_p) delete visibilityIterator_p;
89 1922 : if (dataHandler_p) delete dataHandler_p;
90 1922 : if (phaseCenterPar_p) delete phaseCenterPar_p;
91 :
92 : // Delete the output Ms if we are in buffer mode
93 : // This has to be done after deleting the outputMS data handler
94 1922 : if (userBufferMode_p)
95 : {
96 0 : TableUtil::deleteTable(outMsName_p,true);
97 : }
98 :
99 1922 : return;
100 3084 : }
101 :
102 : // -----------------------------------------------------------------------
103 : // Method to initialize members to default values
104 : // -----------------------------------------------------------------------
105 1922 : void MSTransformManager::initialize()
106 : {
107 : // MS specification parameters
108 1922 : inpMsName_p = String("");
109 1922 : outMsName_p = String("");
110 1922 : datacolumn_p = String("CORRECTED");
111 1922 : makeVirtualModelColReal_p = false; // MODEL_DATA should always be made real via the datacol param.
112 1922 : makeVirtualCorrectedColReal_p = true; // TODO: CORRECTED_DATA should be made real on request
113 1922 : tileShape_p.resize(1,false);
114 : //TileShape of size 1 can have 2 values [0], and [1] ...these are used in to
115 : //determine the tileshape by using MSTileLayout. Otherwise it has to be a
116 : //vector size 3 e.g [4, 15, 351] => a tile shape of 4 stokes, 15 channels 351
117 : //rows.
118 1922 : tileShape_p(0) = 0;
119 :
120 : // Data selection parameters
121 1922 : arraySelection_p = String("");
122 1922 : fieldSelection_p = String("");
123 1922 : scanSelection_p = String("");
124 1922 : timeSelection_p = String("");
125 1922 : spwSelection_p = String("");
126 1922 : baselineSelection_p = String("");
127 1922 : uvwSelection_p = String("");
128 1922 : polarizationSelection_p = String("");
129 1922 : scanIntentSelection_p = String("");
130 1922 : observationSelection_p = String("");
131 1922 : taqlSelection_p = String("");
132 1922 : feedSelection_p = String("");
133 :
134 : // Input-Output index maps
135 1922 : inputOutputObservationIndexMap_p.clear();
136 1922 : inputOutputArrayIndexMap_p.clear();
137 1922 : inputOutputScanIndexMap_p.clear();
138 1922 : inputOutputScanIntentIndexMap_p.clear();
139 1922 : inputOutputFieldIndexMap_p.clear();
140 1922 : inputOutputSPWIndexMap_p.clear();
141 1922 : inputOutputDDIndexMap_p.clear();
142 1922 : inputOutputAntennaIndexMap_p.clear();
143 1922 : outputInputSPWIndexMap_p.clear();
144 1922 : inputOutputChanIndexMap_p.clear();
145 :
146 : // Frequency transformation parameters
147 1922 : smoothCoeff_p.resize(3,false);
148 1922 : smoothCoeff_p(0) = 0.25;
149 1922 : smoothCoeff_p(1) = 0.5;
150 1922 : smoothCoeff_p(2) = 0.25;
151 :
152 : // Frequency specification parameters
153 1922 : mode_p = String("channel"); // Options are: channel, frequency, velocity
154 1922 : start_p = String("0");
155 1922 : width_p = String("1");
156 1922 : nChan_p = -1; // -1 means use all the input channels
157 1922 : velocityType_p = String("radio"); // When mode is velocity options are: optical, radio
158 :
159 : // Phase shifting parameters
160 : // CAS-12706 To run phase shift via a TVI which has
161 : // support for shifting across large offset/angles
162 1922 : dx_p = 0;
163 1922 : dy_p = 0;
164 1922 : tviphaseshift_p = False;
165 1922 : tviphaseshiftConfig_p = Record();
166 :
167 : // Time transformation parameters
168 1922 : scalarAverage_p = false;
169 1922 : timeAverage_p = false;
170 1922 : timeBin_p = 0.0;
171 1922 : timespan_p = String("");
172 1922 : timeAvgOptions_p = vi::AveragingOptions(vi::AveragingOptions::Nothing);
173 1922 : maxuvwdistance_p = 0;
174 : // minbaselines_p = 0;
175 :
176 : // Cal parameters
177 1922 : calibrate_p = false;
178 1922 : callib_p = "";
179 1922 : callibRec_p = Record();
180 :
181 : // UVContSub parameters
182 1922 : uvcontsub_p = False;
183 1922 : uvcontsubRec_p = Record();
184 :
185 : // Spw averaging
186 1922 : spwAverage_p = false;
187 :
188 : // Polarization transformation
189 1922 : polAverage_p = false;
190 1922 : polAverageConfig_p = Record();
191 :
192 : // Pointings interpolation
193 1922 : pointingsInterpolation_p = false;
194 1922 : pointingsInterpolationConfig_p = Record();
195 :
196 : // Weight Spectrum parameters
197 1922 : usewtspectrum_p = false;
198 1922 : spectrumTransformation_p = false;
199 1922 : propagateWeights_p = false;
200 1922 : flushWeightSpectrum_p = false;
201 :
202 : // MS-related members
203 1922 : dataHandler_p = NULL;
204 1922 : inputMs_p = NULL;
205 1922 : selectedInputMs_p = NULL;
206 1922 : outputMs_p = NULL;
207 1922 : selectedInputMsCols_p = NULL;
208 1922 : outputMsCols_p = NULL;
209 :
210 : // VI/VB related members
211 1922 : sortColumns_p = Block<Int>(7);
212 1922 : sortColumns_p[0] = MS::OBSERVATION_ID;
213 1922 : sortColumns_p[1] = MS::ARRAY_ID;
214 1922 : sortColumns_p[2] = MS::SCAN_NUMBER;
215 1922 : sortColumns_p[3] = MS::STATE_ID;
216 1922 : sortColumns_p[4] = MS::FIELD_ID;
217 1922 : sortColumns_p[5] = MS::DATA_DESC_ID;
218 1922 : sortColumns_p[6] = MS::TIME;
219 1922 : visibilityIterator_p = NULL;
220 1922 : channelSelector_p = NULL;
221 :
222 : // Output MS structure related members
223 1922 : inputFlagCategoryAvailable_p = false;
224 1922 : inputWeightSpectrumAvailable_p = false;
225 1922 : weightSpectrumFromSigmaFilled_p = false;
226 1922 : correctedToData_p = false;
227 1922 : bothDataColumnsAreOutput_p = false;
228 1922 : doingData_p = false;
229 1922 : doingCorrected_p = false;
230 1922 : doingModel_p = false;
231 1922 : dataColMap_p.clear();
232 1922 : mainColumn_p = MS::CORRECTED_DATA;
233 1922 : nRowsToAdd_p = 0;
234 :
235 : // Frequency transformation members
236 1922 : chansPerOutputSpw_p = 0;
237 1922 : tailOfChansforLastSpw_p = 0;
238 1922 : interpolationMethod_p = MSTransformations::linear;
239 1922 : baselineMap_p.clear();
240 1922 : rowIndex_p.clear();
241 1922 : spwChannelMap_p.clear();
242 1922 : inputOutputSpwMap_p.clear();
243 1922 : inputOutputChanFactorMap_p.clear();
244 1922 : freqbinMap_p.clear();
245 1922 : numOfInpChanMap_p.clear();
246 1922 : numOfSelChanMap_p.clear();
247 1922 : numOfOutChanMap_p.clear();
248 1922 : numOfCombInputChanMap_p.clear();
249 1922 : numOfCombInterChanMap_p.clear();
250 1922 : weightFactorMap_p.clear();
251 1922 : sigmaFactorMap_p.clear();
252 1922 : newWeightFactorMap_p.clear();
253 1922 : newSigmaFactorMap_p.clear();
254 :
255 : // Reference frame transformation members
256 1922 : fftShiftEnabled_p = false;
257 1922 : fftShift_p = 0;
258 :
259 : // Weight Spectrum members
260 1922 : inputWeightSpectrumAvailable_p = false;
261 1922 : combinationOfSPWsWithDifferentExposure_p = false;
262 :
263 : // Transformations - related function pointers
264 1922 : transformCubeOfDataComplex_p = NULL;
265 1922 : transformCubeOfDataFloat_p = NULL;
266 1922 : fillWeightsPlane_p = NULL;
267 1922 : setWeightsPlaneByReference_p = NULL;
268 1922 : setWeightStripeByReference_p = NULL;
269 1922 : transformStripeOfDataComplex_p = NULL;
270 1922 : transformStripeOfDataFloat_p = NULL;
271 1922 : averageKernelComplex_p = NULL;
272 1922 : averageKernelFloat_p = NULL;
273 1922 : smoothKernelComplex_p = NULL;
274 1922 : smoothKernelFloat_p = NULL;
275 :
276 : // I/O related function pointers
277 1922 : writeOutputPlanesComplex_p = NULL;
278 1922 : writeOutputPlanesFloat_p = NULL;
279 1922 : writeOutputFlagsPlane_p = NULL;
280 1922 : writeOutputFlagsPlaneSlices_p = NULL;
281 1922 : writeOutputFlagsPlaneReshapedSlices_p = NULL;
282 :
283 : // Buffer handling members
284 1922 : bufferMode_p = false;
285 1922 : userBufferMode_p = false;
286 1922 : reindex_p = true;
287 1922 : factory_p = False;
288 1922 : interactive_p = false;
289 1922 : spectrumReshape_p = false;
290 1922 : cubeTransformation_p = false;
291 1922 : dataColumnAvailable_p = false;
292 1922 : correctedDataColumnAvailable_p = false;
293 1922 : modelDataColumnAvailable_p = false;
294 1922 : floatDataColumnAvailable_p = false;
295 1922 : flagCube_p = NULL;
296 1922 : visCube_p = NULL;
297 1922 : visCubeCorrected_p = NULL;
298 1922 : visCubeModel_p = NULL;
299 1922 : visCubeFloat_p = NULL;
300 1922 : weightSpectrum_p = NULL;
301 1922 : sigmaSpectrum_p = NULL;
302 1922 : weight_p = NULL;
303 1922 : sigma_p = NULL;
304 1922 : relativeRow_p = 0;
305 :
306 : // single dish specific
307 1922 : smoothFourier_p = false;
308 :
309 1922 : return;
310 : }
311 :
312 : // -----------------------------------------------------------------------
313 : // Method to parse the configuration parameters
314 : // -----------------------------------------------------------------------
315 1922 : void MSTransformManager::configure(Record &configuration)
316 : {
317 1922 : parseMsSpecParams(configuration);
318 1922 : parseDataSelParams(configuration);
319 1922 : parseFreqTransParams(configuration);
320 1922 : parseChanAvgParams(configuration);
321 1922 : parseRefFrameTransParams(configuration);
322 1922 : parseTimeAvgParams(configuration);
323 1922 : parseCalParams(configuration);
324 1922 : parseUVContSubParams(configuration);
325 1922 : setSpwAvg(configuration);
326 1922 : parsePolAvgParams(configuration);
327 1922 : parsePointingsInterpolationParams(configuration);
328 1922 : parsePhaseShiftParams(configuration);
329 1922 : parseAtmCorrectionParams(configuration);
330 :
331 1922 : return;
332 : }
333 :
334 : // -----------------------------------------------------------------------
335 : // Method to parse input/output MS specification
336 : // -----------------------------------------------------------------------
337 1922 : void MSTransformManager::parseMsSpecParams(Record &configuration)
338 : {
339 1922 : int exists = -1;
340 :
341 1922 : exists = -1;
342 1922 : exists = configuration.fieldNumber ("inputms");
343 1922 : if (exists >= 0)
344 : {
345 1922 : configuration.get (exists, inpMsName_p);
346 3844 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
347 3844 : << "Input file name is " << inpMsName_p << LogIO::POST;
348 : }
349 :
350 1922 : exists = -1;
351 1922 : exists = configuration.fieldNumber ("buffermode");
352 1922 : if (exists >= 0)
353 : {
354 0 : configuration.get (exists, userBufferMode_p);
355 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
356 0 : << "Buffer mode is on " << LogIO::POST;
357 :
358 0 : bufferMode_p = userBufferMode_p;
359 : }
360 :
361 : // In buffer mode this is needed for the time average VI/VB which needs to be informed beforehand
362 1922 : exists = -1;
363 1922 : exists = configuration.fieldNumber ("datacolumn");
364 1922 : if (exists >= 0)
365 : {
366 1922 : configuration.get (exists, datacolumn_p);
367 3844 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
368 3844 : << "Data column is " << datacolumn_p << LogIO::POST;
369 : }
370 :
371 : // In buffer mode outputms is just a random generated filename used as a placeholder for the re-indexed subtables
372 1922 : exists = -1;
373 1922 : exists = configuration.fieldNumber ("outputms");
374 1922 : if (exists >= 0)
375 : {
376 1922 : configuration.get (exists, outMsName_p);
377 :
378 : // Inform of filename only in normal mode, as in buffer mode is random generated
379 1922 : if (not bufferMode_p)
380 : {
381 3844 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
382 3844 : << "Output file name is " << outMsName_p << LogIO::POST;
383 : }
384 : }
385 :
386 1922 : exists = -1;
387 1922 : exists = configuration.fieldNumber ("reindex");
388 1922 : if (exists >= 0)
389 : {
390 1449 : configuration.get (exists, reindex_p);
391 :
392 1449 : if (reindex_p)
393 : {
394 2474 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
395 2474 : << "Re-index is enabled " << LogIO::POST;
396 : }
397 : else
398 : {
399 424 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
400 424 : << "Re-index is disabled " << LogIO::POST;
401 : }
402 : }
403 :
404 1922 : exists = -1;
405 1922 : exists = configuration.fieldNumber ("factory");
406 1922 : if (exists >= 0)
407 : {
408 0 : configuration.get (exists, factory_p);
409 :
410 0 : if (factory_p)
411 : {
412 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
413 0 : << "Factory mode enabled " << LogIO::POST;
414 : }
415 : }
416 :
417 1922 : if (userBufferMode_p)
418 : {
419 0 : interactive_p = true;
420 :
421 0 : exists = -1;
422 0 : exists = configuration.fieldNumber ("interactive");
423 0 : if (exists >= 0)
424 : {
425 0 : configuration.get (exists, interactive_p);
426 :
427 0 : if (interactive_p)
428 : {
429 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
430 0 : << "Interactive mode is enabled - flagging will be applied on input MS " << LogIO::POST;
431 : }
432 : else
433 : {
434 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
435 0 : << "Interactive mode is disabled - flagging will not be applied on input MS " << LogIO::POST;
436 : }
437 : }
438 : }
439 : else
440 : {
441 1922 : interactive_p = false;
442 :
443 1922 : exists = -1;
444 1922 : exists = configuration.fieldNumber ("realmodelcol");
445 1922 : if (exists >= 0)
446 : {
447 84 : configuration.get (exists, makeVirtualModelColReal_p);
448 84 : if (makeVirtualModelColReal_p)
449 : {
450 2 : if (datacolumn_p.contains("ALL") or datacolumn_p.contains("MODEL"))
451 : {
452 4 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
453 : << "MODEL column will be made real in the output MS "
454 4 : << LogIO::POST;
455 : }
456 : else
457 : {
458 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
459 : << "Requested to make virtual MODEL_DATA column real but "
460 : << "MODEL_DATA column not selected in datacolumn parameter "
461 : << "Options that include MODEL_DATA are 'MODEL' and 'ALL'"
462 0 : << LogIO::POST;
463 0 : makeVirtualModelColReal_p = false;
464 : }
465 : }
466 : }
467 :
468 1922 : exists = -1;
469 1922 : exists = configuration.fieldNumber ("usewtspectrum");
470 1922 : if (exists >= 0)
471 : {
472 522 : configuration.get (exists, usewtspectrum_p);
473 522 : if (usewtspectrum_p)
474 : {
475 234 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
476 234 : << "WEIGHT_SPECTRUM will be written in output MS " << LogIO::POST;
477 : }
478 : }
479 :
480 1922 : exists = -1;
481 1922 : exists = configuration.fieldNumber ("tileshape");
482 1922 : if (exists >= 0)
483 : {
484 522 : if ( configuration.type(exists) == casacore::TpInt )
485 : {
486 : Int mode;
487 0 : configuration.get (exists, mode);
488 0 : tileShape_p = Vector<Int>(1,mode);
489 : }
490 522 : else if ( configuration.type(exists) == casacore::TpArrayInt)
491 : {
492 522 : configuration.get (exists, tileShape_p);
493 : }
494 :
495 1044 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
496 1044 : << "Tile shape is " << tileShape_p << LogIO::POST;
497 : }
498 : }
499 :
500 1922 : return;
501 : }
502 :
503 : // -----------------------------------------------------------------------
504 : // Method to parse the data selection parameters
505 : // -----------------------------------------------------------------------
506 1922 : void MSTransformManager::parseDataSelParams(Record &configuration)
507 : {
508 1922 : int exists = -1;
509 :
510 1922 : exists = -1;
511 1922 : exists = configuration.fieldNumber ("array");
512 1922 : if (exists >= 0)
513 : {
514 59 : configuration.get (exists, arraySelection_p);
515 118 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
516 118 : << "array selection is " << arraySelection_p << LogIO::POST;
517 : }
518 :
519 1922 : exists = -1;
520 1922 : exists = configuration.fieldNumber ("field");
521 1922 : if (exists >= 0)
522 : {
523 128 : configuration.get (exists, fieldSelection_p);
524 256 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
525 256 : << "field selection is " << fieldSelection_p << LogIO::POST;
526 : }
527 :
528 1922 : exists = -1;
529 1922 : exists = configuration.fieldNumber ("scan");
530 1922 : if (exists >= 0)
531 : {
532 185 : configuration.get (exists, scanSelection_p);
533 370 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
534 370 : << "scan selection is " << scanSelection_p << LogIO::POST;
535 : }
536 :
537 1922 : exists = -1;
538 1922 : exists = configuration.fieldNumber ("timerange");
539 1922 : if (exists >= 0)
540 : {
541 39 : configuration.get (exists, timeSelection_p);
542 78 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
543 78 : << "timerange selection is " << timeSelection_p << LogIO::POST;
544 : }
545 :
546 1922 : exists = -1;
547 1922 : exists = configuration.fieldNumber ("spw");
548 1922 : if (exists >= 0)
549 : {
550 1200 : configuration.get (exists, spwSelection_p);
551 2400 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
552 2400 : << "spw selection is " << spwSelection_p << LogIO::POST;
553 : }
554 :
555 1922 : exists = -1;
556 1922 : exists = configuration.fieldNumber ("antenna");
557 1922 : if (exists >= 0)
558 : {
559 796 : configuration.get (exists, baselineSelection_p);
560 1592 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
561 1592 : << "antenna selection is " << baselineSelection_p << LogIO::POST;
562 : }
563 :
564 1922 : exists = -1;
565 1922 : exists = configuration.fieldNumber ("uvrange");
566 1922 : if (exists >= 0)
567 : {
568 0 : configuration.get (exists, uvwSelection_p);
569 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
570 0 : << "uvrange selection is " << uvwSelection_p << LogIO::POST;
571 : }
572 :
573 1922 : exists = -1;
574 1922 : exists = configuration.fieldNumber ("correlation");
575 1922 : if (exists >= 0)
576 : {
577 77 : configuration.get (exists, polarizationSelection_p);
578 154 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
579 154 : << "correlation selection is " << polarizationSelection_p << LogIO::POST;
580 : }
581 :
582 1922 : exists = -1;
583 1922 : exists = configuration.fieldNumber ("observation");
584 1922 : if (exists >= 0)
585 : {
586 67 : configuration.get (exists, observationSelection_p);
587 134 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
588 134 : <<"observation selection is " << observationSelection_p << LogIO::POST;
589 : }
590 :
591 1922 : exists = -1;
592 1922 : exists = configuration.fieldNumber ("intent");
593 1922 : if (exists >= 0)
594 : {
595 165 : configuration.get (exists, scanIntentSelection_p);
596 330 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
597 330 : << "scan intent selection is " << scanIntentSelection_p << LogIO::POST;
598 : }
599 :
600 1922 : exists = -1;
601 1922 : exists = configuration.fieldNumber ("taql");
602 1922 : if (exists >= 0)
603 : {
604 357 : configuration.get (exists, taqlSelection_p);
605 714 : logger_p << LogIO::NORMAL2 << LogOrigin("MSTransformManager", __FUNCTION__)
606 714 : << "TaQL selection is " << taqlSelection_p << LogIO::POST;
607 : }
608 :
609 1922 : exists = -1;
610 1922 : exists = configuration.fieldNumber ("feed");
611 1922 : if (exists >= 0)
612 : {
613 0 : configuration.get (exists, feedSelection_p);
614 0 : logger_p << LogIO::NORMAL2 << LogOrigin("MSTransformManager", __FUNCTION__)
615 0 : << "feed selection is " << feedSelection_p << LogIO::POST;
616 : }
617 :
618 1922 : return;
619 : }
620 :
621 : // -----------------------------------------------------------------------
622 : // Method to parse the channel average parameters
623 : // -----------------------------------------------------------------------
624 1922 : void MSTransformManager::parseChanAvgParams(Record &configuration)
625 : {
626 1922 : int exists = -1;
627 :
628 1922 : exists = -1;
629 1922 : exists = configuration.fieldNumber ("chanaverage");
630 1922 : if (exists >= 0)
631 : {
632 140 : configuration.get (exists, channelAverage_p);
633 140 : if (channelAverage_p)
634 : {
635 280 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
636 280 : << "Channel average is activated" << LogIO::POST;
637 : }
638 : else
639 : {
640 0 : return;
641 : }
642 : }
643 : else
644 : {
645 1782 : return;
646 : }
647 :
648 140 : exists = -1;
649 140 : exists = configuration.fieldNumber ("chanbin");
650 140 : if (exists >= 0)
651 : {
652 140 : if ( configuration.type(exists) == casacore::TpInt )
653 : {
654 : Int freqbin;
655 126 : configuration.get (exists, freqbin);
656 :
657 126 : if (freqbin < 2)
658 : {
659 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
660 0 : << "Channel bin is " << freqbin << " disabling channel average" << LogIO::POST;
661 0 : channelAverage_p = False;
662 : }
663 : else
664 : {
665 126 : freqbin_p = Vector<Int>(1,freqbin);
666 :
667 : }
668 : }
669 14 : else if ( configuration.type(exists) == casacore::TpArrayInt)
670 : {
671 14 : if(combinespws_p)
672 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
673 : << "If SPW combination is active, "
674 0 : "chabin cannot be an array" << LogIO::EXCEPTION;
675 :
676 14 : configuration.get (exists, freqbin_p);
677 : }
678 : else
679 : {
680 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
681 0 : << "Wrong format for chanbin parameter (only Int and arrayInt are supported) " << LogIO::POST;
682 : }
683 :
684 280 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
685 280 : << "Channel bin is " << freqbin_p << LogIO::POST;
686 : }
687 : else
688 : {
689 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
690 0 : << "Channel average is activated but no chanbin parameter provided " << LogIO::POST;
691 0 : channelAverage_p = false;
692 0 : return;
693 : }
694 :
695 : // jagonzal: This is now determined by usewtspectrum param and the presence of input WeightSpectrum
696 : /*
697 : exists = configuration.fieldNumber ("useweights");
698 : if (exists >= 0)
699 : {
700 : configuration.get (exists, useweights_p);
701 :
702 : useweights_p.downcase();
703 :
704 : if (useweights_p == "flags")
705 : {
706 : weightmode_p = MSTransformations::flags;
707 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
708 : << "Using FLAGS as weights for channel average" << LogIO::POST;
709 : }
710 : else if (useweights_p == "spectrum")
711 : {
712 : weightmode_p = MSTransformations::spectrum;
713 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
714 : << "Using WEIGHT_SPECTRUM as weights for channel average" << LogIO::POST;
715 : }
716 : else
717 : {
718 : weightmode_p = MSTransformations::flags;
719 : useweights_p = String("flags");
720 : }
721 : }
722 : */
723 :
724 140 : return;
725 : }
726 :
727 : // -----------------------------------------------------------------------
728 : // Method to parse the frequency transformation parameters
729 : // -----------------------------------------------------------------------
730 1922 : void MSTransformManager::parseFreqTransParams(Record &configuration)
731 : {
732 1922 : int exists = -1;
733 :
734 1922 : exists = -1;
735 1922 : exists = configuration.fieldNumber ("combinespws");
736 1922 : if (exists >= 0)
737 : {
738 119 : configuration.get (exists, combinespws_p);
739 :
740 119 : if (combinespws_p)
741 : {
742 238 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
743 238 : << "Combine Spectral Windows is activated" << LogIO::POST;
744 : }
745 : }
746 :
747 1922 : exists = -1;
748 1922 : exists = configuration.fieldNumber ("ddistart");
749 1922 : if (exists >= 0)
750 : {
751 839 : configuration.get (exists, ddiStart_p);
752 839 : if (ddiStart_p > 0)
753 : {
754 144 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
755 144 : << "DDI start is " << ddiStart_p << LogIO::POST;
756 : }
757 : else
758 : {
759 767 : ddiStart_p = 0;
760 : }
761 :
762 : }
763 :
764 1922 : exists = -1;
765 1922 : exists = configuration.fieldNumber ("hanning");
766 1922 : if (exists >= 0)
767 : {
768 92 : configuration.get (exists, hanningSmooth_p);
769 :
770 92 : if (hanningSmooth_p)
771 : {
772 32 : smoothBin_p = 3;
773 32 : smoothCoeff_p.resize(3,false);
774 32 : smoothCoeff_p(0) = 0.25;
775 32 : smoothCoeff_p(1) = 0.5;
776 32 : smoothCoeff_p(2) = 0.25;
777 32 : weightmode_p = MSTransformations::plainSmooth;
778 64 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
779 64 : << "Hanning Smooth is activated" << LogIO::POST;
780 32 : exists = -1;
781 32 : exists = configuration.fieldNumber ("smooth_spw");
782 32 : if (exists >= 0)
783 : {
784 8 : Array<int> smooth_spw;
785 8 : configuration.get (exists, smooth_spw);
786 8 : smooth_spw_p = smooth_spw.tovector();
787 8 : }
788 : }
789 : }
790 :
791 1922 : exists = -1;
792 1922 : exists = configuration.fieldNumber("smoothFourier");
793 1922 : if (exists >= 0)
794 : {
795 760 : configuration.get(exists, smoothFourier_p);
796 760 : if (smoothFourier_p) {
797 320 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
798 320 : << "Fourier smoothing (single dish specific) is activated" << LogIO::POST;
799 : }
800 : }
801 :
802 1922 : return;
803 : }
804 :
805 : // -----------------------------------------------------------------------
806 : // Method to parse the reference frame transformation parameters
807 : // -----------------------------------------------------------------------
808 1922 : void MSTransformManager::parseRefFrameTransParams(Record &configuration)
809 : {
810 1922 : int exists = -1;
811 :
812 1922 : exists = -1;
813 1922 : exists = configuration.fieldNumber ("regridms");
814 1922 : if (exists >= 0)
815 : {
816 112 : configuration.get (exists, regridding_p);
817 :
818 112 : if (regridding_p)
819 : {
820 224 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
821 224 : << "Regrid MS is activated"<< LogIO::POST;
822 : }
823 : else
824 : {
825 0 : return;
826 : }
827 : }
828 :
829 1922 : exists = -1;
830 1922 : exists = configuration.fieldNumber ("phasecenter");
831 1922 : if (exists >= 0)
832 : {
833 : //If phase center is a simple numeric value then it is taken
834 : // as a FIELD_ID otherwise it is converted to a MDirection
835 29 : if( configuration.type(exists) == TpInt )
836 : {
837 4 : int fieldIdForPhaseCenter = -1;
838 4 : configuration.get (exists, fieldIdForPhaseCenter);
839 8 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
840 8 : << "Field Id for phase center is " << fieldIdForPhaseCenter << LogIO::POST;
841 4 : if (phaseCenterPar_p) delete phaseCenterPar_p;
842 4 : phaseCenterPar_p = new casac::variant((long)fieldIdForPhaseCenter);
843 : }
844 : else
845 : {
846 25 : String phaseCenter("");
847 25 : configuration.get (exists, phaseCenter);
848 50 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
849 50 : << "Phase center is " << phaseCenter << LogIO::POST;
850 25 : if (phaseCenterPar_p) delete phaseCenterPar_p;
851 25 : phaseCenterPar_p = new casac::variant(phaseCenter);
852 25 : }
853 : }
854 :
855 1922 : exists = -1;
856 1922 : exists = configuration.fieldNumber ("restfreq");
857 1922 : if (exists >= 0)
858 : {
859 21 : configuration.get (exists, restFrequency_p);
860 21 : if (!restFrequency_p.empty())
861 : {
862 42 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
863 42 : << "Rest frequency is " << restFrequency_p << LogIO::POST;
864 : }
865 : }
866 :
867 1922 : exists = -1;
868 1922 : exists = configuration.fieldNumber ("outframe");
869 1922 : if (exists >= 0)
870 : {
871 43 : configuration.get (exists, outputReferenceFramePar_p);
872 86 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
873 86 : << "Output reference frame is " << outputReferenceFramePar_p << LogIO::POST;
874 : }
875 :
876 1922 : exists = -1;
877 1922 : exists = configuration.fieldNumber ("interpolation");
878 1922 : if (exists >= 0)
879 : {
880 112 : configuration.get (exists, interpolationMethodPar_p);
881 :
882 112 : if (interpolationMethodPar_p.contains("nearest"))
883 : {
884 1 : interpolationMethod_p = MSTransformations::nearestNeighbour;
885 : }
886 111 : else if (interpolationMethodPar_p.contains("linear"))
887 : {
888 98 : interpolationMethod_p = MSTransformations::linear;
889 : }
890 13 : else if (interpolationMethodPar_p.contains("cubic"))
891 : {
892 1 : interpolationMethod_p = MSTransformations::cubic;
893 : }
894 12 : else if (interpolationMethodPar_p.contains("spline"))
895 : {
896 1 : interpolationMethod_p = MSTransformations::spline;
897 : }
898 11 : else if (interpolationMethodPar_p.contains("fftshift"))
899 : {
900 11 : fftShiftEnabled_p = true;
901 11 : interpolationMethod_p = MSTransformations::linear;
902 : }
903 : else
904 : {
905 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
906 0 : << "Interpolation method " << interpolationMethodPar_p << " not available " << LogIO::POST;
907 : }
908 :
909 224 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
910 224 : << "Interpolation method is " << interpolationMethodPar_p << LogIO::POST;
911 : }
912 : else
913 : {
914 1810 : interpolationMethod_p = MSTransformations::linear;
915 : }
916 :
917 1922 : exists = -1;
918 1922 : exists = configuration.fieldNumber ("nspw");
919 1922 : if (exists >= 0)
920 : {
921 112 : configuration.get (exists, nspws_p);
922 :
923 112 : if (nspws_p > 1)
924 : {
925 26 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
926 26 : << "Number of output SPWs is " << nspws_p << LogIO::POST;
927 13 : combinespws_p = true;
928 : }
929 : else
930 : {
931 99 : nspws_p = 1;
932 : }
933 : }
934 :
935 1922 : parseFreqSpecParams(configuration);
936 :
937 1922 : exists = configuration.fieldNumber ("preaverage");
938 1922 : if (exists >= 0) {
939 50 : configuration.get (exists, enableChanPreAverage_p);
940 :
941 50 : if (combinespws_p) {
942 42 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
943 42 : << "Enabling channel pre-averaging" << LogIO::POST;
944 : }
945 : }
946 :
947 1922 : return;
948 : }
949 :
950 : // -----------------------------------------------------------------------
951 : // Method to parse the frequency selection specification
952 : // -----------------------------------------------------------------------
953 1922 : void MSTransformManager::parseFreqSpecParams(Record &configuration)
954 : {
955 1922 : int exists = -1;
956 :
957 1922 : exists = -1;
958 1922 : exists = configuration.fieldNumber ("mode");
959 1922 : if (exists >= 0)
960 : {
961 112 : configuration.get (exists, mode_p);
962 224 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
963 224 : << "Mode is " << mode_p<< LogIO::POST;
964 :
965 112 : if ((mode_p == "frequency") or (mode_p == "velocity"))
966 : {
967 48 : start_p = String("");
968 48 : width_p = String("");
969 : }
970 : }
971 :
972 1922 : exists = -1;
973 1922 : exists = configuration.fieldNumber ("nchan");
974 1922 : if (exists >= 0)
975 : {
976 112 : configuration.get (exists, nChan_p);
977 112 : if (nspws_p > 1)
978 : {
979 26 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
980 26 : << "Number of output channels per output spw is " << nChan_p << LogIO::POST;
981 13 : nChan_p *= nspws_p;
982 : }
983 : else
984 : {
985 198 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
986 198 : << "Number of output channels is " << nChan_p<< LogIO::POST;
987 : }
988 : }
989 :
990 1922 : exists = -1;
991 1922 : exists = configuration.fieldNumber ("start");
992 1922 : if (exists >= 0)
993 : {
994 100 : configuration.get (exists, start_p);
995 200 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
996 200 : << "Start is " << start_p << LogIO::POST;
997 : }
998 :
999 1922 : exists = -1;
1000 1922 : exists = configuration.fieldNumber ("width");
1001 1922 : if (exists >= 0)
1002 : {
1003 106 : configuration.get (exists, width_p);
1004 212 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1005 212 : << "Width is " << width_p << LogIO::POST;
1006 : }
1007 :
1008 1922 : exists = -1;
1009 1922 : exists = configuration.fieldNumber ("veltype");
1010 1922 : if ((exists >= 0) and (mode_p == "velocity"))
1011 : {
1012 21 : configuration.get (exists, velocityType_p);
1013 42 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1014 42 : << "Velocity type is " << velocityType_p << LogIO::POST;
1015 : }
1016 :
1017 1922 : return;
1018 : }
1019 :
1020 : // -----------------------------------------------------------------------
1021 : // Method to parse the phase shifting specification
1022 : // -----------------------------------------------------------------------
1023 : // CAS-12706 To run phase shift via a TVI which has
1024 : // support for shifting across large offset/angles
1025 : // -----------------------------------------------------------------------
1026 1922 : void MSTransformManager::parsePhaseShiftParams(Record &configuration)
1027 : {
1028 1922 : int exists = -1;
1029 :
1030 1922 : exists = -1;
1031 1922 : exists = configuration.fieldNumber("tviphaseshift");
1032 1922 : if (exists >= 0)
1033 : {
1034 90 : configuration.get (exists, tviphaseshift_p);
1035 :
1036 90 : if (tviphaseshift_p)
1037 : {
1038 : // Extract the callib Record
1039 90 : exists = -1;
1040 90 : exists = configuration.fieldNumber("tviphaseshiftlib");
1041 90 : if (configuration.type(exists) == TpRecord)
1042 : {
1043 90 : tviphaseshiftConfig_p = configuration.subRecord(exists);
1044 : }
1045 :
1046 180 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
1047 : << "Phase shifting via TVI with support for large offset/angle "
1048 180 : << LogIO::POST;
1049 : }
1050 : }
1051 :
1052 1922 : return;
1053 : }
1054 :
1055 : // -----------------------------------------------------------------------
1056 : // Method to parse the time average specification
1057 : // -----------------------------------------------------------------------
1058 1922 : void MSTransformManager::parseTimeAvgParams(Record &configuration)
1059 : {
1060 1922 : int exists = -1;
1061 :
1062 1922 : exists = -1;
1063 1922 : exists = configuration.fieldNumber ("timeaverage");
1064 1922 : if (exists >= 0)
1065 : {
1066 207 : configuration.get (exists, timeAverage_p);
1067 :
1068 207 : if (timeAverage_p)
1069 : {
1070 414 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1071 414 : << "Time average is activated" << LogIO::POST;
1072 : }
1073 : }
1074 :
1075 1922 : exists = -1;
1076 1922 : exists = configuration.fieldNumber ("scalaraverage");
1077 1922 : if (exists >= 0)
1078 : {
1079 0 : configuration.get (exists, scalarAverage_p);
1080 :
1081 0 : if (scalarAverage_p)
1082 : {
1083 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1084 0 : << "Scalar average is activated" << LogIO::POST;
1085 : }
1086 : }
1087 :
1088 1922 : if (timeAverage_p || scalarAverage_p)
1089 : {
1090 207 : exists = -1;
1091 207 : exists = configuration.fieldNumber ("timebin");
1092 207 : if (exists >= 0)
1093 : {
1094 207 : String timebin;
1095 207 : configuration.get (exists, timebin);
1096 207 : timeBin_p=casaQuantity(timebin).get("s").getValue();
1097 :
1098 414 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1099 414 : << "Time bin is " << timeBin_p << " seconds" << LogIO::POST;
1100 207 : }
1101 : else
1102 : {
1103 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
1104 0 : << "Time or scalar average is activated but no timebin parameter provided " << LogIO::POST;
1105 0 : timeAverage_p = false;
1106 0 : scalarAverage_p = false;
1107 0 : return;
1108 : }
1109 :
1110 207 : exists = -1;
1111 207 : exists = configuration.fieldNumber ("timespan");
1112 207 : if (exists >= 0)
1113 : {
1114 205 : configuration.get (exists, timespan_p);
1115 :
1116 205 : if (!timespan_p.contains("scan") and !timespan_p.contains("state") and !timespan_p.contains("field"))
1117 : {
1118 137 : timespan_p = String("");
1119 : }
1120 : else
1121 : {
1122 136 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1123 136 : << "Time span is " << timespan_p << LogIO::POST;
1124 : }
1125 : }
1126 :
1127 : // CAS-4850 (jagonzal): For ALMA each bdf is limited to 30s, so we need to combine across state (i.e. su-scan)
1128 207 : if (timeAverage_p && (timeBin_p > 30.0) and !timespan_p.contains("state"))
1129 : {
1130 58 : MeasurementSet tmpMs(inpMsName_p,Table::Old);
1131 58 : MSObservation observationTable = tmpMs.observation();
1132 58 : MSObservationColumns observationCols(observationTable);
1133 58 : String telescopeName = observationCols.telescopeName()(0);
1134 :
1135 58 : if (telescopeName.contains("ALMA"))
1136 : {
1137 10 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
1138 : << "Operating with ALMA data, automatically adding state to timespan "<< endl
1139 10 : << "In order to remove sub-scan boundaries which limit time average to 30s "<< LogIO::POST;
1140 5 : timespan_p += String(",state");
1141 : }
1142 58 : }
1143 :
1144 207 : exists = -1;
1145 207 : exists = configuration.fieldNumber ("maxuvwdistance");
1146 207 : if (exists >= 0)
1147 : {
1148 197 : configuration.get (exists, maxuvwdistance_p);
1149 :
1150 197 : if (maxuvwdistance_p > 0)
1151 : {
1152 2 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1153 : << "Maximum UV distance for baseline-dependent time average is: "
1154 2 : << maxuvwdistance_p << " meters" << LogIO::POST;
1155 : }
1156 : }
1157 :
1158 : /*
1159 : exists = configuration.fieldNumber ("minbaselines");
1160 : if (exists >= 0)
1161 : {
1162 : configuration.get (exists, minbaselines_p);
1163 :
1164 : if (minbaselines_p > 0)
1165 : {
1166 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1167 : << "Minimum number of baselines for time average: " << minbaselines_p << LogIO::POST;
1168 : }
1169 : }
1170 : */
1171 : }
1172 :
1173 1922 : return;
1174 : }
1175 :
1176 : // -----------------------------------------------------------------------
1177 : // Parameter parser for on-the-fly (OTF) calibration
1178 : // -----------------------------------------------------------------------
1179 1922 : void MSTransformManager::parseCalParams(Record &configuration)
1180 : {
1181 1922 : int exists = configuration.fieldNumber("callib");
1182 1922 : if (exists >= 0)
1183 : {
1184 :
1185 9 : if (configuration.type(exists) == TpRecord)
1186 : {
1187 : // Extract the callib Record
1188 9 : callibRec_p = configuration.subRecord(exists);
1189 9 : callib_p="";
1190 :
1191 : // If the Record is non-trivial, calibration is turned on
1192 9 : calibrate_p = callibRec_p.nfields() > 0;
1193 : }
1194 0 : else if (configuration.type(exists) == TpString)
1195 : {
1196 : // Extract the callib String
1197 0 : callib_p = configuration.asString(exists);
1198 0 : callibRec_p = Record();
1199 :
1200 : // If the callib_p String has non-trivial content, calibration in turned on
1201 0 : calibrate_p = callib_p.length() > 0;
1202 :
1203 : }
1204 :
1205 9 : if (calibrate_p)
1206 : {
1207 18 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
1208 18 : << "Calibration is activated" << LogIO::POST;
1209 : }
1210 :
1211 : }
1212 :
1213 1922 : return;
1214 : }
1215 :
1216 : // -----------------------------------------------------------------------
1217 : // Parameter parser for continuum subtraction
1218 : // -----------------------------------------------------------------------
1219 1922 : void MSTransformManager::parseUVContSubParams(Record &configuration)
1220 : {
1221 1922 : int exists = -1;
1222 :
1223 1922 : exists = -1;
1224 1922 : exists = configuration.fieldNumber("uvcontsub");
1225 1922 : if (exists >= 0)
1226 : {
1227 57 : configuration.get (exists, uvcontsub_p);
1228 :
1229 57 : if (uvcontsub_p)
1230 : {
1231 : // Extract the callib Record
1232 57 : exists = -1;
1233 57 : exists = configuration.fieldNumber("uvcontsublib");
1234 57 : if (configuration.type(exists) == TpRecord)
1235 : {
1236 57 : uvcontsubRec_p = configuration.subRecord(exists);
1237 : }
1238 :
1239 114 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",
1240 : __FUNCTION__)
1241 : << "Continuum subtraction is activated "
1242 114 : << LogIO::POST;
1243 :
1244 : // not nice going into the subRec, perhaps a writemodel var
1245 : // could be put in the top level record
1246 57 : int writemodel = uvcontsubRec_p.fieldNumber("writemodel");
1247 57 : if (writemodel >= 0) {
1248 57 : bool dowrite = false;
1249 57 : uvcontsubRec_p.get(writemodel, dowrite);
1250 57 : if (dowrite) {
1251 3 : produceModel_p = true;
1252 : }
1253 : }
1254 : }
1255 : }
1256 1922 : }
1257 :
1258 : // -----------------------------------------------------------------------
1259 : // Method to set spw averaging
1260 : // -----------------------------------------------------------------------
1261 1922 : void MSTransformManager::setSpwAvg(Record &configuration)
1262 : {
1263 1922 : int exists = -1;
1264 :
1265 1922 : exists = -1;
1266 1922 : exists = configuration.fieldNumber ("spwaverage");
1267 1922 : if (exists >= 0)
1268 : {
1269 0 : configuration.get (exists, spwAverage_p);
1270 :
1271 0 : if (spwAverage_p)
1272 : {
1273 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1274 0 : << "Spw average is activated" << LogIO::POST;
1275 : }
1276 : }
1277 1922 : }
1278 :
1279 : // -----------------------------------------------------------------------
1280 : // Parameter parser for polarization transformation
1281 : // -----------------------------------------------------------------------
1282 1922 : void MSTransformManager::parsePolAvgParams(Record &configuration)
1283 : {
1284 1922 : String key("polaverage");
1285 1922 : bool exists = configuration.isDefined(key);
1286 1922 : if (exists) {
1287 6 : polAverage_p = configuration.asBool(key);
1288 : }
1289 :
1290 1922 : key = "polaveragemode";
1291 1922 : if (polAverage_p) {
1292 6 : if (configuration.isDefined(key)) {
1293 6 : polAverageConfig_p.define("mode", configuration.asString(key));
1294 : } else {
1295 0 : polAverageConfig_p.define("mode", "default");
1296 : }
1297 : }
1298 1922 : }
1299 :
1300 1922 : void MSTransformManager::parsePointingsInterpolationParams(casacore::Record &configuration){
1301 1922 : String key("pointingsinterpolation");
1302 1922 : bool exists = configuration.isDefined(key);
1303 1922 : if (exists) {
1304 0 : pointingsInterpolation_p = configuration.asBool(key);
1305 : }
1306 1922 : }
1307 :
1308 1922 : void MSTransformManager::parseAtmCorrectionParams(casacore::Record &configuration) {
1309 1922 : String key("atmCor");
1310 1922 : if (configuration.isDefined(key)) {
1311 760 : doAtmCor_p = configuration.asBool(key);
1312 760 : atmCorConfig_p = configuration;
1313 : } else {
1314 1162 : doAtmCor_p = False;
1315 : }
1316 1922 : }
1317 :
1318 : // -----------------------------------------------------------------------
1319 : // Method to open the input MS, select the data and create the
1320 : // structure of the output MS filling the auxiliary tables.
1321 : // -----------------------------------------------------------------------
1322 1922 : void MSTransformManager::open()
1323 : {
1324 : // Initialize MSTransformDataHandler to open the MeasurementSet object
1325 1922 : if (interactive_p)
1326 : {
1327 : // In buffer mode we may have to modify the flags
1328 0 : dataHandler_p = new MSTransformDataHandler(inpMsName_p,Table::Update);
1329 : }
1330 : else
1331 : {
1332 1922 : dataHandler_p = new MSTransformDataHandler(inpMsName_p,Table::Old);
1333 : }
1334 :
1335 :
1336 : // WARNING: Input MS is re-set at the end of a successful MSTransformDataHandler::makeMSBasicStructure,
1337 : // call therefore we have to use the selected MS always
1338 1922 : inputMs_p = dataHandler_p->getInputMS();
1339 : // Note: We always get the input number of channels because we don't know if pre-averaging will be necessary
1340 1922 : getInputNumberOfChannels();
1341 :
1342 : // Check available data cols to pass this information on to MSTransformDataHandler which creates the MS structure
1343 1922 : checkDataColumnsAvailable();
1344 1922 : checkDataColumnsToFill();
1345 :
1346 :
1347 : // Check whether the MS has correlator pre-averaging and we are smoothing or averaging
1348 1922 : checkCorrelatorPreaveraging();
1349 :
1350 : // Set virtual column operation
1351 1922 : dataHandler_p->setVirtualModelCol(makeVirtualModelColReal_p);
1352 1922 : dataHandler_p->setVirtualCorrectedCol(makeVirtualCorrectedColReal_p);
1353 :
1354 : // Once the input MS is opened we can get the selection indexes,
1355 : // in this way we also validate the selection parameters
1356 1922 : dataHandler_p->setReindex(reindex_p);
1357 1922 : initDataSelectionParams();
1358 :
1359 : // Once the selection parameters have been processed, check consistency in
1360 : // number of channels, if needed.
1361 1918 : checkSPWChannelsKnownLimitation();
1362 :
1363 : // Determine channel specification for output MS
1364 1914 : Vector<Int> chanSpec;
1365 1914 : bool spectralRegridding = combinespws_p or regridding_p;
1366 1914 : if (channelAverage_p and !spectralRegridding)
1367 : {
1368 138 : chanSpec = freqbin_p;
1369 : }
1370 : else
1371 : {
1372 1776 : chanSpec = Vector<Int>(1,1);
1373 : }
1374 :
1375 : // Set-up splitter object
1376 1914 : const String dummyExpr = String("");
1377 1914 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__) << "Select data" << LogIO::POST;
1378 1914 : dataHandler_p->setmsselect((const String)spwSelection_p,
1379 3828 : (const String)fieldSelection_p,
1380 3828 : (const String)baselineSelection_p,
1381 3828 : (const String)scanSelection_p,
1382 3828 : (const String)uvwSelection_p,
1383 3828 : (const String)taqlSelection_p,
1384 : chanSpec,
1385 3828 : (const String)arraySelection_p,
1386 3828 : (const String)polarizationSelection_p,
1387 3828 : (const String)scanIntentSelection_p,
1388 3828 : (const String)observationSelection_p,
1389 3828 : (const String)feedSelection_p);
1390 :
1391 1914 : dataHandler_p->selectTime(timeBin_p,timeSelection_p);
1392 :
1393 1914 : createOutputMSStructure();
1394 :
1395 : // jagonzal (CAS-5076): Reindex state column when there is scan selection
1396 : // jagonzal (CAS-6351): Removing this fix as only implicit selection-based re-indexing has to be applied
1397 : /*
1398 : map<Int, Int> stateRemapper = dataHandler_p->getStateRemapper();
1399 : std::map<Int, Int>::iterator stateRemapperIter;
1400 : for ( stateRemapperIter = stateRemapper.begin();
1401 : stateRemapperIter != stateRemapper.end();
1402 : stateRemapperIter++)
1403 : {
1404 : inputOutputScanIntentIndexMap_p[stateRemapperIter->first] = stateRemapperIter->second;
1405 :
1406 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1407 : << "State " << stateRemapperIter->first << " mapped to " << stateRemapperIter->second << LogIO::POST;
1408 : }
1409 : */
1410 :
1411 : // jagonzal (CAS-5349): Reindex antenna columns when there is antenna selection
1412 1896 : if (!baselineSelection_p.empty() and reindex_p)
1413 : {
1414 753 : Vector<Int> antennaRemapper = dataHandler_p->getAntennaRemapper();
1415 1815 : for (uInt oldIndex=0;oldIndex<antennaRemapper.size();oldIndex++)
1416 : {
1417 1062 : inputOutputAntennaIndexMap_p[oldIndex] = antennaRemapper[oldIndex];
1418 : }
1419 753 : }
1420 :
1421 :
1422 1896 : selectedInputMs_p = dataHandler_p->getSelectedInputMS();
1423 1896 : outputMs_p = dataHandler_p->getOutputMS();
1424 1896 : selectedInputMsCols_p = dataHandler_p->getSelectedInputMSColumns();
1425 1896 : outputMsCols_p = dataHandler_p->getOutputMSColumns();
1426 :
1427 3792 : return;
1428 1932 : }
1429 :
1430 : /**
1431 : * Whether the WEIGHT/SIGMA_SPECTRUM columns should be created in the output MS.
1432 : * This should be honored when creating the output MS structure (in
1433 : * createOutputMSStructure().
1434 : *
1435 : * The logic to say true is: if the WEIGHT/SIGMA_SPECTRUM are present in the input MS or
1436 : * the user has requested the creation of these columns in the output MS anyway via the
1437 : * parameter 'usewtspectrum'
1438 : * This requires that the input configuration be parsed here in MSTransformManager before
1439 : * calling this method, and passed as parameter.
1440 : *
1441 : * @param usewtspectrum value of the usewtspectrum input parameter of mstransform
1442 : *
1443 : * @return whether WEIGHT/SIGMA_SPECTRUM columns should be created in the output MS.
1444 : */
1445 1914 : bool MSTransformManager::shouldCreateOutputWtSpectrum(bool usewtspectrum)
1446 : {
1447 1914 : if (nullptr == inputMs_p) {
1448 0 : throw AipsError("When trying to guess if WEIGHT/SIGMA_SPECTRUM should be created "
1449 0 : "in the output MS: the input MS has not been initialized.");
1450 : }
1451 :
1452 1914 : auto wtSpec = MSColumns(*inputMs_p).weightSpectrum();
1453 1914 : auto inputWeightSpectrumAvailable = !wtSpec.isNull() and wtSpec.isDefined(0);
1454 3828 : return inputWeightSpectrumAvailable or usewtspectrum;
1455 1914 : }
1456 :
1457 : /**
1458 : * Helper method for open() to create the structure of the output MS
1459 : * and check errors.
1460 : *
1461 : * @throws AipsError in case of errors creating the output MS
1462 : */
1463 1914 : void MSTransformManager::createOutputMSStructure()
1464 : {
1465 : // Create output MS structure
1466 1914 : if (not bufferMode_p)
1467 : {
1468 3828 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1469 3828 : << "Create output MS structure" << LogIO::POST;
1470 : }
1471 : else
1472 : {
1473 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1474 0 : << "Create transformed MS Subtables to be stored in memory" << LogIO::POST;
1475 : }
1476 :
1477 :
1478 : //jagonzal (CAS-5174)
1479 1914 : bool outputMSStructureCreated = false;
1480 : try
1481 : {
1482 1914 : Table::TableOption option = Table::New;
1483 1914 : if (bufferMode_p) {
1484 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
1485 0 : << "Create output MS structure" << LogIO::POST;
1486 0 : option = Table::Scratch;
1487 : }
1488 :
1489 1914 : auto createWeightSpectrum = shouldCreateOutputWtSpectrum(usewtspectrum_p);
1490 3810 : outputMSStructureCreated = dataHandler_p->makeMSBasicStructure(outMsName_p,
1491 1914 : datacolumn_p,
1492 1914 : produceModel_p,
1493 : createWeightSpectrum,
1494 1914 : tileShape_p,
1495 1914 : timespan_p,
1496 : option);
1497 : }
1498 18 : catch (const AipsError &ex)
1499 : {
1500 18 : outputMSStructureCreated = false;
1501 18 : logger_p << LogIO::DEBUG1
1502 : << "Exception creating output MS structure: " << ex.getMesg() << endl
1503 18 : << LogIO::POST;
1504 :
1505 18 : throw AipsError(ex.getMesg());
1506 18 : }
1507 :
1508 :
1509 :
1510 1896 : if (!outputMSStructureCreated)
1511 : {
1512 0 : throw AipsError("Error creating output MS structure");
1513 : }
1514 1896 : }
1515 :
1516 : // -----------------------------------------------------------------------
1517 : // Method to close the output MS
1518 : // -----------------------------------------------------------------------
1519 3799 : void MSTransformManager::close()
1520 : {
1521 3799 : if (outputMs_p)
1522 : {
1523 : // unlock MS (the MS data handler will flush it when destroying it).
1524 1896 : outputMs_p->unlock();
1525 1896 : Table::relinquishAutoLocks(true);
1526 :
1527 : // Unset the output MS
1528 1896 : outputMs_p = NULL;
1529 : }
1530 :
1531 3799 : return;
1532 : }
1533 :
1534 : // -----------------------------------------------------------------------
1535 : // Check configuration and input MS characteristics to determine run parameters
1536 : // -----------------------------------------------------------------------
1537 1896 : void MSTransformManager::setup()
1538 : {
1539 : // Check what columns have to filled
1540 : // CAS-5581 (jagonzal): Moving these methods here because we need to know if
1541 : // WEIGHT_SPECTRUM is available to configure the appropriate averaging kernel.
1542 : // - note also that the availability of WEIGHT_SPECTRUM in the input MS needs
1543 : // to be checked even before, as it is needed when doing
1544 : // dataHandler_p->makeMSBasicStructure() in createOutputMSStructure() - CAS-11269
1545 1896 : checkFillFlagCategory();
1546 1896 : checkFillWeightSpectrum();
1547 :
1548 : // Check if we really need to combine SPWs
1549 1896 : if (combinespws_p)
1550 : {
1551 128 : auto nInputSpws = outputMs_p->spectralWindow().nrow();
1552 128 : if (nInputSpws < 2)
1553 : {
1554 76 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
1555 76 : << "There is only one selected SPW, no need to combine " << LogIO::POST;
1556 38 : combinespws_p = false;
1557 : }
1558 : }
1559 :
1560 : // Regrid SPW subtable
1561 1896 : if (combinespws_p)
1562 : {
1563 90 : initRefFrameTransParams();
1564 90 : regridAndCombineSpwSubtable();
1565 90 : reindexDDISubTable();
1566 90 : reindexSourceSubTable();
1567 : //reindexFeedSubTable();
1568 : //reindexSysCalSubTable();
1569 90 : reindexFreqOffsetSubTable();
1570 90 : reindexGenericTimeDependentSubTable("FEED");
1571 90 : reindexGenericTimeDependentSubTable("SYSCAL");
1572 90 : reindexGenericTimeDependentSubTable("CALDEVICE");
1573 90 : reindexGenericTimeDependentSubTable("SYSPOWER");
1574 : }
1575 1806 : else if (regridding_p) // regrid as in the regridms option
1576 : {
1577 61 : initRefFrameTransParams();
1578 61 : regridSpwSubTable();
1579 : }
1580 :
1581 : // Subtable manipulation for polarization averaging
1582 1895 : if (polAverage_p) {
1583 : // Int nInputPolarizations = outputMs_p->polarization().nrow();
1584 6 : Int averagedPolId = getAveragedPolarizationId();
1585 6 : reindexPolarizationIdInDataDesc(averagedPolId);
1586 : }
1587 :
1588 : //// Determine the frequency transformation methods to use ////
1589 :
1590 :
1591 : // Cube level
1592 1895 : if (combinespws_p)
1593 : {
1594 90 : transformCubeOfDataComplex_p = &MSTransformManager::combineCubeOfData;
1595 90 : transformCubeOfDataFloat_p = &MSTransformManager::combineCubeOfData;
1596 90 : spectrumTransformation_p = true;
1597 90 : propagateWeights_p = true;
1598 90 : spectrumReshape_p = true;
1599 90 : cubeTransformation_p = true;
1600 : }
1601 1805 : else if (regridding_p)
1602 : {
1603 60 : transformCubeOfDataComplex_p = &MSTransformManager::regridCubeOfData;
1604 60 : transformCubeOfDataFloat_p = &MSTransformManager::regridCubeOfData;
1605 60 : spectrumTransformation_p = true;
1606 60 : propagateWeights_p = true;
1607 60 : spectrumReshape_p = true;
1608 60 : cubeTransformation_p = true;
1609 : }
1610 1745 : else if (channelAverage_p)
1611 : {
1612 136 : transformCubeOfDataComplex_p = &MSTransformManager::averageCubeOfData;
1613 136 : transformCubeOfDataFloat_p = &MSTransformManager::averageCubeOfData;
1614 136 : spectrumTransformation_p = true;
1615 136 : propagateWeights_p = true;
1616 136 : spectrumReshape_p = true;
1617 136 : cubeTransformation_p = true;
1618 : }
1619 1609 : else if (hanningSmooth_p || smoothFourier_p)
1620 : {
1621 184 : transformCubeOfDataComplex_p = &MSTransformManager::smoothCubeOfData;
1622 184 : transformCubeOfDataFloat_p = &MSTransformManager::smoothCubeOfData;
1623 184 : spectrumTransformation_p = true;
1624 184 : cubeTransformation_p = true;
1625 : }
1626 1425 : else if (nspws_p > 1)
1627 : {
1628 0 : transformCubeOfDataComplex_p = &MSTransformManager::separateCubeOfData;
1629 0 : transformCubeOfDataFloat_p = &MSTransformManager::separateCubeOfData;
1630 0 : spectrumReshape_p = true;
1631 0 : cubeTransformation_p = true;
1632 : }
1633 : else
1634 : {
1635 1425 : transformCubeOfDataComplex_p = &MSTransformManager::copyCubeOfData;
1636 1425 : transformCubeOfDataFloat_p = &MSTransformManager::copyCubeOfData;
1637 : }
1638 :
1639 1895 : bool spectralRegridding = combinespws_p or regridding_p;
1640 :
1641 : // Vector level
1642 1895 : if (channelAverage_p and !hanningSmooth_p and !spectralRegridding)
1643 : {
1644 136 : transformStripeOfDataComplex_p = &MSTransformManager::average;
1645 136 : transformStripeOfDataFloat_p = &MSTransformManager::average;
1646 : }
1647 1759 : else if (!channelAverage_p and hanningSmooth_p and !spectralRegridding)
1648 : {
1649 27 : transformStripeOfDataComplex_p = &MSTransformManager::smooth;
1650 27 : transformStripeOfDataFloat_p = &MSTransformManager::smooth;
1651 : }
1652 1732 : else if (!channelAverage_p and !hanningSmooth_p and spectralRegridding)
1653 : {
1654 143 : transformStripeOfDataComplex_p = &MSTransformManager::regrid;
1655 143 : transformStripeOfDataFloat_p = &MSTransformManager::regrid;
1656 : }
1657 1589 : else if (channelAverage_p and hanningSmooth_p and !spectralRegridding)
1658 : {
1659 0 : transformStripeOfDataComplex_p = &MSTransformManager::averageSmooth;
1660 0 : transformStripeOfDataFloat_p = &MSTransformManager::averageSmooth;
1661 : }
1662 1589 : else if (channelAverage_p and !hanningSmooth_p and spectralRegridding)
1663 : {
1664 2 : transformStripeOfDataComplex_p = &MSTransformManager::averageRegrid;
1665 2 : transformStripeOfDataFloat_p = &MSTransformManager::averageRegrid;
1666 : }
1667 1587 : else if (!channelAverage_p and hanningSmooth_p and spectralRegridding)
1668 : {
1669 5 : transformStripeOfDataComplex_p = &MSTransformManager::smoothRegrid;
1670 5 : transformStripeOfDataFloat_p = &MSTransformManager::smoothRegrid;
1671 : }
1672 1582 : else if (channelAverage_p and hanningSmooth_p and spectralRegridding)
1673 : {
1674 0 : transformStripeOfDataComplex_p = &MSTransformManager::averageSmoothRegrid;
1675 0 : transformStripeOfDataFloat_p = &MSTransformManager::averageSmoothRegrid;
1676 : }
1677 1582 : else if (smoothFourier_p) {
1678 157 : transformStripeOfDataComplex_p = &MSTransformManager::smoothFourierComplex;
1679 157 : transformStripeOfDataFloat_p = &MSTransformManager::smoothFourierFloat;
1680 : }
1681 :
1682 : // If there is not inputWeightSpectrumAvailable_p and no time average then
1683 : // weightSpectrum is constant and has no effect in frequency avg./regridding
1684 1895 : if ((not inputWeightSpectrumAvailable_p) and (not timeAverage_p))
1685 : {
1686 1490 : propagateWeights_p = false;
1687 1490 : weightmode_p = MSTransformations::flagsNonZero;
1688 : }
1689 : else
1690 : {
1691 : // NOTE: It does not hurt to set the averaging kernel even if we are not going to use it
1692 405 : weightmode_p = MSTransformations::flagSpectrumNonZero;
1693 : }
1694 :
1695 : // SPECTRUM columns have to be set when they exists in the input or the user specifies it via usewtspectrum_p
1696 1895 : if (inputWeightSpectrumAvailable_p or usewtspectrum_p)
1697 : {
1698 324 : flushWeightSpectrum_p = true;
1699 : }
1700 : else
1701 : {
1702 1571 : flushWeightSpectrum_p = false;
1703 : }
1704 :
1705 1895 : propagateWeights(propagateWeights_p);
1706 1895 : setChannelAverageKernel(weightmode_p);
1707 1895 : setSmoothingKernel(smoothmode_p);
1708 :
1709 :
1710 : // Set Regridding kernel
1711 1895 : if (fftShiftEnabled_p)
1712 : {
1713 11 : regridCoreComplex_p = &MSTransformManager::interpol1Dfftshift;
1714 11 : regridCoreFloat_p = &MSTransformManager::interpol1Dfftshift;
1715 : }
1716 : else
1717 : {
1718 1884 : regridCoreComplex_p = &MSTransformManager::interpol1D;
1719 1884 : regridCoreFloat_p = &MSTransformManager::interpol1D;
1720 : }
1721 :
1722 : //// Determine the frequency transformation methods to use ////
1723 :
1724 : // Drop channels with non-uniform width when doing only channel average
1725 1895 : if (channelAverage_p and !regridding_p and !combinespws_p )
1726 : {
1727 136 : dropNonUniformWidthChannels();
1728 : }
1729 :
1730 : // Get number of output channels (needed by chan avg and separate SPWs when there is only 1 selected SPW)
1731 1895 : if (channelAverage_p or (nspws_p>1 and !combinespws_p))
1732 : {
1733 144 : getOutputNumberOfChannels();
1734 : }
1735 :
1736 : // Determine weight and sigma factors when either auto or user channel average is set
1737 1895 : if (channelAverage_p or combinespws_p or regridding_p)
1738 : {
1739 286 : calculateNewWeightAndSigmaFactors();
1740 : }
1741 :
1742 :
1743 1895 : if (nspws_p > 1)
1744 : {
1745 13 : uInt totalNumberOfOutputChannels = 0;
1746 13 : if (combinespws_p)
1747 : {
1748 7 : totalNumberOfOutputChannels = inputOutputSpwMap_p[0].second.NUM_CHAN;
1749 : }
1750 : // jagonzal: This is the case when there is only one input SPW and there is no need to combine
1751 : else
1752 : {
1753 6 : uInt spwId = 0;
1754 6 : if (outputInputSPWIndexMap_p.size()>0)
1755 : {
1756 3 : spwId = outputInputSPWIndexMap_p[0];
1757 : }
1758 : else
1759 : {
1760 3 : spwId = 0;
1761 : }
1762 :
1763 6 : totalNumberOfOutputChannels = numOfOutChanMap_p[spwId];
1764 : }
1765 :
1766 :
1767 13 : chansPerOutputSpw_p = totalNumberOfOutputChannels / nspws_p;
1768 13 : if (totalNumberOfOutputChannels % nspws_p)
1769 : {
1770 0 : chansPerOutputSpw_p += 1;
1771 0 : tailOfChansforLastSpw_p = totalNumberOfOutputChannels - chansPerOutputSpw_p*(nspws_p-1);
1772 : }
1773 : else
1774 : {
1775 13 : tailOfChansforLastSpw_p = chansPerOutputSpw_p;
1776 : }
1777 :
1778 13 : if (bufferMode_p)
1779 : {
1780 0 : writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanesInSlices;
1781 0 : writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanesInSlices;
1782 : }
1783 : else
1784 : {
1785 13 : writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInSlices;
1786 13 : writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInSlices;
1787 : }
1788 :
1789 13 : separateSpwSubtable();
1790 13 : separateFeedSubtable();
1791 13 : separateSourceSubtable();
1792 13 : separateSyscalSubtable();
1793 13 : separateFreqOffsetSubtable();
1794 13 : separateCalDeviceSubtable();
1795 13 : separateSysPowerSubtable();
1796 :
1797 : // CAS-5404. DDI sub-table has to be re-indexed after separating SPW sub-table
1798 13 : if (not combinespws_p) reindexDDISubTable();
1799 : }
1800 : else
1801 : {
1802 1882 : if (bufferMode_p)
1803 : {
1804 0 : writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanes;
1805 0 : writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanes;
1806 : }
1807 : else
1808 : {
1809 1882 : writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInBlock;
1810 1882 : writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInBlock;
1811 : }
1812 : }
1813 :
1814 : // Generate Iterator
1815 1895 : setIterationApproach();
1816 1895 : generateIterator();
1817 :
1818 1884 : return;
1819 : }
1820 :
1821 :
1822 : // -----------------------------------------------------------------------
1823 : //
1824 : // -----------------------------------------------------------------------
1825 1440362 : IPosition MSTransformManager::getShape()
1826 : {
1827 1440362 : return getTransformedShape(visibilityIterator_p->getVisBuffer());
1828 : }
1829 :
1830 : // -----------------------------------------------------------------------
1831 : //
1832 : // -----------------------------------------------------------------------
1833 1440362 : IPosition MSTransformManager::getTransformedShape(vi::VisBuffer2 *visBuffer)
1834 : {
1835 1440362 : IPosition outputCubeShape(3);
1836 :
1837 : // Correlations
1838 1440362 : outputCubeShape(0) = visBuffer->nCorrelations();
1839 :
1840 : // Rows
1841 1440362 : outputCubeShape(2) = nRowsToAdd_p;
1842 :
1843 : // Channels
1844 1440362 : if (nspws_p > 1)
1845 : {
1846 9674 : outputCubeShape(1) = chansPerOutputSpw_p;
1847 : }
1848 1430688 : else if (combinespws_p)
1849 : {
1850 32676 : outputCubeShape(1) = inputOutputSpwMap_p[0].second.NUM_CHAN;
1851 : }
1852 1398012 : else if (regridding_p)
1853 : {
1854 45469 : Int inputSpw = visBuffer->spectralWindows()(0);
1855 45469 : outputCubeShape(1) = inputOutputSpwMap_p[inputSpw].second.NUM_CHAN;
1856 : }
1857 1352543 : else if (channelAverage_p)
1858 : {
1859 788522 : Int inputSpw = visBuffer->spectralWindows()(0);
1860 788522 : outputCubeShape(1) = numOfOutChanMap_p[inputSpw];
1861 : }
1862 : else
1863 : {
1864 564021 : outputCubeShape(1) = visBuffer->nChannels();
1865 : }
1866 :
1867 1440362 : return outputCubeShape;
1868 0 : }
1869 :
1870 : // -----------------------------------------------------------------------
1871 : //
1872 : // -----------------------------------------------------------------------
1873 383541 : void MSTransformManager::propagateWeights(bool on)
1874 : {
1875 :
1876 383541 : if (on)
1877 : {
1878 : // Used by SPW combination
1879 23564 : fillWeightsPlane_p = &MSTransformManager::fillWeightsPlane;
1880 23564 : normalizeWeightsPlane_p = &MSTransformManager::normalizeWeightsPlane;
1881 :
1882 : // Used by channel average
1883 23564 : setWeightsPlaneByReference_p = &MSTransformManager::setWeightsPlaneByReference;
1884 23564 : setWeightStripeByReference_p = &MSTransformManager::setWeightStripeByReference;
1885 : }
1886 : else
1887 : {
1888 : // Used by SPW combination
1889 359977 : fillWeightsPlane_p = &MSTransformManager::dontfillWeightsPlane;
1890 359977 : normalizeWeightsPlane_p = &MSTransformManager::dontNormalizeWeightsPlane;
1891 :
1892 : // Used by channel average
1893 359977 : setWeightsPlaneByReference_p = &MSTransformManager::dontsetWeightsPlaneByReference;
1894 359977 : setWeightStripeByReference_p = &MSTransformManager::dontSetWeightStripeByReference;
1895 : }
1896 :
1897 383541 : return;
1898 : }
1899 :
1900 : // -----------------------------------------------------------------------
1901 : //
1902 : // -----------------------------------------------------------------------
1903 338862 : void MSTransformManager::setBufferMode(bool on)
1904 : {
1905 338862 : bufferMode_p = on;
1906 :
1907 338862 : if (nspws_p > 1)
1908 : {
1909 3942 : if (bufferMode_p)
1910 : {
1911 1971 : writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanesInSlices;
1912 1971 : writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanesInSlices;
1913 : }
1914 : else
1915 : {
1916 1971 : writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInSlices;
1917 1971 : writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInSlices;
1918 : }
1919 : }
1920 : else
1921 : {
1922 334920 : if (bufferMode_p)
1923 : {
1924 167460 : writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanes;
1925 167460 : writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanes;
1926 : }
1927 : else
1928 : {
1929 167460 : writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInBlock;
1930 167460 : writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInBlock;
1931 : }
1932 : }
1933 :
1934 338862 : return;
1935 : }
1936 :
1937 : // -----------------------------------------------------------------------
1938 : //
1939 : // -----------------------------------------------------------------------
1940 383541 : void MSTransformManager::setChannelAverageKernel(uInt mode)
1941 : {
1942 383541 : switch (mode)
1943 : {
1944 0 : case MSTransformations::spectrum:
1945 : {
1946 0 : averageKernelComplex_p = &MSTransformManager::weightAverageKernel;
1947 0 : averageKernelFloat_p = &MSTransformManager::weightAverageKernel;
1948 0 : break;
1949 : }
1950 0 : case MSTransformations::flags:
1951 : {
1952 0 : averageKernelComplex_p = &MSTransformManager::flagAverageKernel;
1953 0 : averageKernelFloat_p = &MSTransformManager::flagAverageKernel;
1954 0 : break;
1955 : }
1956 0 : case MSTransformations::cumSum:
1957 : {
1958 0 : averageKernelComplex_p = &MSTransformManager::cumSumKernel;
1959 0 : averageKernelFloat_p = &MSTransformManager::cumSumKernel;
1960 0 : break;
1961 : }
1962 0 : case MSTransformations::flagSpectrum:
1963 : {
1964 0 : averageKernelComplex_p = &MSTransformManager::flagWeightAverageKernel;
1965 0 : averageKernelFloat_p = &MSTransformManager::flagWeightAverageKernel;
1966 0 : break;
1967 : }
1968 0 : case MSTransformations::flagCumSum:
1969 : {
1970 0 : averageKernelComplex_p = &MSTransformManager::flagCumSumKernel;
1971 0 : averageKernelFloat_p = &MSTransformManager::flagCumSumKernel;
1972 0 : break;
1973 : }
1974 146088 : case MSTransformations::flagsNonZero:
1975 : {
1976 146088 : averageKernelComplex_p = &MSTransformManager::flagNonZeroAverageKernel;
1977 146088 : averageKernelFloat_p = &MSTransformManager::flagNonZeroAverageKernel;
1978 146088 : break;
1979 : }
1980 46630 : case MSTransformations::flagSpectrumNonZero:
1981 : {
1982 46630 : averageKernelComplex_p = &MSTransformManager::flagWeightNonZeroAverageKernel;
1983 46630 : averageKernelFloat_p = &MSTransformManager::flagWeightNonZeroAverageKernel;
1984 46630 : break;
1985 : }
1986 190823 : case MSTransformations::flagCumSumNonZero:
1987 : {
1988 190823 : averageKernelComplex_p = &MSTransformManager::flagCumSumNonZeroKernel;
1989 190823 : averageKernelFloat_p = &MSTransformManager::flagCumSumNonZeroKernel;
1990 190823 : break;
1991 : }
1992 0 : default:
1993 : {
1994 0 : averageKernelComplex_p = &MSTransformManager::simpleAverageKernel;
1995 0 : averageKernelFloat_p = &MSTransformManager::simpleAverageKernel;
1996 0 : break;
1997 : }
1998 : }
1999 :
2000 383541 : return;
2001 : }
2002 :
2003 : // -----------------------------------------------------------------------
2004 : //
2005 : // -----------------------------------------------------------------------
2006 383541 : void MSTransformManager::setSmoothingKernel(uInt mode)
2007 : {
2008 383541 : switch (mode)
2009 : {
2010 192718 : case MSTransformations::plainSmooth:
2011 : {
2012 192718 : smoothKernelComplex_p = &MSTransformManager::plainSmooth;
2013 192718 : smoothKernelFloat_p = &MSTransformManager::plainSmooth;
2014 192718 : break;
2015 : }
2016 190823 : case MSTransformations::plainSmoothSpectrum:
2017 : {
2018 190823 : smoothKernelComplex_p = &MSTransformManager::plainSmoothSpectrum;
2019 190823 : smoothKernelFloat_p = &MSTransformManager::plainSmoothSpectrum;
2020 190823 : break;
2021 : }
2022 0 : default:
2023 : {
2024 0 : smoothKernelComplex_p = &MSTransformManager::plainSmooth;
2025 0 : smoothKernelFloat_p = &MSTransformManager::plainSmooth;
2026 0 : break;
2027 : }
2028 : }
2029 :
2030 383541 : return;
2031 : }
2032 :
2033 : // -----------------------------------------------------------------------
2034 : //
2035 : // -----------------------------------------------------------------------
2036 381646 : void MSTransformManager::setSmoothingFourierKernel(uInt mode)
2037 : {
2038 381646 : if (smoothFourier_p) {
2039 1378 : switch (mode)
2040 : {
2041 689 : case MSTransformations::plainSmooth:
2042 : {
2043 : //logger_p << "Set smoothing kernel to smoothFourier" << LogIO::POST;
2044 689 : transformStripeOfDataComplex_p = &MSTransformManager::smoothFourierComplex;
2045 689 : transformStripeOfDataFloat_p = &MSTransformManager::smoothFourierFloat;
2046 689 : break;
2047 : }
2048 689 : case MSTransformations::plainSmoothSpectrum:
2049 : {
2050 : //logger_p << "Set smoothing kernel to smooth (for weight propagation)" << LogIO::POST;
2051 689 : transformStripeOfDataComplex_p = &MSTransformManager::smooth;
2052 689 : transformStripeOfDataFloat_p = &MSTransformManager::smooth;
2053 689 : break;
2054 : }
2055 0 : default:
2056 : {
2057 0 : transformStripeOfDataComplex_p = &MSTransformManager::smoothFourierComplex;
2058 0 : transformStripeOfDataFloat_p = &MSTransformManager::smoothFourierFloat;
2059 0 : break;
2060 : }
2061 : }
2062 : }
2063 :
2064 381646 : return;
2065 : }
2066 :
2067 : // -----------------------------------------------------------------------
2068 : //
2069 : // -----------------------------------------------------------------------
2070 1922 : void MSTransformManager::initDataSelectionParams()
2071 : {
2072 1922 : MSSelection mssel;
2073 :
2074 1922 : if (reindex_p)
2075 : {
2076 1710 : if (!observationSelection_p.empty())
2077 : {
2078 8 : mssel.setObservationExpr(observationSelection_p);
2079 8 : Vector<Int> observationList = mssel.getObservationList(inputMs_p);
2080 16 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2081 16 : << "Selected Observations Ids are " << observationList << LogIO::POST;
2082 :
2083 19 : for (uInt index=0; index < observationList.size(); index++)
2084 : {
2085 11 : inputOutputObservationIndexMap_p[observationList(index)] = index;
2086 : }
2087 8 : }
2088 :
2089 1710 : if (!arraySelection_p.empty())
2090 : {
2091 0 : mssel.setArrayExpr(arraySelection_p);
2092 0 : Vector<Int> arrayList = mssel.getSubArrayList(inputMs_p);
2093 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2094 0 : << "Selected Arrays Ids are " << arrayList << LogIO::POST;
2095 :
2096 0 : for (uInt index=0; index < arrayList.size(); index++)
2097 : {
2098 0 : inputOutputArrayIndexMap_p[arrayList(index)] = index;
2099 : }
2100 0 : }
2101 :
2102 1710 : if (!scanSelection_p.empty())
2103 : {
2104 127 : mssel.setScanExpr(scanSelection_p);
2105 127 : Vector<Int> scanList = mssel.getScanList(inputMs_p);
2106 254 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2107 254 : << "Selected Scans Ids are " << scanList << LogIO::POST;
2108 :
2109 385 : for (uInt index=0; index < scanList.size(); index++)
2110 : {
2111 258 : inputOutputScanIndexMap_p[scanList(index)] = index;
2112 : }
2113 127 : }
2114 :
2115 1710 : if (!scanIntentSelection_p.empty())
2116 : {
2117 101 : mssel.setStateExpr(scanIntentSelection_p);
2118 101 : Vector<Int> scanIntentList = mssel.getStateObsModeList(inputMs_p);
2119 202 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2120 202 : << "Selected Scans Intents Ids are " << scanIntentList << LogIO::POST;
2121 :
2122 340 : for (uInt index=0; index < scanIntentList.size(); index++)
2123 : {
2124 239 : inputOutputScanIntentIndexMap_p[scanIntentList(index)] = index;
2125 : }
2126 101 : }
2127 :
2128 1710 : if (!fieldSelection_p.empty())
2129 : {
2130 58 : mssel.setFieldExpr(fieldSelection_p);
2131 58 : Vector<Int> fieldList = mssel.getFieldList(inputMs_p);
2132 114 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2133 114 : << "Selected Fields Ids are " << fieldList << LogIO::POST;
2134 :
2135 130 : for (uInt index=0; index < fieldList.size(); index++)
2136 : {
2137 73 : inputOutputFieldIndexMap_p[fieldList(index)] = index;
2138 : }
2139 57 : }
2140 : }
2141 :
2142 :
2143 1921 : if (!spwSelection_p.empty())
2144 : {
2145 1148 : mssel.setSpwExpr(spwSelection_p);
2146 1148 : Matrix<Int> spwchan = mssel.getChanList(inputMs_p);
2147 :
2148 : // Get the DD IDs of this spw selection
2149 1145 : Vector<Int> spwddi = mssel.getSPWDDIDList(inputMs_p);
2150 :
2151 : // Take into account the polarization selections
2152 1145 : if (!polarizationSelection_p.empty()){
2153 67 : mssel.setPolnExpr(polarizationSelection_p.c_str());
2154 67 : Vector<Int> polddi = mssel.getDDIDList(inputMs_p);
2155 67 : if (polddi.size() > 0){
2156 : // make an intersection
2157 67 : Vector<Int> commonDDI = set_intersection(spwddi, polddi);
2158 67 : uInt nddids = commonDDI.size();
2159 67 : if (nddids > 0){
2160 67 : spwddi.resize(nddids);
2161 406 : for (uInt ii = 0; ii < nddids; ++ii){
2162 339 : spwddi[ii] = commonDDI[ii];
2163 : }
2164 : }
2165 67 : }
2166 67 : }
2167 :
2168 1145 : uInt nddi = spwddi.size();
2169 : Int ddid;
2170 2290 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2171 2290 : << "Selected SPWs Ids are " << spwchan << LogIO::POST;
2172 : // Example of MS with repeated SPW ID in DD table:
2173 : // DD POL SPW
2174 : // 0 0 0 (RR)
2175 : // 1 1 0 (LL)
2176 : // 2 2 1 (RR,LL)
2177 : // 3 3 2 (RR,LL,RL,LR)
2178 : // example of selection: spw=0,1 correlation=RR, so selected DDs are
2179 : // DD POL SPW
2180 : // 0 0 0
2181 : // 2 2 1
2182 :
2183 : // Do the mapping of DD between input and output
2184 1145 : if (reindex_p)
2185 : {
2186 4278 : for(uInt selection_ii=0;selection_ii<nddi;selection_ii++)
2187 : {
2188 : // Get dd id and set the input-output dd map
2189 : // This will only be used to write the DD ids in the main table
2190 3184 : ddid = spwddi[selection_ii];
2191 3184 : inputOutputDDIndexMap_p[ddid] = selection_ii + ddiStart_p;
2192 : }
2193 : }
2194 :
2195 1145 : IPosition shape = spwchan.shape();
2196 1145 : uInt nSelections = shape[0];
2197 : Int spw,channelStart,channelStop,channelStep,channelWidth;
2198 1145 : if (channelSelector_p == NULL) channelSelector_p = new vi::FrequencySelectionUsingChannels();
2199 :
2200 : // Do the spw mapping between input and output
2201 1145 : uInt outputSpwIndex = 0;
2202 5208 : for(uInt selection_i=0;selection_i<nSelections;selection_i++)
2203 : {
2204 : // Get spw id and set the input-output spw map
2205 4063 : spw = spwchan(selection_i,0);
2206 :
2207 : // Set the channel selection ()
2208 4063 : channelStart = spwchan(selection_i,1);
2209 4063 : channelStop = spwchan(selection_i,2);
2210 4063 : channelStep = spwchan(selection_i,3);
2211 : // number of channels to select, starting with first selected channel:
2212 4063 : channelWidth = 1 + floor(float(channelStop - channelStart) / float(channelStep));
2213 4063 : channelSelector_p->add (spw, channelStart, channelWidth, channelStep);
2214 :
2215 4063 : if (numOfSelChanMap_p.find(spw) == numOfSelChanMap_p.end())
2216 : {
2217 4056 : if (reindex_p)
2218 : {
2219 3173 : inputOutputSPWIndexMap_p[spw] = outputSpwIndex + ddiStart_p;
2220 :
2221 3173 : outputInputSPWIndexMap_p[outputSpwIndex] = spw;
2222 : }
2223 :
2224 4056 : numOfSelChanMap_p[spw] = channelWidth;
2225 :
2226 4056 : outputSpwIndex ++;
2227 :
2228 4056 : inputOutputChanIndexMap_p[spw].clear(); // Accesing the vector creates it
2229 : }
2230 : else
2231 : {
2232 7 : numOfSelChanMap_p[spw] += channelWidth;
2233 : }
2234 :
2235 11045886 : for (Int inpChan=channelStart;inpChan<=channelStop;inpChan += channelStep)
2236 : {
2237 11041823 : inputOutputChanIndexMap_p[spw].push_back(inpChan);
2238 : }
2239 : }
2240 1145 : }
2241 :
2242 : // jagonzal: must fill numOfSelChanMap_p
2243 : else
2244 : {
2245 773 : spwSelection_p = "*";
2246 773 : mssel.setSpwExpr(spwSelection_p);
2247 773 : Matrix<Int> spwchan = mssel.getChanList(inputMs_p);
2248 :
2249 773 : IPosition shape = spwchan.shape();
2250 773 : uInt nSelections = shape[0];
2251 : Int spw,channelStart,channelStop,channelWidth;
2252 9746 : for(uInt selection_i=0;selection_i<nSelections;selection_i++)
2253 : {
2254 : // Get spw id and set the input-output spw map
2255 8973 : spw = spwchan(selection_i,0);
2256 :
2257 : // Set the channel selection ()
2258 8973 : channelStart = spwchan(selection_i,1);
2259 8973 : channelStop = spwchan(selection_i,2);
2260 8973 : channelWidth = channelStop-channelStart+1;
2261 8973 : numOfSelChanMap_p[spw] = channelWidth;
2262 : }
2263 :
2264 : // CAS-8631: Even w/o spw selection MSTransformDataHandler sets spws selection to *
2265 : // in order to obtain the SPW-DDI list. It turns out that sometimes the
2266 : // output DDI sub-table is resorted, for instance in case of non-monotonic
2267 : // DDI-SPW relation, therefore it is necessary to map input-output DDIS
2268 773 : if (reindex_p)
2269 : {
2270 613 : Vector<Int> spwddi = mssel.getSPWDDIDList(inputMs_p);
2271 :
2272 : Int ddid;
2273 613 : uInt nddi = spwddi.size();
2274 6799 : for(uInt selection_ii=0;selection_ii<nddi;selection_ii++)
2275 : {
2276 : // Get dd id and set the input-output dd map
2277 : // This will only be used to write the DD ids in the main table
2278 6186 : ddid = spwddi[selection_ii];
2279 6186 : inputOutputDDIndexMap_p[ddid] = selection_ii + ddiStart_p;
2280 : }
2281 613 : }
2282 :
2283 773 : spwSelection_p = "";
2284 773 : }
2285 :
2286 : // If we have channel average we have to populate the freqbin map
2287 1918 : if (channelAverage_p)
2288 : {
2289 140 : if (!spwSelection_p.empty())
2290 : {
2291 38 : mssel.setSpwExpr(spwSelection_p);
2292 : }
2293 : else
2294 : {
2295 102 : mssel.setSpwExpr("*");
2296 : }
2297 :
2298 : //Vector<Int> spwList = mssel.getSpwList(inputMs_p);
2299 140 : Matrix<Int> spwchan = mssel.getChanList(inputMs_p);
2300 :
2301 : // jagonzal (CAS-7149): Have to remove duplicates: With multiple pols per SPW
2302 : // each SPWId appears various (see times test_chanavg_spw_with_diff_pol_shape)
2303 140 : vector<Int> noDupSpwList;
2304 1528 : for (size_t idx=0;idx < spwchan.nrow(); idx++)
2305 : {
2306 1388 : if (find(noDupSpwList.begin(),noDupSpwList.end(),spwchan(idx,0)) == noDupSpwList.end())
2307 : {
2308 1388 : noDupSpwList.push_back(spwchan(idx,0));
2309 : }
2310 : }
2311 :
2312 : //spwList.resize(noDupSpwList.size());
2313 : //for (uInt idx=0;idx < noDupSpwList.size(); idx++) spwList(idx) = noDupSpwList[idx];
2314 140 : Vector<Int> spwList(noDupSpwList);
2315 :
2316 140 : if (freqbin_p.size() == 1)
2317 : {
2318 130 : if(combinespws_p)
2319 : {
2320 2 : uInt spwAfterComb = 0;
2321 2 : freqbinMap_p[spwAfterComb] = freqbin_p(spwAfterComb);
2322 : }
2323 : else
2324 : {
2325 : // jagonzal (CAS-8018): Update chanbin, otherwise there is a problem with dropped channels
2326 128 : Int freqbin = freqbin_p(0);
2327 128 : freqbin_p.resize(spwList.size(),True);
2328 128 : freqbin_p = freqbin;
2329 :
2330 1483 : for (size_t spw_i=0;spw_i<spwList.size();spw_i++)
2331 : {
2332 1355 : freqbinMap_p[spwList(spw_i)] = freqbin_p(spw_i);
2333 :
2334 : // jagonzal (new WEIGHT/SIGMA convention)
2335 : // jagonzal (CAS-7149): Cut chanbin to not exceed n# selected channels
2336 1355 : if (freqbin_p(spw_i) > (Int)numOfSelChanMap_p[spwList(spw_i)])
2337 : {
2338 8 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
2339 4 : << "Number of selected channels " << numOfSelChanMap_p[spwList(spw_i)]
2340 8 : << " for SPW " << spwList(spw_i)
2341 8 : << " is smaller than specified chanbin " << freqbin_p(spw_i) << endl
2342 8 : << "Setting chanbin to " << numOfSelChanMap_p[spwList(spw_i)]
2343 8 : << " for SPW " << spwList(spw_i)
2344 16 : << LogIO::POST;
2345 4 : freqbinMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
2346 4 : newWeightFactorMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
2347 : // jagonzal (CAS-8018): Update chanbin, otherwise there is a problem with dropped channels
2348 4 : freqbin_p(spw_i) = numOfSelChanMap_p[spwList(spw_i)];
2349 : }
2350 : else
2351 : {
2352 1351 : newWeightFactorMap_p[spwList(spw_i)] = freqbin_p(spw_i);
2353 : }
2354 : }
2355 : }
2356 : }
2357 : else
2358 : {
2359 10 : if (spwList.size() != freqbin_p.size())
2360 : {
2361 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
2362 : << "Number of frequency bins ( "
2363 : << freqbin_p.size() << " ) different from number of selected spws ( "
2364 0 : << spwList.size() << " )" << LogIO::POST;
2365 : }
2366 : else
2367 : {
2368 39 : for (size_t spw_i=0;spw_i<spwList.size();spw_i++)
2369 : {
2370 29 : freqbinMap_p[spwList(spw_i)] = freqbin_p(spw_i);
2371 : // jagonzal (new WEIGHT/SIGMA convention)
2372 : // jagonzal (CAS-7149): Cut chanbin to not exceed n# selected channels
2373 29 : if (freqbin_p(spw_i) > (Int)numOfSelChanMap_p[spwList(spw_i)])
2374 : {
2375 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
2376 0 : << "Number of selected channels " << numOfSelChanMap_p[spwList(spw_i)]
2377 0 : << " for SPW " << spwList(spw_i)
2378 0 : << " is smaller than specified chanbin " << freqbin_p(spw_i) << endl
2379 0 : << "Setting chanbin to " << numOfSelChanMap_p[spwList(spw_i)]
2380 0 : << " for SPW " << spwList(spw_i)
2381 0 : << LogIO::POST;
2382 0 : freqbinMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
2383 0 : newWeightFactorMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
2384 : // jagonzal (CAS-8018): Update chanbin, otherwise there is a problem with dropped channels
2385 0 : freqbin_p(spw_i) = numOfSelChanMap_p[spwList(spw_i)];
2386 : }
2387 : else
2388 : {
2389 29 : newWeightFactorMap_p[spwList(spw_i)] = freqbin_p(spw_i);
2390 : }
2391 : }
2392 : }
2393 : }
2394 140 : }
2395 :
2396 1918 : if (!polarizationSelection_p.empty())
2397 : {
2398 77 : mssel.setPolnExpr(polarizationSelection_p.c_str());
2399 77 : Vector <Vector <Slice> > correlationSlices;
2400 77 : mssel.getCorrSlices(correlationSlices,inputMs_p);
2401 154 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2402 154 : << "Selected correlations are " << correlationSlices << LogIO::POST;
2403 :
2404 77 : if (channelSelector_p == NULL) channelSelector_p = new vi::FrequencySelectionUsingChannels();
2405 :
2406 77 : channelSelector_p->addCorrelationSlices(correlationSlices);
2407 :
2408 : // Get the DDs related to the polarization selection
2409 : // when there is no spw selection
2410 77 : if (spwSelection_p.empty() and reindex_p)
2411 : {
2412 10 : std::vector<Int> polddids = mssel.getDDIDList(inputMs_p).tovector();
2413 : // The output from MSSelection might not be sorted
2414 10 : std::sort(polddids.begin(), polddids.end());
2415 :
2416 : // Make the in/out DD mapping
2417 10 : size_t nddids = polddids.size();
2418 : Int dd;
2419 102 : for(size_t ii=0;ii<nddids;ii++)
2420 : {
2421 : // Get dd id and set the input-output dd map
2422 92 : dd = polddids[ii];
2423 92 : inputOutputDDIndexMap_p[dd] = ii + ddiStart_p;
2424 : }
2425 :
2426 10 : }
2427 :
2428 77 : }
2429 :
2430 3836 : return;
2431 1922 : }
2432 :
2433 : // -----------------------------------------------------------------------
2434 : // Method to initialize the reference frame transformation parameters
2435 : // -----------------------------------------------------------------------
2436 151 : void MSTransformManager::initRefFrameTransParams()
2437 : {
2438 151 : inputReferenceFrame_p = determineInputRefFrame();
2439 :
2440 : // Parse output reference frame
2441 151 : refFrameTransformation_p = true;
2442 151 : radialVelocityCorrection_p = false;
2443 151 : if(outputReferenceFramePar_p.empty()) {
2444 110 : outputReferenceFrame_p = inputReferenceFrame_p;
2445 : }
2446 : // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
2447 41 : else if (outputReferenceFramePar_p == "SOURCE") {
2448 5 : outputReferenceFrame_p = MFrequency::GEO;
2449 5 : radialVelocityCorrection_p = true;
2450 36 : } else if(!MFrequency::getType(outputReferenceFrame_p, outputReferenceFramePar_p)) {
2451 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
2452 0 : << "Problem parsing output reference frame:" << outputReferenceFramePar_p
2453 0 : << LogIO::EXCEPTION;
2454 : }
2455 :
2456 151 : if (outputReferenceFrame_p == inputReferenceFrame_p) {
2457 111 : refFrameTransformation_p = false;
2458 : }
2459 :
2460 : // Determine observatory position from the first row in the observation sub-table of the output (selected) MS
2461 151 : MSObservation observationTable;
2462 151 : if (userBufferMode_p) {
2463 0 : observationTable = selectedInputMs_p->observation();
2464 : } else {
2465 151 : observationTable = outputMs_p->observation();
2466 : }
2467 151 : MSObservationColumns observationCols(observationTable);
2468 151 : String observatoryName = observationCols.telescopeName()(0);
2469 151 : MeasTable::Observatory(observatoryPosition_p,observatoryName);
2470 :
2471 : // jagonzal: This conversion is needed only for cosmetic reasons
2472 : // observatoryPosition_p=MPosition::Convert(observatoryPosition_p, MPosition::ITRF)();
2473 :
2474 : // Determine observation time from the first row in the selected MS
2475 151 : referenceTime_p = selectedInputMsCols_p->timeMeas()(0);
2476 :
2477 : // Access FIELD cols to get phase center and radial velocity
2478 151 : inputMSFieldCols_p = std::make_shared<MSFieldColumns>(selectedInputMs_p->field());
2479 :
2480 151 : phaseCenter_p = determinePhaseCenter();
2481 151 : }
2482 :
2483 : /**
2484 : * Determine input reference frame from the first row in the SPW 8
2485 : * sub-table of the output/selected MS.
2486 : * Helper for the initialization of the reference frame transformations
2487 : *
2488 : * @return Reference frame of output/selected MS.
2489 : */
2490 151 : casacore::MFrequency::Types MSTransformManager::determineInputRefFrame() {
2491 151 : MSSpectralWindow spwTable;
2492 151 : if (userBufferMode_p) {
2493 0 : spwTable = selectedInputMs_p->spectralWindow();
2494 : } else {
2495 151 : spwTable = outputMs_p->spectralWindow();
2496 : }
2497 151 : MSSpWindowColumns spwCols(spwTable);
2498 :
2499 : casacore::MFrequency::Types result;
2500 151 : if (reindex_p) {
2501 148 : result = MFrequency::castType(spwCols.measFreqRef()(0));
2502 : } else {
2503 3 : Int firstSelectedDDI = selectedInputMsCols_p->dataDescId()(0);
2504 3 : MSDataDescription ddiTable = outputMs_p->dataDescription();
2505 3 : MSDataDescColumns ddiCols(ddiTable);
2506 3 : Int firstSelectedSPW = ddiCols.spectralWindowId()(firstSelectedDDI);
2507 3 : result = MFrequency::castType(spwCols.measFreqRef()(firstSelectedSPW));
2508 3 : }
2509 :
2510 151 : return result;
2511 151 : }
2512 :
2513 : /**
2514 : * Determine phase center from output/selected MS.
2515 : * Helper for the initialization of the reference frame transformations
2516 : *
2517 : * @return phase center from output/selected MS.
2518 : */
2519 151 : casacore::MDirection MSTransformManager::determinePhaseCenter() {
2520 151 : casacore::MDirection result;
2521 :
2522 : // Determine phase center
2523 151 : if (phaseCenterPar_p->type() == casac::variant::INT) {
2524 4 : Int fieldIdForPhaseCenter = phaseCenterPar_p->toInt();
2525 :
2526 4 : if (fieldIdForPhaseCenter >= (Int)inputMSFieldCols_p->nrow() ||
2527 : fieldIdForPhaseCenter < 0) {
2528 2 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
2529 : << "Selected FIELD_ID to determine phase center does not exist "
2530 2 : << LogIO::POST;
2531 : } else {
2532 : // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
2533 3 : if (radialVelocityCorrection_p) {
2534 0 : radialVelocity_p = inputMSFieldCols_p->radVelMeas(fieldIdForPhaseCenter,
2535 0 : referenceTime_p.get("s").getValue());
2536 0 : result = inputMSFieldCols_p->phaseDirMeas(fieldIdForPhaseCenter,
2537 0 : referenceTime_p.get("s").getValue());
2538 : } else {
2539 3 : result = inputMSFieldCols_p->phaseDirMeasCol()(fieldIdForPhaseCenter)(IPosition(1,0));
2540 : }
2541 : }
2542 : } else {
2543 147 : String phaseCenter = phaseCenterPar_p->toString(true);
2544 :
2545 : // Determine phase center from the first row in the FIELD sub-table of the output
2546 : // (selected) MS
2547 147 : if (phaseCenter.empty()) {
2548 122 : std::shared_ptr<MSFieldColumns> fieldCols;
2549 122 : if (userBufferMode_p) {
2550 0 : fieldCols = inputMSFieldCols_p;
2551 : } else {
2552 122 : MSField fieldTable = outputMs_p->field();
2553 122 : fieldCols = std::make_shared<MSFieldColumns>(fieldTable);
2554 122 : }
2555 :
2556 : // CAS-8870: Mstransform with outframe=’SOURCE’ crashes because of ephemeris type
2557 122 : Int firstSelectedField = selectedInputMsCols_p->fieldId()(0);
2558 122 : if (inputOutputFieldIndexMap_p.find(firstSelectedField) !=
2559 244 : inputOutputFieldIndexMap_p.end()) {
2560 22 : firstSelectedField = inputOutputFieldIndexMap_p[firstSelectedField];
2561 : }
2562 :
2563 : // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
2564 122 : if (radialVelocityCorrection_p) {
2565 5 : radialVelocity_p = fieldCols->radVelMeas(firstSelectedField, referenceTime_p.get("s").getValue());
2566 :
2567 5 : if (radialVelocity_p.getRef().getType() != MRadialVelocity::GEO) {
2568 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
2569 : << "Cannot perform radial velocity correction with ephemerides attached "
2570 : << "to first selected field " << firstSelectedField << " of type "
2571 0 : << MRadialVelocity::showType(radialVelocity_p.getRef().getType())
2572 : << ".\nType needs to be GEO."
2573 0 : << LogIO::EXCEPTION;
2574 : }
2575 :
2576 5 : result = fieldCols->phaseDirMeas(firstSelectedField,referenceTime_p.get("s").getValue());
2577 : } else {
2578 117 : result = fieldCols->phaseDirMeasCol()(firstSelectedField)(IPosition(1,0));
2579 : }
2580 122 : } else {
2581 : // Parse phase center
2582 25 : if(!casaMDirection(phaseCenter, result)) {
2583 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
2584 0 : << "Cannot interpret phase center " << phaseCenter << LogIO::POST;
2585 : }
2586 : }
2587 147 : }
2588 :
2589 151 : return result;
2590 0 : }
2591 :
2592 : // -----------------------------------------------------------------------
2593 : // Method to re-grid each SPW separately in the SPW sub-table
2594 : // It also sets the input/output frequency arrays to be used by the interpolations
2595 : // -----------------------------------------------------------------------
2596 61 : void MSTransformManager::regridSpwSubTable()
2597 : {
2598 : // Access Spectral Window sub-table
2599 61 : MSSpectralWindow spwTable = outputMs_p->spectralWindow();
2600 61 : auto nInputSpws = spwTable.nrow();
2601 61 : MSSpWindowColumns spwCols(spwTable);
2602 :
2603 : // Access columns which have to be modified
2604 61 : ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
2605 61 : ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
2606 61 : ArrayColumn<Double> effectiveBWCol = spwCols.effectiveBW();
2607 61 : ArrayColumn<Double> resolutionCol = spwCols.resolution();
2608 61 : ScalarColumn<Int> numChanCol = spwCols.numChan();
2609 61 : ScalarColumn<Double> refFrequencyCol = spwCols.refFrequency();
2610 61 : ScalarColumn<Double> totalBandwidthCol = spwCols.totalBandwidth();
2611 61 : ScalarColumn<Int> measFreqRefCol = spwCols.measFreqRef();
2612 :
2613 : Int spwId;
2614 167 : for(rownr_t spw_idx=0; spw_idx<nInputSpws; ++spw_idx) {
2615 107 : if (outputInputSPWIndexMap_p.size() > 0) {
2616 36 : spwId = outputInputSPWIndexMap_p[spw_idx];
2617 : } else {
2618 71 : spwId = spw_idx;
2619 : }
2620 :
2621 : // jagonzal: Skip this SPW in non-reindex mode
2622 107 : if ((!reindex_p) and (numOfSelChanMap_p.find(spwId) == numOfSelChanMap_p.end()))
2623 6 : continue;
2624 :
2625 202 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2626 202 : << "Regridding SPW with Id " << spwId << LogIO::POST;
2627 :
2628 : // Get input frequencies and widths
2629 101 : Vector<Double> originalChanFreq(chanFreqCol(spw_idx));
2630 101 : Vector<Double> originalChanWidth(chanWidthCol(spw_idx));
2631 :
2632 : // Calculate output SPW
2633 101 : Vector<Double> regriddedCHAN_FREQ;
2634 101 : Vector<Double> regriddedCHAN_WIDTH;
2635 101 : Vector<Double> inputCHAN_FREQ;
2636 101 : Vector<Double> inputCHAN_WIDTH;
2637 101 : regridSpwAux(spwId, MFrequency::castType(spwCols.measFreqRef()(spw_idx)),
2638 : originalChanFreq, originalChanWidth,
2639 : inputCHAN_FREQ, inputCHAN_WIDTH,
2640 204 : regriddedCHAN_FREQ, regriddedCHAN_WIDTH, string("Input"));
2641 100 : spwInfo inputSpw(inputCHAN_FREQ, inputCHAN_WIDTH);
2642 100 : spwInfo outputSpw(regriddedCHAN_FREQ, regriddedCHAN_WIDTH);
2643 :
2644 : // Set the output SPW characteristics in the SPW sub-table
2645 100 : numChanCol.put(spw_idx, outputSpw.NUM_CHAN);
2646 100 : chanFreqCol.put(spw_idx, outputSpw.CHAN_FREQ);
2647 100 : chanWidthCol.put(spw_idx, outputSpw.CHAN_WIDTH);
2648 100 : effectiveBWCol.put(spw_idx, outputSpw.EFFECTIVE_BW);
2649 100 : resolutionCol.put(spw_idx, outputSpw.RESOLUTION);
2650 100 : refFrequencyCol.put(spw_idx, outputSpw.REF_FREQUENCY);
2651 100 : totalBandwidthCol.put(spw_idx, outputSpw.TOTAL_BANDWIDTH);
2652 :
2653 : // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
2654 100 : if(outputReferenceFrame_p==MFrequency::GEO) {
2655 : // i.e. outframe was GEO or SOURCE
2656 3 : measFreqRefCol.put(spw_idx, (Int)MFrequency::REST);
2657 : } else {
2658 97 : measFreqRefCol.put(spw_idx, (Int)outputReferenceFrame_p);
2659 : }
2660 :
2661 : // Add input-output SPW pair to map
2662 100 : inputOutputSpwMap_p[spwId] = std::make_pair(inputSpw,outputSpw);
2663 :
2664 : // Prepare frequency transformation engine for the reference time
2665 100 : if (fftShiftEnabled_p) {
2666 4 : MFrequency::Ref inputFrameRef(inputReferenceFrame_p,
2667 4 : MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
2668 4 : MFrequency::Ref outputFrameRef(outputReferenceFrame_p,
2669 4 : MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
2670 4 : refTimeFreqTransEngine_p = MFrequency::Convert(MSTransformations::Hz, inputFrameRef, outputFrameRef);
2671 :
2672 194 : for(uInt chan_idx=0; chan_idx < inputOutputSpwMap_p[spwId].first.CHAN_FREQ.size();
2673 : ++chan_idx) {
2674 190 : inputOutputSpwMap_p[spwId].first.CHAN_FREQ_aux[chan_idx] =
2675 190 : refTimeFreqTransEngine_p(inputOutputSpwMap_p[spwId].first.CHAN_FREQ[chan_idx]).
2676 380 : get(MSTransformations::Hz).getValue();
2677 : }
2678 4 : }
2679 106 : }
2680 70 : }
2681 :
2682 : // -----------------------------------------------------------------------
2683 : // Method to combine and re-grid the SPW sub-table
2684 : // It also sets the input/output frequency arrays to be used by the interpolations
2685 : // -----------------------------------------------------------------------
2686 90 : void MSTransformManager::regridAndCombineSpwSubtable()
2687 : {
2688 : /// Determine input SPW structure ////////////////////
2689 :
2690 : // Access Spectral Window sub-table
2691 90 : MSSpectralWindow spwTable = outputMs_p->spectralWindow();
2692 90 : auto nInputSpws = spwTable.nrow();
2693 90 : MSSpWindowColumns spwCols(spwTable);
2694 :
2695 : // Access columns which have to be modified
2696 90 : ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
2697 90 : ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
2698 90 : ArrayColumn<Double> effectiveBWCol = spwCols.effectiveBW();
2699 90 : ArrayColumn<Double> resolutionCol = spwCols.resolution();
2700 90 : ScalarColumn<Int> numChanCol = spwCols.numChan();
2701 90 : ScalarColumn<Double> refFrequencyCol = spwCols.refFrequency();
2702 90 : ScalarColumn<Double> totalBandwidthCol = spwCols.totalBandwidth();
2703 90 : ScalarColumn<Int> measFreqRefCol = spwCols.measFreqRef();
2704 :
2705 : // Create list of input channels
2706 90 : vector<channelInfo> inputChannels;
2707 714 : for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
2708 : {
2709 : Int spwId;
2710 624 : if (outputInputSPWIndexMap_p.size())
2711 : {
2712 136 : spwId = outputInputSPWIndexMap_p[spw_idx];
2713 : }
2714 : else
2715 : {
2716 488 : spwId = spw_idx;
2717 : }
2718 :
2719 : // jagonzal: Skip this SPW in non-reindex mode
2720 624 : if ((!reindex_p) and (numOfSelChanMap_p.find(spw_idx) == numOfSelChanMap_p.end())) continue;
2721 :
2722 624 : Vector<Double> originalChanFreq(chanFreqCol(spw_idx));
2723 624 : Vector<Double> originalChanWidth(chanWidthCol(spw_idx));
2724 624 : Vector<Double> inputEffectiveBW(effectiveBWCol(spw_idx));
2725 624 : Vector<Double> inputResolution(resolutionCol(spw_idx));
2726 624 : uInt nChannels = originalChanFreq.size();
2727 :
2728 72414 : for (uInt chan_idx=0;chan_idx<nChannels;chan_idx++)
2729 : {
2730 71790 : channelInfo channelInfo_idx;
2731 71790 : channelInfo_idx.SPW_id = spwId;
2732 :
2733 71790 : channelInfo_idx.inpChannel = chan_idx;
2734 71790 : channelInfo_idx.CHAN_FREQ = originalChanFreq(chan_idx);
2735 71790 : channelInfo_idx.CHAN_WIDTH = originalChanWidth(chan_idx);
2736 71790 : channelInfo_idx.EFFECTIVE_BW = inputEffectiveBW(chan_idx);
2737 71790 : channelInfo_idx.RESOLUTION = inputResolution(chan_idx);
2738 :
2739 71790 : inputChannels.push_back(channelInfo_idx);
2740 71790 : }
2741 624 : }
2742 :
2743 : // Sort input channels
2744 90 : sort (inputChannels.begin(), inputChannels.end());
2745 :
2746 : /// Determine combined SPW structure ///////////////////
2747 :
2748 : // Determine combined SPWs
2749 180 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2750 180 : << "Calculate combined SPW frequencies" << LogIO::POST;
2751 :
2752 90 : Vector<Double> combinedCHAN_FREQ;
2753 90 : Vector<Double> combinedCHAN_WIDTH;
2754 90 : std::vector<std::vector<Int> > averageWhichChan;
2755 90 : std::vector<std::vector<Int> > averageWhichSPW;
2756 90 : std::vector<std::vector<Double> > averageChanFrac;
2757 90 : MSTransformRegridder::combineSpws(logger_p,outMsName_p,Vector<Int>(1,-1),
2758 : combinedCHAN_FREQ,combinedCHAN_WIDTH,
2759 : averageWhichChan, averageWhichSPW, averageChanFrac, true);
2760 :
2761 : // Create list of combined channels
2762 90 : vector<channelInfo> combinedChannels;
2763 90 : uInt nCombinedChannels = combinedCHAN_FREQ.size();
2764 61187 : for (uInt chan_idx=0;chan_idx<nCombinedChannels;chan_idx++)
2765 : {
2766 61097 : channelInfo channelInfo_idx;
2767 61097 : channelInfo_idx.SPW_id = 0;
2768 61097 : channelInfo_idx.inpChannel = chan_idx;
2769 61097 : channelInfo_idx.CHAN_FREQ = combinedCHAN_FREQ(chan_idx);
2770 61097 : channelInfo_idx.CHAN_WIDTH = combinedCHAN_WIDTH(chan_idx);
2771 61097 : channelInfo_idx.EFFECTIVE_BW = combinedCHAN_WIDTH(chan_idx);
2772 61097 : channelInfo_idx.RESOLUTION = combinedCHAN_WIDTH(chan_idx);
2773 61097 : channelInfo_idx.contribFrac = averageChanFrac.at(chan_idx);
2774 61097 : channelInfo_idx.contribSPW_id = averageWhichSPW.at(chan_idx);
2775 61097 : channelInfo_idx.contribChannel = averageWhichChan.at(chan_idx);
2776 61097 : combinedChannels.push_back(channelInfo_idx);
2777 61097 : }
2778 :
2779 : // create list of input overlapping channels per combined channel
2780 : // note combineSpws has an edge case growing channels for slight overlap on edges,
2781 : // there the overlap is 1 even though combchannel->overlap(inputchannel) is slightly smaller than 1
2782 90 : inputOutputChanFactorMap_p.clear();
2783 :
2784 61187 : for (auto combChanIter = combinedChannels.begin(); combChanIter != combinedChannels.end(); combChanIter++)
2785 : {
2786 143199 : for (auto k = 0lu; k < combChanIter->contribFrac.size(); k++)
2787 : {
2788 : // combineSpws sorts spw so we need to map back to input selection to get correct input spw
2789 82102 : uInt spw_idx = combChanIter->contribSPW_id[k];
2790 82102 : if (outputInputSPWIndexMap_p.size())
2791 : {
2792 15631 : spw_idx = outputInputSPWIndexMap_p[spw_idx];
2793 : }
2794 :
2795 : // jagonzal: Skip this SPW in non-reindex mode
2796 82102 : if ((!reindex_p) and (numOfSelChanMap_p.find(spw_idx) == numOfSelChanMap_p.end())) continue;
2797 :
2798 82102 : inputOutputChanFactorMap_p[combChanIter->inpChannel].
2799 82102 : push_back(channelContribution(spw_idx, combChanIter->contribChannel[k], combChanIter->inpChannel, combChanIter->contribFrac[k]));
2800 : }
2801 : }
2802 :
2803 : /// Calculate output SPW ///////////////////////////////
2804 90 : Vector<Double> regriddedCHAN_FREQ;
2805 90 : Vector<Double> regriddedCHAN_WIDTH;
2806 90 : Vector<Double> inputCHAN_FREQ;
2807 90 : Vector<Double> inputCHAN_WIDTH;
2808 90 : regridSpwAux(0,inputReferenceFrame_p,combinedCHAN_FREQ,combinedCHAN_WIDTH,inputCHAN_FREQ,inputCHAN_WIDTH,regriddedCHAN_FREQ,regriddedCHAN_WIDTH,string("Combined"));
2809 90 : spwInfo inputSpw(inputCHAN_FREQ,inputCHAN_WIDTH);
2810 90 : spwInfo outputSpw(regriddedCHAN_FREQ,regriddedCHAN_WIDTH);
2811 :
2812 : /// Modify SPW subtable ////////////////////////////////
2813 :
2814 180 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2815 180 : << "Write output SPW subtable " << LogIO::POST;
2816 :
2817 : // Delete combined SPWs (reverse to preserve row number)
2818 90 : uInt rowsToDelete = nInputSpws-1;
2819 624 : for(Int spw_idx=rowsToDelete; spw_idx>0; spw_idx--)
2820 : {
2821 534 : spwTable.removeRow(spw_idx);
2822 : }
2823 :
2824 : // Set the output SPW characteristics in the SPW sub-table
2825 90 : numChanCol.put(0,outputSpw.NUM_CHAN);
2826 90 : chanFreqCol.put(0, outputSpw.CHAN_FREQ);
2827 90 : chanWidthCol.put(0, outputSpw.CHAN_WIDTH);
2828 90 : effectiveBWCol.put(0, outputSpw.EFFECTIVE_BW);
2829 90 : resolutionCol.put(0, outputSpw.RESOLUTION);
2830 90 : refFrequencyCol.put(0,outputSpw.REF_FREQUENCY);
2831 90 : totalBandwidthCol.put(0,outputSpw.TOTAL_BANDWIDTH);
2832 90 : measFreqRefCol.put(0,outputReferenceFrame_p);
2833 :
2834 : /// Add input-output SPW pair to map ///////////////////
2835 90 : inputOutputSpwMap_p[0] = std::make_pair(inputSpw,outputSpw);
2836 :
2837 : // Prepare frequency transformation engine for the reference time
2838 90 : if (fftShiftEnabled_p)
2839 : {
2840 8 : MFrequency::Ref inputFrameRef(inputReferenceFrame_p,
2841 8 : MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
2842 8 : MFrequency::Ref outputFrameRef(outputReferenceFrame_p,
2843 8 : MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
2844 8 : refTimeFreqTransEngine_p = MFrequency::Convert(MSTransformations::Hz, inputFrameRef, outputFrameRef);
2845 :
2846 1040 : for(uInt chan_idx=0; chan_idx<inputOutputSpwMap_p[0].first.CHAN_FREQ.size(); chan_idx++)
2847 : {
2848 1032 : inputOutputSpwMap_p[0].first.CHAN_FREQ_aux[chan_idx] =
2849 1032 : refTimeFreqTransEngine_p(inputOutputSpwMap_p[0].first.CHAN_FREQ[chan_idx]).
2850 2064 : get(MSTransformations::Hz).getValue();
2851 : }
2852 8 : }
2853 :
2854 180 : return;
2855 90 : }
2856 :
2857 :
2858 : // -----------------------------------------------------------------------
2859 : // Auxiliary method common whenever re-gridding is necessary (with or without combining
2860 : // the SPWs). It regrids one SPW.
2861 : // -----------------------------------------------------------------------
2862 191 : void MSTransformManager::regridSpwAux(Int spwId, MFrequency::Types spwInputRefFrame,
2863 : Vector<Double> &originalCHAN_FREQ,
2864 : Vector<Double> &originalCHAN_WIDTH,
2865 : Vector<Double> &inputCHAN_FREQ,
2866 : Vector<Double> &inputCHAN_WIDTH,
2867 : Vector<Double> ®riddedCHAN_FREQ,
2868 : Vector<Double> ®riddedCHAN_WIDTH,
2869 : string msg)
2870 : {
2871 :
2872 : // Print characteristics of input SPW
2873 191 : ostringstream oss;
2874 191 : oss << msg;
2875 191 : oss << " SPW: " << std::setw(5) << originalCHAN_FREQ.size()
2876 : << " channels, first channel = "
2877 191 : << std::setprecision(9) << std::setw(14) << std::scientific
2878 191 : << originalCHAN_FREQ(0) << " Hz"
2879 : << ", last channel = "
2880 191 : << std::setprecision(9) << std::setw(14) << std::scientific
2881 191 : << originalCHAN_FREQ(originalCHAN_FREQ.size() -1) << " Hz"
2882 : << ", first width = "
2883 191 : << std::setprecision(9) << std::setw(14) << std::scientific
2884 191 : << originalCHAN_WIDTH(originalCHAN_WIDTH.size()-1) << " Hz"
2885 : << ", last width = "
2886 191 : << std::setprecision(9) << std::setw(14) << std::scientific
2887 191 : << originalCHAN_WIDTH(originalCHAN_WIDTH.size()-1) << " Hz"
2888 : ;
2889 :
2890 191 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__) << oss.str() << LogIO::POST;
2891 :
2892 : // Apply channel average if necessary
2893 191 : if (freqbinMap_p.find(spwId) != freqbinMap_p.end()) {
2894 2 : calculateIntermediateFrequencies(spwId,originalCHAN_FREQ,originalCHAN_WIDTH,inputCHAN_FREQ,inputCHAN_WIDTH);
2895 :
2896 2 : oss.str("");
2897 2 : oss.clear();
2898 2 : oss << "Averaged SPW: " << std::setw(5) << inputCHAN_WIDTH.size()
2899 : << " channels, first channel = "
2900 2 : << std::setprecision(9) << std::setw(14) << std::scientific
2901 2 : << inputCHAN_FREQ(0) << " Hz"
2902 : << ", last channel = "
2903 2 : << std::setprecision(9) << std::setw(14) << std::scientific
2904 2 : << inputCHAN_FREQ(inputCHAN_WIDTH.size() -1) << " Hz";
2905 4 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2906 4 : << oss.str() << LogIO::POST;
2907 : } else {
2908 189 : numOfCombInputChanMap_p[spwId] = originalCHAN_FREQ.size();
2909 189 : numOfCombInterChanMap_p[spwId] = originalCHAN_FREQ.size();
2910 189 : inputCHAN_FREQ = originalCHAN_FREQ;
2911 189 : inputCHAN_WIDTH = originalCHAN_WIDTH;
2912 : }
2913 :
2914 : // Re-grid the output SPW to be uniform and change reference frame
2915 382 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2916 382 : << "Calculate frequencies in output reference frame " << LogIO::POST;
2917 :
2918 : Double weightScale;
2919 191 : bool ret = MSTransformRegridder::calcChanFreqs(logger_p,
2920 : regriddedCHAN_FREQ, regriddedCHAN_WIDTH,
2921 : weightScale, inputCHAN_FREQ,
2922 191 : inputCHAN_WIDTH, phaseCenter_p,
2923 191 : spwInputRefFrame, referenceTime_p,
2924 191 : observatoryPosition_p, mode_p, nChan_p,
2925 191 : start_p, width_p, restFrequency_p,
2926 191 : outputReferenceFramePar_p,
2927 191 : velocityType_p,
2928 : true, // verbose
2929 191 : radialVelocity_p);
2930 :
2931 191 : if (!ret) {
2932 1 : logger_p << LogIO::SEVERE << "calcChanFreqs failed, check input start and width parameters"
2933 1 : << LogIO::EXCEPTION;
2934 : }
2935 :
2936 190 : ostringstream oss_debug;
2937 190 : oss_debug << "after calcChanFreqs, phaseCenter_p=" << phaseCenter_p << endl
2938 190 : << " inputReferenceFrame_p=" << inputReferenceFrame_p << endl
2939 190 : << " referenceTime_p=" << referenceTime_p << endl
2940 190 : << " observatoryPosition_p=" << observatoryPosition_p << endl
2941 190 : << " mode_p=" << mode_p << endl
2942 190 : << " nChan_p=" << nChan_p << endl
2943 190 : << " start_p=" << start_p << endl
2944 190 : << " width_p=" << width_p << endl
2945 190 : << " restFrequency_p=" << restFrequency_p << endl
2946 190 : << " outputReferenceFrame_p=" << outputReferenceFrame_p << endl
2947 190 : << " velocityType_p=" << velocityType_p << endl
2948 190 : << " radialVelocity_p=" << radialVelocity_p;
2949 380 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__) <<
2950 380 : oss_debug.str() << LogIO::POST;
2951 :
2952 : // jagonzal (new WEIGHT/SIGMA convention in CASA 4.2.2)
2953 190 : if (newWeightFactorMap_p.find(spwId) == newWeightFactorMap_p.end()) {
2954 190 : newWeightFactorMap_p[spwId] = weightScale;
2955 : } else {
2956 0 : newWeightFactorMap_p[spwId] *= weightScale;
2957 : }
2958 :
2959 190 : checkAndPreaverageChannelsIfNeeded(spwId, inputCHAN_FREQ, inputCHAN_WIDTH,
2960 : originalCHAN_FREQ, originalCHAN_WIDTH,
2961 : regriddedCHAN_FREQ, regriddedCHAN_WIDTH);
2962 :
2963 : // Print characteristics of output SPW
2964 190 : oss.str("");
2965 190 : oss.clear();
2966 190 : oss << "Output SPW: " << std::setw(5) << regriddedCHAN_FREQ.size()
2967 : << " channels, first channel = "
2968 190 : << std::setprecision(9) << std::setw(14) << std::scientific
2969 190 : << regriddedCHAN_FREQ(0) << " Hz"
2970 : << ", last channel = "
2971 190 : << std::setprecision(9) << std::setw(14) << std::scientific
2972 190 : << regriddedCHAN_FREQ(regriddedCHAN_FREQ.size()-1) << " Hz"
2973 : <<", first width = "
2974 190 : << std::setprecision(9) << std::setw(14) << std::scientific
2975 190 : << regriddedCHAN_WIDTH(0) << " Hz"
2976 : << ", last width = "
2977 190 : << std::setprecision(9) << std::setw(14) << std::scientific
2978 190 : << regriddedCHAN_WIDTH(regriddedCHAN_WIDTH.size()-1) << " Hz";
2979 :
2980 380 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2981 380 : << oss.str() << LogIO::POST;
2982 191 : }
2983 :
2984 : // -----------------------------------------------------------------------
2985 : //
2986 : // -----------------------------------------------------------------------
2987 13 : void MSTransformManager::separateSpwSubtable()
2988 : {
2989 13 : if (Table::isReadable(outputMs_p->spectralWindowTableName()) and !outputMs_p->spectralWindow().isNull())
2990 : {
2991 : // Access Spectral Window sub-table
2992 13 : MSSpectralWindow spwTable = outputMs_p->spectralWindow();
2993 :
2994 13 : if (spwTable.nrow() > 0)
2995 : {
2996 26 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
2997 26 : << " Multiplexing SPECTRAL_WINDOW sub-table to take into account new SPWs " << LogIO::POST;
2998 :
2999 13 : MSSpWindowColumns spwCols(spwTable);
3000 :
3001 : // Access columns which have to be separated
3002 13 : ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
3003 13 : Vector<Double> chanFreq = chanFreqCol(0);
3004 13 : ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
3005 13 : Vector<Double> chanWidth = chanWidthCol(0);
3006 13 : ArrayColumn<Double> effectiveBWCol = spwCols.chanWidth();
3007 13 : Vector<Double> effectiveBW = effectiveBWCol(0);
3008 13 : ArrayColumn<Double> resolutionCol = spwCols.resolution();
3009 13 : Vector<Double> resolution = resolutionCol(0);
3010 :
3011 : // Resize columns to be separated
3012 : // jagonzal (jagonzal (CAS-7435)): Last spw must have fewer channels
3013 : /*
3014 : if (tailOfChansforLastSpw_p)
3015 : {
3016 : uInt nInChannels = chanFreq.size();
3017 : uInt nOutChannels = nspws_p*chansPerOutputSpw_p;
3018 : uInt newChannels = nOutChannels-nInChannels;
3019 : Double lastFreq = chanFreq(chanFreq.size()-1);
3020 : Double lastWidth = chanWidth(chanFreq.size()-1);
3021 : Double lastEffectiveBW = effectiveBW(chanFreq.size()-1);
3022 : Double lastResolution = resolution(chanFreq.size()-1);
3023 :
3024 : chanFreq.resize(nOutChannels,true);
3025 : chanWidth.resize(nOutChannels,true);
3026 : effectiveBW.resize(nOutChannels,true);
3027 : resolution.resize(nOutChannels,true);
3028 :
3029 : uInt outIndex;
3030 : for (uInt newChanIdx = 0; newChanIdx<newChannels; newChanIdx++)
3031 : {
3032 : outIndex = nInChannels+newChanIdx;
3033 : chanFreq(outIndex) = lastFreq + (newChanIdx+1)*lastWidth;
3034 : chanWidth(outIndex) = lastWidth;
3035 : effectiveBW(outIndex) = lastEffectiveBW;
3036 : resolution(outIndex) = lastResolution;
3037 : }
3038 : }
3039 : */
3040 :
3041 : // Calculate bandwidth per output spw
3042 13 : Double totalBandwidth = chanWidth(0)*chansPerOutputSpw_p;
3043 :
3044 13 : uInt rowIndex = 0;
3045 72 : for (uInt spw_i=0; spw_i<nspws_p; spw_i++)
3046 : {
3047 : // Columns that can be just copied
3048 59 : if (rowIndex > 0)
3049 : {
3050 : // Add row
3051 46 : spwTable.addRow(1,true);
3052 :
3053 46 : spwCols.measFreqRef().put(rowIndex,spwCols.measFreqRef()(0));
3054 46 : spwCols.flagRow().put(rowIndex,spwCols.flagRow()(0));
3055 46 : spwCols.freqGroup().put(rowIndex,spwCols.freqGroup()(0));
3056 46 : spwCols.freqGroupName().put(rowIndex,spwCols.freqGroupName()(0));
3057 46 : spwCols.ifConvChain().put(rowIndex,spwCols.ifConvChain()(0));
3058 46 : spwCols.name().put(rowIndex,spwCols.name()(0));
3059 46 : spwCols.netSideband().put(rowIndex,spwCols.netSideband()(0));
3060 :
3061 : // Optional columns
3062 46 : if (MSTransformDataHandler::columnOk(spwCols.bbcNo()))
3063 : {
3064 4 : spwCols.bbcNo().put(rowIndex,spwCols.bbcNo()(0));
3065 : }
3066 :
3067 46 : if (MSTransformDataHandler::columnOk(spwCols.assocSpwId()))
3068 : {
3069 0 : spwCols.assocSpwId().put(rowIndex,spwCols.assocSpwId()(0));
3070 : }
3071 :
3072 46 : if (MSTransformDataHandler::columnOk(spwCols.assocNature()))
3073 : {
3074 0 : spwCols.assocNature().put(rowIndex,spwCols.assocNature()(0));
3075 : }
3076 :
3077 46 : if (MSTransformDataHandler::columnOk(spwCols.bbcSideband()))
3078 : {
3079 0 : spwCols.bbcSideband().put(rowIndex,spwCols.bbcSideband()(0));
3080 : }
3081 :
3082 46 : if (MSTransformDataHandler::columnOk(spwCols.dopplerId()))
3083 : {
3084 0 : spwCols.dopplerId().put(rowIndex,spwCols.dopplerId()(0));
3085 : }
3086 :
3087 46 : if (MSTransformDataHandler::columnOk(spwCols.receiverId()))
3088 : {
3089 0 : spwCols.receiverId().put(rowIndex,spwCols.receiverId()(0));
3090 : }
3091 :
3092 92 : if (spwTable.tableDesc().isColumn("SDM_WINDOW_FUNCTION") &&
3093 46 : spwTable.tableDesc().columnDescSet().isDefined("SDM_WINDOW_FUNCTION"))
3094 : {
3095 0 : ScalarColumn<String> swfCol(spwTable, "SDM_WINDOW_FUNCTION");
3096 0 : swfCol.put(rowIndex, swfCol(0));
3097 0 : }
3098 :
3099 92 : if (spwTable.tableDesc().isColumn("SDM_NUM_BIN") &&
3100 46 : spwTable.tableDesc().columnDescSet().isDefined("SDM_NUM_BIN"))
3101 : {
3102 0 : ScalarColumn<Int> snbCol(spwTable, "SDM_NUM_BIN");
3103 0 : snbCol.put(rowIndex, snbCol(0));
3104 0 : }
3105 :
3106 92 : if (spwTable.tableDesc().isColumn("SDM_CORR_BIT") &&
3107 46 : spwTable.tableDesc().columnDescSet().isDefined("SDM_CORR_BIT"))
3108 : {
3109 0 : ScalarColumn<String> corrBitCol(spwTable, "SDM_CORR_BIT");
3110 0 : corrBitCol.put(rowIndex, corrBitCol(0));
3111 0 : }
3112 :
3113 : }
3114 :
3115 59 : if ( (spw_i < nspws_p-1) or (tailOfChansforLastSpw_p == 0) )
3116 : {
3117 46 : Slice range(chansPerOutputSpw_p*spw_i,chansPerOutputSpw_p);
3118 :
3119 : // Array columns that have to be modified
3120 46 : spwCols.chanFreq().put(rowIndex,chanFreq(range));
3121 46 : spwCols.chanWidth().put(rowIndex,chanWidth(range));
3122 46 : spwCols.effectiveBW().put(rowIndex,effectiveBW(range));
3123 46 : spwCols.resolution().put(rowIndex,resolution(range));
3124 :
3125 : // Scalar columns that have to be modified
3126 46 : spwCols.numChan().put(rowIndex,chansPerOutputSpw_p);
3127 46 : spwCols.totalBandwidth().put(rowIndex,totalBandwidth);
3128 46 : spwCols.refFrequency().put(rowIndex,chanFreq(range)(0));
3129 46 : }
3130 : // jagonzal (jagonzal (CAS-7435)): Last spw must have fewer channels
3131 : else
3132 : {
3133 13 : Slice range(chansPerOutputSpw_p*spw_i,tailOfChansforLastSpw_p);
3134 :
3135 : // Array columns that have to be modified
3136 13 : spwCols.chanFreq().put(rowIndex,chanFreq(range));
3137 13 : spwCols.chanWidth().put(rowIndex,chanWidth(range));
3138 13 : spwCols.effectiveBW().put(rowIndex,effectiveBW(range));
3139 13 : spwCols.resolution().put(rowIndex,resolution(range));
3140 :
3141 : // Scalar columns that have to be modified
3142 13 : spwCols.numChan().put(rowIndex,tailOfChansforLastSpw_p);
3143 13 : spwCols.totalBandwidth().put(rowIndex,chanWidth(0)*tailOfChansforLastSpw_p);
3144 13 : spwCols.refFrequency().put(rowIndex,chanFreq(range)(0));
3145 : }
3146 :
3147 59 : rowIndex += 1;
3148 : }
3149 :
3150 : // Remove first row
3151 : // spwTable.removeRow(0);
3152 13 : }
3153 : else
3154 : {
3155 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
3156 0 : << "SPECTRAL_WINDOW sub-table found but has no valid content" << LogIO::POST;
3157 : }
3158 13 : }
3159 : else
3160 : {
3161 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
3162 0 : << "SPECTRAL_WINDOW sub-table not found " << LogIO::POST;
3163 : }
3164 :
3165 13 : return;
3166 : }
3167 :
3168 : // -----------------------------------------------------------------------
3169 : //
3170 : // -----------------------------------------------------------------------
3171 13 : void MSTransformManager::separateFeedSubtable()
3172 : {
3173 13 : if (Table::isReadable(outputMs_p->feedTableName()) and !outputMs_p->feed().isNull())
3174 : {
3175 : // Access Feed sub-table
3176 13 : MSFeed feedtable = outputMs_p->feed();
3177 :
3178 13 : if (feedtable.nrow() > 0)
3179 : {
3180 26 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
3181 26 : << " Multiplexing FEED sub-table to take into account new SPWs " << LogIO::POST;
3182 :
3183 13 : MSFeedColumns feedCols(feedtable);
3184 :
3185 : // Get original content from columns
3186 13 : Array<Double> position = feedCols.position().getColumn();
3187 13 : Array<Double> beamOffset = feedCols.beamOffset().getColumn();
3188 13 : Array<String> polarizationType = feedCols.polarizationType().getColumn();
3189 13 : Array<Complex> polResponse = feedCols.polResponse().getColumn();
3190 13 : Array<Double> receptorAngle = feedCols.receptorAngle().getColumn();
3191 13 : Array<Int> antennaId = feedCols.antennaId().getColumn();
3192 13 : Array<Int> beamId = feedCols.beamId().getColumn();
3193 13 : Array<Int> feedId = feedCols.feedId().getColumn();
3194 13 : Array<Double> interval = feedCols.interval().getColumn();
3195 13 : Array<Int> numReceptors = feedCols.numReceptors().getColumn();
3196 13 : Array<Int> spectralWindowId = feedCols.spectralWindowId().getColumn();
3197 13 : Array<Double> time = feedCols.time().getColumn();
3198 :
3199 : // Optional columns
3200 13 : Array<Double> focusLength;
3201 13 : if (MSTransformDataHandler::columnOk(feedCols.focusLength()))
3202 : {
3203 0 : focusLength = feedCols.focusLength().getColumn();
3204 : }
3205 :
3206 13 : Array<Int> phasedFeedId;
3207 13 : if (MSTransformDataHandler::columnOk(feedCols.phasedFeedId()))
3208 : {
3209 0 : phasedFeedId = feedCols.phasedFeedId().getColumn();
3210 : }
3211 :
3212 13 : auto nRowsPerSpw = feedCols.spectralWindowId().nrow();
3213 13 : auto rowIndex = nRowsPerSpw;
3214 59 : for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
3215 : {
3216 : // Add rows
3217 46 : feedtable.addRow(nRowsPerSpw);
3218 :
3219 : // Prepare row reference object
3220 46 : RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
3221 :
3222 : // Reindex SPW col
3223 46 : spectralWindowId = spw_i;
3224 46 : feedCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
3225 :
3226 : // Columns that can be just copied
3227 46 : feedCols.position().putColumnCells(refRow,position);
3228 46 : feedCols.beamOffset().putColumnCells(refRow,beamOffset);
3229 46 : feedCols.polarizationType().putColumnCells(refRow,polarizationType);
3230 46 : feedCols.polResponse().putColumnCells(refRow,polResponse);
3231 46 : feedCols.receptorAngle().putColumnCells(refRow,receptorAngle);
3232 46 : feedCols.antennaId().putColumnCells(refRow,antennaId);
3233 46 : feedCols.beamId().putColumnCells(refRow,beamId);
3234 46 : feedCols.feedId().putColumnCells(refRow,feedId);
3235 46 : feedCols.interval().putColumnCells(refRow,interval);
3236 46 : feedCols.numReceptors().putColumnCells(refRow,numReceptors);
3237 46 : feedCols.time().putColumnCells(refRow,time);
3238 :
3239 : // Optional columns
3240 46 : if (MSTransformDataHandler::columnOk(feedCols.focusLength()))
3241 : {
3242 0 : feedCols.focusLength().putColumnCells(refRow,focusLength);
3243 : }
3244 :
3245 46 : if (MSTransformDataHandler::columnOk(feedCols.phasedFeedId()))
3246 : {
3247 0 : feedCols.phasedFeedId().putColumnCells(refRow,phasedFeedId);
3248 : }
3249 :
3250 : // Increment row offset
3251 46 : rowIndex += nRowsPerSpw;
3252 46 : }
3253 :
3254 13 : }
3255 : else
3256 : {
3257 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
3258 0 : << "FEED sub-table found but has no valid content" << LogIO::POST;
3259 : }
3260 13 : }
3261 : else
3262 : {
3263 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
3264 0 : << "FEED sub-table not found " << LogIO::POST;
3265 : }
3266 :
3267 13 : return;
3268 : }
3269 :
3270 : // -----------------------------------------------------------------------
3271 : //
3272 : // -----------------------------------------------------------------------
3273 13 : void MSTransformManager::separateSourceSubtable()
3274 : {
3275 13 : if (Table::isReadable(outputMs_p->sourceTableName()) and !outputMs_p->source().isNull())
3276 : {
3277 : // Access Source sub-table
3278 13 : MSSource sourcetable = outputMs_p->source();
3279 :
3280 13 : if (sourcetable.nrow() > 0)
3281 : {
3282 26 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
3283 26 : << " Multiplexing SOURCE sub-table to take into account new SPWs " << LogIO::POST;
3284 :
3285 13 : MSSourceColumns sourceCols(sourcetable);
3286 :
3287 : // Get original content from columns
3288 13 : Array<Double> direction = sourceCols.direction().getColumn();
3289 13 : Array<Double> properMotion = sourceCols.properMotion().getColumn();
3290 13 : Array<Int> calibrationGroup = sourceCols.calibrationGroup().getColumn();
3291 13 : Array<String> code = sourceCols.code().getColumn();
3292 13 : Array<Double> interval = sourceCols.interval().getColumn();
3293 13 : Array<String> name = sourceCols.name().getColumn();
3294 13 : Array<Int> numLines = sourceCols.numLines().getColumn();
3295 13 : Array<Int> sourceId = sourceCols.sourceId().getColumn();
3296 13 : Array<Int> spectralWindowId = sourceCols.spectralWindowId().getColumn();
3297 13 : Array<Double> time = sourceCols.time().getColumn();
3298 :
3299 : // Optional columns
3300 13 : Array<Double> position;
3301 13 : if (MSTransformDataHandler::columnOk(sourceCols.position()))
3302 : {
3303 0 : position = sourceCols.position().getColumn();
3304 : }
3305 :
3306 13 : Array<String> transition;
3307 13 : if (MSTransformDataHandler::columnOk(sourceCols.transition()))
3308 : {
3309 1 : transition = sourceCols.transition().getColumn();
3310 : }
3311 :
3312 13 : Array<Double> restFrequency;
3313 13 : if (MSTransformDataHandler::columnOk(sourceCols.restFrequency()))
3314 : {
3315 1 : restFrequency = sourceCols.restFrequency().getColumn();
3316 : }
3317 :
3318 13 : Array<Double> sysvel;
3319 13 : if (MSTransformDataHandler::columnOk(sourceCols.sysvel()))
3320 : {
3321 1 : sysvel = sourceCols.sysvel().getColumn();
3322 : }
3323 :
3324 13 : Array<Int> pulsarId;
3325 13 : if (MSTransformDataHandler::columnOk(sourceCols.pulsarId()))
3326 : {
3327 0 : pulsarId = sourceCols.pulsarId().getColumn();
3328 : }
3329 :
3330 13 : Array<TableRecord> sourceModel;
3331 13 : if (MSTransformDataHandler::columnOk(sourceCols.sourceModel()))
3332 : {
3333 0 : sourceModel = sourceCols.sourceModel().getColumn();
3334 : }
3335 :
3336 :
3337 13 : auto nRowsPerSpw = sourceCols.spectralWindowId().nrow();
3338 13 : auto rowIndex = nRowsPerSpw;
3339 59 : for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
3340 : {
3341 : // Add rows
3342 46 : sourcetable.addRow(nRowsPerSpw);
3343 :
3344 : // Prepare row reference object
3345 46 : RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
3346 :
3347 : // Re-index SPW col
3348 46 : spectralWindowId = spw_i;
3349 46 : sourceCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
3350 :
3351 : // Columns that can be just copied
3352 46 : sourceCols.direction().putColumnCells(refRow,direction);
3353 46 : sourceCols.properMotion().putColumnCells(refRow,properMotion);
3354 46 : sourceCols.calibrationGroup().putColumnCells(refRow,calibrationGroup);
3355 46 : sourceCols.code().putColumnCells(refRow,code);
3356 46 : sourceCols.interval().putColumnCells(refRow,interval);
3357 46 : sourceCols.name().putColumnCells(refRow,name);
3358 46 : sourceCols.numLines().putColumnCells(refRow,numLines);
3359 46 : sourceCols.sourceId().putColumnCells(refRow,sourceId);
3360 46 : sourceCols.time().putColumnCells(refRow,time);
3361 :
3362 : // Optional columns
3363 46 : if (MSTransformDataHandler::columnOk(sourceCols.position()))
3364 : {
3365 0 : sourceCols.position().putColumnCells(refRow,position);
3366 : }
3367 :
3368 46 : if (MSTransformDataHandler::columnOk(sourceCols.transition()))
3369 : {
3370 3 : sourceCols.transition().putColumnCells(refRow,transition);
3371 : }
3372 :
3373 46 : if (MSTransformDataHandler::columnOk(sourceCols.restFrequency()))
3374 : {
3375 3 : sourceCols.restFrequency().putColumnCells(refRow,restFrequency);
3376 : }
3377 :
3378 46 : if (MSTransformDataHandler::columnOk(sourceCols.sysvel()))
3379 : {
3380 3 : sourceCols.sysvel().putColumnCells(refRow,sysvel);
3381 : }
3382 :
3383 46 : if (MSTransformDataHandler::columnOk(sourceCols.pulsarId()))
3384 : {
3385 0 : sourceCols.pulsarId().putColumnCells(refRow,pulsarId);
3386 : }
3387 :
3388 46 : if (MSTransformDataHandler::columnOk(sourceCols.sourceModel()))
3389 : {
3390 0 : sourceCols.sourceModel().putColumnCells(refRow,sourceModel);
3391 : }
3392 :
3393 : // Increment row offset
3394 46 : rowIndex += nRowsPerSpw;
3395 46 : }
3396 :
3397 13 : }
3398 : else
3399 : {
3400 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
3401 0 : << "SOURCE sub-table found but has no valid content" << LogIO::POST;
3402 : }
3403 13 : }
3404 : else
3405 : {
3406 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
3407 0 : << "SOURCE sub-table not found " << LogIO::POST;
3408 : }
3409 :
3410 13 : return;
3411 : }
3412 :
3413 : // -----------------------------------------------------------------------
3414 : //
3415 : // -----------------------------------------------------------------------
3416 13 : void MSTransformManager::separateSyscalSubtable()
3417 : {
3418 :
3419 13 : if (Table::isReadable(outputMs_p->sysCalTableName()) and !outputMs_p->sysCal().isNull())
3420 : {
3421 : // Access SysCal sub-table
3422 1 : MSSysCal syscalTable = outputMs_p->sysCal();
3423 :
3424 1 : if (syscalTable.nrow() > 0)
3425 : {
3426 2 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
3427 2 : << " Multiplexing SYSCAL sub-table to take into account new SPWs " << LogIO::POST;
3428 :
3429 1 : MSSysCalColumns syscalCols(syscalTable);
3430 :
3431 : // Get original content from columns
3432 1 : Array<Int> antennaId = syscalCols.antennaId().getColumn();
3433 1 : Array<Int> feedId = syscalCols.feedId().getColumn();
3434 1 : Array<Double> interval = syscalCols.interval().getColumn();
3435 1 : Array<Int> spectralWindowId = syscalCols.spectralWindowId().getColumn();
3436 1 : Array<Double> time = syscalCols.time().getColumn();
3437 :
3438 : // Optional columns
3439 1 : Array<Float> phaseDiff;
3440 1 : if (MSTransformDataHandler::columnOk(syscalCols.phaseDiff()))
3441 : {
3442 0 : phaseDiff = syscalCols.phaseDiff().getColumn();
3443 : }
3444 :
3445 1 : Array<bool> phaseDiffFlag;
3446 1 : if (MSTransformDataHandler::columnOk(syscalCols.phaseDiffFlag()))
3447 : {
3448 0 : phaseDiffFlag = syscalCols.phaseDiffFlag().getColumn();
3449 : }
3450 :
3451 1 : Array<Float> tant;
3452 1 : if (MSTransformDataHandler::columnOk(syscalCols.tant()))
3453 : {
3454 0 : tant = syscalCols.tant().getColumn();
3455 : }
3456 :
3457 1 : Array<bool> tantFlag;
3458 1 : if (MSTransformDataHandler::columnOk(syscalCols.tantFlag()))
3459 : {
3460 1 : tantFlag = syscalCols.tantFlag().getColumn();
3461 : }
3462 :
3463 1 : Array<Float> tantSpectrum;
3464 1 : if (MSTransformDataHandler::columnOk(syscalCols.tantSpectrum()))
3465 : {
3466 0 : tantSpectrum = syscalCols.tantSpectrum().getColumn();
3467 : }
3468 :
3469 1 : Array<Float> tantTsys;
3470 1 : if (MSTransformDataHandler::columnOk(syscalCols.tantTsys()))
3471 : {
3472 0 : tantTsys = syscalCols.tantTsys().getColumn();
3473 : }
3474 :
3475 1 : Array<bool> tantTsysFlag;
3476 1 : if (MSTransformDataHandler::columnOk(syscalCols.tantTsysFlag()))
3477 : {
3478 1 : tantTsysFlag = syscalCols.tantTsysFlag().getColumn();
3479 : }
3480 :
3481 1 : Array<Float> tantTsysSpectrum;
3482 1 : if (MSTransformDataHandler::columnOk(syscalCols.tantTsysSpectrum()))
3483 : {
3484 0 : tantTsysSpectrum = syscalCols.tantTsysSpectrum().getColumn();
3485 : }
3486 :
3487 1 : Array<Float> tcal;
3488 1 : if (MSTransformDataHandler::columnOk(syscalCols.tcal()))
3489 : {
3490 0 : tcal = syscalCols.tcal().getColumn();
3491 : }
3492 :
3493 1 : Array<bool> tcalFlag;
3494 1 : if (MSTransformDataHandler::columnOk(syscalCols.tcalFlag()))
3495 : {
3496 1 : tcalFlag = syscalCols.tcalFlag().getColumn();
3497 : }
3498 :
3499 1 : Array<Float> tcalSpectrum;
3500 1 : if (MSTransformDataHandler::columnOk(syscalCols.tcalSpectrum()))
3501 : {
3502 1 : tcalSpectrum = syscalCols.tcalSpectrum().getColumn();
3503 : }
3504 :
3505 1 : Array<Float> trx;
3506 1 : if (MSTransformDataHandler::columnOk(syscalCols.trx()))
3507 : {
3508 0 : trx = syscalCols.trx().getColumn();
3509 : }
3510 :
3511 1 : Array<bool> trxFlag;
3512 1 : if (MSTransformDataHandler::columnOk(syscalCols.trxFlag()))
3513 : {
3514 1 : trxFlag = syscalCols.trxFlag().getColumn();
3515 : }
3516 :
3517 1 : Array<Float> trxSpectrum;
3518 1 : if (MSTransformDataHandler::columnOk(syscalCols.trxSpectrum()))
3519 : {
3520 1 : trxSpectrum = syscalCols.trxSpectrum().getColumn();
3521 : }
3522 :
3523 1 : Array<Float> tsky;
3524 1 : if (MSTransformDataHandler::columnOk(syscalCols.tsky()))
3525 : {
3526 0 : tsky = syscalCols.tsky().getColumn();
3527 : }
3528 :
3529 1 : Array<bool> tskyFlag;
3530 1 : if (MSTransformDataHandler::columnOk(syscalCols.tskyFlag()))
3531 : {
3532 1 : tskyFlag = syscalCols.tskyFlag().getColumn();
3533 : }
3534 :
3535 1 : Array<Float> tskySpectrum;
3536 1 : if (MSTransformDataHandler::columnOk(syscalCols.tskySpectrum()))
3537 : {
3538 1 : tskySpectrum = syscalCols.tskySpectrum().getColumn();
3539 : }
3540 :
3541 1 : Array<Float> tsys;
3542 1 : if (MSTransformDataHandler::columnOk(syscalCols.tsys()))
3543 : {
3544 0 : tsys = syscalCols.tsys().getColumn();
3545 : }
3546 :
3547 1 : Array<bool> tsysFlag;
3548 1 : if (MSTransformDataHandler::columnOk(syscalCols.tsysFlag()))
3549 : {
3550 1 : tsysFlag = syscalCols.tsysFlag().getColumn();
3551 : }
3552 :
3553 1 : Array<Float> tsysSpectrum;
3554 1 : if (MSTransformDataHandler::columnOk(syscalCols.tsysSpectrum()))
3555 : {
3556 1 : tsysSpectrum = syscalCols.tsysSpectrum().getColumn();
3557 : }
3558 :
3559 :
3560 1 : auto nRowsPerSpw = syscalCols.spectralWindowId().nrow();
3561 1 : auto rowIndex = nRowsPerSpw;
3562 4 : for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
3563 : {
3564 : // Add rows
3565 3 : syscalTable.addRow(nRowsPerSpw);
3566 :
3567 : // Prepare row reference object
3568 3 : RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
3569 :
3570 : // Re-index SPW col
3571 3 : spectralWindowId = spw_i;
3572 3 : syscalCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
3573 :
3574 : // Columns that can be just copied
3575 3 : syscalCols.antennaId().putColumnCells(refRow,antennaId);
3576 3 : syscalCols.feedId().putColumnCells(refRow,feedId);
3577 3 : syscalCols.interval().putColumnCells(refRow,interval);
3578 3 : syscalCols.time().putColumnCells(refRow,time);
3579 :
3580 : // Optional columns
3581 3 : if (MSTransformDataHandler::columnOk(syscalCols.phaseDiff()))
3582 : {
3583 0 : syscalCols.phaseDiff().putColumnCells(refRow,phaseDiff);
3584 : }
3585 :
3586 3 : if (MSTransformDataHandler::columnOk(syscalCols.phaseDiffFlag()))
3587 : {
3588 0 : syscalCols.phaseDiffFlag().putColumnCells(refRow,phaseDiffFlag);
3589 : }
3590 :
3591 3 : if (MSTransformDataHandler::columnOk(syscalCols.tant()))
3592 : {
3593 0 : syscalCols.tant().putColumnCells(refRow,tant);
3594 : }
3595 :
3596 3 : if (MSTransformDataHandler::columnOk(syscalCols.tantFlag()))
3597 : {
3598 3 : syscalCols.tantFlag().putColumnCells(refRow,tantFlag);
3599 : }
3600 :
3601 3 : if (MSTransformDataHandler::columnOk(syscalCols.tantSpectrum()))
3602 : {
3603 0 : syscalCols.tantSpectrum().putColumnCells(refRow,tantSpectrum);
3604 : }
3605 :
3606 3 : if (MSTransformDataHandler::columnOk(syscalCols.tantTsys()))
3607 : {
3608 0 : syscalCols.tantTsys().putColumnCells(refRow,tantTsys);
3609 : }
3610 :
3611 3 : if (MSTransformDataHandler::columnOk(syscalCols.tantTsysFlag()))
3612 : {
3613 3 : syscalCols.tantTsysFlag().putColumnCells(refRow,tantTsysFlag);
3614 : }
3615 :
3616 3 : if (MSTransformDataHandler::columnOk(syscalCols.tantTsysSpectrum()))
3617 : {
3618 0 : syscalCols.tantTsysSpectrum().putColumnCells(refRow,tantTsysSpectrum);
3619 : }
3620 :
3621 3 : if (MSTransformDataHandler::columnOk(syscalCols.tcal()))
3622 : {
3623 0 : syscalCols.tcal().putColumnCells(refRow,tcal);
3624 : }
3625 :
3626 3 : if (MSTransformDataHandler::columnOk(syscalCols.tcalFlag()))
3627 : {
3628 3 : syscalCols.tcalFlag().putColumnCells(refRow,tcalFlag);
3629 : }
3630 :
3631 3 : if (MSTransformDataHandler::columnOk(syscalCols.tcalSpectrum()))
3632 : {
3633 3 : syscalCols.tcalSpectrum().putColumnCells(refRow,tcalSpectrum);
3634 : }
3635 :
3636 3 : if (MSTransformDataHandler::columnOk(syscalCols.trx()))
3637 : {
3638 0 : syscalCols.trx().putColumnCells(refRow,trx);
3639 : }
3640 :
3641 3 : if (MSTransformDataHandler::columnOk(syscalCols.trxFlag()))
3642 : {
3643 3 : syscalCols.trxFlag().putColumnCells(refRow,trxFlag);
3644 : }
3645 :
3646 3 : if (MSTransformDataHandler::columnOk(syscalCols.trxSpectrum()))
3647 : {
3648 3 : syscalCols.trxSpectrum().putColumnCells(refRow,trxSpectrum);
3649 : }
3650 :
3651 3 : if (MSTransformDataHandler::columnOk(syscalCols.tsky()))
3652 : {
3653 0 : syscalCols.tsky().putColumnCells(refRow,tsky);
3654 : }
3655 :
3656 3 : if (MSTransformDataHandler::columnOk(syscalCols.tskyFlag()))
3657 : {
3658 3 : syscalCols.tskyFlag().putColumnCells(refRow,tskyFlag);
3659 : }
3660 :
3661 3 : if (MSTransformDataHandler::columnOk(syscalCols.tskySpectrum()))
3662 : {
3663 3 : syscalCols.tskySpectrum().putColumnCells(refRow,tskySpectrum);
3664 : }
3665 :
3666 3 : if (MSTransformDataHandler::columnOk(syscalCols.tsys()))
3667 : {
3668 0 : syscalCols.tsys().putColumnCells(refRow,tsys);
3669 : }
3670 :
3671 3 : if (MSTransformDataHandler::columnOk(syscalCols.tsysFlag()))
3672 : {
3673 3 : syscalCols.tsysFlag().putColumnCells(refRow,tsysFlag);
3674 : }
3675 :
3676 3 : if (MSTransformDataHandler::columnOk(syscalCols.tsysSpectrum()))
3677 : {
3678 3 : syscalCols.tsysSpectrum().putColumnCells(refRow,tsysSpectrum);
3679 : }
3680 :
3681 : // Increment row offset
3682 3 : rowIndex += nRowsPerSpw;
3683 3 : }
3684 :
3685 1 : }
3686 : else
3687 : {
3688 0 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
3689 0 : << "SYSCAL sub-table found but has no valid content" << LogIO::POST;
3690 : }
3691 1 : }
3692 : else
3693 : {
3694 24 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
3695 24 : << "SYSCAL sub-table not found " << LogIO::POST;
3696 : }
3697 :
3698 13 : return;
3699 : }
3700 :
3701 : // -----------------------------------------------------------------------
3702 : //
3703 : // -----------------------------------------------------------------------
3704 13 : void MSTransformManager::separateFreqOffsetSubtable()
3705 : {
3706 :
3707 13 : if (Table::isReadable(outputMs_p->freqOffsetTableName()) and !outputMs_p->freqOffset().isNull())
3708 : {
3709 : // Access SysCal sub-table
3710 0 : MSFreqOffset freqoffsetTable = outputMs_p->freqOffset();
3711 :
3712 0 : if (freqoffsetTable.nrow() > 0)
3713 : {
3714 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
3715 0 : << " Multiplexing FREQ_OFFSET sub-table to take into account new SPWs " << LogIO::POST;
3716 :
3717 0 : MSFreqOffsetColumns freqoffsetCols(freqoffsetTable);
3718 :
3719 : // Get original content from columns
3720 0 : Array<Int> antenna1 = freqoffsetCols.antenna1().getColumn();
3721 0 : Array<Int> antenna2 = freqoffsetCols.antenna2().getColumn();
3722 0 : Array<Int> feedId = freqoffsetCols.feedId().getColumn();
3723 0 : Array<Double> interval = freqoffsetCols.interval().getColumn();
3724 0 : Array<Double> offset = freqoffsetCols.offset().getColumn();
3725 0 : Array<Int> spectralWindowId = freqoffsetCols.spectralWindowId().getColumn();
3726 0 : Array<Double> time = freqoffsetCols.time().getColumn();
3727 :
3728 : // NOTE (jagonzal): FreqOffset does not have optional columns
3729 :
3730 0 : auto nRowsPerSpw = freqoffsetCols.spectralWindowId().nrow();
3731 0 : auto rowIndex = nRowsPerSpw;
3732 0 : for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
3733 : {
3734 : // Add rows
3735 0 : freqoffsetTable.addRow(nRowsPerSpw);
3736 :
3737 : // Prepare row reference object
3738 0 : RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
3739 :
3740 : // Re-index SPW col
3741 0 : spectralWindowId = spw_i;
3742 0 : freqoffsetCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
3743 :
3744 : // Columns that can be just copied
3745 0 : freqoffsetCols.antenna1().putColumnCells(refRow,antenna1);
3746 0 : freqoffsetCols.antenna2().putColumnCells(refRow,antenna2);
3747 0 : freqoffsetCols.feedId().putColumnCells(refRow,feedId);
3748 0 : freqoffsetCols.interval().putColumnCells(refRow,interval);
3749 0 : freqoffsetCols.offset().putColumnCells(refRow,offset);
3750 0 : freqoffsetCols.time().putColumnCells(refRow,time);
3751 :
3752 : // Increment row offset
3753 0 : rowIndex += nRowsPerSpw;
3754 0 : }
3755 :
3756 0 : }
3757 : else
3758 : {
3759 0 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
3760 0 : << "FREQ_OFFSET sub-table found but has no valid content" << LogIO::POST;
3761 : }
3762 0 : }
3763 : else
3764 : {
3765 26 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
3766 26 : << "FREQ_OFFSET sub-table not found " << LogIO::POST;
3767 : }
3768 :
3769 13 : return;
3770 : }
3771 :
3772 : // -----------------------------------------------------------------------
3773 : //
3774 : // -----------------------------------------------------------------------
3775 13 : void MSTransformManager::separateCalDeviceSubtable()
3776 : {
3777 13 : if (Table::isReadable(outputMs_p->tableName() + "/CALDEVICE"))
3778 : {
3779 2 : Table subtable(outputMs_p->tableName() + "/CALDEVICE", Table::Update);
3780 :
3781 2 : if (subtable.nrow() > 0)
3782 : {
3783 4 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
3784 4 : << " Multiplexing CALDEVICE sub-table to take into account new SPWs " << LogIO::POST;
3785 :
3786 : // Get RW access to columns
3787 2 : ScalarColumn<Int> antennaIdCol(subtable, "ANTENNA_ID");
3788 2 : ScalarColumn<Int> feedIdCol(subtable, "FEED_ID");
3789 2 : ScalarColumn<Int> spectralWindowIdCol(subtable, "SPECTRAL_WINDOW_ID");
3790 2 : ScalarColumn<Double> timeCol(subtable, "TIME");
3791 2 : ScalarColumn<Double> intervalCol(subtable, "INTERVAL");
3792 2 : ScalarColumn<Int> numCalLoadCol(subtable, "NUM_CAL_LOAD");
3793 2 : ArrayColumn<String> calLoadNamesCol(subtable, "CAL_LOAD_NAMES");
3794 2 : ScalarColumn<Int> numReceptorCol(subtable, "NUM_RECEPTOR");
3795 2 : ArrayColumn<Float> noiseCalCol(subtable, "NOISE_CAL");
3796 2 : ArrayColumn<Float> calEffCol(subtable, "CAL_EFF");
3797 2 : ArrayColumn<Double> temperatureLoadCol(subtable, "TEMPERATURE_LOAD");
3798 :
3799 : // Get original content of columns
3800 2 : Array<Int> antennaId;
3801 2 : if (MSTransformDataHandler::columnOk(antennaIdCol))
3802 2 : antennaId = antennaIdCol.getColumn();
3803 2 : Array<Int> feedId;
3804 2 : if (MSTransformDataHandler::columnOk(feedIdCol))
3805 2 : feedId = feedIdCol.getColumn();
3806 2 : Array<Int> spectralWindowId;
3807 2 : if (MSTransformDataHandler::columnOk(spectralWindowIdCol))
3808 2 : spectralWindowId = spectralWindowIdCol.getColumn();
3809 2 : Array<Double> time;
3810 2 : if (MSTransformDataHandler::columnOk(timeCol))
3811 2 : time = timeCol.getColumn();
3812 2 : Array<Double> interval;
3813 2 : if (MSTransformDataHandler::columnOk(intervalCol))
3814 2 : interval = intervalCol.getColumn();
3815 :
3816 2 : Array<Int> numCalLoad;
3817 2 : if (MSTransformDataHandler::columnOk(numCalLoadCol))
3818 2 : numCalLoad = numCalLoadCol.getColumn();
3819 2 : Array<String> calLoadNames;
3820 2 : if (MSTransformDataHandler::columnOk(calLoadNamesCol))
3821 2 : calLoadNames = calLoadNamesCol.getColumn();
3822 2 : Array<Int> numReceptor;
3823 2 : if (MSTransformDataHandler::columnOk(numReceptorCol))
3824 2 : numReceptor = numReceptorCol.getColumn();
3825 2 : Array<Float> noiseCal;
3826 2 : if (MSTransformDataHandler::columnOk(noiseCalCol))
3827 1 : noiseCal = noiseCalCol.getColumn();
3828 2 : Array<Float> calEff;
3829 2 : if (MSTransformDataHandler::columnOk(calEffCol))
3830 0 : calEff = calEffCol.getColumn();
3831 2 : Array<Double> temperatureLoad;
3832 2 : if (MSTransformDataHandler::columnOk(temperatureLoadCol))
3833 1 : temperatureLoad = temperatureLoadCol.getColumn();
3834 :
3835 :
3836 2 : uInt nRowsPerSpw = spectralWindowId.nelements();
3837 2 : uInt rowIndex = nRowsPerSpw;
3838 6 : for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
3839 : {
3840 : // Add rows
3841 4 : subtable.addRow(nRowsPerSpw);
3842 :
3843 : // Prepare row reference object
3844 4 : RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
3845 :
3846 : // Re-index SPW col
3847 4 : spectralWindowId = spw_i;
3848 4 : spectralWindowIdCol.putColumnCells(refRow,spectralWindowId);
3849 :
3850 : // Columns that can be just copied
3851 4 : if (MSTransformDataHandler::columnOk(antennaIdCol))
3852 4 : antennaIdCol.putColumnCells(refRow,antennaId);
3853 4 : if (MSTransformDataHandler::columnOk(feedIdCol))
3854 4 : feedIdCol.putColumnCells(refRow,feedId);
3855 4 : if (MSTransformDataHandler::columnOk(timeCol))
3856 4 : timeCol.putColumnCells(refRow,time);
3857 4 : if (MSTransformDataHandler::columnOk(intervalCol))
3858 4 : intervalCol.putColumnCells(refRow,interval);
3859 :
3860 4 : if (MSTransformDataHandler::columnOk(numCalLoadCol))
3861 4 : numCalLoadCol.putColumnCells(refRow,numCalLoad);
3862 4 : if (MSTransformDataHandler::columnOk(calLoadNamesCol))
3863 4 : calLoadNamesCol.putColumnCells(refRow,calLoadNames);
3864 4 : if (MSTransformDataHandler::columnOk(numReceptorCol))
3865 4 : numReceptorCol.putColumnCells(refRow,numReceptor);
3866 4 : if (MSTransformDataHandler::columnOk(noiseCalCol))
3867 1 : noiseCalCol.putColumnCells(refRow,noiseCal);
3868 4 : if (MSTransformDataHandler::columnOk(calEffCol))
3869 0 : calEffCol.putColumnCells(refRow,calEff);
3870 4 : if (MSTransformDataHandler::columnOk(temperatureLoadCol))
3871 3 : temperatureLoadCol.putColumnCells(refRow,temperatureLoad);
3872 :
3873 : // Increment row offset
3874 4 : rowIndex += nRowsPerSpw;
3875 4 : }
3876 :
3877 2 : }
3878 : else
3879 : {
3880 0 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
3881 0 : << "CALDEVICE sub-table found but has no valid content" << LogIO::POST;
3882 : }
3883 2 : }
3884 : else
3885 : {
3886 22 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
3887 22 : << "CALDEVICE sub-table not found." << LogIO::POST;
3888 : }
3889 :
3890 13 : return;
3891 : }
3892 :
3893 : // -----------------------------------------------------------------------
3894 : //
3895 : // -----------------------------------------------------------------------
3896 13 : void MSTransformManager::separateSysPowerSubtable()
3897 : {
3898 13 : if (Table::isReadable(outputMs_p->tableName() + "/SYSPOWER"))
3899 : {
3900 2 : Table subtable(outputMs_p->tableName() + "/SYSPOWER", Table::Update);
3901 :
3902 2 : if (subtable.nrow() > 0)
3903 : {
3904 2 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
3905 2 : << " Multiplexing SYSPOWER sub-table to take into account new SPWs " << LogIO::POST;
3906 :
3907 : // Get RW access to columns
3908 1 : ScalarColumn<Int> antennaIdCol(subtable, "ANTENNA_ID");
3909 1 : ScalarColumn<Int> feedIdCol(subtable, "FEED_ID");
3910 1 : ScalarColumn<Int> spectralWindowIdCol(subtable, "SPECTRAL_WINDOW_ID");
3911 1 : ScalarColumn<Double> timeCol(subtable, "TIME");
3912 1 : ScalarColumn<Double> intervalCol(subtable, "INTERVAL");
3913 1 : ArrayColumn<Float> switchedDiffCol(subtable, "SWITCHED_DIFF");
3914 1 : ArrayColumn<Float> switchedSumCol(subtable, "SWITCHED_SUM");
3915 1 : ArrayColumn<Float> requantizerGainCol(subtable, "REQUANTIZER_GAIN");
3916 :
3917 : // Get original content of columns
3918 1 : Array<Int> antennaId;
3919 1 : if (MSTransformDataHandler::columnOk(antennaIdCol))
3920 1 : antennaId = antennaIdCol.getColumn();
3921 1 : Array<Int> feedId;
3922 1 : if (MSTransformDataHandler::columnOk(feedIdCol))
3923 1 : feedId = feedIdCol.getColumn();
3924 1 : Array<Int> spectralWindowId;
3925 1 : if (MSTransformDataHandler::columnOk(spectralWindowIdCol))
3926 1 : spectralWindowId = spectralWindowIdCol.getColumn();
3927 1 : Array<Double> time;
3928 1 : if (MSTransformDataHandler::columnOk(timeCol))
3929 1 : time = timeCol.getColumn();
3930 1 : Array<Double> interval;
3931 1 : if (MSTransformDataHandler::columnOk(intervalCol))
3932 1 : interval = intervalCol.getColumn();
3933 :
3934 1 : Array<Float> switchedDiff;
3935 1 : if (MSTransformDataHandler::columnOk(switchedDiffCol))
3936 1 : switchedDiff = switchedDiffCol.getColumn();
3937 1 : Array<Float> switchedSum;
3938 1 : if (MSTransformDataHandler::columnOk(switchedSumCol))
3939 1 : switchedSum = switchedSumCol.getColumn();
3940 1 : Array<Float> requantizerGain;
3941 1 : if (MSTransformDataHandler::columnOk(requantizerGainCol))
3942 1 : requantizerGain = requantizerGainCol.getColumn();
3943 :
3944 1 : auto nRowsPerSpw = spectralWindowId.nelements();
3945 1 : auto rowIndex = nRowsPerSpw;
3946 2 : for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
3947 : {
3948 : // Add rows
3949 1 : subtable.addRow(nRowsPerSpw);
3950 :
3951 : // Prepare row reference object
3952 1 : RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
3953 :
3954 : // Re-index SPW col
3955 1 : spectralWindowId = spw_i;
3956 1 : spectralWindowIdCol.putColumnCells(refRow,spectralWindowId);
3957 :
3958 : // Columns that can be just copied
3959 1 : if (MSTransformDataHandler::columnOk(antennaIdCol))
3960 1 : antennaIdCol.putColumnCells(refRow,antennaId);
3961 1 : if (MSTransformDataHandler::columnOk(feedIdCol))
3962 1 : feedIdCol.putColumnCells(refRow,feedId);
3963 1 : if (MSTransformDataHandler::columnOk(timeCol))
3964 1 : timeCol.putColumnCells(refRow,time);
3965 1 : if (MSTransformDataHandler::columnOk(intervalCol))
3966 1 : intervalCol.putColumnCells(refRow,interval);
3967 :
3968 1 : if (MSTransformDataHandler::columnOk(switchedDiffCol))
3969 1 : switchedDiffCol.putColumnCells(refRow,switchedDiff);
3970 1 : if (MSTransformDataHandler::columnOk(switchedSumCol))
3971 1 : switchedSumCol.putColumnCells(refRow,switchedSum);
3972 1 : if (MSTransformDataHandler::columnOk(requantizerGainCol))
3973 1 : requantizerGainCol.putColumnCells(refRow,requantizerGain);
3974 :
3975 : // Increment row offset
3976 1 : rowIndex += nRowsPerSpw;
3977 1 : }
3978 :
3979 1 : }
3980 : else
3981 : {
3982 2 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
3983 2 : << "SYSPOWER sub-table found but has no valid content" << LogIO::POST;
3984 : }
3985 2 : }
3986 : else
3987 : {
3988 22 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
3989 22 : << "SYSPOWER sub-table not found." << LogIO::POST;
3990 : }
3991 :
3992 13 : return;
3993 : }
3994 :
3995 : // -----------------------------------------------------------------------
3996 : // Return polarization id corresponding to polarization averaged data (Stokes I)
3997 : // Append Polarization row if necessary
3998 : // -----------------------------------------------------------------------
3999 6 : Int MSTransformManager::getAveragedPolarizationId() {
4000 6 : logger_p << LogOrigin("MSTransformManager", __func__, WHERE);
4001 6 : MSPolarizationColumns cols(outputMs_p->polarization());
4002 6 : Int polId = -1;
4003 6 : auto nrow = cols.nrow();
4004 14 : for (rownr_t i = 0; i < nrow; ++i) {
4005 8 : auto const numCorr = cols.numCorr()(i);
4006 8 : auto const flagRow = cols.flagRow()(i);
4007 8 : if (numCorr == 1 && flagRow == False) {
4008 2 : Vector<Int> const corrType = cols.corrType()(i);
4009 2 : Int const corrType0 = corrType[0];
4010 2 : if (Stokes::type(corrType0) == Stokes::I) {
4011 0 : logger_p << "Matched " << i << LogIO::POST;
4012 0 : polId = i;
4013 0 : break;
4014 : }
4015 2 : }
4016 : }
4017 :
4018 6 : if (polId < 0) {
4019 : // add new row to PolarizationTable
4020 6 : outputMs_p->polarization().addRow(1, False);
4021 6 : polId = nrow;
4022 6 : Matrix<Int> corrProduct(2, 1, 0);
4023 6 : cols.corrProduct().put(polId, corrProduct);
4024 6 : Vector<Int> corrType(1, Stokes::I);
4025 6 : cols.corrType().put(polId, corrType);
4026 6 : cols.flagRow().put(polId, False);
4027 6 : cols.numCorr().put(polId, 1);
4028 6 : }
4029 :
4030 6 : return polId;
4031 6 : }
4032 :
4033 : // -----------------------------------------------------------------------
4034 : // Re-index POLARIZATION_ID's in DATA_DESCRIPTION table
4035 : // -----------------------------------------------------------------------
4036 6 : void MSTransformManager::reindexPolarizationIdInDataDesc(Int newPolarizationId) {
4037 6 : logger_p << LogOrigin("MSTransformManager", __func__, WHERE);
4038 6 : logger_p << "new polid is " << newPolarizationId << LogIO::POST;
4039 6 : MSDataDescColumns ddcols(outputMs_p->dataDescription());
4040 6 : MSPolarizationColumns pcols(outputMs_p->polarization());
4041 6 : rownr_t nrow = ddcols.nrow();
4042 36 : auto __isValidType = [&](Vector<Int> const &ctype) {
4043 68 : return (anyEQ(ctype, (Int)Stokes::XX) && anyEQ(ctype, (Int)Stokes::YY))
4044 68 : || (anyEQ(ctype, (Int)Stokes::RR) && anyEQ(ctype, (Int)Stokes::LL));
4045 : };
4046 44 : for (rownr_t i = 0; i < nrow; ++i) {
4047 38 : Int const polarizationId = ddcols.polarizationId()(i);
4048 38 : Int nCorr = pcols.numCorr()(polarizationId);
4049 38 : Vector<Int> corrType = pcols.corrType()(polarizationId);
4050 38 : bool flagRow = pcols.flagRow()(polarizationId);
4051 38 : bool needReindex = (polarizationId != newPolarizationId) &&
4052 76 : (nCorr > 1) && (flagRow == False) && __isValidType(corrType);
4053 38 : if (needReindex) {
4054 36 : logger_p << "ddid " << i << " polid " << polarizationId << " needs reindex" << LogIO::POST;
4055 36 : ddcols.polarizationId().put(i, newPolarizationId);
4056 : }
4057 38 : }
4058 6 : }
4059 :
4060 :
4061 : // -----------------------------------------------------------------------
4062 : //
4063 : // -----------------------------------------------------------------------
4064 190 : void MSTransformManager::checkAndPreaverageChannelsIfNeeded(Int spwId,
4065 : Vector<Double> &inputCHAN_FREQ,
4066 : Vector<Double> &inputCHAN_WIDTH,
4067 :
4068 : const Vector<Double> &originalCHAN_FREQ,
4069 : const Vector<Double> &originalCHAN_WIDTH,
4070 : const Vector<Double> ®riddedCHAN_FREQ,
4071 : const Vector<Double> ®riddedCHAN_WIDTH
4072 : ) {
4073 : // Check if pre-averaging step is necessary
4074 190 : if (freqbinMap_p.find(spwId) == freqbinMap_p.end()) {
4075 : Double weightScaleDummy;
4076 188 : Vector<Double> tmpCHAN_FREQ;
4077 188 : Vector<Double> tmpCHAN_WIDTH;
4078 376 : MSTransformRegridder::calcChanFreqs(logger_p, tmpCHAN_FREQ, tmpCHAN_WIDTH,
4079 : weightScaleDummy, originalCHAN_FREQ,
4080 188 : originalCHAN_WIDTH, phaseCenter_p,
4081 : inputReferenceFrame_p,
4082 188 : referenceTime_p,
4083 188 : observatoryPosition_p,
4084 376 : String("channel"), -1,
4085 376 : String("0"), String("1"),
4086 188 : restFrequency_p,
4087 188 : outputReferenceFramePar_p,
4088 188 : velocityType_p, false // verbose
4089 : );
4090 :
4091 188 : Double avgCombinedWidth = 0;
4092 119801 : for (uInt chanIdx = 0; chanIdx < tmpCHAN_WIDTH.size(); ++chanIdx) {
4093 119613 : avgCombinedWidth += tmpCHAN_WIDTH(chanIdx);
4094 : }
4095 188 : avgCombinedWidth /= tmpCHAN_WIDTH.size();
4096 :
4097 188 : Double avgRegriddedWidth = 0;
4098 50758 : for (uInt chanIdx=0;chanIdx<regriddedCHAN_WIDTH.size();chanIdx++) {
4099 50570 : avgRegriddedWidth += regriddedCHAN_WIDTH(chanIdx);
4100 : }
4101 188 : avgRegriddedWidth /= regriddedCHAN_WIDTH.size();
4102 :
4103 188 : Double widthFactor = fabs(avgRegriddedWidth/avgCombinedWidth);
4104 188 : uInt widthFactorInt = (uInt)floor(widthFactor + 0.001);
4105 :
4106 188 : if ((widthFactorInt >= 2) and 2*widthFactorInt <= originalCHAN_WIDTH.size()) {
4107 23 : if (!enableChanPreAverage_p) {
4108 46 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4109 : << "Ratio between input and output width is >=2: " << avgRegriddedWidth/avgCombinedWidth
4110 : << ", but not doing pre-channel average (it is disabled by "
4111 46 : << "default since CASA release 5.0)." << LogIO::POST;
4112 :
4113 46 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4114 : << "Regridding to intermediate grid ("
4115 : << originalCHAN_FREQ.size()
4116 : << " channels) for interpolation as in tclean when the "
4117 : << " ratio between the output and input widths is >2."
4118 46 : << LogIO::POST;
4119 :
4120 23 : initGridForRegridTClean(originalCHAN_FREQ, regriddedCHAN_FREQ,
4121 : regriddedCHAN_WIDTH, widthFactor);
4122 :
4123 : } else {
4124 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
4125 : << "mstransform with regridms does not regrid properly for channel widths "
4126 : "> or = 2 x the native channel width, when using channel pre-averaging. Please "
4127 : "use clean or tclean for larger regridding. "
4128 0 : << LogIO::POST;
4129 :
4130 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4131 : << "Ratio between input and output width is " << avgRegriddedWidth/avgCombinedWidth
4132 0 : << ", setting pre-channel average width to " << widthFactorInt << LogIO::POST;
4133 :
4134 0 : doPreAveragingBeforeRegridding(widthFactorInt, spwId,
4135 : originalCHAN_FREQ, originalCHAN_WIDTH,
4136 : inputCHAN_FREQ, inputCHAN_WIDTH);
4137 : }
4138 : }
4139 188 : }
4140 190 : }
4141 :
4142 : // -----------------------------------------------------------------------
4143 : //
4144 : // -----------------------------------------------------------------------
4145 0 : void MSTransformManager::doPreAveragingBeforeRegridding(uInt widthFactor, Int spwId,
4146 : const Vector<Double> &originalCHAN_FREQ,
4147 : const Vector<Double> &originalCHAN_WIDTH,
4148 : Vector<Double> &inputCHAN_FREQ,
4149 : Vector<Double> &inputCHAN_WIDTH) {
4150 0 : channelAverage_p = true;
4151 0 : freqbinMap_p[spwId] = widthFactor;
4152 0 : newWeightFactorMap_p[spwId] /= widthFactor; // jagonzal: Remove channel width contribution to the scale factor
4153 :
4154 : // Calculate averaged frequencies
4155 0 : calculateIntermediateFrequencies(spwId, originalCHAN_FREQ, originalCHAN_WIDTH,
4156 : inputCHAN_FREQ, inputCHAN_WIDTH);
4157 :
4158 0 : ostringstream oss;
4159 0 : oss << "Averaged SPW: " << std::setw(5) << inputCHAN_WIDTH.size()
4160 : << " channels, first channel = "
4161 0 : << std::setprecision(9) << std::setw(14) << std::scientific
4162 0 : << inputCHAN_FREQ(0) << " Hz"
4163 : << ", last channel = "
4164 0 : << std::setprecision(9) << std::setw(14) << std::scientific
4165 0 : << inputCHAN_FREQ(inputCHAN_WIDTH.size() -1) << " Hz";
4166 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4167 0 : << oss.str() << LogIO::POST;
4168 0 : }
4169 :
4170 : // -----------------------------------------------------------------------
4171 : //
4172 : // -----------------------------------------------------------------------
4173 2 : void MSTransformManager::calculateIntermediateFrequencies( Int spwId,
4174 : const Vector<Double> &inputChanFreq,
4175 : const Vector<Double> &inputChanWidth,
4176 : Vector<Double> &intermediateChanFreq,
4177 : Vector<Double> &intermediateChanWidth)
4178 : {
4179 2 : uInt mumOfInterChan = inputChanFreq.size() / freqbinMap_p[spwId];
4180 2 : uInt lastChannelWidth = inputChanFreq.size() % freqbinMap_p[spwId];
4181 2 : if (lastChannelWidth > 0)
4182 : {
4183 2 : mumOfInterChan += 1;
4184 : }
4185 2 : numOfCombInputChanMap_p[spwId] = inputChanFreq.size();
4186 2 : numOfCombInterChanMap_p[spwId] = mumOfInterChan;
4187 2 : intermediateChanFreq.resize(mumOfInterChan,false);
4188 2 : intermediateChanWidth.resize(mumOfInterChan,false);
4189 2 : simpleAverage(freqbinMap_p[spwId], inputChanFreq, intermediateChanFreq);
4190 2 : simpleAverage(freqbinMap_p[spwId], inputChanWidth, intermediateChanWidth);
4191 :
4192 30 : for (uInt chanIdx=0;chanIdx<mumOfInterChan;chanIdx++)
4193 : {
4194 28 : intermediateChanWidth[chanIdx] *= freqbinMap_p[spwId];
4195 : }
4196 :
4197 2 : if (lastChannelWidth > 0)
4198 : {
4199 2 : intermediateChanWidth[mumOfInterChan-1] /= freqbinMap_p[spwId];
4200 2 : intermediateChanWidth[mumOfInterChan-1] *= lastChannelWidth;
4201 : }
4202 :
4203 2 : return;
4204 : }
4205 :
4206 : /**
4207 : * Create a fake grid and create a map [input channels] => [output channels]
4208 : * from it. This is for the tclean-like interpolation that is applied when
4209 : * the width of the output is > 2 x width of the inputs.
4210 : *
4211 : * Irrespective of channel widths, we want as many channels as in the
4212 : * original input, with their (lower) width, but projected/aligned
4213 : * with the output grid. As the output grid is fixed based on the
4214 : * first row timestamp, this only need to be done once, at init time.
4215 : *
4216 : * After this method is run, the interpolation methods can use
4217 : * regridTCleanChanMap_p to interpolate the tclean way.
4218 : *
4219 : * @param originalCHAN_FREQ initial input channel frequencies
4220 : * @param outCHAN_FREQ final output channel frequencies
4221 : * @param outCHAN_WIDTH final output channel widths
4222 : * @param widthFactor avg(output_widths) / avg(input_widths)
4223 : */
4224 23 : void MSTransformManager::initGridForRegridTClean(const Vector<Double> &originalCHAN_FREQ,
4225 : const Vector<Double> &outCHAN_FREQ,
4226 : const Vector<Double> &outCHAN_WIDTH,
4227 : Double widthFactor)
4228 : {
4229 : // build grid with widths of the input channels but aligned with the output
4230 : // grid
4231 23 : regridTCleanCHAN_FREQ_p.resize(originalCHAN_FREQ.size());
4232 23 : Vector<Double> regridTCleanCHAN_WIDTH_p;
4233 23 : regridTCleanCHAN_WIDTH_p.resize(regridTCleanCHAN_FREQ_p.size());
4234 :
4235 23 : const auto &outputFreqs = outCHAN_FREQ;
4236 23 : bool negativeWidths = outputFreqs[0] > outputFreqs[outputFreqs.size()-1];
4237 :
4238 : // swap first/last if "negative width" (decreasing frequencies)
4239 23 : auto startIdx = negativeWidths ? (outCHAN_FREQ.size() -1) : 0;
4240 23 : regridTCleanCHAN_FREQ_p[0] = outCHAN_FREQ[startIdx] - outCHAN_WIDTH[startIdx]/2.;
4241 23 : regridTCleanCHAN_WIDTH_p[0] = outCHAN_WIDTH[startIdx] / widthFactor;
4242 23 : Double widthFactorIdx = static_cast<Double>(regridTCleanCHAN_FREQ_p.size()) /
4243 23 : outCHAN_FREQ.size();
4244 :
4245 46394 : for (size_t idx = 1; idx < regridTCleanCHAN_FREQ_p.size(); ++idx) {
4246 46371 : Int outIdx = static_cast<Int>(idx / widthFactorIdx);
4247 46371 : regridTCleanCHAN_WIDTH_p[idx] = outCHAN_WIDTH[outIdx] / widthFactorIdx;
4248 92742 : regridTCleanCHAN_FREQ_p[idx] = regridTCleanCHAN_FREQ_p[idx-1] +
4249 46371 : regridTCleanCHAN_WIDTH_p[idx];
4250 : }
4251 :
4252 :
4253 : // Build map from fake input channels => output channels
4254 23 : regridTCleanChanMap_p.resize(regridTCleanCHAN_FREQ_p.size());
4255 23 : regridTCleanChanMap_p = -1;
4256 23 : const auto &intermFreqs = regridTCleanCHAN_FREQ_p;
4257 23 : const auto &outputWidths = outCHAN_WIDTH;
4258 46417 : for (uInt mapIdx = 0; mapIdx < regridTCleanChanMap_p.size(); ++mapIdx) {
4259 3759393 : for (uInt outIdx = 0; outIdx < outputFreqs.size(); ++outIdx) {
4260 5974130 : if (intermFreqs[mapIdx] >= outputFreqs[outIdx] - outputWidths[outIdx]/2. and
4261 2214737 : intermFreqs[mapIdx] < outputFreqs[outIdx] + outputWidths[outIdx]/2.) {
4262 46394 : regridTCleanChanMap_p(mapIdx) = outIdx;
4263 46394 : break;
4264 : }
4265 : }
4266 : }
4267 23 : regridTClean_p = true;
4268 23 : }
4269 :
4270 : // -----------------------------------------------------------------------
4271 : // Method to set all the elements of a scalar column to a given value
4272 : // -----------------------------------------------------------------------
4273 189 : void MSTransformManager::reindexColumn(ScalarColumn<Int> &inputCol, Int value)
4274 : {
4275 781654 : for(rownr_t idx=0; idx<inputCol.nrow(); idx++)
4276 : {
4277 781465 : inputCol.put(idx,value);
4278 : }
4279 :
4280 189 : return;
4281 : }
4282 :
4283 : // -----------------------------------------------------------------------
4284 : // Method to re-index Spectral Window column in Source sub-table
4285 : // -----------------------------------------------------------------------
4286 90 : void MSTransformManager::reindexSourceSubTable()
4287 : {
4288 90 : if(Table::isReadable(outputMs_p->sourceTableName()) and !outputMs_p->source().isNull())
4289 : {
4290 :
4291 180 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4292 180 : << "Re-indexing SOURCE sub-table" << LogIO::POST;
4293 :
4294 :
4295 90 : MSSource sourceSubtable = outputMs_p->source();
4296 90 : MSSourceColumns tableCols(sourceSubtable);
4297 90 : ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
4298 90 : ScalarColumn<Int> sourceId = tableCols.sourceId();
4299 90 : reindexColumn(spectralWindowId,0);
4300 :
4301 : // Remove duplicates
4302 90 : std::vector<rownr_t> duplicateIdx;
4303 90 : std::vector< std::pair<uInt,uInt> > sourceIdSpwIdMap;
4304 :
4305 2817 : for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
4306 : {
4307 2727 : std::pair<uInt,uInt> sourceIdSpwId = std::make_pair(spectralWindowId(idx),sourceId(idx));
4308 :
4309 2727 : if (std::find(sourceIdSpwIdMap.begin(),sourceIdSpwIdMap.end(),sourceIdSpwId) != sourceIdSpwIdMap.end())
4310 : {
4311 2479 : duplicateIdx.push_back(idx);
4312 : }
4313 : else
4314 : {
4315 248 : sourceIdSpwIdMap.push_back(sourceIdSpwId);
4316 : }
4317 : }
4318 :
4319 90 : sourceSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
4320 :
4321 90 : }
4322 : else
4323 : {
4324 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
4325 0 : << "SOURCE sub-table not found " << LogIO::POST;
4326 : }
4327 :
4328 90 : return;
4329 : }
4330 :
4331 : // -----------------------------------------------------------------------
4332 : // Method to re-index Spectral Window column in DDI sub-table
4333 : // -----------------------------------------------------------------------
4334 96 : void MSTransformManager::reindexDDISubTable()
4335 : {
4336 96 : if(Table::isReadable(outputMs_p->dataDescriptionTableName()) and !outputMs_p->dataDescription().isNull())
4337 : {
4338 192 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4339 192 : << "Re-indexing DDI sub-table" << LogIO::POST;
4340 :
4341 : // Access DDI sub-table
4342 96 : MSDataDescription ddiTable = outputMs_p->dataDescription();
4343 96 : MSDataDescColumns ddiCols(ddiTable);
4344 :
4345 : // Add a new row for each of the separated SPWs
4346 96 : uInt rowIndex = 0;
4347 238 : for (uInt spw_i=0; spw_i<nspws_p; spw_i++)
4348 : {
4349 142 : if (rowIndex > 0)
4350 : {
4351 : // Add row
4352 46 : ddiTable.addRow(1,true);
4353 :
4354 : // Copy polID and flagRow from the first original SPW
4355 46 : ddiCols.polarizationId().put(rowIndex,ddiCols.polarizationId()(0));
4356 46 : ddiCols.flagRow().put(rowIndex,ddiCols.flagRow()(0));
4357 :
4358 : // Optional columns
4359 46 : if (ddiCols.lagId().isNull()==false and ddiCols.lagId().hasContent()==true)
4360 : {
4361 0 : ddiCols.lagId().put(rowIndex,ddiCols.lagId()(0));
4362 : }
4363 : }
4364 :
4365 : // Set SPW id separately
4366 142 : ddiCols.spectralWindowId().put(rowIndex,ddiStart_p+spw_i);
4367 :
4368 142 : rowIndex += 1;
4369 : }
4370 :
4371 : // Delete the old rows
4372 96 : rownr_t nrowsToDelete = ddiCols.nrow()-nspws_p;
4373 96 : if (nrowsToDelete > 0)
4374 : {
4375 90 : rownr_t rownr = ddiCols.nrow()-1;
4376 90 : Vector<rownr_t> rowsToDelete(nrowsToDelete);
4377 624 : for(rownr_t idx=0; idx<nrowsToDelete; idx++)
4378 : {
4379 534 : rowsToDelete(idx) = rownr;
4380 534 : rownr -= 1;
4381 : }
4382 :
4383 90 : ddiTable.removeRow(rowsToDelete);
4384 90 : }
4385 :
4386 :
4387 96 : }
4388 : else
4389 : {
4390 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
4391 0 : << "DATA_DESCRIPTION sub-table not found " << LogIO::POST;
4392 : }
4393 96 : }
4394 :
4395 : // -----------------------------------------------------------------------
4396 : // Method to re-index Spectral Window column in Feed sub-table
4397 : // -----------------------------------------------------------------------
4398 0 : void MSTransformManager::reindexFeedSubTable()
4399 : {
4400 0 : if(Table::isReadable(outputMs_p->feedTableName()) and !outputMs_p->feed().isNull())
4401 : {
4402 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4403 0 : << "Re-indexing FEED sub-table and removing duplicates" << LogIO::POST;
4404 :
4405 0 : MSFeed feedSubtable = outputMs_p->feed();
4406 0 : MSFeedColumns tableCols(feedSubtable);
4407 0 : ScalarColumn<Int> feedId = tableCols.feedId();
4408 0 : ScalarColumn<Int> antennaId = tableCols.antennaId();
4409 0 : ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
4410 0 : ScalarColumn<Double> time = tableCols.time();
4411 :
4412 : // Re-index SPWId to be 0
4413 0 : reindexColumn(spectralWindowId,0);
4414 :
4415 : // Remove duplicates
4416 0 : std::vector<rownr_t> duplicateIdx;
4417 0 : std::map< std::pair<uInt,uInt> , Double > antennaFeedTimeMap;
4418 0 : std::map< std::pair<uInt,uInt> , Double >::iterator antennaFeedTimeIter;
4419 :
4420 0 : for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
4421 : {
4422 0 : std::pair<uInt,uInt> antennaFeedPair = std::make_pair(antennaId(idx),feedId(idx));
4423 0 : antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
4424 :
4425 0 : if (antennaFeedTimeIter != antennaFeedTimeMap.end())
4426 : {
4427 0 : if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
4428 : {
4429 0 : duplicateIdx.push_back(idx);
4430 : }
4431 : else
4432 : {
4433 0 : antennaFeedTimeMap[antennaFeedPair] = time(idx);
4434 : }
4435 : }
4436 : else
4437 : {
4438 0 : antennaFeedTimeMap[antennaFeedPair] = time(idx);
4439 : }
4440 : }
4441 :
4442 :
4443 0 : feedSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
4444 :
4445 0 : }
4446 : else
4447 : {
4448 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__) <<
4449 0 : "FEED sub-table not found " << LogIO::POST;
4450 : }
4451 :
4452 0 : return;
4453 : }
4454 :
4455 : // -----------------------------------------------------------------------
4456 : // Method to re-index Spectral Window column in SysCal sub-table
4457 : // -----------------------------------------------------------------------
4458 0 : void MSTransformManager::reindexSysCalSubTable()
4459 : {
4460 0 : if(Table::isReadable(outputMs_p->sysCalTableName()) and !outputMs_p->sysCal().isNull())
4461 : {
4462 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4463 0 : << "Re-indexing SYSCAL sub-table and removing duplicates" << LogIO::POST;
4464 :
4465 0 : MSSysCal syscalSubtable = outputMs_p->sysCal();
4466 0 : MSSysCalColumns tableCols(syscalSubtable);
4467 0 : ScalarColumn<Int> feedId = tableCols.feedId();
4468 0 : ScalarColumn<Int> antennaId = tableCols.antennaId();
4469 0 : ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
4470 0 : ScalarColumn<Double> time = tableCols.time();
4471 :
4472 : // Re-index SPWId to be 0
4473 0 : reindexColumn(spectralWindowId,0);
4474 :
4475 : // Remove duplicates
4476 0 : std::vector<rownr_t> duplicateIdx;
4477 0 : std::map< std::pair<uInt,uInt> , Double > antennaFeedTimeMap;
4478 0 : std::map< std::pair<uInt,uInt> , Double >::iterator antennaFeedTimeIter;
4479 :
4480 0 : for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
4481 : {
4482 0 : std::pair<uInt,uInt> antennaFeedPair = std::make_pair(antennaId(idx),feedId(idx));
4483 0 : antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
4484 :
4485 0 : if (antennaFeedTimeIter != antennaFeedTimeMap.end())
4486 : {
4487 0 : if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
4488 : {
4489 0 : duplicateIdx.push_back(idx);
4490 : }
4491 : else
4492 : {
4493 0 : antennaFeedTimeMap[antennaFeedPair] = time(idx);
4494 : }
4495 : }
4496 : else
4497 : {
4498 0 : antennaFeedTimeMap[antennaFeedPair] = time(idx);
4499 : }
4500 : }
4501 :
4502 0 : syscalSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
4503 :
4504 0 : }
4505 : else
4506 : {
4507 0 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
4508 0 : << "SYSCAL sub-table not found " << LogIO::POST;
4509 : }
4510 :
4511 0 : return;
4512 : }
4513 :
4514 : // -----------------------------------------------------------------------
4515 : // Method to re-index Spectral Window column in FreqOffset sub-table
4516 : // -----------------------------------------------------------------------
4517 90 : void MSTransformManager::reindexFreqOffsetSubTable()
4518 : {
4519 90 : if(Table::isReadable(outputMs_p->freqOffsetTableName()) and !outputMs_p->freqOffset().isNull())
4520 : {
4521 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4522 0 : << "Re-indexing FREQ_OFFSET sub-table and removing duplicates" << LogIO::POST;
4523 :
4524 0 : MSFreqOffset freqoffsetSubtable = outputMs_p->freqOffset();
4525 0 : MSFreqOffsetColumns tableCols(freqoffsetSubtable);
4526 0 : ScalarColumn<Int> feedId = tableCols.feedId();
4527 0 : ScalarColumn<Int> antenna1 = tableCols.antenna1();
4528 0 : ScalarColumn<Int> antenna2 = tableCols.antenna2();
4529 0 : ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
4530 0 : ScalarColumn<Double> time = tableCols.time();
4531 :
4532 : // Re-index SPWId to be 0
4533 0 : reindexColumn(spectralWindowId,0);
4534 :
4535 : // Remove duplicates
4536 0 : std::vector<rownr_t> duplicateIdx;
4537 0 : std::map< std::pair < std::pair<uInt,uInt> , uInt> , Double > antennaFeedTimeMap;
4538 0 : std::map< std::pair < std::pair<uInt,uInt> , uInt> , Double >::iterator antennaFeedTimeIter;
4539 :
4540 0 : for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
4541 : {
4542 0 : std::pair < std::pair<uInt,uInt> , uInt> antennaFeedPair = std::make_pair(std::make_pair(antenna1(idx),antenna2(idx)),feedId(idx));
4543 0 : antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
4544 :
4545 0 : if (antennaFeedTimeIter != antennaFeedTimeMap.end())
4546 : {
4547 0 : if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
4548 : {
4549 0 : duplicateIdx.push_back(idx);
4550 : }
4551 : else
4552 : {
4553 0 : antennaFeedTimeMap[antennaFeedPair] = time(idx);
4554 : }
4555 : }
4556 : else
4557 : {
4558 0 : antennaFeedTimeMap[antennaFeedPair] = time(idx);
4559 : }
4560 : }
4561 :
4562 0 : freqoffsetSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
4563 :
4564 0 : }
4565 : else
4566 : {
4567 180 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
4568 180 : << "FREQ_OFFSET sub-table not found " << LogIO::POST;
4569 : }
4570 :
4571 90 : return;
4572 : }
4573 :
4574 : // -----------------------------------------------------------------------
4575 : // Method to re-index Spectral Window column in a generic sub-table (with feedId, antennaId and time columns)
4576 : // -----------------------------------------------------------------------
4577 360 : void MSTransformManager::reindexGenericTimeDependentSubTable(const String& subtabname)
4578 : {
4579 360 : if (Table::isReadable(outputMs_p->tableName() + "/" + subtabname))
4580 : {
4581 294 : Table subtable(outputMs_p->tableName() + "/" + subtabname, Table::Update);
4582 :
4583 147 : if (subtable.nrow() > 0)
4584 : {
4585 198 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4586 : << "Re-indexing SPW column of " << subtabname
4587 198 : << " sub-table and removing duplicates " << LogIO::POST;
4588 :
4589 99 : ScalarColumn<Int> feedId(subtable, "FEED_ID");
4590 99 : ScalarColumn<Int> antennaId(subtable, "ANTENNA_ID");
4591 99 : ScalarColumn<Int> spectralWindowId(subtable, "SPECTRAL_WINDOW_ID");
4592 99 : ScalarColumn<Double> time(subtable, "TIME");
4593 :
4594 : // Re-index SPWId to be 0
4595 99 : reindexColumn(spectralWindowId,0);
4596 :
4597 : // Remove duplicates
4598 99 : std::vector<rownr_t> duplicateIdx;
4599 99 : std::map< std::pair<uInt,uInt> , Double > antennaFeedTimeMap;
4600 99 : std::map< std::pair<uInt,uInt> , Double >::iterator antennaFeedTimeIter;
4601 :
4602 778837 : for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
4603 : {
4604 778738 : std::pair<uInt,uInt> antennaFeedPair = std::make_pair(antennaId(idx),feedId(idx));
4605 778738 : antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
4606 :
4607 778738 : if (antennaFeedTimeIter != antennaFeedTimeMap.end())
4608 : {
4609 777490 : if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
4610 : {
4611 389852 : duplicateIdx.push_back(idx);
4612 : }
4613 : else
4614 : {
4615 387638 : antennaFeedTimeMap[antennaFeedPair] = time(idx);
4616 : }
4617 : }
4618 : else
4619 : {
4620 1248 : antennaFeedTimeMap[antennaFeedPair] = time(idx);
4621 : }
4622 : }
4623 :
4624 99 : subtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
4625 :
4626 99 : }
4627 : else
4628 : {
4629 48 : if (subtabname == casacore::String("FEED"))
4630 : {
4631 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
4632 0 : << subtabname << " sub-table found but has no valid content" << LogIO::POST;
4633 : }
4634 : else
4635 : {
4636 96 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
4637 96 : << subtabname << " sub-table found but has no valid content" << LogIO::POST;
4638 : }
4639 : }
4640 147 : }
4641 : else
4642 : {
4643 213 : if (subtabname == casacore::String("FEED"))
4644 : {
4645 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
4646 0 : << subtabname << " sub-table not found" << LogIO::POST;
4647 : }
4648 : else
4649 : {
4650 426 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
4651 426 : << subtabname << " sub-table not found" << LogIO::POST;
4652 : }
4653 : }
4654 :
4655 360 : return;
4656 : }
4657 :
4658 : // -----------------------------------------------------------------------
4659 : //
4660 : // -----------------------------------------------------------------------
4661 1922 : void MSTransformManager::getInputNumberOfChannels()
4662 : {
4663 : // Access spectral window sub-table
4664 1922 : MSSpectralWindow spwTable = inputMs_p->spectralWindow();
4665 1922 : auto nInputSpws = spwTable.nrow();
4666 1922 : MSSpWindowColumns spwCols(spwTable);
4667 1922 : ScalarColumn<Int> numChanCol = spwCols.numChan();
4668 :
4669 : // Get number of output channels per input spw
4670 19740 : for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
4671 : {
4672 17818 : numOfInpChanMap_p[spw_idx] = numChanCol(spw_idx);
4673 : }
4674 :
4675 3844 : return;
4676 1922 : }
4677 :
4678 : // -----------------------------------------------------------------------
4679 : //
4680 : // -----------------------------------------------------------------------
4681 136 : void MSTransformManager::dropNonUniformWidthChannels()
4682 : {
4683 : // Access spectral window sub-table
4684 136 : MSSpectralWindow spwTable = outputMs_p->spectralWindow();
4685 136 : auto nInputSpws = spwTable.nrow();
4686 136 : MSSpWindowColumns spwCols(spwTable);
4687 136 : ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
4688 136 : ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
4689 136 : ArrayColumn<Double> effectiveBWCol = spwCols.effectiveBW();
4690 136 : ArrayColumn<Double> resolutionCol = spwCols.resolution();
4691 136 : ScalarColumn<Int> numChanCol = spwCols.numChan();
4692 136 : ScalarColumn<Double> totalBandwidthCol = spwCols.totalBandwidth();
4693 :
4694 : uInt nChans;
4695 : Int spwId;
4696 1518 : for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
4697 : {
4698 1382 : nChans = numChanCol(spw_idx);
4699 1382 : Vector<Double> widthVector = chanWidthCol(spw_idx);
4700 :
4701 1382 : if (outputInputSPWIndexMap_p.size()>0)
4702 : {
4703 57 : spwId = outputInputSPWIndexMap_p[spw_idx];
4704 : }
4705 : else
4706 : {
4707 1325 : spwId = spw_idx;
4708 : }
4709 :
4710 : // Skip this SPW in non-reindex mode
4711 1382 : if ((!reindex_p) and (numOfSelChanMap_p.find(spwId) == numOfSelChanMap_p.end())) continue;
4712 :
4713 : //logger_p << dataHandler_p->getDroppedChannelsMap() << LogIO::POST;
4714 :
4715 1382 : if (dataHandler_p->getDroppedChannelsMap().find(spwId) != dataHandler_p->getDroppedChannelsMap().end())
4716 : {
4717 14 : vector<Int>::iterator iter;
4718 14 : Double droppedWidth = 0;
4719 14 : vector<Int> &droppedChannels = dataHandler_p->getDroppedChannelsMap()[spwId];
4720 28 : for (iter = droppedChannels.begin(); iter != droppedChannels.end(); iter++)
4721 : {
4722 28 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
4723 : << "Not enough input channels to populate output channel n# "
4724 14 : << *iter << " from SPW " << spwId << "." << endl
4725 : << "The channel will be dropped in order to have an uniform grid."
4726 28 : << LogIO::POST;
4727 :
4728 14 : droppedWidth += widthVector(*iter);
4729 : }
4730 :
4731 : // Calculate final number of channels
4732 14 : uInt nChansFinal = nChans-droppedChannels.size();
4733 :
4734 14 : if (nChansFinal <= 0)
4735 : {
4736 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
4737 : << "Channel selection does not allow to produce any output channel with the requested width "
4738 0 : << LogIO::POST;
4739 :
4740 0 : throw AipsError("Channel selection does not allow to produce any output channel with the requested width ");
4741 : }
4742 :
4743 :
4744 :
4745 14 : numChanCol.put(spw_idx, nChansFinal);
4746 :
4747 : // Total BW has to be reduced to account for the dropped channels
4748 14 : totalBandwidthCol.put(spw_idx, totalBandwidthCol(spw_idx)-droppedWidth);
4749 :
4750 : // Get current vectors
4751 14 : Vector<Double> effectiveBWVector = effectiveBWCol(spw_idx);
4752 14 : Vector<Double> resolutionVector = resolutionCol(spw_idx);
4753 14 : Vector<Double> frequencyVector = chanFreqCol(spw_idx);
4754 :
4755 : // Declare new vectors
4756 14 : Vector<Double> newWidthVector(nChansFinal);
4757 14 : Vector<Double> newEffectiveBWVector(nChansFinal);
4758 14 : Vector<Double> newResolutionVector(nChansFinal);
4759 14 : Vector<Double> newFrequencyVector(nChansFinal);
4760 :
4761 : // Create a new frequency vector
4762 14 : uInt finalIdx = 0;
4763 14 : vector<Int>::iterator matchIdx;
4764 302 : for (uInt idx=0;idx < widthVector.size(); idx++)
4765 : {
4766 288 : matchIdx = find (droppedChannels.begin(), droppedChannels.end(), idx);
4767 288 : if (matchIdx == droppedChannels.end() )
4768 : {
4769 274 : newWidthVector(finalIdx) = widthVector(idx);
4770 274 : newEffectiveBWVector(finalIdx) = effectiveBWVector(idx);
4771 274 : newResolutionVector(finalIdx) = resolutionVector(idx);
4772 274 : newFrequencyVector(finalIdx) = frequencyVector(idx);
4773 274 : finalIdx ++;
4774 : }
4775 : }
4776 :
4777 : // Put new vectors in corresponding columns
4778 14 : chanWidthCol.put(spw_idx, newWidthVector);
4779 14 : effectiveBWCol.put(spw_idx, newEffectiveBWVector);
4780 14 : resolutionCol.put(spw_idx, newResolutionVector);
4781 14 : chanFreqCol.put(spw_idx, newFrequencyVector);
4782 :
4783 : // Update output number of channels
4784 14 : if (regridding_p) inputOutputSpwMap_p[spw_idx].second.resize(nChansFinal);
4785 14 : }
4786 1382 : }
4787 :
4788 272 : return;
4789 136 : }
4790 :
4791 :
4792 : // -----------------------------------------------------------------------
4793 : //
4794 : // -----------------------------------------------------------------------
4795 144 : void MSTransformManager::getOutputNumberOfChannels()
4796 : {
4797 144 : if (regridding_p or combinespws_p)
4798 : {
4799 8 : map<uInt,uInt>::iterator iter;
4800 18 : for(iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
4801 : {
4802 10 : if (freqbinMap_p.find(iter->first) == freqbinMap_p.end())
4803 : {
4804 : // When doing only re-gridding, maybe not all SPWs require pre-averaging
4805 8 : if (not combinespws_p)
4806 : {
4807 6 : freqbinMap_p[iter->first] = 1;
4808 : }
4809 : // When combining SPWs all of them get the same freqbin
4810 : else
4811 : {
4812 2 : freqbinMap_p[iter->first] = freqbinMap_p[0];
4813 : }
4814 : }
4815 : }
4816 : }
4817 :
4818 : // Access spectral window sub-table
4819 144 : MSSpectralWindow spwTable = outputMs_p->spectralWindow();
4820 144 : auto nInputSpws = spwTable.nrow();
4821 144 : MSSpWindowColumns spwCols(spwTable);
4822 144 : ScalarColumn<Int> numChanCol = spwCols.numChan();
4823 144 : ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
4824 :
4825 144 : if (combinespws_p)
4826 : {
4827 2 : map<uInt,uInt>::iterator iter;
4828 6 : for(iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
4829 : {
4830 : // Note: This will truncate the result, but it is ok because we are dropping the last channel
4831 4 : numOfOutChanMap_p[iter->first] = numOfSelChanMap_p[iter->first] / freqbinMap_p[iter->first];
4832 : }
4833 : }
4834 : else
4835 : {
4836 : // Get number of output channels per input spw
4837 : Int spwId;
4838 1530 : for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
4839 : {
4840 1388 : if (outputInputSPWIndexMap_p.size()>0)
4841 : {
4842 60 : spwId = outputInputSPWIndexMap_p[spw_idx];
4843 : }
4844 : else
4845 : {
4846 1328 : spwId = spw_idx;
4847 : }
4848 :
4849 1388 : numOfOutChanMap_p[spwId] = numChanCol(spw_idx);
4850 : }
4851 : }
4852 :
4853 288 : return;
4854 144 : }
4855 :
4856 : // -----------------------------------------------------------------------
4857 : //
4858 : // -----------------------------------------------------------------------
4859 0 : void MSTransformManager::calculateWeightAndSigmaFactors()
4860 : {
4861 0 : map<uInt,uInt>::iterator iter;
4862 0 : for(iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
4863 : {
4864 0 : weightFactorMap_p[iter->first] = (Float)numOfSelChanMap_p[iter->first] /
4865 0 : (Float)numOfInpChanMap_p[iter->first];
4866 0 : sigmaFactorMap_p[iter->first] = 1./sqrt((Float)numOfSelChanMap_p[iter->first] /
4867 0 : (Float)numOfOutChanMap_p[iter->first]);
4868 : }
4869 :
4870 0 : return;
4871 : }
4872 :
4873 : // -----------------------------------------------------------------------
4874 : //
4875 : // -----------------------------------------------------------------------
4876 286 : void MSTransformManager::calculateNewWeightAndSigmaFactors()
4877 : {
4878 :
4879 286 : map<uInt, uInt>::iterator iter;
4880 2392 : for (iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
4881 : {
4882 : // Populateremaining SPWs of weight factor map
4883 2106 : if (newWeightFactorMap_p.find(iter->first)== newWeightFactorMap_p.end())
4884 : {
4885 : // When doing only re-gridding, maybe not all SPWs require pre-averaging
4886 550 : if (not combinespws_p)
4887 : {
4888 0 : newWeightFactorMap_p[iter->first] = 1;
4889 : }
4890 : // When combining SPWs all of them get the same freqbin
4891 : else
4892 : {
4893 550 : newWeightFactorMap_p[iter->first] = newWeightFactorMap_p[0];
4894 : }
4895 : }
4896 :
4897 : // Populate sigma factor map
4898 2106 : newSigmaFactorMap_p[iter->first] = 1 / sqrt(newWeightFactorMap_p[iter->first]);
4899 : }
4900 :
4901 572 : return;
4902 : }
4903 :
4904 : // -----------------------------------------------------------------------
4905 : // Method to check if flag category has to be filled
4906 : // -----------------------------------------------------------------------
4907 1896 : void MSTransformManager::checkFillFlagCategory()
4908 : {
4909 1896 : inputFlagCategoryAvailable_p = false;
4910 1896 : if ( !selectedInputMsCols_p->flagCategory().isNull()
4911 1896 : && selectedInputMsCols_p->flagCategory().isDefined(0)
4912 5688 : && selectedInputMsCols_p->flagCategory()(0).shape() == 3)
4913 : {
4914 0 : inputFlagCategoryAvailable_p = true;
4915 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4916 0 : << "Optional column FLAG_CATEGORY found in input MS will be written to output MS" << LogIO::POST;
4917 : }
4918 :
4919 1896 : return;
4920 : }
4921 :
4922 : // -----------------------------------------------------------------------
4923 : // Method to check if weight spectrum column has to be filled
4924 : // -----------------------------------------------------------------------
4925 1896 : void MSTransformManager::checkFillWeightSpectrum()
4926 : {
4927 1896 : inputWeightSpectrumAvailable_p = false;
4928 2952 : if (!selectedInputMsCols_p->weightSpectrum().isNull() and
4929 1056 : selectedInputMsCols_p->weightSpectrum().isDefined(0))
4930 : {
4931 207 : inputWeightSpectrumAvailable_p = true;
4932 414 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
4933 414 : << "Optional column WEIGHT_SPECTRUM found in input MS will be written to output MS" << LogIO::POST;
4934 : }
4935 1896 : }
4936 :
4937 : /**
4938 : * Early check for a potential issue that would prevent an MSTransform
4939 : * setup which looks in principle fine from running correctly. Ensures
4940 : * that we catch a current limitation in the underlying iterators /
4941 : * VI/VB2 framework whereby combinespws won't work when the number of
4942 : * channels is different for different SPWs.
4943 : *
4944 : * Requires that numOfInpChanMap_p be populated previously (in
4945 : * getInputNumberOfChannels()).
4946 : *
4947 : * @throws AipsError if combinespws is enabled and the input MS of the
4948 : * current configuration has different number of channels for
4949 : * different SPWs
4950 : */
4951 1918 : void MSTransformManager::checkSPWChannelsKnownLimitation()
4952 : {
4953 1918 : if (not combinespws_p)
4954 1814 : return;
4955 :
4956 132 : auto nSpws = inputMs_p->spectralWindow().nrow();
4957 132 : if (1 >= nSpws or numOfInpChanMap_p.empty() or numOfSelChanMap_p.empty())
4958 28 : return;
4959 :
4960 104 : auto firstNum = numOfSelChanMap_p.begin()->second;
4961 104 : auto diff = std::find_if(numOfSelChanMap_p.begin(), numOfSelChanMap_p.end(),
4962 644 : [&firstNum](const std::pair<casacore::uInt,casacore::uInt> &other) {
4963 644 : return firstNum != other.second; });
4964 :
4965 :
4966 104 : if (numOfSelChanMap_p.end() != diff) {
4967 4 : auto otherNum = diff->second;
4968 4 : throw AipsError("Currently the option 'combinespws' is only supported when the number "
4969 : "of channels is the same for all the spw's selected. One of the SPWs "
4970 8 : "selected has " + std::to_string(firstNum) + " channels, but another "
4971 16 : "selected SPW has " + std::to_string(otherNum) + " channels.");
4972 : }
4973 : }
4974 :
4975 : /**
4976 : * Early check to issue a warning if the data was preaveraged
4977 : * by the correlator ans we are performing a further
4978 : * smoothing and average.
4979 : */
4980 1922 : void MSTransformManager::checkCorrelatorPreaveraging()
4981 : {
4982 1922 : std::string spwPreaveraged;
4983 1922 : if (hanningSmooth_p || channelAverage_p)
4984 : {
4985 172 : auto spwTable = inputMs_p->spectralWindow();
4986 172 : MSSpWindowColumns spwColumns(spwTable);
4987 344 : if (spwTable.tableDesc().isColumn("SDM_WINDOW_FUNCTION") &&
4988 172 : spwTable.tableDesc().columnDescSet().isDefined("SDM_WINDOW_FUNCTION") &&
4989 516 : spwTable.tableDesc().isColumn("SDM_NUM_BIN") &&
4990 172 : spwTable.tableDesc().columnDescSet().isDefined("SDM_NUM_BIN"))
4991 : {
4992 0 : auto nrows = spwColumns.nrow();
4993 0 : auto effBWCol = spwColumns.effectiveBW();
4994 0 : auto chanWidthCol = spwColumns.chanWidth();
4995 0 : ScalarColumn<String> windowFunctionCol(spwTable, "SDM_WINDOW_FUNCTION");
4996 0 : ScalarColumn<Int> numBinCol(spwTable, "SDM_NUM_BIN");
4997 0 : for (size_t spwIdx = 0; spwIdx < nrows; spwIdx++)
4998 : {
4999 0 : auto numBin = numBinCol(spwIdx);
5000 0 : auto windowFunction = windowFunctionCol(spwIdx);
5001 0 : if(windowFunction != "UNKNOWN" && numBin != 1)
5002 0 : spwPreaveraged += std::to_string(spwIdx)+" ";
5003 0 : }
5004 0 : }
5005 172 : }
5006 :
5007 1922 : if(spwPreaveraged != "")
5008 0 : logger_p << LogIO::WARN<<LogOrigin("MSTransformManager", __func__) <<
5009 : "The data has already been preaveraged by the correlator but "
5010 : "further smoothing or averaging has been requested. "
5011 0 : "Preaveraged SPWs are: "<<spwPreaveraged<<LogIO::POST;
5012 1922 : }
5013 :
5014 : // -----------------------------------------------------------------------
5015 : //
5016 : // -----------------------------------------------------------------------
5017 1922 : void MSTransformManager::checkDataColumnsAvailable()
5018 : {
5019 1922 : dataColumnAvailable_p = false;
5020 1922 : correctedDataColumnAvailable_p = false;
5021 1922 : modelDataColumnAvailable_p = false;
5022 :
5023 :
5024 1922 : floatDataColumnAvailable_p = false;
5025 1922 : lagDataColumnAvailable_p = false;
5026 :
5027 :
5028 : // DATA
5029 1922 : if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::DATA)))
5030 : {
5031 1417 : dataColumnAvailable_p = true;
5032 : }
5033 :
5034 :
5035 : // CORRECTED_DATA already exists in the input MS
5036 1922 : if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::CORRECTED_DATA)))
5037 : {
5038 832 : correctedDataColumnAvailable_p = true;
5039 : }
5040 : // CORRECTED_DATA does not exist but there is a calibration parameter set available
5041 1090 : else if (calibrate_p and (makeVirtualCorrectedColReal_p or bufferMode_p))
5042 : {
5043 9 : correctedDataColumnAvailable_p = true;
5044 : }
5045 : // There is no calibration parameter set available
5046 : else
5047 : {
5048 : // TODO: Inform that virtual CORRECTED_DATA is not available
5049 :
5050 : // Unset makeVirtualModelColReal_p as virtual CORRECTED col. is not available
5051 1081 : makeVirtualCorrectedColReal_p = false;
5052 : }
5053 :
5054 : // FLOAT_DATA
5055 1922 : if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::FLOAT_DATA)))
5056 : {
5057 505 : floatDataColumnAvailable_p = true;
5058 : }
5059 :
5060 :
5061 : // MODEL_DATA already exists in the input MS
5062 1922 : if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::MODEL_DATA)))
5063 : {
5064 718 : modelDataColumnAvailable_p = true;
5065 : }
5066 : // MODEL_DATA does not exist but there is a model available in the SOURCE sub-table
5067 : // MODEL_DATA should not be made real if the user does not specify it implicitly
5068 1204 : else if (inputMs_p->source().isColumn(MSSource::SOURCE_MODEL) and makeVirtualModelColReal_p)
5069 : {
5070 1 : modelDataColumnAvailable_p = true;
5071 : }
5072 : // CAS-7390: Provide default MODEL_DATA in buffer mode
5073 1203 : else if (bufferMode_p and not floatDataColumnAvailable_p) // MODEL is not defined for SD data
5074 : {
5075 0 : makeVirtualModelColReal_p = true;
5076 0 : modelDataColumnAvailable_p = true;
5077 : }
5078 : // There is no model available in the SOURCE sub-table
5079 : else
5080 : {
5081 1203 : modelDataColumnAvailable_p = false;
5082 :
5083 : // Inform that virtual MODEL_DATA is not available
5084 1203 : if (makeVirtualModelColReal_p)
5085 : {
5086 1 : if (bufferMode_p)
5087 : {
5088 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
5089 : << "Requested to make virtual MODEL_DATA column available from MSTransformBuffer but"
5090 : << "SOURCE_MODEL column is not present in SOURCE sub-table"
5091 0 : << LogIO::POST;
5092 : }
5093 : else
5094 : {
5095 2 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
5096 : << "Requested to make virtual MODEL_DATA column real but "
5097 : << "SOURCE_MODEL column is not present in SOURCE sub-table"
5098 2 : << LogIO::POST;
5099 : }
5100 : }
5101 :
5102 : // Unset makeVirtualModelColReal_p as virtual MODEL col. is not available
5103 1203 : makeVirtualModelColReal_p = false;
5104 : }
5105 :
5106 :
5107 : // LAG_DATA
5108 1922 : if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::LAG_DATA)))
5109 : {
5110 0 : lagDataColumnAvailable_p = true;
5111 : }
5112 :
5113 1922 : return;
5114 : }
5115 :
5116 : // -----------------------------------------------------------------------
5117 : // Method to check which data columns have to be filled
5118 : // -----------------------------------------------------------------------
5119 1922 : void MSTransformManager::checkDataColumnsToFill()
5120 : {
5121 1922 : dataColMap_p.clear();
5122 1922 : bool mainColSet=false;
5123 1922 : timeAvgOptions_p = vi::AveragingOptions(vi::AveragingOptions::Nothing);
5124 :
5125 1922 : if (datacolumn_p.contains("ALL"))
5126 : {
5127 386 : if (dataColumnAvailable_p)
5128 : {
5129 382 : if (!mainColSet)
5130 : {
5131 382 : mainColumn_p = MS::DATA;
5132 382 : mainColSet = true;
5133 : }
5134 382 : dataColMap_p[MS::DATA] = MS::DATA;
5135 382 : colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
5136 :
5137 382 : timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
5138 382 : timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
5139 : }
5140 :
5141 386 : if (correctedDataColumnAvailable_p)
5142 : {
5143 204 : if (!mainColSet)
5144 : {
5145 4 : mainColumn_p = MS::CORRECTED_DATA;
5146 4 : mainColSet = true;
5147 : }
5148 204 : dataColMap_p[MS::CORRECTED_DATA] = MS::CORRECTED_DATA;
5149 204 : colCheckInfo(MS::columnName(MS::CORRECTED_DATA),MS::columnName(dataColMap_p[MS::CORRECTED_DATA]));
5150 :
5151 204 : timeAvgOptions_p |= vi::AveragingOptions::AverageCorrected;
5152 204 : timeAvgOptions_p |= vi::AveragingOptions::CorrectedFlagWeightAvgFromWEIGHT;
5153 : }
5154 386 : if (dataColumnAvailable_p && correctedDataColumnAvailable_p)
5155 200 : bothDataColumnsAreOutput_p = true;
5156 :
5157 :
5158 386 : if (modelDataColumnAvailable_p)
5159 : {
5160 181 : if (!mainColSet)
5161 : {
5162 0 : mainColumn_p = MS::MODEL_DATA;
5163 0 : mainColSet = true;
5164 : }
5165 181 : dataColMap_p[MS::MODEL_DATA] = MS::MODEL_DATA;
5166 181 : colCheckInfo(MS::columnName(MS::MODEL_DATA),MS::columnName(dataColMap_p[MS::MODEL_DATA]));
5167 :
5168 181 : timeAvgOptions_p |= vi::AveragingOptions::AverageModel;
5169 :
5170 181 : if (correctedDataColumnAvailable_p)
5171 : {
5172 172 : timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromWEIGHT;
5173 : }
5174 9 : else if (dataColumnAvailable_p)
5175 : {
5176 9 : timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromSIGMA;
5177 : }
5178 : else
5179 : {
5180 0 : timeAvgOptions_p |= vi::AveragingOptions::ModelPlainAvg;
5181 : }
5182 : }
5183 :
5184 386 : if (floatDataColumnAvailable_p)
5185 : {
5186 4 : if (!mainColSet)
5187 : {
5188 0 : mainColumn_p = MS::FLOAT_DATA;
5189 0 : mainColSet = true;
5190 : }
5191 4 : dataColMap_p[MS::FLOAT_DATA] = MS::FLOAT_DATA;
5192 4 : colCheckInfo(MS::columnName(MS::FLOAT_DATA),MS::columnName(dataColMap_p[MS::FLOAT_DATA]));
5193 :
5194 4 : timeAvgOptions_p |= vi::AveragingOptions::AverageFloat;
5195 : }
5196 :
5197 386 : if (lagDataColumnAvailable_p)
5198 : {
5199 0 : if (!mainColSet)
5200 : {
5201 0 : mainColumn_p = MS::LAG_DATA;
5202 0 : mainColSet = true;
5203 : }
5204 0 : dataColMap_p[MS::LAG_DATA] = MS::LAG_DATA;
5205 0 : colCheckInfo(MS::columnName(MS::LAG_DATA),MS::columnName(dataColMap_p[MS::LAG_DATA]));
5206 :
5207 : // TODO: LAG_DATA is not yet supported by TVI
5208 : // timeAvgOptions_p |= vi::AveragingOptions::AverageLagData;
5209 : }
5210 : }
5211 1536 : else if (datacolumn_p.contains("DATA,MODEL,CORRECTED"))
5212 : {
5213 3 : if (dataColumnAvailable_p)
5214 : {
5215 3 : if (!mainColSet)
5216 : {
5217 3 : mainColumn_p = MS::DATA;
5218 3 : mainColSet = true;
5219 : }
5220 3 : dataColMap_p[MS::DATA] = MS::DATA;
5221 3 : colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
5222 :
5223 3 : timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
5224 3 : timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
5225 : }
5226 :
5227 3 : if (correctedDataColumnAvailable_p)
5228 : {
5229 3 : if (!mainColSet)
5230 : {
5231 0 : mainColumn_p = MS::CORRECTED_DATA;
5232 0 : mainColSet = true;
5233 : }
5234 3 : dataColMap_p[MS::CORRECTED_DATA] = MS::CORRECTED_DATA;
5235 3 : colCheckInfo(MS::columnName(MS::CORRECTED_DATA),MS::columnName(dataColMap_p[MS::CORRECTED_DATA]));
5236 :
5237 3 : timeAvgOptions_p |= vi::AveragingOptions::AverageCorrected;
5238 3 : timeAvgOptions_p |= vi::AveragingOptions::CorrectedFlagWeightAvgFromWEIGHT;
5239 : }
5240 :
5241 3 : if (dataColumnAvailable_p && correctedDataColumnAvailable_p)
5242 3 : bothDataColumnsAreOutput_p = true;
5243 3 : if (modelDataColumnAvailable_p)
5244 : {
5245 3 : if (!mainColSet)
5246 : {
5247 0 : mainColumn_p = MS::MODEL_DATA;
5248 0 : mainColSet = true;
5249 : }
5250 3 : dataColMap_p[MS::MODEL_DATA] = MS::MODEL_DATA;
5251 3 : colCheckInfo(MS::columnName(MS::MODEL_DATA),MS::columnName(dataColMap_p[MS::MODEL_DATA]));
5252 :
5253 3 : timeAvgOptions_p |= vi::AveragingOptions::AverageModel;
5254 :
5255 3 : if (correctedDataColumnAvailable_p)
5256 : {
5257 3 : timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromWEIGHT;
5258 : }
5259 0 : else if (dataColumnAvailable_p)
5260 : {
5261 0 : timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromSIGMA;
5262 : }
5263 : else
5264 : {
5265 0 : timeAvgOptions_p |= vi::AveragingOptions::ModelPlainAvg;
5266 : }
5267 : }
5268 : }
5269 1533 : else if (datacolumn_p.contains("FLOAT_DATA,DATA"))
5270 : {
5271 :
5272 0 : if (dataColumnAvailable_p)
5273 : {
5274 0 : if (!mainColSet)
5275 : {
5276 0 : mainColumn_p = MS::DATA;
5277 0 : mainColSet = true;
5278 : }
5279 0 : dataColMap_p[MS::DATA] = MS::DATA;
5280 0 : colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
5281 :
5282 0 : timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
5283 0 : timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
5284 : }
5285 : else
5286 : {
5287 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
5288 0 : "DATA column requested but not available in input MS "<< LogIO::POST;
5289 : }
5290 :
5291 0 : if (floatDataColumnAvailable_p)
5292 : {
5293 0 : if (!mainColSet)
5294 : {
5295 0 : mainColumn_p = MS::FLOAT_DATA;
5296 0 : mainColSet = true;
5297 : }
5298 0 : dataColMap_p[MS::FLOAT_DATA] = MS::FLOAT_DATA;
5299 0 : colCheckInfo(MS::columnName(MS::FLOAT_DATA),MS::columnName(dataColMap_p[MS::FLOAT_DATA]));
5300 :
5301 0 : timeAvgOptions_p |= vi::AveragingOptions::AverageFloat;
5302 : }
5303 : else
5304 : {
5305 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
5306 0 : "FLOAT_DATA column requested but not available in input MS "<< LogIO::POST;
5307 : }
5308 : }
5309 1533 : else if (datacolumn_p.contains("FLOAT_DATA"))
5310 : {
5311 471 : if (floatDataColumnAvailable_p)
5312 : {
5313 469 : if (!mainColSet)
5314 : {
5315 469 : mainColumn_p = MS::FLOAT_DATA;
5316 469 : mainColSet = true;
5317 : }
5318 469 : dataColMap_p[MS::FLOAT_DATA] = MS::FLOAT_DATA;
5319 469 : colCheckInfo(MS::columnName(MS::FLOAT_DATA),MS::columnName(dataColMap_p[MS::FLOAT_DATA]));
5320 :
5321 469 : timeAvgOptions_p |= vi::AveragingOptions::AverageFloat;
5322 : }
5323 : else
5324 : {
5325 4 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
5326 4 : "FLOAT_DATA column requested but not available in input MS "<< LogIO::POST;
5327 : }
5328 : }
5329 1062 : else if (datacolumn_p.contains("LAG_DATA,DATA"))
5330 : {
5331 0 : if (dataColumnAvailable_p)
5332 : {
5333 0 : if (!mainColSet)
5334 : {
5335 0 : mainColumn_p = MS::DATA;
5336 0 : mainColSet = true;
5337 : }
5338 0 : dataColMap_p[MS::DATA] = MS::DATA;
5339 0 : colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
5340 :
5341 0 : timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
5342 0 : timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
5343 : }
5344 : else
5345 : {
5346 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
5347 0 : "DATA column requested but not available in input MS "<< LogIO::POST;
5348 : }
5349 :
5350 0 : if (lagDataColumnAvailable_p)
5351 : {
5352 0 : if (!mainColSet)
5353 : {
5354 0 : mainColumn_p = MS::LAG_DATA;
5355 0 : mainColSet = true;
5356 : }
5357 0 : dataColMap_p[MS::LAG_DATA] = MS::LAG_DATA;
5358 0 : colCheckInfo(MS::columnName(MS::LAG_DATA),MS::columnName(dataColMap_p[MS::LAG_DATA]));
5359 :
5360 : // TODO: LAG_DATA is not yet supported by TVI
5361 : // timeAvgOptions_p |= vi::AveragingOptions::AverageLagData;
5362 : }
5363 : else
5364 : {
5365 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
5366 0 : "LAG_DATA column requested but not available in input MS "<< LogIO::POST;
5367 : }
5368 : }
5369 1062 : else if (datacolumn_p.contains("LAG_DATA"))
5370 : {
5371 0 : if (lagDataColumnAvailable_p)
5372 : {
5373 0 : if (!mainColSet)
5374 : {
5375 0 : mainColumn_p = MS::LAG_DATA;
5376 0 : mainColSet = true;
5377 : }
5378 0 : dataColMap_p[MS::LAG_DATA] = MS::LAG_DATA;
5379 0 : colCheckInfo(MS::columnName(MS::LAG_DATA),MS::columnName(dataColMap_p[MS::LAG_DATA]));
5380 :
5381 : // TODO: LAG_DATA is not yet supported by TVI
5382 : // timeAvgOptions_p |= vi::AveragingOptions::AverageLagData;
5383 : }
5384 : else
5385 : {
5386 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
5387 0 : "LAG_DATA column requested but not available in input MS "<< LogIO::POST;
5388 : }
5389 : }
5390 1062 : else if (datacolumn_p.contains("DATA"))
5391 : {
5392 824 : if (dataColumnAvailable_p)
5393 : {
5394 823 : if (!mainColSet)
5395 : {
5396 823 : mainColumn_p = MS::DATA;
5397 823 : mainColSet = true;
5398 : }
5399 823 : dataColMap_p[MS::DATA] = MS::DATA;
5400 823 : colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
5401 :
5402 823 : timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
5403 823 : timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
5404 : }
5405 : else
5406 : {
5407 2 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
5408 2 : "DATA column requested but not available in input MS "<< LogIO::POST;
5409 : }
5410 : }
5411 238 : else if (datacolumn_p.contains("CORRECTED"))
5412 : {
5413 203 : if (correctedDataColumnAvailable_p)
5414 : {
5415 197 : if (!mainColSet)
5416 : {
5417 197 : mainColumn_p = MS::CORRECTED_DATA;
5418 197 : mainColSet = true;
5419 : }
5420 197 : dataColMap_p[MS::CORRECTED_DATA] = MS::DATA;
5421 197 : correctedToData_p = true;
5422 197 : colCheckInfo(MS::columnName(MS::CORRECTED_DATA),MS::columnName(dataColMap_p[MS::CORRECTED_DATA]));
5423 :
5424 197 : timeAvgOptions_p |= vi::AveragingOptions::AverageCorrected;
5425 197 : timeAvgOptions_p |= vi::AveragingOptions::CorrectedFlagWeightAvgFromWEIGHT;
5426 : }
5427 : else
5428 : {
5429 12 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
5430 12 : "CORRECTED_DATA column requested but not available in input MS "<< LogIO::POST;
5431 : }
5432 : }
5433 35 : else if (datacolumn_p.contains("MODEL"))
5434 : {
5435 :
5436 35 : if (modelDataColumnAvailable_p)
5437 : {
5438 33 : if (!mainColSet)
5439 : {
5440 33 : mainColumn_p = MS::MODEL_DATA;
5441 33 : mainColSet = true;
5442 : }
5443 :
5444 33 : dataColMap_p[MS::MODEL_DATA] = MS::DATA;
5445 33 : colCheckInfo(MS::columnName(MS::MODEL_DATA),MS::columnName(dataColMap_p[MS::MODEL_DATA]));
5446 33 : timeAvgOptions_p |= vi::AveragingOptions::AverageModel;
5447 33 : timeAvgOptions_p |= vi::AveragingOptions::ModelPlainAvg;
5448 : }
5449 : else
5450 : {
5451 4 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
5452 4 : "MODEL_DATA column requested but not available in input MS "<< LogIO::POST;
5453 : }
5454 : }
5455 0 : else if (datacolumn_p.contains("NONE") and userBufferMode_p)
5456 : {
5457 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
5458 : << "No datacolumn selected in buffer mode"
5459 0 : << LogIO::POST;
5460 : }
5461 : else
5462 : {
5463 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
5464 0 : << "Requested data column " << datacolumn_p
5465 : << " is not supported, possible choices are ALL,DATA,CORRECTED,MODEL,FLOAT_DATA,LAG_DATA"
5466 0 : << LogIO::POST;
5467 : }
5468 :
5469 1922 : if (produceModel_p) {
5470 3 : const auto colname = (MS::DATA == mainColumn_p) ? "DATA" : "CORRECTED_DATA";
5471 6 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
5472 : << "Will produce a MODEL_DATA column in the output MS, "
5473 : << "with the fit calculated for input " << colname
5474 6 : << LogIO::POST;
5475 3 : dataColMap_p[MS::MODEL_DATA] = mainColumn_p;
5476 : }
5477 :
5478 : // Add shortcuts to be used in the context of WeightSpectrum related transformations
5479 1922 : dataColMap::iterator iter;
5480 :
5481 : // Check if we are doing DATA
5482 1922 : iter = dataColMap_p.find(MS::DATA);
5483 1922 : if (iter != dataColMap_p.end()) doingData_p = true;
5484 :
5485 : // Check if we are doing CORRECTED_DATA
5486 1922 : iter = dataColMap_p.find(MS::CORRECTED_DATA);
5487 1922 : if (iter != dataColMap_p.end()) doingCorrected_p = true;
5488 :
5489 : // Check if we are doing MODEL_DATA
5490 1922 : iter = dataColMap_p.find(MS::MODEL_DATA);
5491 1922 : if (iter != dataColMap_p.end()) doingModel_p = true;
5492 :
5493 3844 : return;
5494 : }
5495 :
5496 :
5497 : // -----------------------------------------------------------------------
5498 : //
5499 : // -----------------------------------------------------------------------
5500 2302 : void MSTransformManager::colCheckInfo(const String& inputColName, const String& outputColName)
5501 : {
5502 2302 : if (inputMs_p->tableDesc().isColumn(inputColName))
5503 : {
5504 2292 : if (not bufferMode_p)
5505 : {
5506 4584 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
5507 : << "Adding " << outputColName << " column to output MS from input " << inputColName<< " column"
5508 4584 : << LogIO::POST;
5509 : }
5510 : else
5511 : {
5512 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
5513 : << inputColName << " column present in input MS will be available from MSTransformBuffer"
5514 0 : << LogIO::POST;
5515 : }
5516 : }
5517 : else
5518 : {
5519 10 : if (not bufferMode_p)
5520 : {
5521 20 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
5522 : << "Adding " << outputColName << " column to output MS from input virtual " << inputColName<< " column"
5523 20 : << LogIO::POST;
5524 : }
5525 : else
5526 : {
5527 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
5528 : << "Virtual " << inputColName << " column present in input MS will be available from MSTransformBuffer"
5529 0 : << LogIO::POST;
5530 : }
5531 : }
5532 :
5533 2302 : return;
5534 : }
5535 :
5536 :
5537 : // -----------------------------------------------------------------------
5538 : // Method to determine sort columns order
5539 : // -----------------------------------------------------------------------
5540 1140 : void MSTransformManager::setIterationApproach()
5541 : {
5542 1140 : uInt nSortColumns = 7;
5543 :
5544 1140 : if (timespan_p.contains("scan")) nSortColumns -= 1;
5545 1140 : if (timespan_p.contains("state")) nSortColumns -= 1;
5546 1140 : if (timespan_p.contains("field")) nSortColumns -= 1;
5547 1140 : if ((combinespws_p) || (spwAverage_p)) nSortColumns -= 1;
5548 :
5549 1140 : sortColumns_p = Block<Int>(nSortColumns);
5550 1140 : uInt sortColumnIndex = 0;
5551 :
5552 1140 : sortColumns_p[0] = MS::OBSERVATION_ID;
5553 1140 : sortColumnIndex += 1;
5554 :
5555 1140 : sortColumns_p[1] = MS::ARRAY_ID;
5556 1140 : sortColumnIndex += 1;
5557 :
5558 1140 : if (!timespan_p.contains("scan"))
5559 : {
5560 1086 : sortColumns_p[sortColumnIndex] = MS::SCAN_NUMBER;
5561 1086 : sortColumnIndex += 1;
5562 : }
5563 : else
5564 : {
5565 108 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
5566 108 : << "Combining data through scans for time average " << LogIO::POST;
5567 : }
5568 :
5569 1140 : if (!timespan_p.contains("state"))
5570 : {
5571 1133 : sortColumns_p[sortColumnIndex] = MS::STATE_ID;
5572 1133 : sortColumnIndex += 1;
5573 : }
5574 : else
5575 : {
5576 14 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
5577 14 : << "Combining data through state for time average" << LogIO::POST;
5578 : }
5579 :
5580 1140 : if (!timespan_p.contains("field"))
5581 : {
5582 1140 : sortColumns_p[sortColumnIndex] = MS::FIELD_ID;
5583 1140 : sortColumnIndex += 1;
5584 : }
5585 : else
5586 : {
5587 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
5588 0 : << "Combining data through field time average" << LogIO::POST;
5589 : }
5590 :
5591 1140 : if ((!combinespws_p) && (!spwAverage_p))
5592 : {
5593 1050 : sortColumns_p[sortColumnIndex] = MS::DATA_DESC_ID;
5594 1050 : sortColumnIndex += 1;
5595 : }
5596 : else
5597 : {
5598 180 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
5599 180 : << "Combining data from selected spectral windows" << LogIO::POST;
5600 : }
5601 :
5602 1140 : sortColumns_p[sortColumnIndex] = MS::TIME;
5603 :
5604 1140 : return;
5605 : }
5606 :
5607 :
5608 : // -----------------------------------------------------------------------
5609 : // Method to generate the initial iterator
5610 : // -----------------------------------------------------------------------
5611 1895 : void MSTransformManager::generateIterator()
5612 : {
5613 1895 : bool isWritable = false;
5614 1895 : if (interactive_p) isWritable = true;
5615 :
5616 : // Prepare time average parameters (common for all cases)
5617 1895 : std::shared_ptr<vi::AveragingParameters> timeavgParams = nullptr;
5618 1895 : if (timeAverage_p)
5619 : {
5620 202 : if (maxuvwdistance_p > 0)
5621 : {
5622 1 : timeAvgOptions_p |= vi::AveragingOptions::BaselineDependentAveraging;
5623 : }
5624 :
5625 : timeavgParams = std::make_shared<vi::AveragingParameters>
5626 404 : (timeBin_p, .0, vi::SortColumns(sortColumns_p, false),
5627 606 : timeAvgOptions_p, maxuvwdistance_p, nullptr, isWritable, dx_p, dy_p);
5628 : }
5629 :
5630 : // Calibrating VI
5631 1895 : if (uvcontsub_p)
5632 : {
5633 : // First determine number of layers
5634 54 : uInt nTVIs = 1;
5635 54 : if (timeAverage_p) nTVIs++;
5636 54 : if (uvcontsub_p) nTVIs++;
5637 :
5638 : // Init vector of TVI factories and populate it
5639 54 : uInt TVIFactoryIdx = 0;
5640 54 : Vector<vi::ViiLayerFactory*> TVIFactories(nTVIs);
5641 :
5642 : // Data layer
5643 54 : vi::IteratingParameters ipar(timeBin_p,vi::SortColumns(sortColumns_p, false));
5644 54 : vi::VisIterImpl2LayerFactory dataLayerTVIFactory(selectedInputMs_p,ipar,isWritable);
5645 54 : TVIFactories[TVIFactoryIdx]=&dataLayerTVIFactory;
5646 54 : TVIFactoryIdx++;
5647 :
5648 : // Time avg. layer
5649 54 : std::unique_ptr<vi::AveragingVi2LayerFactory> timeAverageTVIFactory;
5650 54 : if (timeAverage_p)
5651 : {
5652 0 : timeAverageTVIFactory.reset(new vi::AveragingVi2LayerFactory(*timeavgParams));
5653 0 : TVIFactories[TVIFactoryIdx]=timeAverageTVIFactory.get();
5654 0 : TVIFactoryIdx++;
5655 : }
5656 :
5657 : // UVContSub layer
5658 54 : std::unique_ptr<vi::UVContSubTVILayerFactory> uvContSubTVIFactory;
5659 54 : if (uvcontsub_p)
5660 : {
5661 : // needed for warning to prevent confusion with old uvcontsub!
5662 54 : uvcontsubRec_p.define("allowed_spws", spwSelection_p);
5663 54 : uvContSubTVIFactory.reset(new vi::UVContSubTVILayerFactory (uvcontsubRec_p));
5664 54 : TVIFactories[TVIFactoryIdx]=uvContSubTVIFactory.get();
5665 54 : TVIFactoryIdx++;
5666 : }
5667 :
5668 54 : visibilityIterator_p = new vi::VisibilityIterator2 (TVIFactories);
5669 :
5670 88 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
5671 88 : << "TVI chain is " << visibilityIterator_p->ViiType() << LogIO::POST;
5672 94 : }
5673 1841 : else if (calibrate_p || scalarAverage_p)
5674 : {
5675 : try
5676 : {
5677 : // Isolate iteration parameters
5678 9 : vi::IteratingParameters iterpar;
5679 9 : if (scalarAverage_p)
5680 0 : iterpar = vi::IteratingParameters(timeBin_p,vi::SortColumns(sortColumns_p, false));
5681 : else
5682 9 : iterpar = vi::IteratingParameters(0,vi::SortColumns(sortColumns_p, false));
5683 :
5684 : // By callib String
5685 9 : if (callib_p.length() > 0)
5686 : {
5687 0 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
5688 : << "OTF calibration activated, using calibration file spec to generate iterator"
5689 0 : << LogIO::POST;
5690 :
5691 0 : visibilityIterator_p = new vi::VisibilityIterator2(vi::LayeredVi2Factory(selectedInputMs_p, &iterpar,callib_p, timeavgParams.get()));
5692 : }
5693 : // By callib Record
5694 9 : else if (callibRec_p.nfields() > 0)
5695 : {
5696 18 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
5697 : << "OTF calibration activated, using calibration record spec to generate iterator"
5698 18 : << LogIO::POST;
5699 :
5700 9 : visibilityIterator_p = new vi::VisibilityIterator2(vi::LayeredVi2Factory(selectedInputMs_p, &iterpar,callibRec_p, timeavgParams.get()));
5701 : }
5702 : else // scalar
5703 : {
5704 0 : visibilityIterator_p = new vi::VisibilityIterator2(vi::LayeredVi2Factory(selectedInputMs_p, &iterpar));
5705 : }
5706 9 : }
5707 0 : catch (const MSSelectionError &x)
5708 : {
5709 0 : delete visibilityIterator_p;
5710 :
5711 0 : correctedDataColumnAvailable_p = false;
5712 0 : checkDataColumnsToFill();
5713 :
5714 : // Averaging VI
5715 0 : if (timeAverage_p && !tviphaseshift_p)
5716 : {
5717 0 : visibilityIterator_p = new vi::VisibilityIterator2(vi::AveragingVi2Factory(*timeavgParams, selectedInputMs_p));
5718 : }
5719 : // Polarization Averaging VI
5720 0 : else if (polAverage_p) {
5721 0 : visibilityIterator_p = new vi::VisibilityIterator2(vi::PolAverageVi2Factory(polAverageConfig_p, selectedInputMs_p,
5722 0 : vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
5723 : }
5724 : // Pointings Interpolator VI
5725 0 : else if (pointingsInterpolation_p) {
5726 0 : visibilityIterator_p = new vi::VisibilityIterator2(vi::PointingInterpolationVi2Factory(pointingsInterpolationConfig_p, selectedInputMs_p,
5727 0 : vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
5728 : }
5729 : // CAS-12706 To run phase shift via a TVI which has
5730 : // support for shifting across large offset/angles
5731 0 : else if (tviphaseshift_p) {
5732 :
5733 : // First determine number of layers
5734 0 : uInt nTVIs = (timeAverage_p ? 3 : 2);
5735 :
5736 : // Init vector of TVI factories and populate it
5737 0 : uInt TVIFactoryIdx = 0;
5738 0 : Vector<vi::ViiLayerFactory*> TVIFactories(nTVIs);
5739 :
5740 : // Data layer
5741 0 : vi::IteratingParameters ipar(timeBin_p,vi::SortColumns(sortColumns_p, false));
5742 0 : vi::VisIterImpl2LayerFactory dataLayerTVIFactory(selectedInputMs_p,ipar,isWritable);
5743 0 : TVIFactories[TVIFactoryIdx++]=&dataLayerTVIFactory;
5744 :
5745 : // Time avg. layer
5746 0 : std::unique_ptr<vi::AveragingVi2LayerFactory> timeAverageTVIFactory;
5747 0 : if (timeAverage_p)
5748 : {
5749 0 : timeAverageTVIFactory.reset(new vi::AveragingVi2LayerFactory(*timeavgParams));
5750 0 : TVIFactories[TVIFactoryIdx++]=timeAverageTVIFactory.get();
5751 : }
5752 :
5753 : // Phaseshift layer
5754 0 : vi::PhaseShiftingTVILayerFactory phaseShiftingTVILayerFactory(tviphaseshiftConfig_p);
5755 0 : TVIFactories[TVIFactoryIdx]=&phaseShiftingTVILayerFactory;
5756 :
5757 0 : visibilityIterator_p = new vi::VisibilityIterator2 (TVIFactories);
5758 0 : }
5759 : // Plain VI
5760 : else
5761 : {
5762 0 : visibilityIterator_p = new vi::VisibilityIterator2(*selectedInputMs_p,vi::SortColumns(sortColumns_p, false),
5763 0 : isWritable, NULL, timeBin_p);
5764 : }
5765 0 : }
5766 0 : catch (const AipsError &x)
5767 : {
5768 0 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager",__FUNCTION__)
5769 : << "Error initializing calibration VI: " << x.getMesg()
5770 0 : << LogIO::POST;
5771 0 : throw(x);
5772 0 : }
5773 9 : }
5774 : // Averaging VI
5775 1832 : else if (timeAverage_p && !tviphaseshift_p)
5776 : {
5777 202 : visibilityIterator_p = new vi::VisibilityIterator2(vi::AveragingVi2Factory(*timeavgParams, selectedInputMs_p));
5778 : }
5779 : // Polarization Averaging VI
5780 1630 : else if (polAverage_p) {
5781 12 : visibilityIterator_p = new vi::VisibilityIterator2(vi::PolAverageVi2Factory(polAverageConfig_p, selectedInputMs_p,
5782 18 : vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
5783 : }
5784 : // VI interpolating pointing directions
5785 1624 : else if (pointingsInterpolation_p) {
5786 0 : visibilityIterator_p = new vi::VisibilityIterator2(vi::PointingInterpolationVi2Factory(pointingsInterpolationConfig_p, selectedInputMs_p,
5787 0 : vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
5788 : }
5789 : // CAS-12706 To run phase shift via a TVI which has
5790 : // support for shifting across large offset/angles
5791 1624 : else if (tviphaseshift_p) {
5792 :
5793 : // First determine number of layers
5794 87 : uInt nTVIs = (timeAverage_p ? 3 : 2);
5795 :
5796 : // Init vector of TVI factories and populate it
5797 87 : uInt TVIFactoryIdx = 0;
5798 87 : Vector<vi::ViiLayerFactory*> TVIFactories(nTVIs);
5799 :
5800 : // Data layer
5801 87 : vi::IteratingParameters ipar(timeBin_p,vi::SortColumns(sortColumns_p, false));
5802 87 : vi::VisIterImpl2LayerFactory dataLayerTVIFactory(selectedInputMs_p,ipar,isWritable);
5803 87 : TVIFactories[TVIFactoryIdx++]=&dataLayerTVIFactory;
5804 :
5805 : // Time avg. layer
5806 87 : std::unique_ptr<vi::AveragingVi2LayerFactory> timeAverageTVIFactory;
5807 87 : if (timeAverage_p)
5808 : {
5809 0 : timeAverageTVIFactory.reset(new vi::AveragingVi2LayerFactory(*timeavgParams));
5810 0 : TVIFactories[TVIFactoryIdx++]=timeAverageTVIFactory.get();
5811 : }
5812 :
5813 : // Phaseshift layer
5814 87 : vi::PhaseShiftingTVILayerFactory phaseShiftingTVILayerFactory(tviphaseshiftConfig_p);
5815 87 : TVIFactories[TVIFactoryIdx]=&phaseShiftingTVILayerFactory;
5816 :
5817 87 : visibilityIterator_p = new vi::VisibilityIterator2 (TVIFactories);
5818 91 : }
5819 : // Offline ATM correction
5820 1537 : else if (doAtmCor_p) {
5821 56 : visibilityIterator_p = new vi::VisibilityIterator2(
5822 28 : vi::SDAtmosphereCorrectionVi2Factory(
5823 56 : atmCorConfig_p, selectedInputMs_p, vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable
5824 : )
5825 28 : );
5826 : }
5827 : // Plain VI
5828 : else
5829 : {
5830 3018 : visibilityIterator_p = new vi::VisibilityIterator2(*selectedInputMs_p,vi::SortColumns(sortColumns_p, false),
5831 1509 : isWritable, NULL, timeBin_p);
5832 : }
5833 :
5834 1884 : if (timeAverage_p) visibilityIterator_p->setWeightScaling(vi::WeightScaling::generateUnityWeightScaling());
5835 1884 : if (channelSelector_p != NULL) visibilityIterator_p->setFrequencySelection(*channelSelector_p);
5836 :
5837 3768 : return;
5838 1895 : }
5839 :
5840 :
5841 : // -----------------------------------------------------------------------
5842 : //
5843 : // -----------------------------------------------------------------------
5844 349819 : void MSTransformManager::setupBufferTransformations(vi::VisBuffer2 *vb)
5845 : {
5846 : // Calculate number of rows to add to the output MS depending on the combination parameters
5847 349819 : uInt rowsToAdd = 0;
5848 :
5849 349819 : if ((combinespws_p) or (nspws_p > 1))
5850 : {
5851 : // Fill baseline map using as key Ant1,Ant2,Scan and State,
5852 : // Which are the elements that can be combined in one chunk
5853 7952 : rowIndex_p.clear();
5854 7952 : baselineMap_p.clear();
5855 7952 : Vector<Int> antenna1 = vb->antenna1();
5856 7952 : Vector<Int> antenna2 = vb->antenna2();
5857 7952 : Vector<Int> scan = vb->scan();
5858 7952 : Vector<Int> state = vb->stateId();
5859 7952 : Int relativeTimeInMiliseconds = 0;
5860 1191825 : for (uInt row=0;row<antenna1.size();row++)
5861 : {
5862 1183873 : pair<uInt,uInt> baseline = std::make_pair(antenna1(row),antenna2(row));
5863 1183873 : relativeTimeInMiliseconds = (Int)floor(1E3*(vb->time()(row) - vb->time()(0)));
5864 1183873 : pair< pair<uInt,uInt>, uInt > baselineTime = std::make_pair(baseline,relativeTimeInMiliseconds);
5865 :
5866 : // Fill row index vector with to the first row for every element in the baseline map
5867 1183873 : if (baselineMap_p.find(baselineTime) == baselineMap_p.end())
5868 : {
5869 516343 : rowIndex_p.push_back(row);
5870 : }
5871 :
5872 1183873 : baselineMap_p[baselineTime].push_back(row);
5873 :
5874 : }
5875 :
5876 7952 : rowsToAdd = baselineMap_p.size();
5877 :
5878 : // Fill row index vector with to the first row for every element in the baseline map
5879 : // jagonzal (CAS-8492): For SPW separation only we don't
5880 : // follow the baselineMap order but the input order
5881 7952 : if (combinespws_p)
5882 : {
5883 7234 : uInt rowIndex = 0;
5884 7234 : rowIndex_p.clear();
5885 518402 : for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
5886 : {
5887 511168 : rowIndex_p.push_back((iter->second)[0]);
5888 511168 : rowIndex ++;
5889 : }
5890 : }
5891 7952 : }
5892 : else
5893 : {
5894 341867 : rowsToAdd = vb->nRows();
5895 : }
5896 :
5897 : // Initialize reference frame transformation parameters
5898 349819 : if (refFrameTransformation_p)
5899 : {
5900 1798 : initFrequencyTransGrid(vb);
5901 : }
5902 :
5903 : // Calculate total number for rows to add
5904 349819 : nRowsToAdd_p = rowsToAdd*nspws_p;
5905 :
5906 349819 : return;
5907 :
5908 : }
5909 :
5910 : // -----------------------------------------------------------------------
5911 : // Fill output MS with data from an input VisBuffer
5912 : // -----------------------------------------------------------------------
5913 347959 : void MSTransformManager::fillOutputMs(vi::VisBuffer2 *vb)
5914 : {
5915 347959 : setupBufferTransformations(vb);
5916 :
5917 347959 : if (not bufferMode_p)
5918 : {
5919 : // Create RowRef object to fill new rows
5920 347959 : auto currentRows = outputMs_p->nrow();
5921 347959 : RefRows rowRef( currentRows, currentRows + nRowsToAdd_p/nspws_p - 1);
5922 :
5923 : // Add new rows to output MS
5924 347959 : outputMs_p->addRow(nRowsToAdd_p,false);
5925 :
5926 : // Fill new rows
5927 347959 : weightSpectrumFlatFilled_p = false;
5928 347959 : weightSpectrumFromSigmaFilled_p = false;
5929 347959 : fillWeightCols(vb,rowRef);
5930 347959 : fillDataCols(vb,rowRef);
5931 347959 : fillIdCols(vb,rowRef);
5932 347959 : }
5933 :
5934 347959 : return;
5935 : }
5936 :
5937 : // -----------------------------------------------------------------------
5938 : // Method to initialize the input frequency grid to change reference frame
5939 : // -----------------------------------------------------------------------
5940 1798 : void MSTransformManager::initFrequencyTransGrid(vi::VisBuffer2 *vb)
5941 : {
5942 : // NOTE (jagonzal): According to dpetry the difference between times is negligible but he recommends to use TIME
5943 : // However it does not cross-validate unless we use timeMeas from the MS columns
5944 1798 : ScalarMeasColumn<MEpoch> mainTimeMeasCol = selectedInputMsCols_p->timeMeas();
5945 1798 : MEpoch currentRowTime = mainTimeMeasCol(vb->rowIds()(0));
5946 :
5947 : // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
5948 1798 : MDoppler radVelCorr;
5949 1798 : MDirection inputFieldDirection;
5950 1798 : bool radVelSignificant = false;
5951 1798 : if (radialVelocityCorrection_p && inputMSFieldCols_p->needInterTime(vb->fieldId()(0)))
5952 : {
5953 254 : MRadialVelocity mRV = inputMSFieldCols_p->radVelMeas(vb->fieldId()(0),vb->time()(0));
5954 254 : Quantity mrv = mRV.get("m/s");
5955 254 : Quantity offsetMrv = radialVelocity_p.get("m/s"); // the radvel by which the out SPW def was shifted
5956 254 : radVelCorr = MDoppler(mrv-(Quantity(2.)*offsetMrv));
5957 254 : if (fabs(mrv.getValue()) > 1E-6) radVelSignificant = true;
5958 :
5959 254 : inputFieldDirection = inputMSFieldCols_p->phaseDirMeas(vb->fieldId()(0), vb->time()(0));
5960 254 : }
5961 : else
5962 : {
5963 1544 : inputFieldDirection = vb->phaseCenter();
5964 : }
5965 :
5966 1798 : MFrequency::Ref inputFrameRef = MFrequency::Ref(inputReferenceFrame_p,
5967 1798 : MeasFrame(inputFieldDirection, observatoryPosition_p, currentRowTime));
5968 :
5969 1798 : MFrequency::Ref outputFrameRef;
5970 3596 : outputFrameRef = MFrequency::Ref(outputReferenceFrame_p,
5971 5394 : MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
5972 :
5973 1798 : freqTransEngine_p = MFrequency::Convert(MSTransformations::Hz, inputFrameRef, outputFrameRef);
5974 :
5975 1798 : Int spwIndex = 0;
5976 1798 : if (not combinespws_p)
5977 : {
5978 : // jagonzal : It is not necessary to map spwIndex because we
5979 : // pass the original SPWId down to the interpol1D method
5980 879 : spwIndex = vb->spectralWindows()(0);
5981 : }
5982 :
5983 :
5984 1798 : if (fftShiftEnabled_p)
5985 : {
5986 425 : uInt centralChan = inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ.size()/2;
5987 :
5988 425 : Double oldCentralFrequencyBeforeRegridding = inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ[centralChan];
5989 : Double newCentralFrequencyBeforeRegriddingAtCurrentTime =
5990 425 : freqTransEngine_p(oldCentralFrequencyBeforeRegridding).get(MSTransformations::Hz).getValue();
5991 :
5992 : // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
5993 425 : if (radVelSignificant)
5994 : {
5995 0 : Vector<Double> tmp(1,newCentralFrequencyBeforeRegriddingAtCurrentTime);
5996 0 : newCentralFrequencyBeforeRegriddingAtCurrentTime = radVelCorr.shiftFrequency(tmp)(0);
5997 0 : }
5998 :
5999 425 : Double newCentralFrequencyBeforeRegriddingAtReferenceTime = inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[centralChan];
6000 425 : Double absoluteShift = newCentralFrequencyBeforeRegriddingAtCurrentTime - newCentralFrequencyBeforeRegriddingAtReferenceTime;
6001 :
6002 425 : Double chanWidth = inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[1] - inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[0];
6003 425 : Double bandwidth = inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[inputOutputSpwMap_p[spwIndex].second.NUM_CHAN-1] - inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[0];
6004 425 : bandwidth += chanWidth;
6005 :
6006 425 : fftShift_p = - absoluteShift / bandwidth;
6007 :
6008 425 : ostringstream current;
6009 425 : current << setprecision(numeric_limits<double>::max_digits10)
6010 425 : << newCentralFrequencyBeforeRegriddingAtCurrentTime;
6011 425 : ostringstream reference;
6012 425 : reference << setprecision(numeric_limits<double>::max_digits10)
6013 425 : << newCentralFrequencyBeforeRegriddingAtReferenceTime;
6014 850 : logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
6015 : << "Using fftshift interpolation. The absolute shift is the "
6016 : << "new central frequency at current (input SPW) time - new "
6017 : << "central frequency "
6018 : << "at reference (output SPW) time\nAbsolute shift: "
6019 : << current
6020 : << " - " << reference
6021 : << " = " << absoluteShift << ", bandwidth " << bandwidth
6022 850 : << ", relative shift: " << fftShift_p << LogIO::POST;
6023 :
6024 425 : }
6025 : else
6026 : {
6027 486559 : for(uInt chan_idx=0; chan_idx<inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ.size(); chan_idx++)
6028 : {
6029 485186 : inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[chan_idx] =
6030 970372 : freqTransEngine_p(inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ[chan_idx]).get(MSTransformations::Hz).getValue();
6031 : }
6032 :
6033 : /*
6034 : ostringstream oss;
6035 : oss.precision(30);
6036 : oss << " field direction input frame=" << inputFieldDirection << endl;
6037 : oss << " input frame=" << inputFrameRef << endl;
6038 : oss << " field direction output frame=" << phaseCenter_p << endl;
6039 : oss << " output frame=" << outputFrameRef << endl;
6040 : oss << " transformation engine=" << freqTransEngine_p << endl;
6041 : oss << " before transformation=" << inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ[0] << endl;
6042 : oss << " after transformation=" << inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[0] << endl;
6043 : */
6044 :
6045 :
6046 1373 : if (radVelSignificant)
6047 : {
6048 254 : inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux =
6049 508 : radVelCorr.shiftFrequency(inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux);
6050 :
6051 : /*
6052 : oss << " correction engine=" << radVelCorr << endl;
6053 : oss << " after radial velocity correction=" << inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[0] << endl;
6054 : */
6055 : }
6056 :
6057 : //logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__) << oss.str() << LogIO::POST;
6058 : }
6059 :
6060 3596 : return;
6061 1798 : }
6062 :
6063 : // ----------------------------------------------------------------------------------------
6064 : // Fill auxiliary (meta data) columns which don't depend on the SPW (merely consist of Ids)
6065 : // ----------------------------------------------------------------------------------------
6066 349819 : void MSTransformManager::fillIdCols(vi::VisBuffer2 *vb,RefRows &rowRef)
6067 : {
6068 : // Declare common auxiliary variables
6069 349819 : RefRows absoluteRefRows(rowRef.firstRow(),rowRef.firstRow()+nRowsToAdd_p-1);
6070 349819 : Vector<Int> tmpVectorInt(nRowsToAdd_p,0);
6071 349819 : Vector<Double> tmpVectorDouble(nRowsToAdd_p,0.0);
6072 349819 : Vector<bool> tmpVectorbool(nRowsToAdd_p,false);
6073 :
6074 : // Special case for Data description Id
6075 349819 : if (transformDDIVector(vb->dataDescriptionIds(),tmpVectorInt))
6076 : {
6077 321907 : outputMsCols_p->dataDescId().putColumnCells(absoluteRefRows,tmpVectorInt);
6078 : }
6079 : else
6080 : {
6081 27912 : outputMsCols_p->dataDescId().putColumnCells(absoluteRefRows,vb->dataDescriptionIds());
6082 : }
6083 :
6084 : // Re-indexable Columns
6085 349819 : transformAndWriteReindexableVector(vb->observationId(),tmpVectorInt,true,
6086 349819 : inputOutputObservationIndexMap_p,
6087 349819 : outputMsCols_p->observationId(),absoluteRefRows);
6088 349819 : transformAndWriteReindexableVector(vb->arrayId(),tmpVectorInt,true,
6089 349819 : inputOutputArrayIndexMap_p,
6090 349819 : outputMsCols_p->arrayId(),absoluteRefRows);
6091 349819 : transformAndWriteReindexableVector(vb->fieldId(),tmpVectorInt,!timespan_p.contains("field"),
6092 349819 : inputOutputFieldIndexMap_p,
6093 349819 : outputMsCols_p->fieldId(),absoluteRefRows);
6094 349819 : transformAndWriteReindexableVector(vb->stateId(),tmpVectorInt,!timespan_p.contains("state"),
6095 349819 : inputOutputScanIntentIndexMap_p,
6096 349819 : outputMsCols_p->stateId(),absoluteRefRows);
6097 349819 : transformAndWriteReindexableVector(vb->antenna1(),tmpVectorInt,false,
6098 349819 : inputOutputAntennaIndexMap_p,
6099 349819 : outputMsCols_p->antenna1(),absoluteRefRows);
6100 349819 : transformAndWriteReindexableVector(vb->antenna2(),tmpVectorInt,false,
6101 349819 : inputOutputAntennaIndexMap_p,
6102 349819 : outputMsCols_p->antenna2(),absoluteRefRows);
6103 :
6104 : // Not Re-indexable Columns
6105 349819 : transformAndWriteNotReindexableVector(vb->scan(),tmpVectorInt,!timespan_p.contains("scan"),outputMsCols_p->scanNumber(),absoluteRefRows);
6106 349819 : transformAndWriteNotReindexableVector(vb->processorId(),tmpVectorInt,false,outputMsCols_p->processorId(),absoluteRefRows);
6107 349819 : transformAndWriteNotReindexableVector(vb->feed1(),tmpVectorInt,false,outputMsCols_p->feed1(),absoluteRefRows);
6108 349819 : transformAndWriteNotReindexableVector(vb->feed2(),tmpVectorInt,false,outputMsCols_p->feed2(),absoluteRefRows);
6109 349819 : transformAndWriteNotReindexableVector(vb->time(),tmpVectorDouble,false,outputMsCols_p->time(),absoluteRefRows);
6110 349819 : transformAndWriteNotReindexableVector(vb->timeCentroid(),tmpVectorDouble,false,outputMsCols_p->timeCentroid(),absoluteRefRows);
6111 349819 : transformAndWriteNotReindexableVector(vb->timeInterval(),tmpVectorDouble,false,outputMsCols_p->interval(),absoluteRefRows);
6112 :
6113 : // Special case for vectors that have to be averaged
6114 349819 : if (combinespws_p)
6115 : {
6116 7234 : mapAndAverageVector(vb->flagRow(),tmpVectorbool);
6117 7234 : outputMsCols_p->flagRow().putColumnCells(absoluteRefRows, tmpVectorbool);
6118 :
6119 : // jagonzal: We average exposures by default, if they are the same we obtain the same results
6120 7234 : mapAndAverageVector(vb->exposure(),tmpVectorDouble);
6121 7234 : outputMsCols_p->exposure().putColumnCells(absoluteRefRows, tmpVectorDouble);
6122 : }
6123 : else
6124 : {
6125 342585 : transformAndWriteNotReindexableVector(vb->flagRow(),tmpVectorbool,false,outputMsCols_p->flagRow(),absoluteRefRows);
6126 342585 : transformAndWriteNotReindexableVector(vb->exposure(),tmpVectorDouble,false,outputMsCols_p->exposure(),absoluteRefRows);
6127 : }
6128 :
6129 349819 : if (combinespws_p)
6130 : {
6131 7234 : Matrix<Double> tmpUvw(IPosition(2,3,rowRef.nrows()),0.0);
6132 7234 : Matrix<Float> tmpMatrixFloat(IPosition(2,vb->nCorrelations(),rowRef.nrows()),0.0);
6133 :
6134 7234 : mapMatrix(vb->uvw(),tmpUvw);
6135 7234 : writeMatrix(tmpUvw,outputMsCols_p->uvw(),rowRef,nspws_p);
6136 :
6137 : // WEIGHT/SIGMA are defined as the median of WEIGHT_SPECTRUM / SIGMA_SPECTRUM in the case of SPECTRUM transformation
6138 7234 : if (not spectrumTransformation_p)
6139 : {
6140 0 : if (newWeightFactorMap_p.size() > 0)
6141 : {
6142 0 : mapAndScaleMatrix(vb->weight(),tmpMatrixFloat,newWeightFactorMap_p,vb->spectralWindows());
6143 0 : writeMatrix(tmpMatrixFloat,outputMsCols_p->weight(),rowRef,nspws_p);
6144 : }
6145 : else
6146 : {
6147 : // jagonzal: According to dpetry we have to copy weights from the first SPW
6148 : // This is justified since the rows to be combined _must_ be from the
6149 : // same baseline and therefore have the same UVW coordinates in the MS (in meters).
6150 : // They could therefore be regarded to also have the same WEIGHT, at least to
6151 : // a good approximation.
6152 0 : mapMatrix(vb->weight(),tmpMatrixFloat);
6153 0 : writeMatrix(tmpMatrixFloat,outputMsCols_p->weight(),rowRef,nspws_p);
6154 : }
6155 :
6156 :
6157 : // Sigma must be redefined to 1/weight when corrected data becomes data
6158 0 : if (correctedToData_p)
6159 : {
6160 0 : arrayTransformInPlace(tmpMatrixFloat, vi::AveragingTvi2::weightToSigma);
6161 0 : outputMsCols_p->sigma().putColumnCells(rowRef, tmpMatrixFloat);
6162 0 : writeMatrix(tmpMatrixFloat,outputMsCols_p->sigma(),rowRef,nspws_p);
6163 : }
6164 : else
6165 : {
6166 0 : if (newSigmaFactorMap_p.size() > 0)
6167 : {
6168 0 : mapAndScaleMatrix(vb->sigma(),tmpMatrixFloat,newSigmaFactorMap_p,vb->spectralWindows());
6169 0 : outputMsCols_p->sigma().putColumnCells(rowRef, tmpMatrixFloat);
6170 0 : writeMatrix(tmpMatrixFloat,outputMsCols_p->sigma(),rowRef,nspws_p);
6171 : }
6172 : else
6173 : {
6174 : // jagonzal: According to dpetry we have to copy weights from the first SPW
6175 : // This is justified since the rows to be combined _must_ be from the
6176 : // same baseline and therefore have the same UVW coordinates in the MS (in meters).
6177 : // They could therefore be regarded to also have the same WEIGHT, at least to
6178 : // a good approximation.
6179 0 : mapMatrix(vb->sigma(),tmpMatrixFloat);
6180 0 : writeMatrix(tmpMatrixFloat,outputMsCols_p->sigma(),rowRef,nspws_p);
6181 : }
6182 : }
6183 : }
6184 :
6185 7234 : }
6186 : else
6187 : {
6188 342585 : writeMatrix(vb->uvw(),outputMsCols_p->uvw(),rowRef,nspws_p);
6189 :
6190 : // WEIGHT/SIGMA are defined as the median of WEIGHT_SPECTRUM / SIGMA_SPECTRUM in the case of SPECTRUM transformation
6191 342585 : if (not spectrumTransformation_p)
6192 : {
6193 180388 : if (correctedToData_p) {
6194 :
6195 : // weight -> weight
6196 28211 : Matrix<Float> weights = vb->weight();
6197 28211 : if (newWeightFactorMap_p.size() > 0)
6198 : {
6199 0 : if ( (newWeightFactorMap_p.find(vb->spectralWindows()(0)) != newWeightFactorMap_p.end()) and
6200 0 : (newWeightFactorMap_p[vb->spectralWindows()(0)] != 1) )
6201 : {
6202 0 : weights *= newWeightFactorMap_p[vb->spectralWindows()(0)];
6203 : }
6204 : }
6205 28211 : writeMatrix(weights,outputMsCols_p->weight(),rowRef,nspws_p);
6206 :
6207 : // weight -> sigma
6208 28211 : arrayTransformInPlace(weights, vi::AveragingTvi2::weightToSigma);
6209 28211 : writeMatrix(weights,outputMsCols_p->sigma(),rowRef,nspws_p);
6210 :
6211 28211 : }
6212 152177 : else if(!bothDataColumnsAreOutput_p)
6213 : {
6214 : // sigma -> sigma
6215 138873 : Matrix<Float> sigma = vb->sigma();
6216 138873 : if (newSigmaFactorMap_p.size() > 0)
6217 : {
6218 0 : if ( (newSigmaFactorMap_p.find(vb->spectralWindows()(0)) != newSigmaFactorMap_p.end()) and
6219 0 : (newSigmaFactorMap_p[vb->spectralWindows()(0)] != 1) )
6220 : {
6221 0 : sigma *= newSigmaFactorMap_p[vb->spectralWindows()(0)];
6222 : }
6223 : }
6224 138873 : writeMatrix(sigma,outputMsCols_p->sigma(),rowRef,nspws_p);
6225 :
6226 : // sigma -> weight
6227 138873 : arrayTransformInPlace(sigma, vi::AveragingTvi2::sigmaToWeight);
6228 138873 : writeMatrix(sigma, outputMsCols_p->weight(), rowRef, nspws_p);
6229 138873 : }
6230 : // If both DATA and DATA_CORRECTED are input and output then
6231 : // SIGMA(_SPECTRUM) and WEIGHT(_SPECTRUM) should maintain their alignment
6232 : // with DATA and CORRECTED_DATA, respectively and nothing is done. See CAS-11139
6233 : else
6234 : {
6235 : // weight -> weight
6236 13304 : Matrix<Float> weights = vb->weight();
6237 13304 : if (newWeightFactorMap_p.size() > 0)
6238 : {
6239 0 : if ( (newWeightFactorMap_p.find(vb->spectralWindows()(0)) != newWeightFactorMap_p.end()) and
6240 0 : (newWeightFactorMap_p[vb->spectralWindows()(0)] != 1) )
6241 : {
6242 0 : weights *= newWeightFactorMap_p[vb->spectralWindows()(0)];
6243 : }
6244 : }
6245 13304 : writeMatrix(weights,outputMsCols_p->weight(),rowRef,nspws_p);
6246 :
6247 : // sigma -> sigma
6248 13304 : Matrix<Float> sigma = vb->sigma();
6249 13304 : if (newSigmaFactorMap_p.size() > 0)
6250 : {
6251 0 : if ( (newSigmaFactorMap_p.find(vb->spectralWindows()(0)) != newSigmaFactorMap_p.end()) and
6252 0 : (newSigmaFactorMap_p[vb->spectralWindows()(0)] != 1) )
6253 : {
6254 0 : sigma *= newSigmaFactorMap_p[vb->spectralWindows()(0)];
6255 : }
6256 : }
6257 13304 : writeMatrix(sigma,outputMsCols_p->sigma(),rowRef,nspws_p);
6258 13304 : }
6259 : }
6260 : }
6261 :
6262 699638 : return;
6263 349819 : }
6264 :
6265 : // ------------------------------------------------------------------------------------
6266 : //
6267 : // ------------------------------------------------------------------------------------
6268 3133903 : template <class T> void MSTransformManager::transformAndWriteNotReindexableVector( const Vector<T> &inputVector,
6269 : Vector<T> &outputVector,
6270 : bool constant,
6271 : ScalarColumn<T> &outputCol,
6272 : RefRows &rowReference)
6273 : {
6274 3133903 : bool transformed = transformNotReindexableVector(inputVector,outputVector,constant);
6275 :
6276 3133903 : if (transformed)
6277 : {
6278 57100 : outputCol.putColumnCells(rowReference, outputVector);
6279 : }
6280 : else
6281 : {
6282 3076803 : outputCol.putColumnCells(rowReference, inputVector);
6283 : }
6284 :
6285 3133903 : return;
6286 : };
6287 :
6288 : // ------------------------------------------------------------------------------------
6289 : //
6290 : // ------------------------------------------------------------------------------------
6291 2098914 : template <class T> void MSTransformManager::transformAndWriteReindexableVector( const Vector<T> &inputVector,
6292 : Vector<T> &outputVector,
6293 : bool constant,
6294 : map<uInt,uInt> &inputOutputIndexMap,
6295 : ScalarColumn<T> &outputCol,
6296 : RefRows &rowReference)
6297 : {
6298 2098914 : bool transformed = transformReindexableVector(inputVector,outputVector,constant,inputOutputIndexMap);
6299 :
6300 2098914 : if (transformed)
6301 : {
6302 70324 : outputCol.putColumnCells(rowReference, outputVector);
6303 : }
6304 : else
6305 : {
6306 2028590 : outputCol.putColumnCells(rowReference, inputVector);
6307 : }
6308 :
6309 2098914 : return;
6310 : };
6311 :
6312 : // ------------------------------------------------------------------------------------
6313 : //
6314 : // ------------------------------------------------------------------------------------
6315 349819 : bool MSTransformManager::transformDDIVector(const Vector<Int> &inputVector,Vector<Int> &outputVector)
6316 : {
6317 349819 : bool transformed = true;
6318 :
6319 349819 : if ((combinespws_p) or (nspws_p > 1))
6320 : {
6321 7952 : if (nspws_p > 1)
6322 : {
6323 1971 : uInt absoluteIndex = 0;
6324 14664 : for (uInt index=0; index<rowIndex_p.size();index++)
6325 : {
6326 72429 : for (uInt spwIndex=0;spwIndex < nspws_p; spwIndex++)
6327 : {
6328 59736 : outputVector(absoluteIndex) = ddiStart_p + spwIndex;
6329 59736 : absoluteIndex += 1;
6330 : }
6331 : }
6332 : }
6333 : else
6334 : {
6335 5981 : outputVector = ddiStart_p;
6336 : }
6337 7952 : }
6338 : else
6339 : {
6340 341867 : transformed = transformReindexableVector(inputVector,outputVector,true,inputOutputDDIndexMap_p);
6341 : }
6342 :
6343 349819 : return transformed;
6344 : }
6345 :
6346 : // ------------------------------------------------------------------------------------
6347 : //
6348 : // ------------------------------------------------------------------------------------
6349 7234 : void MSTransformManager::mapAndAverageVector( const Vector<Double> &inputVector,
6350 : Vector<Double> &outputVector)
6351 : {
6352 7234 : Double vec_average = 0;
6353 7234 : vector<uInt> baselineRows;
6354 7234 : uInt row, counts, absoluteIndex = 0;
6355 518402 : for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
6356 : {
6357 : // Get baseline rows vector
6358 511168 : baselineRows = iter->second;
6359 :
6360 : // Compute combined value from each SPW
6361 511168 : counts = 0;
6362 :
6363 1689866 : for (auto iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
6364 : {
6365 1178698 : row = *iter_row;
6366 1178698 : if (counts == 0)
6367 : {
6368 511168 : vec_average = inputVector(row);
6369 : }
6370 : else
6371 : {
6372 667530 : vec_average += inputVector(row);
6373 : }
6374 :
6375 1178698 : counts += 1;
6376 : }
6377 :
6378 : // Normalize value
6379 511168 : if (counts) vec_average /= counts;
6380 :
6381 : // Set value in output vector
6382 1042742 : for (uInt spwIndex=0;spwIndex < nspws_p; spwIndex++)
6383 : {
6384 531574 : outputVector(absoluteIndex) = vec_average;
6385 531574 : absoluteIndex += 1;
6386 : }
6387 : }
6388 :
6389 14468 : return;
6390 7234 : }
6391 :
6392 : // ------------------------------------------------------------------------------------
6393 : //
6394 : // ------------------------------------------------------------------------------------
6395 7234 : void MSTransformManager::mapAndAverageVector( const Vector<bool> &inputVector,
6396 : Vector<bool> &outputVector)
6397 : {
6398 7234 : bool vec_average = false;
6399 7234 : vector<uInt> baselineRows;
6400 7234 : uInt row, counts, absoluteIndex = 0;
6401 518402 : for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
6402 : {
6403 : // Get baseline rows vector
6404 511168 : baselineRows = iter->second;
6405 :
6406 : // Compute combined value from each SPW
6407 511168 : counts = 0;
6408 :
6409 1689866 : for (auto iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
6410 : {
6411 1178698 : row = *iter_row;
6412 1178698 : if (counts == 0)
6413 : {
6414 1178698 : vec_average = inputVector(row);
6415 : }
6416 : else
6417 : {
6418 0 : vec_average &= inputVector(row);
6419 : }
6420 : }
6421 :
6422 : // Set value in output vector
6423 1042742 : for (uInt spwIndex=0;spwIndex < nspws_p; spwIndex++)
6424 : {
6425 531574 : outputVector(absoluteIndex) = vec_average;
6426 531574 : absoluteIndex += 1;
6427 : }
6428 : }
6429 :
6430 14468 : return;
6431 7234 : }
6432 :
6433 :
6434 : // -----------------------------------------------------------------------------------
6435 : // Fill the data from an input matrix with shape [nCol,nBaselinesxnSPWs] into an
6436 : // output matrix with shape [nCol,nBaselines] accumulating the averaging from all SPWS
6437 : // -----------------------------------------------------------------------------------
6438 : template <class T> void MSTransformManager::mapAndAverageMatrix( const Matrix<T> &inputMatrix,
6439 : Matrix<T> &outputMatrix,
6440 : bool convolveFlags,
6441 : vi::VisBuffer2 *vb)
6442 : {
6443 : // Get number of columns
6444 : uInt nCols = outputMatrix.shape()(0);
6445 :
6446 : // Access FLAG_ROW in case we need to convolute the average
6447 : Vector<bool> flags;
6448 : if (convolveFlags) flags = vb->flagRow();
6449 :
6450 : // Fill output array with the combined data from each SPW
6451 : uInt row;
6452 : uInt baseline_index = 0;
6453 : Double normalizingFactor = 0;
6454 : Double contributionFactor = 0;
6455 : vector<uInt> baselineRows;
6456 : for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
6457 : {
6458 : // Get baseline rows vector
6459 : baselineRows = iter->second;
6460 :
6461 : // Reset normalizing factor
6462 : normalizingFactor = 0;
6463 :
6464 : // Compute combined value from each SPW
6465 : for (vector<uInt>::iterator iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
6466 : {
6467 : row = *iter_row;
6468 : if (convolveFlags)
6469 : {
6470 : contributionFactor = !flags(row);
6471 : }
6472 : else
6473 : {
6474 : contributionFactor = 1;
6475 : }
6476 :
6477 : for (uInt col = 0; col < nCols; col++)
6478 : {
6479 : outputMatrix(col,baseline_index) += contributionFactor*inputMatrix(col,row);
6480 : }
6481 :
6482 : normalizingFactor += contributionFactor;
6483 : }
6484 :
6485 : // Normalize accumulated value
6486 : if (normalizingFactor>0)
6487 : {
6488 : for (uInt col = 0; col < nCols; col++)
6489 : {
6490 : outputMatrix(col,baseline_index) /= normalizingFactor;
6491 : }
6492 : }
6493 :
6494 : baseline_index += 1;
6495 : }
6496 :
6497 : return;
6498 : }
6499 :
6500 : // -----------------------------------------------------------------------
6501 : //
6502 : // -----------------------------------------------------------------------
6503 0 : template <class T> void MSTransformManager::mapAndScaleMatrix( const Matrix<T> &inputMatrix,
6504 : Matrix<T> &outputMatrix,
6505 : map<uInt,T> scaleMap,
6506 : Vector<Int> spws)
6507 : {
6508 : // Reset output Matrix
6509 0 : outputMatrix = 0;
6510 :
6511 : // Get number of columns
6512 0 : uInt nCols = outputMatrix.shape()(0);
6513 :
6514 : // Fill output array with the combined data from each SPW
6515 : Int spw;
6516 : uInt row;
6517 0 : uInt baseline_index = 0;
6518 0 : vector<uInt> baselineRows;
6519 : T contributionFactor;
6520 0 : for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
6521 : {
6522 : // Get baseline rows vector
6523 0 : baselineRows = iter->second;
6524 :
6525 : // Reset normalizing factor
6526 :
6527 : // Get value from first SPW (this is for Weight and Sigma and cvel is doing it so)
6528 0 : row = baselineRows.at(0);
6529 0 : spw = spws(row);
6530 0 : if (scaleMap.find(spw) != scaleMap.end())
6531 : {
6532 0 : contributionFactor = scaleMap[spw];
6533 : }
6534 : else
6535 : {
6536 0 : contributionFactor = 1;
6537 : }
6538 :
6539 0 : for (uInt col = 0; col < nCols; col++)
6540 : {
6541 0 : outputMatrix(col,baseline_index) = contributionFactor*inputMatrix(col,row);
6542 : }
6543 :
6544 0 : baseline_index += 1;
6545 : }
6546 :
6547 0 : return;
6548 0 : }
6549 :
6550 :
6551 : // ----------------------------------------------------------------------------------------
6552 : // Fill main (data) columns which have to be combined together to produce bigger SPWs
6553 : // ----------------------------------------------------------------------------------------
6554 347959 : void MSTransformManager::fillDataCols(vi::VisBuffer2 *vb,RefRows &rowRef)
6555 : {
6556 347959 : ArrayColumn<bool> *outputFlagCol=NULL;
6557 823654 : for (dataColMap::iterator iter = dataColMap_p.begin();iter != dataColMap_p.end();iter++)
6558 : {
6559 : // Get applicable *_SPECTRUM (copy constructor uses reference semantics)
6560 : // If channel average or combine, otherwise no need to copy
6561 475695 : const Cube<Float> &applicableSpectrum = getApplicableSpectrum(vb,iter->first);
6562 :
6563 : // Apply transformations
6564 475695 : switch (iter->first)
6565 : {
6566 228860 : case MS::DATA:
6567 : {
6568 228860 : if (mainColumn_p == MS::DATA)
6569 : {
6570 228860 : outputFlagCol = &(outputMsCols_p->flag());
6571 228860 : setTileShape(rowRef,outputMsCols_p->flag());
6572 : }
6573 : else
6574 : {
6575 0 : outputFlagCol = NULL;
6576 : }
6577 :
6578 228860 : setTileShape(rowRef,outputMsCols_p->data());
6579 228860 : transformCubeOfData(vb,rowRef,vb->visCube(),outputMsCols_p->data(), outputFlagCol,applicableSpectrum);
6580 :
6581 228860 : break;
6582 : }
6583 130153 : case MS::CORRECTED_DATA:
6584 : {
6585 130153 : if (mainColumn_p == MS::CORRECTED_DATA)
6586 : {
6587 67772 : outputFlagCol = &(outputMsCols_p->flag());
6588 67772 : setTileShape(rowRef,outputMsCols_p->flag());
6589 : }
6590 : else
6591 : {
6592 62381 : outputFlagCol = NULL;
6593 : }
6594 :
6595 130153 : if (iter->second == MS::DATA)
6596 : {
6597 66172 : setTileShape(rowRef,outputMsCols_p->data());
6598 66172 : transformCubeOfData(vb,rowRef,vb->visCubeCorrected(),outputMsCols_p->data(), outputFlagCol,applicableSpectrum);
6599 : }
6600 : else
6601 : {
6602 63981 : setTileShape(rowRef,outputMsCols_p->correctedData());
6603 63981 : transformCubeOfData(vb,rowRef,vb->visCubeCorrected(),outputMsCols_p->correctedData(), outputFlagCol,applicableSpectrum);
6604 : }
6605 :
6606 130153 : break;
6607 : }
6608 97782 : case MS::MODEL_DATA:
6609 : {
6610 97782 : if (mainColumn_p == MS::MODEL_DATA)
6611 : {
6612 34027 : outputFlagCol = &(outputMsCols_p->flag());
6613 34027 : setTileShape(rowRef,outputMsCols_p->flag());
6614 : }
6615 : else
6616 : {
6617 63755 : outputFlagCol = NULL;
6618 : }
6619 :
6620 97782 : if (produceModel_p)
6621 : {
6622 : // irrespective of wheter iter->second == MS::DATA
6623 : // or iter->second == MS::CORRECTED_DATA
6624 53 : setTileShape(rowRef,outputMsCols_p->modelData());
6625 53 : transformCubeOfData(vb,rowRef,vb->visCubeModel(),outputMsCols_p->modelData(), outputFlagCol,applicableSpectrum);
6626 97729 : } else if (iter->second == MS::DATA) {
6627 34027 : setTileShape(rowRef,outputMsCols_p->data());
6628 34027 : transformCubeOfData(vb,rowRef,vb->visCubeModel(),outputMsCols_p->data(), outputFlagCol,applicableSpectrum);
6629 : }
6630 : else
6631 : {
6632 63702 : setTileShape(rowRef,outputMsCols_p->modelData());
6633 63702 : transformCubeOfData(vb,rowRef,vb->visCubeModel(),outputMsCols_p->modelData(), outputFlagCol,applicableSpectrum);
6634 : }
6635 97782 : break;
6636 : }
6637 18900 : case MS::FLOAT_DATA:
6638 : {
6639 18900 : if (mainColumn_p == MS::FLOAT_DATA)
6640 : {
6641 17300 : outputFlagCol = &(outputMsCols_p->flag());
6642 17300 : setTileShape(rowRef,outputMsCols_p->flag());
6643 : }
6644 : else
6645 : {
6646 1600 : outputFlagCol = NULL;
6647 : }
6648 :
6649 18900 : setTileShape(rowRef,outputMsCols_p->floatData());
6650 18900 : transformCubeOfData(vb,rowRef,vb->visCubeFloat(),outputMsCols_p->floatData(), outputFlagCol,applicableSpectrum);
6651 :
6652 18900 : break;
6653 : }
6654 0 : case MS::LAG_DATA:
6655 : {
6656 : // jagonzal: TODO
6657 0 : break;
6658 : }
6659 0 : default:
6660 : {
6661 : // jagonzal: TODO
6662 0 : break;
6663 : }
6664 : }
6665 : }
6666 :
6667 : // Special case for flag category
6668 347959 : if (inputFlagCategoryAvailable_p)
6669 : {
6670 0 : if (spectrumReshape_p)
6671 : {
6672 0 : IPosition transformedCubeShape = getShape(); //[nC,nF,nR]
6673 0 : IPosition inputFlagCategoryShape = vb->flagCategory().shape(); // [nC,nF,nCategories,nR]
6674 0 : IPosition flagCategoryShape(4, inputFlagCategoryShape(1),
6675 0 : transformedCubeShape(2),
6676 0 : inputFlagCategoryShape(2),
6677 0 : transformedCubeShape(2));
6678 0 : Array<bool> flagCategory(flagCategoryShape,false);
6679 :
6680 0 : outputMsCols_p->flagCategory().putColumnCells(rowRef, flagCategory);
6681 0 : }
6682 : else
6683 : {
6684 0 : outputMsCols_p->flagCategory().putColumnCells(rowRef, vb->flagCategory());
6685 : }
6686 : }
6687 :
6688 347959 : return;
6689 : }
6690 :
6691 : // ----------------------------------------------------------------------------------------
6692 : // Fill weight cols (WEIGHT_SPECTRUM and SIGMA_SPECTRUM) as well as WEIGHT/SIGMA which have to be derived from it using median
6693 : // ----------------------------------------------------------------------------------------
6694 349782 : void MSTransformManager::fillWeightCols(vi::VisBuffer2 *vb,RefRows &rowRef)
6695 : {
6696 : // WEIGHT_SPECTRUM and SIGMA_SPECTRUM are only filled if requested or when WEIGHT_SPECTRUM is present in the input MS
6697 : // But WEIGHT/SIGMA have always to be derived from in-memory WEIGHT_SPECTRUM/SIGMA_SPECTRUM
6698 349782 : if (flushWeightSpectrum_p or spectrumTransformation_p or userBufferMode_p)
6699 : {
6700 : // Switch aux Weight propagation off
6701 190823 : propagateWeights(false);
6702 :
6703 : // Switch average and smooth kernels
6704 190823 : setChannelAverageKernel(MSTransformations::flagCumSumNonZero);
6705 190823 : setSmoothingKernel(MSTransformations::plainSmoothSpectrum);
6706 190823 : setSmoothingFourierKernel(MSTransformations::plainSmoothSpectrum);
6707 :
6708 : // Dummy auxiliary weightSpectrum
6709 190823 : const Cube<Float> applicableSpectrum;
6710 :
6711 190823 : if (spectrumTransformation_p)
6712 : {
6713 : // For SPW separation:
6714 : // Prepare RowReference for spectrum transformations
6715 : // (all data is flushed at once instead of blocks)
6716 169431 : RefRows rowRefSpectrum(rowRef.firstRow(), rowRef.firstRow() + nRowsToAdd_p-1);
6717 :
6718 : // Switch on buffer mode
6719 169431 : Cube<Float> transformedSpectrum;
6720 169431 : Cube<bool> transformedFlag;
6721 169431 : if (not userBufferMode_p)
6722 : {
6723 169431 : setBufferMode(true);
6724 169431 : dataBuffer_p = MSTransformations::weightSpectrum;
6725 169431 : transformedSpectrum.resize(getShape(),false);
6726 169431 : weightSpectrum_p = &transformedSpectrum;
6727 169431 : transformedFlag.resize(getShape(),false);
6728 169431 : flagCube_p = &transformedFlag; // Not used for the output but to extract the average/median
6729 : }
6730 :
6731 :
6732 : // Multiple column operation
6733 169431 : if (doingData_p and doingCorrected_p)
6734 : {
6735 : // Transform WEIGHT_SPECTRUM but don't derive SIGMA_SPECTRUM from it
6736 49077 : transformAndWriteSpectrum( vb,rowRefSpectrum,vb->weightSpectrum(),
6737 : getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
6738 : getOutputWeightColumn(vb,MS::WEIGHT),
6739 49077 : MSTransformations::transformWeight,flushWeightSpectrum_p);
6740 :
6741 : // Convert SIGMA_SPECTRUM to WEIGHT format, transform it and derive SIGMA_SPECTRUM from it
6742 49077 : transformAndWriteSpectrum( vb,rowRefSpectrum,getWeightSpectrumFromSigmaSpectrum(vb),
6743 : getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
6744 : getOutputWeightColumn(vb,MS::SIGMA),
6745 49077 : MSTransformations::transformWeightIntoSigma,flushWeightSpectrum_p);
6746 : }
6747 : // In case of time average we can use directly WEIGHT_SPECTRUM because
6748 : // AveragingTvi2 derives it from the input SIGMA_SPECTRUM or WEIGHT_SPECTRUM
6749 : // depending on the selected DATA column
6750 120354 : else if (timeAverage_p)
6751 : {
6752 : // Transform WEIGHT_SPECTRUM
6753 9244 : transformAndWriteSpectrum( vb,rowRefSpectrum,vb->weightSpectrum(),
6754 : getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
6755 : getOutputWeightColumn(vb,MS::WEIGHT),
6756 9244 : MSTransformations::transformWeight,flushWeightSpectrum_p);
6757 :
6758 : // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
6759 9244 : transformAndWriteSpectrum( vb,rowRefSpectrum,vb->weightSpectrum(),
6760 : getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
6761 : getOutputWeightColumn(vb,MS::SIGMA),
6762 9244 : MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
6763 : }
6764 : // DATA to DATA: Convert SIGMA_SPECTRUM to WEIGHT format, transform it and derive SIGMA_SPECTRUM from it
6765 111110 : else if (doingData_p)
6766 : {
6767 : // Transform WEIGHT_SPECTRUM
6768 46823 : transformAndWriteSpectrum( vb,rowRefSpectrum,getWeightSpectrumFromSigmaSpectrum(vb),
6769 : getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
6770 : getOutputWeightColumn(vb,MS::WEIGHT),
6771 46823 : MSTransformations::transformWeight,flushWeightSpectrum_p);
6772 :
6773 : // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
6774 46823 : transformAndWriteSpectrum( vb,rowRefSpectrum,vb->weightSpectrum(),
6775 : getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
6776 : getOutputWeightColumn(vb,MS::SIGMA),
6777 46823 : MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
6778 : }
6779 : // CORRECTED to DATA: Transform WEIGHT_SPECTRUM and derive SIGMA_SPECTRUM from it
6780 64287 : else if (doingCorrected_p) // CORRECTED to DATA
6781 : {
6782 : // Transform WEIGHT_SPECTRUM
6783 35381 : transformAndWriteSpectrum( vb,rowRefSpectrum,vb->weightSpectrum(),
6784 : getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
6785 : getOutputWeightColumn(vb,MS::WEIGHT),
6786 35381 : MSTransformations::transformWeight,flushWeightSpectrum_p);
6787 :
6788 : // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
6789 35381 : transformAndWriteSpectrum( vb,rowRefSpectrum,vb->weightSpectrum(),
6790 : getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
6791 : getOutputWeightColumn(vb,MS::SIGMA),
6792 35381 : MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
6793 : }
6794 : // MODEL to DATA: Calculate WEIGHT_SPECTRUM using FLAG and derive SIGMA_SPECTRUM from it
6795 28906 : else if (doingModel_p)
6796 : {
6797 : // Transform WEIGHT_SPECTRUM
6798 28864 : transformAndWriteSpectrum( vb,rowRefSpectrum,getWeightSpectrumFlat(vb),
6799 : getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
6800 : getOutputWeightColumn(vb,MS::WEIGHT),
6801 28864 : MSTransformations::transformWeight,flushWeightSpectrum_p);
6802 :
6803 : // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
6804 28864 : transformAndWriteSpectrum( vb,rowRefSpectrum,vb->weightSpectrum(),
6805 : getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
6806 : getOutputWeightColumn(vb,MS::SIGMA),
6807 28864 : MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
6808 : }
6809 :
6810 : // Switch off buffer mode
6811 169431 : if (not userBufferMode_p)
6812 : {
6813 169431 : setBufferMode(false);
6814 169431 : weightSpectrum_p = NULL;
6815 : }
6816 169431 : }
6817 : // Within AveragingTvi2 SIGMA_SPECTRUM is already re-defined to 1/sqrt(WEIGHT_SPECTRUM) if CORRECTED->DATA
6818 : // or obtained from the input SIGMA_SPECTRUM in the case of DATA->DATA or multiple column operation
6819 21392 : else if (timeAverage_p)
6820 : {
6821 : // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
6822 11840 : if (userBufferMode_p)
6823 : {
6824 0 : dataBuffer_p = MSTransformations::weightSpectrum;
6825 : }
6826 : else
6827 : {
6828 11840 : setTileShape(rowRef,getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM));
6829 : }
6830 11840 : transformCubeOfData(vb,rowRef,vb->weightSpectrum(),getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),NULL,applicableSpectrum);
6831 :
6832 11840 : if (userBufferMode_p)
6833 : {
6834 0 : dataBuffer_p = MSTransformations::sigmaSpectrum;
6835 : }
6836 : else
6837 : {
6838 11840 : setTileShape(rowRef,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM));
6839 : }
6840 11840 : transformCubeOfData(vb,rowRef,vb->sigmaSpectrum(),getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),NULL,applicableSpectrum);
6841 : }
6842 : // When CORRECTED becomes DATA, then SIGMA_SPECTRUM has to be re-defined to 1/sqrt(WEIGHT_SPECTRUM)
6843 9552 : else if (correctedToData_p)
6844 : {
6845 : // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
6846 389 : if (userBufferMode_p)
6847 : {
6848 0 : dataBuffer_p = MSTransformations::weightSpectrum;
6849 : }
6850 : else
6851 : {
6852 389 : setTileShape(rowRef,getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM));
6853 : }
6854 389 : transformCubeOfData(vb,rowRef,vb->weightSpectrum(),getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),NULL,applicableSpectrum);
6855 :
6856 389 : if (userBufferMode_p)
6857 : {
6858 0 : dataBuffer_p = MSTransformations::sigmaSpectrum;
6859 : }
6860 : else
6861 : {
6862 389 : setTileShape(rowRef,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM));
6863 : }
6864 : // VI/VB only allocates and populates sigmaSpectrum on request
6865 : // But its contents are not usable for this case
6866 : // So we should just create a local storage
6867 389 : Cube<Float> sigmaSpectrum;
6868 389 : sigmaSpectrum = vb->weightSpectrum(); // Copy constructor does not use reference semantics, but deep copy
6869 : // Apply transformation
6870 389 : arrayTransformInPlace(sigmaSpectrum, vi::AveragingTvi2::weightToSigma);
6871 : // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
6872 389 : transformCubeOfData(vb,rowRef,sigmaSpectrum,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),NULL,applicableSpectrum);
6873 389 : }
6874 : // Pure split operation
6875 : else
6876 : {
6877 : // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
6878 9163 : if (userBufferMode_p)
6879 : {
6880 0 : dataBuffer_p = MSTransformations::weightSpectrum;
6881 : }
6882 : else
6883 : {
6884 9163 : setTileShape(rowRef,getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM));
6885 : }
6886 9163 : transformCubeOfData(vb,rowRef,vb->weightSpectrum(),getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),NULL,applicableSpectrum);
6887 :
6888 9163 : if (userBufferMode_p)
6889 : {
6890 0 : dataBuffer_p = MSTransformations::sigmaSpectrum;
6891 : }
6892 : else
6893 : {
6894 9163 : setTileShape(rowRef,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM));
6895 : }
6896 9163 : transformCubeOfData(vb,rowRef,vb->sigmaSpectrum(),getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),NULL,applicableSpectrum);
6897 : }
6898 :
6899 : // Switch aux Weight propagation on
6900 190823 : propagateWeights(propagateWeights_p);
6901 :
6902 : // Reset average and smooth kernels
6903 190823 : setChannelAverageKernel(weightmode_p);
6904 190823 : setSmoothingKernel(smoothmode_p);
6905 190823 : setSmoothingFourierKernel(MSTransformations::plainSmooth);
6906 190823 : }
6907 :
6908 349782 : return;
6909 : }
6910 :
6911 :
6912 : // ----------------------------------------------------------------------------------------
6913 : // Set tile shape
6914 : // ----------------------------------------------------------------------------------------
6915 1101500 : template <class T> void MSTransformManager::setTileShape( RefRows &rowRef,
6916 : ArrayColumn<T> &outputDataCol)
6917 : {
6918 1101500 : IPosition outputCubeShape = getShape();
6919 1101500 : size_t nCorr = outputCubeShape(0);
6920 1101500 : size_t nChan = outputCubeShape(1);
6921 1101500 : ssize_t nRows = 1048576 / (sizeof(T)*nCorr*nChan);
6922 1101500 : IPosition outputPlaneShape(2,nCorr,nChan);
6923 1101500 : IPosition tileShape(3,nCorr,nChan,nRows);
6924 :
6925 1101500 : outputDataCol.setShape(rowRef.firstRow(),outputPlaneShape,tileShape);
6926 :
6927 2203000 : return;
6928 1101500 : }
6929 :
6930 : // explicit instatiation for the use from SDMSManager
6931 : template void MSTransformManager::setTileShape<Float>(RefRows &, ArrayColumn<Float> &);
6932 : template void MSTransformManager::setTileShape<bool>(RefRows &, ArrayColumn<bool> &);
6933 : template void MSTransformManager::setTileShape<Complex>(RefRows &, ArrayColumn<Complex> &);
6934 :
6935 : // ----------------------------------------------------------------------------------------
6936 : //
6937 : // ----------------------------------------------------------------------------------------
6938 338778 : void MSTransformManager::transformAndWriteSpectrum( vi::VisBuffer2 *vb,
6939 : RefRows &rowRef,
6940 : const Cube<Float> &inputSpectrum,
6941 : ArrayColumn<Float> &outputCubeCol,
6942 : ArrayColumn<Float> &outputMatrixCol,
6943 : MSTransformations::weightTransformation weightTransformation,
6944 : bool /* flushSpectrumCube */)
6945 : {
6946 : // Dummy auxiliary weightSpectrum
6947 338778 : const Cube<Float> applicableSpectrum;
6948 :
6949 : // Check if weight scaling has to be applied
6950 338778 : Float weightScale = 0, sigmaScale = 0;
6951 338778 : if (refFrameTransformation_p)
6952 : {
6953 7180 : if ( (newWeightFactorMap_p.find(vb->spectralWindows()(0)) != newWeightFactorMap_p.end()) and
6954 7180 : (newWeightFactorMap_p[vb->spectralWindows()(0)] != 1) )
6955 : {
6956 1392 : weightScale = newWeightFactorMap_p[vb->spectralWindows()(0)];
6957 : }
6958 :
6959 7180 : if ( (newSigmaFactorMap_p.find(vb->spectralWindows()(0)) != newSigmaFactorMap_p.end()) and
6960 7180 : (newSigmaFactorMap_p[vb->spectralWindows()(0)] != 1) )
6961 : {
6962 1392 : sigmaScale = newSigmaFactorMap_p[vb->spectralWindows()(0)];
6963 : }
6964 : }
6965 :
6966 : // Apply transformations
6967 338778 : switch (weightTransformation)
6968 : {
6969 169389 : case MSTransformations::transformWeight:
6970 : {
6971 169389 : dataBuffer_p = MSTransformations::weightSpectrum;
6972 169389 : transformCubeOfData(vb,rowRef,inputSpectrum,outputCubeCol,NULL,applicableSpectrum);
6973 :
6974 169389 : if (weightScale > 0) *weightSpectrum_p *= weightScale;
6975 :
6976 169389 : break;
6977 : }
6978 49077 : case MSTransformations::transformWeightIntoSigma:
6979 : {
6980 49077 : if (userBufferMode_p)
6981 : {
6982 0 : dataBuffer_p = MSTransformations::sigmaSpectrum;
6983 0 : transformCubeOfData(vb,rowRef,inputSpectrum,outputCubeCol,NULL,applicableSpectrum);
6984 0 : arrayTransformInPlace (*sigmaSpectrum_p,vi::AveragingTvi2::weightToSigma);
6985 :
6986 0 : if (sigmaScale > 0) *sigmaSpectrum_p *= sigmaScale;
6987 : }
6988 : else
6989 : {
6990 49077 : transformCubeOfData(vb,rowRef,inputSpectrum,outputCubeCol,NULL,applicableSpectrum);
6991 49077 : arrayTransformInPlace (*weightSpectrum_p,vi::AveragingTvi2::weightToSigma);
6992 :
6993 49077 : if (sigmaScale > 0) *weightSpectrum_p *= sigmaScale;
6994 : }
6995 :
6996 49077 : break;
6997 : }
6998 120312 : case MSTransformations::weightIntoSigma:
6999 : {
7000 120312 : if (userBufferMode_p)
7001 : {
7002 : // WeightSpectrum is always transformed before sigmaSpectrum
7003 : // so copy weightSpectrum into sigmaSpectrum
7004 0 : sigmaSpectrum_p->operator =(*weightSpectrum_p);
7005 0 : arrayTransformInPlace (*sigmaSpectrum_p,vi::AveragingTvi2::weightToSigma);
7006 :
7007 : // No need to scale in this case as it already happened before
7008 : }
7009 : else
7010 : {
7011 : // WeightSpectrum is always transformed before sigmaSpectrum
7012 : // so transform directly weightSpectrum into sigmaSpectrum
7013 120312 : arrayTransformInPlace (*weightSpectrum_p,vi::AveragingTvi2::weightToSigma);
7014 :
7015 : // No need to scale in this case as it already happened before
7016 : }
7017 120312 : break;
7018 : }
7019 : }
7020 :
7021 : // Write resulting cube
7022 338778 : if ( (not userBufferMode_p) and flushWeightSpectrum_p)
7023 : {
7024 229482 : setTileShape(rowRef,outputCubeCol);
7025 229482 : writeCube(*weightSpectrum_p,outputCubeCol,rowRef);
7026 : }
7027 :
7028 : // Extract median matrix (nCorr x nRow)
7029 : // When separating SPWs this procedure computes the mean of each separated SPW
7030 : // Matrix<Float> medians = partialMedians(*weightSpectrum_p,IPosition(1,1),true);
7031 338778 : if (userBufferMode_p)
7032 : {
7033 0 : switch (weightTransformation)
7034 : {
7035 0 : case MSTransformations::transformWeight:
7036 : {
7037 0 : weight_p->operator =(vi::AveragingTvi2::average(*weightSpectrum_p,*flagCube_p));
7038 0 : break;
7039 : }
7040 0 : case MSTransformations::transformWeightIntoSigma:
7041 : {
7042 0 : sigma_p->operator =(vi::AveragingTvi2::average(*sigmaSpectrum_p,*flagCube_p));
7043 0 : break;
7044 : }
7045 0 : case MSTransformations::weightIntoSigma:
7046 : {
7047 0 : sigma_p->operator =(vi::AveragingTvi2::average(*sigmaSpectrum_p,*flagCube_p));
7048 0 : break;
7049 : }
7050 : }
7051 : }
7052 : else
7053 : {
7054 338778 : Matrix<Float> means = vi::AveragingTvi2::average(*weightSpectrum_p,*flagCube_p);
7055 338778 : writeMatrix(means,outputMatrixCol,rowRef,1);
7056 338778 : }
7057 :
7058 677556 : return;
7059 338778 : }
7060 :
7061 : // -----------------------------------------------------------------------
7062 : // Get *_SPECTRUM column to use depending on the input col
7063 : // -----------------------------------------------------------------------
7064 477555 : const Cube<Float>& MSTransformManager::getApplicableSpectrum(vi::VisBuffer2 *vb, MS::PredefinedColumns datacol)
7065 : {
7066 477555 : if (propagateWeights_p)
7067 : {
7068 29887 : switch (datacol)
7069 : {
7070 17679 : case MS::DATA:
7071 : {
7072 : // NOTE: There is room for optimization here if in the case of
7073 : // A.- Time average and single column operation
7074 : // B.- Single column in the input (George denied this)
7075 : // C.- Time average should not convert SIGMA_SPECTRUM to WEIGHT format if there is chan.avg downstream
7076 : // D.- SIGMA_SPECTRUM should be in WEIGHT format
7077 17679 : return getWeightSpectrumFromSigmaSpectrum(vb);
7078 : break;
7079 : }
7080 6662 : case MS::CORRECTED_DATA:
7081 : {
7082 6662 : return vb->weightSpectrum();
7083 : break;
7084 : }
7085 5546 : case MS::MODEL_DATA:
7086 : {
7087 : // Return either WEIGHT_SPECTRUM or SIGMA_SPECTRUM depending on the other accompany col
7088 5546 : if (doingCorrected_p)
7089 : {
7090 3242 : return vb->weightSpectrum();
7091 : }
7092 2304 : else if (doingData_p)
7093 : {
7094 0 : return getWeightSpectrumFromSigmaSpectrum(vb);
7095 : }
7096 : // When doing only MODEL_DATA only FLAG cube is used, and applicable weightSpectrum must be flat unit
7097 : // The same convention is applied in VbAvg::accumulateElementForCubes for time average
7098 : else
7099 : {
7100 2304 : return getWeightSpectrumFlat(vb);
7101 : }
7102 :
7103 : break;
7104 : }
7105 0 : default:
7106 : {
7107 0 : return vb->weightSpectrum();
7108 : break;
7109 : }
7110 : }
7111 : }
7112 : else
7113 : {
7114 447668 : return weightSpectrumCubeDummy_p;
7115 : }
7116 : }
7117 :
7118 : // -----------------------------------------------------------------------
7119 : // Get output weight column
7120 : // -----------------------------------------------------------------------
7121 763124 : ArrayColumn<Float>& MSTransformManager::getOutputWeightColumn(vi::VisBuffer2 *, MS::PredefinedColumns datacol)
7122 : {
7123 763124 : if (userBufferMode_p)
7124 : {
7125 0 : return dummyWeightCol_p;
7126 : }
7127 : else
7128 : {
7129 763124 : switch (datacol)
7130 : {
7131 212173 : case MS::WEIGHT_SPECTRUM:
7132 : {
7133 212173 : return outputMsCols_p->weightSpectrum();
7134 : break;
7135 : }
7136 212173 : case MS::SIGMA_SPECTRUM:
7137 : {
7138 212173 : return outputMsCols_p->sigmaSpectrum();
7139 : break;
7140 : }
7141 169389 : case MS::WEIGHT:
7142 : {
7143 169389 : return outputMsCols_p->weight();
7144 : break;
7145 : }
7146 169389 : case MS::SIGMA:
7147 : {
7148 169389 : return outputMsCols_p->sigma();
7149 : break;
7150 : }
7151 0 : default:
7152 : {
7153 0 : return outputMsCols_p->weight();
7154 : break;
7155 : }
7156 : }
7157 : }
7158 : }
7159 :
7160 :
7161 : // -----------------------------------------------------------------------
7162 : // Pupulate weightSpectrum derived from sigmaSpectrum
7163 : // -----------------------------------------------------------------------
7164 113579 : const Cube<Float>& MSTransformManager::getWeightSpectrumFromSigmaSpectrum(vi::VisBuffer2 *vb)
7165 : {
7166 113579 : if (weightSpectrumFromSigmaFilled_p)
7167 : {
7168 13331 : return weightSpectrumCube_p;
7169 : }
7170 : else
7171 : {
7172 100248 : weightSpectrumCube_p.resize(vb->getShape(),false);
7173 100248 : weightSpectrumCube_p = vb->sigmaSpectrum(); // = Operator makes a copy
7174 100248 : arrayTransformInPlace (weightSpectrumCube_p,vi::AveragingTvi2::sigmaToWeight);
7175 100248 : weightSpectrumFromSigmaFilled_p = true;
7176 100248 : return weightSpectrumCube_p;
7177 : }
7178 : }
7179 :
7180 : // -----------------------------------------------------------------------
7181 : // Populate a synthetic flat unit weightSpectrum to be use for MODEL_DATA
7182 : // -----------------------------------------------------------------------
7183 31168 : const Cube<Float>& MSTransformManager::getWeightSpectrumFlat(vi::VisBuffer2 *vb)
7184 : {
7185 31168 : if (weightSpectrumFlatFilled_p)
7186 : {
7187 0 : return weightSpectrumCubeFlat_p;
7188 : }
7189 31168 : else if (weightSpectrumCubeFlat_p.shape().isEqual(vb->getShape()))
7190 : {
7191 31148 : weightSpectrumFlatFilled_p = true;
7192 31148 : return weightSpectrumCubeFlat_p;
7193 : }
7194 : else
7195 : {
7196 20 : weightSpectrumCubeFlat_p.resize(vb->getShape(),false);
7197 20 : weightSpectrumCubeFlat_p = 1.0f;
7198 20 : weightSpectrumFlatFilled_p = true;
7199 20 : return weightSpectrumCubeFlat_p;
7200 : }
7201 : }
7202 :
7203 : // -----------------------------------------------------------------------
7204 : // Generic method to write a Matrix from a VisBuffer into a ArrayColumn
7205 : // -----------------------------------------------------------------------
7206 1049373 : template <class T> void MSTransformManager::writeMatrix( const Matrix<T> &inputMatrix,
7207 : ArrayColumn<T> &outputCol,
7208 : RefRows &rowRef,
7209 : uInt nBlocks)
7210 : {
7211 1049373 : if (nBlocks == 1)
7212 : {
7213 1047402 : outputCol.putColumnCells(rowRef, inputMatrix);
7214 : }
7215 : else
7216 : {
7217 : // jagonzal (CAS-8492): Huge bug, each input row must
7218 : // be copied n times not the whole matrix n times
7219 1971 : uInt outRowIdx = 0;
7220 1971 : size_t nInputRows = inputMatrix.shape()(1);
7221 1971 : Matrix<T> outputMatrix(IPosition(2,3,nInputRows*nBlocks));
7222 14664 : for (size_t inputRowIdx = 0; inputRowIdx<nInputRows; inputRowIdx++)
7223 : {
7224 72429 : for (uInt blockIdx = 0; blockIdx<nBlocks; blockIdx++)
7225 : {
7226 59736 : outputMatrix.column(outRowIdx) = inputMatrix.column(inputRowIdx);
7227 59736 : outRowIdx += 1;
7228 : }
7229 : }
7230 :
7231 1971 : RefRows outRowRef(rowRef.firstRow(),rowRef.firstRow()+nInputRows*nBlocks-1);
7232 1971 : outputCol.putColumnCells(outRowRef, outputMatrix);
7233 :
7234 : /*
7235 : uInt offset = 0;
7236 : for (uInt block_i=0;block_i<nBlocks;block_i++)
7237 : {
7238 : uInt startRow_i = rowRef.firstRow()+offset;
7239 : RefRows rowRef_i(startRow_i, startRow_i+inputMatrix.shape()(1)-1);
7240 : outputCol.putColumnCells(rowRef_i, inputMatrix);
7241 : offset += inputMatrix.shape()(1);
7242 : }
7243 : */
7244 1971 : }
7245 1049373 : return;
7246 : }
7247 :
7248 : // -----------------------------------------------------------------------
7249 : // Generic method to write a Cube from a VisBuffer into a ArrayColumn
7250 : // -----------------------------------------------------------------------
7251 664493 : template <class T> void MSTransformManager::writeCube( const Cube<T> &inputCube,
7252 : ArrayColumn<T> &outputCol,
7253 : RefRows &rowRef)
7254 : {
7255 664493 : IPosition shape = inputCube.shape();
7256 664493 : shape(2) = rowRef.nrows();
7257 : bool deleteIt;
7258 664493 : Array<T> outputArray(shape,const_cast<T*>(inputCube.getStorage(deleteIt)),SHARE);
7259 664493 : outputCol.putColumnCells(rowRef, outputArray);
7260 :
7261 1328986 : return;
7262 664493 : }
7263 :
7264 : // explicit instatiation for the use from SDMSManager
7265 : template void MSTransformManager::writeCube<bool>(const Cube<bool> &, ArrayColumn<bool> &, RefRows &);
7266 :
7267 : // -----------------------------------------------------------------------
7268 : //
7269 : // -----------------------------------------------------------------------
7270 457749 : void MSTransformManager::transformCubeOfData( vi::VisBuffer2 *vb,
7271 : RefRows &rowRef,
7272 : const Cube<Complex> &inputDataCube,
7273 : ArrayColumn<Complex> &outputDataCol,
7274 : ArrayColumn<bool> *outputFlagCol,
7275 : const Cube<Float> &inputWeightCube)
7276 : {
7277 457749 : (*this.*transformCubeOfDataComplex_p)(vb,rowRef,inputDataCube,outputDataCol,outputFlagCol,inputWeightCube);
7278 457749 : return;
7279 : }
7280 :
7281 : // -----------------------------------------------------------------------
7282 : //
7283 : // -----------------------------------------------------------------------
7284 281056 : void MSTransformManager::transformCubeOfData( vi::VisBuffer2 *vb,
7285 : RefRows &rowRef,
7286 : const Cube<Float> &inputDataCube,
7287 : ArrayColumn<Float> &outputDataCol,
7288 : ArrayColumn<bool> *outputFlagCol,
7289 : const Cube<Float> &inputWeightCube)
7290 : {
7291 281056 : (*this.*transformCubeOfDataFloat_p)(vb,rowRef,inputDataCube,outputDataCol,outputFlagCol,inputWeightCube);
7292 281056 : return;
7293 : }
7294 :
7295 : // -----------------------------------------------------------------------
7296 : //
7297 : // -----------------------------------------------------------------------
7298 252763 : template <class T> void MSTransformManager::copyCubeOfData( vi::VisBuffer2 *vb,
7299 : RefRows &rowRef,
7300 : const Cube<T> &inputDataCube,
7301 : ArrayColumn<T> &outputDataCol,
7302 : ArrayColumn<bool> *outputFlagCol,
7303 : const Cube<Float> & /* inputWeightCube */)
7304 : {
7305 252763 : writeCube(inputDataCube,outputDataCol,rowRef);
7306 252763 : if (outputFlagCol != NULL)
7307 : {
7308 180388 : writeCube(vb->flagCube(),*outputFlagCol,rowRef);
7309 : }
7310 :
7311 252763 : return;
7312 : }
7313 :
7314 : // -----------------------------------------------------------------------
7315 : // combine - for combinespws=True
7316 : // -----------------------------------------------------------------------
7317 16655 : template <class T> void MSTransformManager::combineCubeOfData( vi::VisBuffer2 *vb,
7318 : RefRows &rowRef,
7319 : const Cube<T> &inputDataCube,
7320 : ArrayColumn<T> &outputDataCol,
7321 : ArrayColumn<bool> *outputFlagCol,
7322 : const Cube<Float> &inputWeightCube)
7323 : {
7324 : // Write flag column too?
7325 16655 : if (outputFlagCol != NULL)
7326 : {
7327 7234 : writeOutputFlagsPlaneSlices_p = &MSTransformManager::writeOutputFlagsPlaneSlices;
7328 7234 : writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::writeOutputFlagsPlaneReshapedSlices;
7329 7234 : writeOutputFlagsPlane_p = &MSTransformManager::writeOutputFlagsPlane;
7330 : }
7331 : else
7332 : {
7333 9421 : writeOutputFlagsPlaneSlices_p = &MSTransformManager::dontWriteOutputFlagsPlaneSlices;
7334 9421 : writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::dontWriteOutputPlaneReshapedSlices;
7335 9421 : writeOutputFlagsPlane_p = &MSTransformManager::dontWriteOutputFlagsPlane;
7336 : }
7337 :
7338 : // Get input flag cube
7339 16655 : const Cube<bool> inputFlagCube = vb->flagCube();
7340 :
7341 : // Get input SPWs and exposures
7342 16655 : Vector<Int> spws = vb->spectralWindows();
7343 16655 : Vector<Double> exposures = vb->exposure();
7344 :
7345 : // Get input cube shape
7346 16655 : IPosition inputCubeShape = inputDataCube.shape();
7347 16655 : uInt nInputCorrelations = inputCubeShape(0);
7348 :
7349 : // Initialize input planes
7350 16655 : IPosition inputPlaneShape(2,nInputCorrelations, numOfCombInputChanMap_p[0]);
7351 16655 : Matrix<Double> normalizingFactorPlane(inputPlaneShape);
7352 16655 : Matrix<T> inputPlaneData(inputPlaneShape);
7353 16655 : Matrix<bool> inputPlaneFlags(inputPlaneShape,false);
7354 16655 : Matrix<Float> inputPlaneWeights(inputPlaneShape);
7355 :
7356 : // Initialize output planes
7357 16655 : IPosition outputPlaneShape(2,nInputCorrelations, inputOutputSpwMap_p[0].second.NUM_CHAN);
7358 16655 : Matrix<T> outputPlaneData(outputPlaneShape);
7359 16655 : Matrix<bool> outputPlaneFlags(outputPlaneShape);
7360 :
7361 16655 : Int spw = 0;
7362 : Double weight;
7363 : uInt inputChannel;
7364 : bool inputChanelFlag;
7365 : Double normalizingFactor;
7366 16655 : uInt row = 0, baseline_index = 0;
7367 16655 : vector<uInt> baselineRows;
7368 16655 : map<Int, uInt> spwRowMap;
7369 16655 : map<Int, uInt>::iterator spwRowMapIter;
7370 16655 : map<Int, uInt> spwFractionCountsMap;
7371 16655 : bool unityContributors = false;
7372 16655 : vector< channelContribution > contributions;
7373 16655 : vector< channelContribution >::iterator contributionsIter;
7374 16655 : map < Int , map < uInt, bool > > removeContributionsMap;
7375 :
7376 16655 : bool combinationOfSPWsWithDifferentExposure = false;
7377 16655 : Double exposure = 0;
7378 :
7379 16655 : relativeRow_p = 0; // Initialize relative row for buffer mode
7380 1060363 : for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
7381 : {
7382 : // Initialize input plane
7383 1043708 : inputPlaneData = 0.0;
7384 :
7385 : // Initialize weights plane
7386 1043708 : inputPlaneWeights = 0.0;
7387 :
7388 : // Initialize normalizing factor plane
7389 1043708 : normalizingFactorPlane = 0.0;
7390 :
7391 : // Fill input plane to benefit from contiguous access to the input cube
7392 1043708 : baselineRows = iter->second;
7393 :
7394 : // Create spw-row map for this baseline and initialize detection of SPWs with different exposure
7395 1043708 : spwRowMap.clear();
7396 1043708 : if (combinationOfSPWsWithDifferentExposure_p and (inputWeightCube.shape().isEqual(inputCubeShape)))
7397 : {
7398 0 : combinationOfSPWsWithDifferentExposure = true;
7399 0 : addWeightSpectrumContribution_p = &MSTransformManager::addWeightSpectrumContribution;
7400 0 : for (vector<uInt>::iterator iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
7401 : {
7402 0 : row = *iter_row;
7403 0 : spw = spws(row);
7404 0 : spwRowMap[spw]=row;
7405 : }
7406 : }
7407 : else
7408 : {
7409 1043708 : exposure = exposures(*baselineRows.begin());
7410 1043708 : combinationOfSPWsWithDifferentExposure = false;
7411 3735430 : for (vector<uInt>::iterator iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
7412 : {
7413 2691722 : row = *iter_row;
7414 2691722 : spw = spws(row);
7415 2691722 : spwRowMap[spw]=row;
7416 :
7417 : // In the case of *_SPECTRUM inputWeightCube is dummy
7418 2691722 : if ((abs(exposure - exposures(row)) > FLT_EPSILON) and (inputWeightCube.shape().isEqual(inputCubeShape)))
7419 : {
7420 2 : combinationOfSPWsWithDifferentExposure = true;
7421 : }
7422 : }
7423 :
7424 1043708 : if (combinationOfSPWsWithDifferentExposure)
7425 : {
7426 2 : combinationOfSPWsWithDifferentExposure_p = true;
7427 2 : addWeightSpectrumContribution_p = &MSTransformManager::addWeightSpectrumContribution;
7428 2 : if (inputWeightSpectrumAvailable_p)
7429 : {
7430 4 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
7431 : << "Detected combination of SPWs with different EXPOSURE "<< endl
7432 : << "Will use WEIGHT_SPECTRUM to combine them "<< endl
7433 4 : << LogIO::POST;
7434 : }
7435 : else
7436 : {
7437 0 : logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
7438 : << "Detected combination of SPWs with different EXPOSURE "<< endl
7439 : << "Will use WEIGHT to combine them (WEIGHT_SPECTRUM not available)"<< endl
7440 0 : << LogIO::POST;
7441 : }
7442 : }
7443 : else
7444 : {
7445 1043706 : addWeightSpectrumContribution_p = &MSTransformManager::dontAddWeightSpectrumContribution;
7446 : }
7447 : }
7448 :
7449 :
7450 91465149 : for (uInt outputChannel = 0; outputChannel < numOfCombInputChanMap_p[0]; outputChannel++)
7451 : {
7452 90421441 : contributions = inputOutputChanFactorMap_p[outputChannel];
7453 :
7454 254016246 : for (uInt pol = 0; pol < inputDataCube.shape()(0); pol++)
7455 : {
7456 163594805 : spwFractionCountsMap.clear();
7457 163594805 : unityContributors = false;
7458 :
7459 : // Go through list of contributors for this output channel and polarization and gather flags info
7460 388946006 : for (contributionsIter = contributions.begin(); contributionsIter != contributions.end(); contributionsIter++)
7461 : {
7462 225351201 : inputChannel = contributionsIter->inpChannel;
7463 225351201 : weight = contributionsIter->weight;
7464 :
7465 : // Add WEIGHT_SPECTRUM to the contribution
7466 225351201 : (*this.*addWeightSpectrumContribution_p)(weight,pol,inputChannel,row,inputWeightCube);
7467 :
7468 : // Find row for this input channel
7469 225351201 : spw = contributionsIter->inpSpw;
7470 225351201 : spwRowMapIter = spwRowMap.find(spw);
7471 225351201 : if (spwRowMapIter != spwRowMap.end())
7472 : {
7473 199526197 : row = spwRowMap[spw];
7474 :
7475 : // Fill flags info
7476 199526197 : inputChanelFlag = inputFlagCube(pol,inputChannel,row);
7477 199526197 : contributionsIter->flag = inputChanelFlag;
7478 :
7479 : // Count input channel if it is not flagged and has non-unity overlapping fraction
7480 199526197 : if (weight<1.0)
7481 : {
7482 44188854 : if (!inputChanelFlag) spwFractionCountsMap[spw] += 1;
7483 : }
7484 : // Count if we have valid unity contributors, otherwise we don't discard non-unity contributors
7485 : else
7486 : {
7487 155337343 : unityContributors = true;
7488 : }
7489 : }
7490 : else
7491 : {
7492 : // Fill flags info
7493 25825004 : contributionsIter->flag = true;
7494 : }
7495 : }
7496 :
7497 : // Remove contributions from SPWs with odd numbers of contributors with non-unity
7498 : // overlap fraction which could influence the averaging asymmetrically
7499 388946006 : for (contributionsIter = contributions.begin(); contributionsIter != contributions.end(); contributionsIter++)
7500 : {
7501 225351201 : inputChannel = contributionsIter->inpChannel;
7502 225351201 : weight = contributionsIter->weight;
7503 225351201 : spw = contributionsIter->inpSpw;
7504 :
7505 : // Find row for this input channel
7506 225351201 : if (!contributionsIter->flag)
7507 : {
7508 : // jagonzal: Caution, accessing the map populates it!!!
7509 180942367 : row = spwRowMap[spw];
7510 :
7511 180942367 : if ((spwFractionCountsMap[spw] % 2 == 0) or (weight >= 1.0) or (!unityContributors))
7512 : {
7513 179910805 : inputPlaneData(pol,outputChannel) += weight*inputDataCube(pol,inputChannel,row);
7514 179910805 : normalizingFactorPlane(pol,outputChannel) += weight;
7515 179910805 : (*this.*fillWeightsPlane_p)(pol,inputChannel,outputChannel,row,inputWeightCube,inputPlaneWeights,weight);
7516 : }
7517 : }
7518 : }
7519 : }
7520 : }
7521 :
7522 : // Normalize combined data and determine input plane flags
7523 1043708 : inputPlaneFlags = false;
7524 91465149 : for (uInt outputChannel = 0; outputChannel < numOfCombInputChanMap_p[0]; outputChannel++)
7525 : {
7526 254016246 : for (uInt pol = 0; pol < nInputCorrelations; pol++)
7527 : {
7528 163594805 : normalizingFactor = normalizingFactorPlane(pol,outputChannel);
7529 163594805 : if (normalizingFactor >= 0.999999) // we lose a couple significant digits in the subtractions
7530 : {
7531 156582441 : inputPlaneData(pol,outputChannel) /= normalizingFactorPlane(pol,outputChannel);
7532 :
7533 : // Normalize weights plane
7534 156582441 : (*this.*normalizeWeightsPlane_p)(pol,outputChannel,inputPlaneWeights,normalizingFactorPlane);
7535 : }
7536 7012364 : else if (normalizingFactor > 0)
7537 : {
7538 33846 : inputPlaneData(pol,outputChannel) /= normalizingFactorPlane(pol,outputChannel);
7539 33846 : inputPlaneFlags(pol,outputChannel) = true;
7540 : }
7541 : else
7542 : {
7543 6978518 : inputPlaneFlags(pol,outputChannel) = true;
7544 : }
7545 : }
7546 : }
7547 :
7548 : // Initialize output flags plane
7549 1043708 : outputPlaneFlags = false;
7550 :
7551 : // Transform input planes and write them
7552 1043708 : transformAndWritePlaneOfData( 0,rowRef.firstRow()+baseline_index*nspws_p,
7553 : inputPlaneData,inputPlaneFlags,inputPlaneWeights,
7554 : outputPlaneData,outputPlaneFlags,outputDataCol,outputFlagCol);
7555 :
7556 :
7557 1043708 : relativeRow_p += nspws_p;
7558 1043708 : baseline_index += 1;
7559 : }
7560 :
7561 33310 : return;
7562 16655 : }
7563 :
7564 : // -----------------------------------------------------------------------
7565 : //
7566 : // -----------------------------------------------------------------------
7567 138 : void MSTransformManager::addWeightSpectrumContribution( Double &weight,
7568 : uInt &pol,
7569 : uInt &inputChannel,
7570 : uInt &row,
7571 : const Cube<Float> &inputWeightsCube)
7572 : {
7573 138 : weight *= inputWeightsCube(pol,inputChannel,row);
7574 :
7575 138 : return;
7576 : }
7577 :
7578 : // -----------------------------------------------------------------------
7579 : //
7580 : // -----------------------------------------------------------------------
7581 225351063 : void MSTransformManager::dontAddWeightSpectrumContribution( Double &,
7582 : uInt &,
7583 : uInt &,
7584 : uInt &,
7585 : const Cube<Float> &)
7586 : {
7587 225351063 : return;
7588 : }
7589 :
7590 : // -----------------------------------------------------------------------
7591 : //
7592 : // -----------------------------------------------------------------------
7593 47536734 : void MSTransformManager::fillWeightsPlane( uInt pol,
7594 : uInt inputChannel,
7595 : uInt outputChannel,
7596 : uInt inputRow,
7597 : const Cube<Float> &inputWeightsCube,
7598 : Matrix<Float> &inputWeightsPlane,
7599 : Double factor)
7600 : {
7601 47536734 : inputWeightsPlane(pol,outputChannel) += factor*inputWeightsCube(pol,inputChannel,inputRow);
7602 :
7603 47536734 : return;
7604 : }
7605 :
7606 : // -----------------------------------------------------------------------
7607 : //
7608 : // -----------------------------------------------------------------------
7609 38844697 : void MSTransformManager::normalizeWeightsPlane( uInt pol,
7610 : uInt outputChannel,
7611 : Matrix<Float> &inputPlaneWeights,
7612 : Matrix<Double> &normalizingFactorPlane)
7613 : {
7614 38844697 : inputPlaneWeights(pol,outputChannel) /= normalizingFactorPlane(pol,outputChannel);
7615 :
7616 38844697 : return;
7617 : }
7618 :
7619 : // -----------------------------------------------------------------------
7620 : //
7621 : // -----------------------------------------------------------------------
7622 348183 : template <class T> void MSTransformManager::averageCubeOfData( vi::VisBuffer2 *vb,
7623 : RefRows &rowRef,
7624 : const Cube<T> &inputDataCube,
7625 : ArrayColumn<T> &outputDataCol,
7626 : ArrayColumn<bool> *outputFlagCol,
7627 : const Cube<Float> &inputWeightCube)
7628 : {
7629 : // Get input spw and flag and weight cubes
7630 348183 : Int inputSpw = vb->spectralWindows()(0);
7631 348183 : const Cube<bool> inputFlagsCube = vb->flagCube();
7632 :
7633 : // Define output plane shape
7634 348183 : IPosition outputPlaneShape = IPosition(2,inputDataCube.shape()(0), numOfOutChanMap_p[inputSpw]);
7635 :
7636 348183 : transformAndWriteCubeOfData( inputSpw, rowRef,
7637 : inputDataCube, inputFlagsCube, inputWeightCube,
7638 : outputPlaneShape, outputDataCol, outputFlagCol);
7639 :
7640 696366 : return;
7641 348183 : }
7642 :
7643 : // -----------------------------------------------------------------------
7644 : //
7645 : // -----------------------------------------------------------------------
7646 101441 : template <class T> void MSTransformManager::smoothCubeOfData( vi::VisBuffer2 *vb,
7647 : RefRows &rowRef,
7648 : const Cube<T> &inputDataCube,
7649 : ArrayColumn<T> &outputDataCol,
7650 : ArrayColumn<bool> *outputFlagCol,
7651 : const Cube<Float> &inputWeightCube)
7652 : {
7653 : // Get input spw and flag cube
7654 101441 : Int inputSpw = vb->spectralWindows()(0);
7655 101441 : const Cube<bool> inputFlagsCube = vb->flagCube();
7656 :
7657 : // Define output plane shape
7658 101441 : IPosition outputPlaneShape = IPosition(2,inputDataCube.shape()(0), inputDataCube.shape()(1));
7659 :
7660 : // Transform cube
7661 101441 : transformAndWriteCubeOfData( inputSpw, rowRef,
7662 : inputDataCube, inputFlagsCube, inputWeightCube,
7663 : outputPlaneShape, outputDataCol, outputFlagCol);
7664 :
7665 202882 : return;
7666 101441 : }
7667 :
7668 : // -----------------------------------------------------------------------
7669 : //
7670 : // -----------------------------------------------------------------------
7671 19763 : template <class T> void MSTransformManager::regridCubeOfData( vi::VisBuffer2 *vb,
7672 : RefRows &rowRef,
7673 : const Cube<T> &inputDataCube,
7674 : ArrayColumn<T> &outputDataCol,
7675 : ArrayColumn<bool> *outputFlagCol,
7676 : const Cube<Float> &inputWeightCube)
7677 : {
7678 : // Get input spw and flag cube
7679 19763 : Int inputSpw = vb->spectralWindows()(0);
7680 19763 : const Cube<bool> inputFlagsCube = vb->flagCube();
7681 :
7682 : // Define output plane shape
7683 19763 : IPosition outputPlaneShape = IPosition(2,inputDataCube.shape()(0), inputOutputSpwMap_p[inputSpw].second.NUM_CHAN);
7684 :
7685 : // Transform cube
7686 19763 : transformAndWriteCubeOfData( inputSpw, rowRef,
7687 : inputDataCube, inputFlagsCube, inputWeightCube,
7688 : outputPlaneShape, outputDataCol, outputFlagCol);
7689 :
7690 39526 : return;
7691 19763 : }
7692 :
7693 : // -----------------------------------------------------------------------
7694 : //
7695 : // -----------------------------------------------------------------------
7696 469387 : template <class T> void MSTransformManager::transformAndWriteCubeOfData( Int inputSpw,
7697 : RefRows &rowRef,
7698 : const Cube<T> &inputDataCube,
7699 : const Cube<bool> &inputFlagsCube,
7700 : const Cube<Float> &inputWeightsCube,
7701 : IPosition &outputPlaneShape,
7702 : ArrayColumn<T> &outputDataCol,
7703 : ArrayColumn<bool> *outputFlagCol)
7704 : {
7705 938774 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager",__FUNCTION__)
7706 : << "Shape of input data cube: " << inputDataCube.shape()
7707 : << ", output plane shape: " << outputPlaneShape
7708 938774 : << LogIO::POST;
7709 :
7710 : // Write flag column too?
7711 469387 : if (outputFlagCol != NULL)
7712 : {
7713 162197 : writeOutputFlagsPlaneSlices_p = &MSTransformManager::writeOutputFlagsPlaneSlices;
7714 162197 : writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::writeOutputFlagsPlaneReshapedSlices;
7715 162197 : writeOutputFlagsPlane_p = &MSTransformManager::writeOutputFlagsPlane;
7716 : }
7717 : else
7718 : {
7719 307190 : writeOutputFlagsPlaneSlices_p = &MSTransformManager::dontWriteOutputFlagsPlaneSlices;
7720 307190 : writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::dontWriteOutputPlaneReshapedSlices;
7721 307190 : writeOutputFlagsPlane_p = &MSTransformManager::dontWriteOutputFlagsPlane;
7722 : }
7723 :
7724 : // Get input number of rows
7725 469387 : uInt nInputRows = inputDataCube.shape()(2);
7726 :
7727 : // Initialize input planes
7728 469387 : Matrix<T> inputPlaneData;
7729 469387 : Matrix<bool> inputPlaneFlags;
7730 469387 : Matrix<Float> inputPlaneWeights;
7731 :
7732 : // Initialize output planes
7733 469387 : Matrix<T> outputPlaneData(outputPlaneShape);
7734 469387 : Matrix<bool> outputPlaneFlags(outputPlaneShape);
7735 :
7736 : // Iterate row by row in order to extract a plane
7737 469387 : relativeRow_p = 0; // Initialize relative row for buffer mode
7738 5272919 : for (uInt rowIndex=0; rowIndex < nInputRows; rowIndex++)
7739 : {
7740 : // Initialize output flags plane
7741 4803532 : outputPlaneFlags = false;
7742 :
7743 : // Fill input planes by reference
7744 4803532 : inputPlaneData = inputDataCube.xyPlane(rowIndex);
7745 4803532 : inputPlaneFlags = inputFlagsCube.xyPlane(rowIndex);
7746 4803532 : (*this.*setWeightsPlaneByReference_p)(rowIndex,inputWeightsCube,inputPlaneWeights);
7747 :
7748 : // Transform input planes and write them
7749 4803532 : transformAndWritePlaneOfData( inputSpw,rowRef.firstRow()+rowIndex*nspws_p,
7750 : inputPlaneData,inputPlaneFlags,inputPlaneWeights,
7751 : outputPlaneData,outputPlaneFlags,outputDataCol,outputFlagCol);
7752 :
7753 4803532 : relativeRow_p += nspws_p;
7754 : }
7755 :
7756 938774 : return;
7757 469387 : }
7758 :
7759 : // -----------------------------------------------------------------------
7760 : //
7761 : // -----------------------------------------------------------------------
7762 0 : template <class T> void MSTransformManager::separateCubeOfData( vi::VisBuffer2 *vb,
7763 : RefRows &rowRef,
7764 : const Cube<T> &inputDataCube,
7765 : ArrayColumn<T> &outputDataCol,
7766 : ArrayColumn<bool> *outputFlagCol,
7767 : const Cube<Float> & /* inputWeightCube */)
7768 : {
7769 : // Write flag column too?
7770 0 : if (outputFlagCol != NULL)
7771 : {
7772 0 : writeOutputFlagsPlaneSlices_p = &MSTransformManager::writeOutputFlagsPlaneSlices;
7773 0 : writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::writeOutputFlagsPlaneReshapedSlices;
7774 0 : writeOutputFlagsPlane_p = &MSTransformManager::writeOutputFlagsPlane;
7775 : }
7776 : else
7777 : {
7778 0 : writeOutputFlagsPlaneSlices_p = &MSTransformManager::dontWriteOutputFlagsPlaneSlices;
7779 0 : writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::dontWriteOutputPlaneReshapedSlices;
7780 0 : writeOutputFlagsPlane_p = &MSTransformManager::dontWriteOutputFlagsPlane;
7781 : }
7782 :
7783 : // Get input flags, spw and number of rows
7784 0 : uInt nInputRows = inputDataCube.shape()(2);
7785 0 : const Cube<bool> inputFlagsCube = vb->flagCube();
7786 :
7787 : // Initialize input planes
7788 0 : Matrix<T> inputPlaneData;
7789 0 : Matrix<bool> inputPlaneFlags;
7790 :
7791 : // Iterate row by row in order to extract a plane
7792 0 : relativeRow_p = 0; // Initialize relative row for buffer mode
7793 0 : for (uInt rowIndex=0; rowIndex < nInputRows; rowIndex++)
7794 : {
7795 : // Fill input planes by reference
7796 0 : inputPlaneData = inputDataCube.xyPlane(rowIndex);
7797 0 : inputPlaneFlags = inputFlagsCube.xyPlane(rowIndex);
7798 :
7799 : // Directly write output plane
7800 0 : writeOutputPlanes( rowRef.firstRow()+rowIndex*nspws_p,
7801 : inputPlaneData,inputPlaneFlags,
7802 : outputDataCol,*outputFlagCol);
7803 :
7804 0 : relativeRow_p += nspws_p;
7805 : }
7806 :
7807 0 : return;
7808 0 : }
7809 :
7810 : // -----------------------------------------------------------------------
7811 : //
7812 : // -----------------------------------------------------------------------
7813 400146 : void MSTransformManager::setWeightsPlaneByReference( uInt inputRow,
7814 : const Cube<Float> &inputWeightsCube,
7815 : Matrix<Float> &inputWeightsPlane)
7816 : {
7817 400146 : inputWeightsPlane = inputWeightsCube.xyPlane(inputRow);
7818 400146 : }
7819 :
7820 : // -----------------------------------------------------------------------
7821 : //
7822 : // -----------------------------------------------------------------------
7823 5847240 : template <class T> void MSTransformManager::transformAndWritePlaneOfData( Int inputSpw,
7824 : uInt row,
7825 : Matrix<T> &inputDataPlane,
7826 : Matrix<bool> &inputFlagsPlane,
7827 : Matrix<Float> &inputWeightsPlane,
7828 : Matrix<T> &outputDataPlane,
7829 : Matrix<bool> &outputFlagsPlane,
7830 : ArrayColumn<T> &outputDataCol,
7831 : ArrayColumn<bool> *outputFlagCol)
7832 : {
7833 : // Get input number of correlations
7834 5847240 : uInt nCorrs = inputDataPlane.shape()(0);
7835 :
7836 : // Get output plane shape
7837 5847240 : IPosition outputPlaneShape = outputDataPlane.shape();
7838 :
7839 : // Initialize vectors
7840 5847240 : Vector<T> inputDataStripe;
7841 5847240 : Vector<bool> inputFlagsStripe;
7842 5847240 : Vector<Float> inputWeightsStripe;
7843 5847240 : Vector<T> outputDataStripe;
7844 5847240 : Vector<bool> outputFlagsStripe;
7845 :
7846 : // Iterate correlation by correlation in order to extract a vector
7847 23476243 : for (uInt corrIndex=0; corrIndex < nCorrs; corrIndex++)
7848 : {
7849 : // Fill input stripes by reference
7850 17629003 : inputDataStripe.reference(inputDataPlane.row(corrIndex));
7851 17629003 : inputFlagsStripe.reference(inputFlagsPlane.row(corrIndex));
7852 17629003 : (*this.*setWeightStripeByReference_p)(corrIndex,inputWeightsPlane,inputWeightsStripe);
7853 :
7854 : // Fill output stripes by reference
7855 17629003 : outputDataStripe.reference(outputDataPlane.row(corrIndex));
7856 17629003 : outputFlagsStripe.reference(outputFlagsPlane.row(corrIndex));
7857 :
7858 17629003 : transformStripeOfData(inputSpw,inputDataStripe,inputFlagsStripe,
7859 : inputWeightsStripe,outputDataStripe,outputFlagsStripe);
7860 : }
7861 :
7862 : // Write output planes
7863 5847240 : writeOutputPlanes(row,outputDataPlane,outputFlagsPlane,outputDataCol,*outputFlagCol);
7864 5847240 : }
7865 :
7866 : // -----------------------------------------------------------------------
7867 : //
7868 : // -----------------------------------------------------------------------
7869 3072542 : void MSTransformManager::writeOutputPlanes( uInt row,
7870 : Matrix<Complex> &outputDataPlane,
7871 : Matrix<bool> &outputFlagsPlane,
7872 : ArrayColumn<Complex> &outputDataCol,
7873 : ArrayColumn<bool> &outputFlagCol)
7874 : {
7875 3072542 : (*this.*writeOutputPlanesComplex_p)(row,outputDataPlane,outputFlagsPlane,outputDataCol,outputFlagCol);
7876 3072542 : }
7877 :
7878 : // -----------------------------------------------------------------------
7879 : //
7880 : // -----------------------------------------------------------------------
7881 2774698 : void MSTransformManager::writeOutputPlanes( uInt row,
7882 : Matrix<Float> &outputDataPlane,
7883 : Matrix<bool> &outputFlagsPlane,
7884 : ArrayColumn<Float> &outputDataCol,
7885 : ArrayColumn<bool> &outputFlagCol)
7886 : {
7887 2774698 : (*this.*writeOutputPlanesFloat_p)(row,outputDataPlane,outputFlagsPlane,outputDataCol,outputFlagCol);
7888 2774698 : }
7889 :
7890 : // -----------------------------------------------------------------------
7891 : //
7892 : // -----------------------------------------------------------------------
7893 0 : void MSTransformManager::setOutputbuffer(Cube<Complex> *& dataBufferPointer,Cube<bool> *& flagBufferPointer)
7894 : {
7895 0 : switch (dataBuffer_p)
7896 : {
7897 0 : case MSTransformations::visCube:
7898 : {
7899 0 : dataBufferPointer=visCube_p;
7900 0 : if (userBufferMode_p)
7901 : {
7902 0 : flagBufferPointer = flagCube_p;
7903 : }
7904 : else
7905 : {
7906 0 : flagBufferPointer = NULL;
7907 : }
7908 0 : break;
7909 : }
7910 0 : case MSTransformations::visCubeCorrected:
7911 : {
7912 0 : dataBufferPointer=visCubeCorrected_p;
7913 0 : if (userBufferMode_p)
7914 : {
7915 0 : flagBufferPointer = flagCube_p;
7916 : }
7917 : else
7918 : {
7919 0 : flagBufferPointer = NULL;
7920 : }
7921 0 : break;
7922 : }
7923 0 : case MSTransformations::visCubeModel:
7924 : {
7925 0 : dataBufferPointer=visCubeModel_p;
7926 0 : if (userBufferMode_p)
7927 : {
7928 0 : flagBufferPointer = flagCube_p;
7929 : }
7930 : else
7931 : {
7932 0 : flagBufferPointer = NULL;
7933 : };
7934 0 : break;
7935 : }
7936 0 : default:
7937 : {
7938 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
7939 : << " Data buffer not specified"
7940 0 : << LogIO::POST;
7941 0 : dataBufferPointer=NULL;
7942 0 : flagBufferPointer=NULL;
7943 0 : break;
7944 : }
7945 : }
7946 :
7947 0 : return;
7948 : }
7949 :
7950 : // -----------------------------------------------------------------------
7951 : //
7952 : // -----------------------------------------------------------------------
7953 2774656 : void MSTransformManager::setOutputbuffer(Cube<Float> *& dataBufferPointer,Cube<bool> *& flagBufferPointer)
7954 : {
7955 2774656 : switch (dataBuffer_p)
7956 : {
7957 0 : case MSTransformations::visCubeFloat:
7958 : {
7959 0 : dataBufferPointer=visCubeFloat_p;
7960 0 : if (userBufferMode_p)
7961 : {
7962 0 : flagBufferPointer = flagCube_p;
7963 : }
7964 : else
7965 : {
7966 0 : flagBufferPointer = NULL;
7967 : };
7968 0 : break;
7969 : }
7970 2774656 : case MSTransformations::weightSpectrum:
7971 : {
7972 2774656 : dataBufferPointer=weightSpectrum_p;
7973 : // In buffer mode we already have a memory resident flagCube
7974 : // And the vector transformations use vectors from a dynamically initialize matrixes
7975 2774656 : if (userBufferMode_p)
7976 : {
7977 0 : flagBufferPointer=NULL;
7978 : }
7979 : else
7980 : {
7981 2774656 : flagBufferPointer = flagCube_p;
7982 : }
7983 2774656 : break;
7984 : }
7985 0 : case MSTransformations::sigmaSpectrum:
7986 : {
7987 0 : dataBufferPointer=sigmaSpectrum_p;
7988 : // In buffer mode we already have a memory resident flagCube
7989 : // And the vector transformations use vectors from a dynamically initialize matrixes
7990 0 : if (userBufferMode_p)
7991 : {
7992 0 : flagBufferPointer=NULL;
7993 : }
7994 : else
7995 : {
7996 0 : flagBufferPointer = flagCube_p;
7997 : }
7998 0 : break;
7999 : }
8000 0 : default:
8001 : {
8002 0 : logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
8003 : << " Data buffer not specified"
8004 0 : << LogIO::POST;
8005 0 : dataBufferPointer=NULL;
8006 0 : flagBufferPointer = NULL;
8007 0 : break;
8008 : }
8009 : }
8010 :
8011 2774656 : return;
8012 : }
8013 :
8014 : // -----------------------------------------------------------------------
8015 : //
8016 : // -----------------------------------------------------------------------
8017 2760889 : template <class T> void MSTransformManager::bufferOutputPlanes( uInt ,
8018 : Matrix<T> &outputDataPlane,
8019 : Matrix<bool> &outputFlagsPlane,
8020 : ArrayColumn<T> &,
8021 : ArrayColumn<bool> &)
8022 : {
8023 : // Get buffer pointers
8024 : Cube<T> *dataBufferPointer;
8025 : Cube<bool> *flagBufferPointer;
8026 2760889 : setOutputbuffer(dataBufferPointer,flagBufferPointer);
8027 :
8028 : // Copy data to buffer
8029 2760889 : dataBufferPointer->xyPlane(relativeRow_p) = outputDataPlane;
8030 :
8031 : // Copy flags to buffer
8032 2760889 : if (flagBufferPointer != NULL)
8033 : {
8034 2760889 : flagBufferPointer->xyPlane(relativeRow_p) = outputFlagsPlane;
8035 : }
8036 :
8037 5521778 : return;
8038 : }
8039 :
8040 : // -----------------------------------------------------------------------
8041 : //
8042 : // -----------------------------------------------------------------------
8043 13767 : template <class T> void MSTransformManager::bufferOutputPlanesInSlices( uInt,
8044 : Matrix<T> &outputDataPlane,
8045 : Matrix<bool> &outputFlagsPlane,
8046 : ArrayColumn<T> & /* outputDataCol */,
8047 : ArrayColumn<bool> & /* outputFlagCol */)
8048 : {
8049 : // Get buffer pointers
8050 : Cube<T> *dataBufferPointer;
8051 : Cube<bool> *flagBufferPointer;
8052 13767 : setOutputbuffer(dataBufferPointer,flagBufferPointer);
8053 :
8054 : // Copy data to buffer
8055 13767 : IPosition outputPlaneShape = outputDataPlane.shape();
8056 13767 : uInt nCorrs = outputPlaneShape(0);
8057 13767 : IPosition outputPlaneShape_i(2,nCorrs,chansPerOutputSpw_p);
8058 13767 : Slice sliceX(0,nCorrs);
8059 :
8060 : uInt spw_i;
8061 13767 : uInt nspws = nspws_p-1;
8062 64032 : for (spw_i=0;spw_i<nspws;spw_i++)
8063 : {
8064 50265 : uInt outRow = relativeRow_p+spw_i;
8065 50265 : Slice sliceY(chansPerOutputSpw_p*spw_i,chansPerOutputSpw_p);
8066 50265 : Matrix<T> outputPlane_i = outputDataPlane(sliceX,sliceY);
8067 50265 : dataBufferPointer->xyPlane(outRow) = outputPlane_i;
8068 :
8069 50265 : if (flagBufferPointer != NULL)
8070 : {
8071 50265 : Matrix<bool> outputFlagPlane_i = outputFlagsPlane(sliceX,sliceY);
8072 50265 : flagBufferPointer->xyPlane(outRow) = outputFlagPlane_i;
8073 50265 : }
8074 : }
8075 :
8076 13767 : uInt outRow = relativeRow_p+spw_i;
8077 13767 : Slice sliceY(chansPerOutputSpw_p*spw_i,tailOfChansforLastSpw_p);
8078 13767 : Matrix<T> outputPlane_i = outputDataPlane(sliceX,sliceY);
8079 13767 : outputPlane_i.resize(outputPlaneShape_i,true); // Resize uses a new storage and copies the old values to it
8080 : // jagonzal (CAS-7435): We have to set the new values to 0
8081 13767 : Slice sliceTail(tailOfChansforLastSpw_p,chansPerOutputSpw_p-tailOfChansforLastSpw_p);
8082 13767 : outputPlane_i(sliceX,sliceTail) = 0; // Slices use reference semantics.
8083 13767 : dataBufferPointer->xyPlane(outRow) = outputPlane_i;
8084 :
8085 13767 : if (flagBufferPointer != NULL)
8086 : {
8087 13767 : Matrix<bool> outputFlagPlane_i = outputFlagsPlane(sliceX,sliceY);
8088 13767 : outputFlagPlane_i.resize(outputPlaneShape_i,true); // Resize uses a new storage and copies the old values to it
8089 : // jagonzal (CAS-7435): We have to set the new values to 0
8090 13767 : outputFlagPlane_i(sliceX,sliceTail) = true; // Slices use reference semantics.
8091 13767 : flagBufferPointer->xyPlane(outRow) = outputFlagPlane_i;
8092 13767 : }
8093 :
8094 27534 : return;
8095 13767 : }
8096 :
8097 : // -----------------------------------------------------------------------
8098 : //
8099 : // -----------------------------------------------------------------------
8100 3057743 : template <class T> void MSTransformManager::writeOutputPlanesInBlock( uInt row,
8101 : Matrix<T> &outputDataPlane,
8102 : Matrix<bool> &outputFlagsPlane,
8103 : ArrayColumn<T> &outputDataCol,
8104 : ArrayColumn<bool> &outputFlagCol)
8105 : {
8106 3057743 : IPosition outputPlaneShape = outputDataPlane.shape();
8107 3057743 : outputDataCol.setShape(row,outputPlaneShape);
8108 3057743 : outputDataCol.put(row, outputDataPlane);
8109 3057743 : (*this.*writeOutputFlagsPlane_p)(outputFlagsPlane,outputFlagCol, outputPlaneShape, row);
8110 3057743 : }
8111 :
8112 :
8113 : // -----------------------------------------------------------------------
8114 : //
8115 : // -----------------------------------------------------------------------
8116 2464110 : void MSTransformManager::writeOutputFlagsPlane( Matrix<bool> &outputPlane,
8117 : ArrayColumn<bool> &outputCol,
8118 : IPosition &outputPlaneShape,
8119 : uInt &outputRow)
8120 : {
8121 2464110 : outputCol.setShape(outputRow,outputPlaneShape);
8122 2464110 : outputCol.put(outputRow, outputPlane);
8123 2464110 : }
8124 :
8125 : // -----------------------------------------------------------------------
8126 : //
8127 : // -----------------------------------------------------------------------
8128 14841 : template <class T> void MSTransformManager::writeOutputPlanesInSlices( uInt row,
8129 : Matrix<T> &outputDataPlane,
8130 : Matrix<bool> &outputFlagsPlane,
8131 : ArrayColumn<T> &outputDataCol,
8132 : ArrayColumn<bool> &outputFlagCol)
8133 : {
8134 14841 : IPosition outputPlaneShape = outputDataPlane.shape();
8135 14841 : uInt nCorrs = outputPlaneShape(0);
8136 14841 : IPosition outputPlaneShape_i(2,nCorrs,chansPerOutputSpw_p);
8137 14841 : Slice sliceX(0,nCorrs);
8138 :
8139 : uInt spw_i;
8140 14841 : uInt nspws = nspws_p-1;
8141 68328 : for (spw_i=0;spw_i<nspws;spw_i++)
8142 : {
8143 53487 : uInt outRow = row+spw_i;
8144 53487 : Slice sliceY(chansPerOutputSpw_p*spw_i,chansPerOutputSpw_p);
8145 53487 : writeOutputPlaneSlices(outputDataPlane,outputDataCol,sliceX,sliceY,outputPlaneShape_i,outRow);
8146 53487 : (*this.*writeOutputFlagsPlaneSlices_p)( outputFlagsPlane,outputFlagCol,
8147 : sliceX,sliceY,outputPlaneShape_i,outRow);
8148 : }
8149 :
8150 14841 : uInt outRow = row+spw_i;
8151 14841 : IPosition outputPlaneShape_tail(2,nCorrs,tailOfChansforLastSpw_p);
8152 14841 : Slice sliceY(chansPerOutputSpw_p*spw_i,tailOfChansforLastSpw_p);
8153 14841 : writeOutputPlaneReshapedSlices(outputDataPlane,outputDataCol,sliceX,sliceY,outputPlaneShape_tail,outRow);
8154 14841 : (*this.*writeOutputFlagsPlaneReshapedSlices_p)( outputFlagsPlane,outputFlagCol,
8155 : sliceX,sliceY,outputPlaneShape_tail,outRow);
8156 14841 : }
8157 :
8158 : // -----------------------------------------------------------------------
8159 : //
8160 : // -----------------------------------------------------------------------
8161 47043 : void MSTransformManager::writeOutputFlagsPlaneSlices( Matrix<bool> &outputPlane,
8162 : ArrayColumn<bool> &outputCol,
8163 : Slice &sliceX,
8164 : Slice &sliceY,
8165 : IPosition &outputPlaneShape,
8166 : uInt &outputRow)
8167 : {
8168 47043 : writeOutputPlaneSlices(outputPlane,outputCol,sliceX,sliceY,outputPlaneShape,outputRow);
8169 47043 : }
8170 :
8171 : // -----------------------------------------------------------------------
8172 : //
8173 : // -----------------------------------------------------------------------
8174 12693 : void MSTransformManager::writeOutputFlagsPlaneReshapedSlices( Matrix<bool> &outputPlane,
8175 : ArrayColumn<bool> &outputCol,
8176 : Slice &sliceX,
8177 : Slice &sliceY,
8178 : IPosition &outputPlaneShape,
8179 : uInt &outputRow)
8180 : {
8181 12693 : writeOutputPlaneReshapedSlices(outputPlane,outputCol,sliceX,sliceY,outputPlaneShape,outputRow);
8182 12693 : }
8183 :
8184 : // -----------------------------------------------------------------------
8185 : //
8186 : // -----------------------------------------------------------------------
8187 100530 : template <class T> void MSTransformManager::writeOutputPlaneSlices( Matrix<T> &outputPlane,
8188 : ArrayColumn<T> &outputCol,
8189 : Slice &sliceX,
8190 : Slice &sliceY,
8191 : IPosition &outputPlaneShape,
8192 : uInt &outputRow)
8193 : {
8194 100530 : Matrix<T> outputPlane_i = outputPlane(sliceX,sliceY);
8195 100530 : outputCol.setShape(outputRow,outputPlaneShape);
8196 100530 : outputCol.put(outputRow, outputPlane_i);
8197 100530 : }
8198 :
8199 : // -----------------------------------------------------------------------
8200 : //
8201 : // -----------------------------------------------------------------------
8202 27534 : template <class T> void MSTransformManager::writeOutputPlaneReshapedSlices( Matrix<T> &outputPlane,
8203 : ArrayColumn<T> &outputCol,
8204 : Slice &sliceX,
8205 : Slice &sliceY,
8206 : IPosition &outputPlaneShape,
8207 : uInt &outputRow)
8208 : {
8209 27534 : Matrix<T> outputPlane_i = outputPlane(sliceX,sliceY);
8210 27534 : outputPlane_i.resize(outputPlaneShape,true);
8211 27534 : outputCol.setShape(outputRow,outputPlaneShape);
8212 27534 : outputCol.put(outputRow, outputPlane_i);
8213 27534 : }
8214 :
8215 : // -----------------------------------------------------------------------
8216 : //
8217 : // -----------------------------------------------------------------------
8218 2802641 : void MSTransformManager::setWeightStripeByReference( uInt corrIndex,
8219 : Matrix<Float> &inputWeightsPlane,
8220 : Vector<Float> &inputWeightsStripe)
8221 : {
8222 2802641 : inputWeightsStripe.reference(inputWeightsPlane.row(corrIndex));
8223 2802641 : }
8224 :
8225 : // -----------------------------------------------------------------------
8226 : //
8227 : // -----------------------------------------------------------------------
8228 9399269 : void MSTransformManager::transformStripeOfData(Int inputSpw,
8229 : const Vector<Complex> &inputDataStripe,
8230 : const Vector<bool> &inputFlagsStripe,
8231 : const Vector<Float> &inputWeightsStripe,
8232 : Vector<Complex> &outputDataStripe,
8233 : Vector<bool> &outputFlagsStripe)
8234 : {
8235 9399269 : if(!smooth_spw_p.empty())
8236 : {
8237 : // Skip this SPW if it is not found in the list of SPWs to smooth
8238 1185696 : if( std::find(smooth_spw_p.begin(), smooth_spw_p.end(), inputSpw) == smooth_spw_p.end())
8239 : {
8240 889272 : outputDataStripe = inputDataStripe;
8241 889272 : outputFlagsStripe = inputFlagsStripe;
8242 889272 : return;
8243 : }
8244 : }
8245 :
8246 8509997 : auto shapeBefore = outputDataStripe.shape();
8247 8509997 : (*this.*transformStripeOfDataComplex_p)(inputSpw, inputDataStripe, inputFlagsStripe,
8248 : inputWeightsStripe, outputDataStripe,
8249 : outputFlagsStripe);
8250 8509997 : auto shapeAfter = outputDataStripe.shape();
8251 8509997 : if (shapeAfter != shapeBefore) {
8252 0 : ostringstream msg;
8253 : msg << "Shape of output complex data stripe changed after applying "
8254 0 : << "transformation. Output shape expected before transformation: "
8255 0 : << shapeBefore
8256 0 : << ". Output shape produced by transformation: " << shapeAfter;
8257 0 : logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager",__FUNCTION__)
8258 0 : << LogIO::POST;
8259 0 : throw AipsError(msg.str());
8260 0 : }
8261 8509997 : }
8262 :
8263 : // -----------------------------------------------------------------------
8264 : //
8265 : // -----------------------------------------------------------------------
8266 8229734 : void MSTransformManager::transformStripeOfData(Int inputSpw,
8267 : const Vector<Float> &inputDataStripe,
8268 : const Vector<bool> &inputFlagsStripe,
8269 : const Vector<Float> &inputWeightsStripe,
8270 : Vector<Float> &outputDataStripe,
8271 : Vector<bool> &outputFlagsStripe)
8272 : {
8273 8229734 : (*this.*transformStripeOfDataFloat_p)( inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe,
8274 : outputDataStripe,outputFlagsStripe);
8275 8229734 : }
8276 :
8277 : // -----------------------------------------------------------------------
8278 : //
8279 : // -----------------------------------------------------------------------
8280 8609202 : template <class T> void MSTransformManager::average(Int inputSpw,
8281 : const Vector<T> &inputDataStripe,
8282 : const Vector<bool> &inputFlagsStripe,
8283 : const Vector<Float> &inputWeightsStripe,
8284 : Vector<T> &outputDataStripe,
8285 : Vector<bool> &outputFlagsStripe)
8286 : {
8287 8609202 : uInt width = freqbinMap_p[inputSpw];
8288 8609202 : uInt startChan = 0;
8289 8609202 : uInt outChanIndex = 0;
8290 8609202 : uInt tail = inputDataStripe.size() % width;
8291 272401874 : while (outChanIndex < outputDataStripe.size())
8292 : {
8293 263792672 : averageKernel( inputDataStripe,inputFlagsStripe,inputWeightsStripe,
8294 : outputDataStripe,outputFlagsStripe,startChan,outChanIndex,width);
8295 263792672 : startChan += width;
8296 263792672 : outChanIndex += 1;
8297 : }
8298 :
8299 : // jagonzal: The last channel is dropped when there are not enough input channels
8300 : // to populate it only when there is no regridding afterwards
8301 8609202 : if (tail and (outChanIndex <= outputDataStripe.size()-1) )
8302 : {
8303 0 : averageKernel( inputDataStripe,inputFlagsStripe,inputWeightsStripe,
8304 : outputDataStripe,outputFlagsStripe,startChan,outChanIndex,tail);
8305 : }
8306 :
8307 8609202 : return;
8308 : }
8309 :
8310 : // -----------------------------------------------------------------------
8311 : //
8312 : // -----------------------------------------------------------------------
8313 4 : template <class T> void MSTransformManager::simpleAverage(uInt width,
8314 : const Vector<T> &inputData,
8315 : Vector<T> &outputData)
8316 : {
8317 : // Dummy variables
8318 4 : Vector<bool> inputFlags,outputFlags;
8319 4 : Vector<Float> inputWeights;
8320 :
8321 4 : uInt startChan = 0;
8322 4 : uInt outChanIndex = 0;
8323 4 : uInt tail = inputData.size() % width;
8324 4 : uInt limit = inputData.size() - tail;
8325 56 : while (startChan < limit)
8326 : {
8327 52 : simpleAverageKernel(inputData,inputFlags,inputWeights,outputData,outputFlags,startChan,outChanIndex,width);
8328 52 : startChan += width;
8329 52 : outChanIndex += 1;
8330 : }
8331 :
8332 : // jagonzal: The last channel is dropped when there are not enough input channels
8333 : // to populate it only when there is no regridding afterwards
8334 4 : if (tail and (outChanIndex <= outputData.size()-1) )
8335 : {
8336 4 : simpleAverageKernel(inputData,inputFlags,inputWeights,outputData,outputFlags,startChan,outChanIndex,tail);
8337 : }
8338 :
8339 8 : return;
8340 4 : }
8341 :
8342 : // -----------------------------------------------------------------------
8343 : //
8344 : // -----------------------------------------------------------------------
8345 142802536 : void MSTransformManager::averageKernel(const Vector<Complex> &inputData,
8346 : const Vector<bool> &inputFlags,
8347 : const Vector<Float> &inputWeights,
8348 : Vector<Complex> &outputData,
8349 : Vector<bool> &outputFlags,
8350 : uInt startInputPos,
8351 : uInt outputPos,
8352 : uInt width)
8353 : {
8354 142802536 : (*this.*averageKernelComplex_p)( inputData,inputFlags,inputWeights,
8355 : outputData,outputFlags,startInputPos,outputPos,width);
8356 142802536 : return;
8357 : }
8358 :
8359 : // -----------------------------------------------------------------------
8360 : //
8361 : // -----------------------------------------------------------------------
8362 120990136 : void MSTransformManager::averageKernel(const Vector<Float> &inputData,
8363 : const Vector<bool> &inputFlags,
8364 : const Vector<Float> &inputWeights,
8365 : Vector<Float> &outputData,
8366 : Vector<bool> &outputFlags,
8367 : uInt startInputPos,
8368 : uInt outputPos,
8369 : uInt width)
8370 : {
8371 120990136 : (*this.*averageKernelFloat_p)( inputData,inputFlags,inputWeights,
8372 : outputData,outputFlags,startInputPos,outputPos,width);
8373 120990136 : return;
8374 : }
8375 :
8376 : // -----------------------------------------------------------------------
8377 : //
8378 : // -----------------------------------------------------------------------
8379 56 : template <class T> void MSTransformManager::simpleAverageKernel(const Vector<T> &inputData,
8380 : const Vector<bool> &,
8381 : const Vector<Float> &,
8382 : Vector<T> &outputData,
8383 : Vector<bool> &,
8384 : uInt startInputPos,
8385 : uInt outputPos,
8386 : uInt width)
8387 : {
8388 56 : uInt pos = startInputPos + 1;
8389 56 : uInt counts = 1;
8390 56 : T avg = inputData(startInputPos);
8391 216 : while (counts < width)
8392 : {
8393 160 : avg += inputData(pos);
8394 160 : counts += 1;
8395 160 : pos += 1;
8396 : }
8397 :
8398 56 : if (counts > 0)
8399 : {
8400 56 : avg /= counts;
8401 : }
8402 :
8403 56 : outputData(outputPos) = avg;
8404 :
8405 56 : return;
8406 : }
8407 :
8408 : // -----------------------------------------------------------------------
8409 : //
8410 : // -----------------------------------------------------------------------
8411 0 : template <class T> void MSTransformManager::flagAverageKernel(const Vector<T> &inputData,
8412 : const Vector<bool> &inputFlags,
8413 : const Vector<Float> &,
8414 : Vector<T> &outputData,
8415 : Vector<bool> &outputFlags,
8416 : uInt startInputPos,
8417 : uInt outputPos,
8418 : uInt width)
8419 : {
8420 0 : uInt samples = 1;
8421 0 : uInt pos = startInputPos + 1;
8422 0 : uInt counts = !inputFlags(startInputPos);
8423 0 : T avg = inputData(startInputPos)*(!inputFlags(startInputPos));
8424 0 : while (samples < width)
8425 : {
8426 0 : avg += inputData(pos)*(!inputFlags(pos));
8427 0 : counts += (!inputFlags(pos));
8428 0 : samples += 1;
8429 0 : pos += 1;
8430 : }
8431 :
8432 0 : if (counts > 0)
8433 : {
8434 0 : avg /= counts;
8435 : }
8436 : else
8437 : {
8438 0 : outputFlags(outputPos) = true;
8439 : }
8440 :
8441 0 : outputData(outputPos) = avg;
8442 :
8443 0 : return;
8444 : }
8445 :
8446 : // -----------------------------------------------------------------------
8447 : //
8448 : // -----------------------------------------------------------------------
8449 0 : template <class T> void MSTransformManager::weightAverageKernel(const Vector<T> &inputData,
8450 : const Vector<bool> &,
8451 : const Vector<Float> &inputWeights,
8452 : Vector<T> &outputData,
8453 : Vector<bool> &outputFlags,
8454 : uInt startInputPos,
8455 : uInt outputPos,
8456 : uInt width)
8457 : {
8458 0 : uInt samples = 1;
8459 0 : uInt pos = startInputPos + 1;
8460 0 : Float counts = inputWeights(startInputPos);
8461 0 : T avg = inputData(startInputPos)*inputWeights(startInputPos);
8462 0 : while (samples < width)
8463 : {
8464 0 : avg += inputData(pos)*inputWeights(pos);
8465 0 : counts += inputWeights(pos);
8466 0 : samples += 1;
8467 0 : pos += 1;
8468 : }
8469 :
8470 0 : if (counts > 0)
8471 : {
8472 0 : avg /= counts;
8473 : }
8474 : else
8475 : {
8476 0 : outputFlags(outputPos) = true;
8477 : }
8478 :
8479 0 : outputData(outputPos) = avg;
8480 :
8481 0 : return;
8482 : }
8483 :
8484 : // -----------------------------------------------------------------------
8485 : //
8486 : // -----------------------------------------------------------------------
8487 0 : template <class T> void MSTransformManager::cumSumKernel(const Vector<T> &inputData,
8488 : const Vector<bool> &,
8489 : const Vector<Float> &,
8490 : Vector<T> &outputData,
8491 : Vector<bool> &,
8492 : uInt startInputPos,
8493 : uInt outputPos,
8494 : uInt width)
8495 : {
8496 0 : uInt pos = startInputPos + 1;
8497 0 : uInt counts = 1;
8498 0 : T avg = inputData(startInputPos);
8499 0 : while (counts < width)
8500 : {
8501 0 : avg += inputData(pos);
8502 0 : counts += 1;
8503 0 : pos += 1;
8504 : }
8505 :
8506 0 : outputData(outputPos) = avg;
8507 :
8508 0 : return;
8509 : }
8510 :
8511 : // -----------------------------------------------------------------------
8512 : //
8513 : // -----------------------------------------------------------------------
8514 0 : template <class T> void MSTransformManager::flagWeightAverageKernel(const Vector<T> &inputData,
8515 : const Vector<bool> &inputFlags,
8516 : const Vector<Float> &inputWeights,
8517 : Vector<T> &outputData,
8518 : Vector<bool> &outputFlags,
8519 : uInt startInputPos,
8520 : uInt outputPos,
8521 : uInt width)
8522 : {
8523 0 : uInt samples = 1;
8524 0 : uInt pos = startInputPos + 1;
8525 0 : Float totalWeight = inputWeights(startInputPos)*(!inputFlags(startInputPos));
8526 0 : Float counts = totalWeight;
8527 0 : T avg = inputData(startInputPos)*totalWeight;
8528 0 : while (samples < width)
8529 : {
8530 0 : totalWeight = inputWeights(pos)*(!inputFlags(pos));
8531 0 : avg += inputData(pos)*totalWeight;
8532 0 : counts += totalWeight;
8533 0 : samples += 1;
8534 0 : pos += 1;
8535 : }
8536 :
8537 0 : if (counts > 0)
8538 : {
8539 0 : avg /= counts;
8540 : }
8541 : else
8542 : {
8543 0 : outputFlags(outputPos) = true;
8544 : }
8545 :
8546 0 : outputData(outputPos) = avg;
8547 :
8548 0 : return;
8549 : }
8550 :
8551 : // -----------------------------------------------------------------------
8552 : //
8553 : // -----------------------------------------------------------------------
8554 0 : template <class T> void MSTransformManager::flagCumSumKernel(const Vector<T> &inputData,
8555 : const Vector<bool> &inputFlags,
8556 : const Vector<Float> &,
8557 : Vector<T> &outputData,
8558 : Vector<bool> &,
8559 : uInt startInputPos,
8560 : uInt outputPos,
8561 : uInt width)
8562 : {
8563 0 : uInt samples = 1;
8564 0 : uInt pos = startInputPos + 1;
8565 0 : T avg = inputData(startInputPos)*(!inputFlags(startInputPos));
8566 0 : while (samples < width)
8567 : {
8568 0 : avg += inputData(pos)*(!inputFlags(pos));
8569 0 : samples += 1;
8570 0 : pos += 1;
8571 : }
8572 :
8573 0 : outputData(outputPos) = avg;
8574 :
8575 0 : return;
8576 : }
8577 :
8578 : // -----------------------------------------------------------------------
8579 : //
8580 : // -----------------------------------------------------------------------
8581 128123966 : template <class T> void MSTransformManager::flagNonZeroAverageKernel(const Vector<T> &inputData,
8582 : const Vector<bool> &inputFlags,
8583 : const Vector<Float> & /* inputWeights */,
8584 : Vector<T> &outputData,
8585 : Vector<bool> &outputFlags,
8586 : uInt startInputPos,
8587 : uInt outputPos,
8588 : uInt width)
8589 : {
8590 128123966 : T avg = 0;
8591 128123966 : uInt samples = 0;
8592 128123966 : uInt inputPos = 0;
8593 128123966 : bool accumulatorFlag = inputFlags(startInputPos);
8594 :
8595 389210668 : for (uInt sample_i=0;sample_i<width;sample_i++)
8596 : {
8597 : // Get input index
8598 261086702 : inputPos = startInputPos + sample_i;
8599 :
8600 : // true/true or false/false
8601 261086702 : if (accumulatorFlag == inputFlags(inputPos))
8602 : {
8603 256998271 : samples += 1;
8604 256998271 : avg += inputData(inputPos);
8605 : }
8606 : // true/false: Reset accumulation when accumulator switches from flagged to unflag
8607 4088431 : else if ( (accumulatorFlag == true) and (inputFlags(inputPos) == false) )
8608 : {
8609 1916304 : accumulatorFlag = false;
8610 1916304 : samples = 1;
8611 1916304 : avg = inputData(inputPos);
8612 : }
8613 : }
8614 :
8615 :
8616 : // Apply normalization factor
8617 128123966 : if (samples > 0)
8618 : {
8619 128123966 : avg /= samples;
8620 128123966 : outputData(outputPos) = avg;
8621 : }
8622 : // This should never happen
8623 : else
8624 : {
8625 0 : accumulatorFlag = true;
8626 0 : outputData(outputPos) = 0; // this should be a code error
8627 : }
8628 :
8629 :
8630 : // Set output flag (it is initialized to false)
8631 128123966 : if (accumulatorFlag)
8632 : {
8633 16120213 : outputFlags(outputPos) = true;
8634 : }
8635 :
8636 256247932 : return;
8637 : }
8638 :
8639 :
8640 : // -----------------------------------------------------------------------
8641 : //
8642 : // -----------------------------------------------------------------------
8643 14678570 : template <class T> void MSTransformManager::flagWeightNonZeroAverageKernel(const Vector<T> &inputData,
8644 : const Vector<bool> &inputFlags,
8645 : const Vector<Float> &inputWeights,
8646 : Vector<T> &outputData,
8647 : Vector<bool> &outputFlags,
8648 : uInt startInputPos,
8649 : uInt outputPos,
8650 : uInt width)
8651 : {
8652 14678570 : T avg = 0;
8653 14678570 : T normalization = 0;
8654 14678570 : uInt inputPos = 0;
8655 14678570 : bool accumulatorFlag = inputFlags(startInputPos);
8656 :
8657 44695750 : for (uInt sample_i=0;sample_i<width;sample_i++)
8658 : {
8659 : // Get input index
8660 30017180 : inputPos = startInputPos + sample_i;
8661 :
8662 : // true/true or false/false
8663 30017180 : if (accumulatorFlag == inputFlags(inputPos))
8664 : {
8665 29643490 : normalization += inputWeights(inputPos);
8666 29643490 : avg += inputData(inputPos)*inputWeights(inputPos);
8667 : }
8668 : // true/false: Reset accumulation when accumulator switches from flagged to unflag
8669 373690 : else if ( (accumulatorFlag == true) and (inputFlags(inputPos) == false) )
8670 : {
8671 172959 : accumulatorFlag = false;
8672 172959 : normalization = inputWeights(inputPos);
8673 172959 : avg = inputData(inputPos)*inputWeights(inputPos);
8674 : }
8675 : }
8676 :
8677 :
8678 : // Apply normalization factor
8679 14678570 : if (normalization > 0)
8680 : {
8681 14673974 : avg /= normalization;
8682 14673974 : outputData(outputPos) = avg;
8683 : }
8684 : // If all weights are zero set accumulatorFlag to true
8685 : else
8686 : {
8687 4596 : accumulatorFlag = true;
8688 4596 : outputData(outputPos) = 0; // If all weights are zero then the avg is 0 too
8689 : }
8690 :
8691 :
8692 : // Set output flag (it is initialized to false)
8693 14678570 : if (accumulatorFlag)
8694 : {
8695 1538381 : outputFlags(outputPos) = true;
8696 : }
8697 :
8698 29357140 : return;
8699 : }
8700 :
8701 : // -----------------------------------------------------------------------
8702 : //
8703 : // -----------------------------------------------------------------------
8704 120990136 : template <class T> void MSTransformManager::flagCumSumNonZeroKernel(const Vector<T> &inputData,
8705 : const Vector<bool> &inputFlags,
8706 : const Vector<Float> & /* inputWeights */,
8707 : Vector<T> &outputData,
8708 : Vector<bool> &outputFlags,
8709 : uInt startInputPos,
8710 : uInt outputPos,
8711 : uInt width)
8712 : {
8713 120990136 : T avg = 0;
8714 120990136 : uInt inputPos = 0;
8715 120990136 : bool accumulatorFlag = inputFlags(startInputPos);
8716 :
8717 367695938 : for (uInt sample_i=0;sample_i<width;sample_i++)
8718 : {
8719 : // Get input index
8720 246705802 : inputPos = startInputPos + sample_i;
8721 :
8722 : // true/true or false/false
8723 246705802 : if (accumulatorFlag == inputFlags(inputPos))
8724 : {
8725 242880186 : avg += inputData(inputPos);
8726 : }
8727 : // true/false: Reset accumulation when accumulator switches from flagged to unflag
8728 3825616 : else if ( (accumulatorFlag == true) and (inputFlags(inputPos) == false) )
8729 : {
8730 1777595 : accumulatorFlag = false;
8731 1777595 : avg = inputData(inputPos);
8732 : }
8733 : }
8734 :
8735 120990136 : outputData(outputPos) = avg;
8736 :
8737 : // Set output flag (it is initialized to false)
8738 120990136 : if (accumulatorFlag)
8739 : {
8740 14770980 : outputFlags(outputPos) = true;
8741 : }
8742 :
8743 120990136 : return;
8744 : }
8745 :
8746 :
8747 : // -----------------------------------------------------------------------
8748 : //
8749 : // -----------------------------------------------------------------------
8750 2567954 : template <class T> void MSTransformManager::smooth(Int ,
8751 : const Vector<T> &inputDataStripe,
8752 : const Vector<bool> &inputFlagsStripe,
8753 : const Vector<Float> &inputWeightsStripe,
8754 : Vector<T> &outputDataStripe,
8755 : Vector<bool> &outputFlagsStripe)
8756 : {
8757 : // Calculate limits
8758 2567954 : uInt width = smoothBin_p;
8759 2567954 : uInt halfWidth = width / 2;
8760 2567954 : uInt outChanStart = halfWidth;
8761 2567954 : uInt outChanStop = inputDataStripe.size() - outChanStart;
8762 :
8763 : // Main loop
8764 176504761 : for (uInt outChan = outChanStart; outChan<outChanStop; outChan++)
8765 : {
8766 173936807 : smoothKernel( inputDataStripe,inputFlagsStripe,inputWeightsStripe,
8767 : outputDataStripe,outputFlagsStripe,outChan);
8768 : }
8769 :
8770 : // Flag lower edge
8771 5406688 : for (uInt outChan = 0; outChan<outChanStart; outChan++)
8772 : {
8773 2838734 : outputFlagsStripe(outChan) = true;
8774 2838734 : outputDataStripe(outChan) = inputDataStripe(outChan);
8775 : }
8776 :
8777 : // Flag higher edge
8778 5406688 : for (uInt outChan = outChanStop; outChan<inputDataStripe.size(); outChan++)
8779 : {
8780 2838734 : outputFlagsStripe(outChan) = true;
8781 2838734 : outputDataStripe(outChan) = inputDataStripe(outChan);
8782 : }
8783 :
8784 2567954 : return;
8785 : }
8786 :
8787 : // -----------------------------------------------------------------------
8788 : //
8789 : // -----------------------------------------------------------------------
8790 52934907 : void MSTransformManager::smoothKernel(const Vector<Complex> &inputData,
8791 : const Vector<bool> &inputFlags,
8792 : const Vector<Float> &inputWeights,
8793 : Vector<Complex> &outputData,
8794 : Vector<bool> &outputFlags,
8795 : uInt outputPos)
8796 : {
8797 52934907 : (*this.*smoothKernelComplex_p)( inputData,inputFlags,inputWeights,
8798 : outputData,outputFlags,outputPos);
8799 52934907 : return;
8800 : }
8801 :
8802 : // -----------------------------------------------------------------------
8803 : //
8804 : // -----------------------------------------------------------------------
8805 121001900 : void MSTransformManager::smoothKernel(const Vector<Float> &inputData,
8806 : const Vector<bool> &inputFlags,
8807 : const Vector<Float> &inputWeights,
8808 : Vector<Float> &outputData,
8809 : Vector<bool> &outputFlags,
8810 : uInt outputPos)
8811 : {
8812 121001900 : (*this.*smoothKernelFloat_p)( inputData,inputFlags,inputWeights,
8813 : outputData,outputFlags,outputPos);
8814 121001900 : return;
8815 : }
8816 :
8817 : // -----------------------------------------------------------------------
8818 : //
8819 : // -----------------------------------------------------------------------
8820 52934907 : template <class T> void MSTransformManager::plainSmooth(const Vector<T> &inputData,
8821 : const Vector<bool> &inputFlags,
8822 : const Vector<Float> &,
8823 : Vector<T> &outputData,
8824 : Vector<bool> &outputFlags,
8825 : uInt outputPos)
8826 : {
8827 52934907 : uInt halfWidth = smoothBin_p / 2;
8828 :
8829 : // Initialization
8830 52934907 : outputFlags(outputPos) = inputFlags(outputPos-halfWidth);
8831 52934907 : outputData(outputPos) = smoothCoeff_p(0)*inputData(outputPos-halfWidth);
8832 :
8833 : // Main loop
8834 158804721 : for (uInt i = 1; i<smoothBin_p;i++)
8835 : {
8836 105869814 : outputData(outputPos) += smoothCoeff_p(i)*inputData(outputPos-halfWidth+i);
8837 :
8838 : // Output sample is flagged if any of the contributors are flagged
8839 105869814 : if (inputFlags(outputPos-halfWidth+i)) outputFlags(outputPos)=true;
8840 : }
8841 :
8842 52934907 : return;
8843 : }
8844 :
8845 : // -----------------------------------------------------------------------
8846 : //
8847 : // -----------------------------------------------------------------------
8848 121001900 : template <class T> void MSTransformManager::plainSmoothSpectrum(const Vector<T> &inputData,
8849 : const Vector<bool> &inputFlags,
8850 : const Vector<Float> &,
8851 : Vector<T> &outputData,
8852 : Vector<bool> &outputFlags,
8853 : uInt outputPos)
8854 : {
8855 121001900 : uInt halfWidth = smoothBin_p / 2;
8856 :
8857 : // Initialization (mind for zeros as there is a division operation)
8858 121001900 : if (inputData(outputPos-halfWidth) <= FLT_MIN)
8859 : {
8860 307472 : outputData(outputPos) = 0;
8861 307472 : outputFlags(outputPos) = true;
8862 : }
8863 : else
8864 : {
8865 120694428 : outputFlags(outputPos) = inputFlags(outputPos-halfWidth);
8866 120694428 : outputData(outputPos) = smoothCoeff_p(0)*smoothCoeff_p(0)/inputData(outputPos-halfWidth);
8867 : }
8868 :
8869 : // Main accumulation loop
8870 438349412 : for (uInt i = 1; i<smoothBin_p;i++)
8871 : {
8872 : // Mind for zeros as there is a division operation
8873 317347512 : if (inputData(outputPos-halfWidth+i) <= FLT_MIN)
8874 : {
8875 614944 : outputFlags(outputPos) = true;
8876 : }
8877 : else
8878 : {
8879 316732568 : outputData(outputPos) += smoothCoeff_p(i)*smoothCoeff_p(i)/inputData(outputPos-halfWidth+i);
8880 :
8881 : // Output sample is flagged if any of the contributors are flagged
8882 316732568 : if (inputFlags(outputPos-halfWidth+i)) outputFlags(outputPos)=true;
8883 : }
8884 : }
8885 :
8886 : // Final propaged weight si the inverse of the accumulation
8887 121001900 : if (outputData(outputPos) > FLT_MIN)
8888 : {
8889 120697178 : outputData(outputPos) = 1/outputData(outputPos);
8890 : }
8891 :
8892 121001900 : return;
8893 : }
8894 :
8895 : // -----------------------------------------------------------------------
8896 : //
8897 : // -----------------------------------------------------------------------
8898 5214205 : template <class T> void MSTransformManager::regrid(Int inputSpw,
8899 : const Vector<T> &inputDataStripe,
8900 : const Vector<bool> &inputFlagsStripe,
8901 : const Vector<Float> &inputWeightsStripe,
8902 : Vector<T> &outputDataStripe,
8903 : Vector<bool> &outputFlagsStripe)
8904 : {
8905 :
8906 5214205 : regridCore( inputSpw,
8907 : inputDataStripe,
8908 : inputFlagsStripe,
8909 : inputWeightsStripe,
8910 : outputDataStripe,
8911 : outputFlagsStripe);
8912 :
8913 5214205 : }
8914 :
8915 : // -----------------------------------------------------------------------
8916 : //
8917 : // -----------------------------------------------------------------------
8918 2613064 : void MSTransformManager::regridCore(Int inputSpw,
8919 : const Vector<Complex> &inputDataStripe,
8920 : const Vector<bool> &inputFlagsStripe,
8921 : const Vector<Float> &inputWeightsStripe,
8922 : Vector<Complex> &outputDataStripe,
8923 : Vector<bool> &outputFlagsStripe)
8924 : {
8925 :
8926 2613064 : (*this.*regridCoreComplex_p)( inputSpw,
8927 : inputDataStripe,
8928 : inputFlagsStripe,
8929 : inputWeightsStripe,
8930 : outputDataStripe,
8931 : outputFlagsStripe);
8932 2613064 : }
8933 :
8934 : // -----------------------------------------------------------------------
8935 : //
8936 : // -----------------------------------------------------------------------
8937 2601141 : void MSTransformManager::regridCore(Int inputSpw,
8938 : const Vector<Float> &inputDataStripe,
8939 : const Vector<bool> &inputFlagsStripe,
8940 : const Vector<Float> &inputWeightsStripe,
8941 : Vector<Float> &outputDataStripe,
8942 : Vector<bool> &outputFlagsStripe)
8943 : {
8944 2601141 : (*this.*regridCoreFloat_p)( inputSpw,
8945 : inputDataStripe,
8946 : inputFlagsStripe,
8947 : inputWeightsStripe,
8948 : outputDataStripe,
8949 : outputFlagsStripe);
8950 2601141 : }
8951 :
8952 : // -----------------------------------------------------------------------
8953 : //
8954 : // -----------------------------------------------------------------------
8955 53813 : void MSTransformManager::fftshift(Int ,
8956 : const Vector<Complex> &inputDataStripe,
8957 : const Vector<bool> &inputFlagsStripe,
8958 : const Vector<Float> &,
8959 : Vector<Complex> &outputDataStripe,
8960 : Vector<bool> &outputFlagsStripe)
8961 : {
8962 53813 : fFFTServer_p.fftshift(outputDataStripe,
8963 : outputFlagsStripe,
8964 107626 : (const Vector<Complex>)inputDataStripe,
8965 53813 : (const Vector<bool>)inputFlagsStripe,
8966 0 : (const uInt)0, // In vectors axis 0 is the only dimension
8967 53813 : (const Double)fftShift_p,
8968 : false, // A good data point has its flag set to false
8969 : false);
8970 53813 : }
8971 :
8972 : // -----------------------------------------------------------------------
8973 : //
8974 : // -----------------------------------------------------------------------
8975 52988 : void MSTransformManager::fftshift(Int ,
8976 : const Vector<Float> &inputDataStripe,
8977 : const Vector<bool> &inputFlagsStripe,
8978 : const Vector<Float> &,
8979 : Vector<Float> &outputDataStripe,
8980 : Vector<bool> &outputFlagsStripe)
8981 : {
8982 52988 : fFFTServer_p.fftshift(outputDataStripe,
8983 : outputFlagsStripe,
8984 105976 : (const Vector<Float>)inputDataStripe,
8985 52988 : (const Vector<bool>)inputFlagsStripe,
8986 0 : (const uInt)0, // In vectors axis 0 is the only dimension
8987 52988 : (const Double)fftShift_p,
8988 : false); // A good data point has its flag set to false
8989 52988 : }
8990 :
8991 : // -----------------------------------------------------------------------
8992 : //
8993 : // -----------------------------------------------------------------------
8994 5214205 : template <class T> void MSTransformManager::interpol1D(Int inputSpw,
8995 : const Vector<T> &inputDataStripe,
8996 : const Vector<bool> &inputFlagsStripe,
8997 : const Vector<Float> &,
8998 : Vector<T> &outputDataStripe,
8999 : Vector<bool> &outputFlagsStripe)
9000 : {
9001 5214205 : if (inputDataStripe.size() < 2) {
9002 417808 : outputDataStripe = inputDataStripe(0);
9003 417808 : outputFlagsStripe = true;
9004 417808 : return;
9005 : }
9006 :
9007 4796397 : if (!regridTClean_p) {
9008 9405494 : InterpolateArray1D<Double,T>::interpolate(outputDataStripe, // Output data
9009 : outputFlagsStripe, // Output flags
9010 4702747 : inputOutputSpwMap_p[inputSpw].second.CHAN_FREQ, // Out chan freq
9011 9405494 : inputOutputSpwMap_p[inputSpw].first.CHAN_FREQ_aux, // In chan freq
9012 : inputDataStripe, // Input data
9013 : inputFlagsStripe, // Input Flags
9014 4702747 : interpolationMethod_p, // Interpolation method
9015 : false, // A good data point has its flag set to false
9016 : false // If false extrapolated data points are set flagged
9017 : );
9018 : } else {
9019 93650 : interpolateByChannelMap(inputSpw,
9020 : inputDataStripe, inputFlagsStripe,
9021 : outputDataStripe, outputFlagsStripe);
9022 : }
9023 : }
9024 :
9025 : /**
9026 : * Introduced to mimic the way tclean regrids when the factor between
9027 : * the output channel width and the input channel width is > 2.
9028 : * Ref. TransformMachines2/FTMachine.cc
9029 : *
9030 : * Uses a map from original input channels => fake output channels,
9031 : * where the fake output channels have the (lower) width of the
9032 : * input channels but are projected/aligned with the output channel
9033 : * grid.
9034 : *
9035 : * @param spw spw index of the input channels, to fetch original
9036 : * input channel freqs
9037 : * @param inputDataStripe input data coming from regridCubeOfData,
9038 : * transformAndWriteCubeOfData, etc. and passed to the
9039 : * regrid/interpolation kernels.
9040 : * @param inputFlagsStripe flags for the inputDataStripe
9041 : * @param outputDataStripe will be interpolated by aggregating
9042 : * input visibilities into wider channels
9043 : * @param outputFlagsStripe flags for outputDataStripe
9044 : */
9045 93650 : template <class T> void MSTransformManager::interpolateByChannelMap(Int spw,
9046 : const Vector<T> &inputDataStripe,
9047 : const Vector<bool> &inputFlagsStripe,
9048 : Vector<T> &outputDataStripe,
9049 : Vector<bool> &outputFlagsStripe)
9050 : {
9051 93650 : Vector<T> intermDataStripe;
9052 93650 : Vector<bool> intermFlagsStripe;
9053 : // Bring frequencies from input grid to fake output grid ( the
9054 : // one with same widths as the original input channels).
9055 187300 : InterpolateArray1D<Double,T>::interpolate(intermDataStripe,
9056 : intermFlagsStripe,
9057 93650 : regridTCleanCHAN_FREQ_p, // Out channel freqs
9058 93650 : inputOutputSpwMap_p[spw].first.CHAN_FREQ_aux, // Input chan freqs
9059 : inputDataStripe,
9060 : inputFlagsStripe,
9061 93650 : interpolationMethod_p,
9062 : false, // flags
9063 : false // extrapolated data points are set flagged
9064 : );
9065 :
9066 : // Aggregate fine grain fake output channels into the final
9067 : // output channels
9068 93650 : outputDataStripe = 0;
9069 93650 : Vector<Double> outWeights;
9070 93650 : outWeights.resize(outputDataStripe.size());
9071 93650 : outWeights = 0.;
9072 71743576 : for (uInt mapIdx = 0; mapIdx < regridTCleanChanMap_p.size(); ++mapIdx) {
9073 71649926 : Int outIdx = regridTCleanChanMap_p[mapIdx];
9074 71649926 : if (outIdx < 0)
9075 0 : continue;
9076 :
9077 109590384 : outputDataStripe[outIdx] = (outputDataStripe[outIdx] * outWeights[outIdx] +
9078 109590384 : intermDataStripe[mapIdx]) /
9079 71649926 : (1. + outWeights[outIdx]);
9080 71649926 : outWeights[outIdx] += 1;
9081 71649926 : outputFlagsStripe[outIdx] |= intermFlagsStripe[mapIdx];
9082 : }
9083 93650 : }
9084 :
9085 : // ------------------------------------------------------------------------
9086 : // casacore::fftshift does not interpolate, it needs interpolation+fftshift
9087 : // ------------------------------------------------------------------------
9088 106801 : template <class T> void MSTransformManager::interpol1Dfftshift(Int inputSpw,
9089 : const Vector<T> &inputDataStripe,
9090 : const Vector<bool> &inputFlagsStripe,
9091 : const Vector<Float> &inputWeightsStripe,
9092 : Vector<T> &outputDataStripe,
9093 : Vector<bool> &outputFlagsStripe)
9094 : {
9095 106801 : Vector<T> regriddedDataStripe(outputDataStripe.shape(),T());
9096 106801 : Vector<bool> regriddedFlagsStripe(outputFlagsStripe.shape(),false);
9097 :
9098 : // This linear interpolation provides a uniform grid (pre-condition to apply fftshift)
9099 106801 : interpol1D(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe,regriddedDataStripe,regriddedFlagsStripe);
9100 :
9101 : // fftshift takes care of time
9102 106801 : fftshift(inputSpw,regriddedDataStripe,regriddedFlagsStripe,inputWeightsStripe,outputDataStripe,outputFlagsStripe);
9103 106801 : }
9104 :
9105 : // -----------------------------------------------------------------------
9106 : //
9107 : // -----------------------------------------------------------------------
9108 4 : template <class T> void MSTransformManager::averageRegrid(Int inputSpw,
9109 : const Vector<T> &inputDataStripe,
9110 : const Vector<bool> &inputFlagsStripe,
9111 : const Vector<Float> &inputWeightsStripe,
9112 : Vector<T> &outputDataStripe,
9113 : Vector<bool> &outputFlagsStripe)
9114 : {
9115 4 : Vector<T> averagedDataStripe(numOfCombInterChanMap_p[inputSpw],T());
9116 4 : Vector<bool> averagedFlagsStripe(numOfCombInterChanMap_p[inputSpw],false);
9117 :
9118 4 : average(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe, averagedDataStripe,averagedFlagsStripe);
9119 :
9120 4 : regrid(inputSpw,averagedDataStripe,averagedFlagsStripe,inputWeightsStripe,outputDataStripe,outputFlagsStripe);
9121 :
9122 8 : return;
9123 4 : }
9124 :
9125 : // -----------------------------------------------------------------------
9126 : //
9127 : // -----------------------------------------------------------------------
9128 184634 : template <class T> void MSTransformManager::smoothRegrid(Int inputSpw,
9129 : const Vector<T> &inputDataStripe,
9130 : const Vector<bool> &inputFlagsStripe,
9131 : const Vector<Float> &inputWeightsStripe,
9132 : Vector<T> &outputDataStripe,
9133 : Vector<bool> &outputFlagsStripe)
9134 : {
9135 184634 : Vector<T> smoothedDataStripe(inputDataStripe.shape(),T());
9136 184634 : Vector<bool> smoothedFlagsStripe(inputFlagsStripe.shape(),false);
9137 :
9138 184634 : smooth(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe,smoothedDataStripe,smoothedFlagsStripe);
9139 :
9140 184634 : regrid(inputSpw,smoothedDataStripe,smoothedFlagsStripe,inputWeightsStripe,outputDataStripe,outputFlagsStripe);
9141 :
9142 369268 : return;
9143 184634 : }
9144 :
9145 : // -----------------------------------------------------------------------
9146 : //
9147 : // -----------------------------------------------------------------------
9148 0 : template <class T> void MSTransformManager::averageSmooth(Int inputSpw,
9149 : const Vector<T> &inputDataStripe,
9150 : const Vector<bool> &inputFlagsStripe,
9151 : const Vector<Float> &inputWeightsStripe,
9152 : Vector<T> &outputDataStripe,
9153 : Vector<bool> &outputFlagsStripe)
9154 : {
9155 0 : Vector<T> averagedDataStripe(outputDataStripe.shape(),T());
9156 0 : Vector<bool> averagedFlagsStripe(outputFlagsStripe.shape(),false);
9157 :
9158 0 : average(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe, averagedDataStripe,averagedFlagsStripe);
9159 :
9160 0 : smooth(inputSpw,averagedDataStripe,averagedFlagsStripe, inputWeightsStripe, outputDataStripe,outputFlagsStripe);
9161 :
9162 0 : return;
9163 0 : }
9164 :
9165 : // -----------------------------------------------------------------------
9166 : //
9167 : // -----------------------------------------------------------------------
9168 0 : template <class T> void MSTransformManager::averageSmoothRegrid(Int inputSpw,
9169 : const Vector<T> &inputDataStripe,
9170 : const Vector<bool> &inputFlagsStripe,
9171 : const Vector<Float> &inputWeightsStripe,
9172 : Vector<T> &outputDataStripe,
9173 : Vector<bool> &outputFlagsStripe)
9174 : {
9175 0 : Vector<T> averageSmoothedDataStripe(numOfCombInterChanMap_p[inputSpw],T());
9176 0 : Vector<bool> averageSmoothedFlagsStripe(numOfCombInterChanMap_p[inputSpw],false);
9177 :
9178 0 : averageSmooth( inputSpw,inputDataStripe,inputFlagsStripe,
9179 : inputWeightsStripe,averageSmoothedDataStripe,averageSmoothedFlagsStripe);
9180 :
9181 0 : regrid( inputSpw,averageSmoothedDataStripe,averageSmoothedFlagsStripe,
9182 : inputWeightsStripe,outputDataStripe,outputFlagsStripe);
9183 :
9184 0 : return;
9185 0 : }
9186 :
9187 : // -----------------------------------------------------------------------
9188 : //
9189 : // -----------------------------------------------------------------------
9190 533008 : void MSTransformManager::smoothFourierFloat(Int,
9191 : const Vector<Float> &inputDataStripe,
9192 : const Vector<bool> &inputFlagStripe,
9193 : const Vector<Float> &,
9194 : Vector<Float> &outputDataStripe,
9195 : Vector<bool> &outputFlagStripe)
9196 : {
9197 : // replace flagged channel data with zero
9198 533008 : auto mutableInputDataStripe = inputDataStripe;
9199 533008 : Int const numChan = mutableInputDataStripe.nelements();
9200 44599088 : for (Int ichan = 0; ichan < numChan; ++ichan) {
9201 44066080 : if (inputFlagStripe[ichan]) {
9202 14365852 : mutableInputDataStripe[ichan] = 0.0f;
9203 : }
9204 : }
9205 :
9206 : // execute convolution
9207 533008 : Convolver<Float> *convolver = getConvolver(numChan);
9208 533008 : convolver->linearConv(outputDataStripe, mutableInputDataStripe);
9209 :
9210 : // copy input flags
9211 533008 : outputFlagStripe = inputFlagStripe;
9212 533008 : }
9213 :
9214 : // -----------------------------------------------------------------------
9215 : //
9216 : // -----------------------------------------------------------------------
9217 532932 : void MSTransformManager::smoothFourierComplex(Int n,
9218 : const Vector<Complex> &inputDataStripe,
9219 : const Vector<bool> &inputFlagStripe,
9220 : const Vector<Float> &inputWeightStripe,
9221 : Vector<Complex> &outputDataStripe, Vector<bool> &outputFlagStripe)
9222 : {
9223 532932 : Vector<Float> inputDataStripeFloat = real(inputDataStripe);
9224 532932 : Vector<Float> outputDataStripeFloat(inputDataStripeFloat.nelements());
9225 532932 : smoothFourierFloat(n, inputDataStripeFloat, inputFlagStripe,
9226 : inputWeightStripe, outputDataStripeFloat, outputFlagStripe);
9227 532932 : convertArray(outputDataStripe, outputDataStripeFloat);
9228 532932 : }
9229 :
9230 : // -----------------------------------------------------------------------
9231 : //
9232 : // -----------------------------------------------------------------------
9233 533008 : Convolver<Float> *MSTransformManager::getConvolver(Int const numChan) {
9234 533008 : if (convolverPool_.find(numChan) == convolverPool_.end()) {
9235 0 : throw AipsError("Failed to get convolver. Smoothing is not properly configured.");
9236 : }
9237 533008 : return &convolverPool_[numChan];
9238 : }
9239 :
9240 : } //# NAMESPACE CASA - END
|