General Purpose Geodetic Library
SgVlbiObservable.cpp
Go to the documentation of this file.
1 /*
2  *
3  * This file is a part of Space Geodetic Library. The library is used by
4  * nuSolve, a part of CALC/SOLVE system, and designed to make analysis of
5  * geodetic VLBI observations.
6  * Copyright (C) 2010-2020 Sergei Bolotin.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #include <iostream>
24 #include <stdlib.h>
25 
26 
27 #include <QtCore/QDataStream>
28 #include <QtCore/QVector>
29 
30 
31 #include <SgLogger.h>
32 #include <SgMathSupport.h>
33 #include <SgTaskConfig.h>
34 #include <SgVector.h>
35 #include <SgVlbiBand.h>
36 #include <SgVlbiObservable.h>
37 #include <SgVlbiObservation.h>
38 #include <SgVlbiSession.h>
39 
40 
41 
42 //
43 // declarations (just to use them only here):
44 void findPeak(const std::complex<double> *cA, int n, double &dD, double &dP);
45 
46 //
47 bool evaluatePhaseCals(const SgVector& pcPhases, const SgVector& pcAmplitudes,
48  const SgVector& pcFreqByChan, double refFreq,
49  double& phaseCalGrd, double& phaseCalGrdAmbig,
50  double& phaseCalPhd, double& phaseCalPhdAmbig,
51  const QString& oId);
52 
53 
54 
55 /*=======================================================================================================
56 *
57 * METHODS:
58 *
59 *======================================================================================================*/
60 //
61 // static first:
63 {
64  return "SgVlbiObservable";
65 };
66 
67 
68 
69 // CONSTRUCTORS:
70 //
71 // An empty constructor:
73  bandKey_(""),
74  sbDelay_("Single Band Delay", SgTaskConfig::VD_SB_DELAY, SgTaskConfig::VR_NONE),
75  grDelay_("Group Delay", SgTaskConfig::VD_GRP_DELAY, SgTaskConfig::VR_NONE),
76  phDelay_("Phase Delay", SgTaskConfig::VD_PHS_DELAY, SgTaskConfig::VR_NONE),
77  phDRate_("Phase Rate", SgTaskConfig::VD_NONE, SgTaskConfig::VR_PHS_RATE),
78  errorCode_(""),
79  tapeQualityCode_(""),
80  nonUsableReason_(),
81  fourfitOutputFName_(""),
82  fourfitControlFile_(""),
83  fourfitCommandOverride_(""),
84  epochOfCorrelation_(tZero),
85  epochOfFourfitting_(tZero),
86  epochOfScan_(tZero),
87  epochCentral_(tZero),
88  tStart_(tZero),
89  tStop_(tZero)
90 {
91  mediaIdx_ = -1;
92  owner_ = obs;
93  band_ = NULL;
94  baseline_ = NULL;
95  stn_1_ = NULL;
96  stn_2_ = NULL;
97  src_ = NULL;
98  referenceFrequency_ = 0.0;
99  totalPhase_ = 0.0;
100  corrCoeff_ = 0.0;
101  snr_ = 0.0;
102  qualityFactor_ = 0;
103  numOfChannels_ = 0;
104  isUsable_ = true;
105 // nonUsableReason_ = NUR_UNDEF;
107  activeRate_ = NULL;
108  fourfitVersion_[0] = -1;
109  fourfitVersion_[1] = -1;
110  //
111  startOffset_ = 0;
112  stopOffset_ = 0;
113  centrOffset_ = 0.0;
114  sampleRate_ = 0.0;
115  bitsPerSample_ = 0;
116  effIntegrationTime_ = 0.0;
117  acceptedRatio_ = 0.0;
118  discardRatio_ = 0.0;
119  incohChanAddAmp_ = 0.0;
120  incohSegmAddAmp_ = 0.0;
122  geocenterTotalPhase_ = 0.0;
123  geocenterResidPhase_ = 0.0;
124  aPrioriDra_[0] = aPrioriDra_[1] = aPrioriDra_[2] = 0.0;
128 
129  //
130  for (int i=0; i<2; i++)
131  {
134  phaseCalRates_[i] = uvFrPerAsec_[i] = uRvR_[i] = corrClocks_[i][0] =
135  corrClocks_[i][1] = instrDelay_[i] = 0.0;
137  };
138  nLags_ = 0;
139  for (int i=0; i<6; i++)
140  fourfitSearchParameters_[i] = 0.0;
142 
147  refFreqByChan_ = NULL;
148  fringeAmplitudeByChan_ = NULL;
149  fringePhaseByChan_ = NULL;
150  polarization_1ByChan_ = NULL;
151  polarization_2ByChan_ = NULL;
152  phaseCalData_1ByChan_ = NULL;
153  phaseCalData_2ByChan_ = NULL;
154  vDlys_ = NULL;
155  vAuxData_ = NULL;
156  corelIndexNumUSB_ = NULL;
157  corelIndexNumLSB_ = NULL;
158 
159  chanIdByChan_ = NULL;
160  loFreqByChan_1_ = NULL;
161  loFreqByChan_2_ = NULL;
162  bbcIdxByChan_1_ = NULL;
163  bbcIdxByChan_2_ = NULL;
164 
165 
166  phaseCalModes_ = -1;
167  //
168  // temporary/tests:
169  sbdDiffBand_ = 0.0;
170  grdDiffBand_ = 0.0;
171  phrDiffBand_ = 0.0;
172  sbdQ_ = 0.0;
173  grdQ_ = 0.0;
174  phrQ_ = 0.0;
175  dTauS_= 0.0;
176  dTest_ = dTest2_ = 0.0;
177 };
178 
179 
180 
181 //
183  bandKey_(band?band->getKey():""),
184  sbDelay_("Single Band Delay", SgTaskConfig::VD_SB_DELAY, SgTaskConfig::VR_NONE),
185  grDelay_("Group Delay", SgTaskConfig::VD_GRP_DELAY, SgTaskConfig::VR_NONE),
186  phDelay_("Phase Delay", SgTaskConfig::VD_PHS_DELAY, SgTaskConfig::VR_NONE),
187  phDRate_("Phase Rate", SgTaskConfig::VD_NONE, SgTaskConfig::VR_PHS_RATE),
188  errorCode_(""),
189  tapeQualityCode_(""),
190  nonUsableReason_(),
191  fourfitOutputFName_(""),
192  fourfitControlFile_(""),
193  fourfitCommandOverride_(""),
194  epochOfCorrelation_(tZero),
195  epochOfFourfitting_(tZero),
196  epochOfScan_(tZero),
197  epochCentral_(tZero),
198  tStart_(tZero),
199  tStop_(tZero)
200 {
201  mediaIdx_ = -1;
202  owner_ = obs;
203  band_ = band;
204  baseline_ = NULL;
205  stn_1_ = NULL;
206  stn_2_ = NULL;
207  src_ = NULL;
208  referenceFrequency_ = 0.0;
209  totalPhase_ = 0.0;
210  corrCoeff_ = 0.0;
211  snr_ = 0.0;
212  qualityFactor_ = 0;
213  numOfChannels_ = 0;
214  isUsable_ = true;
215 // nonUsableReason_ = NUR_UNDEF;
217  activeRate_ = NULL;
218  fourfitVersion_[0] = 0;
219  fourfitVersion_[1] = 0;
220  //
221  startOffset_ = 0;
222  stopOffset_ = 0;
223  centrOffset_ = 0.0;
224  sampleRate_ = 0.0;
225  bitsPerSample_ = 0;
226  effIntegrationTime_ = 0.0;
227  acceptedRatio_ = 0.0;
228  discardRatio_ = 0.0;
229  incohChanAddAmp_ = 0.0;
230  incohSegmAddAmp_ = 0.0;
232  geocenterTotalPhase_ = 0.0;
233  geocenterResidPhase_ = 0.0;
234  aPrioriDra_[0] = aPrioriDra_[1] = aPrioriDra_[2] = 0.0 ;
238  //
239  for (int i=0; i<2; i++)
240  {
243  phaseCalRates_[i] = uvFrPerAsec_[i] = uRvR_[i] = corrClocks_[i][0] =
244  corrClocks_[i][1] = instrDelay_[i] = 0.0;
246  };
247  nLags_ = 0;
248  for (int i=0; i<6; i++)
249  fourfitSearchParameters_[i] = 0.0;
251  //
256  refFreqByChan_ = NULL;
257  fringeAmplitudeByChan_ = NULL;
258  fringePhaseByChan_ = NULL;
259  polarization_1ByChan_ = NULL;
260  polarization_2ByChan_ = NULL;
261  phaseCalData_1ByChan_ = NULL;
262  phaseCalData_2ByChan_ = NULL;
263  vDlys_ = NULL;
264  vAuxData_ = NULL;
265  corelIndexNumUSB_ = NULL;
266  corelIndexNumLSB_ = NULL;
267 
268  chanIdByChan_ = NULL;
269  loFreqByChan_1_ = NULL;
270  loFreqByChan_2_ = NULL;
271  bbcIdxByChan_1_ = NULL;
272  bbcIdxByChan_2_ = NULL;
273 
274  phaseCalModes_ = -1;
275  //
276  // temporary/tests:
277  sbdDiffBand_ = 0.0;
278  grdDiffBand_ = 0.0;
279  phrDiffBand_ = 0.0;
280  sbdQ_ = 0.0;
281  grdQ_ = 0.0;
282  phrQ_ = 0.0;
283  dTauS_= 0.0;
284  dTest_ = dTest2_ = 0.0;
285 };
286 
287 
288 
289 
290 
291 
292 // A copy constructor:
294  bandKey_(o.getBandKey()),
295  sbDelay_(o.sbDelay_),
296  grDelay_(o.grDelay_),
297  phDelay_(o.phDelay_),
298  phDRate_(o.phDRate_),
299  errorCode_(o.getErrorCode()),
300  tapeQualityCode_(o.getTapeQualityCode()),
301  fourfitOutputFName_(o.getFourfitOutputFName()),
302  fourfitControlFile_(o.getFourfitControlFile()),
303  fourfitCommandOverride_(o.getFourfitCommandOverride()),
304  epochOfCorrelation_(o.getEpochOfCorrelation()),
305  epochOfFourfitting_(o.getEpochOfFourfitting()),
306  epochOfScan_(o.getEpochOfScan()),
307  epochCentral_(o.getEpochCentral()),
308  tStart_(o.getTstart()),
309  tStop_(o.getTstop())
310 {
311  owner_ = obs;
312  band_ = o.band_;
313  baseline_ = o.getBaseline();
314  stn_1_ = o.getStn_1();
315  stn_2_ = o.getStn_2();
316  src_ = o.getSrc();
321  setSnr(o.getSnr());
325  activeRate_ = NULL;
328  //
342  setAprioriDra(0, o.getAprioriDra(0));
343  setAprioriDra(1, o.getAprioriDra(1));
344  setAprioriDra(2, o.getAprioriDra(2));
351 
352  for (int i=0; i<2; i++)
353  {
358  setUrVr(i, o.getUrVr(i));
359  setCorrClocks(i, 0, o.getCorrClocks(i, 0));
360  setCorrClocks(i, 1, o.getCorrClocks(i, 1));
361  setInstrDelay(i, o.getInstrDelay(i));
362  }
363  setNlags(o.getNlags());
364  for (int i=0; i<6; i++)
367 
368  //
371  else
373 
376  else
378 
379  if (o.numOfSamplesByChan_USB())
381  else
383 
384  if (o.numOfSamplesByChan_LSB())
386  else
388 
389  if (o.refFreqByChan())
391  else
392  refFreqByChan_ = NULL;
393 
394  if (o.fringeAmplitudeByChan())
396  else
397  fringeAmplitudeByChan_ = NULL;
398 
399  if (o.fringePhaseByChan())
401  else
402  fringePhaseByChan_ = NULL;
403 
404  if (o.polarization_1ByChan())
405  polarization_1ByChan_ = new QVector<char>(*o.polarization_1ByChan());
406  else
407  polarization_1ByChan_ = NULL;
408 
409  if (o.polarization_2ByChan())
410  polarization_2ByChan_ = new QVector<char>(*o.polarization_2ByChan());
411  else
412  polarization_2ByChan_ = NULL;
413 
414  if (o.phaseCalData_1ByChan())
416  else
417  phaseCalData_1ByChan_ = NULL;
418 
419  if (o.vDlys())
420  vDlys_ = new SgVector(*o.vDlys());
421  else
422  vDlys_ = NULL;
423 
424  if (o.vAuxData())
425  vAuxData_ = new SgVector(*o.vAuxData());
426  else
427  vAuxData_ = NULL;
428 
429  if (o.phaseCalData_2ByChan())
431  else
432  phaseCalData_2ByChan_ = NULL;
433 
435 
436  if (o.corelIndexNumUSB())
437  corelIndexNumUSB_ = new QVector<int>(*o.corelIndexNumUSB());
438  else
439  corelIndexNumUSB_ = NULL;
440 
441  if (o.corelIndexNumLSB())
442  corelIndexNumLSB_ = new QVector<int>(*o.corelIndexNumLSB());
443  else
444  corelIndexNumLSB_ = NULL;
445 
446  //
447  if (o.chanIdByChan())
448  chanIdByChan_ = new QVector<char>(*o.chanIdByChan());
449  else
450  chanIdByChan_ = NULL;
451 
452  if (o.loFreqByChan_1())
454  else
455  loFreqByChan_1_ = NULL;
456  if (o.loFreqByChan_2())
458  else
459  loFreqByChan_2_ = NULL;
460 
461  bbcIdxByChan_1_ = o.bbcIdxByChan_1() ? new QVector<int>(*o.bbcIdxByChan_1()) : NULL;
462  bbcIdxByChan_2_ = o.bbcIdxByChan_2() ? new QVector<int>(*o.bbcIdxByChan_2()) : NULL;
463  //
464  // temporary/tests:
468  setSbdQ(o.getSbdQ());
469  setGrdQ(o.getGrdQ());
470  setPhrQ(o.getPhrQ());
471  dTauS_ = o.getTauS();
472  dTest_ = o.dTest_;
473  dTest2_ = o.dTest2_;
474 };
475 
476 
477 
478 //
480 {
481  switch (cfg->getUseDelayType())
482  {
483  default:
485  activeDelay_ = NULL;
486  break;
489  break;
492  break;
495  break;
496  };
497  switch (cfg->getUseRateType())
498  {
499  default:
501  activeRate_ = NULL;
502  break;
505  break;
506  };
507 };
508 
509 
510 
511 // returns true if the obs is potentially good:
513 {
514  bool isOk=true;
515  // quality code:
516  if (cfg && getQualityFactor()<cfg->getQualityCodeThreshold())
517  isOk = false;
518  // deselected station, baseline, source:
520  return false;
522  return false;
524  return false;
526  return false;
527  // ionosphere:
528  //if (isOk && owner_->session()->isAttr(SgVlbiSession::Attr_FF_ION_C_CALCULATED))
530  {
531  if (owner_->observableByKey().size() == 1) //missed obs on the other band
532  isOk = false;
533  if (isOk && cfg && owner_->minQualityFactor() < cfg->getQualityCodeThreshold()) //not enough quality
534  isOk = false;
535  };
536  return isOk;
537 };
538 
539 
540 
542 {
543  isUsable_ = true;
545  //
546  if (cfg && getQualityFactor()<cfg->getQualityCodeThreshold())
547  {
548  isUsable_ = false;
550  };
551  if (1<band_->getMaxNumOfChannels() && numOfChannels_ < 2)
552  {
553  isUsable_ = false;
555  };
557  {
558  isUsable_ = false;
560  };
562  {
563  isUsable_ = false;
565  };
567  {
568  isUsable_ = false;
570  };
572  {
573  isUsable_ = false;
575  };
576  if (errorCode_.simplified().size() &&
577  !((cfg->getUseQualityCodeG() && errorCode_.contains('G')) ||
578  (cfg->getUseQualityCodeH() && errorCode_.contains('H')) ) )
579  {
580  isUsable_ = false;
582  };
583  //
584  // dual band combinations, check other band:
585  if (owner_->session()->bands().size()>1 &&
586 // owner_->session()->isAttr(SgVlbiSession::Attr_FF_ION_C_CALCULATED) &&
594  )
595  {
596  if (owner_->observableByKey().size() == 1)
597  {
598  isUsable_ = false;
600  }
601  else
602  for (int i=0; i<owner_->passiveObses().size(); i++)
603  {
605  if (o->getQualityFactor() < cfg->getQualityCodeThreshold())
606  {
607  isUsable_ = false;
609  };
610  if (1<o->band()->getMaxNumOfChannels() && o->getNumOfChannels() < 2)
611  {
612  isUsable_ = false;
614  };
615  if (o->getErrorCode().simplified().size() &&
616  !((cfg->getUseQualityCodeG() && o->getErrorCode().contains('G')) ||
617  (cfg->getUseQualityCodeH() && o->getErrorCode().contains('H')) ) )
618  {
619  isUsable_ = false;
621  };
622  };
623  };
624 };
625 
626 
627 
628 //
630 {
631  return owner_?(*owner_):tZero;
632 };
633 
634 
635 
636 //
637 QString SgVlbiObservable::strId() const
638 {
639  QString srcN("?"), blnN("?:?");
642  if (!si)
644  if (!bi)
646  if (si)
647  srcN = si->getKey();
648  if (bi)
649  blnN = bi->getKey();
650  return
651  " #" + QString("").setNum(mediaIdx_) + " on " + bandKey_ + "-band, " +
652  epoch().toString(SgMJD::F_YYYYMMDDHHMMSSSS) + " of " + srcN + " at " + blnN +
653  " [" + owner_->getScanName() + "]";
654 };
655 
656 
657 
658 //
660 {
662  if ((numOfChannels_=numOfChans) > 0)
663  {
671  polarization_1ByChan_ = new QVector<char>(numOfChannels_);
672  polarization_2ByChan_ = new QVector<char>(numOfChannels_);
675  //
676  vDlys_ = new SgVector(3);
677  vAuxData_ = new SgVector(5);
678  // fixed size (mimic dbedit behavior):
679  corelIndexNumUSB_ = new QVector<int>(numOfChannels_);
680  corelIndexNumLSB_ = new QVector<int>(numOfChannels_);
681  //
682  chanIdByChan_ = new QVector<char>(numOfChannels_);
685  bbcIdxByChan_1_ = new QVector<int>(numOfChannels_);
686  bbcIdxByChan_2_ = new QVector<int>(numOfChannels_);
687  }
688  else
690  ": allocateChannelsSetupStorages(): an attempt to allocate data with zero number of channels");
691 };
692 
693 
694 
695 //
697 {
699  {
702  };
704  {
707  };
709  {
712  };
714  {
717  };
718  if (refFreqByChan_)
719  {
720  delete refFreqByChan_;
721  refFreqByChan_ = NULL;
722  };
724  {
725  delete fringeAmplitudeByChan_;
726  fringeAmplitudeByChan_ = NULL;
727  };
728  if (fringePhaseByChan_)
729  {
730  delete fringePhaseByChan_;
731  fringePhaseByChan_ = NULL;
732  };
734  {
735  delete polarization_1ByChan_;
736  polarization_1ByChan_ = NULL;
737  };
739  {
740  delete polarization_2ByChan_;
741  polarization_2ByChan_ = NULL;
742  };
744  {
745  delete phaseCalData_1ByChan_;
746  phaseCalData_1ByChan_ = NULL;
747  };
749  {
750  delete phaseCalData_2ByChan_;
751  phaseCalData_2ByChan_ = NULL;
752  };
753  if (vDlys_)
754  {
755  delete vDlys_;
756  vDlys_ = NULL;
757  };
758  if (vAuxData_)
759  {
760  delete vAuxData_;
761  vAuxData_ = NULL;
762  };
763  if (corelIndexNumUSB_)
764  {
765  delete corelIndexNumUSB_;
766  corelIndexNumUSB_ = NULL;
767  };
768  if (corelIndexNumLSB_)
769  {
770  delete corelIndexNumLSB_;
771  corelIndexNumLSB_ = NULL;
772  };
773 
774  if (chanIdByChan_)
775  {
776  delete chanIdByChan_;
777  chanIdByChan_ = NULL;
778  };
779  if (loFreqByChan_1_)
780  {
781  delete loFreqByChan_1_;
782  loFreqByChan_1_ = NULL;
783  };
784  if (loFreqByChan_2_)
785  {
786  delete loFreqByChan_2_;
787  loFreqByChan_2_ = NULL;
788  };
789  if (bbcIdxByChan_1_)
790  {
791  delete bbcIdxByChan_1_;
792  bbcIdxByChan_1_ = NULL;
793  };
794  if (bbcIdxByChan_2_)
795  {
796  delete bbcIdxByChan_2_;
797  bbcIdxByChan_2_ = NULL;
798  };
799 };
800 
801 
802 
803 //
804 /*
805 int SgVlbiObservable::qualityFactor() const
806 {
807  int qFactor;
808  bool isOk;
809  qFactor = qualityCode_.toInt(&isOk);
810  if (!isOk)
811  qFactor = -1;
812  return qFactor;
813 };
814 */
815 
816 
817 
818 //
820 {
821  int n=-29;
822  if (errorCode_ == "" || errorCode_ == " " || errorCode_ == " ")
823  n = 0;
824  else if (errorCode_ == "A")
825  n = -1;
826  else if (errorCode_ == "B")
827  n = -2;
828  else if (errorCode_ == "C")
829  n = -3;
830  else if (errorCode_ == "D")
831  n = -4;
832  else if (errorCode_ == "E")
833  n = -5;
834  else if (errorCode_ == "F")
835  n = -6;
836  else if (errorCode_ == "G")
837  n = -7;
838  else if (errorCode_ == "H")
839  n = -8;
840  else if (errorCode_ == "I")
841  n = -9;
842  else if (errorCode_ == "J")
843  n = -10;
844  else if (errorCode_ == "K")
845  n = -11;
846  else if (errorCode_ == "L")
847  n = -12;
848  else if (errorCode_ == "M")
849  n = -13;
850  else if (errorCode_ == "N")
851  n = -14;
852  else if (errorCode_ == "O")
853  n = -15;
854  else if (errorCode_ == "P")
855  n = -16;
856  else if (errorCode_ == "Q")
857  n = -17;
858  else if (errorCode_ == "R")
859  n = -18;
860  else if (errorCode_ == "S")
861  n = -19;
862  else if (errorCode_ == "T")
863  n = -20;
864  else if (errorCode_ == "U")
865  n = -21;
866  else if (errorCode_ == "V")
867  n = -22;
868  else if (errorCode_ == "W")
869  n = -23;
870  else if (errorCode_ == "X")
871  n = -24;
872  else if (errorCode_ == "Y")
873  n = -25;
874  else if (errorCode_ == "Z")
875  n = -26;
876  return n;
877 };
878 
879 
880 
881 //
883 {
888  if (sbDelay_.getSigma() < 5.0e-12)
890  if (grDelay_.getSigma() < 1.0e-15)
892 };
893 
894 
895 
896 //
898 {
900  if (s.status() == QDataStream::Ok &&
905  return s.status() == QDataStream::Ok;
906  else
907  return false;
908 };
909 
910 
911 
912 //
914 {
915  QString bandKey;
916  int mediaIdx;
917  bool is;
918  unsigned int attributes;
919  s >> bandKey >> mediaIdx >> is >> attributes;
920  if (s.status() == QDataStream::Ok)
921  {
922  if (bandKey_ != bandKey)
923  {
925  ": loadIntermediateResults(): error reading " + bandKey_ +
926  "-band data: bandKey mismatch: got [" + bandKey + "], expected [" + bandKey_ + "]");
927  return false;
928  };
929  if (mediaIdx_ != mediaIdx)
930  {
932  ": loadIntermediateResults(): error reading " + bandKey_ +
933  "-band data: media index mismatch: got [" +
934  QString("").setNum(mediaIdx) + "], expected [" + QString("").setNum(mediaIdx_) + "]");
935  return false;
936  };
937  isUsable_ = is;
938  nonUsableReason_.setAttributes(attributes);
943  return true;
944  };
946  ": loadIntermediateResults(): error reading data: " +
947  (s.status()==QDataStream::ReadPastEnd?"read past end of the file":"read corrupt data"));
948  return false;
949 };
950 
951 
952 
953 //
955 {
956  if (snr_ <= 0.0) // just noise
957  return;
958 
959  if (!owner_)
960  {
962  ": calcPhaseDelay(): cannot calculate phase delay: the owner is NULL");
963  return;
964  };
965  if (!band_)
966  {
968  ": calcPhaseDelay(): cannot calculate phase delay: the band is NULL");
969  return;
970  };
971  SgVlbiAuxObservation *aux_1=owner_->auxObs_1(), *aux_2=owner_->auxObs_2();
972  if (!(aux_1 && aux_2))
973  {
975  ": calcPhaseDelay(): cannot calculate phase delay: the aux obss are NULL");
976  return;
977  };
978  double vPhDly, ePhDly, aPhDly, dNumAmbigs;
979 
980  vPhDly = (totalPhase_ - (aux_2->getParallacticAngle() - aux_1->getParallacticAngle()))*1.0e-6
981  /(2.0*M_PI*referenceFrequency_);
982  if (1.0e-10 < snr_)
983  ePhDly = 1.0e-6/(2.0*M_PI*referenceFrequency_*snr_);
984  else
985  {
987  ": calcPhaseDelay(): got unusual value for SNR: " + QString("").setNum(snr_));
988  ePhDly = 1.0e-6/(2.0*M_PI*referenceFrequency_);
989  };
990  aPhDly = 1.0e-6/referenceFrequency_; // refFreq is in Mhz
991  dNumAmbigs = round((grDelay_.getValue() + grDelay_.ambiguity() - vPhDly)/aPhDly);
992 
993  phDelay_.setValue(vPhDly + dNumAmbigs*aPhDly);
994  phDelay_.setSigma(ePhDly);
996 };
997 
998 
999 
1000 //
1002 {
1003  if (!band_)
1004  {
1006  ": calcPhaseCalDelay(): cannot calculate phase cal effects: band is NULL");
1007  return;
1008  };
1009  if (!refFreqByChan_)
1010  {
1012  ": calcPhaseCalDelay(): cannot calculate phase cal effects: ref.freq storage is NULL");
1013  return;
1014  };
1015  if (!phaseCalData_1ByChan_)
1016  {
1018  ": calcPhaseCalDelay(): cannot calculate phase cal effects: pcal phases @1 storage is NULL");
1019  return;
1020  };
1021  if (!phaseCalData_2ByChan_)
1022  {
1024  ": calcPhaseCalDelay(): cannot calculate phase cal effects: pcal phases @2 storage is NULL");
1025  return;
1026  };
1028  {
1030  ": calcPhaseCalDelay(): cannot calculate phase cal effects: size mismatch for @1: " +
1031  QString("").sprintf("#chan(%d) != #PCchan(%d)",
1033  return;
1034  };
1036  {
1038  ": calcPhaseCalDelay(): cannot calculate phase cal effects: size mismatch for @2");
1039  return;
1040  };
1041  int n=refFreqByChan_->n();
1042  SgVector *pcPhases_1 = new SgVector(n);
1043  SgVector *pcPhases_2 = new SgVector(n);
1044  SgVector *pcAmplitudes_1 = new SgVector(n);
1045  SgVector *pcAmplitudes_2 = new SgVector(n);
1046 
1047  for (int i=0; i<n; i++)
1048  {
1049  pcPhases_1 ->setElement(i, phaseCalData_1ByChan_->getElement(PCCI_PHASE, i) +
1051  pcPhases_2 ->setElement(i, phaseCalData_2ByChan_->getElement(PCCI_PHASE, i) +
1053 //
1054 // pcAmplitudes_1->setElement(i, phaseCalData_1ByChan_->getElement(PCCI_AMPLITUDE, i)*1.0e-4);
1055 // pcAmplitudes_2->setElement(i, phaseCalData_2ByChan_->getElement(PCCI_AMPLITUDE, i)*1.0e-4);
1056 //
1057  pcAmplitudes_1->setElement(i, phaseCalData_1ByChan_->getElement(PCCI_AMPLITUDE, i));
1058  pcAmplitudes_2->setElement(i, phaseCalData_2ByChan_->getElement(PCCI_AMPLITUDE, i));
1059  pcAmplitudes_1->setElement(i, 1.0);
1060  pcAmplitudes_2->setElement(i, 1.0);
1061  };
1062 
1063  double phaseCalGrd=0.0;
1064  double phaseCalGrdAmbig=0.0;
1065  double phaseCalPhd=0.0;
1066  double phaseCalPhdAmbig=0.0;
1067 
1068  if (evaluatePhaseCals(*pcPhases_1, *pcAmplitudes_1, *refFreqByChan_, referenceFrequency_,
1069  phaseCalGrd, phaseCalGrdAmbig, phaseCalPhd, phaseCalPhdAmbig, strId()))
1070  {
1071  phaseCalGrDelays_[0] = phaseCalGrd*1.0e-9;
1072  phaseCalPhDelays_[0] = phaseCalPhd*1.0e-9;
1073  phaseCalGrAmbigSpacings_[0] = phaseCalGrdAmbig*1.0e-9;
1074  phaseCalPhAmbigSpacings_[0] = phaseCalPhdAmbig*1.0e-9;
1075  };
1076 
1077  if (evaluatePhaseCals(*pcPhases_2, *pcAmplitudes_2, *refFreqByChan_, referenceFrequency_,
1078  phaseCalGrd, phaseCalGrdAmbig, phaseCalPhd, phaseCalPhdAmbig, strId()))
1079  {
1080  phaseCalGrDelays_[1] = phaseCalGrd*1.0e-9;
1081  phaseCalPhDelays_[1] = phaseCalPhd*1.0e-9;
1082  phaseCalGrAmbigSpacings_[1] = phaseCalGrdAmbig*1.0e-9;
1083  phaseCalPhAmbigSpacings_[1] = phaseCalPhdAmbig*1.0e-9;
1084  };
1085  //
1086  delete pcPhases_1;
1087  delete pcPhases_2;
1088  delete pcAmplitudes_1;
1089  delete pcAmplitudes_2;
1090 };
1091 /*=====================================================================================================*/
1092 
1093 
1094 
1095 /*=====================================================================================================*/
1096 //
1097 // FRIENDS:
1098 //
1099 /*=====================================================================================================*/
1100 //
1101 
1102 
1103 
1104 /*=====================================================================================================*/
1105 //
1106 // aux functions:
1107 //
1108 /*=====================================================================================================*/
1109 //
1110 bool evaluatePhaseCals(const SgVector& pcPhases, const SgVector& pcAmplitudes,
1111  const SgVector& pcFreqByChan, double refFreq,
1112  double& phaseCalGrd, double& phaseCalGrdAmbig,
1113  double& phaseCalPhd, double& phaseCalPhdAmbig,
1114  const QString& oId)
1115 {
1116  int nChan=pcFreqByChan.n();
1117  phaseCalGrdAmbig = 0.0;
1118  phaseCalPhdAmbig = 0.0;
1119  if (nChan == 0)
1120  {
1122  "evaluatePhaseCals: number of actual channels is zero, nothing to do for the obs " + oId);
1123  return false;
1124  };
1125  if (nChan == 1)
1126  {
1128  "evaluatePhaseCals: have only one actual channel, nothing to do for the obs " + oId);
1129  return false;
1130  };
1131  //
1132  std::complex<double> *x_a, *x_A;
1133  double rfMin, diffMin, d;
1134  int *idxs=new int[nChan], nData=512;
1135  double dD, dP;
1136  diffMin = 1.0e12;
1137  rfMin = 1.0e15;
1138  //
1139  for (int i=0; i<nChan; i++)
1140  {
1141  if ( (d=fabs(pcFreqByChan.getElement(i))) < rfMin)
1142  rfMin = d;
1143  for (int j=i+1; j<nChan; j++)
1144  {
1145  d = fabs(pcFreqByChan.getElement(j) - pcFreqByChan.getElement(i));
1146  if (0.0 < d && d < diffMin)
1147  diffMin = d;
1148  };
1149  };
1150  phaseCalGrdAmbig = 1.0/diffMin*1.0e3;
1151  phaseCalPhdAmbig = 1.0/refFreq*1.0e3;
1152  //
1153  for (int i=0; i<nChan; i++)
1154  if (nData <= (idxs[i]=((fabs(pcFreqByChan.getElement(i)) - rfMin)/diffMin)))
1155  {
1157  "evaluatePCal4GrpDelay: Array overrun for the obs " + oId +
1158  QString("").sprintf(": idxs[%d]=%d for %.2f and Fmin=%.2f Dmin=%.2f",
1159  i, idxs[i], pcFreqByChan.getElement(i), rfMin, diffMin));
1160  delete[] idxs;
1161  return false;
1162  };
1163  //
1164  x_a = new std::complex<double>[nData];
1165  x_A = new std::complex<double>[nData];
1166  for (int i=0; i<nData; i++)
1167  x_a[i] = x_A[i] = std::complex<double>(0.0, 0.0);
1168  for (int i=0; i<nChan; i++)
1169  x_a[idxs[i]] = std::complex<double>(pcAmplitudes.getElement(i)*cos(pcPhases.getElement(i)),
1170  pcAmplitudes.getElement(i)*sin(pcPhases.getElement(i)));
1171  //
1172  // perform FFT:
1173  fft(x_a, x_A, nData, FFT_Inverse);
1174  //
1175  findPeak(x_A, nData, dD, dP);
1176  //
1177  phaseCalGrd = phaseCalGrdAmbig*dD/nData;
1178  phaseCalGrd = fmod(phaseCalGrd + phaseCalGrdAmbig*2.5, phaseCalGrdAmbig) - 0.5*phaseCalGrdAmbig;
1179  //
1180  phaseCalPhd = dP/(2.0*M_PI)*phaseCalPhdAmbig + (refFreq - rfMin)*1.0e-3*phaseCalGrd;
1181  //
1182  delete[] idxs;
1183  delete[] x_a;
1184  delete[] x_A;
1185  return true;
1186 };
1187 
1188 
1189 
1190 //
1191 void findPeak(const std::complex<double> *cA, int n, double &dD, double &dP)
1192 {
1193  double dX1, dX2, dX3, dA1, dA2, dA3, dP1, dP2, dP3;
1194  double d, dx;
1195  int idx1, idx2, idx3;
1196 
1197  idx1 = idx2 = idx3 = 0;
1198  dX1 = dX2 = dX3 = dA1 = dA3 = dP1 = dP2 = dP3 = 0.0;
1199  dA2 = -1.0;
1200  for (int i=0; i<n; i++)
1201  if (dA2 <= (d=abs(cA[i])) )
1202  {
1203  dA2 = d;
1204  idx1 = idx2 = idx3 = i;
1205  };
1206  dX1 = idx2 - 1;
1207  dX2 = idx2;
1208  dX3 = idx2 + 1;
1209 
1210  if (--idx1 < 0)
1211  idx1 += n;
1212  if (n <= ++idx3)
1213  idx3 -= n;
1214  // get amplitudes and phases:
1215  dA1 = abs(cA[idx1]);
1216  dA3 = abs(cA[idx3]);
1217  dP1 = arg(cA[idx1]);
1218  dP2 = arg(cA[idx2]);
1219  dP3 = arg(cA[idx3]);
1220  // adjust the phases if necessary:
1221  if (M_PI <= fabs(dP1 - dP2))
1222  dP1 = dP2 + fmod(dP1 - dP2 + 5.0*M_PI, 2.0*M_PI) - M_PI;
1223  if (M_PI <= fabs(dP2 - dP3))
1224  dP3 = dP2 + fmod(dP3 - dP2 + 5.0*M_PI, 2.0*M_PI) - M_PI;
1225  //
1226  if (false) // general expression for maximum:
1227  {
1228  dD = 0.5*(dX3*dX3*(dA1 - dA2) + dX2*dX2*(dA3 - dA1) + dX1*dX1*(dA2 - dA3))/
1229  (dX3* (dA1 - dA2) + dX2* (dA3 - dA1) + dX1* (dA2 - dA3));
1230  dx = dD - dX2;
1231  }
1232  else // simplified, assuming x1=-1, x2=0, x3=1:
1233  {
1234  dx = 0.5*(dA1 - dA3)/(dA1 - 2.0*dA2 + dA3);
1235  dD = dX2 + dx;
1236  };
1237  //
1238  // it is assumed x1=-1, x2=0, x3=1:
1239  dP = dP2 + 0.5*(dP3 - dP1)*dx + 0.5*(dP1 - 2.0*dP2 + dP3)*dx*dx;
1240  return;
1241 };
1242 /*=====================================================================================================*/
1243 //
1244 // statics:
1245 //
1246 /*=====================================================================================================*/
1247 
1248 
1249 
1250 
1251 /*=====================================================================================================*/
SgLogger * logger
Definition: SgLogger.cpp:231
const SgMJD tZero(1957, 10, 4)
void fft(std::complex< double > x_a[], std::complex< double > x_A[], unsigned int n, FFT_Direction dir)
@ FFT_Inverse
Definition: SgMathSupport.h:82
void findPeak(const std::complex< double > *cA, int n, double &dD, double &dP)
bool evaluatePhaseCals(const SgVector &pcPhases, const SgVector &pcAmplitudes, const SgVector &pcFreqByChan, double refFreq, double &phaseCalGrd, double &phaseCalGrdAmbig, double &phaseCalPhd, double &phaseCalPhdAmbig, const QString &oId)
bool isAttr(uint a) const
Definition: SgAttribute.h:226
void setAttributes(unsigned int a)
Definition: SgAttribute.h:191
void clearAll()
Definition: SgAttribute.h:234
unsigned int getAttributes() const
Definition: SgAttribute.h:183
void addAttr(uint a)
Definition: SgAttribute.h:202
virtual void write(LogLevel, quint32, const QString &, bool=false)
Definition: SgLogger.cpp:88
@ IO_BIN
Definition: SgLogger.h:64
@ IO_DBH
Definition: SgLogger.h:67
@ PREPROC
Definition: SgLogger.h:98
Definition: SgMJD.h:59
@ F_YYYYMMDDHHMMSSSS
Long verbose: Fri, the 2nd of Apr, 2010; 17hr 02min 43.6400sec.
Definition: SgMJD.h:67
QString toString(Format format=F_Verbose) const
Definition: SgMJD.cpp:1008
double getElement(unsigned int i, unsigned int j) const
Definition: SgMatrix.h:385
unsigned int nCol() const
Definition: SgMatrix.h:360
const QString & getKey() const
Definition: SgObjectInfo.h:319
@ Attr_NOT_VALID
omit the observation;
Definition: SgObservation.h:78
bool getUseQualityCodeH() const
Definition: SgTaskConfig.h:849
VlbiDelayType getUseDelayType() const
Definition: SgTaskConfig.h:873
int getQualityCodeThreshold() const
Definition: SgTaskConfig.h:833
VlbiRateType getUseRateType() const
Definition: SgTaskConfig.h:881
bool getUseQualityCodeG() const
Definition: SgTaskConfig.h:841
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 getParallacticAngle() const
int getMaxNumOfChannels() const
Definition: SgVlbiBand.h:392
@ Attr_USE_IONO4GRD
use ionosphere corrections for group delays;
@ Attr_USE_IONO4PHD
use ionosphere corrections for phase delays;
@ Attr_NOT_VALID
omit the baseline;
void setAmbiguitySpacing(double)
bool saveIntermediateResults(QDataStream &) const
double ambiguity() const
double getValue() const
bool loadIntermediateResults(QDataStream &)
double getSigma() const
SgVlbiSourceInfo * src_
bool saveIntermediateResults(QDataStream &) const
void releaseChannelsSetupStorages()
QVector< int > * corelIndexNumLSB()
QVector< int > * bbcIdxByChan_2_
double getPhaseCalPhDelays(int i) const
void setNumOfChannels(int)
double getUvFrPerAsec(int i) const
bool isRestorable_old(const SgTaskConfig *)
double getPhaseCalGrDelays(int i) const
void setBitsPerSample(int bps)
const SgMJD & epoch() const
double getSbdQ() const
SgMatrix * phaseCalData_1ByChan_
int getQualityFactor() const
void setGrdQ(double)
int phaseCalGrAmbigMultipliers_[2]
double getGrdQ() const
void setCorrClocks(int i, int j, double d)
void setTotalPhase(double)
void setHopsRevisionNumber(int num)
QVector< char > * chanIdByChan_
void setGrdDiffBand(double)
SgVlbiMeasurement phDelay_
SgVlbiStationInfo * getStn_1() const
void setPhaseCalGrDelays(int i, double d)
double getSampleRate() const
QVector< char > * polarization_1ByChan()
double getInstrDelay(int i) const
SgVector * loFreqByChan_1()
QVector< char > * chanIdByChan()
void setIncohSegmAddAmp(double d)
QVector< int > * corelIndexNumUSB()
double getFourfitSearchParameters(int i) const
double getTauS() const
int getNumOfChannels() const
void setupActiveMeasurements(const SgTaskConfig *)
SgVector * loFreqByChan_2_
void setPhaseCalModes(int modes)
SgMatrix * phaseCalData_2ByChan()
void setAcceptedRatio(double d)
const QString & getErrorCode() const
SgVlbiBand * band()
SgVector * fringeAmplitudeByChan_
double getSbdDiffBand() const
int getPhaseCalModes() const
double getIncohChanAddAmp() const
QVector< int > * bbcIdxByChan_1_
QVector< int > * corelIndexNumLSB_
SgVlbiObservation * owner()
double probabOfFalseDetection_
SgVlbiMeasurement sbDelay_
void setPhaseCalPhDelays(int i, double d)
SgVector * numOfSamplesByChan_USB_
void setPhrQ(double)
SgVector * numOfAccPeriodsByChan_LSB()
double getAcceptedRatio() const
void setIncohChanAddAmp(double d)
double getCalcFeedCorrDelay() const
SgVlbiObservable(SgVlbiObservation *)
SgVector * numOfSamplesByChan_LSB_
void setCentrOffset(double offset)
double getProbabOfFalseDetection() const
double getPhrDiffBand() const
void setEffIntegrationTime(double d)
QVector< char > * polarization_2ByChan()
SgVector * numOfAccPeriodsByChan_USB()
QVector< int > * bbcIdxByChan_1()
static const QString className()
SgVlbiStationInfo * getStn_2() const
SgVlbiSourceInfo * getSrc() const
double phaseCalPhDelays_[2]
void setGeocenterResidPhase(double d)
void setCorrelStarElev_2(double v)
double getGrdDiffBand() const
void setSnr(double)
void setProbabOfFalseDetection(double d)
void setQualityFactor(int)
double phaseCalRates_[2]
QString strId() const
int phaseCalPhAmbigMultipliers_[2]
double getCorrelZdelay_1() const
double getGeocenterTotalPhase() const
void setNlags(int n)
void setGeocenterTotalPhase(double d)
double getEffIntegrationTime() const
SgMatrix * phaseCalData_2ByChan_
void setDiscardRatio(double d)
double getCorrClocks(int i, int j) const
double phaseCalGrAmbigSpacings_[2]
SgVector * fringeAmplitudeByChan()
void setCorrCoeff(double)
SgVector * vAuxData()
double phaseCalGrDelays_[2]
SgVlbiBaselineInfo * baseline_
void setUrVr(int i, double d)
void setCorrelZdelay_1(double v)
int getStartOffset() const
QVector< char > * polarization_1ByChan_
SgVector * fringePhaseByChan_
SgVector * refFreqByChan_
void checkUsability(const SgTaskConfig *)
double getUrVr(int i) const
double getCentrOffset() const
int errorCode2Int() const
SgVector * numOfSamplesByChan_LSB()
QVector< int > * corelIndexNumUSB_
void setPhrDiffBand(double)
double getAprioriDra(int i) const
void setAprioriDra(int i, double d)
void setInstrDelay(int i, double d)
double getCorrelStarElev_2() const
double getDiscardRatio() const
void setPhaseCalRates(int i, double d)
int getNlags() const
double getTotalPhase() const
void setStopOffset(int offset)
SgVector * vDlys()
SgVlbiStationInfo * stn_2_
int getHopsRevisionNumber() const
int getFourfitVersion(int idx) const
double getIncohSegmAddAmp() const
int getStopOffset() const
void setUvFrPerAsec(int i, double d)
double getSnr() const
QVector< char > * polarization_2ByChan_
SgVector * numOfAccPeriodsByChan_LSB_
SgMatrix * phaseCalData_1ByChan()
SgVector * numOfSamplesByChan_USB()
SgVlbiBaselineInfo * getBaseline() const
void setReferenceFrequency(double)
double getPhaseCalRates(int i) const
void setCorrelZdelay_2(double v)
double getCalcFeedCorrRate() const
double getReferenceFrequency() const
void allocateChannelsSetupStorages(int numOfChans)
SgVlbiMeasurement * activeRate_
double getCorrelStarElev_1() const
bool loadIntermediateResults(QDataStream &)
SgVlbiMeasurement * activeDelay_
int getBitsPerSample() const
SgVlbiBand * band_
void setCalcFeedCorrDelay(double v)
double getCorrCoeff() const
SgVlbiMeasurement phDRate_
double fourfitSearchParameters_[6]
SgVector * loFreqByChan_2()
double phaseCalPhAmbigSpacings_[2]
SgVector * numOfAccPeriodsByChan_USB_
double corrClocks_[2][2]
void setStartOffset(int offset)
double getPhrQ() const
void setSbdDiffBand(double)
SgAttribute nonUsableReason_
SgVector * fringePhaseByChan()
double getGeocenterResidPhase() const
void setSbdQ(double)
SgVector * refFreqByChan()
void setFourfitSearchParameters(int i, double d)
SgVector * loFreqByChan_1_
void setSampleRate(double sr)
SgVlbiObservation * owner_
int getMediaIdx() const
void setCorrelStarElev_1(double v)
void setCalcFeedCorrRate(double v)
QVector< int > * bbcIdxByChan_2()
SgVlbiStationInfo * stn_1_
double getCorrelZdelay_2() const
SgVlbiMeasurement grDelay_
@ Attr_SBD_NOT_VALID
omit the observation if single band delay is analysed;
SgVlbiStationInfo * stn_1()
SgVlbiAuxObservation * auxObs_2()
SgVlbiSession * session()
SgVlbiSourceInfo * src()
SgVlbiBaselineInfo * baseline()
QList< SgVlbiObservable * > & passiveObses()
short int getSourceIdx() const
SgVlbiStationInfo * stn_2()
int minQualityFactor() const
const QString & getScanName() const
QMap< QString, SgVlbiObservable * > & observableByKey()
SgVlbiAuxObservation * auxObs_1()
short int getBaselineIdx() const
@ Attr_HAS_IONO_CORR
the theoretical values are available;
QList< SgVlbiBand * > & bands()
SgVlbiSourceInfo * lookupSourceByIdx(int)
SgVlbiBaselineInfo * lookupBaselineByIdx(int)
@ Attr_NOT_VALID
omit the source;
@ Attr_NOT_VALID
omit the station;