-
Notifications
You must be signed in to change notification settings - Fork 271
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
Irf maker and cut optimiser #2473
base: main
Are you sure you want to change the base?
Conversation
ctapipe/irf/optimise.py
Outdated
def __init__(self, gh_cuts=None, offset_lim=None): | ||
self.gh_cuts = gh_cuts | ||
if gh_cuts: | ||
self.gh_cuts.meta["extname"] = "GH_CUTS" |
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.
extname is the name of a FITS extension. You should't set this in the metadata of the table, but only when writing out, it's the name
argument of write
.
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 got
TypeError: write_table_fits() got an unexpected keyword argument 'name'
when I tried self.gh_cuts.write(out_name, name="GH_CUTS", format="fits", overwrite=overwrite)
and I don't find anything about a name
argument to table.write
, do you mean I should manage the fits file more directly and just cast the tables to hdus?
643a841
to
7c2efc7
Compare
d8f1268
to
b127e30
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
… possibility to save an OptimizationResult with only gh cuts for now.
Analysis Details9 IssuesCoverage and DuplicationsProject ID: cta-observatory_ctapipe_AY52EYhuvuGcMFidNyUs |
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 did a more detailed by-eye code review and have a few suggested changes. I will now do some more detailed testing by running the code, so may submit a second review shortly.
).tag(config=True) | ||
|
||
energy_migration_linear_bins = Bool( | ||
help="Bin energy migration ratio using linear bins", |
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.
Would be useful to mention here what is the default if this is set to false
. Looking at the code, it is geometric (logarithmic) bins. This could also be clearer as:
energy_migration_binning = CaselessStrEnum(
['linear', 'logarithmic'],
help="How energy bins are distributed between energy_migration_min and energy_migration_max",
default_value="logarithmic"
).tag(config=True)
).tag(config=True) | ||
|
||
energy_migration_n_bins = Integer( | ||
help="Number of bins in log scale for energy migration ratio", |
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.
log scale is incorrect if the user chooses energy_migration_linear_bins=True
|
||
@abstractmethod | ||
def make_edisp_hdu( | ||
self, events: QTable, point_like: bool, extname: str = "ENERGY MIGRATION" |
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.
general comment for here and other places: since we have options point_like
and source_is_pointlike
, this is quite confusing. Maybe rename point_like
to direction_cut_applied
or spatial_selection_applied
. That will make it much easier to follow. Also, this is more in line with the fact that we don't use the term "point-like IRFs" anymore, and instead use "SpatialSelection=None | RAD_MAX"
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 will change it to spatial_selection_applied
. I guess we should also change it accordingly in pyirf then, right?
"Do not compute background rate.", | ||
), | ||
**flag( | ||
"point-like", |
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.
see earlier comment: "point-like/full-enclosure" terminology should be replaced to avoid confusion between point-like cuts vs point-like simulated sources. The flag could be spatial_selection_applied
or similar
super().__init__(parent=parent, **kwargs) | ||
|
||
@abstractmethod | ||
def make_bias_resolution_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.
Any reason to not just use __call__
like other Components? (same comment for all Components in this file). That would make the API similar to all other parts of ctapipe
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 reason. I think __call__
would be better 👍 I will also change the benchmark and cut optimization components accordingly.
self, | ||
signal_events: QTable, | ||
background_events: QTable, | ||
theta_cut: QTable, |
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.
maybe to harmonize terminology, use spatial_selection_table
?
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.
Then we should probably not use "theta cut" anywhere anymore, right? So also rename it in the cut calculation components etc.
__all__ = ["EventLoader", "EventPreProcessor"] | ||
|
||
|
||
class EventPreProcessor(QualityQuery): |
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.
preprocess is a word, so this should be EventPreprocessor
,
Also generally we do not inherit from QualityQuery
for in other components, but rather have the component contain a QualityQuery. That makes more semantic sense, as this class does much more than a QualityQuery.
Then you would have a config file much like other classes in ctapipe:
EventPreprocessor:
EventQualityQuery:
quality_critieria:
...
energy_reconstructor: ...
from enum import Enum | ||
|
||
import astropy.units as u | ||
from pyirf.spectral import CRAB_HEGRA, IRFDOC_ELECTRON_SPECTRUM, IRFDOC_PROTON_SPECTRUM |
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.
wasn't this moved to a new package? Or is that just handled inside pyirf?
target_spectrum=self.gamma_target_spectrum, | ||
) | ||
] | ||
if self.optimization_algorithm != "PercentileCuts": |
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.
Might be safer to use isinstance()
here and elsewhere instead of a string compare to the class name, so that if we ever re-factor or rename classes, it gets updated correctly. But that would mean importing those sub-classes or the module, so not clear if that makes it messier.
if include_bkg: | ||
assert isinstance(hdul["BACKGROUND"], fits.BinTableHDU) | ||
|
||
os.remove(output_path) # Delete output file |
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 output_path.unlink()
instead, so no need to import os
.
Thanks! I can also add an example config file (maybe containing all config options and their default values?) at |
As we are planning to produce IRFs on events that were not used to select the GH cut, it makes sense to split the procedure generating IRFs into two tools. Because this splitting results in a large restructuring of the the previous PR on generating IRFs (#2315) that was basically working properly, I open a new PR to preserve the discussion on the old attempt and let its more or less functional code serve as easy reference.