rsa
#
This function implements ‘random sequential addition’ of spheres. The main benefit of this approach is that sphere overlap can be prevented or controlled. The downside is that the function is a bit on the slow side, though efforts have been made to accelerate it using numba jit.
import porespy as ps
import matplotlib.pyplot as plt
import numpy as np
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/openpnm/algorithms/_invasion_percolation.py:358: NumbaDeprecationWarning: The 'nopython' keyword argument was not supplied to the 'numba.jit' decorator. The implicit default value for this argument is currently False, but it will be changed to True in Numba 0.59.0. See https://numba.readthedocs.io/en/stable/reference/deprecation.html#deprecation-of-object-mode-fall-back-behaviour-when-using-jit for details.
def _find_trapped_pores(inv_seq, indices, indptr, outlets): # pragma: no cover
import inspect
b = inspect.signature(ps.generators.rsa)
print(b)
(im_or_shape: <built-in function array>, r: int, volume_fraction: int = 1, clearance: int = 0, protrusion: int = 0, n_max: int = 100000, mode: str = 'contained', return_spheres: bool = False, smooth: bool = True, seed: int = None)
im_or_shape
#
The function can either add spheres an existing image, or create a new image of the given shape and spheres to that. Let’s start with an empty image, and set the void fraction to a low value:
shape = [300, 300]
r = 15
im = ps.generators.rsa(im_or_shape=shape, r=r)
fig, ax = plt.subplots(1, 1, figsize=[4, 4])
ax.axis(False)
ax.imshow(im, origin='lower', interpolation='none');
/tmp/ipykernel_7909/3616168134.py:3: DeprecationWarning: Call to deprecated function (or staticmethod) rsa. (This function will be renamed random_spheres in a future version)
im = ps.generators.rsa(im_or_shape=shape, r=r)

Now let’s fill up the remaining space with as many smaller spheres as possible:
r = 5
im = ps.generators.rsa(im_or_shape=im, r=r)
fig, ax = plt.subplots(1, 1, figsize=[4, 4])
ax.axis(False)
ax.imshow(im, origin='lower', interpolation='none');
/tmp/ipykernel_7909/3742233897.py:2: DeprecationWarning: Call to deprecated function (or staticmethod) rsa. (This function will be renamed random_spheres in a future version)
im = ps.generators.rsa(im_or_shape=im, r=r)

mode
#
Spheres can either be fully contained within the image or be truncated at the edges by specifying mode:
fig, ax = plt.subplots(1, 2, figsize=[8, 4])
r = 20
mode = 'contained'
im1 = ps.generators.rsa(im_or_shape=shape, r=r, mode=mode)
ax[0].imshow(im1, origin='lower', interpolation='none')
ax[0].axis(False)
ax[0].set_title(f'mode = {mode}')
mode = 'extended'
im2 = ps.generators.rsa(im_or_shape=shape, r=r, mode=mode)
ax[1].imshow(im2, origin='lower', interpolation='none')
ax[1].axis(False)
ax[1].set_title(f'mode = {mode}');
/tmp/ipykernel_7909/880368931.py:5: DeprecationWarning: Call to deprecated function (or staticmethod) rsa. (This function will be renamed random_spheres in a future version)
im1 = ps.generators.rsa(im_or_shape=shape, r=r, mode=mode)
/tmp/ipykernel_7909/880368931.py:11: DeprecationWarning: Call to deprecated function (or staticmethod) rsa. (This function will be renamed random_spheres in a future version)
im2 = ps.generators.rsa(im_or_shape=shape, r=r, mode=mode)

clearance
#
Spheres can be made to partially overlap, the so called ‘cherry pit’ model, or to have some clearance:
fig, ax = plt.subplots(1, 2, figsize=[8, 4])
c = -4
im1 = ps.generators.rsa(im_or_shape=shape, r=r, clearance=c)
ax[0].imshow(im1, origin='lower', interpolation='none')
ax[0].axis(False)
ax[0].set_title(f'clearance = {c}')
c = 4
im2 = ps.generators.rsa(im_or_shape=shape, r=r, clearance=c)
ax[1].imshow(im2, origin='lower', interpolation='none')
ax[1].axis(False)
ax[1].set_title(f'clearance = {c}');
/tmp/ipykernel_7909/2646574643.py:4: DeprecationWarning: Call to deprecated function (or staticmethod) rsa. (This function will be renamed random_spheres in a future version)
im1 = ps.generators.rsa(im_or_shape=shape, r=r, clearance=c)
/tmp/ipykernel_7909/2646574643.py:10: DeprecationWarning: Call to deprecated function (or staticmethod) rsa. (This function will be renamed random_spheres in a future version)
im2 = ps.generators.rsa(im_or_shape=shape, r=r, clearance=c)

When adding additional spheres to an existing image, the clearance only applies to new spheres. To enforce clearance between the existing spheres you can dilate them by the amount of clearance desired (or erode them if overlap is desired). In this case you’ll want to set return_sphers=True
to obtain an image of only the new spheres, which can be added to the original ones:
im3 = ps.filters.fftmorphology(im=im2, strel=ps.tools.ps_disk(5), mode='dilation')
im4 = ps.generators.RSA(im_or_shape=im3, r=5, clearance=5, return_spheres=True)
im5 = im2 + im4
fig, ax = plt.subplots(1, 3, figsize=[10, 4])
ax[0].imshow(im2, origin='lower', interpolation='none')
ax[1].imshow(im4, origin='lower', interpolation='none')
ax[2].imshow(im5, origin='lower', interpolation='none');
/tmp/ipykernel_7909/2892074603.py:2: DeprecationWarning: Call to deprecated function (or staticmethod) RSA. (This function has been renamed to rsa (lowercase to meet pep8))
im4 = ps.generators.RSA(im_or_shape=im3, r=5, clearance=5, return_spheres=True)

volume_fraction
and n_max
#
By default it will try to insert as many spheres as possible. This can be controlled by setting the volume fraction or limiting the number of spheres inserted:
fig, ax = plt.subplots(1, 2, figsize=[8, 4])
n_max = 5
im1 = ps.generators.rsa(shape, r=r, clearance=c, n_max=n_max)
ax[0].imshow(im1, origin='lower', interpolation='none')
ax[0].axis(False)
ax[0].set_title(f'n_max = {n_max}')
vf = 0.2
im2 = ps.generators.rsa(shape, r=r, clearance=c, volume_fraction=vf)
ax[1].axis(False)
ax[1].set_title(f'volume_fraction = {vf}')
ax[1].imshow(im2, origin='lower', interpolation='none');
/tmp/ipykernel_7909/1007371573.py:4: DeprecationWarning: Call to deprecated function (or staticmethod) rsa. (This function will be renamed random_spheres in a future version)
im1 = ps.generators.rsa(shape, r=r, clearance=c, n_max=n_max)
/tmp/ipykernel_7909/1007371573.py:10: DeprecationWarning: Call to deprecated function (or staticmethod) rsa. (This function will be renamed random_spheres in a future version)
im2 = ps.generators.rsa(shape, r=r, clearance=c, volume_fraction=vf)

Note that this function returns the spheres as True
which usually indicates the pore phase in porespy, so these will treated as images of holes. If you intended to make an image of sphers, just invert the image:
im1 = ~im1
im2 = ~im2
fig, ax = plt.subplots(1, 2, figsize=[8, 4])
ax[0].imshow(im1, origin='lower', interpolation='none')
ax[0].axis(False)
ax[1].imshow(im2, origin='lower', interpolation='none')
ax[1].axis(False);
