Line data Source code
1 : //# ImagerMultiMS.cc: Implementation of ImagerMultiMS.h
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$
27 :
28 : #include <cassert>
29 :
30 : #include <synthesis/MeasurementEquations/ImagerMultiMS.h>
31 : #include <synthesis/TransformMachines/VisModelData.h>
32 : #include <casacore/casa/BasicSL/String.h>
33 : #include <casacore/casa/Utilities/Assert.h>
34 : #include <casacore/casa/Logging.h>
35 : #include <casacore/casa/Logging/LogIO.h>
36 : #include <casacore/casa/Logging/LogMessage.h>
37 :
38 : #include <casacore/casa/Exceptions/Error.h>
39 : #include <iostream>
40 : #include <casacore/ms/MSSel/MSSelection.h>
41 : #include <casacore/ms/MSSel/MSDataDescIndex.h>
42 : #include <casacore/ms/MeasurementSets/MSHistoryHandler.h>
43 : #include <casacore/ms/MeasurementSets/MeasurementSet.h>
44 : #include <casacore/ms/MeasurementSets/MSDataDescColumns.h>
45 : #include <casacore/ms/MeasurementSets/MSColumns.h>
46 : #include <msvis/MSVis/SimpleSubMS.h>
47 : #include <msvis/MSVis/SubMS.h>
48 : #include <msvis/MSVis/VisSetUtil.h>
49 : #include <msvis/MSVis/VisibilityIterator.h>
50 : #include <casacore/casa/Arrays/Matrix.h>
51 : #include <casacore/casa/Arrays/ArrayMath.h>
52 :
53 : #include <casacore/tables/TaQL/ExprNode.h>
54 : #include <casacore/tables/TaQL/TableParse.h>
55 : #include <casacore/tables/Tables/SetupNewTab.h>
56 :
57 : #include <casacore/lattices/LEL/LatticeExpr.h>
58 :
59 : #include <casacore/casa/OS/File.h>
60 : #include <casacore/casa/OS/HostInfo.h>
61 : #include <casacore/casa/Containers/Record.h>
62 :
63 : #include <sstream>
64 :
65 : using namespace casacore;
66 : namespace casa { //# NAMESPACE CASA - BEGIN
67 :
68 4 : ImagerMultiMS::ImagerMultiMS()
69 4 : : Imager(), blockNChan_p(0), blockStart_p(0), blockStep_p(0), blockSpw_p(0),
70 8 : blockMSSel_p(0), dataSet_p(false)
71 : {
72 :
73 4 : lockCounter_p=0;
74 4 : ms_p=0;
75 4 : mssel_p=0;
76 4 : se_p=0;
77 4 : vs_p=0;
78 4 : ft_p=0;
79 4 : cft_p=0;
80 4 : rvi_p=wvi_p=0;
81 4 : numMS_p=0;
82 :
83 4 : }
84 :
85 0 : Bool ImagerMultiMS::setDataToMemory(const String& msname,
86 : const String& /*mode*/,
87 : const Vector<Int>& nchan,
88 : const Vector<Int>& start,
89 : const Vector<Int>& step,
90 : const Vector<Int>& /*spectralwindowids*/,
91 : const Vector<Int>& /*fieldids*/,
92 : const String& msSelect,
93 : const String& timerng,
94 : const String& fieldnames,
95 : const Vector<Int>& /*antIndex*/,
96 : const String& antnames,
97 : const String& spwstring,
98 : const String& uvdist,
99 : const String& scan,
100 : const String& intent,
101 : const String& obs){
102 0 : useModelCol_p=false;
103 0 : LogIO os(LogOrigin("imager", "setDataToMemory()"), logSink_p);
104 0 : if(!Table::isReadable(msname)){
105 : os << LogIO::SEVERE << "MeasurementSet "
106 : << msname << " does not exist "
107 0 : << LogIO::POST;
108 0 : return false;
109 : }
110 0 : if(intent != ""){
111 : os << LogIO::WARN << "does not support INTENT selection here "
112 0 : << LogIO::POST;
113 : }
114 0 : MeasurementSet thisms(msname, TableLock(TableLock::AutoNoReadLocking),
115 0 : Table::Old);
116 0 : SimpleSubMS splitter(thisms);
117 : //SubMS splitter(thisms);
118 0 : splitter.setmsselect(spwstring, fieldnames, antnames, scan, obs, uvdist,
119 : msSelect, nchan, start, step, "");
120 0 : splitter.selectCorrelations("");
121 0 : splitter.selectTime(-1.0, timerng);
122 0 : MS::PredefinedColumns whichCol=MS::DATA;
123 0 : if(thisms.tableDesc().isColumn("CORRECTED_DATA"))
124 0 : whichCol=MS::CORRECTED_DATA;
125 0 : CountedPtr<MeasurementSet> subMS(splitter.makeMemSubMS(whichCol), true);
126 : //CountedPtr<MeasurementSet> subMS(splitter.makeScratchSubMS(Vector<MS::PredefinedColumns>(1,whichCol), true), true);
127 0 : return setDataOnThisMS(*subMS);
128 :
129 0 : }
130 :
131 :
132 0 : Bool ImagerMultiMS::setDataPerMS(const String& msname, const String& mode,
133 : const Vector<Int>& nchan,
134 : const Vector<Int>& start,
135 : const Vector<Int>& step,
136 : const Vector<Int>& spectralwindowids,
137 : const Vector<Int>& fieldids,
138 : const String& msSelect,
139 : const String& timerng,
140 : const String& fieldnames,
141 : const Vector<Int>& antIndex,
142 : const String& antnames,
143 : const String& spwstring,
144 : const String& uvdist,
145 : const String& scan,
146 : const String& intent,
147 : const String& obs,
148 : const Bool useModel,
149 : const Bool readonly){
150 0 : useModelCol_p=useModel;
151 : // Bool rd=readonly;
152 0 : LogIO os(LogOrigin("imager", "setDataPerMS()"), logSink_p);
153 : // if(useModel)
154 : // rd=true;
155 0 : if(!Table::isReadable(msname)){
156 : os << LogIO::SEVERE << "MeasurementSet "
157 : << msname << " does not exist "
158 0 : << LogIO::POST;
159 0 : return false;
160 : }
161 : else{
162 0 : MeasurementSet thisms;
163 0 : if(!readonly)
164 0 : thisms=MeasurementSet(msname, TableLock(TableLock::AutoNoReadLocking),
165 0 : Table::Update);
166 : else
167 0 : thisms=MeasurementSet(msname, TableLock(TableLock::AutoNoReadLocking),
168 0 : Table::Old);
169 : //thisms=MeasurementSet(msname, TableLock(),
170 : // Table::Old);
171 :
172 0 : thisms.setMemoryResidentSubtables (MrsEligibility::defaultEligible());
173 :
174 0 : return setDataOnThisMS(thisms, mode, nchan, start, step, spectralwindowids, fieldids, msSelect, timerng,
175 0 : fieldnames, antIndex, antnames, spwstring, uvdist, scan, intent, obs);
176 :
177 0 : }
178 :
179 0 : }
180 :
181 :
182 :
183 0 : Bool ImagerMultiMS::setDataOnThisMS(MeasurementSet& thisms, const String& mode,
184 : const Vector<Int>& nchan,
185 : const Vector<Int>& start,
186 : const Vector<Int>& step,
187 : const Vector<Int>& spectralwindowids,
188 : const Vector<Int>& fieldids,
189 : const String& msSelect,
190 : const String& timerng,
191 : const String& fieldnames,
192 : const Vector<Int>& antIndex,
193 : const String& antnames,
194 : const String& spwstring,
195 : const String& uvdist,
196 : const String& scan,
197 : const String& intent,
198 : const String& obs){
199 0 : LogIO os(LogOrigin("imager", "setDataOnThisMS()"), logSink_p);
200 :
201 :
202 0 : dataMode_p=mode;
203 0 : dataNchan_p.resize();
204 0 : dataStart_p.resize();
205 0 : dataStep_p.resize();
206 0 : dataNchan_p=nchan;
207 0 : dataStart_p=start;
208 0 : dataStep_p=step;
209 0 : dataspectralwindowids_p.resize(spectralwindowids.nelements());
210 0 : dataspectralwindowids_p=spectralwindowids;
211 0 : datafieldids_p.resize(fieldids.nelements());
212 0 : datafieldids_p=fieldids;
213 :
214 :
215 :
216 : //make ms
217 : // auto lock for now
218 : // make ms and visset
219 0 : ++numMS_p;
220 0 : blockMSSel_p.resize(numMS_p);
221 0 : blockNChan_p.resize(numMS_p);
222 0 : blockStart_p.resize(numMS_p);
223 0 : blockStep_p.resize(numMS_p);
224 0 : blockSpw_p.resize(numMS_p);
225 : //Using autolocking here
226 : //Will need to rethink this when in parallel mode with multi-cpu access
227 0 : blockMSSel_p[numMS_p-1]=thisms;
228 : //breaking reference
229 0 : if(ms_p.null())
230 0 : ms_p=new MeasurementSet();
231 : else
232 0 : (*ms_p)=MeasurementSet();
233 0 : (*ms_p)=thisms;
234 :
235 :
236 : try{
237 0 : openSubTables();
238 :
239 : //if spectralwindowids=-1 take all
240 0 : if(mode=="none" &&
241 0 : (spectralwindowids.nelements()==1 && spectralwindowids[0]<0)){
242 0 : Int nspw=thisms.spectralWindow().nrow();
243 0 : dataspectralwindowids_p.resize(nspw);
244 0 : indgen(dataspectralwindowids_p);
245 :
246 : }
247 :
248 : // If a selection has been made then close the current MS
249 : // and attach to a new selected MS. We do this on the original
250 : // MS.
251 : //I don't think i need this if statement
252 : // if(datafieldids_p.nelements()>0||datadescids_p.nelements()>0) {
253 0 : os << "Performing selection on MeasurementSet : " << thisms.tableName() << LogIO::POST;
254 : //if(vs_p) delete vs_p; vs_p=0;
255 : //if(mssel_p) delete mssel_p;
256 0 : mssel_p=0;
257 :
258 : // check that sorted table exists (it should), if not, make it now.
259 : //this->makeVisSet(thisms);
260 :
261 : //if you want to use scratch col...make sure they are there
262 0 : if(useModelCol_p){
263 0 : VisSetUtil::addScrCols(thisms, true, false, true, false);
264 0 : VisModelData::clearModel(thisms);
265 : }
266 : //MeasurementSet sorted=thisms.keywordSet().asTable("SORTED_TABLE");
267 :
268 :
269 : //Some MSSelection
270 0 : MSSelection thisSelection;
271 0 : if(datafieldids_p.nelements() > 0){
272 0 : thisSelection.setFieldExpr(MSSelection::indexExprStr(datafieldids_p));
273 0 : os << "Selecting on field ids : " << datafieldids_p << LogIO::POST;
274 : }
275 0 : if(fieldnames != ""){
276 0 : thisSelection.setFieldExpr(fieldnames);
277 0 : os << "Selecting on fields : " << fieldnames << LogIO::POST;
278 : }
279 0 : if(dataspectralwindowids_p.nelements() > 0){
280 0 : thisSelection.setSpwExpr(MSSelection::indexExprStr(dataspectralwindowids_p));
281 0 : os << "Selecting on spectral windows" << LogIO::POST;
282 : }
283 0 : else if(spwstring != ""){
284 0 : thisSelection.setSpwExpr(spwstring);
285 0 : os << "Selecting on spectral windows expression :"<< spwstring << LogIO::POST;
286 : }
287 0 : if(antIndex.nelements() >0){
288 0 : thisSelection.setAntennaExpr( MSSelection::indexExprStr(antIndex) );
289 0 : os << "Selecting on antenna ids : " << antIndex << LogIO::POST;
290 : }
291 0 : if(antnames != ""){
292 0 : Vector<String> antNames(1, antnames);
293 : // thisSelection.setAntennaExpr(MSSelection::nameExprStr( antNames));
294 0 : thisSelection.setAntennaExpr(antnames);
295 0 : os << "Selecting on antenna names : " << antnames << LogIO::POST;
296 :
297 0 : }
298 0 : if(timerng != ""){
299 0 : thisSelection.setTimeExpr(timerng);
300 0 : os << "Selecting on time range : " << timerng << LogIO::POST;
301 : }
302 0 : if(uvdist != ""){
303 0 : thisSelection.setUvDistExpr(uvdist);
304 0 : os << "Selecting on uvdist : " << uvdist << LogIO::POST;
305 : }
306 0 : if(scan != ""){
307 0 : thisSelection.setScanExpr(scan);
308 0 : os << "Selecting on scan : " << scan << LogIO::POST;
309 : }
310 0 : if(intent != ""){
311 0 : thisSelection.setStateExpr(intent);
312 0 : os << "Selecting on State(scan intent) Expr " << intent << LogIO::POST;
313 : }
314 0 : if(obs != ""){
315 0 : thisSelection.setObservationExpr(obs);
316 0 : os << "Selecting on Observation Expr : " << obs << LogIO::POST;
317 : }
318 0 : if(msSelect != ""){
319 0 : thisSelection.setTaQLExpr(msSelect);
320 0 : os << "Selecting via TaQL : " << msSelect << LogIO::POST;
321 : }
322 : //***************
323 :
324 0 : TableExprNode exprNode=thisSelection.toTableExprNode(&thisms);
325 : //if(exprNode.isNull())
326 : // throw(AipsError("Selection failed...review ms and selection parameters"));
327 0 : datafieldids_p.resize();
328 0 : datafieldids_p=thisSelection.getFieldList();
329 0 : if(datafieldids_p.nelements()==0){
330 0 : Int nf=ms_p->field().nrow();
331 0 : datafieldids_p.resize(nf);
332 0 : indgen(datafieldids_p);
333 : }
334 0 : if((numMS_p > 1) || datafieldids_p.nelements() > 1)
335 0 : multiFields_p= true;
336 : //Now lets see what was selected as spw and match it with datadesc
337 : //dataspectralwindowids_p.resize();
338 : //dataspectralwindowids_p=thisSelection.getSpwList();
339 0 : Matrix<Int> chansels=thisSelection.getChanList(NULL, 1, true);
340 0 : mssFreqSel_p.resize();
341 0 : mssFreqSel_p=thisSelection.getChanFreqList(NULL, true);
342 :
343 0 : uInt nms = numMS_p;
344 0 : uInt nrow = chansels.nrow();
345 0 : dataspectralwindowids_p.resize();
346 0 : const MSSpWindowColumns spwc(thisms.spectralWindow());
347 0 : uInt nspw = spwc.nrow();
348 0 : const ScalarColumn<Int> spwNchans(spwc.numChan());
349 0 : Vector<Int> nchanvec = spwNchans.getColumn();
350 : //cerr<<"SetDataOnThisMS::numMS_p="<<numMS_p<<" nchanvec="<<nchanvec<<endl;
351 0 : Int maxnchan = 0;
352 :
353 0 : for (uInt i=0;i<nchanvec.nelements();i++) {
354 0 : maxnchan=max(nchanvec[i],maxnchan);
355 : }
356 : //cout<<"spwchansels_p.shape()="<<spwchansels_p.shape()<<endl;
357 0 : uInt maxnspw = 0;
358 0 : if (numMS_p ==1) {
359 0 : maxnspw=nspw;
360 : }
361 : else {
362 0 : for (Int i=0;i<numMS_p-1;i++) {
363 0 : maxnspw=max(maxnspw,blockSpw_p[i].nelements());
364 : }
365 0 : maxnspw=max(nspw,maxnspw);
366 : }
367 0 : spwchansels_p.resize(nms,maxnspw,maxnchan,true);
368 : //cout<<"After resize: spwchansels_p.shape()="<<spwchansels_p.shape()<<endl;
369 0 : uInt nselspw=0;
370 0 : if (nrow==0) {
371 : //no channel selection, select all channels
372 0 : spwchansels_p.yzPlane(numMS_p-1)=1;
373 0 : dataspectralwindowids_p=thisSelection.getSpwList();
374 : }
375 : else {
376 0 : spwchansels_p.yzPlane(numMS_p-1)=0;
377 0 : Int prvspwid=-1;
378 0 : Vector<Int> selspw;
379 0 : for (uInt i=0;i<nrow;i++) {
380 0 : Vector<Int> sel = chansels.row(i);
381 0 : Int spwid = sel[0];
382 0 : if((sel[1] >= nchanvec[spwid]) || (sel[2] >=nchanvec[spwid]))
383 0 : throw(AipsError("Unexpected selection in spw selection of spwid "+String::toString(spwid)));
384 0 : if (spwid != prvspwid){
385 0 : nselspw++;
386 0 : selspw.resize(nselspw,true);
387 0 : selspw[nselspw-1]=spwid;
388 : }
389 0 : uInt minc= sel[1];
390 0 : uInt maxc = sel[2];
391 0 : uInt step = sel[3];
392 : // step as the same context as in im.selectvis
393 : // select channels
394 0 : for (uInt k=minc;k<(maxc+1);k+=step) {
395 0 : spwchansels_p(numMS_p-1,spwid,k)=1;
396 : }
397 0 : prvspwid=spwid;
398 0 : }
399 0 : dataspectralwindowids_p=selspw;
400 0 : }
401 :
402 : //cout<<"spwchansels_p(before shifting)="<<spwchansels_p<<endl;
403 0 : if(dataspectralwindowids_p.nelements()==0){
404 0 : Int nspwinms=thisms.spectralWindow().nrow();
405 0 : dataspectralwindowids_p.resize(nspwinms);
406 0 : indgen(dataspectralwindowids_p);
407 : }
408 :
409 : // old code
410 : /***
411 : if(dataspectralwindowids_p.nelements()==0){
412 : Int nspwinms=thisms.spectralWindow().nrow();
413 : dataspectralwindowids_p.resize(nspwinms);
414 : indgen(dataspectralwindowids_p);
415 : }
416 : ***/
417 :
418 : // Map the selected spectral window ids to data description ids
419 0 : MSDataDescIndex msDatIndex(thisms.dataDescription());
420 0 : datadescids_p.resize(0);
421 0 : datadescids_p=msDatIndex.matchSpwId(dataspectralwindowids_p);
422 :
423 0 : freqrange_p.resize(nms,2,true);
424 0 : if(mode=="none"){
425 : //check if we can find channel selection in the spw string
426 : //if(nselspw==dataspectralwindowids_p.nelements()){
427 0 : dataMode_p="channel";
428 0 : dataStep_p.resize(dataspectralwindowids_p.nelements());
429 0 : dataStart_p.resize(dataspectralwindowids_p.nelements());
430 0 : dataNchan_p.resize(dataspectralwindowids_p.nelements());
431 0 : Double fmin=C::dbl_max;
432 0 : Double fmax=-(C::dbl_max);
433 :
434 0 : Cube<Int> spwchansels_tmp=spwchansels_p;
435 0 : for (uInt k =0 ; k < dataspectralwindowids_p.nelements(); ++k){
436 0 : uInt curspwid=dataspectralwindowids_p[k];
437 0 : Vector<Double> chanFreq=spwc.chanFreq()(curspwid);
438 0 : Vector<Double> freqResolution = spwc.chanWidth()(curspwid);
439 :
440 :
441 : //dataStep_p[k]=chanselmat.row(k)(3);
442 0 : if (nrow==0) {
443 : //dataStep_p=step[0];
444 0 : dataStep_p[k]=step[0];
445 : }
446 : else {
447 0 : dataStep_p[k]=chansels.row(k)(3);
448 : }
449 : //if(dataStep_p[k] < 1)
450 : // dataStep_p[k]=1;
451 0 : dataStart_p[k]=0;
452 0 : dataNchan_p[k]=nchanvec(curspwid);
453 : //cout<<"SetDataOnThisMS: initial setting dataNchan_p["<<k<<"]="<<dataNchan_p[k]<<endl;
454 : //find start
455 0 : Bool first = true;
456 0 : uInt nchn = 0;
457 0 : uInt lastchan = 0;
458 0 : for (Int j=0 ; j < nchanvec(curspwid); j++) {
459 0 : if (spwchansels_p(numMS_p-1,curspwid,j)==1) {
460 0 : if(first) {
461 0 : dataStart_p[k]=j;
462 0 : first = false;
463 : }
464 0 : lastchan=j;
465 0 : nchn++;
466 : }
467 : }
468 : //dataStart_p[k]=chanselmat.row(k)(1);
469 : //dataNchan_p[k]=Int(ceil(Double(chanselmat.row(k)(2)-dataStart_p[k]))/Double(dataStep_p[k]))+1;
470 0 : dataNchan_p[k]=Int(ceil(Double(lastchan-dataStart_p[k])/Double(dataStep_p[k])))+1;
471 : //cout<<"SetDataOnThisMS: after recalc. of nchan dataNchan_p["<<k<<"]="<<dataNchan_p[k]<<endl;
472 : //if(dataNchan_p[k]<1)
473 : // dataNchan_p[k]=1;
474 : //
475 : //Since msselet will be applied to the data before flags from spwchansels_p
476 : //are applied to the data in FTMachine, shift spwchansels_p by dataStart_p
477 0 : for (Int j=0 ; j < nchanvec(curspwid); j++){
478 0 : if (j<nchanvec(curspwid)-dataStart_p[k]) {
479 0 : spwchansels_tmp(numMS_p-1,curspwid,j) = spwchansels_p(numMS_p-1,curspwid,j+dataStart_p[k]);
480 : }
481 : else {
482 0 : spwchansels_tmp(numMS_p-1,curspwid,j) = 0;
483 : }
484 : }
485 : //for mfs mode need to keep fmin,max info for later image setup
486 : //Int lastchan=dataStart_p[k]+ dataNchan_p[k]*dataStep_p[k];
487 : Int endchanused;
488 0 : if (nrow==0) {
489 : // default spw case
490 0 : endchanused=nchanvec(curspwid);
491 : }
492 : else {
493 0 : endchanused=lastchan;
494 : }
495 0 : for(Int j=dataStart_p[k] ; j < endchanused ; j+=dataStep_p[k]){
496 0 : fmin=min(fmin,chanFreq[j]-abs(freqResolution[j]*(dataStep_p[k]-0.5)));
497 0 : fmax=max(fmax,chanFreq[j]+abs(freqResolution[j]*(dataStep_p[k]-0.5)));
498 : }
499 0 : }
500 : //cerr<<"numMS_p="<<numMS_p<<" fmin="<<fmin<<" fmax="<<fmax<<endl;
501 0 : freqrange_p(numMS_p-1,0)=fmin;
502 0 : freqrange_p(numMS_p-1,1)=fmax;
503 :
504 0 : spwchansels_p=spwchansels_tmp;
505 : //}
506 0 : }
507 :
508 :
509 :
510 : // Now remake the selected ms
511 0 : if(!(exprNode.isNull())){
512 0 : mssel_p = new MeasurementSet(thisms(exprNode));
513 : }
514 : else{
515 : // Null take all the ms ...setdata() blank means that
516 0 : mssel_p = new MeasurementSet(thisms);
517 : }
518 0 : AlwaysAssert(!mssel_p.null(), AipsError);
519 0 : if(mssel_p->nrow()==0) {
520 : //delete mssel_p;
521 0 : mssel_p=0;
522 :
523 : os << "Selection is empty: you may want to review this MSs selection"
524 0 : << LogIO::EXCEPTION;
525 : }
526 : else {
527 0 : mssel_p->flush();
528 : }
529 :
530 0 : if(mssel_p->nrow()!=thisms.nrow()) {
531 0 : os << "Selected " << mssel_p->nrow() << " out of "
532 0 : << thisms.nrow() << " rows." << LogIO::POST;
533 : }
534 : else {
535 0 : os << "Selected all " << mssel_p->nrow() << " rows" << LogIO::POST;
536 : }
537 : // }
538 :
539 : // Tell the user how many channels have been selected.
540 : // NOTE : This code is replicated in Imager.cc.
541 0 : Vector<Int> chancounts(dataspectralwindowids_p.nelements());
542 0 : chancounts=0;
543 : // if( spwstring == "" ) os << "Selected all spws and channels" << LogIO::POST;
544 : // else os << "Channel selection : " << spwstring << LogIO::POST;
545 0 : os << "Selected :";
546 0 : for(uInt k=0;k<dataspectralwindowids_p.nelements();k++)
547 : {
548 0 : for(uInt ch=0;ch<uInt(nchanvec(dataspectralwindowids_p[k]));ch++)
549 0 : {if(spwchansels_p(numMS_p-1,dataspectralwindowids_p[k],ch)) chancounts[k]++; }
550 : //if(chancounts[k]<1)
551 : // throw(AipsError("bad selection in spw "+ String::toString( dataspectralwindowids_p[k])));
552 0 : os << " [" << chancounts[k] << " chans in spw " << dataspectralwindowids_p[k] << "]";
553 : // os << "Selected " << chancounts[k] << " chans in spw "
554 : // << dataspectralwindowids_p[k] << LogIO::POST;
555 : }
556 0 : os << LogIO::POST;
557 :
558 :
559 0 : blockMSSel_p[numMS_p-1]=*mssel_p;
560 : //lets make the visSet now
561 0 : Block<Matrix<Int> > noChanSel;
562 0 : noChanSel.resize(numMS_p);
563 0 : Block<Int> sort(0);
564 : //if(vs_p) delete vs_p; vs_p=0;
565 0 : if(rvi_p) delete rvi_p;
566 0 : rvi_p=0;
567 0 : wvi_p=0;
568 :
569 : //vs_p= new VisSet(blockMSSel_p, sort, noChanSel, useModelCol_p);
570 0 : if(!(mssel_p->isWritable())){
571 0 : rvi_p=new ROVisibilityIterator(blockMSSel_p, sort);
572 :
573 : }
574 : else{
575 0 : wvi_p=new VisibilityIterator(blockMSSel_p, sort);
576 0 : rvi_p=wvi_p;
577 : }
578 :
579 0 : if(imwgt_p.getType()=="none")
580 0 : imwgt_p=VisImagingWeight("natural");
581 0 : rvi_p->useImagingWeight(imwgt_p);
582 : //rvi_p->slurp();
583 :
584 0 : selectDataChannel();
585 0 : dataSet_p=true;
586 :
587 0 : return dataSet_p;
588 0 : }
589 0 : catch(AipsError x){
590 : //Ayeee...lets back out of this one
591 0 : --numMS_p;
592 0 : blockMSSel_p.resize(numMS_p, true);
593 0 : blockNChan_p.resize(numMS_p, true);
594 0 : blockStart_p.resize(numMS_p, true);
595 0 : blockStep_p.resize(numMS_p, true);
596 0 : blockSpw_p.resize(numMS_p, true);
597 : //point it back to the previous ms
598 0 : if(numMS_p >0){
599 0 : mssel_p=new MeasurementSet(blockMSSel_p[numMS_p-1]);
600 : }
601 0 : throw(AipsError(x));
602 0 : }
603 :
604 0 : } //End of setDataPerMS
605 :
606 :
607 0 : Bool ImagerMultiMS::setimage(const Int nx, const Int ny,
608 : const Quantity& cellx, const Quantity& celly,
609 : const String& stokes,
610 : Bool doShift,
611 : const MDirection& phaseCenter,
612 : const Quantity& shiftx, const Quantity& shifty,
613 : const String& mode, const Int nchan,
614 : const Int start, const Int step,
615 : const MRadialVelocity& mStart,
616 : const MRadialVelocity& mStep,
617 : const Vector<Int>& spectralwindowids,
618 : const Int fieldid,
619 : const Int facets,
620 : const Quantity& distance)
621 : {
622 :
623 0 : if(!dataSet_p){
624 0 : LogIO os(LogOrigin("imagerMultiMS", "setimage()"), logSink_p);
625 : os << LogIO::SEVERE
626 : << "Please use setdata before setimage as imager need one ms at least "
627 0 : << LogIO::POST;
628 0 : return false;
629 :
630 0 : }
631 :
632 0 : Bool returnval=Imager::setimage(nx, ny, cellx, celly, stokes,doShift,
633 : phaseCenter, shiftx, shifty, mode, nchan,
634 : start, step, mStart, mStep,
635 : spectralwindowids,
636 : fieldid, facets, distance);
637 :
638 0 : return returnval;
639 : }
640 :
641 0 : Bool ImagerMultiMS::lock(){
642 : //Do nothing for now as its Autolocked..but a better scheme is necessary
643 : //for parallel access to same data for modification
644 :
645 0 : return true;
646 : }
647 :
648 0 : Bool ImagerMultiMS::unlock(){
649 :
650 0 : for (uInt k=0; k < blockMSSel_p.nelements(); ++k){
651 0 : blockMSSel_p[k].relinquishAutoLocks(true);
652 : }
653 0 : return true;
654 :
655 : }
656 :
657 :
658 0 : Bool ImagerMultiMS::selectDataChannel(){
659 :
660 0 : LogIO os(LogOrigin("imager", "selectDataChannel()"), logSink_p);
661 :
662 0 : (blockNChan_p[numMS_p-1]).resize(dataspectralwindowids_p.nelements());
663 0 : (blockStart_p[numMS_p-1]).resize(dataspectralwindowids_p.nelements());
664 0 : (blockStart_p[numMS_p-1]).set(0);
665 0 : (blockStep_p[numMS_p-1]).resize(dataspectralwindowids_p.nelements());
666 0 : (blockStep_p[numMS_p-1]).set(1);
667 0 : (blockSpw_p[numMS_p-1]).resize(dataspectralwindowids_p.nelements());
668 0 : (blockSpw_p[numMS_p-1]).resize();
669 0 : (blockSpw_p[numMS_p-1])=dataspectralwindowids_p;
670 : {
671 : //Fill default numChan for now
672 :
673 0 : MSSpWindowColumns msSpW(ms_p->spectralWindow());
674 0 : Vector<Int> numChan=msSpW.numChan().getColumn();
675 0 : for (uInt k=0; k < dataspectralwindowids_p.nelements(); ++k){
676 0 : blockNChan_p[numMS_p-1][k]=numChan[dataspectralwindowids_p[k]];
677 :
678 : }
679 0 : }
680 :
681 0 : if(dataMode_p=="channel") {
682 :
683 0 : if (dataNchan_p.nelements() != dataspectralwindowids_p.nelements()){
684 0 : if(dataNchan_p.nelements()==1){
685 0 : dataNchan_p.resize(dataspectralwindowids_p.nelements(), true);
686 0 : for(uInt k=1; k < dataspectralwindowids_p.nelements(); ++k){
687 0 : dataNchan_p[k]=dataNchan_p[0];
688 : }
689 : }
690 : else{
691 : os << LogIO::SEVERE
692 : << "Vector of nchan has to be of size 1 or be of the same shape as spw "
693 0 : << LogIO::POST;
694 0 : return false;
695 : }
696 : }
697 0 : if (dataStart_p.nelements() != dataspectralwindowids_p.nelements()){
698 0 : if(dataStart_p.nelements()==1){
699 0 : dataStart_p.resize(dataspectralwindowids_p.nelements(), true);
700 0 : for(uInt k=1; k < dataspectralwindowids_p.nelements(); ++k){
701 0 : dataStart_p[k]=dataStart_p[0];
702 : }
703 : }
704 : else{
705 : os << LogIO::SEVERE
706 : << "Vector of start has to be of size 1 or be of the same shape as spw "
707 0 : << LogIO::POST;
708 0 : return false;
709 : }
710 : }
711 0 : if (dataStep_p.nelements() != dataspectralwindowids_p.nelements()){
712 0 : if(dataStep_p.nelements()==1){
713 0 : dataStep_p.resize(dataspectralwindowids_p.nelements(), true);
714 0 : for(uInt k=1; k < dataspectralwindowids_p.nelements(); ++k){
715 0 : dataStep_p[k]=dataStep_p[0];
716 : }
717 : }
718 : else{
719 : os << LogIO::SEVERE
720 : << "Vector of step has to be of size 1 or be of the same shape as spw "
721 0 : << LogIO::POST;
722 0 : return false;
723 : }
724 : }
725 :
726 : {
727 0 : Int nch=0;
728 0 : for(uInt i=0;i<dataspectralwindowids_p.nelements();i++) {
729 0 : Int spwid=dataspectralwindowids_p(i);
730 0 : if(dataStart_p[i]<0) {
731 : os << LogIO::SEVERE << "Illegal start pixel = "
732 0 : << dataStart_p[i] << " for spw " << spwid
733 0 : << LogIO::POST;
734 0 : return false;
735 : }
736 :
737 0 : if(dataNchan_p[i]<=0){
738 0 : if(dataStep_p[i] <= 0)
739 0 : dataStep_p[i]=1;
740 0 : nch=(blockNChan_p[numMS_p-1](i)-dataStart_p[i])/Int(dataStep_p[i])+1;
741 :
742 : }
743 0 : else nch = dataNchan_p[i];
744 0 : while((nch*dataStep_p[i]+dataStart_p[i]) >
745 0 : blockNChan_p[numMS_p-1](i)){
746 0 : --nch;
747 : }
748 0 : Int end = Int(dataStart_p[i]) + Int(nch-1) * Int(dataStep_p[i]);
749 0 : if(end < 0 || end > (blockNChan_p[numMS_p-1](i)-1)) {
750 0 : os << LogIO::SEVERE << "Illegal step pixel = " << dataStep_p[i]
751 : << " for spw " << spwid
752 : << "\n end channel " << end << " out of range "
753 0 : << dataStart_p[i] << " to "
754 0 : << (blockNChan_p[numMS_p-1](i)-1)
755 :
756 0 : << LogIO::POST;
757 0 : return false;
758 : }
759 : os << LogIO::DEBUG1 << "Selecting "<< nch
760 : << " channels, starting at visibility channel "
761 0 : << dataStart_p[i] << " stepped by "
762 0 : << dataStep_p[i] << " for spw " << spwid << LogIO::POST;
763 0 : dataNchan_p[i]=nch;
764 0 : blockNChan_p[numMS_p-1][i]=nch;
765 0 : blockStep_p[numMS_p-1][i]=dataStep_p[i];
766 0 : blockStart_p[numMS_p-1][i]=dataStart_p[i];
767 : }
768 : }
769 :
770 : }
771 :
772 0 : Block<Vector<Int> > blockGroup(numMS_p);
773 0 : for (Int k=0; k < numMS_p; ++k){
774 0 : blockGroup[k].resize(blockSpw_p[k].nelements());
775 0 : blockGroup[k].set(1);
776 : }
777 :
778 0 : rvi_p->selectChannel(blockGroup, blockStart_p, blockNChan_p,
779 0 : blockStep_p, blockSpw_p);
780 0 : return true;
781 0 : }
782 :
783 0 : Bool ImagerMultiMS::openSubTables(){
784 :
785 : // Reopen disk-resident tables with the default table lock
786 :
787 0 : if((ms_p->tableType()) != Table::Memory){
788 :
789 0 : TableLock tableLock; // default table lock
790 :
791 0 : openSubTable (ms_p->antenna(), antab_p, tableLock);
792 0 : openSubTable (ms_p->dataDescription (), datadesctab_p, tableLock);
793 0 : openSubTable (ms_p->doppler(), dopplertab_p, tableLock);
794 0 : openSubTable (ms_p->feed(), feedtab_p, tableLock);
795 0 : openSubTable (ms_p->field(), fieldtab_p, tableLock);
796 0 : openSubTable (ms_p->flagCmd(), flagcmdtab_p, tableLock);
797 0 : openSubTable (ms_p->freqOffset(), freqoffsettab_p, tableLock);
798 0 : openSubTable (ms_p->observation(), obstab_p, tableLock);
799 0 : openSubTable (ms_p->pointing(), pointingtab_p, tableLock);
800 0 : openSubTable (ms_p->polarization(), poltab_p, tableLock);
801 0 : openSubTable (ms_p->processor(), proctab_p, tableLock);
802 0 : openSubTable (ms_p->source(), sourcetab_p, tableLock);
803 0 : openSubTable (ms_p->spectralWindow(), spwtab_p, tableLock);
804 0 : openSubTable (ms_p->state(), statetab_p, tableLock);
805 0 : openSubTable (ms_p->sysCal(), syscaltab_p, tableLock);
806 0 : openSubTable (ms_p->weather(), weathertab_p, tableLock);
807 :
808 : // Handle the history table specially
809 :
810 0 : if(ms_p->isWritable()){
811 :
812 0 : if(!(Table::isReadable(ms_p->historyTableName()))){
813 :
814 : // setup a new table in case its not there
815 0 : TableRecord &kws = ms_p->rwKeywordSet();
816 0 : SetupNewTable historySetup(ms_p->historyTableName(),
817 0 : MSHistory::requiredTableDesc(),Table::New);
818 0 : kws.defineTable(MS::keywordName(MS::HISTORY), Table(historySetup));
819 :
820 0 : }
821 :
822 0 : historytab_p=Table(ms_p->historyTableName(), TableLock(), Table::Update);
823 :
824 0 : hist_p= new MSHistoryHandler(*ms_p, "imager");
825 : }
826 : }
827 :
828 0 : return true;
829 : }
830 :
831 : #define INITIALIZE_DIRECTION_VECTOR(name) \
832 : do { \
833 : if (name.nelements() < 2) { \
834 : name.resize(2); \
835 : name = 0.0; \
836 : } \
837 : } while (false)
838 0 : Bool ImagerMultiMS::mapExtent(const String &referenceFrame, const String &movingSource,
839 : const String &pointingColumn, Vector<Double> ¢er, Vector<Double> &blc,
840 : Vector<Double> &trc, Vector<Double> &extent) {
841 : // initialize if necessary
842 0 : INITIALIZE_DIRECTION_VECTOR(center);
843 0 : INITIALIZE_DIRECTION_VECTOR(blc);
844 0 : INITIALIZE_DIRECTION_VECTOR(trc);
845 0 : INITIALIZE_DIRECTION_VECTOR(extent);
846 :
847 : try {
848 0 : Bool isValueSet = false;
849 0 : for (size_t i = 0; i < blockMSSel_p.nelements(); ++i) {
850 : //cout << "start MS " << i << endl;
851 0 : MeasurementSet ms = blockMSSel_p[i];
852 0 : Vector<Double> wcenter(2);
853 0 : Vector<Double> wblc(2);
854 0 : Vector<Double> wtrc(2);
855 0 : Vector<Double> wextent(2);
856 : //cout << "run getMapExtent" << endl;
857 0 : Bool status = getMapExtent(ms, referenceFrame, movingSource, pointingColumn,
858 : wcenter, wblc, wtrc, wextent);
859 : //cout << "done Imager::mapExtent" << endl;
860 0 : if (status) {
861 0 : if (!isValueSet) {
862 0 : center = wcenter;
863 0 : blc = wblc;
864 0 : trc = wtrc;
865 0 : extent = wextent;
866 0 : isValueSet = true;
867 : }
868 : else {
869 0 : blc[0] = min(blc[0], wblc[0]);
870 0 : blc[1] = min(blc[1], wblc[1]);
871 0 : trc[0] = max(trc[0], wtrc[0]);
872 0 : trc[1] = max(trc[1], wtrc[1]);
873 : }
874 : }
875 0 : }
876 :
877 0 : if (!isValueSet) {
878 0 : LogIO os(LogOrigin("ImagerMultiMS", "mapExtent", WHERE));
879 0 : os << LogIO::SEVERE << "No valid data found. Failed." << LogIO::POST;
880 :
881 0 : return false;
882 0 : }
883 :
884 : // extent is re-evaluated using true trc and blc
885 0 : extent = trc - blc;
886 :
887 : // declination correction factor
888 0 : Double declinationCorrection = cos(center[1]);
889 :
890 : // center needs to be updated according to specified column name
891 : // and moving source name
892 : MDirection::Types refType;
893 0 : Bool status = MDirection::getType(refType, movingSource);
894 0 : Bool doMovingSourceCorrection = (status == true &&
895 0 : MDirection::N_Types < refType &&
896 0 : refType < MDirection::N_Planets);
897 0 : Bool isOffsetColumn = (pointingColumn.contains("OFFSET")
898 0 : || pointingColumn.contains("Offset")
899 0 : || pointingColumn.contains("offset"));
900 0 : if (isOffsetColumn) {
901 : // center is always (0,0)
902 0 : center = 0.0;
903 0 : declinationCorrection = cos((blc[1] + trc[1]) / 2.0);
904 : }
905 0 : else if (!doMovingSourceCorrection) {
906 : // initial center value should be kept
907 : // if doMovingSourceCorrection is true.
908 : // otherwise, center should be re-evaluated
909 : // using true trc and blc
910 0 : center = (blc + trc) / 2.0;
911 0 : declinationCorrection = cos(center[1]);
912 : }
913 :
914 0 : assert(declinationCorrection != 0.0);
915 : //cout << "declinationCorrection = " << declinationCorrection << endl;
916 :
917 : // apply declinationCorrection to extent[0]
918 0 : extent[0] *= declinationCorrection;
919 : }
920 0 : catch (...) {
921 0 : LogIO os(LogOrigin("ImagerMultiMS", "mapExtent", WHERE));
922 0 : os << LogIO::SEVERE << "Failed due to unknown error" << LogIO::POST;
923 0 : return false;
924 0 : }
925 0 : return true;
926 : }
927 : } //# NAMESPACE CASA - END
|