General Purpose Geodetic Library
SgVlbiSessionUtilities.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 #include <SgVlbiSession.h>
27 
28 
29 #if QT_VERSION >= 0x050000
30 # include <QtWidgets/QMessageBox>
31 #else
32 # include <QtGui/QMessageBox>
33 #endif
34 
35 
36 #include <QtCore/QTextStream>
37 #include <QtCore/QFile>
38 
39 
40 #include <SgCubicSpline.h>
41 #include <SgEstimator.h>
42 #include <SgLogger.h>
44 #include <SgSolutionReporter.h>
45 #include <SgTaskManager.h>
46 #include <SgVector.h>
47 #include <SgVlbiBand.h>
48 #include <SgVlbiObservation.h>
49 
50 
51 #define LOCAL_DEBUG
52 
53 
54 
55 
56 // sorts obs by residuals:
58 
59 
60 
61 /*=======================================================================================================
62 *
63 * METHODS:
64 *
65 *======================================================================================================*/
66 //
68 {
69  bool stnPosRead, stnVelRead, srcPosRead, srcSmRead, axsOfsRead, hiFyEopRead,
70  stnGrdRead, extErpRead;
71  QString path2efaStnPos(config_->evaluatePath2(path2APrioriFiles_,
73  QString path2efaStnVel(config_->evaluatePath2(path2APrioriFiles_,
75  QString path2efaSrcPos(config_->evaluatePath2(path2APrioriFiles_,
77  QString path2efaSrcSsm(config_->evaluatePath2(path2APrioriFiles_,
79  QString path2efaAxsOfs(config_->evaluatePath2(path2APrioriFiles_,
81  QString path2efaHiFyEop(config_->evaluatePath2(path2APrioriFiles_,
83  QString path2efaStnGrd(config_->evaluatePath2(path2APrioriFiles_,
85  QString path2extErp(config_->evaluatePath2(path2APrioriFiles_,
87 
88  stnPosRead = stnVelRead = srcPosRead = srcSmRead = axsOfsRead = hiFyEopRead = stnGrdRead =
89  extErpRead = false;
90 
91  hiFyEopRead = (0<apHiFyEop_.getFileName().size() && apHiFyEop_.isOk());
92  // check for others too:
93 
94 
95 
96 
97  //
98  // read external sites position file:
99  if (path2efaStnPos != apStationPositions_.getFileName())
100  {
101  apStationPositions_.readFile(path2efaStnPos);
102  stnPosRead = true;
104  "::collectAPriories(): load from the file " + apStationPositions_.getFileName() +
105  QString("").sprintf(" %d", apStationPositions_.size()) + " records of a priori sites positions");
106  };
107  // read external sites velocities file:
108  if (path2efaStnVel != apStationVelocities_.getFileName())
109  {
110  apStationVelocities_.readFile(path2efaStnVel);
111  stnVelRead = true;
113  "::collectAPriories(): load from the file " + apStationVelocities_.getFileName() +
114  QString("").sprintf(" %d", apStationVelocities_.size()) + " records of a priori sites velocities");
115  };
116  // read external source positions file:
117  if (path2efaSrcPos != apSourcePositions_.getFileName())
118  {
119  apSourcePositions_.readFile(path2efaSrcPos);
120  srcPosRead = true;
122  "::collectAPriories(): load from the file " + apSourcePositions_.getFileName() +
123  QString("").sprintf(" %d", apSourcePositions_.size()) + " records of a priori sources positions");
124  };
125  // read external source ssm file:
126  if (path2efaSrcSsm != apSourceStrModel_.getFileName())
127  {
128  apSourceStrModel_.readFile(path2efaSrcSsm);
129  srcSmRead = true;
131  "::collectAPriories(): load from the file " + apSourceStrModel_.getFileName() +
132  QString("").sprintf(" %d", apSourceStrModel_.size()) + " records of source structure model");
133  };
134  // read external axis offsets file:
135  if (path2efaAxsOfs != apAxisOffsets_.getFileName())
136  {
137  apAxisOffsets_.readFile(path2efaAxsOfs);
138  axsOfsRead = true;
140  "::collectAPriories(): load from the file " + apAxisOffsets_.getFileName() +
141  QString("").sprintf(" %d", apAxisOffsets_.size()) + " records of a priori axis offsets");
142  };
143  // read external high frequency ERP file:
144  if (path2efaHiFyEop != apHiFyEop_.getFileName())
145  {
146  apHiFyEop_.readFile(path2efaHiFyEop);
147  hiFyEopRead = true;
149  "::collectAPriories(): load from the file " + apHiFyEop_.getFileName() + " model of hi frequency EOP");
150  };
151  // read external mean sites gradients file:
152  if (path2efaStnGrd != apStationGradients_.getFileName())
153  {
154  apStationGradients_.readFile(path2efaStnGrd);
155  stnGrdRead = true;
157  "::collectAPriories(): load from the file " + apStationGradients_.getFileName() +
158  QString("").sprintf(" %d", apStationGradients_.size()) +
159  " records of a priori mean sites gradients");
160  };
161  // read external ERP file:
163  path2extErp != externalErpFile_.getFileName())
164  {
166  extErpRead = true;
168  "::collectAPriories(): read " + QString("").setNum(numOfPts4ErpInterpolation_) +
169  " records from the external a priori ERP file " + externalErpFile_.getFileName() +
170  "; mean epoch: " + tMean_.toString());
171  };
172  // End of reading external files.
174  "::collectAPriories(): files with external a priori were read", true);
175 
176  // Update info:
177  //
178  // first, check stations:
179  SgAPrioriRec *apRec=NULL;
180  for (StationsByName_it it=stationsByName_.begin(); it!=stationsByName_.end(); ++it)
181  {
182  SgVlbiStationInfo *si=it.value();
183  // process coordinates and velocities:
184  if (apStationPositions_.size() && apStationVelocities_.size() && (stnPosRead || stnVelRead))
185  {
187  if (apRec)
188  {
190  si->setR_ea(Sg3dVector(apRec->at(0).getDvalue("0"), apRec->at(0).getDvalue("1"),
191  apRec->at(0).getDvalue("2")));
193  "::collectAPriories(): set up external a priori coords for station " +
194  si->getKey() + "; the diff is " +
195  QString("").sprintf("%.1f mm", (si->getR() - si->getR_ea()).module()*1.0e3) +
196  "; tSince: " + apRec->getTsince().toString());
197  }
198  else
199  {
202  "::collectAPriories(): cannot find station " + si->getKey() +
203  " in the list of a priori coordinates");
204  si->setR_ea(si->getR());
205  };
207  if (apRec)
208  si->setV_ea(Sg3dVector(apRec->at(0).getDvalue("0"), apRec->at(0).getDvalue("1"),
209  apRec->at(0).getDvalue("2")));
210  else
211  {
214  "::collectAPriories(): cannot find station " + si->getKey() +
215  " in the list of a priori velocities");
216  si->setV_ea(v3Zero);
217  };
218  };
219  // process external axis offsets:
220  if (apAxisOffsets_.size() && axsOfsRead)
221  {
222  if ((apRec=apAxisOffsets_.lookupApRecord(si->getKey())))
223  {
225  // set up a posteriori value:
226  si->setAxisOffset_ea(apRec->at(0).getDvalue("1")); // from estimation
228  "::collectAPriories(): set an external a priori axis offset for station " +
229  si->getKey() + "; the diff is " +
230  QString("").sprintf("%.1f mm", (si->getAxisOffset() - si->getAxisOffset_ea())*1.0e3));
231  // check the value from the database and the "a priori" column (==0):
232  if (fabs(si->getAxisOffset() - apRec->at(0).getDvalue("0")) > 1.0e-4)
234  "::collectAPriories(): a priori axis offset for station " + si->getKey() +
235  QString("").sprintf(" has different value in the database (%.1f mm) and "
236  "the external file (%.1f mm)", si->getAxisOffset()*1.0e3, apRec->at(0).getDvalue("0")*1.0e3));
237  }
238  else
239  {
242  "::collectAPriories(): cannot find station " + si->getKey() +
243  " in the list of a priori axis offsets");
244  si->setAxisOffset_ea(si->getAxisOffset());
245  };
246  };
247  // process external mean sites gradients:
248  if (apStationGradients_.size() && stnGrdRead)
249  {
250  if ((apRec=apStationGradients_.lookupApRecord(si->getKey())))
251  {
252  // set up a priori values:
253  si->setGradNorth(apRec->at(0).getDvalue("0"));
254  si->setGradEast (apRec->at(0).getDvalue("1"));
256  "::collectAPriories(): a priori gradients " + QString("").sprintf("(%6.2f and %6.1f mm)",
257  si->getGradNorth()*1000.0, si->getGradEast()*1000.0) +
258  " have been set up for station " + si->getKey());
259  }
260  else
262  "::collectAPriories(): cannot find station " + si->getKey() +
263  " in the list of a priori mean site gradients");
264  };
265  // end of station loop
266  };
268  "::collectAPriories(): the stations were done", true);
269  //
270  // then sources:
271  if ( (apSourcePositions_.size() && srcPosRead) ||
272 // (apSourceStrModel_.size() && srcSmRead)
273  srcSmRead )
274  {
275  for (SourcesByName_it it=sourcesByName_.begin(); it!=sourcesByName_.end(); ++it)
276  {
277  SgVlbiSourceInfo *si=it.value();
278  // positions:
279  if ((apRec=apSourcePositions_.lookupApRecord(si->getKey())))
280  {
282  si->setRA_ea(apRec->at(0).getDvalue("0"));
283  si->setDN_ea(apRec->at(0).getDvalue("1"));
284  si->setAprioriComments(apRec->getComments());
286  si->getRA_ea(), si->getDN_ea()));
288  "::collectAPriories(): set up external a priori coords for source " + si->getKey() +
289  "; the diff is " + QString("").sprintf("%.3f mas",
290  si->getAl2ExtA()*RAD2MAS));
291  }
292  else
293  {
296  "::collectAPriories(): cannot find source " + si->getKey() +
297  " in the list of a priori coordinates");
299  si->setRA_ea(si->getRA());
300  si->setDN_ea(si->getDN());
301  si->setAprioriComments("");
302  si->setAl2ExtA(0.0);
303  };
304  // SSM:
305  // clear the existing model:
306  if (si->sModel().size())
307  si->clearSrcStructPoints();
308  if ((apRec=apSourceStrModel_.lookupApRecord(si->getKey(), tStart_)))
309  {
310  for (int i=0; i<apRec->size(); i++)
311  {
312  double x, y, k, b;
313  bool er, ek, eb;
314  x = y = k = b = 0.0;
315  er = ek = eb = false;
316  x = apRec->at(i).getDvalue("MP_X");
317  y = apRec->at(i).getDvalue("MP_Y");
318  k = apRec->at(i).getDvalue("MP_K");
319  b = apRec->at(i).getDvalue("MP_B");
320  er= apRec->at(i).getBvalue("MP_ER");
321  ek= apRec->at(i).getBvalue("MP_EK");
322  eb= apRec->at(i).getBvalue("MP_EB");
323 /*
324  if (fabs(x) < 1.0e-6 && fabs(y) < 1.0e-6)
325  logger->write(SgLogger::WRN, SgLogger::IO_TXT | SgLogger::FLY_BY, className() +
326  "::collectAPriories(): cannot add SSM for the source \"" + si->getKey() +
327  "\": x and y are zeros");
328  else if (!(0.0 < k && k < 1.0))
329  logger->write(SgLogger::WRN, SgLogger::IO_TXT | SgLogger::FLY_BY, className() +
330  "::collectAPriories(): cannot add SSM for the source \"" + si->getKey() +
331  "\": k is out of range");
332  else
333 */
334  // check for usable values; a user can turn off a model if k==0:
335  if ((1.0e-6 < fabs(x) || 1.0e-6 < fabs(y)) && 0.0 < k && k < 1.0)
336  si->addSrcStructPoint(k, b, x/RAD2MAS, y/RAD2MAS, ek, eb, er);
337  };
339  "::collectAPriories(): found " + QString("").setNum(apRec->size()) +
340  "-component multipoint SS model for the source \"" + si->getKey() + "\"");
341  }
342  else
343  {
344 // logger->write(SgLogger::WRN, SgLogger::IO_TXT | SgLogger::FLY_BY, className() +
345 // "::collectAPriories(): cannot find source " + si->getKey() +
346 // " in the list of SSM");
347  };
348  };
349  };
351  "::collectAPriories(): the sources were done", true);
352 
353 
354  // ERP:
355  // if (extErpRead && externalErpFile_.isOk())
358  {
361  "::collectAPriories(): ERP were prepared for interpolation", true);
362  }
363  else
365  "::collectAPriories(): cannot make ERP interpolation: data are not provided", true);
366 
367  // and individual observations:
368  QString str;
369  double dT, t;
370  dT = (getLeapSeconds() + 32.184)/DAY2SEC;
371  for (int iObs=0; iObs<observations_.size(); iObs++)
372  {
373  SgVlbiObservation *obs=observations_.at(iObs);
374  double dUt, dPx, dPy, dCx, dCy;
375  double ut0i, px0i, py0i;
376  double ut0e, px0e, py0e;
377  double cx0e, cy0e;
378  double r;
379  dUt = dPx = dPy = dCx = dCy = 0.0;
380  t = obs->toDouble() + dT;
381  //
382  // external HiFrequency ERP model:
383  if (hiFyEopRead)
384  {
385  apHiFyEop_.calcCorrections(*obs+dT, dUt, dPx, dPy);
386  dUt /= 1.0e6*DAY2SEC;
387  dPx /= 1.0e3*RAD2MAS;
388  dPy /= 1.0e3*RAD2MAS;
389  /*
390  obs->setAprioriUt1HfContrib(dUt);
391  obs->setAprioriPxHfContrib(dPx);
392  obs->setAprioriPyHfContrib(dPy);
393  */
394  obs->setExtDelayHiFyPxy((obs->getDdel_dPx()*dPx + obs->getDdel_dPy()*dPy));
395  obs->setExtDelayHiFyUt1( obs->getDdel_dUT1()*dUt );
396  obs->setExtRateHiFyPxy ((obs->getDrat_dPx()*dPx + obs->getDrat_dPy()*dPy));
397  obs->setExtRateHiFyUt1 ( obs->getDrat_dUT1()*dUt );
398  // make it SOLVE-compatible:
399  obs->setAprioriUt1HfContrib(0.0);
400  obs->setAprioriPxHfContrib(0.0);
401  obs->setAprioriPyHfContrib(0.0);
402  }
403  else
404  {
405 std::cout << " -- no HF calculated\n";
406  /*
407  // need to add a priori HF from database too:
408  // ... later ...
409  obs->setAprioriUt1HfContrib(dUt);
410  obs->setAprioriPxHfContrib(dPx);
411  obs->setAprioriPyHfContrib(dPy);
412  */
413  obs->setExtDelayHiFyPxy(0.0);
414  obs->setExtDelayHiFyUt1(0.0);
415  obs->setExtRateHiFyPxy (0.0);
416  obs->setExtRateHiFyUt1 (0.0);
417  };
418  //
419  obs->setAprioriUt1HfContrib(dUt);
420  obs->setAprioriPxHfContrib(dPx);
421  obs->setAprioriPyHfContrib(dPy);
422  //
423  // external ERP a priori:
425  {
431 
432  ut0i = innerUt1Interpolator_->spline(t, 0, r)/DAY2SEC;
433  px0i = innerPxyInterpolator_->spline(t, 0, r)/RAD2MAS;
434  py0i = innerPxyInterpolator_->spline(t, 1, r)/RAD2MAS;
435  //
436  dUt = ut0e - ut0i;
437  dPx = px0e - px0i;
438  dPy = py0e - py0i;
439  dCx = cx0e;
440  dCy = cy0e;
441  //
443  {
444  obs->setExtDelayErp(obs->getDdel_dUT1()*dUt +
445  obs->getDdel_dPx() *dPx + obs->getDdel_dPy() *dPy +
446  obs->getDdel_dCipX()*dCx + obs->getDdel_dCipY()*dCy);
447  obs->setExtRateErp (obs->getDrat_dUT1()*dUt +
448  obs->getDrat_dPx() *dPx + obs->getDrat_dPy() *dPy +
449  obs->getDrat_dCipX()*dCx + obs->getDrat_dCipY()*dCy);
450  obs->setAprioriUt1LfContrib(ut0e);
451  obs->setAprioriPxLfContrib(px0e);
452  obs->setAprioriPyLfContrib(py0e);
453  obs->setAprioriCxLfContrib(cx0e);
454  obs->setAprioriCyLfContrib(cy0e);
455  }
456  else
457  {
458  obs->setExtDelayErp(0.0);
459  obs->setExtRateErp (0.0);
460  obs->setAprioriUt1LfContrib(ut0i);
461  obs->setAprioriPxLfContrib(px0i);
462  obs->setAprioriPyLfContrib(py0i);
463  };
464  }
465  else
466  {
467  obs->setExtDelayErp(0.0);
468  obs->setExtRateErp (0.0);
470  {
471  ut0i = innerUt1Interpolator_->spline(t, 0, r)/DAY2SEC;
472  obs->setAprioriUt1LfContrib(ut0i);
473  };
475  {
476  px0i = innerPxyInterpolator_->spline(t, 0, r)/RAD2MAS;
477  py0i = innerPxyInterpolator_->spline(t, 1, r)/RAD2MAS;
478  obs->setAprioriPxLfContrib(px0i);
479  obs->setAprioriPyLfContrib(py0i);
480  };
481  };
482  };
483  if (hiFyEopRead)
485  "::collectAPriories(): the observations have been updated with external model "
486  "of high frequency EOP variations");
488  "::collectAPriories(): the observations were done", true);
489 };
490 
491 
492 
493 //
495  double& vUt1, double& rUt1,
496  double& vPx, double& rPx, double& vPy, double& rPy,
497  double& vCx, double& rCx, double& vCy, double& rCy)
498 {
499  vUt1 = rUt1 = vPx = rPx = vPy = rPy = vCx = rCx = vCy = rCy = 0.0;
500  double dT, t;
501  dT = (getLeapSeconds() + 32.184)/DAY2SEC;
502  t = epoch.toDouble() + dT;
503 
505  {
511  }
512  else
513  {
514  vUt1= innerUt1Interpolator_->spline(t, 0, rUt1);
515  vPx = innerPxyInterpolator_->spline(t, 0, rPx );
516  vPy = innerPxyInterpolator_->spline(t, 1, rPy );
517  };
518  vUt1/= DAY2SEC;
519  rUt1/= DAY2SEC;
520  vPx /= RAD2MAS;
521  rPx /= RAD2MAS;
522  vPy /= RAD2MAS;
523  rPy /= RAD2MAS;
524  vCx /= RAD2MAS;
525  rCx /= RAD2MAS;
526  vCy /= RAD2MAS;
527  rCy /= RAD2MAS;
529  "::getAprioriErp(): the ERP apriori for the epoch " + (epoch + dT).toString() + " are:");
531  "::getAprioriErp(): ut1: " +
532  QString("").sprintf("%12.6fms %12.6fms/d", vUt1*1.0e3*DAY2SEC, rUt1*1.0e3*DAY2SEC));
534  "::getAprioriErp(): p_x: " +
535  QString("").sprintf("%12.6fmas %12.6fmas/d", vPx*RAD2MAS, rPx*RAD2MAS));
537  "::getAprioriErp(): p_y: " +
538  QString("").sprintf("%12.6fmas %12.6fmas/d", vPy*RAD2MAS, rPy*RAD2MAS));
540  "::getAprioriErp(): CIP_x: " +
541  QString("").sprintf("%12.6fmas %12.6fmas/d", vCx*RAD2MAS, rCx*RAD2MAS));
543  "::getAprioriErp(): CIP_y: " +
544  QString("").sprintf("%12.6fmas %12.6fmas/d", vCy*RAD2MAS, rCy*RAD2MAS));
545 };
546 
547 
548 
549 //
551 {
553  if (path2file != externalWeights_.getFileName())
554  externalWeights_.readFile(path2file);
555 };
556 
557 
558 
559 //
561 {
562 
566  delete innerUt1Interpolator_;
568  delete innerPxyInterpolator_;
570  innerUt1Interpolator_ = NULL;
571  innerPxyInterpolator_ = NULL;
572 
573 
574  if (externalErpFile_.isOk())
578 
579  // feed the interpolators:
581  "::prepare4ErpInterpolation(): the spliners were created", true);
582  int n;
583  //
584  // UT1:
585  n = args4Ut1Interpolation_->n();
586  for (int i=0; i<n; i++)
587  {
590  };
591  // Polar motion:
592  n = args4PxyInterpolation_->n();
593  for (int i=0; i<n; i++)
594  {
598  };
600  "::prepare4ErpInterpolation(): the inner interpolator has been fed", true);
601 
602  if (externalErpFile_.isOk())
603  {
604  double utOffset = 0.0;
607  {
608  utOffset = getLeapSeconds();
610  "::prepare4ErpInterpolation(): UT1-UTC will be adjusted by " + QString("").setNum(utOffset) +
611  " secs to get TAI", true);
612  };
613  // External table, UT1 and PM are in one file:
614  n = externalErpFile_.argument()->n();
615  for (int i=0; i<n; i++)
616  {
630  {
637  };
638  };
640  "::prepare4ErpInterpolation(): the outer interpolator has been fed", true);
641  //
643  {
645  "::prepare4ErpInterpolation(): database and external file UT1 types mismatch!"
646  " Trying to adjust, however, it was not tested.");
647 
648  // mimic SOLVE's flybymap.f behavior:
651 
652  for (unsigned int i=0; i<innerUt1Interpolator_->argument().n(); i++)
653  innerUt1Interpolator_->table()(i, 0) -=
655  for (unsigned int i=0; i<externalErpInterpolator_->argument().n(); i++)
659  "::prepare4ErpInterpolation(): the UT1type has been adjusted", true);
660  };
662  "::prepare4ErpInterpolation(): the UT1type was checked", true);
663  };
664  //
667  if (externalErpFile_.isOk())
670  "::prepare4ErpInterpolation(): the spliners were prepared", true);
671 
674 
675  /*
676  for (int i=0; i<innerUt1Interpolator_->numOfRecords(); i++)
677  {
678  QString str;
679  str.sprintf("%2d %14.6f %14.6f",
680  i, innerUt1Interpolator_->argument().getElement(i),
681  innerUt1Interpolator_->table().getElement(i, 0));
682  std::cout << qPrintable(str) << "\n";
683  };
684  std::cout << "PM table of interpolation from the database:\n";
685  for (int i=0; i<innerPxyInterpolator_->numOfRecords(); i++)
686  {
687  QString str;
688  str.sprintf("%2d %14.6f %14.6f %14.6f",
689  i, innerPxyInterpolator_->argument().getElement(i),
690  innerPxyInterpolator_->table().getElement(i, 0),
691  innerPxyInterpolator_->table().getElement(i, 1));
692  std::cout << qPrintable(str) << "\n";
693  };
694  std::cout << "ERP table of interpolation from the external file:\n";
695  for (int i=0; i<externalErpInterpolator_->numOfRecords(); i++)
696  {
697  QString str;
698  str.sprintf("%2d %14.6f %14.6f %14.6f %14.6f",
699  i, externalErpInterpolator_->argument().getElement(i),
700  externalErpInterpolator_->table().getElement(i, SgExternalErpFile::UT1_IDX),
701  externalErpInterpolator_->table().getElement(i, SgExternalErpFile::PMX_IDX),
702  externalErpInterpolator_->table().getElement(i, SgExternalErpFile::PMY_IDX));
703  std::cout << qPrintable(str) << "\n";
704  };
705  */
706 };
707 
708 
709 
710 //
712 {
713  int numOfCorrected=0;
714  // mimic SOLVE:
715  if (!(config_->getUseGoodQualityCodeAtStartup() /* && primaryBand_->getInputFileVersion()<4 */))
716  return numOfCorrected;
717 
718  QString primeBandKey=primaryBand_->getKey();
719  for (int i=0; i<observations_.size(); i++)
720  {
721  SgVlbiObservation *obs=observations_.at(i);
722  for (QMap<QString, SgVlbiObservable*>::iterator it=obs->observableByKey().begin();
723  it!=obs->observableByKey().end(); ++it)
724  {
725  SgVlbiObservable *o=it.value();
726  if (true)
727  {
728  //
729  // turn off any obs with QC<config_->getGoodQualityCodeAtStartup()
732  {
734  numOfCorrected++;
735  };
736  //
737  }
738  else // old version:
739  {
740  if (o->getBandKey()==primeBandKey && obs->isEligible(config_) &&
742  {
744  numOfCorrected++;
745  };
746  };
747  };
748  };
750  "::suppressNotSoGoodObs(): " + QString("").setNum(numOfCorrected) +
751  " observation" + (numOfCorrected==1?" was":"s were") +
752  " deselected due to not sufficiently high Quality Code, " +
753  QString("").setNum(config_->getGoodQualityCodeAtStartup()), true);
754  //
755  return numOfCorrected;
756 };
757 
758 
759 
760 //
762 {
763  if (!(config_ && parametersDescriptor_))
764  return;
765 
767  "::doPostReadActions_old(): post read actions initiated for the session " + getName(), true);
768 
769  // save pointers:
770  SgTaskConfig *config_saved = config_;
771  SgParametersDescriptor *parametersDescriptor_saved = parametersDescriptor_;
772 
773  config_ = new SgTaskConfig;
774  *config_ = *config_saved;
776  *parametersDescriptor_ = *parametersDescriptor_saved;
777 
779  //
780  //
782  //
783  if (config_->getDoIonoCorrection4SBD() && bands().size()>1)
784  {
786  "::doPostReadActions_old(): evaluating ionospheric corrections for single band delays", true);
788  };
789  //
791  {
793  "::doPostReadActions_old(): running clock break detections, early stage", true);
795  };
796  //
798  {
800  "::doPostReadActions_old(): elimination of outliers, early stage", true);
802  };
803  //
804  // restore pointers:
805  delete config_;
806  delete parametersDescriptor_;
807  config_ = config_saved;
808  parametersDescriptor_ = parametersDescriptor_saved;
809 };
810 
811 
812 
813 //
814 void SgVlbiSession::process(bool haveProcessAllBands, bool interactWithGui)
815 {
816  if (!(config_ && parametersDescriptor_))
817  {
819  "::process(): called in nonappropriate form: config of parametersDescriptor is NULL, ignoring");
820  return;
821  };
822 
823  bool hasArc, hasStc;
824  hasArc = hasStc = false;
825  for (int i=0; i<parametersDescriptor_->num(); i++)
826  {
829  hasArc = true;
831  hasStc = true;
832  };
833  if (hasArc && hasStc)
834  {
835  QMessageBox::warning(NULL, "Cannot estimate", "The software is unable to estimate a combination of "
836  "arc or piece-wise parameters and stochastic parameters. Latter releases will do it. Sorry for "
837  "unconvenience");
839  "::process(): cannot estimate arc or pwl AND stochastic parameters in one solution");
840  return;
841  };
842 
843 
844  SgTask *task = new SgTask("Internal run manager for the session " + getName());
845  QList<SgObservation*> *obsList = NULL;
846 
847  // config_->setPath2APrioriFiles(path2APrioriFiles_);
848  task->setConfig(*config_);
849  task->addSession((SgVlbiSessionInfo*)this, this);
851 
852  //
853  QString path2efa;
854  bool have2reloadEfas(false);
857  have2reloadEfas = true;
860  have2reloadEfas = true;
861 
864  have2reloadEfas = true;
867  have2reloadEfas = true;
870  have2reloadEfas = true;
872  if (path2efa != apHiFyEop_.getFileName() && config_->getUseExtAPrioriHiFyErp())
873  have2reloadEfas = true;
876  have2reloadEfas = true;
879  have2reloadEfas = true;
880  //
881 // if (have2reloadEfas || lastProcessedConfig_.getIsSolveCompatible() != config_->getIsSolveCompatible())
882 // if (lastProcessedConfig_ != *config_)
883  if (have2reloadEfas ||
892  )
893  {
896  {
897  // recalc geodetic coordinates:
898  for (StationsByName_it it=stationsByName_.begin(); it!=stationsByName_.end(); ++it)
899  it.value()->recalcRLF(config_->getIsSolveCompatible());
900  // do something else:
901 
902  };
903  };
904  //
905  // check for a file with external weights, if necessary -- read it and update weights.
907  {
909  if (externalWeights_.isOk())
910  {
911  zerofySigma2add();
913  }
914  else
915  {
916  // zerofySigma2add();
918  "::process(): reading an external weights file failed, no weights were applied");
919  };
920  };
921 
923 
924  obsList = (QList<SgObservation*>*) &observations_;
925  QString bandKey=bands_.at(config_->getActiveBandIdx())->getKey();
927  "::process(): starting analysis of the " + bandKey + "-band");
928 
929  for (int i=0; i<observations_.size(); i++)
930  {
931  SgVlbiObservation *obs=observations_.at(i);
932  obs->setupActiveObservable(bandKey);
934  };
935 
936  // set up the manager:
937  mgr->setObservations(obsList);
938  mgr->currentSessionInfo() = (SgVlbiSessionInfo*)this;
939  mgr->currentSession() = this;
940 
941  // GUI:
947  mgr->setHave2InteractWithGui(interactWithGui);
948  // mgr->setHave2InteractWithGui(false);
949 
950  // run it:
951  mgr->prepare4Run();
952  mgr->run(haveProcessAllBands);
953  if (reporter_)
954  reporter_->absorbInfo(mgr);
955  mgr->finisRun();
956 
957  delete task;
958  task = NULL;
959  delete mgr;
960  mgr = NULL;
961  // save the config:
963 };
964 
965 
966 
967 //
969 {
970  for (StationsByName_it it_s=stationsByName_.begin(); it_s!=stationsByName_.end(); ++it_s)
971  {
972  SgVlbiStationInfo *si=it_s.value();
973  //
974  bool isOk=false;
975  for (BaselinesByName_it it_b=baselinesByName_.begin(); it_b!=baselinesByName_.end(); ++it_b)
976  {
977  QString st1Name, st2Name;
978  SgVlbiBaselineInfo *bi=it_b.value();
979  st1Name = bi->getKey().left(8);
980  st2Name = bi->getKey().right(8);
981  if ((si->getKey() == st1Name || si->getKey() == st2Name) &&
983  isOk = true;
984  };
985  if (!isOk)
986  {
989  "::checkExcludedStations(): all baselines of the station " + si->getKey() +
990  " are deselected, the station is turned off too");
991  };
992  };
993 };
994 
995 
996 
997 //
999 {
1000 
1001 
1002 
1003 };
1004 
1005 
1006 //
1007 //
1008 //
1009 
1010 
1011 
1012 //
1013 //
1014 //
1015 //
1016 // ------------------------ clock break related procedures:
1017 //
1018 //
1020  SgVlbiBand* band, double& cbShift, double& cbSigma)
1021 {
1022  // collect the observations for the station:
1023  QList<SgVlbiBaselineInfo*> baselines;
1024  BaselinesByName_it baselineItr=band->baselinesByName().begin();
1025  for (int iBaseline=0; baselineItr!=band->baselinesByName().end(); ++baselineItr, iBaseline++)
1026  {
1027  SgVlbiBaselineInfo* baselineInfo=baselineItr.value();
1028  if ( baselineInfo &&
1029  !baselineInfo->isAttr(SgVlbiBaselineInfo::Attr_NOT_VALID) &&
1030  baselineInfo->getKey().contains(stn->getKey()) )
1031  {
1032  // determine how many points on both sides of the break:
1033  int numOnLeft=0, numOnRight=0;
1034  QList<SgVlbiObservable*> *observables=&baselineInfo->observables();
1035  for (int idx=0; idx<observables->size(); idx++)
1036  {
1037  if (observables->at(idx)->epoch()<=tBreak)
1038  numOnLeft++;
1039  else
1040  numOnRight++;
1041  };
1042  if (numOnLeft>2 && numOnRight>2)
1043  baselines.append(baselineInfo);
1044  };
1045  };
1046  if (!baselines.size()) // complain and return
1047  {
1049  "::calculateClockBreakParameter(): cannot evaluate clock break parameters: num of baselines==0");
1050  return;
1051  }
1052  else
1054  "::calculateClockBreakParameter(): collected " + QString("").setNum(baselines.size()) +
1055  " baselines for the station " + stn->getKey());
1056 
1057  int nZ=0;
1058  for (int iBaseline=0; iBaseline<baselines.size(); iBaseline++)
1059  {
1060  SgVlbiBaselineInfo *baselineInfo=baselines.at(iBaseline);
1061  QList<SgVlbiObservable*> *observables=&baselineInfo->observables();
1062  for (int idx=0; idx<observables->size(); idx++)
1063  nZ++;
1064  };
1065 
1066  SgEstimator *estimator=new SgEstimator(config_);
1067  QList<SgParameter*> *localParameters=new QList<SgParameter*>;
1068  // create parameters list:
1069  SgParameter *pC, *pAi, *pBi;
1070  pC = new SgParameter("Shift");
1071  pC->setSigmaAPriori(1.0e+8);
1072  localParameters->append(pC);
1073  for (int iBaseline=0; iBaseline<baselines.size(); iBaseline++)
1074  {
1075  SgVlbiBaselineInfo *baselineInfo=baselines.at(iBaseline);
1076  pAi = new SgParameter("A_" + QString("").sprintf("%03d_(", iBaseline) +
1077  baselineInfo->getKey() + ")");
1078  pBi = new SgParameter("B_" + QString("").sprintf("%03d_(", iBaseline) +
1079  baselineInfo->getKey() + ")");
1080  pAi->setSigmaAPriori(1.0e+8);
1081  pBi->setSigmaAPriori(1.0e+8);
1082  localParameters->append(pAi);
1083  localParameters->append(pBi);
1084  };
1085  estimator->addParametersList(localParameters);
1086 // estimator->setListP(stochasticParameters);
1087  estimator->prepare2Run(nZ + 10, tStart_, tFinis_, tRefer_);
1088  // feed the estimator:
1089  double res, sig, sign;
1090  SgVector vO_C(1), vSigma(1);
1091  double dsSB=0.1E-9; // 0.1ns
1092  double dsGR=5.E-12; // 5ps
1093  for (int iBaseline=0; iBaseline<baselines.size(); iBaseline++)
1094  {
1095  SgVlbiBaselineInfo *baselineInfo=baselines.at(iBaseline);
1096  sign = -1.0;
1097  if (baselineInfo->getKey().indexOf(stn->getKey())>0) // the second station
1098  sign = 1.0;
1099  pAi = localParameters->at(2*iBaseline + 1);
1100  pBi = localParameters->at(2*iBaseline + 2);
1101  QList<SgVlbiObservable*> *observables=&baselineInfo->observables();
1102  for (int idx=0; idx<observables->size(); idx++)
1103  {
1104  SgVlbiObservable *o=observables->at(idx);
1107  {
1108  res = m->getResidual();
1109  sig = m->sigma2Apply() + dsGR;
1111  sig += dsSB;
1112  if (o->epoch()<=tBreak)
1113  pC->setD(0.0);
1114  else
1115  pC->setD(1.0E-9*sign);
1116  pAi->setD(1.0E-9);
1117  pBi->setD(1.0E-9*(o->epoch() - tBreak));
1118  vO_C.setElement (0, res);
1119  vSigma.setElement(0, sig);
1120  estimator->processObs(o->epoch(), vO_C, vSigma);
1121  };
1122  };
1123  };
1124  estimator->finisRun();
1125  cbShift = pC->getSolution()*1.0E-9;
1126  cbSigma = pC->getSigma()*1.0E-9;
1127  //
1128  for (int i=0; i<localParameters->size(); i++)
1129  delete localParameters->at(i);
1130  delete localParameters;
1131  localParameters = NULL;
1132  delete estimator;
1133 };
1134 
1135 
1136 
1137 //
1139 {
1140  if (!band || !agents.size())
1141  return;
1142 
1143  // first, pick up baselines with clock breaks:
1144  QList<SgVlbiBaselineInfo*> baselines;
1145  QMap<QString, SgVlbiBaselineInfo*>
1147  BaselinesByName_it it=band->baselinesByName().begin();
1148  int nZ=0;
1149  for (int iBaseline=0; it!=band->baselinesByName().end(); ++it, iBaseline++)
1150  {
1151  SgVlbiBaselineInfo *blInfo=it.value();
1152  if (blInfo && !blInfo->isAttr(SgVlbiBaselineInfo::Attr_NOT_VALID))
1153  {
1154  for (int idxAgent=0; idxAgent<agents.size(); idxAgent++)
1155  {
1156  SgClockBreakAgent *agent=agents.at(idxAgent);
1157  if (agent->stn_ && blInfo->getKey().contains(agent->stn_->getKey()))
1158  {
1160  "::calculateClockBreaksParameters(): gathering info for CB on " + agent->epoch_.toString() +
1161  " at " + agent->stn_->getKey() + "; baseline " + blInfo->getKey());
1162  // determine how many points on both sides of the break:
1163  int numOnLeft=0, numOnRight=0;
1164  QList<SgVlbiObservable*> *observables=&blInfo->observables();
1165  for (int idx=0; idx<observables->size(); idx++)
1166  {
1167  if (observables->at(idx)->owner()->isAttr(SgVlbiObservation::Attr_PROCESSED) &&
1168  observables->at(idx)->epoch() < agent->epoch_)
1169  numOnLeft++;
1170  else if (observables->at(idx)->owner()->isAttr(SgVlbiObservation::Attr_PROCESSED) &&
1171  agent->epoch_ < observables->at(idx)->epoch())
1172  numOnRight++;
1173  };
1174  if (numOnLeft>2 && numOnRight>2)
1175  {
1176  if (!baselinesByName.contains(blInfo->getKey()))
1177  {
1178  baselines.append(blInfo);
1179  baselinesByName.insert(blInfo->getKey(), blInfo);
1180  };
1181  nZ += numOnLeft + numOnRight;
1182  };
1183  };
1184  };
1185  };
1186  };
1187  baselinesByName.clear();
1188  if (!baselines.size()) // complain and return
1189  {
1191  "::calculateClockBreaksParameters(): cannot evaluate clock break parameters: num of baselines==0");
1192  return;
1193  }
1194  else
1196  "::calculateClockBreaksParameters(): collect " + QString("").setNum(baselines.size()) +
1197  " baselines for clock breaks evaluation");
1198 
1199  // prepare the estimator:
1200  SgEstimator *estimator=new SgEstimator(config_);
1201  QList<SgParameter*> *localParameters=new QList<SgParameter*>;
1202  // create parameters list:
1203  for (int idxAgent=0; idxAgent<agents.size(); idxAgent++)
1204  {
1205  SgClockBreakAgent *agent=agents.at(idxAgent);
1206  agent->pC_ = new SgParameter("Shift at " + agent->stn_->getKey() +
1207  QString("").sprintf("_%03d", idxAgent));
1208  agent->pC_->setSigmaAPriori(1.0e+8);
1209  localParameters->append(agent->pC_);
1210  };
1211  SgParameter *pAi;
1212  QMap< QString, QList<SgParameter*> >
1213  parametersByBaseline;
1214  for (int iBaseline=0; iBaseline<baselines.size(); iBaseline++)
1215  {
1216  SgVlbiBaselineInfo *baselineInfo=baselines.at(iBaseline);
1217  int nOrder=2;
1218  SgVlbiStationInfo *si;
1219  QList<SgParameter*> parList;
1220  si = baselineInfo->stn_1(stationsByName_);
1221  if (si && si->getClocksModelOrder()>nOrder)
1222  nOrder = si->getClocksModelOrder();
1223  si = baselineInfo->stn_2(stationsByName_);
1224  if (si && si->getClocksModelOrder()>nOrder)
1225  nOrder = si->getClocksModelOrder();
1226  for (int idxP=0; idxP<nOrder; idxP++)
1227  {
1228  pAi = new SgParameter("A_" + QString("").sprintf("%02d_%03d_(", idxP, iBaseline) +
1229  baselineInfo->getKey() + ")");
1230  pAi->setSigmaAPriori(1.0e+8);
1231  localParameters->append(pAi);
1232  parList.append(pAi);
1233  };
1234  parametersByBaseline.insert(baselineInfo->getKey(), parList);
1235  };
1236  // set up the estimator:
1237  estimator->addParametersList(localParameters);
1238  estimator->prepare2Run(nZ + 10, tStart_, tFinis_, tRefer_);
1239  // feed the estimator:
1240  double res, sig, sign;
1241  SgVector vO_C(1), vSigma(1);
1242  for (int iBaseline=0; iBaseline<baselines.size(); iBaseline++)
1243  {
1244  SgVlbiBaselineInfo *blInfo=baselines.at(iBaseline);
1245  const QList<SgParameter*> &parList=parametersByBaseline.value(blInfo->getKey());
1246  QList<SgVlbiObservable*> *observables=&blInfo->observables();
1247  for (int idx=0; idx<observables->size(); idx++)
1248  {
1249  SgVlbiObservable *o=observables->at(idx);
1252  {
1253  res = m->getResidual();
1254  sig = m->sigma2Apply();
1255  // clock breaks parameters:
1256  for (int idxAgent=0; idxAgent<agents.size(); idxAgent++)
1257  {
1258  SgClockBreakAgent *agent=agents.at(idxAgent);
1259  SgParameter *pC=agent->pC_;
1260  sign = -1.0;
1261  if (blInfo->getKey().indexOf(agent->stn_->getKey()) > 0) // the second station
1262  sign = 1.0;
1263  if (o->epoch() <= agent->epoch_)
1264  pC->setD(0.0);
1265  else
1266  pC->setD(1.0E-9*sign);
1267  };
1268  // baselines:
1269  double d(1.0), dt(o->epoch() - tRefer_);
1270  for (int idxP=0; idxP<parList.size(); idxP++)
1271  {
1272  pAi = parList.at(idxP);
1273  pAi->setD(1.0E-9*d);
1274  d *= dt;
1275  };
1276  vO_C.setElement (0, res);
1277  vSigma.setElement(0, sig);
1278  estimator->processObs(o->epoch(), vO_C, vSigma);
1279  };
1280  };
1281  };
1282  // make solution:
1283  estimator->finisRun();
1284  // pick up the solved values:
1285  for (int idxAgent=0; idxAgent<agents.size(); idxAgent++)
1286  {
1287  SgClockBreakAgent *agent=agents.at(idxAgent);
1288  SgParameter *pC=agent->pC_;
1289  agent->shift_ = pC->getSolution()*1.0E-9;
1290  agent->sigma_ = pC->getSigma()*1.0E-9;
1291  };
1292  //
1293  for (int i=0; i<localParameters->size(); i++)
1294  delete localParameters->at(i);
1295  delete localParameters;
1296  localParameters = NULL;
1297  delete estimator;
1298 };
1299 
1300 
1301 
1302 //
1303 bool SgVlbiSession::detectClockBreaks_mode1(SgVlbiBand* band, QString& stnName, SgMJD& tBreak)
1304 {
1305  BaselinesByName candidates;
1306  tBreak = tZero;
1307  // now, we are working with SBD only:
1308  BaselinesByName_it itBaselineInfo=band->baselinesByName().begin();
1309  for (int iBaseline=0; itBaselineInfo!=band->baselinesByName().end(); ++itBaselineInfo, iBaseline++)
1310  {
1311  SgVlbiBaselineInfo *baselineInfo=itBaselineInfo.value();
1312  if (baselineInfo && !baselineInfo->isAttr(SgVlbiBaselineInfo::Attr_NOT_VALID))
1313  {
1314  baselineInfo->calculateClockF1(config_);
1315  baselineInfo->evaluateCBIndicator();
1316  SgClockBreakIndicator *cbi=baselineInfo->cbIndicator();
1317  if (cbi &&
1318 // 0.30 < (cbi->totWrms_ - cbi->minWrms_)/cbi->totWrms_ &&
1319  0.25 < (cbi->totWrms_ - cbi->minWrms_)/cbi->totWrms_ &&
1320  cbi->numOnLeft_ > 0 &&
1321  cbi->numOnRight_ > 0)
1322  {
1323  candidates.insert(baselineInfo->getKey(), baselineInfo);
1324  /*
1325  std::cout << qPrintable(baselineInfo->getKey()) << ": " << qPrintable(band->getKey()) << "-band ++ value "
1326  << 100.0*(cbi->totWrms_ - cbi->minWrms_)/cbi->totWrms_ << "% at "
1327  << qPrintable(cbi->epoch_.toString())
1328  << "; num on the left wing " << cbi->numOnLeft_
1329  << "; num on the right wing " << cbi->numOnRight_
1330  << " cbi->totWrms=" << cbi->totWrms_
1331  << " cbi->minWrms=" << cbi->minWrms_
1332  << "\n";
1333  */
1334  }
1335  else if (cbi &&
1336  cbi->numOnLeft_ > 0 &&
1337  cbi->numOnRight_ > 0)
1338  {
1339  /*
1340  std::cout << qPrintable(baselineInfo->getKey()) << qPrintable(band->getKey()) << "-band -- value "
1341  << 100.0*(cbi->totWrms_ - cbi->minWrms_)/cbi->totWrms_ << "% at "
1342  << qPrintable(cbi->epoch_.toString())
1343  << "; num on the left wing " << cbi->numOnLeft_
1344  << "; num on the right wing " << cbi->numOnRight_
1345  << " cbi->totWrms=" << cbi->totWrms_
1346  << " cbi->minWrms=" << cbi->minWrms_
1347  << "\n";
1348  */
1349  };
1350 
1351  };
1352  };
1353  if (!candidates.size())
1354  return false;
1355  // get maximum (absolute):
1356  double maxConsumed=0.0;
1357  SgVlbiBaselineInfo *blBreak=NULL;
1358  QString blName, stnName_1, stnName_2;
1359  BaselinesByName_it iBli=candidates.begin();
1360  for (; iBli!=candidates.end(); ++iBli)
1361  if (maxConsumed < iBli.value()->cbIndicator()->totWrms_ - iBli.value()->cbIndicator()->minWrms_)
1362  {
1363  maxConsumed = iBli.value()->cbIndicator()->totWrms_ - iBli.value()->cbIndicator()->minWrms_;
1364  blName = iBli.key();
1365  tBreak = iBli.value()->cbIndicator()->epoch_;
1366  };
1367  if (band->baselinesByName().contains(blName))
1368  blBreak = band->baselinesByName().value(blName);
1369  else
1370  {
1371  // complain:
1373  "::detectClockBreaks(): baseline name " + blName +
1374  " is not in band's baselinesByName_ container");
1375  return false;
1376  };
1377  SgVlbiObservable *obs=blBreak->observables().at(0);
1378  stnName_1 = obs->stn_1()->getKey();
1379  stnName_2 = obs->stn_2()->getKey();
1380  /*
1381  std::cout << "Determined: " << qPrintable(blBreak->getKey()) << " with components "
1382  << qPrintable(stnName_1) << " and " << qPrintable(stnName_2)
1383  << " from " << candidates.size() << " candidates\n";
1384  */
1385  //
1386  // ok, now what we've got: blBreak == baseline info with a clock break
1387  // blName == it's name
1388  // stnName_1 == name of the first station and
1389  // stnName_2 == name of the second station at the baseline.
1390  //
1391  // evaluate frequencies:
1392  QMap<QString, int> numByName;
1393  iBli = candidates.begin();
1394  for (; iBli!=candidates.end(); ++iBli)
1395  if (iBli.key().contains(stnName_1) || iBli.key().contains(stnName_2))
1396  {
1397  SgVlbiObservable *obs=iBli.value()->observables().at(0);
1398  SgVlbiStationInfo *s=NULL;
1399 
1400  if ( (s=lookupStationByIdx(obs->owner()->getStation1Idx())) &&
1402  numByName[obs->stn_1()->getKey()]++;
1403  if ( (s=lookupStationByIdx(obs->owner()->getStation2Idx())) &&
1405  numByName[obs->stn_2()->getKey()]++;
1406  };
1407  // get maximum:
1408  QMap<QString, int>::iterator iAux=numByName.begin();
1409  int minN=iAux.value(), maxN=iAux.value();
1410  stnName = iAux.key();
1411  for (; iAux!=numByName.end(); ++iAux)
1412  {
1413  int n=iAux.value();
1414  if (minN>n)
1415  minN = n;
1416  if (maxN<n)
1417  {
1418  maxN = n;
1419  stnName = iAux.key();
1420  };
1421  // std::cout << " ... " << qPrintable(iAux.key()) << ": " << iAux.value() << " ... \n";
1422  };
1423  // determine proper station and epoch:
1424  if (maxN!=minN || (baselinesByName_.size()==1 && maxN==1 && minN==1))
1425  {
1426  if (stationsByName().contains(stnName))
1427  {
1428  // stnBreak = stationsByName().value(stnName);
1429  // std::cout << "The break station is: " << qPrintable(stnName) << "\n";
1430  // adjust break epoch:
1431  iBli = candidates.begin();
1432  for (; iBli!=candidates.end(); ++iBli)
1433  if (iBli.key().contains(stnName) &&
1434  iBli.value()->cbIndicator()->tOnLeft_ <= tBreak && // ensure that it is the same break
1435  tBreak <= iBli.value()->cbIndicator()->tOnRight_)
1436  {
1437  if (tBreak < iBli.value()->cbIndicator()->epoch_)
1438  {
1439  tBreak = iBli.value()->cbIndicator()->epoch_;
1440  // std::cout << " processing " << qPrintable(iBli.key()) << ", epoch: "
1441  // << qPrintable(tBreak.toString()) << "\n";
1442  };
1443  };
1444  // std::cout << "The break epoch is: " << qPrintable(tBreak.toString()) << "\n";
1445  return true;
1446  }
1447  else
1449  "::detectClockBreaks(): stnName " + stnName + " is not in stationsByName() container");
1450  }
1451  else
1453  "::detectClockBreaks(): impossible to guess the station name: maxN==minN==" +
1454  QString("").setNum(maxN));
1455  return false;
1456 };
1457 
1458 
1459 
1460 //
1461 int SgVlbiSession::checkBandForClockBreaks(int bandIdx, bool have2AdjustResiduals)
1462 {
1463  const int clockBreaksLimit=10;
1464  int numOfClockBreaks=0;
1465 
1466  // check:
1467  if (bandIdx < 0 || bands_.size()-1 < bandIdx)
1468  return numOfClockBreaks;
1469  SgVlbiBand *band=bands_.at(bandIdx);
1470  if (!band)
1471  {
1473  "::checkBandForClockBreaks(): got wrong band (=NULL) for the band index " +
1474  QString("").setNum(bandIdx));
1475  return numOfClockBreaks;
1476  };
1477  // proceed:
1479  "::checkBandForClockBreaks(): processing observations from " + band->getKey() + "-band", true);
1480  QString stnName("");
1481  SgMJD tBreak(tZero);
1482  int idx=0, bandIdxSaved;
1483  bandIdxSaved = config_->getActiveBandIdx();
1484  config_->setActiveBandIdx(bandIdx);
1485  while (detectClockBreaks_mode1(band, stnName, tBreak) && idx<clockBreaksLimit)
1486  {
1488  "::checkBandForClockBreaks(): detected clock break #" + QString("").setNum(idx) + " at " +
1489  stnName + " on " + tBreak.toString(), true);
1490  idx++;
1491  // process the clock break:
1492  // determine parameters of the break:
1493  SgVlbiStationInfo *stnBreak=stationsByName().value(stnName);
1494  double shift, sigma;
1495  calculateClockBreakParameter(tBreak, stnBreak, band, shift, sigma);
1497  shift = round(1.0E9*shift); // round to ns
1500  shift = round(1.0E12*shift)*1.0E-3; // round to ps
1501  sigma *= 1.0E9;
1502  if (fabs(shift) > 3.0*sigma) // 3sigma threshold (otherwise, do it by hands):
1503  {
1504  //
1505  // ok, let user know
1507  "::checkBandForClockBreaks(): detected clock break at " + stnBreak->getKey() +
1508  " station on " + tBreak.toString() + "; shift on " +
1509  QString("").sprintf("%.4f ns", shift), true);
1510  // adjust station information concerning the clock break:
1511  correctClockBreak(band, stnBreak, tBreak, shift, sigma, have2AdjustResiduals);
1512  numOfClockBreaks++;
1513  };
1514  // recalculate residuals:
1515  process(true, false);
1516  };
1517  config_->setActiveBandIdx(bandIdxSaved);
1518  return numOfClockBreaks;
1519 };
1520 
1521 
1522 
1523 //
1525 {
1527  "::detectAndProcessClockBreaks(): clock break detection procedure initiated", true);
1528  // evaluate residuals:
1529  process(true, false);
1530  // run through all bands:
1531  for (int iBand=0; iBand<numberOfBands(); iBand++)
1532  checkBandForClockBreaks(iBand, false);
1533 };
1534 
1535 
1536 
1537 //
1539  const SgMJD& tBreak, double shift, double sigma, bool have2AdjustResiduals, bool have2Complain)
1540 {
1541  //
1542  // check for clock reference station, SOLVE will not tolerate it:
1543  if (have2Complain &&
1544  stationsByName().value(stnInfo->getKey())->isAttr(SgVlbiStationInfo::Attr_REFERENCE_CLOCKS) &&
1545  QMessageBox::warning(NULL, "A clock break is at a reference clock station",
1546  "A clock break has occured at clocks of a reference clock station.\n"
1547  "It is suggested to assign a reference clock station attribute to another station "
1548  "and reprocess data.\n"
1549  "Continue anyway?",
1550  QMessageBox::Yes | QMessageBox::No, QMessageBox::No)==QMessageBox::No)
1551  {
1552  return;
1553  };
1554  //
1555  //
1556  SgVlbiStationInfo *stn2Correct=NULL;
1558  stn2Correct = stnInfo;
1559  else
1560  stn2Correct = band->stationsByName().value(stnInfo->getKey());
1561 
1562  //check for existing clock breaks:
1563  SgParameterBreak *clockBreak=NULL;
1564  if (stn2Correct->clockBreaks().size())
1565  for (int i=0; i<stn2Correct->clockBreaks().size(); i++)
1566  if (fabs(*(stn2Correct->clockBreaks().at(i)) - tBreak) < 5.5E-6) // 0.4752 sec
1567  clockBreak = stn2Correct->clockBreaks().at(i);
1568  if (clockBreak) // update existing clock break:
1569  {
1570  clockBreak->setA0(config_->getUseDynamicClockBreaks()? 0.0 : (clockBreak->getA0()+shift));
1571  clockBreak->setS0(sigma);
1573  "::processClockBreakMarks(): the clock break at " + stn2Correct->getKey() +
1574  " station on " + tBreak.toString() + "; has been updated to " +
1575  QString("").sprintf("%.4f ns", clockBreak->getA0()));
1576  }
1577  else // create a new clock break:
1578  {
1579  clockBreak = new SgParameterBreak(tBreak + 5.0E-6, config_->getUseDynamicClockBreaks()?0.0:shift);
1580  clockBreak->setS0(sigma);
1581  if (stn2Correct->clockBreaks().addBreak(clockBreak))
1583  "::processClockBreakMarks(): the new break has been appended to the model");
1584  else
1586  "::processClockBreakMarks(): adding new clock break at " + stn2Correct->getKey() +
1587  " station on " + tBreak.toString() + " failed");
1588  };
1589  //
1590  //
1593  //
1594  //
1595  // at last, update residuals for all bands and redraw plots:
1596  if (have2AdjustResiduals)
1597  for (int iBand=0; iBand<numberOfBands(); iBand++)
1598  {
1599  SgVlbiBand* band=bands_.at(iBand);
1600  for (int iObs=0; iObs<band->observables().size(); iObs++)
1601  {
1602  SgVlbiObservable *o=band->observables().at(iObs);
1603  if (o->epoch()>tBreak+5.0E-6 && o->owner()->baseline()->getKey().contains(stn2Correct->getKey()))
1604  {
1605  if (o->owner()->baseline()->getKey().indexOf(stn2Correct->getKey()) == 0)
1606  {
1607  o->sbDelay().setResidual(o->sbDelay().getResidual() + shift*1.0E-9);
1608  o->grDelay().setResidual(o->grDelay().getResidual() + shift*1.0E-9);
1609  }
1610  else
1611  {
1612  o->sbDelay().setResidual(o->sbDelay().getResidual() - shift*1.0E-9);
1613  o->grDelay().setResidual(o->grDelay().getResidual() - shift*1.0E-9);
1614  }
1615  };
1616  };
1617  };
1618 };
1619 // -------------------------- end of "clock break" procedures.
1620 //
1621 //
1622 //
1623 
1624 
1625 
1626 //
1627 //
1628 //
1629 // -------------------------- dealing with outliers:
1630 //
1631 //
1633 {
1634  for (int iBand=0; iBand<numberOfBands(); iBand++)
1635  eliminateOutliersSimpleMode(iBand, 200, 5.0);
1636 };
1637 
1638 
1639 
1640 //
1641 void SgVlbiSession::eliminateOutliersSimpleMode(int bandIdx, int maxNumOfPasses, double threshold,
1642  double upperLimit)
1643 {
1644  if (bandIdx<0 || bandIdx>bands_.size()-1)
1645  return;
1646  SgVlbiBand *band = bands_.at(bandIdx);
1647  if (!band)
1648  {
1650  "::eliminateOutliersSimpleMode(): got wrong band (=NULL) for the band index " +
1651  QString("").setNum(bandIdx));
1652  return;
1653  };
1654  int numOfEliminated, numOfPasses;
1655  int bandIdxSaved;
1656  bool hasBeenModified;
1657  bool need2check4absValue=upperLimit>0.0;
1658 // double sumW, sumOC, sigma, res, sig;
1659  double sigma;
1660  uint flag;
1661  QList<SgVlbiObservable*> elluminated;
1662  numOfEliminated = 0;
1663  numOfPasses = 0;
1664  hasBeenModified = true;
1665  bandIdxSaved = config_->getActiveBandIdx();
1666  config_->setActiveBandIdx(bandIdx);
1670  while (hasBeenModified && (numOfPasses<maxNumOfPasses))
1671  {
1672  if (numOfPasses>0)
1673  process(true, false);
1674  sigma = band->wrms(DT_DELAY);
1675  hasBeenModified = false;
1676  for (int idx=0; idx<band->observables().size(); idx++)
1677  {
1678  SgVlbiObservable *o=band->observables().at(idx);
1681  {
1682  if (fabs(m->getResidual()) > threshold*sigma ||
1683  (need2check4absValue && fabs(m->getResidual()) > upperLimit) )
1684  {
1685  o->owner()->addAttr(flag);
1687  hasBeenModified = true;
1688  numOfEliminated++;
1689  elluminated << o;
1690  };
1691  };
1692  };
1693  numOfPasses++;
1694  };
1696  "::eliminateOutliersSimpleMode(): eliminated " + QString("").setNum(numOfEliminated) +
1697  (config_->getUseDelayType()==SgTaskConfig::VD_SB_DELAY?" SbDelay":" GrDelay") +
1698  " observables from the " + band->getKey() + "-band in " + QString("").setNum(numOfPasses) +
1699  " passes, the threshold is " + QString("").setNum(threshold));
1700  if (elluminated.size())
1701  {
1703  "::eliminateOutliersSimpleMode(): the eliminated observations are:");
1704  for (int i=0; i<elluminated.size(); i++)
1705  {
1706  SgVlbiObservable *o=elluminated.at(i);
1708  logger->write(SgLogger::INF, SgLogger::PREPROC, className() + "::eliminateOutliersSimpleMode(): # " +
1709  QString("").setNum(o->getMediaIdx()) + " " +
1710  o->epoch().toString(SgMJD::F_Simple) + " " +
1711  o->getBaseline()->getKey() + " @ " + o->getSrc()->getKey() + " residual " +
1712  QString("").sprintf("%.3f +/- %.3f (ns) | %.3f with QC %d",
1713  m->getResidual()*1.0e9,
1714  m->getSigma()*1.0e9,
1715  m->getResidualNorm(), o->getQualityFactor()));
1716  };
1717  elluminated.clear();
1718  };
1719  config_->setActiveBandIdx(bandIdxSaved);
1720 };
1721 
1722 
1723 
1724 //
1725 void SgVlbiSession::eliminateLargeOutliers(int bandIdx, int maxNumOfPasses, double wrmsRatio)
1726 {
1727  if (bandIdx<0 || bandIdx>bands_.size()-1)
1728  return;
1729  SgVlbiBand *band = bands_.at(bandIdx);
1730  if (!band)
1731  {
1733  "::eliminateLargeOutliers(): got wrong band (=NULL) for the band index " +
1734  QString("").setNum(bandIdx));
1735  return;
1736  };
1737  int numOfPasses;
1738  int bandIdxSaved;
1739  bool hasBeenModified;
1740  double sigma, prevSigma, residMax;
1741  uint flag;
1742  QList<SgVlbiObservable*> elliminated;
1743  numOfPasses = 0;
1744  hasBeenModified = true;
1745  bandIdxSaved = config_->getActiveBandIdx();
1746  config_->setActiveBandIdx(bandIdx);
1750  //
1751  prevSigma = band->wrms(DT_DELAY);
1752  //
1754  "::eliminateLargeOutliers(): start of the procedure");
1755  while (hasBeenModified &&
1756  (numOfPasses < maxNumOfPasses) &&
1757  (8 < band->numProcessed(DT_DELAY)))
1758  // (numOfParameters_ < band->numProcessed(DT_DELAY) + 2))
1759  {
1760  SgVlbiObservable *testedObs=NULL;
1761  residMax = 0.0;
1762  hasBeenModified = false;
1763  // first, find a largest residual:
1764  for (int idx=0; idx<band->observables().size(); idx++)
1765  {
1766  SgVlbiObservable *o=band->observables().at(idx);
1769  {
1770  if (residMax < fabs(m->getResidualNorm()))
1771  {
1772  residMax = fabs(m->getResidualNorm());
1773  testedObs= o;
1774  };
1775  };
1776  };
1777  if (testedObs)
1778  {
1780  "::eliminateLargeOutliers(): found a candidate: " + testedObs->strId() + " with norm.resid= " +
1781  QString("").sprintf("%10.4f", residMax));
1782  // deselect it:
1783  testedObs->owner()->addAttr(flag);
1785  // and make a new solution:
1786  process(true, false);
1787  sigma = band->wrms(DT_DELAY);
1788  // check how it was improved:
1789  //std::cout << " ++ wrmsRatio=" << wrmsRatio << " prevSigma=" << prevSigma
1790  //<< " sigma=" << sigma << " prevSigma/sigma=" << prevSigma/sigma << "\n";
1791  if (wrmsRatio < prevSigma/sigma)
1792  {
1793  hasBeenModified = true;
1794  elliminated << testedObs;
1795  prevSigma = sigma;
1797  "::eliminateLargeOutliers(): the obs is removed");
1798  }
1799  else // restore the obs:
1800  {
1801  testedObs->owner()->delAttr(flag);
1802  process(true, false);
1804  "::eliminateLargeOutliers(): the obs is ok: the ratio = " +
1805  QString("").asprintf("%.2f with the threshold of %.2f", prevSigma/sigma, wrmsRatio));
1806  };
1807  }
1808  else
1810  "::eliminateLargeOutliers(): the observable is NULL");
1811  numOfPasses++;
1812  };
1813  //
1815  "::eliminateLargeOutliers(): eliminated " + QString("").setNum(elliminated.size()) +
1816  (config_->getUseDelayType()==SgTaskConfig::VD_SB_DELAY?" SbDelay":" GrDelay") +
1817  " observables from the " + band->getKey() + "-band in " + QString("").setNum(numOfPasses) +
1818  " passes");
1819  if (elliminated.size())
1820  {
1822  "::eliminateLargeOutliers(): the eliminated observations are:");
1823  for (int i=0; i<elliminated.size(); i++)
1824  {
1825  SgVlbiObservable *o=elliminated.at(i);
1828  "::eliminateLargeOutliers(): # " +
1829  QString("").setNum(o->getMediaIdx()) + " " +
1830  o->epoch().toString(SgMJD::F_Simple) + " " +
1831  o->getBaseline()->getKey() + " @ " + o->getSrc()->getKey() + " residual " +
1832  QString("").sprintf("%.3f +/- %.3f (ns) | %.3f with QC %d",
1833  m->getResidual()*1.0e9,
1834  m->getSigma()*1.0e9,
1835  m->getResidualNorm(), o->getQualityFactor()));
1836  };
1837  elliminated.clear();
1838  };
1839  config_->setActiveBandIdx(bandIdxSaved);
1840 };
1841 
1842 
1843 
1844 
1845 //
1847 {
1848  if (bandIdx<0 || bandIdx>bands_.size()-1)
1849  return 0;
1850  SgVlbiBand *band = bands_.at(bandIdx);
1851  if (!band)
1852  {
1854  "::eliminateOutliers(): got wrong band (=NULL) for the band index " +
1855  QString("").setNum(bandIdx));
1856  return 0;
1857  };
1858  double threshold;
1859  int numOfEliminated, numOfPasses, maxNumOfPasses;
1860  int bandIdxSaved;
1861  bool hasBeenModified;
1862  uint flag;
1863  bool wasMeddledIntoWc=false;
1864  QList<SgVlbiObservable*> elluminated;
1865  //
1867  {
1869  wasMeddledIntoWc = true;
1870  };
1871  //
1872  maxNumOfPasses = config_->getOpIterationsLimit();
1873  threshold = config_->getOpThreshold();
1874  numOfEliminated = 0;
1875  numOfPasses = 0;
1876  hasBeenModified = true;
1877  bandIdxSaved = config_->getActiveBandIdx();
1878  config_->setActiveBandIdx(bandIdx);
1880 
1881  // GUI:
1883  (*longOperationStart_)(numOfPasses, maxNumOfPasses, "");
1884 
1887  while (hasBeenModified && (numOfPasses<maxNumOfPasses))
1888  {
1889  if (numOfPasses>0)
1890  process(false, false);
1891  QList<SgVlbiObservable*> outlierCandidates;
1892  for (int idx=0; idx<band->observables().size(); idx++)
1893  {
1894  SgVlbiObservable *o=band->observables().at(idx);
1897  fabs(m->getResidualNorm()) > threshold)
1898  outlierCandidates << o;
1899  };
1900  // ok, there are outliers
1901  if (outlierCandidates.size())
1902  {
1903  qSort(outlierCandidates.begin(), outlierCandidates.end(), normResidSortingOrderLessThan);
1904  // determine how much outliers should be removed:
1905  double max=fabs(outlierCandidates.first()->activeDelay()->getResidualNorm());
1906  if (outlierCandidates.size()>2 && max>2.0*threshold)
1907  {
1908 #ifdef LOCAL_DEBUG
1909  std::cout << " MODE: cluster\n";
1910 #endif
1911  while (fabs(outlierCandidates.last()->activeDelay()->getResidualNorm())<max-0.5*threshold &&
1912  outlierCandidates.size()>1)
1913  outlierCandidates.removeLast();
1914  }
1915  else // otherwise, eliminate only the largest outlier:
1916  {
1917 #ifdef LOCAL_DEBUG
1918  std::cout << " MODE: the largest one\n";
1919 #endif
1920  SgVlbiObservable *o=outlierCandidates.at(0);
1921  outlierCandidates.clear();
1922  outlierCandidates << o;
1923  };
1924 
1925 #ifdef LOCAL_DEBUG
1926  std::cout << "Pass # " << numOfPasses << " (" << maxNumOfPasses << ") "
1927  << "observations to be excluded:\n";
1928 #endif
1929  for (int idx=0; idx<outlierCandidates.size(); idx++)
1930  {
1931  SgVlbiObservable *o=outlierCandidates.at(idx);
1932  o->owner()->addAttr(flag);
1934  numOfEliminated++;
1935  elluminated << o;
1936 #ifdef LOCAL_DEBUG
1937  std::cout << "obs# " << o->owner()->getMediaIdx() << ": (" << qPrintable(o->epoch().toString())
1938  << ") " << qPrintable(o->baseline()->getKey() + " @" + o->src()->getKey())
1939  << " " << o->activeDelay()->getResidualNorm() << " "
1940  << o->activeDelay()->getResidual()*1.0e9 << " +/- "
1941  << o->activeDelay()->getSigma()*1.0e9
1942  << "\n";
1943 #endif
1944  };
1945  numOfPasses++;
1946  hasBeenModified = true;
1947  // GUI part:
1949  {
1951  (*longOperationMessage_)("Processing outliers: pass " +
1952  QString("").setNum(numOfPasses) + " from " + QString("").setNum(maxNumOfPasses));
1954  (*longOperationProgress_)(numOfPasses);
1955  };
1956  //
1957  }
1958  else
1959  {
1960  hasBeenModified = false;
1961 #ifdef LOCAL_DEBUG
1962  std::cout << "the size is 0\n";
1963 #endif
1964  };
1965  outlierCandidates.clear();
1966  };
1967 
1968 #ifdef LOCAL_DEBUG
1969  if (numOfPasses==maxNumOfPasses)
1970  std::cout << "reached max passing number (" << numOfPasses << ")\n";
1971 #endif
1972 
1973  //
1975  "::eliminateOutliers(): eliminated " + QString("").setNum(numOfEliminated) +
1976  " observables from " + band->getKey() + "-band in " + QString("").setNum(numOfPasses) +
1977  " passes with the threshold " + QString("").setNum(threshold));
1978  if (elluminated.size())
1979  {
1981  "::eliminateOutliers(): the eliminated observations are:");
1982  for (int i=0; i<elluminated.size(); i++)
1983  {
1984  SgVlbiObservable *o=elluminated.at(i);
1986  logger->write(SgLogger::INF, SgLogger::PREPROC, className() + "::eliminateOutliers(): # " +
1987  QString("").setNum(o->getMediaIdx()) + " " +
1988  o->epoch().toString(SgMJD::F_Simple) + " " +
1989  o->getBaseline()->getKey() + " @ " + o->getSrc()->getKey() + " residual " +
1990  QString("").sprintf("%.3f +/- %.3f (ns) | %.3f with QC %d",
1991  m->getResidual()*1.0e9,
1992  m->getSigma()*1.0e9,
1993  m->getResidualNorm(), o->getQualityFactor()));
1994  };
1995  elluminated.clear();
1996  };
1997  //
1998  // restore config:
1999  config_->setActiveBandIdx(bandIdxSaved);
2000  if (wasMeddledIntoWc)
2004  (*longOperationStop_)();
2007  return numOfEliminated;
2008 };
2009 
2010 
2011 
2012 //
2014 {
2015  if (bandIdx<0 || bandIdx>bands_.size()-1)
2016  return 0;
2017  SgVlbiBand *band=bands_.at(bandIdx);
2018  if (!band)
2019  {
2021  "::restoreOutliers(): got wrong band (=NULL) for the band index " +
2022  QString("").setNum(bandIdx));
2023  return 0;
2024  };
2025  double threshold;
2026  int numOfRestored, numOfPasses, maxNumOfPasses;
2027  int bandIdxSaved;
2028  bool hasBeenModified;
2029  uint flag;
2030  bool wasMeddledIntoWc=false;
2032  {
2034  wasMeddledIntoWc = true;
2035  };
2036  //
2037  maxNumOfPasses = config_->getOpIterationsLimit();
2038  threshold = config_->getOpThreshold();
2039  numOfRestored = 0;
2040  numOfPasses = 0;
2041  hasBeenModified = true;
2042  bandIdxSaved = config_->getActiveBandIdx();
2043  config_->setActiveBandIdx(bandIdx);
2047  while (hasBeenModified && (numOfPasses<maxNumOfPasses))
2048  {
2049  if (numOfPasses > 0)
2050  process(false, false);
2051  QList<SgVlbiObservable*> outlierCandidates;
2052  for (int idx=0; idx<band->observables().size(); idx++)
2053  {
2054  SgVlbiObservable *o=band->observables().at(idx);
2057  o->owner()->isAttr(flag) &&
2058  o->isUsable() &&
2059  m)
2060  if (fabs(m->getResidualNorm()) < threshold)
2061  outlierCandidates << o;
2062  };
2063  // ok, there are outliers
2064  if (outlierCandidates.size())
2065  {
2066  qSort(outlierCandidates.begin(), outlierCandidates.end(), normResidSortingOrderLessThan);
2067  // determine how much outliers should be removed:
2068  double max, min;
2069  max = fabs(outlierCandidates.first()->activeDelay()->getResidualNorm());
2070  min = fabs(outlierCandidates.last ()->activeDelay()->getResidualNorm());
2071  if (outlierCandidates.size()>2 && min<1.0)
2072  {
2073 #ifdef LOCAL_DEBUG
2074  std::cout << " MODE: cluster-bottom\n";
2075 #endif
2076  while (fabs(outlierCandidates.first()->activeDelay()->getResidualNorm())>1.0 &&
2077  outlierCandidates.size()>1)
2078  outlierCandidates.removeFirst();
2079  }
2080  else if (outlierCandidates.size()>2 && max>1.0) // here the outliers are in the range
2081  // from sigma to sigma*threshold, so we will
2082  // include them all -- sigma will not get lower,
2083  // there is no sense to recalculate the solution
2084  {
2085 #ifdef LOCAL_DEBUG
2086  std::cout << " MODE: cluster-top\n";
2087 #endif
2088  }
2089  else // otherwise, eliminate only the largest outlier:
2090  {
2091 #ifdef LOCAL_DEBUG
2092  std::cout << " MODE: the smallest one\n";
2093 #endif
2094  SgVlbiObservable *o=outlierCandidates.last();
2095  outlierCandidates.clear();
2096  outlierCandidates << o;
2097  };
2098 #ifdef LOCAL_DEBUG
2099  std::cout << "Pass # " << numOfPasses << " (" << maxNumOfPasses << ") "
2100  << "observation to be restored:\n";
2101 #endif
2102  for (int idx=0; idx<outlierCandidates.size(); idx++)
2103  {
2104  SgVlbiObservable *o=outlierCandidates.at(idx);
2105  o->owner()->delAttr(flag);
2106  numOfRestored++;
2107 #ifdef LOCAL_DEBUG
2108  std::cout << "obs# " << o->owner()->getMediaIdx() << ": (" << qPrintable(o->epoch().toString())
2109  << ") " << qPrintable(o->baseline()->getKey() + " @" + o->src()->getKey())
2110  << " " << o->activeDelay()->getResidualNorm() << " "
2111  << o->activeDelay()->getResidual()*1.0e9 << " +/- "
2112  << o->activeDelay()->getSigma()*1.0e9
2113  << "\n";
2114 #endif
2115  };
2116  numOfPasses++;
2117  hasBeenModified = true;
2118  }
2119  else
2120  {
2121  hasBeenModified = false;
2122 #ifdef LOCAL_DEBUG
2123  std::cout << "the size is 0\n";
2124 #endif
2125  };
2126  outlierCandidates.clear();
2127  };
2128 
2129 #ifdef LOCAL_DEBUG
2130  if (numOfPasses==maxNumOfPasses)
2131  std::cout << "reached max passing number (" << numOfPasses << ")\n";
2132 #endif
2133 
2135  "::restoreOutliers(): restored " + QString("").setNum(numOfRestored) +
2136  " observables from " + band->getKey() + "-band in " + QString("").setNum(numOfPasses) +
2137  " passes with the threshold " + QString("").setNum(threshold));
2138  // restore config:
2139  config_->setActiveBandIdx(bandIdxSaved);
2140  if (wasMeddledIntoWc)
2142  hasOutlierRestoratioRun_ = true;
2145  return numOfRestored;
2146 };
2147 
2148 
2149 
2150 
2151 //
2152 //
2153 //
2154 //
2155 // -------------------------- ambiguity resolving part:
2156 //
2158 {
2159  if (bandIdx<0 || bandIdx>bands_.size()-1)
2160  return;
2161  SgVlbiBand *band=bands_.at(bandIdx);
2162  if (!band)
2163  {
2165  "::scanBaselines4GrDelayAmbiguities(): got wrong band (=NULL) for the band index " +
2166  QString("").setNum(bandIdx));
2167  return;
2168  };
2169  for (int i=0; i<observations_.size(); i++)
2170  {
2171  SgVlbiObservation *obs=observations_.at(i);
2172  //obs->setupActiveObservable(bandKey);
2174  };
2175 
2176  bool noTriange=band->stationsByName().size()<3;
2177  //
2178  BaselinesByName_it itBaselineInfo=band->baselinesByName().begin();
2179  for (; itBaselineInfo!=band->baselinesByName().end(); ++itBaselineInfo)
2180  {
2181  SgVlbiBaselineInfo *baselineInfo=itBaselineInfo.value();
2182  if (isInUse(baselineInfo))
2183  {
2184  baselineInfo->scan4Ambiguities();
2185  baselineInfo->evaluateMeanGrDelResiduals();
2186  if (noTriange)
2187  baselineInfo->setGrdAmbiguities2min();
2188  };
2189  };
2190 
2191  // no any closed triangle:
2192  if (noTriange)
2193  {
2195  return;
2196  };
2197 
2198  resolveGrAmbigTriangles(bandIdx);
2199 
2200  //
2202 };
2203 
2204 
2205 
2206 //
2208 {
2209  SgVlbiBand *band=bands_.at(bandIdx);
2210  SgVlbiStationInfo *refStation=NULL, *station=NULL;
2211  int m;
2212  //
2213  // session's map:
2214  m = 0;
2215  for (StationsByName_it it=stationsByName_.begin(); it!=stationsByName_.end(); ++it)
2216  {
2217  SgVlbiStationInfo *stn=it.value();
2219  refStation = stn;
2220  if (m < stn->numProcessed(DT_DELAY))
2221  {
2222  m = stn->numProcessed(DT_DELAY);
2223  station = stn;
2224  };
2225  }
2226  // if the atribute not set yet, choose the reference station that has max observations:
2227  if (!refStation)
2228  {
2229  if (station)
2230  {
2231  refStation = station;
2233  "::resolveGrAmbigTriangles(): cannot find the reference clock station, picked " +
2234  refStation->getKey() + " as the reference one");
2235  }
2236  else
2237  {
2239  "::resolveGrAmbigTriangles(): unable to determine the reference clock station");
2240  return;
2241  };
2242  }
2243  else
2245  "::resolveGrAmbigTriangles(): found " + refStation->getKey() + " as the reference clock station");
2246 
2247  //
2248  // create a list of stations and a list of baselines; the elements of the lists are
2249  // pointers, so no time consuming copies required
2250  QList<SgVlbiStationInfo*> stations;
2251  QList<SgVlbiBaselineInfo*> baselines;
2252  //
2253  //
2254  //StationsByName_it itStationInfo=band->stationsByName().begin();
2255  for (StationsByName_it it=band->stationsByName().begin(); it!=band->stationsByName().end(); ++it)
2256  if (isInUse(it.value()))
2257  stations.append(it.value());
2258  //
2259  for (BaselinesByName_it it=band->baselinesByName().begin(); it!=band->baselinesByName().end(); ++it)
2260  if (isInUse(it.value()))
2261  baselines.append(it.value());
2262  //
2263  int numOfStations=stations.size();
2264  int numOfBaselines=baselines.size();
2265 
2266  SgEstimator *estimator=new SgEstimator(config_);
2267  QList<SgParameter*> *localParameters=new QList<SgParameter*>;
2268  // create parameters list:
2269  SgParameter *pN;
2270  for (int iBaseline=0; iBaseline<numOfBaselines; iBaseline++)
2271  {
2272  SgVlbiBaselineInfo *baselineInfo=baselines.at(iBaseline);
2273  pN = new SgParameter("N_" + QString("").sprintf("%03d_(", iBaseline) +
2274  baselineInfo->getKey() + ")");
2275  pN->setSigmaAPriori(1.0e+8);
2276  baselineInfo->pAux() = pN;
2277  localParameters->append(pN);
2278  };
2279  estimator->addParametersList(localParameters);
2280  estimator->prepare2Run(numOfStations*(numOfStations-1)*(numOfStations-2)/2/3 + 10,
2281  tStart_, tFinis_, tRefer_);
2282  // make constraints:
2283  // first, figure out the reference station:
2284  // lookup session's map for a reference station:
2285  // apply constraints:
2286  for (int i=0; i<numOfBaselines; i++)
2287  {
2288  SgVlbiBaselineInfo *bl=baselines.at(i);
2289  if (bl->getKey().contains(refStation->getKey() + ":") ||
2290  bl->getKey().contains(":" + refStation->getKey()) )
2291  {
2292  bl->pAux()->setD(1.0);
2293  estimator->processConstraint(0.0, 1.0e-13);
2294  };
2295  };
2296  // feed the estimator:
2297  double b, sig;
2298  SgVector vO_C(1), vSigma(1);
2299  SgVlbiBaselineInfo *biIJ, *biIK, *biJK;
2300  SgVlbiStationInfo *stI, *stJ, *stK;
2301  QString blName;
2302  SgMJD t=getTMean();
2303  for (int i=0; i<numOfStations; i++)
2304  {
2305  stI = stations.at(i);
2306  for (int j=i+1; j<numOfStations; j++)
2307  {
2308  stJ = stations.at(j);
2309  biIJ = NULL;
2310  // set up ij-th baseline:
2311  blName = stI->getKey() + ":" + stJ->getKey();
2312  if (band->baselinesByName().contains(blName))
2313  {
2314  biIJ = band->baselinesByName().value(blName);
2315  biIJ->setAuxSign( 1.0);
2316  }
2317  else
2318  {
2319  blName = stJ->getKey() + ":" + stI->getKey();
2320  if (band->baselinesByName().contains(blName))
2321  {
2322  biIJ = band->baselinesByName().value(blName);
2323  biIJ->setAuxSign(-1.0);
2324  };
2325  };
2326  for (int k=j+1; k<numOfStations; k++)
2327  {
2328  stK = stations.at(k);
2329  biIK = NULL;
2330  biJK = NULL;
2331  // set up ik-th baseline:
2332  blName = stI->getKey() + ":" + stK->getKey();
2333  if (band->baselinesByName().contains(blName))
2334  {
2335  biIK = band->baselinesByName().value(blName);
2336  biIK->setAuxSign( 1.0);
2337  }
2338  else
2339  {
2340  blName = stK->getKey() + ":" + stI->getKey();
2341  if (band->baselinesByName().contains(blName))
2342  {
2343  biIK = band->baselinesByName().value(blName);
2344  biIK->setAuxSign(-1.0);
2345  };
2346  };
2347  // set up jk-th baseline:
2348  blName = stJ->getKey() + ":" + stK->getKey();
2349  if (band->baselinesByName().contains(blName))
2350  {
2351  biJK = band->baselinesByName().value(blName);
2352  biJK->setAuxSign( 1.0);
2353  }
2354  else
2355  {
2356  blName = stK->getKey() + ":" + stJ->getKey();
2357  if (band->baselinesByName().contains(blName))
2358  {
2359  biJK = band->baselinesByName().value(blName);
2360  biJK->setAuxSign(-1.0);
2361  };
2362  };
2363  // process the triangle:
2364  if (isInUse(stI) && isInUse(stJ) && isInUse(stK) &&
2365  isInUse(biIJ) && isInUse(biIK) && isInUse(biJK))
2366  {
2367  b = biIK->getMeanGrDelResiduals()*biIK->getAuxSign() -
2368  biIJ->getMeanGrDelResiduals()*biIJ->getAuxSign() -
2369  biJK->getMeanGrDelResiduals()*biJK->getAuxSign();
2370  sig = sqrt(
2374 // biIJ->pAux()->setD( biIJ->getMaxGrdAmbigSpacing()*biIJ->getAuxSign());
2375 // biIK->pAux()->setD(-biIK->getMaxGrdAmbigSpacing()*biIK->getAuxSign());
2376 // biJK->pAux()->setD( biJK->getMaxGrdAmbigSpacing()*biJK->getAuxSign());
2377  biIJ->pAux()->setD(
2379  biIK->pAux()->setD(
2381  biJK->pAux()->setD(
2383 
2384  vO_C.setElement (0, b);
2385  vSigma.setElement(0, sig);
2386  estimator->processObs(t, vO_C, vSigma);
2387  };
2388  };
2389  };
2390  };
2391  estimator->finisRun();
2392  // adjust ambiguities at the baselines:
2393  for (int iBaseline=0; iBaseline<numOfBaselines; iBaseline++)
2394  {
2395  SgVlbiBaselineInfo *baselineInfo=baselines.at(iBaseline);
2396  int deltaN=rint(baselineInfo->pAux()->getSolution());
2397  baselineInfo->shiftAmbiguities(deltaN);
2398  // std::cout << qPrintable(baselineInfo->getKey()) << ": "
2399  // << baselineInfo->pAux()->getSolution() << " +/ " << baselineInfo->pAux()->getSigma()
2400  // << "\n";
2401  };
2402  //
2403  stations.clear();
2404  baselines.clear();
2405  //
2406  for (int i=0; i<localParameters->size(); i++)
2407  delete localParameters->at(i);
2408  delete localParameters;
2409  localParameters = NULL;
2410  delete estimator;
2411 };
2412 
2413 
2414 
2415 //
2417 {
2418  // if the session was not processed yet or was analyzed at another analysis center,
2419  // we are going to process it. Otherwise (i.e., it was already analyzed by us) just
2420  // to read data and display it.
2421  //
2423  {
2425  "::need2runAutomaticDataProcessing(): this session is not processed yet");
2426  return true;
2427  };
2428 
2429  const SgVlbiHistory& history=primaryBand_->history();
2430  int ver, verOfExactAcFullName, verOfAcFullName, verOfAcAbbrevName;
2431  int verOfDomainName;
2432 
2433  if (history.size()<3) // nothing to check
2434  {
2436  "::need2runAutomaticDataProcessing(): the history too short");
2437  return true;
2438  };
2439  //
2440  if (!reporter_ || !reporter_->identities())
2441  {
2443  "::need2runAutomaticDataProcessing(): the reporter is not exists yet");
2444  return true; // nowhere to get clues
2445  };
2446  //
2448  QString str("");
2449  QStringList ambigNames, fullNameElements, abbrevNameElements;
2450  ambigNames << "Authority" << "Center" << "Centre" << "Centro" << "Institute" << "National"
2451  << "Observatory" << "Observatoire" << "Technology" << "University";
2452 
2453  str = "(?:";
2454  for (int i=0; i<ambigNames.size()-1; i++)
2455  str += ambigNames.at(i) + "|";
2456  str += ambigNames.at(ambigNames.size()-1) + ")";
2457 
2458  QRegExp rxF(str), rxA, rxM;
2459  rxF.setCaseSensitivity(Qt::CaseInsensitive);
2460  rxA.setCaseSensitivity(Qt::CaseInsensitive);
2461  rxM.setCaseSensitivity(Qt::CaseInsensitive);
2462 
2463  // to serch for a full ac name or part of it:
2464  fullNameElements = ids->getAcFullName().split(QRegExp("\\W+"), QString::SkipEmptyParts);
2465  str = "(?:";
2466  for (int i=0; i<fullNameElements.size(); i++)
2467  if (!fullNameElements.at(i).contains(rxF))
2468  str += fullNameElements.at(i) + "|";
2469  if (str[str.size()-1] == QChar('|'))
2470  str[str.size()-1] = QChar(')');
2471  rxF.setPattern(str);
2472 
2473  // to serch for an abbreviated ac name or part of it:
2474  abbrevNameElements = ids->getAcAbbrevName().split(QRegExp("\\W+"), QString::SkipEmptyParts);
2475  str = "(?:";
2476  for (int i=0; i<abbrevNameElements.size(); i++)
2477  str += abbrevNameElements.at(i) + "|";
2478  if (str[str.size()-1] == QChar('|'))
2479  str[str.size()-1] = QChar(')');
2480  rxA.setPattern(str);
2481 
2482  // to serch for our domain name:
2483  str = ids->getUserEmailAddress();
2484  QString domainName("");
2485 
2486  rxM.setPattern("\\s*([A-Za-z0-9_]+)@([A-Za-z0-9_]+\\.[A-Za-z0-9_]+)");
2487 
2488  if (ids->getUserEmailAddress().indexOf(rxM) != -1)
2489  domainName = rxM.cap(2);
2490 
2491  ver = history.last()->getVersion() - 1;
2492  verOfExactAcFullName = verOfAcFullName = verOfAcAbbrevName = verOfDomainName = -1;
2493  for (int i=0; i<history.size(); i++)
2494  {
2495  const QString& st=history.at(i)->getText();
2496  int v=history.at(i)->getVersion();
2497  if (st.contains(ids->getAcFullName(), Qt::CaseInsensitive))
2498  verOfExactAcFullName = v;
2499  if (st.contains(rxF))
2500  verOfAcFullName = v;
2501  if (st.contains(rxA))
2502  verOfAcAbbrevName = v;
2503  if (domainName.size()>0 && st.contains(domainName, Qt::CaseInsensitive))
2504  verOfDomainName = v;
2505  };
2506  //
2507  if (verOfAcFullName == -1)
2508  {
2510  "::need2runAutomaticDataProcessing(): cannot find AC full name (" +
2511  ids->getAcFullName() + ") in the history");
2512  return true;
2513  };
2514  if (verOfAcAbbrevName == -1)
2515  {
2517  "::need2runAutomaticDataProcessing(): cannot find AC abbreviated name, " + ids->getAcAbbrevName() +
2518  ", in the history");
2519  return true;
2520  };
2521  //
2522  //
2523  // definitely, it is ours:
2524  if (verOfExactAcFullName == ver)
2525  {
2527  "::need2runAutomaticDataProcessing(): we know this session, found exact full AC name");
2528  return false;
2529  };
2530  if (domainName.size()>0 && verOfDomainName==ver)
2531  {
2533  "::need2runAutomaticDataProcessing(): we know this session, found contact info from our domain");
2534  return false;
2535  };
2536  //
2537  //
2538  if (verOfAcFullName < ver || verOfAcAbbrevName < ver)
2539  {
2541  "::need2runAutomaticDataProcessing(): found fingerprints (" +
2542  QString("").sprintf("%d,%d", verOfAcFullName, verOfAcAbbrevName) +
2543  ") but not for the last version (" + QString("").sprintf("%d", ver) + ")");
2544  return true;
2545  };
2546  //
2547  // perhaps:
2549  "::need2runAutomaticDataProcessing(): the session looks familiar");
2550  return false;
2551 };
2552 
2553 
2554 
2555 //
2557 {
2558  bool has=false;
2559  for (StationsByName_it it=stationsByName_.begin(); it!=stationsByName_.end(); ++it)
2560  {
2561  SgVlbiStationInfo *stn=it.value();
2563  has = true;
2564  };
2565  return has;
2566 };
2567 
2568 
2569 
2570 //
2572 {
2573  bool has=false;
2574  for (StationsByName_it it=stationsByName_.begin(); it!=stationsByName_.end(); ++it)
2575  {
2576  SgVlbiStationInfo *stn=it.value();
2577  if (isInUse(stn) &&
2580  has = true;
2581  };
2582  return has;
2583 };
2584 
2585 
2586 
2587 //
2588 bool SgVlbiSession::writeUserData2File(const QString& fileName)
2589 {
2590  bool isOk=false;
2591  QString str("");
2592  //
2593  QFile f(fileName);
2594  if (!f.open(QIODevice::WriteOnly))
2595  {
2597  "::writeUserData2File(): error opening output file \"" + f.fileName() + "\"");
2598  return isOk;
2599  };
2600  //
2601  SgMJD prevT(tZero);
2602  QMap<QString, QString> hasReported;
2603  // make output:
2604  QTextStream ts(&f);
2605 
2606  ts << "#\n"
2607  << "#YYY MM DD HH MM SS Station_ _ScanID_ Elevation SlntHDel SlntWDel ___partial___ "
2608  << "SlntHRte SlntWRte ___partial___\n"
2609  << "#\n";
2610 
2611  for (int i=0; i<observations_.size(); i++)
2612  {
2613  SgVlbiObservation *obs=observations_.at(i);
2614  SgVlbiAuxObservation *auxObs_1=obs->auxObs_1(), *auxObs_2=obs->auxObs_2();
2615 
2616 // YY MM DD HH MM SS.S station scan_name
2617 // slant_delay partial_slant_delay slant_delay_rate partial_slant_delay_rate
2618  if (prevT < *obs)
2619  {
2620  hasReported.clear();
2621  prevT = *obs;
2622  };
2623  if (auxObs_1 && auxObs_2)
2624  {
2625  if (!hasReported.contains(obs->stn_1()->getKey()))
2626  {
2627  str.sprintf("%s %8s %10s %9.6f %10.2f %8.2f %15.6e %10.2f %8.2f %15.6e",
2628  qPrintable(obs->toString(SgMJD::F_Simple).replace(QRegExp("[:/]"), " ")),
2629  qPrintable(obs->stn_1()->getKey()),
2630  qPrintable(obs->getScanName()),
2631  auxObs_1->getElevationAngle()*RAD2DEG,
2632  1.0e12*auxObs_1->getSlantDelayH(),
2633  1.0e12*auxObs_1->getSlantDelayW(),
2634  auxObs_1->getPartDelayW(),
2635  1.0e15*auxObs_1->getSlantRateH(),
2636  1.0e15*auxObs_1->getSlantRateW(),
2637  auxObs_1->getPartRateW()
2638  );
2639  ts << str << "\n";
2640  hasReported.insert(obs->stn_1()->getKey(), "1");
2641  };
2642  if (!hasReported.contains(obs->stn_2()->getKey()))
2643  {
2644  str.sprintf("%s %8s %10s %9.6f %10.2f %8.2f %15.6e %10.2f %8.2f %15.6e",
2645  qPrintable(obs->toString(SgMJD::F_Simple).replace(QRegExp("[:/]"), " ")),
2646  qPrintable(obs->stn_2()->getKey()),
2647  qPrintable(obs->getScanName()),
2648  auxObs_2->getElevationAngle()*RAD2DEG,
2649  1.0e12*auxObs_2->getSlantDelayH(),
2650  1.0e12*auxObs_2->getSlantDelayW(),
2651  auxObs_2->getPartDelayW(),
2652  1.0e15*auxObs_2->getSlantRateH(),
2653  1.0e15*auxObs_2->getSlantRateW(),
2654  auxObs_2->getPartRateW()
2655  );
2656  ts << str << "\n";
2657  hasReported.insert(obs->stn_2()->getKey(), "2");
2658  };
2659  };
2660  };
2661  ts.setDevice(NULL);
2662  f.close();
2663  return true;
2664 };
2665 /*=====================================================================================================*/
2666 
2667 
2668 
2669 
2670 
2671 
2672 /*=====================================================================================================*/
2673 //
2674 // FRIENDS:
2675 //
2676 /*=====================================================================================================*/
2677 //
2678 
2679 
2680 
2681 /*=====================================================================================================*/
2682 //
2683 // aux functions:
2684 //
2686 {
2687  return
2688  fabs(o1->activeDelay()->getResidualNorm()) > fabs(o2->activeDelay()->getResidualNorm());
2689 };
2690 
2691 
2692 
2693 //
2694 void evaluatePCal4GrpDelay(SgVector& pCalByChan, const SgVector& rFreqByChan, int numOfChannels,
2695  double& pCal4GrpDelay, double& pCalSigma4GrpDelay,
2696  int obsIdx, const SgMJD& epoch,
2697  const QString& sourceName, const QString& baselineName)
2698 {
2699  int numOfActualChannels = rFreqByChan.n();
2700  while (rFreqByChan.getElement(numOfActualChannels-1)==0.0)
2701  numOfActualChannels--;
2702 
2703  if (numOfChannels != numOfActualChannels)
2705  QString("").sprintf("evaluatePCal4GrpDelay(): number of actual channels (%d) is not equal"
2706  "to the declared number (%d), for the Obs#%d, %s @%s, on ",
2707  numOfActualChannels, numOfChannels, obsIdx, qPrintable(sourceName), qPrintable(baselineName))
2708  + epoch.toString());
2709 
2710  if (!numOfActualChannels)
2711  {
2713  QString("").sprintf("evaluatePCal4GrpDelay(): number of actual channels is zero, "
2714  "nothing to do, for the Obs#%d, %s @%s, on ",
2715  obsIdx, qPrintable(sourceName), qPrintable(baselineName)) + epoch.toString());
2716  return;
2717  };
2718  if (numOfActualChannels==1)
2719  {
2721  QString("").sprintf("evaluatePCal4GrpDelay(): only one actual channel, "
2722  "nothing to do, for the Obs#%d, %s @%s, on ",
2723  obsIdx, qPrintable(sourceName), qPrintable(baselineName)) + epoch.toString());
2724  return;
2725  };
2726 
2727  for (int i=0; i<numOfActualChannels; i++)
2728  pCalByChan.setElement(i, fmod(pCalByChan.getElement(i), 360.0));
2729 
2730  for (int i=0; i<numOfActualChannels; i++)
2731  pCalByChan.setElement(i, pCalByChan.getElement(i) - pCalByChan.getElement(0));
2732 
2733  for (int i=0; i<numOfActualChannels; i++)
2734  {
2735  while (pCalByChan.getElement(i) > 180.0)
2736  pCalByChan.setElement(i, pCalByChan.getElement(i) - 360.0);
2737  while (pCalByChan.getElement(i) < -180.0)
2738  pCalByChan.setElement(i, pCalByChan.getElement(i) + 360.0);
2739  };
2740  // now the phases are in cycles:
2741  for (int i=0; i<numOfActualChannels; i++)
2742  pCalByChan.setElement(i, pCalByChan.getElement(i)/360.0);
2743 
2744  for (int j=0; j<2; j++)
2745  for (int i=0; i<numOfActualChannels-1; i++)
2746  {
2747  if (pCalByChan.getElement(i+1) - pCalByChan.getElement(i) > 0.5)
2748  pCalByChan.setElement(i+1, pCalByChan.getElement(i+1) - 1.0);
2749  if (pCalByChan.getElement(i+1) - pCalByChan.getElement(i) < -0.5)
2750  pCalByChan.setElement(i+1, pCalByChan.getElement(i+1) + 1.0);
2751  };
2752 
2753  // estimate the slope:
2754  double weight=1.0;
2755  double sum=0.0, sumX=0.0, sumY=0.0;
2756  double sumXY=0.0, sumX2=0.0, sumY2=0.0;
2757  double a=0.0, b=0.0, /*sigmaA=0.0,*/ sigmaB=0.0;
2758  for (int i=0; i<numOfActualChannels; i++)
2759  {
2760  sum += weight;
2761  sumX += weight*rFreqByChan.getElement(i);
2762  sumY += weight* pCalByChan.getElement(i);
2763  sumXY+= weight*rFreqByChan.getElement(i)* pCalByChan.getElement(i);
2764  sumX2+= weight*rFreqByChan.getElement(i)*rFreqByChan.getElement(i);
2765  sumY2+= weight* pCalByChan.getElement(i)* pCalByChan.getElement(i);
2766  };
2767  double delta = sum*sumX2 - sumX*sumX;
2768  a = (sumX2*sumY - sumX*sumXY)/delta;
2769  b = (sumXY*sum - sumX*sumY )/delta;
2770  double varnc;
2771  if (numOfActualChannels>2)
2772  {
2773  varnc = (sumY2 + a*a*sum + b*b*sumX2 - 2.0*(a*sumY + b*sumXY - a*b*sumX))/(numOfActualChannels - 2);
2774  // sigmaA = sqrt(varnc*sumX2/delta);
2775  sigmaB = sqrt(varnc*sum /delta);
2776  }
2777  else
2778  {
2779  // sigmaA = 0.0;
2780  sigmaB = 0.0;
2781  };
2782 
2783  pCal4GrpDelay = b*1.0e6;
2784  pCalSigma4GrpDelay = sigmaB*1.0e6;
2785  return;
2786 };
2787 
2788 
2789 
2790 
2791 
2792 
2793 
2794 //
2795 // Evaluating the ionospherie effective frequencies for group delay, phase delay and
2796 // group rate observables. The code is from "mk5/progs/solve/sdbh/ionfr.f" file.
2797 // utils/db2vgosDB/do_freq.f
2798 // utils/db2vgosDB/do_freq_merge.f
2799 //
2801  // input:
2802  const SgVector& numOfAccPeriodsByChan_USB, const SgVector& numOfAccPeriodsByChan_LSB,
2803  const SgVector& refFreqByChan, const SgVector& fringeAmplitudeByChan,
2804  const SgVector& numOfSamplesByChan_USB, const SgVector& numOfSamplesByChan_LSB,
2805  double sampleRate, double refFreq, int numOfChannels,
2806  // output:
2807  double& effFreq4GR, double& effFreq4PH, double& effFreq4RT,
2808  // info about the observation (for Log's purposes) and equalWeightsFlag:
2809  const QString& oId, bool useEqualWeights)
2810 {
2811  // set up nominal values:
2812  effFreq4GR = effFreq4PH = effFreq4RT = refFreq;
2813 
2814  // first, check the declared number of channels:
2815  int numOfActualChannels=refFreqByChan.n();
2816  while (numOfActualChannels && refFreqByChan.getElement(numOfActualChannels-1)==0.0)
2817  numOfActualChannels--;
2818 
2819  if (numOfChannels != numOfActualChannels)
2821  QString("").sprintf("evaluateEffectiveFreqs_old(): number of actual channels (%d) is not equal"
2822  "to the declared number (%d) for obs ", numOfActualChannels, numOfChannels) + oId);
2823  if (numOfActualChannels == 0)
2824  {
2826  "evaluateEffectiveFreqs_old(): number of actual channels is zero, nothing to do for obs " + oId);
2827  return;
2828  };
2829  if (numOfActualChannels == 1)
2830  {
2832  "evaluateEffectiveFreqs_old(): only one actual channel, nothing to do for obs " + oId);
2833  return;
2834  };
2835 
2836  int numOfGoodChannels=0;
2837  int numOfGoodAccPeriods=0;
2838  bool hasBadAmplitude=false;
2839  bool hasSequenceBug=true;
2840  bool areSampleNumsUsable=false;
2841  bool areAllFreqsSame=false;
2842  double minFrq, maxFrq, d;
2843  minFrq = maxFrq = refFreqByChan.getElement(0);
2844  // check the channels set up:
2845  for (int i=0; i<numOfActualChannels; i++)
2846  {
2847  // fringe amplitudes:
2848  if (fringeAmplitudeByChan.getElement(i)<0.0 || fringeAmplitudeByChan.getElement(i)>1.0)
2849  hasBadAmplitude = true; // at least one value are bad (ionfr.f: BAD_CHAN)
2850  //
2851  if ((numOfAccPeriodsByChan_USB.getElement(i) + numOfAccPeriodsByChan_LSB.getElement(i))*
2852  fringeAmplitudeByChan.getElement(i) > 1.0E-8)
2853  numOfGoodChannels++;
2854  //
2855  if (numOfAccPeriodsByChan_USB.getElement(i) + numOfAccPeriodsByChan_LSB.getElement(i) > 0.0)
2856  numOfGoodAccPeriods++;
2857  //
2858  if (i>0 && numOfAccPeriodsByChan_LSB.getElement(i)-1 != numOfAccPeriodsByChan_LSB.getElement(i-1))
2859  hasSequenceBug = false;
2860  //
2861  if (numOfSamplesByChan_USB.getElement(i)!=0.0 || numOfSamplesByChan_LSB.getElement(i)!=0.0)
2862  areSampleNumsUsable = true;
2863  //
2864  if (refFreqByChan.getElement(i) > maxFrq)
2865  maxFrq = refFreqByChan.getElement(i);
2866  //
2867  if (refFreqByChan.getElement(i) < minFrq)
2868  minFrq = refFreqByChan.getElement(i);
2869  };
2870  if (maxFrq-minFrq < 0.001) // MHz
2871  areAllFreqsSame = true;
2872 
2873  if (areAllFreqsSame) // complain, return
2874  {
2876  "evaluateEffectiveFreqs_old(): all frequencies are the same, nothing to do for obs " + oId);
2877  return;
2878  };
2879 
2880  if (numOfActualChannels!=numOfGoodChannels || numOfActualChannels!=numOfGoodAccPeriods)// just complain
2882  QString("").sprintf("evaluateEffectiveFreqs_old(): the numbers of actual channels (%d), "
2883  "good channels (%d) and good accumulated periods (%d) are not the same "
2884  "for obs ", numOfActualChannels, numOfGoodChannels, numOfGoodAccPeriods) + oId);
2885 
2886  SgVector weightByChan(numOfActualChannels);
2887  // from John's ionfr.f:
2888  SgVector weightByChan_USB(numOfActualChannels);
2889  SgVector weightByChan_LSB(numOfActualChannels);
2890  //
2891  if (numOfGoodChannels<2 || numOfGoodAccPeriods<2 || hasSequenceBug || hasBadAmplitude)
2892  for (int i=0; i<numOfActualChannels; i++)
2893  {
2894  weightByChan.setElement (i, 1.0);
2895  weightByChan_USB.setElement(i, 0.0);
2896  weightByChan_LSB.setElement(i, 1.0);
2897  }
2898  else if (!areSampleNumsUsable)
2899  for (int i=0; i<numOfActualChannels; i++)
2900  {
2901  d = 1.0;
2902  if (!useEqualWeights)
2903  d = (numOfAccPeriodsByChan_USB.getElement(i) + numOfAccPeriodsByChan_LSB.getElement(i))
2904  *fringeAmplitudeByChan.getElement(i);
2905  weightByChan.setElement(i, d);
2906  weightByChan_USB.setElement(i, numOfAccPeriodsByChan_USB.getElement(i));
2907  weightByChan_LSB.setElement(i, numOfAccPeriodsByChan_LSB.getElement(i));
2908  }
2909  else
2910  for (int i=0; i<numOfActualChannels; i++)
2911  {
2912  d = 1.0;
2913  if (!useEqualWeights)
2914  d = (numOfSamplesByChan_USB.getElement(i) + numOfSamplesByChan_LSB.getElement(i))
2915  *fringeAmplitudeByChan.getElement(i)/sampleRate;
2916  weightByChan.setElement(i, d);
2917  weightByChan_USB.setElement(i, numOfSamplesByChan_USB.getElement(i));
2918  weightByChan_LSB.setElement(i, numOfSamplesByChan_LSB.getElement(i));
2919  };
2920 
2921  // make sums:
2922  double sumWei=0.0;
2923  double sumFr1=0.0;
2924  double sumFr2=0.0;
2925  double sumFq2=0.0;
2926  double sumFri=0.0;
2927  double sumDfi=0.0;
2928  //
2929  double halfBw=sampleRate/4.0/1.0e6;
2930  double df, frq_i;
2931  //
2932  for (int i=0; i<numOfActualChannels; i++)
2933  {
2934  frq_i = refFreqByChan.getElement(i);
2935  // new way:
2936  if (weightByChan_USB.getElement(i)>0.0 && weightByChan_LSB.getElement(i)<1.0E-3)
2937  frq_i = refFreqByChan.getElement(i) - halfBw;
2938  else if (weightByChan_USB.getElement(i)<1.0E-3 && weightByChan_LSB.getElement(i)>0.0)
2939  frq_i = refFreqByChan.getElement(i) + halfBw;
2940  //
2941  df = frq_i - refFreq;
2942  sumWei += weightByChan.getElement(i);
2943  sumFr1 += weightByChan.getElement(i)*df;
2944  sumFr2 += weightByChan.getElement(i)*df*df;
2945  sumFq2 += weightByChan.getElement(i)*frq_i*frq_i;
2946  sumFri += weightByChan.getElement(i)/frq_i;
2947  sumDfi += weightByChan.getElement(i)*df/frq_i;
2948  };
2949  double da=sumWei*sumFr2 - sumFr1*sumFr1;
2950  double db=sumFri*sumFr1 - sumDfi*sumWei;
2951  double dc=sumFri*sumFr2 - sumDfi*sumFr1;
2952 
2953  effFreq4GR = (fabs(db)>1.0E-10)?sqrt(da/db):refFreq;
2954  effFreq4PH = (fabs(dc)>1.0E-10)?sqrt(refFreq*da/dc):refFreq;
2955  effFreq4RT = sqrt(sumFq2/sumWei);
2956 
2957  return;
2958 };
2959 
2960 
2961 
2962 
2963 //
2964 // Evaluating the ionospherie effective frequencies for group delay, phase delay and
2965 // group rate observables. The code is from "mk5/progs/solve/sdbh/ionfr.f" file.
2966 // utils/db2vgosDB/do_freq.f
2967 // utils/db2vgosDB/do_freq_merge.f
2968 //
2970  // input:
2971  const SgVector& numOfAccPeriodsByChan_USB, const SgVector& numOfAccPeriodsByChan_LSB,
2972  const SgVector& refFreqByChan, const SgVector& fringeAmplitudeByChan,
2973  const SgVector& numOfSamplesByChan_USB, const SgVector& numOfSamplesByChan_LSB,
2974  double sampleRate, double refFreq, int numOfChannels,
2975  // output:
2976  double& effFreq4GR, double& effFreq4PH, double& effFreq4RT,
2977  // type of a correlator:
2978  const QString& correlatorType,
2979  // info about the observation (for Log's purposes) and equalWeightsFlag:
2980  const QString& oId, bool useEqualWeights)
2981 {
2982 /*
2983 std::cout << "ObsId: " << qPrintable(oId) << "\n";
2984 std::cout << "sampleRate= " << sampleRate << " refFreq=" << refFreq << " numOfChannels=" << numOfChannels << "\n";
2985 std::cout << "numOfAccPeriodsByChan_USB= " << numOfAccPeriodsByChan_USB << " numOfAccPeriodsByChan_LSB=" << numOfAccPeriodsByChan_LSB << "\n";
2986 std::cout << "refFreqByChan= " << refFreqByChan << " fringeAmplitudeByChan=" << fringeAmplitudeByChan << "\n";
2987 std::cout << "numOfSamplesByChan_USB= " << numOfSamplesByChan_USB << " numOfSamplesByChan_LSB=" << numOfSamplesByChan_LSB << "\n\n";
2988 */
2989  // set up nominal values:
2990  effFreq4GR = effFreq4PH = effFreq4RT = refFreq;
2991  //
2992  // first, check the declared number of channels:
2993  int numOfActualChannels=refFreqByChan.n();
2994  while (numOfActualChannels && fabs(refFreqByChan.getElement(numOfActualChannels-1))<1.0e-6)
2995  numOfActualChannels--;
2996 
2997 
2998  if (numOfActualChannels == 0)
2999  {
3001  "evaluateEffectiveFreqs(): number of actual channels is zero, nothing to do for the obs " + oId);
3002  return;
3003  };
3004  if (numOfActualChannels == 1)
3005  {
3007  "evaluateEffectiveFreqs(): only one actual channel, nothing to do for the obs " + oId);
3008  return;
3009  };
3010  //
3011  if (!(correlatorType.contains("GSI", Qt::CaseInsensitive) ||
3012  correlatorType.contains("K5", Qt::CaseInsensitive)) &&
3013  numOfChannels != numOfActualChannels)
3015  QString("").sprintf("evaluateEffectiveFreqs(): number of actual channels (%d) is not equal"
3016  "to the declared number (%d) for the obs ", numOfActualChannels, numOfChannels) + oId);
3017  //
3018  //
3019  int numOfGoodChannels=0;
3020  int numOfGoodAccPeriods=0;
3021  bool hasBadAmplitude=false;
3022  bool hasSequenceBug=true;
3023  bool areSampleNumsUsable=false;
3024  bool areAllFreqsSame=false;
3025  double minFrq, maxFrq;
3026  minFrq = maxFrq = refFreqByChan.getElement(0);
3027  // check the channels set up:
3028  for (int i=0; i<numOfActualChannels; i++)
3029  {
3030  // fringe amplitudes:
3031  if (fringeAmplitudeByChan.getElement(i)<0.0 || fringeAmplitudeByChan.getElement(i)>1.0)
3032  hasBadAmplitude = true; // at least one value are bad (ionfr.f: BAD_CHAN)
3033  //
3034  if ((numOfAccPeriodsByChan_USB.getElement(i) + numOfAccPeriodsByChan_LSB.getElement(i))*
3035  fringeAmplitudeByChan.getElement(i) > 1.0E-8)
3036  numOfGoodChannels++;
3037  //
3038  if (numOfAccPeriodsByChan_USB.getElement(i) + numOfAccPeriodsByChan_LSB.getElement(i) > 0.0)
3039  numOfGoodAccPeriods++;
3040  //
3041  if (i>0 && numOfAccPeriodsByChan_LSB.getElement(i)-1 != numOfAccPeriodsByChan_LSB.getElement(i-1))
3042  hasSequenceBug = false;
3043  //
3044  if (numOfSamplesByChan_USB.getElement(i)>=1.0 || numOfSamplesByChan_LSB.getElement(i)>=1.0)
3045  areSampleNumsUsable = true;
3046  //
3047  if (refFreqByChan.getElement(i) > maxFrq)
3048  maxFrq = refFreqByChan.getElement(i);
3049  //
3050  if (refFreqByChan.getElement(i) < minFrq)
3051  minFrq = refFreqByChan.getElement(i);
3052  //
3053  };
3054 
3055  if (maxFrq-minFrq < 0.001) // MHz
3056  areAllFreqsSame = true;
3057 
3058  if (areAllFreqsSame) // complain, return
3059  {
3061  "evaluateEffectiveFreqs(): all frequencies are the same, nothing to do for obs " + oId);
3062  return;
3063  };
3064 
3065  if (!(correlatorType.contains("GSI", Qt::CaseInsensitive) ||
3066  correlatorType.contains("K5", Qt::CaseInsensitive)) &&
3067  (numOfActualChannels!=numOfGoodChannels || numOfActualChannels!=numOfGoodAccPeriods)) // complain
3069  QString("").sprintf("evaluateEffectiveFreqs(): the numbers of actual channels (%d), "
3070  "good channels (%d) and good accumulated periods (%d) are not the same "
3071  "for obs ", numOfActualChannels, numOfGoodChannels, numOfGoodAccPeriods) + oId);
3072  if (hasBadAmplitude) // just complain
3074  "evaluateEffectiveFreqs(): bad amplitudes are detected for the obs " + oId);
3075  if (hasSequenceBug) // just complain
3077  "evaluateEffectiveFreqs(): the sequence bug is detected for the obs " + oId);
3078 
3079 
3080  SgVector noAP_USB(numOfActualChannels);
3081  SgVector noAP_LSB(numOfActualChannels);
3082  for (int i=0; i<numOfActualChannels; i++)
3083  {
3084  if (useEqualWeights)
3085  {
3086  if (numOfSamplesByChan_USB.getElement(i) > 0.0)
3087  noAP_USB.setElement(i, 1.0);
3088  else
3089  noAP_USB.setElement(i, 0.0);
3090  if (numOfSamplesByChan_LSB.getElement(i) > 0.0)
3091  noAP_LSB.setElement(i, 1.0);
3092  else
3093  noAP_LSB.setElement(i, 0.0);
3094  }
3095  else if (areSampleNumsUsable)
3096  {
3097  noAP_USB.setElement(i, numOfSamplesByChan_USB.getElement(i));
3098  noAP_LSB.setElement(i, numOfSamplesByChan_LSB.getElement(i));
3099  }
3100  else
3101  {
3102  noAP_USB.setElement(i, numOfAccPeriodsByChan_USB.getElement(i));
3103  noAP_LSB.setElement(i, numOfAccPeriodsByChan_LSB.getElement(i));
3104  };
3105  };
3106 
3107  // make sums:
3108  double sumWei=0.0;
3109  double sumFr1=0.0;
3110  double sumFr2=0.0;
3111  double sumFq2=0.0;
3112  double sumFri=0.0;
3113  double sumDfi=0.0;
3114  //
3115  double halfBw=sampleRate/4.0/1.0e6;
3116  double df, frq_i, wei2, weiUSB, weiLSB;
3117 
3118  // old way:
3119  if (false)
3120  {
3121  for (int i=0; i<numOfActualChannels; i++)
3122  {
3123  frq_i = refFreqByChan.getElement(i);
3124  df = frq_i - refFreq;
3125  if (!useEqualWeights)
3126  {
3127  if (!areSampleNumsUsable)
3128  wei2 = (noAP_USB.getElement(i) + noAP_LSB.getElement(i))*fringeAmplitudeByChan.getElement(i);
3129  else
3130  wei2 = (numOfSamplesByChan_USB.getElement(i) + numOfSamplesByChan_LSB.getElement(i))
3131  *fringeAmplitudeByChan.getElement(i);
3132  }
3133  else
3134  wei2 = 1.0;
3135  //
3136  sumWei += wei2;
3137  sumFr1 += wei2*df;
3138  sumFr2 += wei2*df*df;
3139  sumFq2 += wei2*frq_i*frq_i;
3140  sumFri += wei2/frq_i;
3141  sumDfi += wei2*df/frq_i;
3142  };
3143  }
3144  // new way:
3145  else
3146  {
3147  for (int i=0; i<numOfActualChannels; i++)
3148  {
3149  frq_i = refFreqByChan.getElement(i);
3150  //
3151  if (!useEqualWeights)
3152  {
3153  if (!areSampleNumsUsable)
3154  {
3155  weiUSB = noAP_USB.getElement(i);
3156  weiLSB = noAP_LSB.getElement(i);
3157  }
3158  else
3159  {
3160  weiUSB = numOfSamplesByChan_USB.getElement(i);
3161  weiLSB = numOfSamplesByChan_LSB.getElement(i);
3162  };
3163  wei2 = (weiUSB + weiLSB)*fringeAmplitudeByChan.getElement(i);
3164  if (weiUSB>0.0 && weiLSB>0.0) // nothing to do
3165  {
3166  }
3167  else if (weiUSB > 0.0)
3168  frq_i -= halfBw;
3169 // frq_i += halfBw; // <-- to reproduce the confuse with USB/LSB
3170  else if (weiLSB > 0.0)
3171  frq_i += halfBw;
3172 // frq_i -= halfBw; // <-- to reproduce the confuse with USB/LSB
3173  }
3174  else
3175  wei2 = 1.0;
3176 
3177  df = frq_i - refFreq;
3178 
3179  sumWei += wei2;
3180  sumFr1 += wei2*df;
3181  sumFr2 += wei2*df*df;
3182  sumFq2 += wei2*frq_i*frq_i;
3183  sumFri += wei2/frq_i;
3184  sumDfi += wei2*df/frq_i;
3185  };
3186  };
3187  //
3188  double da=sumWei*sumFr2 - sumFr1*sumFr1;
3189  double db=sumFri*sumFr1 - sumWei*sumDfi;
3190  double dc=sumFri*sumFr2 - sumFr1*sumDfi;
3191 
3192  effFreq4GR = (fabs(db)<1.0E-12)?refFreq:sqrt(da/db);
3193  effFreq4PH = (fabs(dc)<1.0E-12)?refFreq:sqrt(refFreq*da/dc);
3194  effFreq4RT = (sumWei<1.0E-16)?refFreq:sqrt(sumFq2/sumWei);
3195 
3196  // complain:
3197  if (fabs(db)<1.0E-12)
3199  "evaluateEffectiveFreqs(): suspicious channel setup (fabs(db)<1.0E-12) for the obs " + oId);
3200  if (fabs(dc)<1.0E-12)
3202  "evaluateEffectiveFreqs(): suspicious channel setup (fabs(dc)<1.0E-12) for the obs " + oId);
3203  if (sumWei<1.0E-16)
3205  "evaluateEffectiveFreqs(): suspicious channel setup (sumWei<1.0E-16) for the obs " + oId);
3206 
3207  return;
3208 };
3209 /*=====================================================================================================*/
3210 
3211 
3212 
3213 /*=====================================================================================================*/
const Sg3dVector v3Zero(0.0, 0.0, 0.0)
SgLogger * logger
Definition: SgLogger.cpp:231
const SgMJD tZero(1957, 10, 4)
#define RAD2MAS
radians to ms:
Definition: SgMathSupport.h:73
#define DAY2SEC
radians to mas:
Definition: SgMathSupport.h:69
#define RAD2DEG
radians to degrees:
Definition: SgMathSupport.h:41
QMap< QString, SgVlbiBaselineInfo * >::iterator BaselinesByName_it
QMap< QString, SgVlbiBaselineInfo * > BaselinesByName
bool normResidSortingOrderLessThan(SgVlbiObservable *, SgVlbiObservable *)
void evaluateEffectiveFreqs_old_version(const SgVector &numOfAccPeriodsByChan_USB, const SgVector &numOfAccPeriodsByChan_LSB, const SgVector &refFreqByChan, const SgVector &fringeAmplitudeByChan, const SgVector &numOfSamplesByChan_USB, const SgVector &numOfSamplesByChan_LSB, double sampleRate, double refFreq, int numOfChannels, double &effFreq4GR, double &effFreq4PH, double &effFreq4RT, const QString &oId, bool useEqualWeights)
void evaluateEffectiveFreqs(const SgVector &numOfAccPeriodsByChan_USB, const SgVector &numOfAccPeriodsByChan_LSB, const SgVector &refFreqByChan, const SgVector &fringeAmplitudeByChan, const SgVector &numOfSamplesByChan_USB, const SgVector &numOfSamplesByChan_LSB, double sampleRate, double refFreq, int numOfChannels, double &effFreq4GR, double &effFreq4PH, double &effFreq4RT, const QString &correlatorType, const QString &oId, bool useEqualWeights)
void evaluatePCal4GrpDelay(SgVector &pCalByChan, const SgVector &rFreqByChan, int numOfChannels, double &pCal4GrpDelay, double &pCalSigma4GrpDelay, int obsIdx, const SgMJD &epoch, const QString &sourceName, const QString &baselineName)
QMap< QString, SgVlbiSourceInfo * >::iterator SourcesByName_it
QMap< QString, SgVlbiStationInfo * >::iterator StationsByName_it
@ DT_DELAY
Definition: SgWrmsable.h:44
const QString & getComments() const
const SgMJD & getTsince() const
const QString & getFileName() const
SgAPrioriRec * lookupApRecord(const QString &, const SgMJD &=tZero)
bool readFile(const QString &fileName, DataType=DT_UNDEF)
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 addBreak(const SgMJD &t, double a0=0.0, double a1=0.0, double a2=0.0, bool isDynamic=false)
SgParameter * pC_
Definition: SgVlbiSession.h:68
SgVlbiStationInfo * stn_
Definition: SgVlbiSession.h:65
void prepare4Spline()
bool isOk() const
SgMatrix & table()
double spline(double arg, int nColumn, double &r)
SgVector & argument()
void addParametersList(QList< SgParameter * > *, bool=false)
void prepare2Run(int numOfExpectedObs, const SgMJD &, const SgMJD &, const SgMJD &)
void processConstraint(double o_c, double sigma)
void processObs(const SgMJD &t, const SgVector &o_c, const SgVector &sigma)
SgTidalUt1::UT1TideContentType ut1Type() const
InputEopType inputEopType() const
const QString & getFileName() const
bool readFile(const QString &, const SgMJD &, int numOfPoints)
bool readFile(const QString &)
const QString & getFileName() const
void setupExternalWeights(BaselinesByName &)
const QString & getAcAbbrevName() const
Definition: SgIdentities.h:247
const QString & getUserEmailAddress() const
Definition: SgIdentities.h:223
const QString & getAcFullName() const
Definition: SgIdentities.h:239
virtual void write(LogLevel, quint32, const QString &, bool=false)
Definition: SgLogger.cpp:88
@ IO_TXT
Definition: SgLogger.h:65
@ REPORT
Definition: SgLogger.h:95
@ PREPROC
Definition: SgLogger.h:98
@ FLY_BY
Definition: SgLogger.h:85
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
double toDouble() const
Definition: SgMJD.h:531
void setElement(unsigned int i, unsigned int j, double d)
Definition: SgMatrix.h:402
double getElement(unsigned int i, unsigned int j) const
Definition: SgMatrix.h:385
bool readFile(const QString &)
const QString & getFileName() const
void calcCorrections(const SgMJD &, double &dUt1, double &dPx, double &dPy)
double getDversion() const
Definition: SgModelsInfo.h:114
const QString & getKey() const
Definition: SgObjectInfo.h:319
int numProcessed(DataType dType) const
Definition: SgObjectInfo.h:351
double wrms(DataType) const
Definition: SgObjectInfo.h:567
virtual int getMediaIdx() const
@ Attr_NOT_VALID
omit the observation;
Definition: SgObservation.h:78
@ Attr_PROCESSED
the observation has been processed;
Definition: SgObservation.h:79
void setS0(double a)
Definition: SgBreakModel.h:443
double getA0() const
Definition: SgBreakModel.h:363
void setA0(double a)
Definition: SgBreakModel.h:419
@ Attr_DYNAMIC
parameters supposed to be estimated during the common solution;
Definition: SgBreakModel.h:60
double getSolution() const
Definition: SgParameter.h:435
double getSigma() const
Definition: SgParameter.h:443
void setSigmaAPriori(double v)
Definition: SgParameter.h:619
SgParameterCfg::PMode getMode(int i) const
void setD(double d)
Definition: SgPartial.h:347
void absorbInfo(SgTaskManager *)
SgIdentities * identities()
const QString & getExtAPrioriSitesVelocitiesFileName() const
bool getDoIonoCorrection4SBD() const
Definition: SgTaskConfig.h:897
const QString & getExtWeightsFileName() const
Definition: SgTaskConfig.h:969
bool getUseExtAPrioriSitesVelocities() const
void setDoWeightCorrection(bool)
bool getUseExtAPrioriSourceSsm() const
bool getUseExtAPrioriHiFyErp() const
bool getUseExtAPrioriSitesPositions() const
bool getUseExtAPrioriErp() const
bool getIsSolveCompatible() const
Definition: SgTaskConfig.h:913
VlbiDelayType getUseDelayType() const
Definition: SgTaskConfig.h:873
bool getDoWeightCorrection() const
Definition: SgTaskConfig.h:905
bool getUseExtAPrioriMeanGradients() const
bool getDoClockBreakDetectionMode1() const
int getGoodQualityCodeAtStartup() const
Definition: SgTaskConfig.h:857
const QString & getExtAPrioriSitesPositionsFileName() const
const QString & getExtAPrioriHiFyErpFileName() const
static QString evaluatePath2(const QString &dir2, const QString &path2)
bool getUseExternalWeights() const
Definition: SgTaskConfig.h:937
void setActiveBandIdx(int)
bool getUseExtAPrioriSourcesPositions() const
bool getHave2ApplyUt1OceanTideHFContrib() const
Definition: SgTaskConfig.h:384
bool getHave2ApplyPxyOceanTideHFContrib() const
Definition: SgTaskConfig.h:385
bool getDoOutliersEliminationMode1() const
bool getUseExtAPrioriAxisOffsets() const
bool getUseDynamicClockBreaks() const
Definition: SgTaskConfig.h:921
int getOpIterationsLimit() const
const QString & getExtAPrioriMeanGradientsFileName() const
const QString & getExtAPrioriSourcesPositionsFileName() const
double getOpThreshold() const
Definition: SgTaskConfig.h:993
void setUseDelayType(VlbiDelayType)
bool getUseGoodQualityCodeAtStartup() const
Definition: SgTaskConfig.h:865
const QString & getExtAPrioriAxisOffsetsFileName() const
int getActiveBandIdx() const
Definition: SgTaskConfig.h:889
bool getOpHave2SuppressWeightCorrection() const
const QString & getExtAPrioriErpFileName() const
const QString & getExtAPrioriSourceSsmFileName() const
void setLongOperationStart(void(*operation)(int, int, const QString &))
SgVlbiSessionInfo *& currentSessionInfo()
Definition: SgTaskManager.h:85
void setLongOperationMessage(void(*operation)(const QString &))
void setLongOperationStop(void(*operation)())
void setObservations(QList< SgObservation * > *)
virtual void run(bool=true)
void setHave2InteractWithGui(bool have2)
void setLongOperationShowStats(void(*operation)(const QString &label, int numTot, int numPrc, double wrms, double chi2))
virtual bool prepare4Run()
SgVlbiSession *& currentSession()
Definition: SgTaskManager.h:89
void setLongOperationProgress(void(*operation)(int))
virtual void finisRun()
Definition: SgTask.h:59
void setConfig(const SgTaskConfig &)
Definition: SgTask.h:259
void addSession(SgVlbiSessionInfo *, SgVlbiSession *)
Definition: SgTask.cpp:69
void setParameters(const SgParametersDescriptor &)
Definition: SgTask.h:267
double calc(const SgMJD &)
Definition: SgTidalUt1.cpp:120
unsigned int n() const
Definition: SgVector.h:327
void setElement(unsigned int i, double d)
Definition: SgVector.h:348
double getElement(unsigned int i) const
Definition: SgVector.h:362
double getElevationAngle() const
QMap< QString, SgVlbiBaselineInfo * > & baselinesByName()
Definition: SgVlbiBand.h:376
QMap< QString, SgVlbiStationInfo * > & stationsByName()
Definition: SgVlbiBand.h:368
QList< SgVlbiObservable * > & observables()
Definition: SgVlbiBand.h:288
SgVlbiHistory & history()
Definition: SgVlbiBand.h:360
SgVlbiStationInfo * stn_2(QMap< QString, SgVlbiStationInfo * >) const
@ Attr_NOT_VALID
omit the baseline;
SgParameter *& pAux()
SgVlbiStationInfo * stn_1(QMap< QString, SgVlbiStationInfo * >) const
double getMeanGrDelResiduals() const
QList< SgVlbiObservable * > & observables()
void calculateClockF1(SgTaskConfig *)
double getTypicalAmbigSpacing(SgTaskConfig::VlbiDelayType type) const
SgClockBreakIndicator * cbIndicator()
double getMeanGrDelResidualsSigma() const
void setAuxSign(double s)
double getAuxSign() const
void shiftAmbiguities(int deltaN)
double sigma2Apply() const
void setResidual(double)
double getSigma() const
double getResidual() const
double getResidualNorm() const
bool isUsable() const
const SgMJD & epoch() const
int getQualityFactor() const
SgVlbiStationInfo *& stn_2()
SgVlbiStationInfo *& stn_1()
SgVlbiObservation * owner()
SgVlbiSourceInfo * getSrc() const
QString strId() const
SgVlbiSourceInfo *& src()
const QString & getBandKey() const
SgVlbiBaselineInfo * getBaseline() const
SgVlbiBaselineInfo *& baseline()
SgVlbiMeasurement * activeDelay()
SgVlbiMeasurement & grDelay()
SgVlbiMeasurement & sbDelay()
int getMediaIdx() const
double getDrat_dCipY() const
@ Attr_SBD_NOT_VALID
omit the observation if single band delay is analysed;
void setExtRateErp(double v)
SgVlbiStationInfo * stn_1()
SgVlbiAuxObservation * auxObs_2()
void setAprioriCxLfContrib(double v)
void setExtDelayHiFyUt1(double v)
void setAprioriUt1HfContrib(double v)
short int getStation1Idx() const
void setupActiveMeasurement(const SgTaskConfig *)
SgVlbiBaselineInfo * baseline()
double getDdel_dPy() const
void setAprioriCyLfContrib(double v)
double getDrat_dPx() const
void setupActiveObservable(const QString &)
void setAprioriPyLfContrib(double v)
void setExtRateHiFyUt1(double v)
double getDrat_dCipX() const
void setExtDelayErp(double v)
SgVlbiStationInfo * stn_2()
double getDdel_dCipY() const
void setAprioriPyHfContrib(double v)
double getDrat_dUT1() const
void setAprioriUt1LfContrib(double v)
void setExtRateHiFyPxy(double v)
const QString & getScanName() const
void setAprioriPxLfContrib(double v)
void setExtDelayHiFyPxy(double v)
void setAprioriPxHfContrib(double v)
double getDdel_dPx() const
double getDrat_dPy() const
short int getStation2Idx() const
QMap< QString, SgVlbiObservable * > & observableByKey()
double getDdel_dUT1() const
virtual bool isEligible(const SgTaskConfig *)
SgVlbiAuxObservation * auxObs_1()
double getDdel_dCipX() const
const QString & getName() const
@ Attr_FF_OUTLIERS_PROCESSED
outliers have been processed;
@ Attr_FF_AMBIGS_RESOLVED
ambiguities have been resolved;
@ Attr_HAS_IONO_CORR
the theoretical values are available;
@ Attr_HAS_WEIGHTS
the theoretical values are available;
SgMJD tFinis_
last epoch of the observations;
SgMJD tMean_
mean epoch of the observations;
const SgMJD & getTMean() const
SgMJD tStart_
first epoch of the observations;
SgAPriories apStationGradients_
void(* longOperationStart_)(int minStep, int maxStep, const QString &message)
int checkBandForClockBreaks(int, bool)
int numberOfBands() const
StationsByName stationsByName_
bool writeUserData2File(const QString &fileName)
SgVlbiStationInfo * lookupStationByIdx(int)
QList< SgVlbiBand * > & bands()
void resolveGrAmbigTriangles(int bandIdx)
QList< SgVlbiBand * > bands_
SgTidalUt1::UT1TideContentType tabsUt1Type_
void calculateIonoCorrections(const SgTaskConfig *)
SgVector * args4PxyInterpolation_
SgAPriories apStationVelocities_
int restoreOutliers(int bandIdx)
void(* longOperationProgress_)(int step)
double getLeapSeconds()
SgTaskConfig lastProcessedConfig_
QMap< QString, SgVlbiStationInfo * > & stationsByName()
SgAPriories apAxisOffsets_
QList< SgVlbiObservation * > observations_
SgAPriories apSourceStrModel_
SgAPriories apStationPositions_
SgSolutionReporter * reporter_
bool detectClockBreaks_mode1(SgVlbiBand *, QString &, SgMJD &)
void(* longOperationStop_)()
bool hasOutlierRestoratioRun_
void process(bool haveProcessAllBands, bool interactWithGui)
SgAPriories apSourcePositions_
SgCubicSpline * externalErpInterpolator_
bool isInUse(SgVlbiBaselineInfo *)
void scanBaselines4GrDelayAmbiguities(int bandIdx)
SgExternalEopFile externalErpFile_
SgModelsInfo calcInfo_
SgExternalWeights externalWeights_
void(* longOperationMessage_)(const QString &message)
bool hasPxyInterpolation_
void eliminateLargeOutliers(int bandIdx, int maxNumOfPasses, double wrmsRatio)
void correctClockBreak(SgVlbiBand *, SgVlbiStationInfo *, const SgMJD &, double, double, bool, bool=true)
SgCubicSpline * innerUt1Interpolator_
void getAprioriErp(const SgMJD &t, double &vUt1, double &rUt1, double &vPx, double &rPx, double &vPy, double &rPy, double &vCx, double &rCx, double &vCy, double &rCy)
void calculateClockBreaksParameters(QList< SgClockBreakAgent * > &, SgVlbiBand *)
BaselinesByName baselinesByName_
void calculateClockBreakParameter(const SgMJD &, SgVlbiStationInfo *, SgVlbiBand *, double &, double &)
bool hasUt1Interpolation_
SgParametersDescriptor * parametersDescriptor_
QString path2APrioriFiles_
SgVlbiBand * primaryBand_
int eliminateOutliers(int bandIdx)
void eliminateOutliersSimpleMode(int bandIdx, int maxNumOfPasses, double threshold, double=0.0)
bool hasOutlierEliminationRun_
static QString className()
SgVector * args4Ut1Interpolation_
SgMatrix * tabs4Ut1Interpolation_
void(* longOperationShowStats_)(const QString &label, int numTot, int numPrc, double wrms, double chi2)
bool have2InteractWithGui_
int numOfPts4ErpInterpolation_
SourcesByName sourcesByName_
bool isAble2InterpolateErp_
SgCubicSpline * innerPxyInterpolator_
QMap< QString, SgVlbiBaselineInfo * > & baselinesByName()
SgTaskConfig * config_
SgMatrix * tabs4PxyInterpolation_
SgModelEop_JMG_96_hf apHiFyEop_
double getDN_ea() const
void addSrcStructPoint(double k, double b, double x, double y, bool estK=false, bool estB=false, bool estR=false)
double getRA_ea() const
void setAprioriComments(const QString &str)
void setDN_ea(double dn)
double getAl2ExtA() const
double getRA() const
void setRA_ea(double ra)
QList< StructModelMp > & sModel()
void setAl2ExtA(double l)
double getDN() const
static double arcLength(double ra_1, double dn_1, double ra_2, double dn_2)
@ Attr_HAS_A_PRIORI_POS
indicates that the source has a priori position;
double getGradNorth() const
double getAxisOffset() const
void setV_ea(const Sg3dVector &v)
double getGradEast() const
@ Attr_NOT_VALID
omit the station;
@ Attr_CONSTRAIN_COO
constrain station position in estimation;
@ Attr_REFERENCE_CLOCKS
the clocks are the reference ones;
@ Attr_HAS_A_PRIORI_AXO
indicates that the station has a priori axis offset;
@ Attr_ESTIMATE_COO
estimate station position;
@ Attr_HAS_A_PRIORI_POS
indicates that the station has a priori r and v;
void setGradNorth(double v)
void setAxisOffset_ea(double v)
const Sg3dVector & getR()
double getAxisOffset_ea() const
const Sg3dVector & getR_ea()
SgBreakModel & clockBreaks()
int getClocksModelOrder() const
void setR_ea(const Sg3dVector &r)
void setGradEast(double v)