def set_jds(self, val1, val2): self._check_scale(self._scale) # Validate scale. sum12, err12 = two_sum(val1, val2) iy_start = np.trunc(sum12).astype(int) extra, y_frac = two_sum(sum12, -iy_start) y_frac += extra + err12 val = (val1 + val2).astype(np.double) iy_start = np.trunc(val).astype(int) imon = np.ones_like(iy_start) iday = np.ones_like(iy_start) ihr = np.zeros_like(iy_start) imin = np.zeros_like(iy_start) isec = np.zeros_like(y_frac) # Possible enhancement: use np.unique to only compute start, stop # for unique values of iy_start. scale = self.scale.upper().encode('ascii') jd1_start, jd2_start = erfa.dtf2d(scale, iy_start, imon, iday, ihr, imin, isec) jd1_end, jd2_end = erfa.dtf2d(scale, iy_start + 1, imon, iday, ihr, imin, isec) t_start = Time(jd1_start, jd2_start, scale=self.scale, format='jd') t_end = Time(jd1_end, jd2_end, scale=self.scale, format='jd') t_frac = t_start + (t_end - t_start) * y_frac self.jd1, self.jd2 = day_frac(t_frac.jd1, t_frac.jd2)
def value(self): scale = self.scale.upper().encode('ascii') iy_start, ims, ids, ihmsfs = erfa.d2dtf( scale, 0, # precision=0 self.jd1, self.jd2_filled) imon = np.ones_like(iy_start) iday = np.ones_like(iy_start) ihr = np.zeros_like(iy_start) imin = np.zeros_like(iy_start) isec = np.zeros_like(self.jd1) # Possible enhancement: use np.unique to only compute start, stop # for unique values of iy_start. scale = self.scale.upper().encode('ascii') jd1_start, jd2_start = erfa.dtf2d(scale, iy_start, imon, iday, ihr, imin, isec) jd1_end, jd2_end = erfa.dtf2d(scale, iy_start + 1, imon, iday, ihr, imin, isec) dt = (self.jd1 - jd1_start) + (self.jd2 - jd2_start) dt_end = (jd1_end - jd1_start) + (jd2_end - jd2_start) decimalyear = iy_start + dt / dt_end return decimalyear
def _test_erfa_conversion(leap, i_f): i_i, f_i = i_f assume(0 <= f_i < 1) if leap: assume(i_i in leap_sec_days) else: assume(i_i not in leap_sec_days) jd1_in, jd2_in = day_frac(erfa.DJM0 + i_i, f_i) y, mo, d, f = erfa.jd2cal(jd1_in, jd2_in) assert 0 < y < 3000 assert 0 < mo <= 12 assert 0 <= d < 32 assert 0 <= f < 1 jd1_temp, jd2_temp = erfa.cal2jd(y, mo, d) jd1_temp, jd2_temp = day_frac(jd1_temp, jd2_temp) # improve numerics jd1_temp, jd2_temp = day_frac(jd1_temp, jd2_temp + f) jd_change = abs((jd1_temp - jd1_in) + (jd2_temp - jd2_in)) * u.day assert jd_change.to(u.ns) < 1 * u.ns ft = 24 * f h = safe_kind_conversion(np.floor(ft), dtype=int) ft -= h ft *= 60 m = safe_kind_conversion(np.floor(ft), dtype=int) ft -= m ft *= 60 s = ft assert 0 <= h < 24 assert 0 <= m < 60 assert 0 <= s < 60 jd1, jd2 = erfa.dtf2d("UTC", y, mo, d, h, m, s) y2, mo2, d2, f2 = erfa.jd2cal(jd1, jd2) # assert (y, mo, d) == (y2, mo2, d2) # assert (abs(f2-f)*u.day).to(u.s) < 1*u.ns assert jd1 == np.floor(jd1) + 0.5 assert 0 <= jd2 < 1 jd1, jd2 = day_frac(jd1, jd2) jd_change = abs((jd1 - jd1_in) + (jd2 - jd2_in)) * u.day if leap: assert jd_change.to(u.s) < 1 * u.s else: assert jd_change.to(u.ns) < 2 * u.ns # assert jd_change.to(u.ns) < 1 * u.ns return i_o, f_o = day_frac(jd1 - erfa.DJM0, jd2) mjd_change = abs((i_o - i_i) + (f_o - f_i)) * u.day if leap: assert mjd_change.to(u.s) < 1 * u.s else: assert mjd_change.to(u.ns) < 1 * u.ns
def set_jds(self, val1, val2): """Parse the time strings contained in val1 and set jd1, jd2""" # Select subformats based on current self.in_subfmt subfmts = self._select_subfmts(self.in_subfmt) iterator = numpy.nditer([val1, None, None, None, None, None, None], op_dtypes=[val1.dtype] + 5 * [numpy.intc] + [numpy.double]) for val, iy, im, i_day, ihr, i_min, d_sec in iterator: iy[...], im[...], i_day[...], ihr[...], i_min[...], d_sec[...] = ( self.parse_string(val.item(), subfmts)) self.jd1, self.jd2 = dtf2d( self.scale.upper().encode('utf8'), *iterator.operands[1:])
def value(self): scale = self.scale.upper().encode('ascii') iy_start, ims, ids, ihmsfs = erfa.d2dtf(scale, 0, # precision=0 self.jd1, self.jd2_filled) imon = np.ones_like(iy_start) iday = np.ones_like(iy_start) ihr = np.zeros_like(iy_start) imin = np.zeros_like(iy_start) isec = np.zeros_like(self.jd1) # Possible enhancement: use np.unique to only compute start, stop # for unique values of iy_start. scale = self.scale.upper().encode('ascii') jd1_start, jd2_start = erfa.dtf2d(scale, iy_start, imon, iday, ihr, imin, isec) jd1_end, jd2_end = erfa.dtf2d(scale, iy_start + 1, imon, iday, ihr, imin, isec) dt = (self.jd1 - jd1_start) + (self.jd2 - jd2_start) dt_end = (jd1_end - jd1_start) + (jd2_end - jd2_start) decimalyear = iy_start + dt / dt_end return decimalyear
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 set_jds(self, val1, val2): """Parse the time strings contained in val1 and set jd1, jd2""" iterator = np.nditer([val1, None, None, None, None, None, None], op_dtypes=([val1.dtype] + 5 * [np.intc] + [np.double])) try: for val, iy, im, id, ihr, imin, dsec in iterator: timestr = val.item() components = timestr.split() iy[...], im[...], id[...], ihr[...], imin[...], sec = ( int(component) for component in components[:-1]) dsec[...] = sec + float(components[-1]) except Exception: raise ValueError('Time {0} does not match {1} format'.format( timestr, self.name)) self.jd1, self.jd2 = erfa.dtf2d(self.scale.upper().encode('utf8'), *iterator.operands[1:])
def set_jds(self, val1, val2): """Parse the time strings contained in val1 and set jd1, jd2""" iterator = np.nditer([val1, None, None, None, None, None, None], op_dtypes=([val1.dtype] + 5*[np.intc] + [np.double])) try: for val, iy, im, id, ihr, imin, dsec in iterator: timestr = val.item() components = timestr.split() iy[...], im[...], id[...], ihr[...], imin[...], sec = ( int(component) for component in components[:-1]) dsec[...] = sec + float(components[-1]) except: raise ValueError('Time {0} does not match {1} format' .format(timestr, self.name)) self.jd1, self.jd2 = erfa.dtf2d( self.scale.upper().encode('utf8'), *iterator.operands[1:])
def set_jds(self, val1, val2): """Parse the time strings contained in val1 and set jd1, jd2""" # Select subformats based on current self.in_subfmt subfmts = self._select_subfmts(self.in_subfmt) # Be liberal in what we accept: convert bytes to ascii. # Here .item() is needed for arrays with entries of unequal length, # to strip trailing 0 bytes. to_string = (str if val1.dtype.kind == 'U' else lambda x: str(x.item(), encoding='ascii')) iterator = np.nditer([val1, None, None, None, None, None, None], op_dtypes=[val1.dtype] + 5*[np.intc] + [np.double]) for val, iy, im, id, ihr, imin, dsec in iterator: val = to_string(val) iy[...], im[...], id[...], ihr[...], imin[...], dsec[...] = ( self.parse_string(val, subfmts)) jd1, jd2 = erfa.dtf2d(self.scale.upper().encode('ascii'), *iterator.operands[1:]) self.jd1, self.jd2 = day_frac(jd1, jd2)
def set_jds(self, val1, val2): """Convert datetime object contained in val1 to jd1, jd2""" # Iterate through the datetime objects, getting year, month, etc. iterator = np.nditer([val1, None, None, None, None, None, None], flags=['refs_ok'], op_dtypes=[object] + 5 * [np.intc] + [np.double]) for val, iy, im, id, ihr, imin, dsec in iterator: dt = val.item() if dt.tzinfo is not None: dt = (dt - dt.utcoffset()).replace(tzinfo=None) iy[...] = dt.year im[...] = dt.month id[...] = dt.day ihr[...] = dt.hour imin[...] = dt.minute dsec[...] = dt.second + dt.microsecond / 1e6 jd1, jd2 = erfa.dtf2d(self.scale.upper().encode('ascii'), *iterator.operands[1:]) self.jd1, self.jd2 = day_frac(jd1, jd2)
def set_jds(self, val1, val2): """Convert datetime object contained in val1 to jd1, jd2""" # Iterate through the datetime objects, getting year, month, etc. iterator = np.nditer([val1, None, None, None, None, None, None], flags=['refs_ok'], op_dtypes=[object] + 5*[np.intc] + [np.double]) for val, iy, im, id, ihr, imin, dsec in iterator: dt = val.item() if dt.tzinfo is not None: dt = (dt - dt.utcoffset()).replace(tzinfo=None) iy[...] = dt.year im[...] = dt.month id[...] = dt.day ihr[...] = dt.hour imin[...] = dt.minute dsec[...] = dt.second + dt.microsecond / 1e6 jd1, jd2 = erfa.dtf2d(self.scale.upper().encode('ascii'), *iterator.operands[1:]) self.jd1, self.jd2 = day_frac(jd1, jd2)
def mjds_to_jds_pulsar(mjd1, mjd2): # 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(mjd1, mjd2) (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.. # There is: erfa.d2tf. Unfortunately it takes a "number of # digits" argument and returns some kind of bogus # fractional-part-as-an-integer thing. # Worse, it fails to provide nanosecond accuracy. # Good idea, though, because using np.remainder is # numerically unstable and gives bogus values now # and then. This is more stable. f *= 24 h = safe_kind_conversion(np.floor(f), dtype=int) f -= h f *= 60 m = safe_kind_conversion(np.floor(f), dtype=int) f -= m f *= 60 s = f return erfa.dtf2d("UTC", y, mo, d, h, m, s)