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 0 : MS2ASDM::MS2ASDM(MeasurementSet& ms) :
87 : MSColumns(ms),
88 0 : ms_p(ms),
89 0 : baseUid_p("uid://X0/X0/X"),
90 0 : runningId_p(0),
91 0 : currentUid_p("uid://X0/X0/X0"),
92 0 : telName_p(""),
93 : // the maps with defaults
94 0 : asdmFeedId_p(-1),
95 0 : asdmSourceId_p(-1),
96 0 : asdmPointingModelId_p(-1)
97 : {
98 0 : ASDM_p = new ASDM();
99 0 : asdmVersion_p = String((ASDM_p->getEntity()).getEntityVersion());
100 0 : setSBDuration(); // set to default values
101 0 : setSubScanDuration();
102 0 : setDataAPCorrected();
103 0 : setVerbosity();
104 0 : }
105 :
106 0 : MS2ASDM::~MS2ASDM()
107 : {
108 0 : delete ASDM_p;
109 0 : }
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 0 : void MS2ASDM::setBaseUid(const String& baseuid){ baseUid_p = baseuid; }
124 :
125 0 : const String& MS2ASDM::getBaseUid(){ return baseUid_p; }
126 :
127 0 : const std::string& MS2ASDM::getCurrentUid(){
128 0 : static std::string str;
129 0 : str = string(currentUid_p.c_str());
130 0 : return str;
131 : }
132 :
133 0 : const std::string& MS2ASDM::getCurrentUidAsFileName(){
134 0 : static std::string str;
135 0 : str = string(currentUid_p.c_str());
136 0 : std::replace( str.begin(), str.end(), ':', '_' );
137 0 : std::replace( str.begin(), str.end(), '/', '_' );
138 :
139 0 : return str;
140 : }
141 :
142 0 : Bool MS2ASDM::incrementUid()
143 : {
144 : static char cstr[20];
145 0 : runningId_p++;
146 0 : if(sprintf(cstr,"%x", runningId_p) > 0){
147 0 : currentUid_p = baseUid_p + String(cstr);
148 0 : return true;
149 : }
150 : else{
151 0 : runningId_p--;
152 0 : return false;
153 : }
154 : }
155 :
156 0 : 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 0 : LogIO os(LogOrigin("MS2ASDM", "writeASDM()"));
163 :
164 0 : setBaseUid("uid://"+archiveid+"/"+rangeid+"/X");
165 :
166 0 : 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 0 : asdmUID_p = getCurrentUid().c_str();
174 0 : Entity myEntity;
175 0 : myEntity.setEntityId(EntityId(asdmUID_p));
176 0 : myEntity.setEntityIdEncrypted("na");
177 0 : myEntity.setEntityTypeName("ASDM");
178 0 : myEntity.setEntityVersion(asdmVersion_p);
179 0 : myEntity.setInstanceVersion("1");
180 0 : ASDM_p->setEntity(myEntity);
181 :
182 0 : incrementUid();
183 :
184 : // initialize observatory name
185 0 : if(observation().nrow()==0){
186 0 : os << LogIO::SEVERE << "MS Observation table is empty." << LogIO::POST;
187 0 : return false;
188 : }
189 :
190 0 : setObservatoryName(observation().telescopeName()(0)); // get name of observatory from first row of observation table
191 :
192 0 : 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 0 : 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 0 : setSubScanDuration(subscanDuration);
205 :
206 0 : setSBDuration(schedBlockDuration);
207 :
208 0 : setDataAPCorrected(msDataIsAPCorrected);
209 :
210 0 : if(verbose){
211 0 : setVerbosity(1); // set to 1 before releasing
212 : }
213 : else{
214 0 : setVerbosity(0);
215 : }
216 :
217 0 : if(verbosity_p>0){
218 : os << LogIO::NORMAL << "Converting " << ms_p.tableName() << " to ASDM " << asdmfile << endl
219 0 : << "UID base is " << getBaseUid() << ", ASDM UID is " << asdmUID_p
220 0 : << LogIO::POST;
221 : }
222 :
223 : // write the ASDM tables
224 :
225 0 : if(!writeStation()){
226 0 : return false;
227 : }
228 :
229 0 : if(!writeAntenna()){
230 0 : return false;
231 : }
232 :
233 0 : if(!writeSpectralWindow()){
234 0 : return false;
235 : }
236 :
237 0 : if(!writeSource()){
238 0 : return false;
239 : }
240 :
241 0 : if(!writePolarization()){
242 0 : return false;
243 : }
244 :
245 0 : if(!writeProcessor()){
246 0 : return false;
247 : }
248 :
249 0 : if(!writeField()){
250 0 : return false;
251 : }
252 :
253 0 : if(!writeReceiver()){
254 0 : return false;
255 : }
256 :
257 0 : if(!writeFeed()){
258 0 : return false;
259 : }
260 :
261 0 : if(!writeDataDescription()){
262 0 : return false;
263 : }
264 :
265 0 : if(!writeSwitchCycle()){
266 0 : return false;
267 : }
268 :
269 0 : if(!writeState()){
270 0 : return false;
271 : }
272 :
273 0 : if(!writeSysCal()){
274 0 : return false;
275 : }
276 :
277 0 : if(!writeConfigDescription()){
278 0 : return false;
279 : }
280 :
281 0 : if(!writeSBSummaryAndExecBlockStubs()){
282 0 : return false;
283 : }
284 :
285 : // prepare the writing of binary data
286 0 : if(!setDirectory(asdmfile)){
287 0 : return false;
288 : }
289 :
290 0 : if(!writeMainAndScanAndSubScan(datacolumn)){
291 0 : return false;
292 : }
293 :
294 0 : if(!writePointingModel()){
295 0 : return false;
296 : }
297 :
298 0 : if(!writePointing()){
299 0 : return false;
300 : }
301 :
302 : // finish writing the ASDM non-binary data
303 : try{
304 0 : 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 0 : return true;
313 :
314 0 : }
315 :
316 0 : Bool MS2ASDM::setDirectory(const String& asdmfile){
317 :
318 0 : LogIO os(LogOrigin("MS2ASDM", "setDirectory()"));
319 :
320 : // create ASDM output directories
321 0 : Directory asdmDir(asdmfile);
322 : // create if it doesn't exist
323 : try{
324 0 : asdmDir.isEmpty(); // throws if dir doesn't exist
325 : }
326 0 : catch(AipsError x){
327 : try{
328 0 : 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 0 : }
336 : // create ASDM binary output directory
337 0 : Directory asdmDir2(asdmfile+"/ASDMBinary");
338 : try{
339 0 : 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 0 : asdmDir_p = asdmfile;
347 0 : return true;
348 0 : }
349 :
350 :
351 0 : 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 0 : LogIO os(LogOrigin("MS2ASDM", "writeMainBinForOneDDIdAndSubScan()"));
360 :
361 : // return values
362 0 : Int numIntegrations = 0;
363 0 : datasize = 0;
364 0 : dataOid = EntityRef();
365 0 : stateIdV.resize(0);
366 :
367 0 : asdm::ExecBlockRow* eBlockRow = (ASDM_p->getExecBlock()).getRowByKey(eBlockId);
368 0 : string eBlockUID = eBlockRow->getExecBlockUID().getEntityId ().toString();
369 0 : int eBlockNum = eBlockRow->getExecBlockNum();
370 :
371 0 : Bool warned=false; // use later to avoid repetitive warnings
372 0 : Bool warned2=false; // use later to avoid repetitive warnings
373 :
374 : try{
375 :
376 0 : uInt nMainTabRows = ms_p.nrow();
377 :
378 0 : unsigned int subscanNum = theSubScan;
379 :
380 0 : 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 0 : 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 0 : Int DDId = dataDescId()(startRow);
393 0 : 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 0 : Int FId = fieldId()(startRow);
400 0 : 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 0 : 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 0 : Double subScanStartTime = time()(startRow);
419 0 : Double subScanEndTime = time()(endRow);
420 :
421 : // determine number of different timestamps in this subscan
422 0 : unsigned int numTimestampsCorr = 0;
423 0 : unsigned int numTimestampsAuto = 0;
424 0 : for(uInt i=startRow; i<=endRow; i++){
425 :
426 0 : DDId = dataDescId()(i);
427 0 : if(DDId != theDDId){ // skip all other Data Description Ids
428 0 : continue;
429 : }
430 0 : FId = fieldId()(i);
431 0 : if(FId != theFieldId){ // skip all other Field Ids
432 0 : continue;
433 : }
434 :
435 0 : if(antenna1()(i)==antenna2()(i)){
436 0 : numTimestampsAuto++;
437 : }
438 : else{
439 0 : numTimestampsCorr++;
440 : }
441 : } // end for i
442 :
443 0 : 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 0 : String subscanFileName = asdmDir_p+"/ASDMBinary/"+String(getCurrentUidAsFileName());
454 0 : if(verbosity_p>1){
455 0 : cout << " subscan filename is " << subscanFileName << endl;
456 : }
457 : try{
458 0 : 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 0 : ofstream ofs(subscanFileName.c_str());
469 :
470 : // set up SDMDataObjectWriter
471 :
472 0 : SDMDataObjectWriter sdmdow(&ofs, getCurrentUid()); // use default title
473 :
474 0 : uint64_t startTime = (uint64_t) floor(subScanStartTime);
475 0 : unsigned int execBlockNum = eBlockNum; // constant for all scans
476 0 : unsigned int scanNum = theScan; // ASDM scan numbering starts at 1
477 0 : 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 0 : uInt theSampleStartRow = 0;
484 : {
485 0 : uInt maxNRows = 0;
486 :
487 0 : uInt mainTabRowX=startRow;
488 :
489 0 : while(mainTabRowX <= endRow){
490 :
491 0 : DDId = dataDescId()(mainTabRowX);
492 0 : if(DDId != theDDId){ // skip all other Data Description Ids
493 0 : mainTabRowX++;
494 0 : continue;
495 : }
496 0 : FId = fieldId()(mainTabRowX);
497 0 : if(FId != theFieldId){ // skip all other Field Ids
498 0 : mainTabRowX++;
499 0 : continue;
500 : }
501 :
502 0 : Double theTStamp = time()(mainTabRowX);
503 0 : uInt sRow = mainTabRowX;
504 0 : uInt nRows = 0;
505 0 : while(mainTabRowX < nMainTabRows
506 0 : && time()(mainTabRowX)==theTStamp){
507 0 : DDId = dataDescId()(mainTabRowX);
508 0 : if(DDId != theDDId){ // skip all other Data Description Ids
509 0 : mainTabRowX++;
510 0 : continue;
511 : }
512 0 : FId = fieldId()(mainTabRowX);
513 0 : if(FId != theFieldId){ // skip all other Field Ids
514 0 : mainTabRowX++;
515 0 : continue;
516 : }
517 0 : nRows++;
518 0 : mainTabRowX++;
519 : }
520 0 : if(nRows>maxNRows){
521 0 : maxNRows = nRows;
522 0 : 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 0 : unsigned int numAutoCorrs = 0;
530 0 : unsigned int numBaselines = 0;
531 0 : unsigned int numAntennas = 0;
532 0 : vector<Int> ant;
533 : {
534 0 : uInt i = theSampleStartRow;
535 0 : Double thisTStamp = time()(i);
536 0 : while(i<nMainTabRows && time()(i)== thisTStamp){
537 :
538 0 : DDId = dataDescId()(i);
539 0 : if(DDId != theDDId){ // skip all other Data Description Ids
540 0 : i++;
541 0 : continue;
542 : }
543 0 : FId = fieldId()(i);
544 0 : if(FId != theFieldId){ // skip all other Field Ids
545 0 : i++;
546 0 : continue;
547 : }
548 :
549 0 : if(antenna1()(i) == antenna2()(i)){
550 0 : numAutoCorrs++;
551 : }
552 : else{
553 0 : numBaselines++;
554 : }
555 :
556 0 : Bool found = false;
557 0 : for(uInt j=0;j<ant.size();j++){
558 0 : if(antenna1()(i) == ant[j]){
559 0 : found = true;
560 0 : break;
561 : }
562 : }
563 0 : if(!found){
564 0 : ant.push_back(antenna1()(i));
565 0 : stateIdV.push_back( asdmStateId_p[stateId()(i)] );
566 : }
567 0 : found = false;
568 0 : for(uInt j=0;j<ant.size();j++){
569 0 : if(antenna2()(i) == ant[j]){
570 0 : found = true;
571 0 : break;
572 : }
573 : }
574 0 : if(!found){
575 0 : ant.push_back(antenna2()(i));
576 0 : stateIdV.push_back( asdmStateId_p[stateId()(i)] );
577 : }
578 0 : i++;
579 : }
580 : }
581 0 : numAntennas = ant.size();
582 :
583 : CorrelationModeMod::CorrelationMode correlationMode;
584 0 : if(numAutoCorrs==0){
585 0 : correlationMode = CorrelationModeMod::CROSS_ONLY;
586 : }
587 0 : else if(numBaselines>0){
588 0 : 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 0 : vector< AtmPhaseCorrectionMod::AtmPhaseCorrection > apc;
597 0 : if(dataIsAPCorrected()){
598 0 : apc.push_back(AtmPhaseCorrectionMod::AP_CORRECTED);
599 : }
600 : else{
601 0 : apc.push_back(AtmPhaseCorrectionMod::AP_UNCORRECTED);
602 : }
603 0 : vector< SDMDataObject::Baseband > basebands; // ???
604 :
605 : // construct spectral window and basedband vectors
606 :
607 0 : vector<SDMDataObject::SpectralWindow> spectralWindows;
608 :
609 : // for creating a Spectral Window
610 0 : uInt PolId = dataDescription().polarizationId()(theDDId);
611 0 : uInt numStokesMS = polarization().numCorr()(PolId);
612 :
613 0 : asdm::PolarizationRow* PR = (ASDM_p->getPolarization()).getRowByKey(asdmPolarizationId_p[PolId]);
614 0 : uInt numStokes = PR->getNumCorr();
615 0 : Array<Int> corrT = polarization().corrType()(PolId);
616 0 : vector<StokesParameterMod::StokesParameter> crossPolProducts = PR->getCorrType();
617 :
618 0 : vector<StokesParameterMod::StokesParameter> sdPolProduct;
619 0 : float scaleFactor = 1.;
620 0 : uInt spwId = dataDescription().spectralWindowId()(theDDId);
621 0 : unsigned int numSpectralPoint = spectralWindow().numChan()(spwId);
622 :
623 0 : OptionalSpectralResolutionType spectralResolution = SpectralResolutionTypeMod::FULL_RESOLUTION;
624 0 : if(numSpectralPoint<5){
625 : // spectralResolution = SpectralResolutionTypeMod::CHANNEL_AVERAGE;
626 0 : 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 0 : unsigned int numBin = 1; // number of switch cycles
636 0 : NetSidebandMod::NetSideband sideband = CNetSideband::from_int(spectralWindow().netSideband()(spwId));
637 :
638 : SDMDataObject::SpectralWindow spw(crossPolProducts,
639 : sdPolProduct,
640 : scaleFactor,
641 : numSpectralPoint,
642 : numBin,
643 0 : sideband);
644 :
645 0 : spectralWindows.push_back(spw);
646 :
647 :
648 0 : 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 0 : basebands.push_back(bband);
652 :
653 : // construct binary parts for dataStruct
654 0 : unsigned int bpFlagsSize = numSpectralPoint * numStokes * (numBaselines+numAutoCorrs);
655 :
656 0 : vector<AxisNameMod::AxisName> bpFlagsAxes;
657 0 : bpFlagsAxes.push_back(AxisNameMod::TIM); // order: inner part of loop should be last!!!!!!
658 0 : bpFlagsAxes.push_back(AxisNameMod::SPP);
659 0 : bpFlagsAxes.push_back(AxisNameMod::POL);
660 0 : SDMDataObject::BinaryPart bpFlags(bpFlagsSize, bpFlagsAxes);
661 0 : if(verbosity_p>1){
662 0 : cout << "FlagsSize " << bpFlagsSize << " numStokes " << numStokes << endl;
663 : }
664 :
665 0 : unsigned int bpTimesSize = 0; // only needed for data blanking
666 : //unsigned int bpTimesSize = numTimestampsCorr+numTimestampsAuto;
667 0 : vector<AxisNameMod::AxisName> bpTimesAxes;
668 : // bpTimesAxes.push_back(AxisNameMod::TIM);
669 0 : SDMDataObject::BinaryPart bpActualTimes(bpTimesSize, bpTimesAxes);
670 : // cout << "TimesSize " << bpTimesSize << endl;
671 :
672 0 : unsigned int bpDurSize = 0; // only needed for data blanking
673 : // unsigned int bpDurSize = numTimestampsCorr+numTimestampsAuto;
674 0 : vector<AxisNameMod::AxisName> bpDurAxes;
675 : // bpDurAxes.push_back(AxisNameMod::TIM);
676 0 : SDMDataObject::BinaryPart bpActualDurations(bpDurSize, bpDurAxes);
677 : // cout << "DurSize " << bpDurSize << endl;
678 :
679 0 : unsigned int bpLagsSize = 0; // not filled for the moment (only useful if LAG_DATA column present) -> Francois
680 0 : vector<AxisNameMod::AxisName> bpLagsAxes;
681 0 : bpLagsAxes.push_back(AxisNameMod::SPP); // ******
682 0 : SDMDataObject::ZeroLagsBinaryPart bpZeroLags(bpLagsSize, bpLagsAxes, CorrelatorTypeMod::FXF); // ALMA default
683 0 : if(telName_p != "ALMA" && telName_p != "OSF"){
684 0 : if(telName_p == "ACA" || telName_p == "VLBA" || telName_p == "EVLA"){
685 0 : bpZeroLags = SDMDataObject::ZeroLagsBinaryPart(bpLagsSize, bpLagsAxes, CorrelatorTypeMod::FX);
686 : }
687 : else{
688 0 : bpZeroLags = SDMDataObject::ZeroLagsBinaryPart(bpLagsSize, bpLagsAxes, CorrelatorTypeMod::XF);
689 : }
690 : }
691 : // cout << "LagsSize " << bpLagsSize << endl;
692 :
693 0 : unsigned int bpCrossSize = numSpectralPoint * numStokes * numBaselines * 2; // real + imag
694 0 : vector<AxisNameMod::AxisName> bpCrossAxes;
695 : // bpCrossAxes.push_back(AxisNameMod::TIM);
696 0 : bpCrossAxes.push_back(AxisNameMod::BAL);
697 0 : bpCrossAxes.push_back(AxisNameMod::SPP);
698 0 : bpCrossAxes.push_back(AxisNameMod::POL);
699 0 : SDMDataObject::BinaryPart bpCrossData(bpCrossSize, bpCrossAxes);
700 : // cout << "CrossSize " << bpCrossSize << endl;
701 :
702 0 : unsigned int bpAutoSize = numSpectralPoint * numStokes * numAutoCorrs;
703 0 : vector<AxisNameMod::AxisName> bpAutoAxes;
704 : // bpAutoAxes.push_back(AxisNameMod::TIM);
705 0 : bpAutoAxes.push_back(AxisNameMod::ANT);
706 0 : bpAutoAxes.push_back(AxisNameMod::SPP);
707 0 : bpAutoAxes.push_back(AxisNameMod::POL);
708 0 : SDMDataObject::AutoDataBinaryPart bpAutoData(bpAutoSize, bpAutoAxes, false); // not normalised
709 : // cout << "AutoSize " << bpAutoSize << endl;
710 :
711 : SDMDataObject::DataStruct dataStruct( apc, basebands, bpFlags, bpActualTimes, bpActualDurations,
712 0 : 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 0 : 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 0 : unsigned int integrationNum = 1;
745 0 : uInt mainTabRow=startRow;
746 :
747 0 : while(mainTabRow <= endRow){
748 :
749 0 : DDId = dataDescId()(mainTabRow);
750 0 : if(DDId != theDDId){ // skip all other Data Description Ids
751 0 : mainTabRow++;
752 0 : continue;
753 : }
754 0 : FId = fieldId()(mainTabRow);
755 0 : if(FId != theFieldId){ // skip all other Field Ids
756 0 : mainTabRow++;
757 0 : continue;
758 : }
759 :
760 0 : uint64_t timev = (uint64_t) floor((time()(mainTabRow))*1E9); // what units? nanoseconds
761 0 : uint64_t intervalv = (uint64_t) floor(interval()(mainTabRow)*1E9);
762 0 : vector< unsigned int > flags;
763 0 : vector< int64_t > actualTimes;
764 0 : vector< int64_t > actualDurations;
765 0 : vector< float > zeroLags; // LAG_DATA, optional column, not used for the moment
766 0 : vector< float > crossData;
767 : // vector< short > crossData;
768 : // vector< int > crossData; // standard case for ALMA
769 0 : vector< float > autoData;
770 :
771 : ////////////////////////////////////////////////////////
772 : // fill data, time, and flag vectors for this timestamp
773 0 : 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 0 : vector< uInt > rowsSorted;
781 : {
782 0 : vector< uInt > rows;
783 0 : while(mainTabRow < nMainTabRows
784 0 : && time()(mainTabRow)==theTStamp){
785 0 : DDId = dataDescId()(mainTabRow);
786 0 : if(DDId != theDDId){ // skip all other Data Description Ids
787 0 : mainTabRow++;
788 0 : continue;
789 : }
790 0 : FId = fieldId()(mainTabRow);
791 0 : if(FId != theFieldId){ // skip all other Field Ids
792 0 : mainTabRow++;
793 0 : continue;
794 : }
795 0 : rows.push_back(mainTabRow);
796 0 : mainTabRow++;
797 : }
798 :
799 0 : uInt nRows = rows.size();
800 0 : vector<Int> bLine(nRows);
801 0 : uInt maxAnt = 0;
802 0 : for(uInt i=0; i<nRows; i++){
803 0 : uInt a2 = antenna2()(rows[i]);
804 0 : bLine[i] = antenna1()(rows[i])*1000 + a2;
805 0 : if(maxAnt<a2){
806 0 : maxAnt=a2;
807 : }
808 : }
809 :
810 0 : rowsSorted.resize(nRows);
811 0 : uInt expNRows = maxAnt*(maxAnt+1)/2; // (zero-based counting)
812 0 : uInt expNRowsWAuto = maxAnt*(maxAnt+1)/2 + maxAnt+1; // (zero-based counting)
813 0 : Bool haveAuto = false;
814 0 : if(nRows==expNRowsWAuto){
815 0 : haveAuto=true;
816 : }
817 0 : 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 0 : uInt count=0;
823 0 : for(uInt i= (haveAuto ? 0 : 1) ; i<maxAnt+1; i++){
824 0 : for(uInt j=0; j< (haveAuto ? i+1 : i); j++){
825 0 : Int myBLine = j*1000 + i;
826 0 : for(uInt ii=0; ii<nRows; ii++){
827 0 : if(bLine[ii]==myBLine){
828 0 : rowsSorted[count] = rows[ii];
829 0 : break;
830 : }
831 0 : 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 0 : count++;
838 : }
839 : }
840 :
841 0 : }
842 :
843 0 : for(uInt ii=0; ii<rowsSorted.size(); ii++){
844 :
845 0 : uInt iRow = rowsSorted[ii];
846 :
847 0 : DDId = dataDescId()(iRow);
848 0 : FId = fieldId()(iRow);
849 :
850 0 : Matrix<casacore::Complex> dat;
851 0 : Matrix<Bool> flagsm;
852 0 : String dataColumn(datacolumn);
853 0 : dataColumn.upcase();
854 0 : if(dataColumn == "MODEL"){
855 0 : dat.reference(modelData()(iRow));
856 : }
857 0 : else if(dataColumn == "CORRECTED"){
858 0 : dat.reference(correctedData()(iRow));
859 : }
860 : else{
861 0 : dat.reference(data()(iRow));
862 : }
863 0 : flagsm.reference(flag()(iRow));
864 :
865 : //cout << " ii row a1 a2 " << ii << " " << iRow << " " << antenna1()(iRow) << " " << antenna2()(iRow) << endl;
866 :
867 0 : Bool haveAuto = (antenna1()(iRow) == antenna2()(iRow));
868 :
869 0 : if(haveAuto){
870 0 : Complex x;
871 : float a;
872 0 : for(uInt i=0; i<numSpectralPoint; i++){
873 0 : for(uInt j=0; j<numStokesMS; j++){
874 0 : if(skipCorr_p[PolId][j]){
875 0 : continue;
876 : }
877 : else{
878 0 : x = dat(j,i);
879 0 : a = x.real();
880 0 : autoData.push_back( a );
881 : }
882 : }
883 : }
884 : }
885 : else{
886 0 : casacore::Complex x;
887 : float a,b;
888 : // int a,b;
889 0 : for(uInt i=0; i<numSpectralPoint; i++){
890 0 : for(uInt j=0; j<numStokesMS; j++){
891 0 : x = dat(j,i);
892 0 : a = x.real();
893 0 : b = x.imag();
894 0 : crossData.push_back( a );
895 0 : crossData.push_back( b );
896 : }
897 : }
898 : }
899 :
900 : unsigned int ul;
901 0 : for(uInt i=0; i<numSpectralPoint; i++){
902 0 : for(uInt j=0; j<numStokesMS; j++){
903 0 : if(haveAuto && skipCorr_p[PolId][j]){
904 0 : continue;
905 : }
906 : else{
907 0 : if(flagRow()(iRow)){
908 0 : ul = 1;
909 : }
910 : else{
911 0 : ul = flagsm(j,i);
912 : }
913 0 : 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 0 : }// 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 0 : uInt nToAdd1 = 0;
925 0 : uInt nToAdd2 = 0;
926 0 : uInt nToAdd3 = 0;
927 0 : uInt nToAdd4 = 0;
928 0 : uInt nToAdd5 = 0;
929 0 : uInt nToAdd6 = 0;
930 :
931 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : integrationNum++;
999 0 : datasize += flags.size() * sizeof(unsigned int)
1000 0 : + actualTimes.size() * sizeof( int64_t )
1001 0 : + actualDurations.size() * sizeof( int64_t )
1002 0 : + zeroLags.size() * sizeof( float )
1003 0 : + crossData.size() * sizeof( float )
1004 0 : + autoData.size() * sizeof( float );
1005 0 : 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 0 : } // end while
1016 :
1017 0 : sdmdow.done();
1018 :
1019 0 : ofs.close();
1020 :
1021 : // end write subscan
1022 :
1023 0 : incrementUid();
1024 :
1025 0 : }
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 0 : return numIntegrations;
1053 :
1054 0 : } // 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 0 : Bool MS2ASDM::writeStation(){ // create asdm station table and fill station id map
1085 0 : LogIO os(LogOrigin("MS2ASDM", "writeStation()"));
1086 :
1087 0 : Bool rstat = true;
1088 :
1089 0 : asdm::StationTable& tT = ASDM_p->getStation();
1090 :
1091 0 : asdm::StationRow* tR = 0;
1092 :
1093 : // MS has no station table; get information from the antenna table
1094 :
1095 0 : for(uInt irow=0; irow<antenna().nrow(); irow++){
1096 :
1097 : // parameters for the new station row
1098 0 : StationTypeMod::StationType type = StationTypeMod::ANTENNA_PAD;
1099 : // (alternatives are MAINTENANCE_PAD and WEATHER_STATION)
1100 :
1101 : // parameters of the new row
1102 0 : string name = antenna().station()(irow).c_str();
1103 :
1104 0 : vector<Length > position; // take the antenna position (!), (later set the ASDM antenna postion to 0,0,0)
1105 0 : Vector<Double > v; // aux. vector
1106 0 : v.reference(antenna().position()(irow));
1107 0 : for(uInt i=0; i<v.size(); i++){
1108 0 : position.push_back(Length(v[i]));
1109 : }
1110 :
1111 0 : Tag stationId;
1112 0 : String sId = antenna().station()(irow);
1113 0 : tR = tT.newRow(name, position, type);
1114 :
1115 0 : asdm::StationRow* tR2 = 0;
1116 :
1117 0 : tR2 = tT.add(tR);
1118 0 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1119 : // enter tag into the map
1120 0 : 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 0 : } // end for irow
1128 :
1129 0 : EntityId theUid(getCurrentUid());
1130 0 : Entity ent = tT.getEntity();
1131 0 : ent.setEntityId(theUid);
1132 0 : tT.setEntity(ent);
1133 0 : if(verbosity_p>0){
1134 0 : os << LogIO::NORMAL << "Filled Station table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1135 : }
1136 0 : incrementUid();
1137 :
1138 0 : return rstat;
1139 0 : }
1140 :
1141 0 : Bool MS2ASDM::writeAntenna(){ // create asdm antenna table and fill antenna id map
1142 0 : LogIO os(LogOrigin("MS2ASDM", "writeAntenna()"));
1143 :
1144 0 : Bool rstat = true;
1145 :
1146 0 : asdm::AntennaTable& tT = ASDM_p->getAntenna();
1147 :
1148 0 : asdm::AntennaRow* tR = 0;
1149 :
1150 0 : for(uInt irow=0; irow<antenna().nrow(); irow++){
1151 :
1152 : // parameters of the new row
1153 0 : string name = antenna().name()(irow).c_str();
1154 0 : AntennaMakeMod::AntennaMake antennaMake = AntennaMakeMod::UNDEFINED; // no info in MS (presently)
1155 0 : AntennaTypeMod::AntennaType antennaType = ASDMAntennaType( antenna().type()(irow) );
1156 0 : Length dishDiameter = Length( antenna().dishDiameter()(irow) );
1157 :
1158 0 : vector<Length > position;
1159 0 : for(uInt i=0; i<3; i++){
1160 0 : position.push_back(Length(0.)); // the antenna position in the ASDM is the sum of station pos and antenna pos.
1161 : }
1162 :
1163 0 : vector<Length > offset;
1164 0 : Vector<Double > v; // aux. vector
1165 0 : v.reference(antenna().offset()(irow));
1166 0 : for(uInt i=0; i<v.size(); i++){
1167 0 : offset.push_back(Length(v[i]));
1168 : }
1169 :
1170 0 : ArrayTime atime = ASDMArrayTime(time()(0)); // use start time of MS
1171 :
1172 0 : Tag stationId;
1173 0 : String sId = antenna().station()(irow); // the station name
1174 0 : if(asdmStationId_p.find(sId) != asdmStationId_p.end( )){
1175 0 : 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 0 : tR = tT.newRow(name, antennaMake, antennaType, dishDiameter, position, offset, atime, stationId);
1183 :
1184 0 : asdm::AntennaRow* tR2 = 0;
1185 :
1186 0 : tR2 = tT.add(tR);
1187 0 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1188 : // enter tag into the map
1189 0 : asdmAntennaId_p[irow] = tR->getAntennaId();
1190 : }
1191 : else{
1192 0 : os << LogIO::WARN << "Duplicate row in MS Antenna table :" << irow << LogIO::POST;
1193 : }
1194 0 : }
1195 :
1196 0 : EntityId theUid(getCurrentUid());
1197 0 : Entity ent = tT.getEntity();
1198 0 : ent.setEntityId(theUid);
1199 0 : tT.setEntity(ent);
1200 0 : if(verbosity_p>0){
1201 0 : os << LogIO::NORMAL << "Filled Antenna table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1202 : }
1203 0 : incrementUid();
1204 :
1205 0 : return rstat;
1206 0 : }
1207 :
1208 0 : Bool MS2ASDM::writeSpectralWindow(){
1209 0 : LogIO os(LogOrigin("MS2ASDM", "writeSpectralWindow()"));
1210 :
1211 0 : Bool rstat = true;
1212 :
1213 0 : asdm::SpectralWindowTable& tT = ASDM_p->getSpectralWindow();
1214 :
1215 0 : asdm::SpectralWindowRow* tR = 0;
1216 :
1217 0 : for(uInt irow=0; irow<spectralWindow().nrow(); irow++){
1218 :
1219 : // parameters of the new row
1220 0 : BasebandNameMod::BasebandName basebandName = BasebandNameMod::NOBB;
1221 0 : if(!spectralWindow().bbcNo().isNull()){ // BBC_NO is an optional MS column
1222 0 : basebandName = ASDMBBName( spectralWindow().bbcNo()(irow) );
1223 : }
1224 0 : NetSidebandMod::NetSideband netSideband = ASDMNetSideBand( spectralWindow().netSideband()(irow) );
1225 0 : int numChan = spectralWindow().numChan()(irow);
1226 :
1227 0 : Frequency refFreq = Frequency( spectralWindow().refFrequencyQuant()(irow).getValue(unitASDMFreq()) );
1228 0 : SidebandProcessingModeMod::SidebandProcessingMode sidebandProcessingMode = SidebandProcessingModeMod::NONE;
1229 0 : Frequency totBandwidth = Frequency( spectralWindow().totalBandwidthQuant()(irow).getValue(unitASDMFreq()) );
1230 0 : WindowFunctionMod::WindowFunction windowFunction = WindowFunctionMod::UNIFORM;
1231 :
1232 0 : tR = tT.newRow(basebandName, netSideband, numChan, refFreq, sidebandProcessingMode, totBandwidth, windowFunction);
1233 :
1234 0 : Vector< Quantum<Double> > v;
1235 0 : vector< Frequency > chanFreqArray;
1236 0 : v.reference( spectralWindow().chanFreqQuant()(irow) );
1237 0 : for(uInt i=0; i<v.nelements(); i++){
1238 0 : chanFreqArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
1239 : }
1240 0 : tR->setChanFreqArray(chanFreqArray);
1241 :
1242 0 : vector< Frequency > chanWidthArray;
1243 0 : v.reference( spectralWindow().chanWidthQuant()(irow) );
1244 0 : for(uInt i=0; i<v.nelements(); i++){
1245 0 : chanWidthArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
1246 : }
1247 0 : tR->setChanWidthArray(chanWidthArray);
1248 :
1249 0 : vector< Frequency > effectiveBwArray;
1250 0 : v.reference( spectralWindow().effectiveBWQuant()(irow) );
1251 0 : for(uInt i=0; i<v.nelements(); i++){
1252 0 : effectiveBwArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
1253 : }
1254 0 : tR->setEffectiveBwArray(effectiveBwArray);
1255 :
1256 0 : vector< Frequency > resolutionArray;
1257 0 : v.reference( spectralWindow().resolutionQuant()(irow) );
1258 0 : for(uInt i=0; i<v.nelements(); i++){
1259 0 : resolutionArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
1260 : }
1261 0 : tR->setResolutionArray( resolutionArray );
1262 :
1263 0 : MFrequency::Types refFrame = MFrequency::castType(spectralWindow().measFreqRef()(irow));
1264 0 : FrequencyReferenceCodeMod::FrequencyReferenceCode measFreqRef = ASDMFreqRefCode( refFrame );
1265 0 : tR->setMeasFreqRef( measFreqRef );
1266 :
1267 0 : tR->setFreqGroup( spectralWindow().freqGroup()(irow) );
1268 :
1269 0 : tR->setFreqGroupName( string( spectralWindow().freqGroupName()(irow).c_str() ) );
1270 :
1271 0 : 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 0 : asdm::SpectralWindowRow* tR2 = 0;
1277 0 : tR2 = tT.add(tR);
1278 :
1279 0 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1280 : // enter tag into the map
1281 0 : 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 0 : } // end loop over MS SPW table
1287 :
1288 0 : EntityId theUid(getCurrentUid());
1289 0 : Entity ent = tT.getEntity();
1290 0 : ent.setEntityId(theUid);
1291 0 : tT.setEntity(ent);
1292 0 : if(verbosity_p>0){
1293 0 : os << LogIO::NORMAL << "Filled SpectralWindow table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1294 : }
1295 0 : incrementUid();
1296 :
1297 0 : return rstat;
1298 0 : }
1299 :
1300 0 : Bool MS2ASDM::writeSource(){ // create asdm source table and fill source id map
1301 0 : LogIO os(LogOrigin("MS2ASDM", "writeSource()"));
1302 :
1303 0 : Bool rstat = true;
1304 :
1305 0 : asdm::SourceTable& tT = ASDM_p->getSource();
1306 :
1307 0 : asdm::SourceRow* tR = 0;
1308 :
1309 0 : 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 0 : for(uInt irow=0; irow<source().nrow(); irow++){
1316 :
1317 0 : Int sId = source().sourceId()(irow);
1318 :
1319 : // parameters of the new row
1320 :
1321 0 : 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 0 : Int spwId = source().spectralWindowId()(irow);
1326 0 : Tag spectralWindowId;
1327 0 : 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 0 : spectralWindowId = asdmSpectralWindowId_p[spwId];
1332 : }
1333 0 : string code = source().code()(irow).c_str();
1334 0 : if(code=="" || code==" "){
1335 0 : code="-";
1336 : }
1337 0 : vector< Angle > direction;
1338 0 : MDirection theSourceDir = source().directionMeas()(irow);
1339 0 : direction.push_back( Angle( theSourceDir.getAngle( unitASDMAngle() ).getValue()(0) ) ); // RA
1340 0 : direction.push_back( Angle( theSourceDir.getAngle( unitASDMAngle() ).getValue()(1) ) ); // DEC
1341 :
1342 : MDirection::Types dirRef;
1343 0 : MDirection::getType(dirRef, theSourceDir.getRefString());
1344 : DirectionReferenceCodeMod::DirectionReferenceCode directionCode
1345 0 : = ASDMDirRefCode(dirRef);
1346 :
1347 0 : vector< AngularRate > properMotion;
1348 0 : if(!source().properMotionQuant().isNull()){
1349 0 : Vector< Quantity > pMV;
1350 0 : pMV.reference(source().properMotionQuant()(irow));
1351 : try{
1352 0 : properMotion.push_back( AngularRate( pMV[0].getValue(unitASDMAngularRate()) ) );
1353 0 : 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 0 : }
1360 : else{
1361 0 : properMotion.push_back( AngularRate( 0. ) );
1362 0 : properMotion.push_back( AngularRate( 0. ) );
1363 : }
1364 :
1365 0 : string sourceName = (source().name()(irow)).c_str();
1366 :
1367 0 : tR = tT.newRow(timeInterval, spectralWindowId, code, direction, properMotion, sourceName);
1368 :
1369 0 : tR->setDirectionCode(directionCode);
1370 :
1371 0 : asdm::SourceRow* tR2 = 0;
1372 : try{
1373 0 : 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 0 : 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 0 : if( asdmSourceId_p.find(sId) == asdmSourceId_p.end( ) ){
1386 0 : int souId = tR2->getSourceId();
1387 0 : asdmSourceId_p[sId] = souId;
1388 : }
1389 0 : } // end loop over source table
1390 : } // id if source table exists
1391 :
1392 0 : EntityId theUid(getCurrentUid());
1393 0 : Entity ent = tT.getEntity();
1394 0 : ent.setEntityId(theUid);
1395 0 : tT.setEntity(ent);
1396 0 : if(verbosity_p>0){
1397 0 : os << LogIO::NORMAL << "Filled Source table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1398 : }
1399 0 : incrementUid();
1400 :
1401 0 : return rstat;
1402 0 : }
1403 :
1404 :
1405 :
1406 0 : Bool MS2ASDM::writePolarization(){
1407 0 : LogIO os(LogOrigin("MS2ASDM", "writePolarization()"));
1408 :
1409 0 : Bool rstat = true;
1410 0 : asdm::PolarizationTable& tT = ASDM_p->getPolarization();
1411 :
1412 0 : asdm::PolarizationRow* tR = 0;
1413 :
1414 0 : skipCorr_p.resize(0);
1415 :
1416 0 : for(uInt irow=0; irow<polarization().nrow(); irow++){
1417 :
1418 0 : if(polarization().flagRow()(irow)){
1419 0 : continue;
1420 : }
1421 :
1422 0 : vector< Bool > skipCorr;
1423 :
1424 : // parameters of the new row
1425 :
1426 0 : vector< StokesParameterMod::StokesParameter > corrTypeV;
1427 0 : vector< vector< PolarizationTypeMod::PolarizationType > > corrProduct;
1428 :
1429 0 : Vector< Int > v; // aux. vector
1430 0 : v.reference( polarization().corrType()(irow) );
1431 0 : for(uInt i=0; i<v.nelements(); i++){
1432 0 : Bool skip = true;
1433 0 : Stokes::StokesTypes st = static_cast<Stokes::StokesTypes>(v[i]);
1434 0 : if(st == Stokes::LR){ // only add if RL is not also present
1435 0 : if(!stokesTypePresent(v, Stokes::RL)){
1436 0 : skip = false;
1437 : }
1438 : }
1439 0 : 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 0 : skip = false;
1446 : }
1447 0 : corrTypeV.push_back( ASDMStokesParameter( st ) );
1448 0 : skipCorr.push_back(skip);
1449 : }
1450 0 : int numCorr = corrTypeV.size();
1451 0 : skipCorr_p.push_back(skipCorr);
1452 :
1453 : // now read the just created corrTypeV and write the correlation products accordingly
1454 0 : for(uInt i=0; i<corrTypeV.size(); i++){
1455 0 : vector< PolarizationTypeMod::PolarizationType > w;
1456 0 : switch(corrTypeV[i]){
1457 0 : case StokesParameterMod::RR:
1458 0 : w.push_back(PolarizationTypeMod::R);
1459 0 : w.push_back(PolarizationTypeMod::R);
1460 0 : break;
1461 0 : case StokesParameterMod::RL:
1462 0 : w.push_back(PolarizationTypeMod::R);
1463 0 : w.push_back(PolarizationTypeMod::L);
1464 0 : break;
1465 0 : case StokesParameterMod::LR:
1466 0 : w.push_back(PolarizationTypeMod::L);
1467 0 : w.push_back(PolarizationTypeMod::R);
1468 0 : break;
1469 0 : case StokesParameterMod::LL:
1470 0 : w.push_back(PolarizationTypeMod::L);
1471 0 : w.push_back(PolarizationTypeMod::L);
1472 0 : break;
1473 0 : case StokesParameterMod::XX:
1474 0 : w.push_back(PolarizationTypeMod::X);
1475 0 : w.push_back(PolarizationTypeMod::X);
1476 0 : 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 0 : case StokesParameterMod::YY:
1486 0 : w.push_back(PolarizationTypeMod::Y);
1487 0 : w.push_back(PolarizationTypeMod::Y);
1488 0 : 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 0 : corrProduct.push_back(w);
1532 0 : } // end loop over corrTypeV
1533 :
1534 0 : 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 0 : asdm::PolarizationRow* tR2 = 0;
1543 0 : tR2 = tT.add(tR);
1544 :
1545 0 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1546 : // enter tag into the map
1547 0 : asdmPolarizationId_p[irow] = tR->getPolarizationId();
1548 : }
1549 : else{
1550 0 : os << LogIO::WARN << "Duplicate row in MS Polarization table :" << irow << LogIO::POST;
1551 : }
1552 0 : } // end loop over MS Pol table
1553 :
1554 0 : EntityId theUid(getCurrentUid());
1555 0 : Entity ent = tT.getEntity();
1556 0 : ent.setEntityId(theUid);
1557 0 : tT.setEntity(ent);
1558 0 : if(verbosity_p>0){
1559 0 : os << LogIO::NORMAL << "Filled Polarization table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1560 : }
1561 0 : incrementUid();
1562 :
1563 0 : return rstat;
1564 0 : }
1565 :
1566 0 : Bool MS2ASDM::writeCorrelatorMode(){
1567 0 : LogIO os(LogOrigin("MS2ASDM", "writeCorrelatorMode()"));
1568 :
1569 0 : Bool rstat = true;
1570 0 : asdm::CorrelatorModeTable& tT = ASDM_p->getCorrelatorMode();
1571 :
1572 0 : asdm::CorrelatorModeRow* tR = 0;
1573 :
1574 : // create only one row
1575 :
1576 0 : int numBaseband = 1;
1577 0 : vector<BasebandNameMod::BasebandName > basebandNames;
1578 0 : basebandNames.push_back(BasebandNameMod::NOBB);
1579 0 : vector<int > basebandConfig;
1580 0 : basebandConfig.push_back(0);
1581 0 : AccumModeMod::AccumMode accumMode = AccumModeMod::NORMAL;
1582 0 : int binMode = 1; // standard setting for interferometry
1583 0 : int numAxes = 4; // time, antenna, stokes, pol
1584 0 : vector<AxisNameMod::AxisName > axesOrderArray;
1585 0 : axesOrderArray.push_back(AxisNameMod::TIM);
1586 0 : axesOrderArray.push_back(AxisNameMod::ANT);
1587 0 : axesOrderArray.push_back(AxisNameMod::SPP);
1588 0 : axesOrderArray.push_back(AxisNameMod::POL);
1589 0 : vector<FilterModeMod::FilterMode > filterMode;
1590 0 : filterMode.push_back(FilterModeMod::UNDEFINED);
1591 :
1592 0 : CorrelatorNameMod::CorrelatorName correlatorName = CorrelatorNameMod::ALMA_BASELINE; // the default
1593 0 : if(telName_p == "ALMA" || telName_p == "OSF"){
1594 0 : correlatorName = CorrelatorNameMod::ALMA_BASELINE; //???
1595 : }
1596 0 : else if(telName_p == "ACA"){
1597 0 : correlatorName = CorrelatorNameMod::ALMA_ACA; //???
1598 : }
1599 0 : else if(telName_p == "VLA"){
1600 0 : correlatorName = CorrelatorNameMod::NRAO_VLA; //???
1601 : }
1602 0 : else if(telName_p == "EVLA"){
1603 0 : correlatorName = CorrelatorNameMod::NRAO_WIDAR; //???
1604 : }
1605 0 : else if(telName_p == "PDB"){
1606 0 : correlatorName = CorrelatorNameMod::IRAM_PDB; //???
1607 : }
1608 : else{
1609 0 : os << LogIO::WARN << "Unknown telescope name: " << telName_p << ". Assuming ALMA_BASELINE." << LogIO::POST;
1610 : }
1611 :
1612 0 : tR = tT.newRow(numBaseband, basebandNames, basebandConfig, accumMode, binMode, numAxes, axesOrderArray, filterMode, correlatorName);
1613 :
1614 0 : tT.add(tR);
1615 :
1616 0 : EntityId theUid(getCurrentUid());
1617 0 : Entity ent = tT.getEntity();
1618 0 : ent.setEntityId(theUid);
1619 0 : tT.setEntity(ent);
1620 0 : if(verbosity_p>0){
1621 0 : os << LogIO::NORMAL << "Filled CorrelatorMode table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1622 : }
1623 0 : incrementUid();
1624 :
1625 0 : return rstat;
1626 0 : }
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 0 : Bool MS2ASDM::writeProcessor(){
1677 0 : LogIO os(LogOrigin("MS2ASDM", "writeProcessor()"));
1678 :
1679 0 : Bool rstat = true;
1680 0 : asdm::ProcessorTable& tT = ASDM_p->getProcessor();
1681 :
1682 0 : asdm::ProcessorRow* tR = 0;
1683 :
1684 0 : uInt nPRows = processor().nrow();
1685 :
1686 0 : if(nPRows > 0){ // need to test because MS processor table is obligatory but may be empty
1687 0 : for(uInt irow=0; irow<nPRows; irow++){
1688 : // parameters of the new row
1689 0 : Tag modeId;
1690 : ProcessorTypeMod::ProcessorType processorType;
1691 : ProcessorSubTypeMod::ProcessorSubType processorSubType;
1692 0 : if(processor().type()(irow) == "CORRELATOR"){
1693 0 : processorType = ProcessorTypeMod::CORRELATOR;
1694 0 : if(processor().subType()(irow) == "ALMA_CORRELATOR_MODE"){
1695 0 : processorSubType = ProcessorSubTypeMod::ALMA_CORRELATOR_MODE;
1696 : }
1697 : else{
1698 0 : os << LogIO::WARN << "Unsupported processor subType for type CORRELATOR " << processor().subType()(irow)
1699 0 : << " assuming ALMA_CORRELATOR" << LogIO::POST;
1700 0 : 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 0 : vector< asdm::CorrelatorModeRow* > corrModeRows;
1735 0 : vector< asdm::HolographyRow* > holographyRows;
1736 0 : vector< asdm::AlmaRadiometerRow* > almaRadiometerRows;
1737 :
1738 0 : switch(processorSubType){
1739 0 : case ProcessorSubTypeMod::ALMA_CORRELATOR_MODE:
1740 0 : if(!writeCorrelatorMode()){ // create the optional CorrelatorMode table
1741 0 : return false;
1742 : }
1743 0 : corrModeRows = (ASDM_p->getCorrelatorMode()).get();
1744 0 : if(corrModeRows.size()==0){
1745 0 : os << LogIO::SEVERE << "Internal error: ASDM CorrelatorMode table is empty." << LogIO::POST;
1746 0 : return false;
1747 : }
1748 0 : modeId = corrModeRows[0]->getCorrelatorModeId(); // get tag from first row of CorrelatorMode table (there is only one) ???
1749 0 : 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 0 : tR = tT.newRow(modeId, processorType, processorSubType);
1779 : // add the row to the table
1780 0 : asdm::ProcessorRow* tR2 = 0;
1781 0 : tR2 = tT.add(tR);
1782 :
1783 0 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1784 : // enter tag into the map
1785 0 : asdmProcessorId_p[irow] = tR->getProcessorId();
1786 : }
1787 : else{
1788 0 : os << LogIO::WARN << "Duplicate row in MS Processor table :" << irow << LogIO::POST;
1789 : }
1790 0 : } // end loop over MS processor table
1791 : }
1792 : else{ // MS processor table is empty
1793 0 : os << LogIO::WARN << "MS Processor table is empty. Will try to proceed assuming a standard ALMA Correlator." << LogIO::POST;
1794 0 : ProcessorTypeMod::ProcessorType processorType = ProcessorTypeMod::CORRELATOR;
1795 0 : ProcessorSubTypeMod::ProcessorSubType processorSubType = ProcessorSubTypeMod::ALMA_CORRELATOR_MODE;
1796 0 : if(!writeCorrelatorMode()){ // create the optional CorrelatorMode table
1797 0 : return false;
1798 : }
1799 0 : vector< asdm::CorrelatorModeRow* > corrModeRows = ASDM_p->getCorrelatorMode().get();
1800 0 : if(corrModeRows.size()==0){
1801 0 : os << LogIO::SEVERE << "Internal error: ASDM CorrelatorMode table is empty." << LogIO::POST;
1802 0 : return false;
1803 : }
1804 0 : Tag modeId = corrModeRows[0]->getCorrelatorModeId(); // get tag from first row of CorrelatorMode table (there is only one) ???
1805 0 : tR = tT.newRow(modeId, processorType, processorSubType);
1806 0 : tT.add(tR);
1807 : // enter tag into the map connecting it to "-1"
1808 0 : asdmProcessorId_p[-1] = tR->getProcessorId();
1809 0 : } // end if
1810 :
1811 0 : EntityId theUid(getCurrentUid());
1812 0 : Entity ent = tT.getEntity();
1813 0 : ent.setEntityId(theUid);
1814 0 : tT.setEntity(ent);
1815 0 : if(verbosity_p>0){
1816 0 : os << LogIO::NORMAL << "Filled Processor table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1817 : }
1818 0 : incrementUid();
1819 :
1820 0 : return rstat;
1821 0 : }
1822 :
1823 :
1824 0 : Bool MS2ASDM::writeField(){
1825 0 : LogIO os(LogOrigin("MS2ASDM", "writeField()"));
1826 :
1827 0 : Bool rstat = true;
1828 0 : asdm::FieldTable& tT = ASDM_p->getField();
1829 :
1830 0 : asdm::FieldRow* tR = 0;
1831 :
1832 0 : for(uInt irow=0; irow<field().nrow(); irow++){
1833 :
1834 : // parameters of the new row
1835 0 : string fieldName = field().name()(irow).c_str();
1836 0 : string code = field().code()(irow).c_str();
1837 0 : if(code=="" || code==" "){
1838 0 : code="-";
1839 : }
1840 0 : int numPoly = field().numPoly()(irow) + 1; // MS give poly order, ASDM needs number of coefficients
1841 0 : 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 0 : Int numpol = 0;
1846 :
1847 0 : String msAngUnit = "rad"; // MS uses radians here
1848 0 : Matrix< Double > mdir; // aux. matrix
1849 :
1850 :
1851 : MDirection::Types phaseDirRef;
1852 0 : MDirection::getType(phaseDirRef, field().phaseDirMeasCol()(irow)(IPosition(1,0)).getRefString());
1853 : MDirection::Types delayDirRef;
1854 0 : MDirection::getType(delayDirRef, field().delayDirMeasCol()(irow)(IPosition(1,0)).getRefString());
1855 : MDirection::Types refDirRef;
1856 0 : MDirection::getType(refDirRef, field().referenceDirMeasCol()(irow)(IPosition(1,0)).getRefString());
1857 0 : 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 0 : = ASDMDirRefCode(phaseDirRef);
1866 :
1867 0 : vector< vector< Angle > > delayDirV;
1868 0 : mdir.reference(field().delayDir()(irow));
1869 : {
1870 0 : vector< Angle > dirV;
1871 0 : Quantity angle0(mdir(0,numpol), msAngUnit);
1872 0 : dirV.push_back(Angle(angle0.getValue(unitASDMAngle())));
1873 0 : Quantity angle1(mdir(1,numpol), msAngUnit);
1874 0 : dirV.push_back(Angle(angle1.getValue(unitASDMAngle())));
1875 0 : delayDirV.push_back(dirV);
1876 0 : }
1877 :
1878 0 : vector< vector< Angle > > phaseDirV;
1879 0 : mdir.reference(field().phaseDir()(irow));
1880 : {
1881 0 : vector< Angle > dirV;
1882 0 : Quantity angle0(mdir(0,numpol), msAngUnit);
1883 0 : dirV.push_back(Angle(angle0.getValue(unitASDMAngle())));
1884 0 : Quantity angle1(mdir(1,numpol), msAngUnit);
1885 0 : dirV.push_back(Angle(angle1.getValue(unitASDMAngle())));
1886 0 : phaseDirV.push_back(dirV);
1887 0 : }
1888 :
1889 0 : vector< vector< Angle > > referenceDirV;
1890 0 : mdir.reference(field().referenceDir()(irow));
1891 : {
1892 0 : vector< Angle > dirV;
1893 0 : Quantity angle0(mdir(0,numpol), msAngUnit);
1894 0 : dirV.push_back(Angle(angle0.getValue(unitASDMAngle())));
1895 0 : Quantity angle1(mdir(1,numpol), msAngUnit);
1896 0 : dirV.push_back(Angle(angle1.getValue(unitASDMAngle())));
1897 0 : referenceDirV.push_back(dirV);
1898 0 : }
1899 :
1900 : ////tR = tT.newRow(fieldName, code, numPoly, delayDirV, phaseDirV, referenceDirV);
1901 0 : tR = tT.newRow(fieldName, numPoly, delayDirV, phaseDirV, referenceDirV);
1902 :
1903 0 : tR->setCode(code);
1904 0 : tR->setDirectionCode(directionCode);
1905 0 : tR->setTime(ASDMArrayTime(field().timeQuant()(irow).getValue("s")));
1906 :
1907 0 : Int sId = field().sourceId()(irow);
1908 0 : if ( asdmSourceId_p.find(sId) != asdmSourceId_p.end( ) ) {
1909 0 : 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 0 : asdm::FieldRow* tR2 = 0;
1928 0 : tR2 = tT.add(tR);
1929 0 : if(tR2 == tR){ // adding this row caused a new tag to be defined
1930 : // enter tag into the map
1931 0 : 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 0 : } // end loop over MS field table
1952 :
1953 0 : EntityId theUid(getCurrentUid());
1954 0 : Entity ent = tT.getEntity();
1955 0 : ent.setEntityId(theUid);
1956 0 : tT.setEntity(ent);
1957 0 : if(verbosity_p>0){
1958 0 : os << LogIO::NORMAL << "Filled Field table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
1959 : }
1960 0 : incrementUid();
1961 :
1962 0 : return rstat;
1963 0 : }
1964 :
1965 :
1966 0 : Bool MS2ASDM::writeReceiver(){
1967 0 : LogIO os(LogOrigin("MS2ASDM", "writeReceiver()"));
1968 :
1969 0 : Bool rstat = true;
1970 0 : asdm::ReceiverTable& tT = ASDM_p->getReceiver();
1971 :
1972 0 : 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 0 : vector< asdm::SpectralWindowRow* > SPWRows = (ASDM_p->getSpectralWindow()).get();
1978 :
1979 0 : Bool informed = false;
1980 :
1981 0 : for(uInt irow=0; irow<SPWRows.size(); irow++){
1982 :
1983 : // parameters for the new Recevier table row
1984 0 : Tag spectralWindowId = SPWRows[irow]->getSpectralWindowId();
1985 0 : if(!informed){
1986 0 : 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 0 : << LogIO::POST;
1989 : }
1990 0 : informed = true;
1991 : }
1992 0 : asdm::ArrayTimeInterval timeInterval( ASDMTimeInterval(feed().timeQuant()(0), feed().intervalQuant()(0)) );
1993 0 : string name = "unspec. frontend";
1994 : ReceiverBandMod::ReceiverBand frequencyBand;
1995 : ReceiverSidebandMod::ReceiverSideband receiverSideband;
1996 : double dummyF;
1997 0 : setRecBands(SPWRows[irow]->getRefFreq(), dummyF, frequencyBand, receiverSideband);
1998 0 : int numLO = 0; // no information in the MS ???
1999 0 : vector<Frequency > freqLO;
2000 : //freqLO.push_back(Frequency(1.)); // ???
2001 0 : vector<NetSidebandMod::NetSideband > sidebandLO;
2002 : //sidebandLO.push_back(SPWRows[irow]->getNetSideband()); // ???
2003 :
2004 0 : tR = tT.newRow(spectralWindowId, timeInterval, name, numLO, frequencyBand, freqLO, receiverSideband, sidebandLO);
2005 :
2006 : // add the row to the table
2007 0 : tT.add(tR);
2008 0 : } // end loop over SPW rows
2009 :
2010 0 : EntityId theUid(getCurrentUid());
2011 0 : Entity ent = tT.getEntity();
2012 0 : ent.setEntityId(theUid);
2013 0 : tT.setEntity(ent);
2014 0 : if(verbosity_p>0){
2015 0 : os << LogIO::NORMAL << "Filled Receiver table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
2016 : }
2017 0 : incrementUid();
2018 :
2019 0 : return rstat;
2020 0 : }
2021 :
2022 0 : Bool MS2ASDM::writeFeed(){
2023 0 : LogIO os(LogOrigin("MS2ASDM", "writeFeed()"));
2024 :
2025 0 : Bool rstat = true;
2026 0 : asdm::FeedTable& tT = ASDM_p->getFeed();
2027 :
2028 0 : asdm::FeedRow* tR = 0;
2029 :
2030 0 : Bool warned = false;
2031 0 : Bool warned2 = false;
2032 0 : Bool warned3 = false;
2033 :
2034 0 : for(uInt irow=0; irow<feed().nrow(); irow++){
2035 :
2036 : // parameters of the new feed row
2037 0 : Tag antennaId;
2038 0 : Int aid = feed().antennaId()(irow);
2039 0 : if( asdmAntennaId_p.find(aid) != asdmAntennaId_p.end( ) ){
2040 0 : 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 0 : ArrayTimeInterval timeInterval( ASDMTimeInterval(feed().timeQuant()(irow), feed().intervalQuant()(irow)) );
2047 :
2048 0 : int numReceptor = feed().numReceptors()(irow);
2049 :
2050 0 : vector< vector< double > > beamOffsetV;
2051 0 : vector< vector< Length > > focusReferenceV;
2052 0 : vector< PolarizationTypeMod::PolarizationType > polarizationTypesV;
2053 0 : vector< vector< asdm::Complex > > polResponseV;
2054 0 : vector< Angle > receptorAngleV;
2055 0 : vector< int > receiverIdV;
2056 :
2057 0 : Matrix< Double > mboffset; // aux. matrix
2058 0 : mboffset.reference(feed().beamOffset()(irow));
2059 :
2060 0 : Vector< String > polT; // aux. vector
2061 0 : polT.reference(feed().polarizationType()(irow));
2062 :
2063 0 : Matrix< Complex > polR;
2064 0 : polR.reference(feed().polResponse()(irow));
2065 :
2066 0 : Vector< Quantity > receptA;
2067 0 : receptA.reference(feed().receptorAngleQuant()(irow));
2068 :
2069 0 : for(uInt rnum=0; rnum<(uInt)numReceptor; rnum++){ // loop over all receptors
2070 0 : vector< double > abo;
2071 0 : abo.push_back(mboffset(0,rnum));
2072 0 : abo.push_back(mboffset(1,rnum));
2073 0 : beamOffsetV.push_back(abo);
2074 :
2075 0 : vector< Length > afr;
2076 0 : afr.push_back(0); // x
2077 0 : afr.push_back(0); // y
2078 0 : if(!feed().focusLength().isNull()){ // the FOCUS_LENGTH column is optional
2079 0 : afr.push_back(Length(feed().focusLength()(irow))); // z ???
2080 : }
2081 : else{
2082 0 : afr.push_back(0); // z
2083 : }
2084 0 : focusReferenceV.push_back(afr);
2085 :
2086 : try{
2087 0 : 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 0 : vector< asdm::Complex > apr;
2097 0 : for(uInt rnum2=0; rnum2<(uInt)numReceptor; rnum2++){
2098 0 : apr.push_back( ASDMComplex( polR(rnum,rnum2) ) );
2099 : }
2100 0 : polResponseV.push_back(apr);
2101 :
2102 0 : receptorAngleV.push_back( Angle( receptA[rnum].getValue( unitASDMAngle() ) ) );
2103 :
2104 0 : if(telName_p=="ALMA" || telName_p=="ACA" || telName_p == "OSF"){
2105 0 : receiverIdV.push_back(0); // always zero for ALMA
2106 : }
2107 : else{
2108 0 : receiverIdV.push_back(0);
2109 0 : if(!warned){
2110 0 : os << LogIO::WARN << "Setting receiver ID to zero (ALMA convention)." << LogIO::POST;
2111 0 : warned = true;
2112 : }
2113 : }
2114 0 : } // end loop over receptors
2115 :
2116 : // look at SPW Id parameter last!
2117 0 : Tag spectralWindowId;
2118 0 : vector< Tag > spwIdV; // the spw ids fow which to insert rows for this feed
2119 0 : Int spwid = feed().spectralWindowId()(irow);
2120 0 : 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 0 : for(Int ispw=0; ispw<(Int)spectralWindow().nrow(); ispw++){
2123 0 : if( asdmSpectralWindowId_p.find(ispw) != asdmSpectralWindowId_p.end( ) ){
2124 0 : spectralWindowId = asdmSpectralWindowId_p[ispw];
2125 0 : spwIdV.push_back(spectralWindowId);
2126 : }
2127 : }
2128 : }
2129 0 : else if( asdmSpectralWindowId_p.find(spwid) != asdmSpectralWindowId_p.end( ) ){
2130 0 : spectralWindowId = asdmSpectralWindowId_p[spwid];
2131 0 : 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 0 : tR = tT.newRow(antennaId, spwIdV[0], timeInterval, numReceptor, beamOffsetV, focusReferenceV,
2140 : polarizationTypesV, polResponseV, receptorAngleV, receiverIdV);
2141 :
2142 0 : if(telName_p=="ALMA" || telName_p=="ACA" || telName_p == "OSF"){
2143 0 : tR->setFeedNum(1); // always 1 for ALMA
2144 : }
2145 : else{
2146 0 : tR->setFeedNum(1);
2147 0 : if(!warned2){
2148 0 : os << LogIO::WARN << "Assuming single-feed receivers. Setting FeedNum to 1 (as for ALMA)." << LogIO::POST;
2149 0 : warned2 = true;
2150 : }
2151 : }
2152 :
2153 0 : vector< Length > positionV;
2154 0 : Vector< Quantity > pos;
2155 0 : pos.reference(feed().positionQuant()(irow));
2156 0 : for(uInt i=0; i<3; i++){
2157 0 : positionV.push_back( Length( pos[0].getValue( unitASDMLength() ) ) );
2158 : }
2159 0 : tR->setPosition(positionV);
2160 :
2161 0 : if(feed().beamId()(irow)!=-1 && !warned3){ // there should be a beam table in the MS, but presently it is not implemented!!!
2162 0 : os << LogIO::WARN << "MS Feed table contains reference to a Beam table row " << feed().beamId()(irow)
2163 0 : << " but a Beam table is not implemented in CASA. Ignoring." << LogIO::POST;
2164 : }
2165 :
2166 : // add the row to the table
2167 0 : tT.add(tR);
2168 :
2169 0 : int asdmFId = tR->getFeedId(); // the determination of the feed id is done internally by the add() method
2170 0 : Int fId = feed().feedId()(irow);
2171 0 : if( asdmFeedId_p.find(fId) != asdmFeedId_p.end( ) ){ // there is already a mapping
2172 0 : 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 0 : asdmFeedId_p[fId] = asdmFId;
2181 : }
2182 :
2183 : // add the same row for the remaining SPW Ids in the vector accumulated above
2184 0 : for(uint i=1; i<spwIdV.size(); i++){
2185 0 : tR = tT.newRow(antennaId, spwIdV[i], timeInterval, numReceptor, beamOffsetV, focusReferenceV,
2186 : polarizationTypesV, polResponseV, receptorAngleV, receiverIdV);
2187 0 : tT.add(tR);
2188 : }
2189 :
2190 0 : } // end loop over MS feed table
2191 :
2192 0 : EntityId theUid(getCurrentUid());
2193 0 : Entity ent = tT.getEntity();
2194 0 : ent.setEntityId(theUid);
2195 0 : tT.setEntity(ent);
2196 0 : if(verbosity_p>0){
2197 0 : os << LogIO::NORMAL << "Filled Feed table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
2198 : }
2199 0 : incrementUid();
2200 :
2201 0 : return rstat;
2202 0 : }
2203 :
2204 :
2205 0 : Bool MS2ASDM::writeDataDescription(){
2206 0 : LogIO os(LogOrigin("MS2ASDM", "writeDataDescription()"));
2207 :
2208 0 : Bool rstat = true;
2209 0 : asdm::DataDescriptionTable& tT = ASDM_p->getDataDescription();
2210 :
2211 0 : asdm::DataDescriptionRow* tR = 0;
2212 :
2213 : // loop over MS data description table
2214 0 : for(uInt irow=0; irow<dataDescription().nrow(); irow++){
2215 : // parameters for the new row
2216 0 : Tag polOrHoloId;
2217 0 : Tag spectralWindowId;
2218 0 : Int polId = dataDescription().polarizationId()(irow);
2219 0 : Int spwId = dataDescription().spectralWindowId()(irow);
2220 0 : if( asdmPolarizationId_p.find(polId) != asdmPolarizationId_p.end( ) ){
2221 0 : 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 0 : if( asdmSpectralWindowId_p.find(spwId) != asdmSpectralWindowId_p.end( ) ){
2229 0 : 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 0 : tR = tT.newRow(polOrHoloId, spectralWindowId);
2238 :
2239 0 : asdm::DataDescriptionRow* tR2 = 0;
2240 :
2241 0 : tR2 = tT.add(tR);
2242 0 : if(tR2 == tR){ // adding this row caused a new tag to be defined
2243 : // enter tag into the map
2244 0 : asdmDataDescriptionId_p[irow] = tR->getDataDescriptionId();
2245 : }
2246 : else{
2247 0 : os << LogIO::WARN << "Duplicate row in MS DataDesc table :" << irow << LogIO::POST;
2248 : }
2249 0 : } // end loop over MS DD table
2250 :
2251 0 : EntityId theUid(getCurrentUid());
2252 0 : Entity ent = tT.getEntity();
2253 0 : ent.setEntityId(theUid);
2254 0 : tT.setEntity(ent);
2255 0 : if(verbosity_p>0){
2256 0 : os << LogIO::NORMAL << "Filled DataDescription table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
2257 : }
2258 0 : incrementUid();
2259 :
2260 0 : return rstat;
2261 0 : }
2262 :
2263 0 : Bool MS2ASDM::writeSwitchCycle(){
2264 0 : LogIO os(LogOrigin("MS2ASDM", "writeSwitchCycle()"));
2265 :
2266 0 : Bool rstat = true;
2267 :
2268 0 : asdm::SwitchCycleTable& tT = ASDM_p->getSwitchCycle();
2269 :
2270 0 : 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 0 : if(phaseId().isNull()){ // phaseId column doesn't exist
2278 :
2279 : // parameters of the new row
2280 0 : int numStep = 1;
2281 0 : vector< float > weightArray;
2282 0 : weightArray.push_back(1.);
2283 0 : vector< vector< Angle > > dirOffsetArray;
2284 0 : vector< Angle > aV;
2285 0 : aV.push_back(Angle(0.));
2286 0 : aV.push_back(Angle(0.));
2287 0 : dirOffsetArray.push_back(aV);
2288 0 : vector< Frequency > freqOffsetArray;
2289 0 : freqOffsetArray.push_back(Frequency(0.));
2290 0 : vector< Interval > stepDurationArray;
2291 0 : stepDurationArray.push_back(Interval(0)); // set to zero ???
2292 :
2293 0 : tR = tT.newRow(numStep, weightArray, dirOffsetArray, freqOffsetArray, stepDurationArray);
2294 :
2295 0 : tT.add(tR);
2296 :
2297 0 : EntityId theUid(getCurrentUid());
2298 0 : Entity ent = tT.getEntity();
2299 0 : ent.setEntityId(theUid);
2300 0 : tT.setEntity(ent);
2301 0 : if(verbosity_p>0){
2302 : os << LogIO::NORMAL << "PHASE_ID column doesn't exist in MS Main table.\n Filled ASDM SwitchCycle table "
2303 0 : << getCurrentUid() << " with one dummy entry." << LogIO::POST;
2304 : }
2305 0 : incrementUid();
2306 0 : }
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 0 : return rstat;
2315 0 : }
2316 :
2317 0 : Bool MS2ASDM::writeState(){
2318 0 : LogIO os(LogOrigin("MS2ASDM", "writeState()"));
2319 :
2320 0 : Bool rstat = true;
2321 :
2322 0 : asdm::StateTable& tT = ASDM_p->getState();
2323 :
2324 0 : asdm::StateRow* tR = 0;
2325 :
2326 0 : 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 0 : << LogIO::POST;
2330 :
2331 : // parameters of the new row
2332 0 : bool bSig = true;
2333 0 : bool bRef = false;
2334 0 : bool bOnSky = true;
2335 0 : CalibrationDeviceMod::CalibrationDevice calDeviceName = CalibrationDeviceMod::NONE;
2336 :
2337 0 : tR = tT.newRow(calDeviceName, bSig, bRef, bOnSky);
2338 :
2339 0 : tR->setWeight(1.); // optional column
2340 :
2341 : // add the new row to the table
2342 0 : tT.add(tR);
2343 : // enter tag into the map
2344 0 : asdmStateId_p[-1] = tR->getStateId();
2345 : }
2346 : else{ // MS State table exists
2347 0 : for(uInt irow=0; irow<state().nrow(); irow++){
2348 : // parameters of the new row
2349 0 : bool bSig = state().sig()(irow);
2350 0 : bool bRef = state().ref()(irow);
2351 0 : Double loadT = state().load()(irow);
2352 0 : Double noiseT = state().cal()(irow);
2353 0 : bool bOnSky = bSig || bRef;
2354 : CalibrationDeviceMod::CalibrationDevice calDeviceName;
2355 0 : if(0.<loadT && loadT<270.){
2356 0 : calDeviceName = CalibrationDeviceMod::COLD_LOAD;
2357 : }
2358 0 : else if(270<=loadT && loadT<303.){
2359 0 : calDeviceName = CalibrationDeviceMod::AMBIENT_LOAD;
2360 : }
2361 0 : else if(303.<=loadT){
2362 0 : calDeviceName = CalibrationDeviceMod::HOT_LOAD;
2363 : }
2364 0 : else if(0.<noiseT){
2365 0 : calDeviceName = CalibrationDeviceMod::NOISE_TUBE_LOAD;
2366 : }
2367 : else{
2368 0 : calDeviceName = CalibrationDeviceMod::NONE;
2369 0 : if(!bSig){
2370 : os << LogIO::WARN << "Trouble determining Cal Device for row " << irow << " in MS State table."
2371 0 : << "Assuming NONE." << LogIO::POST;
2372 : }
2373 : }
2374 :
2375 0 : tR = tT.newRow(calDeviceName, bSig, bRef, bOnSky);
2376 :
2377 0 : tR->setWeight(1.); // optional column
2378 :
2379 : // add the new row to the table
2380 0 : asdm::StateRow* tR2 = 0;
2381 :
2382 0 : tR2 = tT.add(tR);
2383 : // enter tag into the map
2384 0 : asdmStateId_p[irow] = tR2->getStateId();
2385 0 : if(tR2 != tR){ // adding this row did not cause a new tag to be defined
2386 0 : 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 0 : EntityId theUid(getCurrentUid());
2392 0 : Entity ent = tT.getEntity();
2393 0 : ent.setEntityId(theUid);
2394 0 : tT.setEntity(ent);
2395 0 : if(verbosity_p>0){
2396 0 : os << LogIO::NORMAL << "Filled State table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
2397 : }
2398 0 : incrementUid();
2399 :
2400 0 : return rstat;
2401 0 : }
2402 :
2403 0 : Bool MS2ASDM::writeSysCal(){
2404 0 : LogIO os(LogOrigin("MS2ASDM", "writeSysCal()"));
2405 :
2406 0 : Bool rstat = true;
2407 :
2408 0 : asdm::SysCalTable& tT = ASDM_p->getSysCal();
2409 :
2410 0 : asdm::SysCalRow* tR = 0;
2411 :
2412 0 : uInt nSysCalRows = sysCal().nrow();
2413 :
2414 0 : 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 0 : << LogIO::POST;
2417 :
2418 : // loop over the main table
2419 0 : uInt nMainTabRows = ms_p.nrow();
2420 0 : for(uInt mainTabRow=0; mainTabRow<nMainTabRows; mainTabRow++){
2421 :
2422 : // get DDId and feed id
2423 0 : Int f1Id = feed1()(mainTabRow);
2424 0 : Int f2Id = feed2()(mainTabRow);
2425 0 : Int DDId = dataDescId()(mainTabRow);
2426 : // get start time stamp
2427 0 : Double startTime = timestampStartSecs(mainTabRow);
2428 : // create vectors of info for each antenna
2429 0 : vector< Int > aIdV;
2430 0 : vector< Int > SPWIdV;
2431 0 : vector< Int > feedIdV;
2432 0 : vector< int > nRecV;
2433 0 : vector< int > nChanV;
2434 0 : MapWithDefault<Int, Int> antennaDone(-1);
2435 :
2436 0 : uInt irow = mainTabRow;
2437 : // while ddid and feed id remain the same
2438 0 : while(irow<nMainTabRows &&
2439 0 : dataDescId()(irow) == DDId &&
2440 0 : feed1()(irow) == f1Id &&
2441 0 : feed2()(irow) == f2Id
2442 : ){
2443 0 : Int aId = antenna1()(irow);
2444 : // if info for given antenna not yet filled
2445 0 : if( antennaDone.find(aId) == antennaDone.end( ) ){
2446 : // get info for antenna and fill vectors
2447 0 : aIdV.push_back(aId);
2448 0 : Int spwId = dataDescription().spectralWindowId()(DDId);
2449 0 : SPWIdV.push_back(spwId);
2450 0 : feedIdV.push_back(f1Id);
2451 0 : nRecV.push_back(feed().numReceptors()(f1Id));
2452 0 : nChanV.push_back(spectralWindow().numChan()(spwId));
2453 0 : antennaDone[aId] = f1Id;
2454 : }
2455 0 : aId = antenna2()(irow);
2456 : // if info for given antenna not yet filled
2457 0 : if( antennaDone.find(aId) == antennaDone.end( ) ){
2458 : // get info for antenna and fill vectors
2459 0 : aIdV.push_back(aId);
2460 0 : Int spwId = dataDescription().spectralWindowId()(DDId);
2461 0 : SPWIdV.push_back(spwId);
2462 0 : feedIdV.push_back(f2Id);
2463 0 : nRecV.push_back(feed().numReceptors()(f2Id));
2464 0 : nChanV.push_back(spectralWindow().numChan()(spwId));
2465 0 : antennaDone[aId] = f2Id;
2466 : }
2467 0 : irow++;
2468 : } // end while
2469 : // get end timestamp
2470 0 : Double endTime = timestampEndSecs(irow-1);
2471 : // create ArrayTimeInterval
2472 0 : asdm::ArrayTimeInterval timeInterval( ASDMArrayTime(startTime),
2473 0 : ASDMInterval(endTime-startTime) );
2474 : // create new rows in syscal table based on the vectors
2475 0 : for(uInt i=0; i<aIdV.size(); i++){
2476 : // parameters of the new SysCal row
2477 0 : Tag antennaId = asdmAntennaId_p[aIdV[i]];
2478 0 : Tag spectralWindowId = asdmSpectralWindowId_p[SPWIdV[i]];
2479 0 : int feedId = asdmFeedId_p[feedIdV[i]];
2480 0 : int numReceptor = nRecV[i];
2481 0 : int numChan = nChanV[i];
2482 :
2483 0 : tR = tT.newRow(antennaId, spectralWindowId, timeInterval, feedId, numReceptor, numChan);
2484 :
2485 : // add the new row to the table
2486 0 : tT.add(tR);
2487 0 : }
2488 0 : mainTabRow = irow;
2489 0 : } // 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 0 : EntityId theUid(getCurrentUid());
2812 0 : Entity ent = tT.getEntity();
2813 0 : ent.setEntityId(theUid);
2814 0 : tT.setEntity(ent);
2815 0 : if(verbosity_p>0){
2816 0 : os << LogIO::NORMAL << "Filled SysCal table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
2817 : }
2818 0 : incrementUid();
2819 :
2820 0 : return rstat;
2821 0 : }
2822 :
2823 :
2824 0 : Bool MS2ASDM::writeConfigDescription(){
2825 :
2826 0 : LogIO os(LogOrigin("MS2ASDM", "writeConfigDesc()"));
2827 :
2828 0 : Bool rstat = true;
2829 :
2830 0 : asdm::ConfigDescriptionTable& tT = ASDM_p->getConfigDescription();
2831 :
2832 0 : asdm::ProcessorTable& procT = ASDM_p->getProcessor();
2833 :
2834 0 : asdm::SwitchCycleTable& swcT = ASDM_p->getSwitchCycle();
2835 0 : vector< asdm::SwitchCycleRow * > swcRV = swcT.get();
2836 0 : Tag swcTag = swcRV[0]->getSwitchCycleId(); // preliminary implementation: get tag from first (and only) row
2837 :
2838 0 : uInt nMainTabRows = ms_p.nrow();
2839 0 : uInt nProcTabRows = processor().nrow();
2840 0 : Int dummyProcId = -1;
2841 0 : if(nProcTabRows<1){ // processor table not filled, all data should have proc id == -1
2842 0 : os << LogIO::WARN << "MS Processor table is empty. Will assume processor type is CORRELATOR." << LogIO::POST;
2843 0 : nProcTabRows = 1;
2844 0 : 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 0 : << processorId()(0) << ". Will try to proceed ..." << LogIO::POST;
2847 0 : dummyProcId = processorId()(0); // accept other proc id (e.g. 0)
2848 : }
2849 : }
2850 :
2851 : // temprorarily needed until all processor types are supported
2852 0 : vector<Int> goodSpwV;
2853 0 : vector<Int> badSpwV;
2854 :
2855 : // loop over MS processor table (typically, this loop will only be executed once)
2856 0 : for(uInt uprocId=0; uprocId<nProcTabRows; uprocId++){
2857 :
2858 0 : Int procId = uprocId;
2859 :
2860 0 : if(processor().nrow()<1){
2861 0 : procId = dummyProcId;
2862 : }
2863 :
2864 0 : if(verbosity_p>0){
2865 0 : os << LogIO::NORMAL << "Processor Id: " << procId << LogIO::POST;
2866 : }
2867 :
2868 0 : asdm::ConfigDescriptionRow* tR = 0;
2869 :
2870 0 : Tag procIdTag;
2871 0 : if(asdmProcessorId_p.find(procId) != asdmProcessorId_p.end()){
2872 0 : procIdTag = asdmProcessorId_p[procId];
2873 : }
2874 : else{
2875 0 : if(procId == dummyProcId && asdmProcessorId_p.find(-1) != asdmProcessorId_p.end( )){ // there is no MS Proc table and the main table is
2876 0 : 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 0 : ProcessorTypeMod::ProcessorType processorType = procT.getRowByKey(procIdTag)->getProcessorType();
2886 :
2887 : // loop over data description table
2888 0 : 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 0 : SpectralResolutionTypeMod::SpectralResolutionType spectralType = SpectralResolutionTypeMod::FULL_RESOLUTION;
2892 :
2893 0 : uInt jrow=0;
2894 0 : while(jrow<nMainTabRows){
2895 0 : if(processorId()(jrow)==procId && dataDescId()(jrow)==iDDId){
2896 0 : break;
2897 : }
2898 0 : jrow++;
2899 : }
2900 0 : if(jrow>=nMainTabRows){ // DDId-processor pair not found
2901 0 : continue;
2902 : }
2903 :
2904 : // temprorary solution until other processro types are supported
2905 0 : if(processorType!=ProcessorTypeMod::CORRELATOR){
2906 0 : badSpwV.push_back(dataDescription().spectralWindowId()(iDDId));
2907 : }
2908 : else{
2909 0 : goodSpwV.push_back(dataDescription().spectralWindowId()(iDDId));
2910 : }
2911 : ///////////
2912 :
2913 0 : 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 0 : uInt spwId = dataDescription().spectralWindowId()(iDDId);
2920 0 : if(spectralWindow().numChan()(spwId)<5){
2921 : // spectralType = SpectralResolutionTypeMod::CHANNEL_AVERAGE;
2922 0 : 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 0 : Tag previousTag = Tag();
2932 0 : for(uInt mainTabRow=jrow; mainTabRow<nMainTabRows; mainTabRow++){
2933 :
2934 0 : if(dataDescId()(mainTabRow)!=iDDId || processorId()(mainTabRow)!=procId){
2935 0 : continue;
2936 : }
2937 :
2938 0 : if(verbosity_p>2){
2939 0 : cout << "proc id " << procId << " used at main table row " << mainTabRow << endl;
2940 : }
2941 :
2942 0 : vector<Int> msAntennaIdV;
2943 0 : vector<Int> msDDIdV;
2944 0 : msDDIdV.push_back(iDDId); // always just this one entry
2945 0 : vector<Int> msFeedIdV;
2946 0 : vector<Int> msFeedKeyV;
2947 :
2948 0 : vector<Tag> antennaId;
2949 0 : vector<Tag> dataDId;
2950 0 : vector<int> feedId;
2951 0 : vector<Tag> switchCycleId;
2952 0 : vector<AtmPhaseCorrectionMod::AtmPhaseCorrection> atmPhaseCorrection;
2953 0 : int numAntenna = 0;
2954 0 : int numDD = 0;
2955 0 : 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 0 : uInt numAutoCorrs = 0;
2962 0 : uInt numBaselines = 0;
2963 :
2964 0 : uInt irow = mainTabRow;
2965 0 : Double thisTStamp = time()(irow);
2966 :
2967 0 : while(irow<nMainTabRows && time()(irow)==thisTStamp){
2968 :
2969 0 : if(dataDescId()(irow)!=iDDId || processorId()(irow)!=procId){
2970 0 : irow++;
2971 0 : continue;
2972 : }
2973 :
2974 : // for the later determination of the correlation mode
2975 0 : if(antenna1()(irow) == antenna2()(irow)){
2976 0 : numAutoCorrs++;
2977 : }
2978 : else{
2979 0 : numBaselines++;
2980 : }
2981 :
2982 : // antenna ids
2983 :
2984 0 : Int aId = antenna1()(irow);
2985 0 : Bool found = false;
2986 0 : for(uInt j=0; j<msAntennaIdV.size(); j++){
2987 0 : if(aId == msAntennaIdV[j]){
2988 0 : found = true;
2989 0 : break;
2990 : }
2991 : }
2992 0 : if(!found){
2993 0 : msAntennaIdV.push_back(aId);
2994 0 : 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 0 : aId = antenna2()(irow);
3001 0 : found = false;
3002 0 : for(uInt j=0; j<msAntennaIdV.size(); j++){
3003 0 : if(aId == msAntennaIdV[j]){
3004 0 : found = true;
3005 0 : break;
3006 : }
3007 : }
3008 0 : if(!found){
3009 0 : msAntennaIdV.push_back(aId);
3010 0 : 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 0 : Int fIdi = feed1()(irow);
3020 0 : Int fKeyi = fIdi + 10000*antenna1()(irow);
3021 0 : found = false;
3022 0 : for(uInt j=0;j<msFeedKeyV.size();j++){
3023 0 : if(fKeyi == msFeedKeyV[j]){
3024 0 : found = true;
3025 0 : break;
3026 : }
3027 : }
3028 0 : if(!found){
3029 0 : msFeedKeyV.push_back(fKeyi);
3030 0 : msFeedIdV.push_back(fIdi);
3031 0 : 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 0 : fIdi = feed2()(irow);
3038 0 : fKeyi = fIdi + 10000*antenna2()(irow);
3039 0 : found = false;
3040 0 : for(uInt j=0;j<msFeedKeyV.size();j++){
3041 0 : if(fKeyi == msFeedKeyV[j]){
3042 0 : found = true;
3043 0 : break;
3044 : }
3045 : }
3046 0 : if(!found){
3047 0 : msFeedKeyV.push_back(fKeyi);
3048 0 : msFeedIdV.push_back(fIdi);
3049 0 : 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 0 : irow++;
3057 : } // end while
3058 :
3059 : // sort the antenna ids before entering them into the ConfigDescription table
3060 0 : std::sort(msAntennaIdV.begin(), msAntennaIdV.end());
3061 0 : for(uInt i=0; i<msAntennaIdV.size(); i++){
3062 0 : antennaId.push_back(asdmAntennaId_p[msAntennaIdV[i]]);
3063 : }
3064 0 : numAntenna = antennaId.size();
3065 :
3066 : // (there is just one DDId per config description in this scheme)
3067 0 : dataDId.push_back(asdmDataDescriptionId_p[msDDIdV[0]]);
3068 0 : numDD = 1;
3069 :
3070 : // sort the feed ids before entering them into the ConfigDescription table
3071 0 : std::sort(msFeedIdV.begin(), msFeedIdV.end());
3072 0 : for(uInt i=0; i<msFeedIdV.size(); i++){
3073 0 : feedId.push_back(asdmFeedId_p[msFeedIdV[i]]);
3074 : }
3075 0 : numFeed = feedId.size();
3076 0 : if(numAntenna>1){
3077 0 : numFeed = numFeed/numAntenna;
3078 : }
3079 :
3080 0 : if(numAutoCorrs==0){
3081 0 : correlationMode = CorrelationModeMod::CROSS_ONLY;
3082 : }
3083 0 : else if(numBaselines>0){
3084 0 : correlationMode = CorrelationModeMod::CROSS_AND_AUTO;
3085 : }
3086 : else{
3087 0 : correlationMode = CorrelationModeMod::AUTO_ONLY;
3088 : }
3089 :
3090 0 : 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 0 : if(dataIsAPCorrected()){
3096 0 : atmPhaseCorrection.push_back(AtmPhaseCorrectionMod::AP_CORRECTED);
3097 : }
3098 : else{
3099 0 : atmPhaseCorrection.push_back(AtmPhaseCorrectionMod::AP_UNCORRECTED);
3100 : }
3101 :
3102 : // create a new row with its mandatory attributes.
3103 0 : tR = tT.newRow (numAntenna,
3104 : numDD,
3105 : numFeed,
3106 : correlationMode,
3107 0 : 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 0 : asdm::ConfigDescriptionRow* tR2 = 0;
3134 :
3135 0 : tR2 = tT.add(tR);
3136 0 : Tag newTag = tR2->getConfigDescriptionId();
3137 0 : asdmConfigDescriptionId_p[mainTabRow] = newTag;
3138 0 : if(verbosity_p>1){
3139 0 : cout << "Defined conf desc id for main table row " << mainTabRow << endl;
3140 : }
3141 :
3142 0 : mainTabRow = irow-1;
3143 :
3144 0 : } // end loop over remainder of timestamp in MS main table
3145 :
3146 0 : } // end loop over MS DD table
3147 :
3148 0 : } // end loop over MS processor table
3149 :
3150 : // temporarily needed until all processor types are supported
3151 0 : 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 0 : EntityId theUid(getCurrentUid());
3163 0 : Entity ent = tT.getEntity();
3164 0 : ent.setEntityId(theUid);
3165 0 : tT.setEntity(ent);
3166 0 : if(verbosity_p>0){
3167 0 : os << LogIO::NORMAL << "Filled ConfigDescription table " << getCurrentUid() << " with " << tT.size() << " rows ... " << LogIO::POST;
3168 : }
3169 0 : incrementUid();
3170 :
3171 0 : return rstat;
3172 :
3173 0 : }
3174 :
3175 0 : Bool MS2ASDM::writeSBSummaryAndExecBlockStubs(){
3176 0 : LogIO os(LogOrigin("MS2ASDM", "writeSBSummaryAndExecBlockStubs()"));
3177 :
3178 0 : Bool rstat = true;
3179 :
3180 0 : asdm::SBSummaryTable& tT = ASDM_p->getSBSummary();
3181 :
3182 0 : asdm::SBSummaryRow* tR = 0;
3183 :
3184 0 : asdm::ExecBlockTable& tET = ASDM_p->getExecBlock();
3185 :
3186 0 : asdm::ExecBlockRow* tER = 0;
3187 :
3188 0 : MapWithDefault <asdm::Tag, Double> execBlockStartTime(-1.); // map from SBSummaryID to current execblock start time
3189 0 : MapWithDefault <asdm::Tag, Double> execBlockEndTime(-1.); // map from SBSummaryID to current execblock end time
3190 0 : MapWithDefault <asdm::Tag, asdm::ConfigDescriptionRow*> correspConfigDescRow(0); // map from SBSummaryID to the
3191 : // ConfigDescription row of current exec block
3192 0 : MapWithDefault <asdm::Tag, Int> execBlockNumber(0); // map from SBSummaryID to current execblock number
3193 0 : MapWithDefault <asdm::Tag, Int> obsIdFromSBSum(-1); // map from SBSummaryID to current obs ID
3194 0 : MapWithDefault <asdm::Tag, Double> minBaseline(0.); // map from SBSummaryID to minimum baseline of current exec block
3195 0 : MapWithDefault <asdm::Tag, Double> maxBaseline(0.); // map from SBSummaryID to maximum baseline of current exec block
3196 :
3197 0 : 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 0 : MPosition pos;
3204 : {
3205 0 : MPosition Xpos;
3206 0 : String Xobservatory;
3207 0 : if (observation().nrow() > 0) {
3208 0 : Xobservatory = observation().telescopeName()(observationId()(0));
3209 : }
3210 0 : if (Xobservatory.length() == 0 ||
3211 0 : !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 0 : << LogIO::POST;
3220 0 : Xpos=MPosition::Convert(Xpos, MPosition::WGS84)();
3221 : }
3222 0 : pos = Xpos;
3223 0 : ostringstream oss;
3224 0 : oss << " " << pos << " (WGS84)";
3225 0 : os << LogIO::NORMAL << oss.str() << LogIO::POST;
3226 0 : }
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 0 : Bool warned = false; // aux. var. to avoid warning repetition
3236 0 : uInt nMainTabRows = ms_p.nrow();
3237 :
3238 0 : Int prevSBKey = -1;
3239 0 : double prevReprFreq = (163.+211.)/2.*1E9;
3240 0 : ReceiverBandMod::ReceiverBand prevFrequencyBand = ReceiverBandMod::ALMA_RB_05;
3241 0 : ReceiverSidebandMod::ReceiverSideband prevRSB = ReceiverSidebandMod::TSB;
3242 0 : Int nProcTabRows = processor().nrow();
3243 :
3244 0 : 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 0 : Int obsId = observationId()(mainTabRow);
3250 :
3251 : // parameters of the new SBSummary row
3252 0 : Int ddId = dataDescId()(mainTabRow);
3253 0 : Int spwId = dataDescription().spectralWindowId()(ddId);
3254 0 : Int procId = processorId()(mainTabRow);
3255 :
3256 0 : Bool isWVR = false;
3257 0 : if(procId>=0 && nProcTabRows>0 && procId < nProcTabRows){
3258 0 : if(processor().type()(procId) == "RADIOMETER"){
3259 : //cout << "Found WVR data" << endl;
3260 0 : isWVR = true;
3261 : }
3262 : }
3263 :
3264 0 : 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 0 : double reprFreq = 0.;
3270 0 : Int bandNum = setRecBands(Frequency(frequency), reprFreq, frequencyBand, rSB);
3271 : //cout << "Band " << bandNum << endl;
3272 :
3273 0 : Int sbKey = obsId;
3274 :
3275 0 : if(bandNum >= 0){
3276 0 : 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 0 : 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 0 : prevSBKey = sbKey;
3324 0 : prevReprFreq = reprFreq;
3325 0 : prevFrequencyBand = frequencyBand;
3326 0 : prevRSB = rSB;
3327 :
3328 : //cout << " SBKey " << sbKey << endl;
3329 : //cout << " reprFreq " << reprFreq << endl;
3330 :
3331 0 : String sbsUid("uid://SAFFEC0C0/X1/X1");
3332 0 : ostringstream oss;
3333 0 : oss << sbKey;
3334 0 : sbsUid = sbsUid + String(oss);
3335 0 : EntityRef sbSummaryUID(sbsUid.c_str(), "", "ASDM", asdmVersion_p); // will be reset later when linking the ASDM to an APDM
3336 0 : EntityRef projectUID("uid://SAFFEC0C0/X1/X2", "", "ASDM", asdmVersion_p); // dto.
3337 0 : EntityRef obsUnitSetId("uid://SAFFEC0C0/X1/X3", "", "ASDM", asdmVersion_p); // dto.
3338 :
3339 0 : SBTypeMod::SBType sbType = SBTypeMod::OBSERVATORY; //???
3340 0 : Vector< Quantum< Double > > tRange;
3341 0 : tRange.reference(observation().timeRangeQuant()(obsId));
3342 0 : Double durationSecs = tRange[1].getValue("s") - tRange[0].getValue("s");
3343 0 : if(durationSecs == 0){ // try to derive the sched block duration in a different way
3344 0 : 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 0 : <<LogIO::POST;
3348 0 : warned = true;
3349 : }
3350 0 : durationSecs = timestampEndSecs(nMainTabRows-1) - timestampStartSecs(0);
3351 : }
3352 0 : Interval sbDuration = ASDMInterval(durationSecs);
3353 0 : int numberRepeats = 1;
3354 : // limit the scheduling block duration (not the same as the observation duration)
3355 0 : if(durationSecs > schedBlockDuration_p){
3356 0 : sbDuration = ASDMInterval(schedBlockDuration_p);
3357 0 : numberRepeats = (int) ceil(durationSecs/schedBlockDuration_p);
3358 0 : durationSecs = schedBlockDuration_p;
3359 : }
3360 0 : vector< Angle > centerDirection;
3361 0 : Int fId = fieldId()(mainTabRow);
3362 : // an observation (and an SB) can have many fields. use the first one as representative direction
3363 0 : if(firstFieldIdFromObsId.find(obsId) != firstFieldIdFromObsId.end( )){
3364 0 : fId = firstFieldIdFromObsId[obsId];
3365 : }
3366 : else{
3367 0 : 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 0 : int numObservingMode = 1;
3374 0 : vector< string > observingMode;
3375 0 : observingMode.push_back("observing mode t.b.d.");
3376 0 : int numScienceGoal = 1;
3377 0 : vector< string > scienceGoal;
3378 0 : scienceGoal.push_back("science goal t.b.d.");
3379 0 : int numWeatherConstraint = 1;
3380 0 : vector< string > weatherConstraint;
3381 0 : weatherConstraint.push_back("weather constraint t.b.d.");
3382 :
3383 0 : tR = tT.newRow(sbSummaryUID, projectUID, obsUnitSetId, reprFreq, frequencyBand, sbType, sbDuration,
3384 : ////centerDirection,
3385 : numObservingMode, observingMode, numberRepeats, numScienceGoal,
3386 : scienceGoal, numWeatherConstraint, weatherConstraint);
3387 :
3388 0 : asdm::SBSummaryRow* tR2 = 0;
3389 0 : tR2 = tT.add(tR);
3390 0 : Tag sBSummaryTag = tR2->getSBSummaryId();
3391 0 : if(tR2 == tR){ // adding the row led to the creation of a new tag
3392 0 : if(verbosity_p>2){
3393 0 : cout << "New SBSummary tag created: " << tR2 << endl;
3394 : }
3395 0 : 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 0 : << "(MS Main table row " << mainTabRow << ")" << LogIO::POST;
3399 : }
3400 : else{
3401 0 : 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 0 : if(execBlockStartTime.find(sBSummaryTag) != execBlockStartTime.end( )){ // yes
3411 :
3412 : // continue accumulation of min and max baseline
3413 0 : Double baseLine = MVBaseline( (antenna().positionMeas()(antenna1()(mainTabRow))).getValue(),
3414 0 : (antenna().positionMeas()(antenna2()(mainTabRow))).getValue()
3415 0 : ).getLength().getValue(unitASDMLength());
3416 0 : if(baseLine>maxBaseline[sBSummaryTag]){
3417 0 : maxBaseline[sBSummaryTag] = baseLine;
3418 : }
3419 0 : else if(baseLine<minBaseline[sBSummaryTag]){
3420 0 : minBaseline[sBSummaryTag] = baseLine;
3421 : }
3422 :
3423 : // is the exec block complete?
3424 0 : Double endT = timestampEndSecs(mainTabRow);
3425 0 : if(endT > execBlockEndTime[sBSummaryTag]){ // integration intervals may be different for different DD Ids, take max endT
3426 0 : execBlockEndTime[sBSummaryTag] = endT;
3427 : }
3428 0 : if(verbosity_p>2){
3429 0 : cout << "interval = " << endT - execBlockStartTime[sBSummaryTag] << ", duration == " << durationSecs << endl;
3430 : }
3431 :
3432 0 : if(endT - execBlockStartTime[sBSummaryTag] >= durationSecs){ // yes, it is complete
3433 : // parameters for a new row
3434 :
3435 0 : ArrayTime startTime = ASDMArrayTime(execBlockStartTime[sBSummaryTag]);
3436 0 : ArrayTime endTime = ASDMArrayTime(endT);
3437 0 : int execBlockNum = execBlockNumber[sBSummaryTag];
3438 0 : EntityRef execBlockUID; // to be filled with the EntityRef of the containing ASDM
3439 : try{
3440 0 : 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 0 : incrementUid();
3449 0 : EntityRef projectId = projectUID;
3450 0 : string configName = "configName t.b.d."; // ???
3451 0 : string telescopeName = telName_p;
3452 0 : string observerName = observation().observer()(obsId).c_str();
3453 0 : if(observerName==""){
3454 0 : observerName = "unknown";
3455 : }
3456 : ////string observingLog = "log not filled";
3457 0 : vector<string > observingLog(1);
3458 0 : int numObservingLog = 1;
3459 0 : observingLog[0] = "log not filled";
3460 0 : Vector< String > sV;
3461 0 : 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 0 : EntityRef sessionReference = sbSummaryUID;
3472 : ////string schedulerMode = "CASA exportasdm"; //???
3473 0 : Length baseRangeMin = Length( minBaseline[sBSummaryTag] );
3474 0 : Length baseRangeMax = Length( maxBaseline[sBSummaryTag] );
3475 0 : Length baseRmsMinor = Length(0); // ???
3476 0 : Length baseRmsMajor = Length(0); // ???
3477 0 : Angle basePa = Angle(0); // ???
3478 0 : bool aborted = false;
3479 0 : asdm::ConfigDescriptionRow* cDR = correspConfigDescRow[sBSummaryTag];
3480 0 : int numAntenna = cDR->getNumAntenna();
3481 0 : vector< Tag > antennaId = cDR->getAntennaId();
3482 :
3483 0 : 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 0 : tER2 = tET.add(tER);
3494 0 : 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 0 : asdmExecBlockId_p[execBlockStartTime[sBSummaryTag]] = tER->getExecBlockId();
3499 :
3500 0 : 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 0 : auto startptr = execBlockStartTime.find(sBSummaryTag);
3507 0 : if ( startptr != execBlockStartTime.end( ) ) execBlockStartTime.erase(startptr);
3508 0 : auto endptr = execBlockEndTime.find(sBSummaryTag);
3509 0 : if ( endptr != execBlockEndTime.end( ) ) execBlockEndTime.erase(endptr);
3510 0 : auto corptr = correspConfigDescRow.find(sBSummaryTag);
3511 0 : if ( corptr != correspConfigDescRow.end( ) ) correspConfigDescRow.erase(corptr);
3512 0 : auto sumptr = obsIdFromSBSum.find(sBSummaryTag);
3513 0 : if ( sumptr != obsIdFromSBSum.end( ) ) obsIdFromSBSum.erase(sumptr);
3514 0 : auto minptr = minBaseline.find(sBSummaryTag);
3515 0 : if ( minptr != minBaseline.end( ) ) minBaseline.erase(minptr);
3516 0 : auto maxptr = maxBaseline.find(sBSummaryTag);
3517 0 : if ( maxptr != maxBaseline.end( ) ) maxBaseline.erase(maxptr);
3518 :
3519 0 : }
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 0 : for ( auto iter = execBlockStartTime.begin( ); iter != execBlockStartTime.end( ); ++iter ) {
3527 0 : 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 0 : << "\n Please split out the different spectral bands into individual MSs and process separately." << LogIO::POST;
3530 0 : return false;
3531 : }
3532 : }
3533 :
3534 0 : execBlockStartTime[sBSummaryTag] = timestampStartSecs(mainTabRow);
3535 0 : execBlockEndTime[sBSummaryTag] = timestampEndSecs(mainTabRow); // will be updated
3536 :
3537 0 : Int oldNum = 0;
3538 0 : auto numptr = execBlockNumber.find(sBSummaryTag);
3539 0 : if( numptr != execBlockNumber.end( ) ){
3540 : // increment exec block number
3541 0 : oldNum = numptr->second;
3542 0 : execBlockNumber.erase(numptr);
3543 : }
3544 0 : execBlockNumber[sBSummaryTag] = oldNum + 1; // sequential numbering starting at 1
3545 :
3546 0 : 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 0 : obsIdFromSBSum[sBSummaryTag] = obsId; // remember the obsId for this exec block
3551 :
3552 0 : 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 0 : asdm::ConfigDescriptionRow* cDR = (ASDM_p->getConfigDescription()).getRowByKey(asdmConfigDescriptionId_p[mainTabRow]);
3558 0 : 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 0 : correspConfigDescRow[sBSummaryTag] = cDR; // remember the config description row for this exec block
3564 :
3565 : // start accumulation of min and max baseline
3566 0 : Double bLine = MVBaseline( (antenna().positionMeas()(antenna1()(mainTabRow))).getValue(),
3567 0 : (antenna().positionMeas()(antenna2()(mainTabRow))).getValue()
3568 0 : ).getLength().getValue(unitASDMLength());
3569 0 : minBaseline[sBSummaryTag] = bLine;
3570 0 : maxBaseline[sBSummaryTag] = bLine;
3571 : }
3572 : // skip rest of this timestamp
3573 0 : Double tStamp = time()(mainTabRow);
3574 0 : while(mainTabRow<nMainTabRows
3575 0 : && time()(mainTabRow)==tStamp
3576 0 : && dataDescId()(mainTabRow)==ddId){
3577 0 : mainTabRow++;
3578 : }
3579 0 : mainTabRow--;// we are inside a for loop which will perform the last mainTabRow++
3580 0 : } // end loop over main table
3581 :
3582 : // are there pending exec blocks?
3583 0 : while(execBlockStartTime.size()>0){ // yes
3584 0 : Tag sBSummaryTag = execBlockStartTime.begin( )->first;
3585 0 : tR = tT.getRowByKey(sBSummaryTag);
3586 0 : Int obsId = obsIdFromSBSum[sBSummaryTag];
3587 : // parameters for a new row
3588 0 : ArrayTime startTime = ASDMArrayTime(execBlockStartTime[sBSummaryTag]);
3589 0 : ArrayTime endTime = ASDMArrayTime(execBlockEndTime[sBSummaryTag]);
3590 0 : int execBlockNum = execBlockNumber[sBSummaryTag];
3591 0 : EntityRef execBlockUID; // to be filled with the EntityRef of the containing ASDM
3592 : try{
3593 0 : 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 0 : incrementUid();
3602 0 : EntityRef projectId = tR->getProjectUID();
3603 0 : string configName = "configName t.b.d."; // ???
3604 0 : string telescopeName = telName_p;
3605 0 : string observerName = observation().observer()(obsId).c_str();
3606 0 : if(observerName==""){
3607 0 : observerName = "unknown";
3608 : }
3609 :
3610 : ////string observingLog = "log not filled";
3611 0 : vector<string > observingLog(1);
3612 0 : int numObservingLog = 1;
3613 0 : observingLog[0] = "log not filled";
3614 0 : Vector< String > sV;
3615 0 : if(observation().log().isDefined(obsId)){// log string array not empty
3616 0 : sV.reference(observation().log()(obsId)); // the observation log is an array of strings
3617 0 : observingLog.resize(sV.size());
3618 0 : numObservingLog = observingLog.size();
3619 0 : for(uInt i=0; i<sV.size(); i++){
3620 0 : observingLog[i] = string(sV[i].c_str());
3621 : }
3622 : }
3623 :
3624 : //// string sessionReference = "sessionReference t.b.d."; // ???
3625 : ////EntityRef sbSummary = tR->getSbSummaryUID();
3626 0 : EntityRef sessionReference = tR->getSbSummaryUID();
3627 : ////string schedulerMode = "CASA exportasdm"; //???
3628 0 : Length baseRangeMin = Length( minBaseline[sBSummaryTag] );
3629 0 : Length baseRangeMax = Length( maxBaseline[sBSummaryTag] );
3630 0 : Length baseRmsMinor = Length(0); // ???
3631 0 : Length baseRmsMajor = Length(0); // ???
3632 0 : Angle basePa = Angle(0); // ???
3633 0 : bool aborted = false;
3634 0 : asdm::ConfigDescriptionRow* cDR = correspConfigDescRow[sBSummaryTag];
3635 0 : int numAntenna = cDR->getNumAntenna();
3636 0 : vector< Tag > antennaId = cDR->getAntennaId();
3637 :
3638 0 : 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 0 : tER2 = tET.add(tER);
3649 0 : 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 0 : asdmExecBlockId_p[execBlockStartTime[sBSummaryTag]] = tER->getExecBlockId();
3654 :
3655 0 : 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 0 : auto startptr = execBlockStartTime.find(sBSummaryTag); // need only remove from the map what is tested
3662 0 : if ( startptr != execBlockStartTime.end( ) ) execBlockStartTime.erase(startptr);
3663 0 : auto endptr = execBlockEndTime.find(sBSummaryTag);
3664 0 : if ( endptr != execBlockEndTime.end( ) ) execBlockEndTime.erase(endptr);
3665 :
3666 0 : }
3667 :
3668 : // finish the SBSummary table
3669 0 : EntityId theUid(getCurrentUid());
3670 0 : Entity ent = tT.getEntity();
3671 0 : ent.setEntityId(theUid);
3672 0 : tT.setEntity(ent);
3673 0 : if(verbosity_p>0){
3674 0 : os << LogIO::NORMAL << "Filled SBSummary table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
3675 : }
3676 0 : incrementUid();
3677 :
3678 : // finish the ExecBlock table
3679 0 : theUid = getCurrentUid();
3680 0 : ent = tET.getEntity();
3681 0 : ent.setEntityId(theUid);
3682 0 : tET.setEntity(ent);
3683 0 : if(verbosity_p>0){
3684 0 : os << LogIO::NORMAL << "Filled ExecBlock table " << getCurrentUid() << " with " << tET.size() << " rows ..." << LogIO::POST;
3685 : }
3686 0 : incrementUid();
3687 :
3688 0 : return rstat;
3689 :
3690 0 : }
3691 :
3692 0 : Bool MS2ASDM::writeMainAndScanAndSubScan(const String& datacolumn){
3693 0 : LogIO os(LogOrigin("MS2ASDM", "writeMainAndScanAndSubScan()"));
3694 :
3695 0 : Bool rstat = true;
3696 :
3697 : // check if datacolumn exists
3698 :
3699 0 : String dataColumn(datacolumn);
3700 0 : dataColumn.upcase();
3701 :
3702 0 : if( (dataColumn == "CORRECTED" && !ms_p.tableDesc().isColumn("CORRECTED_DATA"))
3703 0 : || (dataColumn == "MODEL" && !ms_p.tableDesc().isColumn("MODEL_DATA"))
3704 0 : || (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 0 : if(verbosity_p>0){
3712 0 : os << LogIO::NORMAL << "Using column " << dataColumn << "." << LogIO::POST;
3713 : }
3714 : }
3715 :
3716 0 : asdm::MainTable& tT = ASDM_p->getMain();
3717 0 : asdm::MainRow* tR = 0;
3718 :
3719 0 : asdm::ScanTable& tST = ASDM_p->getScan();
3720 0 : asdm::ScanRow* tSR = 0;
3721 :
3722 0 : asdm::SubscanTable& tSST = ASDM_p->getSubscan();
3723 0 : 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 0 : Tag execBlockId = Tag();
3762 0 : int subscanNumber = 0;
3763 : // parameters for the new Scan table row
3764 0 : int scanNumber = 0;
3765 0 : ArrayTime scanStartTime;
3766 0 : ArrayTime scanEndTime;
3767 0 : int scanNumIntent = 0;
3768 0 : int numSubScan = 0;
3769 0 : vector< ScanIntentMod::ScanIntent > scanIntent;
3770 0 : vector< CalDataOriginMod::CalDataOrigin > scanCalDataType;
3771 0 : vector< bool > scanCalibrationOnLine;
3772 : ////bool scanFlagRow = false; // always false ???
3773 :
3774 0 : uInt nMainTabRows = ms_p.nrow();
3775 0 : for(uInt mainTabRow=0; mainTabRow<nMainTabRows; mainTabRow++){
3776 :
3777 0 : Double rowTime = timestampStartSecs(mainTabRow);
3778 :
3779 : // asdmExecBlockId_p defined for this timestamp?
3780 0 : if(asdmExecBlockId_p.find(rowTime) != asdmExecBlockId_p.end( )){ // a new exec block has started
3781 : // is there a previous exec block?
3782 0 : if(execBlockId != Tag()){
3783 : // finish the old exec block
3784 : }
3785 : // set up new exec block
3786 : // parameters for the first scan
3787 0 : execBlockId = asdmExecBlockId_p[rowTime];
3788 0 : asdm::ExecBlockRow* EBR = (ASDM_p->getExecBlock()).getRowByKey(execBlockId);
3789 0 : scanNumber = 1; // ASDM scan numbering starts at 1
3790 0 : subscanNumber = 1; // dito for subscans
3791 0 : scanStart = rowTime;
3792 0 : scanStartTime = ASDMArrayTime( scanStart );
3793 0 : scanEndTime = EBR->getEndTime(); // preset to the end of the execblock
3794 0 : scanNumIntent = 0;
3795 0 : numSubScan = 0;
3796 0 : scanIntent.resize(0);
3797 0 : scanCalDataType.resize(0);
3798 0 : 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 0 : while( mainTabRow<nMainTabRows &&
3847 0 : MSTimeSecs(scanEndTime) - (rowTime = timestampStartSecs(mainTabRow)) > 1E-3 ){ // presently one scan per exec block ???
3848 :
3849 : // parameters for the new SubScan table row
3850 0 : Double subScanEnd = rowTime + subscanDuration_p;
3851 0 : if(subScanEnd > MSTimeSecs(scanEndTime)){
3852 0 : subScanEnd = MSTimeSecs(scanEndTime);
3853 : }
3854 :
3855 : // find all DDIds in the time between now and end of subscan
3856 0 : uInt irow = mainTabRow;
3857 0 : std::map< Int, uInt > subScanDDIdStartRows;
3858 0 : while(irow<nMainTabRows &&
3859 0 : timestampStartSecs(irow) < subScanEnd){
3860 0 : Int ddId = dataDescId()(irow);
3861 0 : if(subScanDDIdStartRows.find(ddId) == subScanDDIdStartRows.end( )){
3862 0 : subScanDDIdStartRows[ddId] = irow; // memorize their start rows
3863 : }
3864 0 : irow++;
3865 : }
3866 :
3867 : // for each DDId found
3868 0 : for( auto iter = subScanDDIdStartRows.begin( ); iter != subScanDDIdStartRows.end( ); ++iter ){
3869 0 : Int theDDId = iter->first;
3870 :
3871 : // find all FieldIds in the time between now and now+subscanduration or until Scan ends
3872 0 : uInt irow2 = mainTabRow;
3873 0 : std::map< Int, uInt > subScanStartRows;
3874 0 : std::map< Int, uInt > subScanEndRows;
3875 0 : while(irow2<nMainTabRows &&
3876 0 : timestampStartSecs(irow2) < subScanEnd){
3877 0 : Int ddId = dataDescId()(irow2);
3878 0 : Int fId = fieldId()(irow2);
3879 0 : if(ddId == theDDId){
3880 0 : if( subScanEndRows.find(fId) != subScanEndRows.end( ) ){
3881 0 : subScanEndRows[fId] = irow2; // update end row
3882 : }
3883 0 : if( subScanStartRows.find(fId) == subScanStartRows.end( ) ){
3884 0 : subScanStartRows[fId] = irow2; // memorize their start rows
3885 0 : subScanEndRows[fId] = irow2; // and end rows
3886 : }
3887 : }
3888 0 : irow2++;
3889 : }
3890 : // for each FieldId
3891 0 : for( auto iter = subScanStartRows.begin( ); iter != subScanStartRows.end( ); ++iter ) {
3892 0 : Int theFId = iter->first;
3893 0 : uInt startRow = subScanStartRows[theFId];
3894 0 : uInt endRow = subScanEndRows[theFId];
3895 : // write subscan
3896 : // parameters for the new SubScan table row
3897 0 : ArrayTime subScanStartArrayTime = ASDMArrayTime(timestampStartSecs(startRow));
3898 0 : ArrayTime subScanEndArrayTime = ASDMArrayTime(timestampEndSecs(endRow));
3899 0 : string fieldName = field().name()(fieldId()(startRow)).c_str();
3900 0 : SubscanIntentMod::SubscanIntent subscanIntent = SubscanIntentMod::ON_SOURCE;
3901 0 : vector< int > numberSubintegration;
3902 : ////bool flagRow = false;
3903 :
3904 : // parameters for the corresponding new Main table row
3905 0 : ArrayTime mainTime = ASDMArrayTime((timestampStartSecs(startRow) + timestampEndSecs(endRow))/2.); // midpoint!
3906 :
3907 0 : 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 0 : Tag configDescriptionId = asdmConfigDescriptionId_p[startRow];
3913 0 : asdm::ConfigDescriptionRow* CDR = (ASDM_p->getConfigDescription()).getRowByKey(configDescriptionId);
3914 0 : 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 0 : Tag fieldIdTag = asdmFieldId_p[theFId];
3921 0 : int numAntenna = CDR->getNumAntenna();
3922 0 : TimeSamplingMod::TimeSampling timeSampling = TimeSamplingMod::INTEGRATION;
3923 0 : 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 0 : EntityRef dataOid; // to be set by the following method call
3927 0 : 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 0 : numIntegration = writeMainBinSubScanForOneDDIdFIdPair(theDDId, theFId,
3934 : datacolumn,
3935 : scanNumber, subscanNumber,
3936 : startRow, endRow,
3937 : execBlockId,
3938 : dataSize, dataOid, stateIdV);
3939 0 : 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 0 : for(uInt i=0; i<(uInt)numIntegration; i++){
3946 0 : 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 0 : tR = tT.newRow(mainTime, configDescriptionId, fieldIdTag, numAntenna, timeSampling, interval, numIntegration,
3953 : scanNumber, subscanNumber, dataSize, dataOid, stateIdV, execBlockId);
3954 0 : tT.add(tR);
3955 :
3956 : // write corresponding Subscan table row
3957 :
3958 0 : tSSR = tSST.newRow(execBlockId, scanNumber, subscanNumber, subScanStartArrayTime, subScanEndArrayTime,
3959 : fieldName, subscanIntent, numIntegration, numberSubintegration //// , flagRow
3960 : );
3961 :
3962 0 : tSST.add(tSSR);
3963 :
3964 0 : subscanNumber++;
3965 0 : numSubScan++;
3966 :
3967 0 : } // end loop over Field indices
3968 :
3969 0 : } // end loop over DD indices
3970 : // update mainTabRow
3971 0 : mainTabRow = irow;
3972 0 : } // end while scan continues
3973 : // scan finished
3974 : // complete and write scan table row
3975 0 : mainTabRow--; // return to the last row of the scan
3976 0 : scanEndTime = ASDMArrayTime( timestampEndSecs(mainTabRow) );
3977 0 : scanNumIntent = 1; // hardwired (???)
3978 0 : for(uInt i=0; i<(uInt)scanNumIntent; i++){
3979 0 : scanIntent.push_back(ScanIntentMod::OBSERVE_TARGET); // hardwired for the moment (???)
3980 0 : scanCalDataType.push_back(CalDataOriginMod::FULL_RESOLUTION_CROSS); // hardwired for the moment (???)
3981 0 : scanCalibrationOnLine.push_back(false); // hardwired for the moment (???)
3982 : }
3983 :
3984 0 : tSR = tST.newRow(execBlockId, scanNumber, scanStartTime, scanEndTime, scanNumIntent, numSubScan, scanIntent,
3985 : scanCalDataType, scanCalibrationOnLine ////, scanFlagRow
3986 : );
3987 :
3988 0 : tST.add(tSR);
3989 :
3990 0 : scanNumber++;
3991 :
3992 : }// end for
3993 :
3994 0 : EntityId theUid(getCurrentUid());
3995 0 : Entity ent = tT.getEntity();
3996 0 : ent.setEntityId(theUid);
3997 0 : tT.setEntity(ent);
3998 0 : if(verbosity_p>0){
3999 0 : os << LogIO::NORMAL << "Filled Main table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
4000 : }
4001 0 : incrementUid();
4002 :
4003 0 : theUid = getCurrentUid();
4004 0 : ent = tST.getEntity();
4005 0 : ent.setEntityId(theUid);
4006 0 : tST.setEntity(ent);
4007 0 : if(verbosity_p>0){
4008 0 : os << LogIO::NORMAL << "Filled Scan table " << getCurrentUid() << " with " << tST.size() << " rows ..." << LogIO::POST;
4009 : }
4010 0 : incrementUid();
4011 :
4012 0 : theUid = getCurrentUid();
4013 0 : ent = tSST.getEntity();
4014 0 : ent.setEntityId(theUid);
4015 0 : tSST.setEntity(ent);
4016 0 : if(verbosity_p>0){
4017 0 : os << LogIO::NORMAL << "Filled SubScan table " << getCurrentUid() << " with " << tSST.size() << " rows ..." << LogIO::POST;
4018 : }
4019 0 : incrementUid();
4020 :
4021 0 : return rstat;
4022 0 : }
4023 :
4024 0 : Bool MS2ASDM::writePointingModel(){ // create asdm PointingModel table
4025 0 : LogIO os(LogOrigin("MS2ASDM", "writePointingModel()"));
4026 :
4027 0 : Bool rstat = true;
4028 :
4029 0 : asdm::PointingModelTable& tT = ASDM_p->getPointingModel();
4030 :
4031 0 : asdm::PointingModelRow* tR = 0;
4032 :
4033 0 : asdm::FeedTable& tFT = ASDM_p->getFeed();
4034 :
4035 0 : 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 0 : for(uInt feedRow=0; feedRow<feedRowV.size(); feedRow++){
4041 :
4042 :
4043 0 : uInt numRec = feedRowV[feedRow]->getNumReceptor();
4044 0 : vector< PolarizationTypeMod::PolarizationType > polTypeV = feedRowV[feedRow]->getPolarizationTypes();
4045 0 : vector< int > receivIdV = feedRowV[feedRow]->getReceiverId();
4046 :
4047 0 : for(uInt iRec=0; iRec<numRec; iRec++){ // loop over all receptors
4048 :
4049 0 : const vector< asdm::ReceiverRow * > recRowV = feedRowV[feedRow]->getReceivers(receivIdV[iRec]);
4050 :
4051 : // parameters for new PointingModel row
4052 :
4053 0 : Tag antennaId = feedRowV[feedRow]->getAntennaId();
4054 0 : int numCoeff = 2; // seems to be the dummy value ???, to be confirmed
4055 0 : vector< string > coeffName;
4056 0 : coeffName.push_back("IA");
4057 0 : coeffName.push_back("IE");
4058 0 : vector< float > coeffVal;
4059 0 : coeffVal.push_back(0.);
4060 0 : coeffVal.push_back(0.);
4061 : PolarizationTypeMod::PolarizationType polarizationType;
4062 : try{
4063 0 : 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 0 : ReceiverBandMod::ReceiverBand receiverBand = recRowV[0]->getFrequencyBand(); // take from the first receiver
4072 0 : string assocNature = "NOT_SET";
4073 0 : int assocPointingModelId = -1;
4074 :
4075 0 : tR = tT.newRow(antennaId, numCoeff, coeffName, coeffVal, polarizationType,
4076 : receiverBand, assocNature, assocPointingModelId);
4077 :
4078 0 : asdm::PointingModelRow* tR2 = 0;
4079 :
4080 0 : tR2 = tT.add(tR);
4081 0 : if(asdmPointingModelId_p.find(antennaId) == asdmPointingModelId_p.end( )){
4082 0 : asdmPointingModelId_p[antennaId] = tR2->getPointingModelId();
4083 : }
4084 :
4085 0 : } // end loop over receptors
4086 :
4087 0 : } // end loop over ASDM Feed table
4088 :
4089 0 : EntityId theUid(getCurrentUid());
4090 0 : Entity ent = tT.getEntity();
4091 0 : ent.setEntityId(theUid);
4092 0 : tT.setEntity(ent);
4093 0 : if(verbosity_p>0){
4094 0 : os << LogIO::NORMAL << "Filled PointingModel table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
4095 : }
4096 0 : incrementUid();
4097 :
4098 0 : return rstat;
4099 0 : }
4100 :
4101 0 : Bool MS2ASDM::writePointing(){ // create asdm pointing table
4102 0 : LogIO os(LogOrigin("MS2ASDM", "writePointing()"));
4103 :
4104 0 : Bool rstat = true;
4105 :
4106 0 : asdm::PointingTable& tT = ASDM_p->getPointing();
4107 :
4108 0 : asdm::PointingRow* tR = 0;
4109 :
4110 0 : uInt nPointingRows = pointing().nrow();
4111 :
4112 0 : if(nPointingRows==0){
4113 0 : os << LogIO::WARN << "MS Pointing table doesn't exist or is empty." << LogIO::POST;
4114 0 : return true; // not an error
4115 : }
4116 :
4117 0 : Bool warned = false; // aux. var. to avoid repetition of warnings
4118 :
4119 : // loop over MS antenna table
4120 0 : for(Int aId=0; aId<(Int)antenna().nrow(); aId++){
4121 :
4122 0 : 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 0 : uInt irow=0;
4129 0 : uInt totNumRows=0; // total of MS Pointing table rows for this antenna
4130 :
4131 0 : 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 0 : Int firstRow=-1;
4135 0 : while(irow<nPointingRows){
4136 0 : if(pointing().antennaId()(irow) == aId){
4137 0 : firstRow = irow;
4138 0 : break;
4139 : }
4140 0 : irow++;
4141 : }
4142 :
4143 0 : if(firstRow==-1){ // no further data for this antenna
4144 0 : break;
4145 : }
4146 :
4147 0 : uInt numRows=1; // number of rows with contiguous timestamps for this antenna
4148 :
4149 : // parameters for the next pointing table row
4150 0 : Tag antennaId = asdmAntennaId_p[aId];
4151 0 : ArrayTimeInterval timeInterval( ASDMTimeInterval( pointing().timeQuant()(firstRow), pointing().intervalQuant()(firstRow)) );
4152 :
4153 0 : bool pointingTracking = pointing().tracking()(firstRow);
4154 :
4155 0 : bool usePolynomials = false;
4156 0 : int numTerm = 0; // to be updated later
4157 :
4158 0 : if(pointing().numPoly()(firstRow)>0){
4159 0 : usePolynomials = true;
4160 0 : numTerm = pointing().numPoly()(irow)+1;
4161 : }
4162 :
4163 0 : ArrayTime timeOrigin = ASDMArrayTime( pointing().timeOriginQuant()(firstRow).getValue("s") );
4164 :
4165 0 : vector< vector< Angle > > pointingDirection;
4166 0 : Vector< MDirection > dirV; // aux. vector to access array column
4167 0 : dirV.reference(pointing().directionMeasCol()(firstRow));
4168 0 : if(numTerm == 0){
4169 0 : 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 0 : vector< vector< Angle > > encoder;
4183 0 : if(pointing().encoderMeas().isNull()){ // encoder column is optional in MS but not in ASDM
4184 0 : if(numTerm == 0){
4185 : // use pointing Direction instead
4186 0 : if(!warned){
4187 : os << LogIO::WARN << "No ENCODER column in MS Pointing table. Will use DIRECTION instead."
4188 0 : << LogIO::POST;
4189 0 : warned = true;
4190 : }
4191 0 : dirV.reference(pointing().directionMeasCol()(firstRow));
4192 0 : 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 0 : encoder.push_back(ASDMAngleV(pointing().encoderMeas()(firstRow)));
4208 : }
4209 :
4210 0 : vector< vector< Angle > > target;
4211 0 : dirV.reference(pointing().targetMeasCol()(firstRow));
4212 0 : if(numTerm == 0){
4213 0 : 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 0 : vector< vector< asdm::Angle > > offset;
4227 : // source offset column is optional in the MS but not in the ASDM
4228 0 : if(pointing().pointingOffsetMeasCol().isNull()){ // no MS source offset column
4229 0 : vector< Angle > angV;
4230 0 : angV.push_back(Angle(0.));
4231 0 : angV.push_back(Angle(0.));
4232 0 : offset.push_back(angV);
4233 0 : if(numTerm>0){
4234 0 : for(uInt i=1; i<(uInt)numTerm; i++){
4235 0 : offset.push_back(angV);
4236 : }
4237 : }
4238 0 : }
4239 : else{
4240 0 : dirV.reference(pointing().pointingOffsetMeasCol()(firstRow));
4241 0 : if(numTerm==0){
4242 0 : 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 0 : vector< vector< Angle > > sourceOffset; // optional in the ASDM and in the MS
4257 0 : 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 0 : int pointingModelId = asdmPointingModelId_p[antennaId];
4275 0 : double endTimeMJD = timeInterval.getStartInMJD() + timeInterval.getDurationInDays();
4276 :
4277 : // check if there are more rows for this antenna with adjacent time intervals
4278 0 : irow++;
4279 :
4280 0 : while(irow<nPointingRows && numTerm==0){ // while we find more adjacent rows and don't use polynomials
4281 :
4282 0 : if(pointing().antennaId()(irow) != aId){
4283 0 : irow++;
4284 0 : 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 0 : ArrayTimeInterval thisTimeInterval = ASDMTimeInterval(pointing().timeQuant()(irow), pointing().intervalQuant()(irow));
4291 0 : if( !casacore::near(endTimeMJD,thisTimeInterval.getStartInMJD()) // row irow is adjacent in time to previous row
4292 0 : || pointingTracking != pointing().tracking()(irow)
4293 0 : || (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 0 : numRows++;
4302 0 : endTimeMJD = thisTimeInterval.getStartInMJD() + thisTimeInterval.getDurationInDays();
4303 :
4304 : // update timeInterval - this may not be exactly the same as adding the durations
4305 0 : timeInterval.setDuration(endTimeMJD - timeInterval.getStartInMJD());
4306 :
4307 0 : dirV.reference(pointing().directionMeasCol()(irow));
4308 0 : pointingDirection.push_back(ASDMAngleV(dirV[0]));
4309 :
4310 0 : if(pointing().encoderMeas().isNull()){ // encoder column is optional
4311 : // use pointing Direction instead
4312 0 : encoder.push_back(ASDMAngleV(dirV[0]));
4313 : }
4314 : else{
4315 0 : encoder.push_back(ASDMAngleV(pointing().encoderMeas()(irow)));
4316 : }
4317 :
4318 0 : dirV.reference(pointing().targetMeasCol()(irow));
4319 0 : target.push_back(ASDMAngleV(dirV[0]));
4320 :
4321 0 : if(pointing().pointingOffsetMeasCol().isNull()){ // source offset column is optional
4322 0 : vector< Angle > angV;
4323 0 : angV.push_back(Angle(0.));
4324 0 : angV.push_back(Angle(0.));
4325 0 : offset.push_back(angV);
4326 0 : }
4327 : else{
4328 0 : dirV.reference(pointing().pointingOffsetMeasCol()(irow));
4329 0 : offset.push_back(ASDMAngleV(dirV[0]));
4330 : }
4331 :
4332 0 : 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 0 : irow++;
4337 :
4338 0 : } // end while accumulating for started entry
4339 :
4340 : // finish the ASDM table row and add it to the table
4341 0 : int numSample = encoder.size();
4342 0 : if(!usePolynomials){
4343 0 : numTerm = numSample;
4344 : }
4345 :
4346 0 : tR = tT.newRow(antennaId, timeInterval, numSample, encoder, pointingTracking, usePolynomials, timeOrigin,
4347 : numTerm, pointingDirection, target, offset, pointingModelId);
4348 :
4349 0 : if(sourceOffset.size()>0){
4350 0 : tR->setSourceOffset(sourceOffset);
4351 : }
4352 :
4353 0 : asdm::PointingRow* tR2 = 0;
4354 :
4355 : try{
4356 0 : 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 0 : 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 0 : 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 0 : totNumRows += numRows;
4374 :
4375 0 : } // end while rows left in pointing table
4376 :
4377 0 : 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 0 : EntityId theUid(getCurrentUid());
4385 0 : Entity ent = tT.getEntity();
4386 0 : ent.setEntityId(theUid);
4387 0 : tT.setEntity(ent);
4388 0 : if(verbosity_p>0){
4389 0 : os << LogIO::NORMAL << "Filled Pointing table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
4390 : }
4391 0 : incrementUid();
4392 :
4393 0 : return rstat;
4394 0 : }
4395 :
4396 0 : StokesParameterMod::StokesParameter MS2ASDM::ASDMStokesParameter( Stokes::StokesTypes s) {
4397 0 : 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 0 : case Stokes::RR: return StokesParameterMod::RR;
4403 0 : case Stokes::RL: return StokesParameterMod::RL;
4404 0 : case Stokes::LR: return StokesParameterMod::LR;
4405 0 : case Stokes::LL: return StokesParameterMod::LL;
4406 0 : case Stokes::XX: return StokesParameterMod::XX;
4407 0 : case Stokes::XY: return StokesParameterMod::XY;
4408 0 : case Stokes::YX: return StokesParameterMod::YX;
4409 0 : 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 0 : AntennaTypeMod::AntennaType MS2ASDM::ASDMAntennaType( const String& type ){
4437 0 : LogIO os(LogOrigin("MS2ASDM", "(ASDMAntennaType)"));
4438 0 : if(type == "GROUND-BASED"){
4439 0 : 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 0 : }
4449 :
4450 0 : ArrayTimeInterval MS2ASDM::ASDMTimeInterval( const Quantity midpoint, const Quantity interval){
4451 0 : Double sTime = midpoint.getValue("s");
4452 0 : Double sInterval = interval.getValue("s");
4453 :
4454 : // watch for sInterval==0 which means these correspond to a constant value over the whole MS
4455 0 : if (sInterval == 0.) {
4456 0 : sTime = timestampStartSecs(0);
4457 0 : 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 0 : if (sInterval > 31536000.0) {
4465 0 : sTime = timestampStartSecs(0);
4466 0 : sInterval = timestampEndSecs(ms_p.nrow()-1) - sTime;
4467 : } else {
4468 : // the usual case, turn sTime into the start time
4469 0 : sTime -= sInterval/2.;
4470 : }
4471 : }
4472 :
4473 0 : ArrayTimeInterval timeInterval( ASDMArrayTime(sTime),
4474 0 : ASDMInterval(sInterval) );
4475 0 : return timeInterval;
4476 : }
4477 :
4478 0 : vector< Angle > MS2ASDM::ASDMAngleV(const MDirection mDir){
4479 0 : vector< Angle > angV;
4480 0 : angV.push_back( mDir.getAngle( unitASDMAngle() ).getValue()(0) );
4481 0 : angV.push_back( mDir.getAngle( unitASDMAngle() ).getValue()(1) );
4482 0 : return angV;
4483 0 : }
4484 :
4485 0 : DirectionReferenceCodeMod::DirectionReferenceCode MS2ASDM::ASDMDirRefCode(const MDirection::Types type){
4486 :
4487 0 : switch(type){
4488 0 : 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 0 : BasebandNameMod::BasebandName MS2ASDM::ASDMBBName( Int BBCNo ){
4529 0 : switch(BBCNo){
4530 0 : case 1: return BasebandNameMod::BB_1;
4531 0 : case 2: return BasebandNameMod::BB_2;
4532 0 : case 3: return BasebandNameMod::BB_3;
4533 0 : 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 0 : case 0:
4539 : default:
4540 0 : return BasebandNameMod::NOBB;
4541 : }
4542 : }
4543 :
4544 0 : NetSidebandMod::NetSideband MS2ASDM::ASDMNetSideBand( Int netSideB ){
4545 0 : switch(netSideB){
4546 0 : case 1: return NetSidebandMod::LSB;
4547 0 : 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 0 : FrequencyReferenceCodeMod::FrequencyReferenceCode MS2ASDM::ASDMFreqRefCode( const MFrequency::Types refFrame ){
4556 0 : LogIO os(LogOrigin("MS2ASDM", "(ASDMFreqRefCode)"));
4557 0 : switch( refFrame ){
4558 0 : case MFrequency::LSRD: return FrequencyReferenceCodeMod::LSRD;
4559 0 : 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 0 : 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 0 : }
4571 :
4572 0 : Bool MS2ASDM::stokesTypePresent( const Vector< Int > corrT,
4573 : const Stokes::StokesTypes st ){
4574 0 : Bool rval = false;
4575 0 : for(uInt j=0; j<corrT.size(); j++){
4576 0 : if(corrT[j]==static_cast<Int>(st)){
4577 0 : rval = true;
4578 0 : break;
4579 : }
4580 : }
4581 0 : return rval;
4582 : }
4583 :
4584 0 : 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 0 : Int rval = -1;
4591 :
4592 0 : Quantity theFreq( refFreq.get(), String(Frequency::unit()) );
4593 0 : Double theFreqGHz = theFreq.getValue("GHz");
4594 :
4595 : //cout << "tel " << telName_p << endl;
4596 : //cout << "Freq (GHz) " << theFreqGHz << endl;
4597 :
4598 : // default values
4599 0 : Quantity tempQ( ((Int)theFreqGHz)*1E9, "Hz");
4600 0 : repFreq = tempQ.getValue(unitASDMFreq());
4601 0 : frequencyBand = ReceiverBandMod::UNSPECIFIED;
4602 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4603 :
4604 : // implementation of the ALMA freq bands !!!
4605 0 : if(telName_p == "ALMA" || telName_p == "OSF" || telName_p == "ACA"){
4606 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : else if(211.<=theFreqGHz && theFreqGHz<275.){
4637 0 : repFreq = (211.+275.)/2.*1E9;
4638 0 : frequencyBand = ReceiverBandMod::ALMA_RB_06;
4639 0 : receiverSideband = ReceiverSidebandMod::TSB;
4640 0 : rval = 6;
4641 : }
4642 0 : else if(275.<=theFreqGHz && theFreqGHz<373.){
4643 0 : repFreq = (275.+373.)/2.*1E9;
4644 0 : frequencyBand = ReceiverBandMod::ALMA_RB_07;
4645 0 : receiverSideband = ReceiverSidebandMod::TSB;
4646 0 : rval = 7;
4647 : }
4648 0 : 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 0 : else if(602.<=theFreqGHz && theFreqGHz<720.){
4655 0 : repFreq = (602.+720.)/2.*1E9;
4656 0 : frequencyBand = ReceiverBandMod::ALMA_RB_09;
4657 0 : receiverSideband = ReceiverSidebandMod::DSB;
4658 0 : 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 0 : Quantity tempQ2(repFreq, "Hz");
4674 0 : repFreq = tempQ2.getValue(unitASDMFreq());
4675 0 : return rval;
4676 0 : }
4677 0 : else if(telName_p == "VLA" || telName_p == "EVLA" || telName_p == "JVLA"){
4678 : // EVLA freq band implementation!!
4679 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : else if(8.0 <=theFreqGHz && theFreqGHz< 12.0){
4710 0 : repFreq = (8.+12.)/2.*1E9;
4711 0 : frequencyBand = ReceiverBandMod::EVLA_X;
4712 0 : receiverSideband = ReceiverSidebandMod::NOSB;
4713 0 : 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 0 : Quantity tempQ2(repFreq, "Hz");
4746 0 : repFreq = tempQ2.getValue(unitASDMFreq());
4747 0 : return rval;
4748 0 : }
4749 :
4750 0 : return 0; // unknown observatory
4751 0 : }
4752 :
4753 :
4754 : } //#End casa namespace
|