rectangular_pillars_array

Generates an array of rectangular pillars with a specified opening size distribution between them.

import matplotlib.pyplot as plt
import porespy as ps
import numpy as np
from porespy.visualization import set_mpl_style
set_mpl_style()
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[1], line 2
      1 import matplotlib.pyplot as plt
----> 2 import porespy as ps
      3 import numpy as np
      4 from porespy.visualization import set_mpl_style

File ~/work/porespy/porespy/src/porespy/__init__.py:15
      1 r"""
      2 #######
      3 PoreSpy
   (...)
     12 
     13 """
---> 15 from .tools._utils import Settings as _Settings
     17 settings = _Settings()
     19 from . import tools

File ~/work/porespy/porespy/src/porespy/tools/__init__.py:48
      1 r"""
      2 
      3 Collection of helper functions for manipulating images
   (...)
     45 
     46 """
---> 48 from ._funcs import *
     49 from ._utils import *
     50 from ._funcs import _check_for_singleton_axes, center_of_mass

File ~/work/porespy/porespy/src/porespy/tools/_funcs.py:4
      1 import logging
      3 import numpy as np
----> 4 import scipy.ndimage as spim
      5 from numba import boolean, njit
      6 from skimage.morphology import ball, disk

File /opt/hostedtoolcache/Python/3.12.5/x64/lib/python3.12/site-packages/scipy/ndimage/__init__.py:152
      1 """
      2 =========================================================
      3 Multidimensional image processing (:mod:`scipy.ndimage`)
   (...)
    119 
    120 """
    122 # Copyright (C) 2003-2005 Peter J. Verveer
    123 #
    124 # Redistribution and use in source and binary forms, with or without
   (...)
    149 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    150 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--> 152 from ._filters import *
    153 from ._fourier import *
    154 from ._interpolation import *

File /opt/hostedtoolcache/Python/3.12.5/x64/lib/python3.12/site-packages/scipy/ndimage/_filters.py:37
     34 import numpy as np
     35 import operator
---> 37 from scipy._lib._util import normalize_axis_index
     38 from . import _ni_support
     39 from . import _nd_image

File /opt/hostedtoolcache/Python/3.12.5/x64/lib/python3.12/site-packages/scipy/_lib/_util.py:18
     10 from typing import (
     11     Optional,
     12     Union,
     13     TYPE_CHECKING,
     14     TypeVar,
     15 )
     17 import numpy as np
---> 18 from scipy._lib._array_api import array_namespace, is_numpy, size as xp_size
     21 AxisError: type[Exception]
     22 ComplexWarning: type[Warning]

File /opt/hostedtoolcache/Python/3.12.5/x64/lib/python3.12/site-packages/scipy/_lib/_array_api.py:21
     18 import numpy.typing as npt
     20 from scipy._lib import array_api_compat
---> 21 from scipy._lib.array_api_compat import (
     22     is_array_api_obj,
     23     size,
     24     numpy as np_compat,
     25     device
     26 )
     28 __all__ = ['array_namespace', '_asarray', 'size', 'device']
     31 # To enable array API and strict array-like input validation

File /opt/hostedtoolcache/Python/3.12.5/x64/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__init__.py:1
----> 1 from numpy import * # noqa: F403
      3 # from numpy import * doesn't overwrite these builtin names
      4 from numpy import abs, max, min, round # noqa: F401

File /opt/hostedtoolcache/Python/3.12.5/x64/lib/python3.12/site-packages/numpy/__init__.py:352, in __getattr__(attr)
    351 def _sanity_check():
--> 352     """
    353     Quick sanity checks for common bugs caused by environment.
    354     There are some cases e.g. with wrong BLAS ABI that cause wrong
    355     results under specific runtime conditions that are not necessarily
    356     achieved during test suite runs, and it is useful to catch those early.
    357 
    358     See https://github.com/numpy/numpy/issues/8577 and other
    359     similar bug reports.
    360 
    361     """
    362     try:
    363         x = ones(2, dtype=float32)

File /opt/hostedtoolcache/Python/3.12.5/x64/lib/python3.12/site-packages/numpy/testing/__init__.py:11
      8 from unittest import TestCase
     10 from . import _private
