-
Notifications
You must be signed in to change notification settings - Fork 2
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
Dl3 reader for LST data #7
base: main
Are you sure you want to change the base?
Conversation
- added an event class for LST dl3 files - tested that class can read LST dl3 files - entire chain not tested - DL3 format for other instruments (e.g. MAGIC) can be slightly different and mya require a different reader ToDo: - MAGIC DL3 reader - test entire chain with LST DL3 files
Found and corrected the following issues, some concern also previous commits to the main branch: - issue of the unti of the event time variable - wrong unit of the ra event variable - dl2 file reader had an error if the ra variable of the pointing position was not precomputed - wrong overwriting of the setter function for the bkgmap maker in the bkg classes
to set attribute bkg_maps instead of the correct _bkg_maps
In general PR looks okey save the inserted docstring placeholders (useless unless replaced with actual docs). I would encourage in the future not to mix topical PRs like this with bug and style fixes in the unrelated classes and modules. |
- Modified the reader so it can read DL3 file regardless the instrument. - Data units are read from hdu header as long as provided. - Tested with LST and MAGIC DL3 files. TODO: - Observatory location not part of the mandatory header keywords. May need to be provided in input file by the user. Will be part of future pull request - Drift method implemented but not tested due to lack of corresponding data.
performance - added some functionalities suggested by Lukas Nickel, but adapted them to the current version - changed the function for retrieving the Obs ID from filename to reading it from the hdu header - changed the is_compatible, so it also identifies compressed files - added the erfaAstromInterpolator for the coordinate transform for speed up - added docstrings to all functions related to the DL3 reader
modes are not to well defined e.g. the H.E.S.S. public data use WOBBLE as the obs mode. Hence, added it to support such files until the allowed modes are better defined.
The latest changes allow the DL3 reader to not only read the LST files, but DL3 files in general. I tested it with LST, H.E.S.S. (public data release), and MAGIC DL3 files. Furthermore added the suggestions from Lukas regarding the interpolator for the coordinate transform and the changes regarding the Obs ID retrieval; changed the compatibility check to not reject compressed files as well. Current version is ready for review. |
from the corresponding PR (#7). - change name from Dl2 to DL2 to agree with the DL3 naming - changed to way the event times are read from DL3 files to be consistent with the 'mjd' naming of the dictionary - the functionality of the code was not changed
Hi, I got a notification here and had a cursory glance, but what I saw made me very nervous about timing information. You add and subtract raw mjd and unix values at different points in the code here instead of using astropy Time and TimeDelta objects. This will result in timestamps that are off by the number of leap seconds between those two times. Never do that. You are also completely neglecting the time scale. |
src/pybkgmodel/data.py
Outdated
event_data[name] *= u.one | ||
|
||
# Event times need to be converted from Instrument reference epoch | ||
ref_epoch = astropy.time.Time(evt_head['MJDREFI']+evt_head['MJDREFF'], format='mjd') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the two argument form of astropy.time.Time
, otherwise you will have precision issues:
ref_epoch = astropy.time.Time(evt_head['MJDREFI'], evt_head['MJDREFF'], format='mjd')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, you need to read the time scale
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added, though I found that in the header of the DL3 files the TIMESYS is given in all-caps whereas astropy prefers lower cases, is there a reason for why it is all-caps in the LST files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because that's what the FITS standard is prescribing
src/pybkgmodel/data.py
Outdated
# Event times need to be converted from Instrument reference epoch | ||
ref_epoch = astropy.time.Time(evt_head['MJDREFI']+evt_head['MJDREFF'], format='mjd') | ||
|
||
event_data['mjd'] = astropy.time.Time((evt_data['TIME'].to_numpy() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not do this! this results in times that are off by the number of leap seconds between the reference epoch and the event time.
The correct solution is (ref_epoch + evt_data["TIME"].quantity).mjd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/pybkgmodel/data.py
Outdated
).mjd * u.d | ||
|
||
# Adapt | ||
evt_time = astropy.time.Time(event_data['mjd'], format='mjd') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now you create a time object a second time.
Just to evt_time = ref_epoch + evt_data["TIME"].quantity
and then evt_data["mjd"] = evt_time.mjd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this is also already implemented in Gammapy, e.g. here: https://github.com/gammapy/gammapy/blob/main/gammapy/utils/time.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplified according to your suggestion.
src/pybkgmodel/data.py
Outdated
try: | ||
evt_hdu = input_file["EVENTS"] | ||
evt_head = evt_hdu.header | ||
evt_data = pandas.DataFrame(evt_hdu.data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use an astropy table to have support for the quantities and metadata stored in the hdu
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for that hint, simplified it a lot. Adapted.
- changed the time handling following Max' recommendations in the discussion of the PR - changed the way the fits file compatibility is checked following Michele's recommendations in the discussion of the PR - changed the setter for the bkg_map_makers following Ievgen's recommendation TODO: - Test with data
src/pybkgmodel/data.py
Outdated
+ ref_epoch.unix), | ||
scale='utc', | ||
format='unix' | ||
event_data['mjd'] = astropy.time.Time((evt_data['TIME'].quantity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The outer time here is unnecessary.
The result of ref_epoch + evt_data["TIME"].quantity
is a time, you are just making a copy again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
src/pybkgmodel/data.py
Outdated
# TODO: current observatory location only La Palma, no mandatory header keyword | ||
obs_loc = EarthLocation(lat=28.761758*u.deg, | ||
lon=-17.890659*u.deg, | ||
height=2200*u.m) | ||
|
||
if evt_head['OBS_MODE'] in ('POINTING', 'WOBBLE'): | ||
|
||
alt_az_frame = AltAz(obstime=evt_time, | ||
alt_az_frame = AltAz(obstime=event_data['mjd'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you can pass a raw mjd value to AltAz(obstime=)
, this needs to be a Time
instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, corrected.
src/pybkgmodel/camera.py
Outdated
@@ -375,7 +375,7 @@ def get_pixel_coords(self): | |||
|
|||
x = (self.xedges[1:] + self.xedges[:-1]) / 2 | |||
y = (self.yedges[1:] + self.yedges[:-1]) / 2 | |||
xx, yy = np.meshgrid(x, y, indexing='ij') | |||
xx, yy = numpy.meshgrid(x, y, indexing='ij') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the wrong resolution of a merge conflict?
The import at the top is import numpy as np
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As entire merge went wrong. I reset the merge. New version should not have this mistake.
src/pybkgmodel/data.py
Outdated
@@ -312,11 +314,11 @@ def load_events(cls, file_name, cuts): | |||
event_data[name] = data[key] | |||
|
|||
# Post processing | |||
event_data['true_zd'] = np.degrees(event_data['true_zd']) | |||
event_data['true_az'] = np.degrees(event_data['true_az']) | |||
event_data['true_zd'] = numpy.degrees(event_data['true_zd']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As entire merge went wrong. I reset the merge. New version should not have this mistake.
@mstrzys I think something went seriously wrong in your last merge commit, all the changes related to reading LST DL3 data were removed |
) | ||
|
||
evt_time = evt_data['TIME'].quantity + ref_epoch | ||
event_data['mjd'] = evt_time.mjd * u.d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure, but I think this mjd will now depend on the timescale of the input file, and I guess you use this value internally and assume it's in UTC or some other fixed timescale?
Why are you storing the mjd in any case and not the full time object?
* len(event_data['pointing_zd']) | ||
) * u.deg | ||
|
||
elif evt_head['OBS_MODE'] == 'DRIFT': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just raise an error to let users know this is not supported instead of providing preliminary or invalid data (same for the next else block, this should be an actual error, not a print statement)
DL3 reader; first for LST data only; to add a DL3 reader also for MAGIC data the filetype check needs a rework, which will go into a separate PR.