Line data Source code
1 : //# MS2ASDM.cc
2 : //#
3 : //# ALMA - Atacama Large Millimeter Array
4 : //# (c) European Southern Observatory, 2002
5 : //# (c) Associated Universities Inc., 2002
6 : //# Copyright by ESO (in the framework of the ALMA collaboration),
7 : //# Copyright by AUI (in the framework of the ALMA collaboration),
8 : //# All rights reserved.
9 : //#
10 : //# This library is free software; you can redistribute it and/or
11 : //# modify it under the terms of the GNU Lesser General Public
12 : //# License as published by the Free software Foundation; either
13 : //# version 2.1 of the License, or (at your option) any later version.
14 : //#
15 : //# This library is distributed in the hope that it will be useful,
16 : //# but WITHOUT ANY WARRANTY, without even the implied warranty of
17 : //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 : //# Lesser General Public License for more details.
19 : //#
20 : //# You should have received a copy of the GNU Lesser General Public
21 : //# License along with this library; if not, write to the Free Software
22 : //# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 : //# MA 02111-1307 USA
24 : //# $Id: $
25 : #include <casacore/tables/TaQL/ExprNode.h>
26 : #include <casacore/tables/Tables/RefRows.h>
27 : #include <casacore/ms/MeasurementSets/MSColumns.h>
28 : #include <casacore/casa/Quanta/MVBaseline.h>
29 : #include <casacore/casa/Arrays/Matrix.h>
30 : #include <casacore/casa/Arrays/Cube.h>
31 : #include <casacore/casa/Arrays/ArrayMath.h>
32 : #include <casacore/casa/Arrays/ArrayOpsDiffShapes.h>
33 : #include <casacore/casa/Arrays/ArrayLogical.h>
34 : #include <casacore/casa/Arrays/ArrayUtil.h>
35 : #include <casacore/casa/Arrays/IPosition.h>
36 : #include <casacore/casa/Arrays/Slice.h>
37 : #include <casacore/casa/Logging/LogIO.h>
38 : #include <casacore/casa/OS/File.h>
39 : #include <casacore/casa/OS/HostInfo.h>
40 : #include <casacore/casa/Containers/Record.h>
41 : #include <casacore/casa/BasicMath/Math.h>
42 : #include <casacore/casa/BasicSL/String.h>
43 : #include <casacore/casa/Utilities/Assert.h>
44 : #include <casacore/casa/Utilities/GenSort.h>
45 : #include <casacore/casa/System/AppInfo.h>
46 : #include <casacore/tables/DataMan/IncrementalStMan.h>
47 : #include <casacore/tables/Tables/ScalarColumn.h>
48 : #include <casacore/tables/Tables/ScaColDesc.h>
49 : #include <casacore/tables/Tables/SetupNewTab.h>
50 : #include <casacore/tables/DataMan/StandardStMan.h>
51 : #include <casacore/tables/Tables/Table.h>
52 : #include <casacore/tables/Tables/TableDesc.h>
53 : #include <casacore/tables/Tables/TableInfo.h>
54 : #include <casacore/tables/Tables/TableLock.h>
55 : #include <casacore/tables/Tables/TableRecord.h>
56 : #include <casacore/tables/Tables/TableCopy.h>
57 : #include <casacore/tables/Tables/TableRow.h>
58 : #include <casacore/tables/DataMan/TiledColumnStMan.h>
59 : #include <casacore/tables/DataMan/TiledShapeStMan.h>
60 : #include <casacore/tables/DataMan/TiledDataStMan.h>
61 : #include <casacore/tables/DataMan/TiledStManAccessor.h>
62 : #include <casacore/measures/Measures/MeasTable.h>
63 : #include <sstream>
64 : #include <iomanip>
65 :
66 : #include <algorithm>
67 : #include <casacore/casa/OS/Directory.h>
68 : #include <alma/ASDM/ASDMAll.h>
69 : #include <alma/ASDMBinaries/SDMDataObjectWriter.h>
70 : #include <alma/ASDMBinaries/SDMDataObject.h>
71 :
72 : #include <alma/MS2ASDM/MS2ASDM.h>
73 :
74 : using asdm::ASDM;
75 : using asdm::TagType;
76 : using namespace asdm;
77 : using namespace asdmbinaries;
78 :
79 : using namespace casacore;
80 : namespace casa {
81 :
82 : using casacore::Double;
83 : using casacore::Complex;
84 : using casacore::Float;
85 :
86 14 : MS2ASDM::MS2ASDM(MeasurementSet& ms) :
87 : MSColumns(ms),
88 14 : ms_p(ms),
89 14 : baseUid_p("uid://X0/X0/X"),
90 14 : runningId_p(0),
91 14 : currentUid_p("uid://X0/X0/X0"),
92 14 : telName_p(""),
93 : // the maps with defaults
94 14 : asdmFeedId_p(-1),
95 14 : asdmSourceId_p(-1),
96 56 : asdmPointingModelId_p(-1)
97 : {
98 14 : ASDM_p = new ASDM();
99 14 : asdmVersion_p = String((ASDM_p->getEntity()).getEntityVersion());
100 14 : setSBDuration(); // set to default values
101 14 : setSubScanDuration();
102 14 : setDataAPCorrected();
103 14 : setVerbosity();
104 14 : }
105 :
106 14 : MS2ASDM::~MS2ASDM()
107 : {
108 14 : delete ASDM_p;
109 14 : }
110 :
111 0 : const String& MS2ASDM::showversion()
112 : {
113 :
114 0 : static String rstr = String(asdmVersion_p);
115 0 : if(rstr==""){
116 0 : ASDM* myASDM = new ASDM();
117 0 : rstr = String((myASDM->getEntity()).getEntityVersion());
118 0 : delete myASDM;
119 : }
120 0 : return rstr;
121 : }
122 :
123 14 : void MS2ASDM::setBaseUid(const String& baseuid){ baseUid_p = baseuid; }
124 :
125 14 : const String& MS2ASDM::getBaseUid(){ return baseUid_p; }
126 :
127 1680 : const std::string& MS2ASDM::getCurrentUid(){
128 1680 : static std::string str;
129 1680 : str = string(currentUid_p.c_str());
130 1680 : return str;
131 : }
132 :
133 536 : const std::string& MS2ASDM::getCurrentUidAsFileName(){
134 536 : static std::string str;
135 536 : str = string(currentUid_p.c_str());
136 536 : std::replace( str.begin(), str.end(), ':', '_' );
137 536 : std::replace( str.begin(), str.end(), '/', '_' );
138 :
139 536 : return str;
140 : }
141 :
142 1195 : Bool MS2ASDM::incrementUid()
143 : {
144 : static char cstr[20];
145 1195 : runningId_p++;
146 1195 : if(sprintf(cstr,"%x", runningId_p) > 0){
147 1195 : currentUid_p = baseUid_p + String(cstr);
148 1195 : return true;
149 : }
150 : else{
151 0 : runningId_p--;
152 0 : return false;
153 : }
154 : }
155 :
156 14 : Bool MS2ASDM::writeASDM(const String& asdmfile, const String& datacolumn,
157 : const String& archiveid, const String& rangeid, Bool verbose,
158 : const casacore::Double subscanDuration, const casacore::Double schedBlockDuration,
159 : const Bool msDataIsAPCorrected)
160 : {
161 :
162 28 : LogIO os(LogOrigin("MS2ASDM", "writeASDM()"));
163 :
164 14 : setBaseUid("uid://"+archiveid+"/"+rangeid+"/X");
165 :
166 14 : if(!incrementUid()){// need to increment before first use
167 : os << LogIO::SEVERE << "Error generating UID"
168 0 : << LogIO::POST;
169 0 : return false;
170 : }
171 :
172 : // set the container UID of all tables == the UID of the ASDM
173 14 : asdmUID_p = getCurrentUid().c_str();
174 14 : Entity myEntity;
175 14 : myEntity.setEntityId(EntityId(asdmUID_p));
176 14 : myEntity.setEntityIdEncrypted("na");
177 14 : myEntity.setEntityTypeName("ASDM");
178 14 : myEntity.setEntityVersion(asdmVersion_p);
179 14 : myEntity.setInstanceVersion("1");
180 14 : ASDM_p->setEntity(myEntity);
181 :
182 14 : incrementUid();
183 :
184 : // initialize observatory name
185 14 : if(observation().nrow()==0){
186 0 : os << LogIO::SEVERE << "MS Observation table is empty." << LogIO::POST;
187 0 : return false;
188 : }
189 :
190 14 : setObservatoryName(observation().telescopeName()(0)); // get name of observatory from first row of observation table
191 :
192 14 : if(subscanDuration<1.){
193 : os << LogIO::SEVERE << "Input error: Unreasonably short sub scan duration limit: " << subscanDuration
194 0 : << " seconds." << LogIO::POST;
195 0 : return false;
196 : }
197 :
198 14 : if(schedBlockDuration<60.){
199 : os << LogIO::SEVERE << "Input error: Unreasonably short scheduling block duration limit: " << schedBlockDuration
200 0 : << " seconds. (Should be >= 60 s)" << LogIO::POST;
201 0 : return false;
202 : }
203 :
204 14 : setSubScanDuration(subscanDuration);
205 :
206 14 : setSBDuration(schedBlockDuration);
207 :
208 14 : setDataAPCorrected(msDataIsAPCorrected);
209 :
210 14 : if(verbose){
211 14 : setVerbosity(1); // set to 1 before releasing
212 : }
213 : else{
214 0 : setVerbosity(0);
215 : }
216 :
217 14 : if(verbosity_p>0){
218 : os << LogIO::NORMAL << "Converting " << ms_p.tableName() << " to ASDM " << asdmfile << endl
219 14 : << "UID base is " << getBaseUid() << ", ASDM UID is " << asdmUID_p
220 14 : << LogIO::POST;
221 : }
222 :
223 : // write the ASDM tables
224 :
225 14 : if(!writeStation()){
226 0 : return false;
227 : }
228 :
229 14 : if(!writeAntenna()){
230 0 : return false;
231 : }
232 :
233 14 : if(!writeSpectralWindow()){
234 0 : return false;
235 : }
236 :
237 14 : if(!writeSource()){
238 0 : return false;
239 : }
240 :
241 14 : if(!writePolarization()){
242 0 : return false;
243 : }
244 :
245 14 : if(!writeProcessor()){
246 0 : return false;
247 : }
248 :
249 14 : if(!writeField()){
250 0 : return false;
251 : }
252 :
253 14 : if(!writeReceiver()){
254 0 : return false;
255 : }
256 :
257 14 : if(!writeFeed()){
258 0 : return false;
259 : }
260 :
261 14 : if(!writeDataDescription()){
262 0 : return false;
263 : }
264 :
265 14 : if(!writeSwitchCycle()){
266 0 : return false;
267 : }
268 :
269 14 : if(!writeState()){
270 0 : return false;
271 : }
272 :
273 14 : if(!writeSysCal()){
274 0 : return false;
275 : }
276 :
277 14 : if(!writeConfigDescription()){
278 0 : return false;
279 : }
280 :
281 14 : if(!writeSBSummaryAndExecBlockStubs()){
282 1 : return false;
283 : }
284 :
285 : // prepare the writing of binary data
286 13 : if(!setDirectory(asdmfile)){
287 0 : return false;
288 : }
289 :
290 13 : if(!writeMainAndScanAndSubScan(datacolumn)){
291 0 : return false;
292 : }
293 :
294 13 : if(!writePointingModel()){
295 0 : return false;
296 : }
297 :
298 13 : if(!writePointing()){
299 0 : return false;
300 : }
301 :
302 : // finish writing the ASDM non-binary data
303 : try{
304 13 : ASDM_p->toFile(asdmfile);
305 : }
306 0 : catch(ConversionException x){
307 0 : os << LogIO::SEVERE << "Error writing ASDM non-binary data:" << x.getMessage()
308 0 : << LogIO::POST;
309 0 : return false;
310 0 : }
311 :
312 13 : return true;
313 :
314 14 : }
315 :
316 13 : Bool MS2ASDM::setDirectory(const String& asdmfile){
317 :
318 26 : LogIO os(LogOrigin("MS2ASDM", "setDirectory()"));
319 :
320 : // create ASDM output directories
321 13 : Directory asdmDir(asdmfile);
322 : // create if it doesn't exist
323 : try{
324 13 : asdmDir.isEmpty(); // throws if dir doesn't exist
325 : }
326 13 : catch(AipsError x){
327 : try{
328 13 : asdmDir.create(false); // do not overwrite
329 : }
330 0 : catch(AipsError y){
331 : os << LogIO::SEVERE << "Error creating ASDM top directory: " << y.getMesg()
332 0 : << LogIO::POST;
333 0 : return false;
334 0 : }
335 13 : }
336 : // create ASDM binary output directory
337 13 : Directory asdmDir2(asdmfile+"/ASDMBinary");
338 : try{
339 13 : asdmDir2.create(false); // do not overwrite
340 : }
341 0 : catch(AipsError x){
342 : os << LogIO::SEVERE << "Error creating ASDMBinary directory: " << x.getMesg()
343 0 : << LogIO::POST;
344 0 : return false;
345 0 : }
346 13 : asdmDir_p = asdmfile;
347 13 : return true;
348 13 : }
349 :
350 :
351 536 : Int MS2ASDM::writeMainBinSubScanForOneDDIdFIdPair(const Int theDDId, const Int theFieldId,
352 : const String& datacolumn,
353 : const uInt theScan, const uInt theSubScan,
354 : const uInt startRow, const uInt endRow,
355 : const Tag eBlockId,
356 : int& datasize, asdm::EntityRef& dataOid,
357 : vector< asdm::Tag >& stateIdV){
358 :
359 1072 : LogIO os(LogOrigin("MS2ASDM", "writeMainBinForOneDDIdAndSubScan()"));
360 :
361 : // return values
362 536 : Int numIntegrations = 0;
363 536 : datasize = 0;
364 536 : dataOid = EntityRef();
365 536 : stateIdV.resize(0);
366 :
367 536 : asdm::ExecBlockRow* eBlockRow = (ASDM_p->getExecBlock()).getRowByKey(eBlockId);
368 1072 : string eBlockUID = eBlockRow->getExecBlockUID().getEntityId ().toString();
369 536 : int eBlockNum = eBlockRow->getExecBlockNum();
370 :
371 536 : Bool warned=false; // use later to avoid repetitive warnings
372 536 : Bool warned2=false; // use later to avoid repetitive warnings
373 :
374 : try{
375 :
376 536 : uInt nMainTabRows = ms_p.nrow();
377 :
378 536 : unsigned int subscanNum = theSubScan;
379 :
380 536 : if(startRow>=nMainTabRows){
381 : os << LogIO::SEVERE << "Internal error: startRow " << startRow << " exceeds end of MS."
382 0 : << LogIO::POST;
383 0 : return -1;
384 : }
385 :
386 536 : if(endRow>=nMainTabRows){
387 : os << LogIO::SEVERE << "Internal error: endRow " << endRow << " exceeds end of MS."
388 0 : << LogIO::POST;
389 0 : return -1;
390 : }
391 :
392 536 : Int DDId = dataDescId()(startRow);
393 536 : if(DDId != theDDId){ // check Data Description Id
394 : os << LogIO::SEVERE << "Internal error: input parameters to this routine are inconsistent.\n"
395 0 : << " DDId in start row should be as given in input parameters ==" << theDDId << LogIO::POST;
396 0 : return -1;
397 : }
398 :
399 536 : Int FId = fieldId()(startRow);
400 536 : if(FId != theFieldId){ // check Field Id
401 : os << LogIO::SEVERE << "Internal error: input parameters to this routine are inconsistent.\n"
402 0 : << " FieldId in start row should be as given in input parameters ==" << theFieldId << LogIO::POST;
403 0 : return -1;
404 : }
405 :
406 536 : if(verbosity_p>1){
407 : os << LogIO::NORMAL << "Writing Main table entries for DataDescId " << DDId
408 : << ", Field Id " << FId << ", ExecBlock " << eBlockNum << ", Scan number " << theScan
409 0 : << ", SubScan number " << theSubScan << LogIO::POST;
410 : }
411 :
412 : //////////////////////
413 : // Construct subscan == SDMDataObject
414 :
415 : // Assume MS main table is sorted in time.
416 :
417 : // Get first timestamp.
418 536 : Double subScanStartTime = time()(startRow);
419 536 : Double subScanEndTime = time()(endRow);
420 :
421 : // determine number of different timestamps in this subscan
422 536 : unsigned int numTimestampsCorr = 0;
423 536 : unsigned int numTimestampsAuto = 0;
424 1844784 : for(uInt i=startRow; i<=endRow; i++){
425 :
426 1844248 : DDId = dataDescId()(i);
427 1844248 : if(DDId != theDDId){ // skip all other Data Description Ids
428 955488 : continue;
429 : }
430 888760 : FId = fieldId()(i);
431 888760 : if(FId != theFieldId){ // skip all other Field Ids
432 192780 : continue;
433 : }
434 :
435 695980 : if(antenna1()(i)==antenna2()(i)){
436 27216 : numTimestampsAuto++;
437 : }
438 : else{
439 668764 : numTimestampsCorr++;
440 : }
441 : } // end for i
442 :
443 536 : if(verbosity_p>1){
444 0 : cout << " subscan number is " << subscanNum << endl;
445 0 : cout << " DDId " << theDDId << " FId " << theFieldId << endl;
446 0 : cout << " start row " << startRow << " end row " << endRow << endl;
447 0 : cout << " subscan number of timestamps with crosscorrelations is " << numTimestampsCorr << endl;
448 0 : cout << " subscan number of timestamps with autocorrelations is " << numTimestampsAuto << endl;
449 0 : cout << " subscan end time is " << subScanEndTime << endl;
450 : }
451 :
452 : // open disk file for subscan
453 1072 : String subscanFileName = asdmDir_p+"/ASDMBinary/"+String(getCurrentUidAsFileName());
454 536 : if(verbosity_p>1){
455 0 : cout << " subscan filename is " << subscanFileName << endl;
456 : }
457 : try{
458 536 : dataOid = EntityRef(getCurrentUid(),"","ASDM",asdmVersion_p);
459 : }
460 0 : catch(asdm::InvalidArgumentException x){
461 : os << LogIO::SEVERE << "Error creating ASDM: UID \"" << getCurrentUid()
462 0 : << "\" (intended for a BLOB) is not a valid Entity reference: " << x.getMessage()
463 0 : << LogIO::POST;
464 0 : return -1;
465 0 : }
466 :
467 : // make sure that this file doesn't exist yet
468 536 : ofstream ofs(subscanFileName.c_str());
469 :
470 : // set up SDMDataObjectWriter
471 :
472 1072 : SDMDataObjectWriter sdmdow(&ofs, getCurrentUid()); // use default title
473 :
474 536 : uint64_t startTime = (uint64_t) floor(subScanStartTime);
475 536 : unsigned int execBlockNum = eBlockNum; // constant for all scans
476 536 : unsigned int scanNum = theScan; // ASDM scan numbering starts at 1
477 536 : if(scanNum == 0 && !warned){
478 0 : os << LogIO::WARN << "Scan Number is 0. Note that by convention scan numbers in ASDMs should start at 1." << LogIO::POST;
479 0 : warned = true;
480 : }
481 :
482 : // find the first occurence of the timestamp which has the most baselines
483 536 : uInt theSampleStartRow = 0;
484 : {
485 536 : uInt maxNRows = 0;
486 :
487 536 : uInt mainTabRowX=startRow;
488 :
489 675592 : while(mainTabRowX <= endRow){
490 :
491 675056 : DDId = dataDescId()(mainTabRowX);
492 675056 : if(DDId != theDDId){ // skip all other Data Description Ids
493 477744 : mainTabRowX++;
494 477744 : continue;
495 : }
496 197312 : FId = fieldId()(mainTabRowX);
497 197312 : if(FId != theFieldId){ // skip all other Field Ids
498 192780 : mainTabRowX++;
499 192780 : continue;
500 : }
501 :
502 4532 : Double theTStamp = time()(mainTabRowX);
503 4532 : uInt sRow = mainTabRowX;
504 4532 : uInt nRows = 0;
505 4532 : while(mainTabRowX < nMainTabRows
506 1182312 : && time()(mainTabRowX)==theTStamp){
507 1177780 : DDId = dataDescId()(mainTabRowX);
508 1177780 : if(DDId != theDDId){ // skip all other Data Description Ids
509 481800 : mainTabRowX++;
510 481800 : continue;
511 : }
512 695980 : FId = fieldId()(mainTabRowX);
513 695980 : if(FId != theFieldId){ // skip all other Field Ids
514 0 : mainTabRowX++;
515 0 : continue;
516 : }
517 695980 : nRows++;
518 695980 : mainTabRowX++;
519 : }
520 4532 : if(nRows>maxNRows){
521 536 : maxNRows = nRows;
522 536 : theSampleStartRow = sRow;
523 : }
524 : } // end while
525 : }
526 :
527 : // determine actual number of baselines and antennas
528 : // (at the same time also fill the stateId vector)
529 536 : unsigned int numAutoCorrs = 0;
530 536 : unsigned int numBaselines = 0;
531 536 : unsigned int numAntennas = 0;
532 536 : vector<Int> ant;
533 : {
534 536 : uInt i = theSampleStartRow;
535 536 : Double thisTStamp = time()(i);
536 224054 : while(i<nMainTabRows && time()(i)== thisTStamp){
537 :
538 223518 : DDId = dataDescId()(i);
539 223518 : if(DDId != theDDId){ // skip all other Data Description Ids
540 4056 : i++;
541 4056 : continue;
542 : }
543 219462 : FId = fieldId()(i);
544 219462 : if(FId != theFieldId){ // skip all other Field Ids
545 0 : i++;
546 0 : continue;
547 : }
548 :
549 219462 : if(antenna1()(i) == antenna2()(i)){
550 216 : numAutoCorrs++;
551 : }
552 : else{
553 219246 : numBaselines++;
554 : }
555 :
556 219462 : Bool found = false;
557 3391720 : for(uInt j=0;j<ant.size();j++){
558 3390782 : if(antenna1()(i) == ant[j]){
559 218524 : found = true;
560 218524 : break;
561 : }
562 : }
563 219462 : if(!found){
564 938 : ant.push_back(antenna1()(i));
565 938 : stateIdV.push_back( asdmStateId_p[stateId()(i)] );
566 : }
567 219462 : found = false;
568 6776690 : for(uInt j=0;j<ant.size();j++){
569 6765160 : if(antenna2()(i) == ant[j]){
570 207932 : found = true;
571 207932 : break;
572 : }
573 : }
574 219462 : if(!found){
575 11530 : ant.push_back(antenna2()(i));
576 11530 : stateIdV.push_back( asdmStateId_p[stateId()(i)] );
577 : }
578 219462 : i++;
579 : }
580 : }
581 536 : numAntennas = ant.size();
582 :
583 : CorrelationModeMod::CorrelationMode correlationMode;
584 536 : if(numAutoCorrs==0){
585 512 : correlationMode = CorrelationModeMod::CROSS_ONLY;
586 : }
587 24 : else if(numBaselines>0){
588 24 : correlationMode = CorrelationModeMod::CROSS_AND_AUTO;
589 : }
590 : else{
591 0 : correlationMode = CorrelationModeMod::AUTO_ONLY;
592 : }
593 : // if datacolumn is FLOAT_DATA make correlation mode == AUTO as well!
594 :
595 :
596 536 : vector< AtmPhaseCorrectionMod::AtmPhaseCorrection > apc;
597 536 : if(dataIsAPCorrected()){
598 0 : apc.push_back(AtmPhaseCorrectionMod::AP_CORRECTED);
599 : }
600 : else{
601 536 : apc.push_back(AtmPhaseCorrectionMod::AP_UNCORRECTED);
602 : }
603 536 : vector< SDMDataObject::Baseband > basebands; // ???
604 :
605 : // construct spectral window and basedband vectors
606 :
607 536 : vector<SDMDataObject::SpectralWindow> spectralWindows;
608 :
609 : // for creating a Spectral Window
610 536 : uInt PolId = dataDescription().polarizationId()(theDDId);
611 536 : uInt numStokesMS = polarization().numCorr()(PolId);
612 :
613 536 : asdm::PolarizationRow* PR = (ASDM_p->getPolarization()).getRowByKey(asdmPolarizationId_p[PolId]);
614 536 : uInt numStokes = PR->getNumCorr();
615 536 : Array<Int> corrT = polarization().corrType()(PolId);
616 536 : vector<StokesParameterMod::StokesParameter> crossPolProducts = PR->getCorrType();
617 :
618 536 : vector<StokesParameterMod::StokesParameter> sdPolProduct;
619 536 : float scaleFactor = 1.;
620 536 : uInt spwId = dataDescription().spectralWindowId()(theDDId);
621 536 : unsigned int numSpectralPoint = spectralWindow().numChan()(spwId);
622 :
623 536 : OptionalSpectralResolutionType spectralResolution = SpectralResolutionTypeMod::FULL_RESOLUTION;
624 536 : if(numSpectralPoint<5){
625 : // spectralResolution = SpectralResolutionTypeMod::CHANNEL_AVERAGE;
626 312 : if(!warned2 && verbosity_p>1){
627 : // os << LogIO::NORMAL << " Less than 5 channels. Assuming data is of spectral resolution type \"CHANNEL_AVERAGE\"." << LogIO::POST;
628 : // }
629 : os << LogIO::NORMAL << " DDId " << theDDId << ": Less than 5 channels. Probably should use spectral resolution type \"CHANNEL_AVERAGE\"."
630 0 : << endl << " But this is not yet implemented. Assuming FULL_RESOLUTION." << LogIO::POST;
631 0 : warned2 = true;
632 : }
633 : }
634 :
635 536 : unsigned int numBin = 1; // number of switch cycles
636 536 : NetSidebandMod::NetSideband sideband = CNetSideband::from_int(spectralWindow().netSideband()(spwId));
637 :
638 : SDMDataObject::SpectralWindow spw(crossPolProducts,
639 : sdPolProduct,
640 : scaleFactor,
641 : numSpectralPoint,
642 : numBin,
643 536 : sideband);
644 :
645 536 : spectralWindows.push_back(spw);
646 :
647 :
648 536 : SDMDataObject::Baseband bband(BasebandNameMod::NOBB, spectralWindows); // how to select name ???? -> Francois
649 : // note: for ALMA only four basebands exist, not easy to find baseband for a given SPW
650 :
651 536 : basebands.push_back(bband);
652 :
653 : // construct binary parts for dataStruct
654 536 : unsigned int bpFlagsSize = numSpectralPoint * numStokes * (numBaselines+numAutoCorrs);
655 :
656 536 : vector<AxisNameMod::AxisName> bpFlagsAxes;
657 536 : bpFlagsAxes.push_back(AxisNameMod::TIM); // order: inner part of loop should be last!!!!!!
658 536 : bpFlagsAxes.push_back(AxisNameMod::SPP);
659 536 : bpFlagsAxes.push_back(AxisNameMod::POL);
660 536 : SDMDataObject::BinaryPart bpFlags(bpFlagsSize, bpFlagsAxes);
661 536 : if(verbosity_p>1){
662 0 : cout << "FlagsSize " << bpFlagsSize << " numStokes " << numStokes << endl;
663 : }
664 :
665 536 : unsigned int bpTimesSize = 0; // only needed for data blanking
666 : //unsigned int bpTimesSize = numTimestampsCorr+numTimestampsAuto;
667 536 : vector<AxisNameMod::AxisName> bpTimesAxes;
668 : // bpTimesAxes.push_back(AxisNameMod::TIM);
669 536 : SDMDataObject::BinaryPart bpActualTimes(bpTimesSize, bpTimesAxes);
670 : // cout << "TimesSize " << bpTimesSize << endl;
671 :
672 536 : unsigned int bpDurSize = 0; // only needed for data blanking
673 : // unsigned int bpDurSize = numTimestampsCorr+numTimestampsAuto;
674 536 : vector<AxisNameMod::AxisName> bpDurAxes;
675 : // bpDurAxes.push_back(AxisNameMod::TIM);
676 536 : SDMDataObject::BinaryPart bpActualDurations(bpDurSize, bpDurAxes);
677 : // cout << "DurSize " << bpDurSize << endl;
678 :
679 536 : unsigned int bpLagsSize = 0; // not filled for the moment (only useful if LAG_DATA column present) -> Francois
680 536 : vector<AxisNameMod::AxisName> bpLagsAxes;
681 536 : bpLagsAxes.push_back(AxisNameMod::SPP); // ******
682 536 : SDMDataObject::ZeroLagsBinaryPart bpZeroLags(bpLagsSize, bpLagsAxes, CorrelatorTypeMod::FXF); // ALMA default
683 536 : if(telName_p != "ALMA" && telName_p != "OSF"){
684 212 : if(telName_p == "ACA" || telName_p == "VLBA" || telName_p == "EVLA"){
685 2 : bpZeroLags = SDMDataObject::ZeroLagsBinaryPart(bpLagsSize, bpLagsAxes, CorrelatorTypeMod::FX);
686 : }
687 : else{
688 210 : bpZeroLags = SDMDataObject::ZeroLagsBinaryPart(bpLagsSize, bpLagsAxes, CorrelatorTypeMod::XF);
689 : }
690 : }
691 : // cout << "LagsSize " << bpLagsSize << endl;
692 :
693 536 : unsigned int bpCrossSize = numSpectralPoint * numStokes * numBaselines * 2; // real + imag
694 536 : vector<AxisNameMod::AxisName> bpCrossAxes;
695 : // bpCrossAxes.push_back(AxisNameMod::TIM);
696 536 : bpCrossAxes.push_back(AxisNameMod::BAL);
697 536 : bpCrossAxes.push_back(AxisNameMod::SPP);
698 536 : bpCrossAxes.push_back(AxisNameMod::POL);
699 536 : SDMDataObject::BinaryPart bpCrossData(bpCrossSize, bpCrossAxes);
700 : // cout << "CrossSize " << bpCrossSize << endl;
701 :
702 536 : unsigned int bpAutoSize = numSpectralPoint * numStokes * numAutoCorrs;
703 536 : vector<AxisNameMod::AxisName> bpAutoAxes;
704 : // bpAutoAxes.push_back(AxisNameMod::TIM);
705 536 : bpAutoAxes.push_back(AxisNameMod::ANT);
706 536 : bpAutoAxes.push_back(AxisNameMod::SPP);
707 536 : bpAutoAxes.push_back(AxisNameMod::POL);
708 536 : SDMDataObject::AutoDataBinaryPart bpAutoData(bpAutoSize, bpAutoAxes, false); // not normalised
709 : // cout << "AutoSize " << bpAutoSize << endl;
710 :
711 : SDMDataObject::DataStruct dataStruct( apc, basebands, bpFlags, bpActualTimes, bpActualDurations,
712 536 : bpZeroLags, bpCrossData, bpAutoData);
713 :
714 : // Parameters of dataStruct:
715 : // apc a vector of AtmPhaseCorrection. If apc is not relevant pass an empty vector.
716 : // basebands a vector of Baseband.
717 : // flags a BinaryPart object describing the flags. If flags is not relevant pass an
718 : // empty BinaryPart object.
719 : // actualTimes a BinaryPart object describing the actual times. If actualTimes is not
720 : // relevant pass an empty BinaryPart object.
721 : // actualDurations a BinaryPart object describing the actual durations. If actualDurations is
722 : // not relevant pass an empty BinaryPart object.
723 : // zeroLags a ZeroLagsBinaryPart object describing the zero lags. If zeroLags is not
724 : // relevant pass an empty ZeroLagsBinaryPart object.
725 : // crossData a BinaryPart object describing the cross data. If crossData is not relevant
726 : // pass an empty BinaryPart object.
727 : // autoData an AutoDataBinaryPart object describing the auto data. If autoData is not
728 : // relevant pass an empty AutoDataBinaryPart object.
729 :
730 :
731 : // Write the global header.
732 536 : sdmdow.corrDataHeader(startTime,
733 : eBlockUID,
734 : execBlockNum,
735 : scanNum,
736 : subscanNum,
737 : numAntennas,
738 : correlationMode, // the correlation mode.
739 : spectralResolution, // the spectral resolution.
740 : dataStruct); // the description of the structure of the binary data.
741 :
742 : //////////////////////////////////////////////////////
743 : // write the integrations until timestamp exceeds limit
744 536 : unsigned int integrationNum = 1;
745 536 : uInt mainTabRow=startRow;
746 :
747 675592 : while(mainTabRow <= endRow){
748 :
749 675056 : DDId = dataDescId()(mainTabRow);
750 675056 : if(DDId != theDDId){ // skip all other Data Description Ids
751 477744 : mainTabRow++;
752 670524 : continue;
753 : }
754 197312 : FId = fieldId()(mainTabRow);
755 197312 : if(FId != theFieldId){ // skip all other Field Ids
756 192780 : mainTabRow++;
757 192780 : continue;
758 : }
759 :
760 4532 : uint64_t timev = (uint64_t) floor((time()(mainTabRow))*1E9); // what units? nanoseconds
761 4532 : uint64_t intervalv = (uint64_t) floor(interval()(mainTabRow)*1E9);
762 4532 : vector< unsigned int > flags;
763 4532 : vector< int64_t > actualTimes;
764 4532 : vector< int64_t > actualDurations;
765 4532 : vector< float > zeroLags; // LAG_DATA, optional column, not used for the moment
766 4532 : vector< float > crossData;
767 : // vector< short > crossData;
768 : // vector< int > crossData; // standard case for ALMA
769 4532 : vector< float > autoData;
770 :
771 : ////////////////////////////////////////////////////////
772 : // fill data, time, and flag vectors for this timestamp
773 4532 : Double theTStamp = time()(mainTabRow);
774 :
775 : // SORT the data by baseline and antenna resp.!!!!!!!!!!!!
776 :
777 : // create a list of the row numbers in this timestamp sorted by baseline in BDF style,
778 : // i.e., e.g., for antennas (1,2,3,4): ['(1,1)', '(1,2)', '(2,2)', '(1,3)', '(2,3)', '(3,3)', '(1,4)',
779 : // '(2,4)', '(3,4)', '(4,4)', '(1,5)', '(2,5)', '(3,5)', '(4,5)', '(5,5)']
780 4532 : vector< uInt > rowsSorted;
781 : {
782 4532 : vector< uInt > rows;
783 4532 : while(mainTabRow < nMainTabRows
784 1182312 : && time()(mainTabRow)==theTStamp){
785 1177780 : DDId = dataDescId()(mainTabRow);
786 1177780 : if(DDId != theDDId){ // skip all other Data Description Ids
787 481800 : mainTabRow++;
788 481800 : continue;
789 : }
790 695980 : FId = fieldId()(mainTabRow);
791 695980 : if(FId != theFieldId){ // skip all other Field Ids
792 0 : mainTabRow++;
793 0 : continue;
794 : }
795 695980 : rows.push_back(mainTabRow);
796 695980 : mainTabRow++;
797 : }
798 :
799 4532 : uInt nRows = rows.size();
800 4532 : vector<Int> bLine(nRows);
801 4532 : uInt maxAnt = 0;
802 700512 : for(uInt i=0; i<nRows; i++){
803 695980 : uInt a2 = antenna2()(rows[i]);
804 695980 : bLine[i] = antenna1()(rows[i])*1000 + a2;
805 695980 : if(maxAnt<a2){
806 51492 : maxAnt=a2;
807 : }
808 : }
809 :
810 4532 : rowsSorted.resize(nRows);
811 4532 : uInt expNRows = maxAnt*(maxAnt+1)/2; // (zero-based counting)
812 4532 : uInt expNRowsWAuto = maxAnt*(maxAnt+1)/2 + maxAnt+1; // (zero-based counting)
813 4532 : Bool haveAuto = false;
814 4532 : if(nRows==expNRowsWAuto){
815 3024 : haveAuto=true;
816 : }
817 1508 : else if(nRows!=expNRows){
818 0 : ostringstream oss;
819 0 : oss << "Expected " << expNRows << " rows in integration but found " << nRows << endl;
820 0 : throw(asdmbinaries::SDMDataObjectWriterException(oss.str()));
821 0 : }
822 4532 : uInt count=0;
823 62744 : for(uInt i= (haveAuto ? 0 : 1) ; i<maxAnt+1; i++){
824 754192 : for(uInt j=0; j< (haveAuto ? i+1 : i); j++){
825 695980 : Int myBLine = j*1000 + i;
826 307030660 : for(uInt ii=0; ii<nRows; ii++){
827 307030660 : if(bLine[ii]==myBLine){
828 695980 : rowsSorted[count] = rows[ii];
829 695980 : break;
830 : }
831 306334680 : if(ii==nRows-1){ // not found
832 0 : ostringstream oss;
833 0 : oss << "Baseline " << myBLine << " not found." << endl;
834 0 : throw(asdmbinaries::SDMDataObjectWriterException(oss.str()));
835 0 : }
836 : }
837 695980 : count++;
838 : }
839 : }
840 :
841 4532 : }
842 :
843 700512 : for(uInt ii=0; ii<rowsSorted.size(); ii++){
844 :
845 695980 : uInt iRow = rowsSorted[ii];
846 :
847 695980 : DDId = dataDescId()(iRow);
848 695980 : FId = fieldId()(iRow);
849 :
850 695980 : Matrix<casacore::Complex> dat;
851 695980 : Matrix<Bool> flagsm;
852 695980 : String dataColumn(datacolumn);
853 695980 : dataColumn.upcase();
854 695980 : if(dataColumn == "MODEL"){
855 0 : dat.reference(modelData()(iRow));
856 : }
857 695980 : else if(dataColumn == "CORRECTED"){
858 0 : dat.reference(correctedData()(iRow));
859 : }
860 : else{
861 695980 : dat.reference(data()(iRow));
862 : }
863 695980 : flagsm.reference(flag()(iRow));
864 :
865 : //cout << " ii row a1 a2 " << ii << " " << iRow << " " << antenna1()(iRow) << " " << antenna2()(iRow) << endl;
866 :
867 695980 : Bool haveAuto = (antenna1()(iRow) == antenna2()(iRow));
868 :
869 695980 : if(haveAuto){
870 27216 : Complex x;
871 : float a;
872 1782648 : for(uInt i=0; i<numSpectralPoint; i++){
873 5266296 : for(uInt j=0; j<numStokesMS; j++){
874 3510864 : if(skipCorr_p[PolId][j]){
875 0 : continue;
876 : }
877 : else{
878 3510864 : x = dat(j,i);
879 3510864 : a = x.real();
880 3510864 : autoData.push_back( a );
881 : }
882 : }
883 : }
884 : }
885 : else{
886 668764 : casacore::Complex x;
887 : float a,b;
888 : // int a,b;
889 11565452 : for(uInt i=0; i<numSpectralPoint; i++){
890 31442064 : for(uInt j=0; j<numStokesMS; j++){
891 20545376 : x = dat(j,i);
892 20545376 : a = x.real();
893 20545376 : b = x.imag();
894 20545376 : crossData.push_back( a );
895 20545376 : crossData.push_back( b );
896 : }
897 : }
898 : }
899 :
900 : unsigned int ul;
901 13348100 : for(uInt i=0; i<numSpectralPoint; i++){
902 36708360 : for(uInt j=0; j<numStokesMS; j++){
903 24056240 : if(haveAuto && skipCorr_p[PolId][j]){
904 0 : continue;
905 : }
906 : else{
907 24056240 : if(flagRow()(iRow)){
908 159744 : ul = 1;
909 : }
910 : else{
911 23896496 : ul = flagsm(j,i);
912 : }
913 24056240 : flags.push_back( ul );
914 : }
915 : }
916 : }
917 : // the following two lines only needed for data blanking
918 : // actualTimes.push_back((int64_t)floor(time()(iRow))*1000.);
919 : // actualDurations.push_back((int64_t)floor(interval()(iRow))*1000.);
920 695980 : }// end loop over rows in this timestamp sorted by baseline
921 :
922 :
923 : // fill with flagged entries in case there are missing baselines in the MS
924 4532 : uInt nToAdd1 = 0;
925 4532 : uInt nToAdd2 = 0;
926 4532 : uInt nToAdd3 = 0;
927 4532 : uInt nToAdd4 = 0;
928 4532 : uInt nToAdd5 = 0;
929 4532 : uInt nToAdd6 = 0;
930 :
931 4532 : if(flags.size()<bpFlagsSize){
932 0 : nToAdd1 = bpFlagsSize - flags.size();
933 0 : for(uInt i=0; i<nToAdd1; i++){
934 0 : flags.push_back(1);
935 : }
936 : }
937 4532 : if(actualTimes.size()<bpTimesSize){
938 0 : nToAdd2 = bpTimesSize-actualTimes.size();
939 0 : for(uInt i=0; i<nToAdd2; i++){
940 0 : actualTimes.push_back(0);
941 : }
942 : }
943 4532 : if(actualDurations.size()<bpDurSize){
944 0 : nToAdd3 = bpDurSize-actualDurations.size();
945 0 : for(uInt i=0; i<nToAdd3; i++){
946 0 : actualDurations.push_back(0);
947 : }
948 : }
949 4532 : if(zeroLags.size()<bpLagsSize){
950 0 : nToAdd4 = bpLagsSize-zeroLags.size();
951 0 : for(uInt i=0; i<nToAdd4; i++){
952 0 : zeroLags.push_back(0.);
953 : }
954 : }
955 4532 : if(crossData.size()<bpCrossSize){
956 0 : nToAdd5 = bpCrossSize-crossData.size();
957 0 : for(uInt i=0; i<nToAdd5; i++){
958 0 : crossData.push_back(0.);
959 : }
960 : }
961 4532 : if(autoData.size()<bpAutoSize){
962 0 : nToAdd6 = bpAutoSize-autoData.size();
963 0 : for(uInt i=0; i<nToAdd6; i++){
964 0 : autoData.push_back(0.);
965 : }
966 : }
967 :
968 4532 : if(nToAdd1+nToAdd2+nToAdd3+nToAdd4+nToAdd5+nToAdd6>0){
969 : os << LogIO::WARN << "Encountered missing integrations for some baselines in MS."
970 : << " Will fill with flagged entries (" << nToAdd1 << ", " << nToAdd2 << ", " << nToAdd3
971 0 : << ", "<< nToAdd4 << ", "<< nToAdd5 << ", "<< nToAdd6 << ")" << LogIO::POST;
972 : }
973 :
974 : // finally write the integration
975 :
976 4532 : if(verbosity_p>1){
977 0 : cout << "Sizes: " << endl;
978 0 : cout << " flags " << flags.size() << endl;
979 0 : cout << " actualTimes " << actualTimes.size() << endl;
980 0 : cout << " actualDurations " << actualDurations.size() << endl;
981 0 : cout << " zeroLags " << zeroLags.size() << endl;
982 0 : cout << " crossData " << crossData.size() << endl;
983 0 : cout << " autoData " << autoData.size() << endl;
984 : }
985 :
986 : try{
987 :
988 4532 : sdmdow.addIntegration(integrationNum, // integration's index.
989 : timev, // midpoint
990 : intervalv, // time interval
991 : flags, // flags binary data
992 : actualTimes, // actual times binary data
993 : actualDurations, // actual durations binary data
994 : zeroLags, // zero lags binary data
995 : crossData, // cross data (can be short or int)
996 : autoData); // single dish data.
997 :
998 4532 : integrationNum++;
999 4532 : datasize += flags.size() * sizeof(unsigned int)
1000 4532 : + actualTimes.size() * sizeof( int64_t )
1001 4532 : + actualDurations.size() * sizeof( int64_t )
1002 4532 : + zeroLags.size() * sizeof( float )
1003 4532 : + crossData.size() * sizeof( float )
1004 4532 : + autoData.size() * sizeof( float );
1005 4532 : numIntegrations++;
1006 :
1007 : }
1008 0 : catch(asdmbinaries::SDMDataObjectWriterException x){
1009 0 : os << LogIO::WARN << "Error writing ASDM:" << x.getMessage() << endl
1010 : << "Will try to continue ..."
1011 0 : << LogIO::POST;
1012 0 : }
1013 : // (Note: subintegrations are used only for channel averaging to gain time res. by sacrificing spec. res.)
1014 :
1015 4532 : } // end while
1016 :
1017 536 : sdmdow.done();
1018 :
1019 536 : ofs.close();
1020 :
1021 : // end write subscan
1022 :
1023 536 : incrementUid();
1024 :
1025 536 : }
1026 0 : catch(asdmbinaries::SDMDataObjectWriterException x){
1027 0 : os << LogIO::SEVERE << "Error creating ASDM: " << x.getMessage()
1028 0 : << LogIO::POST;
1029 0 : return -1;
1030 0 : }
1031 0 : catch(asdmbinaries::SDMDataObjectException x){
1032 0 : os << LogIO::SEVERE << "Error creating ASDM: " << x.getMessage()
1033 0 : << LogIO::POST;
1034 0 : return -1;
1035 0 : }
1036 0 : catch(AipsError y){
1037 : os << LogIO::SEVERE << "Error creating ASDM: " << y.getMesg()
1038 0 : << LogIO::POST;
1039 0 : return -1;
1040 0 : }
1041 0 : catch(std::string z){
1042 : os << LogIO::SEVERE << "Error creating ASDM: " << z
1043 0 : << LogIO::POST;
1044 0 : return -1;
1045 0 : }
1046 0 : catch(std::exception zz){
1047 : os << LogIO::SEVERE << "Error creating ASDM: " << zz.what()
1048 0 : << LogIO::POST;
1049 0 : return -1;
1050 0 : }
1051 :
1052 536 : return numIntegrations;
1053 :
1054 536 : } // end writeMainBinForOneDDIdAndSubScan
1055 :
1056 :
1057 : /////////////////////////////////////
1058 : // // Pattern for wrting a non-binary table:
1059 : // Bool MS2ASDM::writeAntenna(){ // create asdm antenna table and fill antenna id map
1060 : // LogIO os(LogOrigin("MS2ASDM", "writeAntenna()"));
1061 :
1062 : // Bool rstat = true;
1063 :
1064 : // asdm::AntennaTable& tT = ASDM_p->getAntenna();
1065 :
1066 : // asdm::AntennaRow* tR = 0;
1067 :
1068 : // // tR = tT.newRow();
1069 :
1070 : // tT.add(tR);
1071 :
1072 : // EntityId theUid(getCurrentUid());
1073 : // Entity ent = tT.getEntity();
1074 : // ent.setEntityId(theUid);
1075 : // tT.setEntity(ent);
1076 : // if(verbosity_p>0){
1077 : // os << LogIO::NORMAL << "Filled Antenna table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1078 : // }
1079 : // incrementUid();
1080 :
1081 : // return rstat;
1082 : // }
1083 :
1084 14 : Bool MS2ASDM::writeStation(){ // create asdm station table and fill station id map
1085 28 : LogIO os(LogOrigin("MS2ASDM", "writeStation()"));
1086 :
1087 14 : Bool rstat = true;
1088 :
1089 14 : asdm::StationTable& tT = ASDM_p->getStation();
1090 :
1091 14 : asdm::StationRow* tR = 0;
1092 :
1093 : // MS has no station table; get information from the antenna table
1094 :
1095 273 : for(uInt irow=0; irow<antenna().nrow(); irow++){
1096 :
1097 : // parameters for the new station row
1098 259 : StationTypeMod::StationType type = StationTypeMod::ANTENNA_PAD;
1099 : // (alternatives are MAINTENANCE_PAD and WEATHER_STATION)
1100 :
1101 : // parameters of the new row
1102 518 : string name = antenna().station()(irow).c_str();
1103 :
1104 259 : vector<Length > position; // take the antenna position (!), (later set the ASDM antenna postion to 0,0,0)
1105 259 : Vector<Double > v; // aux. vector
1106 259 : v.reference(antenna().position()(irow));
1107 1036 : for(uInt i=0; i<v.size(); i++){
1108 777 : position.push_back(Length(v[i]));
1109 : }
1110 :
1111 259 : Tag stationId;
1112 259 : String sId = antenna().station()(irow);
1113 259 : tR = tT.newRow(name, position, type);
1114 :
1115 259 : asdm::StationRow* tR2 = 0;
1116 :
1117 259 : tR2 = tT.add(tR);
1118 259 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1119 : // enter tag into the map
1120 259 : asdmStationId_p[String(name)] = tR->getStationId();
1121 : }
1122 : else{
1123 0 : os << LogIO::SEVERE << "Duplicate station in MS Antenna table: " << irow << LogIO::POST;
1124 0 : return false;
1125 : }
1126 :
1127 259 : } // end for irow
1128 :
1129 14 : EntityId theUid(getCurrentUid());
1130 14 : Entity ent = tT.getEntity();
1131 14 : ent.setEntityId(theUid);
1132 14 : tT.setEntity(ent);
1133 14 : if(verbosity_p>0){
1134 14 : os << LogIO::NORMAL << "Filled Station table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1135 : }
1136 14 : incrementUid();
1137 :
1138 14 : return rstat;
1139 14 : }
1140 :
1141 14 : Bool MS2ASDM::writeAntenna(){ // create asdm antenna table and fill antenna id map
1142 28 : LogIO os(LogOrigin("MS2ASDM", "writeAntenna()"));
1143 :
1144 14 : Bool rstat = true;
1145 :
1146 14 : asdm::AntennaTable& tT = ASDM_p->getAntenna();
1147 :
1148 14 : asdm::AntennaRow* tR = 0;
1149 :
1150 273 : for(uInt irow=0; irow<antenna().nrow(); irow++){
1151 :
1152 : // parameters of the new row
1153 518 : string name = antenna().name()(irow).c_str();
1154 259 : AntennaMakeMod::AntennaMake antennaMake = AntennaMakeMod::UNDEFINED; // no info in MS (presently)
1155 259 : AntennaTypeMod::AntennaType antennaType = ASDMAntennaType( antenna().type()(irow) );
1156 259 : Length dishDiameter = Length( antenna().dishDiameter()(irow) );
1157 :
1158 259 : vector<Length > position;
1159 1036 : for(uInt i=0; i<3; i++){
1160 777 : position.push_back(Length(0.)); // the antenna position in the ASDM is the sum of station pos and antenna pos.
1161 : }
1162 :
1163 259 : vector<Length > offset;
1164 259 : Vector<Double > v; // aux. vector
1165 259 : v.reference(antenna().offset()(irow));
1166 1036 : for(uInt i=0; i<v.size(); i++){
1167 777 : offset.push_back(Length(v[i]));
1168 : }
1169 :
1170 259 : ArrayTime atime = ASDMArrayTime(time()(0)); // use start time of MS
1171 :
1172 259 : Tag stationId;
1173 259 : String sId = antenna().station()(irow); // the station name
1174 259 : if(asdmStationId_p.find(sId) != asdmStationId_p.end( )){
1175 259 : stationId = asdmStationId_p[sId];
1176 : }
1177 : else{
1178 0 : os << LogIO::SEVERE << "Internal error: No station ID defined for station name " << sId << LogIO::POST;
1179 0 : return false;
1180 : }
1181 :
1182 259 : tR = tT.newRow(name, antennaMake, antennaType, dishDiameter, position, offset, atime, stationId);
1183 :
1184 259 : asdm::AntennaRow* tR2 = 0;
1185 :
1186 259 : tR2 = tT.add(tR);
1187 259 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1188 : // enter tag into the map
1189 259 : asdmAntennaId_p[irow] = tR->getAntennaId();
1190 : }
1191 : else{
1192 0 : os << LogIO::WARN << "Duplicate row in MS Antenna table :" << irow << LogIO::POST;
1193 : }
1194 259 : }
1195 :
1196 14 : EntityId theUid(getCurrentUid());
1197 14 : Entity ent = tT.getEntity();
1198 14 : ent.setEntityId(theUid);
1199 14 : tT.setEntity(ent);
1200 14 : if(verbosity_p>0){
1201 14 : os << LogIO::NORMAL << "Filled Antenna table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1202 : }
1203 14 : incrementUid();
1204 :
1205 14 : return rstat;
1206 14 : }
1207 :
1208 14 : Bool MS2ASDM::writeSpectralWindow(){
1209 28 : LogIO os(LogOrigin("MS2ASDM", "writeSpectralWindow()"));
1210 :
1211 14 : Bool rstat = true;
1212 :
1213 14 : asdm::SpectralWindowTable& tT = ASDM_p->getSpectralWindow();
1214 :
1215 14 : asdm::SpectralWindowRow* tR = 0;
1216 :
1217 121 : for(uInt irow=0; irow<spectralWindow().nrow(); irow++){
1218 :
1219 : // parameters of the new row
1220 107 : BasebandNameMod::BasebandName basebandName = BasebandNameMod::NOBB;
1221 107 : if(!spectralWindow().bbcNo().isNull()){ // BBC_NO is an optional MS column
1222 74 : basebandName = ASDMBBName( spectralWindow().bbcNo()(irow) );
1223 : }
1224 107 : NetSidebandMod::NetSideband netSideband = ASDMNetSideBand( spectralWindow().netSideband()(irow) );
1225 107 : int numChan = spectralWindow().numChan()(irow);
1226 :
1227 214 : Frequency refFreq = Frequency( spectralWindow().refFrequencyQuant()(irow).getValue(unitASDMFreq()) );
1228 107 : SidebandProcessingModeMod::SidebandProcessingMode sidebandProcessingMode = SidebandProcessingModeMod::NONE;
1229 214 : Frequency totBandwidth = Frequency( spectralWindow().totalBandwidthQuant()(irow).getValue(unitASDMFreq()) );
1230 107 : WindowFunctionMod::WindowFunction windowFunction = WindowFunctionMod::UNIFORM;
1231 :
1232 107 : tR = tT.newRow(basebandName, netSideband, numChan, refFreq, sidebandProcessingMode, totBandwidth, windowFunction);
1233 :
1234 107 : Vector< Quantum<Double> > v;
1235 107 : vector< Frequency > chanFreqArray;
1236 107 : v.reference( spectralWindow().chanFreqQuant()(irow) );
1237 42265 : for(uInt i=0; i<v.nelements(); i++){
1238 42158 : chanFreqArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
1239 : }
1240 107 : tR->setChanFreqArray(chanFreqArray);
1241 :
1242 107 : vector< Frequency > chanWidthArray;
1243 107 : v.reference( spectralWindow().chanWidthQuant()(irow) );
1244 42265 : for(uInt i=0; i<v.nelements(); i++){
1245 42158 : chanWidthArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
1246 : }
1247 107 : tR->setChanWidthArray(chanWidthArray);
1248 :
1249 107 : vector< Frequency > effectiveBwArray;
1250 107 : v.reference( spectralWindow().effectiveBWQuant()(irow) );
1251 42265 : for(uInt i=0; i<v.nelements(); i++){
1252 42158 : effectiveBwArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
1253 : }
1254 107 : tR->setEffectiveBwArray(effectiveBwArray);
1255 :
1256 107 : vector< Frequency > resolutionArray;
1257 107 : v.reference( spectralWindow().resolutionQuant()(irow) );
1258 42265 : for(uInt i=0; i<v.nelements(); i++){
1259 42158 : resolutionArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
1260 : }
1261 107 : tR->setResolutionArray( resolutionArray );
1262 :
1263 107 : MFrequency::Types refFrame = MFrequency::castType(spectralWindow().measFreqRef()(irow));
1264 107 : FrequencyReferenceCodeMod::FrequencyReferenceCode measFreqRef = ASDMFreqRefCode( refFrame );
1265 107 : tR->setMeasFreqRef( measFreqRef );
1266 :
1267 107 : tR->setFreqGroup( spectralWindow().freqGroup()(irow) );
1268 :
1269 107 : tR->setFreqGroupName( string( spectralWindow().freqGroupName()(irow).c_str() ) );
1270 :
1271 107 : if(!spectralWindow().dopplerId().isNull()){ // DOPPLER_ID is an optional MS column
1272 0 : tR->setDopplerId( spectralWindow().dopplerId()(irow) );
1273 : }
1274 :
1275 : // add the row to the table
1276 107 : asdm::SpectralWindowRow* tR2 = 0;
1277 107 : tR2 = tT.add(tR);
1278 :
1279 107 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1280 : // enter tag into the map
1281 107 : asdmSpectralWindowId_p[irow] = tR->getSpectralWindowId();
1282 : }
1283 : else{
1284 0 : os << LogIO::WARN << "Duplicate row in MS Spectral Window table :" << irow << LogIO::POST;
1285 : }
1286 107 : } // end loop over MS SPW table
1287 :
1288 14 : EntityId theUid(getCurrentUid());
1289 14 : Entity ent = tT.getEntity();
1290 14 : ent.setEntityId(theUid);
1291 14 : tT.setEntity(ent);
1292 14 : if(verbosity_p>0){
1293 14 : os << LogIO::NORMAL << "Filled SpectralWindow table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1294 : }
1295 14 : incrementUid();
1296 :
1297 14 : return rstat;
1298 14 : }
1299 :
1300 14 : Bool MS2ASDM::writeSource(){ // create asdm source table and fill source id map
1301 28 : LogIO os(LogOrigin("MS2ASDM", "writeSource()"));
1302 :
1303 14 : Bool rstat = true;
1304 :
1305 14 : asdm::SourceTable& tT = ASDM_p->getSource();
1306 :
1307 14 : asdm::SourceRow* tR = 0;
1308 :
1309 14 : if(source().isNull()){// the source table doesn't exist (it is optional)
1310 : os << LogIO::WARN << "MS Source table doesn't exist (it is optional). Cannot create ASDM Source table."
1311 0 : << LogIO::POST;
1312 0 : rstat = true; // not an error
1313 : }
1314 : else {
1315 657 : for(uInt irow=0; irow<source().nrow(); irow++){
1316 :
1317 643 : Int sId = source().sourceId()(irow);
1318 :
1319 : // parameters of the new row
1320 :
1321 1286 : ArrayTimeInterval timeInterval( ASDMTimeInterval(source().timeQuant()(irow), source().intervalQuant()(irow)) );
1322 : //cout << "in writeSource: timeInterval " << source().time()(irow) << ", " << source().interval()(irow) << endl;
1323 : //cout << " timeInterval " << timeInterval.getStartInNanoSeconds() << ", " << timeInterval.getDurationInNanoSeconds() << endl;
1324 :
1325 643 : Int spwId = source().spectralWindowId()(irow);
1326 643 : Tag spectralWindowId;
1327 643 : if( asdmSpectralWindowId_p.find(spwId) == asdmSpectralWindowId_p.end( ) ){
1328 0 : os << LogIO::SEVERE << "Undefined SPW id " << spwId << " in MS Source table row "<< irow << LogIO::POST;
1329 0 : return false;
1330 : } else {
1331 643 : spectralWindowId = asdmSpectralWindowId_p[spwId];
1332 : }
1333 1286 : string code = source().code()(irow).c_str();
1334 643 : if(code=="" || code==" "){
1335 165 : code="-";
1336 : }
1337 643 : vector< Angle > direction;
1338 643 : MDirection theSourceDir = source().directionMeas()(irow);
1339 643 : direction.push_back( Angle( theSourceDir.getAngle( unitASDMAngle() ).getValue()(0) ) ); // RA
1340 643 : direction.push_back( Angle( theSourceDir.getAngle( unitASDMAngle() ).getValue()(1) ) ); // DEC
1341 :
1342 : MDirection::Types dirRef;
1343 643 : MDirection::getType(dirRef, theSourceDir.getRefString());
1344 : DirectionReferenceCodeMod::DirectionReferenceCode directionCode
1345 643 : = ASDMDirRefCode(dirRef);
1346 :
1347 643 : vector< AngularRate > properMotion;
1348 643 : if(!source().properMotionQuant().isNull()){
1349 643 : Vector< Quantity > pMV;
1350 643 : pMV.reference(source().properMotionQuant()(irow));
1351 : try{
1352 643 : properMotion.push_back( AngularRate( pMV[0].getValue(unitASDMAngularRate()) ) );
1353 643 : properMotion.push_back( AngularRate( pMV[1].getValue(unitASDMAngularRate()) ) );
1354 : }
1355 0 : catch(AipsError x){
1356 : os << LogIO::SEVERE << "Error accessing proper motion parameters in MS Source table row " << irow
1357 0 : << ":\n " << x.getMesg() << LogIO::POST;
1358 0 : }
1359 643 : }
1360 : else{
1361 0 : properMotion.push_back( AngularRate( 0. ) );
1362 0 : properMotion.push_back( AngularRate( 0. ) );
1363 : }
1364 :
1365 1286 : string sourceName = (source().name()(irow)).c_str();
1366 :
1367 643 : tR = tT.newRow(timeInterval, spectralWindowId, code, direction, properMotion, sourceName);
1368 :
1369 643 : tR->setDirectionCode(directionCode);
1370 :
1371 643 : asdm::SourceRow* tR2 = 0;
1372 : try{
1373 643 : tR2 = tT.add(tR);
1374 : }
1375 0 : catch(asdm::UniquenessViolationException x){
1376 : os << LogIO::WARN << "While creating ASDM: UID \"" << getCurrentUid()
1377 0 : << "\" Source table: " << x.getMessage() << endl
1378 : << "Will try to continue."
1379 0 : << LogIO::POST;
1380 0 : }
1381 :
1382 643 : if(tR2 != tR){ // did not lead to the creation of a new tag
1383 0 : os << LogIO::WARN << "Duplicate MS Source table row " << irow << ", source id " << sId << LogIO::POST;
1384 : }
1385 643 : if( asdmSourceId_p.find(sId) == asdmSourceId_p.end( ) ){
1386 255 : int souId = tR2->getSourceId();
1387 255 : asdmSourceId_p[sId] = souId;
1388 : }
1389 643 : } // end loop over source table
1390 : } // id if source table exists
1391 :
1392 14 : EntityId theUid(getCurrentUid());
1393 14 : Entity ent = tT.getEntity();
1394 14 : ent.setEntityId(theUid);
1395 14 : tT.setEntity(ent);
1396 14 : if(verbosity_p>0){
1397 14 : os << LogIO::NORMAL << "Filled Source table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1398 : }
1399 14 : incrementUid();
1400 :
1401 14 : return rstat;
1402 14 : }
1403 :
1404 :
1405 :
1406 14 : Bool MS2ASDM::writePolarization(){
1407 28 : LogIO os(LogOrigin("MS2ASDM", "writePolarization()"));
1408 :
1409 14 : Bool rstat = true;
1410 14 : asdm::PolarizationTable& tT = ASDM_p->getPolarization();
1411 :
1412 14 : asdm::PolarizationRow* tR = 0;
1413 :
1414 14 : skipCorr_p.resize(0);
1415 :
1416 51 : for(uInt irow=0; irow<polarization().nrow(); irow++){
1417 :
1418 37 : if(polarization().flagRow()(irow)){
1419 0 : continue;
1420 : }
1421 :
1422 37 : vector< Bool > skipCorr;
1423 :
1424 : // parameters of the new row
1425 :
1426 37 : vector< StokesParameterMod::StokesParameter > corrTypeV;
1427 37 : vector< vector< PolarizationTypeMod::PolarizationType > > corrProduct;
1428 :
1429 37 : Vector< Int > v; // aux. vector
1430 37 : v.reference( polarization().corrType()(irow) );
1431 86 : for(uInt i=0; i<v.nelements(); i++){
1432 49 : Bool skip = true;
1433 49 : Stokes::StokesTypes st = static_cast<Stokes::StokesTypes>(v[i]);
1434 49 : if(st == Stokes::LR){ // only add if RL is not also present
1435 1 : if(!stokesTypePresent(v, Stokes::RL)){
1436 0 : skip = false;
1437 : }
1438 : }
1439 48 : else if(st == Stokes::YX){ // only add if XY is not also present
1440 0 : if(!stokesTypePresent(v, Stokes::XY)){
1441 0 : skip = false;
1442 : }
1443 : }
1444 : else{
1445 48 : skip = false;
1446 : }
1447 49 : corrTypeV.push_back( ASDMStokesParameter( st ) );
1448 49 : skipCorr.push_back(skip);
1449 : }
1450 37 : int numCorr = corrTypeV.size();
1451 37 : skipCorr_p.push_back(skipCorr);
1452 :
1453 : // now read the just created corrTypeV and write the correlation products accordingly
1454 86 : for(uInt i=0; i<corrTypeV.size(); i++){
1455 49 : vector< PolarizationTypeMod::PolarizationType > w;
1456 49 : switch(corrTypeV[i]){
1457 1 : case StokesParameterMod::RR:
1458 1 : w.push_back(PolarizationTypeMod::R);
1459 1 : w.push_back(PolarizationTypeMod::R);
1460 1 : break;
1461 1 : case StokesParameterMod::RL:
1462 1 : w.push_back(PolarizationTypeMod::R);
1463 1 : w.push_back(PolarizationTypeMod::L);
1464 1 : break;
1465 1 : case StokesParameterMod::LR:
1466 1 : w.push_back(PolarizationTypeMod::L);
1467 1 : w.push_back(PolarizationTypeMod::R);
1468 1 : break;
1469 1 : case StokesParameterMod::LL:
1470 1 : w.push_back(PolarizationTypeMod::L);
1471 1 : w.push_back(PolarizationTypeMod::L);
1472 1 : break;
1473 33 : case StokesParameterMod::XX:
1474 33 : w.push_back(PolarizationTypeMod::X);
1475 33 : w.push_back(PolarizationTypeMod::X);
1476 33 : break;
1477 0 : case StokesParameterMod::XY:
1478 0 : w.push_back(PolarizationTypeMod::X);
1479 0 : w.push_back(PolarizationTypeMod::Y);
1480 0 : break;
1481 0 : case StokesParameterMod::YX:
1482 0 : w.push_back(PolarizationTypeMod::Y);
1483 0 : w.push_back(PolarizationTypeMod::X);
1484 0 : break;
1485 12 : case StokesParameterMod::YY:
1486 12 : w.push_back(PolarizationTypeMod::Y);
1487 12 : w.push_back(PolarizationTypeMod::Y);
1488 12 : break;
1489 0 : case StokesParameterMod::RX:
1490 0 : w.push_back(PolarizationTypeMod::R);
1491 0 : w.push_back(PolarizationTypeMod::X);
1492 0 : break;
1493 0 : case StokesParameterMod::RY:
1494 0 : w.push_back(PolarizationTypeMod::R);
1495 0 : w.push_back(PolarizationTypeMod::Y);
1496 0 : break;
1497 0 : case StokesParameterMod::LX:
1498 0 : w.push_back(PolarizationTypeMod::L);
1499 0 : w.push_back(PolarizationTypeMod::X);
1500 0 : break;
1501 0 : case StokesParameterMod::LY:
1502 0 : w.push_back(PolarizationTypeMod::L);
1503 0 : w.push_back(PolarizationTypeMod::Y);
1504 0 : break;
1505 0 : case StokesParameterMod::XR:
1506 0 : w.push_back(PolarizationTypeMod::X);
1507 0 : w.push_back(PolarizationTypeMod::R);
1508 0 : break;
1509 0 : case StokesParameterMod::XL:
1510 0 : w.push_back(PolarizationTypeMod::X);
1511 0 : w.push_back(PolarizationTypeMod::L);
1512 0 : break;
1513 0 : case StokesParameterMod::YR:
1514 0 : w.push_back(PolarizationTypeMod::Y);
1515 0 : w.push_back(PolarizationTypeMod::R);
1516 0 : break;
1517 0 : case StokesParameterMod::YL:
1518 0 : w.push_back(PolarizationTypeMod::Y);
1519 0 : w.push_back(PolarizationTypeMod::L);
1520 0 : break;
1521 0 : case StokesParameterMod::I:
1522 0 : os << LogIO::NORMAL << "Note: Stokes I (probably WVR data) stored with corr. types XX." << LogIO::POST;
1523 0 : w.push_back(PolarizationTypeMod::X);
1524 0 : w.push_back(PolarizationTypeMod::X);
1525 0 : break;
1526 0 : default:
1527 0 : os << LogIO::SEVERE << "Cannot store correlation product for stokes parameter " << CStokesParameter::name(corrTypeV[i]) << LogIO::POST;
1528 0 : rstat = false;
1529 0 : break;
1530 : }
1531 49 : corrProduct.push_back(w);
1532 49 : } // end loop over corrTypeV
1533 :
1534 37 : tR = tT.newRow(numCorr, corrTypeV, corrProduct);
1535 :
1536 : //cout << "ASDM numCorr is " << numCorr << endl;
1537 :
1538 : ////bool flagRow = polarization().flagRow()(irow);
1539 : ////tR->setFlagRow(flagRow);
1540 :
1541 : // add the row to the table
1542 37 : asdm::PolarizationRow* tR2 = 0;
1543 37 : tR2 = tT.add(tR);
1544 :
1545 37 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1546 : // enter tag into the map
1547 14 : asdmPolarizationId_p[irow] = tR->getPolarizationId();
1548 : }
1549 : else{
1550 23 : os << LogIO::WARN << "Duplicate row in MS Polarization table :" << irow << LogIO::POST;
1551 : }
1552 37 : } // end loop over MS Pol table
1553 :
1554 28 : EntityId theUid(getCurrentUid());
1555 14 : Entity ent = tT.getEntity();
1556 14 : ent.setEntityId(theUid);
1557 14 : tT.setEntity(ent);
1558 14 : if(verbosity_p>0){
1559 14 : os << LogIO::NORMAL << "Filled Polarization table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1560 : }
1561 14 : incrementUid();
1562 :
1563 28 : return rstat;
1564 14 : }
1565 :
1566 14 : Bool MS2ASDM::writeCorrelatorMode(){
1567 28 : LogIO os(LogOrigin("MS2ASDM", "writeCorrelatorMode()"));
1568 :
1569 14 : Bool rstat = true;
1570 14 : asdm::CorrelatorModeTable& tT = ASDM_p->getCorrelatorMode();
1571 :
1572 14 : asdm::CorrelatorModeRow* tR = 0;
1573 :
1574 : // create only one row
1575 :
1576 14 : int numBaseband = 1;
1577 14 : vector<BasebandNameMod::BasebandName > basebandNames;
1578 14 : basebandNames.push_back(BasebandNameMod::NOBB);
1579 14 : vector<int > basebandConfig;
1580 14 : basebandConfig.push_back(0);
1581 14 : AccumModeMod::AccumMode accumMode = AccumModeMod::NORMAL;
1582 14 : int binMode = 1; // standard setting for interferometry
1583 14 : int numAxes = 4; // time, antenna, stokes, pol
1584 14 : vector<AxisNameMod::AxisName > axesOrderArray;
1585 14 : axesOrderArray.push_back(AxisNameMod::TIM);
1586 14 : axesOrderArray.push_back(AxisNameMod::ANT);
1587 14 : axesOrderArray.push_back(AxisNameMod::SPP);
1588 14 : axesOrderArray.push_back(AxisNameMod::POL);
1589 14 : vector<FilterModeMod::FilterMode > filterMode;
1590 14 : filterMode.push_back(FilterModeMod::UNDEFINED);
1591 :
1592 14 : CorrelatorNameMod::CorrelatorName correlatorName = CorrelatorNameMod::ALMA_BASELINE; // the default
1593 14 : if(telName_p == "ALMA" || telName_p == "OSF"){
1594 9 : correlatorName = CorrelatorNameMod::ALMA_BASELINE; //???
1595 : }
1596 5 : else if(telName_p == "ACA"){
1597 0 : correlatorName = CorrelatorNameMod::ALMA_ACA; //???
1598 : }
1599 5 : else if(telName_p == "VLA"){
1600 0 : correlatorName = CorrelatorNameMod::NRAO_VLA; //???
1601 : }
1602 5 : else if(telName_p == "EVLA"){
1603 1 : correlatorName = CorrelatorNameMod::NRAO_WIDAR; //???
1604 : }
1605 4 : else if(telName_p == "PDB"){
1606 0 : correlatorName = CorrelatorNameMod::IRAM_PDB; //???
1607 : }
1608 : else{
1609 4 : os << LogIO::WARN << "Unknown telescope name: " << telName_p << ". Assuming ALMA_BASELINE." << LogIO::POST;
1610 : }
1611 :
1612 14 : tR = tT.newRow(numBaseband, basebandNames, basebandConfig, accumMode, binMode, numAxes, axesOrderArray, filterMode, correlatorName);
1613 :
1614 14 : tT.add(tR);
1615 :
1616 14 : EntityId theUid(getCurrentUid());
1617 14 : Entity ent = tT.getEntity();
1618 14 : ent.setEntityId(theUid);
1619 14 : tT.setEntity(ent);
1620 14 : if(verbosity_p>0){
1621 14 : os << LogIO::NORMAL << "Filled CorrelatorMode table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1622 : }
1623 14 : incrementUid();
1624 :
1625 14 : return rstat;
1626 14 : }
1627 :
1628 0 : Bool MS2ASDM::writeAlmaRadiometer(){
1629 0 : LogIO os(LogOrigin("MS2ASDM", "writeAlmaRadiometer()"));
1630 :
1631 0 : Bool rstat = true;
1632 0 : asdm::AlmaRadiometerTable& tT = ASDM_p->getAlmaRadiometer();
1633 :
1634 0 : asdm::AlmaRadiometerRow* tR = 0;
1635 :
1636 0 : tR = tT.newRow();
1637 :
1638 0 : tT.add(tR);
1639 :
1640 0 : EntityId theUid(getCurrentUid());
1641 0 : Entity ent = tT.getEntity();
1642 0 : ent.setEntityId(theUid);
1643 0 : tT.setEntity(ent);
1644 0 : if(verbosity_p>0){
1645 0 : os << LogIO::NORMAL << "Filled AlmaRadiometer table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1646 : }
1647 0 : incrementUid();
1648 :
1649 0 : return rstat;
1650 0 : }
1651 :
1652 0 : Bool MS2ASDM::writeHolography(){
1653 0 : LogIO os(LogOrigin("MS2ASDM", "writeHolography()"));
1654 :
1655 0 : Bool rstat = true;
1656 0 : asdm::HolographyTable& tT = ASDM_p->getHolography();
1657 :
1658 0 : asdm::HolographyRow* tR = 0;
1659 :
1660 : // tR = tT.newRow();
1661 :
1662 0 : tT.add(tR);
1663 :
1664 0 : EntityId theUid(getCurrentUid());
1665 0 : Entity ent = tT.getEntity();
1666 0 : ent.setEntityId(theUid);
1667 0 : tT.setEntity(ent);
1668 0 : if(verbosity_p>0){
1669 0 : os << LogIO::NORMAL << "Filled Holography table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1670 : }
1671 0 : incrementUid();
1672 :
1673 0 : return rstat;
1674 0 : }
1675 :
1676 14 : Bool MS2ASDM::writeProcessor(){
1677 28 : LogIO os(LogOrigin("MS2ASDM", "writeProcessor()"));
1678 :
1679 14 : Bool rstat = true;
1680 14 : asdm::ProcessorTable& tT = ASDM_p->getProcessor();
1681 :
1682 14 : asdm::ProcessorRow* tR = 0;
1683 :
1684 14 : uInt nPRows = processor().nrow();
1685 :
1686 14 : if(nPRows > 0){ // need to test because MS processor table is obligatory but may be empty
1687 8 : for(uInt irow=0; irow<nPRows; irow++){
1688 : // parameters of the new row
1689 4 : Tag modeId;
1690 : ProcessorTypeMod::ProcessorType processorType;
1691 : ProcessorSubTypeMod::ProcessorSubType processorSubType;
1692 4 : if(processor().type()(irow) == "CORRELATOR"){
1693 4 : processorType = ProcessorTypeMod::CORRELATOR;
1694 4 : if(processor().subType()(irow) == "ALMA_CORRELATOR_MODE"){
1695 0 : processorSubType = ProcessorSubTypeMod::ALMA_CORRELATOR_MODE;
1696 : }
1697 : else{
1698 8 : os << LogIO::WARN << "Unsupported processor subType for type CORRELATOR " << processor().subType()(irow)
1699 8 : << " assuming ALMA_CORRELATOR" << LogIO::POST;
1700 4 : processorSubType = ProcessorSubTypeMod::ALMA_CORRELATOR_MODE;
1701 : }
1702 : }
1703 0 : else if(processor().type()(irow) == "SPECTROMETER"){
1704 0 : processorType = ProcessorTypeMod::SPECTROMETER;
1705 0 : if(processor().subType()(irow) == "HOLOGRAPHY"){
1706 0 : processorSubType = ProcessorSubTypeMod::HOLOGRAPHY;
1707 : }
1708 : else{
1709 0 : os << LogIO::WARN << "Unsupported processor subType for type SPECTROMETER " << processor().subType()(irow)
1710 0 : << " assuming HOLOGRAPHY" << LogIO::POST;
1711 0 : processorSubType = ProcessorSubTypeMod::HOLOGRAPHY;
1712 : }
1713 : }
1714 0 : else if(processor().type()(irow) == "RADIOMETER"){
1715 0 : processorType = ProcessorTypeMod::RADIOMETER;
1716 0 : if(processor().subType()(irow) == "ALMA_RADIOMETER"){
1717 0 : processorSubType = ProcessorSubTypeMod::ALMA_RADIOMETER;
1718 : }
1719 : else{
1720 0 : os << LogIO::WARN << "Unsupported processor type " << processor().subType()(irow)
1721 0 : << " assuming ALMA_RADIOMETER" << LogIO::POST;
1722 0 : processorSubType = ProcessorSubTypeMod::ALMA_RADIOMETER;
1723 : }
1724 : }
1725 : else{
1726 0 : os << LogIO::WARN << "Unsupported processor type " << processor().type()(irow)
1727 0 : << " assuming CORRELATOR" << LogIO::POST;
1728 0 : processorType = ProcessorTypeMod::CORRELATOR;
1729 0 : processorSubType = ProcessorSubTypeMod::ALMA_CORRELATOR_MODE;
1730 : }
1731 :
1732 : // the following three vectors need to be declared outside the switch statement below;
1733 : // otherwise the compiler complains
1734 4 : vector< asdm::CorrelatorModeRow* > corrModeRows;
1735 4 : vector< asdm::HolographyRow* > holographyRows;
1736 4 : vector< asdm::AlmaRadiometerRow* > almaRadiometerRows;
1737 :
1738 4 : switch(processorSubType){
1739 4 : case ProcessorSubTypeMod::ALMA_CORRELATOR_MODE:
1740 4 : if(!writeCorrelatorMode()){ // create the optional CorrelatorMode table
1741 0 : return false;
1742 : }
1743 4 : corrModeRows = (ASDM_p->getCorrelatorMode()).get();
1744 4 : if(corrModeRows.size()==0){
1745 0 : os << LogIO::SEVERE << "Internal error: ASDM CorrelatorMode table is empty." << LogIO::POST;
1746 0 : return false;
1747 : }
1748 4 : modeId = corrModeRows[0]->getCorrelatorModeId(); // get tag from first row of CorrelatorMode table (there is only one) ???
1749 4 : break;
1750 0 : case ProcessorSubTypeMod::HOLOGRAPHY:
1751 0 : if(!writeHolography()){ // create the optional Holography table
1752 0 : return false;
1753 : }
1754 0 : holographyRows = (ASDM_p->getHolography()).get();
1755 0 : if(holographyRows.size()==0){
1756 0 : os << LogIO::SEVERE << "Internal error: ASDM Holography table is empty." << LogIO::POST;
1757 0 : return false;
1758 : }
1759 0 : modeId = holographyRows[0]->getHolographyId(); // get tag from first row of Holography table (there is only one) ???
1760 0 : break;
1761 0 : case ProcessorSubTypeMod::ALMA_RADIOMETER:
1762 0 : if(!writeAlmaRadiometer()){ // create the optional AlmaRadiometer table
1763 0 : return false;
1764 : }
1765 0 : almaRadiometerRows = (ASDM_p->getAlmaRadiometer()).get();
1766 0 : if(almaRadiometerRows.size()==0){
1767 0 : os << LogIO::SEVERE << "Internal error: ASDM AlmaRadiometer table is empty." << LogIO::POST;
1768 0 : return false;
1769 : }
1770 0 : modeId = almaRadiometerRows[0]->getAlmaRadiometerId(); // get tag from first row of AlmaRadiometer table (there is only one) ???
1771 0 : break;
1772 0 : default:
1773 : os << LogIO::SEVERE << "Internal error: unsupported processor sub type."
1774 0 : << CProcessorSubType::name(processorSubType) << LogIO::POST;
1775 0 : return false;
1776 : }
1777 :
1778 4 : tR = tT.newRow(modeId, processorType, processorSubType);
1779 : // add the row to the table
1780 4 : asdm::ProcessorRow* tR2 = 0;
1781 4 : tR2 = tT.add(tR);
1782 :
1783 4 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1784 : // enter tag into the map
1785 4 : asdmProcessorId_p[irow] = tR->getProcessorId();
1786 : }
1787 : else{
1788 0 : os << LogIO::WARN << "Duplicate row in MS Processor table :" << irow << LogIO::POST;
1789 : }
1790 4 : } // end loop over MS processor table
1791 : }
1792 : else{ // MS processor table is empty
1793 10 : os << LogIO::WARN << "MS Processor table is empty. Will try to proceed assuming a standard ALMA Correlator." << LogIO::POST;
1794 10 : ProcessorTypeMod::ProcessorType processorType = ProcessorTypeMod::CORRELATOR;
1795 10 : ProcessorSubTypeMod::ProcessorSubType processorSubType = ProcessorSubTypeMod::ALMA_CORRELATOR_MODE;
1796 10 : if(!writeCorrelatorMode()){ // create the optional CorrelatorMode table
1797 0 : return false;
1798 : }
1799 10 : vector< asdm::CorrelatorModeRow* > corrModeRows = ASDM_p->getCorrelatorMode().get();
1800 10 : if(corrModeRows.size()==0){
1801 0 : os << LogIO::SEVERE << "Internal error: ASDM CorrelatorMode table is empty." << LogIO::POST;
1802 0 : return false;
1803 : }
1804 10 : Tag modeId = corrModeRows[0]->getCorrelatorModeId(); // get tag from first row of CorrelatorMode table (there is only one) ???
1805 10 : tR = tT.newRow(modeId, processorType, processorSubType);
1806 10 : tT.add(tR);
1807 : // enter tag into the map connecting it to "-1"
1808 10 : asdmProcessorId_p[-1] = tR->getProcessorId();
1809 10 : } // end if
1810 :
1811 28 : EntityId theUid(getCurrentUid());
1812 14 : Entity ent = tT.getEntity();
1813 14 : ent.setEntityId(theUid);
1814 14 : tT.setEntity(ent);
1815 14 : if(verbosity_p>0){
1816 14 : os << LogIO::NORMAL << "Filled Processor table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1817 : }
1818 14 : incrementUid();
1819 :
1820 14 : return rstat;
1821 14 : }
1822 :
1823 :
1824 14 : Bool MS2ASDM::writeField(){
1825 28 : LogIO os(LogOrigin("MS2ASDM", "writeField()"));
1826 :
1827 14 : Bool rstat = true;
1828 14 : asdm::FieldTable& tT = ASDM_p->getField();
1829 :
1830 14 : asdm::FieldRow* tR = 0;
1831 :
1832 269 : for(uInt irow=0; irow<field().nrow(); irow++){
1833 :
1834 : // parameters of the new row
1835 510 : string fieldName = field().name()(irow).c_str();
1836 510 : string code = field().code()(irow).c_str();
1837 255 : if(code=="" || code==" "){
1838 27 : code="-";
1839 : }
1840 255 : int numPoly = field().numPoly()(irow) + 1; // MS give poly order, ASDM needs number of coefficients
1841 255 : if(numPoly>1){
1842 0 : os << LogIO::SEVERE << "Internal error: MS Field table with NUM_POLY > 0 not yet supported." << LogIO::POST;
1843 0 : return false;
1844 : }
1845 255 : Int numpol = 0;
1846 :
1847 255 : String msAngUnit = "rad"; // MS uses radians here
1848 255 : Matrix< Double > mdir; // aux. matrix
1849 :
1850 :
1851 : MDirection::Types phaseDirRef;
1852 255 : MDirection::getType(phaseDirRef, field().phaseDirMeasCol()(irow)(IPosition(1,0)).getRefString());
1853 : MDirection::Types delayDirRef;
1854 255 : MDirection::getType(delayDirRef, field().delayDirMeasCol()(irow)(IPosition(1,0)).getRefString());
1855 : MDirection::Types refDirRef;
1856 255 : MDirection::getType(refDirRef, field().referenceDirMeasCol()(irow)(IPosition(1,0)).getRefString());
1857 255 : if((phaseDirRef!=delayDirRef) || phaseDirRef!=refDirRef){
1858 : os << LogIO::SEVERE << "Internal error: the reference frames for phase, delay, and reference direction are not identical"
1859 : << "in the MS Field table row " << irow << "." << endl
1860 0 : << "Not yet supported case." << LogIO::POST;
1861 0 : return false;
1862 : }
1863 :
1864 : DirectionReferenceCodeMod::DirectionReferenceCode directionCode
1865 255 : = ASDMDirRefCode(phaseDirRef);
1866 :
1867 255 : vector< vector< Angle > > delayDirV;
1868 255 : mdir.reference(field().delayDir()(irow));
1869 : {
1870 255 : vector< Angle > dirV;
1871 255 : Quantity angle0(mdir(0,numpol), msAngUnit);
1872 255 : dirV.push_back(Angle(angle0.getValue(unitASDMAngle())));
1873 255 : Quantity angle1(mdir(1,numpol), msAngUnit);
1874 255 : dirV.push_back(Angle(angle1.getValue(unitASDMAngle())));
1875 255 : delayDirV.push_back(dirV);
1876 255 : }
1877 :
1878 255 : vector< vector< Angle > > phaseDirV;
1879 255 : mdir.reference(field().phaseDir()(irow));
1880 : {
1881 255 : vector< Angle > dirV;
1882 255 : Quantity angle0(mdir(0,numpol), msAngUnit);
1883 255 : dirV.push_back(Angle(angle0.getValue(unitASDMAngle())));
1884 255 : Quantity angle1(mdir(1,numpol), msAngUnit);
1885 255 : dirV.push_back(Angle(angle1.getValue(unitASDMAngle())));
1886 255 : phaseDirV.push_back(dirV);
1887 255 : }
1888 :
1889 255 : vector< vector< Angle > > referenceDirV;
1890 255 : mdir.reference(field().referenceDir()(irow));
1891 : {
1892 255 : vector< Angle > dirV;
1893 255 : Quantity angle0(mdir(0,numpol), msAngUnit);
1894 255 : dirV.push_back(Angle(angle0.getValue(unitASDMAngle())));
1895 255 : Quantity angle1(mdir(1,numpol), msAngUnit);
1896 255 : dirV.push_back(Angle(angle1.getValue(unitASDMAngle())));
1897 255 : referenceDirV.push_back(dirV);
1898 255 : }
1899 :
1900 : ////tR = tT.newRow(fieldName, code, numPoly, delayDirV, phaseDirV, referenceDirV);
1901 255 : tR = tT.newRow(fieldName, numPoly, delayDirV, phaseDirV, referenceDirV);
1902 :
1903 255 : tR->setCode(code);
1904 255 : tR->setDirectionCode(directionCode);
1905 255 : tR->setTime(ASDMArrayTime(field().timeQuant()(irow).getValue("s")));
1906 :
1907 255 : Int sId = field().sourceId()(irow);
1908 255 : if ( asdmSourceId_p.find(sId) != asdmSourceId_p.end( ) ) {
1909 255 : tR->setSourceId(asdmSourceId_p[sId]);
1910 : }
1911 0 : else if(sId!=-1){ // -1 means "no source"
1912 0 : os << LogIO::WARN << "Undefined source id " << sId << " in MS field table row " << irow << LogIO::POST;
1913 : }
1914 :
1915 : /*
1916 : if(!field().ephemerisId().isNull()){
1917 : Int eid = field().ephemerisId()(irow);
1918 : if(asdmEphemerisId_p.isDefined(eid)){
1919 : tR->setEphemerisId(asdmEphemerisId_p(eid));
1920 : }
1921 : else{
1922 : os << LogIO::WARN << "Undefined ephemeris id " << eid << " in MS field table row " << irow << LogIO::POST;
1923 : }
1924 : }
1925 : */
1926 : // add the row to the table
1927 255 : asdm::FieldRow* tR2 = 0;
1928 255 : tR2 = tT.add(tR);
1929 255 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1930 : // enter tag into the map
1931 255 : asdmFieldId_p[irow] = tR->getFieldId();
1932 : }
1933 : else{
1934 0 : if(sId == tR2->getSourceId()){ // if also the Source ID agrees, we really have a duplication
1935 0 : os << LogIO::SEVERE << "Duplicate row in MS Field table :" << irow << LogIO::POST;
1936 0 : return false;
1937 : }
1938 0 : fieldName = fieldName+"_B";
1939 0 : tR->setFieldName(fieldName);
1940 0 : tR2 = tT.add(tR);
1941 0 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1942 : os << LogIO::WARN << "Duplicate row in MS Field table :" << irow << endl
1943 0 : << " appended \"_B\" to field name for second occurrence. New field name: " << fieldName << LogIO::POST;
1944 0 : asdmFieldId_p[irow] = tR->getFieldId();
1945 : }
1946 : else{
1947 0 : os << LogIO::SEVERE << "Duplicate row in MS Field table :" << irow << LogIO::POST;
1948 0 : return false;
1949 : }
1950 : }
1951 255 : } // end loop over MS field table
1952 :
1953 14 : EntityId theUid(getCurrentUid());
1954 14 : Entity ent = tT.getEntity();
1955 14 : ent.setEntityId(theUid);
1956 14 : tT.setEntity(ent);
1957 14 : if(verbosity_p>0){
1958 14 : os << LogIO::NORMAL << "Filled Field table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1959 : }
1960 14 : incrementUid();
1961 :
1962 14 : return rstat;
1963 14 : }
1964 :
1965 :
1966 14 : Bool MS2ASDM::writeReceiver(){
1967 28 : LogIO os(LogOrigin("MS2ASDM", "writeReceiver()"));
1968 :
1969 14 : Bool rstat = true;
1970 14 : asdm::ReceiverTable& tT = ASDM_p->getReceiver();
1971 :
1972 14 : asdm::ReceiverRow* tR = 0;
1973 :
1974 : // create one row for each spectral window Id and time interval (i.e. receiverId is always == 0)
1975 :
1976 : // loop over ASDM SPW table
1977 14 : vector< asdm::SpectralWindowRow* > SPWRows = (ASDM_p->getSpectralWindow()).get();
1978 :
1979 14 : Bool informed = false;
1980 :
1981 121 : for(uInt irow=0; irow<SPWRows.size(); irow++){
1982 :
1983 : // parameters for the new Recevier table row
1984 107 : Tag spectralWindowId = SPWRows[irow]->getSpectralWindowId();
1985 107 : if(!informed){
1986 14 : if(verbosity_p>0){
1987 : os << LogIO::NORMAL << "Taking validity time interval for all ASDM Receiver table entries from row 0 of MS Feed table."
1988 14 : << LogIO::POST;
1989 : }
1990 14 : informed = true;
1991 : }
1992 214 : asdm::ArrayTimeInterval timeInterval( ASDMTimeInterval(feed().timeQuant()(0), feed().intervalQuant()(0)) );
1993 107 : string name = "unspec. frontend";
1994 : ReceiverBandMod::ReceiverBand frequencyBand;
1995 : ReceiverSidebandMod::ReceiverSideband receiverSideband;
1996 : double dummyF;
1997 107 : setRecBands(SPWRows[irow]->getRefFreq(), dummyF, frequencyBand, receiverSideband);
1998 107 : int numLO = 0; // no information in the MS ???
1999 107 : vector<Frequency > freqLO;
2000 : //freqLO.push_back(Frequency(1.)); // ???
2001 107 : vector<NetSidebandMod::NetSideband > sidebandLO;
2002 : //sidebandLO.push_back(SPWRows[irow]->getNetSideband()); // ???
2003 :
2004 107 : tR = tT.newRow(spectralWindowId, timeInterval, name, numLO, frequencyBand, freqLO, receiverSideband, sidebandLO);
2005 :
2006 : // add the row to the table
2007 107 : tT.add(tR);
2008 107 : } // end loop over SPW rows
2009 :
2010 14 : EntityId theUid(getCurrentUid());
2011 14 : Entity ent = tT.getEntity();
2012 14 : ent.setEntityId(theUid);
2013 14 : tT.setEntity(ent);
2014 14 : if(verbosity_p>0){
2015 14 : os << LogIO::NORMAL << "Filled Receiver table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
2016 : }
2017 14 : incrementUid();
2018 :
2019 14 : return rstat;
2020 14 : }
2021 :
2022 14 : Bool MS2ASDM::writeFeed(){
2023 28 : LogIO os(LogOrigin("MS2ASDM", "writeFeed()"));
2024 :
2025 14 : Bool rstat = true;
2026 14 : asdm::FeedTable& tT = ASDM_p->getFeed();
2027 :
2028 14 : asdm::FeedRow* tR = 0;
2029 :
2030 14 : Bool warned = false;
2031 14 : Bool warned2 = false;
2032 14 : Bool warned3 = false;
2033 :
2034 918 : for(uInt irow=0; irow<feed().nrow(); irow++){
2035 :
2036 : // parameters of the new feed row
2037 904 : Tag antennaId;
2038 904 : Int aid = feed().antennaId()(irow);
2039 904 : if( asdmAntennaId_p.find(aid) != asdmAntennaId_p.end( ) ){
2040 904 : antennaId = asdmAntennaId_p[aid];
2041 : }
2042 : else{
2043 0 : os << LogIO::SEVERE << "Undefined antenna id " << aid << " in MS feed table row "<< irow << LogIO::POST;
2044 0 : return false;
2045 : }
2046 1808 : ArrayTimeInterval timeInterval( ASDMTimeInterval(feed().timeQuant()(irow), feed().intervalQuant()(irow)) );
2047 :
2048 904 : int numReceptor = feed().numReceptors()(irow);
2049 :
2050 904 : vector< vector< double > > beamOffsetV;
2051 904 : vector< vector< Length > > focusReferenceV;
2052 904 : vector< PolarizationTypeMod::PolarizationType > polarizationTypesV;
2053 904 : vector< vector< asdm::Complex > > polResponseV;
2054 904 : vector< Angle > receptorAngleV;
2055 904 : vector< int > receiverIdV;
2056 :
2057 904 : Matrix< Double > mboffset; // aux. matrix
2058 904 : mboffset.reference(feed().beamOffset()(irow));
2059 :
2060 904 : Vector< String > polT; // aux. vector
2061 904 : polT.reference(feed().polarizationType()(irow));
2062 :
2063 904 : Matrix< Complex > polR;
2064 904 : polR.reference(feed().polResponse()(irow));
2065 :
2066 904 : Vector< Quantity > receptA;
2067 904 : receptA.reference(feed().receptorAngleQuant()(irow));
2068 :
2069 2712 : for(uInt rnum=0; rnum<(uInt)numReceptor; rnum++){ // loop over all receptors
2070 1808 : vector< double > abo;
2071 1808 : abo.push_back(mboffset(0,rnum));
2072 1808 : abo.push_back(mboffset(1,rnum));
2073 1808 : beamOffsetV.push_back(abo);
2074 :
2075 1808 : vector< Length > afr;
2076 1808 : afr.push_back(0); // x
2077 1808 : afr.push_back(0); // y
2078 1808 : if(!feed().focusLength().isNull()){ // the FOCUS_LENGTH column is optional
2079 1392 : afr.push_back(Length(feed().focusLength()(irow))); // z ???
2080 : }
2081 : else{
2082 416 : afr.push_back(0); // z
2083 : }
2084 1808 : focusReferenceV.push_back(afr);
2085 :
2086 : try{
2087 1808 : polarizationTypesV.push_back(CPolarizationType::literal(polT[rnum].c_str()));
2088 : }
2089 0 : catch(std::string z){
2090 0 : os << LogIO::SEVERE << "Polarization type " << polT[rnum].c_str() << " for receptor "
2091 : << rnum << " in MS Feed table row " << irow << " not defined in ASDM: "
2092 0 : << z << LogIO::POST;
2093 0 : return false;
2094 0 : }
2095 :
2096 1808 : vector< asdm::Complex > apr;
2097 5424 : for(uInt rnum2=0; rnum2<(uInt)numReceptor; rnum2++){
2098 3616 : apr.push_back( ASDMComplex( polR(rnum,rnum2) ) );
2099 : }
2100 1808 : polResponseV.push_back(apr);
2101 :
2102 1808 : receptorAngleV.push_back( Angle( receptA[rnum].getValue( unitASDMAngle() ) ) );
2103 :
2104 1808 : if(telName_p=="ALMA" || telName_p=="ACA" || telName_p == "OSF"){
2105 1624 : receiverIdV.push_back(0); // always zero for ALMA
2106 : }
2107 : else{
2108 184 : receiverIdV.push_back(0);
2109 184 : if(!warned){
2110 5 : os << LogIO::WARN << "Setting receiver ID to zero (ALMA convention)." << LogIO::POST;
2111 5 : warned = true;
2112 : }
2113 : }
2114 1808 : } // end loop over receptors
2115 :
2116 : // look at SPW Id parameter last!
2117 904 : Tag spectralWindowId;
2118 904 : vector< Tag > spwIdV; // the spw ids fow which to insert rows for this feed
2119 904 : Int spwid = feed().spectralWindowId()(irow);
2120 904 : if(spwid == -1){ // this means the MS Feed row is valid for all SPWs => need to insert same row for each SPW!
2121 : // loop over all SPWs
2122 600 : for(Int ispw=0; ispw<(Int)spectralWindow().nrow(); ispw++){
2123 392 : if( asdmSpectralWindowId_p.find(ispw) != asdmSpectralWindowId_p.end( ) ){
2124 392 : spectralWindowId = asdmSpectralWindowId_p[ispw];
2125 392 : spwIdV.push_back(spectralWindowId);
2126 : }
2127 : }
2128 : }
2129 696 : else if( asdmSpectralWindowId_p.find(spwid) != asdmSpectralWindowId_p.end( ) ){
2130 696 : spectralWindowId = asdmSpectralWindowId_p[spwid];
2131 696 : spwIdV.push_back(spectralWindowId); // just one entry
2132 : }
2133 : else{
2134 0 : os << LogIO::SEVERE << "Undefined SPW id " << spwid << " in MS feed table row "<< irow << LogIO::POST;
2135 0 : return false;
2136 : }
2137 :
2138 : // create the row for the first of the SPW Ids
2139 904 : tR = tT.newRow(antennaId, spwIdV[0], timeInterval, numReceptor, beamOffsetV, focusReferenceV,
2140 : polarizationTypesV, polResponseV, receptorAngleV, receiverIdV);
2141 :
2142 904 : if(telName_p=="ALMA" || telName_p=="ACA" || telName_p == "OSF"){
2143 812 : tR->setFeedNum(1); // always 1 for ALMA
2144 : }
2145 : else{
2146 92 : tR->setFeedNum(1);
2147 92 : if(!warned2){
2148 5 : os << LogIO::WARN << "Assuming single-feed receivers. Setting FeedNum to 1 (as for ALMA)." << LogIO::POST;
2149 5 : warned2 = true;
2150 : }
2151 : }
2152 :
2153 904 : vector< Length > positionV;
2154 904 : Vector< Quantity > pos;
2155 904 : pos.reference(feed().positionQuant()(irow));
2156 3616 : for(uInt i=0; i<3; i++){
2157 2712 : positionV.push_back( Length( pos[0].getValue( unitASDMLength() ) ) );
2158 : }
2159 904 : tR->setPosition(positionV);
2160 :
2161 904 : if(feed().beamId()(irow)!=-1 && !warned3){ // there should be a beam table in the MS, but presently it is not implemented!!!
2162 164 : os << LogIO::WARN << "MS Feed table contains reference to a Beam table row " << feed().beamId()(irow)
2163 328 : << " but a Beam table is not implemented in CASA. Ignoring." << LogIO::POST;
2164 : }
2165 :
2166 : // add the row to the table
2167 904 : tT.add(tR);
2168 :
2169 904 : int asdmFId = tR->getFeedId(); // the determination of the feed id is done internally by the add() method
2170 904 : Int fId = feed().feedId()(irow);
2171 904 : if( asdmFeedId_p.find(fId) != asdmFeedId_p.end( ) ){ // there is already a mapping
2172 890 : if(asdmFId!=asdmFeedId_p[fId]){ // but it doesn't agree with the newly defined id
2173 : os << LogIO::WARN << "Internal problem: field id map inconsistent for MS feed table row:" << irow
2174 0 : << ". MS FId " << fId << " is already mapped to ASDM FId" << asdmFeedId_p[fId]
2175 0 : << " but should also be mapped to ASDM FId " << asdmFId << LogIO::POST;
2176 : }
2177 : }
2178 : else{
2179 : // enter id into the map
2180 14 : asdmFeedId_p[fId] = asdmFId;
2181 : }
2182 :
2183 : // add the same row for the remaining SPW Ids in the vector accumulated above
2184 1088 : for(uint i=1; i<spwIdV.size(); i++){
2185 184 : tR = tT.newRow(antennaId, spwIdV[i], timeInterval, numReceptor, beamOffsetV, focusReferenceV,
2186 : polarizationTypesV, polResponseV, receptorAngleV, receiverIdV);
2187 184 : tT.add(tR);
2188 : }
2189 :
2190 904 : } // end loop over MS feed table
2191 :
2192 14 : EntityId theUid(getCurrentUid());
2193 14 : Entity ent = tT.getEntity();
2194 14 : ent.setEntityId(theUid);
2195 14 : tT.setEntity(ent);
2196 14 : if(verbosity_p>0){
2197 14 : os << LogIO::NORMAL << "Filled Feed table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
2198 : }
2199 14 : incrementUid();
2200 :
2201 14 : return rstat;
2202 14 : }
2203 :
2204 :
2205 14 : Bool MS2ASDM::writeDataDescription(){
2206 28 : LogIO os(LogOrigin("MS2ASDM", "writeDataDescription()"));
2207 :
2208 14 : Bool rstat = true;
2209 14 : asdm::DataDescriptionTable& tT = ASDM_p->getDataDescription();
2210 :
2211 14 : asdm::DataDescriptionRow* tR = 0;
2212 :
2213 : // loop over MS data description table
2214 121 : for(uInt irow=0; irow<dataDescription().nrow(); irow++){
2215 : // parameters for the new row
2216 107 : Tag polOrHoloId;
2217 107 : Tag spectralWindowId;
2218 107 : Int polId = dataDescription().polarizationId()(irow);
2219 107 : Int spwId = dataDescription().spectralWindowId()(irow);
2220 107 : if( asdmPolarizationId_p.find(polId) != asdmPolarizationId_p.end( ) ){
2221 107 : polOrHoloId = asdmPolarizationId_p[polId];
2222 : }
2223 : else{
2224 : os << LogIO::SEVERE << "Inconsistent MS: undefined polarization id " << polId
2225 0 : << " in row " << irow << " of the DataDesc table." << LogIO::POST;
2226 0 : return false;
2227 : }
2228 107 : if( asdmSpectralWindowId_p.find(spwId) != asdmSpectralWindowId_p.end( ) ){
2229 107 : spectralWindowId = asdmSpectralWindowId_p[spwId];
2230 : }
2231 : else{
2232 : os << LogIO::SEVERE << "Inconsistent MS: undefined SPW id " << spwId
2233 0 : << " in row " << irow << " of the DataDesc table." << LogIO::POST;
2234 0 : return false;
2235 : }
2236 :
2237 107 : tR = tT.newRow(polOrHoloId, spectralWindowId);
2238 :
2239 107 : asdm::DataDescriptionRow* tR2 = 0;
2240 :
2241 107 : tR2 = tT.add(tR);
2242 107 : if(tR2 == tR){ // adding this row caused a new tag to be defined
2243 : // enter tag into the map
2244 107 : asdmDataDescriptionId_p[irow] = tR->getDataDescriptionId();
2245 : }
2246 : else{
2247 0 : os << LogIO::WARN << "Duplicate row in MS DataDesc table :" << irow << LogIO::POST;
2248 : }
2249 107 : } // end loop over MS DD table
2250 :
2251 14 : EntityId theUid(getCurrentUid());
2252 14 : Entity ent = tT.getEntity();
2253 14 : ent.setEntityId(theUid);
2254 14 : tT.setEntity(ent);
2255 14 : if(verbosity_p>0){
2256 14 : os << LogIO::NORMAL << "Filled DataDescription table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
2257 : }
2258 14 : incrementUid();
2259 :
2260 14 : return rstat;
2261 14 : }
2262 :
2263 14 : Bool MS2ASDM::writeSwitchCycle(){
2264 28 : LogIO os(LogOrigin("MS2ASDM", "writeSwitchCycle()"));
2265 :
2266 14 : Bool rstat = true;
2267 :
2268 14 : asdm::SwitchCycleTable& tT = ASDM_p->getSwitchCycle();
2269 :
2270 14 : asdm::SwitchCycleRow* tR = 0;
2271 :
2272 : // switch cycle table will only be dummy ? -> Francois
2273 : // dummy if PHASE_ID column doesn't exist in MS main
2274 : // PHASE_ID identifies bin in switch cycle
2275 : // otherwise, e.g. PHASE_ID = 0 and 1 => numStep == 2
2276 :
2277 14 : if(phaseId().isNull()){ // phaseId column doesn't exist
2278 :
2279 : // parameters of the new row
2280 14 : int numStep = 1;
2281 14 : vector< float > weightArray;
2282 14 : weightArray.push_back(1.);
2283 14 : vector< vector< Angle > > dirOffsetArray;
2284 14 : vector< Angle > aV;
2285 14 : aV.push_back(Angle(0.));
2286 14 : aV.push_back(Angle(0.));
2287 14 : dirOffsetArray.push_back(aV);
2288 14 : vector< Frequency > freqOffsetArray;
2289 14 : freqOffsetArray.push_back(Frequency(0.));
2290 14 : vector< Interval > stepDurationArray;
2291 14 : stepDurationArray.push_back(Interval(0)); // set to zero ???
2292 :
2293 14 : tR = tT.newRow(numStep, weightArray, dirOffsetArray, freqOffsetArray, stepDurationArray);
2294 :
2295 14 : tT.add(tR);
2296 :
2297 14 : EntityId theUid(getCurrentUid());
2298 14 : Entity ent = tT.getEntity();
2299 14 : ent.setEntityId(theUid);
2300 14 : tT.setEntity(ent);
2301 14 : if(verbosity_p>0){
2302 : os << LogIO::NORMAL << "PHASE_ID column doesn't exist in MS Main table.\n Filled ASDM SwitchCycle table "
2303 14 : << getCurrentUid() << " with one dummy entry." << LogIO::POST;
2304 : }
2305 14 : incrementUid();
2306 14 : }
2307 : else{ // phaseId column exists
2308 : os << LogIO::SEVERE
2309 : << "PHASE_ID column exists in MS Main table but proper creation of ASDM SwitchCycle table not yet implemented."
2310 0 : << LogIO::POST;
2311 0 : rstat = false;
2312 : }
2313 :
2314 14 : return rstat;
2315 14 : }
2316 :
2317 14 : Bool MS2ASDM::writeState(){
2318 28 : LogIO os(LogOrigin("MS2ASDM", "writeState()"));
2319 :
2320 14 : Bool rstat = true;
2321 :
2322 14 : asdm::StateTable& tT = ASDM_p->getState();
2323 :
2324 14 : asdm::StateRow* tR = 0;
2325 :
2326 14 : if(state().nrow()<1){ // State table not filled
2327 :
2328 : os << LogIO::WARN << "MS State table is empty. Creating ASDM State table with one on-source entry."
2329 10 : << LogIO::POST;
2330 :
2331 : // parameters of the new row
2332 10 : bool bSig = true;
2333 10 : bool bRef = false;
2334 10 : bool bOnSky = true;
2335 10 : CalibrationDeviceMod::CalibrationDevice calDeviceName = CalibrationDeviceMod::NONE;
2336 :
2337 10 : tR = tT.newRow(calDeviceName, bSig, bRef, bOnSky);
2338 :
2339 10 : tR->setWeight(1.); // optional column
2340 :
2341 : // add the new row to the table
2342 10 : tT.add(tR);
2343 : // enter tag into the map
2344 10 : asdmStateId_p[-1] = tR->getStateId();
2345 : }
2346 : else{ // MS State table exists
2347 17 : for(uInt irow=0; irow<state().nrow(); irow++){
2348 : // parameters of the new row
2349 13 : bool bSig = state().sig()(irow);
2350 13 : bool bRef = state().ref()(irow);
2351 13 : Double loadT = state().load()(irow);
2352 13 : Double noiseT = state().cal()(irow);
2353 13 : bool bOnSky = bSig || bRef;
2354 : CalibrationDeviceMod::CalibrationDevice calDeviceName;
2355 13 : if(0.<loadT && loadT<270.){
2356 0 : calDeviceName = CalibrationDeviceMod::COLD_LOAD;
2357 : }
2358 13 : else if(270<=loadT && loadT<303.){
2359 0 : calDeviceName = CalibrationDeviceMod::AMBIENT_LOAD;
2360 : }
2361 13 : else if(303.<=loadT){
2362 0 : calDeviceName = CalibrationDeviceMod::HOT_LOAD;
2363 : }
2364 13 : else if(0.<noiseT){
2365 0 : calDeviceName = CalibrationDeviceMod::NOISE_TUBE_LOAD;
2366 : }
2367 : else{
2368 13 : calDeviceName = CalibrationDeviceMod::NONE;
2369 13 : if(!bSig){
2370 : os << LogIO::WARN << "Trouble determining Cal Device for row " << irow << " in MS State table."
2371 6 : << "Assuming NONE." << LogIO::POST;
2372 : }
2373 : }
2374 :
2375 13 : tR = tT.newRow(calDeviceName, bSig, bRef, bOnSky);
2376 :
2377 13 : tR->setWeight(1.); // optional column
2378 :
2379 : // add the new row to the table
2380 13 : asdm::StateRow* tR2 = 0;
2381 :
2382 13 : tR2 = tT.add(tR);
2383 : // enter tag into the map
2384 13 : asdmStateId_p[irow] = tR2->getStateId();
2385 13 : if(tR2 != tR){ // adding this row did not cause a new tag to be defined
2386 6 : os << LogIO::WARN << "Duplicate row in MS State table :" << irow << LogIO::POST;
2387 : }
2388 : } // end loop over MS state table
2389 : } // end else
2390 :
2391 14 : EntityId theUid(getCurrentUid());
2392 14 : Entity ent = tT.getEntity();
2393 14 : ent.setEntityId(theUid);
2394 14 : tT.setEntity(ent);
2395 14 : if(verbosity_p>0){
2396 14 : os << LogIO::NORMAL << "Filled State table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
2397 : }
2398 14 : incrementUid();
2399 :
2400 14 : return rstat;
2401 14 : }
2402 :
2403 14 : Bool MS2ASDM::writeSysCal(){
2404 28 : LogIO os(LogOrigin("MS2ASDM", "writeSysCal()"));
2405 :
2406 14 : Bool rstat = true;
2407 :
2408 14 : asdm::SysCalTable& tT = ASDM_p->getSysCal();
2409 :
2410 14 : asdm::SysCalRow* tR = 0;
2411 :
2412 14 : uInt nSysCalRows = sysCal().nrow();
2413 :
2414 14 : if(nSysCalRows<1){ // SysCal table not filled
2415 : os << LogIO::WARN << "MS SysCal table doesn't exist or is empty. Creating ASDM SysCal table with default entries."
2416 14 : << LogIO::POST;
2417 :
2418 : // loop over the main table
2419 14 : uInt nMainTabRows = ms_p.nrow();
2420 3807 : for(uInt mainTabRow=0; mainTabRow<nMainTabRows; mainTabRow++){
2421 :
2422 : // get DDId and feed id
2423 3793 : Int f1Id = feed1()(mainTabRow);
2424 3793 : Int f2Id = feed2()(mainTabRow);
2425 3793 : Int DDId = dataDescId()(mainTabRow);
2426 : // get start time stamp
2427 3793 : Double startTime = timestampStartSecs(mainTabRow);
2428 : // create vectors of info for each antenna
2429 3793 : vector< Int > aIdV;
2430 3793 : vector< Int > SPWIdV;
2431 3793 : vector< Int > feedIdV;
2432 3793 : vector< int > nRecV;
2433 3793 : vector< int > nChanV;
2434 3793 : MapWithDefault<Int, Int> antennaDone(-1);
2435 :
2436 3793 : uInt irow = mainTabRow;
2437 : // while ddid and feed id remain the same
2438 3793 : while(irow<nMainTabRows &&
2439 711100 : dataDescId()(irow) == DDId &&
2440 2129535 : feed1()(irow) == f1Id &&
2441 707321 : feed2()(irow) == f2Id
2442 : ){
2443 707321 : Int aId = antenna1()(irow);
2444 : // if info for given antenna not yet filled
2445 707321 : if( antennaDone.find(aId) == antennaDone.end( ) ){
2446 : // get info for antenna and fill vectors
2447 28746 : aIdV.push_back(aId);
2448 28746 : Int spwId = dataDescription().spectralWindowId()(DDId);
2449 28746 : SPWIdV.push_back(spwId);
2450 28746 : feedIdV.push_back(f1Id);
2451 28746 : nRecV.push_back(feed().numReceptors()(f1Id));
2452 28746 : nChanV.push_back(spectralWindow().numChan()(spwId));
2453 28746 : antennaDone[aId] = f1Id;
2454 : }
2455 707321 : aId = antenna2()(irow);
2456 : // if info for given antenna not yet filled
2457 707321 : if( antennaDone.find(aId) == antennaDone.end( ) ){
2458 : // get info for antenna and fill vectors
2459 4664 : aIdV.push_back(aId);
2460 4664 : Int spwId = dataDescription().spectralWindowId()(DDId);
2461 4664 : SPWIdV.push_back(spwId);
2462 4664 : feedIdV.push_back(f2Id);
2463 4664 : nRecV.push_back(feed().numReceptors()(f2Id));
2464 4664 : nChanV.push_back(spectralWindow().numChan()(spwId));
2465 4664 : antennaDone[aId] = f2Id;
2466 : }
2467 707321 : irow++;
2468 : } // end while
2469 : // get end timestamp
2470 3793 : Double endTime = timestampEndSecs(irow-1);
2471 : // create ArrayTimeInterval
2472 7586 : asdm::ArrayTimeInterval timeInterval( ASDMArrayTime(startTime),
2473 7586 : ASDMInterval(endTime-startTime) );
2474 : // create new rows in syscal table based on the vectors
2475 37203 : for(uInt i=0; i<aIdV.size(); i++){
2476 : // parameters of the new SysCal row
2477 33410 : Tag antennaId = asdmAntennaId_p[aIdV[i]];
2478 33410 : Tag spectralWindowId = asdmSpectralWindowId_p[SPWIdV[i]];
2479 33410 : int feedId = asdmFeedId_p[feedIdV[i]];
2480 33410 : int numReceptor = nRecV[i];
2481 33410 : int numChan = nChanV[i];
2482 :
2483 33410 : tR = tT.newRow(antennaId, spectralWindowId, timeInterval, feedId, numReceptor, numChan);
2484 :
2485 : // add the new row to the table
2486 33410 : tT.add(tR);
2487 33410 : }
2488 3793 : mainTabRow = irow;
2489 3793 : } // end loop over main table
2490 : }
2491 : else{ // MS SysCal table exists
2492 0 : for(uInt irow=0; irow<nSysCalRows; irow++){
2493 : // parameters of the new row
2494 0 : Tag antennaId = asdmAntennaId_p[ sysCal().antennaId()(irow) ];
2495 0 : Int spwId = sysCal().spectralWindowId()(irow);
2496 0 : Tag spectralWindowId = asdmSpectralWindowId_p[ spwId ];
2497 0 : int feedId = sysCal().feedId()(irow);
2498 0 : ArrayTimeInterval timeInterval( ASDMTimeInterval(sysCal().timeQuant()(irow), sysCal().intervalQuant()(irow)) );
2499 :
2500 0 : uInt numReceptor = feed().numReceptors()(feedId);
2501 0 : uInt nChan = spectralWindow().numChan()(spwId);
2502 :
2503 0 : tR = tT.newRow(antennaId, spectralWindowId, timeInterval, feedId, (int)numReceptor, (int)nChan);
2504 :
2505 :
2506 : // now set the optional columns if they exist in the MS
2507 :
2508 : // Tant
2509 0 : if(!sysCal().tantFlag().isNull()){
2510 0 : tR->setTantFlag(sysCal().tantFlag()(irow));
2511 : }
2512 0 : if(!sysCal().tantSpectrumQuant().isNull()){
2513 0 : Matrix< Quantum< Float > > sM;
2514 0 : sM.reference(sysCal().tantSpectrumQuant()(irow));
2515 0 : if(sM.shape()(0) != (Int)numReceptor){
2516 : os << LogIO::SEVERE << "Inconsistent MS: TANT spectrum in syscal table row " << irow
2517 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2518 0 : return false;
2519 : }
2520 0 : if(sM.shape()(1) != (Int)nChan){
2521 : os << LogIO::SEVERE << "Inconsistent MS: TANT spectrum in syscal table row " << irow
2522 0 : << " should have second dimension as referenced SPW." << LogIO::POST;
2523 0 : return false;
2524 : }
2525 0 : vector< vector< float > > fVV; // presently a float but should be a Temperature ???
2526 0 : for(uInt i=0; i<numReceptor; i++){
2527 0 : vector< float > fV;
2528 0 : for(uInt j=0; j<nChan; j++){
2529 0 : fV.push_back( sM(i,j).getValue(unitASDMTemp()) );
2530 : }
2531 0 : fVV.push_back(fV);
2532 0 : }
2533 0 : tR->setTantSpectrum(fVV);
2534 0 : }
2535 0 : else if(!sysCal().tantQuant().isNull()){
2536 0 : Vector< Quantum< Float > > sV;
2537 0 : sV.reference(sysCal().tantQuant()(irow));
2538 0 : vector< vector< float > > fVV; // presently a float but should be a Temperature ???
2539 0 : if(sV.size() != numReceptor){
2540 : os << LogIO::SEVERE << "Inconsistent MS: TANT in syscal table row " << irow
2541 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2542 0 : return false;
2543 : }
2544 0 : for(uInt i=0; i<numReceptor; i++){
2545 0 : vector< float > fV;
2546 0 : for(uInt j=0; j<nChan; j++){
2547 0 : fV.push_back( sV[i].getValue(unitASDMTemp()) );
2548 : }
2549 0 : fVV.push_back(fV);
2550 0 : }
2551 0 : tR->setTantSpectrum(fVV);
2552 0 : }
2553 :
2554 : // Tant/Tsys
2555 0 : if(!sysCal().tantTsysFlag().isNull()){
2556 0 : tR->setTantTsysFlag(sysCal().tantTsysFlag()(irow));
2557 : }
2558 0 : if(!sysCal().tantTsysSpectrum().isNull()){
2559 0 : Matrix< Float > sM;
2560 0 : sM.reference(sysCal().tantTsysSpectrum()(irow));
2561 0 : if(sM.shape()(0) != (Int)numReceptor){
2562 : os << LogIO::SEVERE << "Inconsistent MS: TANT_TSYS spectrum in syscal table row " << irow
2563 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2564 0 : return false;
2565 : }
2566 0 : if(sM.shape()(1) != (Int)nChan){
2567 : os << LogIO::SEVERE << "Inconsistent MS: TANT_TSYS spectrum in syscal table row " << irow
2568 0 : << " should have second dimension as referenced SPW." << LogIO::POST;
2569 0 : return false;
2570 : }
2571 0 : vector< vector< float > > fVV;
2572 0 : for(uInt i=0; i<numReceptor; i++){
2573 0 : vector< float > fV;
2574 0 : for(uInt j=0; j<nChan; j++){
2575 0 : fV.push_back( sM(i,j) );
2576 : }
2577 0 : fVV.push_back(fV);
2578 0 : }
2579 0 : tR->setTantTsysSpectrum(fVV);
2580 0 : }
2581 0 : else if(!sysCal().tantTsys().isNull()){
2582 0 : Vector< Float > sV;
2583 0 : sV.reference(sysCal().tantTsys()(irow));
2584 0 : vector< vector< float > > fVV;
2585 0 : if(sV.size() != numReceptor){
2586 : os << LogIO::SEVERE << "Inconsistent MS: TANT_TSYS in syscal table row " << irow
2587 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2588 0 : return false;
2589 : }
2590 0 : for(uInt i=0; i<numReceptor; i++){
2591 0 : vector< float > fV;
2592 0 : for(uInt j=0; j<nChan; j++){
2593 0 : fV.push_back( sV[i] );
2594 : }
2595 0 : fVV.push_back(fV);
2596 0 : }
2597 0 : tR->setTantTsysSpectrum(fVV);
2598 0 : }
2599 :
2600 : // Tcal
2601 0 : if(!sysCal().tcalFlag().isNull()){
2602 0 : tR->setTcalFlag(sysCal().tcalFlag()(irow));
2603 : }
2604 0 : if(!sysCal().tcalSpectrumQuant().isNull()){
2605 0 : Matrix< Quantum< Float > > sM;
2606 0 : sM.reference(sysCal().tcalSpectrumQuant()(irow));
2607 0 : if(sM.shape()(0) != (Int)numReceptor){
2608 : os << LogIO::SEVERE << "Inconsistent MS: TCAL spectrum in syscal table row " << irow
2609 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2610 0 : return false;
2611 : }
2612 0 : if(sM.shape()(1) != (Int)nChan){
2613 : os << LogIO::SEVERE << "Inconsistent MS: TCAL spectrum in syscal table row " << irow
2614 0 : << " should have second dimension as referenced SPW." << LogIO::POST;
2615 0 : return false;
2616 : }
2617 0 : vector< vector< Temperature > > fVV;
2618 0 : for(uInt i=0; i<numReceptor; i++){
2619 0 : vector< Temperature > fV;
2620 0 : for(uInt j=0; j<nChan; j++){
2621 0 : fV.push_back( Temperature(sM(i,j).getValue(unitASDMTemp())) );
2622 : }
2623 0 : fVV.push_back(fV);
2624 0 : }
2625 0 : tR->setTcalSpectrum(fVV);
2626 0 : }
2627 0 : else if(!sysCal().tcalQuant().isNull()){
2628 0 : Vector< Quantum< Float > > sV;
2629 0 : sV.reference(sysCal().tcalQuant()(irow));
2630 0 : vector< vector< Temperature > > fVV;
2631 0 : if(sV.size() != numReceptor){
2632 : os << LogIO::SEVERE << "Inconsistent MS: TCAL in syscal table row " << irow
2633 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2634 0 : return false;
2635 : }
2636 0 : for(uInt i=0; i<numReceptor; i++){
2637 0 : vector< Temperature > fV;
2638 0 : for(uInt j=0; j<nChan; j++){
2639 0 : fV.push_back( Temperature(sV[i].getValue(unitASDMTemp())) );
2640 : }
2641 0 : fVV.push_back(fV);
2642 0 : }
2643 0 : tR->setTcalSpectrum(fVV);
2644 0 : }
2645 :
2646 : // Trx
2647 0 : if(!sysCal().trxFlag().isNull()){
2648 0 : tR->setTrxFlag(sysCal().trxFlag()(irow));
2649 : }
2650 0 : if(!sysCal().trxSpectrumQuant().isNull()){
2651 0 : Matrix< Quantum< Float > > sM;
2652 0 : sM.reference(sysCal().trxSpectrumQuant()(irow));
2653 0 : if(sM.shape()(0) != (Int)numReceptor){
2654 : os << LogIO::SEVERE << "Inconsistent MS: TRX spectrum in syscal table row " << irow
2655 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2656 0 : return false;
2657 : }
2658 0 : if(sM.shape()(1) != (Int)nChan){
2659 : os << LogIO::SEVERE << "Inconsistent MS: TRX spectrum in syscal table row " << irow
2660 0 : << " should have second dimension as referenced SPW." << LogIO::POST;
2661 0 : return false;
2662 : }
2663 0 : vector< vector< Temperature > > fVV;
2664 0 : for(uInt i=0; i<numReceptor; i++){
2665 0 : vector< Temperature > fV;
2666 0 : for(uInt j=0; j<nChan; j++){
2667 0 : fV.push_back( Temperature(sM(i,j).getValue(unitASDMTemp())) );
2668 : }
2669 0 : fVV.push_back(fV);
2670 0 : }
2671 0 : tR->setTrxSpectrum(fVV);
2672 0 : }
2673 0 : else if(!sysCal().trxQuant().isNull()){
2674 0 : Vector< Quantum< Float > > sV;
2675 0 : sV.reference(sysCal().trxQuant()(irow));
2676 0 : vector< vector< Temperature > > fVV;
2677 0 : if(sV.size() != numReceptor){
2678 : os << LogIO::SEVERE << "Inconsistent MS: TRX in syscal table row " << irow
2679 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2680 0 : return false;
2681 : }
2682 0 : for(uInt i=0; i<numReceptor; i++){
2683 0 : vector< Temperature > fV;
2684 0 : for(uInt j=0; j<nChan; j++){
2685 0 : fV.push_back( Temperature(sV[i].getValue(unitASDMTemp())) );
2686 : }
2687 0 : fVV.push_back(fV);
2688 0 : }
2689 0 : tR->setTrxSpectrum(fVV);
2690 0 : }
2691 :
2692 : // Tsky
2693 0 : if(!sysCal().tskyFlag().isNull()){
2694 0 : tR->setTskyFlag(sysCal().tskyFlag()(irow));
2695 : }
2696 0 : if(!sysCal().tskySpectrumQuant().isNull()){
2697 0 : Matrix< Quantum< Float > > sM;
2698 0 : sM.reference(sysCal().tskySpectrumQuant()(irow));
2699 0 : if(sM.shape()(0) != (Int)numReceptor){
2700 : os << LogIO::SEVERE << "Inconsistent MS: TSKY spectrum in syscal table row " << irow
2701 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2702 0 : return false;
2703 : }
2704 0 : if(sM.shape()(1) != (Int)nChan){
2705 : os << LogIO::SEVERE << "Inconsistent MS: TSKY spectrum in syscal table row " << irow
2706 0 : << " should have second dimension as referenced SPW." << LogIO::POST;
2707 0 : return false;
2708 : }
2709 0 : vector< vector< Temperature > > fVV;
2710 0 : for(uInt i=0; i<numReceptor; i++){
2711 0 : vector< Temperature > fV;
2712 0 : for(uInt j=0; j<nChan; j++){
2713 0 : fV.push_back( Temperature(sM(i,j).getValue(unitASDMTemp())) );
2714 : }
2715 0 : fVV.push_back(fV);
2716 0 : }
2717 0 : tR->setTskySpectrum(fVV);
2718 0 : }
2719 0 : else if(!sysCal().tskyQuant().isNull()){
2720 0 : Vector< Quantum< Float > > sV;
2721 0 : sV.reference(sysCal().tskyQuant()(irow));
2722 0 : vector< vector< Temperature > > fVV;
2723 0 : if(sV.size() != numReceptor){
2724 : os << LogIO::SEVERE << "Inconsistent MS: TSKY in syscal table row " << irow
2725 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2726 0 : return false;
2727 : }
2728 0 : for(uInt i=0; i<numReceptor; i++){
2729 0 : vector< Temperature > fV;
2730 0 : for(uInt j=0; j<nChan; j++){
2731 0 : fV.push_back( Temperature(sV[i].getValue(unitASDMTemp())) );
2732 : }
2733 0 : fVV.push_back(fV);
2734 0 : }
2735 0 : tR->setTskySpectrum(fVV);
2736 0 : }
2737 :
2738 : // Tsys
2739 0 : if(!sysCal().tsysFlag().isNull()){
2740 0 : tR->setTsysFlag(sysCal().tsysFlag()(irow));
2741 : }
2742 0 : if(!sysCal().tsysSpectrumQuant().isNull()){
2743 0 : Matrix< Quantum< Float > > sM;
2744 0 : sM.reference(sysCal().tsysSpectrumQuant()(irow));
2745 0 : if(sM.shape()(0) != (Int)numReceptor){
2746 : os << LogIO::SEVERE << "Inconsistent MS: TSYS spectrum in syscal table row " << irow
2747 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2748 0 : return false;
2749 : }
2750 0 : if(sM.shape()(1) != (Int)nChan){
2751 : os << LogIO::SEVERE << "Inconsistent MS: TSYS spectrum in syscal table row " << irow
2752 0 : << " should have second dimension as referenced SPW." << LogIO::POST;
2753 0 : return false;
2754 : }
2755 0 : vector< vector< Temperature > > fVV;
2756 0 : for(uInt i=0; i<numReceptor; i++){
2757 0 : vector< Temperature > fV;
2758 0 : for(uInt j=0; j<nChan; j++){
2759 0 : fV.push_back( Temperature(sM(i,j).getValue(unitASDMTemp())) );
2760 : }
2761 0 : fVV.push_back(fV);
2762 0 : }
2763 0 : tR->setTsysSpectrum(fVV);
2764 0 : }
2765 0 : else if(!sysCal().tsysQuant().isNull()){
2766 0 : Vector< Quantum< Float > > sV;
2767 0 : sV.reference(sysCal().tsysQuant()(irow));
2768 0 : vector< vector< Temperature > > fVV;
2769 0 : if(sV.size() != numReceptor){
2770 : os << LogIO::SEVERE << "Inconsistent MS: TSYS in syscal table row " << irow
2771 0 : << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
2772 0 : return false;
2773 : }
2774 0 : for(uInt i=0; i<numReceptor; i++){
2775 0 : vector< Temperature > fV;
2776 0 : for(uInt j=0; j<nChan; j++){
2777 0 : fV.push_back( Temperature(sV[i].getValue(unitASDMTemp())) );
2778 : }
2779 0 : fVV.push_back(fV);
2780 0 : }
2781 0 : tR->setTsysSpectrum(fVV);
2782 0 : }
2783 :
2784 : // phase diff
2785 0 : if(!sysCal().phaseDiffFlag().isNull()){
2786 0 : tR->setPhaseDiffFlag(sysCal().phaseDiffFlag()(irow));
2787 : }
2788 0 : if(!sysCal().phaseDiffQuant().isNull()){
2789 0 : float pD = sysCal().phaseDiffQuant()(irow).getValue(unitASDMAngle());
2790 0 : vector< vector< float > > fVV;
2791 0 : for(uInt i=0; i<numReceptor; i++){
2792 0 : vector< float > fV;
2793 0 : for(uInt j=0; j<nChan; j++){
2794 0 : fV.push_back(pD);
2795 : }
2796 0 : fVV.push_back(fV);
2797 0 : }
2798 0 : tR->setPhaseDiffSpectrum(fVV);
2799 0 : }
2800 :
2801 : // finally add the completed new row to the table
2802 0 : asdm::SysCalRow* tR2 = 0;
2803 0 : tR2 = tT.add(tR);
2804 0 : if(tR2 != tR){
2805 0 : os << LogIO::WARN << "Duplicate row in MS SysCal table :" << irow << LogIO::POST;
2806 : }
2807 :
2808 0 : } // end loop over MS syscal table
2809 : } // end else
2810 :
2811 14 : EntityId theUid(getCurrentUid());
2812 14 : Entity ent = tT.getEntity();
2813 14 : ent.setEntityId(theUid);
2814 14 : tT.setEntity(ent);
2815 14 : if(verbosity_p>0){
2816 14 : os << LogIO::NORMAL << "Filled SysCal table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
2817 : }
2818 14 : incrementUid();
2819 :
2820 14 : return rstat;
2821 14 : }
2822 :
2823 :
2824 14 : Bool MS2ASDM::writeConfigDescription(){
2825 :
2826 28 : LogIO os(LogOrigin("MS2ASDM", "writeConfigDesc()"));
2827 :
2828 14 : Bool rstat = true;
2829 :
2830 14 : asdm::ConfigDescriptionTable& tT = ASDM_p->getConfigDescription();
2831 :
2832 14 : asdm::ProcessorTable& procT = ASDM_p->getProcessor();
2833 :
2834 14 : asdm::SwitchCycleTable& swcT = ASDM_p->getSwitchCycle();
2835 14 : vector< asdm::SwitchCycleRow * > swcRV = swcT.get();
2836 14 : Tag swcTag = swcRV[0]->getSwitchCycleId(); // preliminary implementation: get tag from first (and only) row
2837 :
2838 14 : uInt nMainTabRows = ms_p.nrow();
2839 14 : uInt nProcTabRows = processor().nrow();
2840 14 : Int dummyProcId = -1;
2841 14 : if(nProcTabRows<1){ // processor table not filled, all data should have proc id == -1
2842 10 : os << LogIO::WARN << "MS Processor table is empty. Will assume processor type is CORRELATOR." << LogIO::POST;
2843 10 : nProcTabRows = 1;
2844 10 : if(ms_p.nrow()>0 && processorId()(0)!=dummyProcId){
2845 : os << LogIO::WARN << " Still, the MS Main table seems to refer to an existing processor id "
2846 7 : << processorId()(0) << ". Will try to proceed ..." << LogIO::POST;
2847 7 : dummyProcId = processorId()(0); // accept other proc id (e.g. 0)
2848 : }
2849 : }
2850 :
2851 : // temprorarily needed until all processor types are supported
2852 14 : vector<Int> goodSpwV;
2853 14 : vector<Int> badSpwV;
2854 :
2855 : // loop over MS processor table (typically, this loop will only be executed once)
2856 28 : for(uInt uprocId=0; uprocId<nProcTabRows; uprocId++){
2857 :
2858 14 : Int procId = uprocId;
2859 :
2860 14 : if(processor().nrow()<1){
2861 10 : procId = dummyProcId;
2862 : }
2863 :
2864 14 : if(verbosity_p>0){
2865 14 : os << LogIO::NORMAL << "Processor Id: " << procId << LogIO::POST;
2866 : }
2867 :
2868 14 : asdm::ConfigDescriptionRow* tR = 0;
2869 :
2870 14 : Tag procIdTag;
2871 14 : if(asdmProcessorId_p.find(procId) != asdmProcessorId_p.end()){
2872 7 : procIdTag = asdmProcessorId_p[procId];
2873 : }
2874 : else{
2875 7 : if(procId == dummyProcId && asdmProcessorId_p.find(-1) != asdmProcessorId_p.end( )){ // there is no MS Proc table and the main table is
2876 7 : procIdTag = asdmProcessorId_p[-1]; // using wrong proc ids
2877 : }
2878 : else{
2879 0 : os << LogIO::SEVERE << "Internal error: undefined mapping for processor id " << procId << LogIO::POST;
2880 0 : return false;
2881 : }
2882 : }
2883 :
2884 : // get processor type from already existing ASDM processor table
2885 14 : ProcessorTypeMod::ProcessorType processorType = procT.getRowByKey(procIdTag)->getProcessorType();
2886 :
2887 : // loop over data description table
2888 121 : for(Int iDDId=0; iDDId<(Int)dataDescription().nrow(); iDDId++){
2889 :
2890 : // find first row in main table with this proc ID and extract spectral type
2891 107 : SpectralResolutionTypeMod::SpectralResolutionType spectralType = SpectralResolutionTypeMod::FULL_RESOLUTION;
2892 :
2893 107 : uInt jrow=0;
2894 2187239 : while(jrow<nMainTabRows){
2895 2187191 : if(processorId()(jrow)==procId && dataDescId()(jrow)==iDDId){
2896 59 : break;
2897 : }
2898 2187132 : jrow++;
2899 : }
2900 107 : if(jrow>=nMainTabRows){ // DDId-processor pair not found
2901 48 : continue;
2902 : }
2903 :
2904 : // temprorary solution until other processro types are supported
2905 59 : if(processorType!=ProcessorTypeMod::CORRELATOR){
2906 0 : badSpwV.push_back(dataDescription().spectralWindowId()(iDDId));
2907 : }
2908 : else{
2909 59 : goodSpwV.push_back(dataDescription().spectralWindowId()(iDDId));
2910 : }
2911 : ///////////
2912 :
2913 59 : if(asdmDataDescriptionId_p.find(iDDId) == asdmDataDescriptionId_p.end( )){
2914 : os << LogIO::SEVERE << "Internal error: undefined mapping for data desc. id " << iDDId
2915 0 : << " in main table row " << jrow << LogIO::POST;
2916 0 : return false;
2917 : }
2918 :
2919 59 : uInt spwId = dataDescription().spectralWindowId()(iDDId);
2920 59 : if(spectralWindow().numChan()(spwId)<5){
2921 : // spectralType = SpectralResolutionTypeMod::CHANNEL_AVERAGE;
2922 18 : if(verbosity_p>1){
2923 : // os << LogIO::NORMAL << " Less than 5 channels. Assuming data is of spectral resolution type \"CHANNEL_AVERAGE\"."
2924 : // << LogIO::POST;
2925 : os << LogIO::WARN << " SPW " << spwId << ": less than 5 channels. Probably should use spectral resolution type \"CHANNEL_AVERAGE\"."
2926 0 : << endl << " But this is not yet implemented. Assuming FULL_RESOLUTION." << LogIO::POST;
2927 : }
2928 : }
2929 :
2930 : // loop over MS Main table
2931 59 : Tag previousTag = Tag();
2932 651139 : for(uInt mainTabRow=jrow; mainTabRow<nMainTabRows; mainTabRow++){
2933 :
2934 651080 : if(dataDescId()(mainTabRow)!=iDDId || processorId()(mainTabRow)!=procId){
2935 645828 : continue;
2936 : }
2937 :
2938 5252 : if(verbosity_p>2){
2939 0 : cout << "proc id " << procId << " used at main table row " << mainTabRow << endl;
2940 : }
2941 :
2942 5252 : vector<Int> msAntennaIdV;
2943 5252 : vector<Int> msDDIdV;
2944 5252 : msDDIdV.push_back(iDDId); // always just this one entry
2945 5252 : vector<Int> msFeedIdV;
2946 5252 : vector<Int> msFeedKeyV;
2947 :
2948 5252 : vector<Tag> antennaId;
2949 5252 : vector<Tag> dataDId;
2950 5252 : vector<int> feedId;
2951 5252 : vector<Tag> switchCycleId;
2952 5252 : vector<AtmPhaseCorrectionMod::AtmPhaseCorrection> atmPhaseCorrection;
2953 5252 : int numAntenna = 0;
2954 5252 : int numDD = 0;
2955 5252 : int numFeed = 0;
2956 : CorrelationModeMod::CorrelationMode correlationMode;
2957 :
2958 : // loop over MS main table and find for this proc id, DDId, and timestamp
2959 : // a) all used antennas
2960 : // b) all used feed IDs
2961 5252 : uInt numAutoCorrs = 0;
2962 5252 : uInt numBaselines = 0;
2963 :
2964 5252 : uInt irow = mainTabRow;
2965 5252 : Double thisTStamp = time()(irow);
2966 :
2967 1372032 : while(irow<nMainTabRows && time()(irow)==thisTStamp){
2968 :
2969 1366780 : if(dataDescId()(irow)!=iDDId || processorId()(irow)!=procId){
2970 655680 : irow++;
2971 655680 : continue;
2972 : }
2973 :
2974 : // for the later determination of the correlation mode
2975 711100 : if(antenna1()(irow) == antenna2()(irow)){
2976 27216 : numAutoCorrs++;
2977 : }
2978 : else{
2979 683884 : numBaselines++;
2980 : }
2981 :
2982 : // antenna ids
2983 :
2984 711100 : Int aId = antenna1()(irow);
2985 711100 : Bool found = false;
2986 9219976 : for(uInt j=0; j<msAntennaIdV.size(); j++){
2987 9189608 : if(aId == msAntennaIdV[j]){
2988 680732 : found = true;
2989 680732 : break;
2990 : }
2991 : }
2992 711100 : if(!found){
2993 30368 : msAntennaIdV.push_back(aId);
2994 30368 : if(asdmAntennaId_p.find(aId) == asdmAntennaId_p.end( )){
2995 : os << LogIO::SEVERE << "Internal error: undefined mapping for antenna1 id " << aId
2996 0 : << " in main table row " << irow << LogIO::POST;
2997 0 : return false;
2998 : }
2999 : }
3000 711100 : aId = antenna2()(irow);
3001 711100 : found = false;
3002 18278924 : for(uInt j=0; j<msAntennaIdV.size(); j++){
3003 18244532 : if(aId == msAntennaIdV[j]){
3004 676708 : found = true;
3005 676708 : break;
3006 : }
3007 : }
3008 711100 : if(!found){
3009 34392 : msAntennaIdV.push_back(aId);
3010 34392 : if(asdmAntennaId_p.find(aId) == asdmAntennaId_p.end( )){
3011 : os << LogIO::SEVERE << "Internal error: undefined mapping for antenna2 id " << aId
3012 0 : << " in main table row " << irow << LogIO::POST;
3013 0 : return false;
3014 : }
3015 : }
3016 :
3017 :
3018 : // feed ids
3019 711100 : Int fIdi = feed1()(irow);
3020 711100 : Int fKeyi = fIdi + 10000*antenna1()(irow);
3021 711100 : found = false;
3022 9219976 : for(uInt j=0;j<msFeedKeyV.size();j++){
3023 9189608 : if(fKeyi == msFeedKeyV[j]){
3024 680732 : found = true;
3025 680732 : break;
3026 : }
3027 : }
3028 711100 : if(!found){
3029 30368 : msFeedKeyV.push_back(fKeyi);
3030 30368 : msFeedIdV.push_back(fIdi);
3031 30368 : if(asdmFeedId_p.find(fIdi) == asdmFeedId_p.end( )){
3032 : os << LogIO::SEVERE << "Internal error: undefined mapping for feed1 id " << fIdi
3033 0 : << " in main table row " << irow << LogIO::POST;
3034 0 : return false;
3035 : }
3036 : }
3037 711100 : fIdi = feed2()(irow);
3038 711100 : fKeyi = fIdi + 10000*antenna2()(irow);
3039 711100 : found = false;
3040 18278924 : for(uInt j=0;j<msFeedKeyV.size();j++){
3041 18244532 : if(fKeyi == msFeedKeyV[j]){
3042 676708 : found = true;
3043 676708 : break;
3044 : }
3045 : }
3046 711100 : if(!found){
3047 34392 : msFeedKeyV.push_back(fKeyi);
3048 34392 : msFeedIdV.push_back(fIdi);
3049 34392 : if(asdmFeedId_p.find(fIdi) == asdmFeedId_p.end( )){
3050 : os << LogIO::SEVERE << "Internal error: undefined mapping for feed2 id " << fIdi
3051 0 : << " in main table row " << irow << LogIO::POST;
3052 0 : return false;
3053 : }
3054 : }
3055 :
3056 711100 : irow++;
3057 : } // end while
3058 :
3059 : // sort the antenna ids before entering them into the ConfigDescription table
3060 5252 : std::sort(msAntennaIdV.begin(), msAntennaIdV.end());
3061 70012 : for(uInt i=0; i<msAntennaIdV.size(); i++){
3062 64760 : antennaId.push_back(asdmAntennaId_p[msAntennaIdV[i]]);
3063 : }
3064 5252 : numAntenna = antennaId.size();
3065 :
3066 : // (there is just one DDId per config description in this scheme)
3067 5252 : dataDId.push_back(asdmDataDescriptionId_p[msDDIdV[0]]);
3068 5252 : numDD = 1;
3069 :
3070 : // sort the feed ids before entering them into the ConfigDescription table
3071 5252 : std::sort(msFeedIdV.begin(), msFeedIdV.end());
3072 70012 : for(uInt i=0; i<msFeedIdV.size(); i++){
3073 64760 : feedId.push_back(asdmFeedId_p[msFeedIdV[i]]);
3074 : }
3075 5252 : numFeed = feedId.size();
3076 5252 : if(numAntenna>1){
3077 5252 : numFeed = numFeed/numAntenna;
3078 : }
3079 :
3080 5252 : if(numAutoCorrs==0){
3081 2228 : correlationMode = CorrelationModeMod::CROSS_ONLY;
3082 : }
3083 3024 : else if(numBaselines>0){
3084 3024 : correlationMode = CorrelationModeMod::CROSS_AND_AUTO;
3085 : }
3086 : else{
3087 0 : correlationMode = CorrelationModeMod::AUTO_ONLY;
3088 : }
3089 :
3090 5252 : switchCycleId.push_back(swcTag); // switch cycle table will only be dummy ? -> Francois
3091 : // dummy if PHASE_ID column doesn't exist in MS main
3092 : // PHASE_ID identifies bin in switch cycle
3093 : // otherwise, e.g. PHASE_ID = 0 and 1 => numStep == 2
3094 :
3095 5252 : if(dataIsAPCorrected()){
3096 0 : atmPhaseCorrection.push_back(AtmPhaseCorrectionMod::AP_CORRECTED);
3097 : }
3098 : else{
3099 5252 : atmPhaseCorrection.push_back(AtmPhaseCorrectionMod::AP_UNCORRECTED);
3100 : }
3101 :
3102 : // create a new row with its mandatory attributes.
3103 10504 : tR = tT.newRow (numAntenna,
3104 : numDD,
3105 : numFeed,
3106 : correlationMode,
3107 5252 : atmPhaseCorrection.size(),
3108 : atmPhaseCorrection,
3109 : processorType,
3110 : spectralType,
3111 : antennaId,
3112 : feedId,
3113 : switchCycleId,
3114 : dataDId,
3115 : procIdTag);
3116 :
3117 : // optional attributes.
3118 : //vector<Tag> assocConfigDescriptionId(1);
3119 : //assocConfigDescriptionId[0] = Tag(1, TagType::ConfigDescription);
3120 : //vector<int> phasedArrayList(2);
3121 : //phasedArrayList[0] = 0;
3122 : //phasedArrayList[1] = 1;
3123 : //vector<bool> flagAnt(2, false);
3124 : // vector<SpectralResolutionTypeMod::SpectralResolutionType> assocNature(1);
3125 : //assocNature[0] = SpectralResolutionTypeMod::FULL_RESOLUTION;
3126 : //tR->setAssocConfigDescriptionId(assocConfigDescriptionId);
3127 : //tR->setPhasedArrayList(phasedArrayList);
3128 : //tR->setFlagAnt(flagAnt);
3129 : //tR->setAssocNature(assocNature);
3130 :
3131 : // add this row to to the config description table.
3132 : // note that this will check for uniqueness
3133 5252 : asdm::ConfigDescriptionRow* tR2 = 0;
3134 :
3135 5252 : tR2 = tT.add(tR);
3136 5252 : Tag newTag = tR2->getConfigDescriptionId();
3137 5252 : asdmConfigDescriptionId_p[mainTabRow] = newTag;
3138 5252 : if(verbosity_p>1){
3139 0 : cout << "Defined conf desc id for main table row " << mainTabRow << endl;
3140 : }
3141 :
3142 5252 : mainTabRow = irow-1;
3143 :
3144 5252 : } // end loop over remainder of timestamp in MS main table
3145 :
3146 59 : } // end loop over MS DD table
3147 :
3148 14 : } // end loop over MS processor table
3149 :
3150 : // temporarily needed until all processor types are supported
3151 14 : if(badSpwV.size() > 0){
3152 : os << LogIO::SEVERE << "Input MS contains data which is not of processor type CORRELATOR.\n"
3153 : << "Writing this data to an ASDM is not yet properly supported by exportasdm.\n"
3154 0 : << "As a temporary solution please create an input MS containing only the following SPWs" << LogIO::POST;
3155 0 : for(uInt ii=0; ii<goodSpwV.size(); ii++){
3156 0 : os << LogIO::SEVERE << " " << goodSpwV[ii] << " " << LogIO::POST;
3157 : }
3158 0 : os << LogIO::SEVERE << "using task \"split\"." << LogIO::POST;
3159 0 : return false;
3160 : }
3161 :
3162 14 : EntityId theUid(getCurrentUid());
3163 14 : Entity ent = tT.getEntity();
3164 14 : ent.setEntityId(theUid);
3165 14 : tT.setEntity(ent);
3166 14 : if(verbosity_p>0){
3167 14 : os << LogIO::NORMAL << "Filled ConfigDescription table " << getCurrentUid() << " with " << tT.size() << " rows ... " << LogIO::POST;
3168 : }
3169 14 : incrementUid();
3170 :
3171 14 : return rstat;
3172 :
3173 14 : }
3174 :
3175 14 : Bool MS2ASDM::writeSBSummaryAndExecBlockStubs(){
3176 28 : LogIO os(LogOrigin("MS2ASDM", "writeSBSummaryAndExecBlockStubs()"));
3177 :
3178 14 : Bool rstat = true;
3179 :
3180 14 : asdm::SBSummaryTable& tT = ASDM_p->getSBSummary();
3181 :
3182 14 : asdm::SBSummaryRow* tR = 0;
3183 :
3184 14 : asdm::ExecBlockTable& tET = ASDM_p->getExecBlock();
3185 :
3186 14 : asdm::ExecBlockRow* tER = 0;
3187 :
3188 14 : MapWithDefault <asdm::Tag, Double> execBlockStartTime(-1.); // map from SBSummaryID to current execblock start time
3189 14 : MapWithDefault <asdm::Tag, Double> execBlockEndTime(-1.); // map from SBSummaryID to current execblock end time
3190 14 : MapWithDefault <asdm::Tag, asdm::ConfigDescriptionRow*> correspConfigDescRow(0); // map from SBSummaryID to the
3191 : // ConfigDescription row of current exec block
3192 14 : MapWithDefault <asdm::Tag, Int> execBlockNumber(0); // map from SBSummaryID to current execblock number
3193 14 : MapWithDefault <asdm::Tag, Int> obsIdFromSBSum(-1); // map from SBSummaryID to current obs ID
3194 14 : MapWithDefault <asdm::Tag, Double> minBaseline(0.); // map from SBSummaryID to minimum baseline of current exec block
3195 14 : MapWithDefault <asdm::Tag, Double> maxBaseline(0.); // map from SBSummaryID to maximum baseline of current exec block
3196 :
3197 14 : MapWithDefault <Int, Int> firstFieldIdFromObsId(-1); // map from obsId to first field id (for the representative direction)
3198 :
3199 : // unfortunately, we have to loop over the main table to get the information
3200 :
3201 : // but beforehand we calculate the position of the array center for later reference
3202 :
3203 14 : MPosition pos;
3204 : {
3205 14 : MPosition Xpos;
3206 14 : String Xobservatory;
3207 14 : if (observation().nrow() > 0) {
3208 14 : Xobservatory = observation().telescopeName()(observationId()(0));
3209 : }
3210 28 : if (Xobservatory.length() == 0 ||
3211 14 : !MeasTable::Observatory(Xpos,Xobservatory)) {
3212 : // unknown observatory
3213 : os << LogIO::WARN << "Unknown observatory: \"" << Xobservatory
3214 0 : << "\". Determining observatory position from antenna 0." << LogIO::POST;
3215 0 : Xpos=MPosition::Convert(antenna().positionMeas()(0), MPosition::WGS84)();
3216 : }
3217 : else{
3218 : os << LogIO::NORMAL << "Using tabulated observatory position for " << Xobservatory << ":"
3219 14 : << LogIO::POST;
3220 14 : Xpos=MPosition::Convert(Xpos, MPosition::WGS84)();
3221 : }
3222 14 : pos = Xpos;
3223 14 : ostringstream oss;
3224 14 : oss << " " << pos << " (WGS84)";
3225 14 : os << LogIO::NORMAL << oss.str() << LogIO::POST;
3226 14 : }
3227 :
3228 : ////MVPosition mObsPos = pos.getValue();
3229 : ////Vector<Double> hlonlat = mObsPos.get(); // get three-vector of height, lon, lat in m, rad, rad
3230 : ////Length siteAltitude = Length(hlonlat(0));
3231 : ////Angle siteLongitude = Angle(hlonlat(1));
3232 : ////Angle siteLatitude = Angle(hlonlat(2));
3233 :
3234 : // loop over main table
3235 14 : Bool warned = false; // aux. var. to avoid warning repetition
3236 14 : uInt nMainTabRows = ms_p.nrow();
3237 :
3238 14 : Int prevSBKey = -1;
3239 14 : double prevReprFreq = (163.+211.)/2.*1E9;
3240 14 : ReceiverBandMod::ReceiverBand prevFrequencyBand = ReceiverBandMod::ALMA_RB_05;
3241 14 : ReceiverSidebandMod::ReceiverSideband prevRSB = ReceiverSidebandMod::TSB;
3242 14 : Int nProcTabRows = processor().nrow();
3243 :
3244 4549 : for(uInt mainTabRow=0; mainTabRow<nMainTabRows; mainTabRow++){
3245 :
3246 : // Step 1: determine SBSummary ID and fill SBSummary table row
3247 : // (duplicate rows will automatically be taken care of by the row adding method)
3248 :
3249 4536 : Int obsId = observationId()(mainTabRow);
3250 :
3251 : // parameters of the new SBSummary row
3252 4536 : Int ddId = dataDescId()(mainTabRow);
3253 4536 : Int spwId = dataDescription().spectralWindowId()(ddId);
3254 4536 : Int procId = processorId()(mainTabRow);
3255 :
3256 4536 : Bool isWVR = false;
3257 4536 : if(procId>=0 && nProcTabRows>0 && procId < nProcTabRows){
3258 3064 : if(processor().type()(procId) == "RADIOMETER"){
3259 : //cout << "Found WVR data" << endl;
3260 0 : isWVR = true;
3261 : }
3262 : }
3263 :
3264 4536 : double frequency = (spectralWindow().refFrequencyQuant()(spwId)).getValue(unitASDMFreq());
3265 : //cout << "Freq " << frequency << endl;
3266 :
3267 : ReceiverBandMod::ReceiverBand frequencyBand; // get from frequency
3268 : ReceiverSidebandMod::ReceiverSideband rSB;
3269 4536 : double reprFreq = 0.;
3270 4536 : Int bandNum = setRecBands(Frequency(frequency), reprFreq, frequencyBand, rSB);
3271 : //cout << "Band " << bandNum << endl;
3272 :
3273 4536 : Int sbKey = obsId;
3274 :
3275 4536 : if(bandNum >= 0){
3276 4536 : if(isWVR){// special case: WVR data is observed in a (potentially) different band but no separate SB is created for it
3277 0 : if(prevSBKey>=0){ // other data was encountered beforehand, there is already a proper SBKey from it
3278 0 : sbKey = prevSBKey;
3279 0 : reprFreq = prevReprFreq;
3280 0 : frequencyBand = prevFrequencyBand;
3281 0 : rSB = prevRSB;
3282 : }
3283 : else{ // we need to peek forward until non-WVR data is found
3284 0 : Bool foundNonWVR = false;
3285 0 : uInt mainTabRowB = 0;
3286 0 : for(mainTabRowB=mainTabRow+1; mainTabRowB<nMainTabRows; mainTabRowB++){
3287 0 : Int procIdB = processorId()(mainTabRowB);
3288 0 : if(procIdB>=0 && nProcTabRows>0 && procIdB < nProcTabRows){
3289 0 : if(processor().type()(procIdB) == "RADIOMETER"){
3290 : //cout << "Found WVR data again" << endl;
3291 0 : continue;
3292 : }
3293 0 : foundNonWVR=true;
3294 0 : break;
3295 :
3296 : }
3297 0 : foundNonWVR=true;
3298 0 : break;
3299 : }// end for
3300 0 : if(foundNonWVR){
3301 0 : obsId = observationId()(mainTabRowB);
3302 0 : ddId = dataDescId()(mainTabRowB);
3303 0 : spwId = dataDescription().spectralWindowId()(ddId);
3304 0 : frequency = (spectralWindow().refFrequencyQuant()(spwId)).getValue(unitASDMFreq());
3305 0 : bandNum = setRecBands(Frequency(frequency), reprFreq, frequencyBand, rSB);
3306 0 : sbKey = obsId+10000*bandNum;
3307 : }
3308 : else{ // there is only WVR data
3309 0 : sbKey = obsId+10000*bandNum;
3310 : }
3311 : }
3312 : }
3313 : else{ // this is normal non-WVR data
3314 4536 : sbKey = obsId+10000*bandNum; // an SB can only observe one band
3315 : }
3316 : }
3317 : else{
3318 : os << LogIO::WARN << "Could not determine ALMA frequency band for frequency "
3319 0 : << frequency << " Hz in MS Spectral Window " << spwId << ". Will try to continue." << LogIO::POST;
3320 0 : sbKey = obsId+10000*bandNum; // an SB can only observe one band
3321 : }
3322 : // memorize freq band info
3323 4536 : prevSBKey = sbKey;
3324 4536 : prevReprFreq = reprFreq;
3325 4536 : prevFrequencyBand = frequencyBand;
3326 4536 : prevRSB = rSB;
3327 :
3328 : //cout << " SBKey " << sbKey << endl;
3329 : //cout << " reprFreq " << reprFreq << endl;
3330 :
3331 4536 : String sbsUid("uid://SAFFEC0C0/X1/X1");
3332 4536 : ostringstream oss;
3333 4536 : oss << sbKey;
3334 4536 : sbsUid = sbsUid + String(oss);
3335 9072 : EntityRef sbSummaryUID(sbsUid.c_str(), "", "ASDM", asdmVersion_p); // will be reset later when linking the ASDM to an APDM
3336 9072 : EntityRef projectUID("uid://SAFFEC0C0/X1/X2", "", "ASDM", asdmVersion_p); // dto.
3337 9072 : EntityRef obsUnitSetId("uid://SAFFEC0C0/X1/X3", "", "ASDM", asdmVersion_p); // dto.
3338 :
3339 4536 : SBTypeMod::SBType sbType = SBTypeMod::OBSERVATORY; //???
3340 4536 : Vector< Quantum< Double > > tRange;
3341 4536 : tRange.reference(observation().timeRangeQuant()(obsId));
3342 4536 : Double durationSecs = tRange[1].getValue("s") - tRange[0].getValue("s");
3343 4536 : if(durationSecs == 0){ // try to derive the sched block duration in a different way
3344 938 : if(!warned){
3345 : os << LogIO::WARN << "Observation time range is zero length for obs ID "
3346 : << obsId << " in MS Observation table.\n Will try to proceed ..."
3347 6 : <<LogIO::POST;
3348 6 : warned = true;
3349 : }
3350 938 : durationSecs = timestampEndSecs(nMainTabRows-1) - timestampStartSecs(0);
3351 : }
3352 4536 : Interval sbDuration = ASDMInterval(durationSecs);
3353 4536 : int numberRepeats = 1;
3354 : // limit the scheduling block duration (not the same as the observation duration)
3355 4536 : if(durationSecs > schedBlockDuration_p){
3356 3948 : sbDuration = ASDMInterval(schedBlockDuration_p);
3357 3948 : numberRepeats = (int) ceil(durationSecs/schedBlockDuration_p);
3358 3948 : durationSecs = schedBlockDuration_p;
3359 : }
3360 4536 : vector< Angle > centerDirection;
3361 4536 : Int fId = fieldId()(mainTabRow);
3362 : // an observation (and an SB) can have many fields. use the first one as representative direction
3363 4536 : if(firstFieldIdFromObsId.find(obsId) != firstFieldIdFromObsId.end( )){
3364 4304 : fId = firstFieldIdFromObsId[obsId];
3365 : }
3366 : else{
3367 232 : firstFieldIdFromObsId[obsId] = fId;
3368 : }
3369 : ////MDirection theFieldDir = field().phaseDirMeas(fId,0);
3370 : ////centerDirection.push_back( theFieldDir.getAngle( unitASDMAngle() ).getValue()(0) ); // RA
3371 : ////centerDirection.push_back( theFieldDir.getAngle( unitASDMAngle() ).getValue()(1) ); // DEC
3372 :
3373 4536 : int numObservingMode = 1;
3374 4536 : vector< string > observingMode;
3375 4536 : observingMode.push_back("observing mode t.b.d.");
3376 4536 : int numScienceGoal = 1;
3377 4536 : vector< string > scienceGoal;
3378 4536 : scienceGoal.push_back("science goal t.b.d.");
3379 4536 : int numWeatherConstraint = 1;
3380 4536 : vector< string > weatherConstraint;
3381 4536 : weatherConstraint.push_back("weather constraint t.b.d.");
3382 :
3383 4536 : tR = tT.newRow(sbSummaryUID, projectUID, obsUnitSetId, reprFreq, frequencyBand, sbType, sbDuration,
3384 : ////centerDirection,
3385 : numObservingMode, observingMode, numberRepeats, numScienceGoal,
3386 : scienceGoal, numWeatherConstraint, weatherConstraint);
3387 :
3388 4536 : asdm::SBSummaryRow* tR2 = 0;
3389 4536 : tR2 = tT.add(tR);
3390 4536 : Tag sBSummaryTag = tR2->getSBSummaryId();
3391 4536 : if(tR2 == tR){ // adding the row led to the creation of a new tag
3392 233 : if(verbosity_p>2){
3393 0 : cout << "New SBSummary tag created: " << tR2 << endl;
3394 : }
3395 233 : if( asdmSBSummaryId_p.find(sbKey) != asdmSBSummaryId_p.end( ) ){
3396 : os << LogIO::WARN << "There is more than one scheduling block necessary for the obsid - freqBand pair ("
3397 : << obsId << ", " << bandNum << ").\n This can presently not yet be handled properly.\n"
3398 1 : << "(MS Main table row " << mainTabRow << ")" << LogIO::POST;
3399 : }
3400 : else{
3401 232 : asdmSBSummaryId_p[sbKey] = sBSummaryTag;
3402 : }
3403 : }
3404 :
3405 : // now have a valid SBSummaryID for the execblock
3406 :
3407 : // Step 2: write exec block table
3408 :
3409 : // has the exec block been started already?
3410 4536 : if(execBlockStartTime.find(sBSummaryTag) != execBlockStartTime.end( )){ // yes
3411 :
3412 : // continue accumulation of min and max baseline
3413 8400 : Double baseLine = MVBaseline( (antenna().positionMeas()(antenna1()(mainTabRow))).getValue(),
3414 8400 : (antenna().positionMeas()(antenna2()(mainTabRow))).getValue()
3415 4200 : ).getLength().getValue(unitASDMLength());
3416 4200 : if(baseLine>maxBaseline[sBSummaryTag]){
3417 0 : maxBaseline[sBSummaryTag] = baseLine;
3418 : }
3419 4200 : else if(baseLine<minBaseline[sBSummaryTag]){
3420 0 : minBaseline[sBSummaryTag] = baseLine;
3421 : }
3422 :
3423 : // is the exec block complete?
3424 4200 : Double endT = timestampEndSecs(mainTabRow);
3425 4200 : if(endT > execBlockEndTime[sBSummaryTag]){ // integration intervals may be different for different DD Ids, take max endT
3426 1532 : execBlockEndTime[sBSummaryTag] = endT;
3427 : }
3428 4200 : if(verbosity_p>2){
3429 0 : cout << "interval = " << endT - execBlockStartTime[sBSummaryTag] << ", duration == " << durationSecs << endl;
3430 : }
3431 :
3432 4200 : if(endT - execBlockStartTime[sBSummaryTag] >= durationSecs){ // yes, it is complete
3433 : // parameters for a new row
3434 :
3435 105 : ArrayTime startTime = ASDMArrayTime(execBlockStartTime[sBSummaryTag]);
3436 105 : ArrayTime endTime = ASDMArrayTime(endT);
3437 105 : int execBlockNum = execBlockNumber[sBSummaryTag];
3438 105 : EntityRef execBlockUID; // to be filled with the EntityRef of the containing ASDM
3439 : try{
3440 105 : execBlockUID = EntityRef(asdmUID_p, "", "ASDM", asdmVersion_p);
3441 : }
3442 0 : catch(asdm::InvalidArgumentException x){
3443 : os << LogIO::SEVERE << "Error creating ASDM: UID \"" << getCurrentUid()
3444 0 : << "\" (intended for the ASDM) is not a valid Entity reference: " << x.getMessage()
3445 0 : << LogIO::POST;
3446 0 : return false;
3447 0 : }
3448 105 : incrementUid();
3449 105 : EntityRef projectId = projectUID;
3450 105 : string configName = "configName t.b.d."; // ???
3451 105 : string telescopeName = telName_p;
3452 210 : string observerName = observation().observer()(obsId).c_str();
3453 105 : if(observerName==""){
3454 27 : observerName = "unknown";
3455 : }
3456 : ////string observingLog = "log not filled";
3457 105 : vector<string > observingLog(1);
3458 105 : int numObservingLog = 1;
3459 105 : observingLog[0] = "log not filled";
3460 105 : Vector< String > sV;
3461 105 : if(observation().log().isDefined(obsId)){// log string array not empty
3462 0 : sV.reference(observation().log()(obsId)); // the observation log is an array of strings
3463 0 : observingLog.resize(sV.size());
3464 0 : numObservingLog = observingLog.size();
3465 0 : for(uInt i=0; i<sV.size(); i++){
3466 0 : observingLog[i] = string(sV[i].c_str());
3467 : }
3468 : }
3469 : ////string sessionReference = "sessionReference t.b.d."; // ???
3470 : ////EntityRef sbSummary = sbSummaryUID;
3471 105 : EntityRef sessionReference = sbSummaryUID;
3472 : ////string schedulerMode = "CASA exportasdm"; //???
3473 105 : Length baseRangeMin = Length( minBaseline[sBSummaryTag] );
3474 105 : Length baseRangeMax = Length( maxBaseline[sBSummaryTag] );
3475 105 : Length baseRmsMinor = Length(0); // ???
3476 105 : Length baseRmsMajor = Length(0); // ???
3477 105 : Angle basePa = Angle(0); // ???
3478 105 : bool aborted = false;
3479 105 : asdm::ConfigDescriptionRow* cDR = correspConfigDescRow[sBSummaryTag];
3480 105 : int numAntenna = cDR->getNumAntenna();
3481 105 : vector< Tag > antennaId = cDR->getAntennaId();
3482 :
3483 105 : tER = tET.newRow(startTime, endTime, execBlockNum, execBlockUID, projectId, configName, telescopeName, observerName,
3484 : numObservingLog, observingLog, //// now vector< string>
3485 : sessionReference, //// now of type EntityRef
3486 : ////sbSummary, schedulerMode,
3487 : baseRangeMin, baseRangeMax, baseRmsMinor, baseRmsMajor, basePa,
3488 : ////siteAltitude, siteLongitude, siteLatitude,
3489 : aborted, numAntenna, antennaId, sBSummaryTag);
3490 :
3491 : asdm::ExecBlockRow* tER2;
3492 :
3493 105 : tER2 = tET.add(tER);
3494 105 : if(tER2 != tER){
3495 0 : os << LogIO::SEVERE << "Internal error: attempt to store duplicate exec block row." << LogIO::POST;
3496 0 : return false;
3497 : }
3498 105 : asdmExecBlockId_p[execBlockStartTime[sBSummaryTag]] = tER->getExecBlockId();
3499 :
3500 105 : if(verbosity_p>2){
3501 0 : std::cout << "eblock id defined in loop 1 for start time " << std::setprecision(13) << execBlockStartTime[sBSummaryTag] << endl;
3502 0 : std::cout << " end time " << std::setprecision(13) << execBlockEndTime[sBSummaryTag] << endl;
3503 : }
3504 :
3505 : // undefine the mapping for this Tag since the ExecBlock was completed
3506 105 : auto startptr = execBlockStartTime.find(sBSummaryTag);
3507 105 : if ( startptr != execBlockStartTime.end( ) ) execBlockStartTime.erase(startptr);
3508 105 : auto endptr = execBlockEndTime.find(sBSummaryTag);
3509 105 : if ( endptr != execBlockEndTime.end( ) ) execBlockEndTime.erase(endptr);
3510 105 : auto corptr = correspConfigDescRow.find(sBSummaryTag);
3511 105 : if ( corptr != correspConfigDescRow.end( ) ) correspConfigDescRow.erase(corptr);
3512 105 : auto sumptr = obsIdFromSBSum.find(sBSummaryTag);
3513 105 : if ( sumptr != obsIdFromSBSum.end( ) ) obsIdFromSBSum.erase(sumptr);
3514 105 : auto minptr = minBaseline.find(sBSummaryTag);
3515 105 : if ( minptr != minBaseline.end( ) ) minBaseline.erase(minptr);
3516 105 : auto maxptr = maxBaseline.find(sBSummaryTag);
3517 105 : if ( maxptr != maxBaseline.end( ) ) maxBaseline.erase(maxptr);
3518 :
3519 105 : }
3520 : // else{ // no, it is not complete
3521 : // }
3522 : }
3523 : else{// no, it has not been started, yet
3524 :
3525 : // check if there is another exec block which started at the same time
3526 6580 : for ( auto iter = execBlockStartTime.begin( ); iter != execBlockStartTime.end( ); ++iter ) {
3527 6245 : if ( iter->second == timestampStartSecs(mainTabRow) ){
3528 : os << LogIO::SEVERE << "Observation of different frequency bands at the same time and under the same observation ID is not supported by the ASDM."
3529 1 : << "\n Please split out the different spectral bands into individual MSs and process separately." << LogIO::POST;
3530 1 : return false;
3531 : }
3532 : }
3533 :
3534 335 : execBlockStartTime[sBSummaryTag] = timestampStartSecs(mainTabRow);
3535 335 : execBlockEndTime[sBSummaryTag] = timestampEndSecs(mainTabRow); // will be updated
3536 :
3537 335 : Int oldNum = 0;
3538 335 : auto numptr = execBlockNumber.find(sBSummaryTag);
3539 335 : if( numptr != execBlockNumber.end( ) ){
3540 : // increment exec block number
3541 103 : oldNum = numptr->second;
3542 103 : execBlockNumber.erase(numptr);
3543 : }
3544 335 : execBlockNumber[sBSummaryTag] = oldNum + 1; // sequential numbering starting at 1
3545 :
3546 335 : if(verbosity_p>2){
3547 0 : std::cout << "eblock number " << oldNum + 1 << " defined for start time " << std::setprecision (9) << timestampStartSecs(mainTabRow) << endl;
3548 : }
3549 :
3550 335 : obsIdFromSBSum[sBSummaryTag] = obsId; // remember the obsId for this exec block
3551 :
3552 335 : if( asdmConfigDescriptionId_p.find(mainTabRow) == asdmConfigDescriptionId_p.end( ) ){
3553 : os << LogIO::SEVERE << "Internal error: undefined config description id for MS main table row "
3554 0 : << mainTabRow << LogIO::POST;
3555 0 : return false;
3556 : }
3557 335 : asdm::ConfigDescriptionRow* cDR = (ASDM_p->getConfigDescription()).getRowByKey(asdmConfigDescriptionId_p[mainTabRow]);
3558 335 : if(cDR ==0){
3559 : os << LogIO::SEVERE << "Internal error: no row in ASDM ConfigDesc Table for ConfigDescriptionId stored for main table row "
3560 0 : << mainTabRow << LogIO::POST;
3561 0 : return false;
3562 : }
3563 335 : correspConfigDescRow[sBSummaryTag] = cDR; // remember the config description row for this exec block
3564 :
3565 : // start accumulation of min and max baseline
3566 670 : Double bLine = MVBaseline( (antenna().positionMeas()(antenna1()(mainTabRow))).getValue(),
3567 670 : (antenna().positionMeas()(antenna2()(mainTabRow))).getValue()
3568 335 : ).getLength().getValue(unitASDMLength());
3569 335 : minBaseline[sBSummaryTag] = bLine;
3570 335 : maxBaseline[sBSummaryTag] = bLine;
3571 : }
3572 : // skip rest of this timestamp
3573 4535 : Double tStamp = time()(mainTabRow);
3574 4535 : while(mainTabRow<nMainTabRows
3575 700565 : && time()(mainTabRow)==tStamp
3576 1401143 : && dataDescId()(mainTabRow)==ddId){
3577 696043 : mainTabRow++;
3578 : }
3579 4535 : mainTabRow--;// we are inside a for loop which will perform the last mainTabRow++
3580 4547 : } // end loop over main table
3581 :
3582 : // are there pending exec blocks?
3583 242 : while(execBlockStartTime.size()>0){ // yes
3584 229 : Tag sBSummaryTag = execBlockStartTime.begin( )->first;
3585 229 : tR = tT.getRowByKey(sBSummaryTag);
3586 229 : Int obsId = obsIdFromSBSum[sBSummaryTag];
3587 : // parameters for a new row
3588 229 : ArrayTime startTime = ASDMArrayTime(execBlockStartTime[sBSummaryTag]);
3589 229 : ArrayTime endTime = ASDMArrayTime(execBlockEndTime[sBSummaryTag]);
3590 229 : int execBlockNum = execBlockNumber[sBSummaryTag];
3591 229 : EntityRef execBlockUID; // to be filled with the EntityRef of the containing ASDM
3592 : try{
3593 229 : execBlockUID = EntityRef(asdmUID_p, "", "ASDM", asdmVersion_p);
3594 : }
3595 0 : catch(asdm::InvalidArgumentException x){
3596 : os << LogIO::SEVERE << "Error creating ASDM: UID \"" << getCurrentUid()
3597 0 : << "\" (intended for an exec block) not a valid Entity reference: " << x.getMessage()
3598 0 : << LogIO::POST;
3599 0 : return false;
3600 0 : }
3601 229 : incrementUid();
3602 229 : EntityRef projectId = tR->getProjectUID();
3603 229 : string configName = "configName t.b.d."; // ???
3604 229 : string telescopeName = telName_p;
3605 458 : string observerName = observation().observer()(obsId).c_str();
3606 229 : if(observerName==""){
3607 4 : observerName = "unknown";
3608 : }
3609 :
3610 : ////string observingLog = "log not filled";
3611 229 : vector<string > observingLog(1);
3612 229 : int numObservingLog = 1;
3613 229 : observingLog[0] = "log not filled";
3614 229 : Vector< String > sV;
3615 229 : if(observation().log().isDefined(obsId)){// log string array not empty
3616 4 : sV.reference(observation().log()(obsId)); // the observation log is an array of strings
3617 4 : observingLog.resize(sV.size());
3618 4 : numObservingLog = observingLog.size();
3619 8 : for(uInt i=0; i<sV.size(); i++){
3620 4 : observingLog[i] = string(sV[i].c_str());
3621 : }
3622 : }
3623 :
3624 : //// string sessionReference = "sessionReference t.b.d."; // ???
3625 : ////EntityRef sbSummary = tR->getSbSummaryUID();
3626 229 : EntityRef sessionReference = tR->getSbSummaryUID();
3627 : ////string schedulerMode = "CASA exportasdm"; //???
3628 229 : Length baseRangeMin = Length( minBaseline[sBSummaryTag] );
3629 229 : Length baseRangeMax = Length( maxBaseline[sBSummaryTag] );
3630 229 : Length baseRmsMinor = Length(0); // ???
3631 229 : Length baseRmsMajor = Length(0); // ???
3632 229 : Angle basePa = Angle(0); // ???
3633 229 : bool aborted = false;
3634 229 : asdm::ConfigDescriptionRow* cDR = correspConfigDescRow[sBSummaryTag];
3635 229 : int numAntenna = cDR->getNumAntenna();
3636 229 : vector< Tag > antennaId = cDR->getAntennaId();
3637 :
3638 229 : tER = tET.newRow(startTime, endTime, execBlockNum, execBlockUID, projectId, configName, telescopeName, observerName,
3639 : numObservingLog, observingLog,
3640 : sessionReference,
3641 : ////sbSummary, schedulerMode,
3642 : baseRangeMin, baseRangeMax, baseRmsMinor, baseRmsMajor, basePa,
3643 : ////siteAltitude, siteLongitude, siteLatitude,
3644 : aborted, numAntenna, antennaId, sBSummaryTag);
3645 :
3646 : asdm::ExecBlockRow* tER2;
3647 :
3648 229 : tER2 = tET.add(tER);
3649 229 : if(tER2 != tER){
3650 0 : os << LogIO::SEVERE << "Internal error: attempt to store duplicate exec block row." << LogIO::POST;
3651 0 : return false;
3652 : }
3653 229 : asdmExecBlockId_p[execBlockStartTime[sBSummaryTag]] = tER->getExecBlockId();
3654 :
3655 229 : if(verbosity_p>2){
3656 0 : std::cout << "eblock id defined in loop 2 for start time " << std::setprecision(13) << execBlockStartTime[sBSummaryTag] << endl;
3657 0 : std::cout << " end time " << std::setprecision(13) << execBlockEndTime[sBSummaryTag] << endl;
3658 : }
3659 :
3660 : // undefine the mapping for this Tag since the ExecBlock was completed
3661 229 : auto startptr = execBlockStartTime.find(sBSummaryTag); // need only remove from the map what is tested
3662 229 : if ( startptr != execBlockStartTime.end( ) ) execBlockStartTime.erase(startptr);
3663 229 : auto endptr = execBlockEndTime.find(sBSummaryTag);
3664 229 : if ( endptr != execBlockEndTime.end( ) ) execBlockEndTime.erase(endptr);
3665 :
3666 229 : }
3667 :
3668 : // finish the SBSummary table
3669 13 : EntityId theUid(getCurrentUid());
3670 13 : Entity ent = tT.getEntity();
3671 13 : ent.setEntityId(theUid);
3672 13 : tT.setEntity(ent);
3673 13 : if(verbosity_p>0){
3674 13 : os << LogIO::NORMAL << "Filled SBSummary table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
3675 : }
3676 13 : incrementUid();
3677 :
3678 : // finish the ExecBlock table
3679 13 : theUid = getCurrentUid();
3680 13 : ent = tET.getEntity();
3681 13 : ent.setEntityId(theUid);
3682 13 : tET.setEntity(ent);
3683 13 : if(verbosity_p>0){
3684 13 : os << LogIO::NORMAL << "Filled ExecBlock table " << getCurrentUid() << " with " << tET.size() << " rows ..." << LogIO::POST;
3685 : }
3686 13 : incrementUid();
3687 :
3688 13 : return rstat;
3689 :
3690 14 : }
3691 :
3692 13 : Bool MS2ASDM::writeMainAndScanAndSubScan(const String& datacolumn){
3693 26 : LogIO os(LogOrigin("MS2ASDM", "writeMainAndScanAndSubScan()"));
3694 :
3695 13 : Bool rstat = true;
3696 :
3697 : // check if datacolumn exists
3698 :
3699 13 : String dataColumn(datacolumn);
3700 13 : dataColumn.upcase();
3701 :
3702 13 : if( (dataColumn == "CORRECTED" && !ms_p.tableDesc().isColumn("CORRECTED_DATA"))
3703 26 : || (dataColumn == "MODEL" && !ms_p.tableDesc().isColumn("MODEL_DATA"))
3704 26 : || (dataColumn == "DATA" && !ms_p.tableDesc().isColumn("DATA"))
3705 : ){
3706 : os << LogIO::SEVERE << "Error: column " << dataColumn << " does not exist in "
3707 0 : << ms_p.tableName() << LogIO::POST;
3708 0 : return false;
3709 : }
3710 : else{
3711 13 : if(verbosity_p>0){
3712 13 : os << LogIO::NORMAL << "Using column " << dataColumn << "." << LogIO::POST;
3713 : }
3714 : }
3715 :
3716 13 : asdm::MainTable& tT = ASDM_p->getMain();
3717 13 : asdm::MainRow* tR = 0;
3718 :
3719 13 : asdm::ScanTable& tST = ASDM_p->getScan();
3720 13 : asdm::ScanRow* tSR = 0;
3721 :
3722 13 : asdm::SubscanTable& tSST = ASDM_p->getSubscan();
3723 13 : asdm::SubscanRow* tSSR = 0;
3724 :
3725 :
3726 : // Scheme
3727 : // loop over main table
3728 : // asdmExecBlockId_p(time()(mainTabRow) defined?
3729 : // if so, a new exec block has started
3730 : // is there a previous exec block?
3731 : // if so, finish it
3732 : // set up new exec block
3733 : // set scanNumber to 1
3734 : // set subscanNumber to 1
3735 : // end if
3736 : // while(scan not finished)
3737 : // find all DDIds in the time between now and now+subscanduration or until Scan ends
3738 : // and memorize their start rows
3739 : // for each DDId found
3740 : // find all FieldIds in the time between now and now+subscanduration or until Scan ends
3741 : // for each FieldId
3742 : // Construct subscan == SDMDataObject
3743 : // using the ConfigDescription table row asdmConfigDescriptionId_p(startRow)
3744 : // and write it
3745 : // write corresponding Main table row and subscan table row
3746 : // subscanNumber++
3747 : // end for
3748 : // end for
3749 : // next mainTabRow
3750 : // error if asdmExecBlockId_p(time()(mainTabRow) defined:
3751 : // end while
3752 : // write scan table row
3753 : // scanNumber++
3754 : // end loop (i.e. next main table row)
3755 :
3756 :
3757 : ////////////////////////////////////////////////
3758 : // Prepare loop over main table
3759 : Double scanStart;
3760 :
3761 13 : Tag execBlockId = Tag();
3762 13 : int subscanNumber = 0;
3763 : // parameters for the new Scan table row
3764 13 : int scanNumber = 0;
3765 13 : ArrayTime scanStartTime;
3766 13 : ArrayTime scanEndTime;
3767 13 : int scanNumIntent = 0;
3768 13 : int numSubScan = 0;
3769 13 : vector< ScanIntentMod::ScanIntent > scanIntent;
3770 13 : vector< CalDataOriginMod::CalDataOrigin > scanCalDataType;
3771 13 : vector< bool > scanCalibrationOnLine;
3772 : ////bool scanFlagRow = false; // always false ???
3773 :
3774 13 : uInt nMainTabRows = ms_p.nrow();
3775 347 : for(uInt mainTabRow=0; mainTabRow<nMainTabRows; mainTabRow++){
3776 :
3777 334 : Double rowTime = timestampStartSecs(mainTabRow);
3778 :
3779 : // asdmExecBlockId_p defined for this timestamp?
3780 334 : if(asdmExecBlockId_p.find(rowTime) != asdmExecBlockId_p.end( )){ // a new exec block has started
3781 : // is there a previous exec block?
3782 334 : if(execBlockId != Tag()){
3783 : // finish the old exec block
3784 : }
3785 : // set up new exec block
3786 : // parameters for the first scan
3787 334 : execBlockId = asdmExecBlockId_p[rowTime];
3788 334 : asdm::ExecBlockRow* EBR = (ASDM_p->getExecBlock()).getRowByKey(execBlockId);
3789 334 : scanNumber = 1; // ASDM scan numbering starts at 1
3790 334 : subscanNumber = 1; // dito for subscans
3791 334 : scanStart = rowTime;
3792 334 : scanStartTime = ASDMArrayTime( scanStart );
3793 334 : scanEndTime = EBR->getEndTime(); // preset to the end of the execblock
3794 334 : scanNumIntent = 0;
3795 334 : numSubScan = 0;
3796 334 : scanIntent.resize(0);
3797 334 : scanCalDataType.resize(0);
3798 334 : scanCalibrationOnLine.resize(0);
3799 : ////scanFlagRow = false;
3800 : } // end if a new exec block has started
3801 0 : else if(execBlockId == Tag()){
3802 0 : os << LogIO::WARN << "Encountered main tab row " << mainTabRow << " which is not part of an execblock." << LogIO::POST;
3803 0 : continue;
3804 : }
3805 0 : else if(MSTimeSecs(scanEndTime) - timestampEndSecs(mainTabRow) <= 0.9){
3806 : os << LogIO::NORMAL << "Potential problem at main tab row " << mainTabRow << ": misaligned scan and execblock end."
3807 0 : << endl << "Will try to continue ..." << LogIO::POST;
3808 : // search back to see if the execblock start can be found
3809 :
3810 0 : Double searchIntervalSecs = 60.;
3811 :
3812 0 : uInt mainTabRowB = mainTabRow;
3813 0 : Bool foundEBStart = false;
3814 0 : Double rowTimeB = rowTime;
3815 0 : while(rowTime - rowTimeB < searchIntervalSecs && mainTabRowB>0){
3816 0 : rowTimeB = timestampStartSecs(--mainTabRowB);
3817 0 : if(asdmExecBlockId_p.find(rowTimeB) != asdmExecBlockId_p.end( )){
3818 0 : foundEBStart = true;
3819 0 : execBlockId = asdmExecBlockId_p[rowTimeB];
3820 0 : asdm::ExecBlockRow* EBR = (ASDM_p->getExecBlock()).getRowByKey(execBlockId);
3821 0 : scanNumber = 1; // ASDM scan numbering starts at 1
3822 0 : subscanNumber = 1; // dito for subscans
3823 0 : scanStart = rowTimeB;
3824 0 : scanStartTime = ASDMArrayTime( scanStart );
3825 0 : scanEndTime = EBR->getEndTime(); // preset to the end of the execblock
3826 0 : scanNumIntent = 0;
3827 0 : numSubScan = 0;
3828 0 : scanIntent.resize(0);
3829 0 : scanCalDataType.resize(0);
3830 0 : scanCalibrationOnLine.resize(0);
3831 : ////scanFlagRow = false;
3832 0 : break;
3833 : }
3834 : }
3835 0 : if(foundEBStart){
3836 0 : os << LogIO::NORMAL << "Problem resolved. Found execblock start " << rowTime - rowTimeB << " s earlier." << LogIO::POST;
3837 : }
3838 : else{
3839 : os << LogIO::SEVERE << "Searched back for " << searchIntervalSecs
3840 0 : << " s. Could not resolve misalignment." << LogIO::POST;
3841 0 : return false;
3842 : }
3843 : }
3844 :
3845 : // while(scan not finished)
3846 1323 : while( mainTabRow<nMainTabRows &&
3847 1323 : MSTimeSecs(scanEndTime) - (rowTime = timestampStartSecs(mainTabRow)) > 1E-3 ){ // presently one scan per exec block ???
3848 :
3849 : // parameters for the new SubScan table row
3850 334 : Double subScanEnd = rowTime + subscanDuration_p;
3851 334 : if(subScanEnd > MSTimeSecs(scanEndTime)){
3852 334 : subScanEnd = MSTimeSecs(scanEndTime);
3853 : }
3854 :
3855 : // find all DDIds in the time between now and end of subscan
3856 334 : uInt irow = mainTabRow;
3857 334 : std::map< Int, uInt > subScanDDIdStartRows;
3858 1392615 : while(irow<nMainTabRows &&
3859 696301 : timestampStartSecs(irow) < subScanEnd){
3860 695980 : Int ddId = dataDescId()(irow);
3861 695980 : if(subScanDDIdStartRows.find(ddId) == subScanDDIdStartRows.end( )){
3862 356 : subScanDDIdStartRows[ddId] = irow; // memorize their start rows
3863 : }
3864 695980 : irow++;
3865 : }
3866 :
3867 : // for each DDId found
3868 690 : for( auto iter = subScanDDIdStartRows.begin( ); iter != subScanDDIdStartRows.end( ); ++iter ){
3869 356 : Int theDDId = iter->first;
3870 :
3871 : // find all FieldIds in the time between now and now+subscanduration or until Scan ends
3872 356 : uInt irow2 = mainTabRow;
3873 356 : std::map< Int, uInt > subScanStartRows;
3874 356 : std::map< Int, uInt > subScanEndRows;
3875 3319837 : while(irow2<nMainTabRows &&
3876 1659901 : timestampStartSecs(irow2) < subScanEnd){
3877 1659580 : Int ddId = dataDescId()(irow2);
3878 1659580 : Int fId = fieldId()(irow2);
3879 1659580 : if(ddId == theDDId){
3880 695980 : if( subScanEndRows.find(fId) != subScanEndRows.end( ) ){
3881 695444 : subScanEndRows[fId] = irow2; // update end row
3882 : }
3883 695980 : if( subScanStartRows.find(fId) == subScanStartRows.end( ) ){
3884 536 : subScanStartRows[fId] = irow2; // memorize their start rows
3885 536 : subScanEndRows[fId] = irow2; // and end rows
3886 : }
3887 : }
3888 1659580 : irow2++;
3889 : }
3890 : // for each FieldId
3891 892 : for( auto iter = subScanStartRows.begin( ); iter != subScanStartRows.end( ); ++iter ) {
3892 536 : Int theFId = iter->first;
3893 536 : uInt startRow = subScanStartRows[theFId];
3894 536 : uInt endRow = subScanEndRows[theFId];
3895 : // write subscan
3896 : // parameters for the new SubScan table row
3897 536 : ArrayTime subScanStartArrayTime = ASDMArrayTime(timestampStartSecs(startRow));
3898 536 : ArrayTime subScanEndArrayTime = ASDMArrayTime(timestampEndSecs(endRow));
3899 1072 : string fieldName = field().name()(fieldId()(startRow)).c_str();
3900 536 : SubscanIntentMod::SubscanIntent subscanIntent = SubscanIntentMod::ON_SOURCE;
3901 536 : vector< int > numberSubintegration;
3902 : ////bool flagRow = false;
3903 :
3904 : // parameters for the corresponding new Main table row
3905 536 : ArrayTime mainTime = ASDMArrayTime((timestampStartSecs(startRow) + timestampEndSecs(endRow))/2.); // midpoint!
3906 :
3907 536 : if(asdmConfigDescriptionId_p.find(startRow) == asdmConfigDescriptionId_p.end( )){
3908 : os << LogIO::SEVERE << "Internal error: undefined config description id for MS main table row "
3909 0 : << startRow << LogIO::POST;
3910 0 : return false;
3911 : }
3912 536 : Tag configDescriptionId = asdmConfigDescriptionId_p[startRow];
3913 536 : asdm::ConfigDescriptionRow* CDR = (ASDM_p->getConfigDescription()).getRowByKey(configDescriptionId);
3914 536 : if(CDR ==0){
3915 : os << LogIO::SEVERE << "Internal error: no row in ASDM ConfigDesc Table for ConfigDescriptionId stored for main table row "
3916 0 : << startRow << LogIO::POST;
3917 0 : return false;
3918 : }
3919 :
3920 536 : Tag fieldIdTag = asdmFieldId_p[theFId];
3921 536 : int numAntenna = CDR->getNumAntenna();
3922 536 : TimeSamplingMod::TimeSampling timeSampling = TimeSamplingMod::INTEGRATION;
3923 1072 : Interval interval = ASDMInterval(intervalQuant()(startRow).getValue("s")); // data sampling interval
3924 : int numIntegration; // to be set by the following method call
3925 : int dataSize; // to be set by the following method call
3926 536 : EntityRef dataOid; // to be set by the following method call
3927 536 : vector< Tag > stateIdV; // "
3928 :
3929 : // Note: for WVR data, a special case would have to be made here or inside
3930 : // writeMainBinSubScanForOneDDIdFIdPair() which does not call corrDataHeader
3931 : // and addIntegration but instead only SDMDataObjectWriter::wvrData()
3932 :
3933 536 : numIntegration = writeMainBinSubScanForOneDDIdFIdPair(theDDId, theFId,
3934 : datacolumn,
3935 : scanNumber, subscanNumber,
3936 : startRow, endRow,
3937 : execBlockId,
3938 : dataSize, dataOid, stateIdV);
3939 536 : if(numIntegration<0){ // error!
3940 : os << LogIO::SEVERE << "Error writing Subscan starting at main table row "
3941 0 : << startRow << LogIO::POST;
3942 0 : return false;
3943 : }
3944 :
3945 5068 : for(uInt i=0; i<(uInt)numIntegration; i++){
3946 4532 : numberSubintegration.push_back(0); // no subintegrations for the moment, no channel averaging (???)
3947 : }
3948 :
3949 : // end write subscan
3950 :
3951 : // write corresponding Main table row
3952 536 : tR = tT.newRow(mainTime, configDescriptionId, fieldIdTag, numAntenna, timeSampling, interval, numIntegration,
3953 : scanNumber, subscanNumber, dataSize, dataOid, stateIdV, execBlockId);
3954 536 : tT.add(tR);
3955 :
3956 : // write corresponding Subscan table row
3957 :
3958 536 : tSSR = tSST.newRow(execBlockId, scanNumber, subscanNumber, subScanStartArrayTime, subScanEndArrayTime,
3959 : fieldName, subscanIntent, numIntegration, numberSubintegration //// , flagRow
3960 : );
3961 :
3962 536 : tSST.add(tSSR);
3963 :
3964 536 : subscanNumber++;
3965 536 : numSubScan++;
3966 :
3967 536 : } // end loop over Field indices
3968 :
3969 356 : } // end loop over DD indices
3970 : // update mainTabRow
3971 334 : mainTabRow = irow;
3972 334 : } // end while scan continues
3973 : // scan finished
3974 : // complete and write scan table row
3975 334 : mainTabRow--; // return to the last row of the scan
3976 334 : scanEndTime = ASDMArrayTime( timestampEndSecs(mainTabRow) );
3977 334 : scanNumIntent = 1; // hardwired (???)
3978 668 : for(uInt i=0; i<(uInt)scanNumIntent; i++){
3979 334 : scanIntent.push_back(ScanIntentMod::OBSERVE_TARGET); // hardwired for the moment (???)
3980 334 : scanCalDataType.push_back(CalDataOriginMod::FULL_RESOLUTION_CROSS); // hardwired for the moment (???)
3981 334 : scanCalibrationOnLine.push_back(false); // hardwired for the moment (???)
3982 : }
3983 :
3984 334 : tSR = tST.newRow(execBlockId, scanNumber, scanStartTime, scanEndTime, scanNumIntent, numSubScan, scanIntent,
3985 : scanCalDataType, scanCalibrationOnLine ////, scanFlagRow
3986 : );
3987 :
3988 334 : tST.add(tSR);
3989 :
3990 334 : scanNumber++;
3991 :
3992 : }// end for
3993 :
3994 13 : EntityId theUid(getCurrentUid());
3995 13 : Entity ent = tT.getEntity();
3996 13 : ent.setEntityId(theUid);
3997 13 : tT.setEntity(ent);
3998 13 : if(verbosity_p>0){
3999 13 : os << LogIO::NORMAL << "Filled Main table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
4000 : }
4001 13 : incrementUid();
4002 :
4003 13 : theUid = getCurrentUid();
4004 13 : ent = tST.getEntity();
4005 13 : ent.setEntityId(theUid);
4006 13 : tST.setEntity(ent);
4007 13 : if(verbosity_p>0){
4008 13 : os << LogIO::NORMAL << "Filled Scan table " << getCurrentUid() << " with " << tST.size() << " rows ..." << LogIO::POST;
4009 : }
4010 13 : incrementUid();
4011 :
4012 13 : theUid = getCurrentUid();
4013 13 : ent = tSST.getEntity();
4014 13 : ent.setEntityId(theUid);
4015 13 : tSST.setEntity(ent);
4016 13 : if(verbosity_p>0){
4017 13 : os << LogIO::NORMAL << "Filled SubScan table " << getCurrentUid() << " with " << tSST.size() << " rows ..." << LogIO::POST;
4018 : }
4019 13 : incrementUid();
4020 :
4021 13 : return rstat;
4022 13 : }
4023 :
4024 13 : Bool MS2ASDM::writePointingModel(){ // create asdm PointingModel table
4025 26 : LogIO os(LogOrigin("MS2ASDM", "writePointingModel()"));
4026 :
4027 13 : Bool rstat = true;
4028 :
4029 13 : asdm::PointingModelTable& tT = ASDM_p->getPointingModel();
4030 :
4031 13 : asdm::PointingModelRow* tR = 0;
4032 :
4033 13 : asdm::FeedTable& tFT = ASDM_p->getFeed();
4034 :
4035 13 : vector< asdm::FeedRow * > feedRowV = tFT.get();
4036 :
4037 : // loop over ASDM Feed table and create Pointing model rows for each
4038 : // receptor of each Feed table row
4039 :
4040 909 : for(uInt feedRow=0; feedRow<feedRowV.size(); feedRow++){
4041 :
4042 :
4043 896 : uInt numRec = feedRowV[feedRow]->getNumReceptor();
4044 896 : vector< PolarizationTypeMod::PolarizationType > polTypeV = feedRowV[feedRow]->getPolarizationTypes();
4045 896 : vector< int > receivIdV = feedRowV[feedRow]->getReceiverId();
4046 :
4047 2688 : for(uInt iRec=0; iRec<numRec; iRec++){ // loop over all receptors
4048 :
4049 1792 : const vector< asdm::ReceiverRow * > recRowV = feedRowV[feedRow]->getReceivers(receivIdV[iRec]);
4050 :
4051 : // parameters for new PointingModel row
4052 :
4053 1792 : Tag antennaId = feedRowV[feedRow]->getAntennaId();
4054 1792 : int numCoeff = 2; // seems to be the dummy value ???, to be confirmed
4055 1792 : vector< string > coeffName;
4056 1792 : coeffName.push_back("IA");
4057 1792 : coeffName.push_back("IE");
4058 1792 : vector< float > coeffVal;
4059 1792 : coeffVal.push_back(0.);
4060 1792 : coeffVal.push_back(0.);
4061 : PolarizationTypeMod::PolarizationType polarizationType;
4062 : try{
4063 1792 : polarizationType = polTypeV[iRec];
4064 : }
4065 : catch(std::string z){
4066 : os << LogIO::SEVERE << "Internal error: invalid polarization type in Feed table row " << z
4067 : << LogIO::POST;
4068 : return false;
4069 : }
4070 :
4071 1792 : ReceiverBandMod::ReceiverBand receiverBand = recRowV[0]->getFrequencyBand(); // take from the first receiver
4072 1792 : string assocNature = "NOT_SET";
4073 1792 : int assocPointingModelId = -1;
4074 :
4075 1792 : tR = tT.newRow(antennaId, numCoeff, coeffName, coeffVal, polarizationType,
4076 : receiverBand, assocNature, assocPointingModelId);
4077 :
4078 1792 : asdm::PointingModelRow* tR2 = 0;
4079 :
4080 1792 : tR2 = tT.add(tR);
4081 1792 : if(asdmPointingModelId_p.find(antennaId) == asdmPointingModelId_p.end( )){
4082 251 : asdmPointingModelId_p[antennaId] = tR2->getPointingModelId();
4083 : }
4084 :
4085 1792 : } // end loop over receptors
4086 :
4087 896 : } // end loop over ASDM Feed table
4088 :
4089 13 : EntityId theUid(getCurrentUid());
4090 13 : Entity ent = tT.getEntity();
4091 13 : ent.setEntityId(theUid);
4092 13 : tT.setEntity(ent);
4093 13 : if(verbosity_p>0){
4094 13 : os << LogIO::NORMAL << "Filled PointingModel table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
4095 : }
4096 13 : incrementUid();
4097 :
4098 13 : return rstat;
4099 13 : }
4100 :
4101 13 : Bool MS2ASDM::writePointing(){ // create asdm pointing table
4102 26 : LogIO os(LogOrigin("MS2ASDM", "writePointing()"));
4103 :
4104 13 : Bool rstat = true;
4105 :
4106 13 : asdm::PointingTable& tT = ASDM_p->getPointing();
4107 :
4108 13 : asdm::PointingRow* tR = 0;
4109 :
4110 13 : uInt nPointingRows = pointing().nrow();
4111 :
4112 13 : if(nPointingRows==0){
4113 4 : os << LogIO::WARN << "MS Pointing table doesn't exist or is empty." << LogIO::POST;
4114 4 : return true; // not an error
4115 : }
4116 :
4117 9 : Bool warned = false; // aux. var. to avoid repetition of warnings
4118 :
4119 : // loop over MS antenna table
4120 200 : for(Int aId=0; aId<(Int)antenna().nrow(); aId++){
4121 :
4122 191 : if(asdmAntennaId_p.find(aId) == asdmAntennaId_p.end( )){
4123 : os << LogIO::SEVERE << "Internal error: no tag defined for antenna id "
4124 0 : << aId << LogIO::POST;
4125 0 : return false;
4126 : }
4127 :
4128 191 : uInt irow=0;
4129 191 : uInt totNumRows=0; // total of MS Pointing table rows for this antenna
4130 :
4131 382 : while(irow<nPointingRows){
4132 :
4133 : // find next pointing entry for this antenna in MS pointing table (== beginning of a new ASDM pointing table entry)
4134 191 : Int firstRow=-1;
4135 71269 : while(irow<nPointingRows){
4136 71269 : if(pointing().antennaId()(irow) == aId){
4137 191 : firstRow = irow;
4138 191 : break;
4139 : }
4140 71078 : irow++;
4141 : }
4142 :
4143 191 : if(firstRow==-1){ // no further data for this antenna
4144 0 : break;
4145 : }
4146 :
4147 191 : uInt numRows=1; // number of rows with contiguous timestamps for this antenna
4148 :
4149 : // parameters for the next pointing table row
4150 191 : Tag antennaId = asdmAntennaId_p[aId];
4151 382 : ArrayTimeInterval timeInterval( ASDMTimeInterval( pointing().timeQuant()(firstRow), pointing().intervalQuant()(firstRow)) );
4152 :
4153 191 : bool pointingTracking = pointing().tracking()(firstRow);
4154 :
4155 191 : bool usePolynomials = false;
4156 191 : int numTerm = 0; // to be updated later
4157 :
4158 191 : if(pointing().numPoly()(firstRow)>0){
4159 0 : usePolynomials = true;
4160 0 : numTerm = pointing().numPoly()(irow)+1;
4161 : }
4162 :
4163 382 : ArrayTime timeOrigin = ASDMArrayTime( pointing().timeOriginQuant()(firstRow).getValue("s") );
4164 :
4165 191 : vector< vector< Angle > > pointingDirection;
4166 191 : Vector< MDirection > dirV; // aux. vector to access array column
4167 191 : dirV.reference(pointing().directionMeasCol()(firstRow));
4168 191 : if(numTerm == 0){
4169 191 : pointingDirection.push_back(ASDMAngleV(dirV[0]));
4170 : }
4171 : else{
4172 0 : if(numTerm != (Int)dirV.size()){
4173 : os << LogIO::SEVERE << "Inconsistent MS: in pointing table row " << firstRow
4174 0 : << ": numpoly + 1 should be == dimension of array DIRECTION." << LogIO::POST;
4175 0 : return false;
4176 : }
4177 0 : for(uInt i=0; i<(uInt)numTerm; i++){
4178 0 : pointingDirection.push_back(ASDMAngleV(dirV[i]));
4179 : }
4180 : }
4181 :
4182 191 : vector< vector< Angle > > encoder;
4183 191 : if(pointing().encoderMeas().isNull()){ // encoder column is optional in MS but not in ASDM
4184 164 : if(numTerm == 0){
4185 : // use pointing Direction instead
4186 164 : if(!warned){
4187 : os << LogIO::WARN << "No ENCODER column in MS Pointing table. Will use DIRECTION instead."
4188 6 : << LogIO::POST;
4189 6 : warned = true;
4190 : }
4191 164 : dirV.reference(pointing().directionMeasCol()(firstRow));
4192 164 : encoder.push_back(ASDMAngleV(dirV[0]));
4193 : }
4194 : else{ // cannot use pointing direction because it contains only polynomial terms
4195 0 : vector< Angle > angV;
4196 0 : angV.push_back(Angle(0.));
4197 0 : angV.push_back(Angle(0.));
4198 0 : if(!warned){
4199 : os << LogIO::WARN << "No ENCODER column in MS Pointing table. Will fill with zeros."
4200 0 : << LogIO::POST;
4201 0 : warned = true;
4202 : }
4203 0 : encoder.push_back(angV);
4204 0 : }
4205 : }
4206 : else{
4207 27 : encoder.push_back(ASDMAngleV(pointing().encoderMeas()(firstRow)));
4208 : }
4209 :
4210 191 : vector< vector< Angle > > target;
4211 191 : dirV.reference(pointing().targetMeasCol()(firstRow));
4212 191 : if(numTerm == 0){
4213 191 : target.push_back(ASDMAngleV(dirV[0]));
4214 : }
4215 : else{
4216 0 : if(numTerm != (Int)dirV.size()){
4217 : os << LogIO::SEVERE << "Inconsistent MS: in pointing table row " << firstRow
4218 0 : << ": numpoly + 1 should be == dimension of array TARGET." << LogIO::POST;
4219 0 : return false;
4220 : }
4221 0 : for(uInt i=0; i<(uInt)numTerm; i++){
4222 0 : target.push_back(ASDMAngleV(dirV[i]));
4223 : }
4224 : }
4225 :
4226 191 : vector< vector< asdm::Angle > > offset;
4227 : // source offset column is optional in the MS but not in the ASDM
4228 191 : if(pointing().pointingOffsetMeasCol().isNull()){ // no MS source offset column
4229 164 : vector< Angle > angV;
4230 164 : angV.push_back(Angle(0.));
4231 164 : angV.push_back(Angle(0.));
4232 164 : offset.push_back(angV);
4233 164 : if(numTerm>0){
4234 0 : for(uInt i=1; i<(uInt)numTerm; i++){
4235 0 : offset.push_back(angV);
4236 : }
4237 : }
4238 164 : }
4239 : else{
4240 27 : dirV.reference(pointing().pointingOffsetMeasCol()(firstRow));
4241 27 : if(numTerm==0){
4242 27 : offset.push_back(ASDMAngleV(dirV[0]));
4243 : }
4244 : else{
4245 0 : if(numTerm != (Int)dirV.size()){
4246 : os << LogIO::SEVERE << "Inconsistent MS: in pointing table row " << firstRow
4247 0 : << ": numpoly + 1 should be == dimension of array POINTING_OFFSET." << LogIO::POST;
4248 0 : return false;
4249 : }
4250 0 : for(uInt i=0; i<(uInt)numTerm; i++){
4251 0 : offset.push_back(ASDMAngleV(dirV[i]));
4252 : }
4253 : }
4254 : }
4255 :
4256 191 : vector< vector< Angle > > sourceOffset; // optional in the ASDM and in the MS
4257 191 : if(!pointing().sourceOffsetMeasCol().isNull()){ // sourceOffset column is present
4258 0 : dirV.reference(pointing().sourceOffsetMeasCol()(firstRow));
4259 0 : if(numTerm==0){
4260 0 : sourceOffset.push_back(ASDMAngleV(dirV[0]));
4261 : }
4262 : else{
4263 0 : if(numTerm != (Int)dirV.size()){
4264 : os << LogIO::SEVERE << "Inconsistent MS: in pointing table row " << firstRow
4265 0 : << ": numpoly + 1 should be == dimension of array SOURCE_OFFSET." << LogIO::POST;
4266 0 : return false;
4267 : }
4268 0 : for(uInt i=0; i<(uInt)numTerm; i++){
4269 0 : sourceOffset.push_back(ASDMAngleV(dirV[i]));
4270 : }
4271 : }
4272 : }
4273 :
4274 191 : int pointingModelId = asdmPointingModelId_p[antennaId];
4275 191 : double endTimeMJD = timeInterval.getStartInMJD() + timeInterval.getDurationInDays();
4276 :
4277 : // check if there are more rows for this antenna with adjacent time intervals
4278 191 : irow++;
4279 :
4280 1272452 : while(irow<nPointingRows && numTerm==0){ // while we find more adjacent rows and don't use polynomials
4281 :
4282 1272261 : if(pointing().antennaId()(irow) != aId){
4283 1216074 : irow++;
4284 1216074 : continue;
4285 : }
4286 :
4287 : // need to do the comparison this way because this is close to how the PointingTable class
4288 : // decides how to add a new row
4289 :
4290 112374 : ArrayTimeInterval thisTimeInterval = ASDMTimeInterval(pointing().timeQuant()(irow), pointing().intervalQuant()(irow));
4291 56187 : if( !casacore::near(endTimeMJD,thisTimeInterval.getStartInMJD()) // row irow is adjacent in time to previous row
4292 56187 : || pointingTracking != pointing().tracking()(irow)
4293 112374 : || (usePolynomials == false && pointing().numPoly()(irow)>0)
4294 : ){
4295 0 : break; // there will be no further samples for this ASDM pointing table row
4296 : }
4297 :
4298 : // found a second pointing row for the antenna ID, now accumulate directions
4299 : // until time ranges not contiguous or end of table
4300 :
4301 56187 : numRows++;
4302 56187 : endTimeMJD = thisTimeInterval.getStartInMJD() + thisTimeInterval.getDurationInDays();
4303 :
4304 : // update timeInterval - this may not be exactly the same as adding the durations
4305 56187 : timeInterval.setDuration(endTimeMJD - timeInterval.getStartInMJD());
4306 :
4307 56187 : dirV.reference(pointing().directionMeasCol()(irow));
4308 56187 : pointingDirection.push_back(ASDMAngleV(dirV[0]));
4309 :
4310 56187 : if(pointing().encoderMeas().isNull()){ // encoder column is optional
4311 : // use pointing Direction instead
4312 22140 : encoder.push_back(ASDMAngleV(dirV[0]));
4313 : }
4314 : else{
4315 34047 : encoder.push_back(ASDMAngleV(pointing().encoderMeas()(irow)));
4316 : }
4317 :
4318 56187 : dirV.reference(pointing().targetMeasCol()(irow));
4319 56187 : target.push_back(ASDMAngleV(dirV[0]));
4320 :
4321 56187 : if(pointing().pointingOffsetMeasCol().isNull()){ // source offset column is optional
4322 22140 : vector< Angle > angV;
4323 22140 : angV.push_back(Angle(0.));
4324 22140 : angV.push_back(Angle(0.));
4325 22140 : offset.push_back(angV);
4326 22140 : }
4327 : else{
4328 34047 : dirV.reference(pointing().pointingOffsetMeasCol()(irow));
4329 34047 : offset.push_back(ASDMAngleV(dirV[0]));
4330 : }
4331 :
4332 56187 : if(!pointing().sourceOffsetMeasCol().isNull()){ // source offset column is optional
4333 0 : dirV.reference(pointing().sourceOffsetMeasCol()(irow));
4334 0 : sourceOffset.push_back(ASDMAngleV(dirV[0]));
4335 : }
4336 56187 : irow++;
4337 :
4338 56187 : } // end while accumulating for started entry
4339 :
4340 : // finish the ASDM table row and add it to the table
4341 191 : int numSample = encoder.size();
4342 191 : if(!usePolynomials){
4343 191 : numTerm = numSample;
4344 : }
4345 :
4346 191 : tR = tT.newRow(antennaId, timeInterval, numSample, encoder, pointingTracking, usePolynomials, timeOrigin,
4347 : numTerm, pointingDirection, target, offset, pointingModelId);
4348 :
4349 191 : if(sourceOffset.size()>0){
4350 0 : tR->setSourceOffset(sourceOffset);
4351 : }
4352 :
4353 191 : asdm::PointingRow* tR2 = 0;
4354 :
4355 : try{
4356 191 : tR2 = tT.add(tR);
4357 : }
4358 0 : catch(asdm::DuplicateKey){
4359 : os << LogIO::WARN << "Caught asdm::DuplicateKey error for antenna id "
4360 0 : << aId << LogIO::POST;
4361 0 : }
4362 191 : if(tR2 != tR){// no new row was inserted
4363 : os << LogIO::WARN << "Internal error: duplicate row in Pointing table for antenna id "
4364 0 : << aId << LogIO::POST;
4365 : }
4366 : else{
4367 191 : if(verbosity_p>1){
4368 : os << LogIO::NORMAL << "Combined " << numRows
4369 : << " MS Pointing table rows into one ASDM Pointing table row for antenna id "
4370 0 : << aId << LogIO::POST;
4371 : }
4372 : }
4373 191 : totNumRows += numRows;
4374 :
4375 191 : } // end while rows left in pointing table
4376 :
4377 191 : if(totNumRows==0){
4378 : os << LogIO::WARN << "No MS Pointing table rows found for antenna id "
4379 0 : << aId << LogIO::POST;
4380 : }
4381 :
4382 : } // end loop over antenna ids
4383 :
4384 9 : EntityId theUid(getCurrentUid());
4385 9 : Entity ent = tT.getEntity();
4386 9 : ent.setEntityId(theUid);
4387 9 : tT.setEntity(ent);
4388 9 : if(verbosity_p>0){
4389 9 : os << LogIO::NORMAL << "Filled Pointing table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
4390 : }
4391 9 : incrementUid();
4392 :
4393 9 : return rstat;
4394 13 : }
4395 :
4396 49 : StokesParameterMod::StokesParameter MS2ASDM::ASDMStokesParameter( Stokes::StokesTypes s) {
4397 49 : switch (s) {
4398 0 : case Stokes::I: return StokesParameterMod::I;
4399 0 : case Stokes::Q: return StokesParameterMod::Q;
4400 0 : case Stokes::U: return StokesParameterMod::U;
4401 0 : case Stokes::V: return StokesParameterMod::V;
4402 1 : case Stokes::RR: return StokesParameterMod::RR;
4403 1 : case Stokes::RL: return StokesParameterMod::RL;
4404 1 : case Stokes::LR: return StokesParameterMod::LR;
4405 1 : case Stokes::LL: return StokesParameterMod::LL;
4406 33 : case Stokes::XX: return StokesParameterMod::XX;
4407 0 : case Stokes::XY: return StokesParameterMod::XY;
4408 0 : case Stokes::YX: return StokesParameterMod::YX;
4409 12 : case Stokes::YY: return StokesParameterMod::YY;
4410 0 : case Stokes::RX: return StokesParameterMod::RX;
4411 0 : case Stokes::RY: return StokesParameterMod::RY;
4412 0 : case Stokes::LX: return StokesParameterMod::LX;
4413 0 : case Stokes::LY: return StokesParameterMod::LY;
4414 0 : case Stokes::XR: return StokesParameterMod::XR;
4415 0 : case Stokes::XL: return StokesParameterMod::XL;
4416 0 : case Stokes::YR: return StokesParameterMod::YR;
4417 0 : case Stokes::YL: return StokesParameterMod::YL;
4418 0 : case Stokes::PP: return StokesParameterMod::PP;
4419 0 : case Stokes::PQ: return StokesParameterMod::PQ;
4420 0 : case Stokes::QP: return StokesParameterMod::QP;
4421 0 : case Stokes::QQ: return StokesParameterMod::QQ;
4422 0 : case Stokes::RCircular: return StokesParameterMod::RCIRCULAR;
4423 0 : case Stokes::LCircular: return StokesParameterMod::LCIRCULAR;
4424 0 : case Stokes::Linear: return StokesParameterMod::LINEAR;
4425 0 : case Stokes::Ptotal: return StokesParameterMod::PTOTAL;
4426 0 : case Stokes::Plinear: return StokesParameterMod::PLINEAR;
4427 0 : case Stokes::PFtotal: return StokesParameterMod::PFTOTAL;
4428 0 : case Stokes::PFlinear: return StokesParameterMod::PFLINEAR;
4429 0 : case Stokes::Pangle: return StokesParameterMod::PANGLE;
4430 0 : case Stokes::Undefined:
4431 : default:
4432 0 : throw(AipsError("Undefined stokes parameter."+String((Int)s)) );
4433 : }
4434 : }
4435 :
4436 259 : AntennaTypeMod::AntennaType MS2ASDM::ASDMAntennaType( const String& type ){
4437 518 : LogIO os(LogOrigin("MS2ASDM", "(ASDMAntennaType)"));
4438 259 : if(type == "GROUND-BASED"){
4439 259 : return AntennaTypeMod::GROUND_BASED;
4440 : }
4441 0 : else if(type == "SPACE-BASED"){
4442 0 : return AntennaTypeMod::SPACE_BASED;
4443 : }
4444 : else{
4445 0 : os << LogIO::WARN << "Unknown antenna type " << type << " assuming GROUND-BASED." << LogIO::POST;
4446 0 : return AntennaTypeMod::GROUND_BASED;
4447 : }
4448 259 : }
4449 :
4450 58032 : ArrayTimeInterval MS2ASDM::ASDMTimeInterval( const Quantity midpoint, const Quantity interval){
4451 58032 : Double sTime = midpoint.getValue("s");
4452 58032 : Double sInterval = interval.getValue("s");
4453 :
4454 : // watch for sInterval==0 which means these correspond to a constant value over the whole MS
4455 58032 : if (sInterval == 0.) {
4456 71 : sTime = timestampStartSecs(0);
4457 71 : sInterval = timestampEndSecs(ms_p.nrow()-1) - sTime;
4458 : } else {
4459 : // very large values of sInterval also signify a constant value, probably in the original SDM
4460 : // this is somewhat arbitrary but is intended to be safe, there's probably no harm
4461 : // in writing out large values to the SDM as they will be recovered when read back in
4462 : // let "large" here be > about 1 year - could probably be smaller and still be safe
4463 : // 24*60*60*365
4464 57961 : if (sInterval > 31536000.0) {
4465 1531 : sTime = timestampStartSecs(0);
4466 1531 : sInterval = timestampEndSecs(ms_p.nrow()-1) - sTime;
4467 : } else {
4468 : // the usual case, turn sTime into the start time
4469 56430 : sTime -= sInterval/2.;
4470 : }
4471 : }
4472 :
4473 116064 : ArrayTimeInterval timeInterval( ASDMArrayTime(sTime),
4474 116064 : ASDMInterval(sInterval) );
4475 58032 : return timeInterval;
4476 : }
4477 :
4478 203208 : vector< Angle > MS2ASDM::ASDMAngleV(const MDirection mDir){
4479 203208 : vector< Angle > angV;
4480 203208 : angV.push_back( mDir.getAngle( unitASDMAngle() ).getValue()(0) );
4481 203208 : angV.push_back( mDir.getAngle( unitASDMAngle() ).getValue()(1) );
4482 203208 : return angV;
4483 0 : }
4484 :
4485 898 : DirectionReferenceCodeMod::DirectionReferenceCode MS2ASDM::ASDMDirRefCode(const MDirection::Types type){
4486 :
4487 898 : switch(type){
4488 898 : case MDirection::J2000: return DirectionReferenceCodeMod::J2000;
4489 0 : case MDirection::JMEAN: return DirectionReferenceCodeMod::JMEAN;
4490 0 : case MDirection::JTRUE: return DirectionReferenceCodeMod::JTRUE;
4491 0 : case MDirection::APP: return DirectionReferenceCodeMod::APP;
4492 0 : case MDirection::B1950: return DirectionReferenceCodeMod::B1950;
4493 0 : case MDirection::B1950_VLA: return DirectionReferenceCodeMod::B1950_VLA;
4494 0 : case MDirection::BMEAN: return DirectionReferenceCodeMod::BMEAN;
4495 0 : case MDirection::BTRUE: return DirectionReferenceCodeMod::BTRUE;
4496 0 : case MDirection::GALACTIC: return DirectionReferenceCodeMod::GALACTIC;
4497 0 : case MDirection::HADEC: return DirectionReferenceCodeMod::HADEC;
4498 0 : case MDirection::AZELSW: return DirectionReferenceCodeMod::AZELSW;
4499 0 : case MDirection::AZELSWGEO: return DirectionReferenceCodeMod::AZELSWGEO;
4500 : //case MDirection::AZELGEO: return DirectionReferenceCodeMod::AZELNEGEO; //(same case as MDirection::AZELNEGEO!)
4501 0 : case MDirection::AZELNEGEO: return DirectionReferenceCodeMod::AZELNEGEO;
4502 0 : case MDirection::JNAT: return DirectionReferenceCodeMod::JNAT;
4503 0 : case MDirection::ECLIPTIC: return DirectionReferenceCodeMod::ECLIPTIC;
4504 0 : case MDirection::MECLIPTIC: return DirectionReferenceCodeMod::MECLIPTIC;
4505 0 : case MDirection::TECLIPTIC: return DirectionReferenceCodeMod::TECLIPTIC;
4506 0 : case MDirection::SUPERGAL: return DirectionReferenceCodeMod::SUPERGAL;
4507 0 : case MDirection::ITRF: return DirectionReferenceCodeMod::ITRF;
4508 0 : case MDirection::TOPO: return DirectionReferenceCodeMod::TOPO;
4509 0 : case MDirection::ICRS: return DirectionReferenceCodeMod::ICRS;
4510 :
4511 0 : case MDirection::MERCURY: return DirectionReferenceCodeMod::MERCURY;
4512 0 : case MDirection::VENUS: return DirectionReferenceCodeMod::VENUS;
4513 0 : case MDirection::MARS: return DirectionReferenceCodeMod::MARS;
4514 0 : case MDirection::JUPITER: return DirectionReferenceCodeMod::JUPITER;
4515 0 : case MDirection::SATURN: return DirectionReferenceCodeMod::SATURN;
4516 0 : case MDirection::URANUS: return DirectionReferenceCodeMod::URANUS;
4517 0 : case MDirection::NEPTUNE: return DirectionReferenceCodeMod::NEPTUNE;
4518 0 : case MDirection::PLUTO: return DirectionReferenceCodeMod::PLUTO;
4519 0 : case MDirection::SUN: return DirectionReferenceCodeMod::SUN;
4520 0 : case MDirection::MOON: return DirectionReferenceCodeMod::MOON;
4521 0 : default:
4522 0 : return DirectionReferenceCodeMod::J2000;
4523 : }
4524 :
4525 : }
4526 :
4527 :
4528 74 : BasebandNameMod::BasebandName MS2ASDM::ASDMBBName( Int BBCNo ){
4529 74 : switch(BBCNo){
4530 18 : case 1: return BasebandNameMod::BB_1;
4531 18 : case 2: return BasebandNameMod::BB_2;
4532 18 : case 3: return BasebandNameMod::BB_3;
4533 18 : case 4: return BasebandNameMod::BB_4;
4534 0 : case 5: return BasebandNameMod::BB_5;
4535 0 : case 6: return BasebandNameMod::BB_6;
4536 0 : case 7: return BasebandNameMod::BB_7;
4537 0 : case 8: return BasebandNameMod::BB_8;
4538 2 : case 0:
4539 : default:
4540 2 : return BasebandNameMod::NOBB;
4541 : }
4542 : }
4543 :
4544 107 : NetSidebandMod::NetSideband MS2ASDM::ASDMNetSideBand( Int netSideB ){
4545 107 : switch(netSideB){
4546 71 : case 1: return NetSidebandMod::LSB;
4547 36 : case 2: return NetSidebandMod::USB;
4548 0 : case 3: return NetSidebandMod::DSB;
4549 0 : case 0:
4550 : default:
4551 0 : return NetSidebandMod::NOSB;
4552 : }
4553 : }
4554 :
4555 107 : FrequencyReferenceCodeMod::FrequencyReferenceCode MS2ASDM::ASDMFreqRefCode( const MFrequency::Types refFrame ){
4556 214 : LogIO os(LogOrigin("MS2ASDM", "(ASDMFreqRefCode)"));
4557 107 : switch( refFrame ){
4558 0 : case MFrequency::LSRD: return FrequencyReferenceCodeMod::LSRD;
4559 27 : case MFrequency::LSRK: return FrequencyReferenceCodeMod::LSRK;
4560 0 : case MFrequency::BARY: return FrequencyReferenceCodeMod::BARY;
4561 0 : case MFrequency::REST: return FrequencyReferenceCodeMod::REST;
4562 0 : case MFrequency::GEO: return FrequencyReferenceCodeMod::GEO;
4563 0 : case MFrequency::GALACTO: return FrequencyReferenceCodeMod::GALACTO;
4564 80 : case MFrequency::TOPO: return FrequencyReferenceCodeMod::TOPO;
4565 0 : default:
4566 : os << LogIO::SEVERE << "Unsupported CASA reference frame " << MFrequency::showType(refFrame)
4567 0 : << ", assuming TOPO." << LogIO::POST;
4568 0 : return FrequencyReferenceCodeMod::TOPO;
4569 : }
4570 107 : }
4571 :
4572 1 : Bool MS2ASDM::stokesTypePresent( const Vector< Int > corrT,
4573 : const Stokes::StokesTypes st ){
4574 1 : Bool rval = false;
4575 2 : for(uInt j=0; j<corrT.size(); j++){
4576 2 : if(corrT[j]==static_cast<Int>(st)){
4577 1 : rval = true;
4578 1 : break;
4579 : }
4580 : }
4581 1 : return rval;
4582 : }
4583 :
4584 4643 : Int MS2ASDM::setRecBands( const asdm::Frequency refFreq,
4585 : double& repFreq,
4586 : ReceiverBandMod::ReceiverBand& frequencyBand,
4587 : ReceiverSidebandMod::ReceiverSideband& receiverSideband){
4588 :
4589 : // return the band number as an Int, -1 means failure, 0 means unknown observatory
4590 4643 : Int rval = -1;
4591 :
4592 4643 : Quantity theFreq( refFreq.get(), String(Frequency::unit()) );
4593 4643 : Double theFreqGHz = theFreq.getValue("GHz");
4594 :
4595 : //cout << "tel " << telName_p << endl;
4596 : //cout << "Freq (GHz) " << theFreqGHz << endl;
4597 :
4598 : // default values
4599 4643 : Quantity tempQ( ((Int)theFreqGHz)*1E9, "Hz");
4600 4643 : repFreq = tempQ.getValue(unitASDMFreq());
4601 4643 : frequencyBand = ReceiverBandMod::UNSPECIFIED;
4602 4643 : receiverSideband = ReceiverSidebandMod::NOSB;
4603 :
4604 : // implementation of the ALMA freq bands !!!
4605 4643 : if(telName_p == "ALMA" || telName_p == "OSF" || telName_p == "ACA"){
4606 3646 : if(31.<=theFreqGHz && theFreqGHz<45.){
4607 0 : repFreq = (31.+45.)/2.*1E9;
4608 0 : frequencyBand = ReceiverBandMod::ALMA_RB_01;
4609 0 : receiverSideband = ReceiverSidebandMod::SSB;
4610 0 : rval = 1;
4611 : }
4612 3646 : else if(67.<=theFreqGHz && theFreqGHz<90.){
4613 0 : repFreq = (67.+90.)/2.*1E9;
4614 0 : frequencyBand = ReceiverBandMod::ALMA_RB_02;
4615 0 : receiverSideband = ReceiverSidebandMod::SSB;
4616 0 : rval = 2;
4617 : }
4618 3646 : else if(84.<=theFreqGHz && theFreqGHz<116.){
4619 0 : repFreq = (84.+116.)/2.*1E9;
4620 0 : frequencyBand = ReceiverBandMod::ALMA_RB_03;
4621 0 : receiverSideband = ReceiverSidebandMod::TSB;
4622 0 : rval = 3;
4623 : }
4624 3646 : else if(125.<=theFreqGHz && theFreqGHz<163.){
4625 0 : repFreq = (125.+163.)/2.*1E9;
4626 0 : frequencyBand = ReceiverBandMod::ALMA_RB_04;
4627 0 : receiverSideband = ReceiverSidebandMod::TSB;
4628 0 : rval = 4;
4629 : }
4630 3646 : else if(163.<=theFreqGHz && theFreqGHz<211.){
4631 0 : repFreq = (163.+211.)/2.*1E9;
4632 0 : frequencyBand = ReceiverBandMod::ALMA_RB_05;
4633 0 : receiverSideband = ReceiverSidebandMod::TSB;
4634 0 : rval = 5;
4635 : }
4636 3646 : else if(211.<=theFreqGHz && theFreqGHz<275.){
4637 3096 : repFreq = (211.+275.)/2.*1E9;
4638 3096 : frequencyBand = ReceiverBandMod::ALMA_RB_06;
4639 3096 : receiverSideband = ReceiverSidebandMod::TSB;
4640 3096 : rval = 6;
4641 : }
4642 550 : else if(275.<=theFreqGHz && theFreqGHz<373.){
4643 402 : repFreq = (275.+373.)/2.*1E9;
4644 402 : frequencyBand = ReceiverBandMod::ALMA_RB_07;
4645 402 : receiverSideband = ReceiverSidebandMod::TSB;
4646 402 : rval = 7;
4647 : }
4648 148 : else if(385.<=theFreqGHz && theFreqGHz<500.){
4649 0 : repFreq = (385.+500.)/2.*1E9;
4650 0 : frequencyBand = ReceiverBandMod::ALMA_RB_08;
4651 0 : receiverSideband = ReceiverSidebandMod::TSB;
4652 0 : rval = 8;
4653 : }
4654 148 : else if(602.<=theFreqGHz && theFreqGHz<720.){
4655 148 : repFreq = (602.+720.)/2.*1E9;
4656 148 : frequencyBand = ReceiverBandMod::ALMA_RB_09;
4657 148 : receiverSideband = ReceiverSidebandMod::DSB;
4658 148 : rval = 9;
4659 : }
4660 0 : else if(787.<=theFreqGHz && theFreqGHz<950.){
4661 0 : repFreq = (787.+950.)/2.*1E9;
4662 0 : frequencyBand = ReceiverBandMod::ALMA_RB_10;
4663 0 : receiverSideband = ReceiverSidebandMod::DSB;
4664 0 : rval = 10;
4665 : }
4666 : else{
4667 0 : repFreq = theFreqGHz*1E9;
4668 0 : frequencyBand = ReceiverBandMod::UNSPECIFIED;
4669 0 : receiverSideband = ReceiverSidebandMod::TSB;
4670 0 : rval = 0;
4671 : }
4672 :
4673 3646 : Quantity tempQ2(repFreq, "Hz");
4674 3646 : repFreq = tempQ2.getValue(unitASDMFreq());
4675 3646 : return rval;
4676 3646 : }
4677 997 : else if(telName_p == "VLA" || telName_p == "EVLA" || telName_p == "JVLA"){
4678 : // EVLA freq band implementation!!
4679 42 : if( 0.033 <=theFreqGHz && theFreqGHz<0.081 ){
4680 0 : repFreq = (0.033/0.081)/2.*1E9;
4681 0 : frequencyBand = ReceiverBandMod::EVLA_4;
4682 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4683 0 : rval = 1;
4684 : }
4685 42 : else if(0.298<=theFreqGHz && theFreqGHz< 0.345){
4686 0 : repFreq = (0.298+0.345)/2.*1E9;
4687 0 : frequencyBand = ReceiverBandMod::EVLA_P;
4688 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4689 0 : rval = 2;
4690 : }
4691 42 : else if(1.0 <=theFreqGHz && theFreqGHz< 2.0){
4692 0 : repFreq = (1.+2.)/2.*1E9;
4693 0 : frequencyBand = ReceiverBandMod::EVLA_L;
4694 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4695 0 : rval = 3;
4696 : }
4697 42 : else if(2.0 <=theFreqGHz && theFreqGHz< 4.0){
4698 0 : repFreq = (2.+4.)/2.*1E9;
4699 0 : frequencyBand = ReceiverBandMod::EVLA_S;
4700 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4701 0 : rval = 4;
4702 : }
4703 42 : else if(4.0 <=theFreqGHz && theFreqGHz< 8.0){
4704 0 : repFreq = (4.+8.)/2.*1E9;
4705 0 : frequencyBand = ReceiverBandMod::EVLA_C;
4706 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4707 0 : rval = 5;
4708 : }
4709 42 : else if(8.0 <=theFreqGHz && theFreqGHz< 12.0){
4710 42 : repFreq = (8.+12.)/2.*1E9;
4711 42 : frequencyBand = ReceiverBandMod::EVLA_X;
4712 42 : receiverSideband = ReceiverSidebandMod::NOSB;
4713 42 : rval = 6;
4714 : }
4715 0 : else if(12. <=theFreqGHz && theFreqGHz< 18.){
4716 0 : repFreq = (12.+18.)/2.*1E9;
4717 0 : frequencyBand = ReceiverBandMod::EVLA_Ku; // a.k.a. U
4718 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4719 0 : rval = 7;
4720 : }
4721 0 : else if(18.0 <=theFreqGHz && theFreqGHz< 26.5){
4722 0 : repFreq = (18.+26.5)/2.*1E9;
4723 0 : frequencyBand = ReceiverBandMod::EVLA_K;
4724 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4725 0 : rval = 8;
4726 : }
4727 0 : else if(26.5 <=theFreqGHz && theFreqGHz< 40.){
4728 0 : repFreq = (26.5+40.)/2.*1E9;
4729 0 : frequencyBand = ReceiverBandMod::EVLA_Ka;
4730 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4731 0 : rval = 9;
4732 : }
4733 0 : else if(40. <=theFreqGHz && theFreqGHz< 50.){
4734 0 : repFreq = (40.+50.)/2.*1E9;
4735 0 : frequencyBand = ReceiverBandMod::EVLA_Q;
4736 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4737 0 : rval = 10;
4738 : }
4739 : else{
4740 0 : repFreq = theFreqGHz*1E9;
4741 0 : frequencyBand = ReceiverBandMod::UNSPECIFIED;
4742 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4743 0 : rval = 0;
4744 : }
4745 42 : Quantity tempQ2(repFreq, "Hz");
4746 42 : repFreq = tempQ2.getValue(unitASDMFreq());
4747 42 : return rval;
4748 42 : }
4749 :
4750 955 : return 0; // unknown observatory
4751 4643 : }
4752 :
4753 :
4754 : } //#End casa namespace
|