def test_erfa_wrapper(): """ Runs a set of tests that mostly make sure vectorization is working as expected """ jd = np.linspace(2456855.5, 2456855.5+1.0/24.0/60.0, 60*2+1) ra = np.linspace(0.0, np.pi*2.0, 5) dec = np.linspace(-np.pi/2.0, np.pi/2.0, 4) aob, zob, hob, dob, rob, eo = erfa.atco13(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, jd, 0.0, 0.0, 0.0, np.pi/4.0, 0.0, 0.0, 0.0, 1014.0, 0.0, 0.0, 0.5) assert aob.shape == (121,) aob, zob, hob, dob, rob, eo = erfa.atco13(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, jd[0], 0.0, 0.0, 0.0, np.pi/4.0, 0.0, 0.0, 0.0, 1014.0, 0.0, 0.0, 0.5) assert aob.shape == () aob, zob, hob, dob, rob, eo = erfa.atco13(ra[:, None, None], dec[None, :, None], 0.0, 0.0, 0.0, 0.0, jd[None, None, :], 0.0, 0.0, 0.0, np.pi/4.0, 0.0, 0.0, 0.0, 1014.0, 0.0, 0.0, 0.5) (aob.shape) == (5, 4, 121) iy, im, id, ihmsf = erfa.d2dtf("UTC", 3, jd, 0.0) assert iy.shape == (121,) assert ihmsf.shape == (121,) assert ihmsf.dtype == erfa.dt_hmsf iy, im, id, ihmsf = erfa.d2dtf("UTC", 3, jd[0], 0.0) assert iy.shape == () assert ihmsf.shape == () assert ihmsf.dtype == erfa.dt_hmsf
def to_value(self, timezone=None, parent=None): """ Convert to (potentially timezone-aware) `~datetime.datetime` object. If ``timezone`` is not ``None``, return a timezone-aware datetime object. Parameters ---------- timezone : {`~datetime.tzinfo`, None} (optional) If not `None`, return timezone-aware datetime. Returns ------- `~datetime.datetime` If ``timezone`` is not ``None``, output will be timezone-aware. """ if timezone is not None: if self._scale != 'utc': raise ScaleValueError( "scale is {}, must be 'utc' when timezone " "is supplied.".format(self._scale)) # Rather than define a value property directly, we have a function, # since we want to be able to pass in timezone information. scale = self.scale.upper().encode('ascii') iys, ims, ids, ihmsfs = erfa.d2dtf( scale, 6, # 6 for microsec self.jd1, self.jd2_filled) ihrs = ihmsfs['h'] imins = ihmsfs['m'] isecs = ihmsfs['s'] ifracs = ihmsfs['f'] iterator = np.nditer([iys, ims, ids, ihrs, imins, isecs, ifracs, None], flags=['refs_ok'], op_dtypes=7 * [iys.dtype] + [object]) for iy, im, id, ihr, imin, isec, ifracsec, out in iterator: if isec >= 60: raise ValueError( 'Time {} is within a leap second but datetime ' 'does not support leap seconds'.format( (iy, im, id, ihr, imin, isec, ifracsec))) if timezone is not None: out[...] = datetime.datetime( iy, im, id, ihr, imin, isec, ifracsec, tzinfo=TimezoneInfo()).astimezone(timezone) else: out[...] = datetime.datetime(iy, im, id, ihr, imin, isec, ifracsec) return self.mask_if_needed(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 str_kwargs(self): """ Generator that yields a dict of values corresponding to the calendar date and time for the internal JD values. """ iys, ims, ids, ihmsfs = d2dtf(self.scale.upper() .encode('utf8'), 6, self.jd1, self.jd2) # Get the str_fmt element of the first allowed output subformat _, _, str_fmt = self._select_subfmts(self.out_subfmt)[0] yday = None has_yday = '{yday:' in str_fmt or False ihrs = ihmsfs[..., 0] imins = ihmsfs[..., 1] isecs = ihmsfs[..., 2] ifracs = ihmsfs[..., 3] for iy, im, iday, ihr, imin, isec, ifracsec in numpy.nditer( [iys, ims, ids, ihrs, imins, isecs, ifracs]): if has_yday: yday = datetime(iy, im, iday).timetuple().tm_yday fracday = (((((ifracsec / 1000000.0 + isec) / 60.0 + imin) / 60.0) + ihr) / 24.0) * (10 ** 6) fracday = '{0:06g}'.format(fracday)[0:self.precision] yield {'year': int(iy), 'mon': int(im), 'day': int(iday), 'hour': int(ihr), 'min': int(imin), 'sec': int(isec), 'fracsec': int(ifracsec), 'yday': yday, 'fracday': fracday}
def str_kwargs(self): """ Generator that yields a dict of values corresponding to the calendar date and time for the internal JD values. """ scale = self.scale.upper().encode('ascii'), iys, ims, ids, ihmsfs = erfa.d2dtf(scale, self.precision, self.jd1, self.jd2_filled) # Get the str_fmt element of the first allowed output subformat _, _, str_fmt = self._select_subfmts(self.out_subfmt)[0] if '{yday:' in str_fmt: has_yday = True else: has_yday = False yday = None ihrs = ihmsfs['h'] imins = ihmsfs['m'] isecs = ihmsfs['s'] ifracs = ihmsfs['f'] for iy, im, id, ihr, imin, isec, ifracsec in np.nditer( [iys, ims, ids, ihrs, imins, isecs, ifracs]): if has_yday: yday = datetime.datetime(iy, im, id).timetuple().tm_yday yield {'year': int(iy), 'mon': int(im), 'day': int(id), 'hour': int(ihr), 'min': int(imin), 'sec': int(isec), 'fracsec': int(ifracsec), 'yday': yday}
def str_kwargs(self): """ Generator that yields a dict of values corresponding to the calendar date and time for the internal JD values. """ scale = self.scale.upper().encode('ascii'), iys, ims, ids, ihmsfs = erfa.d2dtf(scale, self.precision, self.jd1, self.jd2_filled) # Get the str_fmt element of the first allowed output subformat _, _, str_fmt = self._select_subfmts(self.out_subfmt)[0] if '{yday:' in str_fmt: has_yday = True else: has_yday = False yday = None ihrs = ihmsfs['h'] imins = ihmsfs['m'] isecs = ihmsfs['s'] ifracs = ihmsfs['f'] for iy, im, id, ihr, imin, isec, ifracsec in np.nditer( [iys, ims, ids, ihrs, imins, isecs, ifracs], flags=['zerosize_ok']): if has_yday: yday = datetime.datetime(iy, im, id).timetuple().tm_yday yield {'year': int(iy), 'mon': int(im), 'day': int(id), 'hour': int(ihr), 'min': int(imin), 'sec': int(isec), 'fracsec': int(ifracsec), 'yday': yday}
def to_value(self, timezone=None, parent=None): """ Convert to (potentially timezone-aware) `~datetime.datetime` object. If ``timezone`` is not ``None``, return a timezone-aware datetime object. Parameters ---------- timezone : {`~datetime.tzinfo`, None} (optional) If not `None`, return timezone-aware datetime. Returns ------- `~datetime.datetime` If ``timezone`` is not ``None``, output will be timezone-aware. """ if timezone is not None: if self._scale != 'utc': raise ScaleValueError("scale is {}, must be 'utc' when timezone " "is supplied.".format(self._scale)) # Rather than define a value property directly, we have a function, # since we want to be able to pass in timezone information. scale = self.scale.upper().encode('ascii') iys, ims, ids, ihmsfs = erfa.d2dtf(scale, 6, # 6 for microsec self.jd1, self.jd2_filled) ihrs = ihmsfs['h'] imins = ihmsfs['m'] isecs = ihmsfs['s'] ifracs = ihmsfs['f'] iterator = np.nditer([iys, ims, ids, ihrs, imins, isecs, ifracs, None], flags=['refs_ok'], op_dtypes=7*[iys.dtype] + [object]) for iy, im, id, ihr, imin, isec, ifracsec, out in iterator: if isec >= 60: raise ValueError('Time {} is within a leap second but datetime ' 'does not support leap seconds' .format((iy, im, id, ihr, imin, isec, ifracsec))) if timezone is not None: out[...] = datetime.datetime(iy, im, id, ihr, imin, isec, ifracsec, tzinfo=TimezoneInfo()).astimezone(timezone) else: out[...] = datetime.datetime(iy, im, id, ihr, imin, isec, ifracsec) return self.mask_if_needed(iterator.operands[-1])
def value(self): if self._scale == 'utc': # Do the reverse of the above calculation # Note this will return an incorrect value during # leap seconds, so raise an exception in that # case. y, mo, d, hmsf = erfa.d2dtf('UTC',9,self.jd1,self.jd2) if 60 in hmsf[...,2]: raise ValueError('UTC times during a leap second cannot be represented in pulsar_mjd format') j1, j2 = erfa.cal2jd(y,mo,d) return (j1 - erfa.DJM0 + j2) + (hmsf[...,0]/24.0 + hmsf[...,1]/1440.0 + hmsf[...,2]/86400.0 + hmsf[...,3]/86400.0e9) else: # As in TimeMJD return (self.jd1 - erfa.DJM0) + self.jd2
def value(self): if self._scale == 'utc': # Do the reverse of the above calculation # Note this will return an incorrect value during # leap seconds, so raise an exception in that # case. y, mo, d, hmsf = erfa.d2dtf('UTC', 9, self.jd1, self.jd2) if 60 in hmsf[..., 2]: raise ValueError( 'UTC times during a leap second cannot be represented in pulsar_mjd format' ) j1, j2 = erfa.cal2jd(y, mo, d) return (j1 - erfa.DJM0 + j2) + (hmsf[..., 0] / 24.0 + hmsf[..., 1] / 1440.0 + hmsf[..., 2] / 86400.0 + hmsf[..., 3] / 86400.0e9) else: # As in TimeMJD return (self.jd1 - erfa.DJM0) + self.jd2
def to_value(self, parent=None): scale = self.scale.upper().encode('ascii'), iys, ims, ids, ihmsfs = erfa.d2dtf(scale, self.precision, self.jd1, self.jd2) ihrs = ihmsfs[..., 0] imins = ihmsfs[..., 1] isecs = ihmsfs[..., 2] ifracs = ihmsfs[..., 3] fmt = ('{0:04d} {1:02d} {2:02d} {3:02d} {4:02d} {5:02d} 0.{6:0' + str(self.precision) + 'd}') outs = [] for iy, im, id, ihr, imin, isec, ifracsec in np.nditer( [iys, ims, ids, ihrs, imins, isecs, ifracs]): outs.append(fmt.format(int(iy), int(im), int(id), int(ihr), int(imin), int(isec), int(ifracsec))) return np.array(outs).reshape(self.jd1.shape)
def to_value(self, parent=None): scale = self.scale.upper().encode('ascii'), iys, ims, ids, ihmsfs = erfa.d2dtf(scale, self.precision, self.jd1, self.jd2) ihrs = ihmsfs[..., 0] imins = ihmsfs[..., 1] isecs = ihmsfs[..., 2] ifracs = ihmsfs[..., 3] fmt = ('{0:04d} {1:02d} {2:02d} {3:02d} {4:02d} {5:02d} 0.{6:0' + str(self.precision) + 'd}') outs = [] for iy, im, id, ihr, imin, isec, ifracsec in np.nditer( [iys, ims, ids, ihrs, imins, isecs, ifracs]): outs.append( fmt.format(int(iy), int(im), int(id), int(ihr), int(imin), int(isec), int(ifracsec))) return np.array(outs).reshape(self.jd1.shape)
def value(self): if self._scale == 'utc': # Do the reverse of the above calculation # Note this will return an incorrect value during # leap seconds, so raise an exception in that # case. y, mo, d, hmsf = erfa.d2dtf('UTC',9,self.jd1,self.jd2) # For ASTROPY_LT_3_1, convert to the new structured array dtype that # is returned by the new erfa gufuncs. if not hmsf.dtype.names: hmsf = hmsf.view(self._new_ihmsfs_dtype) if numpy.any(hmsf['s'] == 60): raise ValueError('UTC times during a leap second cannot be represented in pulsar_mjd format') j1, j2 = erfa.cal2jd(y,mo,d) return (j1 - erfa.DJM0 + j2) + (hmsf['h']/24.0 + hmsf['m']/1440.0 + hmsf['s']/86400.0 + hmsf['f']/86400.0e9) else: # As in TimeMJD return (self.jd1 - erfa.DJM0) + self.jd2
def to_value(self, parent=None): scale = self.scale.upper().encode('ascii'), iys, ims, ids, ihmsfs = erfa.d2dtf(scale, self.precision, self.jd1, self.jd2) # For ASTROPY_LT_3_1, convert to the new structured array dtype that is # returned by the new erfa gufuncs. if not ihmsfs.dtype.names: ihmsfs = ihmsfs.view(self._new_ihmsfs_dtype) ihrs = ihmsfs['h'] imins = ihmsfs['m'] isecs = ihmsfs['s'] ifracs = ihmsfs['f'] fmt = ('{0:04d} {1:02d} {2:02d} {3:02d} {4:02d} {5:02d} 0.{6:0' + str(self.precision) + 'd}') outs = [] for iy, im, id, ihr, imin, isec, ifracsec in np.nditer( [iys, ims, ids, ihrs, imins, isecs, ifracs]): outs.append(fmt.format(int(iy), int(im), int(id), int(ihr), int(imin), int(isec), int(ifracsec))) return np.array(outs).reshape(self.jd1.shape)
def jds_to_mjds_pulsar(jd1, jd2): # Do the reverse of the above calculation # Note this will return an incorrect value during # leap seconds, so raise an exception in that # case. y, mo, d, hmsf = erfa.d2dtf("UTC", _digits, jd1, jd2) # For ASTROPY_LT_3_1, convert to the new structured array dtype that # is returned by the new erfa gufuncs. if not hmsf.dtype.names: hmsf = hmsf.view(_new_ihmsfs_dtype)[..., 0] if np.any((hmsf["s"] == 60) & (hmsf["f"] != 0)): # if f is exactly zero, this is probably fine to treat as the end of the day. raise ValueError( "UTC times during a leap second cannot be represented in pulsar_mjd format" ) j1, j2 = erfa.cal2jd(y, mo, d) return day_frac( j1 - erfa.DJM0 + j2, hmsf["h"] / 24.0 + hmsf["m"] / 1440.0 + hmsf["s"] / 86400.0 + hmsf["f"] / 86400.0 / 10 ** _digits, )
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