def _igrf_interpolate(time, notilt1967=True): # get time as decimal year, note that epoch is completely arbitrary years = datetime64_as_years(time) if notilt1967 and np.abs(years - 1967.0) < 0.0006: # OpenGGCM special no-tilt hack # g10, g11, h11 = np.linalg.norm(IGRF[0, 1:]), 0.0, 0.0 g10, g11, h11 = -30554.00, 0.0, 0.0 else: g10 = np.interp(years, _IGRF[:, 0], _IGRF[:, 1]) g11 = np.interp(years, _IGRF[:, 0], _IGRF[:, 2]) h11 = np.interp(years, _IGRF[:, 0], _IGRF[:, 3]) return g10, g11, h11
def __init__(self, time='1967-01-01', dip_tilt=None, dip_gsm=None, rdim=3, notilt1967=True): """Construct Cotr instance Args: time (datetime-like): A specific date and time for the transformations (sets earth's geographic and dipole orientations) rdim (int): Dimensionality of rotation matrices dip_tilt (float): if given, override the dipole tilt angle (mu in degrees, positive points north pole sunward) dip_gsm (float): if given, override the dipole gse->gsm angle (psi in degrees, positive points north pole duskward) notilt1967 (bool): if True, then all transforms (except <->mhd transforms) are set to the identity. This is the special OpenGGCM no-dipole-tilt-time. """ self._emat_cache = dict() self._xform_cache = dict() # exact UT time of interest time = as_datetime64(time) self.time = time # dimension of rotation matrices (3 or 4), use 4 to support # translations self.rdim = rdim # modified julian date is days from 00:00UT on 17 Nov 1858 mjd0 = as_datetime64('1858-11-17T00:00:00.0') mjd_td = as_timedelta(time.astype(mjd0.dtype) - mjd0) self.mjd = mjd_td.total_seconds() // (24 * 3600) # ut is hours from midnight dt = as_datetime(time) day = as_datetime64("{0:04d}-{1:02d}-{2:02d}" "".format(dt.year, dt.month, dt.day)) secs = as_timedelta(time - day.astype(time.dtype)).total_seconds() self.ut = secs / 3600.0 # julian centuries (36525 days) since 1 Jan 2000 (epoch 2000) self.t0 = (self.mjd - 51544.5) / 36525.0 # interpolated IGRF g10, g11, h11 = _igrf_interpolate(self.time, notilt1967=notilt1967) self.g10 = g10 self.g11 = g11 self.h11 = h11 self._disable_mag_crds = dip_tilt is not None or dip_gsm is not None years = datetime64_as_years(time) notilt = notilt1967 and np.abs(years - 1967.0) < 0.0006 if self._disable_mag_crds or notilt: dip_tilt = 0.0 if dip_tilt is None else dip_tilt dip_gsm = 0.0 if dip_gsm is None else dip_gsm self._cached_sun_ecliptic_longitude = None self._cached_q_g = None self._cached_q_e = None self._cached_dip_geolon_rad = None self._cached_dip_geolat_rad = None self._cached_dip_tilt = dip_tilt self._cached_dip_gsm = dip_gsm # hack the cache to set all geocentric transforms to the identity # except GSE -> MHD if notilt: eye = np.eye(self.rdim) # matrices 3, 4, and 6 are missing so that gse, gsm, sm, mhd # transformations still do something (from dip_tilt and dip_gsm) for i in (1, 2, 5): self._emat_cache[-i] = eye self._emat_cache[i] = eye
def __init__(self, time='1967-01-01', dip_tilt=None, dip_gsm=None, rdim=3, notilt1967=True): """Construct Cotr instance Args: time (datetime-like): A specific date and time for the transformations (sets earth's geographic and dipole orientations) rdim (int): Dimensionality of rotation matrices dip_tilt (float): if given, override the dipole tilt angle (mu in degrees, positive points north pole sunward) dip_gsm (float): if given, override the dipole gse->gsm angle (psi in degrees, positive points north pole duskward) notilt1967 (bool): if True, then all transforms (except <->mhd transforms) are set to the identity if time is Jan 1 1967. This is the special OpenGGCM no-dipole-tilt-time. """ self._emat_cache = dict() self._xform_cache = dict() # exact UT time of interest time = as_datetime64(time) self.time = time # dimension of rotation matrices (3 or 4), use 4 to support # translations self.rdim = rdim # modified julian date is days from 00:00UT on 17 Nov 1858 mjd0 = as_datetime64('1858-11-17T00:00:00.0') mjd_td = as_timedelta(time.astype(mjd0.dtype) - mjd0) self.mjd = mjd_td.total_seconds() // (24 * 3600) # ut is hours from midnight dt = as_datetime(time) day = as_datetime64("{0:04d}-{1:02d}-{2:02d}" "".format(dt.year, dt.month, dt.day)) secs = as_timedelta(time - day.astype(time.dtype)).total_seconds() self.ut = secs / 3600.0 # julian centuries (36525 days) since 1 Jan 2000 (epoch 2000) self.t0 = (self.mjd - 51544.5) / 36525.0 # interpolated IGRF g10, g11, h11 = _igrf_interpolate(self.time, notilt1967=notilt1967) self.g10 = g10 self.g11 = g11 self.h11 = h11 self._disable_mag_crds = dip_tilt is not None or dip_gsm is not None years = datetime64_as_years(time) notilt = notilt1967 and np.abs(years - 1967.0) < 0.0006 # do i really want the self._disable_mag_crds part of this? what # if i want dip_gsm set by the time, and dip_tilt set by hand... # would anyone ever want that? is it really more natural to say that # if you specify dip_tilt or dip_gsm then both ignore the time? if self._disable_mag_crds or notilt: dip_tilt = 0.0 if dip_tilt is None else dip_tilt dip_gsm = 0.0 if dip_gsm is None else dip_gsm self._cached_sun_ecliptic_longitude = None self._cached_q_g = None self._cached_q_e = None self._cached_dip_geolon_rad = None self._cached_dip_geolat_rad = None self._cached_dip_tilt = dip_tilt self._cached_dip_gsm = dip_gsm # hack the cache to set all geocentric transforms to the identity # except GSE -> MHD if notilt: eye = np.eye(self.rdim) # matrices 3, 4, and 6 are missing so that gse, gsm, sm, mhd # transformations still do something (from dip_tilt and dip_gsm) for i in (1, 2, 5): self._emat_cache[-i] = eye self._emat_cache[i] = eye