Skip to content

Commit d76102b

Browse files
committed
minor
1 parent 3ab68e7 commit d76102b

4 files changed

Lines changed: 194 additions & 67 deletions

File tree

include/dpod.hpp

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,110 @@
1818
#include <cstring>
1919

2020
namespace dso {
21+
/** @brief Parse harmonics off from a dpod_freq_cor file and compute
22+
* (cartesian) corrections (ΔX, ΔY, ΔZ).
23+
*
24+
* Give a dpod20*_freq_corr.txt file, do the following things:
25+
* 1. search through all of the sites included in sites_crd and get their
26+
* frequency/harmonics info,
27+
* 2. compute the total, accumulated harmonics contribution (i.e. for all of
28+
* the included frequencies) in cartesian components (ΔX, ΔY, ΔZ)
29+
* 3. store results of step 2 in an std::vector<Sinex::SiteCoordinateResults>
30+
* and return it.
31+
*
32+
* Hence, if the function is successeful, to get the 'correct' position of a
33+
* given site at the sites_crd vector, the contribution returned from the call
34+
* should be added.
35+
*
36+
* Note that the resulting vector (std::vector<Sinex::SiteCoordinateResults>)
37+
* will have a one-to-one correspondance with the input sites_crd vector, i.e.
38+
* the sites will be placed exactly in the same order.
39+
*
40+
* Why do we need a std::vector<Sinex::SiteCoordinateResults> as input? Well,
41+
* this vector will (probably) hold results/positions from a respective
42+
* dpod SINEX file. But, we must know the SOLN_ID, i.e. the solution id that
43+
* was used to compute/extrapolate the coordinates. The same solution id must
44+
* be used to identify the 'correct' harmonics to be applyied.
45+
*
46+
* See for example the following block:
47+
* ---------------------------------------------------------------------------
48+
#CODE PT __DOMES__SOLN_XYZ_COSAMP__COSSTD__SINAMP__SINSTD
49+
REUB A 97401S002 2 X 2.564 0.183 0.060 0.183
50+
REUB A 97401S002 2 Y 2.498 0.151 1.706 0.151
51+
REUB A 97401S002 2 Z -2.041 0.099 0.593 0.099
52+
ROTA A 66007S001 2 X 0.287 0.106 -0.930 0.106
53+
ROTA A 66007S001 2 Y 1.241 0.086 1.994 0.086
54+
ROTA A 66007S001 2 Z -1.842 0.084 -2.067 0.084
55+
AJAB A 10077S002 1 X -0.000 0.001 0.000 0.001
56+
AJAB A 10077S002 1 Y -0.000 0.001 0.000 0.001
57+
AJAB A 10077S002 1 Z 0.000 0.001 -0.000 0.001
58+
TRIB A 30604S002 1 X 0.884 0.161 -0.812 0.163
59+
TRIB A 30604S002 1 Y 0.409 0.255 -0.705 0.259
60+
TRIB A 30604S002 1 Z -1.148 0.139 -0.276 0.141
61+
SAKA A 12329S001 3 X 4.723 0.294 0.807 0.293
62+
SAKA A 12329S001 3 Y -2.538 0.345 -2.942 0.345
63+
* ---------------------------------------------------------------------------
64+
* has harmonics insformation w.r.t different solution id's; hence, this file
65+
* cannot be treated without prior knowledge of the information in the SINEX
66+
* file.
67+
*
68+
* @param[in] fn Filename of the dpod20*_freq_corr.txt file
69+
* @param[in] t Epoch at which to compute the harmonic contributions. If f is
70+
* the frequency of the harmonic, then the harmonic correction is
71+
* computed as: A_{cos} * cos(2*π*fdoy / f)
72+
* +A_{sin} * sin(2*π*fdoy / f)
73+
* @param[in] sites_crd An std::vector<Sinex::SiteCoordinateResults> where the
74+
* requested sites and solution id's are retrieved from. We are
75+
* going to compute harmonic corrections for each of the sites
76+
* included in this vector, tagged with the same solution id as the
77+
* one recorded in here. Wea re matching against (i.e. identifying
78+
* same sites) by:
79+
* - site_code
80+
* - point_code
81+
* - domes, and
82+
* - solution_id
83+
* @return A std::vector<Sinex::SiteCoordinateResults>, in exactly the same
84+
* order as the input sites_crd vector, but in its (x,y,z) coordinates
85+
* the accumulated frequency corrections are stored (in [m]). In case
86+
* a site is not included in the file or has no harmonic terms, its
87+
* (x,y,z) coordinates will be (0,0,0).
88+
*/
89+
[[nodiscard]]
90+
std::vector<Sinex::SiteCoordinateResults> get_dpod_freq_corr(
91+
const char *fn, const datetime<dso::nanoseconds> &t,
92+
const std::vector<Sinex::SiteCoordinateResults> &sites_crd);
93+
94+
/** @brief Parse harmonics off from a dpod_freq_cor file and compute
95+
* (cartesian) corrections (ΔX, ΔY, ΔZ).
96+
*
97+
* This function does exaclty the same as get_dpod_freq_corr, but instead of
98+
* returning the accumulated frequency correcions, it adds them the passed-in
99+
* sites_crd vector (inplace).
100+
*
101+
* @param[in] fn Filename of the dpod20*_freq_corr.txt file
102+
* @param[in] t Epoch at which to compute the harmonic contributions. If f is
103+
* the frequency of the harmonic, then the harmonic correction is
104+
* computed as: A_{cos} * cos(2*π*fdoy / f)
105+
* +A_{sin} * sin(2*π*fdoy / f)
106+
* @param[in] sites_crd An std::vector<Sinex::SiteCoordinateResults> where the
107+
* requested sites and solution id's are retrieved from. We are
108+
* going to compute harmonic corrections for each of the sites
109+
* included in this vector, tagged with the same solution id as the
110+
* one recorded in here. We are matching against (i.e. identifying
111+
* same sites) by:
112+
* - site_code
113+
* - point_code
114+
* - domes, and
115+
* - solution_id
116+
* At output, the vector will hold the combined input+freq_cor
117+
* terms. I.e., the computed frequency corrections terms will be
118+
* added (per site) each of the vector's input holdings.
119+
* @return An integer, where anything other than 0 denotes an error.
120+
*/
121+
[[nodiscard]]
21122
int apply_dpod_freq_corr(
22-
const char *fn,
23-
const dso::datetime<dso::nanoseconds> &t,
24-
const std::vector<Sinex::SiteCoordinateResults> &sites_crd) noexcept;
123+
const char *fn, const datetime<dso::nanoseconds> &t,
124+
std::vector<Sinex::SiteCoordinateResults> &sites_crd) noexcept;
25125
} /* namespace dso */
26126

