def time_to_mjd_string(t, prec=15): """Print an MJD time with lots of digits (number is 'prec'). astropy does not seem to provide this capability (yet?). """ if t.format == 'pulsar_mjd': (imjd, fmjd) = day_frac(t.jd1 - DJM0, t.jd2) imjd = int(imjd) if fmjd < 0.0: imjd -= 1 y, mo, d, hmsf = d2dtf('UTC', 9, t.jd1, t.jd2) if hmsf[0].size == 1: hmsf = np.array([list(hmsf)]) fmjd = (hmsf[..., 0] / 24.0 + hmsf[..., 1] / 1440.0 + hmsf[..., 2] / 86400.0 + hmsf[..., 3] / 86400.0e9) else: (imjd, fmjd) = day_frac(t.jd1 - DJM0, t.jd2) imjd = int(imjd) assert np.fabs(fmjd) < 2.0 while fmjd >= 1.0: imjd += 1 fmjd -= 1.0 while fmjd < 0.0: imjd -= 1 fmjd += 1.0 fmt = "%." + "%sf" % prec return str(imjd) + (fmt % fmjd)[1:]
def time_to_mjd_string(t, prec=15): """Print an MJD time with lots of digits (number is 'prec'). astropy does not seem to provide this capability (yet?). """ if t.format == 'pulsar_mjd': (imjd, fmjd) = day_frac(t.jd1 - DJM0, t.jd2) imjd = int(imjd) if fmjd<0.0: imjd -= 1 y, mo, d, hmsf = d2dtf('UTC',9,t.jd1,t.jd2) fmjd = (hmsf[...,0]/24.0 + hmsf[...,1]/1440.0 + hmsf[...,2]/86400.0 + hmsf[...,3]/86400.0e9) else: (imjd, fmjd) = day_frac(t.jd1 - DJM0, t.jd2) imjd = int(imjd) assert np.fabs(fmjd) < 2.0 if fmjd >= 1.0: imjd += 1 fmjd -= 1.0 if fmjd < 0.0: imjd -= 1 fmjd += 1.0 fmt = "%." + "%sf" % prec return str(imjd) + (fmt % fmjd)[1:]
def test_day_frac_harmless(): with decimal.localcontext(decimal.Context(prec=40)): i, f = 65536, 3.637978807091714e-12 a = Decimal(i) + Decimal(f) i_d, f_d = day_frac(i, f) a_d = Decimal(i_d) + Decimal(f_d) assert (abs(a - a_d) * u.day).to(u.ns) < 1 * u.ns
def set_jds(self, val1, val2): self._check_scale(self._scale) if self._scale == 'utc': # To get around leap second issues, first convert to YMD, # then back to astropy/ERFA-convention jd1,jd2 using the # ERFA dtf2d() routine which handles leap seconds. v1, v2 = day_frac(val1, val2) (y,mo,d,f) = erfa.jd2cal(erfa.DJM0+v1,v2) # Fractional day to HMS. Uses 86400-second day always. # Seems like there should be a ERFA routine for this.. h = numpy.floor(f*24.0) m = numpy.floor(numpy.remainder(f*1440.0,60)) s = numpy.remainder(f*86400.0,60) self.jd1, self.jd2 = erfa.dtf2d('UTC',y,mo,d,h,m,s) else: self.jd1, self.jd2 = day_frac(val1, val2) self.jd1 += erfa.DJM0
def set_jds(self, val1, val2): self._check_scale(self._scale) if self._scale == 'utc': # To get around leap second issues, first convert to YMD, # then back to astropy/ERFA-convention jd1,jd2 using the # ERFA dtf2d() routine which handles leap seconds. v1, v2 = day_frac(val1, val2) (y, mo, d, f) = erfa.jd2cal(erfa.DJM0 + v1, v2) # Fractional day to HMS. Uses 86400-second day always. # Seems like there should be a ERFA routine for this.. h = numpy.floor(f * 24.0) m = numpy.floor(numpy.remainder(f * 1440.0, 60)) s = numpy.remainder(f * 86400.0, 60) self.jd1, self.jd2 = erfa.dtf2d('UTC', y, mo, d, h, m, s) else: self.jd1, self.jd2 = day_frac(val1, val2) self.jd1 += erfa.DJM0
def from_angles(cls, phase1, phase2=None, factor=None, divisor=None, out=None): """Create a Phase instance from two angles. The two angles will be added, and possibly multiplied by a factor or divided by a divisor, preserving precision using two doubles, one for the integer part and one for the remainder. Note that this class method is mostly meant for internal use. Parameters ---------- phase1 : `~astropy.units.Quantity` With angular units. phase2 : `~astropy.units.Quantity` or `None` With angular units. factor : float or complex Posisble factor to multiply the angles with. divisor : float or complex Posisble divisor to divide the angles by. Raises ------ ValueError If the result is not purely real or purely imaginary """ phase1, imaginary = check_imaginary(phase1) if phase2 is not None: phase2, im2 = check_imaginary(phase2) if im2 is not imaginary: raise ValueError("phase1 and phase2 must either be both " "real or both imaginary.") if factor is not None: factor, imf = check_imaginary(factor) imaginary ^= imf if divisor is not None: divisor, imd = check_imaginary(divisor) if imd and not imaginary: divisor = -divisor imaginary ^= imd # TODO: would be nice if day_frac had an out parameter. phase1_value = phase1.to_value(cls._unit) if phase2 is None: phase2_value = 0. else: phase2_value = phase2.to_value(cls._unit) count, fraction = day_frac(phase1_value, phase2_value, factor=factor, divisor=divisor) if out is None: value = np.empty(count.shape, cls._phase_dtype) out = value.view(cls) else: value = out.view(np.ndarray) value['int'] = count value['frac'] = fraction out.imaginary = imaginary return out
def test_day_frac_round_to_even(jd1, jd2): t_jd1, t_jd2 = day_frac(jd1, jd2) assert (abs(t_jd2) == 0.5) and (t_jd1 % 2 == 0)
def test_day_frac_always_less_than_half(jds): jd1, jd2 = jds t_jd1, t_jd2 = day_frac(jd1, jd2) assert np.all(t_jd1 % 1 == 0) assert np.all(abs(t_jd2) <= 0.5) assert np.all((abs(t_jd2) < 0.5) | (t_jd1 % 2 == 0))
def test_mjd_initialization_precise(i, f): t = Time(val=i, val2=f, format="mjd", scale="tai") jd1, jd2 = day_frac(i + erfa.DJM0, f) jd1_t, jd2_t = day_frac(t.jd1, t.jd2) assert (abs((jd1 - jd1_t) + (jd2 - jd2_t)) * u.day).to(u.ns) < 1 * u.ns
def test_day_frac_idempotent(i, f): i_d, f_d = day_frac(i, f) assert (i_d, f_d) == day_frac(i_d, f_d)
def test_day_frac_exact(i, f): assume(abs(f) < 0.5 or i % 2 == 0) i_d, f_d = day_frac(i, f) assert i == i_d assert f == f_d
def test_day_frac_harmless(i, f): with decimal.localcontext(decimal.Context(prec=40)): a = Decimal(i) + Decimal(f) i_d, f_d = day_frac(i, f) a_d = Decimal(i_d) + Decimal(f_d) assert_almost_equal(a, a_d, atol=Decimal(tiny), rtol=Decimal(0))
def value(self): mjd1, mjd2 = day_frac(self.jd1 - DJM0, self.jd2) return np.longdouble(mjd1) + np.longdouble(mjd2)
def set_jds(self, val, val2): mjd1 = np.float64(np.floor(val)) mjd2 = np.float64(val - mjd1) self.jd1, self.jd2 = day_frac(mjd1 + DJM0, mjd2)
def test_mjd_initialization_precise(): i, f = 65536, 3.637978807091714e-12 # Found using hypothesis t = Time(val=i, val2=f, format="mjd", scale="tai") jd1, jd2 = day_frac(i + erfa.DJM0, f) jd1_t, jd2_t = day_frac(t.jd1, t.jd2) assert (abs((jd1 - jd1_t) + (jd2 - jd2_t)) * u.day).to(u.ns) < 1 * u.ns
def test_day_frac_idempotent(): i, f = 65536, 3.637978807091714e-12 i_d, f_d = day_frac(i, f) assert i_d, f_d == day_frac(i_d, f_d)