# Licensed under a 3-clause BSD style license - see LICENSE.rst"""Time related utility functions."""importnumpyasnpimportastropy.unitsasufromastropy.timeimportTime,TimeDelta__all__=["absolute_time","time_ref_from_dict","time_ref_to_dict","time_relative_to_ref",]TIME_KEYWORDS=["MJDREFI","MJDREFF","TIMEUNIT","TIMESYS","TIMEREF"]# TODO: implement and document this properly.# see https://github.com/gammapy/gammapy/issues/284TIME_REF_FERMI=Time("2001-01-01T00:00:00")# Default time ref used for GTIsTIME_REF_DEFAULT=Time("2000-01-01T00:00:00",scale="tt")#: Default epoch gammapy uses for FITS files (MJDREF)#: 0 MJD, TTDEFAULT_EPOCH=Time(0,format="mjd",scale="tt")deftime_to_fits(time,epoch=None,unit=u.s):"""Convert time to fits format. Times are stored as duration since an epoch in FITS. Parameters ---------- time : `~astropy.time.Time` Time to be converted. epoch : `~astropy.time.Time`, optional Epoch to use for the time. The corresponding keywords must be stored in the same FITS header. Default is None, so the `DEFAULT_EPOCH` is used. unit : `~astropy.units.Unit`, optional Unit, should be stored as `TIMEUNIT` in the same FITS header. Default is u.s. Returns ------- time : astropy.units.Quantity Duration since epoch. """ifepochisNone:epoch=DEFAULT_EPOCHreturn(time-epoch).to(unit)deftime_to_fits_header(time,epoch=None,unit=u.s):"""Convert time to fits header format. Times are stored as duration since an epoch in FITS. Parameters ---------- time : `~astropy.time.Time` Time to be converted. epoch : `~astropy.time.Time`, optional Epoch to use for the time. The corresponding keywords must be stored in the same FITS header. Default is None, so `DEFAULT_EPOCH` is used. unit : `~astropy.units.Unit`, optional Unit, should be stored as `TIMEUNIT` in the same FITS header. Default is u.s. Returns ------- header_entry : tuple(float, string) A float / comment tuple with the time and unit. """ifepochisNone:epoch=DEFAULT_EPOCHtime=time_to_fits(time,epoch)returntime.to_value(unit),unit.to_string("fits")
[docs]deftime_ref_from_dict(meta,format="mjd",scale="tt"):"""Calculate the time reference from metadata. Parameters ---------- meta : dict FITS time standard header information. format: str, optional Format of the `~astropy.time.Time` information. Default is 'mjd'. scale: str, optional Scale of the `~astropy.time.Time` information. Default is 'tt'. Returns ------- time : `~astropy.time.Time` Time object with ``format='MJD'``. """# Note: the float call here is to make sure we use 64-bitmjd=float(meta["MJDREFI"])+float(meta["MJDREFF"])scale=meta.get("TIMESYS",scale).lower()returnTime(mjd,format=format,scale=scale)
[docs]deftime_ref_to_dict(time=None,scale="tt"):"""Convert the epoch to the relevant FITS header keywords. Parameters ---------- time : `~astropy.time.Time`, optional The reference epoch for storing time in FITS. Default is None, so 'DEFAULT_EPOCH' is used. scale: str, optional Scale of the `~astropy.time.Time` information. Default is "tt". Returns ------- meta : dict FITS time standard header information. """iftimeisNone:time=DEFAULT_EPOCHmjd=Time(time,scale=scale).mjdi=np.floor(mjd).astype(np.int64)f=mjd-ireturndict(MJDREFI=i,MJDREFF=f,TIMESYS=scale)
[docs]deftime_relative_to_ref(time,meta):"""Convert a time using an existing reference. The time reference is built as MJDREFI + MJDREFF in units of MJD. The time will be converted to seconds after the reference. Parameters ---------- time : `~astropy.time.Time` Time to be converted. meta : dict Dictionary with the keywords ``MJDREFI`` and ``MJDREFF``. Returns ------- time_delta : `~astropy.time.TimeDelta` Time in seconds after the reference. """time_ref=time_ref_from_dict(meta)returnTimeDelta(time-time_ref,format="sec")
[docs]defabsolute_time(time_delta,meta):"""Convert a MET into human-readable date and time. Parameters ---------- time_delta : `~astropy.time.TimeDelta` Time in seconds after the MET reference. meta : dict Dictionary with the keywords ``MJDREFI`` and ``MJDREFF``. Returns ------- time : `~astropy.time.Time` Absolute time with ``format='ISOT'`` and ``scale='UTC'``. """time=time_ref_from_dict(meta)+time_deltareturnTime(time.utc.isot)
defextract_time_info(row):"""Extract the timing metadata from an event file header. Parameters ---------- row : dict Dictionary with all the metadata of an event file. Returns ------- time_row : dict Dictionary with only the time metadata. """time_row={}fornameinTIME_KEYWORDS:time_row[name]=row[name]returntime_rowdefunique_time_info(rows):"""Check if the time information are identical between all metadata dictionaries. Parameters ---------- rows : list List of dictionaries with a list of time metadata from different observations. Returns ------- status : bool True if the time metadata are identical between observations. """iflen(rows)<=1:returnTruefirst_obs=rows[0]forrowinrows[1:]:fornameinTIME_KEYWORDS:iffirst_obs[name]!=row[name]orrow[name]isNone:returnFalsereturnTrue