pumapy.experimental

pumapy.filters

pumapy.filters.filters

Note: Most of the filters are simple wrappers of functions in either scikitimage or scipy.ndimage. The filters can be run directly in these packages if the user desires, but the wrapping is done for simplicity so that the Workspace class can be used, and the filter executions can be logged by the workspace class in order to document the simulation workflows.

The C++ version of puma implements the filters directly. But for python, there’s no reason to re-invent the wheel when so many great packages exist for image manipulation

pumapy.filters.filters.filter_closing(ws, cutoff, size=5)[source]

3D morphological closing filter (i.e. erosion first and then dilation).

Parameters
  • ws (Workspace) – input workspace

  • cutoff ((int, int)) – cutoff to binarize image

  • size (int) – size of the spherical windows used

Example

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6)
Importing .../100_fiberform.tif ... Done
>>> ws_closing = ws.copy()
>>> puma.filter_closing(ws_closing, cutoff=(90, 255), size=3)
>>> ws_binary = ws.copy()
>>> ws_binary.binarize_range((90, 255))
>>> # puma.compare_slices(ws_binary, ws_closing, 'z', index=1)  # to visualize it
pumapy.filters.filters.filter_dilate(ws, cutoff, size=5)[source]

3D morphological dilation filter.

Parameters
  • ws (Workspace) – input workspace

  • cutoff ((int, int)) – cutoff to binarize image

  • size (int) – size of the spherical windows used

Example

>>> import pumapy as puma
>>> ws = puma.generate_tpms((100, 100, 100), (0.02, 0.05), 0.201, 0)  # generate tpms material
Generating TPMS ...
>>> ws_dilate = ws.copy()
>>> puma.filter_dilate(ws_dilate, cutoff=(1, 1), size=5)  # dilating the copy
>>> # puma.compare_slices(ws, ws_dilate)  # to visualize it
pumapy.filters.filters.filter_edt(ws, cutoff)[source]

3D Exact euclidean distance transform.

Parameters
  • ws (Workspace) – input workspace

  • cutoff ((int, int)) – cutoff to binarize image

Example

>>> import pumapy as puma
>>> ws = puma.generate_tpms((100, 100, 100), (0.02, 0.05), 0.201, 0)  # generate tpms material
Generating TPMS...
>>> ws_edt = ws.copy()
>>> puma.filter_edt(ws_edt, cutoff=(1, 1))
>>> # puma.compare_slices(ws, ws_edt)  # to visualize it
pumapy.filters.filters.filter_erode(ws, cutoff, size=5)[source]

3D morphological erosion filter.

Parameters
  • ws (Workspace) – input workspace

  • cutoff ((int, int)) – cutoff to binarize image

  • size (int) – size of the spherical windows used

Example

>>> import pumapy as puma
>>> ws = puma.generate_tpms((100, 100, 100), (0.02, 0.05), 0.201, 0)  # generate tpms material
Generating TPMS ...
>>> ws_erode = ws.copy()
>>> puma.filter_erode(ws_erode, (1, 1))  # eroding the copy
>>> # puma.compare_slices(ws, ws_erode)  # to visualize it
pumapy.filters.filters.filter_gaussian(ws, sigma=1, apply_on_orientation=False)[source]

3D Gaussian filter

Parameters
  • ws (Workspace) – input workspace

  • sigma (int) – size of kernel

  • apply_on_orientation (bool) – specify whether to apply filter on orientation field

Example

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6)
Importing .../100_fiberform.tif ... Done
>>> ws_gaussian = ws.copy()
>>> puma.filter_gaussian(ws_gaussian, sigma=2, apply_on_orientation=False)
>>> # puma.compare_slices(ws, ws_gaussian, 'z', index=1)  # to visualize it
pumapy.filters.filters.filter_mean(ws, size=5)[source]

3D Mean filter.

Parameters
  • ws (Workspace) – input workspace

  • size (int) – size of window

Example

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6)
Importing .../100_fiberform.tif ... Done
>>> ws_mean = ws.copy()
>>> puma.filter_mean(ws_mean, size=10)
>>> # puma.compare_slices(ws, ws_mean)  # to visualize it
pumapy.filters.filters.filter_median(ws, size)[source]

3D Median filter

Parameters
  • ws (Workspace) – input workspace

  • size (int) – size of window

Example

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6)
Importing .../100_fiberform.tif ... Done
>>> ws_median = ws.copy()
>>> puma.filter_median(ws_median, size=10)
>>> # puma.compare_slices(ws, ws_median)  # to visualize it
pumapy.filters.filters.filter_opening(ws, cutoff, size=5)[source]

3D morphological opening filter (i.e. dilation first and then erosion).

Parameters
  • ws (Workspace) – input workspace

  • cutoff ((int, int)) – cutoff to binarize image

  • size (int) – size of the spherical windows used

Example

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6)
Importing .../100_fiberform.tif ... Done
>>> ws_opening = ws.copy()
>>> puma.filter_opening(ws_opening, cutoff=(90, 255), size=3)
>>> ws_binary = ws.copy()
>>> ws_binary.binarize_range((90, 255))
>>> # puma.compare_slices(ws_binary, ws_opening, 'z', index=1)  # to visualize it

pumapy.generation

pumapy.generation.cylinder_square_array

class pumapy.generation.cylinder_square_array.GeneratorSquareArray(size, porosity)[source]

Bases: object

error_check()[source]
generate()[source]
log_input()[source]
log_output()[source]
pumapy.generation.cylinder_square_array.generate_cylinder_square_array(size, porosity, segmented=True)[source]

Generate a 2D periodic array of circles

Parameters
  • size (int) – length of one side of the output domain

  • porosity (float) – porosity of the output domain

  • segmented (bool) – return a domain that is already segmented (i.e. each sphere with unique ID) or with grayscales 0-255 with threshold=128 for the input diameter

Returns

array of circles

Return type

Workspace

Example

>>> import pumapy as puma
>>> ws = puma.generate_cylinder_square_array(100, 0.8, segmented=True)
Generated in: ...
>>> # puma.render_volume(ws)  # to visualize it

pumapy.generation.pitting

class pumapy.generation.pitting.GeneratorPits(workspace, surface_threshold, mean_radius, deviation_radius, volume_fraction_removed, max_pits)[source]

Bases: object

error_check()[source]
generate()[source]
log_input()[source]
log_output()[source]
pumapy.generation.pitting.generate_pitting(workspace, surface_threshold, mean_radius, deviation_radius, volume_fraction_removed, max_pits=10000)[source]

Generation of pitting into existing workspace

Parameters
  • workspace (pumapy.Workspace) – pumapy workspace to add pitting to

  • surface_threshold (int) – threshold value at which the solid starts. Void phase is contained in (0,surface_threshold-1)

  • mean_radius (float) – mean radius of the pits

  • deviation_radius (float) – deviation in the radius of the pits (plus or minus)

  • volume_fraction_removed (float) – volume fraction to be removed by pits

  • max_pits (int) – maximum number of pits. To ensure while(true) condition doesn’t occur if specified volume_fraction can’t be reached

Returns

None

Return type

None

Example

>>> import pumapy as puma
>>> shape = (200, 200, 200)  # size of the domain, in voxels.
>>> w = 0.08  # value of w in the equations above
>>> q = 0.2  # value of q in the equations above
>>> ws_eq0 = puma.generate_tpms(shape, w, q, equation=0, segmented=False)
Generating TPMS ...
>>> surface_threshold = 128 # threshold value at which the solid starts. Void phase is contained in (0,surface_threshold-1)
>>> mean_radius = 4 # Mean radius of the pits, in voxels
>>> deviation_radius = 3 # Deviation of the pits, in voxels
>>> volume_fraction_removed = 0.01 # Volume fraction of the pits to be removed
>>> puma.experimental.generate_pitting(ws_eq0, surface_threshold, mean_radius, deviation_radius, volume_fraction_removed)
Volume Fraction for cutoff ...
>>> # puma.render_contour(ws_eq0, (128,255))  # to visualize it

pumapy.generation.random_fibers

The following function was copied and modified from the porespy project (distributed under the MIT License). See https://github.com/PMEAL/porespy/blob/dev/porespy/generators/_imgen.py for more information. See https://github.com/PMEAL/porespy/blob/dev/LICENSE for the license.

pumapy.generation.random_fibers.generate_random_fibers(shape, radius, nfibers=None, porosity=None, phi=90.0, theta=90.0, length=None, max_iter=5, allow_intersect=True, segmented=True)[source]

Generates random fibers from number of fibers or porosity

Parameters
  • shape ((int, int, int)) – the shape of the workspace to generate in (Nx, Ny, Nz) where N is the number of voxels.

  • radius (int) – the radius of the fibers in voxels

  • nfibers (int or None) – the number of fibers to add to the domain. Adjust this value to control the final porosity, which is not easily specified since cylinders overlap and intersect different fractions of the domain

  • porosity (float) – the target value for the porosity of the generated mat. The function uses an algorithm for predicting the number of required number of cylinder, and refines this over a certain number of fractional insertions (according to the ‘iterations’ input)

  • phi (float) – a value between 0 and 90 that controls the amount that the fibers lie out of the XY plane, with 0 meaning all fibers lie in the XY plane, and 90 meaning that cylinders are randomly oriented out of the plane by as much as +/- 90 degrees

  • theta (float) – a value between 0 and 90 that controls the amount of rotation in the XY plane, with 0 meaning all fibers point in the X-direction, and 90 meaning they are randomly rotated about the Z axis by as much as +/- 90 degrees

  • length (float) – the length of the cylinders to add. If None (default) then the cylinders will extend beyond the domain in both directions so no ends will exist. If a scalar value is given it will be interpreted as the Euclidean distance between the two ends of the cylinder. Note that one or both of the ends may still lie outside the domain, depending on the randomly chosen center point of the cylinder

  • max_iter (int) – the number of fractional fiber insertions used to target the requested porosity. By default a value of 3 is used (and this is typically effective in getting very close to the targeted porosity), but a greater number can be input to improve the achieved porosity

  • allow_intersect (bool) – allow intersection betweem the fibers

  • segmented (bool) – return a domain that is already segmented (i.e. each fiber with unique ID) or with grayscales 0-255 with threshold=128 for the input diameter

Returns

random fibers domain

Return type

Workspace

pumapy.generation.random_fibers.generate_random_fibers_1D(shape, radius, nfibers=None, porosity=None, direction='z', length=None, max_iter=5, allow_intersect=True, segmented=True)[source]

Generates random 1D fibers from number of fibers or porosity

Parameters
  • shape ((int, int, int)) – the shape of the workspace to generate in (Nx, Ny, Nz) where N is the number of voxels.

  • radius (int) – the radius of the fibers in voxels

  • nfibers (int or None) – the number of fibers to add to the domain. Adjust this value to control the final porosity, which is not easily specified since cylinders overlap and intersect different fractions of the domain

  • porosity (float) – the target value for the porosity of the generated mat. The function uses an algorithm for predicting the number of required number of cylinder, and refines this over a certain number of fractional insertions (according to the ‘iterations’ input)

  • direction (string) – Either ‘x’, ‘y’, or ‘z’. The direction of the 1D fibers

  • length (float) – the length of the cylinders to add. If None (default) then the cylinders will extend beyond the domain in both directions so no ends will exist. If a scalar value is given it will be interpreted as the Euclidean distance between the two ends of the cylinder. Note that one or both of the ends may still lie outside the domain, depending on the randomly chosen center point of the cylinder

  • max_iter (int) – the number of fractional fiber insertions used to target the requested porosity. By default a value of 3 is used (and this is typically effective in getting very close to the targeted porosity), but a greater number can be input to improve the achieved porosity

  • allow_intersect (bool) – allow intersection betweem the fibers

  • segmented (bool) – return a domain that is already segmented (i.e. each fiber with unique ID) or with grayscales 0-255 with threshold=128 for the input diameter

Returns

random fibers domain

Return type

Workspace

Example

>>> import pumapy as puma
>>> # specify porosity
>>> ws_fibers = puma.generate_random_fibers_1D(shape=(100, 100, 100), radius=4, porosity=0.8, direction='x', length=200, allow_intersect=True, segmented=True)
Fibers created...
>>> # puma.render_volume(ws_fibers, cutoff=(1, ws_fibers.max()), cmap='jet')  # to visualize it
>>> # puma.render_orientation(ws_fibers)
>>>
>>> # specify number of fibers
>>> ws_fibers = puma.generate_random_fibers_1D(shape=(100, 100, 100), radius=4, nfibers=100, direction='y', length=200, allow_intersect=True, segmented=False)
Fibers created...
>>> # puma.render_volume(ws_fibers, cutoff=(1, ws_fibers.max()), cmap='jet')  # to visualize it
>>> # puma.render_orientation(ws_fibers)
>>>
>>> # don't allow intersection between fibers
>>> ws_fibers = puma.generate_random_fibers_1D(shape=(100, 100, 100), radius=4, porosity=0.9, direction='z', length=200, allow_intersect=False, segmented=True)
Fibers created...
>>> # puma.render_volume(ws_fibers, cutoff=(1, ws_fibers.max()), cmap='jet')  # to visualize it
>>> # puma.render_orientation(ws_fibers)
pumapy.generation.random_fibers.generate_random_fibers_helper(shape, radius, nfibers, porosity, angle_type, variation, direction, length, max_iter, allow_intersect=True, segmented=True)[source]
pumapy.generation.random_fibers.generate_random_fibers_isotropic(shape, radius, nfibers=None, porosity=None, length=None, max_iter=5, allow_intersect=True, segmented=True)[source]

Generates random isotropic fibers from number of fibers or porosity

Parameters
  • shape ((int, int, int)) – the shape of the workspace to generate in (Nx, Ny, Nz) where N is the number of voxels.

  • radius (int) – the radius of the fibers in voxels

  • nfibers (int or None) – the number of fibers to add to the domain. Adjust this value to control the final porosity, which is not easily specified since cylinders overlap and intersect different fractions of the domain

  • porosity (float) – the target value for the porosity of the generated mat. The function uses an algorithm for predicting the number of required number of cylinder, and refines this over a certain number of fractional insertions (according to the ‘iterations’ input)

  • length (float) – the length of the cylinders to add. If None (default) then the cylinders will extend beyond the domain in both directions so no ends will exist. If a scalar value is given it will be interpreted as the Euclidean distance between the two ends of the cylinder. Note that one or both of the ends may still lie outside the domain, depending on the randomly chosen center point of the cylinder

  • max_iter (int) – the number of fractional fiber insertions used to target the requested porosity. By default a value of 3 is used (and this is typically effective in getting very close to the targeted porosity), but a greater number can be input to improve the achieved porosity

  • allow_intersect (bool) – allow intersection betweem the fibers

  • segmented (bool) – return a domain that is already segmented (i.e. each fiber with unique ID) or with grayscales 0-255 with threshold=128 for the input diameter

