Coverage for pygeodesy/trf.py: 96%
254 statements
« prev ^ index » next coverage.py v7.2.2, created at 2024-01-26 16:28 -0500
« prev ^ index » next coverage.py v7.2.2, created at 2024-01-26 16:28 -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.ETRF88: RefFrame(name='ETRF88', epoch=1988, datum=Datums.GRS80)
35@var RefFrames.ETRF89: RefFrame(name='ETRF89', epoch=1989, datum=Datums.GRS80)
36@var RefFrames.ETRF90: RefFrame(name='ETRF90', epoch=1990, datum=Datums.GRS80)
37@var RefFrames.ETRF91: RefFrame(name='ETRF91', epoch=1991, datum=Datums.GRS80)
38@var RefFrames.ETRF92: RefFrame(name='ETRF92', epoch=1992, datum=Datums.GRS80)
39@var RefFrames.ETRF93: RefFrame(name='ETRF93', epoch=1993, datum=Datums.GRS80)
40@var RefFrames.ETRF94: RefFrame(name='ETRF94', epoch=1994, datum=Datums.GRS80)
41@var RefFrames.ETRF96: RefFrame(name='ETRF96', epoch=1996, datum=Datums.GRS80)
42@var RefFrames.ETRF97: RefFrame(name='ETRF97', epoch=1997, datum=Datums.GRS80)
43@var RefFrames.ETRF2000: RefFrame(name='ETRF2000', epoch=2005, datum=Datums.GRS80)
44@var RefFrames.ETRF2005: RefFrame(name='ETRF2005', epoch=2005, datum=Datums.GRS80)
45@var RefFrames.ETRF2008: RefFrame(name='ETRF2008', epoch=2008, datum=Datums.GRS80)
46@var RefFrames.ETRF2014: RefFrame(name='ETRF2014', epoch=2014, datum=Datums.GRS80)
47@var RefFrames.GDA94: RefFrame(name='GDA94', epoch=1994, datum=Datums.GRS80)
48@var RefFrames.GDA2020: RefFrame(name='GDA2020', epoch=2020, datum=Datums.GRS80)
49@var RefFrames.ITRF88: RefFrame(name='ITRF88', epoch=1988, datum=Datums.GRS80)
50@var RefFrames.ITRF89: RefFrame(name='ITRF89', epoch=1989, datum=Datums.GRS80)
51@var RefFrames.ITRF90: RefFrame(name='ITRF90', epoch=1988, datum=Datums.GRS80)
52@var RefFrames.ITRF91: RefFrame(name='ITRF91', epoch=1988, datum=Datums.GRS80)
53@var RefFrames.ITRF92: RefFrame(name='ITRF92', epoch=1988, datum=Datums.GRS80)
54@var RefFrames.ITRF93: RefFrame(name='ITRF93', epoch=1988, datum=Datums.GRS80)
55@var RefFrames.ITRF94: RefFrame(name='ITRF94', epoch=1993, datum=Datums.GRS80)
56@var RefFrames.ITRF96: RefFrame(name='ITRF96', epoch=1997, datum=Datums.GRS80)
57@var RefFrames.ITRF97: RefFrame(name='ITRF97', epoch=1997, datum=Datums.GRS80)
58@var RefFrames.ITRF2000: RefFrame(name='ITRF2000', epoch=1997, datum=Datums.GRS80)
59@var RefFrames.ITRF2005: RefFrame(name='ITRF2005', epoch=2000, datum=Datums.GRS80)
60@var RefFrames.ITRF2008: RefFrame(name='ITRF2008', epoch=2005, datum=Datums.GRS80)
61@var RefFrames.ITRF2014: RefFrame(name='ITRF2014', epoch=2010, datum=Datums.GRS80)
62@var RefFrames.ITRF2020: RefFrame(name='ITRF2020', epoch=2015, datum=Datums.GRS80)
63@var RefFrames.NAD83: RefFrame(name='NAD83', epoch=1997, datum=Datums.GRS80)
64@var RefFrames.WGS84: RefFrame(name='WGS84', epoch=1984, datum=Datums.GRS80)
65@var RefFrames.WGS84g1150: RefFrame(name='WGS84g1150', epoch=2001, datum=Datums.GRS80)
66@var RefFrames.WGS84g1674: RefFrame(name='WGS84g1674', epoch=2005, datum=Datums.GRS80)
67@var RefFrames.WGS84g1762: RefFrame(name='WGS84g1762', epoch=2005, datum=Datums.GRS80)
68'''
70from pygeodesy.basics import map1, isstr, _xinstanceof, _zip
71from pygeodesy.constants import _float as _F, _0_0, _0_001, _0_5, _1_0
72from pygeodesy.datums import Datums, _earth_datum, Transform, _WGS84
73from pygeodesy.errors import _IsnotError, TRFError
74from pygeodesy.interns import MISSING, NN, _AT_, _COMMASPACE_, _cartesian_, _conversion_, \
75 _datum_, _DOT_, _ellipsoidal_, _exists_, _NAD83_, _no_, \
76 _reframe_, _s_, _SPACE_, _sx_, _sy_, _sz_, _to_, _tx_, _ty_, \
77 _tz_, _WGS84_, _intern as _i
78from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
79from pygeodesy.named import classname, _lazyNamedEnumItem as _lazy, _NamedDict as _XD, \
80 _NamedEnum, _NamedEnumItem, _NamedTuple, Fmt
81from pygeodesy.props import Property_RO, property_RO
82# from pygeodesy.streprs import Fmt # from .named
83from pygeodesy.units import Epoch, Float
85from math import ceil
87__all__ = _ALL_LAZY.trf
88__version__ = '24.01.25'
90_366_0 = 366.0
91_Forward = _0_001 # mm2m, ppb2ppM, mas2as
92_GRS80 = Datums.GRS80
93_Inverse = -_0_001 # same, inverse transforms
94_mas = _mm = _ppb = Float # as == arcseconds
95_mDays = (0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0)
97_ETRF88_ = _i('ETRF88')
98_ETRF89_ = _i('ETRF89')
99_ETRF90_ = _i('ETRF90')
100_ETRF91_ = _i('ETRF91')
101_ETRF92_ = _i('ETRF92')
102_ETRF93_ = _i('ETRF93')
103_ETRF94_ = _i('ETRF94')
104_ETRF96_ = _i('ETRF96')
105_ETRF97_ = _i('ETRF97')
106_ETRF2000_ = _i('ETRF2000')
107_ETRF2005_ = _i('ETRF2005')
108_ETRF2008_ = _i('ETRF2008')
109_ETRF2014_ = _i('ETRF2014')
110_GDA94_ = _i('GDA94')
111_GDA2020_ = _i('GDA2020')
112_ITRF_ = _i('ITRF')
113_ITRF88_ = _i('ITRF88')
114_ITRF89_ = _i('ITRF89')
115_ITRF90_ = _i('ITRF90')
116_ITRF91_ = _i('ITRF91')
117_ITRF92_ = _i('ITRF92')
118_ITRF93_ = _i('ITRF93')
119_ITRF94_ = _i('ITRF94')
120_ITRF96_ = _i('ITRF96')
121_ITRF97_ = _i('ITRF97')
122_ITRF2000_ = _i('ITRF2000')
123_ITRF2005_ = _i('ITRF2005')
124_ITRF2008_ = _i('ITRF2008')
125_ITRF2014_ = _i('ITRF2014')
126_ITRF2020_ = _i('ITRF2020')
127_WGS84g1150_ = _i('WGS84g1150')
128_WGS84g1674_ = _i('WGS84g1674')
129_WGS84g1762_ = _i('WGS84g1762')
130# del _i
133class Helmert7Tuple(_NamedTuple):
134 '''7-Tuple C{(tx, ty, tz, s, sx, sy, sz)} of Helmert transform
135 parameters with translations C{tx}, C{ty} and C{tz} in
136 C{millimeter}, scale C{s} in C{ppb} and rotations C{sx},
137 C{sy} and C{sz} in C{milli-arc-seconds}.
139 @note: The parameters names are often capitalized and
140 alternate names are C{(Tx, Ty, Tz, D, Rx, Ry, Rz)}
141 and C{(T1, T2, T3, D, R1, R2, R3)}.
143 @see: L{Datum} L{Transform} keyword arguments.
144 '''
145 _Names_ = (_tx_, _ty_, _tz_, _s_, _sx_, _sy_, _sz_) # == kwds
146 _Units_ = (_mm, _mm, _mm, _ppb, _mas, _mas, _mas)
148 def __new__(cls, tx, ty, tz, s, sx, sy, sz, name=NN):
149 '''New L{Helmert7Tuple}.
150 '''
151 t = map1(_F, tx, ty, tz, s, sx, sy, sz)
152 return _NamedTuple.__new__(cls, *t, name=name)
155class RefFrame(_NamedEnumItem):
156 '''Terrestrial Reference Frame (TRF) parameters.
157 '''
158 _datum = _GRS80 # Datums.GRS80 or .WGS84 (L{Datum})
159 _epoch = _0_0 # epoch, calendar year (L{Epoch} or C{float})
161 def __init__(self, epoch, datum, name=NN):
162 '''New L{RefFrame}.
164 @arg epoch: Epoch, a fractional calendar year (C{scalar} or C{str}).
165 @arg datum: Datum or ellipsoid (L{Datum}, {Ellipsoid}, L{Ellipsoid2}
166 or L{a_f2Tuple}).
167 @kwarg name: Unique, non-empty name (C{str}).
169 @raise NameError: A L{RefFrame} with that B{C{name}} already exists.
171 @raise TRFError: Invalid B{C{epoch}}.
173 @raise TypeError: Invalid B{C{datum}}.
174 '''
175 if datum is not _GRS80:
176 _earth_datum(self, datum, raiser=_datum_)
177 self._epoch = Epoch(epoch)
178 self._register(RefFrames, name)
180 def __matmul__(self, other): # PYCHOK Python 3.5+
181 '''Convert cartesian or ellipsoidal B{C{other}} to this reframe.
183 @raise TypeError: Invalid B{C{other}}.
184 '''
185 try: # only Cartesian- and LatLonEllipsoidalBase
186 return other.toRefFrame(self)
187 except AttributeError:
188 pass
189 raise _IsnotError(_cartesian_, _ellipsoidal_, other=other)
191 @property_RO
192 def datum(self):
193 '''Get this reference frame's datum (L{Datum}).
194 '''
195 return self._datum
197 @Property_RO
198 def ellipsoid(self):
199 '''Get this reference frame's ellipsoid (L{Ellipsoid} or L{Ellipsoid2}).
200 '''
201 return self._datum.ellipsoid
203 @Property_RO
204 def epoch(self):
205 '''Get this reference frame's epoch (C{Epoch}).
206 '''
207 return self._epoch
209 def toRefFrame(self, point, reframe2, epoch2=None, epoch=None, name=NN):
210 '''Convert a cartesian or geodetic point from this to another reframe and epoch.
212 @return: A copy of the B{C{point}}, converted or renamed.
214 @see: Ellipsoidal methods L{LatLon.toRefFrame<ellipsoidalBase.LatLonEllipsoidalBase.toRefFrame>}
215 and L{Cartesian.toRefFrame<ellipsoidalBase.CartesianEllipsoidalBase.toRefFrame>}
216 for more details.
217 '''
218 b = _MODS.ellipsoidalBase
219 _xinstanceof(b.LatLonEllipsoidalBase, b.CartesianEllipsoidalBase, point=point)
220 r = point.dup(reframe=self)
221 return r.toRefFrame(reframe2, epoch2=epoch2, epoch=epoch, name=name or self.name)
223 def toStr(self, epoch=None, name=NN, **unused): # PYCHOK expected
224 '''Return this reference frame as a text string.
226 @kwarg epoch: Override this reframe's epoch (C{scalar} or C{str}).
227 @kwarg name: Override name (C{str}) or C{None} to exclude the
228 reframe's name.
230 @return: This L{RefFrame}'s attributes (C{str}).
231 '''
232 D = self.datum
233 e = self.epoch if epoch is None else Epoch(epoch)
234 t = (Fmt.EQUAL(name=repr(name or self.name)),
235 Fmt.EQUAL(epoch=e),
236 Fmt.EQUAL(datum=_DOT_(classname(D) + _s_, D.name)))
237 return _COMMASPACE_.join(t[1:] if name is None else t)
240class RefFrames(_NamedEnum):
241 '''(INTERNAL) L{RefFrame} registry, I{must} be a sub-class
242 to accommodate the L{_LazyNamedEnumItem} properties.
243 '''
244 def _Lazy(self, epoch, datum=_GRS80, name=NN):
245 '''(INTERNAL) Instantiate the L{RefFrame}.
246 '''
247 return RefFrame(epoch, datum, name=name)
249RefFrames = RefFrames(RefFrame) # PYCHOK singleton
250'''Some pre-defined L{RefFrame}s, all I{lazily} instantiated.'''
251# <https://GitHub.com/ChrisVeness/geodesy/blob/master/latlon-ellipsoidal-referenceframe.js>
252RefFrames._assert(
253 ETRF88 = _lazy(_ETRF88_, _F(1988)), # epoch?
254 ETRF89 = _lazy(_ETRF89_, _F(1989)), # epoch?
255 ETRF90 = _lazy(_ETRF90_, _F(1990)), # epoch?
256 ETRF91 = _lazy(_ETRF91_, _F(1991)), # epoch?
257 ETRF92 = _lazy(_ETRF92_, _F(1992)), # epoch?
258 ETRF93 = _lazy(_ETRF93_, _F(1993)), # epoch?
259 ETRF94 = _lazy(_ETRF94_, _F(1994)), # epoch?
260 ETRF96 = _lazy(_ETRF96_, _F(1996)), # epoch?
261 ETRF97 = _lazy(_ETRF97_, _F(1997)), # epoch?
262 ETRF2000 = _lazy(_ETRF2000_, _F(2005)),
263 ETRF2005 = _lazy(_ETRF2005_, _F(2005)), # epoch?
264 ETRF2008 = _lazy(_ETRF2008_, _F(2008)), # epoch?
265 ETRF2014 = _lazy(_ETRF2014_, _F(2014)), # epoch?
266 GDA94 = _lazy(_GDA94_, _F(1994)), # Australia
267 GDA2020 = _lazy(_GDA2020_, _F(2020)), # Australia
268 ITRF88 = _lazy(_ITRF88_, _F(1988)),
269 ITRF89 = _lazy(_ITRF89_, _F(1989)),
270 ITRF90 = _lazy(_ITRF90_, _F(1988)),
271 ITRF91 = _lazy(_ITRF91_, _F(1988)),
272 ITRF92 = _lazy(_ITRF92_, _F(1988)),
273 ITRF93 = _lazy(_ITRF93_, _F(1988)),
274 ITRF94 = _lazy(_ITRF94_, _F(1993)),
275 ITRF96 = _lazy(_ITRF96_, _F(1997)),
276 ITRF97 = _lazy(_ITRF97_, _F(1997)),
277 ITRF2000 = _lazy(_ITRF2000_, _F(1997)),
278 ITRF2005 = _lazy(_ITRF2005_, _F(2000)),
279 ITRF2008 = _lazy(_ITRF2008_, _F(2005)), # aka ITRF08
280 ITRF2014 = _lazy(_ITRF2014_, _F(2010)),
281 ITRF2020 = _lazy(_ITRF2020_, _F(2015)),
282 NAD83 = _lazy(_NAD83_, _F(1997)), # CORS96
283 WGS84 = _lazy(_WGS84_, _F(1984), _WGS84),
284 WGS84g1150 = _lazy(_WGS84g1150_, _F(2001), _WGS84),
285 WGS84g1674 = _lazy(_WGS84g1674_, _F(2005), _WGS84),
286 WGS84g1762 = _lazy(_WGS84g1762_, _F(2005), _WGS84)) # same epoch
289def date2epoch(year, month, day):
290 '''Return the reference frame C{epoch} for a calendar day.
292 @arg year: Year of the date (C{scalar}).
293 @arg month: Month in the B{C{year}} (C{scalar}, 1..12).
294 @arg day: Day in the B{C{month}} (C{scalar}, 1..31).
296 @return: Epoch, the fractional year (C{float}).
298 @raise TRFError: Invalid B{C{year}}, B{C{month}} or B{C{day}}.
300 @note: Any B{C{year}} is considered a leap year, i.e. having
301 29 days in February.
302 '''
303 try:
304 y, m, d = map1(int, year, month, day)
305 if y > 0 and 1 <= m <= 12 and 1 <= d <= _mDays[m]:
306 return Epoch(y + float(sum(_mDays[:m]) + d) / _366_0, low=0)
308 raise ValueError # _invalid_
309 except (TRFError, TypeError, ValueError) as x:
310 raise TRFError(year=year, month=month, day=day, cause=x)
313def epoch2date(epoch):
314 '''Return the date for a reference frame C{epoch}.
316 @arg epoch: Fractional year (C{scalar}).
318 @return: 3-Tuple C{(year, month, day)}.
320 @raise TRFError: Invalid B{C{epoch}}.
322 @note: Any B{C{year}} is considered a leap year, i.e. having
323 29 days in February.
324 '''
325 e = Epoch(epoch, low=0)
326 y = int(e)
327 d = int(ceil(_366_0 * (e - y)))
328 for m, n in enumerate(_mDays[1:]):
329 if d > n:
330 d -= n
331 else:
332 break
333 return y, (m + 1), max(1, d)
336def _eTsDs4(inst, reframe, epoch, reframe2, epoch2):
337 '''(INTERNAL) Get epoch, a 0-, 1- or 2-tuple of Helmert L{Transform}s
338 datum and datum2 to convert B{C{refFrame}} observed at B{C{epoch}}
339 into B{C{refFrame2}} observed at B{C{epoch2 or epoch}}.
340 '''
341 r = reframe or inst.reframe
342 if not r:
343 t = _SPACE_(_DOT_(repr(inst), _reframe_), MISSING)
344 raise TRFError(_no_(_conversion_), txt=t)
346 _xinstanceof(RefFrame, reframe2=reframe2, reframe=r)
348 e1 = Epoch(epoch or inst.epoch or r.epoch)
349 e2 = e1 if epoch2 is None else Epoch(epoch2=epoch2)
351 xs = _2Transforms(r.name, e1, reframe2.name, e2)
352 if xs is None:
353 t = _SPACE_(RefFrame.__name__, repr(r.name), _AT_, e1,
354 _to_, repr(reframe2.name), _AT_, e2)
355 raise TRFError(_no_(_conversion_), txt=t)
357 return e2, xs, r.datum, reframe2.datum
360def _intermediate(n1, n2):
361 '''(INTERNAL) Find a trf* "between" C{n1} and C{n2}.
362 '''
363 f = set(m for n, m in _trfXs.keys() if n == n1) # from trf1
364 t = set(n for n, m in _trfXs.keys() if m == n2) # to trf2
365 n = f.intersection(t)
366 return n.pop() if n else NN
369def _2Transform(n1, n2, e, _Forward_Inverse):
370 '''(INTERNAL) Combine the TRF C{xform} and C{rates} from a
371 conversion C{_trfXs[(n1, n2)]} observed at C{B{e}poch}
372 into a single I{datum} L{Transform}.
374 @note: Translations are converted from C{millimeter} to C{meter},
375 rotations from C{milliarcseconds} to C{arcseconds} and
376 scale from C{ppb} to C{ppM}.
377 '''
378 X = _trfXs[(n1, n2)]
379 e -= X.epoch # delta in fractional years
380 d = dict((n, (x + e * r) * _Forward_Inverse) for n, x, r in
381 _zip(Helmert7Tuple._Names_, X.xform, X.rates)) # strict=True
382 return Transform(**d)
385def _2Transforms(n1, e1, n2, e2):
386 '''(INTERNAL) Get 0-, 1- or 2-tuple of Helmert L{Transform}s or C{None}.
387 '''
388 if n1 == n2 or (n1.startswith(_ITRF_) and n2.startswith(_WGS84_)) \
389 or (n2.startswith(_ITRF_) and n1.startswith(_WGS84_)):
390 return () # PYCHOK returns
391 if (n1, n2) in _trfXs:
392 return (_2Transform(n1, n2, e1, _Forward), # PYCHOK returns
393 _2Transform(n1, n2, e2, _Forward)) if e2 != e1 else \
394 (_2Transform(n1, n2, e2, _Forward),)
395 if (n2, n1) in _trfXs:
396 return (_2Transform(n2, n1, e1, _Inverse), # PYCHOK returns
397 _2Transform(n2, n1, e2, _Inverse)) if e2 != e1 else \
398 (_2Transform(n2, n1, e2, _Inverse),)
399 n = _intermediate(n1, n2)
400 if n:
401 return (_2Transform(n1, n, e1, _Forward), # PYCHOK returns
402 _2Transform(n, n2, e2, _Forward))
403 n = _intermediate(n2, n1)
404 if n:
405 return (_2Transform(n, n1, e1, _Inverse), # PYCHOK returns
406 _2Transform(n2, n, e2, _Inverse))
407 return None
410def trfTransforms(reframe, epoch, reframe2, epoch2):
411 '''Get the L{Transform}(s) to convert reframe at epoch to reframe2 at epoch2.
413 @arg reframe: Reference frame to convert I{from} (L{RefFrame} or C{str}).
414 @arg epoch: Epoch to observe I{from} (L{Epoch}, C{scalar} or C{str}).
415 @arg reframe2: Reference frame to convert I{to} (L{RefFrame} or C{str}).
416 @arg epoch2: Epoch to observe to observe I{to} (L{Epoch}, C{scalar} or C{str}).
418 @return: A 0-, 1- or 2-tuple of Helmert L{Transform}s or C{None} if no
419 conversion exists.
420 '''
421 _xinstanceof(RefFrame, str, reframe=reframe, reframe2=reframe2)
422 n1 = reframe.upper() if isstr(reframe) else reframe.name
423 n2 = reframe2.upper() if isstr(reframe2) else reframe2.name
424 return _2Transforms(n1, Epoch(epoch), n2, Epoch(epoch2=epoch2))
427def trfXform(reframe1, reframe2, epoch=None, xform=None, rates=None):
428 '''Define a new Terrestrial Reference Frame (TRF) conversion.
430 @arg reframe1: Source reframe (L{RefFrame}), converting I{from}.
431 @arg reframe2: Destination reframe (L{RefFrame}), converting I{to}.
432 @kwarg epoch: Epoch, a fractional calendar year (C{scalar} or C{str})
433 or C{None} for C{B{reframe2}.epoch}.
434 @kwarg xform: Helmert I{transform} parameters (C{Helmert7Tuple}).
435 @kwarg rates: Helmert I{rate} parameters (C{Helmert7Tuple}), like
436 B{C{xform}}, but in C{units per year}.
438 @raise TRFError: Invalid B{C{epoch}} or TRF conversion already exists.
439 '''
440 _xinstanceof(RefFrame, reframe1=reframe1, reframe2=reframe2)
441 e = reframe2.epoch if epoch is None else Epoch(epoch=epoch)
442 _xinstanceof(Helmert7Tuple, xform=xform, rates=rates)
443 _trfX(reframe1.name, reframe2.name, epoch=e, xform=xform, rates=rates)
446def _trfX(n1, n2, **epoch_xform_rates):
447 '''(INTERNAL) New C{_trfXs} entry.
448 '''
449 n1_n2 = n1, n2
450 if n1_n2 in _trfXs:
451 raise TRFError(trfX=n1_n2, txt=_exists_) # _NameError
452 _trfXs[n1_n2] = _XD(X=n1_n2, **epoch_xform_rates)
455def _H(*ps):
456 h = Helmert7Tuple(*ps)
457 return _Hs.setdefault(h, h) # PYCHOK del
459# TRF conversions specified as an epoch and dual 7-parameter Helmert transforms. Most from U{Transformation
460# Parameters<http://ITRF.IGN.Fr/trans_para.php>}, more at U{Quinsy QPS<https://confluence.QPS.NL/qinsy/
461# files/latest/en/182618383/182618384/1/1579182881000/ITRF_Transformation_Parameters.xlsx>}. See also
462# U{Quinsy International Terrestrial Reference Frame 2014 (ITRF2014)<https://confluence.QPS.NL/qinsy/
463# latest/en/international-terrestrial-reference-frame-2014-itrf2014-182618383.html>}.
464_Hs = dict() # PYCHOK unique HelmertTuples, temporary
465_trfXs = dict() # key is [(from_TRF, to_TRF)] 2-tuple
466_trfX(_ITRF2020_, _ITRF2014_, epoch=_F(2015), # <https://ITRF.IGN.Fr/docs/solutions/itrf2020/Transfo-ITRF2020_TRFs.txt>
467 xform=_H( -1.4, -0.9, 1.4, -0.42, _0_0, _0_0, _0_0),
468 rates=_H( _0_0, -0.1, 0.2, _0_0, _0_0, _0_0, _0_0))
469_trfX(_ITRF2020_, _ITRF2008_, epoch=_F(2015),
470 xform=_H( 0.2, 1.0, 3.3, -0.29, _0_0, _0_0, _0_0),
471 rates=_H( _0_0, -0.1, 0.1, 0.03, _0_0, _0_0, _0_0))
472_trfX(_ITRF2020_, _ITRF2005_, epoch=_F(2015),
473 xform=_H( 2.7, 0.1, -1.4, 0.65, _0_0, _0_0, _0_0),
474 rates=_H( 0.3, -0.1, 0.1, 0.03, _0_0, _0_0, _0_0))
475_trfX(_ITRF2020_, _ITRF2000_, epoch=_F(2015),
476 xform=_H( -0.2, 0.8, -34.2, 2.25, _0_0, _0_0, _0_0),
477 rates=_H( 0.1, _0_0, -1.7, 0.11, _0_0, _0_0, _0_0))
478_trfX(_ITRF2020_, _ITRF97_, epoch=_F(2015),
479 xform=_H( 6.5, -3.9, -77.9, 3.98, _0_0, _0_0, 0.36),
480 rates=_H( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
481_trfX(_ITRF2020_, _ITRF96_, epoch=_F(2015),
482 xform=_H( 6.5, -3.9, -77.9, 3.98, _0_0, _0_0, 0.36),
483 rates=_H( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
484_trfX(_ITRF2020_, _ITRF94_, epoch=_F(2015),
485 xform=_H( 6.5, -3.9, -77.9, 3.98, _0_0, _0_0, 0.36),
486 rates=_H( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
487_trfX(_ITRF2020_, _ITRF93_, epoch=_F(2015),
488 xform=_H( -65.8, 1.9, -71.3, 4.47, -3.36, -4.33, 0.75),
489 rates=_H( -2.8, -0.2, -2.3, 0.12, -0.11, -0.19, 0.07))
490_trfX(_ITRF2020_, _ITRF92_, epoch=_F(2015),
491 xform=_H( 14.5, -1.9, -85.9, 3.27, _0_0, _0_0, 0.36),
492 rates=_H( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
493_trfX(_ITRF2020_, _ITRF91_, epoch=_F(2015),
494 xform=_H( 26.5, 12.1, -91.9, 4.67, _0_0, _0_0, 0.36),
495 rates=_H( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
496_trfX(_ITRF2020_, _ITRF90_, epoch=_F(2015),
497 xform=_H( 24.5, 8.1, -107.9, 4.97, _0_0, _0_0, 0.36),
498 rates=_H( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
499_trfX(_ITRF2020_, _ITRF89_, epoch=_F(2015),
500 xform=_H( 29.5, 32.1, -145.9, 8.37, _0_0, _0_0, 0.36),
501 rates=_H( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
502_trfX(_ITRF2020_, _ITRF88_, epoch=_F(2015),
503 xform=_H( 24.5, -3.9, -169.9, 11.47, 0.1, _0_0, 0.36),
504 rates=_H( 0.1, -0.6, -3.1, 0.12, _0_0, _0_0, 0.02))
506# see U{Transformation Parameters ITRF2014<http://ITRF.IGN.Fr/doc_ITRF/Transfo-ITRF2014_ITRFs.txt>} and
507# Altamimi, Z. U{"EUREF Technical Note 1: Relationship and Transformation between the International and
508# the European Terrestrial Reference Systems"<https://ERTS89.ENSG,IFN.Fr/pub/EUREF-TN-1.pdf>} Appendix A.
509_trfX(_ITRF2014_, _ITRF2008_, epoch=_F(2010), # <http://ITRF.ENSG.IGN.Fr/ITRF_solutions/2014/tp_14-08.php>
510 xform=_H( 1.6, 1.9, 2.4, -0.02, _0_0, _0_0, _0_0),
511 rates=_H( _0_0, _0_0, -0.1, 0.03, _0_0, _0_0, _0_0))
512_trfX(_ITRF2014_, _ITRF2005_, epoch=_F(2010),
513 xform=_H( 2.6, _1_0, -2.3, 0.92, _0_0, _0_0, _0_0),
514 rates=_H( 0.3, _0_0, -0.1, 0.03, _0_0, _0_0, _0_0))
515_trfX(_ITRF2014_, _ITRF2000_, epoch=_F(2010),
516 xform=_H( 0.7, 1.2, -26.1, 2.12, _0_0, _0_0, _0_0),
517 rates=_H( 0.1, 0.1, -1.9, 0.11, _0_0, _0_0, _0_0))
518_trfX(_ITRF2014_, _ITRF97_, epoch=_F(2010),
519 xform=_H( 7.4, -0.5, -62.8, 3.8, _0_0, _0_0, 0.26),
520 rates=_H( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
521_trfX(_ITRF2014_, _ITRF96_, epoch=_F(2010),
522 xform=_H( 7.4, -0.5, -62.8, 3.8, _0_0, _0_0, 0.26),
523 rates=_H( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
524_trfX(_ITRF2014_, _ITRF94_, epoch=_F(2010),
525 xform=_H( 7.4, -0.5, -62.8, 3.8, _0_0, _0_0, 0.26),
526 rates=_H( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
527_trfX(_ITRF2014_, _ITRF93_, epoch=_F(2010),
528 xform=_H( -50.4, 3.3, -60.2, 4.29, -2.81, -3.38, 0.4),
529 rates=_H( -2.8, -0.1, -2.5, 0.12, -0.11, -0.19, 0.07))
530_trfX(_ITRF2014_, _ITRF92_, epoch=_F(2010),
531 xform=_H( 15.4, 1.5, -70.8, 3.09, _0_0, _0_0, 0.26),
532 rates=_H( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
533_trfX(_ITRF2014_, _ITRF91_, epoch=_F(2010),
534 xform=_H( 27.4, 15.5, -76.8, 4.49, _0_0, _0_0, 0.26),
535 rates=_H( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
536_trfX(_ITRF2014_, _ITRF90_, epoch=_F(2010),
537 xform=_H( 25.4, 11.5, -92.8, 4.79, _0_0, _0_0, 0.26),
538 rates=_H( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
539_trfX(_ITRF2014_, _ITRF89_, epoch=_F(2010),
540 xform=_H( 30.4, 35.5, -130.8, 8.19, _0_0, _0_0, 0.26),
541 rates=_H( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
542_trfX(_ITRF2014_, _ITRF88_, epoch=_F(2010),
543 xform=_H( 25.4, -0.5, -154.8, 11.29, 0.1, _0_0, 0.26),
544 rates=_H( 0.1, -0.5, -3.3, 0.12, _0_0, _0_0, 0.02))
546# see U{Transformation Parameters ITRF2008<http://ITRF.IGN.Fr/doc_ITRF/Transfo-ITRF2008_ITRFs.txt>}
547# _trfX(_ITRF2008_, _ITRF2005_, epoch=_F(2005), # <http://ITRF.ENSG.IGN.Fr/ITRF_solutions/2008/tp_08-05.php>
548# xform=_H( -0.5, s -0.9, -4.7, 0.94, _0_0, _0_0, _0_0),
549# rates=_H( 0.3, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0))
550_trfX(_ITRF2008_, _ITRF2005_, epoch=_F(2000),
551 xform=_H( -2.0, -0.9, -4.7, 0.94, _0_0, _0_0, _0_0),
552 rates=_H( 0.3, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0))
553_trfX(_ITRF2008_, _ITRF2000_, epoch=_F(2000),
554 xform=_H( -1.9, -1.7, -10.5, 1.34, _0_0, _0_0, _0_0),
555 rates=_H( 0.1, 0.1, -1.8, 0.08, _0_0, _0_0, _0_0))
556_trfX(_ITRF2008_, _ITRF97_, epoch=_F(2000),
557 xform=_H( 4.8, 2.6, -33.2, 2.92, _0_0, _0_0, 0.06),
558 rates=_H( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
559_trfX(_ITRF2008_, _ITRF96_, epoch=_F(2000),
560 xform=_H( 4.8, 2.6, -33.2, 2.92, _0_0, _0_0, 0.06),
561 rates=_H( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
562_trfX(_ITRF2008_, _ITRF94_, epoch=_F(2000),
563 xform=_H( 4.8, 2.6, -33.2, 2.92, _0_0, _0_0, 0.06),
564 rates=_H( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
565_trfX(_ITRF2008_, _ITRF93_, epoch=_F(2000),
566 xform=_H( -24.0, 2.4, -38.6, 3.41, -1.71, -1.48, -0.3),
567 rates=_H( -2.8, -0.1, -2.4, 0.09, -0.11, -0.19, 0.07))
568_trfX(_ITRF2008_, _ITRF92_, epoch=_F(2000),
569 xform=_H( 12.8, 4.6, -41.2, 2.21, _0_0, _0_0, 0.06),
570 rates=_H( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
571_trfX(_ITRF2008_, _ITRF91_, epoch=_F(2000),
572 xform=_H( 24.8, 18.6, -47.2, 3.61, _0_0, _0_0, 0.06),
573 rates=_H( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
574_trfX(_ITRF2008_, _ITRF90_, epoch=_F(2000),
575 xform=_H( 22.8, 14.6, -63.2, 3.91, _0_0, _0_0, 0.06),
576 rates=_H( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
577_trfX(_ITRF2008_, _ITRF89_, epoch=_F(2000),
578 xform=_H( 27.8, 38.6, -101.2, 7.31, _0_0, _0_0, 0.06),
579 rates=_H( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
580_trfX(_ITRF2008_, _ITRF88_, epoch=_F(2000),
581 xform=_H( 22.8, 2.6, -125.2, 10.41, 0.1, _0_0, 0.06),
582 rates=_H( 0.1, -0.5, -3.2, 0.09, _0_0, _0_0, 0.02))
584_trfX(_ITRF2005_, _ITRF2000_, epoch=_F(2000), # <http://ITRF.ENSG.IGN.Fr/ITRF_solutions/2005/tp_05-00.php>
585 xform=_H( 0.1, -0.8, -5.8, 0.4, _0_0, _0_0, _0_0),
586 rates=_H( -0.2, 0.1, -1.8, 0.08, _0_0, _0_0, _0_0))
588_trfX(_ITRF2000_, _ITRF97_, epoch=_F(1997),
589 xform=_H( 0.67, 0.61, -1.85, 1.55, _0_0, _0_0, _0_0),
590 rates=_H( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
591_trfX(_ITRF2000_, _ITRF96_, epoch=_F(1997),
592 xform=_H( 0.67, 0.61, -1.85, 1.55, _0_0, _0_0, _0_0),
593 rates=_H( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
594_trfX(_ITRF2000_, _ITRF94_, epoch=_F(1997),
595 xform=_H( 0.67, 0.61, -1.85, 1.55, _0_0, _0_0, _0_0),
596 rates=_H( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
597_trfX(_ITRF2000_, _ITRF93_, epoch=_F(1988),
598 xform=_H( 12.7, 6.5, -20.9, 1.95, -0.39, 0.8, -1.14),
599 rates=_H( -2.9, -0.2, -0.6, 0.01, -0.11, -0.19, 0.07))
600_trfX(_ITRF2000_, _ITRF92_, epoch=_F(1988),
601 xform=_H( 1.47, 1.35, -1.39, 0.75, _0_0, _0_0, -0.18),
602 rates=_H( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
603_trfX(_ITRF2000_, _ITRF91_, epoch=_F(1988),
604 xform=_H( 26.7, 27.5, -19.9, 2.15, _0_0, _0_0, -0.18),
605 rates=_H( _0_0, -0.6, -1.4, 0.01, _0_0, _0_0, 0.02))
606_trfX(_ITRF2000_, _ITRF90_, epoch=_F(1988),
607 xform=_H( 2.47, 2.35, -3.59, 2.45, _0_0, _0_0, -0.18),
608 rates=_H( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
609_trfX(_ITRF2000_, _ITRF89_, epoch=_F(1988),
610 xform=_H( 2.97, 4.75, -7.39, 5.85, _0_0, _0_0, -0.18),
611 rates=_H( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
612_trfX(_ITRF2000_, _ITRF88_, epoch=_F(1988),
613 xform=_H( 2.47, 1.15, -9.79, 8.95, 0.1, _0_0, -0.18),
614 rates=_H( _0_0, -0.06, -0.14, 0.01, _0_0, _0_0, 0.02))
616# see Altamimi, Z. U{"EUREF Technical Note 1: Relationship and Transformation between the International and
617# the European Terrestrial Reference Systems"<https://ERTS89.ENSG,IFN.Fr/pub/EUREF-TN-1.pdf>} Table 1.
618# _trfX(_ITRF2014_, _ETRF2014_, epoch=_F(1989),
619# xform=_H( _0_0, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0),
620# rates=_H( _0_0, _0_0, _0_0, _0_0, 0.085, 0.531, -0.77))
621_trfX(_ITRF2005_, _ETRF2005_, epoch=_F(1989),
622 xform=_H( 56.0, 48.0, -37.0, _0_0, _0_0, _0_0, _0_0),
623 rates=_H( _0_0, _0_0, _0_0, _0_0, 0.054, 0.518, -0.781))
624# _trfX(_ITRF2000_, _ETRF2000_, epoch=_F(1989),
625# xform=_H( 54.0, 51.0, -48.0, _0_0, _0_0, _0_0, _0_0),
626# rates=_H( _0_0, _0_0, _0_0, _0_0, 0.081, 0.49, -0.792))
627_trfX(_ITRF97_, _ETRF97_, epoch=_F(1989),
628 xform=_H( 41.0, 41.0, -49.0, _0_0, _0_0, _0_0, _0_0),
629 rates=_H( _0_0, _0_0, _0_0, _0_0, 0.2, 0.5, -0.65))
630_trfX(_ITRF96_, _ETRF96_, epoch=_F(1989),
631 xform=_H( 41.0, 41.0, -49.0, _0_0, _0_0, _0_0, _0_0),
632 rates=_H( _0_0, _0_0, _0_0, _0_0, 0.2, 0.5, -0.65))
633_trfX(_ITRF94_, _ETRF94_, epoch=_F(1989),
634 xform=_H( 41.0, 41.0, -49.0, _0_0, _0_0, _0_0, _0_0),
635 rates=_H( _0_0, _0_0, _0_0, _0_0, 0.2, 0.5, -0.65))
636_trfX(_ITRF93_, _ETRF93_, epoch=_F(1989),
637 xform=_H( 19.0, 53.0, -21.0, _0_0, _0_0, _0_0, _0_0),
638 rates=_H( _0_0, _0_0, _0_0, _0_0, 0.32, 0.78, -0.67))
639_trfX(_ITRF92_, _ETRF92_, epoch=_F(1989),
640 xform=_H( 38.0, 40.0, -37.0, 0.0, 0.0, 0.0, 0.0),
641 rates=_H( _0_0, _0_0, _0_0, _0_0, 0.21, 0.52, -0.68))
642_trfX(_ITRF91_, _ETRF91_, epoch=_F(1989),
643 xform=_H( 21.0, 25.0, -37.0, _0_0, _0_0, _0_0, _0_0),
644 rates=_H( _0_0, _0_0, _0_0, _0_0, 0.21, 0.52, -0.68))
645_trfX(_ITRF90_, _ETRF90_, epoch=_F(1989),
646 xform=_H( 19.0, 28.0, -23.0, _0_0, _0_0, _0_0, _0_0),
647 rates=_H( _0_0, _0_0, _0_0, _0_0, 0.11, 0.57, -0.71))
648_trfX(_ITRF89_, _ETRF89_, epoch=_F(1989),
649 xform=_H( _0_0, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0),
650 rates=_H( _0_0, _0_0, _0_0, _0_0, 0.11, 0.57, -0.71))
652# see Altamimi, Z. U{"EUREF Technical Note 1: Relationship and Transformation between the International and
653# the European Terrestrial Reference Systems"<https://ERTS89.ENSG,IFN.Fr/pub/EUREF-TN-1.pdf>} Table 2.
654_trfX(_ITRF2014_, _ETRF2014_, epoch=_F(2010),
655 xform=_H( _0_0, _0_0, _0_0, _0_0, 1.785, 11.151, -16.17),
656 rates=_H( _0_0, _0_0, _0_0, _0_0, 0.085, 0.531, -0.77))
657_trfX(_ITRF2008_, _ETRF2014_, epoch=_F(2010),
658 xform=_H( -1.6, -1.9, -2.4, 0.02, 1.785, 11.151, -16.17),
659 rates=_H( _0_0, _0_0, 0.1, -0.03, 0.085, 0.531, -0.77))
660_trfX(_ITRF2005_, _ETRF2014_, epoch=_F(2010),
661 xform=_H( -2.6, -1.0, 2.3, -0.92, 1.785, 11.151, -16.17),
662 rates=_H( -0.3, _0_0, 0.1, -0.03, 0.085, 0.531, -0.77))
663_trfX(_ITRF2000_, _ETRF2014_, epoch=_F(2010),
664 xform=_H( -0.7, -1.2, 26.1, -2.12, 1.785, 11.151, -16.17),
665 rates=_H( -0.1, -0.1, 1.9, -0.11, 0.085, 0.531, -0.77))
666_trfX(_ITRF97_, _ETRF2014_, epoch=_F(2010),
667 xform=_H( -7.4, 0.5, 62.8, -3.8, 1.785, 11.151, -16.43),
668 rates=_H( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
669_trfX(_ITRF96_, _ETRF2014_, epoch=_F(2010),
670 xform=_H( -7.4, 0.5, 62.8, -3.8, 1.785, 11.151, -16.43),
671 rates=_H( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
672_trfX(_ITRF94_, _ETRF2014_, epoch=_F(2010),
673 xform=_H( -7.4, 0.5, 62.8, -3.8, 1.785, 11.151, -16.43),
674 rates=_H( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
675_trfX(_ITRF93_, _ETRF2014_, epoch=_F(2010),
676 xform=_H( 50.4, -3.3, 60.2, -4.29, 4.595, 14.531, -16.57),
677 rates=_H( 2.8, 0.1, 2.5, -0.12, 0.195, 0.721, -0.84))
678_trfX(_ITRF92_, _ETRF2014_, epoch=_F(2010),
679 xform=_H( -15.4, -1.5, 70.8, -3.09, 1.785, 11.151, -16.43),
680 rates=_H( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
681_trfX(_ITRF91_, _ETRF2014_, epoch=_F(2010),
682 xform=_H( -27.4, -15.5, 76.8, -4.49, 1.785, 11.151, -16.43),
683 rates=_H( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
684_trfX(_ITRF90_, _ETRF2014_, epoch=_F(2010),
685 xform=_H( -25.4, -11.5, 92.8, -4.79, 1.785, 11.151, -16.43),
686 rates=_H( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
687_trfX(_ITRF89_, _ETRF2014_, epoch=_F(2010),
688 xform=_H( -30.4, -35.5, 130.8, -8.19, 1.785, 11.151, -16.43),
689 rates=_H( -0.1, 0.5, 3.3, -0.12, 0.085, 0.531, -0.79))
691# see U{Altamimi, Z. "EUREF Technical Note 1: Relationship and Transformation between the International and
692# the European Terrestrial Reference Systems"<https://ERTS89.ENSG,IFN.Fr/pub/EUREF-TN-1.pdf>} Table 3,
693# U{Boucher, C. & Altamimi, Z. "Memo: Specifications for reference frame fixing in the analysis of a EUREF GPS
694# campaign" (2011) <https://ETRS89.ENSG.IGN.Fr/memo-V8.pdf>} and U{Altamimi, Z. "Key results of ITRF2014 and
695# implication to ETRS89 realization", EUREF2016<https://www.EUREF.EU/symposia/2016SanSebastian/01-02-Altamimi.pdf>}.
696# _trfX(_ITRF2014_, _ETRF2000_, epoch=_F(2000),
697# xform=_H( 53.7, 51.2, -55.1, 1.02, 0.891, 5.39, -8.712),
698# rates=_H( 0.1, 0.1, -1.9, 0.11, 0.081, 0.49, -0.792))
699_trfX(_ITRF2014_, _ETRF2000_, epoch=_F(2010),
700 xform=_H( 54.7, 52.2, -74.1, 2.12, 1.701, 10.29, -16.632),
701 rates=_H( 0.1, 0.1, -1.9, 0.11, 0.081, 0.49, -0.792))
702# _trfX(_ITRF2008_, _ETRF2000_, epoch=_F(2000),
703# xform=_H( 52.1, 49.3, -58.5, 1.34, 0.891, 5.39, -8.712),
704# rates=_H( 0.1, 0.1, -1.8, 0.08, 0.081, 0.49, -0.792))
705_trfX(_ITRF2008_, _ETRF2000_, epoch=_F(2010),
706 xform=_H( 53.1, 50.3, -76.5, 2.14, 1.701, 10.29, -16.632),
707 rates=_H( 0.1, 0.1, -1.8, 0.08, 0.081, 0.49, -0.792))
708# _trfX(_ITRF2005_, _ETRF2000_, epoch=_F(2000),
709# xform=_H( 54.1, 50.2, -53.8, 0.4, 0.891, 5.39, -8.712),
710# rates=_H( -0.2, 0.1, -1.8, 0.08, 0.081, 0.49, -0.792))
711_trfX(_ITRF2005_, _ETRF2000_, epoch=_F(2010),
712 xform=_H( 52.1, 51.2, -71.8, 1.2, 1.701, 10.29, -16.632),
713 rates=_H( -0.2, 0.1, -1.8, 0.08, 0.081, 0.49, -0.792))
714# _trfX(_ITRF2000_, _ETRF2000_, epoch=_F(2000),
715# xform=_H( 54.0, 51.0, -48.0, _0_0, 0.891, 5.39, -8.712),
716# rates=_H( _0_0, _0_0, _0_0, _0_0, 0.081, 0.49, -0.792))
717_trfX(_ITRF2000_, _ETRF2000_, epoch=_F(2010),
718 xform=_H( 54.0, 51.0, -48.0, _0_0, 1.701, 10.29, -16.632),
719 rates=_H( _0_0, _0_0, _0_0, _0_0, 0.081, 0.49, -0.812))
720_trfX(_ITRF97_, _ETRF2000_, epoch=_F(2010),
721 xform=_H( 54.0, 51.0, -48.0, -1.68, 1.701, 10.29, -16.892),
722 rates=_H( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
723_trfX(_ITRF96_, _ETRF2000_, epoch=_F(2010),
724 xform=_H( 54.0, 51.0, -48.0, -1.68, 1.701, 10.29, -16.892),
725 rates=_H( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
726_trfX(_ITRF94_, _ETRF2000_, epoch=_F(2010),
727 xform=_H( 47.3, 52.7, -11.3, -1.68, 1.701, 10.29, -16.892),
728 rates=_H( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
729_trfX(_ITRF93_, _ETRF2000_, epoch=_F(2010),
730 xform=_H( 105.1, 48.9, -13.9, -2.17, 4.511, 13.67, -17.032),
731 rates=_H( 2.9, 0.2, 0.6, -0.01, 0.191, 0.68, -0.862))
732_trfX(_ITRF92_, _ETRF2000_, epoch=_F(2010),
733 xform=_H( 39.3, 50.7, -3.3, -0.97, 1.701, 10.29, -16.892),
734 rates=_H( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
735_trfX(_ITRF91_, _ETRF2000_, epoch=_F(2010),
736 xform=_H( 27.3, 36.7, 2.7, -2.37, 1.701, 10.29, -16.892),
737 rates=_H( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
738_trfX(_ITRF90_, _ETRF2000_, epoch=_F(2010),
739 xform=_H( 29.3, 40.7, 18.7, -2.67, 1.701, 10.29, -16.892),
740 rates=_H( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
741_trfX(_ITRF89_, _ETRF2000_, epoch=_F(2010),
742 xform=_H( 24.3, 16.7, 56.7, -6.07, 1.701, 10.29, -16.892),
743 rates=_H( _0_0, 0.6, 1.4, -0.01, 0.081, 0.49, -0.812))
745# GDA2020 "Geocentric Datum of Australia 2020 Technical Manual", v1.5, 2020-12-09, Table 3.3 and 3.4
746# <https://www.ICSM.gov.AU/sites/default/files/2020-12/GDA2020%20Technical%20Manual%20V1.5_4.pdf>
747# (the GDA2020 xforms are different but the rates are the same as GDA94, further below)
748_trfX(_ITRF2014_, _GDA2020_, epoch=_F(2020),
749 xform=_H( _0_0, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0),
750 rates=_H( _0_0, _0_0, _0_0, _0_0, 1.50379, 1.18346, 1.20716))
751_trfX(_ITRF2008_, _GDA2020_, epoch=_F(2020),
752 xform=_H( 13.79, 4.55, 15.22, 2.5, 0.2808, 0.2677, -0.4638),
753 rates=_H( 1.42, 1.34, 0.9, 0.109, 1.5461, 1.182, 1.1551))
754_trfX(_ITRF2005_, _GDA2020_, epoch=_F(2020),
755 xform=_H( 40.32, -33.85, -16.72, 4.286, -1.2893, -0.8492, -0.3342),
756 rates=_H( 2.25, -0.62, -0.56, 0.294, -1.4707, -1.1443, -1.1701))
757_trfX(_ITRF2000_, _GDA2020_, epoch=_F(2020),
758 xform=_H(-105.52, 51.58, 231.68, 3.55, 4.2175, 6.3941, 0.8617),
759 rates=_H( -4.66, 3.55, 11.24, 0.249, 1.7454, 1.4868, 1.224))
761# see Table 2 in U{Dawson, J. & Woods, A. "ITRF to GDA94 coordinate transformations", Journal of Applied
762# Geodesy 4 (2010), 189-199<https://www.ResearchGate.net/publication/258401581_ITRF_to_GDA94_coordinate_transformations>}
763# (note, sign of rotations for GDA94 reversed as "Australia assumes rotation to be of coordinate axes",
764# rather than the more conventional "position around the coordinate axes")
765_trfX(_ITRF2008_, _GDA94_, epoch=_F(1994),
766 xform=_H( -84.68, -19.42, 32.01, 9.71, -0.4254, 2.2578, 2.4015),
767 rates=_H( 1.42, 1.34, 0.9, 0.109, 1.5461, 1.182, 1.1551))
768_trfX(_ITRF2005_, _GDA94_, epoch=_F(1994),
769 xform=_H( -79.73, -6.86, 38.03, 6.636, 0.0351, -2.1211, -2.1411),
770 rates=_H( 2.25, -0.62, -0.56, 0.294, -1.4707, -1.1443, -1.1701))
771_trfX(_ITRF2000_, _GDA94_, epoch=_F(1994),
772 xform=_H( -45.91, -29.85, -20.37, 7.07, -1.6705, 0.4594, 1.9356),
773 rates=_H( -4.66, 3.55, 11.24, 0.249, 1.7454, 1.4868, 1.224))
775# see U{Solar, T. & Snay, R.A. "Transforming Positions and Velocities between the
776# International Terrestrial Reference Frame of 2000 and North American Datum of 1983"
777# (2004)<https://www.NGS.NOAA.gov/CORS/Articles/SolerSnayASCE.pdf>}
778_trfX(_ITRF2000_, _NAD83_, epoch=_F(1997), # note NAD83(CORS96)
779 xform=_H( 995.6, -1901.3, -521.5, 0.615, -25.915, -9.426, -11.599),
780 rates=_H( 0.7, -0.7, _0_5, -0.182, -0.06667, 0.75744, 0.05133))
782# see U{Quinsy QPS<https://confluence.QPS.NL/qinsy/files/latest/en/182618383/182618384/1/1579182881000/
783# ITRF_Transformation_Parameters.xlsx>}, sheets ITRF and NAD83
784_trfX(_ITRF2008_, _NAD83_, epoch=_F(1997),
785 xform=_H( 993.43, -1903.31, -526.55, 1.71504, -25.91467, -9.42645, -11.59935),
786 rates=_H( 0.79, -0.6, -1.34, -0.10201, -0.06667, 0.75744, 0.05133))
787_trfX(_ITRF2005_, _NAD83_, epoch=_F(1997),
788 xform=_H( 996.3, -1902.4, -521.9, 0.775, -25.915, -9.426, -11.599),
789 rates=_H( 0.5, -0.6, -1.3, -0.10201, -0.06667, 0.75744, 0.05133))
790_trfX(_ITRF90_, _NAD83_, epoch=_F(1997),
791 xform=_H( 973.0, -1919.2, -482.9, -0.9, -25.79, -9.65, -11.66),
792 rates=_H( _0_0, _0_0, _0_0, _0_0, -0.053, 0.742, 0.032))
793_trfX(_ITRF90_, _WGS84_, epoch=_F(1984),
794 xform=_H( 60.0, -517.0, -223.0, -11.0, 18.3, -0.3, 7.0),
795 rates=_H( _0_0, _0_0, _0_0, _0_0, _0_0, _0_0, _0_0))
796del _H, _Hs
798if __name__ == '__main__':
800 from pygeodesy.interns import _COMMA_, _NL_, _NLATvar_, _STAR_
801 from pygeodesy.lazily import printf
802 from time import localtime
804 D = date2epoch.__name__
805 E = epoch2date.__name__
806 y = localtime()[0]
807 for m in range(1, 13):
808 for d in (1, 15, _mDays[m] - 1, _mDays[m]):
809 f = '%s(%d,%3d,%3d)' % (D, y, m, d)
810 e = date2epoch(y, m, d)
811 t = epoch2date(e)
812 x = NN if t == (y, m, d) else _STAR_
813 e = '%.3f' % (e,)
814 e = '%s, %s(%s)' % (e, E, e)
815 t = '%d,%3d,%3d' % t
816 printf('# %s = %s = %s %s', f, e, t, x)
818 # __doc__ of this file, force all into registery
819 t = [NN] + RefFrames.toRepr(all=True).split(_NL_)
820 printf(_NLATvar_.join(i.strip(_COMMA_) for i in t))
822# **) MIT License
823#
824# Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
825#
826# Permission is hereby granted, free of charge, to any person obtaining a
827# copy of this software and associated documentation files (the "Software"),
828# to deal in the Software without restriction, including without limitation
829# the rights to use, copy, modify, merge, publish, distribute, sublicense,
830# and/or sell copies of the Software, and to permit persons to whom the
831# Software is furnished to do so, subject to the following conditions:
832#
833# The above copyright notice and this permission notice shall be included
834# in all copies or substantial portions of the Software.
835#
836# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
837# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
838# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
839# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
840# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
841# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
842# OTHER DEALINGS IN THE SOFTWARE.
844# % python -m pygeodesy.trf
845#
846# date2epoch(2024, 1, 1) = 2024.003, epoch2date(2024.003) = 2024, 1, 1
847# date2epoch(2024, 1, 15) = 2024.041, epoch2date(2024.041) = 2024, 1, 15
848# date2epoch(2024, 1, 30) = 2024.082, epoch2date(2024.082) = 2024, 1, 30
849# date2epoch(2024, 1, 31) = 2024.085, epoch2date(2024.085) = 2024, 1, 31
850# date2epoch(2024, 2, 1) = 2024.087, epoch2date(2024.087) = 2024, 2, 2 *
851# date2epoch(2024, 2, 15) = 2024.126, epoch2date(2024.126) = 2024, 2, 16 *
852# date2epoch(2024, 2, 28) = 2024.161, epoch2date(2024.161) = 2024, 2, 28
853# date2epoch(2024, 2, 29) = 2024.164, epoch2date(2024.164) = 2024, 3, 1 *
854# date2epoch(2024, 3, 1) = 2024.167, epoch2date(2024.167) = 2024, 3, 2 *
855# date2epoch(2024, 3, 15) = 2024.205, epoch2date(2024.205) = 2024, 3, 16 *
856# date2epoch(2024, 3, 30) = 2024.246, epoch2date(2024.246) = 2024, 3, 31 *
857# date2epoch(2024, 3, 31) = 2024.249, epoch2date(2024.249) = 2024, 4, 1 *
858# date2epoch(2024, 4, 1) = 2024.251, epoch2date(2024.251) = 2024, 4, 1
859# date2epoch(2024, 4, 15) = 2024.290, epoch2date(2024.290) = 2024, 4, 15
860# date2epoch(2024, 4, 29) = 2024.328, epoch2date(2024.328) = 2024, 4, 29
861# date2epoch(2024, 4, 30) = 2024.331, epoch2date(2024.331) = 2024, 4, 30
862# date2epoch(2024, 5, 1) = 2024.333, epoch2date(2024.333) = 2024, 5, 1
863# date2epoch(2024, 5, 15) = 2024.372, epoch2date(2024.372) = 2024, 5, 15
864# date2epoch(2024, 5, 30) = 2024.413, epoch2date(2024.413) = 2024, 5, 30
865# date2epoch(2024, 5, 31) = 2024.415, epoch2date(2024.415) = 2024, 6, 1 *
866# date2epoch(2024, 6, 1) = 2024.418, epoch2date(2024.418) = 2024, 6, 2 *
867# date2epoch(2024, 6, 15) = 2024.456, epoch2date(2024.456) = 2024, 6, 16 *
868# date2epoch(2024, 6, 29) = 2024.495, epoch2date(2024.495) = 2024, 6, 30 *
869# date2epoch(2024, 6, 30) = 2024.497, epoch2date(2024.497) = 2024, 7, 1 *
870# date2epoch(2024, 7, 1) = 2024.500, epoch2date(2024.500) = 2024, 7, 1
871# date2epoch(2024, 7, 15) = 2024.538, epoch2date(2024.538) = 2024, 7, 16 *
872# date2epoch(2024, 7, 30) = 2024.579, epoch2date(2024.579) = 2024, 7, 30
873# date2epoch(2024, 7, 31) = 2024.582, epoch2date(2024.582) = 2024, 7, 31
874# date2epoch(2024, 8, 1) = 2024.585, epoch2date(2024.585) = 2024, 8, 1
875# date2epoch(2024, 8, 15) = 2024.623, epoch2date(2024.623) = 2024, 8, 15
876# date2epoch(2024, 8, 30) = 2024.664, epoch2date(2024.664) = 2024, 8, 31 *
877# date2epoch(2024, 8, 31) = 2024.667, epoch2date(2024.667) = 2024, 9, 1 *
878# date2epoch(2024, 9, 1) = 2024.669, epoch2date(2024.669) = 2024, 9, 2 *
879# date2epoch(2024, 9, 15) = 2024.708, epoch2date(2024.708) = 2024, 9, 16 *
880# date2epoch(2024, 9, 29) = 2024.746, epoch2date(2024.746) = 2024, 9, 30 *
881# date2epoch(2024, 9, 30) = 2024.749, epoch2date(2024.749) = 2024, 10, 1 *
882# date2epoch(2024, 10, 1) = 2024.751, epoch2date(2024.751) = 2024, 10, 1
883# date2epoch(2024, 10, 15) = 2024.790, epoch2date(2024.790) = 2024, 10, 15
884# date2epoch(2024, 10, 30) = 2024.831, epoch2date(2024.831) = 2024, 10, 30
885# date2epoch(2024, 10, 31) = 2024.833, epoch2date(2024.833) = 2024, 10, 31
886# date2epoch(2024, 11, 1) = 2024.836, epoch2date(2024.836) = 2024, 11, 1
887# date2epoch(2024, 11, 15) = 2024.874, epoch2date(2024.874) = 2024, 11, 15
888# date2epoch(2024, 11, 29) = 2024.913, epoch2date(2024.913) = 2024, 11, 29
889# date2epoch(2024, 11, 30) = 2024.915, epoch2date(2024.915) = 2024, 12, 1 *
890# date2epoch(2024, 12, 1) = 2024.918, epoch2date(2024.918) = 2024, 12, 2 *
891# date2epoch(2024, 12, 15) = 2024.956, epoch2date(2024.956) = 2024, 12, 16 *
892# date2epoch(2024, 12, 30) = 2024.997, epoch2date(2024.997) = 2024, 12, 31 *
893# date2epoch(2024, 12, 31) = 2025.000, epoch2date(2025.000) = 2025, 1, 1 *