---> 11 from ._private.utils import *
     12 from ._private.utils import (_assert_valid_refcount, _gen_alignment_data)
     13 from ._private import extbuild

File /opt/hostedtoolcache/Python/3.12.5/x64/lib/python3.12/site-packages/numpy/testing/_private/utils.py:22
     19 import sysconfig
     21 import numpy as np
---> 22 from numpy.core import (
     23      intp, float32, empty, arange, array_repr, ndarray, isnat, array)
     24 from numpy import isfinite, isnan, isinf
     25 import numpy.linalg._umath_linalg

ModuleNotFoundError: No module named 'numpy.core'

spacing

Controls the spacing between the pore centers.

fig, ax = plt.subplots(1, 2, figsize=(10, 5))
np.random.seed(0)
im1 = ps.generators.rectangular_pillars_array(
    shape=[401, 601], spacing=30)
im2 = ps.generators.rectangular_pillars_array(
    shape=[401, 601], spacing=60)

ax[0].imshow(im1, origin='lower', interpolation='none')
ax[0].set_title('Spacing=30')
ax[1].imshow(im2, origin='lower', interpolation='none')
ax[1].set_title('Spacing=60');

lattice

The type of lattice to use, options are 'simple' and 'triangular'

fig, ax = plt.subplots(1, 2, figsize=(10, 5))
np.random.seed(0)
im1 = ps.generators.rectangular_pillars_array(
    shape=[401, 601],
    spacing=70,
    lattice='simple',
)
im2 = ps.generators.rectangular_pillars_array(
    shape=[401, 601],
    spacing=70,
    lattice='triangular',
)

ax[0].imshow(im1, origin='lower', interpolation='none')
ax[0].set_title('Simple Cubic Lattice')
ax[1].imshow(im2, origin='lower', interpolation='none')
ax[1].set_title('Triangular Lattice');

truncate

If True it returns the array within an image of the specified size (i.e. it truncates the full pattern). If False it returns an image that is larger than the requested shape but contains a whole number of unit cells.

fig, ax = plt.subplots(1, 2, figsize=(10, 5))
np.random.seed(0)
im1 = ps.generators.rectangular_pillars_array(
    shape=[401, 601],
    spacing=70,
    lattice='simple',
    truncate=True,
)
im2 = ps.generators.rectangular_pillars_array(
    shape=[401, 601],
    spacing=70,
    lattice='simple',
    truncate=False,
)

ax[0].imshow(im1, origin='lower', interpolation='none')
ax[0].set_title('Truncated to Shape')
ax[1].imshow(im2, origin='lower', interpolation='none')
ax[1].set_title('Expanded to whole number of unit cells');

dist and dist_kwargs

Allows for full control over the distribution of the opening size between pillars. The default is a uniform distribution with sizes ranging from 5 to 15, but any distribution from scipy.stats can be used:

fig, ax = plt.subplots(1, 2, figsize=(10, 5))
np.random.seed(0)
im1 = ps.generators.rectangular_pillars_array(
    shape=[401, 601],
    dist='uniform',
    dist_kwargs=dict(loc=1, scale=3),
)
im2 = ps.generators.rectangular_pillars_array(
    shape=[401, 601],
    dist='norm',
    dist_kwargs=dict(loc=5, scale=2),
)

ax[0].imshow(im1, origin='lower', interpolation='none')
ax[0].set_title('Narrow Uniform Distribution')
ax[1].imshow(im2, origin='lower', interpolation='none')
ax[1].set_title('Normal Distribution');

seed

Initializes the random number generator at a specified state so that identical realizations can be obtained if desired:

fig, ax = plt.subplots(1, 2, figsize=(10, 5))
np.random.seed(0)
im1 = ps.generators.rectangular_pillars_array(
    shape=[401, 601],
    seed=0,
)
im2 = ps.generators.rectangular_pillars_array(
    shape=[401, 601],
    seed=0,
)

ax[0].imshow(im1, origin='lower', interpolation='none')
ax[1].imshow(im2, origin='lower', interpolation='none');