Returns

random fibers domain

Return type

Workspace

Example

>>> import pumapy as puma
>>> # specify porosity
>>> ws_fibers = puma.generate_random_fibers_isotropic(shape=(100, 100, 100), radius=4, porosity=0.8, length=200, allow_intersect=True, segmented=True)
Fibers created...
>>> # puma.render_volume(ws_fibers, cutoff=(1, ws_fibers.max()), cmap='jet')  # to visualize it
>>> # puma.render_orientation(ws_fibers)
>>>
>>> # specify number of fibers
>>> ws_fibers = puma.generate_random_fibers_isotropic(shape=(100, 100, 100), radius=4, nfibers=100, length=200, allow_intersect=True, segmented=False)
Fibers created...
>>> # puma.render_volume(ws_fibers, cutoff=(1, ws_fibers.max()), cmap='jet')  # to visualize it
>>> # puma.render_orientation(ws_fibers)
pumapy.generation.random_fibers.generate_random_fibers_transverseisotropic(shape, radius, nfibers=None, porosity=None, direction='z', variation=0, length=None, max_iter=5, allow_intersect=True, segmented=True)[source]

Generates random transverse isotropic fibers from number of fibers or porosity

Parameters
  • shape ((int, int, int)) – the shape of the workspace to generate in (Nx, Ny, Nz) where N is the number of voxels.

  • radius (int) – the radius of the fibers in voxels

  • nfibers (int or None) – the number of fibers to add to the domain. Adjust this value to control the final porosity, which is not easily specified since cylinders overlap and intersect different fractions of the domain

  • porosity (float) – the target value for the porosity of the generated mat. The function uses an algorithm for predicting the number of required number of cylinder, and refines this over a certain number of fractional insertions (according to the ‘iterations’ input)

  • direction (string) – Either ‘x’, ‘y’, or ‘z’. The direction orthogonal to the plane of the fibers. Example: for fibers oreinted in XY, put ‘z’

  • variation (float) – The angle variation in the orthogonal direction. 0 for no variation, 90 for full variation.

  • length (float) – the length of the cylinders to add. If None (default) then the cylinders will extend beyond the domain in both directions so no ends will exist. If a scalar value is given it will be interpreted as the Euclidean distance between the two ends of the cylinder. Note that one or both of the ends may still lie outside the domain, depending on the randomly chosen center point of the cylinder

  • max_iter (int) – the number of fractional fiber insertions used to target the requested porosity. By default a value of 3 is used (and this is typically effective in getting very close to the targeted porosity), but a greater number can be input to improve the achieved porosity

  • allow_intersect (bool) – allow intersection betweem the fibers

  • segmented (bool) – return a domain that is already segmented (i.e. each fiber with unique ID) or with grayscales 0-255 with threshold=128 for the input diameter

Returns

random fibers domain

Return type

Workspace

Example

>>> import pumapy as puma
>>> # specify porosity
>>> ws_fibers = puma.generate_random_fibers_transverseisotropic(shape=(100, 100, 100), radius=4, porosity=0.8, direction='x', variation=15, length=200, allow_intersect=True, segmented=True)
Fibers created...
>>> # puma.render_volume(ws_fibers, cutoff=(1, ws_fibers.max()), cmap='jet')  # to visualize it
>>> # puma.render_orientation(ws_fibers)
>>>
>>> # specify number of fibers
>>> ws_fibers = puma.generate_random_fibers_transverseisotropic(shape=(100, 100, 100), radius=4, nfibers=100, direction='y', variation=0, length=200, allow_intersect=True, segmented=False)
Fibers created...
>>> # puma.render_volume(ws_fibers, cutoff=(1, ws_fibers.max()), cmap='jet')  # to visualize it
>>> # puma.render_orientation(ws_fibers)
>>>
>>> # don't allow intersection between fibers
>>> ws_fibers = puma.generate_random_fibers_transverseisotropic(shape=(100, 100, 100), radius=4, porosity=0.9, direction='z', variation=30, length=200, allow_intersect=False, segmented=True)
Fibers created...
>>> # puma.render_volume(ws_fibers, cutoff=(1, ws_fibers.max()), cmap='jet')  # to visualize it
>>> # puma.render_orientation(ws_fibers)

pumapy.generation.random_spheres

class pumapy.generation.random_spheres.GeneratorSpheres(size, diameter, porosity, allow_intersect, segmented)[source]

Bases: object

error_check()[source]
generate()[source]
log_input()[source]
log_output()[source]
pumapy.generation.random_spheres.generate_random_spheres(shape, diameter, porosity, allow_intersect=True, segmented=True)[source]

Generation of random spheres domains

Parameters
  • shape ((int, int, int)) – shape of 3D domain (x,y,z)

  • diameter (float) – diameter of the random spheres in voxels

  • porosity (float) – target porosity of the generated structure

  • allow_intersect (bool) – allow the spheres to intersect or not

  • segmented (bool) – return a domain that is already segmented (i.e. each sphere with unique ID) or with grayscales 0-255 with threshold=128 for the input diameter

Returns

random spheres domain

Return type

Workspace

Example

>>> import pumapy as puma
>>> ws_generated = puma.generate_random_spheres(shape=(100,100,100), diameter=10, porosity=0.8, allow_intersect=True, segmented=True)
Approximately ... spheres to be generated...
>>> # puma.render_volume(ws_generated, cutoff=(1, ws_generated.max()), cmap='jet')  # to visualize it

pumapy.generation.single_sphere

class pumapy.generation.single_sphere.GeneratorSphere(size, center, diameter)[source]

Bases: object

error_check()[source]
generate()[source]
log_input()[source]
log_output()[source]
pumapy.generation.single_sphere.generate_sphere(shape, center, diameter, segmented=True)[source]

Generation of a sphere at a given point and diameter

Parameters
  • shape ((int, int, int)) – size of 3D domain (x,y,z)

  • center ((int, int, int)) – centerpoint of sphere (x,y,z)

  • diameter (float) – diameter of the random spheres in voxels

  • segmented (bool) – return a domain that is already segmented (i.e. each sphere with unique ID) or with grayscales 0-255 with threshold=128 for the input diameter

Returns

domain with sphere with input diameter

Return type

Workspace

Example

>>> import pumapy as puma
>>> ws = puma.generate_sphere((100, 100, 100), (50, 50, 50), 80)
Generated in...
>>> # puma.render_volume(ws.matrix[:ws.matrix.shape[0]//2])  # to visualize it
pumapy.generation.single_sphere.get_circle(diameter)[source]
pumapy.generation.single_sphere.get_circle_even(diameter)[source]
pumapy.generation.single_sphere.get_circle_odd(diameter)[source]
pumapy.generation.single_sphere.get_sphere(diameter)[source]

pumapy.generation.tpms

class pumapy.generation.tpms.GeneratorTPMS(size, w, q, equation)[source]

Bases: object

error_check()[source]
generate()[source]
log_input()[source]
log_output()[source]
pumapy.generation.tpms.generate_tpms(shape, w, q, equation=0, segmented=True)[source]

Generation of triply periodic minimal surface material

Parameters
  • shape ((int, int, int)) – shape of 3D domain (x,y,z)

  • w (float or (float, float)) – w parameter for tpms

  • q (float or (float, float)) – q parameter for tpms (float or tuple)

  • equation (int) – equation 0, 1, or 2 for tpms

  • segmented (bool) – return a domain that is already segmented (i.e. 1 for solid and 0 for void) or with grayscales 0-255 with threshold=128 for the solid

Returns

TPMS domain with grayscales from 0-255 with threshold=128 for the normal TPMS geometry

Return type

Workspace

Example

>>> import pumapy as puma
>>> shape = (200, 200, 200)  # size of the domain, in voxels.
>>> w = 0.08  # value of w in the equations above
>>> q = 0.2  # value of q in the equations above
>>> ws_eq0 = puma.generate_tpms(shape, w, q, equation=0, segmented=False)
Generating TPMS ...
>>> ws_eq1 = puma.generate_tpms(shape, w, q, equation=1, segmented=False)
Generating TPMS ...
>>> ws_eq2 = puma.generate_tpms(shape, w, q, equation=2, segmented=False)
Generating TPMS ...
>>> # puma.render_contour(ws_eq0, cutoff=(128, 255))  # to visualize them
>>> # puma.render_contour(ws_eq1, cutoff=(128, 255))
>>> # puma.render_contour(ws_eq2, cutoff=(128, 255))

pumapy.generation.tpms_utils

pumapy.generation.tpms_utils.generate(matrix, l_x, l_y, l_z, wmin, wmax, qmin, qmax, equation)

pumapy.generation.tpms_utils

pumapy.generation.tpms_utils.generate(matrix, l_x, l_y, l_z, wmin, wmax, qmin, qmax, equation)

pumapy.io

pumapy.io.export_texgen_weave

pumapy.io.export_texgen_weave.export_weave_vtu(filename, weave, domain, max_dim_nvox, round_vox_up=True, export_orientation=True)[source]

Exporting weave to vtu, to be read by pumapy

Parameters
  • filename (string) – filepath and name

  • weave (CTextile or child class of CTextile) – weave object, as defined in TexGen

  • domain (CDomainPlanes) – domain size object, as defined in TexGen

  • max_dim_nvox (int) – number of voxels to add in the largest domain dimension

  • round_vox_up (bool) – for the shorter dimensions, round number of voxels up (for +/-1 vox)

  • export_orientation (bool) – specify whether to export orientation

Returns

filename of weave exported (input filename + dimensions)

Return type

string

pumapy.io.input

pumapy.io.input.import_3Dtiff(filename, voxel_length=1e-06, import_ws=True)[source]

Function to io 3D tiff

Parameters
  • filename (string) – filepath and name

  • voxel_length (float) – size of a voxel side

  • import_ws (bool) – if True returns a puma.Workspace, otherwise a ndarray

Returns

domain

Return type

pumapy.Workspace or np.ndarray

Example

>>> import pumapy as puma
>>> ws_tiff = puma.import_3Dtiff(puma.path_to_example_file("50_artfibers.tif"), 1.3e-6, import_ws=True)
Importing ...
>>> ws_tiff.get_shape()
(50, 50, 50)
pumapy.io.input.import_bin(filename)[source]

Import a pumapy.Workspace to binary (.pumapy extension)

Parameters

filename (string) – filepath and name

Returns

domain

Return type

pumapy.Workspace

Example

>>> import pumapy as puma
>>> ws_binary = puma.import_bin(puma.path_to_example_file("fibers_with_orientation.pumapy"))
Importing ...
pumapy.io.input.import_scalar_field_from_chfem(filename, domain_shape, rotate_domain=True)[source]