27127
#endif

src/dpod_extrapolate.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#include "utilities.hpp"
22

3-
int dso::dpod_extrapolate(const dso::datetime<dso::nanoseconds> &t, const std::vector<const char *> &sites_4charid, const char *dpod_snx, const char *dpod_freq=nullptr) noexcept {
3+
int dso::dpod_extrapolate(const dso::datetime<dso::nanoseconds> &t,
4+
const std::vector<const char *> &sites_4charid,
5+
const char *dpod_snx,
6+
const char *dpod_freq = nullptr) noexcept {
47
/* create the sinex instance */
58
dso::Sinex snx(dpod_snx);
69

@@ -24,10 +27,13 @@ int dso::dpod_extrapolate(const dso::datetime<dso::nanoseconds> &t, const std::v
2427

2528
/* append harmonics signal(s) -> crd */
2629
if (dpod_freq) {
27-
if (dso::apply_dpod_freq_corr(dpod_freq, t, crd)) {
28-
fprintf(stderr, "[ERROR] Failed applying dpod frequency corrections; file is %s (traceback: %s)\n", dpod_freq, __func__);
29-
return 1;
30-
}
30+
if (dso::apply_dpod_freq_corr(dpod_freq, t, crd)) {
31+
fprintf(stderr,
32+
"[ERROR] Failed applying dpod frequency corrections; file is %s "
33+
"(traceback: %s)\n",
34+
dpod_freq, __func__);
35+
return 1;
36+
}
3137
}
3238

3339
return 0;

src/parse_dpod_freq_corr.cpp

Lines changed: 80 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include <charconv>
44
#include <cstdio>
55
#include <fstream>
6-
#include <limits>
6+
#include <stdexcept>
77

88
namespace {
99

@@ -89,11 +89,15 @@ constexpr const int sdata_start = 27;
8989
* 012345678901234567890123456789012345678901234567890123456789
9090
* 10 20 30 40 50
9191
*/
92-
int resolve_freq_cor_data_line(const char *line, char cmp, double *data) noexcept {
92+
int resolve_freq_cor_data_line(const char *line, char cmp,
93+
double *data) noexcept {
9394
/* get component (one char) */
9495
cmp = line[24];
9596
if ((cmp != 'X' && cmp != 'Y') && (cmp != 'Z')) {
96-
fprintf(stderr, "[ERROR] Failed resolving dpod/freq line [%s], invalid XYZ field! (traceback: %s)\n", line, __func__);
97+
fprintf(stderr,
98+
"[ERROR] Failed resolving dpod/freq line [%s], invalid XYZ field! "
99+
"(traceback: %s)\n",
100+
line, __func__);
97101
return 1;
98102
}
99103
const char *str = line + 27;
@@ -108,22 +112,25 @@ int resolve_freq_cor_data_line(const char *line, char cmp, double *data) noexcep
108112
}
109113
} /* anonymous namespace */
110114

111-
int dso::apply_dpod_freq_corr(
112-
const char *fn,
113-
const dso::datetime<dso::nanoseconds> &t,
114-
const std::vector<dso::Sinex::SiteCoordinateResults> &sites_crd) noexcept {
115+
std::vector<dso::Sinex::SiteCoordinateResults> dso::get_dpod_freq_corr(
116+
const char *fn, const dso::datetime<dso::nanoseconds> &t,
117+
const std::vector<dso::Sinex::SiteCoordinateResults> &sites_crd) {
115118
/* open dpod freq file */
116119
std::ifstream fin(fn);
117120
if (!fin.is_open()) {
118121
fprintf(stderr,
119122
"[ERROR] Failed opening dpod freq_corr file %s (traceback: %s)\n",
120123
fn, __func__);
121-
return 1;
124+
throw std::runtime_error("[ERROR] Failed opening dpod freq_corr file\n");
122125
}
123126

124127
/* copy of input coordinates */
125128
std::vector<dso::Sinex::SiteCoordinateResults> scpy(sites_crd);
126129

130+
/* zero-out (cartesian) positions */
131+
for (auto it = scpy.begin(); it != scpy.end(); ++it)
132+
it->x = it->y = it->z = 0e0;
133+
127134
/* fractional day of year and phase at epoch */
128135
const auto ymd_ = t.as_ydoy();
129136
const int idoy_ = ymd_.dy().as_underlying_type();
@@ -134,41 +141,46 @@ int dso::apply_dpod_freq_corr(
134141
char line[SZ];
135142
double cfreq = 0;
136143
double data[4];
137-
char ccmp;
144+
char ccmp = 'Q';
138145
double omega = 0e0;
139-
int nfreq=0;
146+
int nfreq = 0;
140147

141148
int error = 0;
142149
while (fin.getline(line, SZ) && (!error)) {
143150
/* skip lines starting with '#', else parse */
144151
if (line[0] != '#') {
145152
/* first check site name */
146153
auto it = std::find_if(
147-
scpy.cbegin(), scpy.cend(), [&](const dso::Sinex::SiteCoordinateResults &site) {
154+
scpy.begin(), scpy.end(),
155+
[&](const dso::Sinex::SiteCoordinateResults &site) {
148156
return ((!std::strncmp(site.msite.site_code(), line + 1, 4) &&
149-
!std::strncmp(site.msite.point_code(), line + 6, 2)) &&
150-
(!std::strncmp(site.msite.domes(), line + 9, 9) &&
151-
!std::strncmp(site.msolnid, line + 18, 4)));
157+
!std::strncmp(site.msite.point_code(), line + 6, 2)) &&
158+
(!std::strncmp(site.msite.domes(), line + 9, 9) &&
159+
!std::strncmp(site.msolnid, line + 18, 4)));
152160
});
153161
/* the station is in the list */
154162
if (it != scpy.cend()) {
155163

156164
error += resolve_freq_cor_data_line(line, ccmp, data);
157165
if (!error) {
158-
const double valmm = data[0] * std::cos(omega) + data[2] * std::sin(omega);
166+
const double valmm =
167+
data[0] * std::cos(omega) + data[2] * std::sin(omega);
159168
switch (ccmp) {
160-
case 'X':
161-
it->x += valmm*1e-3;
162-
break;
163-
case 'Y':
164-
it->y += valmm*1e-3;
165-
break;
166-
case 'Z':
167-
it->z += valmm*1e-3;
168-
break;
169-
default:
170-
fprintf(stderr, "[ERROR] Invalid component in dpod_freq file %s; expected one of X, Y or Z; line is %s (traceback: %s)\n", fn, line);
171-
error += 1;
169+
case 'X':
170+
it->x += valmm * 1e-3;
171+
break;
172+
case 'Y':
173+
it->y += valmm * 1e-3;
174+
break;
175+
case 'Z':
176+
it->z += valmm * 1e-3;
177+
break;
178+
default:
179+
fprintf(stderr,
180+
"[ERROR] Invalid component in dpod_freq file %s; expected "
181+
"one of X, Y or Z; line is %s (traceback: %s)\n",
182+
fn, line, __func__);
183+
error += 1;
172184
}
173185
} /* no coefficients parsing error */
174186
} /* if station in list */
@@ -181,5 +193,45 @@ int dso::apply_dpod_freq_corr(
181193
} /* reading through file entries */
182194

183195
/* we should have read at least one list of frequencies */
184-
return !((error==0) && (nfreq>=1));
196+
if (!((error == 0) && (nfreq >= 1))) {
197+
fprintf(stderr,
198+
"[ERROR] Failed applying parsing/applying frequency corrections "
199+
"from dpod file %s (traceback: %s)\n",
200+
fn, __func__);
201+
throw std::runtime_error(
202+
"[ERROR] Failed applying parsing/applying frequency corrections\n");
203+
}
204+
return scpy;
205+
}
206+
207+
int dso::apply_dpod_freq_corr(
208+
const char *fn, const dso::datetime<dso::nanoseconds> &t,
209+
std::vector<dso::Sinex::SiteCoordinateResults> &sites_crd) noexcept {
210+
int error = 0;
211+
try {
212+
const auto cor = dso::get_dpod_freq_corr(fn, t, sites_crd);
213+
int idx = 0;
214+
for (auto it = sites_crd.begin(); it != sites_crd.end() && (!error); ++it) {
215+
/* we assume here 1-to-1 correspondance between sites_crd and cor */
216+
auto itc = cor.cbegin() + idx;
217+
if ((std::strcmp(itc->msite.site_code(), it->msite.site_code()) ||
218+
std::strcmp(itc->msite.point_code(), it->msite.point_code())) ||
219+
(std::strcmp(itc->msite.domes(), it->msite.domes()) ||
220+
std::strcmp(itc->msolnid, it->msolnid))) {
221+
error += 1;
222+
fprintf(stderr, "[ERROR] Corrupt(?) parsing of dpod_freq_cor file; expected correction for %s and found %s (traceback: %s)\n", itc->msite.site_code(), it->msite.site_code(), __func__);
223+
}
224+
it->x += itc->x;
225+
it->y += itc->y;
226+
it->z += itc->z;
227+
}
228+
} catch (std::exception &e) {
229+
error = 1;
230+
fprintf(stderr,
231+
"[ERROR] Failed applying dpod frequency corrections from file %s "
232+
"(traceback: %s)\n",
233+
fn, __func__);
234+
fprintf(stderr, "[ERROR] Caught exception %s", e.what());
235+
}
236+
return error;
185237
}

test/test_get_dpod_harmonics.cpp

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,5 @@ int main(int argc, char* argv[])
99
return 2;
1010
}
1111

12-
/* place sites in a vector */
13-
std::vector<const char*> sites;
14-
for (int i = 3; i < argc; i++) {
15-
sites.push_back(argv[i]);
16-
}
17-
18-
/* create the sinex instance */
19-
dso::Sinex snx(argv[1]);
20-
21-
/* a vector of SiteId's to hold (intermediate) results */
22-
std::vector<dso::sinex::SiteId> siteids;
23-
24-
/* parse the block SITE/ID to collect info for the given sites */
25-
if (snx.parse_block_site_id(sites, /*use domes=*/false, siteids)) {
26-
fprintf(stderr, "ERROR. Failed matching sites in SINEX file\n");
27-
return 1;
28-
}
29-
30-
std::vector<dso::SiteRealHarmonics> harm;
31-
32-
if (dso::parse_dpod_freq_corr(argv[2], siteids, harm)) {
33-
fprintf(stderr, "ERROR. Failed parsing harmonics from %s\n", argv[2]);
34-
return 3;
35-
}
36-
37-
for (const auto& h : harm) {
38-
for (int i = 0; i < h.harmonics().num_harmonics(); i++) {
39-
printf("%s %.2f %.3f %.3f\n", h.site_name(), *(h.harmonics().operator()(i) + 0), *(h.harmonics().operator()(i) + 2), *(h.harmonics().operator()(i) + 1));
40-
}
41-
}
42-
4312
return 0;
4413
}

0 commit comments

Comments
 (0)