-
Notifications
You must be signed in to change notification settings - Fork 12
EVENTLISTS [readevent] #47
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
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #47 +/- ##
==========================================
- Coverage 95.24% 90.92% -4.33%
==========================================
Files 3 4 +1
Lines 505 617 +112
==========================================
+ Hits 481 561 +80
- Misses 24 56 +32 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
src/events.jl
Outdated
| end | ||
|
|
||
| # If we found both time and energy data, we can return | ||
| if !isempty(times) && !isempty(energies) |
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.
Note that most event lists do not have an "energy" column, so this will keep going through the different extension needlessly.
When you find the time column, you will also have found all the information you can find about single events (energy, PI, etc.).
src/lightcurve.jl
Outdated
| if method === :poisson | ||
| return convert.(T, sqrt.(counts)) | ||
| elseif method === :gaussian | ||
| return convert.(T, sqrt.(counts .+ 1)) |
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.
Gaussian errors need to be given by the user, estimating them like this would be wrong and, in any case, it seems to assume they are Poisson (the sqrt only makes sense in that case, and summing 1 is a quick way to give an error bar when the count rate is 0).
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.
This looks generally really good! I think there are just some redundancies and simplifications that ought to be made to help us maintain this code in the future.
We should also talk about tests and how tests should be organised. We can chat about that in the meeting tomorrow. I'd recommend not being too specific with the tests at this stage, else you'll spend most of your time maintaining the tests when you need to make a small change to how something works.
src/events.jl
Outdated
| function Base.getindex(ev::EventList, i) | ||
| if isnothing(ev.energies) | ||
| return (ev.times[i], nothing) | ||
| else | ||
| return (ev.times[i], ev.energies[i]) | ||
| end | ||
| end |
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.
In my opinion, this method is redundant. If someone wants to access the times or energies they can do that via times or energies and deal with the underlying vector.
src/events.jl
Outdated
| if !issorted(evt_times) | ||
| throw(ArgumentError("Event times must be sorted in ascending order")) | ||
| end | ||
| if length(evt_times) == 0 | ||
| throw(ArgumentError("Event list is empty")) | ||
| end |
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.
These sorts of checks should happen in the event list constructor. If they are not met (i.e. event list is not valid), the event list should not be allowed to be created.
src/events.jl
Outdated
| function get_column(events::EventList, column_name::String) | ||
| if column_name == "TIME" | ||
| return events.times | ||
| elseif column_name == "ENERGY" && !isnothing(events.energies) | ||
| return events.energies | ||
| elseif haskey(events.extra_columns, column_name) | ||
| return events.extra_columns[column_name] | ||
| else | ||
| return nothing | ||
| end | ||
| end |
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 understand your intention behind this, but I would get rid of this method too. An event list is a Julia object, not a FITS table, so we don't need to support these kinds of accessors. It's more code that would have to be maintained.
src/lightcurve.jl
Outdated
| gaussian_errors::Union{Nothing,Vector{T}}=nothing, | ||
| tstart::Union{Nothing,Real}=nothing, | ||
| tstop::Union{Nothing,Real}=nothing, | ||
| filters::Dict{Symbol,Any}=Dict{Symbol,Any}() |
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''d remove this. It isn't clear what it's supposed to be doing, and if it's applying some kind of filter function, then you can just accept the filter function. A dict with the value type Any won't be performant anyway.
src/lightcurve.jl
Outdated
| - `tstart`, `tstop`: Time range limits | ||
| - `filters`: Additional filtering criteria | ||
| """ | ||
| function create_lightcurve( |
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 function does too much and should be broken up into a number of smaller functions that this uses.
For example, a method for
- Filtering
- Binning
- Additional properies (e.g. energy means)
- Metadata extraction
Be sure to put all the validating parts of the code (e.g., are the errors valid) at the start of the function. There's no point computing the counts if it's going to error there later.
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 @kashish2210 this looks fine! Just some small things remaining. The code is getting quite complex, so I'd urge you to split things up into small, reusable functions in future work, but we can clean this up later in different PRs.
src/events.jl
Outdated
| ms = get_mission_support(mission, instrument, epoch) | ||
| # Use mission-specific energy alternatives if available | ||
| energy_alternatives = ms.energy_alternatives | ||
| ms | ||
| else | ||
| nothing | ||
| end |
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 can't see get_mission_support implemented anywhere? Is this related to your new PR? If so, it should be in that PR, not here.
src/events.jl
Outdated
| end | ||
| end | ||
|
|
||
| catch e |
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.
Putting a lot of code inside of a try / catch and then having an open ended catch will lead to catching errors you didn't mean to. Only wrap the line you are expecting to potentially throw the error with the try / catch block.
In general, this function is very long with a lot of nested blocks. Maybe consider breaking the logic up into smaller, reusable functions?
src/lightcurve.jl
Outdated
| timebins::Vector{T} | ||
| bin_edges::Vector{T} | ||
| counts::Vector{Int} | ||
| count_error::Vector{T} | ||
| exposure::Vector{T} | ||
| properties::Vector{EventProperty} | ||
| metadata::LightCurveMetadata | ||
| err_method::Symbol |
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.
Can you add documentation for what these fields are? Why is exposure for example a vector and not just a single value, as some might expect?
|
@fjebaker I have made the changes Here is the summary Specific catch blocks: Replaced broad catch e with specific error handling:Reduced nesting: Simplified the logic flow by: |
|
yup, this is getting complex, but it is needed for GTI and to cover all events, so there should be no bad events from next pr we will be back on our track |
|
@fjebaker, I have only added events here. Should I create a separate PR for the lightcurve? This PR feels a bit complex now. guess |
This reverts commit 34ae9e8.
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.
This is great @kashish2210 and thanks for splitting the events list and lightcurve up so that we can review them in small chunks!
Don't add anything new to this PR. If you can just address the changes I've suggested, then from my end I'm happy for this to be merged!
src/events.jl
Outdated
| # Fields | ||
| - `filepath::String`: Path to the FITS file | ||
| - `hdu::Int`: HDU index that the metadata was read from | ||
| - `energy_units::Union{Nothing,String}`: Units of energy (column name: ENERGY, PI, or PHA) | ||
| - `extra_columns::Dict{String,Vector}`: Extra columns that were requested during read | ||
| - `headers::H`: FITS headers from the selected 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.
No need to do this here, but you can use DocStringExtensions.jl, specifically the FIELDS or TYPEDFIELDS parameters to generate the field documentation directly.
src/events.jl
Outdated
| # Filtering | ||
| EventList supports composable filtering operations: | ||
| ```julia | ||
| # Filter by time (in-place) | ||
| filter_time!(t -> t > 100.0, ev) | ||
| # Filter by energy (in-place) | ||
| filter_energy!(energy_val -> energy_val < 10.0, ev) | ||
| # Non-mutating versions | ||
| ev_filtered = filter_time(t -> t > 100.0, ev) | ||
| ev_filtered = filter_energy(energy_val -> energy_val < 10.0, ev) | ||
| # Composable filtering | ||
| filter_energy!(x -> x < 10.0, filter_time!(t -> t > 100.0, ev)) | ||
| ``` | ||
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.
This should be in the docstring for filter_time! and filter_energy! respectively.
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
Co-authored-by: Fergus Baker <[email protected]>
|
Hey @matteobachetti Thank you for the feedback, I am replying your comment about reason
function filter_energy(f, ev::EventList; inplace::Bool = false)
if inplace
return filter_energy!(f, ev)
else
new_ev = deepcopy(ev)
return filter_energy!(f, new_ev)
end
end@fjebaker @matteobachetti shall I implement this if you guys say i will add this in this PR |
Oh! I see. If that's Julia standard, I'm totally ok with it, I missed the |
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.
Ok for me, I think it's a good starting point for the rest of the open PRs
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.
Nice work! 👍
|
thanks |
This PR includes the update to events.JL function so that it contains now abstract methods with a constructor, and mainly comprises the light curve function with metadata and filter as per the discussion
majorly work on this #29
lightcurve function included create_lightcurve,EventProperty, AbstractLightCurve ,rebin, calculate_errors, LightCurve, LightCurveMetadata
tagging @matteobachetti @fjebaker @stefanocovino