Skip to content

Commit

Permalink
Merge pull request #922 from PMEAL/fixing_pseudo_packing
Browse files Browse the repository at this point in the history
Fixed and improved the pseudo packing functions #enh #bug #api
  • Loading branch information
jgostick authored Mar 25, 2024
2 parents 023645f + d3417c0 commit 8ca4395
Show file tree
Hide file tree
Showing 9 changed files with 1,088 additions and 591 deletions.
400 changes: 155 additions & 245 deletions examples/generators/reference/pseudo_electrostatic_packing.ipynb

Large diffs are not rendered by default.

195 changes: 195 additions & 0 deletions examples/generators/reference/ramp.ipynb

Large diffs are not rendered by default.

277 changes: 149 additions & 128 deletions examples/networks/reference/snow2.ipynb

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,5 @@ exclude = [".git", ".github", ".venv", "build", "docs", "examples", "test"]
line-length = 92
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["E402", "F401", "F403"]
[tool.ruff.lint]
extend-ignore = ["F401"]
31 changes: 0 additions & 31 deletions src/porespy/beta/_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,9 @@

__all__ = [
"local_diff",
"ramp",
]


def ramp(shape, inlet=1.0, outlet=0.0, axis=0):
r"""
Generates an array containing a linear ramp of greyscale values along the given
axis.
Parameter
---------
shape : list
The [X, Y, Z] dimension of the desired image. Z is optional.
inlet : scalar
The values to place the beginning of the specified axis
outlet : scalar
The values to place the end of the specified axis
axis : scalar
The axis along which the ramp should be directed
Returns
-------
ramp : ndarray
An array of the requested shape with greyscale values changing linearly
from inlet to outlet in the direction specified.
"""
vals = np.linspace(inlet, outlet, shape[axis])
vals = np.reshape(vals, [shape[axis]]+[1]*len(shape[1:]))
vals = np.swapaxes(vals, 0, axis)
shape[axis] = 1
ramp = np.tile(vals, shape)
return ramp


def local_diff(vals, im, strel=None):
r"""
Computes the difference pixel and the average of it's neighbors.
Expand Down
70 changes: 58 additions & 12 deletions src/porespy/generators/_imgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"line_segment",
"overlapping_spheres",
"polydisperse_spheres",
"ramp",
"RSA",
"rsa",
"random_spheres",
Expand All @@ -38,6 +39,43 @@
logger = logging.getLogger(__name__)


def ramp(shape, inlet=1.0, outlet=0.0, axis=0):
r"""
Generates an array containing a linear ramp of greyscale values along the given
axis.
Parameter
---------
shape : list
The [X, Y, Z] dimension of the desired image. Z is optional.
inlet : scalar
The values to place the beginning of the specified axis
outlet : scalar
The values to place the end of the specified axis
axis : scalar
The axis along which the ramp should be directed
Returns
-------
ramp : ndarray
An array of the requested shape with greyscale values changing linearly
from inlet to outlet in the direction specified.
Examples
--------
`Click here
<https://porespy.org/examples/generators/reference/ramp.html>`_
to view online example.
"""
shape = np.array(shape)
vals = np.linspace(inlet, outlet, shape[axis])
vals = np.reshape(vals, [shape[axis]]+[1]*len(shape[1:]))
vals = np.swapaxes(vals, 0, axis)
shape[axis] = 1
ramp = np.tile(vals, shape)
return ramp


def cylindrical_plug(shape, r=None, axis=2):
r"""
Generates a cylindrical plug suitable for use as a mask on a tomogram
Expand Down Expand Up @@ -183,14 +221,15 @@ def RSA(*args, **kwargs):
def random_spheres(
im_or_shape: np.array,
r: int,
volume_fraction: int = 1,
volume_fraction: float = 1.0,
clearance: int = 0,
protrusion: int = 0,
n_max: int = 100000,
edges: str = "contained",
return_spheres: bool = False,
smooth: bool = True,
seed: int = None,
value: int = True,
):
r"""
Generates a sphere or disk packing using Random Sequential Addition
Expand Down Expand Up @@ -250,6 +289,10 @@ def random_spheres(
has no effect. To get a repeatable image, the seed must be passed to the
function so it can be initialized the way ``numba`` requires. The default
is ``None``, which means each call will produce a new realization.
value : scalar
The value to set the inserted spheres to. Using `value < 0` is a handy
way to repeatedly insert different sphere sizes into the same image while
making them easy to identify.
Returns
-------
Expand Down Expand Up @@ -291,7 +334,8 @@ def random_spheres(
mode=edges,
return_spheres=return_spheres,
smooth=smooth,
seed=seed)
seed=seed,
value=value)
return im


Expand All @@ -307,6 +351,7 @@ def rsa(
return_spheres: bool = False,
smooth: bool = True,
seed: int = None,
value: int = True,
):
r"""
Generates a sphere or disk packing using Random Sequential Addition
Expand Down Expand Up @@ -397,14 +442,14 @@ def rsa(
"""
logger.debug(f"rsa: Adding spheres of size {r}")
if np.array(im_or_shape).ndim < 2:
im = np.zeros(shape=im_or_shape, dtype=bool)
im = np.zeros(shape=im_or_shape, dtype=type(value))
input_im = np.copy(im)
else:
input_im = np.copy(im_or_shape)
im = np.zeros_like(im_or_shape, dtype=bool)
im = np.zeros_like(im_or_shape, dtype=type(value))
if seed is not None: # Initialize rng so numba sees it
_set_seed(seed)
im = im.astype(bool)
im = im.astype(type(value))
shape_orig = im.shape # Store original image shape, to undo padding at the end
if n_max is None:
n_max = np.inf
Expand All @@ -431,6 +476,7 @@ def rsa(
vf = vf_start
free_sites = np.flatnonzero(options_im)
i = 0
im_temp = np.copy(im).astype(type(value))
while (vf <= vf_final) and (i < n_max) and (len(free_sites) > 0):
# Choose a random site from free_sites
c, count = _make_choice(options_im, free_sites=free_sites)
Expand All @@ -441,11 +487,11 @@ def rsa(
free_sites = np.flatnonzero(options_im)
if all(np.array(c) == -1):
break
im = _insert_disk_at_points(im=im,
coords=np.vstack(c),
r=r,
v=True,
smooth=smooth)
im_temp = _insert_disk_at_points(im=im_temp,
coords=np.vstack(c),
r=r,
v=value,
smooth=smooth)
options_im = _insert_disk_at_points(im=options_im,
coords=np.vstack(c),
r=2*r + int(np.round(clearance/2)),
Expand All @@ -455,10 +501,10 @@ def rsa(
vf += vf_template
i += 1
logger.info(f"Number of spheres inserted: {i}")
im = extract_subsection(im, shape_orig)
im_temp = extract_subsection(im_temp, shape_orig)
logger.debug("Final volume fraction:", vf)
if not return_spheres:
im = im + input_im
im = im_temp + input_im
return im


Expand Down
Loading

0 comments on commit 8ca4395

Please sign in to comment.