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

[Feature] Wiring frb buffers with plot_window #1877

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
67e31b2
Use explicit names for callbacks
cphyc Jul 3, 2018
e36c829
First implementation
cphyc Jul 3, 2018
6ec13e3
Wire the filters to the plot window functionality
cphyc Jul 3, 2018
fcb0eb9
Simplify 2g gaussian filter
cphyc Jul 3, 2018
5543e46
Add test
cphyc Jul 3, 2018
1dbbee2
Pass plot_window to all FixedResolutionbuffer
cphyc Jul 3, 2018
dba66a3
Check on plot window side
cphyc Jul 6, 2018
5d5c59f
DRY: Wrap everything in a single function
cphyc Jul 6, 2018
0fe8f28
More thorough checks
cphyc Jul 6, 2018
873020a
Updating doc
cphyc Jul 6, 2018
d7ddc7a
Remote WIP code
cphyc Jul 6, 2018
64a593a
Make data_is_valid a property
cphyc Jul 7, 2018
296637d
Fix signature of frb
cphyc Jul 7, 2018
0b4b88c
Fix doc
cphyc Jul 7, 2018
71b246d
Update doc to include comments
cphyc Jul 10, 2018
7f0663a
Issue warning when using the nbeam param
cphyc Jul 10, 2018
05dae59
Remove `_data_valid` from plot_window
cphyc Jul 10, 2018
0089d55
Oops
cphyc Jul 10, 2018
adb84a6
Flaking, etc.
Sep 1, 2020
303dcdc
More descriptive test
cphyc Sep 1, 2020
dbc54b3
Take comments into account
cphyc Sep 1, 2020
7be7bdb
Update yt/visualization/fixed_resolution_filters.py
cphyc Sep 1, 2020
f4ee761
bugfix: fix an error where validate_plot decorator would fail for obj…
neutrinoceros Sep 1, 2020
38d569f
exp: deactivate frb data invalidation (should pass tests)
neutrinoceros Oct 11, 2020
5227e6d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 13, 2021
166afce
fix a broken import statement
neutrinoceros Apr 13, 2021
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
17 changes: 17 additions & 0 deletions doc/source/visualizing/callbacks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -887,3 +887,20 @@ Overplot the Path of a Ray
p.annotate_ray(oray)
p.annotate_ray(ray)
p.save()


Applying filters on the final image
-----------------------------------

It is also possible to operate on the plotted image directly by using
one of the fixed resolution buffer filter as described in
:ref:`frb-filters`.

.. python-script::

import yt

ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
p = yt.SlicePlot(ds, 'z', 'density')
p.frb.apply_gauss_beam(sigma=30)
p.save()
7 changes: 3 additions & 4 deletions doc/source/visualizing/manual_plotting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ using them matters.
ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
slc = ds.slice("z", 0.5)
frb = slc.to_frb((20, "kpc"), 512)
frb.apply_gauss_beam(nbeam=30, sigma=2.0)
frb.apply_gauss_beam(sigma=2.0)
frb.apply_white_noise(5e-23)
plt.imshow(frb["gas", "density"].d)
plt.savefig("frb_filters.png")
Expand All @@ -101,13 +101,12 @@ Currently available filters:
Gaussian Smoothing
~~~~~~~~~~~~~~~~~~

.. function:: apply_gauss_beam(self, nbeam=30, sigma=2.0)
.. function:: apply_gauss_beam(self, sigma=2.0)

(This is a proxy for
:class:`~yt.visualization.fixed_resolution_filters.FixedResolutionBufferGaussBeamFilter`.)

This filter convolves the FRB with 2d Gaussian that is "nbeam" pixel wide
and has standard deviation "sigma".
This filter convolves the FRB with 2d Gaussian that has standard deviation "sigma".

White Noise
~~~~~~~~~~~
Expand Down
40 changes: 25 additions & 15 deletions yt/visualization/fixed_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,15 @@ class FixedResolutionBuffer:
("index", "dtheta"),
)

