General Purpose Geodetic Library
SgVlbiSessionUtils4Automation.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) 2010-2020 Sergei Bolotin.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #include <iostream>
24 #include <stdlib.h>
25 
26 
27 
28 #include <SgVlbiSession.h>
29 
30 #if QT_VERSION >= 0x050000
31 # include <QtWidgets/QMessageBox>
32 #else
33 # include <QtGui/QMessageBox>
34 #endif
35 
36 
37 
38 #include <SgLogger.h>
39 #include <SgTaskConfig.h>
40 #include <SgVlbiBand.h>
41 #include <SgVlbiNetworkId.h>
42 
43 
44 
45 #define LOCAL_DEBUG
46 
49 
50 
51 /*=======================================================================================================
52 *
53 * METHODS:
54 *
55 *======================================================================================================*/
56 //
58 {
60  return false;
61  //
63  ap=config_->apByNetId().contains(networkID_)?
65  //
66  // special case (4testing):
67  if (networkID_ == "INT") // special case:
68  return doPostReadActions4Ints(ap);
69  //
70  //
71  if (config_->apByNetId().contains(networkID_))
73  "::doPostReadActions(): post read actions initiated for the session " + getName() +
74  " using " + networkID_ + " scenario", true);
75  else
77  "::doPostReadActions(): post read actions initiated for the session " + getName() +
78  " using " + defaultNetIdName + " scenario", true);
79  //
80  //
81  // prepare the stuff:
83  //
84  // prepare the session:
85  if (ap.doSessionSetup_)
86  {
90  };
91  //
92  //
94  //
95  if (ap.doIonoCorrection4SBD_ && bands().size()>1)
96  {
98  "::doPostReadActions(): evaluating ionospheric corrections for single band delays", true);
100  };
101  //
102  if (ap.doClockBreaksDetection_)
103  {
105  "::doPostReadActions(): clock break detections not implemened yet", true);
106  // check4ClockBreaksAtSBD();
107  // detectAndProcessClockBreaks();
108  };
109  //
110  if (ap.doOutliers_)
111  {
113  "::doPostReadActions(): elimination of outliers, early stage", true);
115  };
116  //
117  return true;
118 };
119 
120 
121 
122 //
123 //
125 {
127  "::doPostReadActions4Ints(): post read actions initiated for the session " + getName() +
128  ", INT mode", true);
129 
130  QMap<QString, int> bandIdxByKey;
132  parIdxs;
133  double opThresholdSaved=config_->getOpThreshold();
134  int primaryBandIdx=-1;
135  //
136  // preparations:
137  //
138  if (primaryBand_->getInputFileVersion() > 3) // clear GSI editings
139  resetAllEditings(true);
140  else
141  {
143  if (ap.doSessionSetup_)
144  {
148  };
149  }
150  //
152  //
153  // init aux sigmas:
154  for (BaselinesByName_it it=baselinesByName_.begin(); it!=baselinesByName_.end(); ++it)
155  it.value()->setSigma2add(DT_DELAY, 20.0e-12);
156  //
157  //
158  for (int i=0; i<bands_.size(); i++)
159  {
160  bandIdxByKey[bands_.at(i)->getKey()] = i;
161  if (bands_.at(i)->getKey() == primaryBand_->getKey())
162  primaryBandIdx = i;
163  };
164  if (!bandIdxByKey.contains("X"))
166  "::doPostReadActions4Ints(): nonstandard band naming: missed X-band");
167  if (!bandIdxByKey.contains("S"))
169  "::doPostReadActions4Ints(): nonstandard band naming: missed S-band");
170  if (primaryBand_->getKey() != "X")
172  "::doPostReadActions4Ints(): nonstandard band naming: the primary band is not X-band");
173  //
174  //
175  //
176  if (ap.doIonoCorrection4SBD_ && bands().size()>1)
177  {
179  "::doPostReadActions4Ints(): evaluating ionospheric corrections for single band delays", true);
181  };
182  //
183  if (ap.doClockBreaksDetection_)
184  {
186  {
188  "::doPostReadActions4Ints(): a clock break was detected for SB delays, cannot proceed in "
189  "automatic mode");
190  resetAllEditings(true);
191  return false;
192  }
193  else
195  "::doPostReadActions4Ints(): scan for clock break @SBD completed");
196  }
197  else
199  "::doPostReadActions4Ints(): scan for clock break @SBD was not required");
200  //
201  //
202  //
203  if (ap.doAmbigResolution_)
204  {
206  "::doPostReadActions4Ints(): starting to resolve ambiguities", true);
207  // SBDelay:
209  parIdxs.clear();
212  process(true, false);
214  "::doPostReadActions4Ints(): obtained SB solution", true);
215  //
216  // Group Delays:
219 
220  //
221  for (int i=0; i<bands_.size(); i++)
222  {
225  process(true, false);
227  "::doPostReadActions4Ints(): finished " +
228  bands_.at(i)->getKey() + "-band clocks only solution");
229  eliminateOutliersSimpleMode(i, (int)(observations_.size()*0.20), 7.0, 25.0e-9);
230  };
234  process(true, false);
235  for (int i=0; i<bands_.size(); i++)
236  {
239  process(true, false);
241  "::doPostReadActions4Ints(): finished " +
242  bands_.at(i)->getKey() + "-band clocks&zenith solution");
243  eliminateOutliersSimpleMode(i, (int)(observations_.size()*0.20), 5.0, 15.0e-9);
244  };
246  "::doPostReadActions4Ints(): done ambiguities", true);
247  config_->setActiveBandIdx(primaryBandIdx);
248  }
249  else
251  "::doPostReadActions4Ints(): check for ambiguities was not required");
252  //
253  //
255  {
257  "::doPostReadActions4Ints(): running clock break detections, early stage", true);
259  };
260  //
261  //
262  if (ap.doIonoCorrection4All_)
263  {
265  "::doPostReadActions4Ints(): adding ionospheric corrections", true);
267  };
268  //
269  //
270  if (ap.doOutliers_ || ap.doWeights_)
271  {
272  int numOfRestored, numOfEliminated;
273  //
274  // make a full solution:
277  parIdxs.clear();
282  else
284 
286  config_->setOpThreshold(3.0);
287  config_->setActiveBandIdx(primaryBandIdx);
290 // process(true, false);
291  //
292  //
293  if (ap.doWeights_)
294  doReWeighting();
295  else
296  process(true, false);
297  //
298 
299  if (ap.doOutliers_)
300  {
301  numOfRestored = numOfEliminated = 0;
302  do
303  {
304  if ((numOfRestored=restoreOutliers(primaryBandIdx)) && ap.doWeights_)
305  doReWeighting();
306  if ((numOfEliminated=eliminateOutliers(primaryBandIdx)) && ap.doWeights_)
307  doReWeighting();
308  }
309  while (numOfRestored + numOfEliminated);
310  };
311  //
314  {
318  process(true, false);
319  };
320  };
321  //
322  //
323  // restore pointers:
324 // delete config_;
325 // delete parametersDescriptor_;
326 // config_ = config_saved;
327 // parametersDescriptor_ = parametersDescriptor_saved;
328  //
329  config_->setOpThreshold(opThresholdSaved);
331  "::doPostReadActions4Ints(): processing the session " + name_ +
332  " in automatic mode has been finished");
333  //
334  //
335  // check the results:
337  {
339  "::doPostReadActions4Ints(): looks like the automatic mode has failed: the number of good obs (" +
340  QString("").setNum(primaryBand_->numProcessed(DT_DELAY)) +
341  ") is close to the number of parameters (" +
342  QString("").setNum(numOfParameters_) + ")");
343  return false;
344  };
345  if ((ap.doOutliers_ || ap.doWeights_) &&
347  {
349  "::doPostReadActions4Ints(): looks like the automatic mode has failed: the number of good obs (" +
350  QString("").setNum(primaryBand_->numProcessed(DT_DELAY)) +
351  ") is less than 30% of total observations (" +
352  QString("").setNum(observations_.size()) + ")");
353  return false;
354  };
355  if ((ap.doOutliers_ || ap.doWeights_) && 80.0 < primaryBand_->wrms(DT_DELAY)*1.0E12)
356  {
358  "::doPostReadActions4Ints(): looks like the automatic mode has failed: the WRMS (" +
359  QString("").setNum(primaryBand_->wrms(DT_DELAY)*1.0E12) + "ps) is too high");
360  return false;
361  };
362 
364  ap.doOutliers_ && ap.doWeights_)
366  return true;
367 };
368 
369 
370 
371 //
373 {
375  process(true, false);
376  double prevChi=primaryBand_->chi2(DT_DELAY);
377  double delta=1.0e-3;
378  int n, limit=7;
379  process(true, false);
380  n = 0;
381  while (delta<fabs(prevChi-primaryBand_->chi2(DT_DELAY)) && n<limit)
382  {
383  prevChi = primaryBand_->chi2(DT_DELAY);
384  process(true, false);
385  n++;
386  };
387  return n;
388 };
389 
390 
391 
392 //
394 {
395  // first, check the presence of reference clock station:
396  bool hasFound;
397  hasFound = false;
398  for (StationsByName_it it = stationsByName_.begin(); it!=stationsByName_.end(); ++it)
399  if (it.value()->isAttr(SgVlbiStationInfo::Attr_REFERENCE_CLOCKS))
400  hasFound = true;
401  if (hasFound)
402  {
404  "::pickupReferenceClocksStation(): a reference clock station was already set for the session");
405  return;
406  };
407  //
409  if (networkID_ == "INT")
410  refStations = clockRefStations4Int;
411  else if (networkID_ == "IVS-R4")
412  refStations = clockRefStations4R4;
413  int num=refStations.size(), idx;
414  SgVlbiStationInfo *stn=NULL;
415  idx = 0;
416  hasFound = false;
417  while (idx<num && !hasFound)
418  {
419  if ( (hasFound=stationsByName_.contains(refStations.at(idx))) )
420  stn = stationsByName_[refStations.at(idx)];
421  idx++;
422  };
423  if (!hasFound) // yet
424  {
425  stn = stationsByName_.begin().value();
427  "::pickupReferenceClocksStation(): cannot find any predefined stations in the session, "
428  "use first available one");
429  };
430  if (stn)
431  {
434  stn->setClocksModelOrder(0);
436  "::pickupReferenceClocksStation(): set a station " + stn->getKey() +
437  " as a reference clocks station");
438  }
439  else
441  "::pickupReferenceClocksStation(): no reference clocks station set for the session");
442 };
443 
444 
445 
446 //
447 void SgVlbiSession::setReferenceClocksStation(const QString& stnKey)
448 {
449  // first, check the presence of reference clock station:
450  if (!stationsByName_.contains(stnKey))
451  {
453  "::setReferenceClocksStation(): cannot find the station " + stnKey + " in the session");
454  return;
455  };
456  //
457  for (StationsByName_it it = stationsByName_.begin(); it!=stationsByName_.end(); ++it)
458  {
459  SgVlbiStationInfo *stn=it.value();
460  //
461  if (stn->isAttr(SgVlbiStationInfo::Attr_REFERENCE_CLOCKS) && stn->getKey()!=stnKey)
462  {
465  stn->setClocksModelOrder(3);
467  "::setReferenceClocksStation(): unset a station " + stn->getKey() +
468  " as a reference clocks station");
469  };
470  if (stn->getKey()==stnKey && !stn->isAttr(SgVlbiStationInfo::Attr_REFERENCE_CLOCKS))
471  {
474  stn->setClocksModelOrder(0);
476  "::setReferenceClocksStation(): set a station " + stn->getKey() +
477  " as a reference clocks station");
478  };
479  };
480 };
481 
482 
483 
484 //
486 {
488  int num=refStations.size(), idx;
489  bool hasFound;
490  SgVlbiStationInfo *stn=NULL;
491 
493  {
494  idx = 0;
495  hasFound = false;
496  while (idx<num && !hasFound)
497  {
498  if ( (hasFound=stationsByName_.contains(refStations.at(idx))) )
499  stn = stationsByName_[refStations.at(idx)];
500  idx++;
501  };
502  if (!hasFound) // yet
503  {
504  stn = stationsByName_.begin().value();
506  "::pickupReferenceCoordinatesStation(): cannot find any predefined stations in the session, "
507  "use the first available one");
508  };
509  if (stn)
510  {
513  "::pickupReferenceCoordinatesStation(): set a station " + stn->getKey() +
514  " as a reference coordinate station");
515  }
516  else
518  "::pickupReferenceCoordinatesStation(): no reference coordinate station set for the session");
519  };
520 };
521 
522 
523 
524 //
526 {
527  const QString stnBlockTag("+STATION_NOTES");
528  const QString phcBlockTag1("+MANUAL");
529  const QString phcBlockTag2("PCAL");
530  const QChar endBlockMark('+');
531  QRegExp endBlockMarkRx("^\\s*\\+");
532  const SgVlbiHistory& history=primaryBand_->history();
533 
534  QMap<QString, bool> manPhCal1_ByKey; // from stations report
535  QMap<QString, bool> manPhCal2_ByKey; // from "+MANUAL PCAL" string
536  QMap<QString, QString> keyByAbbr;
537  QMap<QString, QList<QString> >eventsByKey;
538  QString stnName, stnAbbr;
539  int idx;
540  bool hasFound;
541 
542  idx = 0;
543  hasFound = false;
544  // search station notes block:
545  while (idx<history.size() && !hasFound)
546  {
547  if (history.at(idx)->getText().contains(stnBlockTag))
548  hasFound = true;
549  idx++;
550  };
551  if (!hasFound)
552  {
554  "::checkUseOfManualPhaseCals(): cannot find station notes block in the history records");
555  return;
556  };
557  // parse it:
558  hasFound = false;
559  stnName = "";
560  stnAbbr = "";
561  QRegExp rx("^\\s*([A-Z0-9]{1}[-A-Z0-9_\\s]{1,7})\\s*[:]*\\s*"
562  "\\(([-A-Za-z0-9]{1,2})[-/]{1}([A-Za-z0-9]{1,2})\\):");
563  QString sa1(""), sa2("");
564  while (idx<history.size() && !hasFound)
565  {
566  const QString& str=history.at(idx)->getText();
567  if (str.indexOf(endBlockMarkRx) != -1)
568  hasFound = true;
569  else
570  {
571  if (str.indexOf(rx) != -1)
572  {
573  stnName = rx.cap(1);
574  sa1 = rx.cap(2);
575  sa2 = rx.cap(3);
576  // std::cout << "stnName: [" << qPrintable(stnName) << "]\n";
577  if (stnName.size() < 8)
578  stnName = stnName.leftJustified(8, ' ');
579  stnAbbr = (sa1.size()==2)?sa1:(sa2.size()==2?sa2:"");
580  if (stnAbbr == "")
582  "::checkUseOfManualPhaseCals(): cannot find stnAbbr, the pair is [" + sa1 +
583  "," + sa2 + "]");
584  else
585  {
586  keyByAbbr[stnAbbr] = stnName;
587  sa1 = str.right(str.size() - str.indexOf(':') - 1);
588  eventsByKey[stnName] << sa1;
589  };
590  }
591  else if (str.simplified().size()>0 && stnName.size()>0)
592  eventsByKey[stnName] << str.simplified();
593  };
594  idx++;
595  };
596  //
597  // check collected stuff:
598  if (keyByAbbr.size() != eventsByKey.size())
600  "::checkUseOfManualPhaseCals(): abbreviations and stations size mismatch");
601  for (StationsByName_it it=stationsByName_.begin(); it!=stationsByName_.end(); ++it)
602  if (!eventsByKey.contains(it.key()))
604  "::checkUseOfManualPhaseCals(): cannot find station " + it.key() +
605  " in the station notes block of the history records");
606  //
607  // debug output:
608  if (false)
609  {
610  std::cout << "Got: " << keyByAbbr.size() << " abbrs and " << eventsByKey.size() << " stns \n";
611  std::cout << " Abbrs: \n";
612  for (QMap<QString, QString>::iterator it=keyByAbbr.begin(); it!=keyByAbbr.end(); ++it)
613  std::cout << " abbr: [" << qPrintable(it.key()) << "], key: [" << qPrintable(it.value()) << "]\n";
614  std::cout << " Stns: \n";
615  for (QMap<QString, QList<QString> >::iterator it=eventsByKey.begin(); it!=eventsByKey.end(); ++it)
616  {
617  std::cout << " key: [" << qPrintable(it.key()) << "]: " << "\n";
618  const QList<QString> &lst=it.value();
619  for (int i=0; i<lst.size(); i++)
620  std::cout << " " << i << ": [" << qPrintable(lst.at(i)) << "]\n";
621  };
622  };
623  // eod
624  // check for manual phase calibration comments:
625  for (QMap<QString, QList<QString> >::iterator it=eventsByKey.begin(); it!=eventsByKey.end(); ++it)
626  {
627  const QString &sName=it.key();
628  const QList<QString> &lst=it.value();
629  for (int i=0; i<lst.size(); i++)
630  {
631  const QString &rec=lst.at(i);
632  if (rec.contains("manual", Qt::CaseInsensitive) &&
633  rec.contains("pcal", Qt::CaseInsensitive) &&
634  rec.contains("applied", Qt::CaseInsensitive)
635  )
636  manPhCal1_ByKey[sName] = true;
637  if (rec.contains("manual", Qt::CaseInsensitive) &&
638  rec.contains("phase", Qt::CaseInsensitive) &&
639  rec.contains("calibration", Qt::CaseInsensitive)&&
640  rec.contains("applied", Qt::CaseInsensitive)
641  )
642  manPhCal1_ByKey[sName] = true;
643  if (rec.contains("manual", Qt::CaseInsensitive) &&
644  rec.contains("phasecal",Qt::CaseInsensitive) &&
645  rec.contains("applied", Qt::CaseInsensitive)
646  )
647  manPhCal1_ByKey[sName] = true;
648  if (rec.contains("manual", Qt::CaseInsensitive) &&
649  rec.contains("phase", Qt::CaseInsensitive) &&
650  rec.contains("cal", Qt::CaseInsensitive) &&
651  rec.contains("applied", Qt::CaseInsensitive)
652  )
653  manPhCal1_ByKey[sName] = true;
654  };
655  if (manPhCal1_ByKey.contains(sName) && manPhCal1_ByKey[sName])
657  "::checkUseOfManualPhaseCals(): found manual phasecal record for " + sName +
658  " in the station block");
659  };
660  //
661  // search for manual ph.cal block:
662  QString phcStr;
663  // reset the index
664  if (!hasFound)
665  idx=0;
666  else
667  {
668  idx--;
669  hasFound = false;
670  };
671  //
672  while (idx<history.size() && !hasFound)
673  {
674  if (history.at(idx)->getText().contains(phcBlockTag1) &&
675  history.at(idx)->getText().contains(phcBlockTag2) )
676  {
677  phcStr = history.at(idx)->getText();
678  phcStr.replace(',', ' ');
679  hasFound = true;
680  }
681  idx++;
682  };
683  if (!hasFound)
685  "::checkUseOfManualPhaseCals(): cannot find manual phasecal block in the history records");
686  else
687  {
688  QStringList lst=phcStr.right(
689  phcStr.size() - phcStr.indexOf(phcBlockTag2) - phcBlockTag2.length()).
690  split(" ", QString::SkipEmptyParts);
691  for (int i=0; i<lst.size(); i++)
692  {
693  const QString &abbr=lst.at(i);
694  if (keyByAbbr.contains(abbr))
695  {
696  manPhCal2_ByKey[keyByAbbr[abbr]] = true;
698  "::checkUseOfManualPhaseCals(): the use of manual phasecal was mention for the station " +
699  keyByAbbr[abbr] + "(" + abbr + ") in the manual phasecal block");
700  }
701  else
703  "::checkUseOfManualPhaseCals(): cannot find station abbreviation " + abbr +
704  " in the station description block");
705  };
706  };
707  //
708  // compare two lists of stations with manual phase cals:
709  for (QMap<QString, bool>::const_iterator it=manPhCal1_ByKey.begin(); it!=manPhCal1_ByKey.end(); ++it)
710  if (!manPhCal2_ByKey.contains(it.key()))
711  {
712  // well, usually, they just forget to add the station, complain:
714  "::checkUseOfManualPhaseCals(): according to the station notes block manual phase cals "
715  "were applied to station " + it.key() + ", but it was not listed in the manual phasecal block");
716  // add it:
717  manPhCal2_ByKey[it.key()] = true;
718  };
719  // and the second list, just to check:
720  for (QMap<QString, bool>::const_iterator it=manPhCal2_ByKey.begin(); it!=manPhCal2_ByKey.end(); ++it)
721  {
722  const QString &sName=it.key();
723  if (!manPhCal1_ByKey.contains(sName))
724  // well, usually, they just forget to add the station, complain:
726  "::checkUseOfManualPhaseCals(): according to the manual phasecal block manual phase cals "
727  "were applied to station " + sName + ", but it was not mention in the station notes block");
728  if (stationsByName_.contains(sName))
729  {
732  "::checkUseOfManualPhaseCals(): cable calibrations for station " + sName +
733  " have been turned off because of applied manual phase calibrations");
734  }
735  else
737  "::checkUseOfManualPhaseCals(): cannot find station " + sName + " in the list of stations "
738  "of the session, cannot turn off cable cals for it");
739  };
740 };
741 
742 
743 
744 //
746 {
747  for (StationsByName_it it=stationsByName_.begin(); it!=stationsByName_.end(); ++it)
748  {
749  SgVlbiStationInfo *stn=it.value();
751  stn->setClocksModelOrder(0);
752  else
753  stn->setClocksModelOrder(n);
754  };
755 };
756 
757 
758 
759 //
761 {
762  bool isCbOccurred=false;
763  SgClockBreakAgent agent;
764  QList<SgClockBreakAgent*> cbas, existedCBs;
765  QList<SgClockBreakAgent*> cbAgents;
766  QList<SgVlbiStationInfo*> stations;
768  parIdxs;
769  int primaryBandIdx=-1;
770  double wrms_0;
771 
772  for (int i=0; i<bands_.size(); i++)
773  if (bands_.at(i)->getKey() == primaryBand_->getKey())
774  primaryBandIdx = i;
775  if (primaryBandIdx<0)
776  {
778  "::check4ClockBreaksAtSBD(): cannot find an index of the primary band, check failed");
779  return false;
780  };
781 
782  cbas << &agent;
783 
784  if (stationsByName_.size() == 2) // one baseline, only one station need to be checked
785  {
786  for (StationsByName_it it=stationsByName_.begin(); it!=stationsByName_.end(); ++it)
787  if (!it.value()->isAttr(SgVlbiStationInfo::Attr_REFERENCE_CLOCKS))
788  stations << it.value();
789  }
790  else // otherwice, take all staitons into the list:
791  for (StationsByName_it it=stationsByName_.begin(); it!=stationsByName_.end(); ++it)
792  if (!it.value()->isAttr(SgVlbiStationInfo::Attr_NOT_VALID)) // well, at this stage there should no
793  // be excluded stations, but who knows
794  stations << it.value();
795  //
796  // obtain a solution:
798  config_->setActiveBandIdx(primaryBandIdx);
800  parIdxs.clear();
803  process(true, false);
804  //
805  //
806  eliminateOutliersSimpleMode(primaryBandIdx, (int)(observations_.size()*0.20), 7.0, 30.0e-9);
807  //
808  //
809  wrms_0 = primaryBand_->wrms(DT_DELAY);
811  "::check4ClockBreaksAtSBD(): got a first SB solution", true);
812  //
813  //
814  // pick up existing clock breaks:
815  for (StationsByName_it it=stationsByName_.begin(); it!=stationsByName_.end(); ++it)
816  {
817  SgVlbiStationInfo *stn=it.value();
818  SgBreakModel &breakModel=stn->clockBreaks();
819  for (int brkIdx=0; brkIdx<breakModel.size(); brkIdx++)
820  {
821  SgParameterBreak *brk=breakModel.at(brkIdx);
823  cbAgent->epoch_ = *brk;
824  cbAgent->stn_ = stn;
825  existedCBs << cbAgent;
826  };
827  };
828  //
829  // there is no sence to process each band separately for the single band delays
830  for (int j=0; j<stations.size(); j++)
831  {
832  SgVlbiStationInfo *stn=stations.at(j);
834  "::check4ClockBreaksAtSBD(): processing " + stn->getKey() + " station", true);
835  for (QMap<QString, SgVlbiAuxObservation*>::iterator it=stn->auxObservationByScanId()->begin();
836  it!=stn->auxObservationByScanId()->end(); ++it)
837  {
838  if (it.value()->isAttr(SgVlbiAuxObservation::Attr_PROCESSED))
839  {
840  SgMJD t=*it.value();
841  agent.epoch_ = t;
842  agent.stn_ = stn;
843  agent.shift_ = 0.0;
844  agent.sigma_ = 0.0;
845  if (existedCBs.size())
846  {
847  cbas.clear();
848  cbas << existedCBs;
849  cbas << &agent;
850  };
852  if (agent.sigma_>0.0 && fabs(agent.shift_/agent.sigma_)>5.0 && fabs(agent.shift_)>5.0e-9)
853  {
855  cba->epoch_ = t;
856  cba->stn_ = stn;
857  cba->shift_ = agent.shift_;
858  cba->sigma_ = agent.sigma_;
859  cbAgents << cba;
860  };
861  };
862  };
863  };
864  //
865  //
866  if (cbAgents.size() > 0)
867  {
868  cbas.clear();
869  QMap< QString, QList<SgClockBreakAgent*> >
870  cbasByStn;
871  for (int i=0; i<cbAgents.size(); i++)
872  {
873  SgClockBreakAgent *cba=cbAgents.at(i);
874  cbasByStn[cba->stn_->getKey()] << cba;
875  };
876  for (QMap< QString, QList<SgClockBreakAgent*> >::iterator it=cbasByStn.begin();
877  it!=cbasByStn.end(); ++it)
878  {
879  SgClockBreakAgent *a=NULL;
880  double d=0.0;
881  QList<SgClockBreakAgent*>&l=it.value();
882  for (int i=0; i<l.size(); i++)
883  if (l.at(i)->sigma_>0.0 && fabs(l.at(i)->shift_/l.at(i)->sigma_)>d)
884  {
885  a = l.at(i);
886  d = fabs(l.at(i)->shift_/l.at(i)->sigma_);
887  };
888  if (a && d>0.0)
889  cbas << a;
890  };
891  SgClockBreakAgent *a=NULL;
892  double d=0.0;
893  for (int i=0; i<cbas.size(); i++)
894  if (cbas.at(i)->sigma_>0.0 && fabs(cbas.at(i)->shift_/cbas.at(i)->sigma_)>d)
895  {
896  a = cbas.at(i);
897  d = fabs(cbas.at(i)->shift_/cbas.at(i)->sigma_);
898  };
899  if (a && d>0.0) // ok, this is our break
900  {
901  correctClockBreak(primaryBand_, a->stn_, a->epoch_, round(1.0E9*a->shift_), false, false);
903  "::check4ClockBreaksAtSBD(): running additional solutions to "
904  "check an effect of the clock break");
905  process(true, false);
907  "::check4ClockBreaksAtSBD(): finished; old WRMS were " +
908  QString("").sprintf("%.3fps", wrms_0*1.0e12) + ", the new WRMS are " +
909  QString("").sprintf("%.3fps", primaryBand_->wrms(DT_DELAY)*1.0e12));
910  if (wrms_0/primaryBand_->wrms(DT_DELAY) > 2.0)
912  else
913  {
915  "::check4ClockBreaksAtSBD(): the clock break looks like not real, removing it");
916  a->stn_->clockBreaks().delBreak(a->epoch_);
917  };
918  };
919  };
920 
921  isCbOccurred = false;
922  for (StationsByName_it it=stationsByName_.begin(); it!=stationsByName_.end(); ++it)
923  if (!it.value()->isAttr(SgVlbiStationInfo::Attr_NOT_VALID) &&
924  it.value()->clockBreaks().size()>0)
925  {
926  SgVlbiStationInfo *si=it.value();
927  isCbOccurred = true;
929  "::check4ClockBreaksAtSBD(): detected SB clock break(s) at the station " +
930  si->getKey());
931  for (int i=0; i<si->clockBreaks().size(); i++)
932  {
933  SgParameterBreak *pb=si->clockBreaks().at(i);
935  "::check4ClockBreaksAtSBD(): on " + pb->toString(SgMJD::F_Simple) + " with magnitude " +
936  QString("").sprintf("%.2fps", pb->getA0()*1.0e12));
937  };
938  };
939  return isCbOccurred;
940 };
941 
942 
943 
944 //
945 
946 /*=====================================================================================================*/
947 
948 
949 
950 
951 
952 
953 /*=====================================================================================================*/
954 //
955 // FRIENDS:
956 //
957 /*=====================================================================================================*/
958 //
959 
960 
961 
962 /*=====================================================================================================*/
963 //
964 // aux functions:
965 //
966 
967 /*=====================================================================================================*/
969  clockRefStations4Int(QList<QString>() << "KOKEE " << "TSUKUB32"),
970  clockRefStations4R4 (QList<QString>() << "KOKEE " << "WETTZELL" << "NYALES20"),
971  clockRefStations4Gen(QList<QString>() << "KOKEE " << "WETTZELL" << "NYALES20" << "TSUKUB32");
972 
974  coordRefStations4Gen(QList<QString>() << "WETTZELL" << "KOKEE " << "WESTFORD" << "NYALES20"
975  << "HOBART26" << "HARTRAO " << "ONSALA60"
976  );
977 
978 /*=====================================================================================================*/
SgLogger * logger
Definition: SgLogger.cpp:231
QMap< QString, SgVlbiBaselineInfo * >::iterator BaselinesByName_it
const QString defaultNetIdName
QList< QString > clockRefStations4R4
QList< QString > clockRefStations4Int
QList< QString > coordRefStations4Gen
QList< QString > clockRefStations4Gen
QMap< QString, SgVlbiStationInfo * >::iterator StationsByName_it
@ DT_DELAY
Definition: SgWrmsable.h:44
bool isAttr(uint a) const
Definition: SgAttribute.h:226
void delAttr(uint a)
Definition: SgAttribute.h:210
void addAttr(uint a)
Definition: SgAttribute.h:202
bool delBreak(const SgMJD &t)
SgVlbiStationInfo * stn_
Definition: SgVlbiSession.h:65
virtual void write(LogLevel, quint32, const QString &, bool=false)
Definition: SgLogger.cpp:88
@ PREPROC
Definition: SgLogger.h:98
Definition: SgMJD.h:59
@ F_Simple
Digits: 2010/04/02 17:02:43.6.
Definition: SgMJD.h:68
QString toString(Format format=F_Verbose) const
Definition: SgMJD.cpp:1008
const QString & getKey() const
Definition: SgObjectInfo.h:319
int numProcessed(DataType dType) const
Definition: SgObjectInfo.h:351
double chi2(DataType) const
Definition: SgObjectInfo.h:415
double wrms(DataType) const
Definition: SgObjectInfo.h:567
@ Attr_PROCESSED
the observation has been processed;
Definition: SgObservation.h:79
double getA0() const
Definition: SgBreakModel.h:363
void setMode4Parameter(SgParameterCfg::PMode, ParIdx)
void setMode4Parameters(SgParameterCfg::PMode, const QList< ParIdx > &)
@ Idx_CLOCK_1
index for clocks (order #1)
@ Idx_POLUSUT1
index for EOP: d(UT1-UTC)
@ Idx_BL_LENGTH
index for baseline length
@ Idx_ZENITH
index for wet zenith delay
@ Idx_CLOCK_0
index for clocks (order #0)
void setDoWeightCorrection(bool)
bool getIsSolveCompatible() const
Definition: SgTaskConfig.h:913
void setOpThreshold(double)
QMap< QString, AutomaticProcessing > & apByNetId()
Definition: SgTaskConfig.h:637
void setActiveBandIdx(int)
void setOpMode(OutliersProcessingMode)
double getOpThreshold() const
Definition: SgTaskConfig.h:993
void setUseDelayType(VlbiDelayType)
int getInputFileVersion() const
Definition: SgVlbiBand.h:344
SgVlbiHistory & history()
Definition: SgVlbiBand.h:360
const QString & getName() const
@ Attr_FF_AUTOPROCESSED
automatic data processing performed successfully;
QString networkID_
Network ID (a key);.
QString name_
name of the session (e.g., 10JUL22XE);
StationsByName stationsByName_
QList< SgVlbiBand * > & bands()
QList< SgVlbiBand * > bands_
void calculateIonoCorrections(const SgTaskConfig *)
int restoreOutliers(int bandIdx)
QList< SgVlbiObservation * > observations_
void process(bool haveProcessAllBands, bool interactWithGui)
void scanBaselines4GrDelayAmbiguities(int bandIdx)
void resetAllEditings(bool have2resetConfig)
void correctClockBreak(SgVlbiBand *, SgVlbiStationInfo *, const SgMJD &, double, double, bool, bool=true)
void calculateClockBreaksParameters(QList< SgClockBreakAgent * > &, SgVlbiBand *)
bool doPostReadActions4Ints(const SgTaskConfig::AutomaticProcessing &)
BaselinesByName baselinesByName_
SgParametersDescriptor * parametersDescriptor_
SgVlbiBand * primaryBand_
int eliminateOutliers(int bandIdx)
void eliminateOutliersSimpleMode(int bandIdx, int maxNumOfPasses, double threshold, double=0.0)
static QString className()
void setReferenceClocksStation(const QString &stnKey)
SgTaskConfig * config_
QMap< QString, SgVlbiAuxObservation * > * auxObservationByScanId()
@ Attr_NOT_VALID
omit the station;
@ Attr_REFERENCE_CLOCKS
the clocks are the reference ones;
@ Attr_IGNORE_CABLE_CAL
do not apply cable calibration;
@ Attr_ESTIMATE_COO
estimate station position;
SgBreakModel & clockBreaks()
void setClocksModelOrder(int n)