General Purpose Geodetic Library
SgStnLogCollector.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) 2016-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 #include <math.h>
26 
27 
28 #include <QtCore/QDataStream>
29 #include <QtCore/QDir>
30 #include <QtCore/QFile>
31 #include <QtCore/QRegExp>
32 #include <QtCore/QRegularExpression>
33 #include <QtCore/QStringList>
34 #include <QtCore/QTextStream>
35 
36 
37 #include <SgIoExternalFilter.h>
38 #include <SgStnLogCollector.h>
39 #include <SgVersion.h>
40 #include <SgVlbiAuxObservation.h>
41 #include <SgVlbiObservation.h>
42 #include <SgVlbiStationInfo.h>
43 #include <SgVlbiSourceInfo.h>
44 
45 
46 
47 
48 QString asciifyString(const QString& str);
49 
50 
51 
52 
53 /*=======================================================================================================
54 *
55 * SgCableCalReading's METHODS:
56 *
57 *======================================================================================================*/
58 //
59 // static first:
61 {
62  return "SgCableCalReading";
63 };
64 /*=====================================================================================================*/
65 
66 
67 
68 
69 
70 
71 /*=======================================================================================================
72 *
73 * SgMeteoReading's METHODS:
74 *
75 *======================================================================================================*/
76 //
77 // static first:
79 {
80  return "SgMeteoReading";
81 };
82 /*=====================================================================================================*/
83 
84 
85 
86 
87 
88 
89 /*=======================================================================================================
90 *
91 * SgPointingReading's METHODS:
92 *
93 *======================================================================================================*/
94 //
95 // static first:
97 {
98  return "SgTraklReading";
99 };
100 /*=====================================================================================================*/
101 
102 
103 
104 
105 
106 
107 
108 /*=======================================================================================================
109 *
110 * SgTsysReading's METHODS:
111 *
112 *======================================================================================================*/
113 //
114 // static first:
116 {
117  return "SgTsysReading";
118 };
119 
120 
121 
122 //
123 void SgTsysReading::addTsyses(const QMap<QString, float>& tsys)
124 {
125  for (QMap<QString, float>::const_iterator it=tsys.begin(); it!=tsys.end(); ++it)
126  tsys_.insert(it.key(), it.value());
127 };
128 
129 
130 
131 //
132 void SgTsysReading::addTpconts(const QMap<QString, QVector<int> >& tpcont)
133 {
134  for (QMap<QString, QVector<int> >::const_iterator it=tpcont.begin(); it!=tpcont.end(); ++it)
135  tpcont_.insert(it.key(), it.value());
136 };
137 /*=====================================================================================================*/
138 
139 
140 
141 
142 
143 
144 /*=======================================================================================================
145 *
146 * SgPcalReading's METHODS:
147 *
148 *======================================================================================================*/
149 //
150 // static first:
152 {
153  return "SgPcalReading";
154 };
155 /*=====================================================================================================*/
156 
157 
158 
159 
160 
161 
162 /*=======================================================================================================
163 *
164 * SgSefdReading's METHODS:
165 *
166 *======================================================================================================*/
167 //
168 // static first:
170 {
171  return "SgSefdReading";
172 };
173 
174 
175 
176 //
177 bool SgSefdReading::addValByChanKey(const SgMJD& t, const QString& srcName, double az, double el,
178  const QString& chanKey, const QVector<double>& val)
179 {
180  bool isOk=true;
181  if (t_!=tZero && 0.3/DAY2SEC < fabs(t-t_))
182  {
183  isOk = false;
185  "::addValByChanKey(): unexpected epoch: old: \"" + t_.toString(SgMJD::F_YYYYMMDDHHMMSSSS) +
186  "\", new: \"" + t.toString(SgMJD::F_YYYYMMDDHHMMSSSS));
187  };
188  if (srcName_.size() && srcName != srcName_)
189  {
190  isOk = false;
192  "::addValByChanKey(): source name has changed: old: \"" + srcName_ + "\", new: \"" +
193  srcName + "\"; record of " + t.toString(SgMJD::F_YYYYMMDDHHMMSSSS));
194  };
195  if (-1000<az_ && az != az_)
196  {
197  isOk = false;
199  "::addValByChanKey(): azimuth has changed: old: \"" + QString("").setNum(az_) + ", new: " +
200  QString("").setNum(az) + "; record of " + t.toString(SgMJD::F_YYYYMMDDHHMMSSSS));
201  };
202  if (-1000<el_ && el != el_)
203  {
204  isOk = false;
206  "::addValByChanKey(): elevation has changed: old: \"" + QString("").setNum(el_) + ", new: " +
207  QString("").setNum(el) + "; record of " + t.toString(SgMJD::F_YYYYMMDDHHMMSSSS));
208  };
209  QVector<double> *v =new QVector<double>(val);
210  if (valByChanKey_.contains(chanKey))
211  {
212  isOk = false;
213  valByChanKey_.remove(chanKey);
215  "::addValByChanKey(): the channel key \"" + chanKey + "\" is already in the map");
216  };
217  t_ = t;
218  srcName_ = srcName;
219  az_ = az;
220  el_ = el;
221  valByChanKey_.insert(chanKey, v);
222  return isOk;
223 };
224 
225 
226 /*=====================================================================================================*/
227 
228 
229 
230 
231 
232 
233 /*=======================================================================================================
234 *
235 * SgOnSourceRecord's METHODS:
236 *
237 *======================================================================================================*/
238 //
239 // static first:
241 {
242  return "SgOnSourceRecord";
243 };
244 /*=====================================================================================================*/
245 
246 
247 
248 
249 
250 
251 
252 /*=======================================================================================================
253 *
254 * SgChannelSetup's METHODS:
255 *
256 *======================================================================================================*/
257 //
258 // static first:
260 {
261  return "SgChannelSetup";
262 };
263 
264 
265 
266 //
267 double SgChannelSetup::calcSkyFreq(double loFreq, double bbcFreq, double width,
268  SgChannelSideBand loSideBand, SgChannelSideBand ifSideBand)
269 {
270  double skyFrq;
271 /*
272  if a sideband of the IF is LSB and a sideband of LO is USB, then
273  frq_if = frq_lo + frq_bbc - bandwidth
274 
275  if a sideband of the IF is LSB and a sideband of LO is LSB, then
276  frq_if = frq_lo - frq_bbc - bandwidth
277 
278  if a sideband of the IF is USB and a sideband of LO is USB, then
279  frq_if = frq_lo + frq_bbc
280 
281  and if a sideband of the IF is USB and a sideband of LO is LSB, then
282  frq_if = frq_lo - frq_bbc
283 
284 */
285  //
286  if (ifSideBand==CSB_LSB && loSideBand==CSB_USB)
287  skyFrq = loFreq + bbcFreq - width;
288  else if (ifSideBand==CSB_LSB && loSideBand==CSB_LSB)
289  skyFrq = loFreq - bbcFreq - width;
290  else if (ifSideBand==CSB_USB && loSideBand==CSB_USB)
291  skyFrq = loFreq + bbcFreq;
292  else if (ifSideBand==CSB_USB && loSideBand==CSB_LSB)
293  skyFrq = loFreq - bbcFreq;
294  else
295  return -99.9;
296 
297  return skyFrq + width/2.0;
298 };
299 
300 
301 
302 
303 
304 
305 //
306 bool SgChannelSetup::selfCheck(const QString& stnKey)
307 {
308  isOk_ = true;
309 
310  if (hwType_ == HT_VGOS &&
311  backEndType_ != BET_DBBC3 ) // dbbc3 setup can be figured out from a log file
312  {
313 /*
314  const double frqsStd[64] = {
315  3480.40, 3448.40, 3384.40, 3320.40, 3224.40, 3096.40, 3064.40, 3032.40,
316  3480.40, 3448.40, 3384.40, 3320.40, 3224.40, 3096.40, 3064.40, 3032.40,
317 
318  5720.40, 5688.40, 5624.40, 5560.40, 5464.40, 5336.40, 5304.40, 5272.40,
319  5720.40, 5688.40, 5624.40, 5560.40, 5464.40, 5336.40, 5304.40, 5272.40,
320 
321  6840.40, 6808.40, 6744.40, 6680.40, 6584.40, 6456.40, 6424.40, 6392.40,
322  6840.40, 6808.40, 6744.40, 6680.40, 6584.40, 6456.40, 6424.40, 6392.40,
323 
324  10680.40,10648.40,10584.40,10520.40,10424.40,10296.40,10264.40,10232.40,
325  10680.40,10648.40,10584.40,10520.40,10424.40,10296.40,10264.40,10232.40};
326 
327  const double frqsIsh[64] = {
328  3032.40, 3064.40, 3096.40, 3224.40, 3320.40, 3384.40, 3448.40, 3480.40,
329  3032.40, 3064.40, 3096.40, 3224.40, 3320.40, 3384.40, 3448.40, 3480.40,
330 
331  5272.40, 5304.40, 5336.40, 5464.40, 5560.40, 5624.40, 5688.40, 5720.40,
332  5272.40, 5304.40, 5336.40, 5464.40, 5560.40, 5624.40, 5688.40, 5720.40,
333 
334  6392.40, 6424.40, 6456.40, 6584.40, 6680.40, 6744.40, 6808.40, 6840.40,
335  6392.40, 6424.40, 6456.40, 6584.40, 6680.40, 6744.40, 6808.40, 6840.40,
336 
337  10232.40,10264.40,10296.40,10424.40,10520.40,10584.40,10648.40,10680.40,
338  10232.40,10264.40,10296.40,10424.40,10520.40,10584.40,10648.40,10680.40};
339 */
340 /*
341  QList<QString> chanIds;
342  for (int i=0; i<16; i++)
343  for (int j=0; j<2; j++)
344  chanIds << QString("").sprintf(" %02da%01d", i, j) << QString("").sprintf(" %02db%01d", i, j)
345  << QString("").sprintf(" %02dc%01d", i, j) << QString("").sprintf(" %02dd%01d", i, j);
346 */
347 
348  // std. setup:
349  if (!loFreqById_.size())
350  {
351  loFreqById_.insert("a0", 2472.4);
352  loFreqById_.insert("a1", 2472.4);
353 
354  loFreqById_.insert("b0", 4712.4);
355  loFreqById_.insert("b1", 4712.4);
356 
357  loFreqById_.insert("c0", 5832.4);
358  loFreqById_.insert("c1", 5832.4);
359 
360  loFreqById_.insert("d0", 9672.4);
361  loFreqById_.insert("d1", 9672.4);
362  };
363 
364  for (QMap<QString, double>::iterator it=loFreqByTpSensorKey_.begin(); it!=loFreqByTpSensorKey_.end();
365  ++it)
366  {
367  QString sensorKey=it.key();
368  QString sensorId("");
369  //
370  if (ifIdByTpSensorKey_.contains(sensorKey))
371  sensorId = ifIdByTpSensorKey_.value(sensorKey);
372  else
374  "::selfCheck(): VGOS setup: cannot find sensor ID for key \"" +
375  sensorKey + "\" for station \"" + stnKey + "\"");
376  //
377  };
378  }
379  else
380  {
381  if (bbcFreqByIdx_.size() == 0)
382  {
383  isOk_ = false;
385  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
386  "the map bbcFreqByIdx is empty");
387  };
388  if (bbcBandwidthByIdx_.size() == 0)
389  {
390  isOk_ = false;
392  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
393  "the map bbcBandwidthByIdx is empty");
394  };
395  if (loIdByIdx_.size()==0 && loIdByCid_.size()==0)
396  {
397  isOk_ = false;
399  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
400  "the maps loIdByIdx/loIdByCid are empty");
401  };
402  if (loFreqById_.size() == 0)
403  {
404  isOk_ = false;
406  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
407  "the map loFreqById is empty");
408  };
409  if (loSideBandById_.size() == 0)
410  {
411  isOk_ = false;
413  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
414  "the map loSideBandById is empty");
415  };
416  if (loPolarizationById_.size() == 0)
417  {
418  isOk_ = false;
420  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
421  "the map loPolarizationById is empty");
422  };
423  if (ifIdxById_.size() == 0)
424  {
425  isOk_ = false;
427  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
428  "the map ifIdxById is empty");
429  };
430  if (ifSideBandById_.size() == 0)
431  {
432  isOk_ = false;
434  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
435  "the map ifSideBandById is empty");
436  };
437  for (QMap<QString, int>::const_iterator it=ifIdxById_.begin(); it!=ifIdxById_.end(); ++it)
438  {
439  int cIdx=it.value();
440  QString ifId(it.key());
441  QString loId("");
442 
443  if (loIdByIdx_.contains(cIdx))
444  loId = loIdByIdx_.value(cIdx);
445  else if (loIdByCid_.contains(ifId))
446  loId = loIdByCid_.value(ifId);
447 
448  if (loId.size())
449  {
450  // LO side band:
451  if (!loSideBandById_.contains(loId))
452  {
453  isOk_ = false;
455  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
456  "cannot find side band for LO \"" + loId + "\"");
457  };
458  // channel side band:
459  if (!ifSideBandById_.contains(ifId))
460  {
461  isOk_ = false;
463  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
464  "cannot find side band for channel #" + QString("").setNum(cIdx) + ", ID: \"" + ifId + "\"");
465  };
466 
467  // polarization:
468  if (!loPolarizationById_.contains(loId))
469  {
470  isOk_ = false;
472  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
473  "cannot find polarization for LO \"" + loId + "\"");
474  };
475 
476  // bandwidth:
477  if (!bbcBandwidthByIdx_.contains(cIdx))
478  {
479  isOk_ = false;
481  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
482  "cannot find bandwidth for channel #" + QString("").setNum(cIdx) + ", ID=" + ifId);
483  };
484 
485  if (!bbcFreqByIdx_.contains(cIdx))
486  {
487  isOk_ = false;
489  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
490  "cannot find BBC_FRQ for channel #" + QString("").setNum(cIdx));
491  };
492  if (!loFreqById_.contains(loId))
493  {
494  isOk_ = false;
496  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
497  "cannot find LO frq for channel #" + QString("").setNum(cIdx) + ", loID=" + loId);
498  };
499  }
500  else
501  {
502  isOk_ = false;
504  "::selfCheck(): the channel setup for station \"" + stnKey + "\" is not usable: "
505  "cannot find LO ID for channel #" + QString("").setNum(cIdx) + " with id \"" + ifId + "\"");
506  };
507  };
508  };
509 
510  return isOk_;
511 };
512 /*=====================================================================================================*/
513 
514 
515 
516 
517 
518 
519 
520 
521 
522 /*=======================================================================================================
523 *
524 * SgChannelSkeded's METHODS:
525 *
526 *======================================================================================================*/
527 //
528 // static first:
530 {
531  return "SgChannelSkeded";
532 };
533 
534 
535 
536 //
537 bool SgChannelSkeded::parseSkdFile(const QString& fileName)
538 {
539  QString str("");
540  QFile f(fileName);
542  "::parseSkdFile(): going to parse \"" + f.fileName() + "\" sked file");
543 
544  if (!f.exists()) // it is ok
545  {
547  "::parseSkdFile(): the file " + f.fileName() + " does not exists");
548  return (isOk_=false);
549  };
550 
551  if (f.open(QFile::ReadOnly))
552  {
553  QTextStream s(&f);
554  bool haveDone=false;
555  int numOfReadStrs=0;
556  QRegExp reCodes("^\\$CODES", Qt::CaseInsensitive);
557  QRegExp reFrec("^F\\s+(\\S+)\\s+(\\S+)\\s+(.+)$", Qt::CaseInsensitive);
558  //C SX X 8445.75 10000.0 2 Mk341:1 8.00 1(1,,2) 4
559  QRegExp reCrec("^C\\s+(\\w+)\\s+(\\w+)\\s+(.+)$", Qt::CaseInsensitive);
560  QRegExp reSb("\\w*\\s*\\(([-+0-9,]+)\\).*", Qt::CaseInsensitive);
561  bool getCodesRec=false;
562  QList<QString> lst;
563  QList<QString> stations;
564  double frq, width;
565  int cIdx;
566  bool isOk;
567  bool hasUsb, hasLsb, hasBothBands;
568  QString bandKey("");
569 
570  while (!s.atEnd() && !haveDone)
571  {
572  str = s.readLine();
573  numOfReadStrs++;
574 
575  if (str.size() && str.at(0)== "*")
576  {
577  }
578  else if (reCodes.indexIn(str) != -1)
579  getCodesRec = true;
580  else if (getCodesRec)
581  {
582  if (reFrec.indexIn(str) != -1)
583  {
584  stations.clear();
585  lst = reFrec.cap(3).split(" ", QString::SkipEmptyParts);
586  for (int i=0; i<lst.size(); i++)
587  stations << lst.at(i).leftJustified(8, ' ');
588  if (!stations.size())
590  "::parseSkdFile(): got \"F\" record without stations: \"" + str + "\"");
591  else
592  {
593  for (int i=0; i<stations.size(); i++)
594  {
595  const QString& key=stations.at(i);
596  stnCfgByKey_[key] = StnCfg(key);
597  };
599  "::parseSkdFile(): got " + QString("").setNum(stations.size()) + " stations from F record");
600  };
601  }
602  else if (reCrec.indexIn(str) != -1)
603  {
604  // parse C rec:
605  lst = reCrec.cap(0).split(" ", QString::SkipEmptyParts);
606 
607 // for (int i=0; i<lst.size(); i++)
608 
609  bandKey = lst.at(2);
610  // Sky frequency:
611  frq = lst.at(3).toDouble(&isOk);
612  if (!isOk)
613  {
614  frq = -1.0;
616  "::parseSkdFile(): cannot get sky frequency from C record \"" + str + "\"");
617  };
618  // channel index:
619  cIdx = lst.at(5).toDouble(&isOk);
620  if (!isOk)
621  {
622  cIdx = -1;
624  "::parseSkdFile(): cannot get channel index from C record \"" + str + "\"");
625  };
626  // channel width:
627  width = lst.at(7).toDouble(&isOk);
628  if (!isOk)
629  {
630  width = -1.0;
632  "::parseSkdFile(): cannot get channel width from C record \"" + str + "\"");
633  };
634  // upper/lower side band:
635  hasUsb = hasLsb = hasBothBands = false;
636  QList<SgChannelSideBand>sideBands;
637  if (reSb.indexIn(lst.at(8)) != -1)
638  {
639  lst = reSb.cap(1).split(",", QString::KeepEmptyParts);
640  if (!lst.size())
642  "::parseSkdFile(): nothing to parse side band set up: \"" + str + "\"");
643  else
644  {
645  if (lst.at(0).size())
646  {
647  sideBands << CSB_USB;
648  hasUsb = true;
649  };
650  if (1 < lst.size() && lst.at(1).size())
651  {
652  sideBands << CSB_LSB;
653  hasLsb = true;
654  };
655  if (2 < lst.size() && lst.at(2).size())
656  {
657  sideBands << CSB_USB;
658  hasUsb = true;
659  };
660  if (3 < lst.size() && lst.at(3).size())
661  {
662  sideBands << CSB_LSB;
663  hasLsb = true;
664  };
665  hasBothBands = hasUsb && hasLsb;
666  };
667  }
668  else
670  "::parseSkdFile(): cannot get parse side band set up: \"" + str + "\"");
671  //
672  // crutches:
673  if (hasBothBands)
674  {
675  ChanCfg cc(bandKey, cIdx, frq - width, width, sideBands);
676  for (int i=0; i<stations.size(); i++)
677  stnCfgByKey_[stations.at(i)].channelCfgs().append(ChanCfg(cc));
678  };
679  ChanCfg cc(bandKey, cIdx, frq, width, sideBands);
680  for (int i=0; i<stations.size(); i++)
681  stnCfgByKey_[stations.at(i)].channelCfgs().append(ChanCfg(cc));
682  }
683  else
684  haveDone = true;
685  };
686  };
687  };
688  f.close();
689  //
690  // check:
691  if (!stnCfgByKey_.size())
692  {
693  isOk_ = false;
695  "::parseSkdFile(): nothing has found in the sked file \"" + f.fileName() + "\"");
696  return isOk_;
697  };
698  //
699  //
700  isOk_ = true;
701  for (QMap<QString, StnCfg>::iterator it=stnCfgByKey_.begin(); it!=stnCfgByKey_.end(); ++it)
702  {
703  const StnCfg& cfg=it.value();
704  if (isOk_ && cfg.getStnKey().size() == 0)
705  {
706  isOk_ = false;
708  "::parseSkdFile(): the sked file \"" + f.fileName() +
709  "\" is not usable: station name is missing");
710  }
711  if (isOk_ && cfg.getChannelCfgs().size() == 0)
712  {
713  isOk_ = false;
715  "::parseSkdFile(): the sked file \"" + f.fileName() + "\" is not usable for " + it.key() +
716  ": no channels setup");
717  }
718  else
719  {
720  for (int i=0; i<cfg.getChannelCfgs().size(); i++)
721  {
722  const ChanCfg& cc=cfg.getChannelCfgs().at(i);
723  if (isOk_ && cc.getChanIdx() < 0)
724  {
725  isOk_ = false;
727  "::parseSkdFile(): the sked file \"" + f.fileName() + "\" is not usable for " + it.key() +
728  ": bad channel index for chan#" + QString("").setNum(i));
729  }
730  if (isOk_ && cc.getBandKey().size() < 0)
731  {
732  isOk_ = false;
734  "::parseSkdFile(): the sked file \"" + f.fileName() + "\" is not usable for " + it.key() +
735  ": bad band key for chan#" + QString("").setNum(i));
736  }
737  if (isOk_ && cc.getSkyFrq() < 0.0)
738  {
739  isOk_ = false;
741  "::parseSkdFile(): the sked file \"" + f.fileName() + "\" is not usable for " + it.key() +
742  ": bad sky frequency for chan#" + QString("").setNum(i));
743  }
744  if (isOk_ && cc.getBandWidth() < 0.0)
745  {
746  isOk_ = false;
748  "::parseSkdFile(): the sked file \"" + f.fileName() + "\" is not usable for " + it.key() +
749  ": bad bandwidth for chan#" + QString("").setNum(i));
750  }
751  if (isOk_ && cc.getSideBands().size() < 0)
752  {
753  isOk_ = false;
755  "::parseSkdFile(): the sked file \"" + f.fileName() + "\" is not usable for " + it.key() +
756  ": no sideband setup for chan#" + QString("").setNum(i));
757  };
758  };
759  };
760  };
761  return isOk_;
762 };
763 /*=====================================================================================================*/
764 
765 
766 
767 
768 
769 
770 
771 
772 
773 
774 /*=======================================================================================================
775 *
776 * SgStnLogReadings's METHODS:
777 *
778 *======================================================================================================*/
779 //
780 // static first:
782 {
783  return "SgStnLogReadings";
784 };
785 
786 
787 
788 //
790  stationName_(""),
791  experimentName_(""),
792  fsVersionLabel_(""),
793  backEndInfo_(""),
794  recorderInfo_(""),
795  onSourceRecords_(),
796  cableCals_(),
797  cableLongs_(),
798  meteoPars_(),
799  tSyses_(),
800  dbbc3Tps_(),
801  trakls_(),
802  pcals_(),
803  dot2xpses_(),
804  recordByScan_(),
805  channelSetup_()
806 {
807  itType_= IT_UNDEF;
809  tSensorsPrinted2AntCal_ = false;
810  cableCalAmbig_ = 100.0e-9;
811  cableSign_ = 0;
812 };
813 
814 
815 
816 //
817 SgStnLogReadings::SgStnLogReadings(const QString& stationName) :
818  stationName_(stationName),
819  experimentName_(""),
820  fsVersionLabel_(""),
821  backEndInfo_(""),
822  recorderInfo_(""),
823  onSourceRecords_(),
824  cableCals_(),
825  cableLongs_(),
826  meteoPars_(),
827  tSyses_(),
828  dbbc3Tps_(),
829  trakls_(),
830  pcals_(),
831  dot2xpses_(),
832  recordByScan_()
833 {
835  tSensorsPrinted2AntCal_ = false;
836  cableCalAmbig_ = 100.0e-9;
837  cableSign_ = 0;
838 };
839 
840 
841 
842 //
844 {
845  // free the used memory:
846  onSourceRecords_.clear();
847  //
848  for (int i=0; i<cableCals_.size(); i++)
849  delete cableCals_[i];
850  for (int i=0; i<cableLongs_.size(); i++)
851  delete cableLongs_[i];
852  for (int i=0; i<meteoPars_.size(); i++)
853  delete meteoPars_[i];
854  for (int i=0; i<tSyses_.size(); i++)
855  delete tSyses_[i];
856  for (int i=0; i<dbbc3Tps_.size(); i++)
857  delete dbbc3Tps_[i];
858  for (int i=0; i<trakls_.size(); i++)
859  delete trakls_[i];
860  for (int i=0; i<pcals_.size(); i++)
861  delete pcals_[i];
862 // for (int i=0; i<sefds_.size(); i++)
863 // delete sefds_[i];
864  for (int i=0; i<dot2xpses_.size(); i++)
865  delete dot2xpses_[i];
866 
867  cableCals_.clear();
868  cableLongs_.clear();
869  meteoPars_.clear();
870  tSyses_.clear();
871  dbbc3Tps_.clear();
872  trakls_.clear();
873  pcals_.clear();
874  sefds_.clear();
875  dot2xpses_.clear();
876  recordByScan_.clear();
877 };
878 
879 
880 
881 //
883 {
884  for (int i=0; i<onSourceRecords_.size(); i++)
885  {
886  if (onSourceRecords_.at(i)->cableCals().size())
887  onSourceRecords_.at(i)->cableCals().clear();
888  };
889  for (int i=0; i<cableCals_.size(); i++)
890  delete cableCals_[i];
891  cableCals_.clear();
892  areCableCalsPresent_ = false;
893 };
894 
895 
896 
897 //
899 {
900  for (int i=0; i<onSourceRecords_.size(); i++)
901  if (onSourceRecords_.at(i)->meteoPars().size())
902  onSourceRecords_.at(i)->meteoPars().clear();
903  for (int i=0; i<meteoPars_.size(); i++)
904  delete meteoPars_[i];
905  meteoPars_.clear();
906  areMeteosPresent_ = false;
907 };
908 
909 
910 
911 //
913 {
914  for (int i=0; i<tSyses_.size(); i++)
915  delete tSyses_[i];
916  tSyses_.clear();
917  areTsysesPresent_ = false;
918 };
919 
920 
921 
922 //
924  const QMap<QString, int> *defaultCableSignByStn)
925 {
926  bool hasCableSign;
927  SgMJD tFirst, tLast;
928  SgMJD tLeftMarging, tRightMarging;
929 
930  if (!stationName_.size())
931  stationName_ = stn->name(); // simplified name, no spaces
932 
933  //
934  if (!stn->auxObservationByScanId()->size()) // nothing to worry about
935  {
937  "::verifyReadings(): the station " + stationName_ + " has no any observations; skipped");
938  return;
939  };
940  //
941  tFirst = *stn->auxObservationByScanId()->begin().value();
942  tLast = *(--stn->auxObservationByScanId()->end()).value();
943 
944  tLeftMarging = tFirst - 1.0/24.0; // one hr earlier
945  tRightMarging = tLast + 1.0/24.0; // one hr later
946 
947  hasCableSign = cableSign_ != 0;
948 
949  if (stationName_ == "KOKEE")
950  cableCalAmbig_ = 1.0e-9;
951 
952  for (int i=0; i<onSourceRecords_.size(); i++)
953  {
954  SgOnSourceRecord *osRec=onSourceRecords_.at(i);
955  // if the scan name is missed, try to pick it up:
956  if (!osRec->getScanName().size())
957  lookupScanName(osRec, *stn->auxObservationByScanId());
958  // if the scan name is ok (it is from the log file or picked up):
959  if (osRec->getScanName().size() &&
960  tLeftMarging <= osRec->getTstart() && osRec->getTfinis() <= tRightMarging)
961  {
962  SgOnSourceRecord *r=NULL;
963  if (!recordByScan_.contains(osRec->getScanName()))
964  recordByScan_.insert(osRec->getScanName(), osRec);
965  else
966  {
967  r = recordByScan_.value(osRec->getScanName());
968  /*
969  if (r->cableCals().size()==0 && r->meteoPars().size()==0 && // an empty record, replace it
970  (osRec->cableCals().size()!=0 || osRec->meteoPars().size()!=0) )
971  {
972  recordByScan_.remove(r->getScanName());
973  recordByScan_.insert(osRec->getScanName(), osRec);
974  logger->write(SgLogger::INF, SgLogger::IO, className() +
975  "::verifyReadings(): station " + stationName_ + ": the empty record for the scan " +
976  r->getScanName() + " [" + r->getTstart().toString() + " -- " + r->getTfinis().toString() +
977  "] @ " + r->getSourceName() + " has been replaced by the new one");
978  logger->write(SgLogger::INF, SgLogger::IO, className() +
979  "::verifyReadings(): station " + stationName_ + ": the new record is: [" +
980  osRec->getTstart().toString() + " -- " + osRec->getTfinis().toString() + "] @ " +
981  osRec->getSourceName() + " numRecs(c/m)=" +
982  QString("").setNum(osRec->cableCals().size()) + "/" +
983  QString("").setNum(osRec->meteoPars().size()));
984  //delete r;
985  }
986  else */
987  if (*r == *osRec)
988  {
990  "::verifyReadings(): station " + stationName_ + ": got the duplicate scan \"" +
991  osRec->getScanName() + "\" [" + osRec->getTstart().toString() + " -- " +
992  osRec->getTfinis().toString() + "] @ " + osRec->getSourceName());
993  }
994  else
995  {
997  "::verifyReadings(): station " + stationName_ +
998  ": cannot insert osRec [" + osRec->getTstart().toString(SgMJD::F_Simple) +
999  " -- " + osRec->getTfinis().toString(SgMJD::F_Simple) + "] @ " + osRec->getSourceName() +
1000  " scan " + osRec->getScanName() + ", it's already in the map, nr(c/m)=" +
1001  QString("").setNum(osRec->cableCals().size()) + "/" +
1002  QString("").setNum(osRec->meteoPars().size()));
1003 
1005  "::verifyReadings(): station " + stationName_ +
1006  ": content of the map [" + r->getTstart().toString(SgMJD::F_Simple) +
1007  " -- " + r->getTfinis().toString(SgMJD::F_Simple) + "] @ " + r->getSourceName() +
1008  ", nr(c/m)=" +
1009  QString("").setNum(osRec->cableCals().size()) + "/" +
1010  QString("").setNum(osRec->meteoPars().size()));
1011  };
1012  };
1013  };
1014  };
1015  //
1016  int inRangePts;
1017  inRangePts = 0;
1018  for (int i=0; i<meteoPars_.size(); i++)
1019  if (tFirst<=meteoPars_.at(i)->getT() && meteoPars_.at(i)->getT()<=tLast)
1020  {
1021  areMeteosPresent_ = true;
1022  inRangePts++;
1023  };
1024  // check for number acquired of data:
1025  if (inRangePts<4)
1026  {
1028  "::verifyReadings(): station " + stationName_ + ": insufficient number (" +
1029  QString("").setNum(inRangePts) + ") of meteo parameters; skipped");
1031  areMeteosPresent_ = false;
1032  };
1033  //
1034  // cable cals:
1035  inRangePts = 0;
1036  for (int i=0; i<cableCals_.size(); i++)
1037  if (tFirst<=cableCals_.at(i)->getT() && cableCals_.at(i)->getT()<=tLast)
1038  {
1039  areCableCalsPresent_ = true;
1040  inRangePts++;
1041  };
1042  // check for number acquired of data:
1043  if (inRangePts<4)
1044  {
1046  "::verifyReadings(): station " + stationName_ + ": insufficient number (" +
1047  QString("").setNum(inRangePts) + ") of cable calibrations; skipped");
1049  areCableCalsPresent_ = false;
1050  };
1051  //
1052  // tsyses:
1053  inRangePts = 0;
1054  for (int i=0; i<tSyses_.size(); i++)
1055  if (tFirst<=tSyses_.at(i)->getT() && tSyses_.at(i)->getT()<=tLast)
1056  {
1057  areTsysesPresent_ = true;
1058  inRangePts++;
1059  };
1060  // check for number acquired of data:
1061  if (inRangePts<4)
1062  {
1064  "::verifyReadings(): station " + stationName_ + ": insufficient number (" +
1065  QString("").setNum(inRangePts) + ") of tsys readings; skipped");
1067  areTsysesPresent_ = false;
1068  };
1069  //
1071  {
1072  if (cableLongs_.size()) // try to figure out the cable sign:
1073  {
1074  int signCableLong;
1075  if ((signCableLong=determineCableSignFromLong()) == 0)
1077  "::verifyReadings(): station " + stationName_ +
1078  ": cannot determine the cable sign from cablelong measurements");
1079  else if (!hasCableSign)
1080  {
1081  cableSign_ = signCableLong;
1083  "::verifyReadings(): station " + stationName_ + ": the cable sign has been set to \"" +
1084  (cableSign_>0?"+":"-") + "\" according to cablelong measurements");
1085  hasCableSign = true;
1086  }
1087  else if (signCableLong != cableSign_)
1088  {
1090  "::verifyReadings(): station " + stationName_ +
1091  ": the found cable sign is different from the cablelong measurements: \"" +
1092  (cableSign_>0?"+":"-") + "\" vs \"" + (signCableLong>0?"+":"-") +
1093  "\"; the sign has been reverted");
1094  cableSign_ = signCableLong;
1095  }
1096  else
1098  "::verifyReadings(): station " + stationName_ +
1099  ": the cable sign has been confirmed by cablelong measurements");
1100  }
1101  else
1103  "::verifyReadings(): station " + stationName_ +
1104  ": cannot find any usable cablelong measurements");
1105  };
1106  //
1107  // complain:
1110  "::verifyReadings(): station " + stationName_ + ": cannot find any usable meteo readings");
1113  "::verifyReadings(): station " + stationName_ + ": cannot find any usable cable calibrations");
1114 
1115  if (areCableCalsPresent_ && !hasCableSign)
1116  {
1118  "::verifyReadings(): station " + stationName_ + ": cannot determine the cable calibration sign");
1119  //
1120  // predefined station names:
1121  //
1122  if (defaultCableSignByStn)
1123  {
1124  if (defaultCableSignByStn->contains(stationName_))
1125  {
1126  cableSign_ = defaultCableSignByStn->value(stationName_);
1128  "::verifyReadings(): station " + stationName_ +
1129  ": the cable sign was set to \"" + QString(cableSign_==1?"+":"-") +
1130  "\" according to the list of default cable signs");
1131  };
1132 
1133  }
1134  else
1136  "::verifyReadings(): no default cable cal list were provided");
1137  };
1138  //
1139  // check ambigs, remove outliers and, then, the average:
1142  if (areMeteosPresent_)
1144 };
1145 
1146 
1147 
1148 //
1150  const QMap<QString, SgVlbiAuxObservation*> &auxObservationByScan)
1151 {
1152  if (!osRec->getSourceName().size())
1153  {
1155  "::lookupScanName(): station " + stationName_ +
1156  ": unable to lookup the scan name: no source name provided,");
1158  "::lookupScanName(): station " + stationName_ + ": the on_data record is: " +
1159  osRec->getScanName() + " [" + osRec->getTstart().toString(SgMJD::F_Simple) + " -- " +
1160  osRec->getTfinis().toString(SgMJD::F_Simple) + "] @ \"" + osRec->getSourceName() + "\"");
1161  return;
1162  };
1163 
1164  double tLimit=15.0/60.0/24.0; // 15min window where the scan can be
1165  double dT;
1166  const SgMJD &t=osRec->getTstart() + (osRec->getTfinis() - osRec->getTstart())/2.0;
1167  SgVlbiAuxObservation *auxClosest=auxObservationByScan.begin().value();
1168  SgMJD tClosest=*auxClosest;
1169  //
1170  dT = fabs(tClosest - t);
1171  for (QMap<QString, SgVlbiAuxObservation*>::const_iterator it=auxObservationByScan.begin();
1172  it!=auxObservationByScan.end(); ++it)
1173  {
1174  SgMJD &ti=*it.value();
1175  if ( (fabs(ti-t)<dT) && it.value()->getOwner()->src()->getKey().contains(osRec->getSourceName()))
1176  {
1177  tClosest = ti;
1178  dT = fabs(ti - t);
1179  auxClosest = it.value();
1180  };
1181  };
1182 
1183  if (auxClosest && dT<=tLimit) // found something:
1184  {
1185  osRec->setScanName(auxClosest->getOwner()->getScanName().simplified().toLower());
1186 /*
1187  logger->write(SgLogger::DBG, SgLogger::IO_TXT, className() +
1188  "::lookupScanName(): the scan name " + osRec->getScanName() +
1189  " has been assigned to the on_data record; source: " + osRec->getSourceName() +
1190  ", interval: [" + osRec->getTstart().toString(SgMJD::F_Simple) +
1191  " -- " + osRec->getTfinis().toString(SgMJD::F_Simple) + "]");
1192 */
1193  }
1194  else
1196  "::lookupScanName(): station " + stationName_ +
1197  ": no scan name was assigned to the on_data record: [" +
1198  osRec->getTstart().toString(SgMJD::F_Simple) + " -- " +
1199  osRec->getTfinis().toString(SgMJD::F_Simple) + "] @ " +
1200  osRec->getSourceName());
1201 };
1202 
1203 
1204 
1205 //
1207 {
1208  int cableSign=0;
1209  double window=10.0/60.0/24.0; // 10 mins, is it ok?
1210  QList<int> signByCablelong;
1211  QList<SgCableCalReading*> selectedReadings;
1212  for (int i=0; i<cableLongs_.size(); i++)
1213  {
1214  const SgMJD &tL=cableLongs_.at(i)->getT();
1215  double clV=cableLongs_.at(i)->getV();
1216  for (int j=0; j<cableCals_.size(); j++)
1217  if (fabs(cableCals_.at(j)->getT() - tL) < window)
1218  selectedReadings << cableCals_.at(j);
1219  //
1220  if (selectedReadings.size())
1221  {
1222  double vAverage, ratio;
1224  "::determineCableSignFromLong(): collected " + QString("").setNum(selectedReadings.size()) +
1225  " close cable readings for cablelong measurement on " + tL.toString());
1226  // find average cable measurement:
1227  vAverage = 0.0;
1228  for (int j=0; j<selectedReadings.size(); j++)
1229  vAverage += selectedReadings.at(j)->getV();
1230  vAverage /= selectedReadings.size();
1231  //
1232  ratio = (clV - vAverage)/vAverage;
1233  if (1.0e-3 < ratio)
1234  cableSign = 1;
1235  else if (ratio < -1.0e-3 )
1236  cableSign = -1;
1237  else
1238  cableSign = 0;
1239  signByCablelong << cableSign;
1241  "::determineCableSignFromLong(): average cable cal: " + QString("").setNum(vAverage*1.0e9) +
1242  "ns, cablelong: " + QString("").setNum(clV*1.0e9) +
1243  "ns; the sign is \"" + QString(cableSign==0?"?":(cableSign<0?"-":"+")) + "\"");
1244  selectedReadings.clear();
1245  }
1246  else
1248  "::determineCableSignFromLong(): no close cable readings found for cablelong measurement on " +
1249  tL.toString());
1250  };
1251 
1252  if (signByCablelong.size() == 0)
1253  cableSign = 0;
1254  else if (signByCablelong.size() == 1)
1255  cableSign = signByCablelong.at(0);
1256  else
1257  {
1258  QMap<int, int> signByNum;
1259  for (int i=0; i<signByCablelong.size(); i++)
1260  {
1261  if (signByNum.contains(signByCablelong.at(i)))
1262  signByNum[signByCablelong.at(i)]++;
1263  else
1264  signByNum[signByCablelong.at(i)] = 1;
1265  };
1266  if (signByNum.size() == 1)
1267  {
1268  cableSign = signByNum.begin().key();
1270  "::determineCableSignFromLong(): according to all " +
1271  QString("").setNum(signByCablelong.size()) + " cablelong measurements, the sign is \"" +
1272  QString(cableSign==0?"?":(cableSign<0?"-":"+")) + "\"");
1273  }
1274  else
1275  {
1276  cableSign = 0;
1278  "::determineCableSignFromLong(): cannot determine the proper sign, the "
1279  "numbers of measuremnts are:");
1280  for (QMap<int, int>::iterator it=signByNum.begin(); it!=signByNum.end(); ++it)
1282  "::determineCableSignFromLong(): " +
1283  QString("").sprintf("sign \"%s\": %2d count(s)", it.key()==0?"?":(it.key()<0?"-":"+"),
1284  it.value()));
1285  };
1286  };
1287  signByCablelong.clear();
1288  return cableSign;
1289 };
1290 
1291 
1292 
1293 //
1295 {
1296  double vAverage;
1297  double vDispersion;
1298  double vTmp;
1299  SgCableCalReading *rec=NULL;
1300  int numOfResolvedAmbigs=0;
1301  int numOfOutliers=0;
1302  bool allReadingsRsame;
1303  //
1304  // first, resolve ambiguities:
1305  vAverage = 0.0;
1306  for (int i=0; i<cableCals_.size(); i++)
1307  {
1308  rec = cableCals_.at(i);
1309  if (fabs((rec->getV()-vAverage)/cableCalAmbig_) > 0.75)
1310  {
1311  rec->setV(rec->getV() - round((rec->getV()-vAverage)/cableCalAmbig_)*cableCalAmbig_);
1312  numOfResolvedAmbigs++;
1313  };
1314  vAverage = vAverage*i/(i + 1) + rec->getV()/(i+1);
1315  };
1316  if (numOfResolvedAmbigs)
1318  "::cleanCableCalibrations() station " + stationName_ + ": " +
1319  QString("").setNum(numOfResolvedAmbigs) + " ambiguit" + (numOfResolvedAmbigs==1?"y":"ies") +
1320  " resolved in the cable cal readings");
1321 
1322  //
1323  // check for outliers:
1324  vAverage = 0.0;
1325  vDispersion = 0.0;
1326  vTmp = 0.0;
1327  if (cableCals_.size() > 0)
1328  vTmp = cableCals_.at(0)->getV();
1329  allReadingsRsame = true;
1330  for (int i=0; i<cableCals_.size(); i++)
1331  {
1332  vAverage += cableCals_.at(i)->getV();
1333  vDispersion += cableCals_.at(i)->getV()*cableCals_.at(i)->getV();
1334  if (allReadingsRsame && cableCals_.at(i)->getV()!=vTmp)
1335  allReadingsRsame = false;
1336  };
1337  if (!allReadingsRsame)
1338  {
1339  vAverage /= cableCals_.size();
1340  vDispersion /= cableCals_.size();
1341  vDispersion -= vAverage*vAverage;
1342  if (vDispersion < 0.0)
1343  {
1345  "::cleanCableCalibrations(): station " + stationName_ + ": dispersion^2<0.0 (" +
1346  QString("").sprintf("%.16g", vDispersion) + ")");
1347  vDispersion = -vDispersion;
1348  };
1349  if (vDispersion > 0.0)
1350  {
1351  vDispersion = sqrt(vDispersion);
1352  for (int i=0; i<cableCals_.size(); i++)
1353  if (fabs(cableCals_.at(i)->getV()-vAverage) > 5.0*vDispersion)
1354  {
1355  cableCals_[i]->setIsOk(false);
1356  numOfOutliers++;
1357  };
1358  };
1359  // and adjust the data structures:
1360  if (numOfOutliers)
1361  {
1362  int j;
1363  for (int i=0; i<onSourceRecords_.size(); i++)
1364  {
1367  j = 0;
1368  while (j < cl.size())
1369  if (!cl.at(j)->getIsOk())
1370  cl.removeAt(j);
1371  else
1372  j++;
1373  };
1374  j = 0;
1375  while (j < cableCals_.size())
1376  if (!cableCals_.at(j)->getIsOk())
1377  {
1378  delete cableCals_[j];
1379  cableCals_[j] = NULL;
1380  cableCals_.removeAt(j);
1381  }
1382  else
1383  j++;
1385  "::cleanCableCalibrations(): station " + stationName_ + ": " +
1386  QString("").setNum(numOfOutliers) + " outlier" +
1387  QString(numOfOutliers==1?" has ":"s have ") + "been removed", true);
1388  };
1389  };
1390  //
1391  // remove average:
1392  vAverage = 0.0;
1393  for (int i=0; i<cableCals_.size(); i++)
1394  vAverage += cableCals_.at(i)->getV();
1395  vAverage /= cableCals_.size();
1396  for (int i=0; i<cableCals_.size(); i++)
1397  cableCals_.at(i)->setV(cableCals_.at(i)->getV() - vAverage);
1399  "::cleanCableCalibrations(): station " + stationName_ + ": subtracted the average value of " +
1400  QString("").setNum(vAverage*1.0e9) + "ns from the cable cal readings");
1401 };
1402 
1403 
1404 
1405 //
1407 {
1408  // first, make sure the parameters are in time order:
1409  QMap<QString, SgMeteoReading*>
1410  mpByEpoch;
1411  QString str("");
1412  double d, dt, extrRmin=0.0, extrRmax=1.0;
1413  int nExtr4Rmin=0, nExtr4Rmax=0, numOfDuples=0, numOfSameEpochs=0;
1414  SgMJD t;
1415 
1416  // first, check meteo parameters:
1417  for (int i=0; i<meteoPars_.size(); i++)
1418  {
1419  t = meteoPars_.at(i)->getT();
1420  str = t.toString(SgMJD::F_INTERNAL);
1421  //
1422  // check for duplicates:
1423  if (mpByEpoch.contains(str))
1424  {
1425  if (*mpByEpoch[str] == *meteoPars_.at(i))
1426  {
1428  "::cleanMeteoParameters(): station " + stationName_ + ": got duplicate weather record at " +
1430  numOfDuples++;
1431  }
1432  else
1433  {
1434  logger->write(SgLogger::ERR, SgLogger::IO, className() + "::cleanMeteoParameters(): station " +
1435  stationName_ + ": got two different records at the same epoch " +
1437  numOfSameEpochs++;
1438  };
1439  delete meteoPars_.at(i);
1440  }
1441  else
1442  mpByEpoch.insert(str, meteoPars_.at(i));
1443  };
1444  //
1445  if (numOfDuples)
1447  "::cleanMeteoParameters(): station " + stationName_ + ": " + QString("").setNum(numOfDuples) +
1448  " duplicate meteo records found");
1449  if (numOfSameEpochs)
1451  "::cleanMeteoParameters(): station " + stationName_ + ": " + QString("").setNum(numOfSameEpochs) +
1452  " records with the same epoch and different values found");
1453  //
1454  //
1455 // for (int i=0; i<meteoPars_.size(); i++)
1456 // delete meteoPars_.at(i);
1457  meteoPars_.clear();
1458  meteoPars_ = mpByEpoch.values();
1459  mpByEpoch.clear();
1460  //
1461  if (meteoPars_.size() <= 2)
1462  {
1464  "::cleanMeteoParameters(): station " + stationName_ + ": too small number of meteo records (" +
1465  QString("").setNum(meteoPars_.size()) + "), nothing to do");
1466  return;
1467  };
1468  //
1469  //
1470  int nPars(meteoPars_.size());
1471  SgVector dP(nPars), dT(nPars), dR(nPars);
1472  t = meteoPars_.at(0)->getT();
1473  for (int i=1; i<nPars; i++)
1474  {
1475  t = meteoPars_.at(i)->getT();
1476  //
1477  // calculate reates:
1478  dt = t - meteoPars_.at(i-1)->getT();
1479  d = meteoPars_.at(i)->getM().getPressure() - meteoPars_.at(i-1)->getM().getPressure();
1480  if (0.15 < fabs(d)) // current format has one digit after dot:
1481  dP.setElement(i, d/dt);
1482 
1483  d = meteoPars_.at(i)->getM().getTemperature() - meteoPars_.at(i-1)->getM().getTemperature();
1484  if (0.15 < fabs(d)) // current format has one digit after dot:
1485  dT.setElement(i, d/dt);
1486 
1487  d = meteoPars_.at(i)->getM().getRelativeHumidity() - meteoPars_.at(i-1)->getM().getRelativeHumidity();
1488  if (0.15 < fabs(d)) // current format has one digit after dot:
1489  dR.setElement(i, d/dt);
1490  //
1491  // check for extremums:
1492  if (fabs(meteoPars_.at(i)->getM().getRelativeHumidity() - extrRmin) < 1.0e-6)
1493  nExtr4Rmin++;
1494  if (fabs(meteoPars_.at(i)->getM().getRelativeHumidity() - extrRmax) < 1.0e-6)
1495  nExtr4Rmax++;
1496  //
1497  };
1498 
1499  //
1500  double mrP, mrT, mrR;
1501  int n4P=0, n4T=0, n4R=0;
1502  bool isOkP=true, isOkT=true, isOkR=true, hasSuspiciousExtrems4R=false;
1503  // max allowable rates:
1504  mrP =100.0*24.0; // 100 mbar per hour
1505  mrT =200.0*24.0; // 200 degree per hour
1506  mrR = 10.0*24.0; // 1000% per hour
1507  for (int i=1; i<nPars; i++)
1508  {
1509  if (mrP < fabs(dP.getElement(i)))
1510  {
1512  "::cleanMeteoParameters(): station " + stationName_ +
1513  " has too big pressure rate, " + QString("").setNum(dP.getElement(i)/24.0) +
1514  "(mbar/hr) at the idx " + QString("").setNum(i));
1515  n4P++;
1516  };
1517  if (mrT < fabs(dT.getElement(i)))
1518  {
1520  "::cleanMeteoParameters(): station " + stationName_ +
1521  " has too big atm.temperature rate, " + QString("").setNum(dT.getElement(i)/24.0) +
1522  "(C/hr) at the idx " + QString("").setNum(i));
1523  n4T++;
1524  };
1525  if (mrR < fabs(dR.getElement(i)))
1526  {
1528  "::cleanMeteoParameters(): station " + stationName_ +
1529  " has too big rel.humidity rate, " + QString("").setNum(100.0*dR.getElement(i)/24.0) +
1530  "(%/hr) at the idx " + QString("").setNum(i));
1532  "::cleanMeteoParameters(): station " + stationName_ + ": i-1: " +
1533  meteoPars_.at(i-1)->getT().toString(SgMJD::F_Simple) + " " +
1534  QString("").sprintf("%.4f", meteoPars_.at(i-1)->getM().getRelativeHumidity()) +
1535  "; i: " + meteoPars_.at(i)->getT().toString(SgMJD::F_Simple) + " " +
1536  QString("").sprintf("%.4f", meteoPars_.at(i)->getM().getRelativeHumidity()));
1537 
1538  n4R++;
1539  };
1540  };
1541  if (n4P>10)
1542  {
1543  isOkP = false;
1545  "::cleanMeteoParameters(): station " + stationName_ + " has more than 10 (" +
1546  QString("").setNum(n4P) + ") suspicious big pressure rates, use standard pressure instead");
1547  };
1548  if (n4T>10)
1549  {
1550  isOkT = false;
1552  "::cleanMeteoParameters(): station " + stationName_ + " has more than 10 (" +
1553  QString("").setNum(n4T) +
1554  ") suspicious big atm.temperature rates, use default temperature instead");
1555  };
1556  if (n4R>10)
1557  {
1558  isOkR = false;
1560  "::cleanMeteoParameters(): station " + stationName_ + " has more than 10 (" +
1561  QString("").setNum(n4R) +
1562  ") suspicious big rel.humidity rates, use default humidity instead");
1563  };
1564  if (8 < nExtr4Rmin && 8 < nExtr4Rmax)
1565  {
1567  "::cleanMeteoParameters(): station " + stationName_ + " has too much extremal values (" +
1568  QString("").setNum(nExtr4Rmin) + "/" + QString("").setNum(nExtr4Rmax) +
1569  ") for rel.humidity, use default humidity instead");
1570  hasSuspiciousExtrems4R = true;
1571  };
1572  //
1573  //
1574  // if one of readings is wrong, set it to constant:
1575  if (!isOkP || !isOkT || !isOkR || hasSuspiciousExtrems4R)
1576  {
1577  SgMeteoData m;
1578  for (int i=0; i<meteoPars_.size(); i++)
1579  {
1580  m = meteoPars_.at(i)->getM();
1581  if (!isOkP)
1582  m.setPressure(1013.25);
1583  if (!isOkT)
1584  m.setTemperature(10.0);
1585  if (!isOkR || hasSuspiciousExtrems4R)
1586  m.setRelativeHumidity(0.5);
1587  meteoPars_.at(i)->setM(m);
1588  };
1589  };
1590  //
1592  "::cleanMeteoParameters(): station " + stationName_ + ": the meteoparameters have been ordered");
1593 };
1594 
1595 
1596 
1597 //
1599 {
1600  SgMJD &t=*aux;
1601  int idx_r=0;
1602  int idx_l=meteoPars_.size() - 1;
1603  //
1604  // limit the extrapolation:
1605  if (600.0/DAY2SEC < meteoPars_.at(idx_r)->getT() - t) // 10 mins
1606  {
1607  aux->setMeteoData(meteoPars_.at(idx_r)->getM());
1609  "::interpolateMeteoParameters(): station " + stationName_ + ": epoch " + t.toString() +
1610  " is too far from the first available meteo reading (" + meteoPars_.at(idx_r)->getT().toString() +
1611  "), no extrapolation");
1612  return;
1613  };
1614  if (600.0/DAY2SEC < t - meteoPars_.at(idx_l)->getT()) // 10 mins
1615  {
1616  aux->setMeteoData(meteoPars_.at(idx_l)->getM());
1618  "::interpolateMeteoParameters(): station " + stationName_ + ": epoch " + t.toString() +
1619  " is too far from the last available meteo reading (" + meteoPars_.at(idx_l)->getT().toString() +
1620  "), no extrapolation");
1621  return;
1622  };
1623  //
1624  // assume that first and last measurements are ok
1625  if (t < meteoPars_.at(idx_r)->getT())
1626  idx_l = idx_r++;
1627  else if (meteoPars_.at(idx_l)->getT() < t)
1628  idx_r = idx_l--;
1629  else
1630  {
1631  while (meteoPars_.at(idx_r)->getT()<t && idx_r<meteoPars_.size()-1)
1632  idx_r++;
1633  while (t<meteoPars_.at(idx_l)->getT() && 0<idx_l)
1634  idx_l--;
1635  };
1636  //
1637  //
1638  if (idx_l == idx_r)
1639  aux->setMeteoData(meteoPars_.at(idx_r)->getM());
1640  else
1641  {
1642  double dt, dPr, dTp, dRh, x;
1643  dt = meteoPars_.at(idx_r)->getT() - meteoPars_.at(idx_l)->getT();
1644  x = t - meteoPars_.at(idx_l)->getT();
1645  dPr = meteoPars_.at(idx_r)->getM().getPressure() -
1646  meteoPars_.at(idx_l)->getM().getPressure();
1647  dTp = meteoPars_.at(idx_r)->getM().getTemperature() -
1648  meteoPars_.at(idx_l)->getM().getTemperature();
1649  dRh = meteoPars_.at(idx_r)->getM().getRelativeHumidity() -
1650  meteoPars_.at(idx_l)->getM().getRelativeHumidity();
1651  aux->meteoData().setPressure(meteoPars_.at(idx_l)->getM().getPressure() + dPr/dt*x);
1652  aux->meteoData().setTemperature(meteoPars_.at(idx_l)->getM().getTemperature() + dTp/dt*x);
1653  aux->meteoData().setRelativeHumidity(meteoPars_.at(idx_l)->getM().getRelativeHumidity() + dRh/dt*x);
1654  };
1655 };
1656 
1657 
1658 
1659 //
1661 {
1662  QRegExp reBrokenScanName("([a-zA-Z0-9+-]+)_.+", Qt::CaseInsensitive);
1663  bool isScanNameSuspicious;
1664  //
1665  int numOfExactMatches, numOfMultExactMatches, numOfClosestMatches, cSign;
1666  int numOfChannels, chanIdx, ccIdx;
1667  bool hasMeteoOk, hasCableOk, hasTsysOk;
1668  SgMJD t(tZero);
1669  SgVector *tS;
1670  numOfExactMatches = numOfMultExactMatches = numOfClosestMatches = 0;
1671  hasMeteoOk = hasCableOk = hasTsysOk = false;
1672  static const QString sideBand2str[] = {"UNDEF", "LSB", "USB", "DUAL"};
1673  static const QString polarization2str[] = {"UNDEF", "RCP", "LCP", "HLP", "VLP"};
1674 
1675  cSign = cableSign_;
1676  if (cSign==0)
1677  cSign = 1; // no cable sign found
1678 
1679  ccIdx = SgVlbiAuxObservation::CCT_FSLG; // idx => FS log
1680  if (itType_ == IT_CDMS)
1681  ccIdx = SgVlbiAuxObservation::CCT_CDMS; // idx => CDMS
1682  else if (itType_ == IT_PCMT)
1683  ccIdx = SgVlbiAuxObservation::CCT_PCMT; // idx => PCMT
1684  // adjust the index if CDMS data are from FS log file
1686  ccIdx = SgVlbiAuxObservation::CCT_CDMS; // idx => CDMS too
1687 
1688  //
1689  numOfChannels = channelSetup_.ifIdByTpSensorKey().size();
1690  tS = new SgVector(numOfChannels);
1691  //
1693  for (QMap<QString, SgVlbiAuxObservation*>::iterator it=stn->auxObservationByScanId()->begin();
1694  it!=stn->auxObservationByScanId()->end(); ++it)
1695  {
1696  SgVlbiAuxObservation *aux=it.value();
1697  QString scanName=aux->getOwner()->getScanName().simplified().toLower();
1698  QString scanNameAux("");
1699  QString sourceName=aux->getOwner()->src()->getKey();
1700  QString surrogateScanName("");
1701  int idx4Cable=-1;
1703  double dt, f;
1704 
1705  //
1706  // set up scan start time:
1707  if (itType_==IT_CDMS || itType_==IT_PCMT)
1708  {
1709  if (aux->getOwner()->observableByKey().size())
1710  t = aux->getOwner()->observableByKey().begin().value()->getTstart();
1711  else
1712  t = tZero;
1713  }
1714  else
1715  t = *aux;
1716  //
1717  for (int i=0; i<numOfChannels; i++)
1718  tS->setElement(i, -4.0);
1719  //
1720  // workaround a database bug:
1721  isScanNameSuspicious = reBrokenScanName.indexIn(scanName) != -1;
1722  if (isScanNameSuspicious)
1723  scanNameAux = reBrokenScanName.cap(1).toLower();
1724  if (scanName.size()==9 && scanName.at(8).isLetter())
1725  surrogateScanName = scanName.left(8);
1726  //
1727  // here is a missed scan, e.g. the FS has been restarted:
1728  if (!recordByScan_.contains(scanName) && !isScanNameSuspicious)
1729  {
1730  if (itType_==IT_FSLG)
1732  "::propagateData(): station " + stationName_ + ": cannot find the scan \"" + scanName +
1733  "\" in the log file");
1734  }
1735  else if (isScanNameSuspicious && !recordByScan_.contains(scanNameAux))
1736  {
1737  if (itType_==IT_FSLG)
1739  "::propagateData(): station " + stationName_ + ": cannot find the suspicious scan \"" +
1740  scanNameAux + "\"' in the log file");
1741  }
1742  else if (surrogateScanName.size() &&
1743  !recordByScan_.contains(surrogateScanName) &&
1744  !recordByScan_.contains(scanName))
1745  {
1746  if (itType_==IT_CDMS)
1748  "::propagateData(): station " + stationName_ + ": cannot find the surrogate scan \"" +
1749  scanNameAux + "\"' in the CDMS file");
1750  }
1751  else
1752  {
1753  SgOnSourceRecord *osRec=recordByScan_.value(scanName);
1754  if (!osRec && isScanNameSuspicious)
1755  osRec = recordByScan_.value(scanNameAux);
1756  else if (!osRec && surrogateScanName.size())
1757  osRec = recordByScan_.value(surrogateScanName);
1758  //
1759  if (osRec) // just in case
1760  {
1761  //
1762  // cable calibration:
1764  {
1765  if (osRec->cableCals().size())
1766  {
1767  cables = &osRec->cableCals();
1768  numOfExactMatches++;
1769  }
1770  else
1771  {
1773  "::propagateData(): station " + stationName_ +
1774  ": no cable cal record found for the scan \"" + scanName + "\" in the log file");
1775  numOfClosestMatches++;
1776  };
1777  //
1778  if (osRec->cableCals().size() == 1) // only one record with cable cals:
1779  idx4Cable = 0;
1780  else if (osRec->cableCals().size() > 1)
1781  {
1782  /*
1783  logger->write(SgLogger::DBG, SgLogger::IO, className() +
1784  "::propagateData(): station " + stationName_ + ": found more than one (" +
1785  QString("").setNum(osRec->cableCals().size()) + ") cable cal records for the scan [" +
1786  scanName + "] in the log file");
1787  */
1788  numOfMultExactMatches++;
1789  };
1790  // check source name:
1791  if (osRec->getSourceName().leftJustified(8, ' ') != sourceName)
1793  "::propagateData(): source name mismatch: from the log: \"" + osRec->getSourceName() +
1794  "\", from the obs: \"" + sourceName + "\"");
1795  };
1796  //
1797  if (areTsysesPresent_ && osRec->tSyses().size())
1798  {
1799  SgTsysReading *tsr=NULL;
1800  if (osRec->tSyses().size() == 1)
1801  tsr = osRec->tSyses().last();
1802  else
1803  {
1804  int idx=0;
1805  dt = fabs(osRec->tSyses().at(0)->getT() - t);
1806  for (int i=1; i<osRec->tSyses().size(); i++)
1807  if ((f=fabs(osRec->tSyses().at(i)->getT() - t)) < dt)
1808  {
1809  idx = i;
1810  dt = f;
1811  };
1812  tsr = osRec->tSyses().at(idx);
1813  };
1814  //
1815  chanIdx = 0;
1816  if (tsr)
1817  for (QMap<QString, QString>::const_iterator jt=channelSetup_.ifIdByTpSensorKey().begin();
1818  jt!=channelSetup_.ifIdByTpSensorKey().end(); ++jt, chanIdx++)
1819  if (tsr->getTsys().contains(jt.value()))
1820  tS->setElement(chanIdx, tsr->getTsys().value(jt.value()));
1821  //
1823  1 < osRec->tSyses().size())
1825  "::propagateData(): station " + stationName_ +
1826  ": the OnSource record has more than one (" +
1827  QString("").setNum(osRec->tSyses().size()) + ") TSYS record for the scan \"" +
1828  scanName + "\"");
1829  };
1830  }
1831  else
1833  "::propagateData(): the OnSource record is NULL: the station= " + stationName_ +
1834  ", the scan= \"" + scanName + "\"");
1835  };
1836  // set up:
1837  // meteo:
1839  {
1841  hasMeteoOk = true;
1842  };
1843  // cable calibration:
1845  {
1846  if (idx4Cable == -1)
1847  {
1848  dt = fabs(cables->at((idx4Cable=0))->getT() - t);
1849  for (int i=1; i<cables->size(); i++)
1850  if ((f=fabs(cables->at(i)->getT() - t)) < dt)
1851  {
1852  idx4Cable = i;
1853  dt = f;
1854  };
1855  };
1856  aux->setCableCalibration(cables->at(idx4Cable)->getV()*cSign);
1857  aux->cableCorrections().setElement(ccIdx, cables->at(idx4Cable)->getV()*cSign);
1858  hasCableOk = true;
1859  };
1860  // tsys:
1862  {
1863  aux->setTsyses(*tS);
1864  hasTsysOk = true;
1865  };
1866  };
1867  //
1868  //
1869  if (hasCableOk)
1870  {
1873  stn->setCableCalMultiplierDBCal(cSign);
1875  "::propagateData(): station " + stationName_ + ": " + QString("").setNum(numOfExactMatches) +
1876  " exact " + (numOfMultExactMatches?("(" + QString("").setNum(numOfMultExactMatches) +
1877  (numOfMultExactMatches==1?" is ":" are ") + "multiple) "):"") +
1878  (numOfClosestMatches?"and " + QString("").setNum(numOfClosestMatches) + " closest ":"") +
1879  "matches of cable calibrations were found");
1880  };
1881  if (hasMeteoOk)
1882  {
1886  "::propagateData(): station " + stationName_ + ": meteo parameters were found");
1887  };
1888  if (hasTsysOk)
1889  {
1892  //set up channel info:
1893  stn->tsysIfFreqs().resize(numOfChannels);
1894  stn->tsysIfIds().resize(numOfChannels);
1895  stn->tsysIfSideBands().resize(numOfChannels);
1896  stn->tsysIfPolarizations().resize(numOfChannels);
1897  chanIdx = 0;
1898  for (QMap<QString, QString>::const_iterator jt=channelSetup_.ifIdByTpSensorKey().begin();
1899  jt!=channelSetup_.ifIdByTpSensorKey().end(); ++jt, chanIdx++)
1900  {
1901  const QString &id=jt.value();
1902  const QString &sensorKey=jt.key();
1903  //
1904  stn->tsysIfIds()[chanIdx] = id;
1905  stn->tsysIfFreqs()[chanIdx] = channelSetup_.ifFreqByTpSensorKey()[sensorKey];
1906  //
1908  stn->tsysIfSideBands()[chanIdx] = sideBand2str[sb];
1909  //
1911  stn->tsysIfPolarizations()[chanIdx] = polarization2str[pz];
1912  };
1913 
1915  "::propagateData(): station " + stationName_ + ": tsys data were found");
1916  };
1917 
1918  //
1919  delete tS;
1920  //
1921  return hasMeteoOk || hasCableOk || hasTsysOk;
1922 };
1923 
1924 
1925 
1926 //
1928 {
1929  int allocatedNum=0;
1930  for (int i=0; i<cableCals_.size(); i++)
1931  {
1932  SgCableCalReading *cbl=cableCals_.at(i);
1933  for (int j=0; j<onSourceRecords_.size(); j++)
1934  {
1935  SgOnSourceRecord *osRec=onSourceRecords_.at(j);
1936  if (osRec->getTstart() <= cbl->getT() && cbl->getT() <= osRec->getTfinis())
1937  {
1938  osRec->cableCals() << cbl;
1939  allocatedNum++;
1940  };
1941  };
1942  };
1944  "::allocateCableReadings(): station " + stationName_ + ": " + QString("").setNum(allocatedNum) +
1945  " cable cal readings were linked to on data records");
1946 };
1947 
1948 
1949 
1950 //
1952 {
1953  QString str("");
1954  int idx;
1955 
1956 //s << "#\nNUMB_FRQ: " << channelSetup_.ifIdxById().size() << "\n#\n";
1957  s << "#\nNUMB_FRQ: " << channelSetup_.ifIdByTpSensorKey().size() << "\n#\n";
1958  s << "# Sensor# IF_Freq LO_Freq Sky_freq Pol SensorId Channel# SideBand\n#\n";
1959 
1960  idx = 1;
1961 //for (QMap<QString, int>::const_iterator it=channelSetup_.ifIdxById().begin();
1962 // it!=channelSetup_.ifIdxById().end(); ++it)
1963  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
1964  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it)
1965  {
1966  QString ifKey(it.key());
1967  QString ifId(it.value());
1968 
1969  int cIdx=-1;
1970  if (!channelSetup_.ifIdxById().contains(ifId))
1971  {
1973  "::export2antabFrqs_nativeSetup(): station " + stationName_ +
1974  ": cannot find IF index for if with the id \"" + ifId + "\"");
1975  continue;
1976  }
1977  else
1978  cIdx = channelSetup_.ifIdxById().value(ifId);
1979 
1980 // int cIdx=it.value();
1981 // QString ifId(it.key());
1982  QString loId("");
1985  SgChannelPolarization polarization=CP_UNDEF;
1986  double ifFrq, loFrq, skyFrq, bw;
1987  ifFrq = loFrq = skyFrq = bw = 0.0;
1988 
1989  if (channelSetup_.loIdByIdx().contains(cIdx))
1990  loId = channelSetup_.loIdByIdx().value(cIdx);
1991  else if (channelSetup_.loIdByCid().contains(ifId))
1992  loId = channelSetup_.loIdByCid().value(ifId);
1993  if (loId.size())
1994  {
1995  // LO side band:
1996  if (channelSetup_.loSideBandById().contains(loId))
1997  loSb = channelSetup_.loSideBandById().value(loId);
1998  else
2000  "::export2antabFrqs_nativeSetup(): station " + stationName_ + ": cannot find side band for LO \"" +
2001  loId + "\"");
2002 
2003  // channel side band:
2004  if (channelSetup_.ifSideBandById().contains(ifId))
2005  ifSb = channelSetup_.ifSideBandById().value(ifId);
2006  else
2008  "::export2antabFrqs_nativeSetup(): station " + stationName_ + ": cannot find side band for channel #" +
2009  QString("").setNum(cIdx) + ", ID: \"" + ifId + "\"");
2010 
2011  // polarization:
2012  if (channelSetup_.loPolarizationById().contains(loId))
2013  polarization = channelSetup_.loPolarizationById().value(loId);
2014  else
2016  "::export2antabFrqs_nativeSetup(): station " + stationName_ + ": cannot find polarization for LO \"" +
2017  loId + "\"");
2018 
2019  // bandwidth:
2020  if (channelSetup_.bbcBandwidthByIdx().contains(cIdx))
2021  bw = channelSetup_.bbcBandwidthByIdx().value(cIdx);
2022  else
2024  "::export2antabFrqs_nativeSetup(): station " + stationName_ + ": cannot find bandwidth for channel #" +
2025  QString("").setNum(cIdx) + ", ID=" + ifId);
2026 
2027  if (channelSetup_.bbcFreqByIdx().contains(cIdx))
2028  {
2029  ifFrq = channelSetup_.bbcFreqByIdx().value(cIdx);
2030  //
2031  if (loSb == CSB_USB && ifSb == CSB_USB)
2032  ifFrq = channelSetup_.bbcFreqByIdx().value(cIdx);
2033  else if (loSb == CSB_USB && ifSb == CSB_LSB)
2034  ifFrq = channelSetup_.bbcFreqByIdx().value(cIdx) - bw;
2035  else if (loSb == CSB_LSB && ifSb == CSB_LSB)
2036  ifFrq = - channelSetup_.bbcFreqByIdx().value(cIdx) - bw;
2037 // ifFrq = - channelSetup_.bbcFreqByIdx().value(cIdx);
2038  else if (loSb == CSB_LSB && ifSb == CSB_USB)
2039  ifFrq = - channelSetup_.bbcFreqByIdx().value(cIdx);
2040 // ifFrq = - channelSetup_.bbcFreqByIdx().value(cIdx) - bw;
2041  }
2042  else
2044  "::export2antabFrqs_nativeSetup(): station " + stationName_ + ": cannot find BBC_FRQ for channel #" +
2045  QString("").setNum(cIdx));
2046 
2047  if (channelSetup_.loFreqById().contains(loId))
2048  loFrq = channelSetup_.loFreqById().value(loId);
2049  else
2051  "::export2antabFrqs_nativeSetup(): station " + stationName_ + ": cannot find LO frq for channel #" +
2052  QString("").setNum(cIdx) + ", loID=" + loId);
2053 
2054  skyFrq = loFrq + ifFrq;
2055  }
2056  else
2058  "::export2antabFrqs_nativeSetup(): station " + stationName_ + ": cannot find LO ID for channel #" +
2059  QString("").setNum(cIdx));
2060 
2061  channelSetup_.ifFreqByIdx()[cIdx] = skyFrq;
2062  channelSetup_.ifPolarizationById()[ifId] = polarization;
2063 
2064  str.sprintf("FRQ: %7d %11.2f %11.2f %11.2f",
2065  idx, ifFrq, loFrq, skyFrq);
2066  s << str << " ";
2067  if (polarization == CP_RightCP)
2068  s << " R";
2069  else if (polarization == CP_LeftCP)
2070  s << " L";
2071  else
2072  s << " ?";
2073 
2074  str.sprintf(" %6s ", qPrintable(ifId));
2075  s << str;
2076  str.sprintf("%6d", cIdx);
2077  s << str << " ";
2078 
2079  if (ifSb == CSB_USB)
2080  s << "USB";
2081  else if (ifSb == CSB_LSB)
2082  s << "LSB";
2083  else if (ifSb == CSB_DUAL)
2084  s << "USB/LSB";
2085  else
2086  s << "UNK";
2087  s << "\n";
2088  idx++;
2089  };
2090  s << "#\n";
2091 };
2092 
2093 
2094 
2095 //
2097 {
2098  QString str("");
2099  int idx;
2100 
2101  s << "#\nNUMB_FRQ: " << channelSetup_.ifIdByTpSensorKey().size() << "\n#\n";
2102  s << "# Sensor# IF_Freq LO_Freq Sky_freq Pol SensorId Channel# SideBand\n#\n";
2103 
2104  idx = 1;
2105  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
2106  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it)
2107  {
2108  QString ifKey(it.key());
2109  QString ifId(it.value());
2110  QString loId("");
2111 
2112  int cIdx=-1;
2113  if (!channelSetup_.ifIdxById().contains(ifId))
2114  {
2116  "::export2antabFrqs_vgosSetup(): station " + stationName_ +
2117  ": cannot find IF index for if with the id \"" + ifId + "\"");
2118  continue;
2119  }
2120  else
2121  cIdx = channelSetup_.ifIdxById().value(ifId);
2122 
2124  SgChannelPolarization polarization=CP_UNDEF;
2125  double skyFrq, loFrq=-1.0;
2126  skyFrq = -1.0;
2127 
2128  // channel side band:
2129  if (channelSetup_.ifSideBandById().contains(ifId))
2130  ifSb = channelSetup_.ifSideBandById().value(ifId);
2131  else
2133  "::export2antabFrqs_vgosSetup(): station " + stationName_ +
2134  ": cannot find side band for channel #" + QString("").setNum(cIdx) + ", ID: \"" + ifId + "\"");
2135 
2136  // bandwidth:
2137  skyFrq = channelSetup_.ifFreqByIdx()[cIdx];
2138 
2139  if (channelSetup_.loIdByIdx().contains(cIdx))
2140  loId = channelSetup_.loIdByIdx().value(cIdx);
2141  else if (channelSetup_.loIdByCid().contains(ifId))
2142  loId = channelSetup_.loIdByCid().value(ifId);
2143 
2144 
2145  if (loId.size() && channelSetup_.loFreqById().contains(loId))
2146  loFrq = channelSetup_.loFreqById().value(loId);
2147  else
2149  "::export2antabFrqs_vgosSetup(): station " + stationName_ +
2150  ": cannot find LO frq for channel #" + QString("").setNum(cIdx) + ", loID=\"" + loId + "\"");
2151 
2152 
2153  // polarization:
2154  if (channelSetup_.loPolarizationById().contains(ifId))
2155  polarization = channelSetup_.loPolarizationById().value(ifId);
2156  else
2158  "::export2antabFrqs_vgosSetup(): station " + stationName_ +
2159  ": cannot find polarization for LO \"" + ifId + "\"");
2160 
2161  channelSetup_.ifPolarizationById()[ifId] = polarization;
2162 
2163  str.sprintf("FRQ: %7d %11.2f %11.2f %11.2f ",
2164  idx, -1.0, loFrq, skyFrq);
2165  s << str;
2166 
2167  if (polarization == CP_RightCP)
2168  s << " R";
2169  else if (polarization == CP_LeftCP)
2170  s << " L";
2171  else if (polarization == CP_HorizontalLP)
2172  s << " H";
2173  else if (polarization == CP_VerticalLP)
2174  s << " V";
2175  else
2176  s << " ?";
2177 
2178  str.sprintf(" %6s %6d ", qPrintable(ifId), cIdx);
2179  s << str;
2180 
2181  if (ifSb == CSB_USB)
2182  s << "USB";
2183  else if (ifSb == CSB_LSB)
2184  s << "LSB";
2185  else
2186  s << "UNK";
2187  s << "\n";
2188  idx++;
2189  };
2190  s << "#\n";
2191 };
2192 
2193 
2194 
2195 //
2197 {
2198  QString str("");
2199  int idx;
2200 
2201  if (channelSetup_.ifIdxById().size() != sCfg.getChannelCfgs().size())
2202  {
2204  "::export2antabFrqs_skededSetup(): station " + stationName_ +
2205  ": number of channels are different");
2206  return;
2207  };
2208 //std::cout << " -- 1: sCfg.getChannelCfgs().size()=" << sCfg.getChannelCfgs().size() << "\n";
2209  s << "#\nNUMB_FRQ: " << channelSetup_.ifIdxById().size() << "\n#\n";
2210  s << "# Sensor# IF_Freq LO_Freq Sky_freq Pol SensorId Channel# SideBand\n#\n";
2211 
2212  idx = 1;
2213 
2214  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
2215  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it)
2216  {
2217  QString ifKey(it.key());
2218  QString ifId(it.value());
2219 
2220  int cIdx=-1;
2221  if (!channelSetup_.ifIdxById().contains(ifId))
2222  {
2224  "::export2antabFrqs_nativeSetup(): station " + stationName_ +
2225  ": cannot find IF index for if with the id \"" + ifId + "\"");
2226  continue;
2227  }
2228  else
2229  cIdx = channelSetup_.ifIdxById().value(ifId);
2230 
2232  double skyFrq, bw;
2233  skyFrq = bw = 0.0;
2234  // channel side band:
2235  if (channelSetup_.ifSideBandById().contains(ifId))
2236  ifSb = channelSetup_.ifSideBandById().value(ifId);
2237  else
2239  "::export2antabFrqs_skededSetup(): station " + stationName_ + ": cannot find side band for channel #" +
2240  QString("").setNum(cIdx) + ", ID: \"" + ifId + "\"");
2241  // bandwidth:
2242  bw = sCfg.getChannelCfgs().at(idx - 1).getBandWidth();
2243  skyFrq = sCfg.getChannelCfgs().at(idx - 1).getSkyFrq();
2244  channelSetup_.ifFreqByIdx()[cIdx] = skyFrq;
2246 
2247  str.sprintf("FRQ: %7d %11.2f %11.2f %11.2f",
2248  idx, -1.0, -1.0, skyFrq);
2249  s << str << " ";
2250  s << " ?";
2251 
2252  str.sprintf(" %6s ", qPrintable(ifId));
2253  s << str;
2254  str.sprintf("%6d", cIdx);
2255  s << str << " ";
2256 
2257  if (ifSb == CSB_USB)
2258  s << "USB";
2259  else if (ifSb == CSB_LSB)
2260  s << "LSB";
2261  else
2262  s << "UNK";
2263  s << "\n";
2264  idx++;
2265  };
2266  s << "#\n";
2267 //std::cout << " -- 10\n";
2268 };
2269 
2270 
2271 
2272 //
2274 {
2275  QString str("");
2276  int idx;
2277 
2278  s << "#\nNUMB_FRQ: " << channelSetup_.ifIdxById().size() << "\n#\n";
2279  s << "# Sensor# IF_Freq LO_Freq Sky_freq Pol SensorId Channel# SideBand\n#\n";
2280 
2281  idx = 1;
2282 
2283  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
2284  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it, idx++)
2285  {
2286  QString ifKey(it.key());
2287  QString ifId(it.value());
2288 
2289  int cIdx=-1;
2290  if (!channelSetup_.ifIdxById().contains(ifId))
2291  {
2293  "::export2antabFrqs_missedSetup(): station " + stationName_ +
2294  ": cannot find IF index for if with the id \"" + ifId + "\"");
2295  continue;
2296  }
2297  else
2298  cIdx = channelSetup_.ifIdxById().value(ifId);
2299 
2301 
2302  // channel side band:
2303  if (channelSetup_.ifSideBandById().contains(ifId))
2304  ifSb = channelSetup_.ifSideBandById().value(ifId);
2305  else
2307  "::export2antabFrqs_missedSetup(): station " + stationName_ +
2308  ": cannot find side band for channel #" + QString("").setNum(cIdx) +
2309  ", ID: \"" + ifId + "\"");
2310 
2311  channelSetup_.ifFreqByIdx()[cIdx] = -1.0;
2313  channelSetup_.ifSideBandById()[ifId] = ifSb;
2314 
2315  str.sprintf("FRQ: %7d %11.2f %11.2f %11.2f",
2316  idx, -1.0, -1.0, -1.0);
2317  s << str << " ?";
2318 
2319  str.sprintf(" %6s ", qPrintable(ifId));
2320  s << str;
2321  str.sprintf("%6d", cIdx);
2322  s << str << " ";
2323 
2324  if (ifSb == CSB_USB)
2325  s << "USB";
2326  else if (ifSb == CSB_LSB)
2327  s << "LSB";
2328  else
2329  s << "UNK";
2330  s << "\n";
2331  };
2332 
2333  s << "#\n";
2334 };
2335 
2336 
2337 
2338 //
2340 {
2341  bool isOk;
2342  double skyFrq, bw;
2343  int idx;
2344  QMap<int, double> frqByIdx_Fsl, frqByIdx_Skd;
2345  QMap<int, double> bwByIdx_Fsl, bwByIdx_Skd;
2346  int numOfChansAtSked, numOfChansAtLog;
2347 
2348  numOfChansAtSked = numOfChansAtLog = 0;
2349  isOk = true;
2350  //
2351  // sked's:
2352  for (int i=0; i<sCfg.getChannelCfgs().size(); i++)
2353  {
2354  bw = sCfg.getChannelCfgs().at(i).getBandWidth();
2355  skyFrq = sCfg.getChannelCfgs().at(i).getSkyFrq();
2356  frqByIdx_Skd[i] = skyFrq;
2357  bwByIdx_Skd[i] = bw;
2358  numOfChansAtSked++;
2359  };
2360 
2361  // FS log:
2362  idx = 0;
2363  for (QMap<QString, int>::const_iterator it=channelSetup_.ifIdxById().begin();
2364  it!=channelSetup_.ifIdxById().end(); ++it, idx++)
2365  {
2366  int cIdx=it.value();
2367  QString ifId(it.key());
2368  QString loId("");
2371  double ifFrq, loFrq, skyFrq, bw;
2372  ifFrq = loFrq = skyFrq = bw = 0.0;
2373 
2374  if (channelSetup_.loIdByIdx().contains(cIdx))
2375  loId = channelSetup_.loIdByIdx().value(cIdx);
2376  else if (channelSetup_.loIdByCid().contains(ifId))
2377  loId = channelSetup_.loIdByCid().value(ifId);
2378 
2379  if (loId.size())
2380  {
2381 // loId = channelSetup_.loIdByIdx().value(cIdx);
2382 
2383  // LO side band:
2384  if (channelSetup_.loSideBandById().contains(loId))
2385  loSb = channelSetup_.loSideBandById().value(loId);
2386  else
2388  "::compareChannelSetups(): station " + stationName_ + ": cannot find side band for LO \"" +
2389  loId + "\"");
2390 
2391  // channel side band:
2392  if (channelSetup_.ifSideBandById().contains(ifId))
2393  ifSb = channelSetup_.ifSideBandById().value(ifId);
2394  else
2396  "::compareChannelSetups(): station " + stationName_ + ": cannot find side band for channel #" +
2397  QString("").setNum(cIdx) + ", ID: \"" + ifId + "\"");
2398 
2399  // bandwidth:
2400  if (channelSetup_.bbcBandwidthByIdx().contains(cIdx))
2401  bw = channelSetup_.bbcBandwidthByIdx().value(cIdx);
2402  else
2404  "::compareChannelSetups(): station " + stationName_ + ": cannot find bandwidth for channel #" +
2405  QString("").setNum(cIdx) + ", ID=" + ifId);
2406 
2407  if (channelSetup_.bbcFreqByIdx().contains(cIdx))
2408  {
2409  ifFrq = channelSetup_.bbcFreqByIdx().value(cIdx);
2410  //
2411  if (loSb == CSB_USB && ifSb == CSB_USB)
2412  ifFrq = channelSetup_.bbcFreqByIdx().value(cIdx);
2413  else if (loSb == CSB_USB && ifSb == CSB_LSB)
2414  ifFrq = channelSetup_.bbcFreqByIdx().value(cIdx) - bw;
2415 // here is freq calculation is perverted -- at the time of reading sked file we do not know about
2416 // LO's sidebanad:
2417  else if (loSb == CSB_LSB && ifSb == CSB_LSB)
2418 // ifFrq = - channelSetup_.bbcFreqByIdx().value(cIdx) - bw;
2419  ifFrq = - channelSetup_.bbcFreqByIdx().value(cIdx);
2420  else if (loSb == CSB_LSB && ifSb == CSB_USB)
2421 // ifFrq = - channelSetup_.bbcFreqByIdx().value(cIdx);
2422  ifFrq = - channelSetup_.bbcFreqByIdx().value(cIdx) - bw;
2423  }
2424  else
2426  "::compareChannelSetups(): station " + stationName_ + ": cannot find BBC_FRQ for channel #" +
2427  QString("").setNum(cIdx));
2428 
2429  if (channelSetup_.loFreqById().contains(loId))
2430  loFrq = channelSetup_.loFreqById().value(loId);
2431  else
2433  "::compareChannelSetups(): station " + stationName_ + ": cannot find LO frq for channel #" +
2434  QString("").setNum(cIdx) + ", loID=" + loId);
2435 
2436  skyFrq = loFrq + ifFrq;
2437  }
2438  else
2440  "::compareChannelSetups(): station " + stationName_ + ": cannot find LO ID for channel #" +
2441  QString("").setNum(cIdx));
2442 
2443  // special case:
2444  if (ifSb == CSB_DUAL)
2445  {
2446  frqByIdx_Fsl[idx] = skyFrq - bw;
2447  bwByIdx_Fsl[idx] = bw;
2448  idx++;
2449  numOfChansAtLog++;
2450  };
2451  frqByIdx_Fsl[idx] = skyFrq;
2452  bwByIdx_Fsl[idx] = bw;
2453  numOfChansAtLog++;
2454  };
2455 
2456  // check:
2457  if (frqByIdx_Fsl.size() != frqByIdx_Skd.size())
2458  {
2459  isOk = false;
2461  "::compareChannelSetups(): station " + stationName_ + ": the number of channels are different, " +
2462  QString("").sprintf("%d (log) vs %d (sked)", frqByIdx_Fsl.size(), frqByIdx_Skd.size()));
2463  }
2464  else
2465  {
2466  // Grrr!
2467  // freqs:
2468  QMap<double, int> idxByFrq_Fsl, idxByFrq_Skd;
2469  for (QMap<int, double>::iterator it=frqByIdx_Fsl.begin(); it!=frqByIdx_Fsl.end(); ++it, idx++)
2470  idxByFrq_Fsl[it.value()] = it.key();
2471  for (QMap<int, double>::iterator it=frqByIdx_Skd.begin(); it!=frqByIdx_Skd.end(); ++it, idx++)
2472  idxByFrq_Skd[it.value()] = it.key();
2473  //
2474  QList<double> d_Fsl=idxByFrq_Fsl.keys();
2475  QList<double> d_Skd=idxByFrq_Skd.keys();
2476 
2477  for (int i=0; i<d_Fsl.size(); i++)
2478  {
2479  double frqFsl=d_Fsl.at(i), frqSkd=d_Skd.at(i);
2480  if (1.0e-4 < fabs(frqSkd - frqFsl))
2481  {
2482  isOk = false;
2484  "::compareChannelSetups(): station " + stationName_ +
2485  ": the sky frequency for the channel #" +
2486  QString("").setNum(i) + " is different: " +
2487  QString("").sprintf("%.4f (log) vs %.4f (sked)", frqFsl, frqSkd));
2488  };
2489  };
2490  // bandwidth:
2491  d_Fsl = bwByIdx_Fsl.values();
2492  d_Skd = bwByIdx_Skd.values();
2493  for (int i=0; i<d_Fsl.size(); i++)
2494  {
2495  double bwFsl=d_Fsl.at(i), bwSkd=d_Skd.at(i);
2496  if (1.0e-2 < fabs(bwSkd - bwFsl))
2497  {
2498  isOk = false;
2500  "::compareChannelSetups(): station " + stationName_ +
2501  ": the width for the channel #" +
2502  QString("").setNum(i) + " is different: " +
2503  QString("").sprintf("%.2f (log) vs %.2f (sked)", bwFsl, bwSkd));
2504  };
2505  };
2506  /*
2507  for (QMap<int, double>::iterator it=frqByIdx_Fsl.begin(); it!=frqByIdx_Fsl.end(); ++it, idx++)
2508  {
2509  int cIdx=it.key();
2510  double frqFsl=it.value(), frqSkd;
2511  if (frqByIdx_Skd.contains(cIdx))
2512  {
2513  frqSkd = frqByIdx_Skd.value(cIdx);
2514  if (1.0e-4 < fabs(frqSkd - frqFsl))
2515  {
2516  isOk = false;
2517  logger->write(SgLogger::WRN, SgLogger::IO, className() +
2518  "::compareChannelSetups(): station " + stationName_ +
2519  ": the sky frequency for the channel #" +
2520  QString("").setNum(cIdx) + " is different: " +
2521  QString("").sprintf("%.4f (log) vs %.4f (sked)", frqFsl, frqSkd));
2522  }
2523  }
2524  else
2525  {
2526  isOk = false;
2527  logger->write(SgLogger::WRN, SgLogger::IO, className() +
2528  "::compareChannelSetups(): station " + stationName_ + ": canot find channel index #" +
2529  QString("").setNum(cIdx) + " in the list of sked's channels (frq)");
2530  };
2531  double bwFsl, bwSkd;
2532  bwFsl = bwByIdx_Fsl.value(cIdx);
2533  if (bwByIdx_Skd.contains(cIdx))
2534  {
2535  bwSkd = bwByIdx_Skd.value(cIdx);
2536  if (1.0e-2 < fabs(bwSkd - bwFsl))
2537  {
2538  isOk = false;
2539  logger->write(SgLogger::WRN, SgLogger::IO, className() +
2540  "::compareChannelSetups(): station " + stationName_ +
2541  ": the width for the channel #" +
2542  QString("").setNum(cIdx) + " is different: " +
2543  QString("").sprintf("%.2f (log) vs %.2f (sked)", bwFsl, bwSkd));
2544  };
2545  }
2546  else
2547  {
2548  isOk = false;
2549  logger->write(SgLogger::WRN, SgLogger::IO, className() +
2550  "::compareChannelSetups(): station " + stationName_ + ": canot find channel index #" +
2551  QString("").setNum(cIdx) + " in the list of sked's channels (bw)");
2552  };
2553  };
2554  */
2555  };
2556  return isOk;
2557 };
2558 
2559 
2560 
2561 //
2563 {
2564  bool isOk;
2565  int numOfChansAtSked, numOfChansAtLog;
2566 
2567  numOfChansAtSked = numOfChansAtLog = 0;
2568  isOk = true;
2569  //
2570  // sked's:
2571  numOfChansAtSked = sCfg.getChannelCfgs().size();
2572 
2573  // FS log:
2574  for (QMap<QString, int>::const_iterator it=channelSetup_.ifIdxById().begin();
2575  it!=channelSetup_.ifIdxById().end(); ++it)
2576  {
2577  QString ifId(it.key());
2579  // channel side band:
2580  if (channelSetup_.ifSideBandById().contains(ifId))
2581  ifSb = channelSetup_.ifSideBandById().value(ifId);
2582  else
2584  "::compareChannelNumbers(): station " + stationName_ + ": cannot find side band for channel #" +
2585  QString("").setNum(it.value()) + ", ID: \"" + ifId + "\"");
2586 
2587  // special case:
2588  if (ifSb == CSB_DUAL)
2589  numOfChansAtLog++;
2590  numOfChansAtLog++;
2591  };
2592 
2593  // check:
2594  if (numOfChansAtLog != numOfChansAtSked)
2595  {
2596  isOk = false;
2598  "::compareChannelNumbers(): station " + stationName_ + ": the number of channels are different, " +
2599  QString("").sprintf("%d (log) vs %d (sked)", numOfChansAtLog, numOfChansAtSked));
2600  };
2601  return isOk;
2602 };
2603 
2604 
2605 
2606 //
2607 bool SgStnLogReadings::createAntabFile(const QString& inputLogFileName, const QString& outputFileName,
2608  const QString& stnKey, const SgChannelSkeded *channelSkeded, bool useSkededChannelSetup,
2609  bool have2overwrite, bool reportAllTsysData)
2610 {
2611  enum ChannelSetup2Use {CSU_NONE, CSU_NATIVE, CSU_SKED, CSU_VEX, CSU_VGOS};
2612  bool haveSkeded;
2613  bool haveTsys;
2614  ChannelSetup2Use setup2use;
2615  setup2use = CSU_NONE;
2616  haveSkeded = false;
2617  haveTsys = 0 < tSyses_.size();
2618 
2619  QString str("");
2620 
2621  if (!outputFileName.size())
2622  {
2623  // set up outut file name:
2624  if (5 < inputLogFileName.size() && inputLogFileName.right(4) == QString(".log"))
2625  {
2626  str = inputLogFileName.left(inputLogFileName.size() - 4) + ".ant";
2627  }
2628  else
2629  str = inputLogFileName + ".ant";
2630  }
2631  else
2632  str = outputFileName;
2633  QFile f(str);
2635  "::createAntabFile(): station " + stnKey + ": " +
2636  " going to create " + f.fileName() + " LOG-ANTAB file");
2637 
2638  if (haveTsys)
2639  {
2640  // check channel set up:
2641  if (!channelSkeded)
2643  "::createAntabFile(): station " + stnKey +
2644  ": the sked's channel setup is missing");
2645  else if (!channelSkeded->isOk())
2647  "::createAntabFile(): station " + stnKey +
2648  ": the sked's channel setup is not good, skipping it");
2649  else if (!channelSkeded->stnCfgByKey_.contains(stnKey))
2651  "::createAntabFile(): station " + stnKey +
2652  ": the sked's channel setup does not contain this station, skipping it");
2654  !compareChannelNumbers(channelSkeded->stnCfgByKey_.value(stnKey)))
2656  "::createAntabFile(): station " + stnKey +
2657  ": the number of collected channels and number of channels in the sked are different, skipping it");
2658  else
2659  {
2660  haveSkeded = true;
2662  "::createAntabFile(): station " + stnKey +
2663  ": looks like we have channel setup from sked");
2664  };
2665  //
2666  //
2667  if (channelSetup_.selfCheck(stnKey))
2668  {
2669  setup2use = CSU_NATIVE;
2671  setup2use = CSU_VGOS;
2673  "::createAntabFile(): station " + stnKey +
2674  ": channel setup from the log file looks ok");
2675  if (haveSkeded && channelSetup_.getHwType() != SgChannelSetup::HT_VGOS)
2676  {
2678  "::createAntabFile(): station " + stnKey +
2679  ": comparing sked's and FS log channel setups");
2680  compareChannelSetups(channelSkeded->stnCfgByKey_.value(stnKey));
2681  };
2682  }
2683  else if (haveSkeded)
2684  {
2685  setup2use = CSU_SKED;
2687  "::createAntabFile(): station " + stnKey + ": cannot figure out channel setup from the log "
2688  "file, falling back to the set up from sked file");
2689  }
2690  else
2691  {
2692  setup2use = CSU_NONE;
2694  "::createAntabFile(): station " + stnKey + ": cannot figure out the channel setup");
2695  };
2696 
2697  if (setup2use == CSU_NATIVE && useSkededChannelSetup)
2698  {
2699  setup2use = CSU_SKED;
2701  "::createAntabFile(): station " + stnKey + ": forced to use the set up from sked file");
2702  };
2703  }
2704  else
2706  "::createAntabFile(): station " + stnKey + ": no TSYS data have found in the log file");
2707 
2708  //
2709  //
2710  if (f.exists())
2711  {
2712  if (have2overwrite)
2714  "::createAntabFile(): the file " + f.fileName() + " already exists; it will be overwritten");
2715  else
2716  {
2718  "::createAntabFile(): the file " + f.fileName() + " already exists, skipping");
2719  return false;
2720  };
2721  };
2722  // find associated OnSource records for tsyses:
2723  // ...
2724  // ...
2725 
2726 
2727  if (f.open(QFile::WriteOnly))
2728  {
2729  QTextStream s(&f);
2730 
2731  s << "# LOG-ANTAB Format Version of 2009.08.07\n";
2732  s << "#\n";
2733  s << "# Generator: " << qPrintable(libraryVersion.name()) << "\n";
2734  s << "#\n";
2735  s << "# Generated from log file " << qPrintable(inputLogFileName) << " on "
2736  << qPrintable(SgMJD().currentMJD().toString(SgMJD::F_SOLVE_SPLFL))<<"\n";
2737  s << "#\n";
2738  s << "STATION: " << qPrintable(stnKey) << "\n";
2739  s << "#\n";
2740 
2741  // Data On/Off:
2742  s << "NUMB_DATA_ON: " << onSourceRecords_.size() << "\n";
2743  s << "#\n";
2744  s << "# Data_on start Data_on end Source Scan\n";
2745  s << "#\n";
2746  for (int i=0; i<onSourceRecords_.size(); i++)
2747  {
2749  s << "DATA_ON: "
2750  << qPrintable(rec->getTstart().toString(SgMJD::F_SOLVE_SPLFL_V3)) << " "
2751  << qPrintable(rec->getTfinis().toString(SgMJD::F_SOLVE_SPLFL_V3)) << " "
2752  << qPrintable(rec->getSourceName().leftJustified(8, ' ')) << " "
2753  << qPrintable(rec->getScanName().leftJustified(8, ' ')) << "\n";
2754  };
2755 
2756  // Cable cals:
2757  s << "#\n";
2758  s << "NUMB_CAB: " << cableCals_.size() << "\n";
2759 
2760  if (cableCals_.size())
2761  {
2762  s << "#\n";
2763  s << "SIGN_CAB: " << (cableSign_==0?"UNDEF":(cableSign_<0?"-1":"+1")) << "\n";
2764  s << "#\n";
2765  s << "# Date Cable delay (sec)\n";
2766  s << "#\n";
2767  for (int i=0; i<cableCals_.size(); i++)
2768  {
2769  SgCableCalReading *cc=cableCals_.at(i);
2770  s << "CABLE: "
2771  << qPrintable(cc->getT().toString(SgMJD::F_SOLVE_SPLFL_V3)) << " "
2772  << qPrintable(QString("").sprintf("%12.5E", cc->getV())) << "\n";
2773  };
2774  };
2775 
2776  // meteo:
2777  s << "#\n";
2778  s << "NUMB_METEO: " << meteoPars_.size() << "\n";
2779 
2780  if (meteoPars_.size())
2781  {
2782  s << "#\n";
2783  s << "# Date Temp Pres Humid\n";
2784  s << "#\n";
2785  for (int i=0; i<meteoPars_.size(); i++)
2786  {
2787  SgMeteoReading *mr=meteoPars_.at(i);
2788  s << "METEO: "
2789  << qPrintable(mr->getT().toString(SgMJD::F_SOLVE_SPLFL_V3)) << " "
2790  << qPrintable(QString("").sprintf("%6.2f %7.1f %4.1f",
2791  mr->getM().getTemperature() + 273.15,
2792  mr->getM().getPressure()*100.0,
2793  mr->getM().getRelativeHumidity()*100.0))
2794  << "\n";
2795  };
2796  };
2797  s << "#\n";
2798 
2799  if (tSyses_.size())
2800  {
2801  if (setup2use == CSU_NATIVE)
2803  else if (setup2use == CSU_VGOS)
2805  else if (setup2use == CSU_SKED && channelSkeded->stnCfgByKey_.contains(stnKey))
2806  export2antabFrqs_skededSetup(s, channelSkeded->stnCfgByKey_.value(stnKey));
2807  else if (setup2use == CSU_NONE)
2809  else
2810  {
2811  s << "#\n";
2812  s << "#No FRQ data available\n";
2813  s << "#\n";
2814  };
2815  //
2816  //
2817  int numOfTsyses=0;
2818  if (!reportAllTsysData)
2819  {
2820  s << "# Scan Scan_name Src_name UTC_Time_tag ";
2821  int idx;
2822  idx = 1;
2823  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
2824  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it, idx++)
2825  s << " Ts#" << QString("").sprintf("%03d", idx);
2826  s << "\n#\n";
2827 
2828  // tsyses only for data_valid=on:
2829  for (int i=0; i<onSourceRecords_.size(); i++)
2830  numOfTsyses += onSourceRecords_.at(i)->tSyses().size();
2831  s << "NUMB_TSYS: " << numOfTsyses << "\n";
2832  s << "#\n";
2833  int counter=1;
2834  for (int i=0; i<onSourceRecords_.size(); i++)
2835  {
2837  SgTsysReading *tsr=NULL;
2838  for (int j=0; j<sOn->tSyses().size(); j++)
2839  {
2840  tsr = sOn->tSyses().at(j);
2841  s << str.sprintf("TSYS: %6d ", counter);
2842  str = sOn->getScanName().leftJustified(9, ' ') + " " +
2843  sOn->getSourceName().leftJustified(8, ' ') + " ";
2844  s << str;
2845 
2846  if (tsr && tsr->osRec())
2847  s << tsr->getT().toString(SgMJD::F_SOLVE_SPLFL_V3) << " ";
2848  else
2849  s << sOn->getTstart().toString(SgMJD::F_SOLVE_SPLFL_V3) << " ";
2850 
2851  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
2852  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it)
2853  {
2854  double v;
2855  v = -2.0;
2856  if (tsr && tsr->getTsys().contains(it.value()))
2857  v = tsr->getTsys().value(it.value());
2858  s << str.sprintf(" %7.1f", v);
2859  };
2860  s << "\n";
2861  counter++;
2862  };
2863  };
2864  }
2865  else // all tsys collected from a log file:
2866  {
2867  s << "# Idx Azimuth Elevation UTC_Time_tag ";
2868  int idx;
2869  idx = 1;
2870  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
2871  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it, idx++)
2872  s << " Ts#" << QString("").sprintf("%03d", idx);
2873  s << "\n# (deg) (deg)\n";
2874 
2875  for (int i=0; i<tSyses_.size(); i++)
2876  {
2877  SgTsysReading *tsr=tSyses_.at(i);
2878  s << str.sprintf("TSYS: %6d ", i+1);
2879  str = "SLWEING SLEWING ";
2880  //
2881  SgTraklReading *trakl=NULL;
2882  double dt=1.0e3, d=0.0;
2883  for (int j=0; j<tsr->trakls().size(); j++)
2884  {
2885  if (tsr->trakls().at(j))
2886  {
2887  if ((d=fabs(tsr->getT() - tsr->trakls().at(j)->getT())) < dt)
2888  {
2889  dt = d;
2890  trakl = tsr->trakls().at(j);
2891  };
2892  };
2893  };
2894  if (trakl)
2895  str.sprintf("%10.5f %10.5f", trakl->getAz(), trakl->getEl());
2896 // str.sprintf("%8.3f %8.3f %2d %8.3f",
2897 // trakl->getAz(), trakl->getEl(), tsr->trakls().size(), dt*DAY2SEC);
2898 
2899  s << str << " " << tsr->getT().toString(SgMJD::F_SOLVE_SPLFL_V3) << " ";
2900  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
2901  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it)
2902  {
2903  double v;
2904  v = -2.0;
2905  if (tsr && tsr->getTsys().contains(it.value()))
2906  v = tsr->getTsys().value(it.value());
2907  s << str.sprintf(" %7.1f", v);
2908  };
2909  s << "\n";
2910  };
2911  };
2912  }
2913  else
2914  {
2915  s << "#\nNUMB_FRQ: 0\n#\n";
2916  s << "NUMB_TSYS: 0\n";
2917  s << "#\n#\n# No TSYS records found in the log file\n#\n";
2918  };
2919 
2920 
2921  s << "#\n";
2922  f.close();
2923  s.setDevice(NULL);
2924  };
2925 
2926  return true;
2927 };
2928 
2929 
2930 
2931 //
2932 //
2934 {
2935  QString str("");
2936  QString sPol("");
2937  QString sSbd("");
2938  int idx;
2939 
2941  return;
2942  else
2943  tSensorsPrinted2AntCal_ = true;
2944 
2945  s << "#\nNUM_TP_SENSOR: " << channelSetup_.ifIdByTpSensorKey().size() << "\n";
2946  s << "#\n";
2947  s << "# Sensor IF_Freq LO_Freq Sky_frq_Cen Bdw Pol SensorId IF# SideBand\n";
2948  s << "# tag MHz MHz MHz MHz\n";
2949  s << "#\n";
2950  idx = 1;
2951 
2952  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
2953  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it)
2954  {
2955  QString sensorKey(it.key());
2956  QString ifId(it.value());
2957 
2958  int cIdx=-1;
2959  if (!channelSetup_.ifIdxById().contains(ifId))
2960  {
2962  "::export2antCalFrqs_nativeSetup(): station " + stationName_ +
2963  ": cannot find IF index for if with the id \"" + ifId + "\"");
2964  continue;
2965  }
2966  else
2967  cIdx = channelSetup_.ifIdxById().value(ifId);
2968 
2969  QString loId("");
2972  SgChannelPolarization polarization=CP_UNDEF;
2973  double ifFrq, loFrq, skyFrq, bw;
2974  ifFrq = loFrq = skyFrq = bw = dFiller_;
2975 
2976  if (channelSetup_.loIdByIdx().contains(cIdx))
2977  loId = channelSetup_.loIdByIdx().value(cIdx);
2978  else if (channelSetup_.loIdByCid().contains(ifId))
2979  loId = channelSetup_.loIdByCid().value(ifId);
2980  if (loId.size())
2981  {
2982  // LO side band:
2983  if (channelSetup_.loSideBandById().contains(loId))
2984  loSb = channelSetup_.loSideBandById().value(loId);
2985  else
2987  "::export2antCalFrqs_nativeSetup(): station " + stationName_ + ": cannot find side band for LO \"" +
2988  loId + "\"");
2989 
2990  // channel side band:
2991  if (channelSetup_.ifSideBandById().contains(ifId))
2992  ifSb = channelSetup_.ifSideBandById().value(ifId);
2993  else
2995  "::export2antCalFrqs_nativeSetup(): station " + stationName_ + ": cannot find side band for channel #" +
2996  QString("").setNum(cIdx) + ", ID: \"" + ifId + "\"");
2997 
2998  // polarization:
2999  if (channelSetup_.loPolarizationById().contains(loId))
3000  polarization = channelSetup_.loPolarizationById().value(loId);
3001  else
3003  "::export2antCalFrqs_nativeSetup(): station " + stationName_ + ": cannot find polarization for LO \"" +
3004  loId + "\"");
3005 
3006  // bandwidth:
3007  if (channelSetup_.bbcBandwidthByIdx().contains(cIdx))
3008  bw = channelSetup_.bbcBandwidthByIdx().value(cIdx);
3009  else
3011  "::export2antCalFrqs_nativeSetup(): station " + stationName_ + ": cannot find bandwidth for channel #" +
3012  QString("").setNum(cIdx) + ", ID=" + ifId);
3013 
3014  if (channelSetup_.bbcFreqByIdx().contains(cIdx))
3015  {
3016  ifFrq = channelSetup_.bbcFreqByIdx().value(cIdx);
3017  //
3018  if (loSb == CSB_USB && ifSb == CSB_USB)
3019  ifFrq = channelSetup_.bbcFreqByIdx().value(cIdx);
3020  else if (loSb == CSB_USB && ifSb == CSB_LSB)
3021  ifFrq = channelSetup_.bbcFreqByIdx().value(cIdx) - bw;
3022  else if (loSb == CSB_LSB && ifSb == CSB_LSB)
3023  ifFrq = - channelSetup_.bbcFreqByIdx().value(cIdx) - bw;
3024  else if (loSb == CSB_LSB && ifSb == CSB_USB)
3025  ifFrq = - channelSetup_.bbcFreqByIdx().value(cIdx);
3026  // report central frq:
3027  ifFrq += bw/2.0;
3028  }
3029  else
3031  "::export2antCalFrqs_nativeSetup(): station " + stationName_ + ": cannot find BBC_FRQ for channel #" +
3032  QString("").setNum(cIdx));
3033 
3034  if (channelSetup_.loFreqById().contains(loId))
3035  loFrq = channelSetup_.loFreqById().value(loId);
3036  else
3038  "::export2antCalFrqs_nativeSetup(): station " + stationName_ + ": cannot find LO frq for channel #" +
3039  QString("").setNum(cIdx) + ", loID=" + loId);
3040 
3041  skyFrq = loFrq + ifFrq;
3042  }
3043  else
3045  "::export2antCalFrqs_nativeSetup(): station " + stationName_ + ": cannot find LO ID for channel #" +
3046  QString("").setNum(cIdx));
3047 
3048  channelSetup_.ifFreqByIdx()[cIdx] = skyFrq;
3049  channelSetup_.ifPolarizationById()[ifId] = polarization;
3050 
3051  sPol = sFiller_;
3052  if (polarization == CP_RightCP)
3053  sPol = "R";
3054  else if (polarization == CP_LeftCP)
3055  sPol = "L";
3056  else if (polarization == CP_HorizontalLP)
3057  sPol = "H";
3058  else if (polarization == CP_VerticalLP)
3059  sPol = "V";
3060 
3061  sSbd = sFiller_;
3062  if (ifSb == CSB_USB)
3063  sSbd = "USB";
3064  else if (ifSb == CSB_LSB)
3065  sSbd = "LSB";
3066  else if (ifSb == CSB_DUAL)
3067  sSbd = "USB/LSB";
3068 
3069  str.sprintf("TP_SENSOR: TS_%03d %8.2f %10.2f %10.2f %6.2f %3s %8s %3d %7s",
3070  idx, ifFrq, loFrq, skyFrq, bw,
3071  qPrintable(sPol),
3072  qPrintable(ifId),
3073  cIdx,
3074  qPrintable(sSbd)
3075  );
3076  s << str << "\n";
3077 
3078  idx++;
3079  };
3080  s << "#\n";
3081 };
3082 
3083 
3084 
3085 //
3087 {
3088  QString str("");
3089  QString sPol("");
3090  QString sSensorSbd("");
3091  QString sNetSbd("");
3092  int idx;
3093  QString sortingKey("");
3094  QMap<QString, QString> sensorSetupByKey;
3095 
3096 
3098  return;
3099  else
3100  tSensorsPrinted2AntCal_ = true;
3101 
3102  s << "#\nNUM_TP_SENSOR: " << channelSetup_.ifIdByTpSensorKey().size() << "\n";
3103  s << "#\n";
3104  //
3105  // let know the user about duality of sensors:
3106  if (channelSetup_.origSensorIdById().size())
3107  {
3108  s << "# Note, the following sensor ID(s) were splitted by two sidebands: \n";
3109  for (QMap<QString, QList<QString> >::iterator it=channelSetup_.origSensorIdById().begin();
3110  it!=channelSetup_.origSensorIdById().end(); ++it)
3111  {
3112  const QString& key=it.key();
3113  const QList<QString>& lst=it.value();
3114  str = "# sensor " + key + " => (";
3115  for (int i=0; i<lst.size(); i++)
3116  str += lst.at(i) + ", ";
3117  str.chop(2);
3118  s << str << ")\n";
3119  };
3120  s << "#\n";
3121  };
3122  s << "# Sensor IF_Freq LO_Freq Sky_frq_Cen BndWd Pol SensorId IF# Sensor Net Comments\n";
3123  s << "# tag MHz MHz MHz MHz SideBand SideBand\n";
3124  s << "#\n";
3125  idx = 1;
3126 
3127  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
3128  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it)
3129  {
3130  QString sensorKey(it.key());
3131  QString ifId(it.value());
3132  QString loId("");
3133 
3134  int cIdx=-1;
3135  if (!channelSetup_.ifIdxById().contains(ifId))
3136  {
3138  "::export2antCalFrqs_vgosSetup(): station " + stationName_ +
3139  ": cannot find IF index for IF with ID \"" + ifId + "\"");
3140  continue;
3141  }
3142  else
3143  cIdx = channelSetup_.ifIdxById().value(ifId);
3144 
3147  SgChannelPolarization polarization=CP_UNDEF;
3148  double ifFrq, loFrq, skyFrq, bw;
3149  ifFrq = loFrq = skyFrq = bw = dFiller_;
3150  //
3151  /*
3152  if (channelSetup_.loIdByIdx().contains(cIdx))
3153  loId = channelSetup_.loIdByIdx().value(cIdx);
3154  else if (channelSetup_.loIdByCid().contains(ifId))
3155  loId = channelSetup_.loIdByCid().value(ifId);
3156 */
3157  if (channelSetup_.loIdByTpSensorKey().contains(sensorKey))
3158  loId = channelSetup_.loIdByTpSensorKey().value(sensorKey);
3159  else
3161  "::export2antCalFrqs_vgosSetup(): station " + stationName_ +
3162  ": cannot find LO ID for sensorKey \"" + sensorKey + "\"");
3163  //
3164  // lo sideband:
3165  if (channelSetup_.loSideBandByTpSensorKey().contains(sensorKey))
3166  loSb = channelSetup_.loSideBandByTpSensorKey().value(sensorKey);
3167  else
3169  "::export2antCalFrqs_vgosSetup(): station " + stationName_ +
3170  ": cannot find LO sideband for sensorKey \"" + sensorKey + "\"");
3171 
3172  // channel side band:
3173  if (channelSetup_.ifSideBandById().contains(ifId))
3174  ifSb = channelSetup_.ifSideBandById().value(ifId);
3175  else
3177  "::export2antCalFrqs_vgosSetup(): station " + stationName_ +
3178  ": cannot find side band for channel #" + QString("").setNum(cIdx) + ", ID: \"" + ifId + "\"");
3179 
3180  // LO freq:
3181  if (channelSetup_.loFreqByTpSensorKey().contains(sensorKey))
3182  loFrq = channelSetup_.loFreqByTpSensorKey().value(sensorKey);
3183  else
3185  "::export2antCalFrqs_vgosSetup(): station " + stationName_ +
3186  ": cannot find LO frq for sensorKey \"" + sensorKey + "\"");
3187 
3188  // IF freq:
3189  if (channelSetup_.ifFreqByTpSensorKey().contains(sensorKey))
3190  ifFrq = channelSetup_.ifFreqByTpSensorKey().value(sensorKey);
3191  else
3193  "::export2antCalFrqs_vgosSetup(): station " + stationName_ +
3194  ": cannot find BBC_FRQ for channel #" + QString("").setNum(cIdx));
3195 
3196  // bandwidth:
3197  if (channelSetup_.ifBandwidthByTpSensorKey().contains(sensorKey))
3198  bw = channelSetup_.ifBandwidthByTpSensorKey().value(sensorKey);
3199  else
3201  "::export2antCalFrqs_vgosSetup(): station " + stationName_ +
3202  ": cannot find bandwidth for sensor key \"" + sensorKey + "\", ID=" + ifId);
3203 
3204  skyFrq = SgChannelSetup::calcSkyFreq(loFrq, ifFrq, bw, loSb, ifSb);
3205 
3206  // polarization:
3207  if (channelSetup_.loPolarizationByTpSensorKey().contains(sensorKey))
3208  polarization = channelSetup_.loPolarizationByTpSensorKey().value(sensorKey);
3209  else
3211  "::export2antCalFrqs_vgosSetup(): station " + stationName_ +
3212  ": cannot find LO polarization for sensorKey \"" + sensorKey + "\"");
3213 
3214  channelSetup_.ifPolarizationById()[ifId] = polarization;
3215 
3216  sPol = sFiller_;
3217  if (polarization == CP_RightCP)
3218  sPol = "R";
3219  else if (polarization == CP_LeftCP)
3220  sPol = "L";
3221  else if (polarization == CP_HorizontalLP)
3222  sPol = "H";
3223  else if (polarization == CP_VerticalLP)
3224  sPol = "V";
3225 
3226  sSensorSbd = sNetSbd = sFiller_;
3227  if (ifSb == CSB_USB)
3228  sSensorSbd = "USB";
3229  else if (ifSb == CSB_LSB)
3230  sSensorSbd = "LSB";
3231  else if (ifSb == CSB_DUAL)
3232  sSensorSbd = "USB/LSB";
3233 
3234  if (loSb == CSB_USB)
3235  sNetSbd = "USB";
3236  else if (loSb == CSB_LSB)
3237  sNetSbd = "LSB";
3238  else if (loSb == CSB_DUAL)
3239  sNetSbd = "USB/LSB";
3240 
3241 
3242  str.sprintf("TP_SENSOR: TS_%03d %8.2f %10.2f %10.2f %6.2f %3s %8s %3d %7s %7s %s",
3243  idx, ifFrq, loFrq, skyFrq, bw,
3244  qPrintable(sPol),
3245  qPrintable(ifId),
3246  cIdx,
3247  qPrintable(sSensorSbd),
3248  qPrintable(sNetSbd),
3249  qPrintable(QString(sensorKey).replace(' ', '_'))
3250  );
3251  s << str << "\n";
3252  idx++;
3253 /*
3254 // sortingKey.sprintf("%10.2f %s %s",
3255 // skyFrq, qPrintable(sPol), qPrintable(sensorKey));
3256 
3257  sortingKey.sprintf("%s %10.2f %s",
3258  qPrintable(sPol),
3259  skyFrq,
3260  qPrintable(sensorKey));
3261 
3262  if (!sensorSetupByKey.contains(sortingKey))
3263  sensorSetupByKey[sortingKey] = str;
3264 */
3265  };
3266 /*
3267  // make sorted output:
3268  for (QMap<QString, QString>::iterator it=sensorSetupByKey.begin(); it!=sensorSetupByKey.end(); ++it)
3269  s << it.value() << "\n";
3270 */
3271 
3272  s << "#\n";
3273 };
3274 
3275 
3276 
3277 //
3279 {
3280  QString str("");
3281  QString sPol("");
3282  QString sSbd("");
3283  int idx;
3284 
3286  return;
3287  else
3288  tSensorsPrinted2AntCal_ = true;
3289 
3290  s << "#\nNUM_TP_SENSOR: " << channelSetup_.ifIdByTpSensorKey().size() << "\n";
3291  s << "#\n";
3292  s << "# Sensor IF_Freq LO_Freq Sky_frq_Cen Bdw Pol SensorId IF# SideBand\n";
3293  s << "# tag MHz MHz MHz MHz\n";
3294  s << "#\n";
3295  idx = 1;
3296 
3297  if (channelSetup_.ifIdxById().size() != sCfg.getChannelCfgs().size())
3298  {
3300  "::export2antCalFrqs_skededSetup(): station " + stationName_ +
3301  ": number of channels are different");
3302  return;
3303  };
3304 
3305  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
3306  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it)
3307  {
3308  QString sensorKey(it.key());
3309  QString ifId(it.value());
3310 
3311  int cIdx=-1;
3312  if (!channelSetup_.ifIdxById().contains(ifId))
3313  {
3315  "::export2antCalFrqs_skededSetup(): station " + stationName_ +
3316  ": cannot find IF index for if with the id \"" + ifId + "\"");
3317  continue;
3318  }
3319  else
3320  cIdx = channelSetup_.ifIdxById().value(ifId);
3321 
3323  double ifFrq, loFrq, skyFrq, bw;
3324  ifFrq = loFrq = skyFrq = bw = dFiller_;
3325 
3326  // channel side band:
3327  if (channelSetup_.ifSideBandById().contains(ifId))
3328  ifSb = channelSetup_.ifSideBandById().value(ifId);
3329  else
3331  "::export2antCalFrqs_skededSetup(): station " + stationName_ + ": cannot find side band for channel #" +
3332  QString("").setNum(cIdx) + ", ID: \"" + ifId + "\"");
3333 
3334  // bandwidth:
3335  bw = sCfg.getChannelCfgs().at(idx - 1).getBandWidth();
3336  skyFrq = sCfg.getChannelCfgs().at(idx - 1).getSkyFrq();
3337  channelSetup_.ifFreqByIdx()[cIdx] = skyFrq;
3339 
3340  skyFrq += bw/2.0;
3341 
3342  sPol = sFiller_;
3343  sSbd = sFiller_;
3344  if (ifSb == CSB_USB)
3345  sSbd = "USB";
3346  else if (ifSb == CSB_LSB)
3347  sSbd = "LSB";
3348  else if (ifSb == CSB_DUAL)
3349  sSbd = "USB/LSB";
3350 
3351  str.sprintf("TP_SENSOR: TS_%03d %8.2f %10.2f %10.2f %6.2f %1s %8s %3d %7s",
3352  idx, ifFrq, loFrq, skyFrq, bw,
3353  qPrintable(sPol),
3354  qPrintable(ifId),
3355  cIdx,
3356  qPrintable(sSbd)
3357  );
3358  s << str << "\n";
3359  idx++;
3360  };
3361  s << "#\n";
3362 };
3363 
3364 
3365 
3366 //
3368 {
3369  QString str("");
3370  QString sPol("");
3371  QString sSbd("");
3372  int idx;
3373 
3374  s << "#\nNUM_PC_SENSOR: " << channelSetup_.pcalIdByKey().size() << "\n";
3375  s << "# Sensor Sky_frq_Cen Pol SensorId IF# SideBand Comments\n";
3376  s << "# tag MHz\n";
3377  s << "#\n";
3378 
3379  idx = 1;
3380 
3381  for (QMap<QString, QString>::const_iterator it=channelSetup_.pcalIdByKey().begin();
3382  it!=channelSetup_.pcalIdByKey().end(); ++it)
3383  {
3384  QString key(it.key());
3385  QString id(it.value());
3386 
3387  SgChannelSideBand sideBand=CSB_UNDEF;
3388  SgChannelPolarization polarization=CP_UNDEF;
3389  double skyFrq;
3390  double ifFreq;
3391  double freqOffset;
3392  double width;
3393  bool isOk;
3394  //
3395  skyFrq = dFiller_;
3396  freqOffset = width = 0.0;
3397 
3398  // channel side band:
3399  /*
3400  if (channelSetup_.ifSideBandById().contains(ifId))
3401  ifSb = channelSetup_.ifSideBandById().value(ifId);
3402  else
3403  logger->write(SgLogger::WRN, SgLogger::IO, className() +
3404  "::export2antCalFrqs_vgosSetup(): station " + stationName_ +
3405  ": cannot find side band for channel #" + QString("").setNum(cIdx) + ", ID: \"" + ifId + "\"");
3406  */
3407 
3408  //
3409  // LO frequency:
3410  if (channelSetup_.pcalLoFreqByKey().contains(key))
3411  skyFrq = channelSetup_.pcalLoFreqByKey().value(key);
3412  else
3414  "::export2antCalPcal_vgosSetup(): station " + stationName_ +
3415  ": cannot find LO frequency for PCAL key \"" + key + "\"");
3416  //
3417  if (channelSetup_.pcalSideBandByKey().contains(key))
3418  sideBand = channelSetup_.pcalSideBandByKey().value(key);
3419  else
3421  "::export2antCalPcal_vgosSetup(): station " + stationName_ +
3422  ": cannot find LO sideband for PCAL key \"" + key + "\"");
3423 
3424  // polarization:
3425  if (channelSetup_.pcalPolarizationByKey().contains(key))
3426  polarization = channelSetup_.pcalPolarizationByKey().value(key);
3427  else
3429  "::export2antCalPcal_vgosSetup(): station " + stationName_ +
3430  ": cannot find polarization for PCAL key \"" + key + "\"");
3431 
3432  // freq offset:
3433  if (channelSetup_.pcalOffsetByKey().contains(key))
3434  freqOffset = channelSetup_.pcalOffsetByKey().value(key);
3435  else
3437  "::export2antCalPcal_vgosSetup(): station " + stationName_ +
3438  ": cannot find frequency offset for PCAL key \"" + key + "\"");
3439 
3440  // width:
3441  if (channelSetup_.pcalWidthByKey().contains(key))
3442  width = channelSetup_.pcalWidthByKey().value(key);
3443  else
3445  "::export2antCalPcal_vgosSetup(): station " + stationName_ +
3446  ": cannot find width for PCAL key \"" + key + "\"");
3447 
3448  //
3449  //
3450  // calculate sky frequency:
3451  ifFreq = 0.0;
3452  ifFreq = id.right(4).toDouble(&isOk);
3453  if (isOk)
3454  {
3455  if (sideBand == CSB_USB)
3456  skyFrq += 1024.0 - freqOffset - ifFreq;
3457  else if (sideBand == CSB_LSB)
3458  skyFrq -= 1024.0 - freqOffset - ifFreq;
3459  else
3461  "::export2antCalPcal_vgosSetup(): station " + stationName_ +
3462  ": unsupported sideband \"" + sideBand2Str(sideBand) +
3463  "\" for PCAL key \"" + key + "\", cannot calculate the sky frequency");
3464  }
3465  else
3467  "::export2antCalPcal_vgosSetup(): station " + stationName_ +
3468  ": cannot convert \"" + id.right(4) +
3469  "\" to double for PCAL key \"" + key + "\"");
3470  //
3471  //
3472  sPol = sFiller_;
3473  if (polarization == CP_RightCP)
3474  sPol = "R";
3475  else if (polarization == CP_LeftCP)
3476  sPol = "L";
3477  else if (polarization == CP_HorizontalLP)
3478  sPol = "H";
3479  else if (polarization == CP_VerticalLP)
3480  sPol = "V";
3481 
3482  sSbd = sFiller_;
3483  if (sideBand == CSB_USB)
3484  sSbd = "USB";
3485  else if (sideBand == CSB_LSB)
3486  sSbd = "LSB";
3487  else if (sideBand == CSB_DUAL)
3488  sSbd = "USB/LSB";
3489 
3490 
3491 
3492 
3493 
3494  str.sprintf("PC_SENSOR: PC_%03d %14.2f %3s %8s %d %7s %s",
3495  idx, skyFrq,
3496  qPrintable(sPol),
3497  qPrintable(id),
3498  nFiller_,
3499  qPrintable(sSbd),
3500  qPrintable(QString(key).replace(' ', '_'))
3501  );
3502  s << str << "\n";
3503  idx++;
3504  };
3505  s << "#\n";
3506 };
3507 
3508 
3509 
3510 /*
3511 QString SgStnLogReadings::srcName4AntCal(const QString& srcName)
3512 {
3513  return (srcName.size()?srcName:QString("DUMMY")).leftJustified(8, ' ');
3514 };
3515 */
3516 
3517 
3518 //
3519 QString SgStnLogReadings::str4AntCal(const QString& str, int width)
3520 {
3521  return (str.size()?str:sFiller_).leftJustified(width, ' ');
3522 };
3523 
3524 
3525 
3526 //
3527 bool SgStnLogReadings::createAntCalFile(const QString& inputLogFileName,
3528  const QString& outputFileName, const QString& stnKey, const SgChannelSkeded *channelSkeded,
3529  bool useSkededChannelSetup, bool have2overwrite, bool reportAllReadings, bool supressNonUsedSensors,
3530  int wishedOutputData, const QString& ext4compress, const QString& userCommand)
3531 {
3532  enum ChannelSetup2Use {CSU_NONE, CSU_NATIVE, CSU_SKED, CSU_VEX, CSU_VGOS};
3533  const QString dataFlag[] = {"DATA:OFF", "DATA:ON_SOURCE", "DATA:VALID_ON"};
3534  bool haveSkeded;
3535  ChannelSetup2Use setup2use;
3536  int scanIdx;
3537  QString srcName(sFiller_);
3538  QString scnName(sFiller_);
3539  QString outputContent("");
3540  QString str("");
3541  float el, az;
3542  int outputData=wishedOutputData;
3543  int numOfRecs;
3544  int dataFlagIdx;
3545  bool hasSensor;
3546  bool isOk;
3547 
3548  tSensorsPrinted2AntCal_ = false;
3549  setup2use = CSU_NONE;
3550  haveSkeded = false;
3551  isOk = true;
3552 
3553  // check what user want and what we have:
3554  if (outputData & AOD_DATA_ON && onSourceRecords_.size()==0)
3555  outputData &= ~AOD_DATA_ON;
3556  if (outputData & AOD_CABLE_SIGN && cableSign_==0)
3557  outputData &= ~AOD_CABLE_SIGN;
3558  if (outputData & AOD_CABLE_CAL && cableCals_.size()==0)
3559  outputData &= ~AOD_CABLE_CAL;
3560  if (outputData & AOD_METEO && meteoPars_.size()==0)
3561  outputData &= ~AOD_METEO;
3562  if (outputData & AOD_TSYS && tSyses_.size()==0)
3563  outputData &= ~AOD_TSYS;
3564  if (outputData & AOD_TPI && tSyses_.size()==0)
3565  outputData &= ~AOD_TPI;
3566  if (outputData & AOD_PCAL && pcals_.size()==0)
3567  outputData &= ~AOD_PCAL;
3568  if (outputData & AOD_FMTGPS && dot2xpses_.size()==0)
3569  outputData &= ~AOD_FMTGPS;
3570  if (outputData & AOD_DBBC3TP && dbbc3Tps_.size()==0)
3571  outputData &= ~AOD_DBBC3TP;
3572  if (outputData & AOD_SEFD && sefds_.size()==0)
3573  outputData &= ~AOD_SEFD;
3574  //
3575  // form string with output info:
3576  if (outputData & AOD_DATA_ON)
3577  outputContent += "DATA_ON ";
3578  if (outputData & AOD_CABLE_SIGN)
3579  outputContent += "CABLE_SIGN ";
3580  if (outputData & AOD_CABLE_CAL)
3581  outputContent += "CABLE ";
3582  if (outputData & AOD_METEO)
3583  outputContent += "METEO ";
3584  if (outputData & AOD_TSYS)
3585  outputContent += "TP_SENSOR TSYS ";
3586  if (outputData & AOD_TPI)
3587  {
3588  if (outputData & AOD_TSYS)
3589  outputContent += "TPI ";
3590  else
3591  outputContent += "TP_SENSOR TPI ";
3592  };
3593  if (outputData & AOD_DBBC3TP)
3594  {
3595  if (outputData & AOD_TSYS)
3596  outputContent += "TPC ";
3597  else
3598  outputContent += "TP_SENSOR TPC ";
3599  };
3600  if (outputData & AOD_SEFD)
3601  {
3602  if (outputData & AOD_TSYS)
3603  outputContent += "SEFD ";
3604  else
3605  outputContent += "TP_SENSOR SEFD ";
3606  };
3607  if (outputData & AOD_PCAL)
3608  outputContent += "PC_SENSOR PCAL ";
3609  if (outputData & AOD_FMTGPS)
3610  outputContent += "FMT2GPS_TIMER FMTGPS";
3611 
3612  if (!outputContent.size())
3613  {
3615  "::createAntCalFile(): station " + stnKey + ": nothing to output");
3616  isOk = false;
3617  return isOk;
3618  }
3619  else
3620  {
3621  outputContent.chop(1);
3623  "::createAntCalFile(): station " + stnKey + ": collected content for output: \"" +
3624  outputContent + "\"");
3625  };
3626  //
3627  if (!outputFileName.size())
3628  {
3629  str = inputLogFileName;
3631  if (filter)
3632  str.chop(filter->getDefaultExtension().size() + 1);
3633 
3634  // set up outut file name:
3635  if (5 < str.size() && str.right(4) == QString(".log"))
3636  str.chop(4);
3637  str += "_orig.anc";
3638  if (ext4compress.size())
3639  str += "." + ext4compress;
3640  }
3641  else
3642  str = outputFileName;
3643 
3644  if (ext4compress.size() && str.right(ext4compress.size()) != ext4compress)
3645  str += "." + ext4compress;
3646 
3647  FILE *pipe=NULL;
3648  QTextStream s;
3649  QFile f(str);
3650  //
3652  "::createAntCalFile(): station " + stnKey + ": " +
3653  " going to create ANTCAL file \"" + f.fileName() + "\"");
3654  //
3655  if (f.exists())
3656  {
3657  if (have2overwrite)
3659  "::createAntCalFile(): the file " + f.fileName() + " already exists; it will be overwritten");
3660  else
3661  {
3663  "::createAntCalFile(): the file " + f.fileName() + " already exists, skipping");
3664  isOk = false;
3665  return isOk;
3666  };
3667  };
3668  //
3669  pipe = compressors.openFlt(str, f, s, FLTD_Output);
3670  //
3671 
3672  // if (haveTsys)
3673  if (outputData & (AOD_TSYS | AOD_DBBC3TP | AOD_TPI | AOD_SEFD))
3674  {
3675  // check channel set up:
3676  if (!channelSkeded)
3678  "::createAntCalFile(): station " + stnKey +
3679  ": the sked's channel setup is missing");
3680  else if (!channelSkeded->isOk())
3682  "::createAntCalFile(): station " + stnKey +
3683  ": the sked's channel setup is not good, skipping it");
3684  else if (!channelSkeded->stnCfgByKey_.contains(stnKey))
3686  "::createAntCalFile(): station " + stnKey +
3687  ": the sked's channel setup does not contain this station, skipping it");
3689  !compareChannelNumbers(channelSkeded->stnCfgByKey_.value(stnKey)))
3691  "::createAntCalFile(): station " + stnKey +
3692  ": the number of collected channels and number of channels in the sked are different, skipping it");
3693  else
3694  {
3695  haveSkeded = true;
3697  "::createAntCalFile(): station " + stnKey +
3698  ": looks like we have channel setup from sked");
3699  };
3700  //
3701  //
3702  if (channelSetup_.selfCheck(stnKey))
3703  {
3704  setup2use = CSU_NATIVE;
3707  setup2use = CSU_VGOS;
3709  "::createAntCalFile(): station " + stnKey +
3710  ": channel setup from the log file looks ok");
3711  if (haveSkeded && channelSetup_.getHwType() != SgChannelSetup::HT_VGOS)
3712  {
3714  "::createAntCalFile(): station " + stnKey +
3715  ": comparing sked's and FS log channel setups");
3716  compareChannelSetups(channelSkeded->stnCfgByKey_.value(stnKey));
3717  };
3718  }
3719  else if (haveSkeded)
3720  {
3721  setup2use = CSU_SKED;
3723  "::createAntCalFile(): station " + stnKey + ": cannot figure out channel setup from the log "
3724  "file, falling back to the set up from sked file");
3725  }
3726  else
3727  {
3728  setup2use = CSU_NONE;
3730  "::createAntCalFile(): station " + stnKey + ": cannot figure out the channel setup");
3731  };
3732 
3733  if (setup2use == CSU_NATIVE && useSkededChannelSetup)
3734  {
3735  setup2use = CSU_SKED;
3737  "::createAntCalFile(): station " + stnKey + ": forced to use the set up from sked file");
3738  };
3739  };
3740 
3741  // find associated onSource records for tsyses:
3742  // ...
3743  // ...
3744 
3745  if (s.device())
3746  {
3747  QFile fInpt(inputLogFileName);
3748  QFileInfo fi(fInpt);
3749 
3750  s << "# ANTCAL Format Version 0.96 of 2021.05.17\n#\n";
3751  s << "STATION: " << qPrintable(stnKey) << "\n#\n";
3752 
3753  s << "#\n# Created with command:\n";
3754  s << "#\n# " << qPrintable(userCommand) << "\n#\n";
3755 
3756  if (backEndInfo_.size())
3757  s << "# BACKEND INFO: " << qPrintable(backEndInfo_) << "\n";
3758  if (recorderInfo_.size())
3759  s << "# RECORDER INFO: " << qPrintable(recorderInfo_) << "\n#\n";
3760 
3761 
3762  s << "EXP_CODE: " << qPrintable(experimentName_.size()?experimentName_.toLower():sFiller_) << "\n#\n";
3763  s << "#\n# sec\n#\nUTC_MTAI: " << dFiller_ << "\n#\n#\n";
3764  s << "# Filler values\n# Real Integer Character\n#\n";
3765  s << "FILLERS: " << dFiller_ << " " << nFiller_ << " " << qPrintable(sFiller_) << "\n#\n";
3766 
3767  s << "#\n";
3768  s << "NUM_PROVENANCE: 1\n";
3769  s << "#\n";
3770 
3771  s << "PROVENANCE: 1 GENERATOR: " << qPrintable(libraryVersion.name()) << " / "
3772  << qPrintable(driverVersion->name()) << "\n";
3773  s << "PROVENANCE: 1 CREATED_VARS: " << qPrintable(outputContent) << "\n";
3774  s << "PROVENANCE: 1 CREATION_DATE: "
3775  << qPrintable(SgMJD().currentMJD().toString(SgMJD::F_SOLVE_SPLFL)) << "\n";
3776  s << "PROVENANCE: 1 NUM_FILES: 1\n";
3777 
3778  s << "PROVENANCE: 1 DATA_TYPE: 1 FS_LOG Version " << fsVersionLabel_ << "\n";
3779  s << "PROVENANCE: 1 DATA_FILE: " << qPrintable(fi.canonicalFilePath()) << "\n";
3780 // s << "PROVENANCE: 1 DATA_FILE: " << qPrintable(inputLogFileName) << "\n";
3781 
3782  s << "PROVENANCE: 1 DATA_CREATED: 1 "
3783  << qPrintable(SgMJD(fi.lastModified()).toString(SgMJD::F_SOLVE_SPLFL)) << "\n";
3784  s << "PROVENANCE: 1 NUM_COMMENTS: 1\n";
3785  s << "PROVENANCE: 1 COMMENT: Original field system log\n#\n";
3786  //
3787  //
3788  //
3789  // Data On/Off:
3790  if (outputData & AOD_DATA_ON)
3791  {
3792  s << "#\nNUM_DATA_ON: " << onSourceRecords_.size() << "\n#\n";
3793  s << "# ScanIdx Data_on UTC start Data_on UTC end Source ScanName\n";
3794  s << "# YYYY.DD.MM-hh:mm:ss.ff YYYY.DD.MM-hh:mm:ss.ff\n";
3795  s <<"#\n";
3796  for (int i=0; i<onSourceRecords_.size(); i++)
3797  {
3799  s << "DATA_ON: "
3800  << qPrintable(str.sprintf("%6d ", i+1) +
3801 // sOn->getTstart().toString(SgMJD::F_SOLVE_SPLFL_V3) + " " + // <- epoch of when antenna is on source
3802  sOn->getTdataOn().toString(SgMJD::F_SOLVE_SPLFL_V3) + " " + // <- epoch of data_valid=on
3803  sOn->getTfinis().toString(SgMJD::F_SOLVE_SPLFL_V3) + " " + // <- epoch of data_valid=off
3804 // srcName4AntCal(sOn->getSourceName()) + " " +
3805  str4AntCal(sOn->getSourceName(), 8) + " " +
3806  str4AntCal(sOn->getScanName(), 8) )
3807 // sOn->getScanName().leftJustified(8, ' ') )
3808  << "\n";
3809  };
3810  s << "#\n";
3811  };
3812  //
3813  //
3814  // Cable sign:
3815  if (outputData & AOD_CABLE_SIGN)
3816  s << "#\nCABLE_SIGN: " << (cableSign_<0?"-1":"+1") << "\n";
3817  //
3818  // Cable cals:
3819  if (outputData & AOD_CABLE_CAL)
3820  {
3821  numOfRecs = 0;
3822  if (reportAllReadings)
3823  numOfRecs = cableCals_.size();
3824  else
3825  for (int i=0; i<cableCals_.size(); i++)
3826  if (cableCals_.at(i)->getOsRec())
3827  numOfRecs++;
3828 
3829  s << "#\nNUM_CABLE: " << numOfRecs << "\n";
3830  s << "#\n";
3831  s << "# CblIdx UTC Date Cable delay Source ScanName\n";
3832  s << "# YYYY.DD.MM-hh:mm:ss.ff s\n";
3833  s << "#\n";
3834  for (int i=0; i<cableCals_.size(); i++)
3835  {
3836  SgCableCalReading *cc=cableCals_.at(i);
3837  const SgOnSourceRecord *sOn=cc->getOsRec();
3838  scanIdx = nFiller_;
3839  if (sOn)
3840  scanIdx = sOn->getIdx() + 1;
3841  if (reportAllReadings || sOn)
3842  {
3843  s << "CABLE: " << qPrintable(str.sprintf("%6d ", scanIdx));
3844  s << qPrintable(
3846  str.sprintf(" %12.5E ", cc->getV()) +
3847 
3848  str4AntCal(sOn?sOn->getSourceName():"", 8) + " " +
3849  str4AntCal(sOn?sOn->getScanName():"", 8) )
3850 // (sOn? srcName4AntCal(sOn->getSourceName()) :sFiller_.leftJustified(8, ' ')) + " " +
3851 // (sOn?sOn->getScanName():sFiller_).leftJustified(8, ' ') )
3852  << "\n";
3853  };
3854  };
3855  s << "#\n";
3856  };
3857  //
3858  //
3859  // meteo:
3860  if (outputData & AOD_METEO)
3861  {
3862  numOfRecs = 0;
3863  if (reportAllReadings)
3864  numOfRecs = meteoPars_.size();
3865  else
3866  for (int i=0; i<meteoPars_.size(); i++)
3867  if (meteoPars_.at(i)->getOsRec())
3868  numOfRecs++;
3869 
3870  s << "#\nNUM_METEO: " << numOfRecs << "\n";
3871  s << "#\n";
3872  s << "# MeteoIdx UTC Date Temp Pres Humid ScanIdx Source Scan\n";
3873  s << "# YYYY.DD.MM-hh:mm:ss.ff K Pa %\n";
3874  s << "#\n";
3875  int meteoIdx;
3876  meteoIdx = 0;
3877  for (int i=0; i<meteoPars_.size(); i++)
3878  {
3879  SgMeteoReading *mr=meteoPars_.at(i);
3880  const SgOnSourceRecord *sOn=mr->getOsRec();
3881  scanIdx = nFiller_;
3882  if (sOn)
3883  scanIdx = sOn->getIdx() + 1;
3884  if (reportAllReadings || sOn)
3885  {
3886  s << "METEO: "
3887  << qPrintable(str.sprintf("%7d ", meteoIdx+1))
3888  << qPrintable(mr->getT().toString(SgMJD::F_SOLVE_SPLFL_V3)) << " "
3889  << qPrintable(QString("").sprintf("%6.2f %7.1f %5.1f ",
3890  mr->getM().getTemperature() + 273.15,
3891  mr->getM().getPressure()*100.0,
3892  mr->getM().getRelativeHumidity()*100.0))
3893  << qPrintable(str.sprintf("%6d ", scanIdx))
3894  << qPrintable(
3895  str4AntCal(sOn?sOn->getSourceName():"", 8) + " " +
3896  str4AntCal(sOn?sOn->getScanName():"", 8) )
3897 // (sOn?srcName4AntCal(sOn->getSourceName()):sFiller_.leftJustified(8, ' ')) + " " +
3898 // (sOn?sOn->getScanName():sFiller_).leftJustified(8, ' ') )
3899  << "\n";
3900  meteoIdx++;
3901  };
3902  };
3903  s << "#\n";
3904  };
3905  //
3906  //
3907  // TP_SENSORS:
3908  if (outputData & (AOD_TSYS | AOD_TPI | AOD_SEFD | AOD_DBBC3TP))
3909  {
3910  // sensor info:
3911  s << "#\n#\n";
3912  if (setup2use == CSU_NATIVE)
3913  {
3914 // if (outputData & AOD_DBBC3TP)
3915 // export2antCalFrqs_dbbc3Setup(s);
3916 // else
3917  //export2antCalFrqs_nativeSetup(s);
3919  }
3920  else if (setup2use == CSU_VGOS)
3921  {
3922 // if (outputData & AOD_DBBC3TP)
3923 // export2antCalFrqs_dbbc3Setup(s);
3924 // else
3925 // export2antCalFrqs_dbbc3Setup(s);
3927  }
3928  else if (setup2use == CSU_SKED && channelSkeded->stnCfgByKey_.contains(stnKey))
3929  export2antCalFrqs_skededSetup(s, channelSkeded->stnCfgByKey_.value(stnKey));
3930  else if (setup2use == CSU_NONE)
3932  else
3933  {
3934  s << "#\n";
3935  s << "# No TP_SENSOR data available\n";
3936  s << "#\n";
3937  };
3938  };
3939  //
3940  //
3941  // TSYS:
3942  if (outputData & AOD_TSYS)
3943  {
3944  numOfRecs = 0;
3945  if (reportAllReadings)
3946  {
3947  for (int i=0; i<tSyses_.size(); i++)
3948  if (tSyses_.at(i)->getTsys().size())
3949  numOfRecs++;
3950  }
3951  else
3952  for (int i=0; i<tSyses_.size(); i++)
3953  if (tSyses_.at(i)->getOsRec() && tSyses_.at(i)->getTsys().size())
3954  numOfRecs++;
3955 
3956  s << "#\nNUM_TSYS: " << numOfRecs << "\n";
3957  s << "#\n";
3958  s << "# ScanIdx UTC_Time_tag Sensor Tsys Azimuth Elevat Source Scan DataScopeFlag\n";
3959  s << "# YYYY.DD.MM-hh:mm:ss.ff tag K deg deg\n";
3960  s << "#\n";
3961  //
3962  //
3963  for (int i=0; i<tSyses_.size(); i++)
3964  {
3965  SgTsysReading *tsr=tSyses_.at(i);
3966  if (tsr->getTsys().size())
3967  {
3968  el = az = dFiller_;
3969  //
3970  // check for az/el info:
3971  SgTraklReading *trakl=NULL;
3972  double dt=1.0e3, d=0.0;
3973  //
3974  for (int j=0; j<tsr->trakls().size(); j++)
3975  if (tsr->trakls().at(j) &&
3976  (d=fabs(tsr->getT() - tsr->trakls().at(j)->getT())) < dt)
3977  {
3978  dt = d;
3979  trakl = tsr->trakls().at(j);
3980  };
3981  if (trakl && dt < 4.0/DAY2SEC)
3982  {
3983  az = trakl->getAz();
3984  el = trakl->getEl();
3985  };
3986  //
3987  // src & scan names:
3988  srcName = scnName = sFiller_;
3989  scanIdx = nFiller_;
3990  const SgOnSourceRecord *osRec=tsr->getOsRec();
3991  if (osRec)
3992  {
3993  srcName = osRec->getSourceName();
3994  scnName = osRec->getScanName();
3995  scanIdx = osRec->getIdx() + 1;
3996  };
3997  //
3998  if (reportAllReadings || osRec)
3999  {
4000  int idx=1;
4001  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
4002  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it, idx++)
4003  {
4004  QString sensorKey(it.key());
4005  double v;
4006  hasSensor = false;
4007  v = dFiller_;
4008  if (tsr->getTsys().contains(sensorKey))
4009  {
4010  v = tsr->getTsys().value(sensorKey);
4011  hasSensor = true;
4012  };
4013  if (!supressNonUsedSensors || hasSensor)
4014  {
4015  dataFlagIdx = osRec?(osRec->getTdataOn()<tsr->getT()?2:1):0;
4016  str.sprintf("TSYS: %6d %s TS_%03d %7.1f %9.4f %8.4f %s %s %s",
4017  scanIdx, qPrintable(tsr->getT().toString(SgMJD::F_SOLVE_SPLFL_V3)),
4018  idx, v, az, el,
4019 // qPrintable(srcName.leftJustified(8, ' ')),
4020  qPrintable(str4AntCal(srcName, 8)),
4021  qPrintable(str4AntCal(scnName, 9)),
4022 // qPrintable(srcName4AntCal(srcName)),
4023 // qPrintable(scnName.leftJustified(9, ' ')),
4024  qPrintable(dataFlag[dataFlagIdx])
4025 // , qPrintable(it.key())
4026  );
4027  s << str << "\n";
4028  };
4029  };
4030  };
4031  };
4032  };
4033  s << "#\n";
4034  };
4035  //
4036  //
4037  // TPI data:
4038  if (outputData & AOD_TPI)
4039  {
4040  numOfRecs = 0;
4041  if (reportAllReadings)
4042  {
4043  for (int i=0; i<tSyses_.size(); i++)
4044  if (tSyses_.at(i)->getTpcont().size())
4045  numOfRecs++;
4046  }
4047  else
4048  for (int i=0; i<tSyses_.size(); i++)
4049  if (tSyses_.at(i)->getOsRec() && tSyses_.at(i)->getTpcont().size())
4050  numOfRecs++;
4051 
4052  s << "#\nNUM_TPI: " << numOfRecs << "\n";
4053  s << "#\n";
4054  s << "# ScanIdx UTC_Time_tag Sensor TpiOn TpiOff Azimuth Elevat Source Scan DataScopeFlag\n";
4055  s << "# YYYY.DD.MM-hh:mm:ss.ff tag K K deg deg\n";
4056  s << "#\n";
4057  //
4058  for (int i=0; i<tSyses_.size(); i++)
4059  {
4060  SgTsysReading *tsr=tSyses_.at(i);
4061  if (tsr->getTpcont().size())
4062  {
4063  el = az = dFiller_;
4064  //
4065  // check for az/el info:
4066  SgTraklReading *trakl=NULL;
4067  double dt=1.0e3, d=0.0;
4068  for (int j=0; j<tsr->trakls().size(); j++)
4069  if (tsr->trakls().at(j) &&
4070  (d=fabs(tsr->getT() - tsr->trakls().at(j)->getT())) < dt)
4071  {
4072  dt = d;
4073  trakl = tsr->trakls().at(j);
4074  };
4075  if (trakl && dt < 4.0/DAY2SEC)
4076  {
4077  az = trakl->getAz();
4078  el = trakl->getEl();
4079  };
4080  //
4081  // src & scan names:
4082  srcName = scnName = sFiller_;
4083  scanIdx = nFiller_;
4084  const SgOnSourceRecord *osRec=tsr->getOsRec();
4085  if (osRec)
4086  {
4087  srcName = osRec->getSourceName();
4088  scnName = osRec->getScanName();
4089  scanIdx = osRec->getIdx() + 1;
4090  };
4091  //
4092  if (reportAllReadings || osRec)
4093  {
4094  int idx=1;
4095  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
4096  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it, idx++)
4097  {
4098  QString sensorKey(it.key());
4099  int vOn, vOf;
4100  vOn = vOf = dFiller_;
4101  hasSensor = false;
4102  if (tsr->getTpcont().contains(sensorKey))
4103  {
4104  vOn = tsr->getTpcont().value(sensorKey)[0];
4105  vOf = tsr->getTpcont().value(sensorKey)[1];
4106  hasSensor = true;
4107  };
4108  if (!supressNonUsedSensors || hasSensor)
4109  {
4110  dataFlagIdx = osRec?(osRec->getTdataOn()<tsr->getT()?2:1):0;
4111  str.sprintf("TPI: %6d %s TS_%03d %8d %8d %9.4f %8.4f %s %s %s",
4112  scanIdx, qPrintable(tsr->getT().toString(SgMJD::F_SOLVE_SPLFL_V3)),
4113  idx, vOn, vOf, az, el,
4114 // qPrintable(srcName.leftJustified(8, ' ')),
4115  qPrintable(str4AntCal(srcName, 8)),
4116  qPrintable(str4AntCal(scnName, 9)),
4117 // qPrintable(srcName4AntCal(srcName)),
4118 // qPrintable(scnName.leftJustified(9, ' ')),
4119  qPrintable(dataFlag[dataFlagIdx]));
4120  s << str << "\n";
4121  };
4122  };
4123  };
4124  };
4125  };
4126  s << "#\n";
4127  //
4128  //
4129  };
4130  //
4131  if (outputData & AOD_PCAL)
4132  {
4133  // sensor setups:
4135  //
4136  numOfRecs = 0;
4137  if (reportAllReadings)
4138  numOfRecs = pcals_.size();
4139  else
4140  for (int i=0; i<pcals_.size(); i++)
4141  if (pcals_.at(i)->getOsRec())
4142  numOfRecs++;
4143 
4144  s << "#\nNUM_PCAL: " << numOfRecs << "\n";
4145  s << "#\n";
4146  //
4147  // pcal data:
4148  s << "#\n";
4149  s << "# ScanIdx UTC_Time_tag Sensor Ampl Phase Source Scan DataScopeFlag\n";
4150  s << "# YYYY.DD.MM-hh:mm:ss.ff tag rad [0,2pi)\n";
4151  s << "#\n";
4152 
4153  for (int i=0; i<pcals_.size(); i++)
4154  {
4155  SgPcalReading *pcr=pcals_.at(i);
4156  //
4157  // src & scan names:
4158  srcName = scnName = sFiller_;
4159  scanIdx = nFiller_;
4160  const SgOnSourceRecord *osRec=pcr->getOsRec();
4161  if (osRec)
4162  {
4163  srcName = osRec->getSourceName();
4164  scnName = osRec->getScanName();
4165  scanIdx = osRec->getIdx() + 1;
4166  };
4167  //
4168  if (reportAllReadings || osRec)
4169  {
4170  int idx=1;
4171  for (QMap<QString, QString>::const_iterator it=channelSetup_.pcalIdByKey().begin();
4172  it!=channelSetup_.pcalIdByKey().end(); ++it, idx++)
4173  {
4174  float vAmp, vPhs;
4175  vAmp = vPhs = dFiller_;
4176  hasSensor = false;
4177  if (pcr->getPcal().contains(it.value()))
4178  {
4179  vAmp = *pcr->getPcal().value(it.value());
4180  vPhs = *(pcr->getPcal().value(it.value()) + 1);
4181  vPhs = fmodf(vPhs + 360.0, 360.0)/RAD2DEG; // deg -> rad
4182  hasSensor = true;
4183  };
4184  if (!supressNonUsedSensors || hasSensor)
4185  {
4186  dataFlagIdx = osRec?(osRec->getTdataOn()<pcr->getT()?2:1):0;
4187  str.sprintf("PCAL: %6d %s PC_%03d %8.3f %10.5f %s %s %s",
4188  scanIdx, qPrintable(pcr->getT().toString(SgMJD::F_SOLVE_SPLFL_V3)),
4189  idx, vAmp, vPhs,
4190 // qPrintable(srcName.leftJustified(8, ' ')),
4191  qPrintable(str4AntCal(srcName, 8)),
4192  qPrintable(str4AntCal(scnName, 9)),
4193 // qPrintable(srcName4AntCal(srcName)),
4194 // qPrintable(scnName.leftJustified(9, ' ')),
4195  qPrintable(dataFlag[dataFlagIdx]));
4196  s << str << "\n";
4197  };
4198  };
4199  };
4200  };
4201  s << "#\n";
4202  };
4203  //
4204  //
4205  if (outputData & AOD_FMTGPS)
4206  {
4207  // header:
4208  s << "#\nNUM_FMT2GPS_TIMER: " << channelSetup_.xpsIdByKey().size() << "\n";
4209  s << "# Timer Board\n";
4210  s << "# tag\n";
4211  s << "#\n";
4212  int idx=1;
4213  for (QMap<QString, QString>::const_iterator it=channelSetup_.xpsIdByKey().begin();
4214  it!=channelSetup_.xpsIdByKey().end(); ++it)
4215  {
4216  QString id(it.value());
4217  str.sprintf("FMT2GPS_TIMER: TMR_%03d %s",
4218  idx, qPrintable(id) );
4219  s << str << "\n";
4220  idx++;
4221  };
4222  //
4223  numOfRecs = 0;
4224  if (reportAllReadings)
4225  numOfRecs = dot2xpses_.size();
4226  else
4227  for (int i=0; i<dot2xpses_.size(); i++)
4228  if (dot2xpses_.at(i)->getOsRec())
4229  numOfRecs++;
4230 
4231  s << "#\nNUM_FMTGPS: " << numOfRecs << "\n";
4232  s << "#\n";
4233  s << "# Scan UTC_Time_tag Timer Formatter minus Formatter minus Source Scan\n";
4234  s << "# Idx tag GPS time PPS time\n";
4235  s << "# YYYY.DD.MM-hh:mm:ss.ff s s\n";
4236  s << "#\n";
4237  for (int i=0; i<dot2xpses_.size(); i++)
4238  {
4239  SgDot2xpsReading *d2r=dot2xpses_.at(i);
4240  //
4241  // src & scan names:
4242  srcName = scnName = sFiller_;
4243  scanIdx = nFiller_;
4244  const SgOnSourceRecord *osRec=d2r->getOsRec();
4245  if (osRec)
4246  {
4247  srcName = osRec->getSourceName();
4248  scnName = osRec->getScanName();
4249  scanIdx = osRec->getIdx() + 1;
4250  };
4251  //
4252  if (reportAllReadings || osRec)
4253  {
4254  int idx=1;
4255  for (QMap<QString, QString>::const_iterator it=channelSetup_.xpsIdByKey().begin();
4256  it!=channelSetup_.xpsIdByKey().end(); ++it, idx++)
4257  {
4258  float v1, v2;
4259  v1 = v2 = dFiller_;
4260  hasSensor = false;
4261  if (d2r->getDot2gpsByBrd().contains(it.value()))
4262  {
4263  v1 = d2r->getDot2gpsByBrd().value(it.value());
4264  v2 = d2r->getDot2ppsByBrd().value(it.value());
4265  hasSensor = true;
4266  };
4267  if (!supressNonUsedSensors || hasSensor)
4268  {
4269  str.sprintf("FMTGPS: %6d %s TMR_%03d %16.9e %16.9e %s %s",
4270  scanIdx, qPrintable(d2r->getT().toString(SgMJD::F_SOLVE_SPLFL_V3)),
4271  idx, v1, v2,
4272 // qPrintable(srcName.leftJustified(8, ' ')),
4273  qPrintable(str4AntCal(srcName, 8)),
4274  qPrintable(str4AntCal(scnName, 9)));
4275 // qPrintable(srcName4AntCal(srcName)),
4276 // qPrintable(scnName.leftJustified(9, ' ')) );
4277  s << str << "\n";
4278  };
4279  };
4280  };
4281  };
4282  s << "#\n";
4283  };
4284  //
4285  //
4286  if (outputData & AOD_DBBC3TP)
4287  {
4288  // header:
4289  s << "#\n#\n";
4290 // export2antCalFrqs_dbbc3Setup(s);
4292 
4293  numOfRecs = 0;
4294  if (reportAllReadings)
4295  numOfRecs = dbbc3Tps_.size();
4296  else
4297  for (int i=0; i<dbbc3Tps_.size(); i++)
4298  if (dbbc3Tps_.at(i)->getOsRec())
4299  numOfRecs++;
4300 
4301  s << "#\nNUM_TPC: " << numOfRecs << "\n";
4302  s << "#\n";
4303  s << "# ScanIdx UTC_Time_tag Sensor Gain TpCalOn TpCalOff SEFD Azimuth Elevat Source Scan DataScopeFlag\n";
4304  s << "# YYYY.DD.MM-hh:mm:ss.ff tag Jy deg deg\n";
4305  s << "#\n";
4306  //
4307  for (int i=0; i<dbbc3Tps_.size(); i++)
4308  {
4309  SgDbbc3TpReading *rec=dbbc3Tps_.at(i);
4310  el = az = dFiller_;
4311  //
4312  // check for az/el info:
4313  // ...
4314  //
4315  // src & scan names:
4316  srcName = scnName = sFiller_;
4317  scanIdx = nFiller_;
4318  const SgOnSourceRecord *osRec=rec->getOsRec();
4319  if (osRec)
4320  {
4321  srcName = osRec->getSourceName();
4322  scnName = osRec->getScanName();
4323  scanIdx = osRec->getIdx() + 1;
4324  };
4325  //
4326  if (reportAllReadings || osRec)
4327  {
4328  int idx=1;
4329  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
4330  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it, idx++)
4331  {
4332  double vGain, vOn, vOf, vSefd;
4333  vGain = vOn = vOf = vSefd = dFiller_;
4334  QString bbcId(it.value());
4335 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
4336  QString sbId(it.value().at(it.value().size() - 1));
4337 #else
4338  QString sbId(it.value().back());
4339 #endif
4340  bbcId.chop(1);
4341  hasSensor = false;
4342  if (rec->getTpBySensor().contains(bbcId))
4343  {
4344  if (sbId == "l")
4345  {
4346  vGain = rec->getTpBySensor().value(bbcId).gainL_;
4347  vOn = rec->getTpBySensor().value(bbcId).tpOnL_;
4348  vOf = rec->getTpBySensor().value(bbcId).tpOffL_;
4349  vSefd = rec->getTpBySensor().value(bbcId).sefdL_;
4350  }
4351  else if (sbId == "u")
4352  {
4353  vGain = rec->getTpBySensor().value(bbcId).gainU_;
4354  vOn = rec->getTpBySensor().value(bbcId).tpOnU_;
4355  vOf = rec->getTpBySensor().value(bbcId).tpOffU_;
4356  vSefd = rec->getTpBySensor().value(bbcId).sefdU_;
4357  }
4358  else
4360  "::createAntCalFile(): station " + stnKey +
4361  ": got an unknown sideband id: \"" + sbId + "\", IF id is \"" +
4362  it.value() + "\"");
4363  hasSensor = true;
4364  };
4365  if (!supressNonUsedSensors || hasSensor)
4366  {
4367  dataFlagIdx = osRec?(osRec->getTdataOn()<rec->getT()?2:1):0;
4368  str.sprintf("TPC: %6d %s TS_%03d %8.1f %10.1f %10.1f %10.1f %9.4f %8.4f %s %s %s",
4369  scanIdx, qPrintable(rec->getT().toString(SgMJD::F_SOLVE_SPLFL_V3)),
4370  idx, vGain, vOn, vOf, vSefd, az, el,
4371 // qPrintable(srcName.leftJustified(8, ' ')),
4372  qPrintable(str4AntCal(srcName, 8)),
4373  qPrintable(str4AntCal(scnName, 9)),
4374 // qPrintable(srcName4AntCal(srcName)),
4375 // qPrintable(scnName.leftJustified(9, ' ')),
4376  qPrintable(dataFlag[dataFlagIdx])
4377  );
4378  s << str << "\n";
4379  };
4380  };
4381  };
4382  };
4383  s << "#\n";
4384  };
4385  //
4386  //
4387  if (outputData & AOD_SEFD)
4388  {
4389  // header:
4390  s << "#\n#\n";
4391 // export2antCalFrqs_dbbc3Setup(s);
4393  s << "#\nNUM_SEFD: " << sefds_.size() << "\n#\n";
4394  s << "# some docs on OnOff measurements can be found in FS sources, fs-master/onoff/onoff.txt\n";
4395  s << "# and fs-master/onoff/gain.txt\n";
4396  s << "#\n";
4397  s << "# Sensor UTC_Time_tag SEFD Tsys Tcal Trat Gain Az El Source\n";
4398  s << "# tag YYYY.DD.MM-hh:mm:ss.ff Jy K Jy Compress deg deg\n";
4399  s << "#\n";
4400  //
4401  for (int i=0; i<sefds_.size(); i++)
4402  {
4403  SgSefdReading *sefd=sefds_.at(i);
4404  az = sefd->getAz();
4405  el = sefd->getEl();
4406  srcName = sefd->getSrcName();
4407  //
4408  int idx=1;
4409  for (QMap<QString, QString>::const_iterator it=channelSetup_.ifIdByTpSensorKey().begin();
4410  it!=channelSetup_.ifIdByTpSensorKey().end(); ++it, idx++)
4411  {
4412  QString sensorKey(it.key());
4413  double v2, v3, v4, v5, v6;
4414  v2 = v3 = v4 = v5 = v6 = dFiller_;
4415  hasSensor = false;
4416  if (sefd->getValByChanKey().contains(sensorKey))
4417  {
4418  const QVector<double>
4419  *vec=sefd->getValByChanKey().value(sensorKey);
4420  v2 = vec->at(1);
4421  v3 = vec->at(2);
4422  v4 = vec->at(3);
4423  v5 = vec->at(4);
4424  v6 = vec->at(5);
4425  hasSensor = true;
4426  }
4427  else
4429  "::createAntCalFile(): station " + stnKey +
4430  ": the sensor key \"" + sensorKey + "\" is not found in the SEFD map");
4431  if (!supressNonUsedSensors || hasSensor)
4432  {
4433  str.sprintf("SEFD: TS_%03d %s %10.3f %10.3f %10.3f %10.3f %10.3f %9.4f %9.4f %s",
4434  idx, qPrintable(sefd->getT().toString(SgMJD::F_SOLVE_SPLFL_V3)),
4435  v4, v3, v5, v6, v2,
4436  az, el,
4437  qPrintable(srcName));
4438  s << str << "\n";
4439  };
4440  };
4441  };
4442  s << "#\n";
4443  };
4444  //
4445  // end of output
4446  //
4447  s << "#\n";
4448  s << "#\n";
4449  s << "# End of file\n";
4450  compressors.closeFlt(pipe, f, s);
4451  }
4452  else
4453  isOk = false;
4454 
4455  return isOk;
4456 };
4457 /*=====================================================================================================*/
4458 
4459 
4460 
4461 
4462 
4463 
4464 
4465 
4466 /*=======================================================================================================
4467 *
4468 * SgStnLogCollector's METHODS:
4469 *
4470 *======================================================================================================*/
4471 const QRegularExpression SgStnLogCollector::reFsOld_("^\\d{9}\\D+");
4472 const QRegularExpression SgStnLogCollector::reFsNew_("^\\d{13}\\D+");
4473 //const QRegularExpression SgStnLogCollector::reFsNewest_("^(\\d{4})\\.(\\d{3})\\.(\\d{2}):(\\d{2})[:\\s]"
4474 //"(\\d{2}\\.\\d{1,3})\\D+");
4475 const QRegularExpression SgStnLogCollector::reFsNewest_("^(\\d{4})\\.([0-9\\s]{3})\\.(\\d{2}):(\\d{2})[:\\s]"
4476  "(\\d{2}\\.?\\d{0,3})\\D+");
4477 const QRegularExpression SgStnLogCollector::rePcmt_("^\\s*\\d{4}\\s+\\d{1,2}\\s+\\d{1,2}\\s+\\d{1,2}\\s+"
4478  "\\d{1,2}\\s+\\d{1,2}\\s+[\\d\\.eEdD+-]{1,}\\s+[\\dA-Z+-]{2,}\\s+\\d{3}-\\d{4}[a-z]?\\s*$");
4479 const QRegularExpression SgStnLogCollector::reMet_("^\\s*\\d{2,4}\\s+\\d{1,2}\\s+\\d{1,2}\\s+\\"
4480  "d{1,2}\\s+\\d{1,2}\\s+\\d{1,2}\\s+[+-]?[\\d\\.]{1,}\\s+[+-]?[\\d\\.]{1,}\\s+[+-]?[\\d\\.]{1,}\\s*$");
4481 
4482 
4483 //
4484 // static first:
4485 //
4487 {
4488  return "SgStnLogCollector";
4489 };
4490 
4491 
4492 
4493 // An empty constructor:
4495  stationName_(""),
4496  logReadings_(),
4497  inputLogFileName_(""),
4498  userCommand_("")
4499 {
4501  fsFmt_ = FSEF_UNDEF;
4502  inYear_ = 0;
4503  defaultCableSignByStn_ = NULL;
4504  rinexFileNameByStn_ = NULL;
4507  useSkededChannelSetup_ = false;
4508  channelSkeded_ = NULL;
4509 };
4510 
4511 
4512 
4513 //
4514 // A destructor:
4516 {
4517  for (QMap<QString, Procedure*>::iterator it=procedureByName_.begin();
4518  it!=procedureByName_.end(); ++it)
4519  delete it.value();
4520  procedureByName_.clear();
4521 };
4522 
4523 
4524 
4525 //
4526 bool SgStnLogCollector::readLogFile(const QString& fileName, const QString& stnName,
4527  const SgMJD& tFirst, const SgMJD& tLast, const QString& orderOfMeteo)
4528 {
4529  stationName_ = stnName; // simplified name, no spaces
4530  if (!stationName_.size())
4531  stationName_ = "n/a";
4532 
4534  inputLogFileName_ = fileName;
4535 
4536  QString str("");
4537  QString strTmp("");
4538  QString sScanName("");
4539  QString sSourceName("");
4540  QString versionStr("");
4541  QFile f(fileName);
4542  FILE *pipe=NULL;
4543  SgMJD t, lastReadTsys(tZero), lastReadPcal(tZero);
4544  SgMJD lastReadDot2xps(tZero), lastReadSefd(tZero);
4545  SgMJD tRightMargin(tLast + 5.0/24.0/60.0); // 5 min
4546  SgMJD tAtTheEnd(tLast - 75.0/24.0/60.0); // 75 min
4547  SgMJD tAtTheBegin(tFirst - 7.0/24.0/60.0); // 7 min
4548  SgOnSourceRecord *osRec;
4549  bool isDataOn, isOnSource, reachedEndOfSession, hasStnName;
4550  int oom[3];
4551  hasStnName = (0 < stnName.size());
4552 
4553  // define meteo parameters order:
4554  // natural order:
4555  oom[0] = 0;
4556  oom[1] = 1;
4557  oom[2] = 2;
4558  //
4559  //
4560  if (orderOfMeteo.size())
4561  {
4562  str = "";
4563  for (int i=0; i<orderOfMeteo.size(); i++)
4564  {
4565  if (orderOfMeteo.at(i) == 'T')
4566  {
4567  oom[0] = i;
4568  str += "T";
4569  }
4570  else if (orderOfMeteo.at(i) == 'P')
4571  {
4572  oom[1] = i;
4573  str += "P";
4574  }
4575  else if (orderOfMeteo.at(i) == 'H')
4576  {
4577  oom[2] = i;
4578  str += "H";
4579  }
4580  };
4582  "::readLogFile(): the order of meteoparamters is set to \"" + str + "\"");
4583  };
4584 
4585 
4586 // /500/sessions/2001/cb901/cb90145.log:2001.127.20:06:01.66:"data_valid=on
4587 
4588 //QRegularExpression reOnSource(":preob|#trakl#\\s*Source acquired|#flagr#flagr/antenna,acquired|/onsource/TRACKING",
4589 // "/onsource/TRACKING" occured between data_valid=on and data_valid=off too (e.g., r1980ht.log)
4590 
4591 // QRegularExpression reOnSource(":preob|#trakl#\\s*Source acquired|"
4592 // "#flagr#flagr/antenna,acquired|&preob/onsource|&preob/track|/onsource",
4593 // QRegularExpression::CaseInsensitiveOption);
4594  QRegularExpression reOnSource(":preob|#trakl#\\s*Source acquired|"
4595  "#flagr#flagr/antenna,acquired|&preob[a-z0-9+_-]*/onsource|&preob/track",
4596  QRegularExpression::CaseInsensitiveOption);
4597 //QRegularExpression reDataOn(":data_valid=on|data start\\W+|:midob",
4598  QRegularExpression reDataOn("(:|/)data_valid=on|data start\\W+|:midob",
4599  QRegularExpression::CaseInsensitiveOption);
4600 //QRegularExpression reDataOff(":data_valid=off|data stop\\W+|;terminate|;halt|:postob",
4601  QRegularExpression reDataOff("(:|/)data_valid=off|data stop\\W+|;terminate|;halt|:postob",
4602  QRegularExpression::CaseInsensitiveOption);
4603 
4604  QRegularExpression reTapeOn("/tape\\d?/.*moving,.*(?:nostop|locked)",
4605  QRegularExpression::CaseInsensitiveOption);
4606  QRegularExpression reTapeOff("/tape\\d?/.*(?:stopped,.*unlocked|moving,.*stop|"
4607  "stopped,.*stop)", QRegularExpression::CaseInsensitiveOption);
4608 
4609  QRegularExpression reScanName(":scan_name=([_a-zA-Z0-9+-]{1,}),([a-zA-Z0-9_+-]+),?.*",
4610  QRegularExpression::CaseInsensitiveOption);
4611  QRegularExpression reSourceName(":source=([\\.a-zA-Z0-9_+-]{1,10}),.*",
4612  QRegularExpression::CaseInsensitiveOption);
4613 
4614  QRegularExpression reMeteo("(#wx#/WX/|/?wx/|DSNWX/|wx/weather:)([^,]+),([^,]+),([^,]+).*",
4615  QRegularExpression::CaseInsensitiveOption);
4616 
4617  QRegularExpression reCableCal("(/cable/|cableget/)(.+)",
4618  QRegularExpression::CaseInsensitiveOption);
4619 
4620  QRegularExpression reCableLong("(/cablelong/)(.+)",
4621  QRegularExpression::CaseInsensitiveOption);
4622  QRegularExpression reVersion("(mark\\s+.+\\s+field system\\s+v\\w*\\s*)(.+)",
4623  QRegularExpression::CaseInsensitiveOption);
4624 
4625 //2010.140.18:22:06.70/cablediff/683.3e-6,+
4626  QRegularExpression reCableDiff("((?:/|;\"*\\s*)cable\\s*diff(?:/|;*\\s*))([^,]+),([+-])",
4627  QRegularExpression::CaseInsensitiveOption);
4628 //2012.068.18:11:48.08;"cable sign is positive, OK
4629  QRegularExpression reCableSign("(c\\w?a\\w?b\\w?l\\w?e\\w?|ca\\w{2,2}e)\\s+sign\\s+is\\s+"
4630  "(positive|negative)", QRegularExpression::CaseInsensitiveOption);
4631  QRegularExpression reCableDiffIs("cable\\s+dif{1,2}e\\w{2,3}ce\\s+(?:is|was)",
4632  QRegularExpression::CaseInsensitiveOption);
4633  QRegularExpression reOpComments("\\d+;\"(.+)", QRegularExpression::CaseInsensitiveOption);
4634  //
4635  //2017 9 11 18 3 46 7.92e-12 254-1803
4636  QRegularExpression rePcmt("(\\d{4})\\s+(\\d{1,2})\\s+(\\d{1,2})\\s+"
4637  "(\\d{1,2})\\s+(\\d{1,2})\\s+(\\d{1,2})\\s+"
4638  "(.+)\\s+([\\dA-Z+-]{2,8})\\s+([0-9a-z-]{0,}).*",
4639  QRegularExpression::CaseInsensitiveOption);
4640 // 2017 09 11 18 05 8 -2.8e-12 1300+580 254-1805
4641 // 2017 09 11 18 06 16 -1.765e-11 NRAO512 254-1806
4642  QRegularExpression reMet("(\\d{2,4})\\s+(\\d{1,2})\\s+(\\d{1,2})\\s+"
4643  "(\\d{1,2})\\s+(\\d{1,2})\\s+(\\d{1,2})\\s+"
4644  "([\\d\\.+-]+)\\s+([\\d\\.+-]+)\\s+([\\d\\.+-]+).*",
4645  QRegularExpression::CaseInsensitiveOption);
4646 
4647  QRegularExpression reCdms("([/#]CDMS/)(.+)", QRegularExpression::CaseInsensitiveOption);
4648 
4649  // tsys:
4650  //2019.007.19:06:32.52/tsys/1l,62.2,1u,65.6,2u,56.4,3u,68.0,4u,61.6,ia,60.4
4651  //2019.007.19:06:32.52/tsys/5u,66.5,6u,58.4,7u,61.2,8l,59.1,8u,58.6,ib,55.0
4652  //2019.007.19:06:32.52/tsys/9u,89.3,au,85.7,bu,51.5,cu,92.3,ic,82.8
4653  //2019.007.19:06:32.52/tsys/du,118.7,eu,168.7,id,46.5
4654  QRegularExpression reTsys("([/#]tsys/)([^,]+),([^,]+).*",
4655  QRegularExpression::CaseInsensitiveOption);
4656 
4657  //2020.021.18:00:00.15#rdtca#tsys/ 00a0,217.6, 01a0,126.9, 02a0,123.6, 03a0,106.4, 04a0, 95.2, 05a0, 92.7, 06a0, 98.3, 07a0,119.9
4658  //2020.021.18:00:00.15#rdtca#tsys/ 08a0, 50.6, 09a0, 84.7, 10a0, 87.4, 11a0,118.1, 12a0,$$$$$, 13a0, 86.5, 14a0, 80.5, 15a0, 79.4
4659  //2020.021.18:00:00.15#rdtca#tsys/ AVa0,101.5, SMa0,233.4
4660  //2020.021.18:00:00.15#rdtca#tsys/ 00a1, 80.2, 01a1, 51.4, 02a1, 47.8, 03a1, 45.7, 04a1, 46.4, 05a1, 46.5, 06a1, 44.2, 07a1, 52.0
4661  //2020.021.18:00:00.15#rdtca#tsys/ 08a1, 35.5, 09a1, 46.0, 10a1, 43.8, 11a1, 43.8, 12a1, 60.6, 13a1, 44.5, 14a1, 48.7, 15a1, 49.4
4662  //2020.021.18:00:00.15#rdtca#tsys/ AVa1, 47.8, SMa1, 47.5
4663  /*
4664  */
4665  QRegularExpression reTsysVgos("(#rdtc\\w#tsys/ )([^,]+),([^,]+).*");
4666 
4667 
4668  //2020.021.18:00:00.17#rdtcd#tpcont/ 00d0, 12501, 12325, 01d0, 16054, 15765, 02d0, 20774, 20410, 03d0, 24388, 23985, 04d0, 27599, 27153
4669  //2020.021.18:00:00.17#rdtcd#tpcont/ 05d0, 28085, 27647, 06d0, 29475, 29027, 07d0, 30963, 30479, 08d0, 29392, 28953, 09d0, 30078, 29643
4670  //2020.021.18:00:00.17#rdtcd#tpcont/ 10d0, 37494, 36960, 11d0, 42335, 41705, 12d0, 46499, 45802, 13d0, 51354, 50535, 14d0, 49839, 48925
4671  //2020.021.18:00:00.17#rdtcd#tpcont/ 15d0, 43153, 42272
4672  QRegularExpression reTpcontVgos("(#rdtc\\w#tpcont/ )([^,]+),([^,]+).*");
4673 
4674 
4675  //2022.347.15:11:13.04&setmode_m08/rdbea=pcal=1.400e6;
4676  //2022.347.15:11:13.04&setmode_m08/rdbeb=pcal=1.400e6;
4677  //2022.347.15:11:13.04&setmode_m08/rdbec=pcal=4.400e6;
4678  //2022.347.15:11:13.04&setmode_m08/rdbed=pcal=2.400e6;
4679  //
4680  //2022.322.23:30:09.85&rdbebb/rdbe=pcal=1.4e6;
4681 
4682  QRegularExpression rePcalOffset("&.+/rdbe([a-z0-9]*)=pcal=([0-9\\.eEfFdD+-]+).*");
4683 
4684  //2020.195.11:30:01.17#rdtca#pcal/ 1a0000, 8.686, -98.7, 1a0005, 78.913, 116.7, 1a0010, 8.729, 147.9, 1a0015, 81.273, 4.1
4685  //2020.195.11:30:01.17#rdtca#pcal/ 1a0020, 9.421, 37.5, 1a0025, 88.580, -105.5, 1a0030, 10.177, -72.2, 1a0035, 97.212, 144.1
4686  //2020.195.11:30:01.17#rdtca#pcal/ 1a0040, 11.646, 176.3, 1a0045, 89.248, 33.1, 1a0050, 10.577, 65.5, 1a0055, 93.330, -79.2
4687  //2020.195.11:30:01.17#rdtca#pcal/ 1a0060, 10.255, -47.4, 1a0065, 93.203, 169.1, 1a0070, 10.437, -155.9, 1a0075, 89.414, 59.5
4688  //2020.195.11:30:01.17#rdtca#pcal/ 1a0080, 10.014, 92.8, 1a0085, 84.492, -47.7, 1a0090, 9.561, -14.2, 1a0095, 82.770, -155.3
4689  //2020.195.11:30:01.17#rdtca#pcal/ 1a0100, 8.782, -120.1, 1a0105, 79.763, 101.6, 1a0110, 8.836, 137.8, 1a0115, 77.939, -3.8
4690  //2020.195.11:30:01.17#rdtca#pcal/ 1a0120, 8.740, 32.5, 1a0125, 73.421, -105.2, 1a0130, 8.134, -68.7, 1a0135, 74.094, 150.8
4691  //2020.195.11:30:01.17#rdtca#pcal/ 1a0140, 7.557, -168.7, 1a0145, 69.966, 50.6, 1a0150, 7.977, 88.8, 1a0155, 72.224, -54.9
4692  QRegularExpression rePcalVgos("(#rdtc\\w#pcal/ )([^,]+),([^,]+).*");
4693 
4694  //2020.034.17:11:35.51#onoff# source Az El De I P Center Comp Tsys SEFD Tcal(j) Tcal(r)
4695  //2020.034.17:11:35.51#onoff#VAL casa 295.4 63.4 001l 1 l 3464.40 0.9025 62.33 2139.2 58.787 0.93
4696  //2020.034.17:11:35.51#onoff#VAL casa 295.4 63.4 002l 1 l 3432.40 0.8950 63.19 2407.4 65.123 1.03
4697  //2020.034.17:11:35.51#onoff#VAL casa 295.4 63.4 003l 1 l 3368.40 0.9119 72.97 2638.0 73.812 0.98
4698  // for adults:
4699  QRegularExpression reSefd("#onoff#VAL\\s+([\\.\\d\\w+-]+)\\s+([\\.\\d+-]+)\\s+"
4700  "([\\.\\d+-]+)\\s+([\\w\\d]+)\\s+([\\w\\d]+)\\s+([\\w\\d]+)\\s+([\\.\\d+-]+)\\s+([\\.\\d+-]+)\\s+"
4701  "([\\.\\d+-]+)\\s+([\\.\\d+-]+)\\s+([\\.\\d+-]+)\\s+([\\.\\d+-]+).*");
4702 
4703 
4704  //2020.021.18:00:00.15#rdtca#dot2pps/-1.953124995e-08
4705  //2020.021.18:00:00.15#rdtca#dot2gps/-1.073085937e-04
4706  //QRegularExpression reDot2xpsVgos("(#rdtc\\w#dot2(?:g|p)ps/)([^,]+),([^,]+).*");
4707  //QRegularExpression reDot2xpsVgos("#rdtc(\\w)#dot2([gp])ps/\\s*([0-9eEdD\\.+-]+).*");
4708 //->last QRegularExpression reDot2gpsVgos("#rdtc(\\w)#dot2gps/\\s*([0-9eEdD\\.+-]+).*");
4709  QRegularExpression reDot2xpsVgos("#rdtc(\\w)#dot2(g|p)ps/\\s*([0-9eEdD\\.+-]+).*");
4710 
4711 
4712  //2019.003.18:05:50.86&vcsx8/vc01=132.99,8.000,ul
4713  //2019.003.18:05:50.86&vcsx8/vc02=172.99,8.000,u
4714  QRegularExpression reVc("(/vc)([0-9]{2})=([0-9\\.]+),([^,]+).*");
4715 
4716  //2019.003.18:05:52.80&ifdsx/patch=lo1,1l,2l,3h,4h
4717  //2019.003.18:05:52.80&ifdsx/patch=lo2,9l,10h,11h,12h,13h,14h
4718  //2018.094.17:20:22.65&ifdsx/patch=lo1,a1,a2,a3,a4
4719  //2018.094.17:20:22.65&ifdsx/patch=lo2,b1,b2,b3,b4,b5,b6
4720  //2018.094.17:20:22.65&ifdsx/patch=lo3,a5,a6,a7,a8
4721  QRegularExpression rePatch("([&].+/\"?patch=lo)([^,]+),([^,]+).*");
4722  //2018.003.17:14:29.55&ifdsx/lo=loa,8080.00,usb,rcp,1
4723  QRegularExpression reLo("([&].+/\"?lo=lo)([^,]+),([0-9\\.]+),(\\w)+,(\\w)+.*");
4724  //2021.190.19:42:45.43/lo/rxg,loa0,2152.4,lcp,bb.rxg,range,1000,10000,2015,3,22,lcp,3.00000e-02,rcp,3.00000e-02
4725  //2021.190.19:42:45.43/lo/rxg,loa1,2152.4,rcp,bb.rxg,range,1000,10000,2015,3,22,lcp,3.00000e-02,rcp,3.00000e-02
4726  //2021.315.17:00:25.44/lo/rxg,loa,0,lcp,ottn.rxg,range,0,14000,2021,3,3,lcp,2.50000e-02,rcp,2.50000e-02
4727 
4728  QRegularExpression reLoRxg("[\\d](/lo/rxg,\\s*lo)([^,]+),\\s*([a-zA-Z0-9\\.+-]+),\\s*(\\w)+,\\s*(\\w)+.*");
4729 
4730 
4731  //2016.236.17:21:21.92&setupsx/"channel sky freq lo freq video
4732  //2016.236.17:21:21.92&setupsx/" 01 8210.99 8080.00 130.99
4733  //2016.236.17:21:21.92&setupsx/" 02 8220.99 8080.00 140.99
4734  //2016.236.17:21:21.92&setupsx/" 03 8250.99 8080.00 170.99
4735  //2016.236.17:21:21.92&setupsx/" 04 8310.99 8080.00 230.99
4736  //2016.236.17:21:21.92&setupsx/" 05 8420.99 8080.00 340.99
4737  //2016.236.17:21:21.92&setupsx/" 06 8500.99 8080.00 420.99
4738  //2016.236.17:21:21.92&setupsx/" 07 8550.99 8080.00 470.99
4739  //2016.236.17:21:21.92&setupsx/" 08 8570.99 8080.00 490.99
4740  //2016.236.17:21:21.92&setupsx/" 09 2212.99 2020.00 192.99
4741  //2016.236.17:21:21.92&setupsx/" 10 2227.99 2020.00 207.99
4742  //2016.236.17:21:21.92&setupsx/" 11 2237.99 2020.00 217.99
4743  //2016.236.17:21:21.92&setupsx/" 12 2267.99 2020.00 247.99
4744  //2016.236.17:21:21.92&setupsx/" 13 2287.99 2020.00 267.99
4745  //2016.236.17:21:21.92&setupsx/" 14 2292.99 2020.00 272.99
4746  QRegularExpression reChanSkyFreq("&setup.*/\"channel\\s+sky\\s+freq.*");
4747  QRegularExpression reChanSkyFreqValues("&setup.*/\"\\s+([0-9]+)\\s+([0-9\\.]+)\\s+"
4748  "([0-9\\.]+)\\s+([0-9\\.]+).*");
4749 
4750  //2016.236.17:21:21.92&setupsx/vci01=130.99,4r
4751  //2016.236.17:21:21.92&setupsx/vci02=140.99,4r
4752  //2016.236.17:21:21.92&setupsx/vci14=272.99,4r
4753  //2016.236.17:21:21.92&setupsx/vci15=272.99,4r
4754  //2016.236.17:21:21.92&setupsx/vci16=272.99,4r
4755  QRegularExpression reVci("(/\"?vci)([0-9]{2})=([0-9\\.]+),([^,]+).*");
4756 
4757 
4758  //2019.003.19:31:02.40&bbcsx8/bbc01=612.99,a,8.000,8.000
4759  //2019.070.21:51:37.16&dbbcsx8/bbc01=612.99,a,8.00
4760  //2019.344.18:07:19.78&dbbc_bb/dbbc3=dbbc01=3480.4,a,32,1
4761  //QRegularExpression reBbc("([&]d?bbc.+(?:/|=d)bbc)([0-9]+)=([0-9\\.]+),([^,]+).*");
4762  //2021.315.17:00:17.91&dbbcbb32/bbc041=859.6,f,32.0
4763  //2021.271.20:19:39.04&freq_001/bbc01=612.99,a,8.000,8.000
4764  QRegularExpression reBbc("([&].+(?:/|=d)bbc)([0-9]+)=([0-9\\.]+),([^,]+).*");
4765 
4766  //2020.202.18:01:44.03/dbbc3/dbbc001/ 3480.400000,a,32,1,agc,79,84,15299,15290,14977,14972;
4767  QRegularExpression reDbbc3Tp("/dbbc3/dbbc(\\d{3})/\\s*([0-9\\.+-]+),([^,]+),(\\d+),(\\d+),"
4768  "(\\w+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+);.*");
4769 
4770  // /dbbc3/version/
4771  // /dbbc3/pps_delay/
4772 
4773  //2020.203.18:21:45.11#trakl#[az 10.0149 el 50.0437 azv 0.00000000 elv 0.00000000 mjd 59051 s 66104 ms 980 ]
4774  QRegularExpression reTrakl("#trakl#\\[az\\s+([\\.0-9+-]+)\\s+el\\s+([\\.0-9+-]+)\\s+azv"
4775  "\\s+([\\.0-9+-]+)\\s+elv\\s+([\\.0-9+-]+)\\s+mjd\\s+"
4776  "([\\.0-9+-]+)\\s+s\\s+([\\.0-9+-]+)\\s+ms\\s+"
4777  "([\\.0-9+-]+)\\s*\\]");
4778  // catch a procedure:
4779  QRegularExpression reProcedureDecl("[\\.0-9+-]{2}:\"%\\s+define\\s+(\\S+).*");
4780 
4781  QRegularExpression reEndOfSchd(":(sched_end|\\*end of schedule).*");
4782 
4783  //2015.182.16:40:02.73;proc=t2104ke
4784  QRegularExpression reProc(";proc=(\\S+)");
4785 
4786  // FS 10:
4787  //2021.315.16:59:18.48;equip1,dbbc3_ddc_v,flexbuff,none,none,500.10,3,a/d,101,60,20,none,40,1,in,8bit,cdp,3,return
4788  //2021.315.16:59:18.48;equip2,v107,v15_1,1,1,1,1,15000,15000,15000,15000,128,vsi1-2
4789  //2021.315.16:59:18.48;dbbc3,8,8,v125,v124,57,1
4790  QRegularExpression reEquip("\\d{2}.equip1{0,1},([^,]+),([^,]+),(.+)");
4791 //QRegularExpression reEquip("\\d{2}.equip,([^,]+),([^,]+),(.+)");
4792 
4793  bool hasProc;
4794  QString procName("");
4795  bool hasEquip;
4796  QString backEndName("");
4797  QString recorderName("");
4798 
4799  bool hasProcedures;
4800  bool isProcedureContentMode;
4801  QMap<QString, QString> procedureNameByName;
4802  QList<QString> procedureContent;
4803  QRegularExpression reProcedures("");
4804  QRegularExpression reProcedureContent("");
4805  QString currentProcedureName("");
4806  QString currentProcedureTimeStamp("");
4807 
4808  bool wantTsys(antcalOutputData_ & AOD_TSYS);
4809  bool wantTpi (antcalOutputData_ & AOD_TPI);
4810  bool wantPcal(antcalOutputData_ & AOD_PCAL);
4811  bool wantFmt (antcalOutputData_ & AOD_FMTGPS);
4812 
4813  // what to skip:
4815  {
4816  str = "#trakl#(?!\\[az)|#rdtc.#(?!";
4817  if (wantTsys)
4818  str += "tsys|";
4819  if (wantTpi)
4820  str += "tpcont|";
4821  if (wantPcal)
4822  str += "pcal|";
4823  if (wantFmt)
4824  str += "dot2(:?g|p)ps";
4825  str.chop(1);
4826  str += ")|#antcn#(?!/wx)|\\d[:/]mk6a[=/]/";
4827  }
4828  else
4829  str = "#trakl#(?!\\[az)|#rdtc.#|#antcn#(?!/wx)|\\d[:/]mk6a[=/]/";
4830 
4831 
4832  QRegularExpression re2skip(str);
4833 
4834 
4835 //2020.174.13:46:04.25;location,MGO12M ,104.02,30.68,1890.6
4836  QRegularExpression reLocation(";location,(\\S{1,8})\\s*,\\s*([-+\\.\\d]+)\\s*,"
4837  "\\s*([-+\\.\\d]+)\\s*,\\s*([-+\\.\\d]+).*", QRegularExpression::CaseInsensitiveOption);
4838  bool hasLocation=false;
4839 
4840 //2010.349.17:30:36.87:" APSG27 2010 URUMQI U Ur
4841 //2020.201.05:08:53.14:" VO0202 2020 ONSA13NE 1 Oe
4842  QRegularExpression reStnId("\\d:\"\\s+([A-Z0-9]{1,6})\\s+([0-9]{4})\\s+"
4843  "([_A-Z0-9-]{2,8})\\s+([A-Z0-9])\\s+([A-Z0-9][a-z0-9+-])");
4844 
4845 
4846 
4847  SgTraklReading trakl;
4848  bool have2checkT;
4849  bool hasVersionStr, hasCableSign, needCableSign;
4850  int val, numOfSkippedStrs, numOfReadStrs, numOfProcedureExpanded;
4851  int numOfTries;
4852  qint64 flogSize;
4853  double d;
4854 //bool isData, isTape;
4855  QList<QString> operatorComments;
4856  // /500/sessions/2003/r1083/r1083tc.log ^--??
4857 
4858  QRegularExpressionMatch match;
4859 
4860 
4861  // adjust:
4862  if ((tLast - tFirst) < 3.0/24.0)
4863  tAtTheEnd = tLast - 5.0/24.0/60.0; // for short sessions
4864 
4865 
4866  numOfSkippedStrs = numOfReadStrs = numOfProcedureExpanded = 0;
4867  flogSize = 0;
4868  have2checkT = false;
4869  hasVersionStr = hasCableSign = needCableSign = false;
4870  hasProc = hasEquip = false;
4871 
4873  needCableSign = true;
4874 
4875 
4876 //isData = isTape = false;
4877  numOfTries = 0;
4878  //
4879  if (!f.exists())
4880  {
4882  "::readLogFile(): the log file " + fileName + " does not exist");
4883  return false;
4884  };
4885  //
4886  //
4887  //
4889  "::readLogFile(): station \"" + stationName_ + "\": reading log file " + fileName);
4890  //
4891  if (tZero < tFirst)
4892  inYear_ = tFirst.calcYear();
4893  //
4894  if (fileName.right(9).toLower() == ".cdms.dat")
4896  else if (fileName.right(4).toLower() == ".dat" && fileName.toLower().contains(".pcmt."))
4898  else if (fileName.right(8).toLower() == ".met.dat")
4900  else
4902 
4903  //
4904  isDataOn = false;
4905  isOnSource = false;
4906  reachedEndOfSession = false;
4907  osRec = new SgOnSourceRecord;
4908  osRec->setScanName("");
4909  osRec->setSourceName("");
4910 
4911  hasProcedures = false;
4912  isProcedureContentMode = false;
4913 
4914  flogSize = QFileInfo(fileName).size();
4915  QTextStream s;
4916  pipe = compressors.openFlt(fileName, f, s, FLTD_Input);
4917  if (s.device())
4918  {
4919  bool have2reportNumOfStrings;
4920  have2reportNumOfStrings = (10000000 < flogSize) && logger->isEligible(SgLogger::INF, SgLogger::IO);
4921  while (!s.atEnd() && !reachedEndOfSession)
4922  {
4923  if (procedureContent.size())
4924  {
4925  str = currentProcedureTimeStamp + "&" + currentProcedureName + "/" + procedureContent.takeFirst();
4926 // str = currentProcedureTimeStamp + ":" + procedureContent.takeFirst();
4927  if (procedureContent.size() == 0)
4928  {
4929  currentProcedureName = "";
4930  currentProcedureTimeStamp = "";
4931  };
4932  }
4933  else
4934  {
4935  str = s.readLine();
4936  numOfReadStrs++;
4937  };
4938 
4939 if (have2reportNumOfStrings && numOfReadStrs%100000 == 0)
4940 std::cout << " -- read " << numOfReadStrs/1000 << "K strings file size: " << flogSize << "\n";
4941  //
4942  //
4943  if (str.right(4) == "\\par")
4944  str.chop(4);
4945  //
4946  // guess format of the file:
4947  if ( fsFmt_==FSEF_UNDEF &&
4948  (fsFmt_=guessFsFormat(str))==FSEF_UNDEF &&
4949  numOfTries++>10 && str.size())
4950  {
4952  "::readLogFile(): station " + stationName_ +
4953  ": cannot determine the time mark format after " + QString("").setNum(numOfTries) +
4954  " tries, the log file: " + fileName);
4956  "::readLogFile(): station " + stationName_ +
4957  ": input: \"" + asciifyString(str) + "\"");
4958  f.close();
4959  s.setDevice(NULL);
4960  return false;
4961  };
4962  //
4963  // lookup "version" string:
4964  if (!hasVersionStr && (match=reVersion.match(str)).hasMatch())
4965  {
4966  versionStr = match.captured(0);
4967  logReadings_.setFsVersionLabel(versionStr);
4968  hasVersionStr = true;
4969  };
4970  //
4971  //
4972  // check for lines to skip:
4973  if(str.size()==0 || re2skip.match(str).hasMatch())
4974  {
4975  numOfSkippedStrs++;
4976  }
4977  else if (fsFmt_ == FSEF_PCMT) // simple readings:
4978  {
4979  if ((match=rePcmt.match(str)).hasMatch() &&
4980  extractDataFromPcmtRecord(str, match, t, d, sSourceName, sScanName))
4981  {
4982  SgCableCalReading *cableRec=new SgCableCalReading(t, d); // input is in seconds
4983  logReadings_.cableCals() << cableRec;
4984 
4985  osRec->tStart() = t;
4986  osRec->setScanName(sScanName.toLower());
4987  osRec->setSourceName(sSourceName);
4988  osRec->cableCals() << cableRec;
4989 
4990  if (logReadings_.onSourceRecords().size())
4991  osRec->tFinis() = logReadings_.onSourceRecords().last()->tStart();
4992 
4993  osRec->setIdx(logReadings_.onSourceRecords().size());
4994  logReadings_.onSourceRecords() << osRec;
4995  osRec = new SgOnSourceRecord;
4996 
4997  if (tRightMargin <= t && (!needCableSign || hasCableSign) )
4998  {
4999  reachedEndOfSession = true;
5001  "::readLogFile(): station " + stationName_ +
5002  ": got to the end of the session: " +
5003  tRightMargin.toString(SgMJD::F_Simple) + " <= " +
5005  };
5006  //
5007  if (!hasVersionStr)
5008  {
5009  versionStr = "PCMT or CDMS file";
5010  hasVersionStr = true;
5011  };
5012  };
5013  }
5014  else if (fsFmt_ == FSEF_MET) // simple readings too:
5015  {
5016  SgMeteoData m;
5017  if ((match=reMet.match(str)).hasMatch() &&
5018  extractDataFromMetRecord(str, match, t, m))
5019  {
5020  SgMeteoReading *meteoRec=new SgMeteoReading(t, m);
5021  logReadings_.meteoPars() << meteoRec;
5022  if (tRightMargin <= t && (!needCableSign || hasCableSign))
5023  {
5024  reachedEndOfSession = true;
5026  "::readLogFile(): station " + stationName_ +
5027  ": got to the end of the session: " +
5028  tRightMargin.toString(SgMJD::F_Simple) + " <= " +
5030  };
5031  //
5032  if (!hasVersionStr)
5033  {
5034  versionStr = "External file with meteo data";
5035  hasVersionStr = true;
5036  };
5037  };
5038  }
5039  else // FS log file:
5040  {
5041  //
5042  // first, deal with macroses:
5043  if ((match=reProcedureDecl.match(str)).hasMatch())
5044  {
5045  hasProcedures = true;
5046  procedureNameByName.insert(match.captured(1), match.captured(1));
5047  str = "[\\.0-9]{2}:(";
5048  for (QMap<QString, QString>::iterator it=procedureNameByName.begin();
5049  it!=procedureNameByName.end(); ++it)
5050  str += it.key() + "|";
5051  str.chop(1);
5052  reProcedures.setPattern(str + ")");
5054  "::readLogFile(): station " + stationName_ +
5055  ": found declaration of procedure \"" + match.captured(1) + "\"");
5056  continue;
5057  }
5058  else if (hasProcedures && (match=reProcedures.match(str)).hasMatch())
5059  {
5060  // empty procedure + another one:
5061  if (isProcedureContentMode && currentProcedureName.size() &&
5062  procedureByName_.contains(currentProcedureName) &&
5063  procedureNameByName.contains(currentProcedureName) )
5064  {
5065  procedureByName_.remove(currentProcedureName);
5066  procedureNameByName.remove(currentProcedureName);
5067  // redefine the regExp:
5068  strTmp = "[\\.0-9]{2}:(";
5069  for (QMap<QString, QString>::iterator it=procedureNameByName.begin();
5070  it!=procedureNameByName.end(); ++it)
5071  strTmp += it.key() + "|";
5072  strTmp.chop(1);
5073  reProcedures.setPattern(strTmp + ")");
5075  "::readLogFile(): station " + stationName_ +
5076  ": procedure \"" + currentProcedureName +
5077  "\" is empty, removed from the substitution pool");
5078  };
5079  currentProcedureName = match.captured(1);
5080  currentProcedureTimeStamp = str.left(fsContentStartsAt_[fsFmt_]);
5081  if (procedureByName_.contains(currentProcedureName)) // procedure use mode:
5082  {
5083  Procedure *prc=procedureByName_.value(currentProcedureName);
5084  for (int i=0; i<prc->content().size(); i++)
5085  procedureContent.append(prc->content().at(i));
5086  prc->incNumOfExpanded();
5087  numOfProcedureExpanded++;
5088  continue;
5089  }
5090  else // procedure content mode:
5091  {
5092  procedureByName_.insert(currentProcedureName, new Procedure(currentProcedureName));
5093  isProcedureContentMode = true;
5094  reProcedureContent.setPattern("[\\.0-9]{2}&" + currentProcedureName + "/(.*)");
5096  "::readLogFile(): station " + stationName_ +
5097  ": found content of procedure \"" + currentProcedureName + "\"");
5098  };
5099  }
5100  else if (isProcedureContentMode)
5101  {
5102  Procedure *prc=NULL;
5103  if (procedureByName_.contains(currentProcedureName))
5104  {
5105  prc = procedureByName_.value(currentProcedureName);
5106  if ((match=reProcedureContent.match(str)).hasMatch())
5107  prc->content().append(match.captured(1));
5108  else
5109  {
5111  "::readLogFile(): station " + stationName_ +
5112  ": collected content of procedure \"" + currentProcedureName + "\", " +
5113  QString("").setNum(prc->content().size()) + " record(s) total");
5114  if (!prc->content().size())
5115  {
5116  procedureByName_.remove(currentProcedureName);
5117  procedureNameByName.remove(currentProcedureName);
5118  // redefine the regExp:
5119  strTmp = "[\\.0-9]{2}:(";
5120  for (QMap<QString, QString>::iterator it=procedureNameByName.begin();
5121  it!=procedureNameByName.end(); ++it)
5122  strTmp += it.key() + "|";
5123  strTmp.chop(1);
5124  reProcedures.setPattern(strTmp + ")");
5126  "::readLogFile(): station " + stationName_ +
5127  ": procedure \"" + currentProcedureName +
5128  "\" is empty, removed from the substitution pool");
5129  };
5130  isProcedureContentMode = false;
5131  currentProcedureName = "";
5132  currentProcedureTimeStamp = "";
5133  };
5134  }
5135  else
5137  "::readLogFile(): station " + stationName_ +
5138  ": cannot find procedure \"" + currentProcedureName + "\" in the map; input: \"" +
5139  asciifyString(str) + "\"");
5140  continue;
5141  }
5142  //
5143  // check proc:
5144  else if ((match=reProc.match(str)).hasMatch() && extractEpoch(str, t))
5145  {
5146  hasProc = true;
5147  if (t < tFirst) // session is not started yet:
5148  {
5149  procName = match.captured(1);
5150  }
5151  else if (procName != match.captured(1)) // another session?:
5152  {
5153  if (procName.size())
5155  "::readLogFile(): station " + stationName_ +
5156  ": proc has changed: \"" + procName + "\" => \"" + match.captured(1) +
5157  "\"; input: \"" + asciifyString(str) + "\"");
5158  procName = match.captured(1);
5159  if (tRightMargin <= t && (!needCableSign || hasCableSign))
5160  {
5161  reachedEndOfSession = true;
5163  "::readLogFile(): station " + stationName_ +
5164  ": got to the end of the session: " +
5165  tRightMargin.toString(SgMJD::F_Simple) + " <= " +
5167  };
5168  };
5169  };
5170  if ((match=reEquip.match(str)).hasMatch() && extractEpoch(str, t))
5171  {
5172  if (backEndName.size() && backEndName != match.captured(1))
5173  {
5175  "::readLogFile(): station " + stationName_ +
5176  ": equip (backEnd) has changed: \"" + backEndName + "\" => \"" + match.captured(1) +
5177  "\"; input: \"" + asciifyString(str) + "\"");
5178  };
5179  backEndName = match.captured(1);
5180  //
5181  if (recorderName.size() && recorderName != match.captured(2))
5182  {
5184  "::readLogFile(): station " + stationName_ +
5185  ": equip (recorder) has changed: \"" + recorderName + "\" => \"" + match.captured(2) +
5186  "\"; input: \"" + asciifyString(str) + "\"");
5187  };
5188  recorderName = match.captured(2);
5189  hasEquip = true;
5190  //
5191  if (backEndName == "dbbc3")
5193  if (backEndName.contains("dbbc3_")) // FS 10 whims
5195  else if (backEndName == "dbbc")
5197  else if (backEndName == "rdbe")
5198  {
5201  }
5202  else if (backEndName == "none")
5204  else
5206  logReadings_.setBackEndInfo(backEndName);
5207  logReadings_.setRecorderInfo(recorderName);
5208 
5210  "::readLogFile(): station " + stationName_ +
5211  ": found: backend=\"" + logReadings_.getBackEndInfo() +
5212  "\", recorder=\"" + logReadings_.getRecorderInfo() + "\"");
5213  };
5214  //
5215  //
5216  if (!hasStnName)
5217  {
5218  if ((match=reStnId.match(str)).hasMatch())
5219  {
5220  stationName_ = match.captured(3).leftJustified(8, ' ');
5221  hasStnName = true;
5222  hasLocation = true; // do not need to check location
5224  "::readLogFile(): station " + stationName_ +
5225  ": found a name of the station (from \"stnId\"): \"" + stationName_ + "\"");
5226  };
5227  };
5228  if (!hasLocation)
5229  {
5230  if ((match=reLocation.match(str)).hasMatch())
5231  {
5232  if (!hasStnName)
5233  {
5234  stationName_ = match.captured(1).leftJustified(8, ' ');
5235  hasLocation = true;
5237  "::readLogFile(): station " + stationName_ +
5238  ": found a name of the station (from \"location\"): \"" + stationName_ + "\"");
5239  }
5240  else if (stationName_ != match.captured(1))
5241  {
5243  "::readLogFile(): station " + stationName_ +
5244  ": the station name from \"location\" (\"" + match.captured(1) +
5245  "\") is different");
5246  };
5247  };
5248  };
5249  //
5250  if (have2checkT && extractEpoch(str, t) && tRightMargin <= t && (!needCableSign || hasCableSign))
5251  {
5252  reachedEndOfSession = true;
5254  "::readLogFile(): station " + stationName_ +
5255  ": got to the end of the session: " +
5256  tRightMargin.toString(SgMJD::F_Simple) + " <= " +
5258  };
5259  //
5260  if (reEndOfSchd.match(str).hasMatch() && extractEpoch(str, t) && tFirst < t &&
5261  (!needCableSign || hasCableSign))
5262  {
5263  reachedEndOfSession = true;
5265  "::readLogFile(): station " + stationName_ +
5266  ": got to the end of the session: end of schedule at " +
5268  };
5269  //
5270  if (reachedEndOfSession)
5271  continue;
5272  //
5273  //
5274  //
5275  // search for on source:
5276  if (reOnSource.match(str).hasMatch() ||
5277  reTapeOn.match(str).hasMatch() )
5278  {
5279  if (extractEpoch(str, t))
5280  {
5281  if (!isOnSource)
5282  {
5283  osRec->tStart() = t;
5284  isOnSource = true;
5285  if (tRightMargin <= t && (!needCableSign || hasCableSign))
5286  {
5287  reachedEndOfSession = true;
5289  "::readLogFile(): station " + stationName_ +
5290  ": got to the end of a session: " +
5291  tRightMargin.toString(SgMJD::F_Simple) + " <= " +
5292  t.toString(SgMJD::F_Simple) + " (tRightMargin <= osRec->tStart())");
5293  };
5294  if (tAtTheEnd <= t)
5295  have2checkT = true;
5296  }
5297  else if (420.0/DAY2SEC < (t-osRec->tStart()))
5299  "::readLogFile(): station " + stationName_ +
5300  ": got unexpected `on source' record; string: \"" + asciifyString(str) + "\"");
5301 // "\", prev t: " + osRec->tStart().toString());
5302  };
5303  }
5304  else if ((match=reScanName.match(str)).hasMatch())
5305  {
5306  if (3<osRec->getScanName().size() && osRec->getScanName()!=match.captured(1))
5307  {
5309  "::readLogFile(): station " + stationName_ + ": the scan name \"" +
5310  osRec->getScanName() + "\" will be replaced with \"" + match.captured(1) +
5311  "\", looks like discontinuity in the log file");
5313  "::readLogFile(): station " + stationName_ + ": string: \"" + asciifyString(str) + "\"");
5314  // check if we already got accumulated data:
5315  if (osRec->cableCals().size())
5317  "::readLogFile(): station " + stationName_ +
5318  ": the scan is not empty: size of cable cal list is " +
5319  QString("").setNum(osRec->cableCals().size()));
5320  if (osRec->meteoPars().size())
5322  "::readLogFile(): station " + stationName_ +
5323  ": the scan is not empty: size of meteo parameters list is " +
5324  QString("").setNum(osRec->meteoPars().size()));
5325  };
5326  osRec->setScanName(match.captured(1).toLower());
5327  //
5328  // check experiment name:
5329  if (match.captured(2).size())
5330  {
5331  if (logReadings_.getExperimentName() != match.captured(2))
5332  {
5333  if (logReadings_.getExperimentName().size())
5335  "::readLogFile(): station " + stationName_ +
5336  ": the experiment name has been changed: \"" +
5337  logReadings_.getExperimentName() + "\" => \"" +
5338  match.captured(2) + "\"");
5339  else
5341  "::readLogFile(): station " + stationName_ +
5342  ": found experiment name: \"" + match.captured(2) + "\"");
5343  logReadings_.setExperimentName(match.captured(2));
5344  };
5345  };
5346  //
5347  }
5348  else if ((match=reSourceName.match(str)).hasMatch()
5349 // &&
5350 // !(str.contains("idle", Qt::CaseInsensitive) ||
5351 // str.contains("azel", Qt::CaseInsensitive))
5352  )
5353  {
5354  if (3<osRec->getSourceName().size() &&
5355  osRec->getSourceName()!= QString("idle") &&
5356  osRec->getSourceName()!= QString("azel") &&
5357  osRec->getSourceName()!=match.captured(1).toUpper())
5359  "::readLogFile(): station " + stationName_ +
5360  ": the source name \"" + osRec->getSourceName() +
5361  "\" will be replaced with \"" + match.captured(1).toUpper() +
5362  "\", looks like discontinuity in the log file");
5363  osRec->setSourceName(match.captured(1).toUpper());
5364  }
5365  // search for data on:
5366  else if (reDataOn.match(str).hasMatch() && extractEpoch(str, osRec->tDataOn()))
5367  {
5368  isDataOn = true;
5369  }
5370  // data_valid=off:
5371  else if (reDataOff.match(str).hasMatch() ||
5372  reTapeOff.match(str).hasMatch() )
5373  {
5374  if (extractEpoch(str, t))
5375  {
5376  if (isOnSource)
5377  {
5378  osRec->tFinis() = t;
5379  if (tRightMargin <= t && (!needCableSign || hasCableSign))
5380  {
5381  reachedEndOfSession = true;
5383  "::readLogFile(): station " + stationName_ +
5384  ": got to the end of a session: " +
5385  tRightMargin.toString(SgMJD::F_Simple) + " <= " +
5386  t.toString(SgMJD::F_Simple) + " (tRightMargin <= osRec->tFinis())");
5387  };
5388  //
5389  if (tFirst < t)
5390  {
5391  osRec->setIdx(logReadings_.onSourceRecords().size());
5392  logReadings_.onSourceRecords() << osRec;
5393  };
5394  // check:
5395  if (osRec->getScanName().size() < 3)
5396  {
5398  "::readLogFile(): station " + stationName_ + ": the scan name \"" +
5399  osRec->getScanName() +
5400  "\" too short and cannot be used; the `data_valid=off' string: \"" +
5401  asciifyString(str) + "\"");
5402  };
5403  osRec = new SgOnSourceRecord;
5404  osRec->setScanName("");
5405  osRec->setSourceName("");
5406  isOnSource = false;
5407  isDataOn = false;
5408  }
5409  else if (logReadings_.onSourceRecords().size() &&
5410  420.0/DAY2SEC < (t - logReadings_.onSourceRecords().at(logReadings_.onSourceRecords().size()-1)->getTfinis()))
5412  "::readLogFile(): station " + stationName_ +
5413  ": got unexpected data_valid=off record; string: \"" + asciifyString(str) + "\"");
5414  };
5415  };
5416  //
5417  //
5418  //
5419  //
5420  // end of data on/off switches
5421  //
5422  // check for operator comments:
5423  QRegularExpression reNotUserComments(";\"(?:/| Command from |FiLa10G:|Flexbuff:|"
5424  "start transferring scan|Error opening connection to FILA10G|"
5425  "Error opening connection to flexbuff|.+\\s+1pps diff:).*",
5426  QRegularExpression::CaseInsensitiveOption);
5427  QRegularExpression reFilter1(";\"\\s*Comment from\\s+'\\w+\\(?\\d?\\)?':\\s+\""
5428  "\\s+CHECKLIST\\(?\\w*\\)?:\\s+(\\b.+)", QRegularExpression::CaseInsensitiveOption);
5429  QRegularExpression reFilter2(";\"\\s*CHECKLIST:\\s+(.+)",
5430  QRegularExpression::CaseInsensitiveOption);
5431  QRegularExpression reFilter3(";\"\\s*Comment from\\s+'\\w+\\(?\\w*\\)?':\\s+\"\\s+(\\b.+)",
5432  QRegularExpression::CaseInsensitiveOption);
5433  QRegularExpression reFilterLast(";\"\\s*(\\b.+)",
5434  QRegularExpression::CaseInsensitiveOption);
5435  if (reOpComments.match(str).hasMatch())
5436  {
5437  if (extractEpoch(str, t))
5438  {
5439  extractContent(str, strTmp);
5440  if (!reNotUserComments.match(strTmp).hasMatch())
5441  {
5442  if ((match=reFilter1.match(strTmp)).hasMatch())
5443  strTmp = match.captured(1);
5444  else if ((match=reFilter2.match(strTmp)).hasMatch())
5445  strTmp = match.captured(1);
5446  else if ((match=reFilter3.match(strTmp)).hasMatch())
5447  strTmp = match.captured(1);
5448  else if ((match=reFilterLast.match(strTmp)).hasMatch())
5449  strTmp = match.captured(1);
5450  //
5451  if (strTmp.size() < 100)
5452  operatorComments << t.toString(SgMJD::F_Simple) + ": " + strTmp;
5453  else // split too long strings:
5454  {
5455  QStringList sLst=strTmp.split(QRegExp("\\s"));
5456  QString sAux("");
5457  for (int i=0; i<sLst.size(); i++)
5458  {
5459  sAux += " " + sLst.at(i);
5460  if (sAux.size() > 81)
5461  {
5462  operatorComments << t.toString(SgMJD::F_Simple) + ":" + sAux;
5463  sAux = "";
5464  };
5465  };
5466  if (sAux.size())
5467  operatorComments << t.toString(SgMJD::F_Simple) + ":" + sAux;
5468  };
5469  };
5470  };
5471  };
5472  //
5473  //
5474  if ((match=reTrakl.match(str)).hasMatch()) // VGOS has these records every sec
5475  {
5476  if (extractTraklReading(str, match, t, trakl, tFirst))
5477  {
5478  SgTraklReading *pTrakl=new SgTraklReading(trakl);
5479  logReadings_.trakls() << pTrakl;
5480  //
5481  // add to tsys recs:
5482  int idx=logReadings_.tSyses().size() - 1;
5483  SgTsysReading *pTs=NULL;
5484  while (0 < idx &&
5485  (pTs=logReadings_.tSyses().at(idx)) &&
5486  (t - pTs->getT()) < 60.0/DAY2SEC)
5487  {
5488  if (pTs->trakls().size() < 10)
5489  pTs->trakls() << pTrakl;
5490  idx--;
5491  };
5492  };
5493  }
5494  //
5495  //
5496  // vgos tsys:
5497  else if (reTsysVgos.match(str).hasMatch())
5498  {
5499  QMap<QString, float> tsys;
5500  if (extractTsysVgosReading(str, reTsysVgos, t, tsys, tAtTheBegin) && tsys.size())
5501  {
5502  SgTsysReading *tsr=NULL;
5503  if (0.3/DAY2SEC < fabs(lastReadTsys - t))
5504  {
5505  tsr = new SgTsysReading;
5506  tsr->setT(t);
5507  tsr->setOsRec(isOnSource?osRec:NULL);
5508  tsr->setIsOnSource(isOnSource);
5509  tsr->setIsDataOn(isDataOn);
5510  logReadings_.tSyses() << tsr;
5511  osRec->tSyses() << tsr;
5512  //
5513  // add trakls:
5514  int idx=logReadings_.trakls().size() - 1;
5515  SgTraklReading *pTrakl=NULL;
5516  while (0 < idx &&
5517  (pTrakl=logReadings_.trakls().at(idx)) &&
5518  (t - pTrakl->getT()) < 100.0/DAY2SEC)
5519  {
5520  if (tsr->trakls().size() < 5)
5521  tsr->trakls() << pTrakl;
5522  idx--;
5523  };
5524  }
5525  else
5526  tsr = logReadings_.tSyses().last();
5527  tsr->addTsyses(tsys);
5528  lastReadTsys = t;
5529  };
5530  tsys.clear();
5531  }
5532  //
5533  // vgos tpcont:
5534  else if (reTpcontVgos.match(str).hasMatch())
5535  {
5536  QMap<QString, QVector<int> >
5537  tpcont;
5538  if (extractTpcontVgosReading(str, reTpcontVgos, t, tpcont, tAtTheBegin) && tpcont.size())
5539  {
5540  SgTsysReading *tsr=NULL;
5541  if (0.2/DAY2SEC < fabs(lastReadTsys - t))
5542  {
5543  tsr = new SgTsysReading;
5544  tsr->setT(t);
5545  tsr->setOsRec(isOnSource?osRec:NULL);
5546  tsr->setIsOnSource(isOnSource);
5547  tsr->setIsDataOn(isDataOn);
5548  logReadings_.tSyses() << tsr;
5549  osRec->tSyses() << tsr;
5550  //
5551  // add trakls:
5552  int idx=logReadings_.trakls().size() - 1;
5553  SgTraklReading *pTrakl=NULL;
5554  while (0 < idx &&
5555  (pTrakl=logReadings_.trakls().at(idx)) &&
5556  (t - pTrakl->getT()) < 100.0/DAY2SEC)
5557  {
5558  if (tsr->trakls().size() < 5)
5559  tsr->trakls() << pTrakl;
5560  idx--;
5561  };
5562  }
5563  else
5564  tsr = logReadings_.tSyses().last();
5565  tsr->addTpconts(tpcont);
5566  lastReadTsys = t;
5567  };
5568  tpcont.clear();
5569  }
5570  //
5571  //
5572  // vgos pcal:
5573  else if ((match=rePcalOffset.match(str)).hasMatch())
5574  {
5575  extractPcalOffsetReading(str, match, t, tAtTheEnd, logReadings_.channelSetup(), tFirst);
5576  }
5577  else if ((match=rePcalVgos.match(str)).hasMatch())
5578  {
5579  QMap<QString, float*> pcals;
5580  if (extractPcalVgosReading(str, match, t, pcals, logReadings_.channelSetup(), tAtTheBegin) &&
5581  pcals.size())
5582  {
5583  SgPcalReading *pcr=NULL;
5584  if (0.2/DAY2SEC < fabs(lastReadPcal - t))
5585  {
5586  pcr = new SgPcalReading;
5587  pcr->setT(t);
5588  pcr->setOsRec(isOnSource?osRec:NULL);
5589  logReadings_.pcals() << pcr;
5590  }
5591  else
5592  pcr = logReadings_.pcals().last();
5593 
5594  if (!pcr->addPcals(pcals))
5596  "::readLogFile(): station " + stationName_ +
5597  ": got duplicate pcals; input: \"" + asciifyString(str) + "\"");
5598  lastReadPcal = t;
5599  };
5600  for (QMap<QString, float*>::iterator it=pcals.begin(); it!=pcals.end(); ++it)
5601  delete[] it.value();
5602  pcals.clear();
5603  }
5604  //
5605  // vgos dot2pps/gps:
5606  else if ((match=reDot2xpsVgos.match(str)).hasMatch())
5607  {
5608  float dot2xps=1.0e20;
5609  bool isGps;
5610  QString sKey("");
5611  if (extractDot2xpsVgosReading(str, match, t, sKey, dot2xps, tAtTheBegin, isGps) &&
5612  dot2xps < 1.0e12)
5613  {
5614  if (!logReadings_.channelSetup().xpsIdByKey().contains(sKey))
5615  logReadings_.channelSetup().xpsIdByKey().insert(sKey, sKey);
5616  SgDot2xpsReading *d2r=NULL;
5617  if (0.2/DAY2SEC < fabs(lastReadDot2xps - t))
5618  {
5619  d2r = new SgDot2xpsReading;
5620  d2r->setT(t);
5621  d2r->setOsRec(isOnSource?osRec:NULL);
5622  logReadings_.dot2xpses() << d2r;
5623  }
5624  else
5625  d2r = logReadings_.dot2xpses().last();
5626  if (!(isGps?d2r->addDot2gpsByBrd(sKey, dot2xps):d2r->addDot2ppsByBrd(sKey, dot2xps)))
5628  "::readLogFile(): station " + stationName_ +
5629  ": got duplicate " + (isGps?"dot2gps":"dot2pps") +
5630  "; input: \"" + asciifyString(str) + "\"");
5631  lastReadDot2xps = t;
5632  };
5633  }
5634  // dbbc3 tp reading:
5635  else if ((match=reDbbc3Tp.match(str)).hasMatch())
5636  {
5637  extractEpoch(str, t);
5638 
5639  QString sensorId(match.captured( 1));
5640  QString boardId(match.captured( 3));
5641  QString agc(match.captured( 6));
5642  double bw=0.0;
5643  double gainU=0.0;
5644  double gainL=0.0;
5645  double tpOffU=0.0;
5646  double tpOffL=0.0;
5647  double tpOnU=0.0;
5648  double tpOnL=0.0;
5649  double sefdU=0.0;
5650  double sefdL=0.0;
5651  bw = match.captured( 4).toDouble();
5652  gainU = match.captured( 7).toDouble();
5653  gainL = match.captured( 8).toDouble();
5654  tpOffU = match.captured( 9).toDouble();
5655  tpOffL = match.captured(10).toDouble();
5656  tpOnU = match.captured(11).toDouble();
5657  tpOnL = match.captured(12).toDouble();
5658  sensorId= sensorId.simplified().rightJustified(5, ' ');
5659  QString chanKey=setupTpSensor(sensorId + 'l', "readLogFile()", str);
5660  if (chanKey.size())
5661  {
5662  chanKey = setupTpSensor(sensorId + 'u', "readLogFile()", str);
5663  if (chanKey.size())
5664  {
5665  SgDbbc3TpReading *tp=NULL;
5666  if (1.0/DAY2SEC < fabs(lastReadTsys - t))
5667  {
5668  tp = new SgDbbc3TpReading;
5669  tp->setT(t);
5670  tp->setOsRec(isOnSource?osRec:NULL);
5671  tp->setIsOnSource(isOnSource);
5672  tp->setIsDataOn(isDataOn);
5673  logReadings_.dbbc3Tps() << tp;
5674  osRec->dbbc3Tps() << tp;
5675  }
5676  else
5677  tp = logReadings_.dbbc3Tps().last();
5678  tp->addRecord(sensorId, boardId, bw, agc, gainU, gainL, tpOffU, tpOffL, tpOnU, tpOnL,
5679  sefdU, sefdL);
5680  lastReadTsys = t;
5681  }
5682  else
5684  "::readLogFile(): station " + stationName_ + ": parsing chanKey has failed for \"" +
5685  sensorId + 'u' + "\"; input: \"" + asciifyString(str) + "\"");
5686  }
5687  else
5689  "::readLogFile(): station " + stationName_ + ": parsing chanKey has failed for \"" +
5690  sensorId + 'l' + "\"; input: \"" + asciifyString(str) + "\"");
5691  }
5692  //
5693  // SEFD:
5694  else if ((match=reSefd.match(str)).hasMatch())
5695  {
5696  QString sensId("");
5697  QString srcNam("");
5698  double az, de;
5699  QVector<double> vec;
5700  if (extractSefdReading(str, match, t, sensId, srcNam, az, de, vec, tAtTheBegin))
5701  {
5702  SgSefdReading *sefd=NULL;
5703  if (0.3/DAY2SEC < fabs(lastReadSefd - t))
5704  logReadings_.sefds() << (sefd=new SgSefdReading);
5705  else
5706  sefd = logReadings_.sefds().last();
5707  if (!sefd->addValByChanKey(t, srcNam, az, de, sensId, vec))
5709  "::readLogFile(): station " + stationName_ +
5710  ": got duplicate SEFD; input: \"" + asciifyString(str) + "\"");
5711  lastReadSefd = t;
5712  };
5713  }
5714  //
5715  //
5716  // SX tsys reading:
5717  else if (wantTsys && reTsys.match(str).hasMatch())
5718  {
5719  QMap<QString, float> tsys;
5720  if (extractTsysReading(str, reTsys, t, tsys, tAtTheBegin) && tsys.size())
5721  {
5722  if (fabs(lastReadTsys - t) < 0.1/DAY2SEC)
5723  logReadings_.tSyses().last()->addTsyses(tsys);
5724  else
5725  {
5726  SgTsysReading *tsr=new SgTsysReading;
5727  tsr->setT(t);
5728  tsr->addTsyses(tsys);
5729  tsr->setOsRec(isOnSource?osRec:NULL);
5730  logReadings_.tSyses() << tsr;
5731  osRec->tSyses() << tsr;
5732  //
5733  // add trakls:
5734  int idx=logReadings_.trakls().size() - 1;
5735  SgTraklReading *pTrakl=NULL;
5736  while (0 < idx && (pTrakl=logReadings_.trakls().at(idx)) &&
5737  (t - pTrakl->getT()) < 60.0/DAY2SEC)
5738  {
5739  if (tsr->trakls().size() < 5)
5740  tsr->trakls() << pTrakl;
5741  idx--;
5742  };
5743  };
5744  lastReadTsys = t;
5745  };
5746  tsys.clear();
5747  }
5748  //
5749  // meteo parameters:
5750  else if (reMeteo.match(str).hasMatch())
5751  {
5752  SgMeteoData m;
5753  if (extractMeteoReading(str, reMeteo, t, m, oom) && tFirst < t)
5754  {
5755  SgMeteoReading *meteoRec=new SgMeteoReading(t, m);
5756  logReadings_.meteoPars() << meteoRec;
5757  if (isOnSource)
5758  {
5759  osRec->meteoPars() << meteoRec;
5760  meteoRec->setOsRec(osRec);
5761  };
5762  };
5763  }
5764  //
5765  // bbc reading:
5766  else if ((match=reBbc.match(str)).hasMatch())
5767  {
5768  extractBbcReading(str, match, t, tAtTheEnd, logReadings_.channelSetup(), tFirst);
5769  }
5770  // vc reading:
5771  else if ((match=reVc.match(str)).hasMatch())
5772  {
5773  extractVcReading(str, match, t, tAtTheEnd, logReadings_.channelSetup(), tFirst);
5774  }
5775  // patch reading:
5776  else if ((match=rePatch.match(str)).hasMatch())
5777  {
5778  extractPatchReading(str, match, t, tAtTheEnd, logReadings_.channelSetup(), tFirst);
5779  }
5780  else if ((match=reLo.match(str)).hasMatch())
5781  {
5782  extractLoReading(str, match, t, tAtTheEnd, logReadings_.channelSetup(), tFirst);
5783  }
5784  else if ((match=reLoRxg.match(str)).hasMatch())
5785  {
5786  extractLoRxgReading(str, match, t, tAtTheEnd, logReadings_.channelSetup(), tFirst);
5787  }
5788  else if ((match=reChanSkyFreqValues.match(str)).hasMatch())
5789  {
5790  extractChanSkyFrqReading(str, match, t, tAtTheEnd, logReadings_.channelSetup(), tFirst);
5791  }
5792  else if ((match=reVci.match(str)).hasMatch())
5793  {
5794  extractVciReading(str, match, t, tAtTheEnd, logReadings_.channelSetup(), tFirst);
5795  }
5796  //
5797  //
5798  // cable calibration:
5799  else if ((match=reCableCal.match(str)).hasMatch())
5800  {
5801  hasCableRecord_ = true;
5802  if (extractCableCalibration(str, match, t, d) && tFirst < t)
5803  {
5804  double scale = 4.0e5;
5805  SgCableCalReading *cableRec=new SgCableCalReading(t, d/scale);
5806  logReadings_.cableCals() << cableRec;
5807  if (isOnSource)
5808  {
5809  osRec->cableCals() << cableRec;
5810  cableRec->setOsRec(osRec);
5811  };
5812 // if (tRightMargin <= t)
5813 // reachedEndOfSession = true;
5814  };
5815  }
5816  else if ((match=reCdms.match(str)).hasMatch())
5817  {
5818  hasCdmsRecord_ = true;
5819  if (extractCableCalibration(str, match, t, d) && tFirst < t)
5820  {
5821  double scale = 2e12;
5822  SgCableCalReading *cableRec=new SgCableCalReading(t, d/scale);
5823  logReadings_.cableCals() << cableRec;
5824  if (isOnSource)
5825  {
5826  osRec->cableCals() << cableRec;
5827  cableRec->setOsRec(osRec);
5828  };
5829 // if (tRightMargin <= t)
5830 // reachedEndOfSession = true;
5831  };
5832  }
5833  // cablelong measurements:
5834  else if ((match=reCableLong.match(str)).hasMatch())
5835  {
5836  double scale = 4.0e5;
5837  if (extractCableCalibration(str, match, t, d))
5838  logReadings_.cableLongs() << new SgCableCalReading(t, d/scale);
5839  }
5840  // cable calibration sign:
5841  else if (!hasCableSign)
5842  {
5843  // 1) 2014.252.16:54:02.27/cablediff/647.7e-6,-
5844  if ((match=reCableDiff.match(str)).hasMatch())
5845  {
5846  if (extractCableCalibrationSignByDiff(match, val))
5847  {
5849  hasCableSign = true;
5851  "::readLogFile(): station " + stationName_ +
5852  ": the cable calibration sign was set to \"" +
5853  QString(logReadings_.getCableSign()==1?"+":"-") + "\". Source: cable_diff");
5854  };
5855  }
5856  // 2) 2012.150.17:40:46.48;"cabvle sign is positive, OK
5857  else if (reCableSign.match(str).hasMatch())
5858  {
5859  if (str.contains("positive", Qt::CaseInsensitive))
5860  {
5862  hasCableSign = true;
5864  "::readLogFile(): station " + stationName_ +
5865  ": the cable calibration sign was set to \"+\". Source: cable_sign_is");
5866  }
5867  else if (str.contains("negative", Qt::CaseInsensitive))
5868  {
5870  hasCableSign = true;
5872  "::readLogFile(): station " + stationName_ +
5873  ": the cable calibration sign was set to \"-\". Source: cable_sign_is");
5874  }
5875  else
5877  "::readLogFile(): station " + stationName_ + ": cannot determine proper cable sign "
5878  "from cable_sign_is pattern; input: \"" + asciifyString(str) + "\"");
5879  }
5880  else if (reCableDiffIs.match(str).hasMatch())
5881  {
5882  if (str.contains("positive", Qt::CaseInsensitive) ||
5883  str.contains("larger", Qt::CaseInsensitive) )
5884  {
5886  hasCableSign = true;
5888  "::readLogFile(): station " + stationName_ +
5889  ": the cable calibration sign was set to \"+\". Source: cable_diff_is");
5890  }
5891  else if ( str.contains("negative", Qt::CaseInsensitive) ||
5892  str.contains("smaller", Qt::CaseInsensitive) )
5893  {
5895  hasCableSign = true;
5897  "::readLogFile(): station " + stationName_ +
5898  ": the cable calibration sign was set to \"-\". Source: cable_diff_is");
5899  }
5900  else
5902  "::readLogFile(): station " + stationName_ +
5903  ": cannot determine proper cable sign from cable_diff_is pattern; input: \"" +
5904  asciifyString(str) + "\"");
5905  };
5906  };
5907  };
5908  };
5909  compressors.closeFlt(pipe, f, s);
5910 
5911  // pick up the last data on if the log has been terminated:
5912  if (osRec && osRec->getScanName().size() /*&& osRec->getSourceName().size()*/ &&
5913  (osRec->cableCals().size() || osRec->meteoPars().size() ||
5914  osRec->tSyses().size() || osRec->dbbc3Tps().size() ))
5915  {
5916  osRec->tFinis() = t;
5917  osRec->setIdx(logReadings_.onSourceRecords().size());
5918  logReadings_.onSourceRecords() << osRec;
5920  "::readLogFile(): station " + stationName_ + ": picked up not finished onSource record");
5921  };
5922  };
5923  //
5924  if (!hasProc)
5926  "::readLogFile(): station " + stationName_ + ": no proc record has been found in the log file");
5927  //
5928  if (operatorComments.size())
5929  {
5931  "::readLogFile(): station " + stationName_ + ": collected operator's comments: ");
5932  for (int i=0; i<operatorComments.size(); i++)
5934  "::readLogFile(): station " + stationName_ + ": " + operatorComments.at(i));
5935  };
5936  //
5937  // ok, end of parsing.
5938  //
5939  if (flogSize < 1024)
5940  {
5941  str.setNum(flogSize);
5942  str += "b";
5943  }
5944  else if (flogSize < 1048576)
5945  {
5946  str.setNum(flogSize/1024);
5947  str += "K";
5948  }
5949  else if (flogSize < 1073741824)
5950  {
5951  str.setNum(flogSize/1048576);
5952  str += "M";
5953  }
5954  else
5955  {
5956  str.setNum(flogSize/1073741824);
5957  str += "G";
5958  };
5960  "::readLogFile(): station " + stationName_ + ": " + QString("").setNum(numOfReadStrs) +
5961  " strings of the log file (" + str + ") were read" +
5962  (numOfSkippedStrs>1?" (" + QString("").setNum(numOfSkippedStrs) + " strings were skipped)":""));
5964  "::readLogFile(): station " + stationName_ + ": the log file version: " + versionStr);
5965  if (numOfProcedureExpanded)
5966  {
5968  "::readLogFile(): station " + stationName_ + ": " + QString("").setNum(numOfProcedureExpanded) +
5969  " time(s) procedure(s) were expanded:");
5970  for (QMap<QString, Procedure*>::iterator it=procedureByName_.begin(); it!=procedureByName_.end();
5971  ++it)
5973  "::readLogFile(): station " + stationName_ + ": " + it.value()->getName() + ": " +
5974  QString("").setNum(it.value()->getNumOfExpanded()));
5975  };
5977  "::readLogFile(): station " + stationName_ + ": collected " +
5978  QString("").setNum(logReadings_.onSourceRecords().size()) + " on_source, " +
5979  QString("").setNum(logReadings_.cableCals().size()) + " cable_cal and " +
5980  QString("").setNum(logReadings_.meteoPars().size()) + " meteo records");
5981  //
5982  //
5983  if (wantTsys)
5985  "::readLogFile(): station " + stationName_ + ": collected " +
5986  QString("").setNum(logReadings_.tSyses().size()) + " tsys records");
5989  "::readLogFile(): station " + stationName_ + ": collected " +
5990  QString("").setNum(logReadings_.dbbc3Tps().size()) + " dbbc3 TP records");
5993  "::readLogFile(): station " + stationName_ + ": collected " +
5994  QString("").setNum(logReadings_.sefds().size()) + " SEFD evaluation records");
5995  //
5996  //
5997  if (5 < logReadings_.tSyses().size())
5998  hasTsysRecord_ = true;
5999 
6000  if (rinexFileNameByStn_ &&
6001  rinexFileNameByStn_->contains(stationName_) && logReadings_.meteoPars().size()==0)
6002  {
6003  if (checkRinexFile(fileName, tFirst, tLast, rinexFileNameByStn_->value(stationName_)))
6005  "::readLogFile(): station " + stationName_ + ": collected " +
6006  QString("").setNum(logReadings_.meteoPars().size()) +
6007  " meteo records from RINEX files");
6008  else
6010  "::readLogFile(): station " + stationName_ + ": nothing to get from RINEX files");
6011  };
6012  //
6013  return true;
6014 };
6015 
6016 
6017 
6018 //
6020 {
6021  FieldSystemEpochFormat retFsFmt;
6022  if (reFsNewest_.match(str).hasMatch())
6023  retFsFmt = FSEF_NEWEST;
6024  else if (reFsNew_.match(str).hasMatch())
6025  retFsFmt = FSEF_NEW;
6026  else if (reFsOld_.match(str).hasMatch())
6027  retFsFmt = FSEF_OLD;
6028  else if (rePcmt_.match(str).hasMatch())
6029  retFsFmt = FSEF_PCMT;
6030  else if (reMet_.match(str).hasMatch())
6031  retFsFmt = FSEF_MET;
6032  else
6033  retFsFmt = FSEF_UNDEF;
6034 
6035  return retFsFmt;
6036 };
6037 
6038 
6039 
6040 //
6041 bool SgStnLogCollector::extractEpoch(const QString& str, SgMJD& t)
6042 {
6043  int nYear=0, nMonth=0, nDay=0, nHour=0, nMin=0;
6044  double dSecond=0.0, f=0.0;
6045  bool isOk=true;
6046  QRegularExpressionMatch match;
6047  //
6048  switch (fsFmt_)
6049  {
6050  //340184033;MARK III PC FIELD SYSTEM V 3.65 EFLSBERG 1995 00000000
6051  case FSEF_OLD: // DDDHHMMSS
6052 /* if (reFsOld_.indexIn(str) != -1) */
6053  if (reFsOld_.match(str).hasMatch())
6054  {
6055  nDay = str.mid(0,3).toInt(&isOk);
6056  if (isOk)
6057  {
6058  nHour = str.mid(3,2).toInt(&isOk);
6059  if (isOk)
6060  {
6061  nMin = str.mid(5,2).toInt(&isOk);
6062  if (isOk)
6063  {
6064  dSecond = str.mid(7,2).toInt(&isOk);
6065  nYear = inYear_;
6066  };
6067  };
6068  };
6069  }
6070  else
6071  {
6072  isOk = false;
6074  "::extractEpoch(): looks like not OLD FS format, string: \"" + asciifyString(str) + "\"");
6075 // "::extractEpoch(): looks like not OLD FS format, string: \"" + str + "\"");
6076  };
6077  break;
6078  //9903209333995;Log Opened: Mark IV Field System Version 9.3.17
6079  case FSEF_NEW: // YYDDDHHMMSSss
6080 /* if (reFsNew_.indexIn(str) != -1)*/
6081  if (reFsNew_.match(str).hasMatch())
6082  {
6083  nYear = str.mid(0,2).toInt(&isOk);
6084  if (isOk)
6085  {
6086  nDay = str.mid(2,3).toInt(&isOk);
6087  if (isOk)
6088  {
6089  nHour = str.mid(5,2).toInt(&isOk);
6090  if (isOk)
6091  {
6092  nMin = str.mid(7,2).toInt(&isOk);
6093  if (isOk)
6094  {
6095  dSecond = str.mid(9,2).toInt(&isOk);
6096  if (isOk)
6097  {
6098  f = str.mid(11,2).toInt(&isOk);
6099  if (isOk)
6100  {
6101  dSecond += 0.01*f;
6102  nYear += (nYear>68)?1900:2000;
6103  };
6104  };
6105  };
6106  };
6107  };
6108  };
6109  }
6110  else
6111  {
6112  isOk = false;
6114  "::extractEpoch(): looks like not NEW FS format, string: \"" + asciifyString(str) + "\"");
6115 // "::extractEpoch(): looks like not NEW FS format, string: \"" + str + "\"");
6116  };
6117  break;
6118  //012345678901234567890
6119  //2006.214.20:21:46.26
6120  //2016.019.14:17:00.08;Log Opened: Mark IV Field System Version 9.12.2
6121  //2002.247.18:20:00.0 /wx/ 9.1,1017.0,90.0 -- surprise?
6122  //2020.356.17:00:05 /wx/14.7,84.0,1023.1,4.0,-2 --"--
6123  case FSEF_NEWEST: // YYYY.DDD.HH.MM.SS.ss
6124 /* if (reFsNewest_.indexIn(str) != -1) */
6125  if ((match=reFsNewest_.match(str)).hasMatch())
6126  {
6127  nYear = match.captured(1).toInt(&isOk);
6128  if (isOk)
6129  {
6130  nDay = match.captured(2).toInt(&isOk);
6131  if (isOk)
6132  {
6133  nHour = match.captured(3).toInt(&isOk);
6134  if (isOk)
6135  {
6136  nMin = match.captured(4).toInt(&isOk);
6137  if (isOk)
6138  {
6139  dSecond = match.captured(5).toDouble(&isOk);
6140  fsContentStartsAt_[FSEF_NEWEST] = 15 + match.captured(5).size();
6141  };
6142  };
6143  };
6144  };
6145  /*
6146  nYear = str.mid(0,4).toInt(&isOk);
6147  if (isOk)
6148  {
6149  nDay = str.mid(5,3).toInt(&isOk);
6150  if (isOk)
6151  {
6152  nHour = str.mid(9,2).toInt(&isOk);
6153  if (isOk)
6154  {
6155  nMin = str.mid(12,2).toInt(&isOk);
6156  if (isOk)
6157  {
6158  dSecond = str.mid(15,5).toDouble(&isOk);
6159  if (!isOk) // try as exception:
6160  {
6161  dSecond = str.mid(15,4).toDouble(&isOk);
6162  fsContentStartsAt_[FSEF_NEWEST] = 19;
6163  }
6164  else if (fsContentStartsAt_[FSEF_NEWEST] == 19)
6165  fsContentStartsAt_[FSEF_NEWEST] = 20;
6166  };
6167  };
6168  };
6169  };
6170  */
6171  }
6172  else
6173  {
6174  isOk = false;
6176  "::extractEpoch(): looks like not NEWEST FS format, string: \"" + asciifyString(str) + "\"");
6177 // "::extractEpoch(): looks like not NEWEST FS format, string: \"" + str + "\"");
6178  };
6179  break;
6180  case FSEF_PCMT: //
6181  case FSEF_MET: //
6182  //2017 9 11 18 50 29 1.196e-11 254-1850
6183 /* if (rePcmt_.indexIn(str) != -1) */
6184  if (rePcmt_.match(str).hasMatch())
6185  {
6186  QStringList l=str.split(QRegExp("\\s+"));
6187  if (l.size() >= 6)
6188  {
6189  nYear = l.at(0).toInt(&isOk);
6190  if (isOk)
6191  {
6192  nMonth = l.at(1).toInt(&isOk);
6193  if (isOk)
6194  {
6195  nDay = l.at(2).toInt(&isOk);
6196  if (isOk)
6197  {
6198  nHour = l.at(3).toInt(&isOk);
6199  if (isOk)
6200  {
6201  nMin = l.at(4).toInt(&isOk);
6202  if (isOk)
6203  dSecond = l.at(5).toDouble(&isOk);
6204  };
6205  };
6206  };
6207  };
6208  }
6209  else
6211  "::extractEpoch(): not enough data for PCMT format, the string: \"" +
6212  asciifyString(str) + "\"");
6213 // "::extractEpoch(): not enough data for PCMT format, the string: \"" + str + "\"");
6214  }
6215  else
6216  {
6217  isOk = false;
6219  "::extractEpoch(): looks like not PCMT format, the string: \"" + asciifyString(str) + "\"");
6220 // "::extractEpoch(): looks like not PCMT format, the string: \"" + str + "\"");
6221  };
6222  break;
6223  default:
6224  case FSEF_UNDEF:
6225  isOk = false;
6226  break;
6227  };
6228  //
6229  if (isOk)
6230  {
6231  if (0 < inYear_ && nYear != inYear_)
6232  {
6234  "::extractEpoch(): year has changed: " + QString("").setNum(inYear_) + " => " +
6235  QString("").setNum(nYear) + "; input: \"" + asciifyString(str) + "\"");
6236  inYear_ = nYear;
6237  }
6238  else if (inYear_ == 0)
6239  inYear_ = nYear;
6240  };
6241  //
6242  if (!isOk)
6243  {
6244  if (fsFmt_==FSEF_NEWEST)
6245  {
6246  fsFmt_ = FSEF_NEW;
6247  isOk = extractEpoch(str, t);
6248  if (isOk)
6250  "::extractEpoch(): looks like FS format has changed NEWEST=>NEW: \"" +
6251  asciifyString(str) + "\"");
6252 // "::extractEpoch(): looks like FS format has changed NEWEST=>NEW: \"" + str + "\"");
6253  else
6254  fsFmt_ = FSEF_NEWEST;
6255  }
6256  else if (fsFmt_==FSEF_NEW)
6257  {
6258  // e.g.: /500/sessions/1998/na253/na253ft.log
6259  // olf version of FS has been launched while station observed
6260  fsFmt_ = FSEF_OLD;
6261  isOk = extractEpoch(str, t);
6262  if (isOk)
6264  "::extractEpoch(): looks like FS format has changed NEW=>OLD: \"" + asciifyString(str) + "\"");
6265 // "::extractEpoch(): looks like FS format has changed NEW=>OLD: \"" + str + "\"");
6266  else
6267  fsFmt_ = FSEF_NEW;
6268  };
6269  if (!isOk)
6271  "::extractEpoch(): failed to parse, string: \"" + asciifyString(str) + "\"");
6272 // "::extractEpoch(): failed to parse, string: \"" + str + "\"");
6273  }
6274  else
6275  t.setUpEpoch(nYear, nMonth, nDay, nHour, nMin, dSecond);
6276  return isOk;
6277 };
6278 
6279 
6280 
6281 //
6282 bool SgStnLogCollector::extractContent(const QString& str, QString& content)
6283 {
6284  content = str.mid(fsContentStartsAt_[fsFmt_]);
6285  return content.size() > 0;
6286 };
6287 
6288 
6289 
6290 //
6291 bool SgStnLogCollector::extractMeteoReading(const QString& str, const QRegularExpression& reMeteo,
6292  SgMJD& t, SgMeteoData& m, const int* oom)
6293 {
6294  double d;
6295  bool isOk=false;
6296 
6297  if (!extractEpoch(str, t))
6298  return false;
6299 
6300  //
6301  // here a little bit different approach: there can be meteo parameters:
6302  // either (T,P,RH) or (T,P,RH,WindVel,WindAzimuth)
6303  // PS: we do not use wind velocity and direction.
6304  //
6305 //#if QT_VERSION >= 0x040800
6306 // QString metStr(str.mid(reMeteo.indexIn(str) + reMeteo.cap(1).size()));
6307 //#else
6308 // QRegExp reMeteo2(reMeteo);
6309 // QString metStr(str.mid(reMeteo2.indexIn(str) + reMeteo2.cap(1).size()));
6310 //#endif
6311 
6312  QString metStr(str.mid(reMeteo.match(str).capturedEnd(1)));
6313 
6314  if (metStr.contains("C"))
6315  metStr = metStr.remove("C");
6316  if (metStr.contains("mB"))
6317  metStr = metStr.remove("mB");
6318  if (metStr.contains("%"))
6319  metStr = metStr.remove("%");
6320  if (metStr.contains("weather:"))
6321  metStr = metStr.remove("weather:");
6322 
6323  if (!metStr.size())
6324  {
6326  "::extractMeteoReading(): cannot extract meteo data from \"" + asciifyString(str) + "\"");
6327 // "::extractMeteoReading(): cannot extract meteo data from \"" + str + "\"");
6328  return isOk;
6329  };
6330 
6331  QStringList lst=metStr.split(",");
6332 
6333  if (lst.size() > 2)
6334  {
6335  const QString &strT =lst.at(oom[0]);
6336  const QString &strP =lst.at(oom[1]);
6337  const QString &strRh=lst.at(oom[2]);
6338 
6339  d = strT.toDouble(&isOk);
6340  if (isOk)
6341  {
6342  if (-50.0<=d && d<=80.0) // ?? is it ok, can stations operate in worse conditions?
6343  {
6344  m.setTemperature(d);
6345  d = strP.toDouble(&isOk);
6346  if (isOk)
6347  {
6348  if (d == 1100.0)
6349  {
6350  isOk = false;
6352  "::extractMeteoReading(): the extracted atmospheric pressure looks suspicious: " +
6353  QString("").setNum(d) + "hPa (i.e.,==std.atm.); skipped");
6354  }
6355  else if (d >= 500.0) // 500kPa is at ~5.5km height of the standard atmosphere
6356  {
6357  m.setPressure(d);
6358  d = strRh.toDouble(&isOk);
6359  if (isOk)
6360  {
6361  if (-9.9<=d && d<=120.0)
6362  {
6363  if (d < 0.0)
6364  {
6366  "::extractMeteoReading(): the extracted relative humidity looks suspicious: " +
6367  QString("").setNum(d) + "%; adjusted it to zero");
6368  m.setRelativeHumidity(0.0);
6369  }
6370  else if (100.0 < d)
6371  {
6373  "::extractMeteoReading(): the extracted relative humidity looks suspicious: " +
6374  QString("").setNum(d) + "%; adjusted it to 100%");
6375  m.setRelativeHumidity(1.0);
6376  }
6377  else
6378  m.setRelativeHumidity(d*0.01);
6379  }
6380  else
6381  {
6382  isOk = false;
6384  "::extractMeteoReading(): the extracted relative humidity looks unrealstic: " +
6385  QString("").setNum(d) + "%; skipped");
6386  };
6387  }
6388  else if (strRh.contains("EE.0", Qt::CaseInsensitive))
6389  {
6390  m.setRelativeHumidity(1.0);
6392  "::extractMeteoReading(): forcefully set relative humidity to 1.00 from the string \"" +
6393  strRh + "\"");
6394  }
6395  else
6397  "::extractMeteoReading(): failed to extract relative humidity from \"" + strRh + "\"");
6398  }
6399  else
6400  {
6401  isOk = false;
6403  "::extractMeteoReading(): the extracted atmospheric pressure is too low: " +
6404  QString("").setNum(d) + "hPa; skipped");
6405  };
6406  }
6407  else
6409  "::extractMeteoReading(): failed to extract pressure from \"" + strP + "\"");
6410  }
6411  else
6412  {
6413  isOk = false;
6415  "::extractMeteoReading(): the extracted atmospheric temperature looks unreal: " +
6416  QString("").setNum(d) + "C; skipped");
6417  };
6418  }
6419  else
6421  "::extractMeteoReading(): failed to extract temperature: from \"" + strT + "\"");
6422  }
6423  else
6425  "::extractMeteoReading(): the number of data less than 3: \"" + metStr + "\"");
6426  return isOk;
6427 };
6428 
6429 
6430 
6431 //
6432 bool SgStnLogCollector::extractPcalOffsetReading(const QString& str, const QRegularExpressionMatch& match,
6433  SgMJD& t, const SgMJD& tAtTheEnd, SgChannelSetup& cs, const SgMJD& tFirst)
6434 {
6435  QString sLo("");
6436  double pcalOffset;
6437  bool isOk;
6438 
6439  if (!extractEpoch(str, t))
6440  return false;
6441 
6442  if (tAtTheEnd <= t)
6443  return false;
6444 
6445  sLo = match.captured(1);
6446  pcalOffset = match.captured(2).toDouble(&isOk)*1.0e-6;
6447  if (!isOk)
6448  {
6450  "::extractPcalOffsetReading(): station " + stationName_ +
6451  ": cannot convert \"" + match.capturedEnd(2) + "\" to double; input: \"" +
6452  asciifyString(str) + "\"");
6453  return false;
6454  };
6455 
6456  QList<QString> los;
6457  if (sLo.size() == 0)
6458  los << "*";
6459  else if (sLo.size() == 1)
6460  los << sLo << sLo + "0" << sLo + "1";
6461  else
6462  los << sLo;
6463 
6464  for (int i=0; i<los.size(); i++)
6465  {
6466  sLo = los.at(i);
6467  if (cs.pcalOffsetByLoId().contains(sLo) && cs.pcalOffsetByLoId().value(sLo) != pcalOffset)
6469  "::extractPcalOffsetReading(): station " + stationName_ +
6470  ": pcal frequency offset for LO=" + sLo + " has changed from " +
6471  QString("").setNum(cs.pcalOffsetByLoId().value(sLo)) + " to " +
6472  QString("").setNum(pcalOffset) + "; input: \"" +
6473  asciifyString(str) + "\"");
6474  cs.pcalOffsetByLoId()[sLo] = pcalOffset;
6475  };
6476  return true;
6477 };
6478 
6479 
6480 
6481 
6482 
6483 //
6484 //bool SgStnLogCollector::extractBbcReading(const QString& str, const QRegExp& re, SgMJD& t,
6485 bool SgStnLogCollector::extractBbcReading(const QString& str, const QRegularExpressionMatch& match,
6486  SgMJD& t, const SgMJD& nearTheEnd, SgChannelSetup& cs, const SgMJD& tFirst)
6487 {
6488  QString bbcStr(str.mid(match.capturedEnd(2) + 1));
6489  QString bbcId(match.captured(2));
6490 
6491  if (!extractEpoch(str, t))
6492  return false;
6493 
6494  if (nearTheEnd <= t)
6495  return false;
6496 
6497  bool isOk;
6498  int cIdx;
6499  cIdx = bbcId.toInt(&isOk);
6500  if (!isOk)
6501  {
6503  "::extractBbcReading(): station " + stationName_ +
6504  ": cannot convert \"" + bbcId + "\" to int; input: \"" + asciifyString(str) + "\"");
6505  return false;
6506  };
6507 
6508  QStringList lst=bbcStr.split(",");
6509 /*
6510 Syntax: bbcnn=freq,ifsource,bwu,bwl,avper,gainmode,gainu,gainl
6511 
6512 Response: bbcnn/freq,ifsource,bwu,bwl,avper,gainmode,gainu,gainl,lock,USBpwr,LSBpwr,serno,err
6513 
6514 nn is the BBC index number corresponding to its position in the rack, 01 to 14. Not all racks
6515  have all BBCs.
6516 
6517 Settable Parameters:
6518 
6519 freq -- L.O. frequency in MHz, between 450.00 and 1050.00, inclusive. No default. This frequency
6520  range is greater than the normal range over which the BBC is specified to lock (500 to 1000 MHz)
6521  to allow for testing.
6522 
6523 ifsource -- I.F. input source, one of A, B, C, D. No default.
6524 
6525 bwu -- Bandwidth for USB in MHz. One of 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16. Default 2.
6526 
6527 bwl -- Bandwidth for LSB in MHz. One of 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16. Default bwu.
6528 
6529 avper -- Averaging period in seconds for TPI. May be 0, 1, 2, 4, 10, 20, 40, or 60 seconds. A value
6530  of 0 results in 1/80 sec averaging time. Default 1. The averaging period is common to both
6531  upper and lower sideband. The averaging period is synchronous with the 1 pps.
6532 */
6533  //
6534  //2018.003.17:14:29.54&dbbcsx8/bbc03=285.75,a,8.00
6535  //2018.003.17:14:29.54&dbbcsx8/bbc04=365.75,a,8.00
6536  //2018.003.17:14:29.54&dbbcsx8/bbc05=725.75,b,8.00
6537  //
6538  if (3 <= lst.size())
6539  {
6540  double d;
6541  // BBC freq:
6542  d = lst.at(0).toDouble(&isOk);
6543  if (!isOk)
6544  {
6546  "::extractBbcReading(): station " + stationName_ +
6547  ": cannot convert \"" + lst.at(0) + "\" to double; input: \"" +
6548  asciifyString(str) + "\"");
6549  return false;
6550  };
6551  // IFD ID:
6552  if (cs.bbcFreqByIdx().contains(cIdx) &&
6553  cs.bbcFreqByIdx()[cIdx] != d &&
6554  tFirst < t)
6556  "::extractBbcReading(): station " + stationName_ +
6557  ": IF frequency has changed for BBC #" + bbcId + ": " +
6558  QString("").sprintf("%.2f => %.2f", cs.bbcFreqByIdx()[cIdx], d) +
6559  "; input: \"" + asciifyString(str) + "\"");
6560  cs.bbcFreqByIdx()[cIdx] = d;
6561  cs.loIdByIdx()[cIdx] = lst.at(1);
6562 
6563  // bandwidth:
6564  d = lst.at(2).toDouble(&isOk);
6565  if (!isOk)
6566  {
6568  "::extractBbcReading(): station " + stationName_ +
6569  ": cannot convert \"" + lst.at(2) + "\" to double; input: \"" +
6570  asciifyString(str) + "\"");
6571  return false;
6572  };
6573  if (cs.bbcBandwidthByIdx().contains(cIdx) &&
6574  cs.bbcBandwidthByIdx()[cIdx] != d &&
6575  tFirst < t)
6577  "::extractBbcReading(): station " + stationName_ +
6578  ": IF bandwidth has changed for BBC #" + bbcId + ": " +
6579  QString("").sprintf("%.2f => %.2f", cs.bbcBandwidthByIdx()[cIdx], d) +
6580  "; input: \"" + asciifyString(str) + "\"");
6581  cs.bbcBandwidthByIdx()[cIdx] = d;
6582  //
6583  if (4 < lst.size())
6585  "::extractBbcReading(): station " + stationName_ +
6586  ": got extra data; input: \"" + asciifyString(str) + "\"");
6587  if (cs.getHwType() == SgChannelSetup::HT_UNDEF)
6589  else if (cs.getHwType() != SgChannelSetup::HT_BBC)
6590  {
6592  "::extractBbcReading(): station " + stationName_ +
6593  ": got an unexpected \"bbc\" record; input: \"" + asciifyString(str) + "\"");
6595  };
6596  }
6597  else
6598  {
6600  "::extractBbcReading(): station " + stationName_ +
6601  ": the number of data less than 3: \"" + bbcStr + "\"");
6602  return false;
6603  };
6604  return true;
6605 };
6606 
6607 
6608 
6609 //
6610 bool SgStnLogCollector::extractVcReading(const QString& str, const QRegularExpressionMatch& match,
6611  SgMJD& t, const SgMJD& nearTheEnd, SgChannelSetup& cs, const SgMJD& tFirst)
6612 {
6613 // QString vcStr(str.mid(re.indexIn(str) + re.cap(1).size() +
6614 // re.cap(2).size() + 1));
6615  QString vcStr(str.mid(match.capturedEnd(2) + 1));
6616 
6617  if (!extractEpoch(str, t))
6618  return false;
6619 
6620  if (nearTheEnd <= t)
6621  return false;
6622 
6623  QString bbcId(match.captured(2));
6624  bool isOk;
6625  int cIdx;
6626  cIdx = bbcId.toInt(&isOk);
6627  if (!isOk)
6628  {
6630  "::extractVcReading(): station " + stationName_ +
6631  ": cannot convert \"" + bbcId + "\" to int; input: \"" + asciifyString(str) + "\"");
6632  return false;
6633  };
6634 
6635  QStringList lst=vcStr.split(",");
6636 
6637 /*
6638 Syntax: vcnn=freq,bandwidth,TPIsel,attenU,attenL
6639 
6640 Response: vcnn/freq,bandwidth,TPIsel,attenU,attenl,rem/lcl,LOlock,TP
6641 
6642 Settable parameters:
6643 
6644 freq - Synthesizer frequency in MHz, value must be less than 500.00 MHz. No default.
6645 bandwidth - Final filter bandwidth in MHz, default 2. Choices for Mark III are: 0.125, 0.25, 0.5,
6646  1.0, 2.0, 4.0, 0 (external filter). Choices for Mark IV are: 0.125, 0.5, 2.0, 4.0, 8.0,
6647  16.0, 0 (external filter). Value may be integer for bandwidths of 1, 2, 4, 8, or 16 MHz.
6648 TPIsel - Total power integrator selection. Choices are ul, l, u, if, lo, gr (ground). Default u.
6649 attenU - USB attenuator, 0 or 10 db (default) only.
6650 attenL - LSB attenuator, 0 or 10 db (default) only.*
6651 */
6652  //
6653  //2019.003.18:05:50.86&vcsx8/vc01=132.99,8.000,ul
6654  //2019.003.18:05:50.86&vcsx8/vc02=172.99,8.000,u
6655  //2019.003.18:05:50.86&vcsx8/vc03=272.99,8.000,u
6656 
6657  if (lst.size())
6658  {
6659  double d;
6660  // VC freq:
6661  d = lst.at(0).toDouble(&isOk);
6662  if (!isOk)
6663  {
6665  "::extractVcReading(): station " + stationName_ +
6666  ": cannot convert \"" + lst.at(0) + "\" to double; input: \"" +
6667  asciifyString(str) + "\"");
6668  return false;
6669  };
6670  // IFD ID:
6671  if (cs.bbcFreqByIdx().contains(cIdx) &&
6672  cs.bbcFreqByIdx()[cIdx] != d &&
6673  tFirst < t)
6675  "::extractVcReading(): station " + stationName_ +
6676  ": video frequency has changed for IF #" + bbcId + ": " +
6677  QString("").sprintf("%.2f => %.2f", cs.bbcFreqByIdx()[cIdx], d) +
6678  "; input: \"" + asciifyString(str) + "\"");
6679  cs.bbcFreqByIdx()[cIdx] = d;
6680 
6681  // bandwidth:
6682  d = 2.0;
6683  if (1 < lst.size())
6684  {
6685  d = lst.at(1).toDouble(&isOk);
6686  if (!isOk)
6687  {
6689  "::extractVcReading(): station " + stationName_ +
6690  ": cannot convert \"" + lst.at(2) + "\" to double; input: \"" +
6691  asciifyString(str) + "\"");
6692  return false;
6693  };
6694  };
6695  if (cs.bbcBandwidthByIdx().contains(cIdx) &&
6696  cs.bbcBandwidthByIdx()[cIdx] != d &&
6697  tFirst < t)
6699  "::extractVcReading(): station " + stationName_ +
6700  ": bandwidth has changed for IF #" + bbcId + ": " +
6701  QString("").sprintf("%.2f => %.2f", cs.bbcBandwidthByIdx()[cIdx], d) +
6702  "; input: \"" + asciifyString(str) + "\"");
6703  cs.bbcBandwidthByIdx()[cIdx] = d;
6704  //
6705 
6706  if (cs.getHwType() == SgChannelSetup::HT_UNDEF)
6708  else if (cs.getHwType() != SgChannelSetup::HT_VC)
6709  {
6711  "::extractVcReading(): station " + stationName_ +
6712  ": got unexpected \"vc\" record; input: \"" + asciifyString(str) + "\"");
6714  };
6715  }
6716  else
6717  {
6719  "::extractVcReading(): station " + stationName_ +
6720  ": the number of data less than 2: \"" + vcStr + "\"");
6721  return false;
6722  };
6723  return true;
6724 };
6725 
6726 
6727 
6728 //
6729 bool SgStnLogCollector::extractLoReading(const QString& str, const QRegularExpressionMatch& match,
6730  SgMJD& t, const SgMJD& nearTheEnd, SgChannelSetup& cs, const SgMJD& tFirst)
6731 {
6732  QString loStr(str.mid(match.capturedEnd(1)));
6733 
6734  if (!extractEpoch(str, t))
6735  return false;
6736 
6737  if (nearTheEnd <= t)
6738  return false;
6739 
6740  bool isOk;
6741  QString loId(match.captured(2));
6742  QStringList lst=loStr.split(",");
6743 
6744  //2018.003.17:14:29.55&ifdsx/lo=loa,8080.00,usb,rcp,1
6745  //2018.003.17:14:29.55&ifdsx/lo=lob,8080.00,usb,rcp,1
6746  //2018.003.17:14:29.55&ifdsx/lo=loc,2020.00,usb,rcp,1
6747  //2018.003.17:14:29.55&ifdsx/lo=lod,2020.00,usb,rcp,1
6748  //
6749  if (4 <= lst.size())
6750  {
6751  double d;
6752  d = lst.at(1).toDouble(&isOk);
6753  if (!isOk)
6754  {
6756  "::extractLoReading(): station " + stationName_ +
6757  ": cannot convert \"" + lst.at(1) + "\" to double; input: \"" + asciifyString(str) + "\"");
6758  return false;
6759  };
6760 
6761  if (cs.loFreqById().contains(loId) &&
6762  cs.loFreqById()[loId] != d &&
6763  tFirst < t)
6765  "::extractLoReading(): station " + stationName_ + ": LO frequency changed for LO \"" + loId +
6766  "\": " +
6767  QString("").sprintf("%.2f", cs.loFreqById()[loId]) + " => " +
6768  QString("").sprintf("%.2f", d) + "; input: \"" + asciifyString(str) + "\"");
6769 
6770  cs.loFreqById()[loId] = d;
6771  const QString &sb=lst.at(2);
6772  const QString &pz=lst.at(3);
6773 
6774  if (sb == "usb")
6775  cs.loSideBandById()[loId] = CSB_USB;
6776  else if (sb == "lsb")
6777  cs.loSideBandById()[loId] = CSB_LSB;
6778  else
6779  {
6780  cs.loSideBandById()[loId] = CSB_UNDEF;
6782  "::extractLoReading(): station " + stationName_ +
6783  ": cannot figure out side band form the string \"" + asciifyString(str) + "\"");
6784  };
6785  // polarization:
6786  if (pz == "rcp")
6787  cs.loPolarizationById()[loId] = CP_RightCP;
6788  else if (pz == "lcp")
6789  cs.loPolarizationById()[loId] = CP_LeftCP;
6790  else
6791  {
6792  cs.loPolarizationById()[loId] = CP_UNDEF;
6794  "::extractLoReading(): station " + stationName_ +
6795  ": cannot figure out polarization form the string \"" + asciifyString(str) + "\"");
6796  };
6797  if (5 <= lst.size())
6798  {
6799  d = lst.at(4).toDouble(&isOk);
6800  if (!isOk)
6801  {
6803  "::extractLoReading(): station " + stationName_ +
6804  ": cannot convert \"" + lst.at(4) + "\" to double; input: \"" + asciifyString(str) + "\"");
6805  return false;
6806  };
6807  cs.loPcWidthById()[loId] = d;
6808  // aux:
6809  if (5 < lst.size())
6811  "::extractLoReading(): station " + stationName_ +
6812  ": got extra data; input: \"" + asciifyString(str) + "\"");
6813  };
6814  }
6815  else
6816  {
6818  "::extractLoReading(): station " + stationName_ +
6819  ": the number of data less than 4: \"" + loStr + "\"");
6820  return false;
6821  };
6822 
6823  return true;
6824 };
6825 
6826 
6827 
6828 //
6829 //
6830 bool SgStnLogCollector::extractLoRxgReading(const QString& str, const QRegularExpressionMatch& match,
6831  SgMJD& t, const SgMJD& nearTheEnd, SgChannelSetup& cs, const SgMJD& tFirst)
6832 {
6833  QString loStr(str.mid(match.capturedEnd(1)));
6834 
6835 
6836  if (!extractEpoch(str, t))
6837  return false;
6838  if (nearTheEnd <= t)
6839  return false;
6840 
6841  bool isOk;
6842  QString loId(match.captured(2));
6843  QStringList lst=loStr.split(",");
6844 
6845  //2021.190.19:40:27.52/lo/rxg,loa0,3592.4,lcp,bb.rxg,range,1000,10000,2015,3,22,lcp,3.00000e-02,rcp,3.00000e-02
6846  //2021.190.19:40:27.52/lo/rxg,loa1,3592.4,rcp,bb.rxg,range,1000,10000,2015,3,22,lcp,3.00000e-02,rcp,3.00000e-02
6847  //2021.190.19:40:27.52/lo/rxg,lob0,3990.4,lcp,bb.rxg,range,1000,10000,2015,3,22,lcp,3.00000e-02,rcp,3.00000e-02
6848  //2021.190.19:40:27.53/lo/rxg,lob1,3990.4,rcp,bb.rxg,range,1000,10000,2015,3,22,lcp,3.00000e-02,rcp,3.00000e-02
6849  //2021.190.19:40:27.53/lo/rxg,loc0,10354.4,lcp,undefined
6850  //2021.190.19:40:27.53/lo/rxg,loc1,10354.4,rcp,undefined
6851  //2021.190.19:40:27.53/lo/rxg,lod0,10498.4,lcp,undefined
6852  //2021.190.19:40:27.53/lo/rxg,lod1,10498.4,rcp,undefined
6853  if (3 <= lst.size())
6854  {
6855  double d;
6856  d = lst.at(1).toDouble(&isOk);
6857  if (!isOk)
6858  {
6860  "::extractLoRxgReading(): station " + stationName_ +
6861  ": cannot convert \"" + lst.at(1) + "\" to double; input: \"" + asciifyString(str) + "\"");
6862  return false;
6863  };
6864  if (cs.loFreqById().contains(loId) &&
6865  cs.loFreqById()[loId] != d &&
6866  tFirst < t)
6868  "::extractLoRxgReading(): station " + stationName_ + ": frequency changed for LO \"" + loId +
6869  "\": " +
6870  QString("").sprintf("%.2f", cs.loFreqById()[loId]) + " => " +
6871  QString("").sprintf("%.2f", d) + "; input: \"" + asciifyString(str) + "\"");
6872 
6873  cs.loFreqById()[loId] = d;
6874 
6875  const QString &pz=lst.at(2);
6877 
6878  if (pz == "rcp")
6879  polariz = CP_RightCP;
6880  else if (pz == "lcp")
6881  polariz = CP_LeftCP;
6882  else
6884  "::extractLoRxgReading(): station " + stationName_ +
6885  ": cannot figure out polarization form the string \"" + asciifyString(str) + "\"");
6886  if (cs.loPolarizationById().contains(loId) &&
6887  cs.loPolarizationById()[loId] != polariz &&
6888  tFirst < t)
6890  "::extractLoRxgReading(): station " + stationName_ + ": polarization changed for LO \"" +
6891  loId + "\": " +
6892  polarization2Str(cs.loPolarizationById()[loId]) + " => " +
6893  polarization2Str(polariz) + "; input: \"" + asciifyString(str) + "\"");
6894  cs.loPolarizationById()[loId] = polariz;
6895  }
6896  else
6897  {
6899  "::extractLoRxgReading(): station " + stationName_ +
6900  ": the number of data less than 3: \"" + loStr + "\"");
6901  return false;
6902  };
6903  return true;
6904 };
6905 
6906 
6907 
6908 //
6909 bool SgStnLogCollector::extractPatchReading(const QString& str, const QRegularExpressionMatch& match,
6910  SgMJD& t, const SgMJD& nearTheEnd, SgChannelSetup& cs, UNUSED const SgMJD& tFirst)
6911 {
6912 //QString patchStr(str.mid(re.indexIn(str) + re.cap(1).size()));
6913  QString patchStr(str.mid(match.capturedEnd(1)));
6914 
6915  if (!extractEpoch(str, t))
6916  return false;
6917  if (nearTheEnd <= t)
6918  return false;
6919 
6920  bool isOk;
6921  QStringList lst=patchStr.split(",");
6922 
6923  //2019.003.18:05:52.80&ifdsx/patch=lo1,1l,2l,3h,4h
6924  //2019.003.18:05:52.80&ifdsx/patch=lo2,9l,10h,11h,12h,13h,14h
6925  //2019.003.18:05:52.80&ifdsx/patch=lo3,5h,6h,7h,8h
6926  //
6927  //2018.094.17:20:22.65&ifdsx/patch=lo1,a1,a2,a3,a4
6928  //2018.094.17:20:22.65&ifdsx/patch=lo2,b1,b2,b3,b4,b5,b6
6929  //2018.094.17:20:22.65&ifdsx/patch=lo3,a5,a6,a7,a8
6930 
6931  if (1 < lst.size())
6932  {
6933  QString loId(lst.at(0));
6934 
6935  for (int i=1; i<lst.size(); i++)
6936  {
6937  QString cid(lst.at(i));
6938  QChar sb(cid.at(cid.size() - 1));
6939  if (sb == 'l' || sb == 'h')
6940  {
6941  cid.chop(1);
6942  int cIdx=-1;
6943  cIdx = cid.toInt(&isOk);
6944  if (!isOk)
6945  {
6947  "::extractPatchReading(): station " + stationName_ +
6948  ": cannot convert \"" + cid + "\" to int; input: \"" + asciifyString(str) + "\"");
6949  }
6950  else
6951  cs.loIdByIdx()[cIdx] = loId;
6952  }
6953  else
6954  cs.loIdByCid()[cid] = loId;
6955 // else
6956 // logger->write(SgLogger::ERR, SgLogger::IO, className() +
6957 // "::extractPatchReading(): unexpected patch record #" + QString("").setNum(i) +
6958 // " \"" + cid + "\"; the string \"" + str + "\"");
6959  };
6960  }
6961  else
6962  {
6964  "::extractPatchReading(): station " + stationName_ +
6965  ": nothing found: \"" + asciifyString(str) + "\"");
6966 // ": nothing found: \"" + str + "\"");
6967  return false;
6968  };
6969 
6970  return true;
6971 };
6972 
6973 
6974 
6975 
6976 //
6978  const QRegularExpressionMatch& match,
6979  SgMJD& t, const SgMJD& nearTheEnd, SgChannelSetup& cs, const SgMJD& tFirst)
6980 {
6981  if (!extractEpoch(str, t))
6982  return false;
6983  if (nearTheEnd <= t)
6984  return false;
6985 
6986  bool isOk;
6987  int cIdx=-1;
6988  double skyFrq=-1.0, loFrq=-1.0, videoFrq=-1.0;
6989  QString bbcId(match.captured(1));
6990 
6991  cIdx = bbcId.toInt(&isOk);
6992  if (!isOk)
6993  {
6995  "::extractChanSkyFrqReading(): station " + stationName_ +
6996  ": cannot get channel index; input: \"" + asciifyString(str) + "\"");
6997  return isOk;
6998  };
6999  skyFrq = match.captured(2).toDouble(&isOk);
7000  if (!isOk)
7001  {
7003  "::extractChanSkyFrqReading(): station " + stationName_ +
7004  ": cannot get sky frequency; input: \"" + asciifyString(str) + "\"");
7005  return isOk;
7006  };
7007  loFrq = match.captured(3).toDouble(&isOk);
7008  if (!isOk)
7009  {
7011  "::extractChanSkyFrqReading(): station " + stationName_ +
7012  ": cannot get LO frequency; input: \"" + asciifyString(str) + "\"");
7013  return isOk;
7014  };
7015  videoFrq = match.captured(4).toDouble(&isOk);
7016  if (!isOk)
7017  {
7019  "::extractChanSkyFrqReading(): station " + stationName_ +
7020  ": cannot get video frequency; input: \"" + asciifyString(str) + "\"");
7021  return isOk;
7022  };
7023 
7024  QString loId(""), cId("");
7025  char sbIds[2] = {'l', 'u'};
7026 
7027  if (loFrq < 4000.0)
7028  loId = "b";
7029  else
7030  loId = "a";
7031 
7032  //2016.236.17:21:21.92&setupsx/"channel sky freq lo freq video
7033  //2016.236.17:21:21.92&setupsx/" 01 8210.99 8080.00 130.99
7034  //2016.236.17:21:21.92&setupsx/" 02 8220.99 8080.00 140.99
7035  //...
7036  //2016.236.17:21:21.92&setupsx/" 14 2292.99 2020.00 272.99
7037 
7038  for (int i=0; i<2; i++)
7039  {
7040  cId = QString("").sprintf("%02d%c", cIdx, sbIds[i]);
7041 
7042  if (cs.bbcFreqByIdx().contains(cIdx) &&
7043  cs.bbcFreqByIdx()[cIdx] != videoFrq &&
7044  tFirst < t)
7046  "::extractChanSkyFrqReading(): station " + stationName_ +
7047  ": video frequency has changed for IF #" + bbcId + ": " +
7048  QString("").sprintf("%.2f => %.2f", cs.bbcFreqByIdx()[cIdx], videoFrq) +
7049  "; input: \"" + asciifyString(str) + "\"");
7050 
7051  cs.bbcFreqByIdx()[cIdx] = videoFrq;
7052  cs.loIdByIdx()[cIdx] = loId;
7053  cs.loIdByCid()[cId] = loId;
7054  cs.loFreqById()[loId] = loFrq;
7055  cs.ifSideBandById()[cId] = (i==0?CSB_LSB:CSB_USB);
7056 
7057  if (1.0e-2 < fabs(loFrq + videoFrq - skyFrq)) // check set up:
7059  "::extractChanSkyFrqReading(): station " + stationName_ +
7060  ": got unexpected frequency setup; input: \"" + asciifyString(str) + "\"");
7061  };
7062  //
7063  // just assumption:
7064  cs.loSideBandById()[loId] = CSB_USB;
7065 
7066  if (cs.getHwType() == SgChannelSetup::HT_UNDEF)
7068  else if (cs.getHwType() != SgChannelSetup::HT_NN)
7069  {
7071  "::extractChanSkyFrqReading(): station " + stationName_ +
7072  ": got unexpected \"setup\" record (expected type #" + QString("").setNum(cs.getHwType()) +
7073  "); input: \"" + asciifyString(str) + "\"");
7075  };
7076 
7077  return true;
7078 };
7079 
7080 
7081 
7082 //
7083 bool SgStnLogCollector::extractVciReading(const QString& str, const QRegularExpressionMatch& match,
7084  SgMJD& t, const SgMJD& nearTheEnd, SgChannelSetup& cs, const SgMJD& tFirst)
7085 {
7086 //QString targetStr(str.mid(re.indexIn(str) + re.cap(1).size() +
7087 // re.cap(2).size() + 1));
7088  QString targetStr(str.mid(match.capturedEnd(2) + 1));
7089 
7090  if (!extractEpoch(str, t))
7091  return false;
7092 
7093  if (nearTheEnd <= t)
7094  return false;
7095 
7096  bool isOk;
7097  int cIdx;
7098  QString bbcId(match.captured(2));
7099  cIdx = bbcId.toInt(&isOk);
7100  if (!isOk)
7101  {
7103  "::extractVciReading(): station " + stationName_ +
7104  ": cannot convert \"" + bbcId + "\" to int; input: \"" + asciifyString(str) + "\"");
7105  return false;
7106  };
7107  //2016.236.17:21:21.92&setupsx/vci01=130.99,4r
7108  //2016.236.17:21:21.92&setupsx/vci02=140.99,4r
7109  QStringList lst=targetStr.split(",");
7110  if (2 <= lst.size())
7111  {
7112  double d;
7113  // video freq:
7114  d = lst.at(0).toDouble(&isOk);
7115  if (!isOk)
7116  {
7118  "::extractVciReading(): station " + stationName_ + ": cannot convert \"" + lst.at(0) +
7119  "\" to double; input: \"" + asciifyString(str) + "\"");
7120  return false;
7121  };
7122  // IFD ID:
7123  if (!cs.bbcFreqByIdx().contains(cIdx))
7124  cs.bbcFreqByIdx()[cIdx] = d;
7125  else if (cs.bbcFreqByIdx()[cIdx] != d &&
7126  tFirst < t)
7127  {
7129  "::extractVciReading(): station " + stationName_ +
7130  ": video frequency has changed for IF #" + bbcId + ": " +
7131  QString("").sprintf("%.2f => %.2f", cs.bbcFreqByIdx()[cIdx], d) +
7132  "; input: \"" + asciifyString(str) + "\"");
7133  cs.bbcFreqByIdx()[cIdx] = d;
7134  };
7135  // bandwidth:
7136  QString ss(lst.at(1));
7137  if (1 < ss.size())
7138  {
7139  QString pc(ss.at(ss.size() - 1));
7140  if (pc == "r")
7141  {
7142  cs.loPolarizationById()["a"] = CP_RightCP;
7143  cs.loPolarizationById()["b"] = CP_RightCP;
7144  }
7145  else if (pc == "l")
7146  {
7147  cs.loPolarizationById()["a"] = CP_LeftCP;
7148  cs.loPolarizationById()["b"] = CP_LeftCP;
7149  }
7150  else
7151  {
7152  cs.loPolarizationById()["a"] = CP_UNDEF;
7153  cs.loPolarizationById()["b"] = CP_UNDEF;
7154  };
7155 
7156  ss.chop(1);
7157  d = ss.toDouble(&isOk);
7158  if (!isOk)
7159  {
7161  "::extractVciReading(): station " + stationName_ + ": cannot convert \"" + lst.at(2) +
7162  "\" to double; input: \"" + asciifyString(str) + "\"");
7163  return false;
7164  };
7165  cs.bbcBandwidthByIdx()[cIdx] = d;
7166  };
7167 
7168  if (!cs.loIdByIdx().contains(cIdx))
7169  {
7170  cs.loIdByIdx()[cIdx] = "b";
7172  "::extractVciReading(): station " + stationName_ + ": found unused channel #" +
7173  QString("").sprintf("%02d", cIdx) +
7174  ", attached it to the LO \"b\"; input: \"" + asciifyString(str) + "\"");
7175  };
7176 
7177  //
7178  if (cs.getHwType() == SgChannelSetup::HT_UNDEF)
7180  else if (cs.getHwType() != SgChannelSetup::HT_NN)
7181  {
7183  "::extractVciReading(): station " + stationName_ +
7184  ": got unexpected \"vci\" record; input: \"" + asciifyString(str) + "\"");
7186  };
7187  }
7188  else
7189  {
7191  "::extractVciReading(): station " + stationName_ +
7192  ": the number of data less than 2; input: \"" + asciifyString(str) + "\"");
7193  return false;
7194  };
7195  return true;
7196 };
7197 
7198 
7199 
7200 //
7201 bool SgStnLogCollector::extractTsysReading(const QString& str, const QRegularExpression& reTsys,
7202  SgMJD& t, QMap<QString, float>& tSys, const SgMJD& tAtTheBegin)
7203 {
7204  bool isOk=false;
7205  float f;
7206  QRegularExpression reNoData("\\$+");
7207  QRegularExpression reNotASensor("i([0-9A-Za-z])+");
7208  QRegularExpression reDualSideBand("([0-9A-Za-z])+d");
7209 
7210 
7211  if (!extractEpoch(str, t))
7212  return false;
7213  if (t < tAtTheBegin)
7214  return false;
7215  //
7216  QRegularExpressionMatch match;
7217  QString tsysStr(str.mid(reTsys.match(str).capturedEnd(1)));
7218 
7219  if (!tsysStr.size())
7220  {
7222  "::extractTsysReading(): station " + stationName_ +
7223  ": cannot extract tsys data from \"" + asciifyString(str) + "\"");
7224 // ": cannot extract tsys data from \"" + str + "\"");
7225  return isOk;
7226  };
7227 
7228  QStringList lst=tsysStr.split(",");
7229  if (lst.size()%2)
7231  "::extractTsysReading(): station " + stationName_ +
7232  ": got odd number of tsys readings: \"" + asciifyString(str) + "\"");
7233 // ": got odd number of tsys readings: \"" + str + "\"");
7234 
7235  int numOfRecs=lst.size()/2;
7236  for (int i=0; i<numOfRecs; i++)
7237  {
7238  const QString &strIdx=lst.at(2*i);
7239  const QString &strVal=lst.at(2*i + 1);
7240  QString chanId(strIdx);
7241  if (strIdx.size())
7242  {
7243  if (strVal.size())
7244  {
7245  // skip the averages:
7246  if (!reNotASensor.match(strIdx).hasMatch())
7247  {
7248  if (reNoData.match(strVal).hasMatch())
7249  {
7250  f = -1.0;
7251  isOk = true;
7252  }
7253  else
7254  f = strVal.toFloat(&isOk);
7255  if (isOk)
7256  {
7257  QString sensorKey("");
7258  // special case for sensors with "dual" sideband:
7259  if ((match=reDualSideBand.match(strIdx)).hasMatch())
7260  {
7261  QString sss(match.captured(1));
7262  sensorKey = setupTpSensor(sss + "u", "extractTsysReading()", str);
7263  if (sensorKey.size())
7264  {
7265  tSys.insert(sensorKey, f);
7266  if (!logReadings_.channelSetup().origSensorIdById().contains(strIdx) ||
7267  (logReadings_.channelSetup().origSensorIdById().contains(strIdx) &&
7268  logReadings_.channelSetup().origSensorIdById().value(strIdx).size()<2))
7269  logReadings_.channelSetup().origSensorIdById()[strIdx].append(sss + "u");
7270  };
7271  sensorKey = setupTpSensor(sss + "l", "extractTsysReading()", str);
7272  if (sensorKey.size())
7273  {
7274  tSys.insert(sensorKey, f);
7275  if (!logReadings_.channelSetup().origSensorIdById().contains(strIdx) ||
7276  (logReadings_.channelSetup().origSensorIdById().contains(strIdx) &&
7277  logReadings_.channelSetup().origSensorIdById().value(strIdx).size()<2))
7278  logReadings_.channelSetup().origSensorIdById()[strIdx].append(sss + "l");
7279  };
7280  }
7281  else // regular sensors:
7282  {
7283  sensorKey = setupTpSensor(strIdx, "extractTsysReading()", str);
7284  if (sensorKey.size())
7285  tSys.insert(sensorKey, f);
7286  };
7287  };
7288  };
7289  }
7290  else
7292  "::extractTsysReading(): station " + stationName_ + ": tsysVal #" + QString("").setNum(i) +
7293  " is empty of tsys readings: \"" + asciifyString(str) + "\"");
7294 // " is empty of tsys readings: \"" + str + "\"");
7295  }
7296  else
7298  "::extractTsysReading(): station " + stationName_ + ": chanKey #" + QString("").setNum(i) +
7299  " is empty of tsys readings: \"" + asciifyString(str) + "\"");
7300 // " is empty of tsys readings: \"" + str + "\"");
7301  };
7302  return isOk;
7303 };
7304 
7305 
7306 
7307 //
7308 bool SgStnLogCollector::extractTsysVgosReading(const QString& str, const QRegularExpression& reTsys,
7309  SgMJD& t, QMap<QString, float>& tSys, const SgMJD& tAtTheBegin)
7310 {
7311  bool isOk=false;
7312  float f;
7313  QRegularExpression reNoData("\\$+");
7314  QRegularExpression reNoChan("(AV|SM)(\\w)(\\d)");
7315 
7316  if (!extractEpoch(str, t))
7317  return false;
7318  if (t < tAtTheBegin)
7319  return false;
7320 
7321  QString tsysStr(str.mid(reTsys.match(str).capturedEnd(1)));
7322 
7323  if (!tsysStr.size())
7324  {
7326  "::extractTsysVgosReading(): station " + stationName_ +
7327  ": cannot extract tsys data from \"" + asciifyString(str) + "\"");
7328 // ": cannot extract tsys data from \"" + str + "\"");
7329  return isOk;
7330  };
7331 
7332  QStringList lst=tsysStr.split(",");
7333  if (lst.size()%2)
7335  "::extractTsysVgosReading(): station " + stationName_ +
7336  ": got odd number of tsys readings: \"" + asciifyString(str) + "\"");
7337 // ": got odd number of tsys readings: \"" + str + "\"");
7338 
7339 //2020.021.18:15:39.17#rdtcb#tsys/ 00b0, 53.5, 01b0, 43.6, 02b0, 40.5, 03b0, 41.6, 04b0, 42.7, 05b0, 44.6, 06b0, 44.7, 07b0, 45.6
7340 //2020.021.18:15:39.17#rdtcb#tsys/ 08b0, 46.8, 09b0, 47.7, 10b0, 47.4, 11b0, 50.9, 12b0, 47.7, 13b0, 43.1, 14b0, 46.6, 15b0, 50.2
7341 //2020.021.18:15:39.17#rdtcb#tsys/ AVb0, 45.8, SMb0, 45.7
7342 //2020.021.18:15:39.17#rdtcb#tsys/ 00b1, 53.2, 01b1, 49.8, 02b1, 49.1, 03b1, 49.4, 04b1, 49.5, 05b1, 52.1, 06b1, 53.8, 07b1, 54.7
7343 //2020.021.18:15:39.17#rdtcb#tsys/ 08b1, 57.8, 09b1, 50.6, 10b1, 52.5, 11b1, 49.5, 12b1, 52.3, 13b1, 48.5, 14b1, 48.3, 15b1, 49.5
7344 //2020.021.18:15:39.17#rdtcb#tsys/ AVb1, 51.2, SMb1, 51.2
7345 
7346  int numOfRecs=lst.size()/2;
7347  for (int i=0; i<numOfRecs; i++)
7348  {
7349  const QString &strIdx=lst.at(2*i);
7350  const QString &strVal=lst.at(2*i + 1);
7351  if (strIdx.size())
7352  {
7353  if (strVal.size())
7354  {
7355  // skip the averages:
7356  if (!reNoChan.match(strIdx).hasMatch() && !reNoData.match(strIdx).hasMatch())
7357  {
7358  if (reNoData.match(strVal).hasMatch())
7359  {
7360  f = -1.0;
7361  isOk = true;
7362  }
7363  else
7364  f = strVal.toFloat(&isOk);
7365  //
7366  if (isOk)
7367  {
7368  QString sensorKey=setupTpSensor(strIdx, "extractTsysVgosReading()", str);
7369  if (sensorKey.size())
7370  tSys.insert(sensorKey, f);
7371  };
7372  };
7373  }
7374  else
7376  "::extractTsysVgosReading(): station " + stationName_ + ": tsysVal #" + QString("").setNum(i) +
7377  " is empty of tsys readings: \"" + asciifyString(str) + "\"");
7378  }
7379  else
7381  "::extractTsysVgosReading(): station " + stationName_ + ": chanKey #" + QString("").setNum(i) +
7382  " is empty of tsys readings: \"" + asciifyString(str) + "\"");
7383  };
7384 
7388  {
7390  "::extractTsysVgosReading(): station " + stationName_ +
7391  ": got an unexpected \"bbc\" record; input: \"" + asciifyString(str) + "\"");
7393  };
7394 
7395  return isOk;
7396 };
7397 
7398 
7399 
7400 //
7401 QString SgStnLogCollector::setupTpSensor(const QString& sensorTag, const QString& callerName,
7402  const QString& inputString)
7403 {
7404  const double rdbeChannelBandwidth=32.0;
7405 // DBBC3:
7406 //2020.201.05:14:29.04#onoff#VAL casa 290.1 70.9 001l 1 l 3464.40 1.1078 65.39 2466.4 64.613 1.02
7407 // detector ID: "001l -- 064l, 001u -- 064u:
7408 //
7409 // RDBE:
7410 //2021.028.15:55:34.15#rdtcc#tpcont/ 00c0, 23583, 22926, 01c0, 36283, 35218, 02c0, 41679, 40468, 03c0, 41843, 40647, 04c0, 44458, 43162
7411 // detector ID: "00c0 -- 15c0, 00c1 -- 15c1, ..."
7412 //
7413 //2021.004.16:11:41.88#onoff# source Az El De I P Center Comp Tsys SEFD Tcal(j) Tcal(r)
7414 //2021.004.16:11:41.88#onoff#VAL virgoa 177.3 80.1 1l 1 r 8208.99 0.9961 109.6 2523.7 126.611 0.03
7415 
7417  double loFreq=-9999.9, ifFreq=-9999.9, ifBw=-9.9;
7421  QString chanId(sensorTag.simplified().rightJustified(6, ' '));
7422  QString loId;
7423  QChar cSideBand('-');
7424  QString sFreqSfx(""), sPlrzSfx("x"), sLoSBndSfx("x"), sIfSBndSfx("x");
7425  bool isOk;
7426  int sensorIdx;
7427 
7429  {
7430  QString cPlrz=sensorTag.at(sensorTag.size() - 1);
7431  QString cBand=sensorTag.at(sensorTag.size() - 2);
7432  QString sIdx =sensorTag.left(sensorTag.size() - 2);
7433  loId = QString(cBand) + cPlrz;
7434  //
7435  int offset;
7436  //
7437  if (cBand == 'a')
7438  offset = 0;
7439  else if (cBand == 'b')
7440  offset = 16;
7441  else if (cBand == 'c')
7442  offset = 32;
7443  else if (cBand == 'd')
7444  offset = 48;
7445  else if (cBand == 'e')
7446  offset = 64;
7447  else if (cBand == 'f')
7448  offset = 80;
7449  else if (cBand == 'g')
7450  offset = 96;
7451  else if (cBand == 'h')
7452  offset =112;
7453  else
7454  {
7455  offset = 0;
7457  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7458  ": get unexpected LO key \"" + cBand +
7459  "\"; the tag is \"" + asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7460  return "";
7461  };
7462  sensorIdx = 0;
7463  sensorIdx = sIdx.toInt(&isOk);
7464  if (isOk)
7465  sensorIdx += offset;
7466  else
7467  {
7469  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7470  ": cannot convert \"" + sIdx + "\" to int; the tag is \"" +
7471  asciifyString(sensorTag) + "\", VGOS; input: \"" + inputString + "\"");
7472  return "";
7473  };
7474  //
7475  if (cPlrz == '0')
7476  loPlrz = CP_HorizontalLP;
7477  else if (cPlrz == '1')
7478  loPlrz = CP_VerticalLP;
7479  else
7480  {
7481  loPlrz = CP_UNDEF;
7483  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7484  ": cannot figure out RDBE polarization from \"" + cPlrz + "\"; the tag is: \"" +
7485  asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7486  };
7487  // there is no channel setup:
7488  if (stationName_ == "ISHIOKA ")
7489  ifFreq = 512.0 + rdbeChannelBandwidth/2.0 + rdbeChannelBandwidth*(sensorIdx%16);
7490  else
7491  ifFreq = 512.0 + rdbeChannelBandwidth/2.0 + rdbeChannelBandwidth*(15 - sensorIdx%16);
7492  //
7493  ifSBnd = CSB_USB;
7494  //
7495  ifBw = rdbeChannelBandwidth;
7496  }
7497  else //
7498  {
7499  QString sIdx=sensorTag.left(sensorTag.size() - 1);
7500  cSideBand = sensorTag.at(sensorTag.size() - 1);
7501  //
7504  {
7505  sensorIdx = sIdx.toInt(&isOk);
7506  if (!isOk)
7507  sensorIdx = sIdx.toInt(&isOk, 16); //?
7508  }
7509  else
7510  sensorIdx = sIdx.toInt(&isOk, 16);
7511  if (!isOk)
7512  {
7514  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7515  ": cannot convert \"" + sIdx + "\" to int; the tag is \"" +
7516  sensorTag + "\", other; input: \"" + inputString + "\"");
7517  return "";
7518  };
7519  // LO id:
7520  if (cs.loIdByIdx().contains(sensorIdx))
7521  loId = cs.loIdByIdx()[sensorIdx];
7522  else
7523  {
7525  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7526  ": cannot find LO id for the sensorIdx " + QString("").setNum(sensorIdx) +
7527  "; the tag is \"" + sensorTag + "\"; input: \"" + inputString + "\"");
7528  return "";
7529  };
7530  //
7531  if (cs.loPolarizationById().contains(loId))
7532  loPlrz = cs.loPolarizationById().value(loId);
7533  else
7534  {
7536  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7537  ": LO polarization for LO \"" + loId + "\" is not defined; the tag is: \"" +
7538  asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7539  return "";
7540  };
7541  //
7542  // if frequency:
7543  if (cs.bbcFreqByIdx().contains(sensorIdx))
7544  ifFreq = cs.bbcFreqByIdx()[sensorIdx];
7545  else
7546  {
7548  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7549  ": cannot find BBC frequency for the sensorIdx " + QString("").setNum(sensorIdx) +
7550  "; the tag is \"" + sensorTag + "\"; input: \"" + inputString + "\"");
7551  return "";
7552  };
7553  // if bandwidth:
7554  if (cs.bbcBandwidthByIdx().contains(sensorIdx))
7555  ifBw = cs.bbcBandwidthByIdx()[sensorIdx];
7556  else
7557  {
7559  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7560  ": cannot find BBC bandwidth for the sensorIdx " + QString("").setNum(sensorIdx) +
7561  "; the tag is \"" + sensorTag + "\"; input: \"" + inputString + "\"");
7562  return "";
7563  };
7564  // if sideband:
7565  if (cSideBand.toLower() == 'u')
7566  ifSBnd = CSB_USB;
7567  else if (cSideBand.toLower() == 'l')
7568  ifSBnd = CSB_LSB;
7569  else if (cSideBand.toLower() == 'd')
7570  ifSBnd = CSB_DUAL;
7571  else
7572  {
7574  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7575  ": cannot guess sideband; the tag is \"" + sensorTag + "\"; input: \"" + inputString + "\"");
7576  return "";
7577  };
7578  };
7579  //
7580  //
7581  //
7582  // collect the current LO setup:
7583  if (cs.loFreqById().contains(loId))
7584  loFreq = cs.loFreqById().value(loId);
7585  else
7587  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7588  ": LO frequency for LO \"" + loId + "\" is not defined; the tag is: \"" +
7589  asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7590 
7591  if (cs.loSideBandById().contains(loId))
7592  loSBnd = cs.loSideBandById().value(loId);
7593  else
7595  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7596  ": LO sideband for LO \"" + loId + "\" is not defined; the tag is: \"" +
7597  asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7598  //
7599  //
7600  //
7601  //
7602  // generate the strings:
7603  double skyFrq;
7604  skyFrq = SgChannelSetup::calcSkyFreq(loFreq, ifFreq, ifBw, loSBnd, ifSBnd);
7605  sFreqSfx.sprintf("%08.1f-%08.1f:%05.1f", loFreq, ifFreq, ifBw);
7606  sPlrzSfx = polarization2Str(loPlrz);
7607  sLoSBndSfx = sideBand2Str(loSBnd);
7608  sIfSBndSfx = sideBand2Str(ifSBnd);
7609  //
7610  // ok.
7611 
7612  // set up channel key (for sorting):
7613  QString sensorKey("");
7614  sensorKey.sprintf("%08.1f-", skyFrq);
7615 //sensorKey = sFreqSfx + '-' + sPlrzSfx + '-' + sLoSBndSfx + '-' + sIfSBndSfx + '-' + loId + '-' + chanId;
7616  sensorKey += sPlrzSfx + '-' + loId + '-' + sLoSBndSfx + '-' + sIfSBndSfx + '-' + chanId + '-' + sFreqSfx;
7617 
7618  //
7619  // set up time-varying info:
7620  //
7621  // LO id:
7622  if (loId.size())
7623  {
7624  if (cs.loIdByTpSensorKey().contains(sensorKey))
7625  {
7626  // check:
7627  if (cs.loIdByTpSensorKey()[sensorKey] != loId)
7628  {
7630  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7631  ": got new LO ID \"" + loId + "\" for sensor key \"" + sensorKey +
7632  "\", the previous one is \"" + cs.loIdByTpSensorKey()[sensorKey] +
7633  "\"; the tag is \"" + asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7634  cs.loIdByTpSensorKey()[sensorKey] = loId;
7635  };
7636  }
7637  else
7638  cs.loIdByTpSensorKey()[sensorKey] = loId;
7639  };
7640  // LO freq:
7641  if (-1.0 < loFreq)
7642  {
7643  if (cs.loFreqByTpSensorKey().contains(sensorKey))
7644  {
7645  // check:
7646  if (cs.loFreqByTpSensorKey()[sensorKey] != loFreq)
7647  {
7649  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7650  ": got new LO frequency " +
7651  QString("").sprintf("%8.1f", loFreq) + " for sensor \"" +
7652  chanId + "\", with the sensor key \"" + sensorKey +
7653  "\", the previous one is " +
7654  QString("").sprintf("%8.1f", cs.loFreqByTpSensorKey()[sensorKey]) +
7655  "; the tag is \"" + asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7656  cs.loFreqByTpSensorKey()[sensorKey] = loFreq;
7657  };
7658  }
7659  else
7660  cs.loFreqByTpSensorKey()[sensorKey] = loFreq;
7661  };
7662  //
7663  // LO sideband:
7664  if (cs.loSideBandByTpSensorKey().contains(sensorKey))
7665  {
7666  // check:
7667  if (cs.loSideBandByTpSensorKey()[sensorKey] != loSBnd)
7668  {
7670  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7671  ": got new LO sideband " +
7672  sideBand2Str(loSBnd) + " for sensor \"" +
7673  chanId + "\", with the sensor key \"" + sensorKey +
7674  "\", the previous one is " +
7675  sideBand2Str(cs.loSideBandByTpSensorKey()[sensorKey]) +
7676  "; the tag is \"" + asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7677  cs.loSideBandByTpSensorKey()[sensorKey] = loSBnd;
7678  };
7679  }
7680  else
7681  cs.loSideBandByTpSensorKey()[sensorKey] = loSBnd;
7682  //
7683  // LO polarization:
7684  if (cs.loPolarizationByTpSensorKey().contains(sensorKey))
7685  {
7686  // check:
7687  if (cs.loPolarizationByTpSensorKey()[sensorKey] != loPlrz)
7688  {
7690  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7691  ": got new LO polarization " +
7692  polarization2Str(loPlrz) + " for sensor \"" +
7693  chanId + "\", with the sensor key \"" + sensorKey +
7694  "\", the previous one is " +
7696  "; the tag is \"" + asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7697  cs.loPolarizationByTpSensorKey()[sensorKey] = loPlrz;
7698  };
7699  }
7700  else
7701  cs.loPolarizationByTpSensorKey()[sensorKey] = loPlrz;
7702  //
7703  // IF frequency:
7704  if (-1.0 < ifFreq)
7705  {
7706  if (cs.ifFreqByTpSensorKey().contains(sensorKey))
7707  {
7708  // check:
7709  if (cs.ifFreqByTpSensorKey()[sensorKey] != ifFreq)
7710  {
7712  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7713  ": got new IF frequency " +
7714  QString("").sprintf("%8.1f", ifFreq) + " for sensor \"" +
7715  chanId + "\", with the sensor key \"" + sensorKey +
7716  "\", the previous one is " +
7717  QString("").sprintf("%8.1f", cs.ifFreqByTpSensorKey()[sensorKey]) +
7718  "; the tag is \"" + asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7719  cs.ifFreqByTpSensorKey()[sensorKey] = ifFreq;
7720  };
7721  }
7722  else
7723  cs.ifFreqByTpSensorKey()[sensorKey] = ifFreq;
7724  };
7725  // IF bandwidth:
7726  if (-1.0 < ifBw)
7727  {
7728  if (cs.ifBandwidthByTpSensorKey().contains(sensorKey))
7729  {
7730  // check:
7731  if (cs.ifBandwidthByTpSensorKey()[sensorKey] != ifBw)
7732  {
7734  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7735  ": got new IF bandwidth " +
7736  QString("").sprintf("%8.1f", ifBw) + " for sensor \"" +
7737  chanId + "\", with the sensor key \"" + sensorKey +
7738  "\", the previous one is " +
7739  QString("").sprintf("%8.1f", cs.ifBandwidthByTpSensorKey()[sensorKey]) +
7740  "; the tag is \"" + asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7741  cs.ifBandwidthByTpSensorKey()[sensorKey] = ifBw;
7742  };
7743  }
7744  else
7745  cs.ifBandwidthByTpSensorKey()[sensorKey] = ifBw;
7746  };
7747  //
7748  // IF id:
7749  if (cs.ifIdByTpSensorKey().contains(sensorKey))
7750  {
7751  // check:
7752  if (cs.ifIdByTpSensorKey()[sensorKey] != chanId)
7753  {
7755  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7756  ": got new ID, " +
7757  chanId + ", for the channel key \"" + sensorKey +
7758  "\", the previous one is " + cs.ifIdByTpSensorKey()[sensorKey] +
7759  "; the tag is \"" + asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7760  cs.ifIdByTpSensorKey()[sensorKey] = chanId;
7761  };
7762  }
7763  else
7764  cs.ifIdByTpSensorKey()[sensorKey] = chanId;
7765  //
7766  //
7767  // done with time varying setup
7768  //
7769  //
7770  // IF index:
7771  if (cs.ifIdxById().contains(chanId))
7772  {
7773  // check:
7774  if (cs.ifIdxById()[chanId] != sensorIdx)
7775  {
7777  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7778  ": got new value, " +
7779  QString("").setNum(sensorIdx) + ", for the channel id \"" + chanId +
7780  "\", the previous one is " +
7781  QString("").setNum(cs.ifIdxById()[chanId]) +
7782  "; the tag is \"" + asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7783  cs.ifIdxById()[chanId] = sensorIdx;
7784  };
7785  }
7786  else
7787  cs.ifIdxById()[chanId] = sensorIdx;
7788  //
7789  //
7790  // LO id:
7791 // if (!cs.loIdByIdx().contains(sensorIdx))
7792 // cs.loIdByIdx()[sensorIdx] = loId;
7793  //
7794  //
7795  if (ifSBnd != CSB_UNDEF)
7796  {
7797  if (cs.ifSideBandById().contains(chanId))
7798  {
7799  // check:
7800  if (cs.ifSideBandById()[chanId] != ifSBnd)
7801  {
7803  "::setupTpSensor(): station " + stationName_ + ", caller " + callerName +
7804  ": got new sideband, " +
7805  sideBand2Str(ifSBnd) + ", for the channel id \"" + chanId +
7806  "\", the previous one is " +
7807  sideBand2Str(cs.ifSideBandById()[chanId]) +
7808  "; the tag is \"" + asciifyString(sensorTag) + "\"; input: \"" + inputString + "\"");
7809  cs.ifSideBandById()[chanId] = ifSBnd;
7810  };
7811  }
7812  else
7813  cs.ifSideBandById()[chanId] = ifSBnd;
7814  };
7815  //
7816 
7817  return sensorKey;
7818 };
7819 
7820 
7821 
7822 //
7823 bool SgStnLogCollector::extractTpcontVgosReading(const QString& str, const QRegularExpression& reTpcont,
7824  SgMJD& t, QMap<QString, QVector<int> >& tPcont, const SgMJD& tAtTheBegin)
7825 // SgMJD& t, QMap<char*, int*>& tPcont, const SgMJD& tAtTheBegin)
7826 {
7827  bool isOk=false;
7828  int nOn, nOf;
7829  QRegularExpression reNoData("\\$+");
7830  QVector<int> v(2);
7831 
7832  //
7833  if (!extractEpoch(str, t))
7834  return false;
7835  if (t < tAtTheBegin)
7836  return false;
7837 
7838  QString tpcontStr(str.mid(reTpcont.match(str).capturedEnd(1)));
7839 
7840  if (!tpcontStr.size())
7841  {
7843  "::extractTpcontVgosReading(): station " + stationName_ +
7844  ": cannot extract tpcont data from \"" + asciifyString(str) + "\"");
7845 // ": cannot extract tpcont data from \"" + str + "\"");
7846  return isOk;
7847  };
7848 
7849  QStringList lst=tpcontStr.split(",");
7850  if (lst.size()%3)
7852  "::extractTpcontVgosReading(): station " + stationName_ +
7853  ": got odd number of tpcont readings: \"" + asciifyString(str) + "\"");
7854 // ": got odd number of tpcont readings: \"" + str + "\"");
7855 
7856  //2020.021.18:00:00.17#rdtcd#tpcont/ 00d0, 12501, 12325, 01d0, 16054, 15765, 02d0, 20774, 20410, 03d0, 24388, 23985, 04d0, 27599, 27153
7857  //2020.021.18:00:00.17#rdtcd#tpcont/ 05d0, 28085, 27647, 06d0, 29475, 29027, 07d0, 30963, 30479, 08d0, 29392, 28953, 09d0, 30078, 29643
7858  //2020.021.18:00:00.17#rdtcd#tpcont/ 10d0, 37494, 36960, 11d0, 42335, 41705, 12d0, 46499, 45802, 13d0, 51354, 50535, 14d0, 49839, 48925
7859  //2020.021.18:00:00.17#rdtcd#tpcont/ 15d0, 43153, 42272
7860  //2020.021.18:00:00.17#rdtcd#tpcont/ 00d1, 11542, 11379, 01d1, 13078, 12877, 02d1, 16776, 16491, 03d1, 22232, 21871, 04d1, 27568, 27119
7861  //2020.021.18:00:00.17#rdtcd#tpcont/ 05d1, 26698, 26274, 06d1, 26024, 25611, 07d1, 27530, 27137, 08d1, 33180, 32491, 09d1, 32567, 32122
7862  //2020.021.18:00:00.17#rdtcd#tpcont/ 10d1, 42659, 42099, 11d1, 46937, 46283, 12d1, 50407, 49687, 13d1, 56087, 55247, 14d1, 56042, 55150
7863  //2020.021.18:00:00.17#rdtcd#tpcont/ 15d1, 47024, 46233
7864 
7865  int numOfRecs=lst.size()/3;
7866  for (int i=0; i<numOfRecs; i++)
7867  {
7868  const QString &strIdx=lst.at(3*i);
7869  const QString &strValOn=lst.at(3*i + 1);
7870  const QString &strValOf=lst.at(3*i + 2);
7871  //
7872  if (strIdx.size() && strValOn.size() && strValOf.size())
7873  {
7874  if (reNoData.match(strValOn).hasMatch())
7875  {
7876  nOn = -1;
7877  isOk = true;
7878  }
7879  else
7880  nOn = strValOn.toInt(&isOk);
7881 
7882  if (isOk && reNoData.match(strValOf).hasMatch())
7883  {
7884  nOf = -1;
7885  isOk = true;
7886  }
7887  else
7888  nOf = strValOf.toInt(&isOk);
7889  //
7890  if (isOk)
7891  {
7892  QString sensorKey=setupTpSensor(strIdx, "extractTpcontVgosReading()",
7893  asciifyString(str));
7894  //
7895  v[0] = nOn;
7896  v[1] = nOf;
7897  if (sensorKey.size())
7898  tPcont.insert(sensorKey, QVector<int>(v));
7899  };
7900  }
7901  else
7902  {
7903  if (strIdx.size() == 0)
7905  "::extractTpcontVgosReading(): station " + stationName_ + ": chanKey #" +
7906  QString("").setNum(i) + " is empty of tpcont readings: \"" + asciifyString(str) + "\"");
7907 // " is empty of tpcont readings: \"" + str + "\"");
7908  if (strValOn.size())
7910  "::extractTpcontVgosReading(): station " + stationName_ + ": tpcalon #" +
7911  QString("").setNum(i) + " is empty of tpcont readings: \"" + asciifyString(str) + "\"");
7912 // " is empty of tpcont readings: \"" + str + "\"");
7913  if (strValOf.size())
7915  "::extractTpcontVgosReading(): station " + stationName_ + ": tpcaloff #" +
7916  QString("").setNum(i) + " is empty of tpcont readings: \"" + asciifyString(str) + "\"");
7917 // " is empty of tpcont readings: \"" + str + "\"");
7918  };
7919  };
7920 
7924  {
7926  "::extractTpcontVgosReading(): station " + stationName_ +
7927  ": got an unexpected \"bbc\" record; input: \"" + asciifyString(str) + "\"");
7929  };
7930 
7931  return isOk;
7932 };
7933 
7934 
7935 
7936 //
7937 bool SgStnLogCollector::extractPcalVgosReading(const QString& str, const QRegularExpressionMatch& match,
7938  SgMJD& t, QMap<QString, float*>& pcal, SgChannelSetup& cs, const SgMJD& tAtTheBegin)
7939 {
7940  bool isOk=false;
7941  float dAmp, dPhs;
7942  QRegularExpression reNoData("\\$+");
7943 
7944  //
7945  if (!extractEpoch(str, t))
7946  return false;
7947  if (t < tAtTheBegin)
7948  return false;
7949 
7950 //QString pcalStr(str.mid(rePcal.match(str).capturedEnd(1)));
7951  QString pcalStr(str.mid(match.capturedEnd(1)));
7952 
7953  if (!pcalStr.size())
7954  {
7956  "::extractPcalVgosReading(): station " + stationName_ +
7957  ": cannot extract tpcont data from \"" + asciifyString(str) + "\"");
7958 // ": cannot extract tpcont data from \"" + str + "\"");
7959  return isOk;
7960  };
7961 
7962  QStringList lst=pcalStr.split(",");
7963  if (lst.size()%3)
7965  "::extractPcalVgosReading(): station " + stationName_ +
7966  ": got odd number of tpcont readings: \"" + asciifyString(str) + "\"");
7967 // ": got odd number of tpcont readings: \"" + str + "\"");
7968 
7969  //2020.195.11:30:01.17#rdtca#pcal/ 1a0000, 8.686, -98.7, 1a0005, 78.913, 116.7, 1a0010, 8.729, 147.9, 1a0015, 81.273, 4.1
7970  //2020.195.11:30:01.17#rdtca#pcal/ 1a0020, 9.421, 37.5, 1a0025, 88.580, -105.5, 1a0030, 10.177, -72.2, 1a0035, 97.212, 144.1
7971  //2020.195.11:30:01.17#rdtca#pcal/ 1a0040, 11.646, 176.3, 1a0045, 89.248, 33.1, 1a0050, 10.577, 65.5, 1a0055, 93.330, -79.2
7972  //2020.195.11:30:01.17#rdtca#pcal/ 1a0060, 10.255, -47.4, 1a0065, 93.203, 169.1, 1a0070, 10.437, -155.9, 1a0075, 89.414, 59.5
7973  //2020.195.11:30:01.17#rdtca#pcal/ 1a0080, 10.014, 92.8, 1a0085, 84.492, -47.7, 1a0090, 9.561, -14.2, 1a0095, 82.770, -155.3
7974  //2020.195.11:30:01.17#rdtca#pcal/ 1a0100, 8.782, -120.1, 1a0105, 79.763, 101.6, 1a0110, 8.836, 137.8, 1a0115, 77.939, -3.8
7975  //2020.195.11:30:01.17#rdtca#pcal/ 1a0120, 8.740, 32.5, 1a0125, 73.421, -105.2, 1a0130, 8.134, -68.7, 1a0135, 74.094, 150.8
7976  //2020.195.11:30:01.17#rdtca#pcal/ 1a0140, 7.557, -168.7, 1a0145, 69.966, 50.6, 1a0150, 7.977, 88.8, 1a0155, 72.224, -54.9
7977  //2020.195.11:30:01.17#rdtca#pcal/ 1a0160, 8.275, -19.4, 1a0165, 74.537, -158.0, 1a0170, 8.204, -123.8, 1a0175, 72.798, 88.5
7978  //2020.195.11:30:01.17#rdtca#pcal/ 1a0180, 8.256, 131.2, 1a0185, 73.794, -6.5, 1a0190, 7.957, 28.8, 1a0195, 74.957, -109.7
7979  //2020.195.11:30:01.17#rdtca#pcal/ 1a0200, 8.315, -75.6, 1a0205, 73.965, 144.7, 1a0210, 8.324, 179.7, 1a0215, 74.379, 38.9
7980 
7981  int numOfRecs=lst.size()/3;
7982  for (int i=0; i<numOfRecs; i++)
7983  {
7984  const QString &strIdx=lst.at(3*i).simplified();
7985  const QString &strValAm=lst.at(3*i + 1);
7986  const QString &strValPh=lst.at(3*i + 2);
7987  QString chanId(strIdx.simplified().rightJustified(8, ' '));
7988 
7989  //
7990  if (strIdx.size() && strValAm.size() && strValPh.size())
7991  {
7992  if (reNoData.match(strValAm).hasMatch())
7993  {
7994  dAmp = -1.0;
7995  isOk = true;
7996  }
7997  else
7998  dAmp = strValAm.toFloat(&isOk);
7999 
8000  if (isOk && reNoData.match(strValPh).hasMatch())
8001  {
8002  dPhs = -1.0;
8003  isOk = true;
8004  }
8005  else
8006  dPhs = strValPh.toFloat(&isOk);
8007  //
8008  if (isOk)
8009  {
8010  QChar cPlrz(strIdx.at(0));
8011  QChar cBand(strIdx.at(1));
8012  QString loId(cBand);
8013  QString sensorKey("");
8014  QString sFreqOffset("");
8015  QString sSBndSfx("");
8017  double loFreq;
8018  double freqOffset;
8019  double pcalWidth;
8020  bool hasPcalOffset;
8021  loFreq = freqOffset = pcalWidth = -1.0;
8022  hasPcalOffset = false;
8023  loId += cPlrz;
8024 
8025  //
8026  // get LO's freq:
8027  if (cs.loFreqById().contains(loId))
8028  loFreq = cs.loFreqById().value(loId);
8029  else
8031  "::extractPcalVgosReading(): station " + stationName_ + ": " +
8032  "frequency for LO \"" + loId + "\" is not defined; the tag is: \"" + loId +
8033  "\"; input: \"" + asciifyString(str) + "\"");
8034  //
8035  // get LO's sideband:
8036  if (cs.loSideBandById().contains(loId))
8037  sbd = cs.loSideBandById().value(loId);
8038  else
8040  "::extractPcalVgosReading(): station " + stationName_ +
8041  ": LO sideband for LO \"" + loId + "\" is not defined; the tag is: \"" +
8042  sensorKey + "\"; input: \"" + asciifyString(str) + "\"");
8043  //
8044  // get pcal width from LO setup:
8045  if (cs.loPcWidthById().contains(loId))
8046  pcalWidth = cs.loPcWidthById().value(loId);
8047  else
8049  "::extractPcalVgosReading(): station " + stationName_ +
8050  ": pcal width for LO \"" + loId + "\" is not defined; the tag is: \"" +
8051  chanId + "\"; input: \"" + asciifyString(str) + "\"");
8052  //
8053  // get pcal offset:
8054  if (cs.pcalOffsetByLoId().contains(loId))
8055  {
8056  freqOffset = cs.pcalOffsetByLoId().value(loId);
8057  hasPcalOffset = true;
8058  }
8059  else if (cs.pcalOffsetByLoId().contains(QString(cBand)))
8060  {
8061  freqOffset = cs.pcalOffsetByLoId().value(QString(cBand));
8062  hasPcalOffset = true;
8063  }
8064  else if (cs.pcalOffsetByLoId().contains("*"))
8065  {
8066  freqOffset = cs.pcalOffsetByLoId().value("*");
8067  hasPcalOffset = true;
8068  }
8069  else
8071  "::extractPcalVgosReading(): station " + stationName_ +
8072  ": pcal offset for LO \"" + loId + "\" is not defined; the tag is: \"" +
8073  chanId + "\"; input: \"" + asciifyString(str) + "\"");
8074  //
8075  //
8076  // setup a sensor key:
8077  sFreqOffset.sprintf("%04.1f:%04.1f", freqOffset, pcalWidth);
8078  sensorKey.sprintf("%08.1f-", loFreq);
8079  sSBndSfx = sideBand2Str(sbd);
8080  sensorKey += cPlrz + '-' + loId + '-' + sSBndSfx + '-' + chanId + '-' + sFreqOffset;
8081  //
8082  //
8083  //
8084  //
8085  if (logReadings_.channelSetup().pcalIdByKey().contains(sensorKey))
8086  {
8087  // check:
8088  if (logReadings_.channelSetup().pcalIdByKey()[sensorKey] != chanId)
8089  {
8091  "::extractPcalVgosReading(): station " + stationName_ + ": get new id, " +
8092  chanId + ", for the channel key \"" + sensorKey +
8093  "\", the previous one is " +
8094  logReadings_.channelSetup().pcalIdByKey()[sensorKey] +
8095  "; input: \"" + asciifyString(str) + "\"");
8096  logReadings_.channelSetup().pcalIdByKey()[sensorKey] = chanId;
8097  };
8098  }
8099  else
8100  logReadings_.channelSetup().pcalIdByKey()[sensorKey] = chanId;
8101  //
8102  //
8103  //
8104  // LO freq:
8105  if (logReadings_.channelSetup().pcalLoFreqByKey().contains(sensorKey))
8106  {
8107  // check:
8108  if (logReadings_.channelSetup().pcalLoFreqByKey()[sensorKey] != loFreq)
8109  {
8111  "::extractPcalVgosReading(): station " + stationName_ + ": LO frequency changed from " +
8112  QString("").sprintf("%.1f to %.1f",
8113  logReadings_.channelSetup().pcalLoFreqByKey()[sensorKey], loFreq) +
8114  " for the pcal key \"" + sensorKey + "; input: \"" + asciifyString(str) + "\"");
8115  logReadings_.channelSetup().pcalLoFreqByKey()[sensorKey] = loFreq;
8116  };
8117  }
8118  else if (0.0 < loFreq) // if it is defined:
8119  logReadings_.channelSetup().pcalLoFreqByKey()[sensorKey] = loFreq;
8120  //
8121  // LO sideband:
8122  if (logReadings_.channelSetup().pcalSideBandByKey().contains(sensorKey))
8123  {
8124  // check:
8125  if (logReadings_.channelSetup().pcalSideBandByKey()[sensorKey] != sbd)
8126  {
8128  "::extractPcalVgosReading(): station " + stationName_ + ": LO sideband changed from " +
8129  sideBand2Str(logReadings_.channelSetup().pcalSideBandByKey()[sensorKey]) + " to " +
8130  sideBand2Str(sbd) +
8131  " for the pcal key \"" + sensorKey + "; input: \"" + asciifyString(str) + "\"");
8132  logReadings_.channelSetup().pcalSideBandByKey()[sensorKey] = sbd;
8133  };
8134  }
8135  else if (sbd != CSB_UNDEF)
8136  logReadings_.channelSetup().pcalSideBandByKey()[sensorKey] = sbd;
8137  //
8138  // polarization:
8139  if (cPlrz == '0')
8141  else if (cPlrz == '1')
8143  else
8144  {
8147  "::extractPcalVgosReading(): station " + stationName_ +
8148  ": cannot figure out polarization from \"" + strIdx +
8149  "\"; input: \"" + asciifyString(str) + "\"");
8150  };
8151  //
8152  // frequency offset:
8153  if (logReadings_.channelSetup().pcalOffsetByKey().contains(sensorKey))
8154  {
8155  // check:
8156  if (logReadings_.channelSetup().pcalOffsetByKey()[sensorKey] != freqOffset)
8157  {
8159  "::extractPcalVgosReading(): station " + stationName_ + ": frequency offset changed from " +
8160  QString("").sprintf("%.1f to %.1f",
8161  logReadings_.channelSetup().pcalOffsetByKey()[sensorKey], freqOffset) +
8162  " for the pcal key \"" + sensorKey + "; input: \"" + asciifyString(str) + "\"");
8163  logReadings_.channelSetup().pcalOffsetByKey()[sensorKey] = freqOffset;
8164  };
8165  }
8166  else if (hasPcalOffset) // if it is defined:
8167  logReadings_.channelSetup().pcalOffsetByKey()[sensorKey] = freqOffset;
8168  //
8169  // pcal width:
8170  if (logReadings_.channelSetup().pcalWidthByKey().contains(sensorKey))
8171  {
8172  // check:
8173  if (logReadings_.channelSetup().pcalWidthByKey()[sensorKey] != pcalWidth)
8174  {
8176  "::extractPcalVgosReading(): station " + stationName_ + ": width changed from " +
8177  QString("").sprintf("%.1f to %.1f",
8178  logReadings_.channelSetup().pcalWidthByKey()[sensorKey], pcalWidth) +
8179  " for the pcal key \"" + sensorKey + "; input: \"" + asciifyString(str) + "\"");
8180  logReadings_.channelSetup().pcalWidthByKey()[sensorKey] = pcalWidth;
8181  };
8182  }
8183  else if (0.0 < pcalWidth) // if it is defined:
8184  logReadings_.channelSetup().pcalWidthByKey()[sensorKey] = pcalWidth;
8185  //
8186  //
8187  //
8188  float *f=new float[2];
8189  *f = dAmp;
8190  *(f+1) = dPhs;
8191  pcal.insert(logReadings_.channelSetup().pcalIdByKey()[sensorKey], f);
8192  }
8193  else
8195  "::extractPcalVgosReading(): station " + stationName_ + ": cannot convert str \"" +
8196  strIdx.mid(2) + "\" to int; input: \"" + asciifyString(str) + "\"");
8197  }
8198  else
8199  {
8200  if (strIdx.size() == 0)
8202  "::extractPcalVgosReading(): station " + stationName_ + ": sensorKey #" + QString("").setNum(i) +
8203  " is empty of tpcont readings: \"" + asciifyString(str) + "\"");
8204 // " is empty of tpcont readings: \"" + str + "\"");
8205  if (strValAm.size())
8207  "::extractPcalVgosReading(): station " + stationName_ + ": amplitude #" + QString("").setNum(i) +
8208  " is empty of tpcont readings: \"" + asciifyString(str) + "\"");
8209 // " is empty of tpcont readings: \"" + str + "\"");
8210  if (strValPh.size())
8212  "::extractPcalVgosReading(): station " + stationName_ + ": phase #" + QString("").setNum(i) +
8213  " is empty of tpcont readings: \"" + asciifyString(str) + "\"");
8214 // " is empty of tpcont readings: \"" + str + "\"");
8215  };
8216  };
8217  return isOk;
8218 };
8219 
8220 
8221 
8222 //
8224  const QRegularExpressionMatch& match, SgMJD& t, QString& sKey, float& dot2xps,
8225  const SgMJD& tAtTheBegin, bool& isGps)
8226 {
8227  bool isOk=false;
8228  float f;
8229  //
8230  if (!extractEpoch(str, t))
8231  return false;
8232  if (t < tAtTheBegin)
8233  return false;
8234 
8235  sKey = match.captured(1);
8236  QString cap2(match.captured(2));
8237  QString cap3(match.captured(3));
8238 
8239  isGps = cap2 == "g";
8240  f = cap3.toFloat(&isOk);
8241  if (isOk)
8242  dot2xps = f;
8243  else
8245  "::extractDot2xpsVgosReading(): station " + stationName_ + ": cannot convert \"" + cap3 +
8246  "\" to double; input: \"" + asciifyString(str) + "\"");
8247 
8248  return isOk;
8249 };
8250 
8251 
8252 
8253 
8254 
8255 //
8256 bool SgStnLogCollector::extractTraklReading(const QString& str, const QRegularExpressionMatch& match,
8257  SgMJD& t, SgTraklReading& tr, const SgMJD& tAtTheBegin)
8258 {
8259  bool isOk=false;
8260  double d;
8261  QString s("");
8262 
8263  if (!extractEpoch(str, t))
8264  return false;
8265  if (t < tAtTheBegin)
8266  return false;
8267 // 1 2 3 4 5 6 7
8268 //2020.203.18:21:45.11#trakl#[az 10.0149 el 50.0437 azv 0.00000000 elv 0.00000000 mjd 59051 s 66104 ms 980 ]
8269 
8270  tr.setT(t);
8271  //
8272  if ((s=match.captured(1)).size())
8273  {
8274  d = s.toDouble(&isOk);
8275  if (!isOk)
8277  "::extractTraklReading(): station " + stationName_ +
8278  ": cannot convert to double: \"" + s + "\"; input: \"" + asciifyString(str) + "\"");
8279  else
8280  tr.setAz(d);
8281  };
8282  if ((s=match.captured(2)).size())
8283  {
8284  d = s.toDouble(&isOk);
8285  if (!isOk)
8287  "::extractTraklReading(): station " + stationName_ +
8288  ": cannot convert to double: \"" + s + "\"; input: \"" + asciifyString(str) + "\"");
8289  else
8290  tr.setEl(d);
8291  };
8292  if ((s=match.captured(3)).size())
8293  {
8294  d = s.toDouble(&isOk);
8295  if (!isOk)
8297  "::extractTraklReading(): station " + stationName_ +
8298  ": cannot convert to double: \"" + s + "\"; input: \"" + asciifyString(str) + "\"");
8299  else
8300  tr.setAzv(d);
8301  };
8302  if ((s=match.captured(4)).size())
8303  {
8304  d = s.toDouble(&isOk);
8305  if (!isOk)
8307  "::extractTraklReading(): station " + stationName_ +
8308  ": cannot convert to double: \"" + s + "\"; input: \"" + asciifyString(str) + "\"");
8309  else
8310  tr.setElv(d);
8311  };
8312  return isOk;
8313 };
8314 
8315 
8316 
8317 //
8318 bool SgStnLogCollector::extractSefdReading(const QString& str, const QRegularExpressionMatch& match,
8319  SgMJD& t, QString& sensorId, QString& srcName, double& az, double& de, QVector<double>& vec,
8320  const SgMJD& tAtTheBegin)
8321 {
8322  bool isOk=false;
8323  double d;
8324  QString sensorTag(match.captured(4));
8325  QString s("");
8326 //QRegularExpression notATag("ia|ib|ic|id|ie|if|ig|ih");
8327  QRegularExpression notATag("i[A-Za-z0-9]");
8328 
8329  if (!extractEpoch(str, t))
8330  return false;
8331  if (t < tAtTheBegin)
8332  return false;
8333  if (notATag.match(sensorTag).hasMatch())
8334  return false;
8335 
8336 // 1 2 3 4 5 6 7 8 9 10 11 12
8337 //2020.034.17:11:35.51#onoff#VAL casa 295.4 63.4 001l 1 l 3464.40 0.9025 62.33 2139.2 58.787 0.93
8338 //2020.034.17:11:35.51#onoff#VAL casa 295.4 63.4 002l 1 l 3432.40 0.8950 63.19 2407.4 65.123 1.03
8339 
8340  srcName = match.captured(1);
8341  QString sensorKey=setupTpSensor(sensorTag, "extractSefdReading()", str);
8342  if (!sensorKey.size())
8343  return false;
8344 
8345 //sensorId = logReadings_.channelSetup().ifIdBySensorKey()[chanKey];
8346  sensorId = sensorKey;
8347 
8348  //
8349  if ((s=match.captured(2)).size())
8350  {
8351  d = s.toDouble(&isOk);
8352  if (!isOk)
8354  "::extractSefdReading(): station " + stationName_ +
8355  ": cannot convert to double: \"" + s + "\"; input: \"" + asciifyString(str) + "\"");
8356  else
8357  az = d;
8358  };
8359  //
8360  if ((s=match.captured(3)).size())
8361  {
8362  d = s.toDouble(&isOk);
8363  if (!isOk)
8365  "::extractSefdReading(): station " + stationName_ +
8366  ": cannot convert to double: \"" + s + "\"; input: \"" + asciifyString(str) + "\"");
8367  else
8368  de = d;
8369  };
8370  vec.resize(6);
8371  for (int i=0; i<6; i++)
8372  {
8373  if ((s=match.captured(7 + i)).size())
8374  {
8375  d = s.toDouble(&isOk);
8376  if (!isOk)
8378  "::extractSefdReading(): station " + stationName_ +
8379  ": cannot convert to double: \"" + s + "\"; input: \"" + asciifyString(str) + "\"");
8380  else
8381  vec[i] = d;
8382  };
8383  };
8384  return isOk;
8385 };
8386 
8387 
8388 
8389 //
8390 bool SgStnLogCollector::extractCableCalibration(const QString& str, const QRegularExpressionMatch& match,
8391  SgMJD& t, double& v)
8392 {
8393  if (!extractEpoch(str, t))
8394  return false;
8395 
8396  bool isOk=true;
8397  QString strCableVal(match.captured(2));
8398 
8399 
8400  if (strCableVal.endsWith('-'))
8401  strCableVal.chop(1);
8402  v = strCableVal.toDouble(&isOk);
8403  if (!isOk)
8405  "::extractCableCalibration(): failed to extract cable calibration value from \"" +
8406  strCableVal + "\"");
8407  else if (fabs(v) > 1.0e6) // is it enough?
8408  {
8409  v = 0.0;
8410  isOk = false;
8412  "::extractCableCalibration(): the exctracted value looks suspicious: \"" +
8413  strCableVal + "\", skipped");
8414  };
8415 // else
8416 // v /= 4.0e5;
8417  return isOk;
8418 };
8419 
8420 
8421 
8422 //
8424  const QRegularExpressionMatch& match, SgMJD& t, double& v, QString& source, QString& scan)
8425 {
8426  int nYear=0, nMonth=0, nDay=0, nHour=0, nMin=0;
8427  double dSecond=0.0, f=0.0;
8428  bool isOk=true;
8429 
8430 
8431  nYear = match.captured(1).toInt(&isOk);
8432  if (isOk)
8433  {
8434  nMonth = match.captured(2).toInt(&isOk);
8435  if (isOk)
8436  {
8437  nDay = match.captured(3).toInt(&isOk);
8438  if (isOk)
8439  {
8440  nHour = match.captured(4).toInt(&isOk);
8441  if (isOk)
8442  {
8443  nMin = match.captured(5).toInt(&isOk);
8444  if (isOk)
8445  {
8446  dSecond = match.captured(6).toDouble(&isOk);
8447  if (isOk)
8448  t.setUpEpoch(nYear, nMonth, nDay, nHour, nMin, dSecond);
8449  };
8450  };
8451  };
8452  };
8453  };
8454  if (!isOk)
8456  "::extractDataFromPcmtRecord(): failed to extract epoch from the string \"" + asciifyString(str) + "\"");
8457 // "::extractDataFromPcmtRecord(): failed to extract epoch from the string \"" + str + "\"");
8458  else
8459  {
8460  f = match.captured(7).toDouble(&isOk);
8461  if (isOk)
8462  {
8463  v = f;
8464  source = match.captured(8);
8465  if (match.lastCapturedIndex() >= 9)
8466  scan = match.captured(9);
8467  else
8468  std::cout << " --- no scan\n";
8469  }
8470  else
8472  "::extractDataFromPcmtRecord(): failed to extract cable cal value from the string \"" +
8473  asciifyString(str) + "\"");
8474 // str + "\"");
8475  };
8476  return isOk;
8477 };
8478 
8479 
8480 
8481 //
8483  const QRegularExpressionMatch& match, SgMJD& t, SgMeteoData& m)
8484 {
8485  int nYear=0, nMonth=0, nDay=0, nHour=0, nMin=0;
8486  double dSecond=0.0, f=0.0;
8487  bool isOk=true;
8488 
8489  nYear = match.captured(1).toInt(&isOk);
8490  if (isOk)
8491  {
8492  nMonth = match.captured(2).toInt(&isOk);
8493  if (isOk)
8494  {
8495  nDay = match.captured(3).toInt(&isOk);
8496  if (isOk)
8497  {
8498  nHour = match.captured(4).toInt(&isOk);
8499  if (isOk)
8500  {
8501  nMin = match.captured(5).toInt(&isOk);
8502  if (isOk)
8503  {
8504  dSecond = match.captured(6).toDouble(&isOk);
8505  if (isOk)
8506  t.setUpEpoch(nYear, nMonth, nDay, nHour, nMin, dSecond);
8507  };
8508  };
8509  };
8510  };
8511  };
8512  if (!isOk)
8514  "::extractDataFromMetRecord(): failed to extract epoch from the string \"" +
8515  asciifyString(str) + "\"");
8516 // "::extractDataFromMetRecord(): failed to extract epoch from the string \"" + str + "\"");
8517  else
8518  {
8519  f = match.captured(7).toDouble(&isOk);
8520  if (isOk)
8521  {
8522  m.setPressure(f);
8523  f = match.captured(8).toDouble(&isOk);
8524  if (isOk)
8525  {
8526  m.setTemperature(f);
8527  f = match.captured(9).toDouble(&isOk);
8528  if (isOk)
8529  m.setRelativeHumidity(f*0.01);
8530  else
8532  "::extractDataFromMetRecord(): failed to extract relative humidity from the string \"" +
8533  asciifyString(str) + "\"");
8534 // str + "\"");
8535  }
8536  else
8538  "::extractDataFromMetRecord(): failed to extract pressure from the string \"" +
8539  asciifyString(str) + "\"");
8540 // str + "\"");
8541  }
8542  else
8544  "::extractDataFromMetRecord(): failed to extract temperature from the string \"" +
8545  asciifyString(str) + "\"");
8546 // str + "\"");
8547  };
8548  return isOk;
8549 };
8550 
8551 
8552 
8553 //
8554 bool SgStnLogCollector::extractCableCalibrationSignByDiff(const QRegularExpressionMatch& match, int& v)
8555 {
8556  double d;
8557  bool isOk;
8558 
8559  QString strCableDiff(match.captured(2));
8560  QString strCableSign(match.captured(3));
8561 
8562  d = strCableDiff.toDouble(&isOk);
8563  if (isOk)
8564  {
8565  if (fabs(d) < 1.0e6) // is it enough?
8566  {
8567  if (strCableSign.contains("-"))
8568  v = -1;
8569  else if (strCableSign.contains("+"))
8570  v = 1;
8571  else
8573  "::extractCableCalibrationSignByDiff(): get unusable cable sign char sequence: \"" +
8574  strCableSign + "\"");
8575  }
8576  else
8577  {
8578  isOk = false;
8580  "::extractCableCalibrationSignByDiff(): the cable diff is too big: \"" + strCableDiff + "\"");
8581  };
8582  }
8583  else
8585  "::extractCableCalibrationSignByDiff(): cannot convert diff to double: \"" + strCableDiff + "\"");
8586  return isOk;
8587 };
8588 
8589 
8590 
8591 //
8592 bool SgStnLogCollector::checkRinexFile(const QString& fileName, const SgMJD& tStart,
8593  const SgMJD& tFinis, const QString& rinexStnName)
8594 {
8595  const QString eoh("END OF HEADER");
8596  QString path2Rinex("");
8597  QString str("");
8598  int idx=fileName.lastIndexOf("/");
8599  if (idx>-1)
8600  path2Rinex = fileName.left(idx);
8601 
8602  QDir dir(path2Rinex);
8603  QStringList nameFilters;
8604 // nameFilters << "sa01*0.??m";
8605  nameFilters << rinexStnName + "*.??m";
8606  QStringList nameList=dir.entryList(nameFilters,
8607  QDir::Files | QDir::Readable, QDir::Name | QDir::IgnoreCase);
8608  if (!nameList.size())
8609  {
8611  "::checkRinexFile(): no RINEX file found");
8612  return false;
8613  }
8614  else
8616  "::checkRinexFile(): processing RINEX files for the station " + stationName_);
8617 // 1 2 3 4
8618 //0123456789012345678901234567890123456789012345678901234567890123456789
8619 // 09 9 24 0 1 1 1000.0 22.4 76.7
8620 // 13 6 3 0 1 1 993.3 23.5 76.1
8621 // 18 2 15 0 0 0 1010.5 22.9 100.6 0.0 0.0 0.0 0.0
8622 // 18 5 14 0 0 0 1009.5 27.0 96.3-9999.9-9999.9-9999.9-9999.9
8623 // 18 5 14 0 1 0 1009.5 27.0 96.3-9999.9-9999.9-9999.9-9999.9
8624  QRegExp reData("\\s*(\\d{1,2})\\s+(\\d{1,2})\\s+(\\d{1,2})\\s+"
8625  "(\\d{1,2})\\s+(\\d{1,2})\\s+(\\d{1,2})\\s+"
8626  "(\\d{1,4}\\.\\d+)\\s+([+-\\.\\d]+)\\s+([+-]?[\\.\\d]+)(?:\\s+|$|-99)",
8627  Qt::CaseInsensitive);
8628  int nYr, nMn, nDy, nHr, nMi, nSc;
8629  double fPr, fTp, fRh;
8630  SgMeteoData m;
8631  bool isOk;
8632  logReadings_.meteoPars().clear();
8633  QFile f;
8634  double dP=0.0;
8635  //
8637  {
8640  "::checkRinexFile(): using offset of " + QString("").setNum(dP) + " mbar for atmospheric "
8641  "pressure of \"" + stationName_ + "\" station");
8642  };
8643  //
8644  for (int i=0; i<nameList.size(); i++)
8645  {
8646  const QString &fn=nameList.at(i);
8647 
8649  "::checkRinexFile(): processing " + fn + " file");
8650  str = "";
8651  idx = 0;
8652  f.setFileName(path2Rinex + "/" + fn);
8653  if (f.open(QFile::ReadOnly))
8654  {
8655  QTextStream s(&f);
8656  int count=0;
8657  while (!s.atEnd() && !str.contains(eoh))
8658  {
8659  str = s.readLine();
8660  idx++;
8661  };
8663  "::checkRinexFile(): skipped " + QString("").setNum(idx) + " strings");
8664  while (!s.atEnd())
8665  {
8666  nYr = nMn = nDy = nHr = nMi = nSc = 0;
8667  fPr = fTp = fRh = 0.0;
8668  str = s.readLine();
8669  if (reData.indexIn(str) != -1)
8670  {
8671  nYr = reData.cap(1).toInt(&isOk);
8672  if (isOk)
8673  {
8674  nMn = reData.cap(2).toInt(&isOk);
8675  if (isOk)
8676  {
8677  nDy = reData.cap(3).toInt(&isOk);
8678  if (isOk)
8679  {
8680  nHr = reData.cap(4).toInt(&isOk);
8681  if (isOk)
8682  {
8683  nMi = reData.cap(5).toInt(&isOk);
8684  if (isOk)
8685  {
8686  nSc = reData.cap(6).toInt(&isOk);
8687  if (isOk)
8688  {
8689  fPr = reData.cap(7).toDouble(&isOk);
8690  if (isOk)
8691  {
8692  fTp = reData.cap(8).toDouble(&isOk);
8693  if (isOk)
8694  {
8695  fRh = reData.cap(9).toDouble(&isOk);
8696  if (isOk)
8697  {
8698  SgMJD t(nYr, nMn, nDy, nHr, nMi, (double)nSc);
8699  if (tStart<=t && t<= tFinis)
8700  {
8701  m.setTemperature(fTp);
8702  m.setPressure(fPr + dP);
8703  if (fRh < 0.0)
8704  {
8706  "::checkRinexFile(): the extracted relative humidity looks "
8707  "suspicious: " + QString("").setNum(fRh) + "%; adjusted it to zero");
8708  m.setRelativeHumidity(0.0);
8709  }
8710  else if (100.0 < fRh)
8711  {
8713  "::checkRinexFile(): the extracted relative humidity looks "
8714  "suspicious: " + QString("").setNum(fRh) + "%; adjusted it to 100%");
8715  m.setRelativeHumidity(1.0);
8716  }
8717  else
8718  m.setRelativeHumidity(fRh*0.01);
8719  //
8720  SgMeteoReading *meteoRec=new SgMeteoReading(t, m);
8721  logReadings_.meteoPars() << meteoRec;
8722  count++;
8723  };
8724  idx++;
8725  }
8726  else
8728  "::checkRinexFile(): cannot convert relative humidity to double, "
8729  "string=\"" + reData.cap(9) + "\"");
8730  }
8731  else
8733  "::checkRinexFile(): cannot convert temperature to double, string=\"" +
8734  reData.cap(8) + "\"");
8735  }
8736  else
8738  "::checkRinexFile(): cannot convert pressure to double, string=\"" +
8739  reData.cap(7) + "\"");
8740  }
8741  else
8743  "::checkRinexFile(): cannot convert second to int, string=\"" +
8744  reData.cap(6) + "\"");
8745  }
8746  else
8748  "::checkRinexFile(): cannot convert minute to int, string=\"" +
8749  reData.cap(5) + "\"");
8750  }
8751  else
8753  "::checkRinexFile(): cannot convert hour to int, string=\"" + reData.cap(4) + "\"");
8754  }
8755  else
8757  "::checkRinexFile(): cannot convert day to int, string=\"" + reData.cap(3) + "\"");
8758  }
8759  else
8761  "::checkRinexFile(): cannot convert month to int, string=\"" + reData.cap(2) + "\"");
8762  }
8763  else
8765  "::checkRinexFile(): cannot convert year to int, string=\"" + reData.cap(1) + "\"");
8766  };
8767  };
8768  f.close();
8769  s.setDevice(NULL);
8771  "::checkRinexFile(): extracted " + QString("").setNum(count) + " meteo records from " +
8772  QString("").setNum(idx) + " strings of " + f.fileName() + " RINEX file");
8773  }
8774  else
8775  {
8777  "::checkRinexFile(): unable to read the file \"" + f.fileName() + "\"");
8778  return false;
8779  };
8780  };
8782  "::checkRinexFile(): collected " + QString("").setNum(logReadings_.meteoPars().size()) +
8783  " meteo records");
8784  return logReadings_.meteoPars().size()>0;
8785 };
8786 
8787 
8788 
8789 //
8791  bool createAntabFile, bool overwriteAntabFile, bool reportAllReadings)
8792 {
8793  // output of the raw data:
8795 
8796  // ANTAB:
8797  if (createAntabFile)
8799  useSkededChannelSetup_, overwriteAntabFile, reportAllReadings);
8800 
8801  // verify collected data:
8803  // put data into station data structures:
8805  {
8808  "::propagateData(): the cable calibration data for " + stn->getKey() + " are CDMS");
8809  }
8810  else if (hasCableRecord_ && hasCdmsRecord_)
8811  {
8813  "::propagateData(): both /cable/ and /CDMS/ commands were found for " + stn->getKey() +
8814  " in the log file");
8815  };
8816 
8817  return logReadings_.propagateData(stn);
8818 };
8819 
8820 
8821 
8822 //
8823 bool SgStnLogCollector::readDbbc3DumpFile(const QString& fileName)
8824 {
8825  QString str("");
8826  QFile f;
8827  QTextStream s;
8828  FILE *pipe;
8829  qint64 fileSize;
8830  int numOfReadStrs=0;
8831  bool reachedEndOfSession=false;
8832  QRegularExpressionMatch match;
8833  SgMJD t, lastReadTsys(tZero);
8834 
8835 
8836  QString sEpoch("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):([0-9\\.]+)\\s*UTC\\s*");
8837  QString sSep("\\s*,\\s*");
8838  QString sDbl("([0-9\\.+-]+)");
8839 
8840 
8841  //2020-07-20T17:00:00.379712 UTC: BBC002: 3448,32,agc,66,63,15202,15130,15298,15222,SEFDU: 10174.0 Jy,SEFDL: 9848.0 Jy
8842  QRegularExpression reBbc(sEpoch + ":\\s*BBC(\\d+):\\s*" + sDbl + sSep +
8843  "(\\d+)" + sSep + "(\\w+)" + sSep + "(\\d+)" + sSep + "(\\d+)" + sSep + "(\\d+)" + sSep +
8844  "(\\d+)" + sSep + "(\\d+)" + sSep + "(\\d+)" + sSep + "SEFDU:\\s*" + sDbl + "\\s*Jy" + sSep +
8845  "SEFDL:\\s*" + sDbl + "\\s*Jy.*");
8846 
8847  //2020.202.18:01:44.03/dbbc3/dbbc001/ 3480.400000,a,32,1,agc,79,84,15299,15290,14977,14972;
8848  //QRegularExpression reDbbc3Tp("/dbbc3/dbbc(\\d{3})/\\s*([0-9\\.+-]+),([^,]+),(\\d+),(\\d+),"
8849  // "(\\w+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+);.*");
8850 
8851  QString sensorId("");
8852  int nYr, nMn, nDy, nHr, nMi;
8853  double ifFrq, dSc;
8854  double bw;
8855  QString agc("");
8856  double bbcGainU, bbcGainL;
8857  double bbcTPUOn, bbcTPLOn, bbcTPUOff, bbcTPLOff;
8858  double bbcSEFDU, bbcSEFDL;
8859 
8860  bool isDataOn=false;
8861  bool isOnSource=false;
8862  SgOnSourceRecord *osRec=NULL;
8863  int onSourceIdx=0;
8864  int numOfOnSource;
8865 
8866  fileSize = QFileInfo(fileName).size();
8867 
8868  pipe = compressors.openFlt(fileName, f, s, FLTD_Input);
8869  if (s.device())
8870  {
8871  // clear previous TPC readings:
8872  for (int i=0; i<logReadings_.onSourceRecords().size(); i++)
8873  logReadings_.onSourceRecords()[i]->dbbc3Tps().clear();
8874  for (int i=0; i<logReadings_.dbbc3Tps().size(); i++)
8875  delete logReadings_.dbbc3Tps()[i];
8876  logReadings_.dbbc3Tps().clear();
8878  "::readDbbc3DumpFile(): station " + stationName_ +
8879  ": previously accumulated dbbc3 TP records were reset");
8880 
8881  if ((numOfOnSource=logReadings_.onSourceRecords().size()))
8882  osRec = logReadings_.onSourceRecords().first();
8883 
8884  bool have2reportNumOfStrings=10000000 < fileSize;
8885  while (!s.atEnd() && !reachedEndOfSession)
8886  {
8887  str = s.readLine();
8888  numOfReadStrs++;
8889 
8890 if (have2reportNumOfStrings && numOfReadStrs%200000 == 0)
8891 std::cout << " -- read " << numOfReadStrs/1000 << "K strings; file size: " << fileSize << "\n";
8892 
8893  agc = "";
8894 // bbcIdx = 0;
8895  nYr = nMn = nDy = nHr = nMi = 0;
8896  dSc = ifFrq = bw = bbcGainU = bbcGainL = bbcTPUOn =
8897  bbcTPLOn = bbcTPUOff = bbcTPLOff = bbcSEFDU = bbcSEFDL = 0.0;
8898 
8899  if ((match=reBbc.match(str)).hasMatch())
8900  {
8901  agc = match.captured(10);
8902  // they pass regexp, it is ok do not check for conversion success:
8903  nYr = match.captured( 1).toInt();
8904  nMn = match.captured( 2).toInt();
8905  nDy = match.captured( 3).toInt();
8906  nHr = match.captured( 4).toInt();
8907  nMi = match.captured( 5).toInt();
8908  dSc = match.captured( 6).toDouble();
8909  t.setUpEpoch(nYr, nMn, nDy, nHr, nMi, dSc);
8910  sensorId = match.captured(7).simplified().rightJustified(5, ' ');
8911 // bbcIdx = match.captured( 7).toInt();
8912  ifFrq = match.captured( 8).toDouble();
8913  bw = match.captured( 9).toDouble();
8914  bbcGainU = match.captured(11).toDouble();
8915  bbcGainL = match.captured(12).toDouble();
8916  bbcTPUOn = match.captured(13).toDouble();
8917  bbcTPLOn = match.captured(14).toDouble();
8918  bbcTPUOff = match.captured(15).toDouble();
8919  bbcTPLOff = match.captured(16).toDouble();
8920  bbcSEFDU = match.captured(17).toDouble();
8921  bbcSEFDL = match.captured(18).toDouble();
8922  //
8923  // find onSource record:
8924  while (onSourceIdx<numOfOnSource && (osRec=logReadings_.onSourceRecords()[onSourceIdx]) &&
8925  osRec->tFinis()<t)
8926  onSourceIdx++;
8927  if (osRec && osRec->tStart()<t)
8928  isOnSource = true;
8929  else
8930  isOnSource = false;
8931  //
8932  if (osRec && osRec->tDataOn()<t)
8933  isDataOn = true;
8934  else
8935  isDataOn = false;
8936  //
8937  SgDbbc3TpReading *tp=NULL;
8938  if (0.1/DAY2SEC < fabs(lastReadTsys - t))
8939  {
8940  tp = new SgDbbc3TpReading;
8941  tp->setT(t);
8942  tp->setOsRec(isOnSource?osRec:NULL);
8943  tp->setIsOnSource(isOnSource);
8944  tp->setIsDataOn(isDataOn);
8945  logReadings_.dbbc3Tps() << tp;
8946  if (osRec)
8947  osRec->dbbc3Tps() << tp;
8948  }
8949  else
8950  tp = logReadings_.dbbc3Tps().last();
8951  //
8952  tp->addRecord(sensorId, "", bw, agc, bbcGainU, bbcGainL, bbcTPUOff, bbcTPLOff,
8953  bbcTPUOn, bbcTPLOn, bbcSEFDU, bbcSEFDL);
8954  lastReadTsys = t;
8955  };
8956  };
8957 
8958  };
8959  compressors.closeFlt(pipe, f, s);
8960 
8961 
8963  "::readDbbc3DumpFile(): station " + stationName_ + ": " + QString("").setNum(numOfReadStrs) +
8964  " strings of the DBBC3 dump file \"" + fileName + "\" were read");
8966  "::readDbbc3DumpFile(): station " + stationName_ + ": collected " +
8967  QString("").setNum(logReadings_.dbbc3Tps().size()) + " dbbc3 TP records");
8968 
8969  return true;
8970 };
8971 
8972 /*=====================================================================================================*/
8973 
8974 
8975 
8976 
8977 
8978 
8979 
8980 /*=======================================================================================================
8981 *
8982 * SgVlbaLogCollector's METHODS:
8983 *
8984 *======================================================================================================*/
8985 //
8986 // static first:
8987 //
8989 {
8990  return "SgVlbaLogCollector";
8991 };
8992 
8993 
8994 
8995 // An empty constructor:
8997  logFileName_(""),
8998  readingsByKey_(),
8999  ivs2vlba_()
9000 {
9001  for (int i=0; i<NUM_OF_VLBA_ENTRIES; i++)
9003 };
9004 
9005 
9006 
9007 //
9008 // A destructor:
9010 {
9011  for (QMap<QString, SgStnLogReadings*>::iterator it=readingsByKey_.begin();
9012  it!=readingsByKey_.end(); ++it)
9013  delete it.value();
9014  readingsByKey_.clear();
9015 };
9016 
9017 
9018 
9019 //
9020 bool SgVlbaLogCollector::readLogFile(const QString& fileName, int nYear)
9021 {
9022  QString str("");
9023  QString key("");
9024  QFile f(fileName);
9025  QString stnPattern("([\\w]{2})");
9026  QString srcPattern("([\\d\\w+-]{2,8})");
9027  QString epcPattern("(\\d{3})(?:-|\\s+)(\\d{2}):(\\d{2}):(\\d{2})");
9028  QString dblPattern("([+-\\.\\d]+)");
9029 
9030  QRegExp rePulseCalInfo("PulseCal information for\\s+" + stnPattern + "\\s+",
9031  Qt::CaseInsensitive);
9032  QRegExp reScanCalInfo("Scan information for\\s+" + stnPattern + "\\s+",
9033  Qt::CaseInsensitive);
9034  QRegExp reWeatherInfo("Weather information for\\s+" + stnPattern + "\\s+",
9035  Qt::CaseInsensitive);
9036  QRegExp rePulseCalData
9037  (epcPattern + "\\s+'CC'\\s+" + dblPattern + "\\s+" + dblPattern,
9038  Qt::CaseInsensitive);
9039  QRegExp reScanCalData
9040  (srcPattern + "\\s+" + epcPattern + "\\s+" + epcPattern + "\\s+" +
9041  dblPattern + "\\s+" + dblPattern + "\\s+" + dblPattern,
9042  Qt::CaseInsensitive);
9043  QRegExp rePulseScanData
9044  ("!\\s+" + stnPattern + "\\s+([\\w\\d+-]+)\\s+" + srcPattern + "/(\\d+)\\s+" +
9045  epcPattern + "/" + epcPattern,
9046  Qt::CaseInsensitive);
9047  QRegExp reWeatherData
9048  (epcPattern + "\\s+" + dblPattern + "\\s+" + dblPattern + "\\s+" + dblPattern + "\\s+" +
9049  dblPattern + "\\s+" + dblPattern + "\\s+" + dblPattern + "\\s+" + dblPattern,
9050  Qt::CaseInsensitive);
9051 
9052  logFileName_ = fileName;
9053  SgStnLogReadings *reading=NULL;
9054  SgOnSourceRecord *osRec=NULL;
9055  SgMJD t, t_aux;
9056  bool have2read, isOk;
9057  double d;
9058  int m;
9059  //
9060  if (!f.exists())
9061  {
9063  "::readLogFile(): the log file " + fileName + " does not exist");
9064  return false;
9065  };
9066  //
9067  //
9069  "::readLogFile(): reading log file " + fileName);
9070  //
9071  have2read = true;
9072  if (f.open(QFile::ReadOnly))
9073  {
9074  QTextStream s(&f);
9075  while (!s.atEnd())
9076  {
9077  if (have2read)
9078  str = s.readLine();
9079  else
9080  have2read = true;
9081  //
9082  // pulse cal info:
9083  if (rePulseCalInfo.indexIn(str) != -1)
9084  {
9085  key = rePulseCalInfo.cap(1);
9086  //
9087  if (readingsByKey_.contains(key))
9088  reading = readingsByKey_[key];
9089  else
9090  readingsByKey_.insert(key, (reading=new SgStnLogReadings(key)));
9091  //
9092 // while (!s.atEnd() && !(str.contains(" information ") && !str.contains(key)))
9093  str = "";
9094  while (!s.atEnd() && !str.contains(" information "))
9095  {
9096  str = s.readLine();
9097  //
9098  //
9099  if (rePulseCalData.indexIn(str) != -1)
9100  {
9101  if (strs2mjd(nYear, rePulseCalData.cap(1), rePulseCalData.cap(2),
9102  rePulseCalData.cap(3), rePulseCalData.cap(4), t))
9103  {
9104  d = rePulseCalData.cap(5).toDouble(&isOk);
9105  if (isOk)
9106  reading->cableCals() << new SgCableCalReading(t, d*1.0e-12);
9107  else
9109  "::readLogFile(): failed to extract cable cal value from PulseCalData: \"" +
9110  str + "\"");
9111  }
9112  else
9114  "::readLogFile(): failed to extract epoch from PulseCalData: \"" + str + "\"");
9115  };
9116  if (rePulseScanData.indexIn(str) != -1)
9117  {
9118  m = rePulseScanData.cap(4).toInt(&isOk);
9119  if (isOk)
9120  {
9121  if (m != 999) // are others ok?
9122  {
9123  if (strs2mjd(nYear, rePulseScanData.cap(5), rePulseScanData.cap(6),
9124  rePulseScanData.cap(7), rePulseScanData.cap(8), t))
9125  {
9126  if (strs2mjd(nYear, rePulseScanData.cap(9), rePulseScanData.cap(10),
9127  rePulseScanData.cap(11), rePulseScanData.cap(12), t_aux))
9128  {
9129  osRec = new SgOnSourceRecord;
9130  osRec->setSourceName(rePulseScanData.cap(3).toUpper());
9131  osRec->setTstart(t);
9132  osRec->setTfinis(t_aux);
9133  // check for duplicates:
9134  if (reading->onSourceRecords().size()==0)
9135  reading->onSourceRecords() << osRec;
9136 // else if (*reading->onSourceRecords().last() != *osRec)
9137  else if (!reading->onSourceRecords().last()->isSameArgs(*osRec))
9138  reading->onSourceRecords() << osRec;
9139  else
9140  {
9142  "::readLogFile(): got a duplicate string of PulseScanData: \"" + str + "\"");
9143  delete osRec;
9144  };
9145  }
9146  else
9148  "::readLogFile(): failed to extract epoch_2 from PulseScanData: \"" + str + "\"");
9149  }
9150  else
9152  "::readLogFile(): failed to extract epoch_1 from PulseScanData: \"" + str + "\"");
9153  };
9154  }
9155  else
9157  "::readLogFile(): failed to extract qualifier value from PulseCalData: \"" + str + "\"");
9158  };
9159  };
9160  have2read = false;
9161  };
9162  //
9163  // scan info:
9164  /*
9165  if (reScanCalInfo.indexIn(str) != -1)
9166  {
9167  key = reScanCalInfo.cap(1);
9168  if (readingsByKey_.contains(key))
9169  reading = readingsByKey_[key];
9170  else
9171  {
9172  reading = new SgStnLogReadings;
9173  reading->setStationName(key);
9174  readingsByKey_.insert(key, reading);
9175  };
9176 
9177  while (!s.atEnd() && !(str.contains(" information ") && !str.contains(key)))
9178  {
9179  str = s.readLine();
9180  if (reScanCalData.indexIn(str) != -1)
9181  {
9182  ..*..
9183  };
9184  };
9185  have2read = false;
9186  };
9187  */
9188  //
9189  //
9190  // weather info:
9191  if (reWeatherInfo.indexIn(str) != -1)
9192  {
9193  key = reWeatherInfo.cap(1);
9194  //
9195  if (readingsByKey_.contains(key))
9196  reading = readingsByKey_[key];
9197  else
9198  readingsByKey_.insert(key, (reading=new SgStnLogReadings(key)));
9199  //
9200 // while (!s.atEnd() && !(str.contains(" information ") && !str.contains(key)))
9201  str = "";
9202  while (!s.atEnd() && !str.contains(" information "))
9203  {
9204  str = s.readLine();
9205  if (reWeatherData.indexIn(str) != -1)
9206  {
9207  if (strs2mjd(nYear, reWeatherData.cap(1), reWeatherData.cap(2),
9208  reWeatherData.cap(3), reWeatherData.cap(4), t))
9209  {
9210  double temp, press, dewpt;
9211  temp = reWeatherData.cap(5).toDouble(&isOk);
9212  if (isOk)
9213  {
9214  press = reWeatherData.cap(6).toDouble(&isOk);
9215  if (isOk)
9216  {
9217  dewpt = reWeatherData.cap(7).toDouble(&isOk);
9218  if (isOk)
9219  reading->meteoPars() << new
9220  SgMeteoReading(t, SgMeteoData(temp, press, SgMeteoData::dewPt2Rho(temp, dewpt)));
9221  else
9223  "::readLogFile(): failed to extract dew point from WeatherData: \"" + str + "\"");
9224  }
9225  else
9227  "::readLogFile(): failed to extract pressure from WeatherData: \"" + str + "\"");
9228  }
9229  else
9231  "::readLogFile(): failed to extract temperature from WeatherData: \"" + str + "\"");
9232  }
9233  else
9235  "::readLogFile(): failed to extract epoch from WeatherData: \"" + str + "\"");
9236  };
9237  };
9238  have2read = false;
9239  };
9240  };
9241  f.close();
9242  s.setDevice(NULL);
9243  };
9244 
9245  for (QMap<QString, SgStnLogReadings*>::iterator it=readingsByKey_.begin();
9246  it!=readingsByKey_.end(); ++it)
9247  {
9248  SgStnLogReadings *rd=it.value();
9249  rd->setCableSign(-1);
9250  rd->setCableCalAmbig(1.0e-9);
9251  rd->allocateCableReadings();
9252  };
9253  //
9255  "::readLogFile(): collected logs of " + QString("").setNum(readingsByKey_.size())+
9256  " stations from the log file");
9258  "::readLogFile(): parsing of the log file has been completed");
9259  //
9260  return true;
9261 };
9262 
9263 
9264 
9265 //
9266 bool SgVlbaLogCollector::strs2mjd(int nYear, const QString& sDay, const QString& sHr,
9267  const QString& sMin, const QString& sSec, SgMJD& t)
9268 {
9269  int dy, hr, mi, se;
9270  bool isOk;
9271  isOk = true;
9272 
9273  dy = sDay.toInt(&isOk);
9274  if (isOk)
9275  {
9276  hr = sHr.toInt(&isOk);
9277  if (isOk)
9278  {
9279  mi = sMin.toInt(&isOk);
9280  if (isOk)
9281  {
9282  se = sSec.toInt(&isOk);
9283  if (isOk)
9284  t.setUpEpoch(nYear, 0, dy, hr, mi, se);
9285  else
9287  "::strs2mjd(): failed to extract seconds from \"" + sSec + + "\"");
9288  }
9289  else
9291  "::strs2mjd(): failed to extract minutes from \"" + sMin + + "\"");
9292  }
9293  else
9295  "::strs2mjd(): failed to extract hours from \"" + sHr + + "\"");
9296  }
9297  else
9299  "::strs2mjd(): failed to extract days from \"" + sDay + "\"");
9300  return isOk;
9301 };
9302 
9303 
9304 
9305 //
9307 {
9308  if (isVlba(stn->getKey()))
9309  {
9310  QString vlbaKey=ivs2vlba_.value(stn->getKey());
9311  if (readingsByKey_.contains(vlbaKey))
9312  {
9313  SgStnLogReadings *logReadings=readingsByKey_.value(vlbaKey);
9314 
9315  // verify collected data:
9316  logReadings->verifyReadings(stn, NULL);
9317 
9318  // put data into station data structures:
9319  return logReadings->propagateData(stn);
9320  }
9321  else // VLBA station not found in the log file
9322  {
9324  "::propagateData(): cannot find VLBA station " + stn->getKey() + " (aka " + vlbaKey +
9325  ") in the log file");
9326  return false;
9327  };
9328  }
9329  else // not a VLBA station
9330  {
9332  "::propagateData(): cannot find a station " + stn->getKey() + " in the map of VLBA stations");
9333  return false;
9334  };
9335 };
9336 /*=====================================================================================================*/
9337 
9338 
9339 
9340 
9341 
9342 
9343 
9344 
9345 
9346 /*=====================================================================================================*/
9347 //
9348 // FRIENDS:
9349 //
9350 /*=====================================================================================================*/
9351 //
9352 
9353 
9354 
9355 
9356 /*=====================================================================================================*/
9357 //
9358 // aux functions:
9359 //
9360 //
9361 
9362 
9363 
9364 
9365 /*=====================================================================================================*/
9366 //
9367 // constants:
9368 //
9369 //const QString SgStnLogReadings::sFiller_("n/a");
9370 const QString SgStnLogReadings::sFiller_("DUMMY");
9371 const int SgStnLogReadings::nFiller_ = -999;
9372 const double SgStnLogReadings::dFiller_ = -99.9;
9373 
9374 
9375 int SgStnLogCollector::fsContentStartsAt_[] = {0, 10, 14, 20, 0, 0};
9376 
9377 
9379  { "BR", "CA", "EB", "FD", "GA", "GT", "HN", "JV", "KP", "LA", "MK", "NL", "OV", "PT", "SC" };
9381  { "BR-VLBA ", "CAMBRIDG", "EFLSBERG", "FD-VLBA ", "VLBA85_3", "GBT-VLBA", "HN-VLBA ",
9382  "JODRELL2", "KP-VLBA ", "LA-VLBA ", "MK-VLBA ", "NL-VLBA ", "OV-VLBA ", "PIETOWN ",
9383  "SC-VLBA " };
9384 
9385 
9386 
9387 
9388 
9389 
9390 /*=====================================================================================================*/
9391 
9392 
9393 
9394 
9395 QString asciifyString(const QString& str)
9396 {
9397  QString s("");
9398 //QRegularExpression rx("[\\x{00}-\\x{20}]");
9399  ushort n;
9400  for (int i=0; i<str.size(); i++)
9401  {
9402 // if (rx.match(str.at(i)).hasMatch())
9403  n = str.at(i).unicode();
9404  if (n<32 || 126<n)
9405  s += QString("").sprintf("\\0x%04X", n);
9406  else
9407  s += str.at(i);
9408  };
9409  return s;
9410 };
9411 
9412 
9413 
9414 
9415 
9416 
9417 
9418 
9419 
9420 
9421 
9422 
9423 
9424 
9425 
9426 
9427 /*=====================================================================================================*/
9428 
9429 
9430 
9431 
9432 
SgIoExtFilterHandler compressors
@ FLTD_Output
@ FLTD_Input
SgLogger * logger
Definition: SgLogger.cpp:231
const SgMJD tZero(1957, 10, 4)
#define DAY2SEC
radians to mas:
Definition: SgMathSupport.h:69
#define RAD2DEG
radians to degrees:
Definition: SgMathSupport.h:41
QString asciifyString(const QString &str)
#define NUM_OF_VLBA_ENTRIES
@ AOD_CABLE_CAL
@ AOD_PCAL
@ AOD_CABLE_SIGN
@ AOD_DBBC3TP
@ AOD_FMTGPS
@ AOD_ALL
@ AOD_TPI
@ AOD_METEO
@ AOD_NOVEL
@ AOD_DATA_ON
@ AOD_SEFD
@ AOD_TSYS
SgVersion libraryVersion("SgLib", 0, 8, 2, "Compton Peak (rc2)", SgMJD(2023, 4, 3, 10, 59))
QString polarization2Str(SgChannelPolarization p)
Definition: SgVex.cpp:1127
QString sideBand2Str(SgChannelSideBand sb)
Definition: SgVex.cpp:1113
SgChannelPolarization
Definition: SgVex.h:57
@ CP_UNDEF
Definition: SgVex.h:58
@ CP_VerticalLP
Definition: SgVex.h:62
@ CP_RightCP
Definition: SgVex.h:59
@ CP_HorizontalLP
Definition: SgVex.h:61
@ CP_LeftCP
Definition: SgVex.h:60
SgChannelSideBand
Definition: SgVex.h:47
@ CSB_DUAL
Definition: SgVex.h:51
@ CSB_USB
Definition: SgVex.h:50
@ CSB_LSB
Definition: SgVex.h:49
@ CSB_UNDEF
Definition: SgVex.h:48
#define UNUSED
bool isAttr(uint a) const
Definition: SgAttribute.h:226
void addAttr(uint a)
Definition: SgAttribute.h:202
static const QString className()
void setV(double v)
void setOsRec(SgOnSourceRecord *os)
double getV() const
const SgMJD & getT() const
const SgOnSourceRecord * getOsRec() const
QMap< QString, double > & pcalOffsetByKey()
QMap< QString, SgChannelPolarization > & loPolarizationByTpSensorKey()
QMap< QString, double > & pcalLoFreqByKey()
QMap< QString, SgChannelSideBand > & ifSideBandById()
QMap< QString, int > & ifIdxById()
QMap< QString, QList< QString > > & origSensorIdById()
QMap< QString, SgChannelPolarization > loPolarizationById_
QMap< QString, double > & pcalWidthByKey()
QMap< QString, SgChannelSideBand > & loSideBandById()
QMap< QString, SgChannelPolarization > & loPolarizationById()
QMap< QString, QString > & loIdByTpSensorKey()
QMap< QString, QString > & ifIdByTpSensorKey()
QMap< QString, double > loFreqByTpSensorKey_
QMap< QString, QString > loIdByCid_
QMap< int, double > & bbcBandwidthByIdx()
HwType getHwType() const
QMap< QString, SgChannelPolarization > & pcalPolarizationByKey()
QMap< QString, double > & pcalOffsetByLoId()
void setBackEndType(BackEndType tp)
bool selfCheck(const QString &stnKey)
QMap< int, double > & bbcFreqByIdx()
QMap< QString, QString > & xpsIdByKey()
QMap< QString, double > & loFreqById()
QMap< QString, double > & ifFreqByTpSensorKey()
QMap< QString, QString > & pcalIdByKey()
QMap< QString, double > & loPcWidthById()
QMap< QString, int > ifIdxById_
static double calcSkyFreq(double loFreq, double bbcFreq, double width, SgChannelSideBand loSideBand, SgChannelSideBand ifSideBand)
QMap< QString, double > & ifBandwidthByTpSensorKey()
QMap< QString, SgChannelSideBand > loSideBandById_
QMap< QString, QString > & loIdByCid()
QMap< int, QString > loIdByIdx_
static const QString className()
QMap< int, double > bbcFreqByIdx_
QMap< QString, double > loFreqById_
QMap< int, QString > & loIdByIdx()
QMap< QString, double > & loFreqByTpSensorKey()
BackEndType backEndType_
QMap< QString, SgChannelPolarization > & ifPolarizationById()
QMap< int, double > & ifFreqByIdx()
QMap< QString, SgChannelSideBand > & pcalSideBandByKey()
QMap< QString, QString > ifIdByTpSensorKey_
BackEndType getBackEndType() const
QMap< int, double > bbcBandwidthByIdx_
QMap< QString, SgChannelSideBand > ifSideBandById_
QMap< QString, SgChannelSideBand > & loSideBandByTpSensorKey()
void setHwType(HwType tp)
const QString & getBandKey() const
const QList< SgChannelSideBand > & getSideBands() const
const QList< ChanCfg > & getChannelCfgs() const
const QString & getStnKey() const
QMap< QString, StnCfg > stnCfgByKey_
static const QString className()
bool parseSkdFile(const QString &fileName)
void addRecord(const QString &sensorId, const QString &boardId, double bw, const QString &agc, double gainU, double gainL, double tpOffU, double tpOffL, double tpOnU, double tpOnL, double sefdU, double sefdL)
void setOsRec(SgOnSourceRecord *os)
const SgOnSourceRecord * getOsRec() const
const SgMJD & getT() const
void setIsOnSource(bool isOnSource)
void setT(const SgMJD &t)
const QMap< QString, TpRecord > & getTpBySensor() const
void setIsDataOn(bool isDataOn)
void setT(const SgMJD &t)
const SgOnSourceRecord * getOsRec() const
bool addDot2gpsByBrd(const QString &key, float v)
const QMap< QString, float > & getDot2ppsByBrd() const
const QMap< QString, float > & getDot2gpsByBrd() const
bool addDot2ppsByBrd(const QString &key, float v)
void setOsRec(SgOnSourceRecord *os)
const SgMJD & getT() const
const SgIoExternalFilter * lookupFilterByFileName(const QString &fileName)
static void closeFlt(FILE *&p, QFile &file, QTextStream &ts)
FILE * openFlt(const QString &fileName, QFile &file, QTextStream &ts, FilterDirection)
const QString & getDefaultExtension() const
virtual void write(LogLevel, quint32, const QString &, bool=false)
Definition: SgLogger.cpp:88
@ IO_TXT
Definition: SgLogger.h:65
bool isEligible(LogLevel lvl, quint32 f) const
Definition: SgLogger.h:151
Definition: SgMJD.h:59
@ F_YYYYMMDDHHMMSSSS
Long verbose: Fri, the 2nd of Apr, 2010; 17hr 02min 43.6400sec.
Definition: SgMJD.h:67
@ F_Simple
Digits: 2010/04/02 17:02:43.6.
Definition: SgMJD.h:68
@ F_SOLVE_SPLFL_V3
Another spoolfile represenation of epoch: 2012.01.20-09:14:28.0.
Definition: SgMJD.h:76
@ F_SOLVE_SPLFL
That was used in ECC.dat files: 2010.04.02-17.02.
Definition: SgMJD.h:74
@ F_INTERNAL
Digits, date and time: 20100402.71.
Definition: SgMJD.h:72
QString toString(Format format=F_Verbose) const
Definition: SgMJD.cpp:1008
void setUpEpoch(int year, int month, int day, int hour, int min, double sec)
Definition: SgMJD.cpp:255
int calcYear() const
Definition: SgMJD.cpp:205
double getPressure() const
Definition: SgMeteoData.h:242
void setRelativeHumidity(double rho)
Definition: SgMeteoData.h:274
double getTemperature() const
Definition: SgMeteoData.h:234
void setTemperature(double t)
Definition: SgMeteoData.h:258
void setPressure(double p)
Definition: SgMeteoData.h:266
static double dewPt2Rho(double temperature, double dewPtTemperature)
Definition: SgMeteoData.cpp:40
double getRelativeHumidity() const
Definition: SgMeteoData.h:250
const SgMJD & getT() const
const SgOnSourceRecord * getOsRec() const
void setOsRec(SgOnSourceRecord *os)
static const QString className()
const SgMeteoData & getM() const
const QString & getKey() const
Definition: SgObjectInfo.h:319
QList< SgCableCalReading * > & cableCals()
QList< SgTsysReading * > & tSyses()
static const QString className()
const SgMJD & getTdataOn() const
const QString & getScanName() const
void setScanName(const QString &str)
const SgMJD & getTfinis() const
void setSourceName(const QString &str)
void setTfinis(const SgMJD &t)
QList< SgDbbc3TpReading * > & dbbc3Tps()
const QString & getSourceName() const
const SgMJD & getTstart() const
void setTstart(const SgMJD &t)
QList< SgMeteoReading * > & meteoPars()
const SgOnSourceRecord * getOsRec() const
void setT(const SgMJD &t)
void setOsRec(SgOnSourceRecord *os)
const QMap< QString, float * > & getPcal() const
static const QString className()
const SgMJD & getT() const
bool addPcals(const QMap< QString, float * > &pcals)
const SgMJD & getT() const
static const QString className()
bool addValByChanKey(const SgMJD &t, const QString &srcName, double az, double el, const QString &chanKey, const QVector< double > &val)
double getAz() const
QMap< QString, QVector< double > * > valByChanKey_
double getEl() const
const QMap< QString, QVector< double > * > & getValByChanKey() const
const QString & getSrcName() const
bool extractPcalOffsetReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, const SgMJD &tAtTheEnd, SgChannelSetup &cs, const SgMJD &tFirst)
const QMap< QString, double > * rinexPressureOffsetByStn_
const QMap< QString, QString > * rinexFileNameByStn_
static const QRegularExpression reMet_
FieldSystemEpochFormat fsFmt_
bool extractTraklReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, SgTraklReading &, const SgMJD &tAtTheBegin)
static const QString className()
bool extractTsysVgosReading(const QString &str, const QRegularExpression &reTsys, SgMJD &t, QMap< QString, float > &tSys, const SgMJD &tAtTheBegin)
static const QRegularExpression reFsOld_
bool extractBbcReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, const SgMJD &atEnd, SgChannelSetup &cs, const SgMJD &tFirst)
bool createAntabFile(const QString &stnKey, const QString &outputFileName, bool have2owrt, bool reportAllTsysData)
static const QRegularExpression rePcmt_
bool extractTsysReading(const QString &str, const QRegularExpression &reTsys, SgMJD &t, QMap< QString, float > &tSys, const SgMJD &tAtTheBegin)
bool extractDataFromMetRecord(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, SgMeteoData &m)
bool extractVciReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, const SgMJD &atEnd, SgChannelSetup &cs, const SgMJD &tFirst)
bool readDbbc3DumpFile(const QString &fileName)
const QMap< QString, int > * defaultCableSignByStn_
bool extractCableCalibration(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, double &v)
static int fsContentStartsAt_[]
bool extractCableCalibrationSignByDiff(const QRegularExpressionMatch &match, int &v)
QString setupTpSensor(const QString &sensorTag, const QString &callerName, const QString &inputString)
bool propagateData(SgVlbiStationInfo *stn, bool createAntabFile, bool overwriteAntabFile, bool reportAllTsysData)
bool extractContent(const QString &str, QString &content)
bool extractVcReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, const SgMJD &atEnd, SgChannelSetup &cs, const SgMJD &tFirst)
SgChannelSkeded * channelSkeded_
bool extractPatchReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, const SgMJD &atEnd, SgChannelSetup &cs, const SgMJD &tFirst)
bool extractMeteoReading(const QString &str, const QRegularExpression &reMeteo, SgMJD &t, SgMeteoData &m, const int *oom)
FieldSystemEpochFormat guessFsFormat(const QString &str)
bool readLogFile(const QString &fileName, const QString &stnName, const SgMJD &tFirst, const SgMJD &tLast, const QString &orderOfMeteo)
bool extractChanSkyFrqReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, const SgMJD &atEnd, SgChannelSetup &cs, const SgMJD &tFirst)
bool extractDot2xpsVgosReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, QString &sKey, float &dot2xps, const SgMJD &tAtTheBegin, bool &isGps)
bool extractPcalVgosReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, QMap< QString, float * > &pcal, SgChannelSetup &cs, const SgMJD &tAtTheBegin)
bool extractEpoch(const QString &str, SgMJD &t)
bool extractLoReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, const SgMJD &atEnd, SgChannelSetup &cs, const SgMJD &tFirst)
bool extractDataFromPcmtRecord(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, double &v, QString &source, QString &scan)
static const QRegularExpression reFsNewest_
QMap< QString, Procedure * > procedureByName_
static const QRegularExpression reFsNew_
SgStnLogReadings logReadings_
bool checkRinexFile(const QString &fileName, const SgMJD &tStart, const SgMJD &tFinis, const QString &rinexStnName)
bool extractSefdReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, QString &sensorId, QString &srcName, double &az, double &de, QVector< double > &vec, const SgMJD &tAtTheBegin)
bool extractTpcontVgosReading(const QString &str, const QRegularExpression &reTpcont, SgMJD &t, QMap< QString, QVector< int > > &tPcont, const SgMJD &tAtTheBegin)
bool extractLoRxgReading(const QString &str, const QRegularExpressionMatch &match, SgMJD &t, const SgMJD &atEnd, SgChannelSetup &cs, const SgMJD &tFirst)
const QString & getRecorderInfo() const
QList< SgDbbc3TpReading * > & dbbc3Tps()
static const QString sFiller_
QList< SgTraklReading * > & trakls()
QList< SgDot2xpsReading * > dot2xpses_
QList< SgSefdReading * > sefds_
void export2antabFrqs_vgosSetup(QTextStream &s)
bool createAntabFile(const QString &inputLogFileName, const QString &outputFileName, const QString &stnKey, const SgChannelSkeded *channelSkeded, bool useSkededChannelSetup, bool have2overwrite, bool reportAllTsysData)
void export2antCalFrqs_vgosSetup(QTextStream &s)
QList< SgCableCalReading * > & cableCals()
void export2antabFrqs_skededSetup(QTextStream &s, const SgChannelSkeded::StnCfg &sCfg)
QList< SgTsysReading * > & tSyses()
bool createAntCalFile(const QString &inputLogFileName, const QString &outputFileName, const QString &stnKey, const SgChannelSkeded *channelSkeded, bool useSkededChannelSetup, bool have2overwrite, bool reportAllReadings, bool supressNonUsedSensors, int antcalOutputData, const QString &ext4compress, const QString &userCommand)
void interpolateMeteoParameters(SgVlbiAuxObservation *aux)
void setCableCalAmbig(double a)
void export2antabFrqs_nativeSetup(QTextStream &s)
QList< SgPcalReading * > pcals_
static const QString className()
QList< SgSefdReading * > & sefds()
QList< SgDbbc3TpReading * > dbbc3Tps_
void export2antabFrqs_missedSetup(QTextStream &s)
void setCableSign(int n)
static const double dFiller_
QList< SgCableCalReading * > cableCals_
bool compareChannelSetups(const SgChannelSkeded::StnCfg &sCfg)
void lookupScanName(SgOnSourceRecord *osRec, const QMap< QString, SgVlbiAuxObservation * > &auxObsByScan)
QList< SgMeteoReading * > & meteoPars()
QList< SgDot2xpsReading * > & dot2xpses()
void setRecorderInfo(const QString &info)
void setStationName(const QString &name)
void setBackEndInfo(const QString &info)
QList< SgOnSourceRecord * > & onSourceRecords()
QList< SgOnSourceRecord * > onSourceRecords_
QList< SgTraklReading * > trakls_
SgChannelSetup & channelSetup()
SgChannelSetup channelSetup_
QString str4AntCal(const QString &str, int width)
const QString & getExperimentName() const
void setExperimentName(const QString &name)
QList< SgTsysReading * > tSyses_
QList< SgMeteoReading * > meteoPars_
const QString & getBackEndInfo() const
void export2antCalPcal_vgosSetup(QTextStream &s)
QList< SgCableCalReading * > & cableLongs()
void setFsVersionLabel(const QString &ver)
int getCableSign() const
QList< SgCableCalReading * > cableLongs_
void export2antCalFrqs_skededSetup(QTextStream &s, const SgChannelSkeded::StnCfg &sCfg)
bool compareChannelNumbers(const SgChannelSkeded::StnCfg &sCfg)
bool propagateData(SgVlbiStationInfo *stn)
void verifyReadings(SgVlbiStationInfo *stn, const QMap< QString, int > *defaultCableSignByStn)
static const int nFiller_
QList< SgPcalReading * > & pcals()
QMap< QString, SgOnSourceRecord * > recordByScan_
void setItType(InputType t)
void export2antCalFrqs_nativeSetup(QTextStream &s)
static const QString className()
void setT(const SgMJD &t)
void setElv(float elv)
float getEl() const
float getAz() const
void setAzv(float azv)
void setAz(float az)
void setEl(float el)
const SgMJD & getT() const
void setOsRec(SgOnSourceRecord *os)
void setT(const SgMJD &t)
static const QString className()
void addTsyses(const QMap< QString, float > &tsys)
void setIsOnSource(bool isOnSource)
const QMap< QString, float > & getTsys() const
QMap< QString, QVector< int > > & tpcont()
QList< SgTraklReading * > & trakls()
const SgOnSourceRecord * getOsRec() const
void setIsDataOn(bool isDataOn)
const SgMJD & getT() const
QMap< QString, QVector< int > > tpcont_
QMap< QString, float > & tsys()
const QMap< QString, QVector< int > > & getTpcont() const
QMap< QString, float > tsys_
void addTpconts(const QMap< QString, QVector< int > > &tpcont)
SgOnSourceRecord *& osRec()
void setElement(unsigned int i, double d)
Definition: SgVector.h:348
double getElement(unsigned int i) const
Definition: SgVector.h:362
QString name(NameFormat fmt=NF_Human) const
Definition: SgVersion.cpp:54
static const QString className()
bool readLogFile(const QString &fileName, int year)
bool strs2mjd(int nYear, const QString &sDay, const QString &sHr, const QString &sMin, const QString &sSec, SgMJD &t)
bool propagateData(SgVlbiStationInfo *stn)
static const QString ivsStationNames_[NUM_OF_VLBA_ENTRIES]
bool isVlba(const QString &key) const
static const QString vlbaStationCodes_[NUM_OF_VLBA_ENTRIES]
QMap< QString, QString > ivs2vlba_
QMap< QString, SgStnLogReadings * > readingsByKey_
void setTsyses(const SgVector &ts)
void setCableCalibration(double cable)
void setMeteoData(const SgMeteoData &meteo)
SgVlbiObservation * getOwner() const
const SgVector & cableCorrections() const
SgVlbiSourceInfo * src()
const QString & getScanName() const
QMap< QString, SgVlbiObservable * > & observableByKey()
QMap< QString, SgVlbiAuxObservation * > * auxObservationByScanId()
QVector< QString > & tsysIfSideBands()
QVector< double > & tsysIfFreqs()
QVector< QString > & tsysIfIds()
QString name() const
@ Attr_HAS_CABLE_CAL
a station has cable calibration readings;
@ Attr_METEO_MODIFIED
a station has meteo parameters;
@ Attr_CABLE_CAL_MODIFIED
a station has cable calibration readings;
@ Attr_HAS_METEO
a station has meteo parameters;
@ Attr_CABLE_CAL_IS_CDMS
FS log file contains /CDMS/ readings instead of /cable/;.
void setCableCalMultiplierDBCal(double c)
QVector< QString > & tsysIfPolarizations()
SgVersion * driverVersion
Definition: l2aVersion.cpp:31