Skip to content

Commit

Permalink
Update code
Browse files Browse the repository at this point in the history
  • Loading branch information
nabobalis committed Oct 29, 2024
1 parent 0020371 commit cb010a9
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 76 deletions.
1 change: 1 addition & 0 deletions changelog/205.doc.rst
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
Added a new example for `sunkit_image.radial.rhef` at :ref:`sphx_glr_generated_gallery_radial_histogram_equalization.py`

Added RHEF to :ref:`sphx_glr_generated_gallery_radial_gradient_filters.py` as a comparison to the other filters.
1 change: 1 addition & 0 deletions changelog/231.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improved the Radial Histogram Equalizing Filter (RHEF) (`sunkit_image.radial.rhef`) to work with images outside of SDO/AIA.
134 changes: 58 additions & 76 deletions sunkit_image/radial.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@
import sunpy.map
from sunpy.coordinates import frames


from sunkit_image.utils import (
apply_upsilon,
bin_edge_summary,
blackout_pixels_above_radius,
equally_spaced_bins,
find_pixel_radii,
find_radial_bin_edges,
get_radial_intensity_summary,
)

Expand Down Expand Up @@ -102,9 +100,39 @@ def _normalize_fit_radial_intensity(radii, polynomial, normalization_radius):
polynomial,
)

def _select_rank_method(method):
# For now, we have more than one option for ranking the values
def _percentile_ranks_scipy(arr):
from scipy import stats

Check warning on line 106 in sunkit_image/radial.py

View check run for this annotation

Codecov / codecov/patch

sunkit_image/radial.py#L105-L106

Added lines #L105 - L106 were not covered by tests

return stats.rankdata(arr, method="average") / len(arr)

Check warning on line 108 in sunkit_image/radial.py

View check run for this annotation

Codecov / codecov/patch

sunkit_image/radial.py#L108

Added line #L108 was not covered by tests

def _percentile_ranks_numpy(arr):
sorted_indices = np.argsort(arr)
ranks = np.empty_like(sorted_indices)
ranks[sorted_indices] = np.arange(1, len(arr) + 1)
return ranks / float(len(arr))

Check warning on line 114 in sunkit_image/radial.py

View check run for this annotation

Codecov / codecov/patch

sunkit_image/radial.py#L110-L114

Added lines #L110 - L114 were not covered by tests

def _percentile_ranks_numpy_inplace(arr):
sorted_indices = np.argsort(arr)
arr[sorted_indices] = np.arange(1, len(arr) + 1)
return arr / float(len(arr))

Check warning on line 119 in sunkit_image/radial.py

View check run for this annotation

Codecov / codecov/patch

sunkit_image/radial.py#L116-L119

Added lines #L116 - L119 were not covered by tests

# Select the sort method
if method == "inplace":
ranking_func = _percentile_ranks_numpy_inplace
elif method == "numpy":
ranking_func = _percentile_ranks_numpy
elif method == "scipy":
ranking_func = _percentile_ranks_scipy

Check warning on line 127 in sunkit_image/radial.py

View check run for this annotation

Codecov / codecov/patch

sunkit_image/radial.py#L122-L127

Added lines #L122 - L127 were not covered by tests
else:
msg = f"{method} is invalid. Allowed values are 'inplace', 'numpy', 'scipy'"

Check warning on line 129 in sunkit_image/radial.py

View check run for this annotation

Codecov / codecov/patch

sunkit_image/radial.py#L129

Added line #L129 was not covered by tests
raise NotImplementedError(msg)
return ranking_func

Check warning on line 131 in sunkit_image/radial.py

View check run for this annotation

Codecov / codecov/patch

sunkit_image/radial.py#L131

Added line #L131 was not covered by tests