Import scalar field (e.g. temperature, pressure) output from CHFEM_GPU CUDA kernels (https://gitlab.com/cortezpedro/chfem_gpu)

Parameters
  • filename (string) – file path and name of .bin file

  • domain_shape ((int, int, int)) – shape of domain for which the scalar field was generated

  • rotate_domain (bool) – rotate the domain to be in the same format as export

Returns

scalar field (x,y,z)

Return type

np.ndarray

pumapy.io.input.import_sparta_implicit_surfaces(filename, dimension=3, voxel_length=1e-06, import_ws=True, extend_to_boundary=True)[source]

Function to io sparta implicit surfaces

Parameters
  • filename (string) – filepath and name

  • dimension (int) – dimensionality of imported sparta structure

  • voxel_length (float) – size of a voxel side

  • import_ws (bool) – if True returns a puma.Workspace, otherwise a ndarray

  • extend_to_boundary (bool) – if True recreates nonzero boundary values as extension of inner structure, otherwise all boundary values equal zero

Returns

domain

Return type

pumapy.Workspace or np.ndarray

Example

>>> import pumapy as puma
>>> ws = puma.import_bin(puma.path_to_example_file("fibers_with_orientation.pumapy"))
Importing ...
>>> puma.experimental.export_sparta_implicit_surfaces("surfaces", ws)
Exporting ...
>>> surf = puma.experimental.import_sparta_implicit_surfaces("surfaces.pumapy.isurf", dimension=3, voxel_length=1.0e-6, import_ws=False)
Importing ...
pumapy.io.input.import_stress_field_from_chfem(filename, domain_shape, rotate_domain=True)[source]

Import stress fields output from CHFEM_GPU CUDA kernels (https://gitlab.com/cortezpedro/chfem_gpu)

Parameters
  • filename (string) – file path and name of .bin file

  • domain_shape ((int, int, int)) – shape of domain for which the scalar field was generated

  • rotate_domain (bool) – rotate the domain to be in the same format as export

Returns

direct stresses (x,y,z,3) and shear stresses (x,y,z,3)

Return type

(np.ndarray, np.ndarray)

pumapy.io.input.import_vector_field_from_chfem(filename, domain_shape, rotate_domain=True, correct_direction=None)[source]

Import vector field (e.g. heat flux, displacement, velocity) output from CHFEM_GPU CUDA kernels (https://gitlab.com/cortezpedro/chfem_gpu)

Parameters
  • filename (string) – file path and name of .bin file

  • domain_shape ((int, int, int)) – shape of domain for which the scalar field was generated

  • rotate_domain (bool) – rotate the domain to be in the same format as export

  • correct_direction (str) – correct orientation field according to simulation direction, expects ‘x’, ‘y’, or ‘z’

Returns

vector field (x,y,z,3)

Return type

np.ndarray

pumapy.io.input.import_vti(filename, voxel_length=None, import_ws=True)[source]

Function to import either legacy VTK file (.vtk) or vtkImageData (.vti)

Parameters
  • filename (string) – filepath and name

  • voxel_length (float) – voxel_length. If None, voxel_length from the vtk file is used

  • import_ws (bool) – True returns a puma.Workspace, otherwise a list of ndarrays

Returns

if import_ws is True, then it returns a Workspace. if import_ws is False, it returns a dictionary of ndarrays as {“name1”: data1, “name2”: data2 …}

Return type

pumapy.Workspace or {str: np.ndarray}

Example

>>> import pumapy as puma
>>> ws_vtk = puma.import_vti(puma.path_to_example_file("fibers_with_orientation.vti"))
Importing ...
pumapy.io.input.import_weave_vtu(filename, from_texgen_gui=False)[source]

Import TexGen vtu weave in a Workspace

Parameters
  • filename (string) – file path and name

  • from_texgen_gui (bool) – voxel grid exported from the TexGen GUI (Windows) or from TexGen inside PuMA

Returns

voxelized weave from TexGen

Return type

pumapy.Workspace

pumapy.io.input.io_logs(ws, filename, input=True)[source]

pumapy.io.output

pumapy.io.output.export_3Dtiff(filename, ws_or_nparray, to8bit=True)[source]

Export either a puma.Workspace or numpy array to 3Dtiff

Parameters
  • filename (string) – filepath and name

  • ws_or_nparray (Workspace or ndarray) – to be exported

  • to8bit (bool) – if True, it converts the image to 8bit, otherwise 16bit is exported

Example

>>> import pumapy as puma
>>> ws_tiff = puma.import_3Dtiff(puma.path_to_example_file("50_artfibers.tif"), 1.3e-6, import_ws=True)
Importing ...
>>> puma.export_3Dtiff("50_artfibers.tif", ws_tiff)
Exporting ...
pumapy.io.output.export_bin(filename, ws)[source]

Export a puma.Workspace to binary (.pumapy extension)

Parameters
  • filename (string) – filepath and name

  • ws – to be exported

Type

pumapy.Workspace

Example

>>> import pumapy as puma
>>> ws_binary = puma.import_bin(puma.path_to_example_file("fibers_with_orientation.pumapy"))
Importing ...
>>> puma.export_bin("fibers_with_orientation.vti", ws_binary)
Exporting ...
pumapy.io.output.export_for_chfem(filename, ws, analysis, solver=0, export_nf=True, export_json=True, tol=1e-06, max_iter=10000)[source]

Export a puma.Workspace to run an analysis in CHFEM_GPU CUDA kernels (https://gitlab.com/cortezpedro/chfem_gpu) or CHPACK Julia package (https://gitlab.com/lcc-uff/Chpack.jl)

Parameters
  • filename (string) – filepath and name

  • ws (pumapy.Workspace) – to be exported

  • type_of_analysis (int) – 0 = conductivity, 1 = elasticity, 2 = permeability

  • type_of_solver (int) – 0 = pcg (default), 1 = cg, 2 = minres

  • export_nf (bool) – export .nf file with simulations inputs for CHFEM_GPU

  • export_json (bool) – export .json file with simulations inputs for CHFPACK

  • tol (float) – solver tolerance for simulation

  • max_iter (int) – maximum number of iterations

Example

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing ...
>>> puma.export_for_chfem('200_fiberform', ws, 2, tol=1e-6, max_iter=100000)
pumapy.io.output.export_sparta_implicit_surfaces(filename, ws)[source]

Export a puma.Workspace to binary (.pumapy extension)

Parameters
  • filename (string) – filepath and name

  • ws (pumapy.Workspace) – to be exported

Example

>>> import pumapy as puma
>>> ws = puma.import_bin(puma.path_to_example_file("fibers_with_orientation.pumapy"))
Importing ...
>>> puma.experimental.export_sparta_implicit_surfaces("surfaces", ws)
Exporting ...
pumapy.io.output.export_stl(filename, ws, cutoff, flag_closed_edges=True, flag_gaussian=False, binary=True)[source]

Export a puma.Workspace to STL

Parameters
  • filename (string) – filepath and name

  • ws (pumapy.Workspace) – to be exported

  • cutoff ((int, int)) – specify cutoff to binarize material

  • flag_closed_edges (bool) – close the surface edges on the boundaries

  • flag_gaussian (bool) – apply Gaussian filter before creating surface

Example

>>> import pumapy as puma
>>> ws_imported = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing ...
>>> puma.export_stl('200_fiberform', ws_imported, cutoff=(100, 255), flag_closed_edges=True)
Exporting ...
pumapy.io.output.export_vti(filename, dict_data, voxel_length=None)[source]

Export either a puma.Workspace or numpy array to vti

Parameters
  • filename (string) – filepath and name

  • dict_data (dict or Workspace or np.ndarray) – dictionary setup as {“name1”: data1, “name2”: data2 …} containing either Workspaces or ndarrays

  • voxel_length (float) – with voxel length to give to Numpy arrays (if any)

Example

>>> import pumapy as puma
>>> ws_vtk = puma.import_vti(puma.path_to_example_file("fibers_with_orientation.vti"))
Importing ...
>>> puma.export_vti("fibers_with_orientation.vti", ws_vtk)
Exporting ...

pumapy.material_properties

pumapy.material_properties.anisotropic_radiation

class pumapy.material_properties.anisotropic_radiation.AnisotropicRadiation(workspace, void_cutoff, sources_number, direction, bin_density, export_plot)[source]

Bases: object

compute()[source]
error_check()[source]
log_input()[source]
log_output()[source]
pumapy.material_properties.anisotropic_radiation.compute_extinction_coefficients_anisotropic(ws, rays_distances, sources_number, bin_density=10000, export_pathname=None)[source]

Compute the extinction coefficient based on the ray casting radiation simulation (this is normally a step inside the compute_radiation function)

Parameters
  • ws (pumapy.Workspace) – domain

  • rays_distances (np.ndarray) – rays distances, as output by compute_radiation function

  • sources_number (int) – number of light sources spread randomly in the void space (i.e. 0)

  • bin_density (int) – number of bins used to create histogram of ray distances

  • export_pathname (str) – path to save curve plot of ray distance distribution

Returns

extinction coefficient (beta), its standard deviation

Return type

(float, float)

pumapy.material_properties.anisotropic_radiation.compute_radiation_anisotropic(workspace, void_cutoff, sources_number, bin_density=10000, export_pathname=None)[source]

Compute the anisotropic radiative thermal conductivity through ray tracing

Parameters
  • workspace (pumapy.Workspace) – domain

  • void_cutoff ((int, int)) – specify the void phase

  • sources_number (int) – number of light sources spread randomly in the void space (i.e. 0)

  • bin_density (int) – number of bins used to create histogram of ray distances

  • export_pathname (str) – path to save curve plot of ray distance distribution

Returns

extinction coefficient (beta), its standard deviation and of ray distances

Return type

(float, float, np.ndarray)

pumapy.material_properties.conductivity

Further explained in publication: Semeraro, F., Ferguson, J.C., Acin, M., Panerai, F. and Mansour, N.N., 2021. Anisotropic analysis of fibrous and woven materials part 2: Computation of effective conductivity. Computational Materials Science, 186, p.109956. https://www.sciencedirect.com/science/article/abs/pii/S092702562030447X

pumapy.material_properties.conductivity.compute_electrical_conductivity(workspace, cond_map, direction, side_bc='p', prescribed_bc=None, tolerance=1e-05, maxiter=10000, solver_type='bicgstab', display_iter=True, method='fv', matrix_free=True)[source]

Compute the electrical conductivity

Parameters
  • workspace (pumapy.Workspace) – domain

  • cond_map (IsotropicConductivityMap or AnisotropicConductivityMap) – local constituents electrical conductivities

  • direction (string) – direction for solve (‘x’,’y’,’z’, or ‘’ for prescribed_bc). If provided, prescribed_bc is ignored

  • side_bc (string) – side boundary conditions can be symmetric (‘s’) or periodic (‘p’). Only periodic available when method=’fe’

  • prescribed_bc (pumapy.IsotropicConductivityBC or pumapy.AnisotropicConductivityBC or None) – object holding dirichlet BC, only available for isotropic of MPFA implementations. Need to set direction=’’ in order to provide it. When prescribed_bc is provided, keff is not printed but it is computed as if direction==’x’ for testing purposes.

  • tolerance (float) – tolerance for iterative solver

  • maxiter (int) – maximum Iterations for solver

  • solver_type (string) – solver type, options: ‘bicgstab’ (default), ‘cg’, ‘gmres’, ‘minres’ (only for method=’fe’), ‘direct’

  • display_iter (bool) – display iterations and residual

  • method (string) – whether to use finite volume solver (‘fv’, either isotropic solver if IsotropicConductivityMap is passed, or mpfa if AnisotropicConductivityMap) or finite element Q1-Q1 EBE solver (‘fe’). For the latter method, it is recommended to use solver_type=’minres’ as lighter and faster

  • matrix_free (bool) – if True, then use matrix-free method if possible (only available for fv isotropic solver or for fe solver when the solver type is not ‘direct’)

Returns

electrical conductivity, potential field, flux

Return type

((float, float, float), numpy.ndarray, numpy.ndarray)

pumapy.material_properties.conductivity.compute_thermal_conductivity(workspace, cond_map, direction, side_bc='p', prescribed_bc=None, tolerance=1e-05, maxiter=10000, solver_type='bicgstab', display_iter=True, method='fv', matrix_free=True)[source]

Compute the thermal conductivity

Parameters
  • workspace (pumapy.Workspace) – domain

  • cond_map (IsotropicConductivityMap or AnisotropicConductivityMap) – local constituents themal conductivities

  • direction (string) – direction for solve (‘x’,’y’,’z’, or ‘’ for prescribed_bc). If provided, prescribed_bc is ignored

  • side_bc (string) – side boundary conditions can be symmetric (‘s’) or periodic (‘p’). Only periodic available when method=’fe’

  • prescribed_bc (pumapy.IsotropicConductivityBC or pumapy.AnisotropicConductivityBC or None) – object holding dirichlet BC, only available for isotropic of MPFA implementations. Need to set direction=’’ in order to provide it. When prescribed_bc is provided, keff is not printed but it is computed as if direction==’x’ for testing purposes.

  • tolerance (float) – tolerance for iterative solver

  • maxiter (int) – maximum Iterations for solver

  • solver_type (string) – solver type, options: ‘bicgstab’ (default), ‘cg’, ‘gmres’, ‘minres’ (only for method=’fe’), ‘direct’

  • display_iter (bool) – display iterations and residual

  • method (string) – whether to use finite volume solver (‘fv’, either isotropic solver if IsotropicConductivityMap is passed, or mpfa if AnisotropicConductivityMap) or finite element Q1-Q1 EBE solver (‘fe’). For the latter method, it is recommended to use solver_type=’minres’ as lighter and faster

  • matrix_free (bool) – if True, then use matrix-free method if possible (only available for fv isotropic solver or for fe solver when the solver type is not ‘direct’)

Returns

thermal conductivity, temperature field, flux

Return type

((float, float, float), numpy.ndarray, numpy.ndarray)

Example

>>> import pumapy as puma
>>> ws_fiberform = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing .../200_fiberform.tif ... Done
>>> ws_fiberform.rescale(0.5, segmented=False)
Rescaled workspace size: (100, 100, 100)
>>> # Conductivity with Isotropic local phases
>>> cond_map = puma.IsotropicConductivityMap()
>>> cond_map.add_material((0, 89), 0.0257)
>>> cond_map.add_material((90, 255), 12)
>>> k_eff_x, T_x, q_x = puma.compute_thermal_conductivity(ws_fiberform, cond_map, 'x', 's', matrix_free=True)
Approximate memory requirement for simulation...
>>> # Conductivity with Anisotropic local phases
>>> puma.compute_orientation_st(ws_fiberform, cutoff=(90, 255))
First gradient computation...
>>> cond_map = puma.AnisotropicConductivityMap()
>>> # conductivity of the void phase to be 0.0257 (air at STP)
>>> cond_map.add_isotropic_material((0, 89), 0.0257)
>>> # axial fiber conductivity of 12, radial fiber conductivity of 0.7
>>> cond_map.add_material_to_orient((90, 255), 12., 0.7)
>>> k_eff_z, T_z, q_z = puma.compute_thermal_conductivity(ws_fiberform, cond_map, 'z', 's')  # method='fe' for finite element
Approximate memory requirement for simulation...
>>> # plot_conductivity_fields(ws, T_z, q_z)  # to visualize fields
>>> # export_conductivity_fields_vti("path/to/folder", ws, T_z, q_z)  # to export fields
pumapy.material_properties.conductivity.export_conductivity_fields_vti(filepath, workspace, T, q)[source]

Export conductivity fields, as output by the conductivity function

Parameters
  • filepath (string) –

  • workspace (puma.Workspace or numpy.ndarray) – domain

  • T (numpy.ndarray) – temperature field

  • q (numpy.ndarray) – flux field

pumapy.material_properties.conductivity.plot_conductivity_fields(workspace, T, q, show_cbar=True, show_edges=False, xy_view=False, rm_id=None, notebook=False)[source]

Plot the workspace colored by the temperature and flux fields, as output by the conductivity function

Parameters
  • workspace (pumapy.Workspace) – domain

  • T (numpy.ndarray) – temperature field

  • q (numpy.ndarray) – flux field

  • show_cbar (bool) – show colorbar in each plot

  • show_edges (bool) – show edges in mesh

  • xy_view (bool) – show plot aligned with xy plane

  • rm_id (float or None) – remove a phase of the material from thresholded mesh

  • notebook (bool) – plotting interactively in a jupyter notebook (overwrites show_grid to False)

pumapy.material_properties.elasticity

pumapy.material_properties.elasticity.compute_elasticity(workspace, elast_map, direction, side_bc='p', tolerance=1e-05, maxiter=100000, solver_type='bicgstab', display_iter=True, method='fv', matrix_free=True)[source]

Compute the effective elasticity coefficient

Parameters
  • workspace (pumapy.Workspace) – domain

  • elast_map (pumapy.ElasticityMap) – local elasticity of the constituents

  • direction (string) – direction for solve (‘x’,’y’, ‘z’, ‘yz’, ‘xz’, ‘xy’)

  • side_bc (string) – side boundary conditions can be symmetric (‘s’) or periodic (‘p’). Only periodic available when method=’fe’

  • tolerance – tolerance for iterative solver

  • maxiter (int) – maximum Iterations for solver

  • solver_type (string) – solver type, options: ‘bicgstab’ (default), ‘minres’ (only for method=’fe’), ‘gmres’, ‘direct’

  • display_iter (bool) – display iterations and residual

  • method (string) – whether to use finite volume solver (‘fv’, i.e. mpsa) or finite element Q1-Q1 EBE solver (‘fe’). For the latter method, it is recommended to use solver_type=’minres’ as lighter and faster

  • matrix_free (bool) – if True, then use matrix-free method if possible (only available for fe solver when the solver type is not ‘direct’)

Type

tolerance: float

Returns

elasticity, displacement field, direct stresses (sigma xx, yy, zz), shear stresses (tau yz, xz, xy)

Return type

((float, float, float, float, float, float), numpy.ndarray, numpy.ndarray, numpy.ndarray)

Example

>>> import pumapy as puma
>>> ws = puma.Workspace.from_shape_value((20, 20, 20), 1)
>>> ws[int(ws.matrix.shape[0] / 2):] = 2
>>> elast_map = puma.experimental.ElasticityMap()
>>> elast_map.add_isotropic_material((1, 1), 200, 0.3)
>>> elast_map.add_isotropic_material((2, 2), 400, 0.1)
>>> C = np.zeros((6, 6))
>>> C[:, 0], u, s, t = puma.experimental.compute_elasticity(ws, elast_map, direction='x', solver_type='direct')
Approximate memory requirement for simulation: ...
>>> C[:, 1], u, s, t = puma.experimental.compute_elasticity(ws, elast_map, direction='y', solver_type='direct')
Approximate memory requirement for simulation: ...
>>> C[:, 2], u, s, t = puma.experimental.compute_elasticity(ws, elast_map, direction='z', solver_type='direct')
Approximate memory requirement for simulation: ...
>>> C[:, 3], u, s, t = puma.experimental.compute_elasticity(ws, elast_map, direction='yz', solver_type='direct')
Approximate memory requirement for simulation: ...
>>> C[:, 4], u, s, t = puma.experimental.compute_elasticity(ws, elast_map, direction='xz', solver_type='direct')
Approximate memory requirement for simulation: ...
>>> C[:, 5], u, s, t = puma.experimental.compute_elasticity(ws, elast_map, direction='xy', solver_type='direct')
Approximate memory requirement for simulation: ...
>>> coeffs = puma.experimental.get_E_nu_from_elasticity(C)
E1 ...
>>> #puma.plot_elasticity_fields(ws, u, s, t)  # to visualize fields
>>> #puma.warp_elasticity_fields(ws, u, s, t, 5)  # to visualize fields
>>> #puma.export_elasticity_fields_vti("path/to/folder", ws, u, s, t)  # to export fields
>>> C1, u, s, t = puma.experimental.compute_elasticity(ws, elast_map, direction='x', solver_type='direct', method='fe')  # finite element solver
Approximate memory requirement for simulation: ...
pumapy.material_properties.elasticity.compute_stress_analysis(workspace, elast_map, prescribed_bc, side_bc='p', tolerance=1e-05, maxiter=100000, solver_type='bicgstab', display_iter=True)[source]

Compute stress analysis based on specific user-input dirichlet boundary conditions

Parameters
  • workspace (pumapy.Workspace) – domain

  • elast_map (pumapy.ElasticityMap) – local elasticity of the constituents

  • prescribed_bc (pumapy.ElasticityBC) – object holding the elasticity dirichlet boundary conditions

  • side_bc (string) – side boundary conditions can be symmetric (‘s’) or periodic (‘p’)

  • tolerance – tolerance for iterative solver

  • maxiter (int) – maximum Iterations for solver

  • solver_type (string) – solver type, options: ‘gmres’ (default), ‘bicgstab’, ‘direct’

  • display_iter (bool) – display iterations and residual

Type

tolerance: float

Returns

elasticity, displacement field, direct stresses (sigma xx, yy, zz), shear stresses (tau yz, xz, xy)

Return type

(numpy.ndarray, numpy.ndarray, numpy.ndarray)

Example

>>> import pumapy as puma
>>> ws = puma.Workspace.from_shape_value((20, 22, 22), 1)
>>> ws[ws.matrix.shape[0]//2:] = 2
>>> ws[:, [0, -1]] = 0
>>> ws[:, :, [0, -1]] = 0
>>> elast_map = puma.experimental.ElasticityMap()
>>> elast_map.add_isotropic_material((0, 0), 1e-5, 0.3)
>>> elast_map.add_isotropic_material((1, 1), 200, 0.3)
>>> elast_map.add_isotropic_material((2, 2), 400, 0.1)
>>> bc = puma.experimental.ElasticityBC(ws)
>>> bc.xfaces[0, :, :, 0] = 0
>>> bc.xfaces[0, :, :, 1] = 0
>>> bc.xfaces[0, :, :, 2] = 0
>>> bc.xfaces[1, :, :, 0] = 0
>>> bc.xfaces[1, :, :, 1] = 1
>>> bc.xfaces[1, :, :, 2] = 0
>>> u, s, t = puma.experimental.compute_stress_analysis(ws, elast_map, bc)
Approximate memory requirement for simulation: ...
>>> # puma.warp_elasticity_fields(ws[:, 1:-1, 1:-1], u[:, 1:-1, 1:-1], s[:, 1:-1, 1:-1], t[:, 1:-1, 1:-1], 20, show_original=0., show_edges=True)  # to visualize
pumapy.material_properties.elasticity.export_elasticity_fields_vti(filepath, workspace, u, s, t)[source]

Export conductivity fields, as output by the conductivity function

Parameters
  • filepath (string) –

  • workspace (puma.Workspace or numpy.ndarray) – domain

  • u (numpy.ndarray) – displacement field

  • s (numpy.ndarray) – direct stress field

  • t (numpy.ndarray) – shear stress field

pumapy.material_properties.elasticity.get_E_nu_from_elasticity(C)[source]

Compute Young’s moduli E1, E2, E3, Shear moduli G23, G13, G12, and Poisson’s ratios nu23, nu13, nu12 for an orthotropic material from its symmetric elastic stiffness tensor

Parameters

C (np.ndarray) – 6x6 elasticity tensor

Returns

Young’s moduli E1, E2, E3, Shear moduli G23, G13, G12, and Poisson’s ratios nu23, nu13, nu12

Return type

(float, float, float, float, float, float, float, float, float)

pumapy.material_properties.elasticity.plot_elasticity_fields(workspace, u, s, t, show_cbar=True, show_edges=False, xy_view=False, rm_id=None, notebook=False)[source]

Plot the workspace according to the displacement and stress fields output by the elasticity functions

Parameters
  • workspace (pumapy.Workspace) – domain

  • u (numpy.ndarray) – displacement field

  • s (numpy.ndarray) – direct stress field

  • t (numpy.ndarray) – shear stress field

  • show_cbar (bool) – show colorbar in each plot

  • show_edges (bool) – show edges in mesh

  • xy_view (bool) – show plot aligned with xy plane

  • rm_id (float or None) – remove a phase of the material from thresholded mesh

  • notebook (bool) – plotting interactively in a jupyter notebook (overwrites show_grid to False)

pumapy.material_properties.elasticity.remove_rbms(workspace, void_id, direction)[source]

Remove Rigid Body Movements (RBMs), i.e. unconnected or “floating” voxels, in a segmented domain along a specified direction

Parameters
  • workspace (pumapy.Workspace) – domain

  • void_id (int) – specify the void ID to discard from RBMs identification

  • direction (str) – Cartesian direction that has to be connected, options: ‘x’, ‘y’, ‘z’

Returns

workspace without the possible RBMs determined by not being connected from side to side N.B. The output workspace is segmented into 0=void, 1=solid

Return type

pumapy.Workspace

Example

>>> import pumapy as puma
>>> workspace = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"))
Importing ...
>>> workspace.binarize(103)
>>> new_ws = puma.experimental.remove_rbms(workspace, void_id=0, direction='y')
>>> # puma.render_volume(workspace, (1, 1), solid_color=(255, 255, 255))  # to visualize before and after
>>> # puma.render_volume(new_ws, (1, new_ws.max()), solid_color=(255, 255, 255))
pumapy.material_properties.elasticity.warp_elasticity_fields(workspace, u, s, t, scale_factor=1, show_original=0.0, show_cbar=True, show_edges=False, xy_view=False, rm_id=None, show_axes=True, notebook=False)[source]

Warp the workspace according to the displacement field output by the elasticity functions, and colored by displacement and stress components

Parameters
  • workspace (pumapy.Workspace) – domain

  • u (numpy.ndarray) – displacement field

  • s (numpy.ndarray) – direct stress field

  • t (numpy.ndarray) – shear stress field

  • scale_factor (float) – scaling factor for warp

  • show_original (float) – opacity of the original workspace before warp

  • show_cbar (bool) – show colorbar in each plot

  • show_edges (bool) – show edges in mesh

  • xy_view (bool) – show plot aligned with xy plane

  • rm_id (float or None) – remove a phase of the material from warped mesh (only works for 2D slice)

  • show_axes (float) – show the axes and side dimensions

  • notebook (bool) – plotting interactively in a jupyter notebook (overwrites show_grid to False)

pumapy.material_properties.mean_intercept_length

pumapy.material_properties.mean_intercept_length.compute_mean_intercept_length(workspace, void_cutoff)[source]

Computation of the mean intercept length

Parameters
  • workspace (pumapy.Workspace) – domain

  • void_cutoff ((int, int)) – specify the void or gaseous phase of the domain

Returns

mean intercept length in x,y,z

Return type

(float, float, float)

Example

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing ...
>>> mil = puma.compute_mean_intercept_length(ws, (0, 89))

pumapy.material_properties.orientation

Further explained in publication: Semeraro, F., Ferguson, J.C., Panerai, F., King, R.J. and Mansour, N.N., 2020. Anisotropic analysis of fibrous and woven materials part 1: Estimation of local orientation. Computational Materials Science, 178, p.109631. (https://www.sciencedirect.com/science/article/abs/pii/S0927025620301221)

class pumapy.material_properties.orientation.OrientationST(ws, sigma, rho, cutoff, edt)[source]

Bases: object

compute()[source]
error_check()[source]
log_input()[source]
log_output()[source]
pumapy.material_properties.orientation.compute_angular_differences(matrix, orientation1, orientation2, cutoff)[source]

Compute angular difference between two orientation ndarrays

Parameters
  • matrix (np.ndarray) – domain matrix

  • orientation1 (np.ndarray) – orientation as (x, y, z, 3)

  • orientation2 (np.ndarray) – orientation as (x, y, z, 3)

  • cutoff ((int, int)) – to binarize domain

Returns

angle_errors in degrees, mean, std

Return type

(np.ndarray, float, float)

pumapy.material_properties.orientation.compute_orientation_st(ws, cutoff, sigma=0.7, rho=1.4, edt=False)[source]

Compute orientation of the material by the structure tensor algorithm

Parameters
  • ws (pumapy.Workspace) – domain

  • cutoff ((int, int)) – which grayscales to consider

  • sigma (float) – kernel size parameter for Gaussian derivatives (should be lower than rho)

  • rho (float) – kernel size parameter for Gaussian filter of derivatives of grayscales (should be higher than sigma)

  • edt (bool) – indicating if we need to apply Euclidean Distance Transform before computing ST

Returns

True if successful, False otherwise.

Return type

bool

Example

>>> import pumapy as puma
>>> import pyvista as pv
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6)  # import example file
Importing ...
>>> puma.compute_orientation_st(ws, cutoff=(90, 255), sigma=0.7, rho=1.4)  # compute orientation
First gradient computation ...
>>> # p = pv.Plotter(shape=(1, 2))  # to visualize the orientation field
>>> # p.subplot(0, 0)
>>> # p.add_text("Microstructure")
>>> # puma.render_contour(ws, (90, 255), add_to_plot=p, plot_directly=False)
>>> # p.subplot(0, 1)
>>> # p.add_text("Detected fiber orientation")
>>> # puma.render_orientation(ws, add_to_plot=p, plot_directly=False)
>>> # p.show()  # to visualize it

pumapy.material_properties.permeability

The following FE numerical method and implementation are based on the following research paper:

Lopes, P.C., Vianna, R.S., Sapucaia, V.W., Semeraro, F., Leiderman, R. and Pereira, A.M., 2023. Simulation toolkit for digital material characterization of large image-based microstructures. Computational Materials Science, 219, p.112021. (https://www.sciencedirect.com/science/article/pii/S0927025623000150)

pumapy.material_properties.permeability.compute_permeability(workspace, solid_cutoff, direction='xyz', tol=1e-08, maxiter=10000, solver_type='minres', display_iter=True, matrix_free=True, precondition=False, output_fields=True)[source]

Compute the permeability using first-order Q1-Q1 Finite Element solver and periodic BC on the sides.

Note: the iterative solvers have been observed to struggle converging for some cases. This is often connected to having the preconditioner option as True.

Parameters
  • workspace (pumapy.Workspace) – domain

  • solid_cutoff ((int, int)) – specify the solid phase

  • direction (str) – direction for solve (‘xyz’,’x’,’y’,’z’). Note that if solver_type=”direct”, then the direction is considered as “xyz” automatically because there is no need to invert the A sparse matrix multiple times

  • tol (float) – tolerance for iterative solver

  • maxiter (int) – maximum Iterations for solver

  • solver_type (string) – solver type, options: ‘minres’ (default, only works if precondition=False), ‘cg’, ‘direct’

  • display_iter (bool) – display iteration in iterative solver

  • matrix_free (bool) – solve system using matrix-free method (True, recommended) or building the sparse A matrix (False)

  • precondition (bool) – solve system with Jacobi preconditioner (True) or without (False, default because it reduces memory, but more iterations. The default minres iterative solver does not support this kind of preconditioner)

  • output_fields (bool) – export velocity and pressure fields (True, default) or not (False, lower memory)

Returns

effective permeability (3x3 matrix) and, if output_fields=True, the normalized velocity field for the corresponding direction (arranged as tuple of numpy.ndarrays, i.e. (ux, uy, uz). If output_fields=False, then (None, None, None) is output

Return type

numpy.ndarray, (numpy.ndarray, numpy.ndarray, numpy.ndarray)

Example

>>> import pumapy as puma
>>> import pyvista as pv
>>> ws = puma.generate_random_fibers_transverseisotropic(shape=(50, 50, 50), radius=2, porosity=0.7, direction='x', variation=15, length=200, allow_intersect=True, segmented=True)
 Fibers created...
>>> keff, (ux, _, _) = puma.compute_permeability(ws, (1, ws.max()), direction='x', tol=1e-7)
Approximate memory requirement for simulation: ...
>>> # p = pv.Plotter()  # to visualize it
>>> # puma.render_orientation(ux, add_to_plot=p, scale_factor=2e12, plot_directly=False)
>>> # ws.voxel_length = 1  # the voxel_length is converted to 1 for plotting the workspace together with the velocity
>>> # puma.render_volume(ws, cutoff=(1, ws.max()), add_to_plot=p, plot_directly=False, cmap='jet')
>>> # p.show()

pumapy.material_properties.radiation

class pumapy.material_properties.radiation.Radiation(workspace, void_cutoff, sources_number, particles_number, boundary_behavior, bin_density, export_plot)[source]

Bases: object

compute()[source]
error_check()[source]
generate_sources()[source]
log_input()[source]
log_output()[source]
pumapy.material_properties.radiation.compute_extinction_coefficients(ws, rays_distances, sources_number, particles_number, bin_density=10000, export_pathname=None)[source]

Compute the extinction coefficient based on the ray casting radiation simulation (this is normally a step inside the compute_radiation function)

Parameters
  • ws (pumapy.Workspace) – domain

  • rays_distances (np.ndarray) – rays distances, as output by compute_radiation function

  • sources_number (int) – number of light sources spread randomly in the void space (i.e. 0)

  • degree_accuracy (int) – angle difference between rays emitted in degrees (has to be an exact divider of 180°)

  • bin_density (int) – number of bins used to create histogram of ray distances

  • export_pathname (str) – path to save curve plot of ray distance distribution

Returns

extinction coefficient (beta), its standard deviation

Return type

(float, float)

pumapy.material_properties.radiation.compute_radiation(workspace, void_cutoff, sources_number, particles_number, boundary_behavior=1, bin_density=10000, export_pathname=None)[source]

Compute the radiative thermal conductivity through ray tracing (N.B. 0 material ID in workspace refers to gas phases unless otherwise specified)

Parameters
  • workspace (pumapy.Workspace) – domain

  • void_cutoff ((int, int)) – specify the void phase

  • sources_number (int) – number of light sources spread randomly in the void space (i.e. 0)

  • particles_number (int) – number of particles emitted at each source point

  • boundary_behavior (int) – how to treat particles exiting the domain: 0=kill, 1=periodic (default)

  • bin_density (int) – number of bins used to create histogram of ray distances

  • export_pathname (str) – path to save curve plot of ray distance distribution

Returns

extinction coefficient (beta), its standard deviation and of ray distances

Return type

(float, float, np.ndarray)

Example

>>> import pumapy as puma
>>> ws_fiberform = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 0.65e-6)
Importing ...
>>> beta, beta_std, rays_distances = puma.experimental.compute_radiation(ws_fiberform, (0, 89), 100, 500)
 Number of particles in Ray Tracing simulation...

pumapy.material_properties.surface_area

class pumapy.material_properties.surface_area.SurfaceArea(workspace, cutoff, flag_gaussian)[source]

Bases: object

compute()[source]
log_input()[source]
log_output()[source]
pumapy.material_properties.surface_area.compute_surface_area(workspace, cutoff, flag_gaussian=False)[source]

Computation of the surface area based on isosurface

Parameters
  • workspace (pumapy.Workspace) – domain

  • cutoff ((int, int)) – specify the solid phase

  • flag_gaussian (bool) – apply Gaussian filter before generating surface

Returns

area, specific_area

Return type

(float, float)

Example

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6) # import workspace
Importing ...
>>> area, specific_area = puma.compute_surface_area(ws, cutoff=(90, 255)) # computing surface area

pumapy.material_properties.tortuosity

pumapy.material_properties.tortuosity.compute_continuum_tortuosity(workspace, cutoff, direction, side_bc='p', prescribed_bc=None, tolerance=0.0001, maxiter=10000, solver_type='cg', display_iter=True, matrix_free=True)[source]

Compute the tortuosity modelling the local conductivity as isotropic

Parameters
  • workspace (pumapy.Workspace) – domain

  • cutoff ((int, int)) – cutoff to binarize domain specifying the void phase

  • direction (string) – direction for solve (‘x’,’y’, or ‘z’)

  • side_bc (string) – side boundary conditions (string) can be symmetric (‘s’), periodic (‘p’) or dirichlet (‘d’)

  • prescribed_bc (pumapy.IsotropicConductivityBC or None) – 3D array holding dirichlet BC

  • tolerance (float) – tolerance for iterative solver

  • maxiter (int) – maximum Iterations for solver

  • solver_type (string) – solver type, options: ‘cg’ (default), ‘bicgstab’, ‘direct’

  • display_iter (bool) – display iterations and residual

  • matrix_free (bool) – if True, then use matrix-free method

Returns

tortuosity, diffusivity, porosity, concentration field

Return type

((float, float, float), float, float, numpy.ndarray)

Example

>>> import pumapy as puma
>>> ws_fiberform = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing ...
>>> n_eff_x, Deff_x, poro, C_x = puma.compute_continuum_tortuosity(ws_fiberform, (0, 89), 'x', side_bc='s', tolerance=1e-4)
Approximate memory requirement for simulation...
pumapy.material_properties.tortuosity.divide_zero(x, y)[source]

pumapy.material_properties.volume_fraction

class pumapy.material_properties.volume_fraction.VolumeFraction(workspace, cutoff, display)[source]

Bases: object

compute()[source]
error_check()[source]
log_input()[source]
log_output()[source]
pumapy.material_properties.volume_fraction.compute_volume_fraction(workspace, cutoff, display=True)[source]

Compute the volume fraction

Parameters
  • workspace (pumapy.Workspace or np.ndarray) – domain

  • cutoff ((int, int)) – to binarize domain

  • display (bool) – print result

Returns

volume fraction

Return type

float

Example

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6) # import example file
Importing ...
>>> vf = puma.compute_volume_fraction(ws, cutoff=(90, 255)) # compute volume fraction
Volume Fraction for cutoff ...

pumapy.physics_models.finite_element

pumapy.physics_models.finite_element.fe_conductivity

The following FE numerical method and implementation are based on the following research paper:

Lopes, P.C., Vianna, R.S., Sapucaia, V.W., Semeraro, F., Leiderman, R. and Pereira, A.M., 2023. Simulation toolkit for digital material characterization of large image-based microstructures. Computational Materials Science, 219, p.112021. (https://www.sciencedirect.com/science/article/pii/S0927025623000150)

class pumapy.physics_models.finite_element.fe_conductivity.ConductivityFE(workspace, cond_map, direction, tolerance, maxiter, solver_type, display_iter, matrix_free)[source]

Bases: pumapy.physics_models.utils.linear_solvers.PropertySolver

assemble_Amatrix()[source]
compute()[source]
compute_effective_coefficient()[source]
compute_element_conductivity(cond, k, BC, B, ind, onlyB)[source]
compute_rhs()[source]
create_element_matrices(onlyB)[source]
create_k(ks)[source]
error_check()[source]
initialize()[source]
log_input()[source]
log_output()[source]
orient_k(ks, e)[source]

pumapy.physics_models.finite_element.fe_elasticity

The following FE numerical method and implementation are based on the following research paper:

Lopes, P.C., Vianna, R.S., Sapucaia, V.W., Semeraro, F., Leiderman, R. and Pereira, A.M., 2023. Simulation toolkit for digital material characterization of large image-based microstructures. Computational Materials Science, 219, p.112021. (https://www.sciencedirect.com/science/article/pii/S0927025623000150)

class pumapy.physics_models.finite_element.fe_elasticity.ElasticityFE(workspace, elast_map, direction, tolerance, maxiter, solver_type, display_iter, matrix_free)[source]

Bases: pumapy.physics_models.utils.linear_solvers.PropertySolver

assemble_Amatrix()[source]
compute()[source]
compute_effective_coefficient()[source]
compute_element_stiffness(C, k, BC, B, ind, onlyB)[source]
compute_rhs()[source]
create_C(cs)[source]
create_element_matrices(onlyB)[source]
error_check()[source]
initialize()[source]
log_input()[source]
log_output()[source]
orient_C(cs, e)[source]

pumapy.physics_models.finite_element.fe_permeability

The following FE numerical method and implementation are based on the following research paper:

Lopes, P.C., Vianna, R.S., Sapucaia, V.W., Semeraro, F., Leiderman, R. and Pereira, A.M., 2023. Simulation toolkit for digital material characterization of large image-based microstructures. Computational Materials Science, 219, p.112021. (https://www.sciencedirect.com/science/article/pii/S0927025623000150)

class pumapy.physics_models.finite_element.fe_permeability.Permeability(workspace, solid_cutoff, direction, tolerance, maxiter, solver_type, display_iter, matrix_free, preconditioner, output_fields)[source]

Bases: pumapy.physics_models.utils.linear_solvers.PropertySolver

assemble_Amatrix()[source]
assemble_bvector(direction)[source]
compute()[source]
compute_effective_coefficient(d)[source]
create_element_matrices()[source]
error_check()[source]
generate_mf_inds_and_preconditioner()[source]
initialize()[source]
log_input()[source]
log_output()[source]
reconstruct_velocity()[source]
solve()[source]

pumapy.physics_models.finite_volume

pumapy.physics_models.finite_volume.anisotropic_conductivity_utils

pumapy.physics_models.finite_volume.anisotropic_conductivity_utils.assign_prescribed_bc_cy(not_dir_x, not_dir_y, not_dir_z, Td, dirichlet_bc_xfaces, dirichlet_bc_yfaces, dirichlet_bc_zfaces, len_x, len_y, len_z, i_iv)
pumapy.physics_models.finite_volume.anisotropic_conductivity_utils.create_Ab_indices_cy(I_A, J_A, I_b, counter_A, counter_b, i_cv, len_x, len_y, len_z, len_xyz, side_bc)
pumapy.physics_models.finite_volume.anisotropic_conductivity_utils.create_T_ivs_cy(T, tf, i_cv, len_x, len_y, len_z, len_xyz, side_bc, t_sw, t_se, t_nw, t_ne, t_tsw, t_tse, t_tnw, t_tne)
pumapy.physics_models.finite_volume.anisotropic_conductivity_utils.index_at_p(index, size)
pumapy.physics_models.finite_volume.anisotropic_conductivity_utils.index_at_s(index, size)

pumapy.physics_models.finite_volume.anisotropic_conductivity_utils

pumapy.physics_models.finite_volume.anisotropic_conductivity_utils.assign_prescribed_bc_cy(not_dir_x, not_dir_y, not_dir_z, Td, dirichlet_bc_xfaces, dirichlet_bc_yfaces, dirichlet_bc_zfaces, len_x, len_y, len_z, i_iv)
pumapy.physics_models.finite_volume.anisotropic_conductivity_utils.create_Ab_indices_cy(I_A, J_A, I_b, counter_A, counter_b, i_cv, len_x, len_y, len_z, len_xyz, side_bc)
pumapy.physics_models.finite_volume.anisotropic_conductivity_utils.create_T_ivs_cy(T, tf, i_cv, len_x, len_y, len_z, len_xyz, side_bc, t_sw, t_se, t_nw, t_ne, t_tsw, t_tse, t_tnw, t_tne)
pumapy.physics_models.finite_volume.anisotropic_conductivity_utils.index_at_p(index, size)
pumapy.physics_models.finite_volume.anisotropic_conductivity_utils.index_at_s(index, size)

pumapy.physics_models.finite_volume.elasticity_utils

pumapy.physics_models.finite_volume.elasticity_utils.assign_prescribed_bc_cy(not_dir_x, not_dir_y, not_dir_z, Dd, dirichlet_bc_xfaces, dirichlet_bc_yfaces, dirichlet_bc_zfaces, len_x, len_y, len_z, i_iv)
pumapy.physics_models.finite_volume.elasticity_utils.create_Ab_indices_cy(I_A, J_A, I_b, counter_A, counter_b, i_cv, len_x, len_y, len_z, len_xyz, side_bc)
pumapy.physics_models.finite_volume.elasticity_utils.create_u_ivs_cy(u, uf, i_cv, len_x, len_y, len_z, len_xyz, side_bc, u_sw, u_se, u_nw, u_ne, u_tsw, u_tse, u_tnw, u_tne)
pumapy.physics_models.finite_volume.elasticity_utils.index_at_p(index, size)
pumapy.physics_models.finite_volume.elasticity_utils.index_at_p_pad(index, size)
pumapy.physics_models.finite_volume.elasticity_utils.index_at_s(index, size)
pumapy.physics_models.finite_volume.elasticity_utils.index_at_s_pad(index, size)
pumapy.physics_models.finite_volume.elasticity_utils.pad_domain_cy(ws_pad, orient_pad, need_to_orient, len_x, len_y, len_z, side_bc)

pumapy.physics_models.finite_volume.elasticity_utils

pumapy.physics_models.finite_volume.elasticity_utils.assign_prescribed_bc_cy(not_dir_x, not_dir_y, not_dir_z, Dd, dirichlet_bc_xfaces, dirichlet_bc_yfaces, dirichlet_bc_zfaces, len_x, len_y, len_z, i_iv)
pumapy.physics_models.finite_volume.elasticity_utils.create_Ab_indices_cy(I_A, J_A, I_b, counter_A, counter_b, i_cv, len_x, len_y, len_z, len_xyz, side_bc)
pumapy.physics_models.finite_volume.elasticity_utils.create_u_ivs_cy(u, uf, i_cv, len_x, len_y, len_z, len_xyz, side_bc, u_sw, u_se, u_nw, u_ne, u_tsw, u_tse, u_tnw, u_tne)
pumapy.physics_models.finite_volume.elasticity_utils.index_at_p(index, size)
pumapy.physics_models.finite_volume.elasticity_utils.index_at_p_pad(index, size)
pumapy.physics_models.finite_volume.elasticity_utils.index_at_s(index, size)
pumapy.physics_models.finite_volume.elasticity_utils.index_at_s_pad(index, size)
pumapy.physics_models.finite_volume.elasticity_utils.pad_domain_cy(ws_pad, orient_pad, need_to_orient, len_x, len_y, len_z, side_bc)

pumapy.physics_models.finite_volume.isotropic_conductivity

class pumapy.physics_models.finite_volume.isotropic_conductivity.IsotropicConductivity(workspace, cond_map, direction, side_bc, prescribed_bc, tolerance, maxiter, solver_type, display_iter, matrix_free)[source]

Bases: pumapy.physics_models.utils.linear_solvers.PropertySolver

assemble_Amatrix()[source]
assemble_bvector()[source]
compute()[source]
compute_effective_coefficient()[source]
error_check()[source]
initialize()[source]
log_input()[source]
log_output()[source]
setup_cond_matrices()[source]

pumapy.physics_models.finite_volume.isotropic_conductivity_utils

pumapy.physics_models.finite_volume.isotropic_conductivity_utils.compute_flux(T, cond, l_x, l_y, l_z)
pumapy.physics_models.finite_volume.isotropic_conductivity_utils.index_at_p(i, j, k, len_x, len_y, len_z)
pumapy.physics_models.finite_volume.isotropic_conductivity_utils.index_at_s(i, j, k, len_x, len_y, len_z)
pumapy.physics_models.finite_volume.isotropic_conductivity_utils.setup_matrices_cy(_kf, l_x, l_y, l_z, domain_bc_check, bc_check, prescribed_bc, side_bc)

pumapy.physics_models.finite_volume.isotropic_conductivity_utils

pumapy.physics_models.finite_volume.isotropic_conductivity_utils.compute_flux(T, cond, l_x, l_y, l_z)
pumapy.physics_models.finite_volume.isotropic_conductivity_utils.index_at_p(i, j, k, len_x, len_y, len_z)
pumapy.physics_models.finite_volume.isotropic_conductivity_utils.index_at_s(i, j, k, len_x, len_y, len_z)
pumapy.physics_models.finite_volume.isotropic_conductivity_utils.setup_matrices_cy(_kf, l_x, l_y, l_z, domain_bc_check, bc_check, prescribed_bc, side_bc)

pumapy.physics_models.finite_volume.mpfa_conductivity

Further explained in publication: Semeraro, F., Ferguson, J.C., Acin, M., Panerai, F. and Mansour, N.N., 2021. Anisotropic analysis of fibrous and woven materials part 2: Computation of effective conductivity. Computational Materials Science, 186, p.109956. https://www.sciencedirect.com/science/article/abs/pii/S092702562030447X

class pumapy.physics_models.finite_volume.mpfa_conductivity.AnisotropicConductivity(workspace, cond_map, direction, side_bc, dirichlet_bc, tolerance, maxiter, solver_type, display_iter)[source]

Bases: pumapy.physics_models.utils.linear_solvers.PropertySolver

assemble_matrices()[source]
compute()[source]
compute_Kmat(i, i_cv)[source]
compute_effective_coefficient()[source]
compute_fluxes()[source]
compute_transmissibility(i, i_cv_in)[source]
error_check()[source]
initialize()[source]
initialize_mpfa()[source]
log_input()[source]
log_output()[source]

pumapy.physics_models.finite_volume.mpsa_elasticity

class pumapy.physics_models.finite_volume.mpsa_elasticity.Elasticity(workspace, elast_map, direction, side_bc, tolerance, maxiter, solver_type, display_iter, dirichlet_bc)[source]

Bases: pumapy.physics_models.utils.linear_solvers.PropertySolver

assemble_matrices()[source]
compute()[source]
compute_Cmat(i, i_cv)[source]
compute_effective_coefficient()[source]
compute_stresses()[source]
compute_transmissibility(i, i_cv_in)[source]
error_check()[source]
initialize()[source]
initialize_mpsa()[source]
log_input()[source]
log_output()[source]

pumapy.physics_models.finite_volume.mpxa_matrices

matrices used in MPFA and MPSA functions

pumapy.physics_models.finite_volume.mpxa_matrices.create_d1_mpfa(k, d)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.create_d1_mpsa(c, d)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.create_d2_mpfa(k, d)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.create_d2_mpsa(c, d)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.create_mpfa_indices()[source]
pumapy.physics_models.finite_volume.mpxa_matrices.create_mpsa_indices()[source]
pumapy.physics_models.finite_volume.mpxa_matrices.div_Ed_mpfa(q_sw, q_se, q_nw, q_ne, q_tsw, q_tse, q_tnw, q_tne)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.div_Ed_mpsa(s_sw, s_se, s_nw, s_ne, s_tsw, s_tse, s_tnw, s_tne)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.div_Eu_mpfa(E_sw, E_se, E_nw, E_ne, E_tsw, E_tse, E_tnw, E_tne)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.div_Eu_mpsa(E_sw, E_se, E_nw, E_ne, E_tsw, E_tse, E_tnw, E_tne)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.fill_Ampfa(k, ndx, ndy, ndz)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.fill_Ampsa(c, ndx, ndy, ndz)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.fill_Bmpfa(k)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.fill_Bmpsa(c)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.fill_Cmpfa(k, ndx, ndy, ndz)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.fill_Cmpsa(c, ndx, ndy, ndz)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.fill_Dmpfa(k)[source]
pumapy.physics_models.finite_volume.mpxa_matrices.fill_Dmpsa(c)[source]

pumapy.physics_models.particle

pumapy.physics_models.particle.raycasting

class pumapy.physics_models.particle.raycasting.RayCasting(matrix, particles_number, source_locations, valid_phase, boundary_behavior=0)[source]

Bases: object

error_check()[source]
expand_sources()[source]
generate_spherical_walkers()[source]

pumapy.physics_models

pumapy.physics_models.utils

pumapy.physics_models.utils.boundary_conditions

class pumapy.physics_models.utils.boundary_conditions.AnisotropicConductivityBC(workspace)[source]

Bases: object

class pumapy.physics_models.utils.boundary_conditions.ElasticityBC(workspace)[source]

Bases: object

class pumapy.physics_models.utils.boundary_conditions.IsotropicConductivityBC(workspace)[source]

Bases: object

show_dirichlet()[source]

pumapy.physics_models.utils.linear_solvers

class pumapy.physics_models.utils.linear_solvers.MinResSolverDisplay[source]

Bases: object

class pumapy.physics_models.utils.linear_solvers.PropertySolver(workspace, solver_type, allowed_solvers, tolerance, maxiter, display_iter)[source]

Bases: object

solve()[source]
class pumapy.physics_models.utils.linear_solvers.SolverDisplay[source]

Bases: object

pumapy.physics_models.utils.property_maps

class pumapy.physics_models.utils.property_maps.AnisotropicConductivityMap[source]

Bases: pumapy.physics_models.utils.property_maps.MaterialPropertyMap

add_isotropic_material(cutoff, k)[source]
add_material(cutoff, kxx, kyy, kzz, kxy, kxz, kyz)[source]
add_material_to_orient(cutoff, k_axial, k_radial)[source]
add_orthotropic_material(cutoff, kxx, kyy, kzz)[source]
class pumapy.physics_models.utils.property_maps.ElasticityMap[source]

Bases: pumapy.physics_models.utils.property_maps.MaterialPropertyMap

add_isotropic_material(cutoff, E_youngmod, nu_poissrat)[source]
add_material(cutoff, C11, C12, C13, C14, C15, C16, C22, C23, C24, C25, C26, C33, C34, C35, C36, C44, C45, C46, C55, C56, C66)[source]
add_material_to_orient(cutoff, E_axial, E_radial, nu_poissrat_12, nu_poissrat_23, G12)[source]
add_orthotropic_material(cutoff, E_x, E_y, E_z, nu_yz, nu_xz, nu_xy, G_yz, G_xz, G_xy)[source]
add_transverse_isotropic_material(cutoff, E_a, E_t, nu_a, nu_t, G_a)[source]
show()[source]
class pumapy.physics_models.utils.property_maps.IsotropicConductivityMap[source]

Bases: pumapy.physics_models.utils.property_maps.MaterialPropertyMap

add_material(cutoff, conductivity)[source]
class pumapy.physics_models.utils.property_maps.MaterialPropertyMap[source]

Bases: object

error_check(cutoff, conductivity)[source]
get_material(i)[source]
get_size()[source]
show()[source]

pumapy

Copyright @ 2017, 2020, 2021 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All Rights Reserved. This software may be used, reproduced, and provided to others only as permitted under the terms of the agreement under which it was acquired from the U.S. Government. Neither title to, nor ownership of, the software is hereby transferred. This notice shall remain on all copies of the software. This file is available under the terms of the NASA Open Source Agreement (NOSA), and further subject to the additional disclaimer below: Disclaimer: THE SOFTWARE AND/OR TECHNICAL DATA ARE PROVIDED “AS IS” WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE AND/OR TECHNICAL DATA WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SOFTWARE AND/OR TECHNICAL DATA WILL BE ERROR FREE, OR ANY WARRANTY THAT TECHNICAL DATA, IF PROVIDED, WILL CONFORM TO THE SOFTWARE. IN NO EVENT SHALL THE UNITED STATES GOVERNMENT, OR ITS CONTRACTORS OR SUBCONTRACTORS, BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE AND/OR TECHNICAL DATA, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE AND/OR TECHNICAL DATA. THE UNITED STATES GOVERNMENT DISCLAIMS ALL WARRANTIES AND LIABILITIES REGARDING THIRD PARTY COMPUTER SOFTWARE, DATA, OR DOCUMENTATION, IF SAID THIRD PARTY COMPUTER SOFTWARE, DATA, OR DOCUMENTATION IS PRESENT IN THE NASA SOFTWARE AND/OR TECHNICAL DATA, AND DISTRIBUTES IT “AS IS.” RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST THE UNITED STATES GOVERNMENT AND ITS CONTRACTORS AND SUBCONTRACTORS, AND SHALL INDEMNIFY AND HOLD HARMLESS THE UNITED STATES GOVERNMENT AND ITS CONTRACTORS AND SUBCONTRACTORS FOR ANY LIABILITIES, DEMANDS, DAMAGES, EXPENSES OR LOSSES THAT MAY ARISE FROM RECIPIENT’S USE OF THE SOFTWARE AND/OR TECHNICAL DATA, INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR RESULTING FROM, THE USE THEREOF. IF RECIPIENT FURTHER RELEASES OR DISTRIBUTES THE NASA SOFTWARE AND/OR TECHNICAL DATA, RECIPIENT AGREES TO OBTAIN THIS IDENTICAL WAIVER OF CLAIMS, INDEMNIFICATION AND HOLD HARMLESS, AGREEMENT WITH ANY ENTITIES THAT ARE PROVIDED WITH THE SOFTWARE AND/OR TECHNICAL DATA.

Root directory for the pumapy package. Please refer to this publication for a detailed software architecture explanation:

@article{ferguson2021update,

title={Update 3.0 to “puma: The porous microstructure analysis software”,(pii: s2352711018300281)}, author={Ferguson, Joseph C and Semeraro, Federico and Thornton, John M and Panerai, Francesco and Borner, Arnaud and Mansour, Nagi N}, journal={SoftwareX}, volume={15}, pages={100775}, year={2021}, publisher={Elsevier}

}

pumapy.segmentation

pumapy.segmentation.ccl

Functions to relying on Connected Component Labeling (CCL)

pumapy.segmentation.ccl.fill_closed_pores(workspace, solid_cutoff, fill_value, return_pores=False)[source]

Identify the porespace and fill closed porosity

Parameters
  • workspace (pumapy.Workspace) – domain

  • solid_cutoff ((int, int)) – specify the solid range to discard from pores identification

  • fill_value (int) – value to fill closed porosity with

  • return_pores (bool) – specifies whether to return identified pores

Returns

filled workspace with IDs set as: 0 for void, 1 for solid, fill_value for added filler material. In addition, if return_pores==True, then it also returns the porespace marked as: 0 solid, 1 largest pore (likely open porosity), >1 other pores

Return type

pumapy.Workspace

Example

>>> import pumapy as puma
>>> ws = puma.generate_random_spheres((100, 100, 100), diameter=20, porosity=0.8, allow_intersect=True, segmented=False)
Approximately ... spheres to be generated...
>>> # puma.render_volume(ws[:ws.matrix.shape[0] // 2])  # to visualize workspace
>>> ws.binarize_range((1, 250))
>>> # puma.render_volume(ws[:ws.matrix.shape[0] // 2])
>>> filled_ws, pores = puma.fill_closed_pores(ws, (1, 1), fill_value=2, return_pores=True)
>>> # puma.render_volume(pores, cutoff=(0, pores.max()), cmap='jet')  # to visualize pores
pumapy.segmentation.ccl.identify_porespace(workspace, solid_cutoff, connectivity=None)[source]

Identify the porespace

Parameters
  • workspace (pumapy.Workspace) – domain

  • solid_cutoff ((int, int)) – specify the solid range to discard from pores identification

  • connectivity (int or None) – Maximum number of orthogonal hops to consider a pixel/voxel as a neighbor (None automatically gives full connectivity of input.ndim, which for 3D domain is 3, for 2D is 2)

Returns

porespace marked as: 0 solid, 1 largest pore (likely open porosity), >1 other pores

Return type

np.ndarray

Example

>>> import pumapy as puma
>>> ws = puma.generate_sphere((100, 100, 100), (50, 50, 50), 40, segmented=False)
Generated in...
>>> ws.binarize_range((1, 253))
>>> # puma.render_volume(ws[:ws.matrix.shape[0] // 2], cutoff=(0, 255))  # to visualize workspace
>>> pores = puma.identify_porespace(ws, (1, 1))
>>> # puma.render_volume(pores[:pores.shape[0] // 2], cutoff=(0, pores.max()))  # to visualize pores

pumapy.utilities

pumapy.utilities.example_files

pumapy.utilities.example_files.list_example_files()[source]

List all example files available inside the folder python/pumapy/data

Returns

List of example file names

Return type

list

pumapy.utilities.example_files.path_to_example_file(example_filename)[source]

Path to example data that is installed with pumapy (used for testing and tutorial)

Parameters

example_filename (str) – name of the example file (check python/pumapy/data for a list of example files)

Returns

path to the example file, which can be used to import it

Return type

str

Example

>>> import pumapy as puma
>>> ws_example = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif")) # import example file
Importing ...
>>> # puma.plot_slices(ws_example) # visualize example file

pumapy.utilities.generic_checks

pumapy.utilities.generic_checks.check_ws_cutoff(workspace, cutoff)[source]
pumapy.utilities.generic_checks.estimate_max_memory(material_property, workspace_shape, solver_type='iterative', need_to_orient=False, mf=True, perm_fluid_vf=1.0)[source]

Compute an estimate of the extra maximum memory required to run a specified material property on a domain

Parameters
  • material_property (string) – property to estimate, options: ‘anisotropic_conductivity’, ‘isotropic_conductivity’, ‘tortuosity’, ‘elasticity’, ‘permeability’

  • workspace_shape ((int, int, int)) – size of the domain to compute

  • solver_type (string) – type of solver, options: ‘direct’, ‘iterative’

  • need_to_orient (bool) – domain with orientation (needed for anisotropic conductivity and elasticity)

  • mf (bool) – using matrix-free construction of the system (needed for FE methods)

Returns

number of Bytes

Return type

int

pumapy.utilities.generic_checks.greater_than_exc(var, lim, var_name)[source]
pumapy.utilities.generic_checks.greater_than_inc(var, lim, var_name)[source]
pumapy.utilities.generic_checks.less_than_exc(var, lim, var_name)[source]
pumapy.utilities.generic_checks.less_than_inc(var, lim, var_name)[source]
pumapy.utilities.generic_checks.range_exc(var, var_range, var_name)[source]
pumapy.utilities.generic_checks.range_inc(var, var_range, var_name)[source]
pumapy.utilities.generic_checks.set_random_seed(seed)[source]

Set random seed for scipy and numpy to make results reproducible. NB: if you want to generate the same material twice in the same process, you need to call it twice (see example)

Parameters

seed (int) – random seed

Example

>>> import pumapy as puma
>>> puma.set_random_seed(1)
>>> ws = puma.generate_random_spheres((100, 100, 100), 20, 0.5, allow_intersect=True, segmented=False)
Approximately ... spheres to be generated...
>>> # puma.render_volume(ws)  # to visualize it
>>> puma.set_random_seed(1)  # need to call it again to get the same domain!
>>> ws = puma.generate_random_spheres((100, 100, 100), 20, 0.5, allow_intersect=True, segmented=False)
Approximately ... spheres to be generated...
>>> # puma.render_volume(ws)
pumapy.utilities.generic_checks.size_check(size)[source]

pumapy.utilities.isosurface

class pumapy.utilities.isosurface.Isosurface(workspace, cutoff, flag_closed_edges, flag_gaussian)[source]

Bases: object

apply_gaussian()[source]
buffer_matrix()[source]
compute()[source]
error_check()[source]
flip_matrix()[source]
log_input()[source]
log_output()[source]
class pumapy.utilities.isosurface.TriMesh[source]

Bases: object

copy(other)[source]
create_mesh()[source]
save(filename, binary=True)[source]
pumapy.utilities.isosurface.generate_isosurface(workspace, cutoff, flag_closed_edges=True, flag_gaussian=False)[source]

Generation of isosurface based on cutoff provided

Parameters
  • workspace (pumapy.Workspace or numpy.ndarray) – domain

  • cutoff ((int, int)) – specify cutoff to binarize material

  • flag_closed_edges (bool) – close edges of surfaces on the boundaries

  • flag_gaussian (bool) – apply Gaussian filter before generating surface

Returns

triangulated surface

Return type

TriMesh

pumapy.utilities.logger

class pumapy.utilities.logger.Colors[source]

Bases: object

BOLD = '\x1b[1m'
ENDC = '\x1b[0m'
FAIL = '\x1b[91m'
HEADER = '\x1b[95m'
OKBLUE = '\x1b[94m'
OKCYAN = '\x1b[96m'
OKGREEN = '\x1b[92m'
UNDERLINE = '\x1b[4m'
WARNING = '\x1b[93m'
class pumapy.utilities.logger.Logger[source]

Bases: object

log_bool(var_name, val)[source]
log_item(val)[source]
log_line(val)[source]
log_section(name)[source]
log_value(var_name, val)[source]
new_line()[source]
print_error()[source]
write_log()[source]
pumapy.utilities.logger.print_warning(warning_text)[source]

pumapy.utilities.timer

class pumapy.utilities.timer.Timer[source]

Bases: object

current = 0
elapsed()[source]
print_elapsed(msg='')[source]
reset()[source]
start()[source]

pumapy.utilities.workspace

class pumapy.utilities.workspace.Workspace(**kwargs)[source]

Bases: object

apply_mask(mask, apply_to_orientation=False)[source]

Apply mask of same size as the matrix by leaving the mask’s 1s unchanged and setting mask’s 0s to 0

Parameters
  • mask (np.ndarray) – array of type bool with same size as matrix

  • apply_to_orientation (bool) – specifying whether the mask is to be applied to the orientation (if present)

Returns

None

Example

>>> import pumapy as puma
>>> ws = puma.Workspace.from_shape_value_vector((10, 10, 10), 1, (0.4, 2, 5))
>>> mask = np.random.randint(255, size=(10, 10, 10)) > 100
>>> ws.apply_mask(mask, apply_to_orientation=True)
>>> # puma.render_volume(ws, style='edges')  # to visualize it
average()[source]

Return average of domain

Returns

grayscale average

Return type

float

binarize(threshold)[source]

Binarize the workspace according to threshold, inclusive for higher range set to 1, lower to 0

Parameters

threshold (int) – grayscale value dividing the domain into 0s and 1s (threshold turns into 1)

Returns

None

Example

>>> import pumapy as puma
>>> ws_fiberform = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing ...
>>> ws2 = ws_fiberform.copy()
>>> ws2.binarize(100)
>>> # puma.compare_slices(ws_fiberform, ws2)  # to visualize it
binarize_range(ones_cutoff)[source]

Binarize the workspace according to range within cutoff, inclusive for cutoff ints set to 1, rest to 0

Parameters

ones_cutoff ((int, int)) – convert a range of grayscale values specified by the cutoff into 1s, rest into 0s

Returns

None

Example

>>> import pumapy as puma
>>> ws_fiberform = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing ...
>>> ws2 = ws_fiberform.copy()
>>> ws2.binarize_range((100, 255))
>>> # puma.compare_slices(ws_fiberform, ws2)  # to visualize it
copy()[source]

Create a copy of the workspace

Returns

copy of workspace

Return type

pumapy.Workspace

create_orientation()[source]

Create orientation field of the same size as the matrix

Returns

None

Example

>>> import pumapy as puma
>>> ws = puma.Workspace.from_shape((10, 10, 10))
>>> ws.create_orientation()
classmethod from_array(nparray)[source]

Generate workspace matrix from numpy array.

Parameters

nparray (np.ndarray) – array of shape (X,Y,Z) to be assigned to the matrix variable. NB: array is turned into type uint16

Returns

new workspace

Return type

pumapy.Workspace

Example

>>> import pumapy as puma
>>> array = np.random.randint(5, size=(10, 10, 10))
>>> ws = puma.Workspace.from_array(array)
>>> # puma.render_volume(ws, style='edges')  # to visualize it
classmethod from_shape(shape, orientation=False)[source]

Generate workspace from shape, all matrix value set to zero.

Parameters
  • shape ((int, int, int)) – shape of workspace to be created

  • orientation (bool) – specify if workspace contains orientation

Returns

new workspace

Return type

pumapy.Workspace

Example

>>> import pumapy as puma
>>> ws = puma.Workspace.from_shape((10, 11, 12))
>>> # puma.render_volume(ws, style='edges')  # to visualize it
classmethod from_shape_value(shape, value, orientation=False)[source]

Generate workspace from shape, all matrix values set to the value passed.

Parameters
  • shape ((int, int, int)) – shape of workspace to be created

  • value (int) – value to be assigned to the matrix variable

  • orientation (bool) – specify if workspace contains orientation

Returns

new workspace

Return type

pumapy.Workspace

Example

>>> import pumapy as puma
>>> ws = puma.Workspace.from_shape_value((20, 31, 212), 1)
>>> # puma.render_volume(ws, style='edges')  # to visualize it
classmethod from_shape_value_vector(shape, value, vector)[source]

Generate workspace from shape, all matrix and orientation set to the values passed.

Parameters
  • shape ((int, int, int)) – shape of workspace to be created

  • value (int) – value to be assigned to the matrix variable

  • vector ((float, float, float)) – vector to be assigned to the orientation variable

Returns

new workspace with orientation

Return type

pumapy.Workspace

Example

>>> import pumapy as puma
>>> ws = puma.Workspace.from_shape_value_vector((5, 6, 2), 1, (0.4, 2, 5))
>>> # puma.render_orientation(ws)  # to visualize it
classmethod from_shape_vector(shape, vector)[source]

Generate workspace from shape, all orientation vectors set to the vector passed.

Parameters
  • shape ((int, int, int)) – shape of workspace to be created

  • vector ((float, float, float)) – vector to be assigned to the orientation variable

Returns

new workspace with orientation

Return type

pumapy.Workspace

Example

>>> import pumapy as puma
>>> ws = puma.Workspace.from_shape_vector((5, 6, 2), (0.4, 2, 5))
>>> # puma.render_orientation(ws)  # to visualize it
get_shape()[source]

Return shape of domain

Returns

shape of domain (matrix)

Return type

(int, int, int)

get_size()[source]

Return size

Returns

number of voxels

Return type

int

len_x()[source]

Return x dimension length

Returns

number of voxels in x dimension

Return type

int

len_y()[source]

Return y dimension length

Returns

number of voxels in y dimension

Return type

int

len_z()[source]

Return z dimension length

Returns

number of voxels in z dimension

Return type

int

max()[source]

Return maximum of domain

Returns

maximum

Return type

int

min()[source]

Return minimum of domain

Returns

minimum

Return type

int

orientation_magnitude()[source]

Return orientation vector’s magnitude

Returns

orientation field magnitude

Return type

np.ndarray

porosity(cutoff=(0, 0), display=False)[source]

Compute porosity of domain

Parameters
  • cutoff ((int, int)) – void cutoff

  • display (bool) – print result

Returns

volume fraction

Return type

float

Example

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6)
Importing ...
>>> ws.porosity(cutoff=(0, 89), display=True)
Volume Fraction for cutoff (0, 89): ...
rescale(scale, segmented, anti_aliasing=True, interpolation_order=1)[source]

Rescale both matrix and orientation (if present) by rescaling the content by a specified factor

Parameters
  • scale (float) – specifying the scaling factor

  • segmented (bool) – specifying whether the domain is already segmented (True) or grayscales (False)

  • anti_aliasing (bool) – if aliasing is to be prevented applying a Gaussian filter to smooth before scaling. If domain is segmented, automatically set to False in order to preserve domain

  • interpolation_order (int) – order of the interpolation spline used. For segmented, it is enforced to be 0, which is ‘nearest neighbor’ to preserve the segmentation

Returns

None

Example

>>> import pumapy as puma
>>> ws_fiberform = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing ...
>>> ws2 = ws_fiberform.copy()
>>> ws2.rescale(0.5, segmented=False)
Rescaled workspace size: (100, 100, 100)
>>> # puma.compare_slices(ws_fiberform, ws2)    # to visualize it, pay attention to the shape
resize(shape, segmented, anti_aliasing=True, interpolation_order=1)[source]

Resize both matrix and orientation (if present) by rescaling the content to specified size

Parameters
  • shape ((int, int, int)) – shape of workspace to be resized

  • segmented (bool) – specifying whether the domain is already segmented (True) or grayscales (False)

  • anti_aliasing (bool) – if aliasing is to be prevented applying a Gaussian filter to smooth before scaling. If domain is segmented, automatically set to False in order to preserve domain

  • interpolation_order (int) – order of the interpolation spline used. For segmented, it is enforced to be 0,which is ‘nearest neighbor’ to preserve the segmentation

Returns

None

Example

>>> import pumapy as puma
>>> ws_fiberform = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing ...
>>> ws2 = ws_fiberform.copy()
>>> ws2.resize((100, 200, 200), segmented=False)
>>> # puma.compare_slices(ws_fiberform, ws2)  # to visualize it
resize_new_matrix(shape, value=None)[source]

Resize matrix numpy array

Parameters
  • shape ((int, int, int)) – shape of workspace to be resized

  • value (int) – value to be assigned to the new resized matrix variable

Example

>>> import pumapy as puma
>>> ws = puma.Workspace()
>>> ws.resize_new_matrix((10, 10, 10), value=3)
>>> # puma.render_volume(ws, style='edges')  # to visualize it
resize_new_orientation(shape, orientation_value=None)[source]

Resize orientation numpy array

Parameters
  • shape ((int, int, int)) – shape of workspace to be resized

  • orientation_value ((float, float, float)) – vector to be assigned to the new resized orientation variable

Example

>>> import pumapy as puma
>>> ws = puma.Workspace()
>>> ws.resize_new_orientation((10, 10, 10), orientation_value=(1., 0., 0.))
>>> # puma.render_orientation(ws)  # to visualize it
rotate(degrees, around_axis, reshape=True, boundary_mode='reflect', apply_to_orientation=True)[source]

Rotate domain by specified degrees

Parameters
  • degrees (float) – degrees to rotate domain

  • around_axis (string) – specify around what axis to perform the rotation. It can be ‘x’, ‘y’ or ‘z’

  • reshape (bool) – specify whether to reshape the domain (and therefore contain every voxel - reshape=True) or keep its original size (reshape=False)

  • boundary_mode (string) – specifying what to do with the boundaries. Options: ‘reflect’, ‘constant’, ‘nearest’, ‘mirror’, ‘wrap’

  • apply_to_orientation (bool) – specify whether to apply rotation to the orientation, if present

Returns

None

Example

>>> import pumapy as puma
>>> ws_fiberform = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing ...
>>> ws_copy = ws_fiberform.copy()
>>> ws_copy.rotate(45, 'z', reshape=False, boundary_mode='reflect')
>>> # puma.compare_slices(ws_fiberform, ws_copy)  # to visualize it
>>> ws_copy = ws_fiberform.copy()
>>> ws_copy.rotate(45, 'z', reshape=True, boundary_mode='constant')
>>> # puma.compare_slices(ws_fiberform, ws_copy)  # to visualize it
>>> ws_copy = ws_fiberform.copy()
>>> ws_copy.rotate(45, 'z', reshape=True, boundary_mode='reflect')
>>> # puma.compare_slices(ws_fiberform, ws_copy)  # to visualize it
set(matrix_value=None, orientation_value=None)[source]

Set all elements in matrix equal to value (and orientation to vectorvalue is passed)

Parameters
  • matrix_value (int) – value to fill to the matrix variable. NB this value will be turned into np.uint16

  • orientation_value (((float, float, float))) – vector to fill to the orientation variable

Returns

None

Example

>>> import pumapy as puma
>>> ws = puma.Workspace.from_shape_value((10, 10, 10), 5)
>>> ws.set(matrix_value=4)
set_material_id(cutoff, value)[source]

Threshold the workspace according to cutoff (i.e. tuple with inclusive range to set)

Parameters
  • cutoff ((int, int)) – convert a range of grayscale values specified by the cutoff into an single ID number

  • value (int) – ID number to assign to range

Returns

None

Example

>>> import pumapy as puma
>>> ws_fiberform = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing ...
>>> ws2 = ws_fiberform.copy()
>>> ws2.set_material_id((0, 100), 0)    # NB the order of these operations is important!
>>> ws2.set_material_id((100, 255), 1)  # this is why binarize and binarize_range should be preferred
>>> # puma.compare_slices(ws_fiberform, ws2)  # to visualize it
set_matrix(nparray)[source]

Set matrix with numpy array

Parameters

nparray (np.ndarray) – array of shape (X,Y,Z) to be assigned to the matrix variable

Returns

None

Example

>>> import pumapy as puma
>>> ws = puma.Workspace()
>>> nparray = np.random.randint(5, size=(10, 10, 10))
>>> ws.set_matrix(nparray)  # equivalent to ws.matrix = nparray.copy().astype(np.uint16)
>>> # puma.render_volume(ws, style='edges')  # to visualize it
set_orientation(nparray)[source]

Set orientation with numpy array

Parameters

nparray (np.ndarray) – array of shape (X,Y,Z, 3) to be assigned to the orientation variable

Returns

None

Example

>>> import pumapy as puma
>>> ws = puma.Workspace()
>>> ws.set_orientation(np.random.rand(10, 10, 10, 3))
>>> # puma.render_orientation(ws, solid_color=None)  # to visualize it
set_voxel_length(voxel_length)[source]

Set voxel size, which by default is set to 1e-6

Parameters

voxel_length (float) – size of a voxel side

Returns

None

Example

>>> import pumapy as puma
>>> array = np.random.randint(5, size=(10, 10, 10))
>>> ws = puma.Workspace.from_array(array)
>>> ws.set_voxel_length(1)  # equivalent to ws.voxel_length = 1
>>> # puma.render_volume(ws, style='edges')  # to visualize it
show_matrix()[source]

Print content of matrix domain’s variable

show_orientation(dec=1)[source]

Print content of orientation domain’s variable

unique_values()[source]

Return unique values in domain matrix variable

Returns

unique values

Return type

np.ndarray

unique_values_counts()[source]

Return unique values and their counts in domain matrix variable

Returns

unique values and counts

Return type

(np.ndarray, int)

pumapy.visualization

pumapy.visualization.render

class pumapy.visualization.render.Renderer(existing_plot=None, filter_type=None, workspace=None, cutoff=None, solid_color=None, style=None, origin=None, window_size=None, opacity=None, background=None, show_grid=None, plot_directly=None, show_axes=None, show_outline=None, cmap=None, scale_factor=None, notebook=None, sampling=None)[source]

Bases: object

build_plotter()[source]
render()[source]
pumapy.visualization.render.render_contour(workspace, cutoff, solid_color=(255, 255, 255), style='surface', origin=(0.0, 0.0, 0.0), window_size=(1920, 1200), opacity=1.0, background=(0.3, 0.3, 0.3), show_grid=True, plot_directly=True, show_axes=True, show_outline=True, add_to_plot=None, notebook=False)[source]

Contour render using Pyvista Contour filter

Parameters
  • workspace (Workspace or np.ndarray) – domain

  • cutoff ((int, int)) – specifying the values at which the isosurface is created

  • solid_color ((int, int, int)) – a solid color to color the surface (e.g. for white (255, 255, 255))

  • style (string) – specifying the representation style (‘surface’, ‘edges’, ‘wireframe’, ‘points’)

  • origin ((float, float, float)) – origin of the data as

  • window_size ((int, int)) – with the popup window size

  • opacity (float) – opacity of contour

  • background – color of the background from (0., 0., 0.) (black) to (1., 1., 1.) (white)

  • show_grid (bool) – show the grid with the size of the sides

  • plot_directly (bool) – whether to return a Plotter object (to make further changes to it) or show the plot directly

  • show_axes (bool) – show orientation axis in the bottom left corner

  • show_outline (bool) – show the bounding box outline of the domain

  • add_to_plot (pyvista.Plotter or None) – pass an already existing plotter object to add on top of this plot

  • notebook (bool) – plotting interactively in a jupyter notebook (overwrites show_grid to False)

Type

background: (float, float, float)

Returns

None is plot_directly is True, otherwise a plotter object

Return type

pyvista.Plotter or None

Example

>>> import pumapy as puma
>>> ws_contour = puma.import_3Dtiff(puma.path_to_example_file("50_artfibers.tif"))
Importing ...
>>> # puma.render_contour(ws_contour, (128,255))  # to visualize it
pumapy.visualization.render.render_contour_multiphase(workspace, cutoffs, solid_colors=None, style='surface', origin=(0.0, 0.0, 0.0), window_size=(1920, 1200), opacity=1.0, background=(0.3, 0.3, 0.3), show_grid=True, plot_directly=True, show_axes=True, show_outline=True, add_to_plot=None, notebook=False)[source]

Contour render for multi-phase materials using Pyvista

Parameters
  • workspace (Workspace or ndarray) – domain

  • cutoffs (tuple) – n cutoffs is the number of materials. specifies the low and high cutoff ranges

  • solid_colors (tuple or None) – solid colors to color the different phases’ surface e.g. for white ((255, 255, 255), (0, 0, 0), …)

  • style (string) – specifying the representation style (‘surface’, ‘edges’, ‘wireframe’, ‘points’)

  • origin ((float, float, float)) – origin of the data as

  • window_size ((int, int)) – with the popup window size

  • opacity (float) – opacity of contour

  • background – color of the background from (0., 0., 0.) (black) to (1., 1., 1.) (white)

  • show_grid (bool) – show the grid with the size of the sides

  • plot_directly (bool) – whether to return a Plotter object (to make further changes to it) or show the plot directly

  • show_axes (bool) – show orientation axis in the bottom left corner

  • show_outline (bool) – show the bounding box outline of the domain

  • add_to_plot (pyvista.Plotter or None) – pass an already existing plotter object to add on top of this plot

  • notebook (bool) – plotting interactively in a jupyter notebook (overwrites show_grid to False)

Type

background: (float, float, float)

Returns

None is plot_directly is True, otherwise a plotter object

Return type

pyvista.Plotter or None

Example

>>> import pumapy as puma
>>> ws_multiphase = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6)
Importing ...
>>> # puma.render_contour_multiphase(ws_multiphase, ((100, 150), (150, 255)))  # to visualize it
pumapy.visualization.render.render_orientation(workspace, scale_factor=1.0, solid_color=None, style='surface', origin=(0.0, 0.0, 0.0), window_size=(1920, 1200), opacity=1.0, background=(0.3, 0.3, 0.3), show_grid=True, cmap=None, plot_directly=True, show_axes=True, show_outline=True, add_to_plot=None, notebook=False, sampling=None)[source]

Orientation render using Pyvista Glyph filter

Parameters
  • workspace (Workspace or np.ndarray) – domain

  • scale_factor (float) – scale the arrows by a factor

  • solid_color (None or (int, int, int) or str) – a solid color for the arrows. Deafult is None, which colors the vectors by their magnitude. To color white, input set solid_color=(255, 255, 255)

  • style (string) – specifying the representation style (‘surface’, ‘edges’, ‘wireframe’, ‘points’)

  • origin ((float, float, float)) – origin of the data as

  • window_size ((int, int)) – with the popup window size

  • opacity (float) – opacity of arrows

  • background – color of the background from (0., 0., 0.) (black) to (1., 1., 1.) (white)

  • show_grid (bool) – show the grid with the size of the sides

  • cmap (str or None) – matplotlib colormap to use (overwritten by solid_color if specified)

  • plot_directly (bool) – whether to return a Plotter object (to make further changes to it) or show the plot directly

  • show_axes (bool) – show orientation axis in the bottom left corner

  • show_outline (bool) – show the bounding box outline of the domain

  • add_to_plot (pyvista.Plotter or None) – pass an already existing plotter object to add on top of this plot

  • notebook (bool) – plotting interactively in a jupyter notebook (overwrites show_grid to False)

  • sampling (int or None) – number of arrows to sample (None means plot an arrow at each voxel)

Type

background: (float, float, float)

Returns

None is plot_directly is True, otherwise a plotter object

Return type

pyvista.Plotter or None

Example

>>> import pumapy as puma
>>> ws_orientation = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6)
Importing ...
>>> puma.compute_orientation_st(ws_orientation, (90, 255))
First gradient computation ...
>>> # puma.render_orientation(ws_orientation)  # to visualize it
pumapy.visualization.render.render_volume(workspace, cutoff=None, solid_color=None, style='surface', origin=(0.0, 0.0, 0.0), window_size=(1920, 1200), opacity=1.0, background=(0.3, 0.3, 0.3), show_grid=True, plot_directly=True, show_axes=True, show_outline=True, cmap='gray', add_to_plot=None, notebook=False)[source]

Volume render using Pyvista Threshold filter

Parameters
  • workspace (Workspace or np.ndarray) – domain

  • cutoff ((int, int) or (float, float) or None) – specifying the values to render

  • solid_color ((int, int, int) or None) – if set to None (default), the material is colored by the matrix’s values. Otherwise, a solid color can be specified (e.g. for white (255, 255, 255))

  • style (string) – specifying the representation style (‘surface’, ‘edges’, ‘wireframe’, ‘points’)

  • origin ((float, float, float)) – origin of the data as

  • window_size ((int, int)) – with the popup window size

  • opacity (float) – opacity of volume

  • background – color of the background from (0., 0., 0.) (black) to (1., 1., 1.) (white)

  • show_grid (bool) – show the grid with the size of the sides

  • plot_directly (bool) – whether to return a Plotter object (to make further changes to it) or show the plot directly

  • show_axes (bool) – show orientation axis in the bottom left corner

  • show_outline (bool) – show the bounding box outline of the domain

  • cmap (str) – matplotlib colormap to use (overwritten by solid_color if specified)

  • add_to_plot (pyvista.Plotter or None) – pass an already existing plotter object to add on top of this plot

  • notebook (bool) – plotting interactively in a jupyter notebook (overwrites show_grid to False)

Type

background: (float, float, float)

Returns

None is plot_directly is True, otherwise a plotter object

Return type

pyvista.Plotter or None

Example

>>> import pumapy as puma
>>> ws_volume = puma.import_3Dtiff(puma.path_to_example_file("200_fiberform.tif"), 1.3e-6)
Importing ...
>>> # puma.render_volume(ws_volume)  # to visualize it
pumapy.visualization.render.render_warp(workspace, scale_factor=1.0, color_by='magnitude', style='surface', origin=(0.0, 0.0, 0.0), window_size=(1920, 1200), opacity=1.0, background=(0.3, 0.3, 0.3), show_grid=True, cmap='jet', plot_directly=True, show_axes=True, show_outline=True, add_to_plot=None, notebook=False)[source]

Warp a domain by an orientation field

Parameters
  • workspace (Workspace) – domain with both matrix and orientation defined

  • scale_factor (float) – scale the orientation by a factor

  • color_by (str) – it can be ‘magnitude’, which colors warped domain by magnitude of vectors, or ‘x’, ‘y’ or ‘z’, which colors it by the orientation component, or ‘matrix’, which colors it by the matrix phases

  • style (string) – specifying the representation style (‘surface’, ‘edges’, ‘wireframe’, ‘points’)

  • origin ((float, float, float)) – origin of the data as

  • window_size ((int, int)) – with the popup window size

  • opacity (float) – opacity of arrows

  • background – color of the background from (0., 0., 0.) (black) to (1., 1., 1.) (white)

  • show_grid (bool) – show the grid with the size of the sides

  • cmap (str) – matplotlib colormap to use

  • plot_directly (bool) – whether to return a Plotter object (to make further changes to it) or show the plot directly

  • show_axes (bool) – show orientation axis in the bottom left corner

  • show_outline (bool) – show the bounding box outline of the domain

  • add_to_plot (pyvista.Plotter or None) – pass an already existing plotter object to add on top of this plot

  • notebook (bool) – plotting interactively in a jupyter notebook (overwrites show_grid to False)

Type

background: (float, float, float)

Returns

None is plot_directly is True, otherwise a plotter object

Return type

pyvista.Plotter or None

Example

>>> import pumapy as puma
>>> import numpy as np
>>> dim = 50
>>> ws = puma.generate_cylinder_square_array(dim, 0.44)
Generated in: ...
>>> ws.matrix = np.repeat(ws.matrix, 5, axis=2)
>>> #puma.render_volume(ws)  # to visualize it
>>> mat_elast = puma.experimental.ElasticityMap()
>>> mat_elast.add_isotropic_material((0, 0), 68.3, 0.3)
>>> mat_elast.add_isotropic_material((1, 1), 379.3, 0.1)
>>> C = np.zeros((6, 6))
>>> C[:, 0], u, s, t = puma.experimental.compute_elasticity(ws, mat_elast, direction='x', side_bc='p', solver_type="bicgstab")
Approximate memory requirement for simulation: ...
>>> #puma.experimental.warp_elasticity_fields(ws, u, s, t, scale_factor=10, xy_view=True)  # to visualize it

pumapy.visualization.slicer

class pumapy.visualization.slicer.CompareSlicer(img1, img2, slice_direction, color_range1, color_map1, color_range2, color_map2, index, axis_labels, slices1, slices2, rows1, cols1, rows2, cols2)[source]

Bases: pumapy.visualization.slicer.IndexTracker

update()[source]
class pumapy.visualization.slicer.IndexTracker(img, img2, slice_direction, index, axis_labels, slices, slices_titles)[source]

Bases: object

static error_checks(img, img2, slice_direction)[source]
static format_coord(x, y)[source]
onkey(event)[source]
onscroll(event)[source]
static rotate_domain_mpl(img, slice_direction)[source]
update()[source]
class pumapy.visualization.slicer.PlotSlicer(img, slice_direction, color_range, color_map, index, axis_labels, slices, rows, cols)[source]

Bases: pumapy.visualization.slicer.IndexTracker

update()[source]
pumapy.visualization.slicer.compare_slices(ws_nparray1, ws_nparray2, slice_direction='z', crange1=None, cmap1='gray', crange2=None, cmap2='gray', index=1)[source]

Plot slices of domain along a specified direction (z default)

Parameters
  • ws_nparray1 (Workspace or np.ndarray) – domain

  • ws_nparray2 (Workspace or np.ndarray) – domain

  • slice_direction (string) – ‘x’, ‘y’, ‘z’

  • crange1 ((int, int)) – color range for plot 1, specify min and max grayscale

  • cmap1 (string) – color map for plot 1, ‘gray’ (default), ‘jet’ or refer to matplotlib for other colormaps

  • crange2 ((int, int)) – color range for plot 2, specify min and max grayscale

  • cmap2 (string) – color map for plot 2, ‘gray’ (default), ‘jet’ or refer to matplotlib for other colormaps

  • index (int) – specifying the slice index in which the plot will be opened

Returns

slicer object

Return type

CompareSlicer

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6)
Importing ...
>>> ws2 = ws.copy()
>>> ws2.binarize_range((100, 255))
>>> #puma.compare_slices(ws, ws2)  # to visualize it
pumapy.visualization.slicer.plot_slices(ws_nparray, slice_direction='z', crange=None, cmap='gray', index=1)[source]

Plot slices of domain along a specified direction (z default)

Parameters
  • ws_nparray (Workspace or np.ndarray) – domain

  • slice_direction (string) – ‘x’, ‘y’, ‘z’

  • crange ((int, int) or None) – color range, i.e. specify min and max grayscale

  • cmap (string) – color map for the plot, ‘gray’ (default), ‘jet’ or refer to matplotlib for other colormaps

  • index – specifying the slice index in which the plot will be opened

Type

int

Returns

slicer object

Return type

PlotSlicer

>>> import pumapy as puma
>>> ws = puma.import_3Dtiff(puma.path_to_example_file("100_fiberform.tif"), 1.3e-6)
Importing ...
>>> #puma.plot_slices(ws)  # to visualize it