Coverage for pygeodesy/trf.py: 95%
518 statements
« prev ^ index » next coverage.py v7.2.2, created at 2024-02-12 13:15 -0500
« prev ^ index » next coverage.py v7.2.2, created at 2024-02-12 13:15 -0500
2# -*- coding: utf-8 -*-
4u'''I{Veness}' Terrestrial Reference Frames (TRF).
6Classes L{RefFrame}, registry L{RefFrames} and L{TRFError}.
8Transcoded from I{Chris Veness'} (C) 2006-2022 JavaScript originals
9U{latlon-ellipsoidal-referenceframe.js<https://GitHub.com/ChrisVeness/geodesy/blob/master/
10latlon-ellipsoidal-referenceframe.js>} and U{latlon-ellipsoidal-referenceframe-txparams.js
11<https://GitHub.com/ChrisVeness/geodesy/blob/master/latlon-ellipsoidal-referenceframe-txparams.js>}.
13Following is a copy of the comments in I{Veness}' U{latlon-ellipsoidal-referenceframe.js
14<https://GitHub.com/ChrisVeness/geodesy/blob/master/latlon-ellipsoidal-referenceframe.js>}.
16Modern geodetic reference frames: a latitude/longitude point defines a geographic location on,
17above or below the earth’s surface, measured in degrees from the equator and the U{International
18Reference Meridian<https://WikiPedia.org/wiki/IERS_Reference_Meridian>} (IRM) and metres above
19the ellipsoid within a given I{Terrestrial Reference Frame} at a given I{epoch}.
21This is scratching the surface of complexities involved in high precision geodesy, but may
22be of interest and/or value to those with less demanding requirements. More information U{here
23<https://www.Movable-Type.co.UK/scripts/geodesy-library.html>} and U{here
24<https://www.Movable-Type.co.UK/scripts/geodesy-library.html#latlon-ellipsoidal-referenceframe>}.
26Note that I{ITRF solutions} do not directly use an ellipsoid, but are specified by Cartesian
27coordinates. The GRS80 ellipsoid is recommended for transformations to geographical coordinates.
29Note WGS84(G730/G873/G1150) are coincident with ITRF at 10-centimetre level, see also U{here
30<ftp://ITRF.ENSG.IGN.Fr/pub/itrf/WGS84.TXT>}. WGS84(G1674) and ITRF20014 / ITRF2008 I{"are likely
31to agree at the centimeter level"}, see also U{QPS/Qinsy<https://Confluence.QPS.NL/qinsy/
32en/how-to-deal-with-etrs89-datum-and-time-dependent-transformation-parameters-45353274.html>}.
34@var RefFrames.ETRF2000: RefFrame(name='ETRF2000', epoch=2005, datum=Datums.GRS80) .Xforms=(0, -14)
35@var RefFrames.ETRF2005: RefFrame(name='ETRF2005', epoch=2005, datum=Datums.GRS80) .Xforms=(0, -1)
36@var RefFrames.ETRF2008: RefFrame(name='ETRF2008', epoch=2008, datum=Datums.GRS80) .Xforms=(0, 0)
37@var RefFrames.ETRF2014: RefFrame(name='ETRF2014', epoch=2014, datum=Datums.GRS80) .Xforms=(0, -14)
38@var RefFrames.ETRF2020: RefFrame(name='ETRF2020', epoch=2020, datum=Datums.GRS80) .Xforms=(0, -14)
39@var RefFrames.ETRF88: RefFrame(name='ETRF88', epoch=1988, datum=Datums.GRS80) .Xforms=(0, 0)
40@var RefFrames.ETRF89: RefFrame(name='ETRF89', epoch=1989, datum=Datums.GRS80) .Xforms=(0, -1)
41@var RefFrames.ETRF90: RefFrame(name='ETRF90', epoch=1990, datum=Datums.GRS80) .Xforms=(0, -1)
42@var RefFrames.ETRF91: RefFrame(name='ETRF91', epoch=1991, datum=Datums.GRS80) .Xforms=(0, -1)
43@var RefFrames.ETRF92: RefFrame(name='ETRF92', epoch=1992, datum=Datums.GRS80) .Xforms=(0, -1)
44@var RefFrames.ETRF93: RefFrame(name='ETRF93', epoch=1993, datum=Datums.GRS80) .Xforms=(0, -1)
45@var RefFrames.ETRF94: RefFrame(name='ETRF94', epoch=1994, datum=Datums.GRS80) .Xforms=(0, -1)
46@var RefFrames.ETRF96: RefFrame(name='ETRF96', epoch=1996, datum=Datums.GRS80) .Xforms=(0, -1)
47@var RefFrames.ETRF97: RefFrame(name='ETRF97', epoch=1997, datum=Datums.GRS80) .Xforms=(0, -1)
48@var RefFrames.GDA2020: RefFrame(name='GDA2020', epoch=2020, datum=Datums.GRS80) .Xforms=(0, -4)
49@var RefFrames.GDA94: RefFrame(name='GDA94', epoch=1994, datum=Datums.GRS80) .Xforms=(0, -3)
50@var RefFrames.ITRF2000: RefFrame(name='ITRF2000', epoch=1997, datum=Datums.GRS80) .Xforms=(15, -4)
51@var RefFrames.ITRF2005: RefFrame(name='ITRF2005', epoch=2000, datum=Datums.GRS80) .Xforms=(8, -3)
52@var RefFrames.ITRF2008: RefFrame(name='ITRF2008', epoch=2005, datum=Datums.GRS80) .Xforms=(17, -2)
53@var RefFrames.ITRF2014: RefFrame(name='ITRF2014', epoch=2010, datum=Datums.GRS80) .Xforms=(16, -1)
54@var RefFrames.ITRF2020: RefFrame(name='ITRF2020', epoch=2015, datum=Datums.GRS80) .Xforms=(16, 0)
55@var RefFrames.ITRF88: RefFrame(name='ITRF88', epoch=1988, datum=Datums.GRS80) .Xforms=(3, -4)
56@var RefFrames.ITRF89: RefFrame(name='ITRF89', epoch=1989, datum=Datums.GRS80) .Xforms=(4, -4)
57@var RefFrames.ITRF90: RefFrame(name='ITRF90', epoch=1988, datum=Datums.GRS80) .Xforms=(6, -4)
58@var RefFrames.ITRF91: RefFrame(name='ITRF91', epoch=1988, datum=Datums.GRS80) .Xforms=(4, -4)
59@var RefFrames.ITRF92: RefFrame(name='ITRF92', epoch=1988, datum=Datums.GRS80) .Xforms=(4, -4)
60@var RefFrames.ITRF93: RefFrame(name='ITRF93', epoch=1988, datum=Datums.GRS80) .Xforms=(4, -4)
61@var RefFrames.ITRF94: RefFrame(name='ITRF94', epoch=1993, datum=Datums.GRS80) .Xforms=(4, -4)
62@var RefFrames.ITRF96: RefFrame(name='ITRF96', epoch=1997, datum=Datums.GRS80) .Xforms=(5, -5)
63@var RefFrames.ITRF97: RefFrame(name='ITRF97', epoch=1997, datum=Datums.GRS80) .Xforms=(5, -4)
64@var RefFrames.NAD83: RefFrame(name='NAD83', epoch=1997, datum=Datums.GRS80) .Xforms=(0, -5)
65@var RefFrames.WGS84: RefFrame(name='WGS84', epoch=1984, datum=Datums.GRS80) .Xforms=(0, -1)
66@var RefFrames.WGS84g1150: RefFrame(name='WGS84g1150', epoch=2001, datum=Datums.GRS80) .Xforms=(0, 0)
67@var RefFrames.WGS84g1674: RefFrame(name='WGS84g1674', epoch=2005, datum=Datums.GRS80) .Xforms=(0, 0)
68@var RefFrames.WGS84g1762: RefFrame(name='WGS84g1762', epoch=2005, datum=Datums.GRS80) .Xforms=(0, 0)
69'''
71from pygeodesy.basics import map1, neg, isstr, _xinstanceof, _xisscalar, _zip
72from pygeodesy.constants import _float as _F, _0_0s, _0_0, _0_001, _0_5, _1_0 # _N_1_0
73from pygeodesy.datums import Datums, _earth_datum, _minus, _Names7, Transform, _WGS84 # _S1_S
74from pygeodesy.errors import TRFError, _xkwds
75from pygeodesy.interns import MISSING, NN, _AT_, _COMMASPACE_, _conversion_, \
76 _datum_, _DOT_, _exists_, _invalid_, _MINUS_, \
77 _NAD83_, _no_, _PLUS_, _reframe_, _s_, _SPACE_, \
78 _to_, _WGS84_, _x_, _intern as _i
79from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
80from pygeodesy.named import ADict, classname, _lazyNamedEnumItem as _lazy, _Named, \
81 _NamedEnum, _NamedEnumItem, _NamedTuple, Fmt, unstr
82from pygeodesy.props import Property, Property_RO, property_RO
83# from pygeodesy.streprs import Fmt, unstr # from .named
84from pygeodesy.units import Epoch, Float
86from math import ceil
88__all__ = _ALL_LAZY.trf
89__version__ = '24.02.12'
91_EP0CH = Epoch(0, low=0)
92_Es = {_EP0CH: _EP0CH} # L{Epoch}s, deleted below
93_GRS80 = Datums.GRS80
94_inverse_ = 'inverse'
95_MAS = _MM = _PPB = Float # Units
96_MM2M = _0_001 # scale mm2m, ppb2ppM, mas2as
97_mDays = (0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0)
98_366_0 = _F(sum(_mDays))
99_Ps = {} # L{TRFXform7Tuple}s, deleted below
100# _S_S1 = _N_1_0 / _S1_S # Transform.s for .s1 == 0
101_unity_ = 'unity'
102_v_ = 'v'
104_ETRF88_ = _i('ETRF88')
105_ETRF89_ = _i('ETRF89')
106_ETRF90_ = _i('ETRF90')
107_ETRF91_ = _i('ETRF91')
108_ETRF92_ = _i('ETRF92')
109_ETRF93_ = _i('ETRF93')
110_ETRF94_ = _i('ETRF94')
111_ETRF96_ = _i('ETRF96')
112_ETRF97_ = _i('ETRF97')
113_ETRF2000_ = _i('ETRF2000')
114_ETRF2005_ = _i('ETRF2005')
115_ETRF2008_ = _i('ETRF2008')
116_ETRF2014_ = _i('ETRF2014')
117_ETRF2020_ = _i('ETRF2020')
118_GDA94_ = _i('GDA94')
119_GDA2020_ = _i('GDA2020')
120_ITRF_ = _i('ITRF')
121_ITRF88_ = _i('ITRF88')
122_ITRF89_ = _i('ITRF89')
123_ITRF90_ = _i('ITRF90')
124_ITRF91_ = _i('ITRF91')
125_ITRF92_ = _i('ITRF92')
126_ITRF93_ = _i('ITRF93')
127_ITRF94_ = _i('ITRF94')
128_ITRF96_ = _i('ITRF96')
129_ITRF97_ = _i('ITRF97')
130_ITRF2000_ = _i('ITRF2000')
131_ITRF2005_ = _i('ITRF2005')
132_ITRF2008_ = _i('ITRF2008')
133_ITRF2014_ = _i('ITRF2014')
134_ITRF2020_ = _i('ITRF2020')
135_WGS84g1150_ = _i('WGS84g1150')
136_WGS84g1674_ = _i('WGS84g1674')
137_WGS84g1762_ = _i('WGS84g1762')
138# del _i
141def _E(epoch): # deleted below
142 '''(INTERNAL) De-dup L{Epochs}s.
143 '''
144 e = Epoch(_F(epoch))
145 return _Es.setdefault(e, e) # PYCHOK del
148def _P(*ps, **name): # deleted below
149 '''(INTERNAL) De-dup L{TRFXform7Tuple}s.
150 '''
151 t = TRFXform7Tuple(map(_F, ps), **name)
152 return _Ps.setdefault(t, t) # PYCHOK del
155def _xellipsoidal(point):
156 '''(INTERNAL) Check an ellipsoidal position, return C{True}
157 if cartesian, C{False} if geodetic ellipsoidal.
158 '''
159 m = _MODS.ellipsoidalBase
160 c = isinstance(point, m.CartesianEllipsoidalBase)
161 if not c:
162 _xinstanceof(m.CartesianEllipsoidalBase,
163 m.LatLonEllipsoidalBase, point=point)
164 return c
167class RefFrame(_NamedEnumItem):
168 '''Terrestrial Reference Frame (TRF) parameters.
169 '''
170 _datum = _GRS80 # Datums.GRS80 or .WGS84 (L{Datum})
171 _epoch = _EP0CH # epoch, fractional year (L{Epoch})
173 def __init__(self, epoch, datum, name=NN):
174 '''New L{RefFrame}.
176 @arg epoch: Epoch, a fractional calendar year (C{scalar} or C{str}).
177 @arg datum: Datum or ellipsoid (L{Datum}, {Ellipsoid}, L{Ellipsoid2}
178 or L{a_f2Tuple}).
179 @kwarg name: Unique, non-empty name (C{str}).
181 @raise NameError: A L{RefFrame} with that B{C{name}} already exists.
183 @raise TRFError: Invalid B{C{epoch}}.
185 @raise TypeError: Invalid B{C{datum}}.
186 '''
187 if datum is not _GRS80:
188 _earth_datum(self, datum, raiser=_datum_)
189 self._epoch = _Epoch(epoch)
190 self._Xs = {} # dict of I{to} Xforms
191 if name:
192 self._register(RefFrames, name)
194 def __eq__(self, other):
195 return isinstance(other, RefFrame) and other.epoch == self.epoch \
196 and other.datum == self.datum
198 def __lt__(self, other): # for sorting
199 return isinstance(other, RefFrame) and (self.name < other.name
200 or self.epoch < other.epoch)
202 def __matmul__(self, point): # PYCHOK Python 3.5+
203 '''Convert an ellipsoidal B{C{point}} to this reframe and epoch.
205 @see: Method C{toRefFrame}.
206 '''
207 _xellipsoidal(point)
208 return point.toRefFrame(self)
210 @property_RO
211 def datum(self):
212 '''Get this reference frame's datum (L{Datum}).
213 '''
214 return self._datum
216 @Property_RO
217 def ellipsoid(self):
218 '''Get this reference frame's ellipsoid (L{Ellipsoid} or L{Ellipsoid2}).
219 '''
220 return self._datum.ellipsoid
222 @Property_RO
223 def epoch(self):
224 '''Get this reference frame's epoch (C{Epoch}).
225 '''
226 return self._epoch
228 def toRefFrame(self, point, reframe2, **epoch2_epoch_name):
229 '''Convert an ellipsoidal point from this reframe and from C{epoch}
230 to an other C{reframe2} and C{epoch2 or epoch}.
232 @arg point: The point to convert (C{Cartesian} or C{LatLon}).
233 @arg reframe2: Reference frame to convert I{to} (L{RefFrame}).
234 @kwarg epoch2_epoch_name: Optional keyword arguments C{B{epoch2}=None},
235 C{B{epoch}=None} and C{B{name}=NN}.
237 @return: A copy of the B{C{point}}, converted or renamed.
239 @raise TypeError: Invalid B{C{point}}.
241 @note: The B{C{point}}'s C{reframe} and C{epoch} are overridden by
242 this reframe and B{C{epoch}} or this reframe's epoch.
244 @see: Ellipsoidal methods L{LatLon.toRefFrame<ellipsoidalBase.LatLonEllipsoidalBase.toRefFrame>}
245 and L{Cartesian.toRefFrame<ellipsoidalBase.CartesianEllipsoidalBase.toRefFrame>}
246 for more details.
247 '''
248 _xellipsoidal(point)
249 kwds = _xkwds(epoch2_epoch_name, name=self.name)
250 p = point.dup(reframe=self) if point.reframe != self else point
251 return p.toRefFrame(reframe2, reframe=self, **kwds)
253 def toStr(self, epoch=None, name=NN, **unused): # PYCHOK expected
254 '''Return this reference frame as a text string.
256 @kwarg epoch: Override this reframe's epoch (C{scalar} or C{str}).
257 @kwarg name: Override name (C{str}) or C{None} to exclude the
258 reframe's name.
260 @return: This L{RefFrame}'s attributes (C{str}).
261 '''
262 D = self.datum
263 e = self.epoch if epoch is None else _Epoch(epoch)
264 t = (Fmt.EQUAL(name=repr(name or self.name)),
265 Fmt.EQUAL(epoch=e),
266 Fmt.EQUAL(datum=_DOT_(classname(D) + _s_, D.name)))
267 return _COMMASPACE_.join(t[int(name is None):])
269 def Xform(self, reframe2):
270 '''Get the converter Xform I{from} this reference frame I{to} C{reframe2}.
272 @arg reframe2: Destination frame to convert I{to} (L{RefFrame} or C{str}).
274 @return: The L{TRFXform} instance or C{None} if not available.
276 @raise TypeError: Invalid B{C{reframe2}}.
277 '''
278 _xinstanceof(RefFrame, str, reframe2=reframe2)
279 n2 = reframe2 if isstr(reframe2) else reframe2.name
280 return self._Xs.get(n2, None)
282 def Xforms(self, inverse=False):
283 '''Return all Xforms converting I{from} or I{to} this reference frame.
285 @kwarg inverse: If C{True}, get all I{inverse, to} Xforms (C{bool}).
287 @return: An L{ADict} of I{from} C{[refName2]=}L{TRFXform}s) or if
288 C{B{inverse}=True} of I{to} C{[refName1]=}L{TRFXform}s).
289 '''
290 def _Xi(n2):
291 for n1, r in RefFrames.items():
292 if n2 in r._Xs:
293 yield n1, r
295 return ADict(_Xi(self.name) if inverse else self._Xs)
298class RefFrames(_NamedEnum):
299 '''(INTERNAL) L{RefFrame} registry, I{must} be a sub-class
300 to accommodate the L{_LazyNamedEnumItem} properties.
301 '''
302 def _Lazy(self, epoch, datum=_GRS80, name=NN):
303 '''(INTERNAL) Instantiate the L{RefFrame}.
304 '''
305 return RefFrame(epoch, datum, name=name)
307RefFrames = RefFrames(RefFrame) # PYCHOK singleton
308'''Some pre-defined L{RefFrame}s, all I{lazily} instantiated.'''
309# <https://GitHub.com/ChrisVeness/geodesy/blob/master/latlon-ellipsoidal-referenceframe.js>
310RefFrames._assert(
311 ETRF88 = _lazy(_ETRF88_, _E(1988)), # epoch, datum?
312 ETRF89 = _lazy(_ETRF89_, _E(1989)), # epoch, datum?
313 ETRF90 = _lazy(_ETRF90_, _E(1990)), # epoch, datum?
314 ETRF91 = _lazy(_ETRF91_, _E(1991)), # epoch, datum?
315 ETRF92 = _lazy(_ETRF92_, _E(1992)), # epoch, datum?
316 ETRF93 = _lazy(_ETRF93_, _E(1993)), # epoch, datum?
317 ETRF94 = _lazy(_ETRF94_, _E(1994)), # epoch, datum?
318 ETRF96 = _lazy(_ETRF96_, _E(1996)), # epoch, datum?
319 ETRF97 = _lazy(_ETRF97_, _E(1997)), # epoch, datum?
320 ETRF2000 = _lazy(_ETRF2000_, _E(2005)),
321 ETRF2005 = _lazy(_ETRF2005_, _E(2005)), # epoch, datum?
322 ETRF2008 = _lazy(_ETRF2008_, _E(2008)), # epoch, datum?
323 ETRF2014 = _lazy(_ETRF2014_, _E(2014)), # epoch, datum?
324 ETRF2020 = _lazy(_ETRF2020_, _E(2020)), # epoch, datum?
325 GDA94 = _lazy(_GDA94_, _E(1994)), # Australia
326 GDA2020 = _lazy(_GDA2020_, _E(2020)), # Australia
327 ITRF88 = _lazy(_ITRF88_, _E(1988)),
328 ITRF89 = _lazy(_ITRF89_, _E(1989)),
329 ITRF90 = _lazy(_ITRF90_, _E(1988)),
330 ITRF91 = _lazy(_ITRF91_, _E(1988)),
331 ITRF92 = _lazy(_ITRF92_, _E(1988)),
332 ITRF93 = _lazy(_ITRF93_, _E(1988)),
333 ITRF94 = _lazy(_ITRF94_, _E(1993)),
334 ITRF96 = _lazy(_ITRF96_, _E(1997)),
335 ITRF97 = _lazy(_ITRF97_, _E(1997)),
336 ITRF2000 = _lazy(_ITRF2000_, _E(1997)), # aka ITRF00
337 ITRF2005 = _lazy(_ITRF2005_, _E(2000)),
338 ITRF2008 = _lazy(_ITRF2008_, _E(2005)), # aka ITRF08
339 ITRF2014 = _lazy(_ITRF2014_, _E(2010)),
340 ITRF2020 = _lazy(_ITRF2020_, _E(2015)),
341 NAD83 = _lazy(_NAD83_, _E(1997)), # aka CORS96
342 WGS84 = _lazy(_WGS84_, _E(1984), _WGS84),
343 WGS84g1150 = _lazy(_WGS84g1150_, _E(2001), _WGS84),
344 WGS84g1674 = _lazy(_WGS84g1674_, _E(2005), _WGS84),
345 WGS84g1762 = _lazy(_WGS84g1762_, _E(2005), _WGS84)) # same epoch
348class TransformXform(Transform):
349 '''Helmert transformation, extended with an C{Xform} converter.
351 @see: L{Transform<datums.Transform>} and L{Xform<TRFXform>}.
352 '''
353 _Xform = None
355 def __init__(self, name=NN, **tx_ty_tz_s_sx_sy_sz): # PYCHOK signature
356 '''New L{TransformXform}.
358 @kwarg name: Optional name (C{str}), I{not registered}.
360 @see: L{Transform<datums.Transform>} for details.
362 @note: This L{TransformXform}'s name starts with C{"-"} if
363 its C{Xform} was I{inversed}.
364 '''
365 Transform.__init__(self, **tx_ty_tz_s_sx_sy_sz)
366 if name:
367 self.name = name
369 def __eq__(self, other):
370 return isinstance(other, TransformXform) and Transform.__eq__(self, other)
372 def rename(self, name=NN):
373 '''Change this transform and its Xform's name.
375 @arg name: The new name (C{str}), overriding
376 the base name.
378 @return: The old name (C{str}).
379 '''
380 X = self.Xform
381 return Transform.rename(self, name or (X.toStr() if X else NN))
383 def toRefFrame(self, point, name=NN): # PYCHOK signature
384 '''Convert an ellipsoidal point using this transform and Xform.
386 @arg point: The point to convert (C{Cartesian} or C{LatLon}).
388 @return: A copy of the B{C{point}}, converted I{directly} to
389 this transform's Xform's C{refName2} and C{epoch}.
391 @note: The B{C{point}}'s original C{reframe} and C{epoch} are
392 I{ignored}, its C{datum} and C{height} are preserved
393 but I{not} taken into account.
394 '''
395 C = _xellipsoidal(point)
396 c = point.dup() if C else point.toCartesian()
397 r = c.toTransforms_(self)
398 if not C: # i.e. back to LatLon
399 r = r.toLatLon(datum=point.datum, height=point.height,
400 LatLon=point.classof)
401 X = self.Xform
402 if X:
403 r.reframe = X.reframe2
404 r.epoch = X.epoch
406 r.rename(name or self.name)
407 return r
409 def toTransform(self, epoch1, **epoch2_inverse):
410 '''Return this transform observed at B{C{epoch1}} as a Helmert
411 L{TransformXform}, optionally at B{C{epoch2 or epoch1}}.
413 @arg epoch1: Epoch to observe I{from} (C{scalar}).
414 @kwarg epoch2: Optional epoch to observe I{to} (C{scalar}).
415 @kwarg epoch2_inverse: Optional C{B{epoch2}=None} and
416 C{B{inverse}=False}, see L{TRFXform}'s method
417 L{toTransform<TRFXform.toTransform>}.
419 @return: The Helmert transform (L{TransformXform}).
421 @raise TRFError: Invalid B{C{epoch1}}, B{C{epoch2}} or
422 missing Xform.
423 '''
424 X = self.Xform
425 if X is None:
426 raise TRFError(Xform=X, txt=MISSING)
427 X = X.dup(name=X.toStr())
428 return X.toTransform(epoch1, **epoch2_inverse)
430 def velocities(self, factor=_MM2M):
431 '''Compute the X, Y and Z I{velocities} of this transform.
433 @kwarg factor: Factor to scale this Xform's C{rates} (C{scalar}), default
434 from C{milli-meter-} to C{meter-per-year}.
436 @return: A L{Vector3Tuple}C{(x, y, z)} or C{None}.
438 @raise TypeError: Non-scalar B{C{factor}}.
440 @see: Altamimi, Z. "EUREF-TN-1-Jan-31-2024", U{Appendix A, equation (3)
441 <http://ETRS89.ENSG.IGN.FR/pub/EUREF-TN-1-Jan-31-2024.pdf>}.
442 '''
443 v = self.Xform
444 if v is not None:
445 r = v.rates * factor # eq (3) ...
446 t = self.dup(tx=r.sx, ty=r.sy, tz=r.sz, # s=_S_S1, # Xyy-dot
447 s1=0, isunity=False, name=NN(self.name, _v_))
448 v = t.transform(r.tx, r.ty, r.tz) # Xyy
449 return v
451 @Property
452 def Xform(self):
453 '''Get the Xform of this Helmert (L{TRFXform} or C{None}).
454 '''
455 return self._Xform
457 @Xform.setter # PYCHOK setter!
458 def Xform(self, Xform):
459 '''Set the Xform of this Helmert (L{TRFXform}).
461 @raise TypeError: Invalid B{C{Xform}}.
462 '''
463 _xinstanceof(TRFXform, Xform=Xform)
464 self._Xform = Xform
467class TRFXform7Tuple(_NamedTuple):
468 '''7-Tuple C{(tx, ty, tz, s, sx, sy, sz)} of conversion parameters with
469 translations C{tx}, C{ty} and C{tz} in C{milli-meter}, scale C{s} in
470 C{ppb} and rates C{sx}, C{sy} and C{sz} in C{milli-arc-seconds-per-year}.
472 @note: The parameters are also named as C{(Tx, Ty, Tz, D, Rx, Ry, Rz)}
473 or C{(T1, T2, T3, D, R1, R2, R3)}.
475 @see: Class L{TransformXform}'s matching keyword argument names.
476 '''
477 _Names_ = _Names7 # ('tx', 'ty', 'tz', _s_, 'sx', 'sy', 'sz') == Transform.__init__
478 _Units_ = (_MM, _MM, _MM, _PPB, _MAS, _MAS, _MAS)
480 def __add__(self, other):
481 _xinstanceof(TRFXform7Tuple, other=other)
482 return type(self)(((a + b) for a, b in _zip(self, other)), name=_PLUS_) # .fsums._add_op
484 def __eq__(self, other):
485 return isinstance(other, TRFXform7Tuple) and all(a == b for a, b in
486 _zip(self, other))
488 def __hash__(self):
489 return self._hash # memoized
491 def __mul__(self, factor):
492 _xisscalar(factor=factor)
493 return type(self)((s * factor for s in self), name=self.name)
495 def __neg__(self):
496 return self.inverse()
498 def __sub__(self, other):
499 _xinstanceof(TRFXform7Tuple, other=other)
500 return type(self)(((a - b) for a, b in _zip(self, other)), name=_MINUS_) # .fsums._ub_op
502 @Property_RO
503 def _hash(self):
504 return hash(s for s in self)
506 def inverse(self, name=NN):
507 '''Return the inverse of this transform.
509 @kwarg name: Optional name (C{str}).
511 @return: Inverse (L{TransformXform}).
512 '''
513 n = name or _minus(self.name)
514 return type(self)(map(neg, self), name=n)
516 @Property_RO
517 def isunity(self):
518 '''Is this a C{unity, identidy} transform (C{bool}).
519 '''
520 return not any(self)
523class TRFXform(_Named):
524 '''A Terrestrial Reference Frame (TRF) converter between two
525 reference frames observed at an C{epoch}.
526 '''
527 _epoch = _EP0CH
528 _epoch_d = _0_0
529 _indir_d = NN # refName
530 _inver_d = False
531 refName1 = \
532 refName2 = NN
533 rates = \
534 xform = _P(*_0_0s(len(_Names7)), name=_unity_)
536 def __init__(self, refName1, refName2, epoch=None, xform=None,
537 rates=None, name=NN):
538 '''New L{trfXform}.
540 @arg refName1: Source reframe (C{str}), converting I{from}.
541 @arg refName2: Destination reframe (C{str}), converting I{to}.
542 @kwarg epoch: Epoch, a fractional year (L{Epoch}, C{scalar} or C{str}).
543 @kwarg xform: I{Transform} parameters (L{TRFXform7Tuple}).
544 @kwarg rates: I{Rate} parameters (L{TRFXform7Tuple}), like B{C{xform}},
545 but in C{units-per-year}.
546 @kwarg name: Optional name (C{str}), overriding the default from
547 method L{toStr<TRFXform.toStr>}.
549 @return: The TRF converter (L{TRFXform}).
551 @raise TRFError: Invalid B{C{epoch}}, B{C{xform}} or B{C{rates}}.
552 '''
553 self.refName1 = str(refName1)
554 self.refName2 = str(refName2)
555 _xinstanceof(TRFXform7Tuple, xform=xform, rates=rates)
556 self.epoch = epoch
557 self.xform = xform
558 self.rates = rates
559 self.rename(name or self.toStr())
561 def __eq__(self, other):
562 return isinstance(other, TRFXform) and self.epoch == other.epoch and \
563 self.xform == other.xform and self.rates == other.rates
565 def __lt__(self, other): # for sorting
566 return isinstance(other, TRFXform) and (self.refName1 < other.refName1
567 or self.refName2 < other.refName2
568 or self.epoch < other.epoch)
570 def __neg__(self):
571 return self.inverse()
573 def __repr__(self):
574 return self.toRepr()
576 def __str__(self):
577 return self.toStr()
579 def _at(self, epoch):
580 '''(INTERNAL) Return C{self.nameB{@}epoch}.
581 '''
582 n = self.name
583 if epoch != self.epoch:
584 _e = _AT_(NN, epoch)
585 if not n.endswith(_e):
586 n = NN(n, _e)
587 return n
589 @Property
590 def epoch(self):
591 '''Get the epoch (L{Epoch}).
592 '''
593 return self._epoch
595 @epoch.setter # PYCHOK setter!
596 def epoch(self, epoch):
597 '''Set the epoch (L{Epoch}, C{scalar} or C{str}).
599 @raise TRFError: Invalid B{C{epoch}}.
600 '''
601 e = _Epoch(epoch)
602 if self._epoch != e:
603 self._epoch = e
604 self.rename(self._at(e))
606 @property_RO
607 def epoched(self):
608 '''Get this Xform's I{epoch} deltas (C{float}).
609 '''
610 return self._epoch_d
612 @property_RO
613 def indirected(self):
614 '''Is this an I{indirected} Xform? (C{str}) or C{NN}.
615 '''
616 return self._indir_d
618 def inverse(self, name=NN):
619 '''Get an I{inverse} of this Xform, C{refName1} and C{-2} swapped.
621 @return: Inverse (L{TRFXform}).
622 '''
623 return self.dup(refName1=self.refName2, xform=-self.xform,
624 refName2=self.refName1, rates=-self.rates,
625 name=name or _minus(self.name),
626 _inver_d=not self.inversed)
628 @property_RO
629 def inversed(self):
630 '''Is this an I{inversed} Xform? (C{bool}).
631 '''
632 return self._inver_d
634 def _reframe(self, name, datum=_GRS80):
635 '''(INTERNAL) Get an un-/registered frame.
636 '''
637 r = RefFrames.get(name)
638 if r is None or r.datum != datum:
639 r = RefFrame(self.epoch, datum)
640 r.name = name # unregistered
641 return r
643 @property_RO
644 def reframe1(self):
645 '''Get the un-/registered I{from} frame (C{RefFrame}).
646 '''
647 return self._reframe(self.refName1)
649 @property_RO
650 def reframe2(self):
651 '''Get the un-/registered I{to} frame (C{RefFrame}).
652 '''
653 return self._reframe(self.refName2)
655 def rename(self, name=NN):
656 '''Change this Xform's name.
658 @arg name: The new name (C{str}), overriding the
659 base name C{"refName1@epochxrefName2"}.
661 @return: The old name (C{str}).
662 '''
663 return _Named.rename(self, name or self.toStr())
665 def toEpoch(self, epoch):
666 '''Convert this Xform to B{C{epoch}}, if needed.
668 @arg epoch: Epoch, fractional year (C{Epoch}, C{scalar}
669 or C{str}).
671 @return: This Xform or a copy converted to B{C{epoch}}.
673 @raise TRFError: Invalid B{C{epoch}}.
674 '''
675 e = _Epoch(epoch)
676 X, d = self, e - self.epoch
677 if d:
678 t = X.xform + X.rates * d
679 X = X.dup(epoch=e, xform=t, name=X._at(e))
680 X._epoch_d += d # abs(d)?
681 return X
683 def toHelmert(self, factor=_MM2M):
684 '''Return the Helmert transform from this Xform scaled accordingly.
686 @kwarg factor: Scale to convert C{milli-meter} (C{scalar}).
688 @return: The Helmert transform (L{TransformXform}).
690 @note: By defaut, Translations are converted from C{milli-meter} to
691 C{meter}, rates from C{milli-arc-seconds} to C{arc-seconds}
692 and scale from C{ppb} to C{ppM}.
693 '''
694 h = self.xform * factor
695 H = TransformXform(name=self.name, **dict(h.items()))
696 H.Xform = self
697 return H
699 def toRefFrame(self, point, epoch=None, datum=_GRS80, **epoch2_name):
700 '''Convert an ellipsoidal point from this Xform's C{refName1} and
701 C{epoch} to this Xform's C{refName2} and C{epoch2 or epoch}.
703 @arg point: The point to convert (C{Cartesian} or C{LatLon}).
704 @kwarg epoch: Optional epoch ((L{Epoch}, C{scalar} or C{str})),
705 overriding this Xform's C{epoch}.
706 @kwarg datum: Optional datum to define a temporary L{RefFrame} from
707 this Xform's C{refName1} or C{refName2} (C{datum}).
708 @kwarg epoch2_name: Optional keyword arguments B{C{epoch2}=None}
709 and C{B{name}=NN}.
711 @return: A copy of the B{C{point}}, converted or renamed.
713 @see: Method L{RefFrame.toRefFrame} for more details.
714 '''
715 def _r(name):
716 r = RefFrames.get(name)
717 if r is None or r.datum != datum:
718 r = RefFrame(epoch or self.epoch, datum)
719 r.name = name # unregistered
720 return r
722 return _r(self.refName1).toRefFrame(point,
723 _r(self.refName2), epoch=epoch, **epoch2_name)
725 def toRepr(self, **unused): # PYCHOK signature
726 '''Return the represention of this Xform (C{str}).
727 '''
728 return unstr(self.classname, name=self.name, epoch=self.epoch)
730 def toStr(self, epoch=None, **unused): # PYCHOK signature
731 '''Return this Xform as C{"refName1B{@}epochB{x}refName2"} (C{str}).
733 @kwarg epoch: Epoch (C{Epoch}, C{scalar} or C{str}), overriding
734 this Xform's epoch.
735 '''
736 e = self.epoch if epoch is None else _Epoch(epoch)
737 return NN(_AT_(self.refName1, e), _x_, self.refName2)
739 def toTransform(self, epoch, epoch2=None, inverse=False):
740 '''Combine this Xform observed at B{C{epoch}} into a Helmert
741 L{TransformXform}, optionally at B{C{epoch2 or epoch}}.
743 @arg epoch: Epoch to observe I{from} (C{scalar}).
744 @kwarg epoch2: Optional epoch to observe I{to} (C{scalar}).
745 @kwarg inverse: Use the Xform's inverse (C{bool}).
747 @return: The Helmert transform (L{TransformXform}).
749 @raise TRFError: Invalid B{C{epoch}} or B{C{epoch2}}.
751 @see: Method L{toHelmert}.
752 '''
753 # X=self.toEpoch(epoch); if epoch2: X=X.toEpoch(epoch2)
754 e = epoch if epoch2 is None else Epoch(epoch2=epoch2)
755 X = self.toEpoch(e)
756 if inverse:
757 X = X.inverse()
758 return X.toHelmert()
761def date2epoch(year, month, day):
762 '''Return the C{epoch} for a calendar day.
764 @arg year: Year of the date (C{scalar}).
765 @arg month: Month in the B{C{year}} (C{scalar}, 1..12).
766 @arg day: Day in the B{C{month}} (C{scalar}, 1..31).
768 @return: Epoch, the fractional year (C{float}).
770 @raise TRFError: Invalid B{C{year}}, B{C{month}} or B{C{day}}.
772 @note: Any B{C{year}} is considered a leap year, i.e. having
773 29 days in February.
774 '''
775 try:
776 y, m, d = map1(int, year, month, day)
777 if y > 0 and 1 <= m <= 12 and 1 <= d <= _mDays[m]:
778 e = y + float(sum(_mDays[:m]) + d) / _366_0
779 return Epoch(e, low=0)
781 raise ValueError # _invalid_
782 except (TRFError, TypeError, ValueError) as x:
783 raise TRFError(year=year, month=month, day=day, cause=x)
786def epoch2date(epoch):
787 '''Return the date for a reference frame C{epoch}.
789 @arg epoch: Fractional year (C{scalar}).
791 @return: 3-Tuple C{(year, month, day)}.
793 @raise TRFError: Invalid B{C{epoch}}.
795 @note: Any B{C{year}} is considered a leap year, i.e. having
796 29 days in February.
797 '''
798 e = _Epoch(epoch, low=0)
799 y = int(e)
800 d = int(ceil(_366_0 * (e - y)))
801 for m, n in enumerate(_mDays[1:]):
802 if d > n:
803 d -= n
804 else:
805 break
806 return y, (m + 1), max(1, d)
809def _Epoch(e, **kwds):
810 '''(INTERNAL) Get the C{Epoch(B{e})}.
811 '''
812 return e if isinstance(e, Epoch) and not kwds else Epoch(e, **kwds)
815def _eT0Ds4(inst, reframe, epoch, reframe2, epoch2):
816 '''(INTERNAL) Get epoch, a Helmert L{Transform}s or 0-tuple, datum
817 and datum2 to convert B{C{refFrame}} observed at B{C{epoch}}
818 into B{C{refFrame2}} observed at C{epoch2 or epoch}.
819 '''
820 r = reframe or inst.reframe
821 if not r:
822 t = _SPACE_(_DOT_(repr(inst), _reframe_), MISSING)
823 raise TRFError(_no_(_conversion_), txt=t)
825 _xinstanceof(RefFrame, reframe2=reframe2, reframe=r)
827 e1 = _Epoch(epoch or inst.epoch or r.epoch)
828 e2 = e1 if epoch2 is None else Epoch(epoch2=epoch2)
830 t0 = _toTransform0(r.name, e1, reframe2.name, e2)
831 if t0 is None:
832 t = _SPACE_(RefFrame.__name__, _AT_(r.name, e1),
833 _to_, _AT_(reframe2.name, e2))
834 raise TRFError(_no_(_conversion_), txt=t)
836 if t0: # is not ()
837 e2 = t0.Xform.epoch
838 return e2, t0, r.datum, reframe2.datum
841def _direct(n1, n2):
842 '''(INTERNAL) Get the C{n1} to C{n2} Xform or C{None}.
843 '''
844 X = RefFrames.get(n1)
845 if X:
846 X = X._Xs.get(n2, None)
847 return X
850def _indirects(n1, n2):
851 '''(INTERNAL) Yield all Xforms between C{n1} and C{n2} via C{n}.
852 '''
853 def _X4(_Xs, n2):
854 for n, X1 in _Xs.items():
855 X2 = _direct(n, n2)
856 if X2:
857 yield X1, X2, n, True # +
858 X2 = _direct(n2, n)
859 if X2:
860 yield X1, X2, n, False # -
862 r = RefFrames.get(n1)
863 if r:
864 for X1, X2, n, f in _X4(r._Xs, n2):
865 e1, e2 = X1.epoch, X2.epoch
866 if e1 < e2: # X1 to e2
867 X1 = X1.toEpoch(e2)
868 e1 = e2
869 elif e1 > e2: # X2 to e1
870 X2 = X2.toEpoch(e1)
871 # U{Appendix, Table 7, last column "Sum of the previous ..."
872 # <https://Geodesy.NOAA.gov/TOOLS/Htdp/Pearson_Snay_2012.pdf">}
873 X = TRFXform(n1, n2, epoch=e1,
874 xform=X1.xform + (X2.xform if f else -X2.xform),
875 rates=X1.rates + (X2.rates if f else -X2.rates),
876 name=NN(X1._at(e1), _PLUS_ if f else _MINUS_,
877 X2._at(e1)))
878 X._epoch_d = X1.epoched + X2.epoched # max, abs?
879 X._indir_d = n # reframe?
880 yield X
883def _reframe(**name_reframe):
884 '''(INTERNAL) Get a C{reframe}.
885 '''
886 if len(name_reframe) == 1:
887 for r in name_reframe.values():
888 break
889 if isstr(r) and r: # not NN
890 r = RefFrames.get(r)
891 if r and isinstance(r, RefFrame):
892 return r
893 raise TRFError(**name_reframe) # _invalid_
896def _toTransform0(n1, e1, n2, e2, **indirect_inverse):
897 '''(INTERNAL) Return a L{TransformXform}, 0-tuple or C{None}.
898 '''
899 if (n1 == n2 and e1 == e2):
900 return () # unity?
902 for X in _toTransforms(n1, e1, n2, e2, **indirect_inverse):
903 return X # first OK?
905 if (n1.startswith(_ITRF_) and n2.startswith(_WGS84_)) or \
906 (n2.startswith(_ITRF_) and n1.startswith(_WGS84_)):
907 return () # unity?
909 return None
912def _toTransforms(n1, e1, n2, e2, indirect=True, inverse=True):
913 '''(INTERNAL) Yield all possible Helmert transforms, if any.
914 '''
915 def _k(X):
916 return -X.epoch
918 X = _direct(n1, n2)
919 if X:
920 yield X.toTransform(e1, epoch2=e2)
922 if inverse:
923 X = _direct(n2, n1)
924 if X:
925 yield X.toTransform(e1, epoch2=e2, inverse=True)
927 if indirect:
928 for X in sorted(_indirects(n1, n2), key=_k):
929 yield X.toTransform(e1, epoch2=e2)
931 if inverse:
932 for X in sorted(_indirects(n2, n1), key=_k):
933 yield X.toTransform(e1, epoch2=e2, inverse=True)
936def trfTransform0(reframe, reframe2, epoch=None, epoch2=None, indirect=True, inverse=True):
937 '''Get a Helmert transform to convert one C{reframe} observed at C{epoch}
938 to an other C{reframe2} at observed at C{epoch2 or epoch}.
940 @return: A L{TransformXform} instance, a C{0-tuple} for I{unity, identity} or
941 C{None} if no conversion exists.
943 @see: Function L{trfTransforms} for futher details.
944 '''
945 return _trfT0s(_toTransform0, reframe, reframe2, epoch, epoch2,
946 indirect=indirect, inverse=inverse)
949def trfTransforms(reframe, reframe2, epoch=None, epoch2=None, indirect=True, inverse=True):
950 '''Yield all Helmert transform to convert one C{reframe} observed at C{epoch}
951 to an other C{reframe2} at observed at C{epoch2 or epoch}.
953 @arg reframe: The frame to convert I{from} (L{RefFrame} or C{str}).
954 @arg reframe2: The frame to convert I{to} (L{RefFrame} or C{str}).
955 @arg epoch: Epoch to observe I{from} (L{Epoch}, C{scalar} or C{str}),
956 otherwise C{B{reframe}}'s C{epoch}.
957 @kwarg epoch2: Optional epoch to observe to observe I{to} (L{Epoch}, C{scalar}
958 or C{str}), otherwise B{C{epoch}} or C{B{reframe}}'s C{epoch}.
959 @kwarg indirect: If C{True}, include transforms via I{one} intermediate reframe,
960 otherwise only I{direct} B{C{reframe}} to B{C{reframe2}}
961 transforms (C{bool}).
962 @kwarg inverse: If C{True}, include inverse, otherwise only forward transforms
963 (C{bool}).
965 @return: A L{TransformXform} instance for each available conversion.
967 @raise TRFError: Invalid B{C{reframe}}, B{C{epoch}}, B{C{reframe2}} or
968 B{C{epoch2}}.
970 @raise TypeError: Invalid B{C{reframe}} or B{C{reframe2}}.
971 '''
972 return _trfT0s(_toTransforms, reframe, reframe2, epoch, epoch2,
973 indirect=indirect, inverse=inverse)
976def _trfT0s(_toT0s, reframe, reframe2, epoch, epoch2, **indirect_inverse):
977 '''(INTERNAL) Handle C{trfTransforms0} and C{trfTransforms} calls.
978 '''
979 r1 = _reframe(reframe=reframe)
980 e1 = r1.epoch if epoch is None else _Epoch(epoch)
981 r2 = _reframe(reframe2=reframe2)
982 e2 = e1 if epoch2 is None else Epoch(epoch2=epoch2)
983 return _toT0s(r1.name, e1, r2.name, e2, **indirect_inverse)
986def trfXform(reframe1, reframe2, epoch=None, xform=None, rates=None):
987 '''Define a new Terrestrial Reference Frame (TRF) converter or get an
988 existing one.
990 @arg reframe1: Source frame (L{RefFrame} or C{str}), converting I{from}.
991 @arg reframe2: Destination frame (L{RefFrame} or C{str}), converting I{to}.
992 @kwarg epoch: Epoch, a fractional year (L{Epoch}, C{scalar} or C{str})
993 or C{None} for C{B{reframe2}}'s epoch.
994 @kwarg xform: I{Transform} parameters (L{TRFXform7Tuple}).
995 @kwarg rates: I{Rate} parameters (L{TRFXform7Tuple}), as B{C{xform}},
996 but in C{units-per-year}.
998 @return: The new TRF converter (L{TRFXform}) or if no B{C{epoch}},
999 B{C{xform}} and B{C{rates}} are given, return the existing
1000 one (L{TRFXform}) or C{None} if not available.
1002 @raise TRFError: Invalid B{C{reframe1}}, B{C{reframe2}}, B{C{epoch}},
1003 B{C{xform}} or B{C{rates}} or the TRF converter
1004 already exists.
1005 '''
1006 try:
1007 r1 = _reframe(reframe1=reframe1)
1008 r2 = _reframe(reframe2=reframe2)
1009 if epoch is None:
1010 if xform is rates is None:
1011 return r1._Xs.get(r2.name, None)
1012 e = r2.epoch
1013 else:
1014 e = _Epoch(epoch)
1015 return _trfX(r1.name, r2.name, epoch=e, xform=xform,
1016 rates=rates)
1017 except (TypeError, ValueError) as x:
1018 t = unstr(trfXform, reframe1, reframe2, epoch=epoch)
1019 raise TRFError(t, cause=x)
1022def _trfX(n1, n2, **epoch_xform_rates):
1023 '''(INTERNAL) New, I{unique} L{TRFXform} converter.
1024 '''
1025 r1 = RefFrames.get(n1)
1026 r2 = RefFrames.get(n2)
1027 if r1 and r2:
1028 if n2 in r1._Xs:
1029 raise ValueError(_exists_)
1030 elif n1 in r2._Xs:
1031 raise ValueError(_SPACE_(_inverse_, _exists_))
1032 else:
1033 raise ValueError(_invalid_)
1034 r1._Xs[n2] = X = TRFXform(n1, n2, **epoch_xform_rates)
1035 return X
1038# TRF conversions specified as an epoch and 2 sets of 7-parameters. Most from Altamimi, Z. U{"EUREF Technical
1039# Note 1: Relationship and Transformation between the International and the European Terrestrial Reference
1040# Systems"<https://ERTS89.ENSG.IFN.Fr/pub/EUREF-TN-1-Jan-31-2024.pdf>} Appendix A, more at U{Quinsy QPS <https://
1041# confluence.QPS.NL/qinsy/files/latest/en/182618383/182618384/1/1579182881000/ITRF_Transformation_Parameters.xlsx>}.
1042# See also U{Quinsy International Terrestrial Reference Frame 2014 (ITRF2014)<https://confluence.QPS.NL/qinsy/latest/
1043# en/international-terrestrial-reference-frame-2014-itrf2014-182618383.html>}.
1044_trfX(_ITRF2020_, _ITRF2014_, epoch=_E(2015), # <https://ITRF.IGN.Fr/docs/solutions/itrf2020/Transfo-ITRF2020_TRFs.txt>
1045 xform=_P( -1.4, -0.9, 1.4, -0.42, _0_0, _0_0, _0_0),
1046 rates=_P( _0_0, -0.1, 0.2, _0_0, _0_0, _0_0, _0_0))
1047_trfX(_ITRF2020_, _ITRF2008_, epoch=_E(2015),
1048 xform=_P( 0.2, 1.0, 3.3, -0.29, _0_0, _0_0, _0_0),
1049 rates=_P( _0_0, -0.1, 0.1, 0.03, _0_0, _0_0, _0_0))
1050_trfX(_ITRF2020_, _ITRF2005_, epoch=_E(2015),
1051 xform=_P( 2.7, 0.1, -1.4, 0.65, _0_0, _0_0, _0_0),
1052 rates=_P( 0.3, -0.1, 0.1, 0.03, _0_0, _0_0, _0_0))
1053_trfX(_ITRF2020_, _ITRF2000_, epoch=_E(2015),
1054 xform=_P( -0.2, 0.8, -34.2, 2.25, _0_0, _0_0, _0_0),
1055 rates=_P( 0.1, _0_0, -1.7, 0.11, _0_0, _0_0, _0_0))
1056_trfX(_ITRF2020_, _ITRF97_, epoch=_E(2015),
1057 xform=_P( 6.5, -3.9, -77.9, 3.98, _0_0, _0_0, 0.36),
1058 rates=_P( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
1059_trfX(_ITRF2020_, _ITRF96_, epoch=_E(2015),
1060 xform=_P( 6.5, -3.9, -77.9, 3.98, _0_0, _0_0, 0.36),
1061 rates=_P( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
1062_trfX(_ITRF2020_, _ITRF94_, epoch=_E(2015),
1063 xform=_P( 6.5, -3.9, -77.9, 3.98, _0_0, _0_0, 0.36),
1064 rates=_P( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
1065_trfX(_ITRF2020_, _ITRF93_, epoch=_E(2015),
1066 xform=_P( -65.8, 1.9, -71.3, 4.47, -3.36, -4.33, 0.75),
1067 rates=_P( -2.8, -0.2, -2.3, 0.12, -0.11, -0.19, 0.07))
1068_trfX(_ITRF2020_, _ITRF92_, epoch=_E(2015),
1069 xform=_P( 14.5, -1.9, -85.9, 3.27, _0_0, _0_0, 0.36),
1070 rates=_P( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
1071_trfX(_ITRF2020_, _ITRF91_, epoch=_E(2015),
1072 xform=_P( 26.5, 12.1, -91.9, 4.67, _0_0, _0_0, 0.36),
1073 rates=_P( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
1074_trfX(_ITRF2020_, _ITRF90_, epoch=_E(2015),
1075 xform=_P( 24.5, 8.1, -107.9, 4.97, _0_0, _0_0, 0.36),
1076 rates=_P( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
1077_trfX(_ITRF2020_, _ITRF89_, epoch=_E(2015),
1078 xform=_P( 29.5, 32.1, -145.9, 8.37, _0_0, _0_0, 0.36),
1079 rates=_P( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
1080_trfX(_ITRF2020_, _ITRF88_, epoch=_E(2015),
1081 xform=_P( 24.5, -3.9, -169.9, 11.47, 0.1, _0_0, 0.36),
1082 rates=_P( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
1084# see U{Transformation Parameters ITRF2014<http://ITRF.IGN.Fr/doc_ITRF/Transfo-ITRF2014_ITRFs.txt>} and
1085# Altamimi, Z. U{"EUREF Technical Note 1: Relationship and Transformation between the International and
1086# the European Terrestrial Reference Systems"<https://ERTS89.ENSG,IFN.Fr/pub/EUREF-TN-1.pdf>} Appendix A.
1087_trfX(_ITRF2014_, _ITRF2008_, epoch=(2010), # <http://ITRF.ENSG.IGN.Fr/ITRF_solutions/2014/tp_14-08.php>
1088 xform=_P( 1.6, 1.9, 2.4, -0.02, _0_0, _0_0, _0_0),
1089 rates=_P( _0_0, _0_0, -0.1, 0.03, _0_0, _0_0, _0_0))
1090_trfX(_ITRF2014_, _ITRF2005_, epoch=_E(2010),
1091 xform=_P( 2.6, _1_0, -2.3, 0.92, _0_0, _0_0, _0_0),
1092 rates=_P( 0.3, _0_0, -0.1, 0.03, _0_0, _0_0, _0_0))
1093_trfX(_ITRF2014_, _ITRF2000_, epoch=_E(2010),
1094 xform=_P( 0.7, 1.2, -26.1, 2.12, _0_0, _0_0, _0_0),
1095 rates=_P( 0.1, 0.1, -1.9, 0.11, _0_0, _0_0, _0_0))
1096_trfX(_ITRF2014_, _ITRF97_, epoch=_E(2010),
1097 xform=_P( 7.4, -0.5, -62.8, 3.8, _0_0, _0_0, 0.26),
1098 rates=_P( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
1099_trfX(_ITRF2014_, _ITRF96_, epoch=_E(2010),
1100 xform=_P( 7.4, -0.5, -62.8, 3.8, _0_0, _0_0, 0.26),
1101 rates=_P( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
1102_trfX(_ITRF2014_, _ITRF94_, epoch=_E(2010),
1103 xform=_P( 7.4, -0.5, -62.8, 3.8, _0_0, _0_0, 0.26),
1104 rates=_P( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
1105_trfX(_ITRF2014_, _ITRF93_, epoch=_E(2010),
1106 xform=_P( -50.4, 3.3, -60.2, 4.29, -2.81, -3.38, 0.4),
1107 rates=_P( -2.8, -0.1, -2.5, 0.12, -0.11, -0.19, 0.07))
1108_trfX(_ITRF2014_, _ITRF92_, epoch=_E(2010),
1109 xform=_P( 15.4, 1.5, -70.8, 3.09, _0_0, _0_0, 0.26),
1110 rates=_P( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
1111_trfX(_ITRF2014_, _ITRF91_, epoch=_E(2010),
1112 xform=_P( 27.4, 15.5, -76.8, 4.49, _0_0, _0_0, 0.26),
1113 rates=_P( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
1114_trfX(_ITRF2014_, _ITRF90_, epoch=_E(2010),
1115 xform=_P( 25.4, 11.5, -92.8, 4.79, _0_0, _0_0, 0.26),
1116 rates=_P( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
1117_trfX(_ITRF2014_, _ITRF89_, epoch=_E(2010),
1118 xform=_P( 30.4, 35.5, -130.8, 8.19, _0_0, _0_0, 0.26),
1119 rates=_P( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
1120_trfX(_ITRF2014_, _ITRF88_, epoch=_E(2010),
1121 xform=_P( 25.4, -0.5, -154.8, 11.29, 0.1, _0_0, 0.26),
1122 rates=_P( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
1124# Pearson, C. & Snay, R. U{"Introducing HTDP 3.1 to transform coordinates across time and spatial reference
1125# frames"<https://Geodesy.NOAA.gov/TOOLS/Htdp/Pearson_Snay_2012.pdf> Table 7, 1st and 2nd column
1126_trfX(_ITRF2008_, _ITRF2005_, epoch=_E(2005),
1127 xform=_P( -0.5, -0.9, -4.7, 0.94, _0_0, _0_0, _0_0),
1128 rates=_P( 0.3, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0))
1129# _trfX(_ITRF2008_, _ITRF2005_, epoch=_E(1997),
1130# xform=_P( -2.9, -0.9, -4.7, 0.94, _0_0, _0_0, _0_0),
1131# rates=_P( 0.3, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0))
1132# see U{Transformation Parameters ITRF2008<http://ITRF.IGN.Fr/doc_ITRF/Transfo-ITRF2008_ITRFs.txt>}
1133# _trfX(_ITRF2008_, _ITRF2005_, epoch=_E(2000), # <http://ITRF.ENSG.IGN.Fr/ITRF_solutions/2008/tp_08-05.php>
1134# xform=_P( -2.0, -0.9, -4.7, 0.94, _0_0, _0_0, _0_0),
1135# rates=_P( 0.3, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0))
1136_trfX(_ITRF2008_, _ITRF2000_, epoch=_E(2000),
1137 xform=_P( -1.9, -1.7, -10.5, 1.34, _0_0, _0_0, _0_0),
1138 rates=_P( 0.1, 0.1, -1.8, 0.08, _0_0, _0_0, _0_0))
1139_trfX(_ITRF2008_, _ITRF97_, epoch=_E(2000),
1140 xform=_P( 4.8, 2.6, -33.2, 2.92, _0_0, _0_0, 0.06),
1141 rates=_P( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
1142_trfX(_ITRF2008_, _ITRF96_, epoch=_E(2000),
1143 xform=_P( 4.8, 2.6, -33.2, 2.92, _0_0, _0_0, 0.06),
1144 rates=_P( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
1145_trfX(_ITRF2008_, _ITRF94_, epoch=_E(2000),
1146 xform=_P( 4.8, 2.6, -33.2, 2.92, _0_0, _0_0, 0.06),
1147 rates=_P( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
1148_trfX(_ITRF2008_, _ITRF93_, epoch=_E(2000),
1149 xform=_P( -24.0, 2.4, -38.6, 3.41, -1.71, -1.48, -0.3),
1150 rates=_P( -2.8, -0.1, -2.4, 0.09, -0.11, -0.19, 0.07))
1151_trfX(_ITRF2008_, _ITRF92_, epoch=_E(2000),
1152 xform=_P( 12.8, 4.6, -41.2, 2.21, _0_0, _0_0, 0.06),
1153 rates=_P( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
1154_trfX(_ITRF2008_, _ITRF91_, epoch=_E(2000),
1155 xform=_P( 24.8, 18.6, -47.2, 3.61, _0_0, _0_0, 0.06),
1156 rates=_P( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
1157_trfX(_ITRF2008_, _ITRF90_, epoch=_E(2000),
1158 xform=_P( 22.8, 14.6, -63.2, 3.91, _0_0, _0_0, 0.06),
1159 rates=_P( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
1160_trfX(_ITRF2008_, _ITRF89_, epoch=_E(2000),
1161 xform=_P( 27.8, 38.6, -101.2, 7.31, _0_0, _0_0, 0.06),
1162 rates=_P( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
1163_trfX(_ITRF2008_, _ITRF88_, epoch=_E(2000),
1164 xform=_P( 22.8, 2.6, -125.2, 10.41, 0.1, _0_0, 0.06),
1165 rates=_P( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
1167# Pearson, C. & Snay, R. U{"Introducing HTDP 3.1 to transform coordinates across time and spatial reference
1168# frames"<https://Geodesy.NOAA.gov/TOOLS/Htdp/Pearson_Snay_2012.pdf> Table 7, 3rd column
1169# _trfX(_ITRF2005_, _ITRF2000_, epoch=_E(1997),
1170# xform=_P( 0.7, -1.1, -0.4, 0.16, -0.2, 0.1 -1.8),
1171# rates=_P( -0.2, 0.1, -1.8, 0.08, _0_0, _0_0, _0_0))
1172_trfX(_ITRF2005_, _ITRF2000_, epoch=_E(2000), # <http://ITRF.ENSG.IGN.Fr/ITRF_solutions/2005/tp_05-00.php>
1173 xform=_P( 0.1, -0.8, -5.8, 0.4, _0_0, _0_0, _0_0),
1174 rates=_P( -0.2, 0.1, -1.8, 0.08, _0_0, _0_0, _0_0))
1176_trfX(_ITRF2000_, _ITRF97_, epoch=_E(1997),
1177 xform=_P( 0.67, 0.61, -1.85, 1.55, _0_0, _0_0, _0_0),
1178 rates=_P( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, -0.02)) # 0.02?
1179_trfX(_ITRF2000_, _ITRF96_, epoch=_E(1997),
1180 xform=_P( 0.67, 0.61, -1.85, 1.55, _0_0, _0_0, _0_0),
1181 rates=_P( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
1182_trfX(_ITRF2000_, _ITRF94_, epoch=_E(1997),
1183 xform=_P( 0.67, 0.61, -1.85, 1.55, _0_0, _0_0, _0_0),
1184 rates=_P( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
1185_trfX(_ITRF2000_, _ITRF93_, epoch=_E(1988),
1186 xform=_P( 12.7, 6.5, -20.9, 1.95, -0.39, 0.8, -1.14),
1187 rates=_P( -2.9, -0.2, -0.6, 0.01, -0.11, -0.19, 0.07))
1188_trfX(_ITRF2000_, _ITRF92_, epoch=_E(1988),
1189 xform=_P( 1.47, 1.35, -1.39, 0.75, _0_0, _0_0, -0.18),
1190 rates=_P( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
1191_trfX(_ITRF2000_, _ITRF91_, epoch=_E(1988),
1192 xform=_P( 26.7, 27.5, -19.9, 2.15, _0_0, _0_0, -0.18),
1193 rates=_P( _0_0, -0.6, -1.4, 0.01, _0_0, _0_0, 0.02))
1194_trfX(_ITRF2000_, _ITRF90_, epoch=_E(1988),
1195 xform=_P( 2.47, 2.35, -3.59, 2.45, _0_0, _0_0, -0.18),
1196 rates=_P( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
1197_trfX(_ITRF2000_, _ITRF89_, epoch=_E(1988),
1198 xform=_P( 2.97, 4.75, -7.39, 5.85, _0_0, _0_0, -0.18),
1199 rates=_P( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
1200_trfX(_ITRF2000_, _ITRF88_, epoch=_E(1988),
1201 xform=_P( 2.47, 1.15, -9.79, 8.95, 0.1, _0_0, -0.18),
1202 rates=_P( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
1204# Soler, T .& Snay R.A. U{"Transforming Positions and Velocities between the International Terrestrial
1205# Reference Frame of 2000 and North American Datum of 1983"<https://www.ResearchGate.net/publication/245291390>},
1206# Pearson, C. & Snay, R. U{"Introducing HTDP 3.1 to transform coordinates across time and spatial reference
1207# frames"<https://Geodesy.NOAA.gov/TOOLS/Htdp/Pearson_Snay_2012.pdf> Table 7, 5th and 6th column
1208_trfX(_ITRF97_, _ITRF96_, epoch=_E(1997),
1209 xform=_P( -2.07, -0.21, 9.95, -0.93496, 0.1267, -0.22355, -0.06065,),
1210 rates=_P( 0.69, -0.1, 1.86, -0.19201, 0.01347, -0.01514, 0.00027))
1211_trfX(_ITRF96_, _NAD83_, epoch=_E(1997),
1212 xform=_P( 991.0, -190.72, -512.9, _0_0, 25.79, 9.65, 11.66,),
1213 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.0532, -0.7423, -0.0316,))
1215# see Altamimi, Z. U{"EUREF Technical Note 1: Relationship and Transformation between the International and
1216# the European Terrestrial Reference Systems"<https://ERTS89.ENSG.IFN.Fr/pub/EUREF-TN-1-Jan-31-2024.pdf>} Table 1.
1217# _trfX(_ITRF2020_, _ETRF2020_, epoch=_E(1989), # see Table 2 below
1218# xform=_P( _0_0, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0),
1219# rates=_P( _0_0, _0_0, _0_0, _0_0, 0.086, 0.519, -0.753))
1220# _trfX(_ITRF2014_, _ETRF2014_, epoch=_E(1989), # see Table 3 below
1221# xform=_P( _0_0, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0),
1222# rates=_P( _0_0, _0_0, _0_0, _0_0, 0.085, 0.531, -0.77))
1223_trfX(_ITRF2005_, _ETRF2005_, epoch=_E(1989),
1224 xform=_P( 56.0, 48.0, -37.0, _0_0, _0_0, _0_0, _0_0),
1225 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.054, 0.518, -0.781))
1226# _trfX(_ITRF2000_, _ETRF2000_, epoch=_E(1989), # see Table 4 below
1227# xform=_P( 54.0, 51.0, -48.0, _0_0, _0_0, _0_0, _0_0),
1228# rates=_P( _0_0, _0_0, _0_0, _0_0, 0.081, 0.49, -0.792))
1229_trfX(_ITRF97_, _ETRF97_, epoch=_E(1989),
1230 xform=_P( 41.0, 41.0, -49.0, _0_0, _0_0, _0_0, _0_0),
1231 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.2, 0.5, -0.65))
1232_trfX(_ITRF96_, _ETRF96_, epoch=_E(1989),
1233 xform=_P( 41.0, 41.0, -49.0, _0_0, _0_0, _0_0, _0_0),
1234 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.2, 0.5, -0.65))
1235_trfX(_ITRF94_, _ETRF94_, epoch=_E(1989),
1236 xform=_P( 41.0, 41.0, -49.0, _0_0, _0_0, _0_0, _0_0),
1237 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.2, 0.5, -0.65))
1238_trfX(_ITRF93_, _ETRF93_, epoch=_E(1989),
1239 xform=_P( 19.0, 53.0, -21.0, _0_0, _0_0, _0_0, _0_0),
1240 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.32, 0.78, -0.67))
1241_trfX(_ITRF92_, _ETRF92_, epoch=_E(1989),
1242 xform=_P( 38.0, 40.0, -37.0, 0.0, 0.0, 0.0, 0.0),
1243 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.21, 0.52, -0.68))
1244_trfX(_ITRF91_, _ETRF91_, epoch=_E(1989),
1245 xform=_P( 21.0, 25.0, -37.0, _0_0, _0_0, _0_0, _0_0),
1246 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.21, 0.52, -0.68))
1247_trfX(_ITRF90_, _ETRF90_, epoch=_E(1989),
1248 xform=_P( 19.0, 28.0, -23.0, _0_0, _0_0, _0_0, _0_0),
1249 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.11, 0.57, -0.71))
1250_trfX(_ITRF89_, _ETRF89_, epoch=_E(1989),
1251 xform=_P( _0_0, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0),
1252 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.11, 0.57, -0.71))
1254# see Altamimi, Z. U{"EUREF Technical Note 1: Relationship and Transformation between the International and
1255# the European Terrestrial Reference Systems"<https://ERTS89.ENSG.IFN.Fr/pub/EUREF-TN-1-Jan-31-2024.pdf>} Table 2.
1256_trfX(_ITRF2020_, _ETRF2020_, epoch=_E(2015),
1257 xform=_P( _0_0, _0_0, _0_0, _0_0, 2.236, 13.494, -19.578),
1258 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.086, 0.519, -0.753))
1259_trfX(_ITRF2014_, _ETRF2020_, epoch=_E(2015),
1260 xform=_P( 1.4, 0.9, -1.4, 0.42, 2.236, 13.494, -19.578),
1261 rates=_P( _0_0, 0.1, -0.2, _0_0, 0.086, 0.519, -0.753))
1262_trfX(_ITRF2008_, _ETRF2020_, epoch=_E(2015),
1263 xform=_P( 3.0, 2.8, 0.5, 0.55, 2.236, 13.494, -19.578),
1264 rates=_P( _0_0, 0.1, -0.3, 0.03, 0.086, 0.519, -0.753))
1265_trfX(_ITRF2005_, _ETRF2020_, epoch=_E(2015),
1266 xform=_P( 5.5, 1.9, -4.2, 1.49, 2.236, 13.494, -19.578),
1267 rates=_P( 0.3, 0.1, -0.3, 0.03, 0.086, 0.519, -0.753))
1268_trfX(_ITRF2000_, _ETRF2020_, epoch=_E(2015),
1269 xform=_P( 2.6, 2.6, -37.0, 3.09, 2.236, 13.494, -19.578),
1270 rates=_P( 0.1, 0.2, -2.1, 0.11, 0.086, 0.519, -0.753))
1271_trfX(_ITRF97_, _ETRF2020_, epoch=_E(2015),
1272 xform=_P( 9.3, -2.1, -80.7, 4.82, 2.236, 13.494, -19.218),
1273 rates=_P( 0.1, -0.4, -3.5, 0.12, 0.086, 0.519, -0.733))
1274_trfX(_ITRF96_, _ETRF2020_, epoch=_E(2015),
1275 xform=_P( 9.3, -2.1, -80.7, 4.82, 2.236, 13.494, -19.218),
1276 rates=_P( 0.1, -0.4, -3.5, 0.12, 0.086, 0.519, -0.733))
1277_trfX(_ITRF94_, _ETRF2020_, epoch=_E(2015),
1278 xform=_P( 9.3, -2.1, -80.7, 4.82, 2.236, 13.494, -19.218),
1279 rates=_P( 0.1, -0.4, -3.5, 0.12, 0.086, 0.519, -0.733))
1280_trfX(_ITRF93_, _ETRF2020_, epoch=_E(2015),
1281 xform=_P( -63.0, 3.7, -74.1, 5.31, -1.124, 9.164, -18.828),
1282 rates=_P( -2.8, _0_0, -2.7, 0.12, -0.024, 0.329, -0.683))
1283_trfX(_ITRF92_, _ETRF2020_, epoch=_E(2015),
1284 xform=_P( 17.3, -0.1, -88.7, 4.11, 2.236, 13.494, -19.218),
1285 rates=_P( 0.1, -0.4, -3.5, 0.12, 0.086, 0.519, -0.733))
1286_trfX(_ITRF91_, _ETRF2020_, epoch=_E(2015),
1287 xform=_P( 29.3, 13.9, -94.7, 5.51, 2.236, 13.494, -19.218),
1288 rates=_P( 0.1, -0.4, -3.5, 0.12, 0.086, 0.519, -0.733))
1289_trfX(_ITRF90_, _ETRF2020_, epoch=_E(2015),
1290 xform=_P( 27.3, 9.9, -110.7, 5.81, 2.236, 13.494, -19.218),
1291 rates=_P( 0.1, -0.4, -3.5, 0.12, 0.086, 0.519, -0.733))
1292_trfX(_ITRF89_, _ETRF2020_, epoch=_E(2015),
1293 xform=_P( 32.3, 33.9, -148.7, 9.21, 2.236, 13.494, -19.218),
1294 rates=_P( 0.1, -0.4, -3.5, 0.12, 0.086, 0.519, -0.733))
1295_trfX(_ITRF88_, _ETRF2020_, epoch=_E(2015),
1296 xform=_P( 27.3, -2.1, -172.7, 12.31, 2.336, 13.494, -19.218),
1297 rates=_P( 0.1, -0.4, -3.5, 0.12, 0.086, 0.519, -0.733))
1299# see Altamimi, Z. U{"EUREF Technical Note 1: Relationship and Transformation between the International and
1300# the European Terrestrial Reference Systems"<https://ERTS89.ENSG.IFN.Fr/pub/EUREF-TN-1-Jan-31-2024.pdf>} Table 3.
1301_trfX(_ITRF2020_, _ETRF2014_, epoch=_E(2015),
1302 xform=_P( -1.4, -0.9, 1.4, 0.42, 2.21, 13.806, -20.02),
1303 rates=_P( _0_0, -0.1, 0.2, _0_0, 0.085, 0.531, -0.77))
1304_trfX(_ITRF2014_, _ETRF2014_, epoch=_E(2015),
1305 xform=_P( _0_0, _0_0, _0_0, _0_0, 2.21, 13.806, -20.02),
1306 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.085, 0.531, -0.77))
1307_trfX(_ITRF2008_, _ETRF2014_, epoch=_E(2015),
1308 xform=_P( -1.6, -1.9, -1.9, -0.13, 2.21, 13.806, -20.02),
1309 rates=_P( _0_0, _0_0, 0.1, -0.03, 0.085, 0.531, -0.77))
1310_trfX(_ITRF2005_, _ETRF2014_, epoch=_E(2015),
1311 xform=_P( -4.1, -1.0, 2.8, -1.07, 2.21, 13.806, -20.02),
1312 rates=_P( -0.3, _0_0, 0.1, -0.03, 0.085, 0.531, -0.77))
1313_trfX(_ITRF2000_, _ETRF2014_, epoch=_E(2015),
1314 xform=_P( -1.2, -1.7, 35.6, -2.67, 2.21, 13.806, -20.02),
1315 rates=_P( -0.1, -0.1, 1.9, -0.11, 0.085, 0.531, -0.77))
1316_trfX(_ITRF97_, _ETRF2014_, epoch=_E(2015),
1317 xform=_P( -7.9, 3.0, 79.3, -4.40, 2.210, 13.806, -20.38),
1318 rates=_P( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
1319_trfX(_ITRF96_, _ETRF2014_, epoch=_E(2015),
1320 xform=_P( -7.9, 3.0, 79.3, -4.40, 2.210, 13.806, -20.38),
1321 rates=_P( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
1322_trfX(_ITRF94_, _ETRF2014_, epoch=_E(2015),
1323 xform=_P( -7.9, 3.0, 79.3, -4.40, 2.210, 13.806, -20.38),
1324 rates=_P( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
1325_trfX(_ITRF93_, _ETRF2014_, epoch=_E(2015),
1326 xform=_P( 64.4, -2.8, 72.7, -4.89, 5.570, 18.136, -20.77),
1327 rates=_P( 2.8, 0.1, 2.5, -0.12, 0.195, 0.721, -0.84))
1328_trfX(_ITRF92_, _ETRF2014_, epoch=_E(2015),
1329 xform=_P( -15.9, 1.0, 87.3, -3.69, 2.21, 13.806, -20.38),
1330 rates=_P( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
1331_trfX(_ITRF91_, _ETRF2014_, epoch=_E(2015),
1332 xform=_P( -27.9, -13.0, 93.3, -5.09, 2.21, 13.806, -20.38),
1333 rates=_P( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
1334_trfX(_ITRF90_, _ETRF2014_, epoch=_E(2015),
1335 xform=_P( -25.9, -9.0, 109.3, -5.39, 2.21, 13.806, -20.38),
1336 rates=_P( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
1337_trfX(_ITRF89_, _ETRF2014_, epoch=_E(2015),
1338 xform=_P( -30.9, -33.0, 147.3, -8.79, 2.21, 13.806, -20.38),
1339 rates=_P( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
1340_trfX(_ITRF88_, _ETRF2014_, epoch=_E(2015),
1341 xform=_P( -25.9, 3.0, 171.3, -11.89, 2.11, 13.806, -20.38),
1342 rates=_P( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
1344# see U{Altamimi, Z. "EUREF Technical Note 1: Relationship and Transformation between the International and
1345# the European Terrestrial Reference Systems"<https://ERTS89.ENSG,IFN.Fr/pub/EUREF-TN-1-Jan-31-2024.pdf>} Table 4,
1346# U{Boucher, C. & Altamimi, Z. "Memo: Specifications for reference frame fixing in the analysis of a EUREF GPS
1347# campaign" (2011) <https://ETRS89.ENSG.IGN.Fr/memo-V8.pdf>} and U{Altamimi, Z. "Key results of ITRF2014 and
1348# implication to ETRS89 realization", EUREF2016<https://www.EUREF.EU/symposia/2016SanSebastian/01-02-Altamimi.pdf>}.
1349_trfX(_ITRF2020_, _ETRF2000_, epoch=_E(2015),
1350 xform=_P( 53.8, 51.8, -82.2, 2.25, 2.106, 12.74, -20.592),
1351 rates=_P( 0.1, _0_0, -1.7, 0.11, 0.081, 0.49, -0.792))
1352# _trfX(_ITRF2014_, _ETRF2000_, epoch=_E(2000),
1353# xform=_P( 53.7, 51.2, -55.1, 1.02, 0.891, 5.39, -8.712),
1354# rates=_P( 0.1, 0.1, -1.9, 0.11, 0.081, 0.49, -0.792))
1355_trfX(_ITRF2014_, _ETRF2000_, epoch=_E(2015),
1356 xform=_P( 55.2, 52.7, -83.6, 2.67, 2.106, 12.74, -20.592),
1357 rates=_P( 0.1, 0.1, -1.9, 0.11, 0.081, 0.49, -0.792))
1358# _trfX(_ITRF2008_, _ETRF2000_, epoch=_E(2000),
1359# xform=_P( 52.1, 49.3, -58.5, 1.34, 0.891, 5.39, -8.712),
1360# rates=_P( 0.1, 0.1, -1.8, 0.08, 0.081, 0.49, -0.792))
1361_trfX(_ITRF2008_, _ETRF2000_, epoch=_E(2015),
1362 xform=_P( 53.6, 50.8, -85.5, 2.54, 2.106, 12.74, -20.592),
1363 rates=_P( 0.1, 0.1, -1.8, 0.08, 0.081, 0.49, -0.792))
1364# _trfX(_ITRF2005_, _ETRF2000_, epoch=_E(2000),
1365# xform=_P( 54.1, 50.2, -53.8, 0.4, 0.891, 5.39, -8.712),
1366# rates=_P( -0.2, 0.1, -1.8, 0.08, 0.081, 0.49, -0.792))
1367_trfX(_ITRF2005_, _ETRF2000_, epoch=_E(2015),
1368 xform=_P( 51.1, 51.7, -80.8, 1.6, 2.106, 12.74, -20.592),
1369 rates=_P( -0.2, 0.1, -1.8, 0.08, 0.081, 0.49, -0.792))
1370# _trfX(_ITRF2000_, _ETRF2000_, epoch=_E(2000),
1371# xform=_P( 54.0, 51.0, -48.0, _0_0, 0.891, 5.39, -8.712),
1372# rates=_P( _0_0, _0_0, _0_0, _0_0, 0.081, 0.49, -0.792))
1373_trfX(_ITRF2000_, _ETRF2000_, epoch=_E(2015),
1374 xform=_P( 54.0, 51.0, -48.0, _0_0, 2.106, 12.74, -20.592),
1375 rates=_P( _0_0, _0_0, _0_0, _0_0, 0.081, 0.49, -0.792))
1376_trfX(_ITRF97_, _ETRF2000_, epoch=_E(2015),
1377 xform=_P( 47.3, 55.7, -4.3, -1.73, 2.106, 12.74, -20.952),
1378 rates=_P( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
1379_trfX(_ITRF96_, _ETRF2000_, epoch=_E(2015),
1380 xform=_P( 47.3, 55.7, -4.3, -1.73, 2.106, 12.74, -20.952),
1381 rates=_P( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
1382_trfX(_ITRF94_, _ETRF2000_, epoch=_E(2015),
1383 xform=_P( 47.3, 55.7, -4.3, -1.73, 2.106, 12.74, -20.952),
1384 rates=_P( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
1385_trfX(_ITRF93_, _ETRF2000_, epoch=_E(2015),
1386 xform=_P( 119.6, 49.9, -10.9, -2.22, 5.466, 17.07, -21.342),
1387 rates=_P( 2.9, 0.2, 0.6, -0.01, 0.191, 0.68, -0.862))
1388_trfX(_ITRF92_, _ETRF2000_, epoch=_E(2015),
1389 xform=_P( 39.3, 53.7, 3.7, -1.02, 2.106, 12.74, -20.952),
1390 rates=_P( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
1391_trfX(_ITRF91_, _ETRF2000_, epoch=_E(2015),
1392 xform=_P( 27.3, 39.7, 9.7, -2.42, 2.106, 12.74, -20.952),
1393 rates=_P( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
1394_trfX(_ITRF90_, _ETRF2000_, epoch=_E(2015),
1395 xform=_P( 29.3, 43.7, 25.7, -2.72, 2.106, 12.74, -20.952),
1396 rates=_P( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
1397_trfX(_ITRF89_, _ETRF2000_, epoch=_E(2015),
1398 xform=_P( 24.3, 19.7, 63.7, -6.12, 2.106, 12.74, -20.952),
1399 rates=_P( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
1400_trfX(_ITRF88_, _ETRF2000_, epoch=_E(2015),
1401 xform=_P( 29.3, 55.7, 87.7, -9.22, 2.006, 12.74, -20.952),
1402 rates=_P( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
1404# GDA2020 "Geocentric Datum of Australia 2020 Technical Manual", v1.5, 2020-12-09, Table 3.3 and 3.4
1405# <https://www.ICSM.gov.AU/sites/default/files/2020-12/GDA2020%20Technical%20Manual%20V1.5_4.pdf>
1406# (the GDA2020 xforms are different but the rates are the same as GDA94, further below)
1407_trfX(_ITRF2014_, _GDA2020_, epoch=_E(2020),
1408 xform=_P( _0_0, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0),
1409 rates=_P( _0_0, _0_0, _0_0, _0_0, 1.50379, 1.18346, 1.20716))
1410_trfX(_ITRF2008_, _GDA2020_, epoch=_E(2020),
1411 xform=_P( 13.79, 4.55, 15.22, 2.5, 0.2808, 0.2677, -0.4638),
1412 rates=_P( 1.42, 1.34, 0.9, 0.109, 1.5461, 1.182, 1.1551))
1413_trfX(_ITRF2005_, _GDA2020_, epoch=_E(2020),
1414 xform=_P( 40.32, -33.85, -16.72, 4.286, -1.2893, -0.8492, -0.3342),
1415 rates=_P( 2.25, -0.62, -0.56, 0.294, -1.4707, -1.1443, -1.1701))
1416_trfX(_ITRF2000_, _GDA2020_, epoch=_E(2020),
1417 xform=_P(-105.52, 51.58, 231.68, 3.55, 4.2175, 6.3941, 0.8617),
1418 rates=_P( -4.66, 3.55, 11.24, 0.249, 1.7454, 1.4868, 1.224))
1420# see Table 2 in U{Dawson, J. & Woods, A. "ITRF to GDA94 coordinate transformations", Journal of Applied
1421# Geodesy 4 (2010), 189-199<https://www.ResearchGate.net/publication/258401581_ITRF_to_GDA94_coordinate_transformations>}
1422# (note, sign of rotations for GDA94 reversed as "Australia assumes rotation to be of coordinate axes",
1423# rather than the more conventional "position around the coordinate axes")
1424_trfX(_ITRF2008_, _GDA94_, epoch=_E(1994),
1425 xform=_P( -84.68, -19.42, 32.01, 9.71, -0.4254, 2.2578, 2.4015),
1426 rates=_P( 1.42, 1.34, 0.9, 0.109, 1.5461, 1.182, 1.1551))
1427_trfX(_ITRF2005_, _GDA94_, epoch=_E(1994),
1428 xform=_P( -79.73, -6.86, 38.03, 6.636, 0.0351, -2.1211, -2.1411),
1429 rates=_P( 2.25, -0.62, -0.56, 0.294, -1.4707, -1.1443, -1.1701))
1430_trfX(_ITRF2000_, _GDA94_, epoch=_E(1994),
1431 xform=_P( -45.91, -29.85, -20.37, 7.07, -1.6705, 0.4594, 1.9356),
1432 rates=_P( -4.66, 3.55, 11.24, 0.249, 1.7454, 1.4868, 1.224))
1434# see U{Solar, T. & Snay, R.A. "Transforming Positions and Velocities between the International Terrestrial Reference
1435# Frame of 2000 and North American Datum of 1983" (2004)<https://www.NGS.NOAA.gov/CORS/Articles/SolerSnayASCE.pdf>}
1436_trfX(_ITRF2000_, _NAD83_, epoch=_E(1997), # note NAD83(CORS96)
1437 xform=_P( 995.6, -1901.3, -521.5, 0.615, -25.915, -9.426, -11.599),
1438 rates=_P( 0.7, -0.7, _0_5, -0.182, -0.06667, 0.75744, 0.05133))
1440# see U{Quinsy QPS<https://confluence.QPS.NL/qinsy/files/latest/en/182618383/182618384/1/1579182881000/
1441# ITRF_Transformation_Parameters.xlsx>}, sheets ITRF and NAD83 and Pearson, C. & Snay, R. U{"Introducing
1442# HTDP 3.1 to transform coordinates across time and spatial reference frames"<https://Geodesy.NOAA.gov/
1443# TOOLS/Htdp/Pearson_Snay_2012.pdf> Table 7, 7th column
1444_trfX(_ITRF2008_, _NAD83_, epoch=_E(1997),
1445 xform=_P( 993.43, -1903.31, -526.55, 1.71504, -25.91467, -9.42645, -11.59935),
1446 rates=_P( 0.79, -0.6, -1.34, -0.10201, -0.06667, 0.75744, 0.05133))
1447# see U{Quinsy QPS<https://confluence.QPS.NL/qinsy/files/latest/en/182618383/182618384/1/1579182881000/
1448# ITRF_Transformation_Parameters.xlsx>}, sheets ITRF and NAD83
1449_trfX(_ITRF2005_, _NAD83_, epoch=_E(1997),
1450 xform=_P( 996.3, -1902.4, -521.9, 0.775, -25.915, -9.426, -11.599),
1451 rates=_P( 0.5, -0.6, -1.3, -0.10201, -0.06667, 0.75744, 0.05133))
1452_trfX(_ITRF90_, _NAD83_, epoch=_E(1997),
1453 xform=_P( 973.0, -1919.2, -482.9, -0.9, -25.79, -9.65, -11.66),
1454 rates=_P( _0_0, _0_0, _0_0, _0_0, -0.053, 0.742, 0.032))
1455trfXform(_ITRF90_, _WGS84_, epoch=_E(1984), # coverage
1456 xform=_P( 60.0, -517.0, -223.0, -11.0, 18.3, -0.3, 7.0),
1457 rates=_P( _0_0, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0))
1459del _E, _Es, _P, _Ps
1461if __name__ == '__main__':
1463 def _main():
1464 from pygeodesy.interns import _COLONSPACE_,_COMMA_, _NL_, _NLATvar_, _STAR_, _vs_
1465 from pygeodesy.lazily import printf
1466 from time import localtime
1468 D = date2epoch.__name__
1469 E = epoch2date.__name__
1470 y = localtime()[0]
1471 for m in range(1, 13):
1472 for d in (1, 15, _mDays[m] - 1, _mDays[m]):
1473 f = '%s(%d,%3d,%3d)' % (D, y, m, d)
1474 e = date2epoch(y, m, d)
1475 t = epoch2date(e)
1476 x = NN if t == (y, m, d) else _STAR_
1477 e = '%.3f' % (e,)
1478 e = '%s, %s(%s)' % (e, E, e)
1479 t = '%d,%3d,%3d' % t
1480 printf('# %s = %s = %s %s', f, e, t, x)
1482 # __doc__ of this file, force all into registery
1483 def _RFs():
1484 yield NN
1485 for t in RefFrames.toRepr(all=True).split(_NL_):
1486 t = t.strip(_COMMA_)
1487 n = t.split(_COLONSPACE_)[0].split(_DOT_)[1]
1488 r = RefFrames.get(n)
1489 x = len(r.Xforms()), -len(r.Xforms(inverse=True))
1490 yield '%s .Xforms=%s' % (t, x)
1492 printf(_NLATvar_.join(sorted(_RFs())), nt=1)
1494 X, t = (), 0 # all form
1495 for r in RefFrames.values():
1496 X += tuple(r._Xs.values())
1497 for X in sorted(X):
1498 t += 1
1499 printf('#%4d %-22s xform=%r', t, X.name, X.xform)
1500 printf('#%27s rates=%r', _SPACE_, X.rates)
1502 t = _MODS.basics._xargs_kwds_names(Transform.__init__)
1503 for n in TRFXform7Tuple._Names_:
1504 if n not in t:
1505 raise AssertionError(_SPACE_(n, _vs_, t))
1507 _main()
1508 del _main
1510# **) MIT License
1511#
1512# Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
1513#
1514# Permission is hereby granted, free of charge, to any person obtaining a
1515# copy of this software and associated documentation files (the "Software"),
1516# to deal in the Software without restriction, including without limitation
1517# the rights to use, copy, modify, merge, publish, distribute, sublicense,
1518# and/or sell copies of the Software, and to permit persons to whom the
1519# Software is furnished to do so, subject to the following conditions:
1520#
1521# The above copyright notice and this permission notice shall be included
1522# in all copies or substantial portions of the Software.
1523#
1524# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1525# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1526# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1527# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
1528# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1529# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1530# OTHER DEALINGS IN THE SOFTWARE.
1532# % python -m pygeodesy.trf
1533#
1534# date2epoch(2024, 1, 1) = 2024.003, epoch2date(2024.003) = 2024, 1, 1
1535# date2epoch(2024, 1, 15) = 2024.041, epoch2date(2024.041) = 2024, 1, 15
1536# date2epoch(2024, 1, 30) = 2024.082, epoch2date(2024.082) = 2024, 1, 30
1537# date2epoch(2024, 1, 31) = 2024.085, epoch2date(2024.085) = 2024, 1, 31
1538# date2epoch(2024, 2, 1) = 2024.087, epoch2date(2024.087) = 2024, 2, 2 *
1539# date2epoch(2024, 2, 15) = 2024.126, epoch2date(2024.126) = 2024, 2, 16 *
1540# date2epoch(2024, 2, 28) = 2024.161, epoch2date(2024.161) = 2024, 2, 28
1541# date2epoch(2024, 2, 29) = 2024.164, epoch2date(2024.164) = 2024, 3, 1 *
1542# date2epoch(2024, 3, 1) = 2024.167, epoch2date(2024.167) = 2024, 3, 2 *
1543# date2epoch(2024, 3, 15) = 2024.205, epoch2date(2024.205) = 2024, 3, 16 *
1544# date2epoch(2024, 3, 30) = 2024.246, epoch2date(2024.246) = 2024, 3, 31 *
1545# date2epoch(2024, 3, 31) = 2024.249, epoch2date(2024.249) = 2024, 4, 1 *
1546# date2epoch(2024, 4, 1) = 2024.251, epoch2date(2024.251) = 2024, 4, 1
1547# date2epoch(2024, 4, 15) = 2024.290, epoch2date(2024.290) = 2024, 4, 15
1548# date2epoch(2024, 4, 29) = 2024.328, epoch2date(2024.328) = 2024, 4, 29
1549# date2epoch(2024, 4, 30) = 2024.331, epoch2date(2024.331) = 2024, 4, 30
1550# date2epoch(2024, 5, 1) = 2024.333, epoch2date(2024.333) = 2024, 5, 1
1551# date2epoch(2024, 5, 15) = 2024.372, epoch2date(2024.372) = 2024, 5, 15
1552# date2epoch(2024, 5, 30) = 2024.413, epoch2date(2024.413) = 2024, 5, 30
1553# date2epoch(2024, 5, 31) = 2024.415, epoch2date(2024.415) = 2024, 6, 1 *
1554# date2epoch(2024, 6, 1) = 2024.418, epoch2date(2024.418) = 2024, 6, 2 *
1555# date2epoch(2024, 6, 15) = 2024.456, epoch2date(2024.456) = 2024, 6, 16 *
1556# date2epoch(2024, 6, 29) = 2024.495, epoch2date(2024.495) = 2024, 6, 30 *
1557# date2epoch(2024, 6, 30) = 2024.497, epoch2date(2024.497) = 2024, 7, 1 *
1558# date2epoch(2024, 7, 1) = 2024.500, epoch2date(2024.500) = 2024, 7, 1
1559# date2epoch(2024, 7, 15) = 2024.538, epoch2date(2024.538) = 2024, 7, 16 *
1560# date2epoch(2024, 7, 30) = 2024.579, epoch2date(2024.579) = 2024, 7, 30
1561# date2epoch(2024, 7, 31) = 2024.582, epoch2date(2024.582) = 2024, 7, 31
1562# date2epoch(2024, 8, 1) = 2024.585, epoch2date(2024.585) = 2024, 8, 1
1563# date2epoch(2024, 8, 15) = 2024.623, epoch2date(2024.623) = 2024, 8, 15
1564# date2epoch(2024, 8, 30) = 2024.664, epoch2date(2024.664) = 2024, 8, 31 *
1565# date2epoch(2024, 8, 31) = 2024.667, epoch2date(2024.667) = 2024, 9, 1 *
1566# date2epoch(2024, 9, 1) = 2024.669, epoch2date(2024.669) = 2024, 9, 2 *
1567# date2epoch(2024, 9, 15) = 2024.708, epoch2date(2024.708) = 2024, 9, 16 *
1568# date2epoch(2024, 9, 29) = 2024.746, epoch2date(2024.746) = 2024, 9, 30 *
1569# date2epoch(2024, 9, 30) = 2024.749, epoch2date(2024.749) = 2024, 10, 1 *
1570# date2epoch(2024, 10, 1) = 2024.751, epoch2date(2024.751) = 2024, 10, 1
1571# date2epoch(2024, 10, 15) = 2024.790, epoch2date(2024.790) = 2024, 10, 15
1572# date2epoch(2024, 10, 30) = 2024.831, epoch2date(2024.831) = 2024, 10, 30
1573# date2epoch(2024, 10, 31) = 2024.833, epoch2date(2024.833) = 2024, 10, 31
1574# date2epoch(2024, 11, 1) = 2024.836, epoch2date(2024.836) = 2024, 11, 1
1575# date2epoch(2024, 11, 15) = 2024.874, epoch2date(2024.874) = 2024, 11, 15
1576# date2epoch(2024, 11, 29) = 2024.913, epoch2date(2024.913) = 2024, 11, 29
1577# date2epoch(2024, 11, 30) = 2024.915, epoch2date(2024.915) = 2024, 12, 1 *
1578# date2epoch(2024, 12, 1) = 2024.918, epoch2date(2024.918) = 2024, 12, 2 *
1579# date2epoch(2024, 12, 15) = 2024.956, epoch2date(2024.956) = 2024, 12, 16 *
1580# date2epoch(2024, 12, 30) = 2024.997, epoch2date(2024.997) = 2024, 12, 31 *
1581# date2epoch(2024, 12, 31) = 2025.000, epoch2date(2025.000) = 2025, 1, 1 *
1583# 1 ITRF2005@2015xETRF2000 xform=TRFXform7Tuple(tx=51.1, ty=51.7, tz=-80.8, s=1.6, sx=2.106, sy=12.74, sz=-20.592)
1584# rates=TRFXform7Tuple(tx=-0.2, ty=0.1, tz=-1.8, s=0.08, sx=0.081, sy=0.49, sz=-0.792)
1585# 2 ITRF88@2015xETRF2000 xform=TRFXform7Tuple(tx=29.3, ty=55.7, tz=87.7, s=-9.22, sx=2.006, sy=12.74, sz=-20.952)
1586# rates=TRFXform7Tuple(tx=0.0, ty=0.6, tz=1.4, s=-0.01, sx=0.081, sy=0.49, sz=-0.812)
1587# 3 ITRF2005@1989xETRF2005 xform=TRFXform7Tuple(tx=56.0, ty=48.0, tz=-37.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1588# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.054, sy=0.518, sz=-0.781)
1589# 4 ITRF88@2015xETRF2014 xform=TRFXform7Tuple(tx=-25.9, ty=3.0, tz=171.3, s=-11.89, sx=2.11, sy=13.806, sz=-20.38)
1590# rates=TRFXform7Tuple(tx=-0.1, ty=0.5, tz=3.3, s=-0.12, sx=0.085, sy=0.531, sz=-0.79)
1591# 5 ITRF88@2015xETRF2020 xform=TRFXform7Tuple(tx=27.3, ty=-2.1, tz=-172.7, s=12.31, sx=2.336, sy=13.494, sz=-19.218)
1592# rates=TRFXform7Tuple(tx=0.1, ty=-0.4, tz=-3.5, s=0.12, sx=0.086, sy=0.519, sz=-0.733)
1593# 6 ITRF89@2015xETRF2000 xform=TRFXform7Tuple(tx=24.3, ty=19.7, tz=63.7, s=-6.12, sx=2.106, sy=12.74, sz=-20.952)
1594# rates=TRFXform7Tuple(tx=0.0, ty=0.6, tz=1.4, s=-0.01, sx=0.081, sy=0.49, sz=-0.812)
1595# 7 ITRF89@2015xETRF2014 xform=TRFXform7Tuple(tx=-30.9, ty=-33.0, tz=147.3, s=-8.79, sx=2.21, sy=13.806, sz=-20.38)
1596# rates=TRFXform7Tuple(tx=-0.1, ty=0.5, tz=3.3, s=-0.12, sx=0.085, sy=0.531, sz=-0.79)
1597# 8 ITRF89@2015xETRF2020 xform=TRFXform7Tuple(tx=32.3, ty=33.9, tz=-148.7, s=9.21, sx=2.236, sy=13.494, sz=-19.218)
1598# rates=TRFXform7Tuple(tx=0.1, ty=-0.4, tz=-3.5, s=0.12, sx=0.086, sy=0.519, sz=-0.733)
1599# 9 ITRF89@1989xETRF89 xform=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1600# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.11, sy=0.57, sz=-0.71)
1601# 10 ITRF90@1984xWGS84 xform=TRFXform7Tuple(tx=60.0, ty=-517.0, tz=-223.0, s=-11.0, sx=18.3, sy=-0.3, sz=7.0)
1602# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1603# 11 ITRF2005@1994xGDA94 xform=TRFXform7Tuple(tx=-79.73, ty=-6.86, tz=38.03, s=6.636, sx=0.0351, sy=-2.1211, sz=-2.1411)
1604# rates=TRFXform7Tuple(tx=2.25, ty=-0.62, tz=-0.56, s=0.294, sx=-1.4707, sy=-1.1443, sz=-1.1701)
1605# 12 ITRF90@1997xNAD83 xform=TRFXform7Tuple(tx=973.0, ty=-1919.2, tz=-482.9, s=-0.9, sx=-25.79, sy=-9.65, sz=-11.66)
1606# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=-0.053, sy=0.742, sz=0.032)
1607# 13 ITRF90@2015xETRF2000 xform=TRFXform7Tuple(tx=29.3, ty=43.7, tz=25.7, s=-2.72, sx=2.106, sy=12.74, sz=-20.952)
1608# rates=TRFXform7Tuple(tx=0.0, ty=0.6, tz=1.4, s=-0.01, sx=0.081, sy=0.49, sz=-0.812)
1609# 14 ITRF2005@2015xETRF2014 xform=TRFXform7Tuple(tx=-4.1, ty=-1.0, tz=2.8, s=-1.07, sx=2.21, sy=13.806, sz=-20.02)
1610# rates=TRFXform7Tuple(tx=-0.3, ty=0.0, tz=0.1, s=-0.03, sx=0.085, sy=0.531, sz=-0.77)
1611# 15 ITRF90@2015xETRF2014 xform=TRFXform7Tuple(tx=-25.9, ty=-9.0, tz=109.3, s=-5.39, sx=2.21, sy=13.806, sz=-20.38)
1612# rates=TRFXform7Tuple(tx=-0.1, ty=0.5, tz=3.3, s=-0.12, sx=0.085, sy=0.531, sz=-0.79)
1613# 16 ITRF2005@2015xETRF2020 xform=TRFXform7Tuple(tx=5.5, ty=1.9, tz=-4.2, s=1.49, sx=2.236, sy=13.494, sz=-19.578)
1614# rates=TRFXform7Tuple(tx=0.3, ty=0.1, tz=-0.3, s=0.03, sx=0.086, sy=0.519, sz=-0.753)
1615# 17 ITRF90@2015xETRF2020 xform=TRFXform7Tuple(tx=27.3, ty=9.9, tz=-110.7, s=5.81, sx=2.236, sy=13.494, sz=-19.218)
1616# rates=TRFXform7Tuple(tx=0.1, ty=-0.4, tz=-3.5, s=0.12, sx=0.086, sy=0.519, sz=-0.733)
1617# 18 ITRF90@1989xETRF90 xform=TRFXform7Tuple(tx=19.0, ty=28.0, tz=-23.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1618# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.11, sy=0.57, sz=-0.71)
1619# 19 ITRF91@2015xETRF2000 xform=TRFXform7Tuple(tx=27.3, ty=39.7, tz=9.7, s=-2.42, sx=2.106, sy=12.74, sz=-20.952)
1620# rates=TRFXform7Tuple(tx=0.0, ty=0.6, tz=1.4, s=-0.01, sx=0.081, sy=0.49, sz=-0.812)
1621# 20 ITRF91@2015xETRF2014 xform=TRFXform7Tuple(tx=-27.9, ty=-13.0, tz=93.3, s=-5.09, sx=2.21, sy=13.806, sz=-20.38)
1622# rates=TRFXform7Tuple(tx=-0.1, ty=0.5, tz=3.3, s=-0.12, sx=0.085, sy=0.531, sz=-0.79)
1623# 21 ITRF91@1989xETRF91 xform=TRFXform7Tuple(tx=21.0, ty=25.0, tz=-37.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1624# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.21, sy=0.52, sz=-0.68)
1625# 22 ITRF92@2015xETRF2000 xform=TRFXform7Tuple(tx=39.3, ty=53.7, tz=3.7, s=-1.02, sx=2.106, sy=12.74, sz=-20.952)
1626# rates=TRFXform7Tuple(tx=0.0, ty=0.6, tz=1.4, s=-0.01, sx=0.081, sy=0.49, sz=-0.812)
1627# 23 ITRF92@2015xETRF2014 xform=TRFXform7Tuple(tx=-15.9, ty=1.0, tz=87.3, s=-3.69, sx=2.21, sy=13.806, sz=-20.38)
1628# rates=TRFXform7Tuple(tx=-0.1, ty=0.5, tz=3.3, s=-0.12, sx=0.085, sy=0.531, sz=-0.79)
1629# 24 ITRF92@2015xETRF2020 xform=TRFXform7Tuple(tx=17.3, ty=-0.1, tz=-88.7, s=4.11, sx=2.236, sy=13.494, sz=-19.218)
1630# rates=TRFXform7Tuple(tx=0.1, ty=-0.4, tz=-3.5, s=0.12, sx=0.086, sy=0.519, sz=-0.733)
1631# 25 ITRF92@1989xETRF92 xform=TRFXform7Tuple(tx=38.0, ty=40.0, tz=-37.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1632# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.21, sy=0.52, sz=-0.68)
1633# 26 ITRF93@2015xETRF2000 xform=TRFXform7Tuple(tx=119.6, ty=49.9, tz=-10.9, s=-2.22, sx=5.466, sy=17.07, sz=-21.342)
1634# rates=TRFXform7Tuple(tx=2.9, ty=0.2, tz=0.6, s=-0.01, sx=0.191, sy=0.68, sz=-0.862)
1635# 27 ITRF93@2015xETRF2014 xform=TRFXform7Tuple(tx=64.4, ty=-2.8, tz=72.7, s=-4.89, sx=5.57, sy=18.136, sz=-20.77)
1636# rates=TRFXform7Tuple(tx=2.8, ty=0.1, tz=2.5, s=-0.12, sx=0.195, sy=0.721, sz=-0.84)
1637# 28 ITRF93@2015xETRF2020 xform=TRFXform7Tuple(tx=-63.0, ty=3.7, tz=-74.1, s=5.31, sx=-1.124, sy=9.164, sz=-18.828)
1638# rates=TRFXform7Tuple(tx=-2.8, ty=0.0, tz=-2.7, s=0.12, sx=-0.024, sy=0.329, sz=-0.683)
1639# 29 ITRF93@1989xETRF93 xform=TRFXform7Tuple(tx=19.0, ty=53.0, tz=-21.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1640# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.32, sy=0.78, sz=-0.67)
1641# 30 ITRF94@2015xETRF2000 xform=TRFXform7Tuple(tx=47.3, ty=55.7, tz=-4.3, s=-1.73, sx=2.106, sy=12.74, sz=-20.952)
1642# rates=TRFXform7Tuple(tx=0.0, ty=0.6, tz=1.4, s=-0.01, sx=0.081, sy=0.49, sz=-0.812)
1643# 31 ITRF94@2015xETRF2014 xform=TRFXform7Tuple(tx=-7.9, ty=3.0, tz=79.3, s=-4.4, sx=2.21, sy=13.806, sz=-20.38)
1644# rates=TRFXform7Tuple(tx=-0.1, ty=0.5, tz=3.3, s=-0.12, sx=0.085, sy=0.531, sz=-0.79)
1645# 32 ITRF94@2015xETRF2020 xform=TRFXform7Tuple(tx=9.3, ty=-2.1, tz=-80.7, s=4.82, sx=2.236, sy=13.494, sz=-19.218)
1646# rates=TRFXform7Tuple(tx=0.1, ty=-0.4, tz=-3.5, s=0.12, sx=0.086, sy=0.519, sz=-0.733)
1647# 33 ITRF94@1989xETRF94 xform=TRFXform7Tuple(tx=41.0, ty=41.0, tz=-49.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1648# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.2, sy=0.5, sz=-0.65)
1649# 34 ITRF96@1989xETRF96 xform=TRFXform7Tuple(tx=41.0, ty=41.0, tz=-49.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1650# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.2, sy=0.5, sz=-0.65)
1651# 35 ITRF97@1989xETRF97 xform=TRFXform7Tuple(tx=41.0, ty=41.0, tz=-49.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1652# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.2, sy=0.5, sz=-0.65)
1653# 36 ITRF2000@1994xGDA94 xform=TRFXform7Tuple(tx=-45.91, ty=-29.85, tz=-20.37, s=7.07, sx=-1.6705, sy=0.4594, sz=1.9356)
1654# rates=TRFXform7Tuple(tx=-4.66, ty=3.55, tz=11.24, s=0.249, sx=1.7454, sy=1.4868, sz=1.224)
1655# 37 ITRF2000@2015xETRF2000 xform=TRFXform7Tuple(tx=54.0, ty=51.0, tz=-48.0, s=0.0, sx=2.106, sy=12.74, sz=-20.592)
1656# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.081, sy=0.49, sz=-0.792)
1657# 38 ITRF96@2015xETRF2000 xform=TRFXform7Tuple(tx=47.3, ty=55.7, tz=-4.3, s=-1.73, sx=2.106, sy=12.74, sz=-20.952)
1658# rates=TRFXform7Tuple(tx=0.0, ty=0.6, tz=1.4, s=-0.01, sx=0.081, sy=0.49, sz=-0.812)
1659# 39 ITRF97@2015xETRF2000 xform=TRFXform7Tuple(tx=47.3, ty=55.7, tz=-4.3, s=-1.73, sx=2.106, sy=12.74, sz=-20.952)
1660# rates=TRFXform7Tuple(tx=0.0, ty=0.6, tz=1.4, s=-0.01, sx=0.081, sy=0.49, sz=-0.812)
1661# 40 ITRF2000@2015xETRF2014 xform=TRFXform7Tuple(tx=-1.2, ty=-1.7, tz=35.6, s=-2.67, sx=2.21, sy=13.806, sz=-20.02)
1662# rates=TRFXform7Tuple(tx=-0.1, ty=-0.1, tz=1.9, s=-0.11, sx=0.085, sy=0.531, sz=-0.77)
1663# 41 ITRF96@2015xETRF2014 xform=TRFXform7Tuple(tx=-7.9, ty=3.0, tz=79.3, s=-4.4, sx=2.21, sy=13.806, sz=-20.38)
1664# rates=TRFXform7Tuple(tx=-0.1, ty=0.5, tz=3.3, s=-0.12, sx=0.085, sy=0.531, sz=-0.79)
1665# 42 ITRF97@2015xETRF2014 xform=TRFXform7Tuple(tx=-7.9, ty=3.0, tz=79.3, s=-4.4, sx=2.21, sy=13.806, sz=-20.38)
1666# rates=TRFXform7Tuple(tx=-0.1, ty=0.5, tz=3.3, s=-0.12, sx=0.085, sy=0.531, sz=-0.79)
1667# 43 ITRF2000@2015xETRF2020 xform=TRFXform7Tuple(tx=2.6, ty=2.6, tz=-37.0, s=3.09, sx=2.236, sy=13.494, sz=-19.578)
1668# rates=TRFXform7Tuple(tx=0.1, ty=0.2, tz=-2.1, s=0.11, sx=0.086, sy=0.519, sz=-0.753)
1669# 44 ITRF91@2015xETRF2020 xform=TRFXform7Tuple(tx=29.3, ty=13.9, tz=-94.7, s=5.51, sx=2.236, sy=13.494, sz=-19.218)
1670# rates=TRFXform7Tuple(tx=0.1, ty=-0.4, tz=-3.5, s=0.12, sx=0.086, sy=0.519, sz=-0.733)
1671# 45 ITRF96@2015xETRF2020 xform=TRFXform7Tuple(tx=9.3, ty=-2.1, tz=-80.7, s=4.82, sx=2.236, sy=13.494, sz=-19.218)
1672# rates=TRFXform7Tuple(tx=0.1, ty=-0.4, tz=-3.5, s=0.12, sx=0.086, sy=0.519, sz=-0.733)
1673# 46 ITRF97@2015xETRF2020 xform=TRFXform7Tuple(tx=9.3, ty=-2.1, tz=-80.7, s=4.82, sx=2.236, sy=13.494, sz=-19.218)
1674# rates=TRFXform7Tuple(tx=0.1, ty=-0.4, tz=-3.5, s=0.12, sx=0.086, sy=0.519, sz=-0.733)
1675# 47 ITRF2000@2020xGDA2020 xform=TRFXform7Tuple(tx=-105.52, ty=51.58, tz=231.68, s=3.55, sx=4.2175, sy=6.3941, sz=0.8617)
1676# rates=TRFXform7Tuple(tx=-4.66, ty=3.55, tz=11.24, s=0.249, sx=1.7454, sy=1.4868, sz=1.224)
1677# 48 ITRF2000@1988xITRF88 xform=TRFXform7Tuple(tx=2.47, ty=1.15, tz=-9.79, s=8.95, sx=0.1, sy=0.0, sz=-0.18)
1678# rates=TRFXform7Tuple(tx=0.0, ty=-0.06, tz=-0.14, s=0.01, sx=0.0, sy=0.0, sz=0.02)
1679# 49 ITRF2000@1988xITRF89 xform=TRFXform7Tuple(tx=2.97, ty=4.75, tz=-7.39, s=5.85, sx=0.0, sy=0.0, sz=-0.18)
1680# rates=TRFXform7Tuple(tx=0.0, ty=-0.06, tz=-0.14, s=0.01, sx=0.0, sy=0.0, sz=0.02)
1681# 50 ITRF2000@1988xITRF90 xform=TRFXform7Tuple(tx=2.47, ty=2.35, tz=-3.59, s=2.45, sx=0.0, sy=0.0, sz=-0.18)
1682# rates=TRFXform7Tuple(tx=0.0, ty=-0.06, tz=-0.14, s=0.01, sx=0.0, sy=0.0, sz=0.02)
1683# 51 ITRF2000@1988xITRF91 xform=TRFXform7Tuple(tx=26.7, ty=27.5, tz=-19.9, s=2.15, sx=0.0, sy=0.0, sz=-0.18)
1684# rates=TRFXform7Tuple(tx=0.0, ty=-0.6, tz=-1.4, s=0.01, sx=0.0, sy=0.0, sz=0.02)
1685# 52 ITRF2000@1988xITRF92 xform=TRFXform7Tuple(tx=1.47, ty=1.35, tz=-1.39, s=0.75, sx=0.0, sy=0.0, sz=-0.18)
1686# rates=TRFXform7Tuple(tx=0.0, ty=-0.06, tz=-0.14, s=0.01, sx=0.0, sy=0.0, sz=0.02)
1687# 53 ITRF2000@1988xITRF93 xform=TRFXform7Tuple(tx=12.7, ty=6.5, tz=-20.9, s=1.95, sx=-0.39, sy=0.8, sz=-1.14)
1688# rates=TRFXform7Tuple(tx=-2.9, ty=-0.2, tz=-0.6, s=0.01, sx=-0.11, sy=-0.19, sz=0.07)
1689# 54 ITRF2000@1997xITRF94 xform=TRFXform7Tuple(tx=0.67, ty=0.61, tz=-1.85, s=1.55, sx=0.0, sy=0.0, sz=0.0)
1690# rates=TRFXform7Tuple(tx=0.0, ty=-0.06, tz=-0.14, s=0.01, sx=0.0, sy=0.0, sz=0.02)
1691# 55 ITRF2000@1997xITRF96 xform=TRFXform7Tuple(tx=0.67, ty=0.61, tz=-1.85, s=1.55, sx=0.0, sy=0.0, sz=0.0)
1692# rates=TRFXform7Tuple(tx=0.0, ty=-0.06, tz=-0.14, s=0.01, sx=0.0, sy=0.0, sz=0.02)
1693# 56 ITRF97@1997xITRF96 xform=TRFXform7Tuple(tx=-2.07, ty=-0.21, tz=9.95, s=-0.93496, sx=0.1267, sy=-0.22355, sz=-0.06065)
1694# rates=TRFXform7Tuple(tx=0.69, ty=-0.1, tz=1.86, s=-0.19201, sx=0.01347, sy=-0.01514, sz=0.00027)
1695# 57 ITRF2000@1997xITRF97 xform=TRFXform7Tuple(tx=0.67, ty=0.61, tz=-1.85, s=1.55, sx=0.0, sy=0.0, sz=0.0)
1696# rates=TRFXform7Tuple(tx=0.0, ty=-0.06, tz=-0.14, s=0.01, sx=0.0, sy=0.0, sz=-0.02)
1697# 58 ITRF2000@1997xNAD83 xform=TRFXform7Tuple(tx=995.6, ty=-1901.3, tz=-521.5, s=0.615, sx=-25.915, sy=-9.426, sz=-11.599)
1698# rates=TRFXform7Tuple(tx=0.7, ty=-0.7, tz=0.5, s=-0.182, sx=-0.06667, sy=0.75744, sz=0.05133)
1699# 59 ITRF2005@1997xNAD83 xform=TRFXform7Tuple(tx=996.3, ty=-1902.4, tz=-521.9, s=0.775, sx=-25.915, sy=-9.426, sz=-11.599)
1700# rates=TRFXform7Tuple(tx=0.5, ty=-0.6, tz=-1.3, s=-0.10201, sx=-0.06667, sy=0.75744, sz=0.05133)
1701# 60 ITRF96@1997xNAD83 xform=TRFXform7Tuple(tx=991.0, ty=-190.72, tz=-512.9, s=0.0, sx=25.79, sy=9.65, sz=11.66)
1702# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.0532, sy=-0.7423, sz=-0.0316)
1703# 61 ITRF2005@2020xGDA2020 xform=TRFXform7Tuple(tx=40.32, ty=-33.85, tz=-16.72, s=4.286, sx=-1.2893, sy=-0.8492, sz=-0.3342)
1704# rates=TRFXform7Tuple(tx=2.25, ty=-0.62, tz=-0.56, s=0.294, sx=-1.4707, sy=-1.1443, sz=-1.1701)
1705# 62 ITRF2005@2000xITRF2000 xform=TRFXform7Tuple(tx=0.1, ty=-0.8, tz=-5.8, s=0.4, sx=0.0, sy=0.0, sz=0.0)
1706# rates=TRFXform7Tuple(tx=-0.2, ty=0.1, tz=-1.8, s=0.08, sx=0.0, sy=0.0, sz=0.0)
1707# 63 ITRF2008@1994xGDA94 xform=TRFXform7Tuple(tx=-84.68, ty=-19.42, tz=32.01, s=9.71, sx=-0.4254, sy=2.2578, sz=2.4015)
1708# rates=TRFXform7Tuple(tx=1.42, ty=1.34, tz=0.9, s=0.109, sx=1.5461, sy=1.182, sz=1.1551)
1709# 64 ITRF2008@1997xNAD83 xform=TRFXform7Tuple(tx=993.43, ty=-1903.31, tz=-526.55, s=1.71504, sx=-25.91467, sy=-9.42645, sz=-11.59935)
1710# rates=TRFXform7Tuple(tx=0.79, ty=-0.6, tz=-1.34, s=-0.10201, sx=-0.06667, sy=0.75744, sz=0.05133)
1711# 65 ITRF2008@2015xETRF2000 xform=TRFXform7Tuple(tx=53.6, ty=50.8, tz=-85.5, s=2.54, sx=2.106, sy=12.74, sz=-20.592)
1712# rates=TRFXform7Tuple(tx=0.1, ty=0.1, tz=-1.8, s=0.08, sx=0.081, sy=0.49, sz=-0.792)
1713# 66 ITRF2008@2015xETRF2014 xform=TRFXform7Tuple(tx=-1.6, ty=-1.9, tz=-1.9, s=-0.13, sx=2.21, sy=13.806, sz=-20.02)
1714# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.1, s=-0.03, sx=0.085, sy=0.531, sz=-0.77)
1715# 67 ITRF2008@2015xETRF2020 xform=TRFXform7Tuple(tx=3.0, ty=2.8, tz=0.5, s=0.55, sx=2.236, sy=13.494, sz=-19.578)
1716# rates=TRFXform7Tuple(tx=0.0, ty=0.1, tz=-0.3, s=0.03, sx=0.086, sy=0.519, sz=-0.753)
1717# 68 ITRF2008@2020xGDA2020 xform=TRFXform7Tuple(tx=13.79, ty=4.55, tz=15.22, s=2.5, sx=0.2808, sy=0.2677, sz=-0.4638)
1718# rates=TRFXform7Tuple(tx=1.42, ty=1.34, tz=0.9, s=0.109, sx=1.5461, sy=1.182, sz=1.1551)
1719# 69 ITRF2008@2000xITRF2000 xform=TRFXform7Tuple(tx=-1.9, ty=-1.7, tz=-10.5, s=1.34, sx=0.0, sy=0.0, sz=0.0)
1720# rates=TRFXform7Tuple(tx=0.1, ty=0.1, tz=-1.8, s=0.08, sx=0.0, sy=0.0, sz=0.0)
1721# 70 ITRF2008@2000xITRF88 xform=TRFXform7Tuple(tx=22.8, ty=2.6, tz=-125.2, s=10.41, sx=0.1, sy=0.0, sz=0.06)
1722# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.2, s=0.09, sx=0.0, sy=0.0, sz=0.02)
1723# 71 ITRF2008@2000xITRF89 xform=TRFXform7Tuple(tx=27.8, ty=38.6, tz=-101.2, s=7.31, sx=0.0, sy=0.0, sz=0.06)
1724# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.2, s=0.09, sx=0.0, sy=0.0, sz=0.02)
1725# 72 ITRF2008@2000xITRF90 xform=TRFXform7Tuple(tx=22.8, ty=14.6, tz=-63.2, s=3.91, sx=0.0, sy=0.0, sz=0.06)
1726# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.2, s=0.09, sx=0.0, sy=0.0, sz=0.02)
1727# 73 ITRF2008@2000xITRF91 xform=TRFXform7Tuple(tx=24.8, ty=18.6, tz=-47.2, s=3.61, sx=0.0, sy=0.0, sz=0.06)
1728# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.2, s=0.09, sx=0.0, sy=0.0, sz=0.02)
1729# 74 ITRF2008@2000xITRF92 xform=TRFXform7Tuple(tx=12.8, ty=4.6, tz=-41.2, s=2.21, sx=0.0, sy=0.0, sz=0.06)
1730# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.2, s=0.09, sx=0.0, sy=0.0, sz=0.02)
1731# 75 ITRF2008@2000xITRF93 xform=TRFXform7Tuple(tx=-24.0, ty=2.4, tz=-38.6, s=3.41, sx=-1.71, sy=-1.48, sz=-0.3)
1732# rates=TRFXform7Tuple(tx=-2.8, ty=-0.1, tz=-2.4, s=0.09, sx=-0.11, sy=-0.19, sz=0.07)
1733# 76 ITRF2008@2000xITRF94 xform=TRFXform7Tuple(tx=4.8, ty=2.6, tz=-33.2, s=2.92, sx=0.0, sy=0.0, sz=0.06)
1734# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.2, s=0.09, sx=0.0, sy=0.0, sz=0.02)
1735# 77 ITRF2008@2000xITRF96 xform=TRFXform7Tuple(tx=4.8, ty=2.6, tz=-33.2, s=2.92, sx=0.0, sy=0.0, sz=0.06)
1736# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.2, s=0.09, sx=0.0, sy=0.0, sz=0.02)
1737# 78 ITRF2008@2000xITRF97 xform=TRFXform7Tuple(tx=4.8, ty=2.6, tz=-33.2, s=2.92, sx=0.0, sy=0.0, sz=0.06)
1738# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.2, s=0.09, sx=0.0, sy=0.0, sz=0.02)
1739# 79 ITRF2008@2005xITRF2005 xform=TRFXform7Tuple(tx=-0.5, ty=-0.9, tz=-4.7, s=0.94, sx=0.0, sy=0.0, sz=0.0)
1740# rates=TRFXform7Tuple(tx=0.3, ty=0.0, tz=0.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1741# 80 ITRF2014@2015xETRF2000 xform=TRFXform7Tuple(tx=55.2, ty=52.7, tz=-83.6, s=2.67, sx=2.106, sy=12.74, sz=-20.592)
1742# rates=TRFXform7Tuple(tx=0.1, ty=0.1, tz=-1.9, s=0.11, sx=0.081, sy=0.49, sz=-0.792)
1743# 81 ITRF2014@2015xETRF2014 xform=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=2.21, sy=13.806, sz=-20.02)
1744# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.085, sy=0.531, sz=-0.77)
1745# 82 ITRF2014@2015xETRF2020 xform=TRFXform7Tuple(tx=1.4, ty=0.9, tz=-1.4, s=0.42, sx=2.236, sy=13.494, sz=-19.578)
1746# rates=TRFXform7Tuple(tx=0.0, ty=0.1, tz=-0.2, s=0.0, sx=0.086, sy=0.519, sz=-0.753)
1747# 83 ITRF2014@2020xGDA2020 xform=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1748# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=1.50379, sy=1.18346, sz=1.20716)
1749# 84 ITRF2014@2010xITRF2000 xform=TRFXform7Tuple(tx=0.7, ty=1.2, tz=-26.1, s=2.12, sx=0.0, sy=0.0, sz=0.0)
1750# rates=TRFXform7Tuple(tx=0.1, ty=0.1, tz=-1.9, s=0.11, sx=0.0, sy=0.0, sz=0.0)
1751# 85 ITRF2014@2010xITRF2005 xform=TRFXform7Tuple(tx=2.6, ty=1.0, tz=-2.3, s=0.92, sx=0.0, sy=0.0, sz=0.0)
1752# rates=TRFXform7Tuple(tx=0.3, ty=0.0, tz=-0.1, s=0.03, sx=0.0, sy=0.0, sz=0.0)
1753# 86 ITRF2014@2010xITRF2008 xform=TRFXform7Tuple(tx=1.6, ty=1.9, tz=2.4, s=-0.02, sx=0.0, sy=0.0, sz=0.0)
1754# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=-0.1, s=0.03, sx=0.0, sy=0.0, sz=0.0)
1755# 87 ITRF2014@2010xITRF88 xform=TRFXform7Tuple(tx=25.4, ty=-0.5, tz=-154.8, s=11.29, sx=0.1, sy=0.0, sz=0.26)
1756# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.3, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1757# 88 ITRF2014@2010xITRF89 xform=TRFXform7Tuple(tx=30.4, ty=35.5, tz=-130.8, s=8.19, sx=0.0, sy=0.0, sz=0.26)
1758# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.3, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1759# 89 ITRF2014@2010xITRF90 xform=TRFXform7Tuple(tx=25.4, ty=11.5, tz=-92.8, s=4.79, sx=0.0, sy=0.0, sz=0.26)
1760# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.3, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1761# 90 ITRF2014@2010xITRF91 xform=TRFXform7Tuple(tx=27.4, ty=15.5, tz=-76.8, s=4.49, sx=0.0, sy=0.0, sz=0.26)
1762# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.3, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1763# 91 ITRF2014@2010xITRF92 xform=TRFXform7Tuple(tx=15.4, ty=1.5, tz=-70.8, s=3.09, sx=0.0, sy=0.0, sz=0.26)
1764# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.3, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1765# 92 ITRF2014@2010xITRF93 xform=TRFXform7Tuple(tx=-50.4, ty=3.3, tz=-60.2, s=4.29, sx=-2.81, sy=-3.38, sz=0.4)
1766# rates=TRFXform7Tuple(tx=-2.8, ty=-0.1, tz=-2.5, s=0.12, sx=-0.11, sy=-0.19, sz=0.07)
1767# 93 ITRF2014@2010xITRF94 xform=TRFXform7Tuple(tx=7.4, ty=-0.5, tz=-62.8, s=3.8, sx=0.0, sy=0.0, sz=0.26)
1768# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.3, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1769# 94 ITRF2014@2010xITRF96 xform=TRFXform7Tuple(tx=7.4, ty=-0.5, tz=-62.8, s=3.8, sx=0.0, sy=0.0, sz=0.26)
1770# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.3, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1771# 95 ITRF2014@2010xITRF97 xform=TRFXform7Tuple(tx=7.4, ty=-0.5, tz=-62.8, s=3.8, sx=0.0, sy=0.0, sz=0.26)
1772# rates=TRFXform7Tuple(tx=0.1, ty=-0.5, tz=-3.3, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1773# 96 ITRF2020@2015xETRF2000 xform=TRFXform7Tuple(tx=53.8, ty=51.8, tz=-82.2, s=2.25, sx=2.106, sy=12.74, sz=-20.592)
1774# rates=TRFXform7Tuple(tx=0.1, ty=0.0, tz=-1.7, s=0.11, sx=0.081, sy=0.49, sz=-0.792)
1775# 97 ITRF2020@2015xETRF2014 xform=TRFXform7Tuple(tx=-1.4, ty=-0.9, tz=1.4, s=0.42, sx=2.21, sy=13.806, sz=-20.02)
1776# rates=TRFXform7Tuple(tx=0.0, ty=-0.1, tz=0.2, s=0.0, sx=0.085, sy=0.531, sz=-0.77)
1777# 98 ITRF2020@2015xETRF2020 xform=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=2.236, sy=13.494, sz=-19.578)
1778# rates=TRFXform7Tuple(tx=0.0, ty=0.0, tz=0.0, s=0.0, sx=0.086, sy=0.519, sz=-0.753)
1779# 99 ITRF2020@2015xITRF2000 xform=TRFXform7Tuple(tx=-0.2, ty=0.8, tz=-34.2, s=2.25, sx=0.0, sy=0.0, sz=0.0)
1780# rates=TRFXform7Tuple(tx=0.1, ty=0.0, tz=-1.7, s=0.11, sx=0.0, sy=0.0, sz=0.0)
1781# 100 ITRF2020@2015xITRF2005 xform=TRFXform7Tuple(tx=2.7, ty=0.1, tz=-1.4, s=0.65, sx=0.0, sy=0.0, sz=0.0)
1782# rates=TRFXform7Tuple(tx=0.3, ty=-0.1, tz=0.1, s=0.03, sx=0.0, sy=0.0, sz=0.0)
1783# 101 ITRF2020@2015xITRF2008 xform=TRFXform7Tuple(tx=0.2, ty=1.0, tz=3.3, s=-0.29, sx=0.0, sy=0.0, sz=0.0)
1784# rates=TRFXform7Tuple(tx=0.0, ty=-0.1, tz=0.1, s=0.03, sx=0.0, sy=0.0, sz=0.0)
1785# 102 ITRF2020@2015xITRF2014 xform=TRFXform7Tuple(tx=-1.4, ty=-0.9, tz=1.4, s=-0.42, sx=0.0, sy=0.0, sz=0.0)
1786# rates=TRFXform7Tuple(tx=0.0, ty=-0.1, tz=0.2, s=0.0, sx=0.0, sy=0.0, sz=0.0)
1787# 103 ITRF2020@2015xITRF88 xform=TRFXform7Tuple(tx=24.5, ty=-3.9, tz=-169.9, s=11.47, sx=0.1, sy=0.0, sz=0.36)
1788# rates=TRFXform7Tuple(tx=0.1, ty=-0.6, tz=-3.1, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1789# 104 ITRF2020@2015xITRF89 xform=TRFXform7Tuple(tx=29.5, ty=32.1, tz=-145.9, s=8.37, sx=0.0, sy=0.0, sz=0.36)
1790# rates=TRFXform7Tuple(tx=0.1, ty=-0.6, tz=-3.1, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1791# 105 ITRF2020@2015xITRF90 xform=TRFXform7Tuple(tx=24.5, ty=8.1, tz=-107.9, s=4.97, sx=0.0, sy=0.0, sz=0.36)
1792# rates=TRFXform7Tuple(tx=0.1, ty=-0.6, tz=-3.1, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1793# 106 ITRF2020@2015xITRF91 xform=TRFXform7Tuple(tx=26.5, ty=12.1, tz=-91.9, s=4.67, sx=0.0, sy=0.0, sz=0.36)
1794# rates=TRFXform7Tuple(tx=0.1, ty=-0.6, tz=-3.1, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1795# 107 ITRF2020@2015xITRF92 xform=TRFXform7Tuple(tx=14.5, ty=-1.9, tz=-85.9, s=3.27, sx=0.0, sy=0.0, sz=0.36)
1796# rates=TRFXform7Tuple(tx=0.1, ty=-0.6, tz=-3.1, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1797# 108 ITRF2020@2015xITRF93 xform=TRFXform7Tuple(tx=-65.8, ty=1.9, tz=-71.3, s=4.47, sx=-3.36, sy=-4.33, sz=0.75)
1798# rates=TRFXform7Tuple(tx=-2.8, ty=-0.2, tz=-2.3, s=0.12, sx=-0.11, sy=-0.19, sz=0.07)
1799# 109 ITRF2020@2015xITRF94 xform=TRFXform7Tuple(tx=6.5, ty=-3.9, tz=-77.9, s=3.98, sx=0.0, sy=0.0, sz=0.36)
1800# rates=TRFXform7Tuple(tx=0.1, ty=-0.6, tz=-3.1, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1801# 110 ITRF2020@2015xITRF96 xform=TRFXform7Tuple(tx=6.5, ty=-3.9, tz=-77.9, s=3.98, sx=0.0, sy=0.0, sz=0.36)
1802# rates=TRFXform7Tuple(tx=0.1, ty=-0.6, tz=-3.1, s=0.12, sx=0.0, sy=0.0, sz=0.02)
1803# 111 ITRF2020@2015xITRF97 xform=TRFXform7Tuple(tx=6.5, ty=-3.9, tz=-77.9, s=3.98, sx=0.0, sy=0.0, sz=0.36)
1804# rates=TRFXform7Tuple(tx=0.1, ty=-0.6, tz=-3.1, s=0.12, sx=0.0, sy=0.0, sz=0.02)