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
Change parametrisation from geom_true to energy_axis_true #2479
Merged
Merged
Changes from 4 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
2227729
Adapt MapDataset
AtreyeeS 18447e7
Adapt MapDatasetMaker
AtreyeeS 618e759
change BINSZ to BINSZ_DEFAULT
AtreyeeS acb4cc0
Adapt MapDataset
AtreyeeS 51e7297
Adapt MapDatasetMaker
AtreyeeS 7df9907
change BINSZ to BINSZ_DEFAULT
AtreyeeS f116b93
Fix high-level interface
Bultako d936eb9
address review comments
Bultako 9c64a01
Merge branch 'cleanup1' of https://github.com/AtreyeeS/gammapy into c…
AtreyeeS 4224305
Make e_true default to e_ereco
AtreyeeS d662561
Minor cleanup and fix of lightcurve notebook
adonath 24c8c0d
Fix light-curve notebook
adonath File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,16 +2,24 @@ | |
import logging | ||
from functools import lru_cache | ||
import numpy as np | ||
import astropy.units as u | ||
from astropy.coordinates import Angle | ||
from astropy.nddata.utils import NoOverlapError | ||
from astropy.utils import lazyproperty | ||
from gammapy.irf import EnergyDependentMultiGaussPSF | ||
from gammapy.maps import Map | ||
from gammapy.maps import Map, WcsGeom | ||
from gammapy.modeling.models import BackgroundModel | ||
from .background import make_map_background_irf | ||
from .edisp_map import make_edisp_map | ||
from .exposure import _map_spectrum_weight, make_map_exposure_true_energy | ||
from .fit import BINSZ_IRF, MIGRA_AXIS_DEFAULT, RAD_AXIS_DEFAULT, MapDataset | ||
from .fit import ( | ||
BINSZ_IRF_DEFAULT, | ||
MARGIN_IRF_DEFAULT, | ||
MIGRA_AXIS_DEFAULT, | ||
RAD_AXIS_DEFAULT, | ||
ENERGY_AXIS_DEFAULT, | ||
MapDataset, | ||
) | ||
from .psf_map import make_psf_map | ||
|
||
__all__ = ["MapDatasetMaker", "MapMakerRing"] | ||
|
@@ -28,14 +36,16 @@ class MapDatasetMaker: | |
Reference image geometry in reco energy, used for counts and background maps | ||
offset_max : `~astropy.coordinates.Angle` | ||
Maximum offset angle | ||
geom_true : `~gammapy.maps.WcsGeom` | ||
Reference image geometry in true energy, used for IRF maps. It can have a coarser | ||
spatial bins than the counts geom. | ||
If none, the same as geom is assumed | ||
energy_axis_true: `~gammapy.maps.MapAxis` | ||
True energy axis used for IRF maps | ||
migra_axis : `~gammapy.maps.MapAxis` | ||
Migration axis for edisp map | ||
rad_axis : `~gammapy.maps.MapAxis` | ||
Radial axis for psf map. | ||
binsz_irf: float | ||
IRF Map pixel size in degrees. | ||
margin_irf: float | ||
IRF map margin size in degrees | ||
cutout : bool | ||
Whether to cutout the observation. | ||
cutout_mode : {'trim', 'partial', 'strict'} | ||
|
@@ -47,19 +57,27 @@ def __init__( | |
self, | ||
geom, | ||
offset_max, | ||
geom_true=None, | ||
background_oversampling=None, | ||
energy_axis_true=None, | ||
migra_axis=None, | ||
rad_axis=None, | ||
binsz_irf=None, | ||
margin_irf=None, | ||
cutout_mode="trim", | ||
cutout=True, | ||
): | ||
|
||
self.geom = geom | ||
self.geom_true = geom_true if geom_true else geom.to_binsz(BINSZ_IRF) | ||
self.offset_max = Angle(offset_max) | ||
self.background_oversampling = background_oversampling | ||
self.migra_axis = migra_axis if migra_axis else MIGRA_AXIS_DEFAULT | ||
self.rad_axis = rad_axis if rad_axis else RAD_AXIS_DEFAULT | ||
self.energy_axis_true = energy_axis_true or ENERGY_AXIS_DEFAULT | ||
self.binsz_irf = binsz_irf or BINSZ_IRF_DEFAULT | ||
|
||
self.margin_irf = margin_irf or MARGIN_IRF_DEFAULT | ||
self.margin_irf = self.margin_irf * u.deg | ||
|
||
self.cutout_mode = cutout_mode | ||
self.cutout_width = 2 * self.offset_max | ||
self.cutout = cutout | ||
|
@@ -75,25 +93,39 @@ def _cutout_geom(self, geom, observation): | |
else: | ||
return geom | ||
|
||
@lazyproperty | ||
def wcs_irf(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please rename to |
||
"""Spatial geometry of IRF Maps (`Geom`)""" | ||
wcs = self.geom.to_image() | ||
return WcsGeom.create( | ||
binsz=self.binsz_irf, | ||
width=wcs.width + self.margin_irf, | ||
skydir=wcs.center_skydir, | ||
proj=wcs.projection, | ||
coordsys=wcs.coordsys, | ||
) | ||
|
||
@lazyproperty | ||
def geom_irf(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please rename to |
||
"""Geom of Exposure map associated with IRFs (`Geom`)""" | ||
return self.wcs_irf.to_cube([self.energy_axis_true]) | ||
|
||
@lazyproperty | ||
def geom_exposure(self): | ||
"""Exposure map geom (`Geom`)""" | ||
energy_axis = self.geom_true.get_axis_by_name("energy") | ||
geom_exposure = self.geom.to_image().to_cube([energy_axis]) | ||
geom_exposure = self.geom.to_image().to_cube([self.energy_axis_true]) | ||
return geom_exposure | ||
|
||
@lazyproperty | ||
def geom_psf(self): | ||
"""PSFMap geom (`Geom`)""" | ||
energy_axis = self.geom_true.get_axis_by_name("ENERGY") | ||
geom_psf = self.geom_true.to_image().to_cube([self.rad_axis, energy_axis]) | ||
geom_psf = self.wcs_irf.to_cube([self.rad_axis, self.energy_axis_true]) | ||
return geom_psf | ||
|
||
@lazyproperty | ||
def geom_edisp(self): | ||
"""EdispMap geom (`Geom`)""" | ||
energy_axis = self.geom_true.get_axis_by_name("ENERGY") | ||
geom_edisp = self.geom_true.to_image().to_cube([self.migra_axis, energy_axis]) | ||
geom_edisp = self.wcs_irf.to_cube([self.migra_axis, self.energy_axis_true]) | ||
return geom_edisp | ||
|
||
def make_counts(self, observation): | ||
|
@@ -150,7 +182,8 @@ def make_exposure_irf(self, observation): | |
exposure : `Map` | ||
Exposure map. | ||
""" | ||
geom = self._cutout_geom(self.geom_true, observation) | ||
|
||
geom = self._cutout_geom(self.geom_irf, observation) | ||
exposure = make_map_exposure_true_energy( | ||
pointing=observation.pointing_radec, | ||
livetime=observation.observation_live_time_duration, | ||
|
@@ -281,7 +314,7 @@ def make_mask_safe_irf(self, observation): | |
mask : `~numpy.ndarray` | ||
Mask | ||
""" | ||
geom = self._cutout_geom(self.geom_true, observation) | ||
geom = self._cutout_geom(self.geom_irf, observation) | ||
offset = geom.separation(observation.pointing_radec) | ||
return offset >= self.offset_max | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back 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.
I think for the true energy axis we should not introduce any default, except for
e_true = e_reco
, as we already do in many places. The default here (looks like it was copied over fromgammapy.spectrum
) does not really make sense for a cube analysis. The model evaluation will be much to slow and heavily oversampled for no good reason.Please remove the default axis here and just uses
energy_axis_true
=energy_axis_reco
as a default, where appropriate.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.
Yes, I did indeed copy it over from
gammapy.spectrum
, and this is clearly a poor choice of binning (which I think we need to take from the IRFs at some point anyways). But I think it might be needed to have a defaulte_true
binning. I remember I was getting very different indices between spectral and map based analysis once, which was solved by changing thee_true
. This would be quite non-intuitive for a general user...@registerrier @bkhelifi do you have an opinion about this?
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.
Yes, the assumption of the 3D model evaluation is that we use a "fine" binning (I think we never clarified, what this actually means, probably >5 bins / decade, but we should document it somewhere). If this is not fulfilled, the user can currently get bad or unexpected results. I think in general we should change to using
SpectralModel.integral()
in the 3D analysis as well (just as we do for 1D), this should already improve (if not solve...) the discrepancy. Note, that for theSpectrumDatasetMaker
I already removed the default fore_true
. But we can certainly discuss, whether we re-introduce it in a consistent way and with a plausible choice for 1D as well as 3D.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 that the issue is not only the fine binning but the total range.
In theory, the true energy binning is supposed to cover the 0 to + infinity range. It is of course not necessary in practice, but the range has to be larger than the
e_reco
one to account for spill-over.This is far from a small approximation in many cases if users define a range close to the actual safe range.
A possibility could be to decide that by default
e_true
is binned starting frome_reco[0]*0.7
up toe_reco[-1]*1.3
. Or even to leave as a possible parameter the leakage fraction (with default at 30% for instance).