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