def _cls_scale(cls, scale: str) -> "Type[TimeArray]": """Check that scale is valid and return corresponding type""" if scale not in cls._scales(): scales = ", ".join(sorted(cls._scales())) raise exceptions.UnknownSystemError( f"Scale {scale!r} unknown. Use one of {scales}") return cls._scales()[scale]
def get(ellipsoid: str) -> "Ellipsoid": """Get an ellipsoid by name""" try: return _ELLIPSOIDS[ellipsoid] except KeyError: ellipsoids = ", ".join(sorted(_ELLIPSOIDS)) raise exceptions.UnknownSystemError( f"Ellipsoid {ellipsoid!r} unknown. Use one of {ellipsoids}")
def __new__(cls, val, fmt, val2=None, _jd1=None, _jd2=None): """Create a new TimeArray""" if cls.scale is None: raise ValueError( f"{cls.__name__} cannot be instantiated. Use Time(val=..., scale={cls.scale!r}) instead" ) if fmt not in cls._formats(): formats = ", ".join(cls._formats()) raise exceptions.UnknownSystemError( f"Format {fmt!r} unknown. Use one of {formats}") # Convert to numpy array and read format fmt_values = cls._formats()[fmt](val, val2, cls.scale) val = np.asarray(val) if val2 is not None: val2 = np.asarray(val2) if val2.shape != val.shape: raise ValueError( f"'val2' must have the same shape as 'val': {val.shape}") if val2.ndim == 0: val2 = val2.item() if val.ndim == 0: val = val.item() # Store values on array obj = np.asarray(fmt_values.value).view(cls) jd1 = fmt_values.jd1 if _jd1 is None else _jd1 jd2 = fmt_values.jd2 if _jd2 is None else _jd2 # Validate shape fmt_ndim = cls._formats()[fmt].ndim if obj.ndim > fmt_ndim: raise ValueError( f"{type(self).__name__!r} must be a {fmt_ndim - 1} or {fmt_ndim}-dimensional array for format type {obj_fmt}" ) # Freeze if isinstance(jd1, np.ndarray): jd1.flags.writeable = False if isinstance(jd2, np.ndarray): jd2.flags.writeable = False super(TimeBase, obj).__setattr__("fmt", fmt) super(TimeBase, obj).__setattr__("jd1", jd1) super(TimeBase, obj).__setattr__("jd2", jd2) if isinstance(obj, np.ndarray): obj.flags.writeable = False return obj
def get(model: str) -> "PlateMotionModel": """Get a tectonic plate motion model by name Args: model: Plate motion model name Returns: Instance of PlateMotionModel dataclass """ try: return replace(_PLATE_MOTION_MODELS[model]) # Make a copy of PlateMotionModel object except KeyError: models = ", ".join(sorted(_PLATE_MOTION_MODELS)) raise exceptions.UnknownSystemError(f"Tectonic plate model {model!r} unknown. Use one of {models}")
def __init__(self, plate: str, model: str = "itrf2014") -> None: """Initilialize PlateMotion object by defining tectonic plate Args: plate: Name of tectonic plate model: Name of plate motion model """ model_ = plate_motion_models.get(model) if not plate in model_.plates: raise exceptions.UnknownSystemError( f"Tectonic plate {plate!r} unknown in plate motion model {model!r}. " f"Use one of {model_.plates}") self.plate = plate self.model = model self.pole = model_.get_pole(plate, unit="radian per year")
def create(val: np.ndarray, system: str, **dir_args: Any) -> "DirectionArray": """Factory for creating DirectionArrays for different systems See each direction class for exact optional parameters. Args: val: Array of position values. system: Name of direction system. dir_args: Additional arguments used to create the DirectionArray. Returns: Array with positions in the given system. """ if system not in _SYSTEMS: systems = ", ".join(_SYSTEMS) raise exceptions.UnknownSystemError( f"System {system!r} unknown. Use one of {systems}") return _SYSTEMS[system](val, **dir_args)
def get_pole(self, plate: str, unit: Union[None, str] = None ) -> "RotationPole": """Get rotation pole object for given tectonic plate Args: plate: Name of tectonic plate (e.g. eura) model: Plate motion model name unit: Define unit of rotation pole (e.g. 'radian per year', 'milliarcsecond per year') Returns: Instance of RotationPole dataclass for chosen tectonic plate """ try: pole = replace(self.poles[plate]) # Make a copy of RotationPole object except KeyError: plates = ", ".join(sorted(self.poles.keys())) raise exceptions.UnknownSystemError(f"Tectonic plate {plate!r} unknown in plate motion model {self.name}. Use one of {plates}") if unit: for entry in ["wx", "wy", "wz", "dwx", "dwy", "dwz"]: setattr(pole, entry, getattr(pole, entry) * Unit(pole.unit).to(unit).m) pole.unit = unit return pole
def to_system(self, system: str) -> "PosDeltaBase": """Convert to a different system Args: system: Name of new system. Returns: PosDeltaBase representing the same positions or position deltas in the new system. """ # Don't convert if not necessary if system == self.system: return self # Raise error for unknown systems if system not in _SYSTEMS: systems = ", ".join(_SYSTEMS) raise exceptions.UnknownSystemError( f"System {system!r} unknown. Use one of {systems}") if system in self._cache: return self._cache[system] # Convert to new system hop = (self.system, system) if hop in _CONVERSIONS: self._cache[system] = _SYSTEMS[system].convert_to( self, _CONVERSIONS[hop]) return self._cache[system] if hop not in _CONVERSION_HOPS: _CONVERSION_HOPS[self.cls_name][hop] = _find_conversion_hops(hop) val = self for one_hop in _CONVERSION_HOPS[hop]: val = _SYSTEMS[one_hop[-1]].convert_to(val, _CONVERSIONS[one_hop]) self._cache[one_hop[-1]] = val return val
def to_scale(self, scale: str) -> "TimeArray": """Convert time to a different scale Returns a new TimeArray with the same time in the new scale. Args: scale: Name of new scale. Returns: TimeArray representing the same times in the new scale. """ # Don't convert if not necessary if scale == self.scale: return self # Raise error for unknown scales if scale not in self._scales(): scales = ", ".join(self._scales()) raise exceptions.UnknownSystemError( f"Scale {scale!r} unknown. Use one of {scales}") # Convert to new scale hop = (self.scale, scale) if hop in _CONVERSIONS: jd1, jd2 = _CONVERSIONS[hop](self) return self._scales()[scale].from_jds(jd1, jd2, self.fmt) if hop not in _CONVERSION_HOPS: _CONVERSION_HOPS[hop] = _find_conversion_hops(hop) converted_time = self for one_hop in _CONVERSION_HOPS[hop]: jd1, jd2 = _CONVERSIONS[one_hop](converted_time) converted_time = self._scales()[one_hop[-1]].from_jds( jd1, jd2, self.fmt) return converted_time