source: ntrip/trunk/BNC/src/rinex/reqcanalyze.cpp@ 6283

Last change on this file since 6283 was 6283, checked in by mervart, 10 years ago
File size: 20.3 KB
RevLine 
[3899]1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class: t_reqcAnalyze
30 *
31 * Purpose: Analyze RINEX Files
32 *
33 * Author: L. Mervart
34 *
35 * Created: 11-Apr-2012
36 *
[6255]37 * Changes:
[3899]38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iostream>
[4361]42#include <iomanip>
[4579]43#include <qwt_plot_renderer.h>
[4574]44
[3899]45#include "reqcanalyze.h"
[5070]46#include "bnccore.h"
[3899]47#include "bncsettings.h"
[4254]48#include "reqcedit.h"
[4255]49#include "bncutils.h"
[4300]50#include "graphwin.h"
[4307]51#include "polarplot.h"
[4577]52#include "availplot.h"
[4662]53#include "eleplot.h"
[4672]54#include "dopplot.h"
[3899]55
56using namespace std;
57
58// Constructor
59////////////////////////////////////////////////////////////////////////////
60t_reqcAnalyze::t_reqcAnalyze(QObject* parent) : QThread(parent) {
61
62 bncSettings settings;
[4254]63
[4257]64 _logFileName = settings.value("reqcOutLogFile").toString(); expandEnvVar(_logFileName);
65 _logFile = 0;
66 _log = 0;
[6271]67 _currEpo = 0;
[4254]68 _obsFileNames = settings.value("reqcObsFile").toString().split(",", QString::SkipEmptyParts);
[4257]69 _navFileNames = settings.value("reqcNavFile").toString().split(",", QString::SkipEmptyParts);
[6275]70
71 connect(this, SIGNAL(dspSkyPlot(const QString&, const QByteArray&, QVector<t_polarPoint*>*,
72 const QByteArray&, QVector<t_polarPoint*>*,
73 const QByteArray&, double)),
74 this, SLOT(slotDspSkyPlot(const QString&, const QByteArray&, QVector<t_polarPoint*>*,
75 const QByteArray&, QVector<t_polarPoint*>*,
76 const QByteArray&, double)));
77
78 connect(this, SIGNAL(dspAvailPlot(const QString&, const QByteArray&)),
79 this, SLOT(slotDspAvailPlot(const QString&, const QByteArray&)));
[3899]80}
81
82// Destructor
83////////////////////////////////////////////////////////////////////////////
84t_reqcAnalyze::~t_reqcAnalyze() {
[4255]85 for (int ii = 0; ii < _rnxObsFiles.size(); ii++) {
86 delete _rnxObsFiles[ii];
87 }
88 for (int ii = 0; ii < _ephs.size(); ii++) {
89 delete _ephs[ii];
90 }
91 delete _log; _log = 0;
92 delete _logFile; _logFile = 0;
[5072]93 if (BNC_CORE->mode() != t_bncCore::interactive) {
[5066]94 qApp->exit(0);
[4452]95 }
[3899]96}
97
[6255]98//
[3899]99////////////////////////////////////////////////////////////////////////////
100void t_reqcAnalyze::run() {
101
[4255]102 // Open Log File
103 // -------------
104 _logFile = new QFile(_logFileName);
[4517]105 if (_logFile->open(QIODevice::WriteOnly | QIODevice::Text)) {
106 _log = new QTextStream();
107 _log->setDevice(_logFile);
108 }
[4255]109
110 // Initialize RINEX Observation Files
111 // ----------------------------------
[4525]112 t_reqcEdit::initRnxObsFiles(_obsFileNames, _rnxObsFiles, _log);
[3899]113
[4257]114 // Read Ephemerides
115 // ----------------
116 t_reqcEdit::readEphemerides(_navFileNames, _ephs);
117
[4255]118 // Loop over all RINEX Files
119 // -------------------------
[4254]120 for (int ii = 0; ii < _rnxObsFiles.size(); ii++) {
121 analyzeFile(_rnxObsFiles[ii]);
122 }
123
[4255]124 // Exit
125 // ----
[4452]126 emit finished();
127 deleteLater();
[3899]128}
[4254]129
[6255]130//
[4254]131////////////////////////////////////////////////////////////////////////////
[4260]132void t_reqcAnalyze::analyzeFile(t_rnxObsFile* obsFile) {
[4259]133
[4517]134 if (_log) {
135 *_log << "\nAnalyze File\n"
136 << "------------\n"
[4701]137 << "File: " << obsFile->fileName().toAscii().data() << endl;
[4517]138 }
[4260]139
[6271]140 _qcFile.clear();
[4343]141
[4342]142 // A priori Coordinates
143 // --------------------
[4679]144 ColumnVector xyzSta = obsFile->xyz();
[4342]145
[4262]146 // Loop over all Epochs
147 // --------------------
[4541]148 try {
[6271]149 bool firstEpo = true;
[4541]150 while ( (_currEpo = obsFile->nextEpoch()) != 0) {
[6271]151 if (firstEpo) {
152 firstEpo = false;
153 _qcFile._startTime = _currEpo->tt;
154 _qcFile._antennaName = obsFile->antennaName();
155 _qcFile._markerName = obsFile->markerName();
156 _qcFile._receiverType = obsFile->receiverType();
157 _qcFile._interval = obsFile->interval();
[4688]158 }
[6271]159 _qcFile._endTime = _currEpo->tt;
[6255]160
[6271]161 t_qcEpo qcEpo;
162 qcEpo._epoTime = _currEpo->tt;
163 qcEpo._PDOP = cmpDOP(xyzSta);
164
[4541]165 // Loop over all satellites
166 // ------------------------
167 for (unsigned iObs = 0; iObs < _currEpo->rnxSat.size(); iObs++) {
168 const t_rnxObsFile::t_rnxSat& rnxSat = _currEpo->rnxSat[iObs];
[6271]169 t_satObs satObs;
170 t_rnxObsFile::setObsFromRnx(obsFile, _currEpo, rnxSat, satObs);
[6281]171 t_qcObs& qcObs = qcEpo._qcObs[satObs._prn];
172 setQcObs(qcEpo._epoTime, xyzSta, satObs, qcObs);
173 updateQcSat(qcObs, _qcFile._qcSat[satObs._prn]);
[4262]174 }
[6271]175 _qcFile._qcEpo.push_back(qcEpo);
176 }
[6255]177
[6281]178 analyzeMultipath();
179
[6271]180 preparePlotData(obsFile);
[4678]181
[6271]182 printReport();
[4541]183 }
184 catch (QString str) {
185 if (_log) {
186 *_log << "Exception " << str << endl;
[4262]187 }
[4541]188 else {
[6255]189 qDebug() << str;
[4541]190 }
191 }
[6271]192}
[4262]193
[6271]194// Compute Dilution of Precision
195////////////////////////////////////////////////////////////////////////////
196double t_reqcAnalyze::cmpDOP(const ColumnVector& xyzSta) const {
[4268]197
[6271]198 if (xyzSta.size() != 3) {
199 return 0.0;
[4268]200 }
201
[6271]202 unsigned nSat = _currEpo->rnxSat.size();
[4706]203
[6271]204 if (nSat < 4) {
205 return 0.0;
[4718]206 }
[6271]207
208 Matrix AA(nSat, 4);
209
210 unsigned nSatUsed = 0;
211 for (unsigned iSat = 0; iSat < nSat; iSat++) {
212
213 const t_rnxObsFile::t_rnxSat& rnxSat = _currEpo->rnxSat[iSat];
214 const t_prn& prn = rnxSat.prn;
215
216 t_eph* eph = 0;
217 for (int ie = 0; ie < _ephs.size(); ie++) {
218 if (_ephs[ie]->prn() == prn) {
219 eph = _ephs[ie];
220 break;
221 }
[4718]222 }
[6271]223 if (eph) {
224 ColumnVector xSat(4);
225 ColumnVector vv(3);
226 if (eph->getCrd(_currEpo->tt, xSat, vv, false) == success) {
227 ++nSatUsed;
228 ColumnVector dx = xSat.Rows(1,3) - xyzSta;
229 double rho = dx.norm_Frobenius();
230 AA(nSatUsed,1) = dx(1) / rho;
231 AA(nSatUsed,2) = dx(2) / rho;
232 AA(nSatUsed,3) = dx(3) / rho;
233 AA(nSatUsed,4) = 1.0;
234 }
[4718]235 }
236 }
[6271]237
238 if (nSatUsed < 4) {
239 return 0.0;
240 }
241
242 AA = AA.Rows(1, nSatUsed);
243
244 SymmetricMatrix QQ;
245 QQ << AA.t() * AA;
246 QQ = QQ.i();
247
248 return sqrt(QQ.trace());
[4254]249}
[4263]250
[6255]251//
[4263]252////////////////////////////////////////////////////////////////////////////
[6271]253void t_reqcAnalyze::updateQcSat(const t_qcObs& qcObs, t_qcSat& qcSat) {
254 if (qcObs._hasL1 && qcObs._hasL2) {
255 qcSat._numObs += 1;
256 }
257 if (qcObs._slipL1 && qcObs._slipL2) {
258 qcSat._numSlipsFlagged += 1;
259 }
260}
[4265]261
[6271]262//
263////////////////////////////////////////////////////////////////////////////
[6281]264void t_reqcAnalyze::setQcObs(const bncTime& epoTime, const ColumnVector& xyzSta,
265 const t_satObs& satObs, t_qcObs& qcObs) {
[4338]266
[6281]267 t_eph* eph = 0;
268 for (int ie = 0; ie < _ephs.size(); ie++) {
269 if (_ephs[ie]->prn() == satObs._prn) {
270 eph = _ephs[ie];
271 break;
[6271]272 }
[6281]273 }
274 if (eph) {
275 ColumnVector xc(4);
276 ColumnVector vv(3);
277 if (xyzSta.size() && eph->getCrd(epoTime, xc, vv, false) == success) {
278 double rho, eleSat, azSat;
279 topos(xyzSta(1), xyzSta(2), xyzSta(3), xc(1), xc(2), xc(3), rho, eleSat, azSat);
280 qcObs._eleSet = true;
281 qcObs._azDeg = azSat * 180.0/M_PI;
282 qcObs._eleDeg = eleSat * 180.0/M_PI;
283 }
284 if (satObs._prn.system() == 'R') {
[6271]285 qcObs._slotSet = true;
[6281]286 qcObs._slotNum = eph->slotNum();
[6271]287 }
288 }
289
[6281]290 // Check Gaps
291 // ----------
292 if (qcObs._lastObsTime.valid()) {
293 double dt = epoTime - qcObs._lastObsTime;
294 if (dt > 1.5 * _qcFile._interval) {
295 qcObs._gapL1 = true;
296 qcObs._gapL2 = true;
297 }
298 }
299 qcObs._lastObsTime = epoTime;
[6271]300
[4608]301 // Availability and Slip Flags
302 // ---------------------------
[6137]303 double L1 = 0.0;
304 double L2 = 0.0;
305 double P1 = 0.0;
306 double P2 = 0.0;
[6271]307 for (unsigned iFrq = 0; iFrq < satObs._obs.size(); iFrq++) {
308 const t_frqObs* frqObs = satObs._obs[iFrq];
[6137]309 if (frqObs->_rnxType2ch[0] == '1') {
310 if (frqObs->_phaseValid) {
[6281]311 L1 = frqObs->_phase;
[6271]312 qcObs._hasL1 = true;
313 qcObs._slipL1 = frqObs->_slip;
[6137]314 }
315 if (frqObs->_codeValid) {
[6255]316 P1 = frqObs->_code;
[6137]317 }
318 if (frqObs->_snrValid) {
[6271]319 qcObs._SNR1 = frqObs->_snr;
[6137]320 }
321 }
[6271]322 else if ( (satObs._prn.system() != 'E' && frqObs->_rnxType2ch[0] == '2') ||
323 (satObs._prn.system() == 'E' && frqObs->_rnxType2ch[0] == '5') ) {
[6137]324 if (frqObs->_phaseValid) {
[6281]325 L2 = frqObs->_phase;
326 qcObs._hasL2 = true;
[6271]327 qcObs._slipL2 = frqObs->_slip;
[6137]328 }
329 if (frqObs->_codeValid) {
[6255]330 P2 = frqObs->_code;
[6137]331 }
332 if (frqObs->_snrValid) {
[6271]333 qcObs._SNR2 = frqObs->_snr;
[6137]334 }
335 }
[4571]336 }
[4608]337
[6281]338 // Compute the Multipath Linear Combination
339 // ----------------------------------------
340 if (L1 != 0.0 && L2 != 0.0 && P1 != 0.0 && P2 != 0.0) {
[6017]341 double f1 = 0.0;
342 double f2 = 0.0;
[6271]343 if (satObs._prn.system() == 'G') {
[6017]344 f1 = t_CST::freq(t_frequency::G1, 0);
345 f2 = t_CST::freq(t_frequency::G2, 0);
346 }
[6271]347 else if (satObs._prn.system() == 'R') {
348 f1 = t_CST::freq(t_frequency::R1, qcObs._slotNum);
349 f2 = t_CST::freq(t_frequency::R2, qcObs._slotNum);
[6017]350 }
[6271]351 else if (satObs._prn.system() == 'E') {
[6017]352 f1 = t_CST::freq(t_frequency::E1, 0);
353 f2 = t_CST::freq(t_frequency::E5, 0);
354 }
[4266]355
[4391]356 L1 = L1 * t_CST::c / f1;
357 L2 = L2 * t_CST::c / f2;
[4266]358
[6281]359 qcObs._rawMP1 = P1 - L1 - 2.0*f2*f2/(f1*f1-f2*f2) * (L1 - L2);
360 qcObs._rawMP2 = P2 - L2 - 2.0*f1*f1/(f1*f1-f2*f2) * (L1 - L2);
361 qcObs._mpSet = true;
[4265]362 }
[4263]363}
[4350]364
[6255]365//
[4350]366////////////////////////////////////////////////////////////////////////////
[6281]367void t_reqcAnalyze::analyzeMultipath() {
[4675]368
[6271]369 const double SLIPTRESH = 10.0; // cycle-slip threshold (meters)
370 const double chunkStep = 600.0; // 10 minutes
[4584]371
[6271]372 // Loop over all satellites available
373 // ----------------------------------
374 QMutableMapIterator<t_prn, t_qcSat> it(_qcFile._qcSat);
375 while (it.hasNext()) {
376 it.next();
377 const t_prn& prn = it.key();
378 t_qcSat& qcSat = it.value();
[4351]379
[6271]380 // Loop over all Chunks of Data
381 // ----------------------------
382 for (bncTime chunkStart = _qcFile._startTime;
383 chunkStart < _qcFile._endTime; chunkStart += chunkStep) {
[4702]384
[6281]385 bncTime chunkEnd = chunkStart + chunkStep;
[4353]386
[6281]387 QVector<t_qcObs*> obsVec;
388 QVector<double> MP1;
389 QVector<double> MP2;
[6271]390
391 // Loop over all Epochs within one Chunk of Data
392 // ---------------------------------------------
393 for (int iEpo = 0; iEpo < _qcFile._qcEpo.size(); iEpo++) {
[6280]394 t_qcEpo& qcEpo = _qcFile._qcEpo[iEpo];
[6281]395 if (chunkStart <= qcEpo._epoTime && qcEpo._epoTime < chunkEnd) {
396 if (qcEpo._qcObs.contains(prn)) {
397 t_qcObs& qcObs = qcEpo._qcObs[prn];
398 obsVec << &qcObs;
399 if (qcObs._mpSet) {
400 MP1 << qcObs._rawMP1;
401 MP2 << qcObs._rawMP2;
[6213]402 }
[4590]403 }
404 }
405 }
[4563]406
[6281]407 // Compute the multipath mean and standard deviation
408 // -------------------------------------------------
409 if (MP1.size() > 1) {
[6271]410 double meanMP1 = 0.0;
411 double meanMP2 = 0.0;
412 for (int ii = 0; ii < MP1.size(); ii++) {
413 meanMP1 += MP1[ii];
414 meanMP2 += MP2[ii];
415 }
416 meanMP1 /= MP1.size();
417 meanMP2 /= MP2.size();
[4590]418
[6271]419 bool slipMP = false;
[6281]420
[6271]421 double stdMP1 = 0.0;
422 double stdMP2 = 0.0;
423 for (int ii = 0; ii < MP1.size(); ii++) {
424 double diff1 = MP1[ii] - meanMP1;
425 double diff2 = MP2[ii] - meanMP2;
426 if (fabs(diff1) > SLIPTRESH || fabs(diff2) > SLIPTRESH) {
427 slipMP = true;
428 break;
429 }
430 stdMP1 += diff1 * diff1;
[6276]431 stdMP2 += diff2 * diff2;
[4700]432 }
[6255]433
[6271]434 if (slipMP) {
[6281]435 stdMP1 = 0.0;
436 stdMP2 = 0.0;
[6271]437 qcSat._numSlipsFound += 1;
[4702]438 }
[6271]439 else {
[6281]440 stdMP1 = sqrt(stdMP1 / (MP1.size()-1));
441 stdMP2 = sqrt(stdMP2 / (MP2.size()-1));
[6271]442 }
[6281]443
444 for (int ii = 0; ii < obsVec.size(); ii++) {
445 t_qcObs* qcObs = obsVec[ii];
446 if (slipMP) {
447 qcObs->_slipL1 = true;
448 qcObs->_slipL2 = true;
449 }
450 else {
451 qcObs->_stdMP1 = stdMP1;
452 qcObs->_stdMP2 = stdMP2;
453 }
454 }
[6255]455 }
[6281]456 }
457 }
458}
459
460//
461////////////////////////////////////////////////////////////////////////////
462void t_reqcAnalyze::preparePlotData(const t_rnxObsFile* obsFile) {
463
464 QVector<t_polarPoint*>* dataMP1 = new QVector<t_polarPoint*>;
465 QVector<t_polarPoint*>* dataMP2 = new QVector<t_polarPoint*>;
466 QVector<t_polarPoint*>* dataSNR1 = new QVector<t_polarPoint*>;
467 QVector<t_polarPoint*>* dataSNR2 = new QVector<t_polarPoint*>;
468
469 bncSettings settings;
470 QString reqSkyPlotSystems = settings.value("reqcSkyPlotSystems").toString();
471 bool plotGPS = false;
472 bool plotGlo = false;
473 bool plotGal = false;
474 if (reqSkyPlotSystems == "GPS") {
475 plotGPS = true;
476 }
477 else if (reqSkyPlotSystems == "GLONASS") {
478 plotGlo = true;
479 }
480 else if (reqSkyPlotSystems == "Galileo") {
481 plotGal = true;
482 }
483 else {
484 plotGPS = true;
485 plotGlo = true;
486 plotGal = true;
487 }
488
489 // Loop over all observations
490 // --------------------------
491 for (int iEpo = 0; iEpo < _qcFile._qcEpo.size(); iEpo++) {
492 t_qcEpo& qcEpo = _qcFile._qcEpo[iEpo];
493 QMapIterator<t_prn, t_qcObs> it(qcEpo._qcObs);
494 while (it.hasNext()) {
495 it.next();
496 const t_prn& prn = it.key();
497 const t_qcObs& qcObs = it.value();
[6271]498 if ( (prn.system() == 'G' && plotGPS) ||
499 (prn.system() == 'R' && plotGlo) ||
500 (prn.system() == 'E' && plotGal) ) {
[6281]501
502 (*dataSNR1) << (new t_polarPoint(qcObs._azDeg, 90.0 - qcObs._eleDeg, qcObs._SNR1));
503 (*dataSNR2) << (new t_polarPoint(qcObs._azDeg, 90.0 - qcObs._eleDeg, qcObs._SNR2));
504
505 (*dataMP1) << (new t_polarPoint(qcObs._azDeg, 90.0 - qcObs._eleDeg, qcObs._stdMP1));
506 (*dataMP2) << (new t_polarPoint(qcObs._azDeg, 90.0 - qcObs._eleDeg, qcObs._stdMP2));
[4700]507 }
[4353]508 }
[6271]509 }
[4353]510
[6271]511 // Show the plots
512 // --------------
513 if (BNC_CORE->GUIenabled()) {
514 QFileInfo fileInfo(obsFile->fileName());
515 QByteArray title = fileInfo.fileName().toAscii();
[6275]516 emit dspSkyPlot(obsFile->fileName(), "MP1", dataMP1, "MP2", dataMP2, "Meters", 2.0);
517 emit dspSkyPlot(obsFile->fileName(), "SNR1", dataSNR1, "SNR2", dataSNR2, "dbHz", 54.0);
518 emit dspAvailPlot(obsFile->fileName(), title);
[6271]519 }
520 else {
521 for (int ii = 0; ii < dataMP1->size(); ii++) {
522 delete dataMP1->at(ii);
[4351]523 }
[6271]524 delete dataMP1;
525 for (int ii = 0; ii < dataMP2->size(); ii++) {
526 delete dataMP2->at(ii);
[4591]527 }
[6271]528 delete dataMP2;
529 for (int ii = 0; ii < dataSNR1->size(); ii++) {
530 delete dataSNR1->at(ii);
[4659]531 }
[6271]532 delete dataSNR1;
533 for (int ii = 0; ii < dataSNR2->size(); ii++) {
534 delete dataSNR2->at(ii);
[5141]535 }
[6271]536 delete dataSNR2;
[4350]537 }
538}
[4572]539
[6255]540//
[4572]541////////////////////////////////////////////////////////////////////////////
[6275]542void t_reqcAnalyze::slotDspSkyPlot(const QString& fileName, const QByteArray& title1,
543 QVector<t_polarPoint*>* data1, const QByteArray& title2,
544 QVector<t_polarPoint*>* data2, const QByteArray& scaleTitle,
545 double maxValue) {
[4572]546
[5068]547 if (BNC_CORE->GUIenabled()) {
[4573]548
[6271]549 if (maxValue == 0.0) {
550 if (data1) {
551 for (int ii = 0; ii < data1->size(); ii++) {
552 double val = data1->at(ii)->_value;
553 if (maxValue < val) {
554 maxValue = val;
555 }
556 }
557 }
558 if (data2) {
559 for (int ii = 0; ii < data2->size(); ii++) {
560 double val = data2->at(ii)->_value;
561 if (maxValue < val) {
562 maxValue = val;
563 }
564 }
565 }
566 }
[4659]567
[6271]568 QwtInterval scaleInterval(0.0, maxValue);
[4671]569
[4573]570 QVector<QWidget*> plots;
[6271]571 if (data1) {
572 t_polarPlot* plot1 = new t_polarPlot(QwtText(title1), scaleInterval,
573 BNC_CORE->mainWindow());
574 plot1->addCurve(data1);
575 plots << plot1;
576 }
577 if (data2) {
578 t_polarPlot* plot2 = new t_polarPlot(QwtText(title2), scaleInterval,
579 BNC_CORE->mainWindow());
580 plot2->addCurve(data2);
581 plots << plot2;
582 }
[4666]583
[6271]584 t_graphWin* graphWin = new t_graphWin(0, fileName, plots,
585 &scaleTitle, &scaleInterval);
[4666]586
[4573]587 graphWin->show();
588
589 bncSettings settings;
590 QString dirName = settings.value("reqcPlotDir").toString();
591 if (!dirName.isEmpty()) {
[6271]592 QByteArray ext = (scaleTitle == "Meters") ? "_M.png" : "_S.png";
[4579]593 graphWin->savePNG(dirName, ext);
[4573]594 }
595 }
[4572]596}
[4679]597
[6271]598//
[4679]599////////////////////////////////////////////////////////////////////////////
[6275]600void t_reqcAnalyze::slotDspAvailPlot(const QString& fileName, const QByteArray& title) {
[4679]601
[6280]602 t_plotData plotData;
[6278]603 QMap<t_prn, t_plotData> plotDataMap;
[6272]604
[6278]605 for (int ii = 0; ii < _qcFile._qcEpo.size(); ii++) {
606 const t_qcEpo& qcEpo = _qcFile._qcEpo[ii];
[6280]607 double mjdX24 = qcEpo._epoTime.mjddec() * 24.0;
608
609 plotData._mjdX24 << mjdX24;
610 plotData._PDOP << qcEpo._PDOP;
611 plotData._numSat << qcEpo._qcObs.size();
612
[6278]613 QMapIterator<t_prn, t_qcObs> it(qcEpo._qcObs);
614 while (it.hasNext()) {
615 it.next();
616 const t_prn& prn = it.key();
617 const t_qcObs& qcObs = it.value();
[6280]618 t_plotData& data = plotDataMap[prn];
[6283]619 data._mjdX24 << mjdX24;
620 data._eleDeg << qcObs._eleDeg;
[6280]621 if (qcObs._hasL1) data._L1ok << mjdX24;
622 if (qcObs._hasL2) data._L2ok << mjdX24;
623 if (qcObs._slipL1) data._L1slip << mjdX24;
624 if (qcObs._slipL2) data._L2slip << mjdX24;
625 if (qcObs._gapL1) data._L1gap << mjdX24;
626 if (qcObs._gapL2) data._L2gap << mjdX24;
[6278]627 }
628 }
629
[6279]630
[6271]631 if (BNC_CORE->GUIenabled()) {
[6278]632 t_availPlot* plotA = new t_availPlot(0, plotDataMap);
[6271]633 plotA->setTitle(title);
[4679]634
[6278]635 t_elePlot* plotZ = new t_elePlot(0, plotDataMap);
[4679]636
[6279]637 t_dopPlot* plotD = new t_dopPlot(0, plotData);
[4679]638
[6271]639 QVector<QWidget*> plots;
640 plots << plotA << plotZ << plotD;
641 t_graphWin* graphWin = new t_graphWin(0, fileName, plots, 0, 0);
[4679]642
[6271]643 int ww = QFontMetrics(graphWin->font()).width('w');
644 graphWin->setMinimumSize(120*ww, 40*ww);
[4679]645
[6271]646 graphWin->show();
[4679]647
[6271]648 bncSettings settings;
649 QString dirName = settings.value("reqcPlotDir").toString();
650 if (!dirName.isEmpty()) {
651 QByteArray ext = "_A.png";
652 graphWin->savePNG(dirName, ext);
[4679]653 }
[4681]654 }
[4679]655}
[4689]656
657// Finish the report
658////////////////////////////////////////////////////////////////////////////
[6271]659void t_reqcAnalyze::printReport() {
[5368]660
[4689]661 if (!_log) {
662 return;
663 }
664
[6271]665 *_log << "Marker name: " << _qcFile._markerName << endl
666 << "Receiver: " << _qcFile._receiverType << endl
667 << "Antenna: " << _qcFile._antennaName << endl
668 << "Start time: " << _qcFile._startTime.datestr().c_str() << ' '
669 << _qcFile._startTime.timestr().c_str() << endl
670 << "End time: " << _qcFile._endTime.datestr().c_str() << ' '
671 << _qcFile._endTime.timestr().c_str() << endl
672 << "Interval: " << _qcFile._interval << endl
673 << "# Sat.: " << _qcFile._qcSat.size() << endl;
[4689]674
[4701]675 int numObs = 0;
676 int numSlipsFlagged = 0;
677 int numSlipsFound = 0;
[6271]678 QMapIterator<t_prn, t_qcSat> it(_qcFile._qcSat);
[4693]679 while (it.hasNext()) {
680 it.next();
[6271]681 const t_qcSat& qcSat = it.value();
682 numObs += qcSat._numObs;
683 numSlipsFlagged += qcSat._numSlipsFlagged;
684 numSlipsFound += qcSat._numSlipsFound;
[4693]685 }
[4701]686 *_log << "# Obs.: " << numObs << endl
687 << "# Slips (file): " << numSlipsFlagged << endl
688 << "# Slips (found): " << numSlipsFound << endl;
[4693]689
[4689]690 _log->flush();
691}
Note: See TracBrowser for help on using the repository browser.