Line data Source code
1 : //# newsimulator.cc: Simulation program
2 : //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //#
5 : //# This program is free software; you can redistribute it and/or modify it
6 : //# under the terms of the GNU General Public License as published by the Free
7 : //# Software Foundation; either version 2 of the License, or (at your option)
8 : //# any later version.
9 : //#
10 : //# This program is distributed in the hope that it will be useful, but WITHOUT
11 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 : //# more details.
14 : //#
15 : //# You should have received a copy of the GNU General Public License along
16 : //# with this program; if not, write to the Free Software Foundation, Inc.,
17 : //# 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 : //#
19 : //# Correspondence concerning AIPS++ should be addressed as follows:
20 : //# Internet email: casa-feedback@nrao.edu.
21 : //# Postal address: AIPS++ Project Office
22 : //# National Radio Astronomy Observatory
23 : //# 520 Edgemont Road
24 : //# Charlottesville, VA 22903-2475 USA
25 : //#
26 : //# $Id: Simulator.cc,v 1.1.2.4 2006/10/06 21:03:19 kgolap Exp $
27 :
28 : #include <stdexcept>
29 : #include <casacore/casa/Arrays/Matrix.h>
30 : #include <casacore/casa/Arrays/ArrayMath.h>
31 : #include <casacore/casa/Exceptions/Error.h>
32 : #include <iostream>
33 :
34 : #include <casacore/casa/Logging.h>
35 : #include <casacore/casa/Logging/LogIO.h>
36 : #include <casacore/casa/OS/File.h>
37 : #include <casacore/casa/Containers/Record.h>
38 : #include <casacore/casa/Containers/RecordInterface.h>
39 :
40 : #include <casacore/tables/TaQL/TableParse.h>
41 : #include <casacore/tables/Tables/TableRecord.h>
42 : #include <casacore/tables/Tables/TableDesc.h>
43 : #include <casacore/tables/Tables/TableLock.h>
44 : #include <casacore/tables/TaQL/ExprNode.h>
45 :
46 : #include <casacore/casa/BasicSL/String.h>
47 : #include <casacore/casa/Utilities/Assert.h>
48 : #include <casacore/casa/Utilities/Fallible.h>
49 :
50 : #include <casacore/casa/BasicSL/Constants.h>
51 :
52 : #include <casacore/casa/Logging/LogSink.h>
53 : #include <casacore/casa/Logging/LogMessage.h>
54 :
55 : #include <casacore/casa/Arrays/ArrayMath.h>
56 :
57 : #include <msvis/MSVis/VisSet.h>
58 : #include <msvis/MSVis/VisSetUtil.h>
59 : #include <synthesis/MeasurementComponents/VisCal.h>
60 : #include <synthesis/MeasurementComponents/VisCalGlobals.h>
61 : #include <casacore/ms/MSOper/NewMSSimulator.h>
62 :
63 : #include <casacore/measures/Measures/Stokes.h>
64 : #include <casacore/casa/Quanta/UnitMap.h>
65 : #include <casacore/casa/Quanta/UnitVal.h>
66 : #include <casacore/casa/Quanta/MVAngle.h>
67 : #include <casacore/measures/Measures/MDirection.h>
68 : #include <casacore/measures/Measures/MPosition.h>
69 : #include <casacore/casa/Quanta/MVEpoch.h>
70 : #include <casacore/measures/Measures/MEpoch.h>
71 :
72 : #include <casacore/ms/MeasurementSets/MeasurementSet.h>
73 : #include <casacore/ms/MeasurementSets/MSColumns.h>
74 :
75 : #include <casacore/ms/MSOper/MSSummary.h>
76 : #include <synthesis/MeasurementEquations/SkyEquation.h>
77 : #include <synthesis/MeasurementComponents/ImageSkyModel.h>
78 : #include <synthesis/MeasurementComponents/SimACohCalc.h>
79 : #include <synthesis/MeasurementComponents/SimACoh.h>
80 : //#include <synthesis/MeasurementComponents/SimVisJones.h>
81 : #include <synthesis/TransformMachines/VPSkyJones.h>
82 : #include <synthesis/TransformMachines/StokesImageUtil.h>
83 : #include <casacore/lattices/LEL/LatticeExpr.h>
84 :
85 : #include <synthesis/MeasurementEquations/Simulator.h>
86 : #include <synthesis/MeasurementComponents/CleanImageSkyModel.h>
87 : #include <synthesis/MeasurementComponents/GridBoth.h>
88 : #include <synthesis/TransformMachines/WProjectFT.h>
89 : #include <synthesis/MeasurementComponents/GridBoth.h>
90 : #include <synthesis/TransformMachines/MosaicFTNew.h>
91 : #include <synthesis/MeasurementEquations/VPManager.h>
92 : #include <synthesis/TransformMachines/HetArrayConvFunc.h> //2016
93 : #include <synthesis/TransformMachines/SimpleComponentFTMachine.h>
94 : #include <casacore/casa/OS/HostInfo.h>
95 : #include <casacore/images/Images/PagedImage.h>
96 : #include <casacore/casa/Arrays/Cube.h>
97 : #include <casacore/casa/Arrays/Vector.h>
98 : #include <sstream>
99 :
100 : #include <casacore/casa/namespace.h>
101 :
102 : namespace casa {
103 :
104 0 : Simulator::Simulator():
105 0 : msname_p(String("")), ms_p(0), mssel_p(0), vs_p(0),
106 0 : seed_p(11111),
107 0 : ac_p(0), distance_p(0), ve_p(), vc_p(), nSpw(0), vp_p(0), gvp_p(0),
108 0 : sim_p(0),
109 : // epJ_p(0),
110 0 : epJTableName_p(),
111 0 : prtlev_(0)
112 : {
113 0 : }
114 :
115 :
116 2 : Simulator::Simulator(String& msname)
117 2 : : msname_p(msname), ms_p(0), mssel_p(0), vs_p(0), seed_p(11111),
118 2 : ac_p(0), distance_p(0),ve_p(), vc_p(), nSpw(0), vp_p(0), gvp_p(0),
119 2 : sim_p(0),
120 : // epJ_p(0),
121 2 : epJTableName_p(),
122 4 : prtlev_(0)
123 : {
124 2 : defaults();
125 :
126 2 : if(!sim_p) {
127 2 : sim_p= new NewMSSimulator(msname);
128 : //sim_p->setPrtlev(prtlev());
129 : }
130 :
131 2 : ve_p.setPrtlev(prtlev());
132 :
133 : // Make a MeasurementSet object for the disk-base MeasurementSet that we just
134 : // created
135 2 : ms_p = new MeasurementSet(msname, TableLock(TableLock::AutoNoReadLocking),
136 2 : Table::Update);
137 2 : AlwaysAssert(ms_p, AipsError);
138 :
139 2 : }
140 :
141 :
142 0 : Simulator::Simulator(MeasurementSet &theMs)
143 0 : : msname_p(""), ms_p(0), mssel_p(0), vs_p(0), seed_p(11111),
144 0 : ac_p(0), distance_p(0), ve_p(), vc_p(), vp_p(0), gvp_p(0),
145 0 : sim_p(0),
146 : // epJ_p(0),
147 0 : epJTableName_p(),
148 0 : prtlev_(0)
149 : {
150 0 : LogIO os(LogOrigin("simulator", "simulator(MeasurementSet& theMs)"));
151 :
152 0 : defaults();
153 :
154 0 : msname_p=theMs.tableName();
155 :
156 0 : if(!sim_p) {
157 0 : sim_p= new NewMSSimulator(theMs);
158 : //sim_p->setPrtlev(prtlev());
159 : }
160 :
161 0 : ve_p.setPrtlev(prtlev());
162 :
163 0 : ms_p = new MeasurementSet(theMs);
164 0 : AlwaysAssert(ms_p, AipsError);
165 :
166 : // get info from the MS into Simulator:
167 0 : if (!getconfig())
168 0 : os << "Can't find antenna information for loaded MS" << LogIO::WARN;
169 0 : if (!sim_p->getSpWindows(nSpw,spWindowName_p,nChan_p,startFreq_p,freqInc_p,stokesString_p))
170 0 : os << "Can't find spectral window information for loaded MS" << LogIO::WARN;
171 0 : freqRes_p.resize(nSpw);
172 0 : for (Int i=0;i<nSpw;++i)
173 0 : freqRes_p[i]=freqInc_p[i];
174 0 : if (!sim_p->getFields(nField,sourceName_p,sourceDirection_p,calCode_p))
175 0 : os << "Can't find Field/Source information for loaded MS" << LogIO::WARN;
176 :
177 0 : if (!sim_p->getFeedMode(feedMode_p))
178 0 : os << "Can't find Feed information for loaded MS" << LogIO::WARN;
179 : else
180 0 : feedsHaveBeenSet=true;
181 :
182 0 : }
183 :
184 :
185 :
186 0 : Simulator::Simulator(const Simulator &other)
187 0 : : msname_p(""), ms_p(0), vs_p(0), seed_p(11111),
188 0 : ac_p(0), distance_p(0),ve_p(), vc_p(), vp_p(0), gvp_p(0),
189 0 : sim_p(0),
190 : // epJ_p(0),
191 0 : epJTableName_p(),
192 0 : prtlev_(0)
193 : {
194 0 : defaults();
195 0 : ms_p = new MeasurementSet(*other.ms_p);
196 0 : if(other.mssel_p) {
197 0 : mssel_p = new MeasurementSet(*other.mssel_p);
198 : }
199 0 : }
200 :
201 0 : Simulator &Simulator::operator=(const Simulator &other)
202 : {
203 0 : if (ms_p && this != &other) {
204 0 : *ms_p = *(other.ms_p);
205 : }
206 0 : if (mssel_p && this != &other && other.mssel_p) {
207 0 : *mssel_p = *(other.mssel_p);
208 : }
209 0 : if (vs_p && this != &other) {
210 0 : *vs_p = *(other.vs_p);
211 : }
212 0 : if (ac_p && this != &other) {
213 0 : *ac_p = *(other.ac_p);
214 : }
215 :
216 : // TBD VisEquation/VisCal stuff
217 :
218 0 : if (vp_p && this != &other) {
219 0 : *vp_p = *(other.vp_p);
220 : }
221 0 : if (gvp_p && this != &other) {
222 0 : *gvp_p = *(other.gvp_p);
223 : }
224 0 : if (sim_p && this != &other) {
225 0 : *sim_p = *(other.sim_p);
226 : }
227 : // if (epJ_p && this != &other) *epJ_p = *(other.epJ_p);
228 0 : return *this;
229 : }
230 :
231 2 : Simulator::~Simulator()
232 : {
233 2 : if (ms_p) {
234 2 : ms_p->relinquishAutoLocks();
235 2 : ms_p->unlock();
236 2 : delete ms_p;
237 : }
238 2 : ms_p = 0;
239 2 : if (mssel_p) {
240 0 : mssel_p->relinquishAutoLocks();
241 0 : mssel_p->unlock();
242 0 : delete mssel_p;
243 : }
244 2 : mssel_p = 0;
245 2 : if (vs_p) {
246 0 : delete vs_p;
247 : }
248 2 : vs_p = 0;
249 :
250 : // Delete all vis-plane calibration corruption terms
251 2 : resetviscal();
252 :
253 : // Delete all im-plane calibration corruption terms
254 2 : resetimcal();
255 :
256 2 : if(sim_p) delete sim_p; sim_p = 0;
257 :
258 2 : if(sm_p) delete sm_p; sm_p = 0;
259 2 : if(ft_p) delete ft_p; ft_p = 0;
260 2 : if(cft_p) delete cft_p; cft_p = 0;
261 :
262 2 : }
263 :
264 :
265 2 : void Simulator::defaults()
266 : {
267 2 : UnitMap::putUser("Pixel", UnitVal(1.0), "Pixel solid angle");
268 2 : UnitMap::putUser("Beam", UnitVal(1.0), "Beam solid angle");
269 2 : gridfunction_p="SF";
270 : // Use half the machine memory as cache. The user can override
271 : // this via the setoptions function().
272 2 : cache_p=(HostInfo::memoryTotal()/8)*1024;
273 :
274 2 : tile_p=16;
275 2 : ftmachine_p="gridft";
276 2 : padding_p=1.3;
277 2 : facets_p=1;
278 2 : sm_p = 0;
279 2 : ft_p = 0;
280 2 : cft_p = 0;
281 2 : vp_p = 0;
282 2 : gvp_p = 0;
283 2 : sim_p = 0;
284 2 : images_p = 0;
285 2 : nmodels_p = 1;
286 : // info for configurations
287 2 : areStationCoordsSet_p = false;
288 2 : telescope_p = "UNSET";
289 2 : nmodels_p = 0;
290 :
291 : // info for fields and schedule:
292 2 : nField=0;
293 2 : sourceName_p.resize(1);
294 2 : sourceName_p[0]="UNSET";
295 2 : calCode_p.resize(1);
296 2 : calCode_p[0]="";
297 2 : sourceDirection_p.resize(1);
298 :
299 : // info for spectral windows
300 2 : nSpw=0;
301 2 : spWindowName_p.resize(1);
302 2 : nChan_p.resize(1);
303 2 : startFreq_p.resize(1);
304 2 : freqInc_p.resize(1);
305 2 : freqRes_p.resize(1);
306 2 : stokesString_p.resize(1);
307 2 : spWindowName_p[0]="UNSET";
308 2 : nChan_p[0]=1;
309 2 : startFreq_p[0]=Quantity(50., "GHz");
310 2 : freqInc_p[0]=Quantity(0.1, "MHz");
311 2 : freqRes_p[0]=Quantity(0.1, "MHz");
312 2 : stokesString_p[0]="RR RL LR LL";
313 :
314 : // feeds
315 2 : feedMode_p = "perfect R L";
316 2 : nFeeds_p = 1;
317 2 : feedsHaveBeenSet = false;
318 2 : feedsInitialized = false;
319 :
320 : // times
321 2 : integrationTime_p = Quantity(10.0, "s");
322 2 : useHourAngle_p=true;
323 2 : refTime_p = MEpoch(Quantity(0.0, "s"), MEpoch::UTC);
324 2 : timesHaveBeenSet_p=false;
325 :
326 : // VP stuff
327 2 : doVP_p=false;
328 2 : doDefaultVP_p = true;
329 :
330 2 : };
331 :
332 :
333 0 : Bool Simulator::close()
334 : {
335 0 : LogIO os(LogOrigin("Simulator", "close()", WHERE));
336 : os << "Closing MeasurementSet and detaching from Simulator"
337 0 : << LogIO::POST;
338 :
339 : // Delete all im-plane calibration corruption terms
340 0 : resetimcal();
341 : // Delete all vis-plane calibration corruption terms
342 0 : resetviscal();
343 :
344 0 : ms_p->unlock();
345 0 : if(mssel_p) mssel_p->unlock();
346 0 : if(vs_p) delete vs_p; vs_p = 0;
347 0 : if(mssel_p) delete mssel_p; mssel_p = 0;
348 0 : if(ms_p) delete ms_p; ms_p = 0;
349 0 : if(sm_p) delete sm_p; sm_p = 0;
350 0 : if(ft_p) delete ft_p; ft_p = 0;
351 0 : if(cft_p) delete cft_p; cft_p = 0;
352 :
353 0 : return true;
354 0 : }
355 :
356 2 : Bool Simulator::resetviscal() {
357 4 : LogIO os(LogOrigin("Simulator", "reset()", WHERE));
358 : try {
359 :
360 2 : os << "Resetting all visibility corruption components" << LogIO::POST;
361 :
362 : // The noise term (for now)
363 2 : if(ac_p) delete ac_p; ac_p=0;
364 :
365 : // Delete all VisCals
366 2 : for (uInt i=0;i<vc_p.nelements();++i)
367 0 : if (vc_p[i]) delete vc_p[i];
368 2 : vc_p.resize(0,true);
369 :
370 : // reset the VisEquation (by sending an empty vc_p)
371 2 : ve_p.setapply(vc_p);
372 :
373 0 : } catch (AipsError x) {
374 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
375 0 : return false;
376 0 : }
377 2 : return true;
378 2 : }
379 :
380 :
381 2 : Bool Simulator::resetimcal() {
382 4 : LogIO os(LogOrigin("Simulator", "reset()", WHERE));
383 : try {
384 :
385 2 : os << "Reset all image-plane corruption components" << LogIO::POST;
386 :
387 2 : if(vp_p) delete vp_p; vp_p=0;
388 2 : if(gvp_p) delete gvp_p; gvp_p=0;
389 : /*
390 : // if(epJ_p) delete epJ_p; epJ_p=0;
391 : */
392 :
393 0 : } catch (AipsError x) {
394 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
395 0 : return false;
396 0 : }
397 2 : return true;
398 2 : }
399 :
400 :
401 0 : Bool Simulator::reset() {
402 0 : LogIO os(LogOrigin("Simulator", "reset()", WHERE));
403 : try {
404 :
405 : // reset vis-plane cal terms
406 0 : resetviscal();
407 :
408 : // reset im-plane cal terms
409 0 : resetimcal();
410 :
411 0 : } catch (AipsError x) {
412 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
413 0 : return false;
414 0 : }
415 0 : return true;
416 0 : }
417 :
418 :
419 0 : String Simulator::name() const
420 : {
421 0 : if (detached()) {
422 0 : return "none";
423 : }
424 0 : return msname_p;
425 : }
426 :
427 0 : String Simulator::state()
428 : {
429 0 : ostringstream os;
430 0 : os << "Need to write the state() method!" << LogIO::POST;
431 0 : if(doVP_p) {
432 0 : os << " Primary beam correction is enabled" << endl;
433 : }
434 0 : return String(os);
435 0 : }
436 :
437 0 : Bool Simulator::summary()
438 : {
439 0 : LogIO os(LogOrigin("Simulator", "summary()", WHERE));
440 0 : createSummary(os);
441 0 : predictSummary(os);
442 0 : corruptSummary(os);
443 :
444 0 : return true;
445 0 : }
446 :
447 :
448 0 : Bool Simulator::createSummary(LogIO& os)
449 : {
450 0 : Bool configResult = configSummary(os);
451 0 : Bool fieldResult = fieldSummary(os);
452 0 : Bool windowResult = spWindowSummary(os);
453 0 : Bool feedResult = feedSummary(os);
454 :
455 0 : if (!configResult && !fieldResult && !windowResult && !feedResult) {
456 0 : os << "=======================================" << LogIO::POST;
457 0 : os << "No create-type information has been set" << LogIO::POST;
458 0 : os << "=======================================" << LogIO::POST;
459 0 : return false;
460 : } else {
461 : // user has set at least ONE, so we report on each
462 0 : if (!configResult) {
463 0 : os << "No configuration information set yet, but other create-type info HAS been set" << LogIO::POST;
464 : }
465 0 : if (!fieldResult) {
466 0 : os << "No field information set yet, but other create-type info HAS been set" << LogIO::POST;
467 : }
468 0 : if (!windowResult) {
469 0 : os << "No window information set yet, but other create-type info HAS been set" << LogIO::POST;
470 : }
471 0 : if (!feedResult) {
472 0 : os << "No feed information set yet, but other create-type info HAS been set" << LogIO::POST;
473 0 : os << "(feeds will default to perfect R-L feeds if not set)" << LogIO::POST;
474 : }
475 0 : os << "======================================================================" << LogIO::POST;
476 : }
477 0 : return true;
478 : }
479 :
480 :
481 :
482 0 : Bool Simulator::configSummary(LogIO& os)
483 : {
484 0 : if ( ! areStationCoordsSet_p ) {
485 0 : return false;
486 : } else {
487 0 : os << "----------------------------------------------------------------------" << LogIO::POST;
488 0 : os << "Generating (u,v,w) using this configuration: " << LogIO::POST;
489 0 : os << " x y z diam mount station " << LogIO::POST;
490 0 : for (uInt i=0; i< x_p.nelements(); i++) {
491 0 : os << x_p(i)
492 0 : << " " << y_p(i)
493 0 : << " " << z_p(i)
494 0 : << " " << diam_p(i)
495 0 : << " " << mount_p(i)
496 0 : << " " << padName_p(i)
497 0 : << LogIO::POST;
498 : }
499 0 : os << " Coordsystem = " << coordsystem_p << LogIO::POST;
500 : os << " RefLocation = " <<
501 0 : mRefLocation_p.getAngle("deg").getValue("deg") << LogIO::POST;
502 : }
503 0 : return true;
504 :
505 : }
506 :
507 :
508 :
509 0 : Bool Simulator::fieldSummary(LogIO& os)
510 : {
511 0 : os << "----------------------------------------------------------------------" << LogIO::POST;
512 0 : os << " Field information: " << LogIO::POST;
513 0 : if (nField==0)
514 0 : os << "NO Field window information set" << LogIO::POST;
515 : else
516 0 : os << " Name direction calcode" << LogIO::POST;
517 0 : for (Int i=0;i<nField;i++)
518 0 : os << sourceName_p[i]
519 0 : << " " << formatDirection(sourceDirection_p[i])
520 0 : << " " << calCode_p[i]
521 0 : << LogIO::POST;
522 0 : return true;
523 : }
524 :
525 :
526 :
527 0 : Bool Simulator::timeSummary(LogIO& os)
528 : {
529 0 : if(integrationTime_p.getValue("s") <= 0.0) {
530 0 : return false;
531 : } else {
532 0 : os << "----------------------------------------------------------------------" << LogIO::POST;
533 0 : os << " Time information: " << LogIO::POST;
534 : os << " integration time = " << integrationTime_p.getValue("s")
535 0 : << " s" << LogIO::POST;
536 0 : os << " reference time = " << MVTime(refTime_p.get("s").getValue("d")).string()
537 0 : << LogIO::POST;
538 : }
539 0 : return true;
540 : }
541 :
542 :
543 :
544 0 : Bool Simulator::spWindowSummary(LogIO& os)
545 : {
546 0 : os << "----------------------------------------------------------------------" << LogIO::POST;
547 0 : os << " Spectral Windows information: " << LogIO::POST;
548 0 : if (nSpw==0)
549 0 : os << "NO Spectral window information set" << LogIO::POST;
550 : else
551 0 : os << " Name nchan freq[GHz] freqInc[MHz] freqRes[MHz] stokes" << LogIO::POST;
552 0 : for (Int i=0;i<nSpw;i++)
553 0 : os << spWindowName_p[i]
554 0 : << " " << nChan_p[i]
555 0 : << " " << startFreq_p[i].getValue("GHz")
556 0 : << " " << freqInc_p[i].getValue("MHz")
557 0 : << " " << freqRes_p[i].getValue("MHz")
558 0 : << " " << stokesString_p[i]
559 0 : << LogIO::POST;
560 0 : return true;
561 : }
562 :
563 :
564 0 : Bool Simulator::feedSummary(LogIO& os)
565 : {
566 0 : if (!feedsHaveBeenSet) {
567 0 : return false;
568 : } else {
569 0 : os << "----------------------------------------------------------------------" << LogIO::POST;
570 0 : os << " Feed information: " << LogIO::POST;
571 0 : os << feedMode_p << LogIO::POST;
572 : }
573 0 : return true;
574 : }
575 :
576 :
577 0 : Bool Simulator::predictSummary(LogIO& os)
578 : {
579 0 : Bool vpResult = vpSummary(os);
580 0 : Bool optionsResult = optionsSummary(os);
581 :
582 : // keep compiler happy
583 0 : if (!vpResult && !optionsResult) {}
584 0 : return true;
585 : }
586 :
587 :
588 0 : Bool Simulator::vpSummary(LogIO& /*os*/)
589 : {
590 0 : if (vp_p) {
591 0 : vp_p->summary();
592 0 : return true;
593 : } else {
594 0 : return false;
595 : }
596 : }
597 :
598 :
599 0 : Bool Simulator::optionsSummary(LogIO& /*os*/)
600 : {
601 0 : return true;
602 : }
603 :
604 :
605 0 : Bool Simulator::corruptSummary(LogIO& os)
606 : {
607 0 : if (vc_p.nelements()<1 && !ac_p) {
608 0 : os << "===========================================" << LogIO::POST;
609 0 : os << "No corrupting-type information has been set" << LogIO::POST;
610 0 : os << "===========================================" << LogIO::POST;
611 0 : return false;
612 : }
613 : else {
614 0 : os << "Visibilities will be CORRUPTED with the following terms:" << LogIO::POST;
615 :
616 0 : Int napp(vc_p.nelements());
617 0 : for (Int iapp=0;iapp<napp;++iapp)
618 : os << LogIO::NORMAL << ". "
619 0 : << vc_p[iapp]->siminfo()
620 0 : << LogIO::POST;
621 :
622 : // Report also on the noise settings
623 0 : noiseSummary(os);
624 :
625 : }
626 0 : return true;
627 : }
628 :
629 :
630 0 : Bool Simulator::noiseSummary(LogIO& os)
631 : {
632 0 : if (!ac_p) {
633 0 : return false;
634 : } else {
635 0 : os << "Thermal noise corruption activated" << LogIO::POST;
636 0 : os << "Thermal noise mode: " << noisemode_p << LogIO::POST;
637 : }
638 0 : return true;
639 : }
640 :
641 :
642 :
643 :
644 :
645 :
646 :
647 :
648 :
649 :
650 :
651 :
652 :
653 : //========================================================================
654 : // SETUP OBSERVATION
655 :
656 :
657 2 : Bool Simulator::settimes(const Quantity& integrationTime,
658 : const Bool useHourAngle,
659 : const MEpoch& refTime)
660 : {
661 :
662 4 : LogIO os(LogOrigin("simulator", "settimes()"));
663 : // Negative integration time crashes casa
664 2 : AlwaysAssert(integrationTime.getValue("s")>=0, AipsError);
665 : try {
666 :
667 2 : integrationTime_p=integrationTime;
668 2 : useHourAngle_p=useHourAngle;
669 2 : refTime_p=refTime;
670 :
671 : os << "Times " << endl
672 2 : << " Integration time " << integrationTime.getValue("s") << "s" << LogIO::POST;
673 2 : if(useHourAngle) {
674 2 : os << " Times will be interpreted as hour angles for first source" << LogIO::POST;
675 : }
676 :
677 2 : sim_p->settimes(integrationTime, useHourAngle, refTime);
678 :
679 2 : timesHaveBeenSet_p=true;
680 :
681 2 : return true;
682 0 : } catch (AipsError x) {
683 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
684 0 : return false;
685 0 : }
686 : return true;
687 :
688 2 : }
689 :
690 :
691 :
692 0 : Bool Simulator::setseed(const Int seed) {
693 0 : seed_p = seed;
694 0 : return true;
695 : }
696 :
697 :
698 :
699 2 : Bool Simulator::setconfig(const String& telname,
700 : const Vector<Double>& x,
701 : const Vector<Double>& y,
702 : const Vector<Double>& z,
703 : const Vector<Double>& dishDiameter,
704 : const Vector<Double>& offset,
705 : const Vector<String>& mount,
706 : const Vector<String>& antName,
707 : const Vector<String>& padName,
708 : const String& coordsystem,
709 : const MPosition& mRefLocation)
710 : {
711 4 : LogIO os(LogOrigin("Simulator", "setconfig()"));
712 :
713 2 : telescope_p = telname;
714 2 : x_p.resize(x.nelements());
715 2 : x_p = x;
716 2 : y_p.resize(y.nelements());
717 2 : y_p = y;
718 2 : z_p.resize(z.nelements());
719 2 : z_p = z;
720 2 : diam_p.resize(dishDiameter.nelements());
721 2 : diam_p = dishDiameter;
722 2 : offset_p.resize(offset.nelements());
723 2 : offset_p = offset;
724 2 : mount_p.resize(mount.nelements());
725 2 : mount_p = mount;
726 2 : antName_p.resize(antName.nelements());
727 2 : antName_p = antName;
728 2 : padName_p.resize(padName.nelements());
729 2 : padName_p = padName;
730 2 : coordsystem_p = coordsystem;
731 2 : mRefLocation_p = mRefLocation;
732 :
733 2 : uInt nn = x_p.nelements();
734 :
735 2 : if (diam_p.nelements() == 1) {
736 0 : diam_p.resize(nn);
737 0 : diam_p.set(dishDiameter(0));
738 : }
739 2 : if (mount_p.nelements() == 1) {
740 0 : mount_p.resize(nn);
741 0 : mount_p.set(mount(0));
742 : }
743 2 : if (mount_p.nelements() == 0) {
744 0 : mount_p.resize(nn);
745 0 : mount_p.set("alt-az");
746 : }
747 2 : if (offset_p.nelements() == 1) {
748 0 : offset_p.resize(nn);
749 0 : offset_p.set(offset(0));
750 : }
751 2 : if (offset_p.nelements() == 0) {
752 0 : offset_p.resize(nn);
753 0 : offset_p.set(0.0);
754 : }
755 2 : if (antName_p.nelements() == 1) {
756 0 : antName_p.resize(nn);
757 0 : antName_p.set(antName(0));
758 : }
759 2 : if (antName_p.nelements() == 0) {
760 0 : antName_p.resize(nn);
761 0 : antName_p.set("UNKNOWN");
762 : }
763 2 : if (padName_p.nelements() == 1) {
764 0 : padName_p.resize(nn);
765 0 : padName_p.set(padName(0));
766 : }
767 2 : if (padName_p.nelements() == 0) {
768 0 : padName_p.resize(nn);
769 0 : padName_p.set("UNKNOWN");
770 : }
771 :
772 2 : AlwaysAssert( (nn == y_p.nelements()) , AipsError);
773 2 : AlwaysAssert( (nn == z_p.nelements()) , AipsError);
774 2 : AlwaysAssert( (nn == diam_p.nelements()) , AipsError);
775 2 : AlwaysAssert( (nn == offset_p.nelements()) , AipsError);
776 2 : AlwaysAssert( (nn == mount_p.nelements()) , AipsError);
777 :
778 2 : areStationCoordsSet_p = true;
779 :
780 2 : sim_p->initAnt(telescope_p, x_p, y_p, z_p, diam_p, offset_p, mount_p, antName_p, padName_p,
781 2 : coordsystem_p, mRefLocation_p);
782 :
783 2 : return true;
784 2 : }
785 :
786 :
787 :
788 0 : Bool Simulator::getconfig() {
789 : // get it from NewMSSimulator
790 0 : Matrix<Double> xyz_p;
791 : Int nAnt;
792 0 : if (sim_p->getAnt(telescope_p, nAnt, &xyz_p, diam_p, offset_p, mount_p, antName_p, padName_p,
793 0 : coordsystem_p, mRefLocation_p)) {
794 0 : x_p.resize(nAnt);
795 0 : y_p.resize(nAnt);
796 0 : z_p.resize(nAnt);
797 0 : for (Int i=0;i<nAnt;i++) {
798 0 : x_p(i)=xyz_p(0,i);
799 0 : y_p(i)=xyz_p(1,i);
800 0 : z_p(i)=xyz_p(2,i);
801 : }
802 0 : areStationCoordsSet_p = true;
803 0 : return true;
804 : } else {
805 0 : return false;
806 : }
807 0 : }
808 :
809 :
810 :
811 2 : Bool Simulator::setfield(const String& sourceName,
812 : const MDirection& sourceDirection,
813 : const String& calCode,
814 : const Quantity& distance)
815 : {
816 4 : LogIO os(LogOrigin("Simulator", "setfield()"));
817 : try {
818 :
819 2 : if (sourceName == "") {
820 0 : os << LogIO::SEVERE << "must provide a source name" << LogIO::POST;
821 0 : return false;
822 : }
823 :
824 2 : nField++;
825 :
826 2 : if (prtlev()>2) os << "nField = " << nField << LogIO::POST;
827 :
828 2 : distance_p.resize(nField,true);
829 2 : distance_p[nField-1]=distance;
830 2 : sourceName_p.resize(nField,true);
831 2 : sourceName_p[nField-1]=sourceName;
832 2 : sourceDirection_p.resize(nField,true);
833 2 : sourceDirection_p[nField-1]=sourceDirection;
834 2 : calCode_p.resize(nField,true);
835 2 : calCode_p[nField-1]=calCode;
836 :
837 2 : sim_p->initFields(sourceName, sourceDirection, calCode);
838 :
839 0 : } catch (AipsError x) {
840 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
841 0 : return false;
842 0 : }
843 2 : return true;
844 2 : };
845 :
846 :
847 :
848 :
849 0 : Bool Simulator::setmosaicfield(const String& sourcename, const String& calcode, const MDirection& fieldcenter, const Int xmosp, const Int ymosp, const Quantity& mosspacing, const Quantity& distance)
850 : {
851 :
852 0 : Int nx = xmosp;
853 0 : Int ny = ymosp;
854 0 : Double roffset = mosspacing.getValue("rad");
855 : Double newraval, newdecval;
856 0 : uInt k=0;
857 0 : for (Int i=0; i< nx; ++i) {
858 0 : for(Int j=0; j < ny; ++j) {
859 0 : if((nx/2)!=floor(nx/2)) { // odd number of fields in x direction(ra)
860 0 : newraval = fieldcenter.getAngle().getValue("rad")(0) +
861 0 : (i-ceil(nx/2.0))*roffset/cos(fieldcenter.getAngle().getValue("rad")(1));
862 : }
863 : else { //even case
864 0 : newraval = fieldcenter.getAngle().getValue("rad")(0) +
865 0 : ((i-ceil(nx/2)) - 0.5)*roffset/cos(fieldcenter.getAngle().getValue("rad")(1));
866 : }
867 0 : if((ny/2)!=floor(ny/2)) {
868 0 : newdecval = fieldcenter.getAngle().getValue("rad")(1) +
869 0 : (j-ceil(ny/2.0))*roffset;
870 : }
871 : else {
872 0 : newdecval = fieldcenter.getAngle().getValue("rad")(1) +
873 0 : ((j-ceil(ny/2.0)) - 0.5)*roffset;
874 : }
875 0 : if(newraval >2.0*C::pi) {
876 0 : newraval = newraval - 2.0*C::pi;
877 : }
878 : Int sign;
879 0 : if(abs(newdecval) >C::pi/2) {
880 0 : if(newdecval<0) {
881 0 : sign = -1;
882 : }
883 : else {
884 0 : sign = 1;
885 : }
886 0 : newdecval = sign*(C::pi - abs(newdecval));
887 0 : newraval = abs(C::pi - newraval);
888 : }
889 0 : Quantity newdirra(newraval, "rad");
890 0 : Quantity newdirdec(newdecval, "rad");
891 0 : MDirection newdir(newdirra, newdirdec);
892 0 : newdir.setRefString(fieldcenter.getRefString());
893 0 : ostringstream oos;
894 0 : oos << sourcename << "_" << k ;
895 :
896 :
897 0 : setfield(String(oos), newdir, calcode, distance);
898 :
899 0 : ++k;
900 0 : }
901 : }
902 :
903 :
904 0 : return true;
905 : }
906 :
907 :
908 :
909 2 : Bool Simulator::setspwindow(const String& spwName,
910 : const Quantity& freq,
911 : const Quantity& deltafreq,
912 : const Quantity& freqresolution,
913 : const MFrequency::Types& freqType,
914 : const Int nChan,
915 : const String& stokes)
916 :
917 : {
918 4 : LogIO os(LogOrigin("Simulator", "setspwindow()"));
919 : try {
920 2 : if (nChan == 0) {
921 0 : os << LogIO::SEVERE << "must provide nchannels" << LogIO::POST;
922 0 : return false;
923 : }
924 :
925 2 : nSpw++;
926 : #ifdef RI_DEBUG
927 : os << "nspw = " << nSpw << LogIO::POST;
928 : #endif
929 2 : spWindowName_p.resize(nSpw,true);
930 2 : spWindowName_p[nSpw-1] = spwName;
931 2 : nChan_p.resize(nSpw,true);
932 2 : nChan_p[nSpw-1] = nChan;
933 2 : startFreq_p.resize(nSpw,true);
934 2 : startFreq_p[nSpw-1] = freq;
935 2 : freqInc_p.resize(nSpw,true);
936 2 : freqInc_p[nSpw-1] = deltafreq;
937 2 : freqRes_p.resize(nSpw,true);
938 2 : freqRes_p[nSpw-1] = freqresolution;
939 2 : stokesString_p.resize(nSpw,true);
940 2 : stokesString_p[nSpw-1] = stokes;
941 :
942 : #ifdef RI_DEBUG
943 : os << "sending init to MSSim for spw = " << spWindowName_p[nSpw-1] << LogIO::POST;
944 : #endif
945 :
946 : //freqType=MFrequency::TOPO;
947 2 : sim_p->initSpWindows(spWindowName_p[nSpw-1], nChan_p[nSpw-1],
948 2 : startFreq_p[nSpw-1], freqInc_p[nSpw-1],
949 2 : freqRes_p[nSpw-1], freqType,
950 2 : stokesString_p[nSpw-1]);
951 :
952 0 : } catch (AipsError x) {
953 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
954 0 : return false;
955 0 : }
956 2 : return true;
957 2 : };
958 :
959 :
960 2 : Bool Simulator::setfeed(const String& mode,
961 : const Vector<Double>& x,
962 : const Vector<Double>& y,
963 : const Vector<String>& pol)
964 : {
965 4 : LogIO os(LogOrigin("Simulator", "setfeed()"));
966 :
967 2 : if (mode != "perfect R L" && mode != "perfect X Y" && mode != "list") {
968 : os << LogIO::SEVERE <<
969 : "Currently, only perfect R L or perfect X Y feeds or list are recognized"
970 0 : << LogIO::POST;
971 0 : return false;
972 : }
973 2 : feedMode_p = mode;
974 2 : sim_p->initFeeds(feedMode_p, x, y, pol);
975 :
976 2 : nFeeds_p = x.nelements();
977 2 : feedsHaveBeenSet = true;
978 :
979 2 : return true;
980 2 : };
981 :
982 :
983 :
984 :
985 0 : Bool Simulator::setvp(const Bool dovp,
986 : const Bool doDefaultVPs,
987 : const String& vpTable,
988 : const Bool doSquint,
989 : const Quantity &parAngleInc,
990 : const Quantity &skyPosThreshold,
991 : const Float &pbLimit)
992 : {
993 0 : LogIO os(LogOrigin("Simulator", "setvp()"));
994 :
995 0 : os << "Setting voltage pattern parameters" << LogIO::POST;
996 0 : doVP_p=dovp;
997 0 : doDefaultVP_p = doDefaultVPs;
998 0 : vpTableStr_p = vpTable;
999 0 : if (doSquint) {
1000 0 : squintType_p = BeamSquint::GOFIGURE;
1001 : } else {
1002 0 : squintType_p = BeamSquint::NONE;
1003 : }
1004 0 : parAngleInc_p = parAngleInc;
1005 0 : skyPosThreshold_p = skyPosThreshold;
1006 :
1007 0 : if (doDefaultVP_p) {
1008 0 : os << "Using system default voltage patterns for each telescope" << LogIO::POST;
1009 : } else {
1010 0 : if (vpTableStr_p != String("")) {
1011 0 : os << "Using user defined voltage patterns in Table "<< vpTableStr_p
1012 0 : << LogIO::POST;
1013 : }
1014 : }
1015 0 : if (doSquint) {
1016 0 : os << "Beam Squint will be included in the VP model" << LogIO::POST;
1017 : os << "and the parallactic angle increment is "
1018 0 : << parAngleInc_p.getValue("deg") << " degrees" << LogIO::POST;
1019 : }
1020 0 : pbLimit_p = pbLimit;
1021 0 : return true;
1022 0 : };
1023 :
1024 :
1025 :
1026 :
1027 :
1028 :
1029 :
1030 :
1031 :
1032 :
1033 :
1034 :
1035 :
1036 : //========================================================================
1037 : // Create corruption terms - top level specialized routines
1038 :
1039 :
1040 : // NEW NOISE WITH ANoise
1041 :
1042 0 : Bool Simulator::setnoise(const String& mode,
1043 : const String& caltable, // if blank, not stored
1044 : const Quantity& simplenoise,
1045 : // ATM calculation
1046 : const Quantity& pground,
1047 : const Float relhum,
1048 : const Quantity& altitude,
1049 : const Quantity& waterheight,
1050 : const Quantity& pwv,
1051 : // OR user-specified tau and tatmos
1052 : const Float tatmos=250.0,
1053 : const Float tau=0.1,
1054 : // antenna parameters used for either option
1055 : const Float antefficiency=0.80,
1056 : const Float spillefficiency=0.85,
1057 : const Float correfficiency=0.85,
1058 : const Float trx=150.0,
1059 : const Float tground=270.0,
1060 : const Float tcmb=2.73,
1061 : const Bool OTF=true,
1062 : const Float senscoeff=0.0,
1063 : const Int rxtype=0
1064 : ) {
1065 :
1066 0 : LogIO os(LogOrigin("Simulator", "setnoise2()", WHERE));
1067 :
1068 : try {
1069 :
1070 : //cout<<" Sim::setnoise "<<pground<<" "<<relhum<<" "<<altitude<<" "<<waterheight<<" "<<pwv<<endl;
1071 :
1072 0 : noisemode_p = mode;
1073 :
1074 0 : RecordDesc simparDesc;
1075 0 : simparDesc.addField ("type", TpString);
1076 0 : simparDesc.addField ("mode", TpString);
1077 0 : simparDesc.addField ("caltable", TpString);
1078 :
1079 0 : simparDesc.addField ("amplitude", TpFloat); // for constant scale
1080 : // simparDesc.addField ("scale", TpFloat); // for fractional fluctuations
1081 0 : simparDesc.addField ("combine" ,TpString);
1082 :
1083 : // have to be defined here or else have to be added later
1084 0 : simparDesc.addField ("startTime", TpDouble);
1085 0 : simparDesc.addField ("stopTime", TpDouble);
1086 :
1087 0 : simparDesc.addField ("antefficiency" ,TpFloat);
1088 0 : simparDesc.addField ("spillefficiency",TpFloat);
1089 0 : simparDesc.addField ("correfficiency" ,TpFloat);
1090 0 : simparDesc.addField ("trx" ,TpFloat);
1091 0 : simparDesc.addField ("tground" ,TpFloat);
1092 0 : simparDesc.addField ("tcmb" ,TpFloat);
1093 0 : simparDesc.addField ("senscoeff" ,TpFloat);
1094 0 : simparDesc.addField ("rxType" ,TpInt);
1095 :
1096 : // user-override of ATM calculated tau
1097 0 : simparDesc.addField ("tatmos" ,TpFloat);
1098 0 : simparDesc.addField ("tau0" ,TpFloat);
1099 :
1100 0 : simparDesc.addField ("mean_pwv" ,TpDouble);
1101 0 : simparDesc.addField ("pground" ,TpDouble);
1102 0 : simparDesc.addField ("relhum" ,TpFloat);
1103 0 : simparDesc.addField ("altitude" ,TpDouble);
1104 0 : simparDesc.addField ("waterheight" ,TpDouble);
1105 :
1106 0 : simparDesc.addField ("seed" ,TpInt);
1107 :
1108 : // RI todo setnoise2 if tau0 is not defined, use freqdep
1109 :
1110 0 : String caltbl=caltable;
1111 0 : caltbl.trim();
1112 : string::size_type strlen;
1113 0 : strlen=caltbl.length();
1114 0 : if (strlen>3)
1115 0 : if (caltbl.substr(strlen-3,3)=="cal") {
1116 0 : caltbl.resize(strlen-3);
1117 0 : strlen-=3;
1118 : }
1119 0 : if (strlen>1)
1120 0 : if (caltbl.substr(strlen-1,1)==".") {
1121 0 : caltbl.resize(strlen-1);
1122 0 : strlen-=1;
1123 : }
1124 0 : if (strlen>1)
1125 0 : if (caltbl.substr(strlen-1,1)=="_") {
1126 0 : caltbl.resize(strlen-1);
1127 0 : strlen-=1;
1128 : }
1129 :
1130 0 : Record simpar(simparDesc,RecordInterface::Variable);
1131 0 : simpar.define ("seed", seed_p);
1132 0 : simpar.define ("type", "A Noise");
1133 0 : if (strlen>1)
1134 0 : simpar.define ("caltable", caltbl+".A.cal");
1135 0 : simpar.define ("mode", mode);
1136 0 : simpar.define ("combine", ""); // SPW,FIELD, etc
1137 :
1138 0 : if (mode=="simplenoise") {
1139 : os << "Using simple noise model with noise level of " << simplenoise.getValue("Jy")
1140 0 : << " Jy" << LogIO::POST;
1141 0 : simpar.define ("amplitude", Float(simplenoise.getValue("Jy")) );
1142 0 : simpar.define ("mode", "simple");
1143 :
1144 0 : } else if (mode=="tsys-atm" or mode=="tsys-manual") {
1145 : // do be scaled in a minute by a Tsys-derived M below
1146 0 : simpar.define ("amplitude", Float(1.0) );
1147 : // os << "adding noise with unity amplitude" << LogIO::POST;
1148 0 : simpar.define ("mode", mode);
1149 :
1150 : } else {
1151 0 : throw(AipsError("unsupported mode "+mode+" in setnoise()"));
1152 : }
1153 :
1154 0 : Bool saveOnthefly=false;
1155 0 : if (simpar.isDefined("onthefly")) {
1156 0 : saveOnthefly=simpar.asBool("onthefly");
1157 : }
1158 0 : simpar.define("onthefly",OTF);
1159 :
1160 : // create the ANoise
1161 0 : if (!create_corrupt(simpar))
1162 0 : throw(AipsError("could not create ANoise in Simulator::setnoise"));
1163 :
1164 0 : if (mode=="tsys-atm" or mode=="tsys-manual") {
1165 :
1166 0 : simpar.define ("antefficiency" ,antefficiency );
1167 0 : simpar.define ("correfficiency" ,correfficiency );
1168 0 : simpar.define ("spillefficiency",spillefficiency);
1169 0 : simpar.define ("trx" ,trx );
1170 0 : simpar.define ("tground" ,tground );
1171 0 : simpar.define ("tcmb" ,tcmb );
1172 :
1173 0 : if (rxtype>=0) {
1174 0 : simpar.define ("rxType", rxtype);
1175 0 : if (rxtype>0) {
1176 0 : os<<"User has requested Double Sideband Receiver"<<LogIO::POST;
1177 : }
1178 : } else {
1179 0 : simpar.define ("rxType", 0);
1180 0 : os<<"User has not set Rx type, using 2SB"<<LogIO::POST;
1181 : }
1182 :
1183 0 : if ( senscoeff > 0.0 ) {
1184 0 : simpar.define ("senscoeff", Float(senscoeff) );
1185 0 : os << "adding noise with the sensitivity constant of " << senscoeff << LogIO::POST;
1186 : } else {
1187 0 : simpar.define("senscoeff", Float(1./ sqrt(2.)));
1188 0 : os << "adding noise with the sensitivity constant of 1/sqrt(2)" << LogIO::POST;
1189 : }
1190 :
1191 0 : if (pwv.getValue("mm")>0.) {
1192 0 : if (pwv.getValue("mm")>100.)
1193 0 : throw(AipsError(" you input PWV="+String::toString(pwv.getValue("mm"))+"mm. The most common reason for this error is forgetting to set units, which default to meters"));
1194 :
1195 0 : simpar.define ("mean_pwv", pwv.getValue("mm"));
1196 : } else {
1197 0 : simpar.define ("mean_pwv", Double(1.));
1198 : // we want to set it, but it doesn't get used unless ATM is being used
1199 0 : if (mode=="tsys-atm") os<<"User has not set PWV, using 1mm"<<LogIO::POST;
1200 : }
1201 :
1202 0 : if (mode=="tsys-manual") {
1203 : // user can override the ATM calculated optical depth
1204 : // with tau0 to be used over the entire SPW,
1205 0 : simpar.define ("tau0" ,tau );
1206 0 : if (tatmos>10)
1207 0 : simpar.define ("tatmos" ,tatmos );
1208 : else
1209 0 : simpar.define ("tatmos" ,250. );
1210 : // AtmosCorruptor cal deal with
1211 : // an MF in tsys-manual mode - it will use ATM to calculate
1212 : // the relative opacity across the band, but it won't properly
1213 : // integrate the atmosphere to get T_ebb.
1214 : // so for now we'll just make tsys-manual mean freqDepPar=false
1215 :
1216 0 : simpar.define ("type", "T");
1217 : //simpar.define ("type", "M");
1218 :
1219 : } else {
1220 : // otherwise ATM will be used to calculate tau from pwv
1221 : // catch uninitialized variant @#$^@! XML interface
1222 0 : if (pground.getValue("mbar")>100.)
1223 0 : simpar.define ("pground", pground.getValue("mbar"));
1224 : else {
1225 0 : simpar.define ("pground", Double(560.));
1226 0 : os<<"User has not set ground pressure, using 560mb"<<LogIO::POST;
1227 : }
1228 0 : if (relhum>0)
1229 0 : simpar.define ("relhum", relhum);
1230 : else {
1231 0 : simpar.define ("relhum", 20.);
1232 0 : os<<"User has not set ground relative humidity, using 20%"<<LogIO::POST;
1233 : }
1234 0 : if (altitude.getValue("m")>0.)
1235 0 : simpar.define ("altitude", altitude.getValue("m"));
1236 : else {
1237 0 : simpar.define ("altitude", Double(5000.));
1238 0 : os<<"User has not set site altitude, using 5000m"<<LogIO::POST;
1239 : }
1240 0 : if (waterheight.getValue("m")>100.)
1241 0 : simpar.define ("waterheight", waterheight.getValue("km"));
1242 : else {
1243 0 : simpar.define ("waterheight", Double(2.0));
1244 0 : os<<"User has not set water scale height, using 2km"<<LogIO::POST;
1245 : }
1246 : // as a function of frequency (freqDepPar=true)
1247 : //simpar.define ("type", "TF");
1248 0 : simpar.define ("type", "TF NOISE");
1249 : // simpar.define ("type", "MF");
1250 : }
1251 :
1252 0 : if (strlen>1)
1253 0 : simpar.define ("caltable", caltbl+".T.cal");
1254 : //simpar.define ("caltable", caltbl+".M.cal");
1255 :
1256 0 : simpar.define("onthefly",saveOnthefly);
1257 :
1258 : // create the T
1259 0 : if (!create_corrupt(simpar))
1260 0 : throw(AipsError("could not create T in Simulator::setnoise"));
1261 : //throw(AipsError("could not create M in Simulator::setnoise"));
1262 : }
1263 :
1264 0 : } catch (AipsError x) {
1265 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
1266 0 : return false;
1267 0 : }
1268 0 : return true;
1269 0 : }
1270 :
1271 :
1272 :
1273 :
1274 0 : Bool Simulator::setgain(const String& mode,
1275 : const String& caltable,
1276 : const Quantity& interval,
1277 : const Vector<Double>& amplitude)
1278 : {
1279 0 : LogIO os(LogOrigin("Simulator", "setgain()", WHERE));
1280 :
1281 : try {
1282 :
1283 0 : if(mode=="table") {
1284 0 : os << LogIO::SEVERE << "Cannot yet read from table" << LogIO::POST;
1285 0 : return false;
1286 : }
1287 : else {
1288 : // RI TODO Sim::setgain add mode=simple and =normal
1289 0 : if (mode=="fbm" or mode=="random") {
1290 :
1291 : // set record format for calibration table simulation information
1292 0 : RecordDesc simparDesc;
1293 0 : simparDesc.addField ("type", TpString);
1294 0 : simparDesc.addField ("caltable", TpString);
1295 0 : simparDesc.addField ("mode", TpString);
1296 0 : simparDesc.addField ("interval", TpDouble);
1297 0 : simparDesc.addField ("camp", TpComplex);
1298 0 : simparDesc.addField ("amplitude", TpDouble);
1299 0 : simparDesc.addField ("combine", TpString);
1300 0 : simparDesc.addField ("startTime", TpDouble);
1301 0 : simparDesc.addField ("stopTime", TpDouble);
1302 0 : simparDesc.addField ("seed", TpInt);
1303 :
1304 : // Create record with the requisite field values
1305 0 : Record simpar(simparDesc,RecordInterface::Variable);
1306 0 : simpar.define ("type", "G JONES");
1307 0 : simpar.define ("interval", interval.getValue("s"));
1308 0 : simpar.define ("mode", mode);
1309 0 : Complex camp(0.1,0.1);
1310 0 : if (amplitude.size()==1)
1311 0 : camp=Complex(amplitude[0],amplitude[0]);
1312 : else
1313 0 : camp=Complex(amplitude[0],amplitude[1]);
1314 0 : simpar.define ("camp", camp);
1315 0 : os << LogIO::NORMAL << "Gain corruption with complex RMS amplitude = " << camp << LogIO::POST;
1316 0 : simpar.define ("amplitude", Double(abs(camp)));
1317 : //simpar.define ("amplitude", amplitude);
1318 0 : simpar.define ("caltable", caltable);
1319 0 : simpar.define ("combine", "");
1320 0 : simpar.define ("seed", seed_p);
1321 :
1322 : // create the G
1323 0 : if (!create_corrupt(simpar))
1324 0 : throw(AipsError("could not create G in Simulator::setgain"));
1325 :
1326 0 : } else {
1327 0 : throw(AipsError("unsupported mode "+mode+" in setgain()"));
1328 : }
1329 : }
1330 0 : } catch (AipsError x) {
1331 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
1332 0 : return false;
1333 0 : }
1334 0 : return true;
1335 0 : }
1336 :
1337 :
1338 :
1339 :
1340 :
1341 :
1342 :
1343 0 : Bool Simulator::settrop(const String& mode,
1344 : const String& caltable, // output
1345 : const Float pwv,
1346 : const Float deltapwv,
1347 : const Float beta,
1348 : const Float windspeed,
1349 : const Float simintsec=-1.) {
1350 :
1351 0 : LogIO os(LogOrigin("Simulator", "settrop()", WHERE));
1352 :
1353 : #ifndef RI_DEBUG
1354 : try {
1355 : #endif
1356 :
1357 0 : if (mode=="test"||mode=="individual"||mode=="screen") {
1358 :
1359 : // set record format for calibration table simulation information
1360 0 : RecordDesc simparDesc;
1361 0 : simparDesc.addField ("type", TpString);
1362 0 : simparDesc.addField ("caltable", TpString);
1363 0 : simparDesc.addField ("mean_pwv", TpFloat);
1364 0 : simparDesc.addField ("mode", TpString);
1365 0 : simparDesc.addField ("delta_pwv", TpFloat);
1366 0 : simparDesc.addField ("beta", TpFloat);
1367 0 : simparDesc.addField ("windspeed", TpFloat);
1368 0 : simparDesc.addField ("combine", TpString);
1369 :
1370 0 : if(simintsec>0.){
1371 0 : simparDesc.addField ("simint", TpString);
1372 : }
1373 :
1374 0 : simparDesc.addField ("startTime", TpDouble);
1375 0 : simparDesc.addField ("stopTime", TpDouble);
1376 :
1377 0 : simparDesc.addField ("antefficiency" ,TpFloat);
1378 0 : simparDesc.addField ("spillefficiency",TpFloat);
1379 0 : simparDesc.addField ("correfficiency" ,TpFloat);
1380 0 : simparDesc.addField ("trx" ,TpFloat);
1381 0 : simparDesc.addField ("tcmb" ,TpFloat);
1382 0 : simparDesc.addField ("tatmos" ,TpFloat);
1383 :
1384 0 : simparDesc.addField ("tground" ,TpFloat);
1385 0 : simparDesc.addField ("pground" ,TpDouble);
1386 0 : simparDesc.addField ("relhum" ,TpFloat);
1387 0 : simparDesc.addField ("altitude" ,TpDouble);
1388 0 : simparDesc.addField ("waterheight" ,TpDouble);
1389 :
1390 0 : simparDesc.addField ("seed" ,TpInt);
1391 :
1392 : // create record with the requisite field values
1393 0 : Record simpar(simparDesc,RecordInterface::Variable);
1394 0 : simpar.define ("type", "TF");
1395 0 : simpar.define ("caltable", caltable);
1396 0 : simpar.define ("mean_pwv", pwv);
1397 0 : simpar.define ("mode", mode);
1398 0 : simpar.define ("delta_pwv", deltapwv);
1399 0 : simpar.define ("beta", beta);
1400 0 : simpar.define ("windspeed", windspeed);
1401 0 : simpar.define ("combine", "");
1402 :
1403 0 : if(simintsec>0.){
1404 0 : simpar.define ("simint", String::toString(simintsec)+"s");
1405 : }
1406 :
1407 0 : simpar.define ("seed", seed_p);
1408 :
1409 : // if (tground>100.)
1410 : // simpar.define ("tground", tground);
1411 : // else {
1412 0 : simpar.define ("tground", Float(270.));
1413 : // os<<"User has not set ground temperature, using 270K"<<LogIO::POST;
1414 : // }
1415 : // if (pground.getValue("mbar")>100.)
1416 : // simpar.define ("pground", pground.getValue("mbar"));
1417 : // else {
1418 0 : simpar.define ("pground", Double(560.));
1419 : // os<<"User has not set ground pressure, using 560mb"<<LogIO::POST;
1420 : // }
1421 : // if (relhum>0)
1422 : // simpar.define ("relhum", relhum);
1423 : // else {
1424 0 : simpar.define ("relhum", Float(20.));
1425 : // os<<"User has not set ground relative humidity, using 20%"<<LogIO::POST;
1426 : // }
1427 : // if (altitude.getValue("m")>0.)
1428 : // simpar.define ("altitude", altitude.getValue("m"));
1429 : // else {
1430 0 : simpar.define ("altitude", Double(5000.));
1431 : // os<<"User has not set site altitude, using 5000m"<<LogIO::POST;
1432 : // }
1433 : // if (waterheight.getValue("m")>100.)
1434 : // simpar.define ("waterheight", waterheight.getValue("km"));
1435 : // else {
1436 0 : simpar.define ("waterheight", Double(2.0)); // km
1437 : // os<<"User has not set water scale height, using 2km"<<LogIO::POST;
1438 : // }
1439 0 : simpar.define ("spillefficiency", Float(.85));
1440 :
1441 : // create the T
1442 0 : if (!create_corrupt(simpar))
1443 0 : throw(AipsError("could not create T in Simulator::settrop"));
1444 :
1445 0 : } else {
1446 0 : throw(AipsError("unsupported mode "+mode+" in settrop()"));
1447 : }
1448 :
1449 : #ifndef RI_DEBUG
1450 0 : } catch (AipsError x) {
1451 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
1452 0 : return false;
1453 0 : }
1454 : #endif
1455 0 : return true;
1456 0 : }
1457 :
1458 :
1459 :
1460 :
1461 :
1462 :
1463 0 : Bool Simulator::setleakage(const String& /*mode*/, const String& table,
1464 : //const Quantity& interval,
1465 : const Vector<Double>& amplitude,
1466 : const Vector<Double>& offset)
1467 : {
1468 :
1469 0 : LogIO os(LogOrigin("Simulator", "setleakage()", WHERE));
1470 :
1471 : #ifndef RI_DEBUG
1472 : try {
1473 : #endif
1474 :
1475 : // set record format for calibration table simulation information
1476 0 : RecordDesc simparDesc;
1477 0 : simparDesc.addField ("type", TpString);
1478 0 : simparDesc.addField ("caltable", TpString);
1479 : // leave this one for generic SVC::createCorruptor
1480 0 : simparDesc.addField ("amplitude", TpDouble);
1481 0 : simparDesc.addField ("camp", TpComplex);
1482 0 : simparDesc.addField ("offset", TpComplex);
1483 0 : simparDesc.addField ("combine", TpString);
1484 : //simparDesc.addField ("interval", TpDouble);
1485 0 : simparDesc.addField ("simint", TpString);
1486 0 : simparDesc.addField ("startTime", TpDouble);
1487 0 : simparDesc.addField ("stopTime", TpDouble);
1488 :
1489 0 : simparDesc.addField ("seed", TpInt);
1490 :
1491 : // create record with the requisite field values
1492 0 : Record simpar(simparDesc,RecordInterface::Variable);
1493 0 : simpar.define ("type", "D");
1494 0 : simpar.define ("caltable", table);
1495 0 : Complex camp(0.1,0.1);
1496 0 : if (amplitude.size()==1)
1497 0 : camp=Complex(amplitude[0],amplitude[0]);
1498 : else
1499 0 : camp=Complex(amplitude[0],amplitude[1]);
1500 0 : simpar.define ("camp", camp);
1501 0 : simpar.define ("amplitude", Double(abs(camp)));
1502 0 : Complex off(0.,0.);
1503 0 : if (offset.size()==1)
1504 0 : off=Complex(offset[0],offset[0]);
1505 : else
1506 0 : off=Complex(offset[0],offset[1]);
1507 0 : simpar.define ("offset", off);
1508 :
1509 : //simpar.define ("interval", interval.getValue("s"));
1510 : // provide infinite interval
1511 0 : simpar.define ("simint", "infinite");
1512 :
1513 0 : simpar.define ("combine", "");
1514 0 : simpar.define ("seed", seed_p);
1515 :
1516 :
1517 : // create the D
1518 0 : if (!create_corrupt(simpar))
1519 0 : throw(AipsError("could not create D in Simulator::setleakage"));
1520 :
1521 : #ifndef RI_DEBUG
1522 0 : } catch (AipsError x) {
1523 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
1524 0 : return false;
1525 0 : }
1526 : #endif
1527 0 : return true;
1528 0 : }
1529 :
1530 :
1531 :
1532 :
1533 :
1534 :
1535 :
1536 :
1537 :
1538 :
1539 :
1540 :
1541 :
1542 :
1543 :
1544 :
1545 :
1546 :
1547 :
1548 : //========================================================================
1549 : // OLD as yet unconverted corruption generation routines
1550 :
1551 : // OLD NOISE WITH ACoh
1552 :
1553 0 : Bool Simulator::oldsetnoise(const String& mode,
1554 : const String& /*table*/,
1555 : const Quantity& simplenoise,
1556 : const Float antefficiency=0.80,
1557 : const Float correfficiency=0.85,
1558 : const Float spillefficiency=0.85,
1559 : const Float tau=0.0,
1560 : const Float trx=50.0,
1561 : const Float tatmos=250.0,
1562 : const Float tcmb=2.73) {
1563 :
1564 0 : LogIO os(LogOrigin("Simulator", "oldsetnoise()", WHERE));
1565 : try {
1566 :
1567 0 : noisemode_p = mode;
1568 :
1569 0 : os << LogIO::WARN << "Using deprecated ACoh Noise - this will dissapear in the future - please switch to sm.setnoise unless you are simulating single dish data" << LogIO::POST;
1570 :
1571 0 : if(mode=="table") {
1572 0 : os << LogIO::SEVERE << "Cannot yet read from table" << LogIO::POST;
1573 0 : return false;
1574 : }
1575 0 : else if (mode=="simplenoise") {
1576 : os << "Using simple noise model with noise level of " << simplenoise.getValue("Jy")
1577 0 : << " Jy" << LogIO::POST;
1578 0 : if(ac_p) delete ac_p; ac_p = 0;
1579 0 : ac_p = new SimACoh(seed_p, simplenoise.getValue("Jy") );
1580 : }
1581 : else {
1582 0 : os << "Using the Brown calculated noise model" << LogIO::POST;
1583 0 : os << " eta_ant=" << antefficiency << " eta_corr=" << correfficiency << " eta_spill=" << spillefficiency << LogIO::POST;
1584 0 : os << " tau=" << tau << " trx=" << trx << " tatmos=" << tatmos << " tcmb=" << tcmb << LogIO::POST;
1585 0 : if(ac_p) delete ac_p; ac_p = 0;
1586 0 : ac_p = new SimACohCalc(seed_p, antefficiency, correfficiency,
1587 0 : spillefficiency, tau, Quantity(trx, "K"),
1588 0 : Quantity(tatmos, "K"), Quantity(tcmb, "K"));
1589 : }
1590 :
1591 0 : return true;
1592 0 : } catch (AipsError x) {
1593 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
1594 0 : return false;
1595 0 : }
1596 : return true;
1597 :
1598 0 : }
1599 :
1600 :
1601 :
1602 :
1603 :
1604 0 : Bool Simulator::setpa(const String& /*mode*/, const String& /*table*/,
1605 : const Quantity& /*interval*/) {
1606 :
1607 0 : LogIO os(LogOrigin("Simulator", "setpa()", WHERE));
1608 :
1609 : try {
1610 :
1611 0 : throw(AipsError("Corruption by simulated errors temporarily disabled (06Nov20 gmoellen)"));
1612 : /*
1613 : if(mode=="table") {
1614 : os << LogIO::SEVERE << "Cannot yet read from table" << LogIO::POST;
1615 : return false;
1616 : }
1617 : else {
1618 : makeVisSet();
1619 : if(pj_p) delete pj_p; pj_p = 0;
1620 : pj_p = new PJones (*vs_p, interval.get("s").getValue());
1621 : os <<"Using parallactic angle correction"<< LogIO::POST;
1622 : }
1623 : */
1624 : return true;
1625 0 : } catch (AipsError x) {
1626 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
1627 0 : return false;
1628 0 : }
1629 : return true;
1630 0 : };
1631 :
1632 :
1633 :
1634 :
1635 0 : Bool Simulator::setbandpass(const String& /*mode*/, const String& /*table*/,
1636 : const Quantity& /*interval*/,
1637 : const Vector<Double>& /*amplitude*/) {
1638 :
1639 0 : LogIO os(LogOrigin("Simulator", "setbandpass()", WHERE));
1640 :
1641 : try {
1642 :
1643 0 : throw(AipsError("Corruption by simulated errors temporarily disabled (06Nov20 gmoellen)"));
1644 :
1645 : /*
1646 : if(mode=="table") {
1647 : os << LogIO::SEVERE << "Cannot yet read from table" << LogIO::POST;
1648 : return false;
1649 : }
1650 : else {
1651 : os << LogIO::SEVERE << "Cannot yet calculate bandpass" << LogIO::POST;
1652 : return false;
1653 : }
1654 : return true;
1655 : */
1656 0 : } catch (AipsError x) {
1657 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
1658 :
1659 0 : return false;
1660 0 : }
1661 : return true;
1662 0 : }
1663 :
1664 :
1665 :
1666 :
1667 0 : Bool Simulator::setpointingerror(const String& epJTableName,
1668 : const Bool applyPointingOffsets,
1669 : const Bool doPBCorrection)
1670 : {
1671 0 : LogIO os(LogOrigin("Simulator", "close()", WHERE));
1672 0 : epJTableName_p = epJTableName;
1673 : // makeVisSet();
1674 : try {
1675 0 : throw(AipsError("Corruption by simulated errors temporarily disabled (06Nov20 gmoellen)"));
1676 : /*
1677 : if (epJ_p) delete epJ_p;epJ_p=0;
1678 : {
1679 : epJ_p = new EPJones(*vs_p);
1680 : epJ_p->load(epJTableName_p,"","diagonal");
1681 : }
1682 : */
1683 : }
1684 0 : catch (AipsError x)
1685 : {
1686 : os << LogIO::SEVERE << "Caught exception: "
1687 0 : << x.getMesg() << LogIO::POST;
1688 0 : return false;
1689 0 : }
1690 :
1691 : applyPointingOffsets_p = applyPointingOffsets;
1692 : doPBCorrection_p = doPBCorrection;
1693 : return true;
1694 0 : }
1695 :
1696 :
1697 :
1698 :
1699 :
1700 :
1701 :
1702 :
1703 :
1704 :
1705 :
1706 : //========================================================================
1707 : // CORRUPTION - GENERIC VISCAL FUNCTIONS
1708 :
1709 :
1710 :
1711 0 : Bool Simulator::create_corrupt(Record& simpar)
1712 : {
1713 0 : LogIO os(LogOrigin("Simulator", "create_corrupt()", WHERE));
1714 0 : SolvableVisCal *svc(NULL);
1715 :
1716 : // RI todo sim::create_corrupt assert that ms has certain structure
1717 :
1718 : try {
1719 0 : makeVisSet();
1720 :
1721 0 : String upType=simpar.asString("type");
1722 0 : upType.upcase();
1723 0 : os << LogIO::NORMAL << "Creating "<< upType <<" Calibration structure for data corruption." << LogIO::POST;
1724 :
1725 0 : svc = createSolvableVisCal(upType,*vs_p);
1726 :
1727 0 : svc->setPrtlev(prtlev());
1728 :
1729 0 : Vector<Double> solTimes;
1730 0 : svc->setSimulate(*vs_p,simpar,solTimes);
1731 :
1732 : // add to the pointer block of VCs:
1733 0 : uInt napp=vc_p.nelements();
1734 0 : vc_p.resize(napp+1,false,true);
1735 0 : vc_p[napp] = (VisCal*) svc;
1736 : // svc=NULL;
1737 0 : ve_p.setapply(vc_p);
1738 :
1739 0 : } catch (AipsError x) {
1740 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
1741 0 : if (svc) delete svc;
1742 0 : throw(AipsError("Error in Simulator::create_corrupt"));
1743 : return false;
1744 0 : }
1745 0 : return true;
1746 0 : }
1747 :
1748 :
1749 :
1750 :
1751 :
1752 :
1753 :
1754 : //========================================================================
1755 : // corrupt and setapply, for actually changing visibilities
1756 :
1757 :
1758 : /// this can be used to load any table, just that it has to have the right form
1759 :
1760 0 : Bool Simulator::setapply(const String& type,
1761 : const Double& t,
1762 : const String& table,
1763 : const String& /*spw*/,
1764 : const String& /*field*/,
1765 : const String& interp,
1766 : const Bool& calwt,
1767 : const Vector<Int>& spwmap,
1768 : const Float& opacity)
1769 : {
1770 0 : LogIO os(LogOrigin("Simulator", "setapply()", WHERE));
1771 :
1772 : // First try to create the requested VisCal object
1773 0 : VisCal *vc(NULL);
1774 :
1775 : try {
1776 :
1777 0 : makeVisSet();
1778 :
1779 : // Set record format for calibration table application information
1780 0 : RecordDesc applyparDesc;
1781 0 : applyparDesc.addField ("t", TpDouble);
1782 0 : applyparDesc.addField ("table", TpString);
1783 0 : applyparDesc.addField ("interp", TpString);
1784 0 : applyparDesc.addField ("spw", TpArrayInt);
1785 0 : applyparDesc.addField ("field", TpArrayInt);
1786 0 : applyparDesc.addField ("calwt",TpBool);
1787 0 : applyparDesc.addField ("spwmap",TpArrayInt);
1788 0 : applyparDesc.addField ("opacity",TpFloat);
1789 :
1790 : // Create record with the requisite field values
1791 0 : Record applypar(applyparDesc);
1792 0 : applypar.define ("t", t);
1793 0 : applypar.define ("table", table);
1794 0 : applypar.define ("interp", interp);
1795 0 : applypar.define ("spw",Vector<Int>());
1796 0 : applypar.define ("field",Vector<Int>());
1797 : // applypar.define ("spw",getSpwIdx(spw));
1798 : // applypar.define ("field",getFieldIdx(field));
1799 0 : applypar.define ("calwt",calwt);
1800 0 : applypar.define ("spwmap",spwmap);
1801 0 : applypar.define ("opacity", opacity);
1802 :
1803 0 : String upType=type;
1804 0 : if (upType=="")
1805 : // Get type from table
1806 0 : upType = calTableType(table);
1807 :
1808 : // Must be upper case
1809 0 : upType.upcase();
1810 :
1811 : os << LogIO::NORMAL
1812 : << "Arranging to CORRUPT with:"
1813 0 : << LogIO::POST;
1814 :
1815 : // Add a new VisCal to the apply list
1816 0 : vc = createVisCal(upType,*vs_p);
1817 :
1818 0 : vc->setApply(applypar);
1819 :
1820 : os << LogIO::NORMAL << ". "
1821 0 : << vc->applyinfo()
1822 0 : << LogIO::POST;
1823 :
1824 0 : } catch (AipsError x) {
1825 : os << LogIO::SEVERE << x.getMesg()
1826 : << " Check inputs and try again."
1827 0 : << LogIO::POST;
1828 0 : if (vc) delete vc;
1829 0 : throw(AipsError("Error in Simulator::setapply."));
1830 : return false;
1831 0 : }
1832 :
1833 : // Creation apparently successful, so add to the apply list
1834 : // TBD: consolidate with above?
1835 : try {
1836 :
1837 0 : uInt napp=vc_p.nelements();
1838 0 : vc_p.resize(napp+1,false,true);
1839 0 : vc_p[napp] = vc;
1840 0 : vc=NULL;
1841 :
1842 : // Maintain sort of apply list
1843 0 : ve_p.setapply(vc_p);
1844 :
1845 0 : return true;
1846 :
1847 0 : } catch (AipsError x) {
1848 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
1849 0 : << LogIO::POST;
1850 0 : if (vc) delete vc;
1851 0 : throw(AipsError("Error in Simulator::setapply."));
1852 : return false;
1853 0 : }
1854 : return false;
1855 0 : }
1856 :
1857 :
1858 :
1859 :
1860 :
1861 :
1862 : // Bool Simulator::corrupt() {
1863 0 : Bool Simulator::corrupt() {
1864 :
1865 : // VIS-plane (only) corruption
1866 :
1867 0 : LogIO os(LogOrigin("Simulator", "corrupt()", WHERE));
1868 :
1869 : try {
1870 :
1871 0 : ms_p->lock();
1872 0 : if(mssel_p) mssel_p->lock();
1873 :
1874 : // makeVisSet();
1875 : // AlwaysAssert(vs_p, AipsError);
1876 :
1877 : // Arrange the sort for efficient cal apply (different from sort order
1878 : // created by makeVisSet) and if there's a vs_p delete it and replace with
1879 : // this one. also delete it at the end of this routine
1880 0 : Block<Int> columns;
1881 : // include scan iteration
1882 0 : columns.resize(5);
1883 0 : columns[0]=MS::ARRAY_ID;
1884 0 : columns[1]=MS::SCAN_NUMBER;
1885 0 : columns[2]=MS::FIELD_ID;
1886 0 : columns[3]=MS::DATA_DESC_ID;
1887 0 : columns[4]=MS::TIME;
1888 :
1889 0 : if(vs_p) {
1890 0 : delete vs_p; vs_p=0;
1891 : }
1892 0 : Matrix<Int> noselection;
1893 0 : if(mssel_p) {
1894 0 : vs_p = new VisSet(*mssel_p,columns,noselection);
1895 : }
1896 : else {
1897 0 : vs_p = new VisSet(*ms_p,columns,noselection);
1898 : }
1899 0 : AlwaysAssert(vs_p, AipsError);
1900 :
1901 : // initCalSet() happens in VS creation unless there is a stored channel selection
1902 : // in the ms, and it equals the channel selection passed from here in mssel_p
1903 : // vs_p->initCalSet();
1904 :
1905 0 : VisIter& vi=vs_p->iter();
1906 0 : VisBuffer vb(vi);
1907 :
1908 : // Ensure VisEquation is ready - this sorts the VCs
1909 : // if we want a different order for corruption we will either need to
1910 : // implement the sort here or create a VE::setcorrupt(vc_p)
1911 0 : ve_p.setapply(vc_p);
1912 :
1913 : // set to corrupt Model down to B (T,D,G,etc) and correct Observed with AN,M,K
1914 0 : ve_p.setPivot(VisCal::B);
1915 :
1916 : // Apply
1917 0 : if (vc_p.nelements()>0) {
1918 : os << LogIO::NORMAL << "Doing visibility corruption."
1919 0 : << LogIO::POST;
1920 0 : for (uInt i=0;i<vc_p.nelements();i++) {
1921 : // os << vc_p[i]->longTypeName() << endl << vc_p[i]->siminfo() << endl <<
1922 : // "spwok = " << vc_p[i]->spwOK() << LogIO::POST;
1923 0 : os << vc_p[i]->siminfo() << "spwok = " << vc_p[i]->spwOK();
1924 0 : if (vc_p[i]->type() >= ve_p.pivot())
1925 0 : os << " in corrupt mode." << endl << LogIO::POST;
1926 : else
1927 0 : os << " in correct mode." << endl << LogIO::POST;
1928 : }
1929 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
1930 : // Only if
1931 0 : if (ve_p.spwOK(vi.spectralWindow())) {
1932 0 : for (vi.origin(); vi.more(); vi++) {
1933 :
1934 : // corrupt model to pivot, correct data up to pivot
1935 0 : ve_p.collapseForSim(vb);
1936 :
1937 : // Deposit corrupted visibilities into DATA
1938 : // vi.setVis(vb.modelVisCube(), VisibilityIterator::Observed);
1939 0 : vi.setVis(vb.visCube(), VisibilityIterator::Observed);
1940 : // for now, Also deposit in corrected
1941 : // (until newmmssimulator doesn't make corrected anymore)
1942 : // actually we should have this check if corrected is there,
1943 : // and if it is for some reason, copy data into it.
1944 : // RI TODO Sim::corrupt check for existence of Corrected
1945 0 : vi.setVis(vb.visCube(), VisibilityIterator::Corrected);
1946 :
1947 : // RI TODO is this 100% right?
1948 0 : vi.setWeightMat(vb.weightMat());
1949 :
1950 : }
1951 : }
1952 : else
1953 0 : cout << "Encountered data spw " << vi.spectralWindow() << " for which there is no (simulated) calibration." << endl;
1954 : }
1955 : }
1956 :
1957 :
1958 : // Old-fashioned noise, for now
1959 0 : if(ac_p != NULL){
1960 : // os << LogIO::WARN << "Using deprecated ACoh Noise - this will dissapear in the future - please switch to sm.setnoise" << LogIO::POST;
1961 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
1962 0 : for (vi.origin(); vi.more(); vi++) {
1963 :
1964 : // affects vb.visibility() i.e. Observed
1965 0 : ac_p->apply(vb);
1966 0 : vi.setVis(vb.visibility(), VisibilityIterator::Observed);
1967 0 : vi.setVis(vb.visibility(), VisibilityIterator::Corrected);
1968 : }
1969 : }
1970 : }
1971 :
1972 : // Flush to disk
1973 0 : vs_p->flush();
1974 :
1975 : // since we made a specially sorted vs_p for corrupt, should we delete it
1976 : // and make one with the regular order?
1977 : // if(vs_p) {
1978 : // delete vs_p; vs_p=0;
1979 : // makeVisSet()
1980 : // }
1981 :
1982 0 : ms_p->relinquishAutoLocks();
1983 0 : ms_p->unlock();
1984 0 : if(mssel_p) mssel_p->unlock();
1985 :
1986 0 : } catch (std::exception& x) {
1987 0 : ms_p->relinquishAutoLocks();
1988 0 : ms_p->unlock();
1989 0 : if(mssel_p) mssel_p->unlock();
1990 0 : throw(AipsError(x.what()));
1991 : return false;
1992 0 : }
1993 0 : return true;
1994 0 : }
1995 :
1996 :
1997 :
1998 :
1999 :
2000 :
2001 :
2002 :
2003 :
2004 :
2005 :
2006 :
2007 :
2008 :
2009 :
2010 :
2011 :
2012 :
2013 :
2014 :
2015 2 : Bool Simulator::observe(const String& sourcename,
2016 : const String& spwname,
2017 : const Quantity& startTime,
2018 : const Quantity& stopTime,
2019 : const Bool add_observation,
2020 : const Bool state_sig,
2021 : const Bool state_ref,
2022 : const double& state_cal,
2023 : const double& state_load,
2024 : const unsigned int state_sub_scan,
2025 : const String& state_obs_mode,
2026 : const String& observername,
2027 : const String& projectname)
2028 : {
2029 4 : LogIO os(LogOrigin("Simulator", "observe()", WHERE));
2030 :
2031 :
2032 : try {
2033 :
2034 2 : if(!feedsHaveBeenSet && !feedsInitialized) {
2035 0 : os << "Feeds have not been set - using default " << feedMode_p << LogIO::WARN;
2036 0 : sim_p->initFeeds(feedMode_p);
2037 0 : feedsInitialized = true;
2038 : }
2039 2 : if(!timesHaveBeenSet_p) {
2040 : os << "Times have not been set - using defaults " << endl
2041 : << " Times will be interpreted as hour angles for first source"
2042 0 : << LogIO::WARN;
2043 : }
2044 :
2045 2 : sim_p->observe(sourcename, spwname, startTime, stopTime,
2046 : add_observation, state_sig, state_ref, state_cal,state_load,state_sub_scan,state_obs_mode,observername,projectname);
2047 :
2048 :
2049 2 : if(ms_p) delete ms_p; ms_p=0;
2050 2 : if(mssel_p) delete mssel_p; mssel_p=0;
2051 4 : ms_p = new MeasurementSet(msname_p,
2052 2 : TableLock(TableLock::AutoNoReadLocking),
2053 2 : Table::Update);
2054 :
2055 2 : ms_p->flush();
2056 2 : ms_p->unlock();
2057 :
2058 0 : } catch (AipsError x) {
2059 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
2060 0 : return false;
2061 0 : }
2062 2 : return true;
2063 2 : }
2064 :
2065 :
2066 :
2067 :
2068 0 : Bool Simulator::observemany(const Vector<String>& sourcenames,
2069 : const String& spwname,
2070 : const Vector<Quantity>& startTimes,
2071 : const Vector<Quantity>& stopTimes,
2072 : const Vector<MDirection>& directions,
2073 : const Bool add_observation=true,
2074 : const Bool state_sig=true,
2075 : const Bool state_ref=true,
2076 : const double& state_cal=0.,
2077 : const double& state_load=0.,
2078 : const unsigned int state_sub_scan=0,
2079 : const String& state_obs_mode="OBSERVE_TARGET#ON_SOURCE",
2080 : const String& observername="CASA simulator",
2081 : const String& projectname="CASA simulation")
2082 : {
2083 0 : LogIO os(LogOrigin("Simulator", "observemany()", WHERE));
2084 :
2085 :
2086 : try {
2087 :
2088 0 : if(!feedsHaveBeenSet && !feedsInitialized) {
2089 0 : os << "Feeds have not been set - using default " << feedMode_p << LogIO::WARN;
2090 0 : sim_p->initFeeds(feedMode_p);
2091 0 : feedsInitialized = true;
2092 : }
2093 0 : if(!timesHaveBeenSet_p) {
2094 : os << "Times have not been set - using defaults " << endl
2095 : << " Times will be interpreted as hour angles for first source"
2096 0 : << LogIO::WARN;
2097 : }
2098 :
2099 0 : sim_p->observe(sourcenames, spwname, startTimes, stopTimes, directions,
2100 : add_observation, state_sig, state_ref, state_cal,state_load,state_sub_scan,state_obs_mode,observername,projectname);
2101 :
2102 0 : if(ms_p) delete ms_p; ms_p=0;
2103 0 : if(mssel_p) delete mssel_p; mssel_p=0;
2104 0 : ms_p = new MeasurementSet(msname_p,
2105 0 : TableLock(TableLock::AutoNoReadLocking),
2106 0 : Table::Update);
2107 :
2108 0 : ms_p->flush();
2109 0 : ms_p->unlock();
2110 :
2111 0 : } catch (AipsError x) {
2112 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
2113 0 : return false;
2114 0 : }
2115 0 : return true;
2116 0 : }
2117 :
2118 :
2119 :
2120 :
2121 :
2122 :
2123 0 : Bool Simulator::predict(const Vector<String>& modelImage,
2124 : const String& compList,
2125 : const Bool incremental) {
2126 :
2127 0 : LogIO os(LogOrigin("Simulator", "predict()", WHERE));
2128 :
2129 : // Note that incremental here does not apply to se_p->predict(false),
2130 : // Rather it means: add the calculated model visibility to the data visibility.
2131 : // We return a MS with Data, Model, and Corrected columns identical
2132 :
2133 : try {
2134 :
2135 : os << "Predicting visibilities using model: " << modelImage <<
2136 0 : " and componentList: " << compList << LogIO::POST;
2137 0 : if (incremental) {
2138 0 : os << "The data column will be incremented" << LogIO::POST;
2139 : } else {
2140 0 : os << "The data column will be replaced" << LogIO::POST;
2141 : }
2142 0 : if(!ms_p) {
2143 : os << "MeasurementSet pointer is null : logic problem!"
2144 0 : << LogIO::EXCEPTION;
2145 : }
2146 :
2147 0 : bool heterogeneous=False;
2148 0 : for (uInt i=1;i<diam_p.nelements();i++)
2149 0 : if (diam_p(i)!=diam_p(0)) heterogeneous=True;
2150 0 : if (heterogeneous) {
2151 0 : if (compList!=String("")) {
2152 0 : os<<"Heterogeneous array is not supported for simulation from components. Primary beam will be applied by telescope name.\n"<<LogIO::WARN;
2153 : }
2154 0 : if ((modelImage[0]!=String(""))&&(ftmachine_p!="mosaic")) {
2155 0 : os<<"Heterogeneous array is only supported for ALMA,ACA,OVRO telescopes, and only with option ftmachine=mosaic."<<LogIO::WARN;
2156 : }
2157 : }
2158 :
2159 0 : ms_p->lock();
2160 0 : if(mssel_p) mssel_p->lock();
2161 0 : if (!createSkyEquation( modelImage, compList)) {
2162 0 : os << LogIO::SEVERE << "Failed to create SkyEquation" << LogIO::POST;
2163 0 : return false;
2164 : }
2165 0 : if (incremental) {
2166 0 : se_p->predict(false,MS::MODEL_DATA);
2167 : } else {
2168 0 : se_p->predict(false,MS::DATA); //20091030 RI changed SE::predict to use DATA
2169 : }
2170 0 : destroySkyEquation();
2171 :
2172 : // Copy the predicted visibilities over to the observed and
2173 : // the corrected data columns
2174 0 : makeVisSet();
2175 :
2176 0 : VisIter& vi = vs_p->iter();
2177 0 : VisBuffer vb(vi);
2178 0 : vi.origin();
2179 0 : vi.originChunks();
2180 :
2181 : //os << "Copying predicted visibilities from MODEL_DATA to DATA and CORRECTED_DATA" << LogIO::POST;
2182 :
2183 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()){
2184 0 : for (vi.origin(); vi.more(); vi++) {
2185 : // vb.setVisCube(vb.modelVisCube());
2186 :
2187 0 : if (incremental) {
2188 0 : vi.setVis( (vb.modelVisCube() + vb.visCube()),
2189 : VisibilityIterator::Corrected);
2190 0 : vi.setVis(vb.correctedVisCube(),VisibilityIterator::Observed);
2191 :
2192 : // model=1 is more consistent with VS::initCalSet
2193 : // vi.setVis(vb.correctedVisCube(),VisibilityIterator::Model);
2194 : } else {
2195 : // from above, the prediction is now already in Observed.
2196 : // RI TODO remove scratch columns from NewMSSimulator;
2197 : // until then we;ll just leave them 1 and Corr=Obs (for imaging)
2198 : //vi.setVis(vb.visCube(),VisibilityIterator::Observed);
2199 0 : vi.setVis(vb.visCube(),VisibilityIterator::Corrected);
2200 : }
2201 0 : vb.setModelVisCube(Complex(1.0,0.0));
2202 0 : vi.setVis(vb.modelVisCube(),VisibilityIterator::Model);
2203 : }
2204 : }
2205 0 : ms_p->unlock();
2206 0 : if(mssel_p) mssel_p->lock();
2207 :
2208 0 : } catch (AipsError x) {
2209 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
2210 0 : ms_p->unlock();
2211 0 : if(mssel_p) mssel_p->lock();
2212 0 : return false;
2213 0 : }
2214 0 : return true;
2215 0 : }
2216 :
2217 :
2218 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2219 : // copied from SynthesisImager
2220 0 : void Simulator::getVPRecord(Record &rec, PBMath::CommonPB &kpb, String telescop)
2221 : {
2222 0 : LogIO os(LogOrigin("Simulator", "getVPRecord",WHERE));
2223 :
2224 0 : VPManager *vpman=VPManager::Instance();
2225 0 : if ((doDefaultVP_p)||(vpTableStr_p != String(""))) {
2226 0 : if (doDefaultVP_p) {
2227 0 : os << "Using default Voltage Patterns from the VPManager" << LogIO::POST;
2228 0 : vpman->reset();
2229 : } else {
2230 0 : os << "Loading Voltage Pattern information from " << vpTableStr_p << LogIO::POST;
2231 0 : vpman->loadfromtable(vpTableStr_p );
2232 : }
2233 0 : os << "Temporary alert : The state of the vpmanager tool has been modified by loading these primary beam models. If any of your scripts rely on the vpmanager state being preserved throughout your CASA session, please use vp.saveastable() and vp.loadfromtable() as needed. "<< LogIO::POST;
2234 : }
2235 : // if dodefault=false, and no table is provided, it will used what is in
2236 : // the vpmanager already.
2237 : else {
2238 0 : os << "Using Voltage Patterns from the VPManager" << LogIO::POST;
2239 : }
2240 :
2241 : // PBMath::CommonPB kpb;
2242 0 : PBMath::enumerateCommonPB(telescop, kpb);
2243 : // Record rec;
2244 0 : vpman->getvp(rec, telescop);
2245 :
2246 : //ostringstream oss; rec.print(oss);
2247 : //os << "Using VP model : " << oss.str() << LogIO::POST;
2248 :
2249 0 : if(rec.empty()){
2250 0 : if((telescop=="EVLA")){
2251 0 : os << LogIO::WARN << "vpmanager does not list EVLA. Using VLA beam parameters. To use EVLA beams, please use the vpmanager and set the vptable parameter in tclean (see inline help for vptable)." << LogIO::POST;
2252 0 : telescop="VLA";
2253 0 : vpman->getvp(rec, telescop);
2254 0 : kpb=PBMath::VLA;
2255 : }
2256 : else{
2257 0 : os << LogIO::WARN << "vpmanager does not have a beam for "+telescop <<".\n Please use the vpmanager to define one (and optionally save its state as a table and supply its name via the vptable parameter.)" << LogIO::POST;
2258 0 : kpb=PBMath::UNKNOWN;
2259 : }
2260 : }
2261 :
2262 0 : }// get VPRecord
2263 :
2264 :
2265 :
2266 0 : Bool Simulator::createSkyEquation(const Vector<String>& image,
2267 : const String complist)
2268 : {
2269 :
2270 0 : LogIO os(LogOrigin("Simulator", "createSkyEquation()", WHERE));
2271 :
2272 : try {
2273 0 : if(sm_p==0) {
2274 0 : sm_p = new CleanImageSkyModel();
2275 : }
2276 0 : AlwaysAssert(sm_p, AipsError);
2277 :
2278 : // Add the componentlist
2279 0 : if(complist!="") {
2280 0 : if(!Table::isReadable(complist)) {
2281 : os << LogIO::SEVERE << "ComponentList " << complist
2282 0 : << " not readable" << LogIO::POST;
2283 0 : return false;
2284 : }
2285 0 : componentList_p=new ComponentList(complist, true);
2286 0 : if(componentList_p==0) {
2287 : os << LogIO::SEVERE << "Cannot create ComponentList from " << complist
2288 0 : << LogIO::POST;
2289 0 : return false;
2290 : }
2291 0 : if(!sm_p->add(*componentList_p)) {
2292 : os << LogIO::SEVERE << "Cannot add ComponentList " << complist
2293 0 : << " to SkyModel" << LogIO::POST;
2294 0 : return false;
2295 : }
2296 : } else {
2297 0 : componentList_p=0;
2298 : }
2299 :
2300 0 : nmodels_p = image.nelements();
2301 0 : if (nmodels_p == 1 && image(0) == "") nmodels_p = 0;
2302 :
2303 0 : int models_found=0;
2304 0 : if (nmodels_p > 0) {
2305 0 : images_p.resize(nmodels_p);
2306 :
2307 0 : for (Int model=0;model<Int(nmodels_p);model++) {
2308 0 : if(image(model)=="") {
2309 : os << LogIO::SEVERE << "Need a name for model " << model+1
2310 0 : << LogIO::POST;
2311 0 : return false;
2312 : } else {
2313 0 : if(!Table::isReadable(image(model))) {
2314 0 : os << LogIO::SEVERE << image(model) << " is unreadable" << LogIO::POST;
2315 : } else {
2316 0 : images_p[model]=0;
2317 : os << "Opening model " << model << " named "
2318 0 : << image(model) << LogIO::POST;
2319 0 : images_p[model]=new PagedImage<Float>(image(model));
2320 0 : AlwaysAssert(images_p[model], AipsError);
2321 : // RI TODO is this a logic problem with more than one source??
2322 : // Add distance
2323 0 : if((distance_p.nelements() > 0 && distance_p.nelements() <= static_cast<uInt>(nField)) && abs(distance_p[nField-1].get().getValue())>0.0) {
2324 0 : os << " Refocusing to distance " << distance_p[nField-1].get("km").getValue()
2325 0 : << " km" << LogIO::POST;
2326 0 : Record info(images_p[model]->miscInfo());
2327 0 : info.define("distance", distance_p[nField-1].get("m").getValue());
2328 0 : images_p[model]->setMiscInfo(info);
2329 0 : }
2330 :
2331 : // FTMachine only works in Hz and LSRK
2332 0 : CoordinateSystem cs = images_p[model]->coordinates();
2333 0 : String errorMsg;
2334 0 : cs.setSpectralConversion(errorMsg,MFrequency::showType(MFrequency::LSRK));
2335 0 : Int spectralIndex=cs.findCoordinate(Coordinate::SPECTRAL);
2336 0 : AlwaysAssert(spectralIndex>=0, AipsError);
2337 0 : SpectralCoordinate spectralCoord=cs.spectralCoordinate(spectralIndex);
2338 0 : Vector<String> units(1); units = "Hz";
2339 : // doesn't work: cs.spectralCoordinate(spectralIndex).setWorldAxisUnits(units);
2340 0 : spectralCoord.setWorldAxisUnits(units);
2341 : // put spectralCoord back into cs
2342 0 : cs.replaceCoordinate(spectralCoord,spectralIndex);
2343 : // and cs into image
2344 0 : images_p[model]->setCoordinateInfo(cs);
2345 :
2346 :
2347 0 : if(sm_p->add(*images_p[model])!=model) {
2348 0 : os << LogIO::SEVERE << "Error adding model " << model << LogIO::POST;
2349 0 : return false;
2350 : }
2351 0 : models_found++;
2352 0 : }
2353 : }
2354 : }
2355 : }
2356 :
2357 0 : if(models_found<=0 and componentList_p==0) {
2358 0 : os << LogIO::SEVERE << "No model images found" << LogIO::POST;
2359 0 : return false;
2360 : }
2361 :
2362 :
2363 :
2364 0 : if(vs_p) {
2365 0 : delete vs_p; vs_p=0;
2366 : }
2367 0 : makeVisSet();
2368 :
2369 0 : cft_p = new SimpleComponentFTMachine();
2370 :
2371 0 : MeasurementSet *ams=0;
2372 :
2373 0 : if(mssel_p) {
2374 0 : ams=mssel_p;
2375 : }
2376 : else {
2377 0 : ams=ms_p;
2378 : }
2379 : // 2016 from SynthesisImager:
2380 0 : MSColumns msc(*ams);
2381 0 : String telescop=msc.observation().telescopeName()(0);
2382 : PBMath::CommonPB kpb;
2383 0 : Record rec;
2384 0 : getVPRecord( rec, kpb, telescop );
2385 :
2386 0 : if((ftmachine_p=="sd")||(ftmachine_p=="both")||(ftmachine_p=="mosaic")) {
2387 0 : if(!gvp_p) {
2388 0 : if (rec.asString("name")=="COMMONPB" && kpb !=PBMath::UNKNOWN ){
2389 0 : String commonPBName;
2390 0 : PBMath::nameCommonPB(kpb, commonPBName);
2391 0 : os << "Using common PB "<<commonPBName<<" for beam calculation for telescope " << telescop << LogIO::POST;
2392 0 : gvp_p=new VPSkyJones(msc, true, parAngleInc_p, squintType_p, skyPosThreshold_p);
2393 0 : }
2394 : else{
2395 0 : PBMath myPB(rec);
2396 0 : String whichPBMath;
2397 0 : PBMathInterface::namePBClass(myPB.whichPBClass(), whichPBMath);
2398 0 : os << "Using the PB defined by " << whichPBMath << " for beam calculation for telescope " << telescop << LogIO::POST;
2399 0 : gvp_p= new VPSkyJones(telescop, myPB, parAngleInc_p, squintType_p, skyPosThreshold_p);
2400 0 : kpb=PBMath::DEFAULT;
2401 0 : }
2402 : }
2403 0 : if(ftmachine_p=="sd") {
2404 0 : os << "Performing Single dish gridding " << LogIO::POST;
2405 0 : if(gridfunction_p=="pb") {
2406 0 : ft_p = new SDGrid(*gvp_p, cache_p/2, tile_p, gridfunction_p);
2407 : }
2408 : else {
2409 0 : ft_p = new SDGrid(cache_p/2, tile_p, gridfunction_p);
2410 : }
2411 : }
2412 0 : else if(ftmachine_p=="mosaic") {
2413 : // RI TODO need stokesString for current spw - e.g. currSpw()?
2414 0 : os << "Performing Mosaic gridding for model images (uv convolution)" << LogIO::POST;
2415 : //2016 from SynthesisImager:
2416 0 : ft_p = new MosaicFTNew(gvp_p, mLocation_p, stokesString_p[0], cache_p/2, tile_p, true);
2417 0 : PBMathInterface::PBClass pbtype=PBMathInterface::AIRY;
2418 0 : if(rec.asString("name")=="IMAGE")
2419 0 : pbtype=PBMathInterface::IMAGE;
2420 : ///Use Heterogenous array mode for the following
2421 0 : if((kpb == PBMath::UNKNOWN) || (kpb==PBMath::OVRO) || (kpb==PBMath::ACA)
2422 0 : || (kpb==PBMath::ALMA)){
2423 0 : String PBName;
2424 0 : PBMath::nameCommonPB(kpb,PBName);
2425 0 : os << "Enabling Heterogeneous Array for PBMath "<<PBName<<LogIO::POST;
2426 : // Will use Airys - to do something more complex we need to
2427 : // use HetArrayConvFunv::fromRecord
2428 0 : if ((kpb==PBMath::ACA) || (kpb==PBMath::ALMA)) {
2429 0 : os << "For model images, will use 10.7m Airy PB for diameter=12 dishes, and 6.25m Airy PB for diameter=7 dishes." << LogIO::POST;
2430 : } else {
2431 0 : os << "For model images, will use Airy PB scaled to dish diameter."<<LogIO::POST;
2432 : }
2433 0 : CountedPtr<SimplePBConvFunc> mospb=new HetArrayConvFunc(pbtype, "");
2434 0 : static_cast<MosaicFTNew &>(*ft_p).setConvFunc(mospb);
2435 0 : }
2436 : //gvp_p->summary();
2437 : ///2016
2438 : }
2439 0 : else if(ftmachine_p=="both") {
2440 : os << "Performing single dish gridding with convolution function "
2441 0 : << gridfunction_p << LogIO::POST;
2442 : os << "and interferometric gridding with convolution function SF"
2443 0 : << LogIO::POST;
2444 :
2445 0 : ft_p = new GridBoth(*gvp_p, cache_p/2, tile_p,
2446 0 : mLocation_p,
2447 0 : gridfunction_p, "SF", padding_p);
2448 : }
2449 :
2450 0 : VisIter& vi(vs_p->iter());
2451 : // Get bigger chunks o'data: this should be tuned some time
2452 : // since it may be wrong for e.g. spectral line
2453 0 : vi.setRowBlocking(100);
2454 : }
2455 :
2456 : else {
2457 0 : os << "Synthesis gridding " << LogIO::POST;
2458 : // Now make the FTMachine
2459 : // if(wprojPlanes_p>1) {
2460 0 : if (ftmachine_p=="wproject") {
2461 0 : os << "Fourier transforms will use specified common tangent point:" << LogIO::POST;
2462 : // RI TODO how does this work with more than one field?
2463 0 : os << formatDirection(sourceDirection_p[nField-1]) << LogIO::POST;
2464 : // ft_p = new WProjectFT(*ams, facets_p, cache_p/2, tile_p, false);
2465 0 : ft_p = new WProjectFT(wprojPlanes_p, mLocation_p, cache_p/2, tile_p, false);
2466 : }
2467 0 : else if (ftmachine_p=="pbwproject") {
2468 : os << "Fourier transforms will use specified common tangent point and PBs"
2469 0 : << LogIO::POST;
2470 0 : os << formatDirection(sourceDirection_p[nField-1]) << LogIO::POST;
2471 :
2472 : // if (!epJ_p)
2473 : os << "Antenna pointing related term (EPJones) not set. "
2474 : << "This is required when using pbwproject FTMachine."
2475 : << "(gmoellen 06Nov20: pointing errors temporarily disabled)"
2476 0 : << LogIO::EXCEPTION;
2477 :
2478 : /*
2479 : doVP_p = false; // Since this FTMachine includes PB
2480 : if (wprojPlanes_p<=1)
2481 : {
2482 : os << LogIO::NORMAL
2483 : << "You are using wprojplanes=1. Doing co-planar imaging "
2484 : << "(no w-projection needed)"
2485 : << LogIO::POST;
2486 : os << "Performing pb-projection"
2487 : << LogIO::POST;
2488 : }
2489 : if((wprojPlanes_p>1)&&(wprojPlanes_p<64))
2490 : {
2491 : os << LogIO::WARN
2492 : << "No. of w-planes set too low for W projection - recommend at least 128"
2493 : << LogIO::POST;
2494 : os << "Performing pb + w-plane projection"
2495 : << LogIO::POST;
2496 : }
2497 : // epJ_p = new EPJones(*vs_p);
2498 : // epJ_p->load(epJTableName_p,"","diagonal");
2499 : if(!gvp_p)
2500 : {
2501 : os << "Using defaults for primary beams used in gridding" << LogIO::POST;
2502 : gvp_p=new VPSkyJones(*ms_p, true, parAngleInc_p, squintType_p);
2503 : }
2504 : // ft_p = new PBWProjectFT(*ms_p, epJ, gvp_p, facets_p, cache_p/2,
2505 : // doPointing, tile_p, paStep_p,
2506 : // pbLimit_p, true);
2507 :
2508 : String cfCacheDirName = "cache";
2509 : if (mssel_p)
2510 : ft_p = new PBWProjectFT(*mssel_p, epJ_p,
2511 : // gvp_p,
2512 : wprojPlanes_p, cache_p/2,
2513 : cfCacheDirName,
2514 : applyPointingOffsets_p, doPBCorrection_p,
2515 : tile_p,
2516 : 0.0, // Not required here. parAngleInc_p is used in gvp_p
2517 : pbLimit_p, true);
2518 : else
2519 : ft_p = new PBWProjectFT(*ms_p, epJ_p,
2520 : // gvp_p,
2521 : wprojPlanes_p, cache_p/2,
2522 : cfCacheDirName,
2523 : applyPointingOffsets_p, doPBCorrection_p,
2524 : tile_p,
2525 : 0.0, // Not required here. parAngleInc_p is used in gvp_p
2526 : pbLimit_p, true);
2527 : AlwaysAssert(ft_p, AipsError);
2528 : cft_p = new SimpleComponentFTMachine();
2529 : AlwaysAssert(cft_p, AipsError);
2530 :
2531 : */
2532 : }
2533 : else {
2534 0 : os << "Fourier transforms will use image centers as tangent points" << LogIO::POST;
2535 0 : ft_p = new GridFT(cache_p/2, tile_p, gridfunction_p, mLocation_p, padding_p);
2536 : }
2537 : }
2538 0 : AlwaysAssert(ft_p, AipsError);
2539 :
2540 : // tell ftmachine about the transformations in model images above - no.
2541 : //Vector<Int> dataspectralwindowids_p;
2542 : //Bool freqFrameValid_p = true;
2543 : //ft_p->setSpw(dataspectralwindowids_p, freqFrameValid_p);
2544 :
2545 0 : se_p = new SkyEquation ( *sm_p, *vs_p, *ft_p, *cft_p );
2546 :
2547 : // Now add any SkyJones that are needed
2548 : // (vp_p is not applied to images if ftmachine=mosaic)
2549 0 : if(doVP_p) {
2550 0 : if (rec.asString("name")=="COMMONPB" && kpb !=PBMath::UNKNOWN ){
2551 : // String commonPBName;
2552 : // PBMath::nameCommonPB(kpb, commonPBName);
2553 : // os << "SkyEquation using common PB "<<commonPBName<<" for beam calculation for telescope " << telescop << LogIO::POST;
2554 0 : vp_p=new VPSkyJones(msc, true, parAngleInc_p, squintType_p, skyPosThreshold_p);
2555 : } else {
2556 0 : PBMath myPB(rec);
2557 : // String whichPBMath;
2558 : // PBMathInterface::namePBClass(myPB.whichPBClass(), whichPBMath);
2559 : // os << "SkyEquation using the PB defined by " << whichPBMath << " for beam calculation for telescope " << telescop << LogIO::POST;
2560 0 : vp_p= new VPSkyJones(telescop, myPB, parAngleInc_p, squintType_p, skyPosThreshold_p);
2561 0 : kpb=PBMath::DEFAULT;
2562 0 : }
2563 0 : vp_p->summary();
2564 0 : se_p->setSkyJones(*vp_p);
2565 : } else {
2566 0 : vp_p=0;
2567 : }
2568 0 : } catch (AipsError x) {
2569 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
2570 0 : ms_p->unlock();
2571 0 : if(mssel_p) mssel_p->lock();
2572 0 : return false;
2573 0 : }
2574 0 : return true;
2575 0 : };
2576 :
2577 0 : void Simulator::destroySkyEquation()
2578 : {
2579 0 : if(se_p) delete se_p; se_p=0;
2580 0 : if(sm_p) delete sm_p; sm_p=0;
2581 0 : if(vp_p) delete vp_p; vp_p=0;
2582 0 : if(componentList_p) delete componentList_p; componentList_p=0;
2583 :
2584 0 : for (Int model=0;model<Int(nmodels_p);model++) {
2585 0 : if(images_p[model]) delete images_p[model]; images_p[model]=0;
2586 : }
2587 0 : };
2588 :
2589 :
2590 :
2591 :
2592 :
2593 :
2594 :
2595 :
2596 :
2597 :
2598 :
2599 :
2600 :
2601 :
2602 2 : Bool Simulator::setlimits(const Double shadowLimit,
2603 : const Quantity& elevationLimit)
2604 : {
2605 :
2606 4 : LogIO os(LogOrigin("Simulator", "setlimits()", WHERE));
2607 :
2608 : try {
2609 :
2610 2 : sim_p->setFractionBlockageLimit( shadowLimit );
2611 2 : sim_p->setElevationLimit( elevationLimit );
2612 0 : } catch (AipsError x) {
2613 0 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
2614 0 : return false;
2615 0 : }
2616 2 : return true;
2617 2 : }
2618 :
2619 2 : Bool Simulator::setauto(const Double autocorrwt)
2620 : {
2621 :
2622 4 : LogIO os(LogOrigin("Simulator", "setauto()", WHERE));
2623 :
2624 : try {
2625 :
2626 2 : sim_p->setAutoCorrelationWt(autocorrwt);
2627 :
2628 : } catch (AipsError x) {
2629 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
2630 : return false;
2631 : }
2632 2 : return true;
2633 2 : }
2634 :
2635 0 : void Simulator::makeVisSet() {
2636 :
2637 0 : if(vs_p) return;
2638 :
2639 0 : Block<int> sort(0);
2640 0 : sort.resize(5);
2641 0 : sort[0] = MS::FIELD_ID;
2642 0 : sort[1] = MS::FEED1;
2643 0 : sort[2] = MS::ARRAY_ID;
2644 0 : sort[3] = MS::DATA_DESC_ID;
2645 0 : sort[4] = MS::TIME;
2646 0 : Matrix<Int> noselection;
2647 0 : if(mssel_p) {
2648 0 : vs_p = new VisSet(*mssel_p,sort,noselection);
2649 : }
2650 : else {
2651 0 : if (ms_p)
2652 0 : vs_p = new VisSet(*ms_p,sort,noselection);
2653 : else
2654 0 : throw(AipsError("No measurement set open in Simulator."));
2655 : }
2656 0 : AlwaysAssert(vs_p, AipsError);
2657 :
2658 0 : }
2659 :
2660 :
2661 :
2662 0 : Bool Simulator::setoptions(const String& ftmachine, const Int cache, const Int tile,
2663 : const String& gridfunction, const MPosition& mLocation,
2664 : const Float padding, const Int facets, const Double maxData,
2665 : const Int wprojPlanes)
2666 : {
2667 0 : LogIO os(LogOrigin("Simulator", "setoptions()", WHERE));
2668 :
2669 0 : os << "Setting processing options" << LogIO::POST;
2670 :
2671 0 : sim_p->setMaxData(maxData*1024.0*1024.0);
2672 :
2673 0 : ftmachine_p=downcase(ftmachine);
2674 0 : if(cache>0) cache_p=cache;
2675 0 : if(tile>0) tile_p=tile;
2676 0 : gridfunction_p=downcase(gridfunction);
2677 0 : mLocation_p=mLocation;
2678 0 : if(padding>=1.0) {
2679 0 : padding_p=padding;
2680 : }
2681 0 : facets_p=facets;
2682 0 : wprojPlanes_p = wprojPlanes;
2683 : // Destroy the FTMachine
2684 0 : if(ft_p) {delete ft_p; ft_p=0;}
2685 0 : if(cft_p) {delete cft_p; cft_p=0;}
2686 :
2687 0 : return true;
2688 0 : }
2689 :
2690 :
2691 0 : Bool Simulator::detached() const
2692 : {
2693 0 : return false;
2694 : }
2695 :
2696 0 : String Simulator::formatDirection(const MDirection& direction) {
2697 0 : MVAngle mvRa=direction.getAngle().getValue()(0);
2698 0 : MVAngle mvDec=direction.getAngle().getValue()(1);
2699 0 : ostringstream oss;
2700 0 : oss.setf(ios::left, ios::adjustfield);
2701 0 : oss.width(14);
2702 0 : oss << mvRa(0.0).string(MVAngle::TIME,8);
2703 0 : oss.width(14);
2704 0 : oss << mvDec.string(MVAngle::DIG2,8);
2705 0 : oss << " " << MDirection::showType(direction.getRefPtr()->getType());
2706 0 : return String(oss);
2707 0 : }
2708 :
2709 0 : String Simulator::formatTime(const Double time) {
2710 0 : MVTime mvtime(Quantity(time, "s"));
2711 0 : return mvtime.string(MVTime::DMY,7);
2712 0 : }
2713 :
2714 :
2715 :
2716 0 : Bool Simulator::setdata(const Vector<Int>& spectralwindowids,
2717 : const Vector<Int>& fieldids,
2718 : const String& msSelect)
2719 :
2720 : {
2721 :
2722 :
2723 0 : LogIO os(LogOrigin("Simulator", "setdata()", WHERE));
2724 :
2725 0 : if(!ms_p) {
2726 : os << LogIO::SEVERE << "Program logic error: MeasurementSet pointer ms_p not yet set"
2727 0 : << LogIO::POST;
2728 0 : return false;
2729 : }
2730 :
2731 : try {
2732 :
2733 0 : os << "Selecting data" << LogIO::POST;
2734 :
2735 : // Map the selected spectral window ids to data description ids
2736 0 : MSDataDescColumns dataDescCol(ms_p->dataDescription());
2737 0 : Vector<Int> ddSpwIds=dataDescCol.spectralWindowId().getColumn();
2738 :
2739 0 : Vector<Int> datadescids(0);
2740 0 : for (uInt row=0; row<ddSpwIds.nelements(); row++) {
2741 0 : Bool found=false;
2742 0 : for (uInt j=0; j<spectralwindowids.nelements(); j++) {
2743 0 : if (ddSpwIds(row)==spectralwindowids(j)) found=true;
2744 : };
2745 0 : if (found) {
2746 0 : datadescids.resize(datadescids.nelements()+1,true);
2747 0 : datadescids(datadescids.nelements()-1)=row;
2748 : };
2749 : };
2750 :
2751 0 : if(vs_p) delete vs_p; vs_p=0;
2752 0 : if(mssel_p) delete mssel_p; mssel_p=0;
2753 :
2754 : // If a selection has been made then close the current MS
2755 : // and attach to a new selected MS. We do this on the original
2756 : // MS.
2757 0 : if(fieldids.nelements()>0||datadescids.nelements()>0) {
2758 0 : os << "Performing selection on MeasurementSet" << LogIO::POST;
2759 0 : Table& original=*ms_p;
2760 :
2761 : // Now we make a condition to do the old FIELD_ID, SPECTRAL_WINDOW_ID
2762 : // selection
2763 0 : TableExprNode condition;
2764 0 : String colf=MS::columnName(MS::FIELD_ID);
2765 0 : String cols=MS::columnName(MS::DATA_DESC_ID);
2766 0 : if(fieldids.nelements()>0&&datadescids.nelements()>0){
2767 0 : condition=original.col(colf).in(fieldids)&&original.col(cols).in(datadescids);
2768 0 : os << "Selecting on field and spectral window ids" << LogIO::POST;
2769 : }
2770 0 : else if(datadescids.nelements()>0) {
2771 0 : condition=original.col(cols).in(datadescids);
2772 0 : os << "Selecting on spectral window id" << LogIO::POST;
2773 : }
2774 0 : else if(fieldids.nelements()>0) {
2775 0 : condition=original.col(colf).in(fieldids);
2776 0 : os << "Selecting on field id" << LogIO::POST;
2777 : }
2778 :
2779 : // Now remake the original ms
2780 0 : mssel_p = new MeasurementSet(original(condition));
2781 :
2782 : //AlwaysAssert(mssel_p, AipsError);
2783 : //mssel_p->rename(msname_p+"/SELECTED_TABLE", Table::Scratch);
2784 0 : if(mssel_p->nrow()==0) {
2785 0 : delete mssel_p; mssel_p=0;
2786 : os << LogIO::WARN
2787 : << "Selection is empty: reverting to original MeasurementSet"
2788 0 : << LogIO::POST;
2789 0 : mssel_p=new MeasurementSet(original);
2790 : }
2791 : else {
2792 0 : mssel_p->flush();
2793 : }
2794 :
2795 0 : }
2796 : else {
2797 0 : mssel_p=new MeasurementSet(*ms_p);
2798 : }
2799 : {
2800 0 : Int len = msSelect.length();
2801 0 : Int nspace = msSelect.freq (' ');
2802 0 : Bool nullSelect=(msSelect.empty() || nspace==len);
2803 0 : if (!nullSelect) {
2804 0 : os << "Now applying selection string " << msSelect << LogIO::POST;
2805 : MeasurementSet* mssel_p2;
2806 : // Apply the TAQL selection string, to remake the original MS
2807 0 : String parseString="select from $1 where " + msSelect;
2808 0 : mssel_p2=new MeasurementSet(tableCommand(parseString,*mssel_p).table());
2809 0 : AlwaysAssert(mssel_p2, AipsError);
2810 : // Rename the selected MS as */SELECTED_TABLE2
2811 : //mssel_p2->rename(msname_p+"/SELECTED_TABLE2", Table::Scratch);
2812 0 : if (mssel_p2->nrow()==0) {
2813 : os << LogIO::WARN
2814 : << "Selection string results in empty MS: "
2815 : << "reverting to original MeasurementSet"
2816 0 : << LogIO::POST;
2817 0 : delete mssel_p2;
2818 : } else {
2819 0 : if (mssel_p) {
2820 0 : delete mssel_p;
2821 0 : mssel_p=mssel_p2;
2822 0 : mssel_p->flush();
2823 : }
2824 : }
2825 0 : } else {
2826 0 : os << "No selection string given" << LogIO::POST;
2827 : }
2828 :
2829 0 : if(mssel_p->nrow()!=ms_p->nrow()) {
2830 0 : os << "By selection " << ms_p->nrow() << " rows are reduced to "
2831 0 : << mssel_p->nrow() << LogIO::POST;
2832 : }
2833 : else {
2834 0 : os << "Selection did not drop any rows" << LogIO::POST;
2835 : }
2836 : }
2837 :
2838 : // Now create the VisSet
2839 0 : if(vs_p) delete vs_p; vs_p=0;
2840 0 : makeVisSet();
2841 : //Now assign the source directions to something selected or sensible
2842 : {
2843 : //Int fieldsel=0;
2844 0 : if(fieldids.nelements() >0) {
2845 : //fieldsel=fieldids(0);
2846 : // RI TODO does sim:setdata need this?
2847 0 : nField=fieldids.nelements();
2848 0 : for (Int i=0;i<nField;i++) {
2849 : // RI TODO check whether index in field column is just i or need
2850 : // to search for fieldid
2851 0 : (vs_p->iter()).msColumns().field().name().get(i,sourceName_p[i]);
2852 0 : sourceDirection_p[i]=(vs_p->iter()).msColumns().field().phaseDirMeas(i);
2853 0 : (vs_p->iter()).msColumns().field().code().get(i,calCode_p[i]);
2854 : }
2855 : }
2856 : }
2857 0 : return true;
2858 0 : } catch (AipsError x) {
2859 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
2860 0 : << LogIO::POST;
2861 0 : return false;
2862 0 : }
2863 : return true;
2864 0 : }
2865 :
2866 : } // end namespace casa
|