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

feat: add option to turn off optimization #173

Merged
merged 1 commit into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

* Add support of `regions.Regions` [#163]
* Add option to turn off optimization in `fill`. The optimization degrades MOCs that are
way more precise than the given WCS [#166]
* Creation of a MOC from a zone (defined by min/max ra and dec)`MOC.from_zone`
* Creation of a single MOC from a lot of small cones is faster with the new option in
`MOC.from_cones`: the keyword 'union_strategy' can now take the value 'small_cones'.
Expand Down
16 changes: 11 additions & 5 deletions python/mocpy/moc/moc.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,20 +384,26 @@ def contains_lonlat(self, lon, lat, keep_inside=True):

# TODO: implement: def contains_including_surrounding(self, lon, lat, distance)

def fill(self, ax, wcs, **kw_mpl_pathpatch):
def fill(self, ax, wcs, optimize=True, **kw_mpl_pathpatch):
"""
Draw the MOC on a matplotlib axis.

This performs the projection of the cells from the world coordinate system to the pixel image coordinate system.
You are able to specify various styling kwargs for `matplotlib.patches.PathPatch`
(see the `list of valid keywords <https://matplotlib.org/api/_as_gen/matplotlib.patches.PathPatch.html#matplotlib.patches.PathPatch>`__).
This performs the projection of the cells from the world coordinate system to the
pixel image coordinate system. You can provide style keyword arguments as in
`matplotlib.patches.PathPatch`
(see the `list of valid keywords
<https://matplotlib.org/api/_as_gen/matplotlib.patches.PathPatch.html#matplotlib.patches.PathPatch>`__).

Parameters
----------
ax : `matplotlib.axes.Axes`
Matplotlib axis.
wcs : `astropy.wcs.WCS`
WCS defining the World system <-> Image system projection.
optimize : bool, optional
If this is set to True, the MOC will be degraded so that no HEALPix will be
smaller than one pixel as defined by the WCS. It can be useful to deactivate this
optimization for svg outputs or if you take an insert of a WCS. Default is True.
kw_mpl_pathpatch
Plotting arguments for `matplotlib.patches.PathPatch`.

Expand All @@ -418,7 +424,7 @@ def fill(self, ax, wcs, **kw_mpl_pathpatch):
>>> ax = fig.add_subplot(projection=wcs)
>>> moc.fill(ax, wcs, color='blue')
"""
fill.fill(self, ax, wcs, **kw_mpl_pathpatch)
fill.fill(self, ax, wcs, optimize=optimize, **kw_mpl_pathpatch)

def border(self, ax, wcs, **kw_mpl_pathpatch):
"""
Expand Down
8 changes: 6 additions & 2 deletions python/mocpy/moc/plot/fill.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def add_patches_to_mpl_axe(patches, ax, wcs, **kw_mpl_pathpatch):
_set_wcs(ax, wcs)


def fill(moc, ax, wcs, **kw_mpl_pathpatch):
def fill(moc, ax, wcs, *, optimize=True, **kw_mpl_pathpatch):
"""Fill the figure's ax with the patches.

Parameters
Expand All @@ -122,11 +122,15 @@ def fill(moc, ax, wcs, **kw_mpl_pathpatch):
ax : matplotlib.pyplot.axes
wcs : astropy.wcs.WCS
projection from astropy
optimize : bool, optional
If this is set to True, the MOC will be degraded so that no HEALPix will be
smaller than one pixel as defined by the WCS. It can be useful to deactivate this
optimization for svg outputs or if you take an insert of a WCS. Default to True.
"""
# Simplify the MOC for plotting purposes:
# 1. Degrade the MOC if the FOV is enough big so that we cannot see the smallest HEALPix cells.
# 2. For small FOVs, plot the MOC & POLYGONAL_MOC_FROM_FOV.
moc_to_plot = build_plotting_moc(moc=moc, wcs=wcs)
moc_to_plot = build_plotting_moc(moc=moc, wcs=wcs, optimize=optimize)

# If the FOV contains no cells, then moc_to_plot (i.e. the intersection between the moc
# and the MOC created from the FOV polygon) will be empty.
Expand Down
29 changes: 15 additions & 14 deletions python/mocpy/moc/plot/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,21 @@ def _set_wcs(ax, wcs):
ax.set_ylim([y_min, y_max])


def build_plotting_moc(moc, wcs):
def build_plotting_moc(moc, wcs, optimize=True):
"""Plot a moc."""
# Get the WCS cdelt giving the deg.px^(-1) resolution.
cdelt = wcs.wcs.cdelt
# Convert in rad.px^(-1)
cdelt = np.abs((2 * np.pi / 360) * cdelt[0])
# Get the minimum depth such as the resolution of a cell is contained in 1px.
depth_res = int(np.floor(np.log2(np.sqrt(np.pi / 3) / cdelt)))
depth_res = max(depth_res, 0)
# Degrade the moc to that depth for plotting purposes. It is not necessary to plot pixels
# that we will not see because they are contained in 1px.
moc_plot = moc
if moc.max_order > depth_res:
moc_plot = moc.degrade_to_order(depth_res)
moc_plot = moc # creates a copy to keep the original moc untouched
if optimize:
# Get the WCS cdelt giving the deg.px^(-1) resolution.
cdelt = wcs.wcs.cdelt
# Convert in rad.px^(-1)
cdelt = np.abs((2 * np.pi / 360) * cdelt[0])
# Get the minimum depth such as the resolution of a cell is contained in 1px.
depth_res = int(np.floor(np.log2(np.sqrt(np.pi / 3) / cdelt)))
depth_res = max(depth_res, 0)
# Degrade the moc to that depth for plotting purposes. It is not necessary to plot pixels
# that we will not see because they are contained in 1px.
if moc.max_order > depth_res:
moc_plot = moc.degrade_to_order(depth_res)

# Get the MOC delimiting the FOV polygon
width_px = int(wcs.wcs.crpix[0] * 2.0) # Supposing the wcs is centered in the axis
Expand All @@ -56,7 +57,7 @@ def build_plotting_moc(moc, wcs):
Y_px = np.append(Y_px, Y[-1, :-1])
Y_px = np.append(Y_px, Y[1:, 0][::-1])

# Disable the output of warnings when encoutering NaNs.
# Disable the output of warnings when encountering NaNs.
warnings.filterwarnings("ignore")
# Inverse projection from pixel coordinate space to the world coordinate space
viewport = pixel_to_skycoord(X_px, Y_px, wcs)
Expand Down
Loading