def __init__(self, data_source, bounds, buff_size, antialias=True, periodic=False):
def __init__(
self,
data_source,
bounds,
buff_size,
antialias=True,
periodic=False,
filters=None,
):
self.data_source = data_source
self.ds = data_source.ds
self.bounds = bounds
Expand All @@ -97,6 +105,8 @@ def __init__(self, data_source, bounds, buff_size, antialias=True, periodic=Fals
self._filters = []
self.axis = data_source.axis
self.periodic = periodic
self._data_valid = False
self._filters = filters if filters else []

ds = getattr(data_source, "ds", None)
if ds is not None:
Expand All @@ -122,7 +132,7 @@ def __delitem__(self, item):
del self.data[item]

def __getitem__(self, item):
if item in self.data:
if item in self.data and self._data_valid:
return self.data[item]
mylog.info(
"Making a fixed resolution buffer of (%s) %d by %d",
Expand Down Expand Up @@ -162,6 +172,7 @@ def __getitem__(self, item):

ia = ImageArray(buff, units=units, info=self._get_info(item))
self.data[item] = ia
self._data_valid = True
return self.data[item]

def __setitem__(self, item, val):
Expand Down Expand Up @@ -539,14 +550,14 @@ class CylindricalFixedResolutionBuffer(FixedResolutionBuffer):
that supports non-aligned input data objects, primarily cutting planes.
"""

def __init__(self, data_source, radius, buff_size, antialias=True):

def __init__(self, data_source, radius, buff_size, antialias=True, filters=None):
self.data_source = data_source
self.ds = data_source.ds
self.radius = radius
self.buff_size = buff_size
self.antialias = antialias
self.data = {}
self._filters = filters if filters else []

ds = getattr(data_source, "ds", None)
if ds is not None:
Expand Down Expand Up @@ -576,12 +587,6 @@ class OffAxisProjectionFixedResolutionBuffer(FixedResolutionBuffer):
that supports off axis projections. This calls the volume renderer.
"""

def __init__(self, data_source, bounds, buff_size, antialias=True, periodic=False):
self.data = {}
FixedResolutionBuffer.__init__(
self, data_source, bounds, buff_size, antialias, periodic
)

def __getitem__(self, item):
if item in self.data:
return self.data[item]
Expand Down Expand Up @@ -628,11 +633,16 @@ class ParticleImageBuffer(FixedResolutionBuffer):

"""

def __init__(self, data_source, bounds, buff_size, antialias=True, periodic=False):
self.data = {}
FixedResolutionBuffer.__init__(
self, data_source, bounds, buff_size, antialias, periodic
)
def __init__(
self,
data_source,
radius,
buff_size,
antialias=True,
periodic=False,
filters=None,
):
super().__init__(data_source, radius, buff_size, antialias, periodic, filters)

# set up the axis field names
axis = self.axis
Expand Down
42 changes: 24 additions & 18 deletions yt/visualization/fixed_resolution_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

import numpy as np

from yt._maintenance.deprecation import issue_deprecation_warning

filter_registry = {}


def apply_filter(f):
@wraps(f)
def newfunc(*args, **kwargs):
args[0]._filters.append((f.__name__, (args, kwargs)))
frb = args[0]
frb._filters.append((f.__name__, (args, kwargs)))
# Invalidate the data of the frb to force its regeneration
frb._data_valid = False
return args[0]

return newfunc
Expand Down Expand Up @@ -37,33 +42,34 @@ class FixedResolutionBufferGaussBeamFilter(FixedResolutionBufferFilter):
"""
This filter convolves
:class:`yt.visualization.fixed_resolution.FixedResolutionBuffer` with
2d gaussian that is 'nbeam' pixels wide and has standard deviation
'sigma'.
2d gaussian that has standard deviation 'sigma'. Extra arguments
are directly passed to `scipy.ndimage.gaussian_filter`.
"""

_filter_name = "gauss_beam"

def __init__(self, nbeam=30, sigma=2.0):
matthewturk marked this conversation as resolved.
Show resolved Hide resolved
self.nbeam = nbeam
def __init__(self, sigma=2.0, truncate=4.0, **kwargs):
if "nbeam" in kwargs:
issue_deprecation_warning(
"The `nbeam` argument has been deprecated and should be replaced by "
"the `truncate` argument where `truncate=nbeam/sigma`."
)
truncate = kwargs["nbeam"] / sigma

self.sigma = sigma
self.truncate = truncate
self.extra_args = kwargs

def apply(self, buff):
from yt.utilities.on_demand_imports import _scipy

hnbeam = self.nbeam // 2
sigma = self.sigma

l = np.linspace(-hnbeam, hnbeam, num=self.nbeam + 1)
x, y = np.meshgrid(l, l)
g2d = (1.0 / (sigma * np.sqrt(2.0 * np.pi))) * np.exp(
-((x / sigma) ** 2 + (y / sigma) ** 2) / (2 * sigma ** 2)
spl = _scipy.ndimage.gaussian_filter(
buff,
self.sigma,
truncate=self.truncate,
**self.extra_args,
)
g2d /= g2d.max()

npm, nqm = np.shape(buff)
spl = _scipy.signal.convolve(buff, g2d)

return spl[hnbeam : npm + hnbeam, hnbeam : nqm + hnbeam]
return spl


class FixedResolutionBufferWhiteNoiseFilter(FixedResolutionBufferFilter):
Expand Down
28 changes: 16 additions & 12 deletions yt/visualization/plot_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ def invalidate_data(f):
@wraps(f)
def newfunc(*args, **kwargs):
rv = f(*args, **kwargs)
args[0]._data_valid = False
args[0]._plot_valid = False
plot = args[0]
# if plot._frb is not None:
# plot._frb._data_valid = False
plot._plot_valid = False
return rv

return newfunc
Expand Down Expand Up @@ -94,16 +96,15 @@ def newfunc(*args, **kwargs):
def validate_plot(f):
@wraps(f)
def newfunc(*args, **kwargs):
if hasattr(args[0], "_data_valid"):
if not args[0]._data_valid:
args[0]._recreate_frb()
if hasattr(args[0], "_profile_valid"):
if not args[0]._profile_valid:
args[0]._recreate_profile()
if not args[0]._plot_valid:
plot = args[0]
if hasattr(plot, "data_is_valid") and not plot.data_is_valid:
plot._recreate_frb()
if hasattr(plot, "_profile_valid") and not plot._profile_valid:
plot._recreate_profile()
if not plot._plot_valid:
# it is the responsibility of _setup_plots to
# call args[0].run_callbacks()
args[0]._setup_plots()
# call plot.run_callbacks()
plot._setup_plots()
rv = f(*args, **kwargs)
return rv

Expand Down Expand Up @@ -428,7 +429,10 @@ def _switch_ds(self, new_ds, data_source=None):
new_object = getattr(new_ds, name)(**kwargs)

self.data_source = new_object
self._data_valid = self._plot_valid = False

if self._frb is not None:
self._frb._data_valid = False
self._plot_valid = False

for d in "xyz":
lim_name = d + "lim"
Expand Down
Loading