1 /* Copyright 2002-2024 CS GROUP
2 * Licensed to CS GROUP (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.files.sinex;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.hipparchus.geometry.euclidean.threed.Vector3D;
25 import org.orekit.errors.OrekitException;
26 import org.orekit.errors.OrekitMessages;
27 import org.orekit.models.earth.displacement.PsdCorrection;
28 import org.orekit.time.AbsoluteDate;
29 import org.orekit.utils.TimeSpanMap;
30
31 /**
32 * Station model.
33 * <p>
34 * Since Orekit 11.1, this class handles multiple site antenna
35 * eccentricity.
36 * The {@link #getEccentricities(AbsoluteDate)} method can be
37 * used to access the site antenna eccentricity values for a
38 * given epoch.
39 * </p>
40 * @author Bryan Cazabonne
41 * @since 10.3
42 */
43 public class Station {
44
45 /** Site code. */
46 private String siteCode;
47
48 /** DOMES number. */
49 private String domes;
50
51 /** Start of validity. */
52 private AbsoluteDate validFrom;
53
54 /** End of validity. */
55 private AbsoluteDate validUntil;
56
57 /** Eccentricity reference system. */
58 private ReferenceSystem eccRefSystem;
59
60 /** TimeSpanMap of site antenna eccentricities. */
61 private final TimeSpanMap<Vector3D> eccentricitiesTimeSpanMap;
62
63 /** Antenna type.
64 * @since 12.0
65 */
66 private final TimeSpanMap<String> antennaTypesMap;
67
68 /** Post-Seismic Deformation.
69 * @since 12.0
70 */
71 private final TimeSpanMap<List<PsdCorrection>> psdMap;
72
73 /** Station position. */
74 private Vector3D position;
75
76 /** Station velocity. */
77 private Vector3D velocity;
78
79 /** Coordinates reference epoch. */
80 private AbsoluteDate epoch;
81
82 /**
83 * Constructor.
84 */
85 public Station() {
86 this.eccentricitiesTimeSpanMap = new TimeSpanMap<>(null);
87 this.antennaTypesMap = new TimeSpanMap<>(null);
88 this.psdMap = new TimeSpanMap<>(null);
89 this.position = Vector3D.ZERO;
90 this.velocity = Vector3D.ZERO;
91 }
92
93 /**
94 * Get the site code (station identifier).
95 * @return the site code
96 */
97 public String getSiteCode() {
98 return siteCode;
99 }
100
101 /**
102 * Set the site code (station identifier).
103 * @param siteCode the site code to set
104 */
105 public void setSiteCode(final String siteCode) {
106 this.siteCode = siteCode;
107 }
108
109 /**
110 * Get the site DOMES number.
111 * @return the DOMES number
112 */
113 public String getDomes() {
114 return domes;
115 }
116
117 /**
118 * Set the DOMES number.
119 * @param domes the DOMES number to set
120 */
121 public void setDomes(final String domes) {
122 this.domes = domes;
123 }
124
125 /**
126 * Get start of validity.
127 * @return start of validity
128 */
129 public AbsoluteDate getValidFrom() {
130 return validFrom;
131 }
132
133 /**
134 * Set the start of validity.
135 * @param validFrom the start of validity to set
136 */
137 public void setValidFrom(final AbsoluteDate validFrom) {
138 this.validFrom = validFrom;
139 }
140
141 /**
142 * Get end of validity.
143 * @return end of validity
144 */
145 public AbsoluteDate getValidUntil() {
146 return validUntil;
147 }
148
149 /**
150 * Set the end of validity.
151 * @param validUntil the end of validity to set
152 */
153 public void setValidUntil(final AbsoluteDate validUntil) {
154 this.validUntil = validUntil;
155 }
156
157 /**
158 * Get the reference system used to define the eccentricity vector (local or cartesian).
159 * @return the reference system used to define the eccentricity vector
160 */
161 public ReferenceSystem getEccRefSystem() {
162 return eccRefSystem;
163 }
164
165 /**
166 * Set the reference system used to define the eccentricity vector (local or cartesian).
167 * @param eccRefSystem the reference system used to define the eccentricity vector
168 */
169 public void setEccRefSystem(final ReferenceSystem eccRefSystem) {
170 this.eccRefSystem = eccRefSystem;
171 }
172
173 /**
174 * Get the station antenna eccentricities for the given epoch.
175 * <p>
176 * Vector convention: X-Y-Z or UP-NORTH-EAST.
177 * See {@link #getEccRefSystem()} method.
178 * <p>
179 * If there is no eccentricity values for the given epoch, an
180 * exception is thrown.
181 * @param date epoch
182 * @return station antenna eccentricities (m)
183 * @since 11.1
184 */
185 public Vector3D getEccentricities(final AbsoluteDate date) {
186 final Vector3D eccAtEpoch = eccentricitiesTimeSpanMap.get(date);
187 // If the entry is null, there is no valid eccentricity values for the input epoch
188 if (eccAtEpoch == null) {
189 // Throw an exception
190 throw new OrekitException(OrekitMessages.MISSING_STATION_DATA_FOR_EPOCH, date);
191 }
192 return eccAtEpoch;
193 }
194
195 /**
196 * Get the TimeSpanMap of site antenna eccentricities.
197 * @return the TimeSpanMap of site antenna eccentricities
198 * @since 11.1
199 */
200 public TimeSpanMap<Vector3D> getEccentricitiesTimeSpanMap() {
201 return eccentricitiesTimeSpanMap;
202 }
203
204 /** Add a station eccentricity vector entry valid before a limit date.<br>
205 * Using <code>addStationEccentricitiesValidBefore(entry, t)</code> will make <code>entry</code>
206 * valid in ]-∞, t[ (note the open bracket).
207 * @param entry station eccentricity vector entry
208 * @param latestValidityDate date before which the entry is valid
209 * (must be different from <b>all</b> dates already used for transitions)
210 * @since 11.1
211 */
212 public void addStationEccentricitiesValidBefore(final Vector3D entry, final AbsoluteDate latestValidityDate) {
213 eccentricitiesTimeSpanMap.addValidBefore(entry, latestValidityDate, false);
214 }
215
216 /** Add a station eccentricity vector entry valid after a limit date.<br>
217 * Using <code>addStationEccentricitiesValidAfter(entry, t)</code> will make <code>entry</code>
218 * valid in [t, +∞[ (note the closed bracket).
219 * @param entry station eccentricity vector entry
220 * @param earliestValidityDate date after which the entry is valid
221 * (must be different from <b>all</b> dates already used for transitions)
222 * @since 11.1
223 */
224 public void addStationEccentricitiesValidAfter(final Vector3D entry, final AbsoluteDate earliestValidityDate) {
225 eccentricitiesTimeSpanMap.addValidAfter(entry, earliestValidityDate, false);
226 }
227
228 /** Get the TimeSpanMap of Post-Seismic Deformation.
229 * @return the TimeSpanMap of Post-Seismic Deformation
230 * @since 12.1
231 */
232 public TimeSpanMap<List<PsdCorrection>> getPsdTimeSpanMap() {
233 return psdMap;
234 }
235
236 /** Add a Post-Seismic Deformation entry valid after a limit date.<br>
237 * Using {@code addPsdCorrectionValidAfter(entry, t)} will make {@code entry}
238 * valid in [t, +∞[ (note the closed bracket).
239 * @param entry Post-Seismic Deformation entry
240 * @param earliestValidityDate date after which the entry is valid
241 * (must be different from <b>all</b> dates already used for transitions)
242 * @since 12.1
243 */
244 public void addPsdCorrectionValidAfter(final PsdCorrection entry, final AbsoluteDate earliestValidityDate) {
245
246 // get the list of corrections active just after earthquake date
247 List<PsdCorrection> corrections = psdMap.get(earliestValidityDate.shiftedBy(1.0e-3));
248
249 if (corrections == null ||
250 earliestValidityDate.durationFrom(corrections.get(0).getEarthquakeDate()) > 1.0e-3) {
251 // either this is the first earthquake we consider or
252 // this earthquake is after another one already considered
253 // we need to create a new list of corrections for this new earthquake
254 corrections = new ArrayList<>();
255 psdMap.addValidAfter(corrections, earliestValidityDate, false);
256 }
257
258 // add the entry to the current list
259 corrections.add(entry);
260
261 }
262
263 /**
264 * Get the antenna type for the given epoch.
265 * If there is no antenna types for the given epoch, an
266 * exception is thrown.
267 * @param date epoch
268 * @return antenna type
269 * @since 12.0
270 */
271 public String getAntennaType(final AbsoluteDate date) {
272 final String typeAtEpoch = antennaTypesMap.get(date);
273 // If the entry is null, there is no valid type for the input epoch
274 if (typeAtEpoch == null) {
275 // Throw an exception
276 throw new OrekitException(OrekitMessages.MISSING_STATION_DATA_FOR_EPOCH, date);
277 }
278 return typeAtEpoch;
279 }
280
281 /**
282 * Get the TimeSpanMap of site antenna type.
283 * @return the TimeSpanMap of site antenna type
284 * @since 12.0
285 */
286 public TimeSpanMap<String> getAntennaTypeTimeSpanMap() {
287 return antennaTypesMap;
288 }
289
290 /** Add a antenna type entry valid before a limit date.<br>
291 * Using <code>addAntennaTypeValidBefore(entry, t)</code> will make <code>entry</code>
292 * valid in ]-∞, t[ (note the open bracket).
293 * @param entry antenna type entry
294 * @param latestValidityDate date before which the entry is valid
295 * (must be different from <b>all</b> dates already used for transitions)
296 * @since 12.0
297 */
298 public void addAntennaTypeValidBefore(final String entry, final AbsoluteDate latestValidityDate) {
299 antennaTypesMap.addValidBefore(entry, latestValidityDate, false);
300 }
301
302 /** Add a antenna type entry valid after a limit date.<br>
303 * Using <code>addAntennaTypeValidAfter(entry, t)</code> will make <code>entry</code>
304 * valid in [t, +∞[ (note the closed bracket).
305 * @param entry antenna type entry
306 * @param earliestValidityDate date after which the entry is valid
307 * (must be different from <b>all</b> dates already used for transitions)
308 * @since 12.0
309 */
310 public void addAntennaTypeValidAfter(final String entry, final AbsoluteDate earliestValidityDate) {
311 antennaTypesMap.addValidAfter(entry, earliestValidityDate, false);
312 }
313
314 /**
315 * Get the station position.
316 * @return the station position (m)
317 */
318 public Vector3D getPosition() {
319 return position;
320 }
321
322 /**
323 * Set the station position.
324 * @param position the position to set
325 */
326 public void setPosition(final Vector3D position) {
327 this.position = position;
328 }
329
330 /**
331 * Get the station velocity.
332 * @return the station velocity (m/s)
333 */
334 public Vector3D getVelocity() {
335 return velocity;
336 }
337
338 /**
339 * Set the station velocity.
340 * @param velocity the velocity to set
341 */
342 public void setVelocity(final Vector3D velocity) {
343 this.velocity = velocity;
344 }
345
346 /**
347 * Get the coordinates reference epoch.
348 * @return the coordinates reference epoch
349 */
350 public AbsoluteDate getEpoch() {
351 return epoch;
352 }
353
354 /**
355 * Set the coordinates reference epoch.
356 * @param epoch the epoch to set
357 */
358 public void setEpoch(final AbsoluteDate epoch) {
359 this.epoch = epoch;
360 }
361
362 /** Eccentricity reference system. */
363 public enum ReferenceSystem {
364
365 /** Local reference system Up, North, East. */
366 UNE("UNE"),
367
368 /** Cartesian reference system X, Y, Z. */
369 XYZ("XYZ");
370
371 /** Codes map. */
372 private static final Map<String, ReferenceSystem> CODES_MAP = new HashMap<>();
373 static {
374 for (final ReferenceSystem type : values()) {
375 CODES_MAP.put(type.getName(), type);
376 }
377 }
378
379 /** Name used to define the reference system in SINEX file. */
380 private final String name;
381
382 /**
383 * Constructor.
384 * @param name name used to define the reference system in SINEX file
385 */
386 ReferenceSystem(final String name) {
387 this.name = name;
388 }
389
390 /**
391 * Get the name used to define the reference system in SINEX file.
392 * @return the name
393 */
394 public String getName() {
395 return name;
396 }
397
398 /**
399 * Get the eccentricity reference system corresponding to the given value.
400 * @param value given value
401 * @return the corresponding eccentricity reference system
402 */
403 public static ReferenceSystem getEccRefSystem(final String value) {
404 return CODES_MAP.get(value);
405 }
406
407 }
408
409 }
410