Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use configurable Time (de-)serialization (from) to FITS #14344

Open
maxnoe opened this issue Jan 31, 2023 · 4 comments
Open

Use configurable Time (de-)serialization (from) to FITS #14344

maxnoe opened this issue Jan 31, 2023 · 4 comments

Comments

@maxnoe
Copy link
Member

maxnoe commented Jan 31, 2023

What is the problem this feature will solve?

We are using existing and are developing new data formats based on FITS, which prescribe time formats.

At the moment, conversion from astropy.time.Time to the FITS representation needs to be done "by hand", since astropy only supports storing times as two jd floats without choice of the reference time and the option to only store a single floating point column.

It would be great if we could extend the functions in astropy.io.fits.fitstime to support serializing times in the format the FITS standard / FITS time paper describe.

E.g. letting users specify:

  • Format (one column / two columns)
  • Reference time (e.g. FERMI uses a "Mission Elapsed Time" with reference time 2001-01-01

Describe the desired outcome

Having configurable functionality in astropy for storing Time instances in certain fits defined formats.

I.e.

def time_to_fits(table):

should gain some keyword arguments to let users define the desired format.

Additional context

@mhvk
Copy link
Contributor

mhvk commented Jan 31, 2023

Agreed this would be good. In a way, the machinery is partially in place in time.info.serialize_method having the options "jd1_jd2" and "formatted_value" - for FITS one would perhaps want to add something like "jd1_jd2_reftime" - which would be used for any time formats that are subclasses of TimeFromEpoch. For Fermi data, that would then involve creating a new TimeFermiSec class (like the current TimeCxcSec) -- I think this might make sense to have anyway.

Though it will likely be easier to implement anything like this if we first ensure that the lower-level routines can take such reference times! I.e., actually address your request. As I noted in #14343, I think that might first of all involve writing a routine that just converts a single Time instance to and from fits.Column (with relevant header information), refactoring time_to_fits and fits_to_time to make use of that.

Not trivial, though! Pinging @aaryapatil since she originally implemented the FITS time machinery for her GSOC project.

@maxnoe
Copy link
Member Author

maxnoe commented Jan 31, 2023

For Fermi data, that would then involve creating a new TimeFermiSec class (like the current TimeCxcSec) -- I think this might make sense to have anyway.

MMh, that's not the direction I wanted to go into. FERMI was just an example. The FITS standard is very clear: time in columns and headers is actual elapsed time since an epoch and the epoch is defined in header keywords.

So astropy should on reading from fits parse the corresponding headers, which can be global or per-column, create the epoch from that and just do epoch + time_value.quantity.

On conversion to fits, astropy should take the reference epoch as a Time instance and a unit, use that to convert TIme instances to column(s) with the given unit relative to the epoch.

@mhvk
Copy link
Contributor

mhvk commented Jan 31, 2023

OK, makes sense - so, first just do the conversion with a bit more care!

If I recall correctly, the conversion from FITS to Time does already allow any reference epoch. Is that indeed the case? If so, what would be needed is the ability to explicitly set the reference epoch. I think the global reference epoch could be done fairly simple, by allowing one to pass in a header to time_to_fits which can give those reference information (with defaults supplied as needed, and things like inconsistent OBSGEO* just leading to errors).

p.s. The above would leave a separate question on how to set a header cards with a reference epoch with a Time instance. Which could probably be combined with the long-standing issue of setting header cards with Quantity.

@maxnoe
Copy link
Member Author

maxnoe commented Feb 1, 2023

The above would leave a separate question on how to set a header cards with a reference epoch with a Time instance. Which could probably be combined with the long-standing issue of setting header cards with Quantity.

I don't think this is really related, since there is a pretty strict standard on how to store the epoch value for times. Then other times are stored using again floats of elapsed time to that epoch.

There are 3 formats with corresponding header keywords that users can chose (iso format with DATEREF, jd with JDREF and mjd with MJDREF). The jd and mjd ref variant can be given as integer and fractional part optionally, which is mostly not needed since the epoch are usually exactly representable in a single float anyways.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants