General Purpose Geodetic Library
SgVlbiSessionIoFringes.cpp
Go to the documentation of this file.
1 /*
2  *
3  * This file is a part of Space Geodetic Library. The library is used by
4  * nuSolve, a part of CALC/SOLVE system, and designed to make analysis of
5  * geodetic VLBI observations.
6  * Copyright (C) 2015-2020 Sergei Bolotin.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #include <iostream>
24 #include <stdlib.h>
25 
26 
27 
28 #include <QtCore/QDateTime>
29 #include <QtCore/QDir>
30 #include <QtCore/QFile>
31 #include <QtCore/QFileInfo>
32 #include <QtCore/QList>
33 #include <QtCore/QMap>
34 #include <QtCore/QTextStream>
35 #include <QtCore/QVector>
36 
37 
38 #include <SgVlbiSession.h>
39 
40 #include <SgConstants.h>
41 #include <SgLogger.h>
42 #include <SgVersion.h>
43 #include <SgVlbiBand.h>
44 #include <SgVlbiObservation.h>
45 
46 
47 
48 
49 
50 #ifdef HAVE_MK4_DATA_H
51 extern "C"
52 {
53 // workaround "complex" stuff:
54  #define T230_VERSION 0
55  #include <hops/mk4_data.h>
56 }
57 #endif
58 //
59 //
60 #ifdef HAVE_MK4_DFIO_H
61 extern "C"
62 {
63  #include <hops/mk4_dfio.h>
64 }
65 #endif
66 //
67 //
68 #ifdef HAVE_MK4_VEX_H
69 // workaround warnings about redefinitions of TRUE and FALSE (Qt vs HOPS):
70 # ifdef FALSE
71 # define FALSE_SAVED FALSE
72 # undef FALSE
73 # endif
74 # ifdef TRUE
75 # define TRUE_SAVED TRUE
76 # undef TRUE
77 # endif
78 extern "C"
79 {
80  #include <hops/mk4_vex.h>
81 }
82 # ifdef FALSE_SAVED
83 # undef FALSE
84 # define FALSE FALSE_SAVED
85 # undef FALSE_SAVED
86 # endif
87 # ifdef TRUE_SAVED
88 # undef TRUE
89 # define TRUE TRUE_SAVED
90 # undef TRUE_SAVED
91 # endif
92 #endif
93 
94 
95 
96 
97 
98 /*=======================================================================================================
99 *
100 * Auxiliary data structures
101 *
102 *======================================================================================================*/
103 
104 
105 
106 
107 /*=======================================================================================================
108 *
109 * I/O utilities:
110 *
111 *======================================================================================================*/
112 //
113 #if !defined HAVE_MK4_DATA_H || !defined HAVE_MK4_DFIO_H || !defined HAVE_MK4_VEX_H
114 bool SgVlbiSession::getDataFromFringeFiles(const QString&, const QString&, const QString&,
115  const QString&, const QString&, const QList<QString>&)
116 {
117  std::cout << "HOPS were not found.\n";
119  "::getDataFromFringeFiles(): cannot read fringe files, the software was compiled without HOPS "
120  "support");
121  return false;
122 };
123 
124 
125 
126 //
127 void SgVlbiSession::parseVexFile(const QString&, QString&, QString&)
128 {
129 };
130 
131 
132 
133 //
134 void SgVlbiSession::processVexFile(const QString&, QMap<QString, StationInfo>&, VexInfo&,
135  const QMap<QString, QString>&, QString&)
136 {
137 };
138 
139 
140 
141 //
142 void SgVlbiSession::processFringeFile(const QString&, const QString&, const QMap<QString, StationInfo>&,
143  const VexInfo&, const QString&, const QMap<QString, QString>&, const QMap<QString, QString>&,
144  const QMap<QString, QString>&, const QMap<QString, QString>&, const QMap<QString, QString>&,
145  const QMap<QString, int>&, int&)
146 {
147 };
148 
149 
150 
151 //
153 {
154  return false;
155 };
156 //
157 //
158 //
159 //
160 #else
161 //
162 //
163 //
164 //
165 // auxiliary data structures (we do not need them outside of this file):
166 struct ChannelInfo
167 {
168  QString name_; /* External channel name */
169  QString polarization_; /* R or L */
170  double sky_frequency_; /* Hz */
171  QString net_sideband_; /* U or L */
172  double bandwidth_; /* Hz */
173  QString band_id_; /* Linkword (internal use) */
174  QString chan_id_; /* Linkword (internal use) */
175  QString bbc_id_; /* Linkword (internal use) */
176  QString pcal_id_; /* Linkword (internal use) */
177  QString if_id_; /* Linkword (internal use) */
178  int bbc_no_; /* Physical BBC# */
179  QString if_name_; /* Physical IF name */
180  double if_total_lo_; /* Hz */
181  QString if_sideband_; /* U or L */
182  ChannelInfo();
183  ChannelInfo(const ChannelInfo& ci);
184  ChannelInfo& operator=(const ChannelInfo& ci);
185 };
186 //
187 ChannelInfo::ChannelInfo() :
188  name_(""),
189  polarization_(""),
190  net_sideband_(""),
191  band_id_(""),
192  chan_id_(""),
193  bbc_id_(""),
194  pcal_id_(""),
195  if_id_(""),
196  if_name_(""),
197  if_sideband_("")
198 {
199  sky_frequency_ = -1.0;
200  bandwidth_ = -1.0;
201  bbc_no_ = -1;
202  if_total_lo_ = -1.0;
203 };
204 ChannelInfo::ChannelInfo(const ChannelInfo& ci)
205 {
206  name_ = ci.name_;
207  polarization_ = ci.polarization_;
208  sky_frequency_ = ci.sky_frequency_;
209  net_sideband_ = ci.net_sideband_;
210  bandwidth_ = ci.bandwidth_;
211  band_id_ = ci.band_id_;
212  chan_id_ = ci.chan_id_;
213  bbc_id_ = ci.bbc_id_;
214  pcal_id_ = ci.pcal_id_;
215  if_id_ = ci.if_id_;
216  bbc_no_ = ci.bbc_no_;
217  if_name_ = ci.if_name_;
218  if_total_lo_ = ci.if_total_lo_;
219  if_sideband_ = ci.if_sideband_;
220 };
221 ChannelInfo& ChannelInfo::operator=(const ChannelInfo& ci)
222 {
223  name_ = ci.name_;
224  polarization_ = ci.polarization_;
225  sky_frequency_ = ci.sky_frequency_;
226  net_sideband_ = ci.net_sideband_;
227  bandwidth_ = ci.bandwidth_;
228  band_id_ = ci.band_id_;
229  chan_id_ = ci.chan_id_;
230  bbc_id_ = ci.bbc_id_;
231  pcal_id_ = ci.pcal_id_;
232  if_id_ = ci.if_id_;
233  bbc_no_ = ci.bbc_no_;
234  if_name_ = ci.if_name_;
235  if_total_lo_ = ci.if_total_lo_;
236  if_sideband_ = ci.if_sideband_;
237  return *this;
238 };
239 //
240 //
241 //
242 struct StationInfo
243 {
244  QString name_;
245  QString id_2char_;
246  QString id_1char_;
247  int recorderType_;
248  int trackFormat_;
249  int bits_sample_;
250  double sampleRate_;
251  QMap<QString, ChannelInfo> channelByName_;
252  StationInfo();
253  StationInfo(const StationInfo& si);
254  StationInfo& operator=(const StationInfo& si);
255 };
256 //
257 StationInfo::StationInfo() :
258  name_(""),
259  id_2char_(""),
260  id_1char_(""),
261  channelByName_()
262 {
263  recorderType_ = -1;
264  trackFormat_ = -1;
265  bits_sample_ = -1;
266  sampleRate_ = -1.0;
267 };
268 //
269 StationInfo::StationInfo(const StationInfo& si) :
270  name_(si.name_),
271  id_2char_(si.id_2char_),
272  id_1char_(si.id_1char_),
273  channelByName_()
274 {
275  recorderType_ = si.recorderType_;
276  trackFormat_ = si.trackFormat_;
277  bits_sample_ = si.bits_sample_;
278  sampleRate_ = si.sampleRate_;
279  channelByName_.clear();
280  for (QMap<QString, ChannelInfo>::const_iterator it=si.channelByName_.begin();
281  it!=si.channelByName_.end(); ++it)
282  channelByName_.insert(it.key(), it.value());
283 };
284 StationInfo& StationInfo::operator=(const StationInfo& si)
285 {
286  name_ = si.name_;
287  id_2char_ = si.id_2char_;
288  id_1char_ = si.id_1char_;
289  recorderType_ = si.recorderType_;
290  trackFormat_ = si.trackFormat_;
291  bits_sample_ = si.bits_sample_;
292  sampleRate_ = si.sampleRate_;
293  channelByName_.clear();
294  for (QMap<QString, ChannelInfo>::const_iterator it=si.channelByName_.begin();
295  it!=si.channelByName_.end(); ++it)
296  channelByName_.insert(it.key(), it.value());
297  return *this;
298 };
299 //
300 
301 
302 
303 struct VexInfo
304 {
305  double sampleRate_;
306  double apLength_;
307  QString expName_;
308  VexInfo();
309  VexInfo(const VexInfo& vi);
310  VexInfo& operator=(const VexInfo& vi);
311 };
312 //
313 VexInfo::VexInfo() : expName_("")
314 {
315  sampleRate_ = -1.0;
316  apLength_ = -1.0;
317 };
318 VexInfo::VexInfo(const VexInfo& vi)
319 {
320  *this = vi;
321 };
322 VexInfo& VexInfo::operator=(const VexInfo& vi)
323 {
324  sampleRate_ = vi.sampleRate_;
325  apLength_ = vi.apLength_;
326  expName_ = vi.expName_;
327  return *this;
328 };
329 //
330 
331 
332 
333 //
334 struct FringeFileName
335 {
336  QString baselineId_;
337  QString bandId_;
338  QString sequenceId_;
339  QString rootCodeId_;
340  bool isOk_;
341  int sequenceNumber_;
342  FringeFileName();
343  inline FringeFileName(const FringeFileName& fn) {*this = fn;};
344  FringeFileName(const QString fileName);
345  QString fileName() const
346  {return isOk_?(baselineId_ + "." + bandId_ + "." + sequenceId_ + "." + rootCodeId_):"";};
347  QString id() const
348  {return isOk_?(baselineId_ + "." + bandId_):"";};
349  FringeFileName& operator=(const FringeFileName& fn);
350 };
351 //
352 FringeFileName::FringeFileName() : baselineId_(""), bandId_(""), sequenceId_(""), rootCodeId_("")
353 {
354  isOk_ = false;
355  sequenceNumber_ = 0;
356 };
357 //
358 FringeFileName::FringeFileName(const QString fileName) :
359  baselineId_(""), bandId_(""), sequenceId_(""), rootCodeId_("")
360 {
361  isOk_ = false;
362  sequenceNumber_ = 0;
363  QStringList itemList=fileName.split('.');
364  if (itemList.size() == 4)
365  {
366  baselineId_ = itemList.at(0);
367  bandId_ = itemList.at(1);
368  sequenceId_ = itemList.at(2);
369  rootCodeId_ = itemList.at(3);
370  if (baselineId_.size()==2 && baselineId_.at(0)!=baselineId_.at(1) &&
371  bandId_.size()==1 && sequenceId_.size()>0 && rootCodeId_.size()>0)
372  sequenceNumber_ = sequenceId_.toInt(&isOk_);
373  };
374 };
375 //
376 FringeFileName& FringeFileName::operator=(const FringeFileName& fn)
377 {
378  baselineId_ = fn.baselineId_;
379  bandId_ = fn.bandId_;
380  sequenceId_ = fn.sequenceId_;
381  rootCodeId_ = fn.rootCodeId_;
382  isOk_ = fn.isOk_;
383  sequenceNumber_ = fn.sequenceNumber_;
384  return *this;
385 };
386 
387 
388 
389 
390 
391 //
392 class FringeFileMap : public QMap<QString, FringeFileName>
393 {
394 public:
395  inline FringeFileMap() : QMap<QString, FringeFileName>() {};
396  inline ~FringeFileMap() {clear();};
397  void registerFileName(const QString fileName);
398 };
399 //
400 void FringeFileMap::registerFileName(const QString fileName)
401 {
402  FringeFileName ffName(fileName);
403  if (ffName.isOk_)
404  {
405  if (contains(ffName.id()))
406  {
407  if (value(ffName.id()).sequenceNumber_ < ffName.sequenceNumber_)
408  {
410  "FringeFileMap::registerFileName(): the fringe file name " +
411  (*this)[ffName.id()].fileName() + " is being replaced by " + ffName.fileName());
412  (*this)[ffName.id()] = ffName;
413  };
414  }
415  else
416  {
417  insert(ffName.id(), ffName);
418  }
419  };
420 };
421 
422 
423 
424 //
425 struct CorelRootFileName
426 {
427  QString sourceId_;
428  QString rootCodeId_;
429  bool isOk_;
430  CorelRootFileName();
431  CorelRootFileName(const QString fileName);
432  inline CorelRootFileName(const CorelRootFileName& cr) {*this = cr;};
433 
434  QString fileName() const
435  {return isOk_?(sourceId_ + "." + rootCodeId_):"";};
436  CorelRootFileName& operator=(const CorelRootFileName& cr);
437 };
438 //
439 CorelRootFileName::CorelRootFileName() : sourceId_(""), rootCodeId_("")
440 {
441  isOk_ = false;
442 };
443 //
444 CorelRootFileName::CorelRootFileName(const QString fileName) :
445  sourceId_(""), rootCodeId_("")
446 {
447  isOk_ = false;
448  QStringList itemList=fileName.split('.');
449  if (itemList.size() == 2)
450  {
451  sourceId_ = itemList.at(0);
452  rootCodeId_ = itemList.at(1);
453  isOk_ = true;
454  };
455 };
456 //
457 CorelRootFileName& CorelRootFileName::operator=(const CorelRootFileName& cr)
458 {
459  sourceId_ = cr.sourceId_;
460  rootCodeId_ = cr.rootCodeId_;
461  isOk_ = cr.isOk_;
462  return *this;
463 };
464 
465 
466 
467 
468 
469 
470 
471 
472 
473 
474 
475 // end of aux data structures
476 
477 
478 //
479 //
480 //
481 bool SgVlbiSession::getDataFromFringeFiles(const QString& path2data,
482  const QString& altDatabaseName, const QString& altCorrelatorName,
483  const QString& historyFileName, const QString& mapFileName,
484  const QList<QString>& fringeErrorCodes2Skip)
485 {
486  bool isOk=false, isScanDirOk;
487  QDir dir(path2data);
488  QList<QString> dirsOfScans;
489  QStringList dirList;
490  QRegExp reScanDirName("[0-9]{3}-[0-9]{4}[a-zA-Z]{0,1}");
491 //QRegExp reVexFileName("^([0-9a-zA-Z+-_]{1,8})\\.([\\w]{6,7})$");
492  int idx;
493  // per scan entries:
494 // QString vexFileName("");
495  FringeFileMap scanFileNames;
496  QMap<QString, CorelRootFileName>
497  crootById;
498  QString sPiName, sExperDescr;
499  QMap<QString, int> piNamesByCount, expDescrsByCount, expNameByCount;
500  QMap<int, int> expSerialNumByCount;
501  QString correlatorComments(historyFileName);
502  QString correlatorName("");
503  QMap<QString, QString> stnNameById, stnNameByI; // maps of station name by 2- and 1-char Ids
504  //
505  // for name maps:
506  QMap<QString, QString> stn2stn;
507  QMap<QString, QString> src2src;
508  QMap<QString, QString> bnd2bnd;
509  QMap<QString, int> fringeErrorCodeByInt;
510  QMap<QString, int> corrNameByCount;
511 
512 
513  dirList = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name);
514  if (dirList.size() == 0)
515  {
517  "::getDataFromFringeFiles(): nothing to read");
518  return isOk;
519  };
520 
521  //
522  //
523  importMapFile(mapFileName, stn2stn, src2src, bnd2bnd);
524  if (stn2stn.size())
526  "::getDataFromFringeFiles(): loaded " + QString("").setNum(stn2stn.size()) +
527  " entries for station name maps");
528  if (src2src.size())
530  "::getDataFromFringeFiles(): loaded " + QString("").setNum(src2src.size()) +
531  " entries for source name maps");
532  if (bnd2bnd.size())
534  "::getDataFromFringeFiles(): loaded " + QString("").setNum(bnd2bnd.size()) +
535  " entries for bnd name maps");
536  if (fringeErrorCodes2Skip.size())
537  {
538  for (int i=0; i<fringeErrorCodes2Skip.size(); i++)
539  fringeErrorCodeByInt.insert(fringeErrorCodes2Skip.at(i), 1);
540  };
541  //
542  //
543  for (int i=0; i<dirList.size(); i++)
544  dirsOfScans << dirList.at(i);
545 
547  "::getDataFromFringeFiles(): filtered " + QString("").setNum(dirsOfScans.size()) +
548  " scan entries from " + QString("").setNum(dirList.size()) + " total number of directories");
549 
550  stnNameById.clear();
551  stnNameByI.clear();
552  for (int i=0; i<dirsOfScans.size(); i++)
553  {
554  const QString &inDirName=dirsOfScans.at(i);
555  CorelRootFileName croot;
556 
557  dir.setPath(path2data + "/" + inDirName);
558  dirList.clear();
559  dirList = dir.entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::Readable, QDir::Name);
560 
562  "::getDataFromFringeFiles(): processing directory '" + dir.path() + "'");
563 
564  isScanDirOk = true;
565  scanFileNames.clear();
566  crootById.clear();
567  //
568  // analyze what we get:
569  QStringList listOfVexFiles;
570  for (int j=0; j<dirList.size(); j++)
571  {
572  const QString &fileName=dirList.at(j);
573  // if (fileName.contains(reVexFileName))
574  // if (reVexFileName.indexIn(fileName) != -1)
575  // if (reVexFileName.indexIn(fileName) != -1)
576  // {
577  CorelRootFileName croot(fileName);
578  if (croot.isOk_)
579  {
580  if (!crootById.contains(croot.rootCodeId_))
581  crootById.insert(croot.rootCodeId_, croot);
582  else
584  "::getDataFromFringeFiles(): the croot file " + fileName + " with crootId '" +
585  croot.rootCodeId_ + "' already registered as '" +
586  crootById.value(croot.rootCodeId_).fileName() + "'");
587  // }
588  // else
589  // logger->write(SgLogger::WRN, SgLogger::IO, className() +
590  // "::getDataFromFringeFiles: the croot file " + fileName + " is not good");
591  }
592  else
593  scanFileNames.registerFileName(fileName);
594  };
595  // check our containers:
596  if (crootById.size() < 1)
597  {
599  "::getDataFromFringeFiles(): cannot find any VEX file in the directory " + dir.path() +
600  ", skipped");
601  isScanDirOk = false;
602  };
603  if (scanFileNames.size() < 1)
604  {
606  "::getDataFromFringeFiles(): cannot find any usable fringe file in the directory " +
607  dir.path() + ", skipped");
608  isScanDirOk = false;
609  };
610  //
611  if (isScanDirOk)
612  {
613  QMap<QString, QMap<QString, StationInfo> >
614  stnInfoByNameById;
615  QMap<QString, VexInfo> vexInfoById;
616  //
617  // ok, first, read VEXes:
618  for (QMap<QString, CorelRootFileName>::iterator it=crootById.begin(); it!=crootById.end(); ++it)
619  {
620  VexInfo vi;
621  QMap<QString, StationInfo>
622  stnInfoByName;
623  const QString &vexFileName=it.value().fileName();
624  //
625  // collect available data from a VEX file (data that we should expect in the scan dir):
626 
627  processVexFile(dir.path() + "/" + vexFileName, stnInfoByName, vi, stn2stn, correlatorName);
628  if (correlatorName == "difx" || correlatorName == "sfxc")
629  correlatorName = "";
630  vexInfoById.insert(it.key(), vi);
631  stnInfoByNameById.insert(it.key(), stnInfoByName);
632 
633  // check station names and ids:
634  for (QMap<QString, StationInfo>::iterator it=stnInfoByName.begin();
635  it!=stnInfoByName.end(); ++it)
636  {
637  const QString& stnName=it.value().name_;
638  const QString& stn2chrId=it.value().id_2char_;
639  const QString& stn1chrId=it.value().id_1char_;
640  // check 2-chars id:
641  if (stnNameById.contains(stn2chrId))
642  {
643  if (stnNameById.value(stn2chrId) != stnName)
644  {
646  "::getDataFromFringeFiles(): -------------------------------------------");
648  "::getDataFromFringeFiles(): the croot file " + inDirName + "/" + vexFileName +
649  " contains station identities that missmatch previous data:");
651  "::getDataFromFringeFiles(): " + stnNameById.value(stn2chrId) + "[" +
652  stn2chrId + "] != " + stnName);
654  "::getDataFromFringeFiles(): -------------------------------------------");
655  };
656  }
657  else
658  stnNameById.insert(stn2chrId, stnName);
659  // check 1-chars id:
660  if (stnNameByI.contains(stn1chrId))
661  {
662  if (stnNameByI.value(stn1chrId) != stnName)
663  {
665  "::getDataFromFringeFiles(): -------------------------------------------");
667  "::getDataFromFringeFiles(): the croot file " + inDirName + "/" + vexFileName +
668  " contains station identities that missmatch previous data:");
670  "::getDataFromFringeFiles(): " + stnNameByI.value(stn1chrId) + "[" +
671  stn1chrId + "] != " + stnName);
673  "::getDataFromFringeFiles(): -------------------------------------------");
674  };
675  }
676  else
677  stnNameByI.insert(stn1chrId, stnName);
678  };
679  //
680  parseVexFile(dir.path() + "/" + vexFileName, sPiName, sExperDescr);
681  // collect all available P.I. names and experiment descriptions to check consistency (later)
682  piNamesByCount[sPiName]++;
683  expDescrsByCount[sExperDescr]++;
684  expNameByCount[vi.expName_]++;
685  corrNameByCount[correlatorName]++;
687  "::getDataFromFringeFiles(): the corel.root file " + vexFileName + " has been processed");
688  };
689  //
690  // then, get data from each baseline:
691  /*
692  for (int j=0; j<scanFileNames.size(); j++)
693  {
694  const QString &crootId=scanFileNames.at(j).rootCodeId_;
695 
696  if (!(crootById.contains(crootId) && vexInfoById.contains(crootId) &&
697  stnInfoByNameById.contains(crootId)))
698  logger->write(SgLogger::WRN, SgLogger::IO, className() +
699  "::getDataFromFringeFiles(): cannot find a corel.root file for the fringe file '" +
700  scanFileNames.at(j).fileName() + "' with rootId=[" + crootId + "], skipped");
701  else
702  {
703  processFringeFile(dir.path(), scanFileNames.at(j).fileName(), stnInfoByNameById.value(crootId),
704  vexInfoById.value(crootId), crootById.value(crootId).fileName(), stnNameById, stnNameByI,
705  stn2stn, src2src, fringeErrorCodeByInt);
706  };
707  };
708  */
709  for (QMap<QString, FringeFileName>::iterator jt=scanFileNames.begin(); jt!=scanFileNames.end();
710  ++jt)
711  {
712  FringeFileName &ffn=jt.value();
713  const QString &crootId=ffn.rootCodeId_;
714  int sn;
715  if (!(crootById.contains(crootId) && vexInfoById.contains(crootId) &&
716  stnInfoByNameById.contains(crootId)))
718  "::getDataFromFringeFiles(): cannot find a corel.root file for the fringe file '" +
719  ffn.fileName() + "' with rootId=[" + crootId + "], skipped");
720  else
721  {
722  sn = 0;
723  processFringeFile(dir.path(), ffn.fileName(), stnInfoByNameById.value(crootId),
724  vexInfoById.value(crootId), crootById.value(crootId).fileName(), stnNameById, stnNameByI,
725  stn2stn, src2src, bnd2bnd, fringeErrorCodeByInt, sn);
726  expSerialNumByCount[sn]++;
727  };
728  };
729  //
730  // end of data processing.
731  };
732  };
733  //
734  //
735  // check: did we read something at all:
736  if (!bands_.size())
737  {
739  "::getDataFromFringeFiles(): nothing useful found");
740  return false;
741  };
742  //
743  //
744  setOriginType(OT_MK4); // flag it
745  setCorrelatorType("MK4 ");
748  //
749  //
750  // set global stuff here:
751  //
752  if (piNamesByCount.count() == 1)
753  {
754  if (piNamesByCount.begin().key().size())
755  setPiAgencyName(piNamesByCount.begin().key());
756  else
757  setPiAgencyName("Undefined");
759  "::getDataFromFringeFiles(): session P.I agency name was set to " + getPiAgencyName());
760  }
761  else
762  {
763  // need add more diagnostics here:
764  setPiAgencyName("Mixed");
766  "::getDataFromFringeFiles(): more than one PI agency names collected:");
767  for (QMap<QString, int>::iterator itt=piNamesByCount.begin(); itt!=piNamesByCount.end(); ++itt)
769  "::getDataFromFringeFiles(): \"" + itt.key() + "\" => " + QString("").setNum(itt.value()));
770  };
771  if (expNameByCount.count() == 1)
772  {
773  if (expNameByCount.begin().key().size())
774  setSessionCode(expNameByCount.begin().key().toUpper()); // take into account Mike Titus effect
775  else
776  setSessionCode("Undefined");
778  "::getDataFromFringeFiles(): session code was set to " + getSessionCode());
779  }
780  else
781  {
782  // need add more diagnostics here:
783  setSessionCode("Mixed");
785  "::getDataFromFringeFiles(): more than one experiment name found:");
786  for (QMap<QString, int>::iterator itt=expNameByCount.begin(); itt!=expNameByCount.end(); ++itt)
788  "::getDataFromFringeFiles(): \"" + itt.key() + "\" => " + QString("").setNum(itt.value()));
789  };
790  if (expDescrsByCount.count() == 1)
791  {
792  if (expDescrsByCount.begin().key().size())
793  setDescription(expDescrsByCount.begin().key());
794  else
795  setDescription("Undefined");
797  "::getDataFromFringeFiles(): session description was set to " + getDescription());
798  }
799  else
800  {
801  // need add more diagnostics here:
802  setDescription("Mixed");
804  "::getDataFromFringeFiles(): more than one experiment description found:");
805  for (QMap<QString, int>::iterator itt=expDescrsByCount.begin(); itt!=expDescrsByCount.end(); ++itt)
807  "::getDataFromFringeFiles(): \"" + itt.key() + "\" => " + QString("").setNum(itt.value()));
808  };
809  //
810  if (getExperimentSerialNumber() == 0) // is not set through command line arg
811  {
812  if (expSerialNumByCount.count() == 1)
813  {
814  int n;
815  n = expSerialNumByCount.begin().key();
816  if (0<n && n!=16383)
817  {
818  setExperimentSerialNumber(expSerialNumByCount.begin().key());
820  "::getDataFromFringeFiles(): session serial number was set to " +
821  QString("").sprintf("%d", getExperimentSerialNumber()));
822  }
823  else
825  "::getDataFromFringeFiles(): the observations do not have correct experiment serial number " +
826  QString("").sprintf("(==%d)", n));
827  }
828  else
829  {
830  // need add more diagnostics here:
832  "::getDataFromFringeFiles(): more than one experiment serial number found:");
833  for (QMap<int, int>::iterator it=expSerialNumByCount.begin(); it!=expSerialNumByCount.end(); ++it)
835  "::getDataFromFringeFiles(): " + QString("").sprintf("%d -> %d times", it.key(), it.value()));
836  };
837  };
838  if (corrNameByCount.count() == 1)
839  {
840  if (corrNameByCount.begin().key().size())
841  {
842  setCorrelatorName(corrNameByCount.begin().key());
844  "::getDataFromFringeFiles(): correlator name was set to \"" + getCorrelatorName() + "\"");
845  }
846  else
847  {
848  setCorrelatorName("");
850  "::getDataFromFringeFiles(): cannot find correlator name in the vex files");
851  };
852  }
853  else
854  {
855  // need add more diagnostics here:
856  setCorrelatorName("Mixed");
858  "::getDataFromFringeFiles(): more than one correlator name collected:");
859  for (QMap<QString, int>::iterator itt=corrNameByCount.begin(); itt!=corrNameByCount.end(); ++itt)
861  "::getDataFromFringeFiles(): \"" + itt.key() + "\" => " + QString("").setNum(itt.value()));
862  };
863  //
864  if (altCorrelatorName.size())
865  {
866  setCorrelatorName(altCorrelatorName);
868  "::getDataFromFringeFiles(): correlator name was explicitly set to \"" + altCorrelatorName + "\"");
869  };
870  //
871  if (altDatabaseName.size() == 9)
872  {
873  setName(altDatabaseName);
874  setNetworkSuffix(altDatabaseName.at(8));
875  setOfficialName("UNKN");
876  setSubmitterName("UNKN");
877  setSchedulerName("UNKN");
879  "::getDataFromFringeFiles(): database name was explicitly set to " + altDatabaseName);
880  }
881  else if (altDatabaseName.size() && altDatabaseName.size()!=9)
883  "::getDataFromFringeFiles(): the provided database name, " + altDatabaseName +
884  ", was ignored");
885  //
886  //
887  QMap<double, SgVlbiBand*> bandByFreq;
888  QString str("");
889  for (int i=0; i<bands_.size(); i++)
890  {
891  SgVlbiBand *band=bands_.at(i);
892  QString bandKey=band->getKey();
893  band->setTCreation(SgMJD::currentMJD().toUtc());
894  band->setInputFileName(path2data + "/*");
895  band->setInputFileVersion(0);
896  //
897  // quick'n'dirty:
898  idx = 0;
899  SgVlbiObservable *o=observations_.at(idx)->observable(bandKey);
900  while (!o && idx<observations_.size())
901  o = observations_.at(idx++)->observable(bandKey);
902  if (o)
904  else
906  "::getDataFromFringeFiles(): cannot set up a frequency for " + bandKey + "-band");
907  if (bandByFreq.contains(band->getFrequency()))
908  {
910  "::getDataFromFringeFiles(): the frequency " + QString("").setNum(band->getFrequency()) +
911  " is already registered");
912  }
913  else
914  bandByFreq.insert(band->getFrequency(), band);
915  };
916  //
917  //
918  // load correlator's comments for history records:
919  //
920  if (correlatorComments.size()==0)
921  {
922  dir.setPath(path2data + "/../control/");
923  str = "";
924  if (!dir.exists())
926  "::getDataFromFringeFiles(): cannot get correlator comments, the directory does not exist: " +
927  dir.path());
928  else
929  {
930  dirList.clear();
931  dirList = dir.entryList(QStringList() << "*.corr",
932  QDir::Files | QDir::NoDotAndDotDot | QDir::Readable, QDir::Name);
933  if (dirList.size() == 0)
934  {
936  "::getDataFromFringeFiles(): cannot get correlator comments, no any *.corr file found: " +
937  dir.path());
938  }
939  else if (dirList.size() > 1)
940  {
942  "::getDataFromFringeFiles(): found more than one file with correlator comments:");
943  for (int j=0; j<dirList.size(); j++)
945  "::getDataFromFringeFiles(): " + dirList.at(j));
946  str = dirList.at(0);
948  "::getDataFromFringeFiles(): picked up this one: " + str);
949  }
950  else
951  str = dirList.at(0);
952  };
953  if (str.size())
954  correlatorComments = path2data + "/../control/" + str;
955  };
956  if (correlatorComments.size())
957  getCorrelatorHistory(correlatorComments);
958  else
959  {
960  for (int i=0; i<bands_.size(); i++)
961  {
962  bands_.at(i)->history().addHistoryRecord("== The correlator report was not provided. ==",
963  SgMJD::currentMJD().toUtc());
964  bands_.at(i)->history().addHistoryRecord("== ", SgMJD::currentMJD().toUtc());
965  };
967  "::getDataFromFringeFiles(): the correlator report was not provided.");
968  };
969  //
970  //
971  // set up a primary band:
972  // standard IVS case:
973  QString primeBandKey;
974  if (bandByKey_.size()==2 && bandByKey_.contains("X") && bandByKey_.contains("S"))
975  {
977  "::getDataFromFringeFiles(): importing typical IVS session");
978  primaryBand_ = bandByKey_.value("X");
979  }
980  else
981  {
983  "::getDataFromFringeFiles(): importing a foreign session setup");
984  if (bandByFreq.size() > 1)
985  primaryBand_ = bandByFreq.begin().value();
986  else
987  primaryBand_ = bands_.at(0);
988  };
990  primeBandKey = primaryBand_->getKey();
991  //
992  // remove observations that are not in the primary band:
993  int num;
994  idx = num = 0;
995  while (idx<observations_.size())
996  {
997  SgVlbiObservation *obs=observations_.at(idx);
998  if (!obs->observable(primeBandKey))
999  {
1001  "::getDataFromFringeFiles(): the observation " + obs->getKey() +
1002  " of the scan " + obs->getScanName() + " is being removed from the data set");
1003  observationByKey_.remove(obs->getKey());
1004  observations_.removeAt(idx);
1005  idx--;
1006  num++;
1007  delete obs;
1008  };
1009  idx++;
1010  };
1011  if (num)
1012  {
1014  "::getDataFromFringeFiles(): " + QString("").setNum(num) +
1015  " second-band-only observation" + (num==1?" was":"s were") + " removed");
1016  //
1017  // check source list:
1018  // ...
1019  };
1020  //
1021  //
1022  if (selfCheck(false))
1024  "::getDataFromFringeFiles(): session selfcheck complete");
1025  else
1026  {
1028  "::getDataFromFringeFiles(): the selfcheck for the session failed");
1029  return false;
1030  };
1031  //
1032  // calculate aux data:
1033  for (int i=0; i<observations_.size(); i++)
1034  {
1035  SgVlbiObservation *obs=observations_.at(i);
1036  for (QMap<QString, SgVlbiObservable*>::iterator it=obs->observableByKey().begin();
1037  it!=obs->observableByKey().end(); ++it)
1038  {
1039  SgVlbiObservable *o=it.value();
1040  o->calcPhaseCalDelay();
1041  };
1042  };
1044  "::getDataFromFringeFiles(): phase cal delays were calculated");
1045  //
1046  //
1048  {
1050  "::getDataFromFringeFiles(): cannot get the experiment serial number");
1051  };
1052  //
1053  return true;
1054 };
1055 
1056 
1057 
1058 //
1059 void SgVlbiSession::parseVexFile(const QString& vexFileName, QString& sPiName, QString& sExpDescr)
1060 {
1061  QFile f(vexFileName);
1062  QString str;
1063  bool foundPiName, foundExpDescr;
1064 // QRegExp reExpDescr("^\\s*exper_description\\s*=\\s*(\\S+\\s*)+;$");
1065  QRegExp reExpDescr("^\\s*exper_description\\s*=\\s*\"?(\\S+.*\\S+)\"?;$");
1066  QRegExp rePiName("^\\s*PI_name\\s*=\\s*(\\S+);");
1067 
1068 
1069  foundPiName = foundExpDescr = false;
1070  if (f.open(QFile::ReadOnly))
1071  {
1072  QTextStream s(&f);
1073  //
1074  while (!s.atEnd() && !(foundPiName && foundExpDescr))
1075  {
1076  str = s.readLine();
1077  if (str.contains(reExpDescr))
1078  {
1079  sExpDescr = reExpDescr.cap(1);
1080  if (sExpDescr.at(0) == '\"')
1081  sExpDescr.remove(0,1);
1082  if (sExpDescr.at(sExpDescr.size()-1) == '\"')
1083  sExpDescr.chop(1);
1084  foundExpDescr = true;
1085  }
1086  else if (str.contains(rePiName))
1087  {
1088  sPiName = rePiName.cap(1);
1089  foundPiName = true;
1090  };
1091  };
1092  if (!foundPiName)
1094  "::parseVexFile(): PI Name was not found; the file is " + vexFileName);
1095  if (!foundExpDescr)
1097  "::parseVexFile(): Experiment Description was not found; the file is " + vexFileName);
1098 
1099  f.close();
1100  s.setDevice(NULL);
1101  }
1102  else
1104  "::parseVexFile(): cannot open a file " + vexFileName + " for reading");
1105 };
1106 
1107 
1108 
1109 //
1110 void SgVlbiSession::processVexFile(const QString& vexFileName, QMap<QString, StationInfo> &stationByName,
1111  VexInfo& vi, const QMap<QString, QString>& stn2stn, QString& correlatorName)
1112 {
1113  bool have2clearEnv;
1114  QString path2textFiles(PATH_2_HOPS_SHARE);
1115 
1116  have2clearEnv = false;
1117  if (!getenv("TEXT"))
1118  {
1119  path2textFiles += QString("/text");
1120  setenv("TEXT", qPrintable(path2textFiles), 0);
1121  have2clearEnv = true;
1123  "::processVexFile(): the env.variable TEXT was set to " + path2textFiles);
1124  };
1125  //
1126  //
1127  int rc=0;
1128  char vexkey[2]={0,0};
1129  char *filename;
1130  vex vexRoot;
1131  scan_struct *scan=NULL;
1132  evex_struct *evex=NULL;
1133  *vexRoot.filename = 0;
1134 
1135  filename = new char[vexFileName.size() + 1];
1136  strcpy(filename, qPrintable(vexFileName));
1137 
1138  if ((rc=get_vex(filename, OVEX | EVEX | IVEX | LVEX, vexkey, &vexRoot)) != 0)
1139  {
1141  "::processVexFile(): cannot get_vex the file " + vexFileName + "; RC=" + QString("").setNum(rc));
1142  }
1143  else if (!(scan=vexRoot.ovex))
1144  {
1146  "::processVexFile(): the ovex struct is NULL");
1147  }
1148  else if (!(evex=vexRoot.evex))
1149  {
1151  "::processVexFile(): the evex struct is NULL");
1152  }
1153  else
1154  {
1155  QString sScanName("");
1156  QString sSrcName("");
1157  int numStns;
1158 
1159  vi.expName_ = scan->exper_name;
1160  vi.apLength_ = evex->ap_length;
1161 
1162  stationByName.clear();
1163  // SAMPLRAT
1164  // APLENGTH
1165  // BBC IND
1166  // BIT SAMPL
1167  // LO FREQ
1168  source_struct &src=scan->src;
1169  sScanName = scan->scan_name;
1170  correlatorName = scan->correlator;
1171  sSrcName = src.source_name;
1172  numStns = scan->nst;
1173  for (int i=0; i<numStns; i++)
1174  {
1175  station_struct &stn=scan->st[i];
1176  int maxNumChannels=sizeof(stn.channels)/sizeof(chan_struct);
1177  StationInfo station;
1178  station.name_.sprintf("%-8s", stn.site_name);
1179  // map it:
1180  if (stn2stn.size() && stn2stn.contains(station.name_) && stn2stn.value(station.name_).size()>1)
1181  {
1182  station.name_ = stn2stn.value(station.name_);
1184  "::processVexFile(): the input station name \"" + stn.site_name + "\" has been mapped to \"" +
1185  station.name_ + "\"");
1186  };
1187  station.id_2char_ = stn.site_id;
1188  station.id_1char_ = stn.mk4_site_id;
1189  if (stn.recorder_type != I_UNDEFINED)
1190  station.recorderType_ = stn.recorder_type;
1191  else if (stn.rack_type != I_UNDEFINED)
1192  station.recorderType_ = stn.rack_type;
1193  if (stn.track_format != I_UNDEFINED)
1194  station.trackFormat_ = stn.track_format;
1195  if (stn.bits_sample != I_UNDEFINED)
1196  station.bits_sample_ = stn.bits_sample;
1197  if (stn.samplerate != F_UNDEFINED)
1198  station.sampleRate_ = stn.samplerate;
1199  for (int j=0; j<maxNumChannels; j++)
1200  {
1201  chan_struct &chan=stn.channels[j];
1202  if (chan.sky_frequency > 1.0e3)
1203  {
1204  ChannelInfo channel;
1205  channel.name_ = chan.chan_name;
1206  channel.polarization_ = chan.polarization;
1207  channel.sky_frequency_ = chan.sky_frequency;
1208  channel.net_sideband_ = chan.net_sideband;
1209  channel.bandwidth_ = chan.bandwidth;
1210  channel.band_id_ = chan.band_id;
1211  channel.chan_id_ = chan.chan_id;
1212  channel.bbc_id_ = chan.bbc_id;
1213  channel.pcal_id_ = chan.pcal_id;
1214  channel.if_id_ = chan.if_id;
1215  channel.bbc_no_ = chan.bbc_no;
1216  channel.if_name_ = chan.if_name;
1217  channel.if_total_lo_ = chan.if_total_lo;
1218  channel.if_sideband_ = chan.if_sideband;
1219  station.channelByName_[channel.name_] = channel;
1220  };
1221  };
1222  if (stationByName.contains(station.name_))
1224  "::processVexFile(): got a duplicate record for the station \"" + station.name_ + "\"");
1225  stationByName[station.name_] = station;
1226  };
1227  };
1228  //
1229  // clear stuff:
1230  delete[] filename;
1231  if (have2clearEnv)
1232  unsetenv("TEXT");
1233 };
1234 
1235 
1236 
1237 //
1238 void SgVlbiSession::processFringeFile(const QString& path2file, const QString& fringeFileName,
1239  const QMap<QString, StationInfo>& stnsInfo, const VexInfo& vexInfo, const QString& vexFileName,
1240  const QMap<QString, QString>& stnNameById, const QMap<QString, QString>& stnNameByI,
1241  const QMap<QString, QString>& stn2stn, const QMap<QString, QString>& src2src,
1242  const QMap<QString, QString>& bnd2bnd, const QMap<QString, int>& fringeErrorCodeByInt,
1243  int& expSerialNumber)
1244 {
1245  int rc=0;
1246  char *filename;
1247  mk4_fringe fringe;
1248  QString str("");
1249  QString bandKey("");
1250  QRegExp reBandName("^(\\S*)([0-9a-zA-Z]{2})\\.([a-zA-Z]{1})\\."
1251  "\\d+\\.([0-9a-zA-Z]{5,7})$");
1252  //
1253  fringe.nalloc = 0;
1254  str = path2file + "/" + fringeFileName;
1255  filename = new char[str.size() + 1];
1256  strcpy(filename, qPrintable(str));
1257  //
1258  if (fringeFileName.contains(reBandName))
1259  {
1260  bandKey = reBandName.cap(3);
1261  };
1262  //
1263  // check map of bands:
1264  if (bnd2bnd.size())
1265  {
1266  if (!check4NameMap(bnd2bnd, bandKey))
1267  {
1269  "::processFringeFile(): skipping the observation " + fringeFileName +
1270  ": the band \"" + bandKey + "\" have to be skipped");
1271  clear_mk4fringe(&fringe);
1272  delete[] filename;
1273  return;
1274  };
1275  };
1276  //
1277  if ((rc=read_mk4fringe(filename, &fringe)) != 0)
1278  {
1280  "::processFringeFile(): cannot read_mk4fringe the file " + str +
1281  "; RC=" + QString("").setNum(rc));
1282  }
1283  else if (!bandKey.size())
1284  {
1286  "::processFringeFile(): cannot figure out a name of band from the file name " + str);
1287  }
1288  else
1289  {
1290  type_200 *t200=fringe.t200;
1291  type_201 *t201=fringe.t201;
1292  type_202 *t202=fringe.t202;
1293  type_203 *t203=fringe.t203;
1294  type_204 *t204=fringe.t204;
1295  type_205 *t205=fringe.t205;
1296  type_206 *t206=fringe.t206;
1297  type_207 *t207=fringe.t207;
1298  type_208 *t208=fringe.t208;
1299  type_210 *t210=fringe.t210;
1300  //type_212 *t212=fringe.t212[0];
1301 
1302  if (fringeErrorCodeByInt.size() && t208->errcode != ' ')
1303  {
1304  if (fringeErrorCodeByInt.contains("*") ||
1305  fringeErrorCodeByInt.contains(QString(t208->errcode)))
1306  {
1308  "::processFringeFile(): skipping the observation " + fringeFileName +
1309  ": the fringe error code is \"" + QString(t208->errcode) + "\"");
1310  clear_mk4fringe(&fringe);
1311  delete[] filename;
1312  return;
1313  };
1314  };
1315 
1316 /*
1317 // fringeErrorCodeByInt
1318  if (t208->errcode != ' ')
1319  {
1320  logger->write(SgLogger::INF, SgLogger::IO, className() +
1321  "::processFringeFile(): skipping the observation " + fringeFileName +
1322  ": the fringe error code is \"" + QString(t208->errcode) + "\"");
1323  clear_mk4fringe(&fringe);
1324  delete[] filename;
1325  return;
1326  };
1327 */
1328 
1329  // check is it already imported:
1330  SgVlbiBand *band=NULL;
1331  //
1332  QString station1Name, station2Name, sourceName, baselineName;
1333  QString scanName, scanId, obsKey;
1334  int obsIdx;
1335  int nTmp;
1336  double f;
1337  SgMJD epoch;
1338  SgVlbiStationInfo *station1Info, *station2Info;
1339  SgVlbiStationInfo *bandStation1Info, *bandStation2Info;
1340  SgVlbiSourceInfo *sourceInfo, *bandSourceInfo;
1341  SgVlbiBaselineInfo *baselineInfo, *bandBaselineInfo;
1342  SgVlbiObservation *obs=NULL;
1343  SgVlbiObservable *o=NULL;
1344  SgVlbiAuxObservation *auxObs_1=NULL, *auxObs_2=NULL;
1345 
1346  double refFreq=0.0;
1347  bool isSbdSigmaNan, isSbdSigmaInf;
1348  bool isGrdSigmaNan, isGrdSigmaInf;
1349  bool isPhrSigmaNan, isPhrSigmaInf;
1350  bool isTmp;
1351  char buff1[32], buff2[32];
1352  int numOfChannels;
1353  double effFreq4GR=0.0, effFreq4PH=0.0, effFreq4RT=0.0;
1354 
1355 
1356  if (bandByKey_.contains(bandKey))
1357  band = bandByKey_.value(bandKey);
1358  else
1359  {
1360  band = new SgVlbiBand;
1361  band->setKey(bandKey);
1362  bands_.append(band);
1363  bandByKey_.insert(bandKey, band);
1364  };
1365  //
1366  epoch.setUpEpoch(t200->frt.year, 0, t200->frt.day, // Fringe Reference Time
1367  t200->frt.hour, t200->frt.minute, t200->frt.second);
1368 
1369  // stations and source names:
1370  // the t202's char fields are not null-terminated strings, just arrays
1371  memset(buff1, 0, 32);
1372  memset(buff2, 0, 32);
1373  strncpy(buff1, t202->ref_name, 8);
1374  strncpy(buff2, t202->rem_name, 8);
1375  station1Name.sprintf("%-8s", buff1);
1376  station2Name.sprintf("%-8s", buff2);
1377  sourceName .sprintf("%-8s", t201->source);
1378  //
1379  // map the names:
1380  if (stn2stn.size())
1381  {
1382  if (!check4NameMap(stn2stn, station1Name))
1383  {
1385  "::processFringeFile(): skipping the observation " + fringeFileName +
1386  ": the station \"" + station1Name + "\" have to be skipped");
1387  clear_mk4fringe(&fringe);
1388  delete[] filename;
1389  return;
1390  };
1391  if (!check4NameMap(stn2stn, station2Name))
1392  {
1394  "::processFringeFile(): skipping the observation " + fringeFileName +
1395  ": the station \"" + station2Name + "\" have to be skipped");
1396  clear_mk4fringe(&fringe);
1397  delete[] filename;
1398  return;
1399  };
1400  };
1401  if (src2src.size())
1402  {
1403  if (!check4NameMap(src2src, sourceName))
1404  {
1406  "::processFringeFile(): skipping the observation " + fringeFileName +
1407  ": the source \"" + sourceName + "\" have to be skipped");
1408  clear_mk4fringe(&fringe);
1409  delete[] filename;
1410  return;
1411  };
1412  };
1413  //
1414  //
1415  // verify stations names and ids:
1416  // one-char id:
1417  str = QString(t202->baseline[0]);
1418  if (!stnNameByI.contains(str))
1419  {
1421  "::processFringeFile(): cannot find a station for ref one-char id '" + str + "'");
1422  clear_mk4fringe(&fringe);
1423  delete[] filename;
1424  return;
1425  }
1426  else if (stnNameByI.value(str) != station1Name)
1427  {
1429  "::processFringeFile(): the file '" + filename + "' contains wrong station identities: " +
1430  station1Name + " instead of " + stnNameByI.value(str) + " with CId='" + str + "'");
1431  clear_mk4fringe(&fringe);
1432  delete[] filename;
1433  return;
1434  };
1435  str = QString(t202->baseline[1]);
1436  if (!stnNameByI.contains(str))
1437  {
1439  "::processFringeFile(): cannot find a station for rem one-char id '" + str + "'");
1440  clear_mk4fringe(&fringe);
1441  delete[] filename;
1442  return;
1443  }
1444  else if (stnNameByI.value(str) != station2Name)
1445  {
1447  "::processFringeFile(): the file '" + filename + "' contains wrong station identities: " +
1448  station2Name + " instead of " + stnNameByI.value(str) + " with CId='" + str + "'");
1449  clear_mk4fringe(&fringe);
1450  delete[] filename;
1451  return;
1452  };
1453  // two-chars id:
1454  str = QString(t202->ref_intl_id[0]);
1455  str += QString(t202->ref_intl_id[1]);
1456  if (!stnNameById.contains(str))
1457  {
1459  "::processFringeFile(): cannot find a station for two-char id '" + str + "'");
1460  clear_mk4fringe(&fringe);
1461  delete[] filename;
1462  return;
1463  }
1464  else if (stnNameById.value(str) != station1Name)
1465  {
1467  "::processFringeFile(): the file '" + filename + "' contains wrong station identities: " +
1468  station1Name + " instead of " + stnNameById.value(str) + " with SId='" + str + "'");
1469  clear_mk4fringe(&fringe);
1470  delete[] filename;
1471  return;
1472  };
1473  str = QString(t202->rem_intl_id[0]);
1474  str += QString(t202->rem_intl_id[1]);
1475  if (!stnNameById.contains(str))
1476  {
1478  "::processFringeFile(): cannot find a station for two-char id '" + str + "'");
1479  clear_mk4fringe(&fringe);
1480  delete[] filename;
1481  return;
1482  }
1483  else if (stnNameById.value(str) != station2Name)
1484  {
1486  "::processFringeFile(): the file '" + filename + "' contains wrong station identities: " +
1487  station2Name + " instead of " + stnNameById.value(str) + " with SId='" + str + "'");
1488  clear_mk4fringe(&fringe);
1489  delete[] filename;
1490  return;
1491  };
1492  // ok here
1493  //
1494  baselineName = station1Name + ":" + station2Name;
1495  // scanId and scanName:
1496  scanId = epoch.toString(SgMJD::F_INTERNAL) + "@" + sourceName;
1497  if (t200->scan_name)
1498  scanName.sprintf("%-10s", t200->scan_name);
1499  else
1500  scanName.sprintf("%03d-%02d:%02d:%04.1f@%s",
1501  epoch.calcDayOfYear(), epoch.calcHour(), epoch.calcMin(), epoch.calcSec(),
1502  qPrintable(sourceName));
1503 
1504  // pick up or create an observation:
1505  obsKey.sprintf("%s",
1506  qPrintable(epoch.toString(SgMJD::F_INTERNAL) + "-" + baselineName + "@" + sourceName));
1507  if (observationByKey_.contains(obsKey))
1508  obs = observationByKey_.value(obsKey);
1509  else
1510  {
1511  obs = new SgVlbiObservation(this);
1512  obs->setMJD(epoch);
1513  obs->setScanName(scanName);
1514  obs->setScanId(scanId);
1515  obs->setCorrRootFileName(vexFileName);
1516  obs->setKey(obsKey);
1517  obs->setMediaIdx(observations_.size());
1518  observations_.append(obs);
1519  observationByKey_.insert(obsKey, obs);
1520  };
1521  o = new SgVlbiObservable(obs, band);
1522  obsIdx = obs->getMediaIdx();
1523  o->setMediaIdx(obsIdx);
1524  if (!obs->addObservable(bandKey, o))
1525  {
1527  "::processFringeFile(): failed to add the observable at the baseline <" +
1528  station1Name + ":" + station2Name + "> observing " + sourceName + " source at " +
1529  epoch.toString(SgMJD::F_YYYYMMDDHHMMSSSS) + " on the " + bandKey + "-band");
1530  };
1531  obs->setupActiveObservable(bandKey);
1532  // determine number of channels:
1533  numOfChannels = 0;
1534  nTmp = 16; // ver "00" has dimension of 16
1535  if (t205->version_no[0] == '0' && t205->version_no[1] == '0')
1536  {}
1537  else if (t205->version_no[0] == '0' && t205->version_no[1] == '1')
1538  nTmp = 64;
1539  else
1541  "::processFringeFile(): unknown version of the type_205 struct: " +
1542  path2file + "/" + fringeFileName);
1543  for (int i=0; i<nTmp; i++)
1544  if (t205->ffit_chan[i].channels[0]>-1 ||
1545  t205->ffit_chan[i].channels[1]>-1 )
1546  numOfChannels++;
1547  o->allocateChannelsSetupStorages(numOfChannels);
1548  expSerialNumber = t200->expt_no;
1549  //
1550  //
1551  // station #1:
1552  if (stationsByName_.contains(station1Name))
1553  station1Info = stationsByName_.value(station1Name);
1554  else // new station, add it to the container and register its index:
1555  {
1556  station1Info = new SgVlbiStationInfo(stationsByName_.size(), station1Name);
1557  stationsByName_.insert(station1Info->getKey(), station1Info);
1558  stationsByIdx_.insert(station1Info->getIdx(), station1Info);
1559  station1Info->setCid(t202->baseline[0]);
1560  station1Info->setSid(t202->ref_intl_id[0], t202->ref_intl_id[1]);
1561  };
1562  // station #2:
1563  if (stationsByName_.contains(station2Name))
1564  station2Info = stationsByName_.value(station2Name);
1565  else // new station, add it to the container and register its index:
1566  {
1567  station2Info = new SgVlbiStationInfo(stationsByName_.size(), station2Name);
1568  stationsByName_.insert(station2Info->getKey(), station2Info);
1569  stationsByIdx_.insert(station2Info->getIdx(), station2Info);
1570  station2Info->setCid(t202->baseline[1]);
1571  station2Info->setSid(t202->rem_intl_id[0], t202->rem_intl_id[1]);
1572  };
1573  // source:
1574  if (sourcesByName_.contains(sourceName))
1575  sourceInfo = sourcesByName_.value(sourceName);
1576  else // new source, add it to the container and register its index:
1577  {
1578  sourceInfo = new SgVlbiSourceInfo(sourcesByName_.size(), sourceName);
1579  sourcesByName_.insert(sourceInfo->getKey(), sourceInfo);
1580  sourcesByIdx_.insert(sourceInfo->getIdx(), sourceInfo);
1581  };
1582  // baseline:
1583  if (baselinesByName_.contains(baselineName))
1584  baselineInfo = baselinesByName_.value(baselineName);
1585  else // new baseline, add it to the container and register its index:
1586  {
1587  baselineInfo = new SgVlbiBaselineInfo(baselinesByName_.size(), baselineName);
1588  baselinesByName_.insert(baselineInfo->getKey(), baselineInfo);
1589  baselinesByIdx_.insert(baselineInfo->getIdx(), baselineInfo);
1590  };
1591  // 4band:
1592  // band's station #1:
1593  if (band->stationsByName().contains(station1Name))
1594  bandStation1Info = band->stationsByName().value(station1Name);
1595  else // new station, add it to the container:
1596  {
1597  bandStation1Info = new SgVlbiStationInfo(station1Info->getIdx(), station1Name);
1598  band->stationsByName().insert(bandStation1Info->getKey(), bandStation1Info);
1599  band->stationsByIdx().insert(bandStation1Info->getIdx(), bandStation1Info);
1600  };
1601  // band's station #2:
1602  if (band->stationsByName().contains(station2Name))
1603  bandStation2Info = band->stationsByName().value(station2Name);
1604  else // new station, add it to the container:
1605  {
1606  bandStation2Info = new SgVlbiStationInfo(station2Info->getIdx(), station2Name);
1607  band->stationsByName().insert(bandStation2Info->getKey(), bandStation2Info);
1608  band->stationsByIdx().insert(bandStation2Info->getIdx(), bandStation2Info);
1609  };
1610  // band's source:
1611  if (band->sourcesByName().contains(sourceName))
1612  bandSourceInfo = band->sourcesByName().value(sourceName);
1613  else // new source, add it to the container:
1614  {
1615  bandSourceInfo = new SgVlbiSourceInfo(sourceInfo->getIdx(), sourceName);
1616  band->sourcesByName().insert(bandSourceInfo->getKey(), bandSourceInfo);
1617  band->sourcesByIdx().insert(bandSourceInfo->getIdx(), bandSourceInfo);
1618  };
1619  // band's baselines:
1620  if (band->baselinesByName().contains(baselineName))
1621  bandBaselineInfo = band->baselinesByName().value(baselineName);
1622  else // new baseline, add it to the container and register its index:
1623  {
1624  bandBaselineInfo = new SgVlbiBaselineInfo(baselineInfo->getIdx(), baselineName);
1625  band->baselinesByName().insert(bandBaselineInfo->getKey(), bandBaselineInfo);
1626  band->baselinesByIdx().insert(bandBaselineInfo->getIdx(), bandBaselineInfo);
1627  };
1628  //
1629  obs->setStation1Idx(station1Info->getIdx());
1630  obs->setStation2Idx(station2Info->getIdx());
1631  obs->setSourceIdx(sourceInfo->getIdx());
1632  obs->setBaselineIdx(baselineInfo->getIdx());
1633  obs->setApLength(vexInfo.apLength_);
1634  //
1635  // plus additional info:
1636  o->setFourfitOutputFName(fringeFileName);
1637  //
1638  // collect observables:
1639  // single band delay:
1640 
1641  o->sbDelay().setValue(1.0e-6*t208->tot_sbd_ref);
1642  // group delay:
1643  o->grDelay().setValue(1.0e-6*t208->tot_mbd_ref);
1644  // delay rate:
1645  o->phDRate().setValue(1.0e-6*t208->tot_rate_ref);
1646  //
1647  // workaround the DBH "feature":
1648  isSbdSigmaNan = isSbdSigmaInf = isGrdSigmaNan = isGrdSigmaInf = isPhrSigmaNan = isPhrSigmaInf
1649  = false;
1650  // single band delay sigma (in microsec):
1651  f = t208->sbd_error;
1652  if (isinf(f) != 0)
1653  {
1655  "::processFringeFile(): the observation #" + QString("").setNum(obsIdx) +
1656  " at the baseline <" + baselineName + "> observing " + sourceName + " source at " +
1658  " contains wrong sigma (inf) for the single band delay", true);
1659  isSbdSigmaInf = true;
1660  f = 1.0;
1661  };
1662  if (isnan(f) != 0)
1663  {
1665  "::processFringeFile(): the observation #" + QString("").setNum(obsIdx) +
1666  " at the baseline <" + baselineName + "> observing " + sourceName + " source at " +
1668  " contains wrong sigma (nan) for the single band delay", true);
1669  isSbdSigmaNan = true;
1670  f = 1.0;
1671  };
1672  o->sbDelay().setSigma(1.0e-6*f);
1673  //
1674  // group delay sigma (in seconds):
1675  f = t208->mbd_error;
1676  if (isinf(f) != 0)
1677  {
1679  "::processFringeFile(): the observation #" + QString("").setNum(obsIdx) +
1680  " at the baseline <" + baselineName + "> observing " + sourceName + " source at " +
1682  " contains wrong sigma (inf) for the group delay", true);
1683  isGrdSigmaInf = true;
1684  f = 1.0e-6;
1685  };
1686  if (isnan(f) != 0)
1687  {
1689  "::processFringeFile(): the observation #" + QString("").setNum(obsIdx) +
1690  " at the baseline <" + baselineName + "> observing " + sourceName + " source at " +
1692  " contains wrong sigma (nan) for the group delay", true);
1693  isGrdSigmaNan = true;
1694  f = 1.0e-6;
1695  };
1696  o->grDelay().setSigma(1.0e-6*f);
1697  //
1698  // delay rate sigma:
1699  f = t208->rate_error;
1700  if (isinf(f) != 0)
1701  {
1703  "::processFringeFile(): the observation #" + QString("").setNum(obsIdx) +
1704  " at the baseline <" + baselineName + "> observing " + sourceName + " source at " +
1706  " contains wrong sigma (inf) for the group delay", true);
1707  isPhrSigmaInf = true;
1708  f = 1.0e-6;
1709  };
1710  if (isnan(f) != 0)
1711  {
1713  "::processFringeFile(): the observation #" + QString("").setNum(obsIdx) +
1714  " at the baseline <" + baselineName + "> observing " + sourceName + " source at " +
1716  " contains wrong sigma (nan) for the group delay", true);
1717  isPhrSigmaNan = true;
1718  f = 1.0e-6;
1719  };
1720  o->phDRate().setSigma(1.0e-6*f);
1721  // complain:
1722  if (isSbdSigmaNan || isSbdSigmaInf ||
1723  isGrdSigmaNan || isGrdSigmaInf ||
1724  isPhrSigmaNan || isPhrSigmaInf )
1725  {
1726  QString s1(""), s2(""), s3("");
1727  s1 = (isSbdSigmaNan || isGrdSigmaNan || isPhrSigmaNan)?"(nan)":"(inf)";
1728  if (isSbdSigmaNan || isSbdSigmaInf)
1729  s2 = "single band delay, ";
1730  if (isGrdSigmaNan || isGrdSigmaInf)
1731  s2+= "group delay, ";
1732  if (isPhrSigmaNan || isPhrSigmaInf)
1733  s2+= "delay rate, ";
1734  s2 = s2.left(s2.size() - 2);
1735  if (o->getFourfitOutputFName().size())
1736  s3 = obs->getScanName().trimmed() + "/" + o->getFourfitOutputFName();
1737 
1739  "::processFringeFile(): The observation #" + QString("").setNum(obsIdx) +
1740  ", " + s3 + " contains wrong sigma " + s1 + " for " + s2 + ".");
1741  };
1742  //
1743  // single band:
1744  o->sbDelay().setResidualFringeFitting(1.0e-6*t208->resid_sbd); // sec
1745  // group delay:
1746  o->grDelay().setResidualFringeFitting(1.0e-6*t208->resid_mbd); // sec
1747  // delay rate:
1748  o->phDRate().setResidualFringeFitting(1.0e-6*t208->resid_rate); // sec per sec
1749  //
1750  //
1751  o->grDelay().setAmbiguitySpacing(1.0e-6*t208->ambiguity); // usec->sec
1752  str = t208->quality;
1753  nTmp = str.toInt(&isTmp);
1754  o->setQualityFactor(isTmp ? nTmp : 0);
1755  o->setErrorCode(QString(t208->errcode));
1756  //
1757  memset(buff1, 0, 32);
1758  strncpy(buff1, t208->tape_qcode, sizeof(t208->tape_qcode)<32?sizeof(t208->tape_qcode):31);
1759  o->setTapeQualityCode(buff1);
1760  //
1761  o->setReferenceFrequency((refFreq=t205->ref_freq));
1762  o->setCorrCoeff(t208->amplitude);
1763  o->setTotalPhase(t208->totphase_ref*DEG2RAD); // in radians
1764  o->setIncohChanAddAmp(t208->inc_chan_ampl);
1765  o->setIncohSegmAddAmp(t208->inc_seg_ampl);
1766  o->setSnr(t208->snr);
1767  o->setProbabOfFalseDetection(t208->prob_false);
1768  o->setGeocenterTotalPhase(t208->totphase*DEG2RAD); // in radians
1769  o->setGeocenterResidPhase(t208->resphase*DEG2RAD); // in radians
1770  o->setAprioriDra(0, 1.0e-6*t208->adelay);
1771  o->setAprioriDra(1, 1.0e-6*t208->arate);
1772  o->setAprioriDra(2, 1.0e-6*t208->aaccel);
1773  // single band:
1774  o->sbDelay().setGeocenterValue(1.0e-6*t208->tot_sbd); // sec
1775  // group delay:
1776  o->grDelay().setGeocenterValue(1.0e-6*t208->tot_mbd); // sec
1777  // delay rate:
1778  o->phDRate().setGeocenterValue(1.0e-6*t208->tot_rate);// sec per sec
1779  //
1780  // VGOS contribution:
1781  str = QString(t208->version_no[0]);
1782  str += QString(t208->version_no[1]);
1783  nTmp = str.toInt(&isTmp);
1784  if (isTmp)
1785  {
1786  if (nTmp > 0)
1787  {
1788  obs->setDTec (t201->dispersion);
1789  obs->setDTecStdDev(t208->tec_error);
1790  };
1791  }
1792  else
1794  "::processFringeFile(): cannot convert version number [" + str +
1795  "] to integer type: " + o->strId());
1796  //
1797  //
1798  // alloc auxiliary data:
1799  if (!station1Info->auxObservationByScanId()->contains(scanId)) // new scan, insert data:
1800  {
1801  auxObs_1 = new SgVlbiAuxObservation;
1802  auxObs_1->setMJD(epoch);
1803  auxObs_1->setAzimuthAngle (t202->ref_az *DEG2RAD);
1804  auxObs_1->setElevationAngle (t202->ref_elev *DEG2RAD);
1805  auxObs_1->setEstZenithDelay (t202->ref_zdelay*1.0e-6); // musec -> sec
1806  auxObs_1->setTapeId(QString("").sprintf("%.8s", t202->ref_tape));
1807  station1Info->auxObservationByScanId()->insert(scanId, auxObs_1);
1808  }
1809  else
1810  auxObs_1 = station1Info->auxObservationByScanId()->value(scanId);
1811  if (!station2Info->auxObservationByScanId()->contains(scanId)) // new scan, insert data:
1812  {
1813  auxObs_2 = new SgVlbiAuxObservation;
1814  auxObs_2->setMJD(epoch);
1815  auxObs_2->setAzimuthAngle (t202->rem_az *DEG2RAD);
1816  auxObs_2->setElevationAngle (t202->rem_elev *DEG2RAD);
1817  auxObs_2->setEstZenithDelay (t202->rem_zdelay*1.0e-6); // musec -> sec
1818  auxObs_2->setTapeId(QString("").sprintf("%.8s", t202->rem_tape));
1819  station2Info->auxObservationByScanId()->insert(scanId, auxObs_2);
1820  }
1821  else
1822  auxObs_2 = station2Info->auxObservationByScanId()->value(scanId);
1823  //
1824  // aux data:
1825  o->setStartOffset(t200->start_offset);
1826  o->setStopOffset (t200->stop_offset);
1827  o->setCentrOffset(t205->offset);
1828  o->setEffIntegrationTime(t206->intg_time);
1829  o->setAcceptedRatio(t206->accept_ratio);
1830  o->setDiscardRatio(t206->discard);
1831 
1832  o->setCorrelStarElev_1(t202->ref_elev *DEG2RAD);
1833  o->setCorrelStarElev_2(t202->rem_elev *DEG2RAD);
1834  o->setCorrelZdelay_1 (t202->ref_zdelay*1.0e-6); // musec -> sec
1835  o->setCorrelZdelay_2 (t202->rem_zdelay*1.0e-6); // musec -> sec
1836 
1837  // set up epochs of events:
1838  // correlation:
1839  epoch.setUpEpoch( t200->corr_date.year, 0,
1840  t200->corr_date.day,
1841  t200->corr_date.hour,
1842  t200->corr_date.minute,
1843  t200->corr_date.second);
1844  o->setEpochOfCorrelation(epoch);
1845  // fringing:
1846  epoch.setUpEpoch( t200->fourfit_date.year, 0,
1847  t200->fourfit_date.day,
1848  t200->fourfit_date.hour,
1849  t200->fourfit_date.minute,
1850  t200->fourfit_date.second);
1851  o->setEpochOfFourfitting(epoch);
1852  // nominal scan time:
1853  epoch.setUpEpoch( t200->scantime.year, 0,
1854  t200->scantime.day,
1855  t200->scantime.hour,
1856  t200->scantime.minute,
1857  t200->scantime.second);
1858  o->setEpochOfScan(epoch);
1859  //
1860  // "central" scan epoch:
1861  epoch.setUpEpoch( t205->utc_central.year, 0,
1862  t205->utc_central.day,
1863  t205->utc_central.hour,
1864  t205->utc_central.minute,
1865  t205->utc_central.second);
1866  o->setEpochCentral(epoch);
1867  // and another couple of epochs:
1868  // "start":
1869  epoch.setUpEpoch( t205->start.year, 0,
1870  t205->start.day,
1871  t205->start.hour,
1872  t205->start.minute,
1873  t205->start.second);
1874  o->setTstart(epoch);
1875  // "stop":
1876  epoch.setUpEpoch( t205->stop.year, 0,
1877  t205->stop.day,
1878  t205->stop.hour,
1879  t205->stop.minute,
1880  t205->stop.second);
1881  o->setTstop(epoch);
1882  //
1883  // sample rate (mimic read_mk4.f):
1884  bool hasStn_1Info=false, hasStn_2Info=false;
1885  StationInfo si_1, si_2;
1886  if (stnsInfo.contains(station1Name))
1887  {
1888  si_1 = stnsInfo[station1Name];
1889  hasStn_1Info = true;
1890  }
1891  else
1893  "::processFringeFile(): the station#1, " + station1Name + ", was not found in the VEX file");
1894  if (stnsInfo.contains(station2Name))
1895  {
1896  si_2 = stnsInfo[station2Name];
1897  hasStn_2Info = true;
1898  }
1899  else
1901  "::processFringeFile(): the station#2, " + station2Name + ", was not found in the VEX file");
1902  if (hasStn_1Info && hasStn_2Info && si_1.sampleRate_ != si_2.sampleRate_)
1903  {
1905  "::processFringeFile(): stations sample rates mismatch: " +
1906  QString("").sprintf("%g vs %g.", si_1.sampleRate_, si_2.sampleRate_) + ": " + o->strId());
1907  };
1908  f = t203->channels[0].sample_rate*1.0e3;
1909  if (hasStn_1Info && fabs(si_1.sampleRate_ - f)>0.0 && si_1.sampleRate_>0.0)
1910  {
1911  if (t204->ff_version[0] <= 3)
1912  f = si_1.sampleRate_;
1913  else
1915  "::processFringeFile(): OVEX and Fringe sample rates mismatch: " +
1916  QString("").sprintf("%g vs %g.", si_1.sampleRate_, f) + ": " + o->strId());
1917  };
1918  o->setSampleRate(f);
1919  //
1920  if (hasStn_1Info && hasStn_2Info && si_1.bits_sample_ != si_2.bits_sample_)
1922  "::processFringeFile(): stations bits per sample mismatch: " +
1923  QString("").sprintf("%d vs %d", si_1.bits_sample_, si_2.bits_sample_) + ": " + o->strId());
1924  if (hasStn_1Info)
1925  o->setBitsPerSample(si_1.bits_sample_);
1926  //
1927  // collect data necessary to evaluate the effective frequencies (for ionospheric correction):
1928  isTmp = ( t206->version_no[0]=='0' &&
1929  t206->version_no[1]=='0' ); // this version does not contain weights
1930  for (int i=0; i<numOfChannels; i++)
1931  {
1932  int idx=t205->ffit_chan[i].channels[0];
1933  if (idx==-1)
1934  {
1936  "::processFringeFile(): first channel index is -1, switch to the second one");
1937  idx=t205->ffit_chan[i].channels[1];
1938  };
1939  o->numOfAccPeriodsByChan_USB()->setElement(i, t206->accepted[i].usb);
1940  o->numOfAccPeriodsByChan_LSB()->setElement(i, t206->accepted[i].lsb);
1941  o->numOfSamplesByChan_USB()->setElement (i, isTmp?0.0:t206->weights[i].usb);
1942  o->numOfSamplesByChan_LSB()->setElement (i, isTmp?0.0:t206->weights[i].lsb);
1943  o->refFreqByChan()->setElement (i, t203->channels[idx].ref_freq*1.0e-6); // ->MHz
1944  (*o->polarization_1ByChan())[i] = t203->channels[idx].refpol;
1945  (*o->polarization_2ByChan())[i] = t203->channels[idx].rempol;
1946  o->fringeAmplitudeByChan()->setElement (i, t210->amp_phas[i].ampl);
1947  o->fringePhaseByChan()->setElement (i, t210->amp_phas[i].phase*DEG2RAD);
1948  // phase calibration data:
1949  o->phaseCalData_1ByChan()->setElement (0,i, t207->ref_pcamp [i].usb*1.0e4);
1950  o->phaseCalData_2ByChan()->setElement (0,i, t207->rem_pcamp [i].usb*1.0e4);
1951  o->phaseCalData_1ByChan()->setElement (1,i, t207->ref_pcphase [i].usb*DEG2RAD);
1952  o->phaseCalData_2ByChan()->setElement (1,i, t207->rem_pcphase [i].usb*DEG2RAD);
1953  o->phaseCalData_1ByChan()->setElement (2,i, t207->ref_pcfreq [i].usb*1.0e-3);
1954  o->phaseCalData_2ByChan()->setElement (2,i, t207->rem_pcfreq [i].usb*1.0e-3);
1955  o->phaseCalData_1ByChan()->setElement (3,i, t207->ref_pcoffset[i].usb*DEG2RAD);
1956  o->phaseCalData_2ByChan()->setElement (3,i, t207->rem_pcoffset[i].usb*DEG2RAD);
1957  o->phaseCalData_1ByChan()->setElement (4,i, t207->ref_errate [i]);
1958  o->phaseCalData_2ByChan()->setElement (4,i, t207->rem_errate [i]);
1959  // check and rescale phase cal data
1960  // compare usb and lsb pcal's:
1961  // amps:
1962  if (fabs(t207->ref_pcamp[i].usb - t207->ref_pcamp[i].lsb) > 1.0e-8)
1964  "::processFringeFile(): reference station, sidebands have different phase cal amplitudes: " +
1965  QString("").sprintf("%g vs %g, diff=%g", t207->ref_pcamp[i].usb, t207->ref_pcamp[i].lsb,
1966  fabs(t207->ref_pcamp[i].usb - t207->ref_pcamp[i].lsb)));
1967  if (fabs(t207->rem_pcamp[i].usb - t207->rem_pcamp[i].lsb) > 1.0e-8)
1969  "::processFringeFile(): remote station, sidebands have different phase cal amplitudes: " +
1970  QString("").sprintf("%g vs %g, diff=%g", t207->rem_pcamp[i].usb, t207->rem_pcamp[i].lsb,
1971  fabs(t207->rem_pcamp[i].usb - t207->rem_pcamp[i].lsb)));
1972  // phases:
1973  if (fabs(t207->ref_pcphase[i].usb - t207->ref_pcphase[i].lsb) > 1.0e-8)
1975  "::processFringeFile(): reference station, sidebands have different phase cal phases: " +
1976  QString("").sprintf("%g vs %g, diff=%g", t207->ref_pcphase[i].usb, t207->ref_pcphase[i].lsb,
1977  fabs(t207->ref_pcphase[i].usb - t207->ref_pcphase[i].lsb)));
1978  if (fabs(t207->rem_pcphase[i].usb - t207->rem_pcphase[i].lsb) > 1.0e-8)
1980  "::processFringeFile(): remote station, sidebands have different phase cal phases: " +
1981  QString("").sprintf("%g vs %g, diff=%g", t207->rem_pcphase[i].usb, t207->rem_pcphase[i].lsb,
1982  fabs(t207->rem_pcphase[i].usb - t207->rem_pcphase[i].lsb)));
1983  if (t207->ref_errate[i] != 0.0)
1985  "::processFringeFile(): reference station has a non-zero pcal error rate: " +
1986  QString("").sprintf("%g", t207->ref_errate[i]));
1987  if (t207->rem_errate[i] != 0.0)
1989  "::processFringeFile(): remote station has a non-zero pcal error rate: " +
1990  QString("").sprintf("%g", t207->ref_errate[i]));
1991  //
1992  // ok, continue:
1993  (*o->chanIdByChan()) [i] = t205->ffit_chan[i].ffit_chan_id;
1994  (*o->corelIndexNumUSB())[i] = t205->ffit_chan[i].channels[0]>-1 ?
1995  t203->channels[t205->ffit_chan[i].channels[0]].index:-1;
1996  (*o->corelIndexNumLSB())[i] = t205->ffit_chan[i].channels[1]>-1 ?
1997  t203->channels[t205->ffit_chan[i].channels[1]].index:-1;
1998  //
1999  // station #1:
2000  str = t203->channels[idx].ref_chan_id;
2001  if (hasStn_1Info)
2002  {
2003  if (si_1.channelByName_.contains(str))
2004  {
2005  const ChannelInfo &ci=si_1.channelByName_.value(str);
2006  o->loFreqByChan_1()->setElement(i, ci.if_total_lo_);
2007  (*o->bbcIdxByChan_1())[i] = ci.bbc_no_;
2008  }
2009  else
2010  {
2012  "::processFringeFile(): cannot find channel ID [" + str + "] in the corel root file " +
2013  vexFileName + " for the station " + station1Info->getKey());
2014  };
2015  };
2016  // station #2:
2017  str = t203->channels[idx].rem_chan_id;
2018  if (hasStn_2Info)
2019  {
2020  if (si_2.channelByName_.contains(str))
2021  {
2022  const ChannelInfo &ci=si_2.channelByName_.value(str);
2023  o->loFreqByChan_2()->setElement(i, ci.if_total_lo_);
2024  (*o->bbcIdxByChan_2())[i] = ci.bbc_no_;
2025  }
2026  else
2027  {
2029  "::processFringeFile(): cannot find channel ID [" + str + "] in the corel root file " +
2030  vexFileName + " for the station " + station2Info->getKey());
2031  };
2032  };
2033  //
2034  //
2035  //
2036  };
2037  // check and rescale phase cal data
2038  for (int i=0; i<numOfChannels; i++)
2039  {
2040  for (int j=0; j<5; j++)
2041  {
2042  if (isnan(o->phaseCalData_1ByChan()->getElement (j,i)))
2043  {
2045  "::processFringeFile(): st1 one of phase cal values is NAN " +
2046  QString("").sprintf("(chan=%d:dat=%d)", i, j) + " from the scan " + obs->getScanName() +
2047  " fringefile " + fringeFileName);
2048  o->phaseCalData_1ByChan()->setElement (j,i, -100.0);
2049  };
2050  if (isnan(o->phaseCalData_2ByChan()->getElement (j,i)))
2051  {
2053  "::processFringeFile(): st2 one of phase cal values is NAN " +
2054  QString("").sprintf("(chan=%d:dat=%d)", i, j) + " from the scan " + obs->getScanName() +
2055  " fringefile " + fringeFileName);
2056  o->phaseCalData_2ByChan()->setElement (j,i, -100.0);
2057  };
2058  };
2059  };
2060  //
2062  *o->refFreqByChan(), *o->fringeAmplitudeByChan(),
2064  o->getSampleRate(), refFreq, numOfChannels,
2065  effFreq4GR, effFreq4PH, effFreq4RT, getCorrelatorType(), o->strId());
2066  o->grDelay().setEffFreq(effFreq4GR);
2067  o->phDelay().setEffFreq(effFreq4PH);
2068  o->phDRate().setEffFreq(effFreq4RT);
2069  o->setPhaseCalModes(t207->pcal_mode);
2070  //
2071  //
2072  o->setFourfitVersion(0, t204->ff_version[0]);
2073  o->setFourfitVersion(1, t204->ff_version[1]);
2074  o->setFourfitControlFile(t204->control_file);
2075  o->setFourfitCommandOverride(t204->override);
2076  //
2077  o->setPhaseCalRates(0, t207->ref_pcrate*1.0e-6);
2078  o->setPhaseCalRates(1, t207->rem_pcrate*1.0e-6);
2079  o->setUvFrPerAsec(0, t202->u);
2080  o->setUvFrPerAsec(1, t202->v);
2081  o->setUrVr(0, t202->uf);
2082  o->setUrVr(1, t202->vf);
2083  o->setCorrClocks(0, 0, t202->ref_clock*1.0e-6); // musec -> sec
2084  o->setCorrClocks(0, 1, t202->rem_clock*1.0e-6); // musec -> sec
2085  o->setCorrClocks(1, 0, t202->ref_clockrate);
2086  o->setCorrClocks(1, 1, t202->rem_clockrate);
2087  o->setInstrDelay(0, t202->ref_idelay*1.0e-6); // musec -> sec
2088  o->setInstrDelay(1, t202->rem_idelay*1.0e-6); // musec -> sec
2089  o->setNlags(t202->nlags);
2090  for (int i=0; i<6; i++)
2091  o->setFourfitSearchParameters(i, t205->search[i]);
2092  o->setHopsRevisionNumber(t200->software_rev[0]);
2093  // check the rest of array, if the fields are non-zero, complain:
2094  for (unsigned int i=1; i<sizeof(type_200::software_rev)/sizeof(short); i++)
2095  if (t200->software_rev[i] != 0)
2097  "::processFringeFile(): type200's software revision has more than one meaningful field at " +
2098  "the scan " + obs->getScanName() + " fringefile " + fringeFileName);
2099 
2100  //
2101  // per band statistics:
2102  bandStation1Info->incNumTotal(DT_DELAY);
2103  bandStation2Info->incNumTotal(DT_DELAY);
2104  bandSourceInfo->incNumTotal(DT_DELAY);
2105  bandBaselineInfo->incNumTotal(DT_DELAY);
2106 
2107  bandStation1Info->incNumTotal(DT_RATE);
2108  bandStation2Info->incNumTotal(DT_RATE);
2109  bandSourceInfo->incNumTotal(DT_RATE);
2110  bandBaselineInfo->incNumTotal(DT_RATE);
2111  //
2112  clear_mk4fringe(&fringe);
2113  };
2114  //
2115  // clear stuff:
2116  delete[] filename;
2117 };
2118 
2119 
2120 
2121 //
2122 bool SgVlbiSession::getCorrelatorHistory(const QString& fileName)
2123 {
2124  QString str, strAux;
2125  QFile f(fileName);
2126  if (!bands_.size())
2127  {
2129  "::getCorrelatorHistory(): the session has no any band");
2130  return false;
2131  };
2132  SgVlbiHistory &history=bands_.at(0)->history();
2133  if (!f.exists())
2134  {
2136  "::getCorrelatorHistory(): the history file [" + f.fileName() + "] does not exist");
2137  return false;
2138  }
2139  else
2140  {
2141  if (f.open(QFile::ReadOnly))
2142  {
2143  QTextStream s(&f);
2144  int numOfStrs(0);
2145  QFileInfo fi(f.fileName());
2146  QDateTime d(fi.lastModified());
2147 
2148 //std::cout << " fi.lastModified(): " << qPrintable(fi.lastModified().toString()) << "\n";
2149 //std::cout << " fi.created (): " << qPrintable(fi.created().toString()) << "\n";
2150 
2151  // dealing with Qt's bug: in the current version of Qt QFileInfo::created() returns last modified
2152  // epoch, while QFileInfo::lastModified() reports time of creation (hope, they will fix it later):
2153  if (d < fi.created())
2154  d = fi.created();
2155  d = d.toUTC(); // keep history records in UTC
2156  // check the last modified epoch, sometimes when clocks at comuters are not synchronized,
2157  // it can show time that is ahead of the current time:
2158  QDateTime ct(QDateTime::currentDateTimeUtc());
2159  SgMJD tCreated( d.date().year(), d.date().month(), d.date().day(),
2160  d.time().hour(), d.time().minute(),
2161  d.time().second()+d.time().msec()*0.001);
2162  SgMJD tCurrent( ct.date().year(), ct.date().month(), ct.date().day(),
2163  ct.time().hour(), ct.time().minute(),
2164  ct.time().second()+ct.time().msec()*0.001);
2165  if (tCurrent < tCreated) // the file was created in future:
2166  {
2168  "::getCorrelatorHistory(): the correlator report file has the `last modified time' that "
2169  "is from future, " + tCreated.toString(SgMJD::F_YYYYMMDDHHMMSSSS) + ", the current time is: " +
2170  tCurrent.toString(SgMJD::F_YYYYMMDDHHMMSSSS) + ". The difference is " +
2171  interval2Str(tCreated - tCurrent));
2172  tCreated = tCurrent - 60.0/DAY2SEC;
2174  "::getCorrelatorHistory(): the `last modified time' of the correlator report file "
2175  "has been adjuted to " + tCreated.toString(SgMJD::F_YYYYMMDDHHMMSSSS));
2176  };
2177  while (!s.atEnd())
2178  {
2179  str = s.readLine();
2180  history.append(new SgVlbiHistoryRecord(tCreated, 1, str));
2181  numOfStrs++;
2182  };
2183  f.close();
2184  s.setDevice(NULL);
2186  "::getCorrelatorHistory(): read " + QString("").setNum(numOfStrs) +
2187  " strings from the history file [" + f.fileName() + "]");
2188  }
2189  else
2190  {
2192  "::getCorrelatorHistory(): cannot open the history file [" + f.fileName() + "] for read access");
2193  return false;
2194  };
2195  };
2196  // propagate to other bands:
2197  if (bands_.size() > 1)
2198  {
2199  for (int bIdx=1; bIdx<bands_.size(); bIdx++)
2200  {
2201  SgVlbiHistory &historyDest=bands_.at(bIdx)->history();
2202  for (int i=0; i<history.size(); i++)
2203  historyDest.append(new SgVlbiHistoryRecord(history.at(i)->getEpoch(),
2204  history.at(i)->getVersion(), history.at(i)->getText()));
2206  "::getCorrelatorHistory(): the history records were propagated to the " +
2207  bands_.at(bIdx)->getKey() + "-band");
2208  };
2209  }
2210  return true;
2211 };
2212 
2213 
2214 
2215 
2216 
2217 #endif // !defined HAVE_MK4_DATA_H || !defined HAVE_MK4_DFIO_H || !defined HAVE_MK4_VEX_H
2218 /*=====================================================================================================*/
2219 
2220 
2221 
2222 
2223 /*=====================================================================================================*/
SgLogger * logger
Definition: SgLogger.cpp:231
QString interval2Str(double days)
Definition: SgMJD.cpp:1370
#define DAY2SEC
radians to mas:
Definition: SgMathSupport.h:56
#define DEG2RAD
hours to radians:
Definition: SgMathSupport.h:40
QMap< QString, QString > src2src
QMap< QString, QString > stn2stn
void evaluateEffectiveFreqs(const SgVector &numOfAccPeriodsByChan_USB, const SgVector &numOfAccPeriodsByChan_LSB, const SgVector &refFreqByChan, const SgVector &fringeAmplitudeByChan, const SgVector &numOfSamplesByChan_USB, const SgVector &numOfSamplesByChan_LSB, double sampleRate, double refFreq, int numOfChannels, double &effFreq4GR, double &effFreq4PH, double &effFreq4RT, const QString &correlatorType, const QString &oId, bool useEqualWeights=false)
@ DT_DELAY
Definition: SgWrmsable.h:44
@ DT_RATE
Definition: SgWrmsable.h:45
void addAttr(uint a)
Definition: SgAttribute.h:202
virtual void write(LogLevel, quint32, const QString &, bool=false)
Definition: SgLogger.cpp:88
@ IO_TXT
Definition: SgLogger.h:65
@ IO_DBH
Definition: SgLogger.h:67
Definition: SgMJD.h:59
@ F_YYYYMMDDHHMMSSSS
Long verbose: Fri, the 2nd of Apr, 2010; 17hr 02min 43.6400sec.
Definition: SgMJD.h:67
@ F_INTERNAL
Digits, date and time: 20100402.71.
Definition: SgMJD.h:72
QString toString(Format format=F_Verbose) const
Definition: SgMJD.cpp:1007
int calcHour() const
Definition: SgMJD.h:495
int calcDayOfYear() const
Definition: SgMJD.cpp:237
static SgMJD currentMJD()
Definition: SgMJD.cpp:118
void setUpEpoch(int year, int month, int day, int hour, int min, double sec)
Definition: SgMJD.cpp:254
int calcMin() const
Definition: SgMJD.h:502
double calcSec() const
Definition: SgMJD.h:509
void setElement(unsigned int i, unsigned int j, double d)
Definition: SgMatrix.h:402
double getElement(unsigned int i, unsigned int j) const
Definition: SgMatrix.h:385
void setKey(const QString &key)
Definition: SgObjectInfo.h:447
int getIdx() const
Definition: SgObjectInfo.h:335
void incNumTotal(DataType, int=1)
Definition: SgObjectInfo.h:519
const QString & getKey() const
Definition: SgObjectInfo.h:319
virtual int getMediaIdx() const
virtual void setMediaIdx(int idx)
virtual void setMJD(const SgMJD &)
void setElement(unsigned int i, double d)
Definition: SgVector.h:348
void setAzimuthAngle(double angle)
void setEstZenithDelay(double d)
void setElevationAngle(double angle)
void setTapeId(const QString id)
void setFrequency(double f)
Definition: SgVlbiBand.h:402
void setTCreation(const SgMJD &t)
Definition: SgVlbiBand.h:410
QMap< QString, SgVlbiBaselineInfo * > & baselinesByName()
Definition: SgVlbiBand.h:376
QMap< QString, SgVlbiStationInfo * > & stationsByName()
Definition: SgVlbiBand.h:368
void setInputFileName(const QString &fileName)
Definition: SgVlbiBand.h:418
void setInputFileVersion(int version)
Definition: SgVlbiBand.h:426
QMap< int, SgVlbiBaselineInfo * > & baselinesByIdx()
Definition: SgVlbiBand.h:304
QMap< QString, SgVlbiSourceInfo * > & sourcesByName()
Definition: SgVlbiBand.h:384
QMap< int, SgVlbiSourceInfo * > & sourcesByIdx()
Definition: SgVlbiBand.h:312
double getFrequency() const
Definition: SgVlbiBand.h:320
QMap< int, SgVlbiStationInfo * > & stationsByIdx()
Definition: SgVlbiBand.h:296
@ Attr_PRIMARY
the band is a primary band;
Definition: SgVlbiBand.h:60
void setAmbiguitySpacing(double)
void setEffFreq(double)
void setResidualFringeFitting(double r)
void setGeocenterValue(double)
QVector< int > * corelIndexNumLSB()
void setEpochOfCorrelation(const SgMJD &)
const QString & getFourfitOutputFName() const
void setEpochCentral(const SgMJD &)
void setBitsPerSample(int bps)
void setTstart(const SgMJD &t)
void setCorrClocks(int i, int j, double d)
void setTotalPhase(double)
void setHopsRevisionNumber(int num)
double getSampleRate() const
QVector< char > * polarization_1ByChan()
SgVector * loFreqByChan_1()
QVector< char > * chanIdByChan()
void setIncohSegmAddAmp(double d)
QVector< int > * corelIndexNumUSB()
void setPhaseCalModes(int modes)
SgMatrix * phaseCalData_2ByChan()
void setAcceptedRatio(double d)
void setTstop(const SgMJD &t)
void setEpochOfFourfitting(const SgMJD &)
SgVector * numOfAccPeriodsByChan_LSB()
void setIncohChanAddAmp(double d)
void setCentrOffset(double offset)
void setEffIntegrationTime(double d)
void setFourfitOutputFName(const QString &)
QVector< char > * polarization_2ByChan()
SgVector * numOfAccPeriodsByChan_USB()
QVector< int > * bbcIdxByChan_1()
void setFourfitControlFile(const QString &cf)
SgVlbiMeasurement & phDRate()
void setGeocenterResidPhase(double d)
void setCorrelStarElev_2(double v)
void setSnr(double)
void setProbabOfFalseDetection(double d)
void setQualityFactor(int)
QString strId() const
void setNlags(int n)
void setGeocenterTotalPhase(double d)
void setDiscardRatio(double d)
SgVector * fringeAmplitudeByChan()
void setCorrCoeff(double)
void setEpochOfScan(const SgMJD &)
void setUrVr(int i, double d)
void setCorrelZdelay_1(double v)
SgVector * numOfSamplesByChan_LSB()
void setAprioriDra(int i, double d)
void setInstrDelay(int i, double d)
void setPhaseCalRates(int i, double d)
void setStopOffset(int offset)
void setUvFrPerAsec(int i, double d)
void setErrorCode(const QString &)
SgMatrix * phaseCalData_1ByChan()
SgVector * numOfSamplesByChan_USB()
void setFourfitCommandOverride(const QString &co)
void setReferenceFrequency(double)
void setCorrelZdelay_2(double v)
double getReferenceFrequency() const
void allocateChannelsSetupStorages(int numOfChans)
SgVlbiMeasurement & phDelay()
void setTapeQualityCode(const QString &code)
SgVector * loFreqByChan_2()
SgVlbiMeasurement & grDelay()
void setStartOffset(int offset)
SgVlbiMeasurement & sbDelay()
SgVector * fringePhaseByChan()
SgVector * refFreqByChan()
void setFourfitSearchParameters(int i, double d)
void setSampleRate(double sr)
void setCorrelStarElev_1(double v)
QVector< int > * bbcIdxByChan_2()
void setFourfitVersion(int idx, int ver)
void setStation1Idx(short int idx)
void setScanId(const QString &sId)
void setSourceIdx(short int idx)
void setApLength(double d)
bool addObservable(const QString &, const SgVlbiObservable &)
void setDTecStdDev(double e)
void setScanName(const QString &sName)
void setDTec(double d)
void setupActiveObservable(const QString &)
void setCorrRootFileName(const QString &sName)
void setStation2Idx(short int idx)
SgVlbiObservable * observable(const QString &)
const QString & getScanName() const
QMap< QString, SgVlbiObservable * > & observableByKey()
const QString & getKey()
void setBaselineIdx(short int idx)
void setKey(const QString &)
const QString & getCorrelatorType() const
void setOfficialName(const QString &name)
void setSchedulerName(const QString &name)
void setSessionCode(const QString &code)
void setDescription(const QString &description)
@ OT_MK4
observations are from Mk4-compatible correlator output;
void setName(const QString &name)
void setCorrelatorType(const QString &name)
CorrelatorPostProcSoftware cppsSoft_
@ Attr_FF_CREATED
the session has been imported from correlator;//vgosDbMake
const QString & getCorrelatorName() const
int getExperimentSerialNumber() const
void setExperimentSerialNumber(int sn)
const QString & getPiAgencyName() const
const QString & getDescription() const
void setNetworkSuffix(const QString &suffix)
void setSubmitterName(const QString &name)
void setCorrelatorName(const QString &name)
const QString & getSessionCode() const
void setPiAgencyName(const QString &name)
void setOriginType(OriginType type)
StationsByName stationsByName_
QMap< QString, SgVlbiObservation * > observationByKey_
bool getDataFromFringeFiles(const QString &path2, const QString &altDatabaseName, const QString &altCorrelatorName, const QString &historyFileName, const QString &mapFileName, const QList< QString > &)
QList< SgVlbiBand * > bands_
void processFringeFile(const QString &path2file, const QString &fringeFileName, const QMap< QString, StationInfo > &stnsInfo, const VexInfo &, const QString &vexFileName, const QMap< QString, QString > &stnNameById, const QMap< QString, QString > &stnNameByI, const QMap< QString, QString > &stn2stn, const QMap< QString, QString > &src2src, const QMap< QString, QString > &bnd2bnd, const QMap< QString, int > &fringeErrorCodeByInt, int &expSerialNumber)
bool selfCheck(bool guiExpected)
QMap< QString, SgVlbiBand * > bandByKey_
QList< SgVlbiObservation * > observations_
bool getCorrelatorHistory(const QString &fileName)
QMap< int, SgVlbiStationInfo * > stationsByIdx_
void importMapFile(const QString &mapFileName, QMap< QString, QString > &map4Stn, QMap< QString, QString > &map4Src, QMap< QString, QString > &map4Bnd)
void parseVexFile(const QString &, QString &, QString &)
BaselinesByName baselinesByName_
void processVexFile(const QString &, QMap< QString, StationInfo > &, VexInfo &, const QMap< QString, QString > &stn2stn, QString &correlatorName)
SgVlbiBand * primaryBand_
static QString className()
QMap< int, SgVlbiBaselineInfo * > baselinesByIdx_
SourcesByName sourcesByName_
bool check4NameMap(const QMap< QString, QString > &map, QString &name)
QMap< int, SgVlbiSourceInfo * > sourcesByIdx_
QMap< QString, SgVlbiAuxObservation * > * auxObservationByScanId()
void setSid(char c1, char c2)