Chandra-specific astropy Time class¶
The cxotime
package provides a CxoTime
class which provides Chandra-specific
functionality while deriving from the Time class of the astropytime package.
The astropytime package provides robust 128-bit time representation,
arithmetic, and comparisons.
The Chandra-specific time formats which are added to the astropy Time class
are shown in the table below. Like DateTime, the CxoTime
class
default is to interpret any numerical values as secs
(aka cxcsec
in
the native Time class).
Format |
Description |
System |
---|---|---|
secs |
Seconds since 1998-01-01T00:00:00 (TT) |
utc |
date |
YYYY:DDD:hh:mm:ss.ss.. |
utc |
frac_year |
YYYY.ffffff = date as a floating point year |
utc |
greta |
YYYYDDD.hhmmsssss (string) |
utc |
maude |
YYYYDDDhhmmsssss (integer) |
utc |
The standard built-in Time formats that are available in CxoTime
are:
Format |
Example |
---|---|
byear |
1950.0 |
byear_str |
‘B1950.0’ |
cxcsec |
63072064.184 |
datetime |
datetime(2000, 1, 2, 12, 0, 0) |
decimalyear |
2000.45 |
fits |
‘2000-01-01T00:00:00.000(TAI)’ |
gps |
630720013.0 |
iso |
‘2000-01-01 00:00:00.000’ |
isot |
‘2000-01-01T00:00:00.000’ |
jd |
2451544.5 |
jyear |
2000.0 |
jyear_str |
‘J2000.0’ |
mjd |
51544.0 |
plot_date |
730120.0003703703 |
unix |
946684800.0 |
yday |
2000:001:00:00:00.000 |
Basic initialization¶
>>> from cxotime import CxoTime
>>> t = CxoTime(100.0)
>>> t.date
'1998:001:00:00:36.816'
>>> t.format
'secs'
>>> t.scale
'utc'
>>> import astropy.units as u
>>> t2 = t + [1, 2] * u.day + [10, 20] * u.s
>>> t2.date
array(['1998:002:00:00:46.816', '1998:003:00:00:56.816'], dtype='<U21')
>>> t = CxoTime([['1998:001:00:00:01.000', '1998:001:00:00:02.000'],
['1998:001:00:00:03.000', '1998:001:00:00:04.000']])
>>> t.secs
array([[ 64.184, 65.184],
[ 66.184, 67.184]])
>>> t.format
'date'
Guessing and specifying the format¶
Generally speaking CxoTime
will successfully guess the format for
string-based times. However this requires some time, so if you know the
format in advance then it is recommended to provide this via the format
argument.
>>> t = CxoTime('2020001223344555', format='maude')
>>> t.date
'2020:001:22:33:44.555'
Fast conversion between formats¶
Converting between time formats (e.g. from CXC seconds to Year Day-of-Year) is
easily done with the CxoTime
class, but this involves some overhead and is
relatively slow for scalar values or small arrays (less than around 100
elements). For applications where this conversion time ends up being significant,
the cxotime package provides a different interface that is typically at least
10x faster for scalar values or small arrays.
For fast conversion of an input date or dates to a different format there are two options that are described in the next two sections.
convert_time_format
¶
The first option is a generalized time format conversion function
convert_time_format()
that can be used to convert between
any of the supported fast formats:
secs: CXC seconds
date: Year Day-of-Year
greta: GRETA format (input can be string, float or int)
maude: MAUDE format (input can be string or int)
jd: Julian Day (requires fmt_in=”jd” to identity this format)
For example:
>>> from cxotime import convert_time_format
>>> convert_time_format("2022:001:00:00:00.123", "greta")
'2022001.000000123'
>>> convert_time_format(100.123, "date")
'1998:001:00:00:36.939'
>>> convert_time_format(2459580.5, "date", fmt_in="jd")
'2022:001:00:00:00.000'
Note that this function can be used to convert between any of the supported CxoTime
formats, but it will internally use a CxoTime
object so the performance will not be
improved. For example:
>>> convert_time_format(2022.123, fmt_out="date", fmt_in="frac_year")
'2022:045:21:28:48.000'
# Exactly equivalent to:
>>> CxoTime(2022.123, format="frac_year").date
'2022:045:21:28:48.000'
Convenience functions like secs2date
¶
For historical compatibility and for succinct code, direct conversion between any two
of the “fast” formats is also available via convenience functions. These have the name
<fmt_in>2<fmt_out>
where fmt_in
and fmt_out
are the input and output formats.
Examples include date2secs()
, secs2greta()
,
and greta2jd()
.
- ::
>>> from cxotime import secs2greta >>> secs2greta([100, 1000]) array(['1998001.000036816', '1998001.001536816'], dtype='<U17')
Print common time conversions¶
The cxotime package has functionality to convert a time betweeen a variety of common
time formats. This convenience function is available in two ways, either as a
command line script or as class method print_conversions()
:
$ cxotime 2022:002:12:00:00
local 2022 Sun Jan 02 07:00:00 AM EST
iso_local 2022-01-02T07:00:00-05:00
date 2022:002:12:00:00.000
cxcsec 757512069.184
decimalyear 2022.00411
iso 2022-01-02 12:00:00.000
unix 1641124800.000
$ cxotime # Print current time
local 2023 Tue Jan 10 01:41:02 PM EST
iso_local 2023-01-10T13:41:02.603000-05:00
date 2023:010:18:41:02.603
cxcsec 789763331.787
decimalyear 2023.02679
iso 2023-01-10 18:41:02.603
unix 1673376062.603
or in python:
>>> from cxotime import CxoTime
>>> tm = CxoTime("2022-01-02 12:00:00.000")
>>> tm.print_conversions()
local 2022 Sun Jan 02 07:00:00 AM EST
iso_local 2022-01-02T07:00:00-05:00
date 2022:002:12:00:00.000
cxcsec 757512069.184
decimalyear 2022.00411
iso 2022-01-02 12:00:00.000
unix 1641124800.000
CxoTime.NOW sentinel¶
The CxoTime
class has a special sentinel value CxoTime.NOW
which can be used
to specify the current time. This is useful for example when defining a function that
has accepts a CxoTime-like argument that defaults to the current time.
Note
Prior to introduction of CxoTime.NOW
, the standard idiom was to specify
None
as the argument default to indicate the current time. This is still
supported but is strongly discouraged for new code.
For example:
>>> from cxotime import CxoTime
>>> def my_func(stop=CxoTime.NOW):
... stop = CxoTime(stop)
... print(stop)
...
>>> my_func()
2024:006:11:37:41.930
This can also be used in a dataclass to specify an attribute that is optional and defaults to the current time when the object is created:
>>> import time
>>> from dataclasses import dataclass
>>> from cxotime import CxoTime, CxoTimeDescriptor
>>> @dataclass
... class MyData:
... start: CxoTime = CxoTimeDescriptor(required=True)
... stop: CxoTime = CxoTimeDescriptor(default=CxoTime.NOW)
...
>>> obj1 = MyData("2022:001")
>>> print(obj1.start)
2022:001:00:00:00.000
>>> time.sleep(2)
>>> obj2 = MyData("2022:001")
>>> dt = obj2.stop - obj1.stop
>>> round(dt.sec, 2)
2.0
Compatibility with DateTime¶
The key differences between CxoTime
and DateTime are:
In
CxoTime
the date ‘2000:001’ is ‘2000:001:00:00:00’ instead of ‘2000:001:12:00:00’ in DateTime (prior to version 4.0). In most cases this interpretation is more rational and expected.In
CxoTime
the date ‘2001-01-01T00:00:00’ is UTC by default, while in DateTime that is interpreted as TT by default. This is triggered by theT
in the middle. A date like ‘2001-01-01 00:00:00’ defaults to UTC in bothCxoTime
and DateTime.In
CxoTime
the difference of two dates is a TimeDelta object which is transformable to any time units. In DateTime the difference of two dates is a floating point value in days.Conversely, starting with
CxoTime
one can add or subtract a TimeDelta or any quantity with time units.
API docs¶
Cxotime¶
- class cxotime.cxotime.CxoTime(*args, **kwargs)[source]¶
Time class for Chandra analysis that is based on
astropy.time.Time
.The CXO-specific time formats which are added to the astropy
Time
class are shown in the table below. LikeDateTime
, theCxoTime
class default is to interpret any numerical values assecs
(akacxcsec
in the nativeTime
class).All of these formats use the UTC scale.
Format
Description
secs
Seconds since 1998-01-01T00:00:00 (TT) (float)
date
YYYY:DDD:hh:mm:ss.ss.. (string)
frac_year
YYYY.ffffff = date as a floating point year
greta
YYYYDDD.hhmmsss (string)
muade
YYYDDDhhmmsss (integer)
Important differences:
In
CxoTime
the date ‘2000:001’ is ‘2000:001:00:00:00’ instead of ‘2000:001:12:00:00’ inDateTime
. In most cases this interpretation is more rational and expected.In
CxoTime
the date ‘2001-01-01T00:00:00’ is UTC by default, while inDateTime
that is interpreted as TT by default. This is triggered by theT
in the middle. A date like ‘2001-01-01 00:00:00’ defaults to UTC in bothCxoTime
andDateTime
.
The standard built-in Time formats that are available in
CxoTime
are:Format
Example
byear
1950.0
byear_str
‘B1950.0’
cxcsec
63072064.184
datetime
datetime(2000, 1, 2, 12, 0, 0)
decimalyear
2000.45
fits
‘2000-01-01T00:00:00.000(TAI)’
gps
630720013.0
iso
‘2000-01-01 00:00:00.000’
isot
‘2000-01-01T00:00:00.000’
jd
2451544.5
jyear
2000.0
jyear_str
‘J2000.0’
mjd
51544.0
plot_date
730120.0003703703
unix
946684800.0
yday
2000:001:00:00:00.000
- get_conversions()[source]¶
Get a dict of conversions to a standard set of formats.
Example:
>>> from cxotime import CxoTime >>> t = CxoTime('2010:001:00:00:00') >>> t.get_conversions() {'local': '2009 Thu Dec 31 07:00:00 PM EST', 'iso_local': '2009-12-31T19:00:00-05:00', 'date': '2010:001:00:00:00.000', 'cxcsec': 378691266.184, 'decimalyear': 2010.0, 'iso': '2010-01-01 00:00:00.000', 'unix': 1262304000.0}
- classmethod linspace(start: CxoTime | str | float | int | ndarray | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | complex | bytes | _NestedSequence[bool | int | float | complex | str | bytes] | None, stop: CxoTime | str | float | int | ndarray | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | complex | bytes | _NestedSequence[bool | int | float | complex | str | bytes] | None, num: int | None = None, step_max: Quantity | None = None)[source]¶
Get a uniform time series that covers the given time range.
Output times either divide the time range into
num
intervals or are uniformly spaced by up tostep_max
, and cover the time range fromstart
tostop
.Note that returned intervals may be larger than
step_max
by floating point error. If calling code requires that all the intervals be less than a value,step_max
should be set to a value at least slightly smaller than the desired maximum value.- Parameters:
- startCxoTimeLike
Start time of the time range.
- stopCxoTimeLike
Stop time of the time range.
- numint | None
Number of time bins.
- step_maxu.Quantity (timelike)
Maximum time interval step. Should be positive nonzero.
- Returns:
- CxoTime
CxoTime with time bin edges for each interval.
- classmethod now()[source]¶
Creates a new object corresponding to the instant in time this method is called.
Note
“Now” is determined using the ~datetime.datetime.now function, so its accuracy and precision is determined by that function. Generally that means it is set by the accuracy of your system clock. The timezone is set to UTC.
- Returns:
- nowtime
Time
A new Time object (or a subclass of Time if this is called from such a subclass) at the current time.
- nowtime
- print_conversions(file=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>)[source]¶
Print a table of conversions to a standard set of formats.
Example:
>>> from cxotime import CxoTime >>> t = CxoTime('2010:001:00:00:00') >>> t.print_conversions() local 2009 Thu Dec 31 07:00:00 PM EST iso_local 2009-12-31T19:00:00-05:00 date 2010:001:00:00:00.000 cxcsec 378691266.184 decimalyear 2010.00000 iso 2010-01-01 00:00:00.000 unix 1262304000.000
- Parameters:
file – file-like, optional File-like object to write output (default=sys.stdout).
- class cxotime.cxotime.CxoTimeDescriptor(*, default=None, required=False, cls=None)[source]¶
Descriptor for an attribute that is CxoTime (in date format) or None if not set.
This allows setting the attribute with any
CxoTimeLike
value.Note that setting this descriptor to
None
will set the attribute toNone
, which is different thanCxoTime(None)
which returns the current time.To set an attribute to the current time, use
CxoTime.NOW
, either as the default or when setting the attribute.- Parameters:
- defaultCxoTimeLike, optional
Default value for the attribute which is provide to the
CxoTime
constructor. If not specified orNone
, the default for the attribute isNone
.- requiredbool, optional
If
True
, the attribute is required to be set explicitly when the object is created. IfFalse
the default value is used if the attribute is not set.
Examples
>>> from dataclasses import dataclass >>> from cxotime import CxoTime, CxoTimeDescriptor >>> @dataclass ... class MyClass: ... start: CxoTime | None = CxoTimeDescriptor() ... stop: CxoTime = CxoTimeDescriptor(default=CxoTime.NOW) ... >>> obj = MyClass("2023:100") # Example run at 2024:006:12:02:35 >>> obj.start <CxoTime object: scale='utc' format='date' value=2023:100:00:00:00.000> >>> obj.stop <CxoTime object: scale='utc' format='date' value=2024:006:12:02:35.000>
Converters¶
- cxotime.convert.convert_time_format(val, fmt_out, *, fmt_in=None)[source]¶
Convert a time to a different format.
- Parameters:
- valCxoTimeLike
Time value
- fmt_outstr
Output format
- fmt_instr
Input format (default is to guess)
- Returns:
- val_outstr
Time string in output format
- cxotime.convert.date2greta(date)¶
Convert Date (Year, day-of-year, time) to GRETA date.
This is equivalent to
CxoTime(date, format='date').greta
but potentially 10x faster.Format in: - YYYY:DDD:HH:MM:SS.sss - YYYY:DDD:HH:MM:SS - YYYY:DDD:HH:MM - YYYY:DDD Format out: YYYYDDD.HHMMSSsss (str)
- Parameters:
- datestr, bytes, float, list, ndarray
Date (Year, day-of-year, time)
- Returns:
- datestr, np.ndarray[str]
GRETA date
- cxotime.convert.date2jd(date)¶
Convert Date (Year, day-of-year, time) to Julian Date.
This is equivalent to
CxoTime(date, format='date').jd
but potentially 10x faster.Format in: - YYYY:DDD:HH:MM:SS.sss - YYYY:DDD:HH:MM:SS - YYYY:DDD:HH:MM - YYYY:DDD Format out: Julian Date (numeric)
- Parameters:
- datestr, bytes, float, list, ndarray
Date (Year, day-of-year, time)
- Returns:
- jdfloat, ndarray[float]
Julian Date
- cxotime.convert.date2maude(date)¶
Convert Date (Year, day-of-year, time) to MAUDE date.
This is equivalent to
CxoTime(date, format='date').maude
but potentially 10x faster.Format in: - YYYY:DDD:HH:MM:SS.sss - YYYY:DDD:HH:MM:SS - YYYY:DDD:HH:MM - YYYY:DDD Format out: YYYYDDD.HHMMSSsss (int)
- Parameters:
- datestr, bytes, float, list, ndarray
Date (Year, day-of-year, time)
- Returns:
- dateint, ndarray[int]
MAUDE date
- cxotime.convert.date2secs(date)¶
Convert Date (Year, day-of-year, time) to CXC seconds.
This is equivalent to
CxoTime(date, format='date').secs
but potentially 10x faster.Format in: - YYYY:DDD:HH:MM:SS.sss - YYYY:DDD:HH:MM:SS - YYYY:DDD:HH:MM - YYYY:DDD Format out: CXC seconds (numeric)
- Parameters:
- datestr, bytes, float, list, ndarray
Date (Year, day-of-year, time)
- Returns:
- timefloat, ndarray[float]
CXC seconds
- cxotime.convert.greta2date(date)¶
Convert GRETA date to Date (Year, day-of-year, time).
This is equivalent to
CxoTime(date, format='greta').date
but potentially 10x faster.Format in: YYYYDDD.HHMMSSsss (str or float) Format out: YYYY:DDD:HH:MM:SS.sss
- Parameters:
- datestr, bytes, float, list, np.ndarray
GRETA date
- Returns:
- datestr, ndarray[str]
Date (Year, day-of-year, time)
- cxotime.convert.greta2jd(date)¶
Convert GRETA date to Julian Date.
This is equivalent to
CxoTime(date, format='greta').jd
but potentially 10x faster.Format in: YYYYDDD.HHMMSSsss (str or float) Format out: Julian Date (numeric)
- Parameters:
- datestr, bytes, float, list, np.ndarray
GRETA date
- Returns:
- jdfloat, ndarray[float]
Julian Date
- cxotime.convert.greta2maude(date)¶
Convert GRETA date to MAUDE date.
This is equivalent to
CxoTime(date, format='greta').maude
but potentially 10x faster.Format in: YYYYDDD.HHMMSSsss (str or float) Format out: YYYYDDD.HHMMSSsss (int)
- Parameters:
- datestr, bytes, float, list, np.ndarray
GRETA date
- Returns:
- dateint, ndarray[int]
MAUDE date
- cxotime.convert.greta2secs(date)¶
Convert GRETA date to CXC seconds.
This is equivalent to
CxoTime(date, format='greta').secs
but potentially 10x faster.Format in: YYYYDDD.HHMMSSsss (str or float) Format out: CXC seconds (numeric)
- Parameters:
- datestr, bytes, float, list, np.ndarray
GRETA date
- Returns:
- timefloat, ndarray[float]
CXC seconds
- cxotime.convert.jd2date(jd)¶
Convert Julian Date to Date (Year, day-of-year, time).
This is equivalent to
CxoTime(jd, format='jd').date
but potentially 10x faster.Format in: Julian Date (numeric) Format out: YYYY:DDD:HH:MM:SS.sss
- Parameters:
- jdfloat, int, list, ndarray
Julian Date
- Returns:
- datestr, ndarray[str]
Date (Year, day-of-year, time)
- cxotime.convert.jd2greta(jd)¶
Convert Julian Date to GRETA date.
This is equivalent to
CxoTime(jd, format='jd').greta
but potentially 10x faster.Format in: Julian Date (numeric) Format out: YYYYDDD.HHMMSSsss (str)
- Parameters:
- jdfloat, int, list, ndarray
Julian Date
- Returns:
- datestr, np.ndarray[str]
GRETA date
- cxotime.convert.jd2maude(jd)¶
Convert Julian Date to MAUDE date.
This is equivalent to
CxoTime(jd, format='jd').maude
but potentially 10x faster.Format in: Julian Date (numeric) Format out: YYYYDDD.HHMMSSsss (int)
- Parameters:
- jdfloat, int, list, ndarray
Julian Date
- Returns:
- dateint, ndarray[int]
MAUDE date
- cxotime.convert.jd2secs(jd)¶
Convert Julian Date to CXC seconds.
This is equivalent to
CxoTime(jd, format='jd').secs
but potentially 10x faster.Format in: Julian Date (numeric) Format out: CXC seconds (numeric)
- Parameters:
- jdfloat, int, list, ndarray
Julian Date
- Returns:
- timefloat, ndarray[float]
CXC seconds
- cxotime.convert.maude2date(date)¶
Convert MAUDE date to Date (Year, day-of-year, time).
This is equivalent to
CxoTime(date, format='maude').date
but potentially 10x faster.Format in: YYYYDDDHHMMSSsss (str or int) Format out: YYYY:DDD:HH:MM:SS.sss
- Parameters:
- datestr, bytes, int, list, ndarray
MAUDE date
- Returns:
- datestr, ndarray[str]
Date (Year, day-of-year, time)
- cxotime.convert.maude2greta(date)¶
Convert MAUDE date to GRETA date.
This is equivalent to
CxoTime(date, format='maude').greta
but potentially 10x faster.Format in: YYYYDDDHHMMSSsss (str or int) Format out: YYYYDDD.HHMMSSsss (str)
- Parameters:
- datestr, bytes, int, list, ndarray
MAUDE date
- Returns:
- datestr, np.ndarray[str]
GRETA date
- cxotime.convert.maude2jd(date)¶
Convert MAUDE date to Julian Date.
This is equivalent to
CxoTime(date, format='maude').jd
but potentially 10x faster.Format in: YYYYDDDHHMMSSsss (str or int) Format out: Julian Date (numeric)
- Parameters:
- datestr, bytes, int, list, ndarray
MAUDE date
- Returns:
- jdfloat, ndarray[float]
Julian Date
- cxotime.convert.maude2secs(date)¶
Convert MAUDE date to CXC seconds.
This is equivalent to
CxoTime(date, format='maude').secs
but potentially 10x faster.Format in: YYYYDDDHHMMSSsss (str or int) Format out: CXC seconds (numeric)
- Parameters:
- datestr, bytes, int, list, ndarray
MAUDE date
- Returns:
- timefloat, ndarray[float]
CXC seconds
- cxotime.convert.print_time_conversions()[source]¶
Interface to entry_point script
cxotime
to print time conversions
- cxotime.convert.secs2date(time)¶
Convert CXC seconds to Date (Year, day-of-year, time).
This is equivalent to
CxoTime(time, format='secs').date
but potentially 10x faster.Format in: CXC seconds (numeric) Format out: YYYY:DDD:HH:MM:SS.sss
- Parameters:
- timefloat, int, list, ndarray
CXC seconds
- Returns:
- datestr, ndarray[str]
Date (Year, day-of-year, time)
- cxotime.convert.secs2greta(time)¶
Convert CXC seconds to GRETA date.
This is equivalent to
CxoTime(time, format='secs').greta
but potentially 10x faster.Format in: CXC seconds (numeric) Format out: YYYYDDD.HHMMSSsss (str)
- Parameters:
- timefloat, int, list, ndarray
CXC seconds
- Returns:
- datestr, np.ndarray[str]
GRETA date
- cxotime.convert.secs2jd(time)¶
Convert CXC seconds to Julian Date.
This is equivalent to
CxoTime(time, format='secs').jd
but potentially 10x faster.Format in: CXC seconds (numeric) Format out: Julian Date (numeric)
- Parameters:
- timefloat, int, list, ndarray
CXC seconds
- Returns:
- jdfloat, ndarray[float]
Julian Date
- cxotime.convert.secs2maude(time)¶
Convert CXC seconds to MAUDE date.
This is equivalent to
CxoTime(time, format='secs').maude
but potentially 10x faster.Format in: CXC seconds (numeric) Format out: YYYYDDD.HHMMSSsss (int)
- Parameters:
- timefloat, int, list, ndarray
CXC seconds
- Returns:
- dateint, ndarray[int]
MAUDE date