Line data Source code
1 : //# SynthesisImagerVi2.cc: Implementation of SynthesisImager.h
2 : //# Copyright (C) 1997-2019
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //# This library is free software; you can redistribute it and/or modify it
5 : //# under the terms of the GNU General Public License as published by
6 : //# the Free Software Foundation; either version 3 of the License, or (at your
7 : //# option) any later version.
8 : //#
9 : //# This library is distributed in the hope that it will be useful, but WITHOUT
10 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
12 : //# License for more details.
13 : //#
14 : //# https://www.gnu.org/licenses/
15 : //#
16 : //# You should have received a copy of the GNU General Public License
17 : //# along with this library; if not, write to the Free Software Foundation,
18 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
19 : //#
20 : //# Queries concerning CASA should be submitted at
21 : //# https://help.nrao.edu
22 : //#
23 : //# Postal address: CASA Project Manager
24 : //# National Radio Astronomy Observatory
25 : //# 520 Edgemont Road
26 : //# Charlottesville, VA 22903-2475 USA
27 : //#
28 : //#
29 : //# $Id$
30 :
31 : #define CFC_VERBOSE false /* Control the verbosity when building CFCache. */
32 :
33 : #include <casacore/casa/Exceptions/Error.h>
34 : #include <iostream>
35 : #include <sstream>
36 :
37 : #include <casacore/casa/Arrays/Matrix.h>
38 : #include <casacore/casa/Arrays/ArrayMath.h>
39 : #include <casacore/casa/Arrays/ArrayLogical.h>
40 :
41 :
42 : #include <casacore/casa/Logging.h>
43 : #include <casacore/casa/Logging/LogIO.h>
44 : #include <casacore/casa/Logging/LogMessage.h>
45 : #include <casacore/casa/Logging/LogSink.h>
46 : #include <casacore/casa/Logging/LogMessage.h>
47 : #include <casacore/casa/System/ProgressMeter.h>
48 :
49 : #include <casacore/casa/OS/DirectoryIterator.h>
50 : #include <casacore/casa/OS/File.h>
51 : #include <casacore/casa/OS/HostInfo.h>
52 : #include <casacore/casa/OS/Path.h>
53 : //#include <casa/OS/Memory.h>
54 :
55 : #include <casacore/lattices/LRegions/LCBox.h>
56 :
57 : #include <casacore/measures/Measures/MeasTable.h>
58 :
59 : #include <casacore/ms/MeasurementSets/MSHistoryHandler.h>
60 : #include <casacore/ms/MeasurementSets/MeasurementSet.h>
61 : #include <casacore/ms/MSSel/MSSelection.h>
62 :
63 :
64 : #include <synthesis/ImagerObjects/SynthesisImagerVi2.h>
65 :
66 : #include <synthesis/ImagerObjects/SynthesisUtilMethods.h>
67 : #include <synthesis/ImagerObjects/SIImageStore.h>
68 : #include <synthesis/ImagerObjects/SIImageStoreMultiTerm.h>
69 : #include <synthesis/ImagerObjects/CubeMajorCycleAlgorithm.h>
70 : #include <synthesis/ImagerObjects/CubeMakeImageAlgorithm.h>
71 : #include <synthesis/MeasurementEquations/VPManager.h>
72 : #include <imageanalysis/Utilities/SpectralImageUtil.h>
73 : #include <msvis/MSVis/MSUtil.h>
74 : #include <msvis/MSVis/VisSetUtil.h>
75 : #include <msvis/MSVis/VisImagingWeight.h>
76 :
77 : #include <synthesis/TransformMachines2/GridFT.h>
78 : #include <synthesis/TransformMachines2/WPConvFunc.h>
79 : #include <synthesis/TransformMachines2/WProjectFT.h>
80 : #include <synthesis/TransformMachines2/VisModelData.h>
81 : #include <synthesis/TransformMachines2/AWProjectFT.h>
82 : #include <synthesis/TransformMachines2/HetArrayConvFunc.h>
83 : #include <synthesis/TransformMachines2/MosaicFTNew.h>
84 : #include <synthesis/TransformMachines2/AWPLPG.h>
85 : #include <synthesis/TransformMachines2/MultiTermFTNew.h>
86 : #include <synthesis/TransformMachines2/AWProjectWBFTNew.h>
87 : #include <synthesis/TransformMachines2/AWConvFunc.h>
88 : //#include <synthesis/TransformMachines2/AWConvFuncEPJones.h>
89 : #include <synthesis/TransformMachines2/NoOpATerm.h>
90 : #include <synthesis/TransformMachines2/SDGrid.h>
91 : #include <synthesis/TransformMachines/WProjectFT.h>
92 : #include <synthesis/TransformMachines2/BriggsCubeWeightor.h>
93 : #include <casacore/casa/Utilities/Regex.h>
94 : #include <casacore/casa/OS/Directory.h>
95 : #include <msvis/MSVis/VisibilityIteratorImpl2.h>
96 : //#include <casadbus/utilities/BusAccess.h>
97 : //#include <casadbus/session/DBusSession.h>
98 :
99 : #include <sys/types.h>
100 : #include <unistd.h>
101 : #include <iomanip>
102 : #include <thread>
103 : #include <synthesis/Parallel/Applicator.h>
104 :
105 : using namespace std;
106 :
107 : using namespace casacore;
108 :
109 : namespace casa { //# NAMESPACE CASA - BEGIN
110 : extern Applicator applicator;
111 1711 : SynthesisImagerVi2::SynthesisImagerVi2() : SynthesisImager(), vi_p(0), fselections_p(nullptr), imparsVec_p(0), gridparsVec_p(0) {
112 : /*cerr << "is applicator initialized " << applicator.initialized() << endl;
113 : if(!applicator.initialized()){
114 : int argc=1;
115 : char **argv;
116 : casa::applicator.init ( argc, argv );
117 : cerr << "controller ?" << applicator.isController() << " worker? " << applicator.isWorker() << " numprocs " << applicator.numProcs() << endl;
118 : }
119 : */
120 1711 : mss_p.resize(0);
121 1711 : }
122 :
123 2594 : SynthesisImagerVi2::~SynthesisImagerVi2(){
124 3500 : for (uInt k=0; k < mss_p.nelements(); ++k){
125 1789 : if(mss_p[k])
126 1789 : delete mss_p[k];
127 : }
128 1711 : SynthesisUtilMethods::getResource("End Run");
129 2594 : }
130 :
131 1804 : Bool SynthesisImagerVi2::selectData(const SynthesisParamsSelect& selpars){
132 3608 : LogIO os( LogOrigin("SynthesisImagerVi2","selectData",WHERE) );
133 1804 : Bool retval=True;
134 :
135 1804 : SynthesisUtilMethods::getResource("Start Run");
136 :
137 : try
138 : {
139 :
140 :
141 1804 : MeasurementSet thisms;
142 : { ///Table system seems to have a bug when running in multi-process as the source table disappears
143 : /// temporarily when other processes are updating it
144 1804 : uInt exceptCounter=0;
145 :
146 : while(true){
147 : try{
148 : //Respect the readonly flag...necessary for multi-process access
149 3608 : thisms=MeasurementSet(selpars.msname, TableLock(TableLock::UserNoReadLocking),
150 3608 : selpars.readonly ? Table::Old : Table::Update);
151 1804 : break;
152 : }
153 0 : catch(AipsError &x){
154 :
155 0 : String mes=x.getMesg();
156 0 : if(mes.contains("FilebufIO::readBlock") || mes.contains("SOURCE")){
157 0 : std::this_thread::sleep_for(std::chrono::milliseconds(50));
158 0 : os << LogIO::WARN << "#####CATCHING a sleep because "<< mes<< LogIO::POST;
159 : }
160 : else
161 0 : throw(AipsError("Error in selectdata: "+mes));
162 :
163 0 : if(exceptCounter > 100){
164 0 : throw(AipsError("Error in selectdata got 100 of this exeception: "+mes));
165 :
166 : }
167 :
168 0 : }
169 0 : ++exceptCounter;
170 0 : }
171 : }//End of work around for table disappearing bug
172 :
173 :
174 :
175 1804 : useScratch_p=selpars.usescratch;
176 1804 : readOnly_p = selpars.readonly;
177 1804 : lockMS(thisms);
178 1804 : thisms.setMemoryResidentSubtables (MrsEligibility::defaultEligible());
179 :
180 :
181 : // cout << "**************** usescr : " << useScratch_p << " readonly : " << readOnly_p << endl;
182 : //if you want to use scratch col...make sure they are there
183 : ///Need to clear this in first pass only...child processes or loops for cube ///should skip it
184 1804 : if(!(impars_p.mode.contains("cube")) || ((impars_p.mode.contains("cube")) && doingCubeGridding_p)){
185 1793 : if(selpars.usescratch && !selpars.readonly){
186 38 : VisSetUtil::addScrCols(thisms, true, false, true, false);
187 38 : refim::VisModelData::clearModel(thisms);
188 : }
189 : ////TESTOO
190 : //Int CPUID;
191 : //MPI_Comm_rank(MPI_COMM_WORLD, &CPUID);
192 : //cerr << " SELPARS " << selpars.toRecord() << endl;
193 1793 : if(!selpars.incrmodel && !selpars.usescratch && !selpars.readonly)
194 17 : refim::VisModelData::clearModel(thisms, selpars.field, selpars.spw);
195 : }//end of first pass if for cubes
196 : // unlockMSs();
197 :
198 :
199 1804 : os << "MS : " << selpars.msname << " | ";
200 :
201 : //Some MSSelection
202 : //If everything is empty (which is valid) it will throw an exception..below
203 : //So make sure the main defaults are not empy i.e field and spw
204 1804 : MSSelection thisSelection;
205 1804 : if(selpars.field != ""){
206 615 : thisSelection.setFieldExpr(selpars.field);
207 615 : os << "Selecting on fields : " << selpars.field << " | " ;//LogIO::POST;
208 : }else
209 1189 : thisSelection.setFieldExpr("*");
210 1804 : if(selpars.spw != ""){
211 665 : thisSelection.setSpwExpr(selpars.spw);
212 665 : os << "Selecting on spw :"<< selpars.spw << " | " ;//LogIO::POST;
213 : }else
214 1139 : thisSelection.setSpwExpr("*");
215 :
216 1804 : if(selpars.antenna != ""){
217 91 : Vector<String> antNames(1, selpars.antenna);
218 : // thisSelection.setAntennaExpr(MSSelection::nameExprStr( antNames));
219 91 : thisSelection.setAntennaExpr(selpars.antenna);
220 91 : os << "Selecting on antenna names : " << selpars.antenna << " | " ;//LogIO::POST;
221 :
222 91 : }
223 1804 : if(selpars.timestr != ""){
224 14 : thisSelection.setTimeExpr(selpars.timestr);
225 14 : os << "Selecting on time range : " << selpars.timestr << " | " ;//LogIO::POST;
226 : }
227 1804 : if(selpars.uvdist != ""){
228 0 : thisSelection.setUvDistExpr(selpars.uvdist);
229 0 : os << "Selecting on uvdist : " << selpars.uvdist << " | " ;//LogIO::POST;
230 : }
231 1804 : if(selpars.scan != ""){
232 14 : thisSelection.setScanExpr(selpars.scan);
233 14 : os << "Selecting on scan : " << selpars.scan << " | " ;//LogIO::POST;
234 : }
235 1804 : if(selpars.obs != ""){
236 0 : thisSelection.setObservationExpr(selpars.obs);
237 0 : os << "Selecting on Observation Expr : " << selpars.obs << " | " ;//LogIO::POST;
238 : }
239 1804 : if(selpars.state != ""){
240 72 : thisSelection.setStateExpr(selpars.state);
241 72 : os << "Selecting on Scan Intent/State : " << selpars.state << " | " ;//LogIO::POST;
242 : }
243 : // if(selpars.taql != ""){
244 : // thisSelection.setTaQLExpr(selpars.taql);
245 : // os << "Selecting via TaQL : " << selpars.taql << " | " ;//LogIO::POST;
246 : // }
247 1804 : os << "[Opened " << (readOnly_p?"in readonly mode":(useScratch_p?"with scratch model column":"with virtual model column")) << "]" << LogIO::POST;
248 1804 : TableExprNode exprNode=thisSelection.toTableExprNode(&thisms);
249 1801 : if(!(exprNode.isNull()))
250 : {
251 :
252 :
253 1801 : MeasurementSet thisMSSelected0 = MeasurementSet(thisms(exprNode));
254 1801 : mss_p.resize(mss_p.nelements()+1, false, true);
255 1801 : if(selpars.taql != "")
256 : {
257 0 : MSSelection mss0;
258 0 : mss0.setTaQLExpr(selpars.taql);
259 0 : os << "Selecting via TaQL : " << selpars.taql << " | " ;//LogIO::POST;
260 :
261 0 : TableExprNode tenWithTaQL=mss0.toTableExprNode(&thisMSSelected0);
262 0 : MeasurementSet thisMSSelected1 = MeasurementSet(thisMSSelected0(tenWithTaQL));
263 : //mss4vi_p[mss4vi_p.nelements()-1]=MeasurementSet(thisms(exprNode));
264 0 : mss_p[mss_p.nelements()-1]=new MeasurementSet(thisMSSelected1);
265 0 : }
266 : else
267 1801 : mss_p[mss_p.nelements()-1]=new MeasurementSet(thisMSSelected0);
268 :
269 1801 : os << " NRows selected : " << (mss_p[mss_p.nelements()-1])->nrow() << LogIO::POST;
270 1801 : unlockMSs();
271 1801 : }
272 : else{
273 0 : throw(AipsError("Selection for given MS "+selpars.msname+" is invalid"));
274 : }
275 1801 : if((mss_p[mss_p.nelements()-1])->nrow() ==0){
276 1 : delete mss_p[mss_p.nelements()-1];
277 1 : mss_p.resize(mss_p.nelements()-1, True, True);
278 1 : if(mss_p.nelements()==0)
279 1 : throw(AipsError("Data selection ended with 0 rows"));
280 : //Sill have some valid ms's so return false and do not proceed to do
281 : //channel selection
282 0 : unlockMSs();
283 0 : return False;
284 : }
285 :
286 :
287 :
288 : ///Channel selection
289 : {
290 1800 : if(!fselections_p) fselections_p=new FrequencySelections();
291 1800 : Matrix<Int> chanlist = thisSelection.getChanList(mss_p[mss_p.nelements()-1]);
292 1800 : Matrix<Double> freqList=thisSelection.getChanFreqList(mss_p[mss_p.nelements()-1]);
293 : //cerr << std::setprecision(12) << "FreqList " << freqList << endl;
294 1800 : IPosition shape = freqList.shape();
295 1800 : uInt nSelections = shape[0];
296 : ///temporary variable as we carry that for tunechunk...till we get rid of it
297 1800 : selFreqFrame_p=selpars.freqframe;
298 1800 : Bool ignoreframe=False;
299 1800 : MFrequency::Types freqFrame=MFrequency::castType(MSColumns(*mss_p[mss_p.nelements()-1]).spectralWindow().measFreqRef()(Int(chanlist(0,0))));
300 :
301 1800 : if(selpars.freqframe == MFrequency::REST ||selpars.freqframe == MFrequency::Undefined){
302 21 : selFreqFrame_p=freqFrame;
303 21 : ignoreframe=True;
304 : }
305 1800 : if(selpars.freqbeg==""){
306 : // Going round the problem of CAS-8829
307 : /*vi::FrequencySelectionUsingChannels channelSelector;
308 :
309 : channelSelector.add(thisSelection, mss_p[mss_p.nelements()-1]);
310 :
311 : fselections_p.add(channelSelector);
312 : */
313 : ////////////////////////////
314 : Double lowfreq;
315 : Double topfreq;
316 1789 : Vector<Int> fieldList=thisSelection.getFieldList(mss_p[mss_p.nelements()-1]);
317 : // cerr << "chanlist " << chanlist.column(0) << "\n fieldList " << fieldList << endl;
318 :
319 : //cerr << "selpars.freqframe " << selpars.freqframe << endl;
320 1789 : vi::FrequencySelectionUsingFrame channelSelector(selFreqFrame_p);
321 : ///temporary variable as we carry that for tunechunk
322 :
323 1789 : Bool selectionValid=False;
324 4190 : for(uInt k=0; k < nSelections; ++k){
325 2401 : Bool thisSpwSelValid=False;
326 : //The getChanfreqList is wrong for beg and end..going round that too.
327 4802 : Vector<Double> freqies=MSColumns(*mss_p[mss_p.nelements()-1]).spectralWindow().chanFreq()(Int(chanlist(k,0)));
328 4802 : Vector<Double> chanwidth=MSColumns(*mss_p[mss_p.nelements()-1]).spectralWindow().chanWidth()(Int(chanlist(k,0)));
329 :
330 2401 : if(freqList(k,3) < 0.0){
331 94 : topfreq=freqies(chanlist(k,1));//-chanwidth(chanlist(k,1))/2.0;
332 94 : lowfreq=freqies(chanlist(k,2));//+chanwidth(chanlist(k,2))/2.0;
333 : //lowfreq=freqList(k,2); //+freqList(k,3)/2.0;
334 : //topfreq=freqList(k, 1); //-freqList(k,3)/2.0;
335 : }
336 : else{
337 2307 : lowfreq=freqies(chanlist(k,1));//-chanwidth(chanlist(k,1))/2.0;
338 2307 : topfreq=freqies(chanlist(k,2));//+chanwidth(chanlist(k,2))/2.0;
339 : //lowfreq=freqList(k,1);//-freqList(k,3)/2.0;
340 : //topfreq=freqList(k, 2);//+freqList(k,3)/2.0;
341 : }
342 :
343 2401 : if(!ignoreframe){
344 :
345 :
346 : //cerr << "begin " << lowfreq << " " << topfreq << endl;
347 : //vi::VisibilityIterator2 tmpvi(mss_p, vi::SortColumns(), false);
348 : //VisBufferUtil::getFreqRangeFromRange(lowfreq, topfreq, freqFrame, lowfreq, topfreq, tmpvi, selFreqFrame_p);
349 : // lockMS(*(const_cast<MeasurementSet*> (mss_p[mss_p.nelements()-1])));
350 2380 : if(MSUtil::getFreqRangeInSpw( lowfreq,
351 4760 : topfreq, Vector<Int>(1,chanlist(k,0)), Vector<Int>(1,chanlist(k,1)),
352 4760 : Vector<Int>(1, chanlist(k,2)-chanlist(k,1)+1),
353 2380 : *mss_p[mss_p.nelements()-1] ,
354 : selFreqFrame_p,
355 : fieldList, False))
356 : {
357 2362 : selectionValid=True;
358 2362 : thisSpwSelValid=True;
359 : }
360 : // unlockMSs();
361 :
362 : }
363 :
364 2401 : if(thisSpwSelValid || ignoreframe){
365 2383 : andFreqSelection(mss_p.nelements()-1, Int(freqList(k,0)), lowfreq, topfreq, selFreqFrame_p);
366 2383 : andChanSelection(mss_p.nelements()-1, Int(chanlist(k,0)), Int(chanlist(k,1)),Int(chanlist(k,2)));
367 : }
368 2401 : }
369 1789 : if(! (selectionValid && !ignoreframe)){
370 : //os << "Did not match spw selection in the selected ms " << LogIO::WARN << LogIO::POST;
371 21 : retval=False;
372 : }
373 : //fselections_p->add(channelSelector);
374 : //////////////////////////////////
375 1789 : }
376 : else{
377 :
378 : //////More workaroung CAS-8829
379 : //MFrequency::Types freqFrame=MFrequency::castType(MSColumns(*mss_p[mss_p.nelements()-1]).spectralWindow().measFreqRef()(Int(freqList(0,0))));
380 11 : Quantity freq;
381 11 : Quantity::read(freq, selpars.freqbeg);
382 11 : Double lowfreq=freq.getValue("Hz");
383 11 : Quantity::read(freq, selpars.freqend);
384 11 : Double topfreq=freq.getValue("Hz");
385 :
386 : ////Work aroun CAS-8829
387 : // if(vi_p)
388 : //VisBufferUtil::getFreqRangeFromRange(lowfreq, topfreq, selpars.freqframe, lowfreq, topfreq, *vi_p, freqFrame);
389 : //cerr << "lowFreq "<< lowfreq << " topfreq " << topfreq << endl;
390 : //vi::FrequencySelectionUsingFrame channelSelector((vi_p ? freqFrame :selpars.freqframe));
391 : //vi::FrequencySelectionUsingFrame channelSelector(selpars.freqframe);
392 22 : for(uInt k=0; k < nSelections; ++k){
393 : //channelSelector.add(Int(freqList(k,0)), lowfreq, topfreq);
394 : //andFreqSelection((mss_p.nelements()-1), Int(freqList(k,0)), lowfreq, topfreq, vi_p ?freqFrame : selpars.freqframe);
395 11 : andFreqSelection((mss_p.nelements()-1), Int(freqList(k,0)), lowfreq, topfreq, selFreqFrame_p);
396 : }
397 : //fselections_p->add(channelSelector);
398 :
399 11 : }
400 1800 : }//End of channel selection
401 :
402 1800 : writeAccess_p=writeAccess_p && !selpars.readonly;
403 1800 : createVisSet(writeAccess_p);
404 :
405 : /////// Remove this when the new vi/vb is able to get the full freq range.
406 1800 : mssFreqSel_p.resize();
407 1800 : mssFreqSel_p = thisSelection.getChanFreqList(NULL,true);
408 :
409 : //// Set the data column on which to operate
410 : // TT: added checks for the requested data column existace
411 : // cout << "Using col : " << selpars.datacolumn << endl;
412 1800 : if( selpars.datacolumn.contains("data") || selpars.datacolumn.contains("obs") )
413 136 : { if( thisms.tableDesc().isColumn("DATA") ) { datacol_p = FTMachine::OBSERVED; }
414 0 : else { os << LogIO::SEVERE <<"DATA column does not exist" << LogIO::EXCEPTION;}
415 : }
416 1664 : else if( selpars.datacolumn.contains("corr") ) { datacol_p = FTMachine::CORRECTED; }
417 0 : else { os << LogIO::WARN << "Invalid data column : " << selpars.datacolumn << ". Using corrected (or observed if corrected doesn't exist)" << LogIO::POST; datacol_p = FTMachine::CORRECTED;}
418 :
419 :
420 1800 : dataSel_p.resize(dataSel_p.nelements()+1, true);
421 1800 : dataSel_p[dataSel_p.nelements()-1]=selpars;
422 : //cerr << "AT THE end of DATASEL " << selpars.toRecord() << endl;
423 :
424 1800 : unlockMSs();
425 1809 : }
426 4 : catch(AipsError &x)
427 : {
428 4 : unlockMSs();
429 4 : throw( AipsError("Error in selectData() : "+x.getMesg()) );
430 4 : }
431 :
432 1800 : return retval;
433 :
434 :
435 :
436 1804 : }
437 2383 : void SynthesisImagerVi2::andChanSelection(const Int msId, const Int spwId, const Int startchan, const Int endchan){
438 :
439 2383 : map<Int, Vector<Int> > spwsel;
440 2383 : auto it=channelSelections_p.find(msId);
441 2383 : if(it !=channelSelections_p.end())
442 594 : spwsel=it->second;
443 2383 : auto hasspw=spwsel.find(spwId);
444 2383 : Vector<Int>chansel(2,-1);
445 2383 : if(hasspw != spwsel.end()){
446 30 : chansel.resize();
447 30 : chansel=hasspw->second;
448 : }
449 2383 : Int nchan=endchan-startchan+1;
450 2383 : if(chansel(1)== -1)
451 2353 : chansel(1)=startchan;
452 2383 : if(chansel(1) >= startchan){
453 2354 : if(nchan > (chansel(1)-startchan+chansel(0))){
454 2353 : chansel(0)=nchan;
455 : }
456 : else{
457 1 : chansel(0)=chansel(1)-startchan+chansel(0);
458 : }
459 2354 : chansel(1)=startchan;
460 : }
461 : else{
462 29 : if((chansel(0) -(startchan - chansel(1)+1)) < nchan){
463 29 : chansel(0)=nchan+(startchan-chansel(1));
464 : }
465 : }
466 2383 : spwsel[spwId]=chansel;
467 2383 : channelSelections_p[msId]=spwsel;
468 : //cerr << "chansel "<< channelSelections_p << endl;
469 :
470 2383 : }
471 2394 : void SynthesisImagerVi2::andFreqSelection(const Int msId, const Int spwId, const Double freqBeg, const Double freqEnd, const MFrequency::Types frame){
472 :
473 :
474 2394 : Int key=msId;
475 :
476 2394 : Bool isDefined=False;
477 2394 : FrequencySelectionUsingFrame frameSel(frame);
478 3363 : for (uInt k =0; k<freqBegs_p.size(); ++k){
479 : //cerr <<freqBegs_p[k].first << " == " << key << " && " << freqSpws_p[k].second<< " == " << spwId << " && " << freqBeg << " < " << freqEnds_p[k].second<< " && " << freqEnd << " > " << freqBegs_p[k].second << endl;
480 969 : if((freqBegs_p[k].first == key || key <0 ) && (freqSpws_p[k].second==spwId || spwId <0) && (freqBeg < freqEnds_p[k].second) && (freqEnd > freqBegs_p[k].second)){
481 12 : isDefined=True;
482 : //cerr << k << " inside freqBegs " << freqBegs_p[k].second << " " << freqBeg << endl;
483 12 : if(freqBegs_p[k].second < freqBeg)
484 0 : freqBegs_p[k].second=freqBeg;
485 12 : if(freqEnds_p[k].second > freqEnd)
486 3 : freqEnds_p[k].second=freqEnd;
487 12 : if(msId < 0) key=freqBegs_p[k].first;
488 : //cerr << "modified " << freqBegs_p[k].second << " " << freqEnds_p[k].second << endl;
489 : }
490 : ///add only those that have the same msid
491 969 : if(freqBegs_p[k].first == key){
492 : //cerr << "added " << k << " freqBegs " << freqBegs_p[k].second << " " << freqEnds_p[k].second << endl;
493 885 : frameSel.add(freqSpws_p[k].second , freqBegs_p[k].second, freqEnds_p[k].second);
494 : }
495 : }
496 2394 : if(!isDefined && msId >=0){
497 : //cerr << "undefined " << key << " freqBegs " << freqBeg << " " << freqEnd << endl;
498 2382 : freqBegs_p.push_back(make_pair(key, freqBeg));
499 2382 : freqEnds_p.push_back(make_pair(key, freqEnd));
500 2382 : freqSpws_p.push_back(make_pair(key, spwId));
501 2382 : frameSel.add(spwId, freqBeg, freqEnd);
502 : }
503 2394 : CountedPtr<vi::FrequencySelections> copyFsels=fselections_p->clone();
504 2394 : uInt nMSs=copyFsels->size() <=msId ? msId+1 : copyFsels->size();
505 : //cerr << "nms " << nMSs << endl;
506 2394 : fselections_p=new FrequencySelections();
507 4872 : for (uInt k=0; k < nMSs ; ++k){
508 2478 : if(k==uInt(key)){
509 2394 : fselections_p->add(frameSel);
510 : //cerr <<"adding framesel " << frameSel.toString() << endl;
511 : }
512 : else{
513 84 : const FrequencySelectionUsingFrame& thissel= static_cast<const FrequencySelectionUsingFrame &> (copyFsels->get(k));
514 : //cerr <<"framesel orig " << thissel.toString() << endl;
515 84 : fselections_p->add(thissel);
516 :
517 : }
518 : }
519 :
520 :
521 :
522 2394 : }
523 :
524 0 : void SynthesisImagerVi2::tuneChunk(const Int gmap) {
525 :
526 0 : CoordinateSystem cs=itsMappers.imageStore(gmap)->getCSys();
527 0 : IPosition imshape=itsMappers.imageStore(gmap)->getShape();
528 : /////For some reason imagestore returns 0 channel image sometimes
529 : ////
530 0 : if(imshape(3) < 1) {
531 0 : return;
532 : }
533 :
534 0 : Double minFreq=SpectralImageUtil::worldFreq(cs, 0.0);
535 0 : Double maxFreq=SpectralImageUtil::worldFreq(cs,imshape(3)-1);
536 :
537 0 : if(maxFreq < minFreq){
538 0 : Double tmp=minFreq;
539 0 : minFreq=maxFreq;
540 0 : maxFreq=tmp;
541 : }
542 :
543 0 : Int spectralIndex=cs.findCoordinate(Coordinate::SPECTRAL);
544 0 : SpectralCoordinate spectralCoord=cs.spectralCoordinate(spectralIndex);
545 0 : maxFreq+=fabs(spectralCoord.increment()(0))/2.0;
546 0 : minFreq-=fabs(spectralCoord.increment()(0))/2.0;
547 0 : if(minFreq < 0.0) minFreq=0.0;
548 0 : MFrequency::Types intype=spectralCoord.frequencySystem(True);
549 :
550 0 : if(!VisBufferUtil::getFreqRangeFromRange(minFreq, maxFreq, intype, minFreq, maxFreq, *vi_p, selFreqFrame_p)){
551 : //Do not retune if conversion did not happen
552 0 : return;
553 : }
554 :
555 0 : maxFreq+=3.0*fabs(spectralCoord.increment()(0))/2.0;
556 0 : minFreq-=3.0*fabs(spectralCoord.increment()(0))/2.0;
557 0 : if(minFreq < 0.0) minFreq=0.0;
558 :
559 0 : auto copyFreqBegs=freqBegs_p;
560 0 : auto copyFreqEnds=freqEnds_p;
561 0 : auto copyFreqSpws= freqSpws_p;
562 : ///////////////TESTOO
563 : //cerr << std::setprecision(12) << "AFTER maxFreq " << maxFreq << " minFreq " << minFreq << endl;
564 : //for (Int k =0 ; k < (fselections_p->size()) ; ++k){
565 : // cerr << k << (fselections_p->get(k)).toString() << endl;
566 : // }
567 : ///////////////////////////////////////
568 : ///TESTOO
569 : // andFreqSelection(-1, -1, minFreq, maxFreq, MFrequency::TOPO);
570 0 : andFreqSelection(-1, -1, minFreq, maxFreq, selFreqFrame_p);
571 :
572 0 : vi_p->setFrequencySelection (*fselections_p);
573 :
574 0 : freqBegs_p=copyFreqBegs;
575 0 : freqEnds_p=copyFreqEnds;
576 0 : freqSpws_p=copyFreqSpws;
577 0 : }
578 :
579 :
580 892 : Bool SynthesisImagerVi2::defineImage(
581 : SynthesisParamsImage& impars,
582 : const SynthesisParamsGrid& gridpars)
583 : {
584 1784 : LogIO os( LogOrigin("SynthesisImagerVi2", "defineImage", WHERE) );
585 :
586 892 : if (mss_p.nelements() == 0)
587 0 : os << "SelectData has to be run before defineImage" << LogIO::EXCEPTION;
588 :
589 892 : CoordinateSystem csys;
590 892 : CountedPtr<refim::FTMachine> ftm, iftm;
591 892 : impars_p = impars;
592 892 : gridpars_p = gridpars;
593 :
594 : try {
595 892 : os << "Define image coordinates for [" << impars.imageName << "] : "
596 892 : << LogIO::POST;
597 892 : os << "Define image coordinates for [" << impars.imageName << "] : " << LogIO::POST;
598 : // cerr << "DEFIM " << gridpars_p.ftmachine << endl;
599 : // cerr << "###### gridpars compute " << gridpars.computePAStep << " " << gridpars_p.computePAStep << endl;
600 893 : csys = impars_p.buildCoordinateSystem( *vi_p, channelSelections_p, mss_p );
601 : //use the location defined for coordinates frame;
602 891 : mLocation_p=impars_p.obslocation;
603 891 : IPosition imshape = impars_p.shp();
604 :
605 :
606 890 : os << "Impars: start " << impars_p.start << LogIO::POST;
607 : os << "Shape: " << imshape
608 890 : << " Spectral: " << csys.spectralCoordinate().referenceValue()
609 1780 : << " at " << csys.spectralCoordinate().referencePixel()
610 1780 : << " with increment " << csys.spectralCoordinate().increment()
611 3560 : << LogIO::POST;
612 :
613 906 : if( (itsMappers.nMappers()==0) ||
614 16 : (impars_p.imsize[0]*impars_p.imsize[1] > itsMaxShape[0]*itsMaxShape[1]))
615 : {
616 876 : itsMaxShape=imshape;
617 876 : itsMaxCoordSys=csys;
618 : }
619 890 : itsNchan = imshape[3];
620 890 : itsCsysRec = impars_p.getcsys();
621 : /*
622 : os << "Define image [" << impars.imageName << "] : nchan : " << impars.nchan
623 : //<< ", freqstart:" << impars.freqStart.getValue() << impars.freqStart.getUnit()
624 : << ", start:" << impars.start
625 : << ", imsize:" << impars.imsize
626 : << ", cellsize: [" << impars.cellsize[0].getValue() << impars.cellsize[0].getUnit()
627 : << " , " << impars.cellsize[1].getValue() << impars.cellsize[1].getUnit()
628 : << LogIO::POST;
629 : */
630 : // phasecenter
631 890 : if (impars_p.phaseCenterFieldId == -1) {
632 : // user-specified
633 338 : phaseCenter_p = impars_p.phaseCenter;
634 552 : } else if (impars_p.phaseCenterFieldId >= 0) {
635 : // FIELD_ID
636 15 : auto const msobj = mss_p[0];
637 15 : MSFieldColumns msfield(msobj->field());
638 15 : phaseCenter_p=msfield.phaseDirMeas(impars_p.phaseCenterFieldId);
639 15 : } else {
640 : // use default FIELD_ID (0)
641 537 : auto const msobj = mss_p[0];
642 537 : MSFieldColumns msfield(msobj->field());
643 537 : phaseCenter_p=msfield.phaseDirMeas(0);
644 537 : }
645 :
646 :
647 906 : if ( (itsMappers.nMappers() == 0) or
648 16 : (impars_p.imsize[0]*impars_p.imsize[1] > itsMaxShape[0]*itsMaxShape[1])
649 : ) {
650 874 : itsMaxShape = imshape;
651 874 : itsMaxCoordSys = csys;
652 : }
653 890 : itsNchan = imshape[3];
654 890 : itsCsysRec = impars_p.getcsys();
655 :
656 : // os << "Define image [" << impars.imageName << "] : nchan : " << impars.nchan
657 : // //<< ", freqstart:" << impars.freqStart.getValue() << impars.freqStart.getUnit()
658 : // << ", start:" << impars.start
659 : // << ", imsize:" << impars.imsize
660 : // << ", cellsize: [" << impars.cellsize[0].getValue() << impars.cellsize[0].getUnit()
661 : // << " , " << impars.cellsize[1].getValue() << impars.cellsize[1].getUnit()
662 : // << LogIO::POST;
663 :
664 : // phasecenter
665 890 : if (impars_p.phaseCenterFieldId == -1) { // user-specified
666 338 : phaseCenter_p = impars_p.phaseCenter;
667 552 : } else if (impars_p.phaseCenterFieldId >= 0) { // FIELD_ID
668 15 : auto const msobj = mss_p[0];
669 15 : MSFieldColumns msfield(msobj->field());
670 15 : phaseCenter_p = msfield.phaseDirMeas(impars_p.phaseCenterFieldId);
671 15 : } else { // use default FIELD_ID (0)
672 537 : auto const msobj = mss_p[0];
673 537 : MSFieldColumns msfield(msobj->field());
674 537 : phaseCenter_p = msfield.phaseDirMeas(0);
675 537 : }
676 890 : }
677 2 : catch (AipsError &x) {
678 : os << "Error in building Coordinate System and Image Shape: "
679 : << x.getMesg()
680 2 : << LogIO::EXCEPTION;
681 2 : }
682 :
683 : try {
684 890 : os << "Set Gridding options for [" << impars_p.imageName << "]"
685 890 : << " with ftmachine: " << gridpars.ftmachine
686 890 : << LogIO::POST;
687 :
688 890 : itsVpTable = gridpars.vpTable;
689 1702 : itsMakeVP = ( gridpars.ftmachine.contains("mosaicft") or
690 1702 : gridpars.ftmachine.contains("awprojectft") ) ?
691 : False : True;
692 :
693 : //cerr << "DEFINEimage " << impars_p.toRecord() << endl;
694 :
695 1780 : createFTMachine(
696 890 : ftm, iftm, gridpars.ftmachine, impars_p.nTaylorTerms, gridpars.mType,
697 890 : gridpars.facets, gridpars.wprojplanes,
698 890 : gridpars.padding, gridpars.useAutoCorr, gridpars.useDoublePrec,
699 890 : gridpars.convFunc,
700 890 : gridpars.aTermOn, gridpars.psTermOn, gridpars.mTermOn,
701 1780 : gridpars.wbAWP, gridpars.cfCache, gridpars.usePointing, gridpars.pointingOffsetSigDev.tovector(),
702 890 : gridpars.doPBCorr, gridpars.conjBeams,
703 890 : gridpars.computePAStep, gridpars.rotatePAStep,
704 890 : gridpars.interpolation, impars_p.freqFrameValid, 1000000000, 16, impars_p.stokes,
705 890 : impars_p.imageName,
706 890 : gridpars.pointingDirCol, gridpars.convertFirst, gridpars.skyPosThreshold,
707 890 : gridpars.convSupport, gridpars.truncateSize, gridpars.gwidth, gridpars.jwidth,
708 890 : gridpars.minWeight, gridpars.clipMinMax, impars_p.pseudoi
709 : );
710 :
711 : }
712 0 : catch (AipsError &x) {
713 0 : os << "Error in setting up FTMachine(): " << x.getMesg() << LogIO::EXCEPTION;
714 0 : }
715 :
716 :
717 : try {
718 1780 : appendToMapperList(
719 1780 : impars_p.imageName, csys, impars_p.shp(),
720 : ftm, iftm,
721 890 : gridpars.distance, gridpars.facets, gridpars.chanchunks, impars_p.overwrite,
722 890 : gridpars.mType, gridpars.padding, impars_p.nTaylorTerms, impars_p.startModel
723 : );
724 :
725 890 : imageDefined_p = true;
726 : }
727 0 : catch(AipsError &x) {
728 0 : os << "Error in adding Mapper: " + x.getMesg() << LogIO::EXCEPTION;
729 0 : }
730 :
731 890 : imparsVec_p.resize(imparsVec_p.nelements()+1, true);
732 890 : imparsVec_p[imparsVec_p.nelements()-1] = impars_p;
733 : ///For now cannot deal with cube and mtmfs in C++ parallel mode
734 890 : if (imparsVec_p[0].deconvolver == "mtmfs") setCubeGridding(False);
735 : // cerr << "DECONV " << imparsVec_p[0].deconvolver
736 : // << " cube gridding " << doingCubeGridding_p << endl;
737 890 : gridparsVec_p.resize(gridparsVec_p.nelements()+1, true);
738 890 : gridparsVec_p[imparsVec_p.nelements()-1] = gridpars_p;
739 : // For now as awproject does not work with the c++ mpi cube gridding
740 : // make sure it works the old way as mfs
741 : // if ( gridparsVec_p[0].ftmachine.contains("awproject") )
742 : // setCubeGridding(False);
743 890 : itsMakeVP =
744 1702 : ( gridparsVec_p[0].ftmachine.contains("mosaicft") or
745 1702 : (gridparsVec_p[0].ftmachine.at(0,3) == "awp")
746 2592 : ) ? False : True;
747 890 : return true;
748 898 : }
749 :
750 842 : Bool SynthesisImagerVi2::defineImage(
751 : CountedPtr<SIImageStore> imstor,
752 : SynthesisParamsImage& impars,
753 : const SynthesisParamsGrid& gridpars)
754 : {
755 842 : gridpars_p=gridpars;
756 842 : Int id = itsMappers.nMappers();
757 842 : CoordinateSystem csys = imstor->getCSys();
758 842 : IPosition imshape = imstor->getShape();
759 842 : Int nx=imshape[0], ny=imshape[1];
760 842 : if ( (id==0) || (nx*ny > itsMaxShape[0]*itsMaxShape[1]) ) {
761 827 : itsMaxShape=imshape;
762 827 : itsMaxCoordSys=csys;
763 : }
764 842 : mLocation_p=impars.obslocation;
765 : // phasecenter
766 842 : if (impars.phaseCenterFieldId == -1) { // user-specified
767 395 : phaseCenter_p = impars.phaseCenter;
768 : }
769 447 : else if (impars.phaseCenterFieldId >= 0) { // FIELD_ID
770 9 : auto const msobj = mss_p[0];
771 9 : MSFieldColumns msfield(msobj->field());
772 9 : phaseCenter_p = msfield.phaseDirMeas(impars.phaseCenterFieldId);
773 9 : }
774 : else { // use default FIELD_ID (0)
775 438 : auto const msobj = mss_p[0];
776 438 : MSFieldColumns msfield(msobj->field());
777 438 : phaseCenter_p = msfield.phaseDirMeas(0);
778 438 : }
779 :
780 842 : itsVpTable = gridpars.vpTable;
781 712 : itsMakeVP = ( gridpars.ftmachine.contains("mosaicft") or
782 1554 : (gridpars.ftmachine.at(0,3) == "awp")
783 1554 : ) ? False : True;
784 842 : CountedPtr<refim::FTMachine> ftm, iftm;
785 :
786 1684 : createFTMachine(
787 842 : ftm, iftm, gridpars.ftmachine, impars.nTaylorTerms, gridpars.mType,
788 842 : gridpars.facets, gridpars.wprojplanes,
789 842 : gridpars.padding,gridpars.useAutoCorr,gridpars.useDoublePrec,
790 842 : gridpars.convFunc,
791 842 : gridpars.aTermOn,gridpars.psTermOn, gridpars.mTermOn,
792 842 : gridpars.wbAWP,gridpars.cfCache,gridpars.usePointing,
793 842 : gridpars.pointingOffsetSigDev.tovector(),
794 842 : gridpars.doPBCorr,gridpars.conjBeams,
795 842 : gridpars.computePAStep,gridpars.rotatePAStep,
796 842 : gridpars.interpolation, impars.freqFrameValid, 1000000000, 16, impars.stokes,
797 842 : impars.imageName,
798 842 : gridpars.pointingDirCol, gridpars.convertFirst, gridpars.skyPosThreshold,
799 842 : gridpars.convSupport, gridpars.truncateSize, gridpars.gwidth, gridpars.jwidth,
800 842 : gridpars.minWeight, gridpars.clipMinMax, impars.pseudoi);
801 :
802 842 : if (gridpars.facets >1) {
803 : // Make and connect the list.
804 : Block<CountedPtr<SIImageStore> > imstorList =
805 0 : createFacetImageStoreList( imstor, gridpars.facets );
806 0 : for( uInt facet=0; facet<imstorList.nelements(); facet++) {
807 0 : CountedPtr<refim::FTMachine> new_ftm, new_iftm;
808 0 : if (facet == 0) {
809 0 : new_ftm = ftm;
810 0 : new_iftm = iftm;
811 : }
812 : else {
813 0 : new_ftm = ftm->cloneFTM();
814 0 : new_iftm = iftm->cloneFTM();
815 : }
816 0 : itsMappers.addMapper(
817 0 : createSIMapper( gridpars.mType, imstorList[facet], new_ftm, new_iftm)
818 : );
819 0 : }
820 0 : }
821 : else {
822 842 : itsMappers.addMapper(
823 1684 : createSIMapper( gridpars.mType, imstor, ftm, iftm)
824 : );
825 : }
826 842 : impars_p = impars;
827 842 : gridpars_p = gridpars;
828 842 : imageDefined_p = true;
829 :
830 842 : imparsVec_p.resize(imparsVec_p.nelements()+1, true);
831 842 : imparsVec_p[imparsVec_p.nelements()-1] = impars_p;
832 :
833 842 : gridparsVec_p.resize(gridparsVec_p.nelements()+1, true);
834 842 : gridparsVec_p[gridparsVec_p.nelements()-1] = gridpars_p;
835 :
836 842 : return true;
837 842 : }
838 :
839 0 : Bool SynthesisImagerVi2::defineImage(CountedPtr<SIImageStore> imstor,
840 : const String& ftmachine)
841 : {
842 0 : CountedPtr<refim::FTMachine> ftm, iftm;
843 :
844 : // The following call to createFTMachine() uses the
845 : // following defaults
846 : //
847 : // facets=1, wprojplane=1, padding=1.0, useAutocorr=false,
848 : // useDoublePrec=true, gridFunction=String("SF")
849 : //
850 0 : createFTMachine(ftm, iftm, ftmachine);
851 :
852 0 : Int id=itsMappers.nMappers();
853 0 : CoordinateSystem csys =imstor->getCSys();
854 0 : IPosition imshape=imstor->getShape();
855 0 : Int nx=imshape[0], ny=imshape[1];
856 0 : if( (id==0) || (nx*ny > itsMaxShape[0]*itsMaxShape[1]))
857 : {
858 0 : itsMaxShape=imshape;
859 0 : itsMaxCoordSys=csys;
860 : }
861 :
862 0 : itsMappers.addMapper( createSIMapper( "default", imstor, ftm, iftm ) );
863 0 : imageDefined_p=true;
864 0 : return true;
865 0 : }
866 0 : Bool SynthesisImagerVi2::defineImage(CountedPtr<SIImageStore> imstor,
867 : const Record& ftmRec, const Record& iftmRec)
868 : {
869 0 : CountedPtr<refim::FTMachine> ftm, iftm;
870 0 : ftm=refim::VisModelData::NEW_FT(ftmRec);
871 0 : iftm=refim::VisModelData::NEW_FT(iftmRec);
872 :
873 0 : Int id=itsMappers.nMappers();
874 0 : CoordinateSystem csys =imstor->getCSys();
875 0 : IPosition imshape=imstor->getShape();
876 0 : Int nx=imshape[0], ny=imshape[1];
877 0 : if( (id==0) || (nx*ny > itsMaxShape[0]*itsMaxShape[1]))
878 : {
879 0 : itsMaxShape=imshape;
880 0 : itsMaxCoordSys=csys;
881 : }
882 :
883 0 : itsMappers.addMapper( createSIMapper( "default", imstor, ftm, iftm, id ) );
884 0 : imageDefined_p=true;
885 0 : return true;
886 0 : }
887 826 : Bool SynthesisImagerVi2::weight(const Record& inrec){
888 826 : String type, rmode, filtertype;
889 826 : Quantity noise, fieldofview,filterbmaj,filterbmin, filterbpa;
890 : Double robust, fracBW;
891 : Int npixels;
892 : Bool multiField, useCubeBriggs;
893 826 : SynthesisUtilMethods::getFromWeightRecord(type, rmode,noise, robust,fieldofview,npixels, multiField, useCubeBriggs,
894 : filtertype, filterbmaj,filterbmin, filterbpa, fracBW, inrec);
895 826 : return weight(type, rmode,noise, robust,fieldofview,npixels, multiField, useCubeBriggs,
896 1652 : filtertype, filterbmaj,filterbmin, filterbpa, fracBW );
897 :
898 :
899 826 : }
900 1545 : Bool SynthesisImagerVi2::weight(const String& type, const String& rmode,
901 : const Quantity& noise, const Double robust,
902 : const Quantity& fieldofview,
903 : const Int npixels, const Bool multiField, const Bool useCubeBriggs,
904 : const String& filtertype, const Quantity& filterbmaj,
905 : const Quantity& filterbmin, const Quantity& filterbpa, Double fracBW)
906 : {
907 3090 : LogIO os(LogOrigin("SynthesisImagerVi2", "weight()", WHERE));
908 :
909 1545 : if(rmode=="bwtaper") //See CAS-13021 for bwtaper algorithm details
910 : {
911 3 : if(fracBW == 0.0)
912 : {
913 1 : Double minFreq = 0.0;
914 1 : Double maxFreq = 0.0;
915 :
916 1 : if(itsMaxShape(3) < 1) {
917 0 : cout << "SynthesisImagerVi2::weight Only one channel in image " << endl;
918 : }
919 : else{
920 1 : minFreq=abs(SpectralImageUtil::worldFreq(itsMaxCoordSys, 0.0));
921 1 : maxFreq=abs(SpectralImageUtil::worldFreq(itsMaxCoordSys,itsMaxShape(3)-1));
922 :
923 1 : if(maxFreq < minFreq){
924 0 : Double tmp=minFreq;
925 0 : minFreq=maxFreq;
926 0 : maxFreq=tmp;
927 : }
928 :
929 1 : if((maxFreq != 0.0) || (minFreq != 0.0)) fracBW = 2*(maxFreq - minFreq)/(maxFreq + minFreq);
930 :
931 1 : os << LogIO::NORMAL << " Fractional bandwidth used by briggsbwtaper " << fracBW << endl; //<< LogIO::POST;
932 :
933 : }
934 : }
935 : }
936 :
937 3090 : weightParams_p=SynthesisUtilMethods::fillWeightRecord(type, rmode,noise, robust,fieldofview,
938 1545 : npixels, multiField, useCubeBriggs,filtertype, filterbmaj,filterbmin, filterbpa, fracBW);
939 :
940 : try {
941 : //Int nx=itsMaxShape[0];
942 : //Int ny=itsMaxShape[1];
943 :
944 :
945 : ///////////////////////
946 3090 : Quantity cellx=Quantity(itsMaxCoordSys.increment()[0], itsMaxCoordSys.worldAxisUnits()[0]);
947 3090 : Quantity celly=Quantity(itsMaxCoordSys.increment()[1], itsMaxCoordSys.worldAxisUnits()[1]);
948 : os << LogIO::NORMAL // Loglevel INFO
949 1545 : << "Set imaging weights : " ; //<< LogIO::POST;
950 :
951 1545 : if (type=="natural") {
952 : os << LogIO::NORMAL // Loglevel INFO
953 1484 : << "Natural weighting" << LogIO::POST;
954 1484 : imwgt_p=VisImagingWeight("natural");
955 : }
956 61 : else if (type=="radial") {
957 1 : os << "Radial weighting" << LogIO::POST;
958 1 : imwgt_p=VisImagingWeight("radial");
959 : }
960 : else{
961 60 : vi_p->originChunks();
962 60 : vi_p->origin();
963 60 : if(!imageDefined_p)
964 0 : throw(AipsError("Need to define image"));
965 60 : Int nx=itsMaxShape[0];
966 60 : Int ny=itsMaxShape[1];
967 120 : Quantity cellx=Quantity(itsMaxCoordSys.increment()[0], itsMaxCoordSys.worldAxisUnits()[0]);
968 120 : Quantity celly=Quantity(itsMaxCoordSys.increment()[1], itsMaxCoordSys.worldAxisUnits()[1]);
969 60 : if(type=="superuniform"){
970 1 : if(!imageDefined_p) throw(AipsError("Please define image first"));
971 1 : Int actualNpix=npixels;
972 1 : if(actualNpix <=0)
973 1 : actualNpix=3;
974 : os << LogIO::NORMAL // Loglevel INFO
975 : << "SuperUniform weighting over a square cell spanning ["
976 : << -actualNpix
977 1 : << ", " << actualNpix << "] in the uv plane" << LogIO::POST;
978 2 : imwgt_p=VisImagingWeight(*vi_p, rmode, noise, robust, nx,
979 : ny, cellx, celly, actualNpix,
980 1 : actualNpix, multiField);
981 : }
982 59 : else if ((type=="robust")||(type=="uniform")||(type=="briggs")) {
983 59 : if(!imageDefined_p) throw(AipsError("Please define image first"));
984 59 : Quantity actualFieldOfView_x(fieldofview), actualFieldOfView_y(fieldofview) ;
985 59 : Int actualNPixels_x(npixels),actualNPixels_y(npixels) ;
986 59 : String wtype;
987 59 : if(type=="briggs") {
988 46 : wtype = "Briggs";
989 : }
990 : else {
991 13 : wtype = "Uniform";
992 : }
993 59 : if(actualFieldOfView_x.get().getValue()==0.0&&actualNPixels_x==0) {
994 59 : actualNPixels_x=nx;
995 59 : actualFieldOfView_x=Quantity(actualNPixels_x*cellx.get("rad").getValue(),"rad");
996 59 : actualNPixels_y=ny;
997 59 : actualFieldOfView_y=Quantity(actualNPixels_y*celly.get("rad").getValue(),"rad");
998 : os << LogIO::NORMAL // Loglevel INFO
999 : << wtype
1000 : << " weighting: sidelobes will be suppressed over full image"
1001 59 : << LogIO::POST;
1002 : }
1003 0 : else if(actualFieldOfView_x.get().getValue()>0.0&&actualNPixels_x==0) {
1004 0 : actualNPixels_x=nx;
1005 0 : actualNPixels_y=ny;
1006 : os << LogIO::NORMAL // Loglevel INFO
1007 : << wtype
1008 : << " weighting: sidelobes will be suppressed over specified field of view: "
1009 0 : << actualFieldOfView_x.get("arcsec").getValue() << " arcsec by "
1010 0 : << actualFieldOfView_y.get("arcsec").getValue() << " arcsec" << LogIO::POST;
1011 : }
1012 0 : else if(actualFieldOfView_x.get().getValue()==0.0&&actualNPixels_x>0) {
1013 0 : actualFieldOfView_x=Quantity(actualNPixels_x*cellx.get("rad").getValue(),"rad");
1014 0 : actualFieldOfView_y=Quantity(actualNPixels_y*celly.get("rad").getValue(),"rad");
1015 : os << LogIO::NORMAL // Loglevel INFO
1016 : << wtype
1017 : << " weighting: sidelobes will be suppressed over full image field of view: "
1018 0 : << actualFieldOfView_x.get("arcsec").getValue() << " arcsec by "
1019 0 : << actualFieldOfView_y.get("arcsec").getValue() << " arcsec" << LogIO::POST;
1020 : }
1021 : else {
1022 : os << LogIO::NORMAL // Loglevel INFO
1023 : << wtype
1024 : << " weighting: sidelobes will be suppressed over specified field of view: "
1025 0 : << actualFieldOfView_x.get("arcsec").getValue() << " arcsec by "
1026 0 : << actualFieldOfView_y.get("arcsec").getValue() << " arcsec" << LogIO::POST;
1027 : }
1028 : os << LogIO::DEBUG1
1029 : << "Weighting used " << actualNPixels_x << " by " << actualNPixels_y << " uv pixels."
1030 59 : << LogIO::POST;
1031 59 : Quantity actualCellSize_x(actualFieldOfView_x.get("rad").getValue()/actualNPixels_x, "rad");
1032 59 : Quantity actualCellSize_y(actualFieldOfView_y.get("rad").getValue()/actualNPixels_y, "rad");
1033 :
1034 :
1035 : // cerr << "rmode " << rmode << " noise " << noise << " robust " << robust << " npixels " << actualNPixels << " cellsize " << actualCellSize << " multifield " << multiField << endl;
1036 : // Timer timer;
1037 : //timer.mark();
1038 : //Construct imwgt_p with old vi for now if old vi is in use as constructing with vi2 is slower
1039 : //Determine if any image is cube
1040 59 : if(useCubeBriggs){
1041 82 : String outstr=String("Doing spectral cube Briggs weighting formula -- " + rmode + (rmode=="abs" ? " with estimated noise "+ String::toString(noise.getValue())+noise.getUnit() : ""));
1042 41 : os << outstr << LogIO::POST;
1043 : //VisImagingWeight nat("natural");
1044 : //vi_p->useImagingWeight(nat);
1045 41 : if(rmode=="abs" && robust==0.0 && noise.getValue()==0.0)
1046 0 : throw(AipsError("Absolute Briggs formula does not allow for robust 0 and estimated noise per visibility 0"));
1047 :
1048 41 : CountedPtr<refim::BriggsCubeWeightor> bwgt=new refim::BriggsCubeWeightor(wtype=="Uniform" ? "none" : rmode, noise, robust,fracBW, npixels, multiField);
1049 82 : for (Int k=0; k < itsMappers.nMappers(); ++k){
1050 41 : itsMappers.getFTM2(k)->setBriggsCubeWeight(bwgt);
1051 : }
1052 :
1053 :
1054 41 : }
1055 : else
1056 : {
1057 36 : imwgt_p=VisImagingWeight(*vi_p, wtype=="Uniform" ? "none" : rmode, noise, robust,
1058 : actualNPixels_x, actualNPixels_y, actualCellSize_x,
1059 18 : actualCellSize_y, 0, 0, multiField);
1060 : }
1061 :
1062 : /*
1063 : if(rvi_p !=NULL){
1064 : imwgt_p=VisImagingWeight(*rvi_p, rmode, noise, robust,
1065 : actualNPixels, actualNPixels, actualCellSize,
1066 : actualCellSize, 0, 0, multiField);
1067 : }
1068 : else{
1069 : ////This is slower by orders of magnitude as of 2014/06/25
1070 : imwgt_p=VisImagingWeight(*vi_p, rmode, noise, robust,
1071 : actualNPixels, actualNPixels, actualCellSize,
1072 : actualCellSize, 0, 0, multiField);
1073 : }
1074 : */
1075 : //timer.show("After making visweight ");
1076 :
1077 59 : }
1078 : else {
1079 : //this->unlock();
1080 : os << LogIO::SEVERE << "Unknown weighting " << type
1081 0 : << LogIO::EXCEPTION;
1082 0 : return false;
1083 : }
1084 60 : }
1085 :
1086 : //// UV-Tapering
1087 : //cout << "Taper type : " << filtertype << " : " << (filtertype=="gaussian") << endl;
1088 1545 : if( filtertype == "gaussian" ) {
1089 : // os << "Setting uv-taper" << LogIO::POST;
1090 32 : imwgt_p.setFilter( filtertype, filterbmaj, filterbmin, filterbpa );
1091 : }
1092 1545 : vi_p->useImagingWeight(imwgt_p);
1093 : ///////////////////////////////
1094 :
1095 1545 : SynthesisUtilMethods::getResource("Set Weighting");
1096 :
1097 : /// return true;
1098 :
1099 1545 : }
1100 0 : catch(AipsError &x)
1101 : {
1102 0 : throw( AipsError("Error in Weighting : "+x.getMesg()) );
1103 0 : }
1104 :
1105 1545 : return true;
1106 1545 : }
1107 :
1108 890 : void SynthesisImagerVi2::appendToMapperList(String imagename,
1109 : CoordinateSystem& csys,
1110 : IPosition imshape,
1111 : CountedPtr<refim::FTMachine>& ftm,
1112 : CountedPtr<refim::FTMachine>& iftm,
1113 : Quantity distance,
1114 : Int facets,
1115 : Int chanchunks,
1116 : const Bool overwrite,
1117 : String mappertype,
1118 : Float padding,
1119 : uInt ntaylorterms,
1120 : const Vector<String> &startmodel)
1121 : {
1122 1780 : LogIO log_l(LogOrigin("SynthesisImagerVi2", "appendToMapperList(ftm)"));
1123 : //---------------------------------------------
1124 : // Some checks..
1125 :
1126 890 : if(facets > 1 && itsMappers.nMappers() > 0)
1127 0 : log_l << "Facetted image has to be the first of multifields" << LogIO::EXCEPTION;
1128 :
1129 890 : TcleanProcessingInfo procInfo;
1130 890 : CompositeNumber cn(uInt(imshape[0] * 2));
1131 : // heuristic factors multiplied to imshape based on gridder
1132 890 : size_t fudge_factor = 15;
1133 890 : if (ftm->name()=="MosaicFTNew") {
1134 54 : fudge_factor = 20;
1135 : }
1136 836 : else if (ftm->name()=="GridFT") {
1137 538 : fudge_factor = 9;
1138 : }
1139 890 : std::tie(procInfo, std::ignore, std::ignore) =
1140 1780 : nSubCubeFitInMemory(fudge_factor, imshape, padding);
1141 :
1142 : // chanchunks auto-calculation block, for now still here for awproject (CAS-12204)
1143 890 : if(chanchunks<1)
1144 : {
1145 0 : log_l << "Automatically calculated chanchunks";
1146 0 : log_l << " using imshape : " << imshape << LogIO::POST;
1147 :
1148 : // Do calculation here.
1149 : // This runs once per image field (for multi-field imaging)
1150 : // This runs once per cube partition, and will see only its own partition's shape
1151 : //chanchunks=1;
1152 :
1153 0 : chanchunks = procInfo.chnchnks;
1154 :
1155 : /*log_l << "Required memory " << required_mem / nlocal_procs / 1024. / 1024. / 1024.
1156 : << "\nAvailable memory " << memory_avail / 1024. / 1024 / 1024.
1157 : << " (rc: memory fraction " << usr_memfrac << "% rc memory " << usr_mem / 1024.
1158 : << ")\n" << nlocal_procs << " other processes on node\n"
1159 : << "Setting chanchunks to " << chanchunks << LogIO::POST;
1160 : */
1161 : }
1162 : //record this in gridpars_p
1163 890 : gridpars_p.chanchunks=chanchunks;
1164 890 : if( imshape.nelements()==4 && imshape[3]<chanchunks )
1165 : {
1166 0 : log_l << LogIO::WARN << "An image with " << imshape[3] << " channel(s) cannot be divided into " << chanchunks << " chunks. Please set chanchunks=1 or choose chanchunks<nchan." << LogIO::EXCEPTION;
1167 : }
1168 :
1169 890 : if(chanchunks > 1 && itsMappers.nMappers() > 0)
1170 0 : log_l << "Channel chunking is currently not supported with multi(outlier)-fields. Please submit a feature request if needed." << LogIO::EXCEPTION;
1171 :
1172 890 : if(chanchunks > 1) itsDataLoopPerMapper=true;
1173 :
1174 890 : AlwaysAssert( ( ( ! (ftm->name()=="MosaicFTNew" && mappertype=="imagemosaic") ) &&
1175 : ( ! (ftm->name()=="AWProjectWBFT" && mappertype=="imagemosaic") )) ,
1176 : AipsError );
1177 : //---------------------------------------------
1178 :
1179 : // Create the ImageStore object
1180 890 : CountedPtr<SIImageStore> imstor;
1181 890 : MSColumns msc(*(mss_p[0]));
1182 890 : imstor = createIMStore(imagename, csys, imshape, overwrite,msc, mappertype, ntaylorterms, distance, procInfo, facets, iftm->useWeightImage(), startmodel );
1183 :
1184 : // Create the Mappers
1185 890 : if( facets<2 && chanchunks<2) // One facet. Just add the above imagestore to the mapper list.
1186 : {
1187 886 : itsMappers.addMapper( createSIMapper( mappertype, imstor, ftm, iftm, ntaylorterms) );
1188 : }
1189 : else // This field is facetted. Make a list of reference imstores, and add all to the mapper list.
1190 : {
1191 :
1192 4 : if ( facets>1 && chanchunks==1 )
1193 : {
1194 : // Make and connect the list.
1195 4 : Block<CountedPtr<SIImageStore> > imstorList = createFacetImageStoreList( imstor, facets );
1196 44 : for( uInt facet=0; facet<imstorList.nelements(); facet++)
1197 : {
1198 40 : CountedPtr<refim::FTMachine> new_ftm, new_iftm;
1199 40 : if(facet==0){ new_ftm = ftm; new_iftm = iftm; }
1200 36 : else{ new_ftm=ftm->cloneFTM(); new_iftm=iftm->cloneFTM(); }
1201 : // imstorList[facet]->setDataPolFrame(imstor->getDataPolFrame());
1202 40 : itsMappers.addMapper(createSIMapper( mappertype, imstorList[facet], new_ftm, new_iftm, ntaylorterms));
1203 40 : }
1204 4 : }// facets
1205 0 : else if ( facets==1 && chanchunks>1 )
1206 : {
1207 : // Make and connect the list.
1208 0 : Block<CountedPtr<SIImageStore> > imstorList = createChanChunkImageStoreList( imstor, chanchunks );
1209 0 : for( uInt chunk=0; chunk<imstorList.nelements(); chunk++)
1210 : {
1211 :
1212 0 : CountedPtr<refim::FTMachine> new_ftm, new_iftm;
1213 0 : if(chunk==0){
1214 0 : new_ftm = ftm;
1215 0 : new_iftm = iftm; }
1216 : else{
1217 0 : new_ftm=ftm->cloneFTM();
1218 0 : new_iftm=iftm->cloneFTM(); }
1219 0 : imstorList[chunk]->setDataPolFrame(imstor->getDataPolFrame());
1220 0 : itsMappers.addMapper(createSIMapper( mappertype, imstorList[chunk], new_ftm, new_iftm, ntaylorterms));
1221 0 : }
1222 0 : }// chanchunks
1223 : else
1224 : {
1225 0 : throw( AipsError("Error in requesting "+String::toString(facets)+" facets on a side with " + String::toString(chanchunks) + " channel chunks. Support for faceting along with channel chunking is not yet available. Please submit a feature-request if you need multiple facets as well as chanchunks. ") );
1226 : }
1227 :
1228 : }// facets or chunks
1229 :
1230 890 : }
1231 :
1232 : /////////////////////////
1233 : /**
1234 : * Calculations of memory required / available -> nchunks .
1235 : *
1236 : * Returns a tuple with a TcleanProcessingInfo, vector of start channels per subchunk,
1237 : * vector of end channels.
1238 : */
1239 1718 : std::tuple<TcleanProcessingInfo, Vector<Int>, Vector<Int> > SynthesisImagerVi2::nSubCubeFitInMemory(const Int fudge_factor, const IPosition& imshape, const Float padding){
1240 3436 : LogIO log_l(LogOrigin("SynthesisImagerVi2", "nSubCubeFitInMemory"));
1241 :
1242 1718 : Double required_mem = fudge_factor * sizeof(Float);
1243 1718 : int nsubcube=1;
1244 1718 : CompositeNumber cn(uInt(imshape[0] * 2));
1245 8590 : for (size_t i = 0; i < imshape.nelements(); i++) {
1246 : // gridding pads image and increases to composite number
1247 6872 : if (i < 2) {
1248 3436 : required_mem *= cn.nextLargerEven(Int(padding*Float(imshape[i])-0.5));
1249 : }
1250 : else {
1251 3436 : required_mem *= imshape[i];
1252 : }
1253 : }
1254 :
1255 : // get number of tclean processes running on the same machine
1256 1718 : size_t nlocal_procs = 1;
1257 1718 : if (getenv("OMPI_COMM_WORLD_LOCAL_SIZE")) {
1258 0 : std::stringstream ss(getenv("OMPI_COMM_WORLD_LOCAL_SIZE"));
1259 0 : ss >> nlocal_procs;
1260 0 : }
1261 : //cerr << "NUM_PROC " << nlocal_procs << endl;
1262 : // assumes all processes need the same amount of memory
1263 1718 : required_mem *= nlocal_procs;
1264 : Double usr_memfrac, usr_mem;
1265 1718 : AipsrcValue<Double>::find(usr_memfrac, "system.resources.memfrac", 80.);
1266 1718 : AipsrcValue<Double>::find(usr_mem, "system.resources.memory", -1.);
1267 : Double memory_avail;
1268 1718 : if (usr_mem > 0.) {
1269 0 : memory_avail = usr_mem * 1024. * 1024.;
1270 : }
1271 : else {
1272 1718 : memory_avail = Double(HostInfo::memoryFree()) * (usr_memfrac / 100.) * 1024.;
1273 : }
1274 : // compute required chanchunks to fit into the available memory
1275 1718 : nsubcube = (int)std::ceil((Double)required_mem / memory_avail);
1276 1718 : Int nworkers= applicator.numProcs() < 2 ? 1 : applicator.numProcs()-1;
1277 1718 : if((nsubcube/nworkers) >1 && nworkers !=1){
1278 0 : nsubcube=(Int(std::floor(Float(nsubcube)/Float(nworkers)))+1)*nworkers;
1279 :
1280 : }
1281 1718 : if (imshape.nelements() == 4 && imshape[3] < nsubcube) {
1282 0 : nsubcube = imshape[3];
1283 : // TODO make chanchunks a divisor of nchannels?
1284 : }
1285 1718 : nsubcube = nsubcube < 1 ? 1 : nsubcube;
1286 1718 : if( (imshape[3] >= nworkers) && (nsubcube < nworkers)){
1287 0 : nsubcube=nworkers;
1288 : ///TESTOO
1289 : //if(imshape[3] > 2*nworkers)
1290 : // nsubcube=2*nworkers;
1291 :
1292 : }
1293 1718 : else if(imshape[3] < (applicator.numProcs()-1)){
1294 0 : nsubcube=imshape[3];
1295 : }
1296 1718 : Int chunksize=imshape[3]/nsubcube;
1297 1718 : Int rem=imshape[3] % nsubcube;
1298 : //case of nchan < numprocs
1299 1718 : if(chunksize==0 && rem > 0){
1300 0 : nsubcube=rem;
1301 0 : chunksize=1;
1302 0 : rem=0;
1303 : }
1304 : ///Avoid an extra chunk with 1 channel as it cause bumps in linear interpolation
1305 : ///See CAS-12625
1306 : /*
1307 : while((rem==1) && (chunksize >1)){
1308 : nsubcube +=1;
1309 : chunksize=imshape[3]/nsubcube;
1310 : rem=imshape[3] % nsubcube;
1311 : }
1312 : if(rem !=0) ++nsubcube;
1313 : . */
1314 1718 : Vector<Int> start(nsubcube,0);
1315 1718 : Vector<Int> end(nsubcube,chunksize-1);
1316 1718 : if(rem >0){
1317 0 : end(0)+=1;
1318 0 : --rem;
1319 : }
1320 1718 : for (Int k=1; k < nsubcube; ++k){
1321 0 : start(k)=end(k-1)+1;
1322 : // end(k)=((k !=nsubcube-1) || rem==0)? (start(k)+chunksize-1) : (start(k)+rem-1);
1323 0 : end(k)=(start(k)+chunksize-1);
1324 0 : if(rem > 0){
1325 0 : end(k)+=1;
1326 0 : --rem;
1327 : }
1328 : }
1329 :
1330 : // print mem related info to log
1331 1718 : const float toGB = 1024.0 * 1024.0 * 1024.0;
1332 1718 : std::ostringstream usr_mem_msg;
1333 1718 : if (usr_mem > 0.) {
1334 0 : usr_mem_msg << usr_mem / 1024.;
1335 : } else {
1336 1718 : usr_mem_msg << "-";
1337 : }
1338 1718 : std::ostringstream oss;
1339 1718 : oss << setprecision(4);
1340 1718 : oss << "Required memory: " << required_mem / toGB
1341 1718 : << " GB. Available mem.: " << memory_avail / toGB
1342 1718 : << " GB (rc, mem. fraction: " << usr_memfrac
1343 1718 : << "%, memory: " << usr_mem_msg.str()
1344 1718 : << ") => Subcubes: " << nsubcube
1345 1718 : << ". Processes on node: " << nlocal_procs << ".\n";
1346 1718 : log_l << oss.str() << LogIO::POST;
1347 :
1348 1718 : TcleanProcessingInfo procInfo;
1349 1718 : procInfo.mpiprocs = nlocal_procs;
1350 1718 : procInfo.chnchnks = nsubcube;
1351 1718 : procInfo.memavail = memory_avail / toGB;
1352 1718 : procInfo.memreq = required_mem / toGB;
1353 3436 : return make_tuple(procInfo, start, end);
1354 1718 : }
1355 :
1356 827 : void SynthesisImagerVi2::runMajorCycleCube( const Bool dopsf,
1357 : const Record inpcontrol) {
1358 1654 : LogIO os( LogOrigin("SynthesisImagerVi2","runMajorCycleCube",WHERE) );
1359 827 : if(dopsf){
1360 285 : runCubeGridding(True);
1361 : ///Store the beamsets in ImageInfo
1362 571 : for(Int k=0; k < itsMappers.nMappers(); ++k){
1363 :
1364 288 : (itsMappers.imageStore(k))->getBeamSet();
1365 : }
1366 : }
1367 : else
1368 543 : runCubeGridding(False, inpcontrol);
1369 :
1370 :
1371 :
1372 827 : }
1373 2117 : void SynthesisImagerVi2::runMajorCycle(const Bool dopsf,
1374 : const Bool savemodel)
1375 : {
1376 4234 : LogIO os( LogOrigin("SynthesisImagerVi2","runMajorCycle",WHERE) );
1377 :
1378 : // cout << "Savemodel : " << savemodel << " readonly : " << readOnly_p << " usescratch : " << useScratch_p << endl;
1379 2117 : Bool savemodelcolumn = savemodel && !readOnly_p && useScratch_p;
1380 2117 : Bool savevirtualmodel = savemodel && !readOnly_p && !useScratch_p;
1381 :
1382 2117 : if( savemodelcolumn ) os << "Saving model column" << LogIO::POST;
1383 2117 : if( savevirtualmodel ) os << "Saving virtual model" << LogIO::POST;
1384 :
1385 2117 : SynthesisUtilMethods::getResource("Start Major Cycle");
1386 :
1387 2117 : itsMappers.checkOverlappingModels("blank");
1388 :
1389 : {
1390 2117 : vi::VisBuffer2* vb=vi_p->getVisBuffer();
1391 2117 : vi_p->originChunks();
1392 2117 : vi_p->origin();
1393 2117 : Double numcoh=0;
1394 4306 : for (uInt k=0; k< mss_p.nelements(); ++k)
1395 2189 : numcoh+=Double(mss_p[k]->nrow());
1396 : ProgressMeter pm(1.0, numcoh,
1397 4234 : dopsf?"Gridding Weights and PSF":"Major Cycle", "","","",true);
1398 2117 : rownr_t cohDone=0;
1399 :
1400 :
1401 2117 : if(!dopsf)itsMappers.initializeDegrid(*vb);
1402 2117 : itsMappers.initializeGrid(*vi_p,dopsf);
1403 2116 : SynthesisUtilMethods::getResource("After initGrid for all mappers");
1404 : ////Under some peculiar selection criterion and low channel ms vb2 seems to return more channels than in spw
1405 : {
1406 2116 : vi_p->originChunks();
1407 2116 : vi_p->origin();
1408 2116 : Int nchannow=vb->nChannels();
1409 2116 : Int spwnow=vb->spectralWindows()[0];
1410 2116 : Int nchaninms=MSColumns(vb->ms()).spectralWindow().numChan()(spwnow);
1411 : //cerr << "chans " << nchaninms << " " << nchannow << endl;
1412 :
1413 2116 : if (nchaninms < nchannow){
1414 0 : cerr << "NCHANS ms" << nchaninms << " now " << nchannow << " spw " << spwnow << " " << vb->spectralWindows() << endl;
1415 0 : throw(AipsError("A nasty Visbuffer2 error occured...wait for CNGI"));
1416 : }
1417 : }
1418 : //////
1419 6164 : for (vi_p->originChunks(); vi_p->moreChunks();vi_p->nextChunk())
1420 : {
1421 :
1422 491821 : for (vi_p->origin(); vi_p->more(); vi_p->next())
1423 : {
1424 : //if (SynthesisUtilMethods::validate(*vb)==SynthesisUtilMethods::NOVALIDROWS) break; // No valid rows in this VB
1425 : // cerr << "nRows "<< vb->nRow() << " " << max(vb->visCube()) << endl;
1426 487773 : if (SynthesisUtilMethods::validate(*vb)!=SynthesisUtilMethods::NOVALIDROWS)
1427 : {
1428 487773 : if(!dopsf) {
1429 313921 : { Cube<Complex> mod(vb->nCorrelations(), vb->nChannels(), vb->nRows(), Complex(0.0));
1430 313921 : vb->setVisCubeModel(mod);
1431 313921 : }
1432 313921 : itsMappers.degrid(*vb, savevirtualmodel );
1433 313921 : if(savemodelcolumn && writeAccess_p ){
1434 9648 : const_cast<MeasurementSet& >((vi_p->ms())).lock(true);
1435 9648 : vi_p->writeVisModel(vb->visCubeModel());
1436 9648 : const_cast<MeasurementSet& >((vi_p->ms())).unlock();
1437 :
1438 : //static_cast<VisibilityIteratorImpl2 *> (vi_p->getImpl())->writeVisModel(vb->visCubeModel());
1439 :
1440 : // Cube<Complex> tt=vb->visCubeModel();
1441 : // tt = 20.0;
1442 : // cout << "Vis:" << tt << endl;
1443 : // static_cast<VisibilityIteratorImpl2 *> (vi_p->getImpl())->writeVisModel(tt);
1444 : }
1445 : }
1446 487773 : itsMappers.grid(*vb, dopsf, (refim::FTMachine::Type)datacol_p);
1447 :
1448 487772 : cohDone += vb->nRows();
1449 487772 : pm.update(Double(cohDone));
1450 : }
1451 : }
1452 : }
1453 :
1454 : // cerr << "VI2 data: " << cohDone << endl;
1455 : // exit(0);
1456 : //cerr << "IN SYNTHE_IMA" << endl;
1457 : //VisModelData::listModel(rvi_p->getMeasurementSet());
1458 2115 : SynthesisUtilMethods::getResource("Before finalize for all mappers");
1459 2115 : if(!dopsf) itsMappers.finalizeDegrid(*vb);
1460 2115 : itsMappers.finalizeGrid(*vb, dopsf);
1461 :
1462 2117 : }
1463 :
1464 2115 : itsMappers.checkOverlappingModels("restore");
1465 :
1466 2115 : unlockMSs();
1467 :
1468 2115 : SynthesisUtilMethods::getResource("End Major Cycle");
1469 :
1470 2117 : }// end runMajorCycle
1471 :
1472 :
1473 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1474 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1475 :
1476 : /// The mapper loop is outside the data iterator loop.
1477 : /// This is for cases where the image size is large compared to the RAM and
1478 : /// where data I/O is the relatively minor cost.
1479 0 : void SynthesisImagerVi2::runMajorCycle2(const Bool dopsf,
1480 : const Bool savemodel)
1481 : {
1482 0 : LogIO os( LogOrigin("SynthesisImagerVi2","runMajorCycle2",WHERE) );
1483 :
1484 : // cout << "Savemodel : " << savemodel << " readonly : " << readOnly_p << " usescratch : " << useScratch_p << endl;
1485 :
1486 0 : Bool savemodelcolumn = savemodel && !readOnly_p && useScratch_p;
1487 0 : Bool savevirtualmodel = savemodel && !readOnly_p && !useScratch_p;
1488 :
1489 0 : if( savemodelcolumn ) os << "Saving model column" << LogIO::POST;
1490 0 : if( savevirtualmodel ) os << "Saving virtual model" << LogIO::POST;
1491 :
1492 0 : itsMappers.checkOverlappingModels("blank");
1493 :
1494 0 : Bool resetModel=False;
1495 0 : if( savemodelcolumn && writeAccess_p)
1496 : {
1497 0 : resetModel=True;
1498 0 : os << "Iterating through the model column to reset it to zero" << LogIO::POST;
1499 0 : vi::VisBuffer2* vb=vi_p->getVisBuffer();
1500 0 : vi_p->originChunks();
1501 0 : vi_p->origin();
1502 0 : Double numcoh=0;
1503 0 : for (uInt k=0; k< mss_p.nelements(); ++k)
1504 0 : numcoh+=Double(mss_p[k]->nrow());
1505 : ProgressMeter pm(1.0, numcoh,
1506 0 : dopsf?"Seting model column to zero":"pre-Major Cycle", "","","",True);
1507 0 : rownr_t cohDone=0;
1508 0 : for (vi_p->originChunks(); vi_p->moreChunks();vi_p->nextChunk())
1509 : {
1510 :
1511 0 : for (vi_p->origin(); vi_p->more(); vi_p->next())
1512 : {
1513 0 : if (SynthesisUtilMethods::validate(*vb)!=SynthesisUtilMethods::NOVALIDROWS)
1514 : {
1515 0 : { Cube<Complex> mod(vb->nCorrelations(), vb->nChannels(), vb->nRows(), Complex(0.0));
1516 0 : vb->setVisCubeModel(mod);
1517 0 : }
1518 0 : vi_p->writeVisModel(vb->visCubeModel());
1519 :
1520 : }
1521 0 : cohDone += vb->nRows();;
1522 0 : pm.update(Double(cohDone));
1523 : }
1524 : }
1525 0 : }// setting model to zero
1526 :
1527 : //Need to inialize the the forward ft machine to save the virtual model on first pass of each ms.
1528 0 : if(!dopsf && savevirtualmodel){
1529 0 : vi::VisBuffer2* vb=vi_p->getVisBuffer();
1530 0 : vi_p->originChunks();
1531 0 : vi_p->origin();
1532 0 : itsMappers.initializeDegrid(*vb, -1);
1533 : }
1534 :
1535 0 : for(Int gmap=0;gmap<itsMappers.nMappers();gmap++)
1536 : {
1537 0 : os << "Running major cycle for chunk : " << gmap << LogIO::POST;
1538 :
1539 0 : SynthesisUtilMethods::getResource("Start Major Cycle for mapper"+String::toString(gmap));
1540 0 : CountedPtr<vi::FrequencySelections> copyFsels=fselections_p->clone();
1541 : ///CAS-12132 create a new visiter for each chunk
1542 0 : createVisSet(writeAccess_p);
1543 : ////////////////////////
1544 0 : vi::VisBuffer2* vb=vi_p->getVisBuffer();
1545 : /// Careful where tunechunk
1546 0 : tuneChunk(gmap);
1547 :
1548 0 : vi_p->originChunks();
1549 0 : vi_p->origin();
1550 :
1551 0 : Double numcoh=0;
1552 0 : for (uInt k=0; k< mss_p.nelements(); ++k)
1553 0 : numcoh+=Double(mss_p[k]->nrow());
1554 :
1555 :
1556 : ProgressMeter pm(1.0, numcoh,
1557 0 : dopsf?"Gridding Weights and PSF":"Major Cycle", "","","",true);
1558 0 : rownr_t cohDone=0;
1559 :
1560 :
1561 0 : itsMappers.getFTM2(gmap, False)->reset();
1562 0 : itsMappers.getFTM2(gmap, True)->reset();
1563 :
1564 0 : if(!dopsf){
1565 0 : itsMappers.initializeDegrid(*vb, gmap);
1566 : //itsMappers.getMapper(gmap)->initializeDegrid(*vb);
1567 : }
1568 0 : itsMappers.initializeGrid(*vi_p,dopsf, gmap);
1569 : //itsMappers.getMapper(gmap)->initializeGrid(*vb,dopsf);
1570 :
1571 0 : SynthesisUtilMethods::getResource("After initialize for mapper"+String::toString(gmap));
1572 0 : Int iterNum=0;
1573 :
1574 :
1575 0 : for (vi_p->originChunks(); vi_p->moreChunks();vi_p->nextChunk())
1576 : {
1577 :
1578 0 : for (vi_p->origin(); vi_p->more(); vi_p->next())
1579 : {
1580 : //if (SynthesisUtilMethods::validate(*vb)==SynthesisUtilMethods::NOVALIDROWS) break; // No valid rows in this VB
1581 : // cerr << "nRows "<< vb->nRow() << " " << max(vb->visCube()) << endl;
1582 0 : if (SynthesisUtilMethods::validate(*vb)!=SynthesisUtilMethods::NOVALIDROWS)
1583 : {
1584 :
1585 0 : if(!dopsf) {
1586 0 : if(resetModel==False)
1587 : {
1588 0 : Cube<Complex> mod(vb->nCorrelations(), vb->nChannels(), vb->nRows(), Complex(0.0));
1589 0 : vb->setVisCubeModel(mod);
1590 0 : }
1591 0 : itsMappers.degrid(*vb, savevirtualmodel, gmap );
1592 : //itsMappers.getMapper(gmap)->degrid(*vb); //, savevirtualmodel );
1593 0 : if(savemodelcolumn && writeAccess_p ){
1594 0 : vi_p->writeVisModel(vb->visCubeModel());
1595 : //vi_p->writeBackChanges(vb);
1596 : // static_cast<VisibilityIteratorImpl2 *> (vi_p->getImpl())->writeVisModel(vb->visCubeModel());
1597 : }
1598 :
1599 : }
1600 0 : itsMappers.grid(*vb, dopsf, (refim::FTMachine::Type)(datacol_p), gmap);
1601 : //itsMappers.getMapper(gmap)->grid(*vb, dopsf, datacol_p);
1602 0 : cohDone += vb->nRows();
1603 0 : ++iterNum;
1604 0 : pm.update(Double(cohDone));
1605 : }
1606 : }
1607 : }
1608 : //cerr << "IN SYNTHE_IMA" << endl;
1609 : //VisModelData::listModel(rvi_p->getMeasurementSet());
1610 :
1611 0 : SynthesisUtilMethods::getResource("Before finalize for mapper"+String::toString(gmap));
1612 :
1613 0 : if(!dopsf)
1614 : {
1615 0 : itsMappers.finalizeDegrid(*vb,gmap);
1616 : //itsMappers.getMapper(gmap)->finalizeDegrid();
1617 : }
1618 0 : itsMappers.finalizeGrid(*vb, dopsf,gmap);
1619 : //itsMappers.getMapper(gmap)->finalizeGrid(*vb, dopsf);
1620 :
1621 : // itsMappers.getMapper(gmap)->releaseImageLocks();
1622 0 : itsMappers.getMapper(gmap)->imageStore()->releaseComplexGrids();
1623 :
1624 0 : SynthesisUtilMethods::getResource("End Major Cycle for mapper"+String::toString(gmap));
1625 0 : fselections_p=copyFsels;
1626 0 : }// end of mapper loop
1627 : ///CAS-12132 create a new visiter for each chunk
1628 0 : createVisSet(writeAccess_p);
1629 : ////////////////////////
1630 : //////vi_p->setFrequencySelection(*fselections_p);
1631 :
1632 0 : itsMappers.checkOverlappingModels("restore");
1633 :
1634 0 : unlockMSs();
1635 :
1636 0 : SynthesisUtilMethods::getResource("End Major Cycle");
1637 :
1638 0 : }// end runMajorCycle2
1639 :
1640 : //////////////////////////////
1641 :
1642 : ////////////////////////////////////////////////////////////////////////////////////////////////
1643 :
1644 827 : bool SynthesisImagerVi2::runCubeGridding(Bool dopsf, const Record inpcontrol){
1645 :
1646 1654 : LogIO logger(LogOrigin("SynthesisImagerVi2", "runCubeGridding", WHERE));
1647 :
1648 : //dummy for now as init is overloaded on this signature
1649 827 : int argc=1;
1650 827 : char **argv=nullptr;
1651 827 : casa::applicator.init ( argc, argv );
1652 : //For serial or master only
1653 827 : if ( applicator.isController() ) {
1654 827 : CubeMajorCycleAlgorithm cmc;
1655 : //casa::applicator.defineAlgorithm(cmc);
1656 : //Initialize everything to get the setup as serial
1657 : {
1658 :
1659 827 : vi_p->originChunks();
1660 827 : vi_p->origin();
1661 :
1662 : }
1663 : ///Break things into chunks for parallelization or memory availabbility
1664 827 : Vector<Int> startchan;
1665 827 : Vector<Int> endchan;
1666 : Int numchunks;
1667 827 : Int fudge_factor = 15;
1668 827 : if ((itsMappers.getFTM2(0))->name()=="MosaicFTNew") {
1669 130 : fudge_factor = 20;
1670 : }
1671 697 : else if ((itsMappers.getFTM2(0))->name()=="GridFT") {
1672 619 : fudge_factor = 9;
1673 : }
1674 827 : TcleanProcessingInfo procInfo;
1675 827 : std::tie(procInfo, startchan, endchan)=nSubCubeFitInMemory(fudge_factor, itsMaxShape, gridpars_p.padding);
1676 827 : numchunks = procInfo.chnchnks;
1677 : ////TESTOO
1678 : //numchunks=2;
1679 : //startchan.resize(2);startchan[0]=0; startchan[1]=2;
1680 : //endchan.resize(2); endchan[0]=1; endchan[1]=2;
1681 :
1682 : /////END TESTOO
1683 : //cerr << "NUMCHUNKS " << numchunks << " start " << startchan << " end " << endchan << endl;
1684 827 : Record controlRecord=inpcontrol;
1685 : //For now just field 0 but should loop over all
1686 : ///This is to pass in explicit model, residual names etc
1687 827 : controlRecord.define("nfields", Int(imparsVec_p.nelements()));
1688 : //CountedPtr<SIImageStore> imstor = imageStore ( 0 );
1689 : // checking that psf, residual and sumwt is allDone
1690 : //cerr << "shapes " << imstor->residual()->shape() << " " << imstor->sumwt()->shape() << endl;
1691 827 : if(!dopsf){
1692 :
1693 : //controlRecord.define("lastcycle", savemodel);
1694 543 : controlRecord.define("nmajorcycles", nMajorCycles);
1695 543 : Vector<String> modelnames(Int(imparsVec_p.nelements()),"");
1696 1096 : for(uInt k=0; k < imparsVec_p.nelements(); ++k){
1697 553 : Int imageStoreId=k;
1698 553 : if(k>0){
1699 10 : if(gridparsVec_p[0].chanchunks >1 && uInt(itsMappers.nMappers()) >= (gridparsVec_p[0].chanchunks + gridparsVec_p.nelements()))
1700 0 : imageStoreId+=gridparsVec_p[0].chanchunks-1;
1701 10 : if(gridparsVec_p[0].facets >1)
1702 0 : imageStoreId+=gridparsVec_p[0].facets*gridparsVec_p[0].facets-1;
1703 : }
1704 553 : if((itsMappers.imageStore(imageStoreId))->hasModel()){
1705 289 : modelnames(k)=imparsVec_p[k].imageName+".model";
1706 289 : (itsMappers.imageStore(k))->model()->unlock();
1707 289 : controlRecord.define("modelnames", modelnames);
1708 : }
1709 : }
1710 :
1711 543 : }
1712 827 : Vector<String> weightnames(Int(imparsVec_p.nelements()),"");
1713 827 : Vector<String> pbnames(Int(imparsVec_p.nelements()),"");
1714 1669 : for(uInt k=0; k < imparsVec_p.nelements(); ++k){
1715 842 : Int imageStoreId=k;
1716 842 : if(k>0){
1717 15 : if(gridparsVec_p[0].chanchunks >1 && uInt(itsMappers.nMappers()) >= (gridparsVec_p[0].chanchunks + gridparsVec_p.nelements()))
1718 0 : imageStoreId+=gridparsVec_p[0].chanchunks-1;
1719 15 : if(gridparsVec_p[0].facets >1)
1720 0 : imageStoreId+=gridparsVec_p[0].facets*gridparsVec_p[0].facets-1;
1721 : }
1722 : //cerr << "FTMachine name " << (itsMappers.getFTM2(imageStoreId))->name() << endl;
1723 842 : if((itsMappers.getFTM2(imageStoreId))->useWeightImage()){
1724 : //cerr << "Mosaic weight image " << max(itsMappers.imageStore(imageStoreId)->weight(k)->get()) << endl;
1725 179 : weightnames(k)=itsMappers.imageStore(imageStoreId)->weight(k)->name();
1726 :
1727 :
1728 : }
1729 842 : if(itsMakeVP){
1730 663 : pbnames(k)=itsMappers.imageStore(imageStoreId)->pb(k)->name();
1731 663 : (itsMappers.imageStore(imageStoreId)->pb(k))->unlock();
1732 : }
1733 : }
1734 827 : controlRecord.define("weightnames", weightnames);
1735 827 : controlRecord.define("pbnames", pbnames);
1736 : // Tell the child processes not to do the dividebyweight process as this is done
1737 : // tell each child to do the normars stuff
1738 827 : controlRecord.define("dividebyweight", True);
1739 827 : controlRecord.defineRecord("normpars", normpars_p);
1740 : ///Let's see if no per chan weight density was chosen
1741 827 : String weightdensityimage=getWeightDensity();
1742 827 : if(weightdensityimage != "")
1743 2 : controlRecord.define("weightdensity", weightdensityimage);
1744 :
1745 827 : Record vecSelParsRec, vecImParsRec, vecGridParsRec;
1746 827 : Vector<Int>vecRange(2);
1747 1683 : for (uInt k = 0; k < dataSel_p.nelements(); ++k) {
1748 856 : Record selparsRec = dataSel_p[k].toRecord();
1749 856 : vecSelParsRec.defineRecord(String::toString(k), selparsRec);
1750 856 : }
1751 1669 : for (uInt k=0; k < imparsVec_p.nelements(); ++k){
1752 842 : Record imparsRec = imparsVec_p[k].toRecord();
1753 : //need to send polrep
1754 842 : imparsRec.define("polrep", Int((itsMappers.imageStore(k))->getDataPolFrame()));
1755 : //need to send movingSourceName if any
1756 842 : imparsRec.define("movingsource", movingSource_p);
1757 842 : Record gridparsRec = gridparsVec_p[k].toRecord();
1758 : /* Might need this to pass the state of the global ftmachines...test for parallel when needed
1759 : String err;
1760 : Record ftmrec, iftmrec;
1761 : if(!( (itsMappers.getFTM2(k)->toRecord(err, iftmrec,False)) && (itsMappers.getFTM2(k, false)->toRecord(err, ftmrec,False))))
1762 : throw(AipsError("FTMachines serialization failed"));
1763 : gridparsRec.defineRecord("ftmachine", ftmrec);
1764 : gridparsRec.defineRecord("iftmachine", iftmrec);
1765 : */
1766 842 : vecImParsRec.defineRecord(String::toString(k), imparsRec);
1767 842 : vecGridParsRec.defineRecord(String::toString(k), gridparsRec);
1768 842 : }
1769 827 : String workingdir="";
1770 : //Int numchan=(dopsf) ? imstor->psf()->shape()[3] : imstor->residual()->shape() [3];
1771 : //copy the imageinfo of main image here
1772 827 : if(dopsf)
1773 284 : cubePsfImageInfo_p=(itsMappers.imageStore(0)->psf())->imageInfo();
1774 1669 : for(Int k=0; k < itsMappers.nMappers(); ++k){
1775 :
1776 842 : if(dopsf){
1777 :
1778 580 : for(uInt j =0; j <(itsMappers.imageStore(k)->getNTaylorTerms(true)); ++j){
1779 : ///TESTOO
1780 : //(itsMappers.imageStore(k))->psf(j)->set(0.0);
1781 : /////////
1782 291 : (itsMappers.imageStore(k))->psf(j)->unlock();
1783 291 : (itsMappers.imageStore(k))->pb()->unlock();
1784 : }
1785 : }
1786 : else{
1787 1108 : for(uInt j =0; j <(itsMappers.imageStore(k)->getNTaylorTerms(false)); ++j){
1788 : /////////TESTOO
1789 : //(itsMappers.imageStore(k))->residual(j)->set(0.0);
1790 : ///////
1791 555 : (itsMappers.imageStore(k))->residual(j)->unlock();
1792 : }
1793 : }
1794 1690 : for(uInt j =0; j <(itsMappers.imageStore(k)->getNTaylorTerms(true)); ++j){
1795 : //cerr << k << " type " << (itsMappers.imageStore(k))->sumwt(j)->imageType() << " name " << (itsMappers.imageStore(k))->sumwt(j)->name() << endl;
1796 :
1797 :
1798 1696 : Path namewgt( (itsMappers.imageStore(k))->sumwt(j)->name());
1799 848 : workingdir=namewgt.dirName();
1800 : ///TESTOO
1801 : //(itsMappers.imageStore(k))->sumwt(j)->set(0.0);
1802 : ////
1803 848 : (itsMappers.imageStore(k))->sumwt(j)->unlock();
1804 : //(itsMappers.imageStore(k))->releaseLocks();
1805 848 : }
1806 842 : (itsMappers.imageStore(k))->releaseLocks();
1807 : }
1808 : //Send the working directory as the child and master may be at different places
1809 :
1810 827 : controlRecord.define("workingdirectory", workingdir);
1811 : // For now this contains lastcycle if necessary in the future this
1812 : // should come from the master control record
1813 :
1814 : //Int numprocs = applicator.numProcs();
1815 : //cerr << "Number of procs: " << numprocs << endl;
1816 827 : Int rank ( 0 );
1817 : Bool assigned; //(casa::casa::applicator.nextAvailProcess(pwrite, rank));
1818 827 : Bool allDone ( false );
1819 827 : Vector<Bool> retvals(numchunks, False);
1820 827 : Int indexofretval=0;
1821 1654 : for ( Int k=0; k < numchunks; ++k ) {
1822 827 : assigned=casa::applicator.nextAvailProcess ( cmc, rank );
1823 : //cerr << "assigned "<< assigned << endl;
1824 827 : while ( !assigned ) {
1825 0 : rank = casa::applicator.nextProcessDone ( cmc, allDone );
1826 : //cerr << "while rank " << rank << endl;
1827 : Bool status;
1828 0 : Record returnRec;
1829 0 : casa::applicator.get(returnRec);
1830 0 : casa::applicator.get ( status );
1831 0 : retvals(indexofretval)=status;
1832 0 : if(dopsf)
1833 0 : updateImageBeamSet(returnRec);
1834 0 : if(returnRec.isDefined("tempfilenames")){
1835 0 : std::vector<String> b=returnRec.asArrayString("tempfilenames").tovector();
1836 0 : tempFileNames_p.insert(std::end(tempFileNames_p), std::begin(b), std::end(b));
1837 0 : }
1838 :
1839 0 : ++indexofretval;
1840 0 : if ( status )
1841 : //cerr << k << " rank " << rank << " successful " << endl;
1842 0 : cerr << "" ;
1843 : else
1844 0 : logger << LogIO::SEVERE << k << " rank " << rank << " failed " << LogIO::POST;
1845 0 : assigned = casa::applicator.nextAvailProcess ( cmc, rank );
1846 :
1847 0 : }
1848 :
1849 : ///send process info
1850 : // put data sel params #1
1851 827 : applicator.put ( vecSelParsRec );
1852 : // put image sel params #2
1853 827 : applicator.put ( vecImParsRec );
1854 : // put gridders params #3
1855 827 : applicator.put ( vecGridParsRec );
1856 : // put which channel to process #4
1857 827 : vecRange(0)=startchan(k);
1858 827 : vecRange(1)=endchan(k);
1859 827 : applicator.put ( vecRange );
1860 : // psf or residual CubeMajorCycleAlgorithm #5
1861 827 : applicator.put ( dopsf );
1862 : // store modelvis and other controls #6
1863 827 : applicator.put ( controlRecord );
1864 : // weighting scheme #7
1865 827 : applicator.put( weightParams_p);
1866 : /// Tell worker to process it
1867 827 : applicator.apply ( cmc );
1868 :
1869 : }
1870 : // Wait for all outstanding processes to return
1871 827 : rank = casa::applicator.nextProcessDone ( cmc, allDone );
1872 1654 : while ( !allDone ) {
1873 : Bool status;
1874 827 : Record returnRec;
1875 827 : casa::applicator.get(returnRec);
1876 827 : casa::applicator.get ( status );
1877 827 : if(dopsf)
1878 284 : updateImageBeamSet(returnRec);
1879 827 : if(returnRec.isDefined("tempfilenames")){
1880 807 : std::vector<String> b=returnRec.asArrayString("tempfilenames").tovector();
1881 807 : tempFileNames_p.insert(std::end(tempFileNames_p), std::begin(b), std::end(b));
1882 807 : }
1883 827 : retvals(indexofretval)=status;
1884 827 : ++indexofretval;
1885 827 : if ( status )
1886 : //cerr << "remainder rank " << rank << " successful " << endl;
1887 826 : cerr << "";
1888 : else
1889 1 : logger << LogIO::SEVERE << "remainder rank " << rank << " failed " << LogIO::POST;
1890 :
1891 827 : rank = casa::applicator.nextProcessDone ( cmc, allDone );
1892 827 : if(casa::applicator.isSerial())
1893 827 : allDone=true;
1894 827 : }
1895 827 : if(anyEQ(retvals, False)){
1896 : //cerr << retvals << endl;
1897 1 : ostringstream oss;
1898 : oss << "One or more of the cube section failed in de/gridding. Return values for "
1899 1 : "the sections: " << retvals;
1900 1 : throw(AipsError(oss));
1901 1 : }
1902 826 : if(!dopsf && normpars_p.isDefined("pblimit") && (normpars_p.asFloat("pblimit") > 0.0) ){
1903 : try{
1904 490 : SIImageStore::copyMask(itsMappers.imageStore(0)->pb(), itsMappers.imageStore(0)->residual());
1905 469 : (itsMappers.imageStore(0))->residual()->unlock();
1906 : //(itsMappers.imageStore(0)->pb())->pixelMask().unlock();
1907 469 : (itsMappers.imageStore(0))->pb()->unlock();
1908 : }
1909 3 : catch(AipsError &x) {
1910 3 : if(!String(x.getMesg()).contains("T/F"))
1911 0 : throw(AipsError(x.getMesg()));
1912 : else{
1913 3 : logger << LogIO::WARN << "Error : " << x.getMesg() << LogIO::POST;
1914 : //cout << "x.getMesg() " << endl;
1915 : }
1916 : ///ignore copy mask error and proceed as this happens with interactive
1917 3 : }
1918 : }
1919 : else{
1920 708 : LatticeLocker lock1 (*(itsMappers.imageStore(0)->psf()), FileLocker::Write);
1921 354 : itsMappers.imageStore(0)->psf()->setImageInfo(cubePsfImageInfo_p);
1922 354 : itsMappers.imageStore(0)->psf()->unlock();
1923 354 : (itsMappers.imageStore(0))->pb()->unlock();
1924 354 : }
1925 :
1926 839 : }
1927 :
1928 :
1929 826 : return true;
1930 :
1931 827 : }
1932 : /////////////////////////
1933 20 : void SynthesisImagerVi2::predictModel(){
1934 40 : LogIO os( LogOrigin("SynthesisImagerVi2","predictModel ",WHERE) );
1935 :
1936 20 : os << "---------------------------------------------------- Predict Model ---------------------------------------------" << LogIO::POST;
1937 :
1938 20 : Bool savemodelcolumn = !readOnly_p && useScratch_p;
1939 20 : Bool savevirtualmodel = !readOnly_p && !useScratch_p;
1940 : //os<<"PREDICTMODEL: readOnly_p=="<<readOnly_p<<" useScratch_p=="<<useScratch_p<<LogIO::POST;
1941 20 : if( savemodelcolumn ) os << "Saving model column" << LogIO::POST;
1942 20 : if( savevirtualmodel ) os << "Saving virtual model" << LogIO::POST;
1943 :
1944 20 : itsMappers.checkOverlappingModels("blank");
1945 :
1946 :
1947 : {
1948 20 : vi::VisBuffer2* vb = vi_p->getVisBuffer();;
1949 20 : vi_p->originChunks();
1950 20 : vi_p->origin();
1951 20 : Double numberCoh=0;
1952 42 : for (uInt k=0; k< mss_p.nelements(); ++k)
1953 22 : numberCoh+=Double(mss_p[k]->nrow());
1954 :
1955 40 : ProgressMeter pm(1.0, numberCoh, "Predict Model", "","","",true);
1956 20 : rownr_t cohDone=0;
1957 :
1958 20 : itsMappers.initializeDegrid(*vb);
1959 42 : for (vi_p->originChunks(); vi_p->moreChunks();vi_p->nextChunk())
1960 : {
1961 :
1962 8750 : for (vi_p->origin(); vi_p->more(); vi_p->next())
1963 : {
1964 : //if (SynthesisUtilMethods::validate(*vb)==SynthesisUtilMethods::NOVALIDROWS) break; //No valid rows in this MS
1965 : //if !usescratch ...just save
1966 8728 : vb->setVisCubeModel(Complex(0.0, 0.0));
1967 8728 : itsMappers.degrid(*vb, savevirtualmodel);
1968 :
1969 8728 : if(savemodelcolumn && writeAccess_p ){
1970 :
1971 4888 : const_cast<MeasurementSet& >((vi_p->ms())).lock(true);
1972 :
1973 4888 : vi_p->writeVisModel(vb->visCubeModel());
1974 :
1975 : //cerr << "nRows "<< vb->nRows() << " " << max(vb->visCubeModel()) << endl;
1976 4888 : const_cast<MeasurementSet& >((vi_p->ms())).unlock();
1977 : }
1978 :
1979 8728 : cohDone += vb->nRows();
1980 8728 : pm.update(Double(cohDone));
1981 :
1982 : }
1983 : }
1984 20 : itsMappers.finalizeDegrid(*vb);
1985 20 : }
1986 :
1987 20 : itsMappers.checkOverlappingModels("restore");
1988 20 : itsMappers.releaseImageLocks();
1989 20 : unlockMSs();
1990 :
1991 20 : }// end of predictModel
1992 :
1993 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1994 144 : void SynthesisImagerVi2::makeSdImage(Bool dopsf)
1995 : {
1996 288 : LogIO os( LogOrigin("SynthesisImagerVi2","makeSdImage",WHERE) );
1997 :
1998 : // Bool dopsf=false;
1999 144 : if(datacol_p==FTMachine::PSF) dopsf=true;
2000 :
2001 : {
2002 144 : vi::VisBuffer2* vb = vi_p->getVisBuffer();;
2003 144 : vi_p->originChunks();
2004 144 : vi_p->origin();
2005 :
2006 144 : Double numberCoh=0;
2007 314 : for (uInt k=0; k< mss_p.nelements(); ++k)
2008 170 : numberCoh+=Double(mss_p[k]->nrow());
2009 :
2010 288 : ProgressMeter pm(1.0, numberCoh, "Predict Model", "","","",true);
2011 144 : rownr_t cohDone=0;
2012 :
2013 144 : itsMappers.initializeGrid(*vi_p,dopsf);
2014 766 : for (vi_p->originChunks(); vi_p->moreChunks(); vi_p->nextChunk())
2015 : {
2016 622 : if (vi_p->getImpl()->isNewMs()) {
2017 170 : itsMappers.handleNewMs(vi_p->ms());
2018 : }
2019 204441 : for (vi_p->origin(); vi_p->more(); vi_p->next())
2020 : {
2021 203819 : itsMappers.grid(*vb, dopsf, (refim::FTMachine::Type)datacol_p);
2022 203819 : cohDone += vb->nRows();
2023 203819 : pm.update(Double(cohDone));
2024 : }
2025 : }
2026 144 : itsMappers.finalizeGrid(*vb, dopsf);
2027 :
2028 144 : }
2029 :
2030 144 : unlockMSs();
2031 :
2032 144 : }// end makeSDImage
2033 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2034 2 : void SynthesisImagerVi2::makeImage(String type, const String& imagename, const String& complexImage, const Int whichModel)
2035 : {
2036 4 : LogIO os( LogOrigin("SynthesisImager","makeImage",WHERE) );
2037 :
2038 :
2039 2 : refim::FTMachine::Type seType(refim::FTMachine::OBSERVED);
2040 2 : if(type=="observed") {
2041 0 : seType=refim::FTMachine::OBSERVED;
2042 : os << LogIO::NORMAL // Loglevel INFO
2043 : << "Making dirty image from " << type << " data "
2044 0 : << LogIO::POST;
2045 : }
2046 2 : else if (type=="model") {
2047 0 : seType=refim::FTMachine::MODEL;
2048 : os << LogIO::NORMAL // Loglevel INFO
2049 : << "Making dirty image from " << type << " data "
2050 0 : << LogIO::POST;
2051 : }
2052 2 : else if (type=="corrected") {
2053 0 : seType=refim::FTMachine::CORRECTED;
2054 : os << LogIO::NORMAL // Loglevel INFO
2055 : << "Making dirty image from " << type << " data "
2056 0 : << LogIO::POST;
2057 : }
2058 2 : else if (type=="psf") {
2059 2 : seType=refim::FTMachine::PSF;
2060 : os << "Making point spread function "
2061 2 : << LogIO::POST;
2062 : }
2063 0 : else if (type=="residual") {
2064 0 : seType=refim::FTMachine::RESIDUAL;
2065 : os << LogIO::NORMAL // Loglevel INFO
2066 : << "Making dirty image from " << type << " data "
2067 0 : << LogIO::POST;
2068 : }
2069 0 : else if (type=="singledish-observed") {
2070 0 : seType=refim::FTMachine::OBSERVED;
2071 : os << LogIO::NORMAL
2072 0 : << "Making single dish image from observed data" << LogIO::POST;
2073 : }
2074 0 : else if (type=="singledish") {
2075 0 : seType=refim::FTMachine::CORRECTED;
2076 : os << LogIO::NORMAL
2077 0 : << "Making single dish image from corrected data" << LogIO::POST;
2078 : }
2079 0 : else if (type=="coverage") {
2080 0 : seType=refim::FTMachine::COVERAGE;
2081 : os << LogIO::NORMAL
2082 : << "Making single dish coverage function "
2083 0 : << LogIO::POST;
2084 : }
2085 0 : else if (type=="holography") {
2086 0 : seType=refim::FTMachine::CORRECTED;
2087 : os << LogIO::NORMAL
2088 : << "Making complex holographic image from corrected data "
2089 0 : << LogIO::POST;
2090 : }
2091 0 : else if (type=="holography-observed") {
2092 0 : seType=refim::FTMachine::OBSERVED;
2093 : os << LogIO::NORMAL
2094 : << "Making complex holographic image from observed data "
2095 0 : << LogIO::POST;
2096 : }
2097 :
2098 2 : String imageName=(itsMappers.imageStore(whichModel))->getName();
2099 2 : String cImageName(complexImage);
2100 2 : if(complexImage=="") {
2101 2 : cImageName=imageName+".compleximage";
2102 : }
2103 2 : Bool keepComplexImage=(complexImage!="")||(type.contains("holography"));
2104 : //cerr << "name " << (itsMappers.getFTM2(whichModel))->name() << endl;
2105 2 : if(((itsMappers.getFTM2(whichModel))->name())!="MultiTermFTNew"){
2106 : ////Non multiterm case
2107 : //cerr << "whichModel " << whichModel << " itsMappers num " << itsMappers.nMappers() << " shape " << (itsMappers.imageStore(whichModel))->getShape() << endl;
2108 : ///the SIImageStore sometimes return 0 shape...
2109 2 : CoordinateSystem csys=itsMaxCoordSys;
2110 2 : IPosition shp=itsMaxShape;
2111 2 : if((itsMappers.imageStore(whichModel))->getShape().product()!=0 ){
2112 2 : csys= (itsMappers.imageStore(whichModel))->getCSys();
2113 2 : shp=(itsMappers.imageStore(whichModel))->getShape();
2114 : }
2115 2 : itsMappers.releaseImageLocks();
2116 2 : PagedImage<Float> theImage( shp, csys, imagename);
2117 0 : PagedImage<Complex> cImageImage(theImage.shape(),
2118 : theImage.coordinates(),
2119 4 : cImageName);
2120 2 : if(!keepComplexImage)
2121 2 : cImageImage.table().markForDelete();
2122 :
2123 :
2124 2 : Matrix<Float> weight;
2125 2 : if(cImageImage.shape()[3] > 1){
2126 1 : cImageImage.set(Complex(0.0));
2127 1 : cImageImage.tempClose();
2128 1 : makeComplexCubeImage(cImageName, seType, whichModel);
2129 : }
2130 : else{
2131 1 : (itsMappers.getFTM2(whichModel))->makeImage(seType, *vi_p, cImageImage, weight);
2132 : }
2133 2 : if(seType==refim::FTMachine::PSF){
2134 2 : StokesImageUtil::ToStokesPSF(theImage, cImageImage);
2135 2 : StokesImageUtil::normalizePSF(theImage);
2136 : }
2137 : else{
2138 0 : StokesImageUtil::To(theImage, cImageImage);
2139 : }
2140 2 : }
2141 : else{
2142 : ///Multiterm
2143 : //refim::MultiTermFTNew *theft=static_cast<refim::MultiTermFTNew *>( (itsMappers.getFTM2(whichModel))->cloneFTM());
2144 0 : refim::MultiTermFTNew *theft=static_cast<refim::MultiTermFTNew *>( (itsMappers.getFTM2(whichModel)).get());
2145 0 : Int ntaylor= seType==refim::FTMachine::PSF ? theft->psfNTerms() : theft->nTerms();
2146 0 : if(ntaylor<2)
2147 0 : throw(AipsError("some issue with muti term setting "));
2148 0 : Vector<CountedPtr<ImageInterface<Float> > >theImage(ntaylor);
2149 0 : Vector<CountedPtr<ImageInterface<Complex> > >cImageImage(ntaylor);
2150 0 : Vector<CountedPtr<Matrix<Float> > >weight(ntaylor);
2151 0 : for (Int taylor=0; taylor < ntaylor; ++taylor){
2152 0 : theImage[taylor]=new PagedImage<Float>((itsMappers.imageStore(whichModel))->getShape(), (itsMappers.imageStore(whichModel))->getCSys(), imagename+".tt"+String::toString(taylor));
2153 0 : cImageImage[taylor]=new PagedImage<Complex> (theImage[taylor]->shape(),
2154 0 : theImage[taylor]->coordinates(),
2155 0 : cImageName+".tt"+String::toString(taylor));
2156 0 : if(!keepComplexImage)
2157 0 : static_cast<PagedImage<Complex> *> (cImageImage[taylor].get())->table().markForDelete();
2158 0 : weight[taylor]=new Matrix<Float>();
2159 :
2160 : }
2161 0 : theft->makeMTImages(seType, *vi_p, cImageImage, weight);
2162 0 : Float maxpsf=1.0;
2163 0 : for (Int taylor=0; taylor < ntaylor; ++taylor){
2164 0 : if(seType==refim::FTMachine::PSF){
2165 0 : StokesImageUtil::ToStokesPSF(*(theImage[taylor]), *(cImageImage[taylor]));
2166 0 : if(taylor==0){
2167 0 : maxpsf=StokesImageUtil::normalizePSF(*theImage[taylor]);
2168 : //cerr << "maxpsf " << maxpsf << endl;
2169 : }
2170 : else{
2171 : ///divide by max;
2172 0 : (*theImage[taylor]).copyData((LatticeExpr<Float>)((*theImage[taylor])/maxpsf));
2173 : }
2174 : }
2175 : else{
2176 0 : StokesImageUtil::To(*(theImage[taylor]), *(cImageImage[taylor]));
2177 : }
2178 : }
2179 : //delete theft;
2180 :
2181 0 : }
2182 2 : unlockMSs();
2183 :
2184 2 : }// end makeImage
2185 : /////////////////////////////////////////////////////
2186 :
2187 1 : void SynthesisImagerVi2::makeComplexCubeImage(const String& cimage, const refim::FTMachine::Type imtype, const Int whichmodel){
2188 1 : CubeMakeImageAlgorithm *cmi=new CubeMakeImageAlgorithm();
2189 : // Dummies for using the right signature for init
2190 1 : Path cimpath(cimage);
2191 1 : String cimname=cimpath.absoluteName();
2192 : //cerr << "ABSOLUTE path " << cimname << endl;
2193 1 : Int argc = 1;
2194 1 : char **argv = nullptr;
2195 1 : casa::applicator.init(argc, argv);
2196 1 : if(applicator.isController())
2197 : {
2198 1 : Record vecSelParsRec;
2199 2 : for (uInt k = 0; k < dataSel_p.nelements(); ++k) {
2200 1 : Record selparsRec = dataSel_p[k].toRecord();
2201 1 : vecSelParsRec.defineRecord(String::toString(k), selparsRec);
2202 1 : }
2203 1 : Record imparsRec = imparsVec_p[whichmodel].toRecord();
2204 : //cerr << "which model " << whichmodel << " record " << imparsRec << endl;
2205 1 : Record gridparsRec = gridparsVec_p[whichmodel].toRecord();
2206 : ///Break things into chunks for parallelization or memory availabbility
2207 1 : Vector<Int> startchan;
2208 1 : Vector<Int> endchan;
2209 : Int numchunks;
2210 1 : Int fudge_factor = 15;
2211 1 : if ((itsMappers.getFTM2(0))->name()=="MosaicFTNew") {
2212 1 : fudge_factor = 20;
2213 : }
2214 0 : else if ((itsMappers.getFTM2(0))->name()=="GridFT") {
2215 0 : fudge_factor = 9;
2216 : }
2217 1 : TcleanProcessingInfo procInfo;
2218 1 : std::tie(procInfo, startchan, endchan)=nSubCubeFitInMemory(fudge_factor, itsMaxShape, gridpars_p.padding);
2219 1 : numchunks = procInfo.chnchnks;
2220 :
2221 1 : Int imageType=Int(imtype);
2222 1 : Int rank(0);
2223 : Bool assigned;
2224 1 : Bool allDone(false);
2225 1 : Vector<Int> chanRange(2);
2226 2 : for (Int k=0; k < numchunks; ++k) {
2227 1 : assigned=casa::applicator.nextAvailProcess ( *cmi, rank );
2228 : //cerr << "assigned "<< assigned << endl;
2229 1 : while ( !assigned ) {
2230 0 : rank = casa::applicator.nextProcessDone ( *cmi, allDone );
2231 : //cerr << "while rank " << rank << endl;
2232 : Bool status;
2233 0 : casa::applicator.get(status);
2234 : /*if ( status )
2235 : cerr << k << " rank " << rank << " successful " << endl;
2236 : else
2237 : cerr << k << " rank " << rank << " failed " << endl;
2238 : */
2239 0 : assigned = casa::applicator.nextAvailProcess ( *cmi, rank );
2240 :
2241 : }
2242 1 : applicator.put(vecSelParsRec);
2243 : // put image sel params #2
2244 1 : applicator.put(imparsRec);
2245 : // put gridder params #3
2246 1 : applicator.put(gridparsRec);
2247 : // put which channel to process #4
2248 1 : chanRange(0)=startchan(k);
2249 1 : chanRange(1)=endchan(k);
2250 1 : applicator.put(chanRange);
2251 : //Type of image #5
2252 1 : applicator.put(imageType);
2253 : // weighting parameters #6
2254 1 : applicator.put( weightParams_p);
2255 : // complex imagename #7
2256 1 : applicator.put(cimname);
2257 1 : applicator.apply(*cmi);
2258 : }
2259 : // Wait for all outstanding processes to return
2260 1 : rank = casa::applicator.nextProcessDone(*cmi, allDone);
2261 2 : while (!allDone) {
2262 : Bool status;
2263 1 : casa::applicator.get(status);
2264 : /*
2265 : if(status)
2266 : cerr << "remainder rank " << rank << " successful " << endl;
2267 : else
2268 : cerr << "remainder rank " << rank << " failed " << endl;
2269 : */
2270 1 : rank = casa::applicator.nextProcessDone(*cmi, allDone);
2271 1 : if(casa::applicator.isSerial())
2272 1 : allDone=true;
2273 : }
2274 1 : }//applicator controller section
2275 1 : }
2276 :
2277 :
2278 :
2279 1768 : CountedPtr<SIMapper> SynthesisImagerVi2::createSIMapper(String mappertype,
2280 : CountedPtr<SIImageStore> imagestore,
2281 : CountedPtr<refim::FTMachine> ftmachine,
2282 : CountedPtr<refim::FTMachine> iftmachine,
2283 : uInt /*ntaylorterms*/)
2284 : {
2285 3536 : LogIO os( LogOrigin("SynthesisImagerVi2","createSIMapper",WHERE) );
2286 :
2287 1768 : CountedPtr<SIMapper> localMapper;
2288 :
2289 : try
2290 : {
2291 :
2292 1768 : if( mappertype == "default" || mappertype == "multiterm" )
2293 : {
2294 1768 : localMapper = new SIMapper( imagestore, ftmachine, iftmachine );
2295 : }
2296 0 : else if( mappertype == "imagemosaic") // || mappertype == "mtimagemosaic" )
2297 : {
2298 0 : localMapper = new SIMapperImageMosaic( imagestore, ftmachine, iftmachine );
2299 : }
2300 : else
2301 : {
2302 0 : throw(AipsError("Unknown mapper type : " + mappertype));
2303 : }
2304 :
2305 : }
2306 0 : catch(AipsError &x) {
2307 0 : throw(AipsError("Error in createSIMapper : " + x.getMesg() ) );
2308 0 : }
2309 3536 : return localMapper;
2310 1768 : }
2311 :
2312 3688 : void SynthesisImagerVi2::lockMS(MeasurementSet& thisms){
2313 3688 : thisms.lock(!readOnly_p);
2314 3688 : thisms.antenna().lock(false);
2315 3688 : thisms.dataDescription().lock(false);
2316 3688 : thisms.feed().lock(false);
2317 3688 : thisms.field().lock(false);
2318 3688 : thisms.observation().lock(false);
2319 3688 : thisms.polarization().lock(false);
2320 3688 : thisms.processor().lock(false);
2321 3688 : thisms.spectralWindow().lock(false);
2322 3688 : thisms.state().lock(false);
2323 3688 : if(!thisms.doppler().isNull())
2324 150 : thisms.doppler().lock(false);
2325 3688 : if(!thisms.flagCmd().isNull())
2326 3688 : thisms.flagCmd().lock(false);
2327 3688 : if(!thisms.freqOffset().isNull())
2328 150 : thisms.freqOffset().lock(false);
2329 : //True here as we can write in that
2330 3688 : if(!thisms.history().isNull())
2331 : // thisms.history().lock(!readOnly_p);
2332 3688 : thisms.history().lock(false);
2333 3688 : if(!thisms.pointing().isNull())
2334 3688 : thisms.pointing().lock(false);
2335 : //we write virtual model here
2336 3688 : if(!thisms.source().isNull())
2337 3688 : thisms.source().lock(!readOnly_p);
2338 3688 : if(!thisms.sysCal().isNull())
2339 315 : thisms.sysCal().lock(false);
2340 3688 : if(!thisms.weather().isNull())
2341 315 : thisms.weather().lock(false);
2342 :
2343 3688 : }
2344 : ///////////////////////
2345 :
2346 821 : Vector<SynthesisParamsSelect> SynthesisImagerVi2::tuneSelectData(){
2347 821 : vi_p->originChunks();
2348 821 : vi_p->origin();
2349 821 : vi::VisBuffer2* vb=vi_p->getVisBuffer();
2350 821 : Int spwnow=vb->spectralWindows()[0];
2351 821 : Int nchaninms=MSColumns(vb->ms()).spectralWindow().numChan()(spwnow);
2352 : //For some small number of channels in the ms vi/vb2 retuning the selection
2353 : //will sometimes return more channels than what is in the ms...this is a
2354 : //kludge here to bypass it...mostly seen in test_tclean
2355 : /// write to the test !! till someboody fixes this is vi2 or wait for cngi
2356 : //if savescratch column we have tune...otherwise some channel may be 0
2357 : // when chunking or in parallel
2358 : //cerr << "nchanims " << nchaninms << endl;
2359 821 : if(nchaninms <30 && !(!readOnly_p && useScratch_p))
2360 810 : return dataSel_p;
2361 :
2362 11 : return SynthesisImager::tuneSelectData();
2363 : }
2364 : //////////////////////
2365 1800 : void SynthesisImagerVi2::lockMSs(){
2366 3684 : for(uInt i=0;i<mss_p.nelements();i++)
2367 : {
2368 :
2369 1884 : MeasurementSet *ms_l = const_cast<MeasurementSet* >(mss_p[i]);
2370 1884 : lockMS(*ms_l);
2371 : }
2372 :
2373 1800 : }
2374 8272 : void SynthesisImagerVi2::unlockMSs()
2375 : {
2376 16544 : LogIO os( LogOrigin("SynthesisImagerVi2","unlockMSs",WHERE) );
2377 16915 : for(uInt i=0;i<mss_p.nelements();i++)
2378 : {
2379 8643 : os << LogIO::NORMAL2 << "Unlocking : " << (mss_p[i])->tableName() << LogIO::POST;
2380 8643 : MeasurementSet *ms_l = const_cast<MeasurementSet* >(mss_p[i]);
2381 8643 : ms_l->unlock();
2382 8643 : ms_l->antenna().unlock();
2383 8643 : ms_l->dataDescription().unlock();
2384 8643 : ms_l->feed().unlock();
2385 8643 : ms_l->field().unlock();
2386 8643 : ms_l->observation().unlock();
2387 8643 : ms_l->polarization().unlock();
2388 8643 : ms_l->processor().unlock();
2389 8643 : ms_l->spectralWindow().unlock();
2390 8643 : ms_l->state().unlock();
2391 : //
2392 : // Unlock the optional sub-tables as well, if they are present
2393 : //
2394 8643 : if(!(ms_l->source().isNull())) ms_l->source().unlock();
2395 8643 : if(!(ms_l->doppler().isNull())) ms_l->doppler().unlock();
2396 8643 : if(!(ms_l->flagCmd().isNull())) ms_l->flagCmd().unlock();
2397 8643 : if(!(ms_l->freqOffset().isNull())) ms_l->freqOffset().unlock();
2398 8643 : if(!(ms_l->history().isNull())) ms_l->history().unlock();
2399 8643 : if(!(ms_l->pointing().isNull())) ms_l->pointing().unlock();
2400 8643 : if(!(ms_l->sysCal().isNull())) ms_l->sysCal().unlock();
2401 8643 : if(!(ms_l->weather().isNull())) ms_l->weather().unlock();
2402 : }
2403 8272 : }
2404 1732 : void SynthesisImagerVi2::createFTMachine(
2405 : CountedPtr<refim::FTMachine>& theFT,
2406 : CountedPtr<refim::FTMachine>& theIFT,
2407 : const String& ftname,
2408 : const uInt nTaylorTerms,
2409 : const String mType,
2410 : const Int facets, //=1
2411 : //------------------------------
2412 : const Int wprojplane, //=1,
2413 : const Float padding, //=1.0,
2414 : const Bool useAutocorr, //=false,
2415 : const Bool useDoublePrec, //=true,
2416 : const String gridFunction, //=String("SF"),
2417 : //------------------------------
2418 : const Bool aTermOn, //= true,
2419 : const Bool psTermOn, //= true,
2420 : const Bool mTermOn, //= false,
2421 : const Bool wbAWP, //= true,
2422 : const String cfCache, //= "",
2423 : const Bool usePointing, //= false,
2424 : // const Vector<Float> pointingOffsetSigDev, //= 10.0,
2425 : const vector<float> pointingOffsetSigDev, // = {10,10}
2426 : const Bool doPBCorr, //= true,
2427 : const Bool conjBeams, //= true,
2428 : const Float computePAStep, //=360.0
2429 : const Float rotatePAStep, //=5.0
2430 : const String interpolation, //="linear"
2431 : const Bool freqFrameValid, //=true
2432 : const Int cache, //=1000000000,
2433 : const Int tile, //=16
2434 : const String stokes, //=I
2435 : const String imageNamePrefix,
2436 : //---------------------------
2437 : const String &pointingDirCol,
2438 : const String &convertFirst,
2439 : const Float skyPosThreshold,
2440 : const Int convSupport,
2441 : const Quantity &truncateSize,
2442 : const Quantity &gwidth,
2443 : const Quantity &jwidth,
2444 : const Float minWeight,
2445 : const Bool clipMinMax,
2446 : const Bool pseudoI
2447 : )
2448 :
2449 : {
2450 3464 : LogIO os( LogOrigin("SynthesisImagerVi2","createFTMachine",WHERE));
2451 :
2452 :
2453 1732 : if (ftname == "gridft") {
2454 1242 : if (facets >1) {
2455 : theFT = new refim::GridFT(
2456 : cache, tile,
2457 6 : gridFunction, mLocation_p, phaseCenter_p, padding,
2458 : useAutocorr, useDoublePrec
2459 3 : );
2460 : theIFT = new refim::GridFT(
2461 : cache, tile,
2462 6 : gridFunction, mLocation_p, phaseCenter_p, padding,
2463 : useAutocorr, useDoublePrec
2464 3 : );
2465 : }
2466 : else {
2467 : theFT = new refim::GridFT(
2468 : cache, tile,
2469 1239 : gridFunction, mLocation_p, padding,
2470 : useAutocorr, useDoublePrec
2471 1239 : );
2472 : theIFT = new refim::GridFT(
2473 : cache, tile,
2474 1239 : gridFunction, mLocation_p, padding,
2475 : useAutocorr, useDoublePrec
2476 1239 : );
2477 : }
2478 : }
2479 490 : else if (ftname == "wprojectft") {
2480 45 : Double maxW = -1.0;
2481 45 : Double minW = -1.0;
2482 45 : Double rmsW = -1.0;
2483 45 : if (wprojplane < 1)
2484 7 : casa::refim::WProjectFT::wStat(*vi_p, minW, maxW, rmsW);
2485 45 : if (facets > 1) {
2486 2 : theFT = new refim::WProjectFT(wprojplane, phaseCenter_p, mLocation_p,
2487 1 : cache/2, tile, useAutocorr, padding, useDoublePrec, minW, maxW, rmsW);
2488 2 : theIFT = new refim::WProjectFT(wprojplane, phaseCenter_p, mLocation_p,
2489 1 : cache/2, tile, useAutocorr, padding, useDoublePrec, minW, maxW, rmsW);
2490 : }
2491 : else {
2492 44 : theFT = new refim::WProjectFT(wprojplane, mLocation_p,
2493 44 : cache/2, tile, useAutocorr, padding, useDoublePrec, minW, maxW, rmsW);
2494 44 : theIFT = new refim::WProjectFT(wprojplane, mLocation_p,
2495 44 : cache/2, tile, useAutocorr, padding, useDoublePrec, minW, maxW, rmsW);
2496 : }
2497 : CountedPtr<refim::WPConvFunc> sharedconvFunc =
2498 45 : static_cast<refim::WProjectFT &>(*theFT).getConvFunc();
2499 : //static_cast<WProjectFT &>(*theFT).setConvFunc(sharedconvFunc);
2500 45 : static_cast<refim::WProjectFT &>(*theIFT).setConvFunc(sharedconvFunc);
2501 45 : }
2502 :
2503 445 : else if ( ftname == "mosaic" || ftname== "mosft" || ftname == "mosaicft" || ftname== "MosaicFT" || ftname == "awp2"){
2504 :
2505 208 : createMosFTMachine(theFT, theIFT, padding, useAutocorr, useDoublePrec, rotatePAStep, stokes, conjBeams);
2506 : }
2507 237 : else if ((ftname.at(0,3)=="awp") || (ftname== "mawprojectft") || (ftname == "protoft")) {
2508 93 : createAWPFTMachine(theFT, theIFT, ftname, facets, wprojplane,
2509 : padding, useAutocorr, useDoublePrec, gridFunction,
2510 : aTermOn, psTermOn, mTermOn, wbAWP, cfCache,
2511 : usePointing, pointingOffsetSigDev, doPBCorr, conjBeams, computePAStep,
2512 : rotatePAStep, cache,tile,imageNamePrefix);
2513 : }
2514 :
2515 288 : else if ( ftname == "mosaic" or
2516 288 : ftname == "mosft" or
2517 432 : ftname == "mosaicft" or
2518 144 : ftname == "MosaicFT" ) {
2519 0 : createMosFTMachine(
2520 : theFT, theIFT,
2521 : padding, useAutocorr, useDoublePrec, rotatePAStep, stokes, conjBeams
2522 : );
2523 : }
2524 144 : else if ( ftname == "sd" ) {
2525 144 : createSDFTMachine(
2526 : theFT, theIFT,
2527 : pointingDirCol, convertFirst,
2528 : skyPosThreshold, doPBCorr, rotatePAStep,
2529 : gridFunction, convSupport, truncateSize, gwidth, jwidth,
2530 : minWeight, clipMinMax, cache, tile, stokes
2531 : );
2532 : }
2533 : else {
2534 0 : throw( AipsError( "Invalid FTMachine name : " + ftname ) );
2535 : }
2536 :
2537 : // Now, clone and pack the chosen FT into a MultiTermFT if needed.
2538 1732 : if( mType == "multiterm" ) {
2539 119 : AlwaysAssert( nTaylorTerms>=1 , AipsError );
2540 :
2541 : CountedPtr<refim::FTMachine> theMTFT =
2542 119 : new refim::MultiTermFTNew( theFT, nTaylorTerms, true /*forward*/ );
2543 : CountedPtr<refim::FTMachine> theMTIFT =
2544 119 : new refim::MultiTermFTNew( theIFT, nTaylorTerms, false /*forward*/ );
2545 :
2546 119 : theFT = theMTFT;
2547 119 : theIFT = theMTIFT;
2548 119 : }
2549 :
2550 : // Now, set the SkyJones if needed, and if not internally generated.
2551 1732 : if ( mType == "imagemosaic" and
2552 0 : ( ftname != "awprojectft" and
2553 0 : ftname != "mawprojectft" and
2554 0 : ftname != "proroft" ) ) {
2555 0 : CountedPtr<refim::SkyJones> vp;
2556 0 : MSColumns msc(*(mss_p[0]));
2557 0 : Quantity parang(0.0,"deg");
2558 0 : Quantity skyposthreshold(0.0,"deg");
2559 0 : vp = new refim::VPSkyJones(
2560 : msc, true, parang, BeamSquint::NONE, skyposthreshold
2561 0 : );
2562 :
2563 0 : Vector<CountedPtr<refim::SkyJones> > skyJonesList(1);
2564 0 : skyJonesList(0) = vp;
2565 0 : theFT->setSkyJones( skyJonesList );
2566 0 : theIFT->setSkyJones( skyJonesList );
2567 0 : }
2568 :
2569 : // For mode=cubedata, set the freq frame to invalid.
2570 : // get this info from buildCoordSystem
2571 : // theFT->setSpw( tspws, false );
2572 : // theIFT->setSpw( tspws, false );
2573 1732 : theFT->setFrameValidity( freqFrameValid );
2574 1732 : theIFT->setFrameValidity( freqFrameValid );
2575 :
2576 : // Set interpolation mode
2577 1732 : theFT->setFreqInterpolation( interpolation );
2578 1732 : theIFT->setFreqInterpolation( interpolation );
2579 :
2580 : // Set tracking of moving source if any
2581 1732 : if (movingSource_p != "") {
2582 22 : theFT->setMovingSource(movingSource_p);
2583 22 : theIFT->setMovingSource(movingSource_p);
2584 : }
2585 : /* vi_p has chanselection now
2586 : //channel selections from spw param
2587 : theFT->setSpwChanSelection(chanSel_p);
2588 : theIFT->setSpwChanSelection(chanSel_p);
2589 : */
2590 :
2591 : // Set pseudo-I if requested.
2592 1732 : if (pseudoI == true) {
2593 1 : os << "Turning on Pseudo-I gridding" << LogIO::POST;
2594 1 : theFT->setPseudoIStokes(true);
2595 1 : theIFT->setPseudoIStokes(true);
2596 : }
2597 :
2598 1732 : }
2599 :
2600 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2601 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2602 93 : void SynthesisImagerVi2::createAWPFTMachine(CountedPtr<refim::FTMachine>& theFT, CountedPtr<refim::FTMachine>& theIFT,
2603 : const String& ftmName,
2604 : const Int,// facets, //=1
2605 : //------------------------------
2606 : const Int wprojPlane, //=1,
2607 : const Float,// padding, //=1.0,
2608 : const Bool,// useAutocorr, //=false,
2609 : const Bool useDoublePrec, //=true,
2610 : const String,// gridFunction, //=String("SF"),
2611 : //------------------------------
2612 : const Bool aTermOn, //= true,
2613 : const Bool psTermOn, //= true,
2614 : const Bool mTermOn, //= false,
2615 : const Bool wbAWP, //= true,
2616 : const String cfCache, //= "",
2617 : const Bool usePointing, //= false,
2618 : const vector<Float> pointingOffsetSigDev,//={10,10},
2619 : const Bool doPBCorr, //= true,
2620 : const Bool conjBeams, //= true,
2621 : const Float computePAStep, //=360.0
2622 : const Float rotatePAStep, //=5.0
2623 : const Int cache, //=1000000000,
2624 : const Int tile, //=16
2625 : const String imageNamePrefix
2626 : )
2627 :
2628 : {
2629 186 : LogIO os( LogOrigin("SynthesisImagerVi2","createAWPFTMachine",WHERE));
2630 :
2631 93 : if (wprojPlane<=1)
2632 : {
2633 : os << LogIO::NORMAL
2634 : << "You are using wprojplanes=1. Doing co-planar imaging (no w-projection needed)"
2635 92 : << LogIO::POST;
2636 92 : os << LogIO::NORMAL << "Performing WBA-Projection" << LogIO::POST; // Loglevel PROGRESS
2637 : }
2638 : // if((wprojPlane>1)&&(wprojPlane<64))
2639 : // {
2640 : // os << LogIO::WARN
2641 : // << "No. of w-planes set too low for W projection - recommend at least 128"
2642 : // << LogIO::POST;
2643 : // os << LogIO::NORMAL << "Performing WBAW-Projection" << LogIO::POST; // Loglevel PROGRESS
2644 : // }
2645 :
2646 : // CountedPtr<ATerm> apertureFunction = createTelescopeATerm(mss4vi_p[0], aTermOn);
2647 : // CountedPtr<PSTerm> psTerm = new PSTerm();
2648 : // CountedPtr<WTerm> wTerm = new WTerm();
2649 :
2650 : // //
2651 : // // Selectively switch off CFTerms.
2652 : // //
2653 : // if (aTermOn == false) {apertureFunction->setOpCode(CFTerms::NOOP);}
2654 : // if (psTermOn == false) psTerm->setOpCode(CFTerms::NOOP);
2655 :
2656 : // //
2657 : // // Construct the CF object with appropriate CFTerms.
2658 : // //
2659 : // CountedPtr<ConvolutionFunction> tt;
2660 : // tt = AWProjectFT::makeCFObject(aTermOn, psTermOn, true, mTermOn, wbAWP);
2661 : // CountedPtr<ConvolutionFunction> awConvFunc;
2662 : // // awConvFunc = new AWConvFunc(apertureFunction,psTerm,wTerm, !wbAWP);
2663 : // if ((ftmName=="mawprojectft") || (mTermOn))
2664 : // awConvFunc = new AWConvFuncEPJones(apertureFunction,psTerm,wTerm,wbAWP);
2665 : // else
2666 : // awConvFunc = new AWConvFunc(apertureFunction,psTerm,wTerm,wbAWP);
2667 :
2668 93 : MSObservationColumns msoc((mss_p[0])->observation());
2669 93 : String telescopeName=msoc.telescopeName()(0);
2670 : CountedPtr<refim::ConvolutionFunction> awConvFunc = refim::AWProjectFT::makeCFObject(telescopeName,
2671 : aTermOn,
2672 : psTermOn, (wprojPlane > 1),
2673 93 : mTermOn, wbAWP, conjBeams);
2674 :
2675 : //
2676 : // Construct the appropriate re-sampler.
2677 : //
2678 93 : CountedPtr<refim::VisibilityResamplerBase> visResampler;
2679 : // if (ftmName=="protoft") visResampler = new ProtoVR();
2680 : //elsef
2681 93 : visResampler = new refim::AWVisResampler();
2682 : // CountedPtr<VisibilityResamplerBase> visResampler = new VisibilityResampler();
2683 :
2684 : //
2685 : // Construct and initialize the CF cache object.
2686 : //
2687 :
2688 :
2689 : // CountedPtr<CFCache> cfCacheObj = new CFCache();
2690 : // cfCacheObj->setCacheDir(cfCache.data());
2691 : // // cerr << "Setting wtImagePrefix to " << imageNamePrefix.c_str() << endl;
2692 : // cfCacheObj->setWtImagePrefix(imageNamePrefix.c_str());
2693 : // cfCacheObj->initCache2();
2694 :
2695 93 : CountedPtr<refim::CFCache> cfCacheObj;
2696 :
2697 :
2698 : //
2699 : // Finally construct the FTMachine with the CFCache, ConvFunc and
2700 : // Re-sampler objects.
2701 : //
2702 93 : Float pbLimit_l=1e-3;
2703 :
2704 93 : theFT = new refim::AWProjectWBFT(wprojPlane, cache/2,
2705 : cfCacheObj, awConvFunc,
2706 : visResampler,
2707 : /*true */usePointing, pointingOffsetSigDev ,doPBCorr,
2708 : tile, computePAStep, pbLimit_l, true,conjBeams,
2709 93 : useDoublePrec);
2710 :
2711 93 : cfCacheObj = new refim::CFCache();
2712 93 : cfCacheObj->setCacheDir(cfCache.data());
2713 : // Get the LAZYFILL setting from the user configuration. If not
2714 : // found, default to False.
2715 : //
2716 : // With lazy fill ON, CFCache loads the required CFs on-demand
2717 : // from the disk. And periodically triggers garbage collection to
2718 : // release CFs that aren't required immediately.
2719 93 : if(impars_p.mode.contains("cube")){
2720 19 : cfCacheObj->setLazyFill(False);
2721 : }
2722 : else
2723 74 : cfCacheObj->setLazyFill(refim::SynthesisUtils::getenv("CFCache.LAZYFILL",1)==1);
2724 : // cerr << "Setting wtImagePrefix to " << imageNamePrefix.c_str() << endl;
2725 93 : cfCacheObj->setWtImagePrefix(imageNamePrefix.c_str());
2726 93 : cfCacheObj->initCache2(CFC_VERBOSE);
2727 :
2728 93 : theFT->setCFCache(cfCacheObj);
2729 :
2730 :
2731 93 : Quantity rotateOTF(rotatePAStep,"deg");
2732 93 : static_cast<refim::AWProjectWBFT &>(*theFT).setObservatoryLocation(mLocation_p);
2733 93 : static_cast<refim::AWProjectWBFT &>(*theFT).setPAIncrement(Quantity(computePAStep,"deg"),rotateOTF);
2734 :
2735 : // theIFT = new AWProjectWBFT(wprojPlane, cache/2,
2736 : // cfCacheObj, awConvFunc,
2737 : // visResampler,
2738 : // /*true */usePointing, doPBCorr,
2739 : // tile, computePAStep, pbLimit_l, true,conjBeams,
2740 : // useDoublePrec);
2741 :
2742 : // static_cast<AWProjectWBFT &>(*theIFT).setObservatoryLocation(mLocation_p);
2743 : // static_cast<AWProjectWBFT &>(*theIFT).setPAIncrement(Quantity(computePAStep,"deg"),rotateOTF);
2744 :
2745 93 : theIFT = new refim::AWProjectWBFT(static_cast<refim::AWProjectWBFT &>(*theFT));
2746 :
2747 93 : os << "Sending frequency selection information " << mssFreqSel_p << " to AWP FTM." << LogIO::POST;
2748 93 : theFT->setSpwFreqSelection( mssFreqSel_p );
2749 93 : theIFT->setSpwFreqSelection( mssFreqSel_p );
2750 :
2751 :
2752 93 : }
2753 :
2754 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2755 :
2756 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2757 :
2758 :
2759 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2760 :
2761 208 : void SynthesisImagerVi2:: createMosFTMachine(CountedPtr<refim::FTMachine>& theFT,CountedPtr<refim::FTMachine>& theIFT, const Float /*padding*/, const Bool useAutoCorr, const Bool useDoublePrec, const Float rotatePAStep, const String stokes, const Bool doConjBeams){
2762 :
2763 416 : LogIO os(LogOrigin("SynthesisImagerVi2", "createMosFTMachine",WHERE));
2764 :
2765 208 : MSColumns msc(vi_p->ms());
2766 208 : String telescop=msc.observation().telescopeName()(0);
2767 208 : Bool multiTel=False;
2768 208 : Int msid=0;
2769 1737 : for(vi_p->originChunks(); vi_p->moreChunks(); vi_p->nextChunk()){
2770 1529 : if(((vi_p->getVisBuffer())->msId() != msid) && telescop != MSColumns(vi_p->ms()).observation().telescopeName()(0)){
2771 0 : msid=(vi_p->getVisBuffer())->msId();
2772 0 : multiTel=True;
2773 : }
2774 : }
2775 208 : vi_p->originChunks();
2776 :
2777 :
2778 :
2779 : PBMath::CommonPB kpb;
2780 208 : Record rec;
2781 208 : getVPRecord( rec, kpb, telescop );
2782 :
2783 :
2784 208 : if(rec.empty()){os << LogIO::SEVERE << "Cannot proceed with mosaicft gridder without a valid PB model" << LogIO::POST; }
2785 :
2786 : /*
2787 : VPManager *vpman=VPManager::Instance();
2788 : PBMath::CommonPB kpb;
2789 : PBMath::enumerateCommonPB(telescop, kpb);
2790 : Record rec;
2791 : vpman->getvp(rec, telescop);
2792 : */
2793 :
2794 208 : refim::VPSkyJones* vps= nullptr;
2795 : //cerr << "rec " << rec << " kpb " << kpb << endl;
2796 : //cerr << "createMOs ftname " << gridpars_p.ftmachine << endl;
2797 208 : if (!gridpars_p.ftmachine.contains("mos")) {
2798 0 : cerr << "PASTERP " << rotatePAStep << " " << gridpars_p.computePAStep << endl;
2799 0 : bool dosquint = (gridpars_p.computePAStep < 180); //anything beneath 180 deg ...you are not serious about squint correction
2800 : // TESTOO
2801 0 : dosquint = False;
2802 : ///////
2803 :
2804 0 : cerr << "Doing AWPLPG" << " wprojplanes " << gridpars_p.wprojplanes << endl;
2805 0 : theFT = new refim::AWPLPG(vps , gridpars_p.wprojplanes, dosquint, rotatePAStep*(C::pi)/180.0, mLocation_p, stokes, useAutoCorr, useDoublePrec, gridpars_p.usePointing);
2806 0 : theIFT = new refim::AWPLPG(vps , gridpars_p.wprojplanes, dosquint, rotatePAStep*(C::pi)/180.0, mLocation_p, stokes, useAutoCorr, useDoublePrec, gridpars_p.usePointing);
2807 0 : CountedPtr<refim::SimplePBConvFunc> mospb=new refim::HetArrayConvFunc();
2808 0 : static_cast<refim::AWPLPG &>(*theFT).setConvFunc(mospb);
2809 0 : static_cast<refim::AWPLPG &>(*theIFT).setConvFunc(mospb);
2810 :
2811 0 : }
2812 : else{
2813 208 : if(rec.asString("name")=="COMMONPB" && kpb !=PBMath::UNKNOWN ){
2814 191 : vps= new refim::VPSkyJones(msc, true, Quantity(rotatePAStep, "deg"), BeamSquint::GOFIGURE, Quantity(360.0, "deg"));
2815 : /////Don't know which parameter has pb threshold cutoff that the user want
2816 : ////leaving at default
2817 : ////vps.setThreshold(minPB);
2818 :
2819 : }
2820 : else{
2821 17 : PBMath myPB(rec);
2822 17 : String whichPBMath;
2823 17 : PBMathInterface::namePBClass(myPB.whichPBClass(), whichPBMath);
2824 17 : os << "Using the PB defined by " << whichPBMath << " for beam calculation for telescope " << telescop << LogIO::POST;
2825 17 : vps= new refim::VPSkyJones(telescop, myPB, Quantity(rotatePAStep, "deg"), BeamSquint::GOFIGURE, Quantity(360.0, "deg"));
2826 : //kpb=PBMath::DEFAULT;
2827 17 : }
2828 :
2829 208 : theFT = new refim::MosaicFTNew(vps, mLocation_p, stokes, 1000000000, 16, useAutoCorr,
2830 208 : useDoublePrec, doConjBeams, gridpars_p.usePointing);
2831 208 : PBMathInterface::PBClass pbtype=((kpb==PBMath::EVLA) || multiTel)? PBMathInterface::COMMONPB: PBMathInterface::AIRY;
2832 208 : if(rec.asString("name")=="IMAGE")
2833 0 : pbtype=PBMathInterface::IMAGE;
2834 : ///Use Heterogenous array mode for the following
2835 208 : if((kpb == PBMath::UNKNOWN) || (kpb==PBMath::OVRO) || (kpb==PBMath::ACA)
2836 195 : || (kpb==PBMath::ALMA) || (kpb==PBMath::EVLA) || multiTel){
2837 182 : CountedPtr<refim::SimplePBConvFunc> mospb=new refim::HetArrayConvFunc(pbtype, itsVpTable);
2838 182 : static_cast<refim::MosaicFTNew &>(*theFT).setConvFunc(mospb);
2839 182 : }
2840 : ///////////////////make sure both FTMachine share the same conv functions.
2841 208 : theIFT= new refim::MosaicFTNew(static_cast<refim::MosaicFTNew &>(*theFT));
2842 : }
2843 208 : }
2844 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2845 :
2846 144 : void SynthesisImagerVi2::createSDFTMachine(CountedPtr<refim::FTMachine>& theFT,
2847 : CountedPtr<refim::FTMachine>& theIFT,
2848 : const String &pointingDirCol,
2849 : const String &convertFirst,
2850 : const Float skyPosThreshold,
2851 : const Bool /*doPBCorr*/,
2852 : const Float rotatePAStep,
2853 : const String& gridFunction,
2854 : const Int convSupport,
2855 : const Quantity& truncateSize,
2856 : const Quantity& gwidth,
2857 : const Quantity& jwidth,
2858 : const Float minWeight,
2859 : const Bool clipMinMax,
2860 : const Int cache,
2861 : const Int tile,
2862 : const String &stokes,
2863 : const Bool pseudoI) {
2864 : // // member variable itsVPTable is VP table name
2865 288 : LogIO os(LogOrigin("SynthesisImagerVi2", "createSDFTMachine", WHERE));
2866 : os << LogIO::NORMAL // Loglevel INFO
2867 144 : << "Performing single dish gridding..." << LogIO::POST;
2868 : os << LogIO::NORMAL1 // gridFunction is too cryptic for most users.
2869 144 : << "with convolution function " << gridFunction << LogIO::POST;
2870 :
2871 : // Now make the Single Dish Gridding
2872 : os << LogIO::NORMAL // Loglevel INFO
2873 144 : << "Gridding will use specified common tangent point:" << LogIO::POST;
2874 144 : os << LogIO::NORMAL << SynthesisUtilMethods::asComprehensibleDirectionString(phaseCenter_p)
2875 144 : << LogIO::POST; // Loglevel INFO
2876 144 : String const gridfunclower = downcase(gridFunction);
2877 144 : if(gridfunclower=="pb") {
2878 22 : refim::SkyJones *vp = nullptr;
2879 22 : MSColumns msc(*mss_p[0]);
2880 : // todo: NONE is OK?
2881 22 : BeamSquint::SquintType squintType = BeamSquint::NONE;
2882 22 : Quantity skyPosThresholdQuant((Double)skyPosThreshold+180.0, "deg");
2883 22 : Quantity parAngleStepQuant((Double)rotatePAStep, "deg");
2884 22 : if (itsVpTable.empty()) {
2885 : os << LogIO::NORMAL // Loglevel INFO
2886 22 : << "Using defaults for primary beams used in gridding" << LogIO::POST;
2887 22 : vp=new refim::VPSkyJones(msc, true, parAngleStepQuant, squintType,
2888 22 : skyPosThresholdQuant);
2889 : } else {
2890 : os << LogIO::NORMAL // Loglevel INFO
2891 0 : << "Using VP as defined in " << itsVpTable << LogIO::POST;
2892 0 : Table vpTable( itsVpTable );
2893 0 : vp=new refim::VPSkyJones(msc, vpTable, parAngleStepQuant, squintType,
2894 0 : skyPosThresholdQuant);
2895 0 : }
2896 22 : theFT = new refim::SDGrid(mLocation_p, *vp, cache/2, tile, gridfunclower,
2897 22 : convSupport, minWeight, clipMinMax);
2898 22 : theIFT = new refim::SDGrid(mLocation_p, *vp, cache/2, tile, gridfunclower,
2899 22 : convSupport, minWeight, clipMinMax);
2900 144 : } else if (gridfunclower=="gauss" || gridfunclower=="gjinc") {
2901 3 : DirectionCoordinate dirCoord = itsMaxCoordSys.directionCoordinate();
2902 3 : Vector<String> units = dirCoord.worldAxisUnits();
2903 3 : Vector<Double> increments = dirCoord.increment();
2904 3 : Quantity cellx(increments[0], units[0]);
2905 3 : Quantity celly(increments[1], units[1]);
2906 6 : if (cellx != celly &&
2907 3 : ((!truncateSize.getUnit().empty()||truncateSize.getUnit()=="pixel")
2908 3 : || (!gwidth.getUnit().empty()||gwidth.getUnit()=="pixel")
2909 3 : || (!jwidth.getUnit().empty()||jwidth.getUnit()=="pixel"))) {
2910 : os << LogIO::WARN
2911 : << "The " << gridFunction << " gridding doesn't support non-square grid." << endl
2912 0 : << "Result may be wrong." << LogIO::POST;
2913 : }
2914 : Float truncateValue, gwidthValue, jwidthValue;
2915 3 : if (truncateSize.getUnit().empty() || truncateSize.getUnit()=="pixel")
2916 3 : truncateValue = truncateSize.getValue();
2917 : else
2918 0 : truncateValue = truncateSize.getValue("rad")/celly.getValue("rad");
2919 3 : if (gwidth.getUnit().empty() || gwidth.getUnit()=="pixel")
2920 3 : gwidthValue = gwidth.getValue();
2921 : else
2922 0 : gwidthValue = gwidth.getValue("rad")/celly.getValue("rad");
2923 3 : if (jwidth.getUnit().empty() || jwidth.getUnit()=="pixel")
2924 3 : jwidthValue = jwidth.getValue();
2925 : else
2926 0 : jwidthValue = jwidth.getValue("rad")/celly.getValue("rad");
2927 3 : theFT = new refim::SDGrid(mLocation_p, cache/2, tile, gridfunclower,
2928 3 : truncateValue, gwidthValue, jwidthValue, minWeight, clipMinMax);
2929 3 : theIFT = new refim::SDGrid(mLocation_p, cache/2, tile, gridfunclower,
2930 3 : truncateValue, gwidthValue, jwidthValue, minWeight, clipMinMax);
2931 3 : }
2932 : else {
2933 119 : theFT = new refim::SDGrid(mLocation_p, cache/2, tile, gridfunclower,
2934 119 : convSupport, minWeight, clipMinMax);
2935 119 : theIFT = new refim::SDGrid(mLocation_p, cache/2, tile, gridfunclower,
2936 119 : convSupport, minWeight, clipMinMax);
2937 : }
2938 144 : theFT->setPointingDirColumn(pointingDirCol);
2939 144 : static_cast<refim::SDGrid*>(theFT.get())->setConvertFirst(convertFirst);
2940 144 : static_cast<refim::SDGrid*>(theIFT.get())->setConvertFirst(convertFirst);
2941 :
2942 : // turn on Pseudo Stokes mode if necessary
2943 144 : if (pseudoI || stokes == "XX" || stokes == "YY" || stokes == "XXYY"
2944 288 : || stokes == "RR" || stokes == "LL" || stokes == "RRLL") {
2945 4 : theFT->setPseudoIStokes(True);
2946 4 : theIFT->setPseudoIStokes(True);
2947 : }
2948 144 : }
2949 :
2950 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2951 : //// Get/Set Weight Grid.... write to disk and read
2952 :
2953 : /// todo : do for full mapper list, and taylor terms.
2954 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2955 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2956 2 : Bool SynthesisImagerVi2::setWeightDensity( const String& weightimagename)
2957 : {
2958 4 : LogIO os(LogOrigin("SynthesisImagerVi2", "setWeightDensity()", WHERE));
2959 : try
2960 : {
2961 2 : if(weightimagename.size() !=0){
2962 2 : Table::isReadable(weightimagename, True);
2963 2 : PagedImage<Float> im(weightimagename);
2964 2 : imwgt_p=VisImagingWeight(im);
2965 2 : im.unlock();
2966 2 : }
2967 : else{
2968 : ////In memory weight densities is being deprecated...we should get rid of this bit
2969 0 : Int ndensities=1;
2970 0 : if((itsMappers.imageStore(0)->gridwt()->nelements())==5)
2971 0 : ndensities=(itsMappers.imageStore(0)->gridwt())->shape()[4];
2972 0 : Int nx=(itsMappers.imageStore(0)->gridwt())->shape()[0];
2973 0 : Int ny=(itsMappers.imageStore(0)->gridwt())->shape()[1];
2974 0 : Block<Matrix<Float> > densitymatrices(ndensities);
2975 0 : if(((itsMappers.imageStore(0)->gridwt())->shape().nelements())==5){
2976 0 : IPosition blc(Vector<Int>(5,0));
2977 0 : for (uInt fid=0;fid<densitymatrices.nelements();fid++)
2978 : {
2979 0 : densitymatrices[fid].resize();
2980 0 : Array<Float> lala;
2981 0 : blc[4]=fid;
2982 0 : itsMappers.imageStore(0)->gridwt()->getSlice(lala, blc, IPosition(5, nx, ny,1,1,1), True);
2983 0 : densitymatrices[fid].reference( lala.reform(IPosition(2, nx, ny)));
2984 0 : }
2985 0 : }
2986 : else{
2987 0 : Array<Float> lala;
2988 0 : itsMappers.imageStore(0)->gridwt()->get(lala, True);
2989 0 : densitymatrices[0].reference( lala.reform(IPosition(2, nx, ny)));
2990 0 : }
2991 0 : imwgt_p.setWeightDensity( densitymatrices );
2992 0 : }
2993 :
2994 2 : vi_p->useImagingWeight(imwgt_p);
2995 2 : itsMappers.releaseImageLocks();
2996 :
2997 : }
2998 0 : catch (AipsError &x)
2999 : {
3000 0 : throw(AipsError("In setWeightDensity : "+x.getMesg()));
3001 0 : }
3002 2 : return true;
3003 2 : }
3004 :
3005 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3006 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3007 :
3008 :
3009 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3010 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3011 1800 : void SynthesisImagerVi2::createVisSet(const Bool /*writeAccess*/)
3012 : {
3013 3600 : LogIO os( LogOrigin("SynthesisImagerVi2","createVisSet",WHERE) );
3014 : //cerr << "mss_p num" << mss_p.nelements() << " sel " << fselections_p->size() << endl;
3015 1800 : lockMSs();
3016 1800 : if(mss_p.nelements() > uInt(fselections_p->size()) && (fselections_p->size() !=0)){
3017 0 : throw(AipsError("Discrepancy between Number of MSs and Frequency selections"));
3018 : }
3019 1800 : vi_p=new vi::VisibilityIterator2(mss_p, vi::SortColumns(), true); //writeAccess);
3020 :
3021 1800 : if(fselections_p->size() !=0){
3022 1800 : CountedPtr<vi::FrequencySelections> tmpfselections=new FrequencySelections();
3023 : //Temporary fix till we get rid of old vi and we can get rid of tuneSelect
3024 1800 : if(uInt(fselections_p->size()) > mss_p.nelements()){
3025 0 : for(uInt k=0 ; k < mss_p.nelements(); ++k){
3026 0 : tmpfselections->add(fselections_p->get(k));
3027 : }
3028 : }
3029 : else{
3030 1800 : tmpfselections=fselections_p;
3031 : }
3032 : ////end of fix for tuneSelectdata
3033 1800 : vi_p->setFrequencySelection (*tmpfselections);
3034 :
3035 1800 : }
3036 : //
3037 1800 : vi_p->originChunks();
3038 1800 : vi_p->origin();
3039 : ////make sure to use the latest imaging weight scheme
3040 1800 : vi_p->useImagingWeight(imwgt_p);
3041 1800 : unlockMSs();
3042 1800 : }// end of createVisSet
3043 :
3044 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3045 : // Method to run the AWProjectFT machine to seperate the CFCache
3046 : // construction from imaging. This is done by splitting the
3047 : // operation in two steps: (1) run the FTM in "dry" mode to create a
3048 : // "blank" CFCache, and (2) re-load the "blank" CFCache and "fill"
3049 : // it.
3050 : //
3051 : // If someone can get me (SB) out of the horrible statc_casts in the
3052 : // code below, I will be most grateful (we are out of it! :-)).
3053 : //
3054 7 : void SynthesisImagerVi2::dryGridding(const Vector<String>& cfList)
3055 : {
3056 14 : LogIO os( LogOrigin("SynthesisImagerVi2","dryGridding",WHERE) );
3057 :
3058 7 : rownr_t cohDone=0;
3059 7 : Int whichFTM=0;
3060 : (void)cfList;
3061 : // If not an AWProject-class FTM, make this call a NoOp. Might be
3062 : // useful to extend it to other projection FTMs -- but later.
3063 7 : String ftmName = ((*(itsMappers.getFTM2(whichFTM)))).name();
3064 :
3065 7 : if (!((itsMappers.getFTM2(whichFTM,true))->isUsingCFCache())) return;
3066 :
3067 7 : os << "---------------------------------------------------- Dry Gridding ---------------------------------------------" << LogIO::POST;
3068 :
3069 : //
3070 : // Go through the entire MS in "dry" mode to set up a "blank"
3071 : // CFCache. This is done by setting the AWPWBFT in dryrun mode
3072 : // and gridding. The process of gridding emits CFCache, which
3073 : // will be "blank" in a dry run.
3074 : {
3075 7 : vi::VisBuffer2* vb=vi_p->getVisBuffer();
3076 7 : vi_p->originChunks();
3077 7 : vi_p->origin();
3078 7 : Double numberCoh=0;
3079 14 : for (uInt k=0; k< mss_p.nelements(); ++k)
3080 7 : numberCoh+=Double(mss_p[k]->nrow());
3081 :
3082 14 : ProgressMeter pm(1.0, numberCoh, "dryGridding", "","","",true);
3083 :
3084 7 : itsMappers.initializeGrid(*vi_p);
3085 :
3086 : // Set the gridder (iFTM) to run in dry-gridding mode
3087 7 : (itsMappers.getFTM2(whichFTM,true))->setDryRun(true);
3088 :
3089 7 : Bool aTermIsOff=False;
3090 : {
3091 7 : CountedPtr<refim::FTMachine> ftm=itsMappers.getFTM2(whichFTM,True);
3092 7 : CountedPtr<refim::ConvolutionFunction> cf=ftm->getAWConvFunc();
3093 7 : aTermIsOff = cf->getTerm("ATerm")->isNoOp();
3094 7 : }
3095 :
3096 : os << "Making a \"blank\" CFCache"
3097 : << (aTermIsOff?" (without the A-Term)":"")
3098 7 : << LogIO::WARN << LogIO::POST;
3099 :
3100 : // Step through the MS. This triggers the logic in the Gridder
3101 : // to determine all the CFs that will be required. These empty
3102 : // CFs are written to the CFCache which can then be filled via
3103 : // a call to fillCFCache().
3104 31 : for (vi_p->originChunks(); vi_p->moreChunks();vi_p->nextChunk())
3105 : {
3106 732 : for (vi_p->origin(); vi_p->more(); vi_p->next())
3107 : {
3108 708 : if (SynthesisUtilMethods::validate(*vb)!=SynthesisUtilMethods::NOVALIDROWS)
3109 : {
3110 708 : itsMappers.grid(*vb, true, refim::FTMachine::OBSERVED, whichFTM);
3111 708 : cohDone += vb->nRows();
3112 708 : pm.update(Double(cohDone));
3113 : // If there is no term that depends on time, don't iterate over the entire data base
3114 708 : if (aTermIsOff) break;
3115 : }
3116 : }
3117 : }
3118 7 : }
3119 7 : if (cohDone == 0) os << "No valid rows found in dryGridding." << LogIO::EXCEPTION << LogIO::POST;
3120 : // Unset the dry-gridding mode.
3121 7 : (itsMappers.getFTM2(whichFTM,true))->setDryRun(false);
3122 :
3123 : //itsMappers.checkOverlappingModels("restore");
3124 7 : unlockMSs();
3125 : //fillCFCache(cfList);
3126 7 : }
3127 : //
3128 : // Re-load the CFCache from the disk using the supplied list of CFs
3129 : // (as cfList). Then extract the ConvFunc object (which was setup
3130 : // in the FTM) and call it's makeConvFunction2() to fill the CF.
3131 : // Finally, unset the dry-run mode of the FTM.
3132 : //
3133 7 : void SynthesisImagerVi2::fillCFCache(const Vector<String>& cfList,
3134 : const String& ftmName,
3135 : const String& cfcPath,
3136 : const Bool& psTermOn,
3137 : const Bool& aTermOn,
3138 : const Bool& conjBeams)
3139 : {
3140 14 : LogIO os( LogOrigin("SynthesisImagerVi2","fillCFCache",WHERE) );
3141 : // If not an AWProject-class FTM, make this call a NoOp. Might be
3142 : // useful to extend it to other projection FTMs -- but later.
3143 : // String ftmName = ((*(itsMappers.getFTM(whichFTM)))).name();
3144 :
3145 7 : if (!ftmName.contains("awproject") and
3146 0 : !ftmName.contains("multitermftnew")) return;
3147 : //if (!ftmName.contains("awproject")) return;
3148 :
3149 7 : os << "---------------------------------------------------- fillCFCache ---------------------------------------------" << LogIO::POST;
3150 :
3151 : //String cfcPath = itsMappers.getFTM(whichFTM)->getCacheDir();
3152 : //String imageNamePrefix=itsMappers.getFTM(whichFTM)->getCFCache()->getWtImagePrefix();
3153 :
3154 : //cerr << "Path = " << path << endl;
3155 :
3156 : // CountedPtr<AWProjectWBFTNew> tmpFT = new AWProjectWBFTNew(static_cast<AWProjectWBFTNew &> (*(itsMappers.getFTM(whichFTM))));
3157 :
3158 :
3159 7 : Float dPA=360.0,selectedPA=2*360.0;
3160 7 : if (cfList.nelements() > 0)
3161 : {
3162 7 : CountedPtr<refim::CFCache> cfCacheObj = new refim::CFCache();
3163 : //Vector<String> wtCFList; wtCFList.resize(cfList.nelements());
3164 : //for (Int i=0; i<wtCFList.nelements(); i++) wtCFList[i] = "WT"+cfList[i];
3165 : //Directory dir(path);
3166 7 : Vector<String> cfList_p=cfList;//dir.find(Regex(Regex::fromPattern("CFS*")));
3167 7 : Vector<String> wtCFList_p;
3168 7 : wtCFList_p.resize(cfList_p.nelements());
3169 49 : for (Int i=0; i<(Int)wtCFList_p.nelements(); i++) wtCFList_p[i]="WT"+cfList_p[i];
3170 :
3171 : //cerr << cfList_p << endl;
3172 7 : cfCacheObj->setCacheDir(cfcPath.data());
3173 :
3174 7 : os << "Re-loading the \"blank\" CFCache for filling" << LogIO::WARN << LogIO::POST;
3175 :
3176 7 : cfCacheObj->initCacheFromList2(cfcPath, cfList_p, wtCFList_p,
3177 : selectedPA, dPA,CFC_VERBOSE);
3178 :
3179 : // tmpFT->setCFCache(cfCacheObj);
3180 7 : Vector<Double> uvScale, uvOffset;
3181 7 : Matrix<Double> vbFreqSelection;
3182 7 : CountedPtr<refim::CFStore2> cfs2 = CountedPtr<refim::CFStore2>(&cfCacheObj->memCache2_p[0],false);//new CFStore2;
3183 7 : CountedPtr<refim::CFStore2> cfwts2 = CountedPtr<refim::CFStore2>(&cfCacheObj->memCacheWt2_p[0],false);//new CFStore2;
3184 :
3185 : //
3186 : // Get whichFTM from itsMappers (SIMapperCollection) and
3187 : // cast it as AWProjectWBFTNew. Then get the ConvFunc from
3188 : // the FTM and cast it as AWConvFunc. Finally call
3189 : // AWConvFunc::makeConvFunction2().
3190 : //
3191 : // (static_cast<AWConvFunc &>
3192 : // (*(static_cast<AWProjectWBFTNew &> (*(itsMappers.getFTM(whichFTM)))).getAWConvFunc())
3193 : // ).makeConvFunction2(String(path), uvScale, uvOffset, vbFreqSelection,
3194 : // *cfs2, *cfwts2);
3195 :
3196 : // This is a global methond in AWConvFunc. Does not require
3197 : // FTM to be constructed (which can be expensive in terms of
3198 : // memory footprint).
3199 7 : refim::AWConvFunc::makeConvFunction2(String(cfcPath), uvScale, uvOffset, vbFreqSelection,
3200 7 : *cfs2, *cfwts2, psTermOn, aTermOn, conjBeams);
3201 7 : }
3202 : //cerr << "Mem used = " << itsMappers.getFTM(whichFTM)->getCFCache()->memCache2_p[0].memUsage() << endl;
3203 : //(static_cast<AWProjectWBFTNew &> (*(itsMappers.getFTM(whichFTM)))).getCFCache()->initCache2();
3204 7 : }
3205 :
3206 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3207 7 : void SynthesisImagerVi2::reloadCFCache()
3208 : {
3209 14 : LogIO os( LogOrigin("SynthesisImagerVi2","reloadCFCache",WHERE) );
3210 7 : Int whichFTM=0;
3211 7 : CountedPtr<refim::FTMachine> ftm=itsMappers.getFTM2(whichFTM,true);
3212 :
3213 : // Proceed only if FMTs uses the CFCache mechanism. The first FTM
3214 : // in the Mapper is used to make this decision. Not sure if the
3215 : // framework pipes allow other FTMs in SIMapper to be
3216 : // fundamentally different. If it does, and if that is
3217 : // triggered, the current decision may be insufficient.
3218 7 : if (!(ftm->isUsingCFCache())) return; // Better check than checking against FTM name
3219 :
3220 7 : os << "-------------------------------------------- Re-load CFCache ---------------------------------------------" << LogIO::POST;
3221 :
3222 : // Following code that distinguishes between MultiTermFTM and
3223 : // all others should ideally be replaced with a polymorphic
3224 : // solution. I.e. all FTMs should have a working getFTM2(bool)
3225 : // method. This is required since MultiTermFTM is a container
3226 : // FTM and it's getFTM2() returns the internal (per-MTMFS term)
3227 : // FTMs. Non-container FTMs must return a pointer to
3228 : // themselves. The if-else below is because attempts to make
3229 : // AWProjectFT::getFTM2() work have failed.
3230 : //
3231 : // Control reaches this stage only if the isUsingCFCache() test
3232 : // above return True. The only FTMs what will pass that test
3233 : // for now are AWProjectFT (and its derivatives) and
3234 : // MultiTermFTM if it is constructed with AWP.
3235 : //
3236 7 : CountedPtr<refim::CFCache> cfc;
3237 7 : if (ftm->name().contains("MultiTerm")) cfc = ftm->getFTM2(true)->getCFCache();
3238 7 : else cfc = ftm->getCFCache();
3239 7 : cfc->setLazyFill((refim::SynthesisUtils::getenv("CFCache.LAZYFILL",1)==1));
3240 7 : cfc->initCache2();
3241 :
3242 :
3243 : // String path,imageNamePrefix;
3244 : // if (ftm->name().contains("MultiTerm"))
3245 : // {
3246 : // path = ftm->getFTM2(true)->getCacheDir();
3247 : // imageNamePrefix = ftm->getFTM2(true)->getCFCache()->getWtImagePrefix();
3248 : // }
3249 : // else
3250 : // {
3251 : // path = ftm->getCacheDir();
3252 : // imageNamePrefix = ftm->getCFCache()->getWtImagePrefix();
3253 : // }
3254 :
3255 :
3256 : // CountedPtr<refim::CFCache> cfCacheObj = new refim::CFCache();
3257 : // cfCacheObj->setCacheDir(path.c_str());
3258 : // cfCacheObj->setWtImagePrefix(imageNamePrefix.c_str());
3259 : // cfCacheObj->setLazyFill((refim::SynthesisUtils::getenv("CFCache.LAZYFILL",1)==1));
3260 : // cfCacheObj->initCache2();
3261 :
3262 : // // This assumes the itsMappers is always SIMapperCollection.
3263 : // for (whichFTM = 0; whichFTM < itsMappers.nMappers(); whichFTM++)
3264 : // {
3265 : // CountedPtr<refim::FTMachine> ifftm=itsMappers.getFTM2(whichFTM,true),
3266 : // fftm=itsMappers.getFTM2(whichFTM,false);
3267 :
3268 : // ifftm->setCFCache(cfCacheObj,true);
3269 : // fftm->setCFCache(cfCacheObj,true);
3270 : // }
3271 7 : }
3272 : //////////////////
3273 0 : bool SynthesisImagerVi2::makeMosaicSensitivity(){
3274 : ///We will bother with the first image. As A projection style gridding
3275 : ///usually is done on that first image.
3276 : /// if necessary in the future we will need to migrate this to SIMapper to
3277 : /// do it for all fields if multiple fields are A-projected.
3278 0 : if(!itsMappers.getFTM2(0))
3279 0 : return False;
3280 : /////////////////
3281 0 : vi::VisBuffer2* vb=vi_p->getVisBuffer();
3282 0 : vi_p->originChunks();
3283 0 : vi_p->origin();
3284 0 : Double numcoh=0;
3285 0 : for (uInt k=0; k< mss_p.nelements(); ++k)
3286 0 : numcoh+=Double(mss_p[k]->nrow());
3287 : ProgressMeter pm(1.0, numcoh,
3288 0 : "Gridding Weights for PB", "","","",true);
3289 0 : rownr_t cohDone=0;
3290 :
3291 :
3292 : ///This will initialize weight grid too.
3293 0 : itsMappers.initializeGrid(*vi_p,True);
3294 0 : for (vi_p->originChunks(); vi_p->moreChunks();vi_p->nextChunk())
3295 : {
3296 :
3297 0 : for (vi_p->origin(); vi_p->more(); vi_p->next())
3298 : {
3299 0 : if (SynthesisUtilMethods::validate(*vb)!=SynthesisUtilMethods::NOVALIDROWS)
3300 : {
3301 0 : itsMappers.getFTM2(0)->gridImgWeights(*vb);
3302 0 : cohDone += vb->nRows();
3303 0 : pm.update(Double(cohDone));
3304 : }
3305 : }
3306 : }
3307 : //now load the images in weight and sumwt
3308 0 : itsMappers.getFTM2(0)-> finalizeToWeightImage(*vb, imageStore(0));
3309 : //cerr << "@@@@@@@MAKING PB " << endl;
3310 0 : return True;
3311 :
3312 :
3313 0 : }
3314 :
3315 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3316 676 : Bool SynthesisImagerVi2::loadMosaicSensitivity(){
3317 676 : String ftmname=itsMappers.getFTM2(0)->name();
3318 :
3319 676 : if(ftmname.contains("Mosaic") || ftmname.contains("AWProjectWB")){
3320 : //sumwt has been calcuated
3321 252 : Bool donesumwt=(max(itsMappers.imageStore(0)->sumwt()->get()) > 0.0);
3322 : //cerr << "Done sumwght " << donesumwt << max(itsMappers.imageStore(0)->sumwt()->get()) << endl;
3323 252 : if(donesumwt){
3324 504 : IPosition shp=itsMappers.imageStore(0)->weight()->shape();
3325 504 : CoordinateSystem cs=itsMappers.imageStore(0)->weight()->coordinates();
3326 252 : CountedPtr<TempImage<Float> > wgtim=new TempImage<Float>(shp, cs);
3327 252 : wgtim->copyData(*(itsMappers.imageStore(0)->weight()));
3328 252 : (static_cast<refim::FTMachine &>( *(itsMappers.getFTM2(0,False)))).setWeightImage(*wgtim);
3329 252 : static_cast<refim::FTMachine &>( *(itsMappers.getFTM2(0,True))).setWeightImage(*wgtim);
3330 252 : return true;
3331 252 : }
3332 :
3333 :
3334 : }
3335 424 : return false;
3336 676 : }
3337 : /////////////////////////////////////////////////
3338 0 : Record SynthesisImagerVi2::apparentSensitivity()
3339 : {
3340 0 : LogIO os(LogOrigin("SynthesisImagerVi2", "apparentSensitivity()", WHERE));
3341 :
3342 0 : Record outrec;
3343 : try {
3344 :
3345 : os << LogIO::NORMAL // Loglevel INFO
3346 : << "Calculating apparent sensitivity from MS weights, as modified by gridding weight function"
3347 0 : << LogIO::POST;
3348 : os << LogIO::NORMAL // Loglevel INFO
3349 : << "(assuming that MS weights have correct scale and units)"
3350 0 : << LogIO::POST;
3351 :
3352 0 : Double sumNatWt=0.0;
3353 0 : Double sumGridWt=0.0;
3354 0 : Double sumGridWt2OverNatWt=0.0;
3355 :
3356 0 : Float iNatWt(0.0),iGridWt(0.0);
3357 :
3358 0 : vi::VisBuffer2* vb = vi_p->getVisBuffer();
3359 0 : vi_p->originChunks();
3360 0 : vi_p->origin();
3361 :
3362 : // Discover if weightSpectrum non-trivially available
3363 0 : Bool doWtSp=vi_p->weightSpectrumExists();
3364 :
3365 : //////
3366 0 : for(vi_p->originChunks(); vi_p->moreChunks(); vi_p->nextChunk())
3367 : {
3368 0 : for (vi_p->origin(); vi_p->more(); vi_p->next())
3369 : {
3370 0 : auto nRow=vb->nRows();
3371 0 : const Vector<Bool>& rowFlags(vb->flagRow());
3372 :
3373 0 : const Vector<Int>& a1(vb->antenna1()), a2(vb->antenna2());
3374 :
3375 : // Extract weights correctly (use WEIGHT_SPECTRUM, if available)
3376 0 : Int nCorr=vb->nCorrelations();
3377 0 : Matrix<Float> wtm;
3378 0 : Cube<Float> wtc;
3379 0 : if (doWtSp)
3380 : // WS available [nCorr,nChan,nRow]
3381 0 : wtc.reference(vb->weightSpectrum());
3382 : else {
3383 : // WS UNavailable weight()[nCorr,nRow] --> [nCorr,nChan,nRow]
3384 0 : wtc.reference(vb->weight().reform(IPosition(3,nCorr,1,nRow))); // unchan'd weight as single-chan
3385 : }
3386 0 : Int nChanWt=wtc.shape()(1); // Might be 1 (no WtSp)
3387 :
3388 0 : Cube<Bool> flagCube(vb->flagCube());
3389 0 : for (rownr_t row=0; row<nRow; row++) {
3390 0 : if (!rowFlags(row) && a1(row)!=a2(row)) { // exclude ACs
3391 :
3392 0 : for (Int ich=0;ich<vb->nChannels();++ich) {
3393 0 : if( !flagCube(0,ich,row) && !flagCube(nCorr-1,ich,row)) { // p-hands unflagged
3394 :
3395 : // Accumulate relevant info
3396 :
3397 : // Simple sum of p-hand for now
3398 0 : iNatWt=wtc(0,ich%nChanWt,row)+wtc(nCorr-1,ich%nChanWt,row);
3399 :
3400 0 : iGridWt=2.0f*vb->imagingWeight()(ich,row);
3401 :
3402 0 : if (iGridWt>0.0 && iNatWt>0.0) {
3403 0 : sumNatWt+=(iNatWt);
3404 0 : sumGridWt+=(iGridWt);
3405 0 : sumGridWt2OverNatWt+=(iGridWt*iGridWt/iNatWt);
3406 : }
3407 : }
3408 : }
3409 : }
3410 : } // row
3411 0 : } // vb
3412 : } // chunks
3413 :
3414 0 : if (sumNatWt==0.0) {
3415 0 : os << "Cannot calculate sensitivity: sum of selected natural weights is zero" << LogIO::EXCEPTION;
3416 : }
3417 0 : if (sumGridWt==0.0) {
3418 0 : os << "Cannot calculate sensitivity: sum of gridded weights is zero" << LogIO::EXCEPTION;
3419 : }
3420 :
3421 0 : Double effSensitivity = sqrt(sumGridWt2OverNatWt)/sumGridWt;
3422 :
3423 0 : Double natSensitivity = 1.0/sqrt(sumNatWt);
3424 0 : Double relToNat=effSensitivity/natSensitivity;
3425 :
3426 : os << LogIO::NORMAL << "RMS Point source sensitivity : " // Loglevel INFO
3427 : << effSensitivity // << " Jy/beam" // actually, units are arbitrary
3428 0 : << LogIO::POST;
3429 : os << LogIO::NORMAL // Loglevel INFO
3430 0 : << "Relative to natural weighting : " << relToNat << LogIO::POST;
3431 :
3432 : // Fill output Record
3433 0 : outrec.define("relToNat",relToNat);
3434 0 : outrec.define("effSens",effSensitivity);
3435 :
3436 0 : } catch (AipsError x) {
3437 0 : throw(x);
3438 : return outrec;
3439 0 : }
3440 0 : return outrec;
3441 :
3442 0 : }
3443 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3444 :
3445 752 : Bool SynthesisImagerVi2::makePB()
3446 : {
3447 1504 : LogIO os( LogOrigin("SynthesisImagerVi2","makePB",WHERE) );
3448 :
3449 752 : if( itsMakeVP==False )
3450 : {
3451 173 : if( ((itsMappers.getFTM2(0))->name())!="MultiTermFTNew")
3452 133 : if(!loadMosaicSensitivity()){
3453 0 : if(!makeMosaicSensitivity())
3454 0 : throw(AipsError("Problem with making/loading sensitivity image for A -projection gridder"));
3455 : }
3456 : }
3457 : else
3458 : {
3459 579 : Bool doDefaultVP = itsVpTable.length()>0 ? False : True;
3460 :
3461 579 : CoordinateSystem coordsys=itsMappers.imageStore(0)->getCSys();
3462 579 : String telescope=coordsys.obsInfo().telescope();
3463 :
3464 579 : if (doDefaultVP) {
3465 :
3466 573 : MSAntennaColumns ac(mss_p[0]->antenna());
3467 573 : Double dishDiam=ac.dishDiameter()(0);
3468 573 : if(!allEQ(ac.dishDiameter().getColumn(), dishDiam))
3469 : os << LogIO::WARN
3470 : << "The MS has multiple antenna diameters ..PB could be wrong "
3471 0 : << LogIO::POST;
3472 573 : return makePBImage( telescope, False, dishDiam);
3473 573 : }
3474 : else{
3475 6 : return makePBImage(telescope );
3476 : }
3477 :
3478 579 : }
3479 :
3480 173 : return False;
3481 752 : }
3482 :
3483 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3484 :
3485 579 : Bool SynthesisImagerVi2::makePrimaryBeam(PBMath& pbMath)
3486 : {
3487 1158 : LogIO os( LogOrigin("SynthesisImagerVi2","makePrimaryBeam",WHERE) );
3488 :
3489 579 : os << "vi2 : Evaluating Primary Beam model onto image grid(s)" << LogIO::POST;
3490 :
3491 579 : itsMappers.initPB();
3492 :
3493 579 : vi::VisBuffer2* vb = vi_p->getVisBuffer();
3494 579 : vi_p->originChunks();
3495 579 : vi_p->origin();
3496 579 : std::map<Int, std::set<Int>> fieldsDone;
3497 579 : VisBufferUtil vbU(*vb);
3498 : ///////if tracking a moving source
3499 579 : MDirection origMovingDir;
3500 579 : MDirection newPhaseCenter;
3501 579 : Bool trackBeam=getMovingDirection(*vb, origMovingDir, True);
3502 : //////
3503 1307 : for(vi_p->originChunks(); vi_p->moreChunks(); vi_p->nextChunk())
3504 : {
3505 154098 : for (vi_p->origin(); vi_p->more(); vi_p->next())
3506 : {
3507 153370 : Bool fieldDone=False;
3508 153370 : if(fieldsDone.count(vb->msId() >0)){
3509 152768 : fieldDone=fieldDone || (fieldsDone[vb->msId()].count(vb->fieldId()(0)) > 0);
3510 : }
3511 : else{
3512 602 : fieldsDone[vb->msId()]=std::set<int>();
3513 : }
3514 153370 : if(!fieldDone){
3515 613 : fieldsDone[vb->msId()].insert(vb->fieldId()(0));
3516 613 : if(trackBeam){
3517 5 : MDirection newMovingDir;
3518 5 : getMovingDirection(*vb, newMovingDir);
3519 : //newPhaseCenter=vb->phaseCenter();
3520 5 : newPhaseCenter=vbU.getPhaseCenter(*vb);
3521 5 : newPhaseCenter.shift(MVDirection(-newMovingDir.getAngle()+origMovingDir.getAngle()), False);
3522 5 : }
3523 613 : itsMappers.addPB(*vb,pbMath, newPhaseCenter, trackBeam);
3524 :
3525 : }
3526 : }
3527 : }
3528 579 : itsMappers.releaseImageLocks();
3529 579 : unlockMSs();
3530 :
3531 579 : return True;
3532 579 : }// end makePB
3533 :
3534 584 : Bool SynthesisImagerVi2::getMovingDirection(const vi::VisBuffer2& vb, MDirection& outDir, const Bool useImageEpoch){
3535 584 : MDirection movingDir;
3536 584 : Bool trackBeam=False;
3537 :
3538 1168 : MeasFrame mFrame(MEpoch(Quantity(vb.time()(0), "s"), MSColumns(vb.ms()).timeMeas()(0).getRef()), mLocation_p);
3539 584 : if(useImageEpoch){
3540 579 : mFrame.resetEpoch((itsMappers.imageStore(0))->getCSys().obsInfo().obsDate());
3541 :
3542 : }
3543 584 : if(movingSource_p != ""){
3544 : MDirection::Types refType;
3545 10 : trackBeam=True;
3546 10 : if(Table::isReadable(movingSource_p, False)){
3547 : //seems to be a table so assuming ephemerides table
3548 6 : Table laTable(movingSource_p);
3549 6 : Path leSentier(movingSource_p);
3550 6 : MeasComet laComet(laTable, leSentier.absoluteName());
3551 6 : movingDir.setRefString("COMET");
3552 6 : mFrame.set(laComet);
3553 6 : }
3554 : ///if not a table
3555 4 : else if(casacore::MDirection::getType(refType, movingSource_p)){
3556 0 : if(refType > casacore::MDirection::N_Types && refType < casacore::MDirection:: N_Planets ){
3557 : ///A known planet
3558 0 : movingDir.setRefString(movingSource_p);
3559 : }
3560 : }
3561 4 : else if(upcase(movingSource_p)=="TRACKFIELD"){
3562 4 : VisBufferUtil vbU(vb);
3563 4 : movingDir=vbU.getEphemDir(vb, MEpoch(mFrame.epoch()).get("s").getValue());
3564 4 : }
3565 : else{
3566 0 : throw(AipsError("Erroneous tracking direction set to make pb"));
3567 : }
3568 10 : MDirection::Ref outref1(MDirection::AZEL, mFrame);
3569 10 : MDirection tmphazel=MDirection::Convert(movingDir, outref1)();
3570 10 : MDirection::Ref outref(vb.phaseCenter().getRef().getType(), mFrame);
3571 10 : outDir=MDirection::Convert(tmphazel, outref)();
3572 10 : }
3573 : else{
3574 574 : outDir=vb.phaseCenter();
3575 574 : trackBeam=False;
3576 : }
3577 584 : return trackBeam;
3578 :
3579 :
3580 584 : }
3581 1 : CountedPtr<vi::VisibilityIterator2> SynthesisImagerVi2::getVi(){
3582 1 : return vi_p;
3583 : }
3584 1 : CountedPtr<refim::FTMachine> SynthesisImagerVi2::getFTM(const Int fid, Bool ift){
3585 1 : if(itsMappers.nMappers() <=fid)
3586 0 : throw(AipsError("Mappers have not been set for field "+String::toString(fid)));
3587 1 : return (itsMappers.getFTM2(fid, ift));
3588 :
3589 : }
3590 284 : void SynthesisImagerVi2::updateImageBeamSet(Record& returnRec){
3591 284 : if(returnRec.isDefined("imageid") && returnRec.asInt("imageid")==0){
3592 : //ImageInfo ii=(itsMappers.imageStore(0)->psf())->imageInfo();
3593 283 : Vector<Int> chanRange(0);
3594 283 : if(returnRec.isDefined("chanrange"))
3595 283 : chanRange=returnRec.asArrayInt("chanrange");
3596 283 : Int npol=(itsMappers.imageStore(0)->getShape())(2);
3597 283 : Int nchan=(itsMappers.imageStore(0)->getShape())(3);
3598 283 : if(chanRange.nelements() ==2 && chanRange(1) < nchan){
3599 :
3600 283 : ImageBeamSet iibeamset=cubePsfImageInfo_p.getBeamSet();
3601 283 : Matrix<GaussianBeam> mbeams=iibeamset.getBeams();
3602 283 : if(mbeams.nelements()==0){
3603 262 : mbeams.resize(itsMappers.imageStore(0)->getShape()(3), itsMappers.imageStore(0)->getShape()(2));
3604 262 : mbeams.set(GaussianBeam(Vector<Quantity>(3, Quantity(1e-12, "arcsec"))));
3605 : }
3606 283 : Cube<Float> recbeams(returnRec.asArrayFloat("beams"));
3607 2549 : for(Int c=chanRange[0]; c <= chanRange[1]; ++c){
3608 4703 : for(Int p=0; p < npol; ++p){
3609 2437 : mbeams(c,p)=GaussianBeam(Quantity(recbeams(c-chanRange[0], p, 0),"arcsec"), Quantity(recbeams(c-chanRange[0], p, 1),"arcsec"), Quantity(recbeams(c-chanRange[0], p, 2),"deg"));
3610 :
3611 : }
3612 : }
3613 283 : cubePsfImageInfo_p.setBeams(ImageBeamSet(mbeams));
3614 :
3615 283 : }
3616 : //itsMappers.imageStore(0)->psf()->setImageInfo(ii);
3617 : //itsMappers.imageStore(0)->psf()->unlock();
3618 :
3619 :
3620 283 : }
3621 284 : }
3622 :
3623 : } //# NAMESPACE CASA - END
3624 :
|