def intensity_enhance(
smap,
*,
radial_bin_edges=None,
scale=None,
summarize_bin_edges="center",
Expand Down Expand Up @@ -136,9 +164,10 @@ def intensity_enhance(
----------
smap : `sunpy.map.Map`
The sunpy map to enhance.
radial_bin_edges : `astropy.units.Quantity`
radial_bin_edges : `astropy.units.Quantity`, optional
A two-dimensional array of bin edges of size ``[2, nbins]`` where ``nbins`` is
the number of bins.
Defaults to `None` which will use equally spaced bins.
scale : `astropy.units.Quantity`, optional
The radius of the Sun expressed in map units.
For example, in typical Helioprojective Cartesian maps the solar radius is expressed in
Expand Down Expand Up @@ -209,7 +238,6 @@ def intensity_enhance(

# Return a map with the intensity enhanced above the normalization radius
# and the same meta data as the input map.

new_map = sunpy.map.Map(smap.data * enhancement, smap.meta)
new_map.plot_settings["norm"] = None
return new_map
Expand All @@ -224,7 +252,7 @@ def nrgf(
width_function=np.std,
width_function_kwargs=None,
application_radius=1 * u.R_sun,
progress=True,
progress=False,
fill=np.nan,
):
"""
Expand Down Expand Up @@ -269,11 +297,12 @@ def nrgf(
application_radius : `astropy.units.Quantity`, optional
The NRGF is applied to emission at radii above the application_radius.
Defaults to 1 solar radii.
progress : ``bool``, optional
Show a progressbar while computing
fill : ``any``, optional
The value to be placed outside of the bounds of the algorithm
Defaults to NAN.
progress : `bool`, optional
Show a progressbar while computing.
Defaults to `False`.
fill : Any, optional
The value to be placed outside of the bounds of the algorithm.
Defaults to NaN.
Returns
-------
Expand Down Expand Up @@ -402,7 +431,7 @@ def fnrgf(
width_function=np.std,
application_radius=1 * u.R_sun,
number_angular_segments=130,
progress=True,
progress=False,
fill=np.nan,
):
"""
Expand Down Expand Up @@ -451,11 +480,12 @@ def fnrgf(
number_angular_segments : `int`
Number of angular segments in a circular annulus.
Defaults to 130.
progress : ``bool``, optional
Show a progressbar while computing
fill : ``any``, optional
The value to be placed outside of the bounds of the algorithm
Defaults to NAN.
progress : `bool`, optional
Show a progressbar while computing.
Defaults to `False`.
fill : Any, optional
The value to be placed outside of the bounds of the algorithm.
Defaults to NaN.
Returns
-------
Expand Down Expand Up @@ -595,57 +625,6 @@ def fnrgf(
return new_map


def _select_rank_method(method):
# For now, we have more than one option for ranking the values
def _percentile_ranks_scipy(arr):
from scipy import stats

return stats.rankdata(arr, method="average") / len(arr)

def _percentile_ranks_numpy(arr):
sorted_indices = np.argsort(arr)
ranks = np.empty_like(sorted_indices)
ranks[sorted_indices] = np.arange(1, len(arr) + 1)
return ranks / float(len(arr))

def _percentile_ranks_numpy_inplace(arr):
sorted_indices = np.argsort(arr)
arr[sorted_indices] = np.arange(1, len(arr) + 1)
return arr / float(len(arr))

# Select the sort method
if method == "inplace":
ranking_func = _percentile_ranks_numpy_inplace
elif method == "numpy":
ranking_func = _percentile_ranks_numpy
elif method == "scipy":
ranking_func = _percentile_ranks_scipy
else:
msg = f"{method} is invalid. Allowed values are 'inplace', 'numpy', 'scipy'"
raise NotImplementedError(msg)
return ranking_func


def find_radial_bin_edges(smap, radial_bin_edges=None):
# Get the radii for every pixel, ensuring units are correct (in terms of pixels or solar radii)
map_r = find_pixel_radii(smap)
# Automatically generate radial bin edges if none are provided
if radial_bin_edges is None:
radial_bin_edges = equally_spaced_bins(0, np.max(map_r.value), smap.data.shape[0] // 2) * u.R_sun

# Ensure radial_bin_edges are within the bounds of the map_r values
if radial_bin_edges[1, -1] > np.max(map_r):
radial_bin_edges = (
equally_spaced_bins(
inner_value=radial_bin_edges[0, 0].to(u.R_sun).value,
outer_value=np.max(map_r.to(u.R_sun)).value,
nbins=radial_bin_edges.shape[1] // 2,
)
* u.R_sun
)
return radial_bin_edges, map_r


@u.quantity_input(application_radius=u.R_sun, vignette=u.R_sun)
def rhef(
smap,
Expand All @@ -655,7 +634,7 @@ def rhef(
upsilon=0.35,
method="numpy",
vignette=None,
progress=True,
progress=False,
fill=np.nan,
):
"""
Expand Down Expand Up @@ -683,15 +662,18 @@ def rhef(
Defaults to 0 solar radii.
upsilon : float or None, optional
A double-sided gamma function to apply to modify the equalized histograms. Defaults to 0.35.
method : str, optional
Method used to rank the pixels for equalization. Defaults to 'inplace', with 'scipy' and 'numpy' as other options.
method : {"inplace", "numpy", "scipy"}, optional
Method used to rank the pixels for equalization.
Defaults to 'inplace'.
vignette : `astropy.units.Quantity`, optional
Radius beyond which pixels will be set to NAN. Defaults to None, must be in units that are compatible with "R_sun" as the value will be transformed.
progress : bool, optional
If True, display a progress bar during the filtering process. Defaults to True.
fill : ``any``, optional
The value to be placed outside of the bounds of the algorithm
Defaults to NAN.
progress : `bool`, optional
Show a progressbar while computing.
Defaults to `False`.
fill : Any, optional
The value to be placed outside of the bounds of the algorithm.
Defaults to NaN.
Returns
-------
`sunpy.map.Map`
Expand Down
43 changes: 43 additions & 0 deletions sunkit_image/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"remove_duplicate",
"apply_upsilon",
"blackout_pixels_above_radius",
"find_radial_bin_edges"
]


Expand Down Expand Up @@ -400,3 +401,45 @@ def blackout_pixels_above_radius(smap, radius_limit=1.5 * u.R_sun, fill=np.nan):

# Create a new map with the masked data
return sunpy.map.Map(masked_data, smap.meta)


def find_radial_bin_edges(smap, radial_bin_edges=None):
"""
Calculate radial bin edges for a solar map, either using provided edges or
generating them automatically.
Parameters
----------
smap : `sunpy.map.Map`
A sunpy Map containing the data to be binned.
radial_bin_edges : `astropy.units.Quantity`, optional
Pre-defined bin edges for radial binning. Should be a Quantity array with units
of solar radii (u.R_sun) or pixels. If `None` (the default), bin edges
will be automatically generated based on the map dimensions.
Returns
-------
`astropy.units.Quantity`
The final bin edges used for radial binning.
`astropy.units.Quantity`
Array of radial distances for each pixel in the map, matching the input
map dimensions.
"""
# Get the radii for every pixel, ensuring units are correct (in terms of pixels or solar radii)
map_r = find_pixel_radii(smap)

# Automatically generate radial bin edges if none are provided
if radial_bin_edges is None:
radial_bin_edges = equally_spaced_bins(0, np.max(map_r.value), smap.data.shape[0] // 2) * u.R_sun

Check warning on line 433 in sunkit_image/utils/utils.py

View check run for this annotation

Codecov / codecov/patch

sunkit_image/utils/utils.py#L433

Added line #L433 was not covered by tests

# Ensure radial_bin_edges are within the bounds of the map_r values
if radial_bin_edges[1, -1] > np.max(map_r):
radial_bin_edges = (
equally_spaced_bins(
inner_value=radial_bin_edges[0, 0].to(u.R_sun).value,
outer_value=np.max(map_r.to(u.R_sun)).value,
nbins=radial_bin_edges.shape[1] // 2,
)
* u.R_sun
)
return radial_bin_edges, map_r

0 comments on commit cb010a9

Please sign in to comment.