Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull request to merge MAGNET into dev branch #975

Open
wants to merge 141 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
141 commits
Select commit Hold shift + click to select a range
e3e5a34
Removed reduce_peaks from _snows
mkaguer Aug 2, 2022
d77cd32
Created new _magnet file including filters for magnet extraction
mkaguer Aug 2, 2022
8d5cedc
Now importing filters from _magnet
mkaguer Aug 2, 2022
b2a68a8
Added unit tests
mkaguer Aug 2, 2022
18b2e5c
Fixed two pores with same number bug
mkaguer Aug 4, 2022
dcad569
Remove properties from spheres_to_network that are nonsensical
mkaguer Aug 13, 2022
d0349fe
ensur the shape of t_conns is nt by 2
mkaguer Aug 22, 2022
6130425
remove phases from spheres_to_network
mkaguer Aug 26, 2022
a429ac9
Added if " __name__" == "__main__" simualtion
mkaguer Aug 26, 2022
7c568f2
Added parallelization to loops using dask
mkaguer Aug 26, 2022
282021a
Delete junctions with dt < 3
mkaguer Aug 30, 2022
559299a
Remove erroneous P12 definition
mkaguer Aug 30, 2022
4460691
Prevent pores from being inserted in constrictions
mkaguer Aug 30, 2022
456d447
Added simulation to end of file for testing
mkaguer Aug 30, 2022
b11626f
Deleted pores with dt < 3 along long throats
mkaguer Aug 30, 2022
15307b3
Remove print(d) line
mkaguer Aug 30, 2022
8aadd99
Merge branch 'MAGNET_Mike' into MAGNET_fix_bugs
mkaguer Aug 31, 2022
29272f9
Attempted to fix throats, almost!
mkaguer Sep 6, 2022
cdbabd1
Fixed missing throats
mkaguer Sep 7, 2022
1f6de58
Merge branch 'dev' into MAGNET_Mike
mkaguer Sep 7, 2022
15a2bef
Fixed magnet to work with 3D images
mkaguer Sep 13, 2022
c37d299
use fft to find junctions
mkaguer Sep 15, 2022
8850ba7
cleaned up find_pore_bodies and find_throat_skeleton
mkaguer Sep 19, 2022
9ad85e5
simplified spheres_to_network in order to speed up
mkaguer Sep 19, 2022
bca6f11
Updated test simulation to match changes to functions
mkaguer Sep 19, 2022
69dac56
Use Pn_l = Pn_l[0:2] for now
mkaguer Sep 20, 2022
bef86c7
Removed volume and equivalent diamter and added radius
mkaguer Sep 20, 2022
a7ed3c1
removed get_tqdm
mkaguer Sep 20, 2022
7058112
replace insert_sphere with _insert_disk_at_points
mkaguer Sep 23, 2022
bbedc63
Reshape according to number of dimensions
mkaguer Sep 23, 2022
f27a9b4
Cache _insert_disk_at_points
mkaguer Sep 25, 2022
55a8ce9
commented out reduce_peaks on maximums
mkaguer Oct 20, 2022
b7441f7
Fixed 3d structuring element used for t_conns
mkaguer Oct 20, 2022
5e008b0
fixed np.delete on throat conns so it actually deletes
mkaguer Oct 20, 2022
8044a56
Deleted junction points where dt == 0
mkaguer Oct 20, 2022
80c393d
Changed pt to pts in find_pore_bodies
mkaguer Oct 20, 2022
6e77cdf
added skeleton_parallel
mkaguer Oct 20, 2022
28634f2
Added new 3d test image
mkaguer Oct 20, 2022
caf413b
Moved check network health up
mkaguer Oct 20, 2022
aa8c377
Configured boundary pores
mkaguer Oct 20, 2022
317ac22
Moved where a and b are defined
mkaguer Oct 20, 2022
2f7e620
Commented out where throat diameter connecting boundary pores are set
mkaguer Oct 20, 2022
0557d3a
wrote magnet function that calls all subsequent functions
mkaguer Oct 21, 2022
2d9f8ee
import magnet in __init__ file
mkaguer Oct 21, 2022
a5a5ff4
Updated simulation to use new magnet function
mkaguer Oct 21, 2022
d4e663f
made l_max argument used in finding pores on long throats
mkaguer Oct 21, 2022
c0cdc60
Usinng l_max when calling magnet
mkaguer Oct 24, 2022
8ff8e0a
Importing skeleton_parallel in __init__ file
mkaguer Oct 24, 2022
918f814
Fixed overlap argument in skeleton_parallel
mkaguer Oct 24, 2022
97de169
Divs is not equal to cores
mkaguer Oct 26, 2022
fc13d9f
Added export and padding arguments to test magnet
mkaguer Nov 3, 2022
d59583f
Added padding to skeleton
mkaguer Nov 3, 2022
6569ba3
Fixed how we handle boundary pores
mkaguer Nov 3, 2022
ed0cf26
Added boundary pores as argument
mkaguer Nov 3, 2022
1a19af3
Added if export statement
mkaguer Nov 3, 2022
5468d74
Updated a comment on pressure parameter
mkaguer Nov 3, 2022
c20a2ed
Updated arguments on skeleton_parallel
mkaguer Nov 3, 2022
2800516
Removed all ps.filters in magnet
mkaguer Nov 3, 2022
7793f00
Merge branch 'dev' into MAGNET_Mike
mkaguer Nov 4, 2022
426e03b
Added throat radius
mkaguer Nov 9, 2022
ecebce1
Merge branch 'dev' into MAGNET_Mike
mkaguer Nov 16, 2022
0241c80
Added _insert_disks_at_points_m method for magnet
mkaguer Nov 24, 2022
80c59a1
Added helper functions for skeleton
mkaguer Nov 24, 2022
2f3238f
updated test simulation to match changes
mkaguer Nov 24, 2022
cf382db
removed comment about calculating dt twice in estimate overlap
mkaguer Nov 24, 2022
f72af0b
Updated spheres_to_network to include finding throat radius
mkaguer Nov 24, 2022
5bd08e8
Created magnet function for user
mkaguer Nov 24, 2022
daf2d23
Merge branch 'dev' into MAGNET_Mike
mkaguer Nov 24, 2022
25da3d3
Fixed skeleton warning message
mkaguer Nov 24, 2022
e43d670
Added import skimage as ski
mkaguer Nov 24, 2022
b8caac5
Removed all occurences of ps.
mkaguer Nov 24, 2022
5dfaa2a
Ensure im has floating solids removed
mkaguer Nov 25, 2022
cd48a35
Added fix me comment for overlapping throats
mkaguer Nov 28, 2022
9fb64ba
Fixed edge case when np.sum(mx) = 0
mkaguer Nov 28, 2022
1bf3457
Ensure im has floating solids removed
mkaguer Nov 28, 2022
b881a23
estimated overlap should be 2 times the maximum dt
mkaguer Nov 28, 2022
4b9242f
Ensure sk.dtype is the same in parallel and serial
mkaguer Nov 28, 2022
e4713a5
ensure no floating folids for 3d images only
mkaguer Dec 12, 2022
0ea4119
Remove 0.95 multiplier on lines 362 and 365
mkaguer Dec 13, 2022
c8d4d72
Fixed throat connections
mkaguer Jan 22, 2023
2f964e6
Change 3D kernel for finding throat conns
mkaguer Jan 23, 2023
92c0e33
Removed 2nd maximum filter step in insert_pore_bodies
mkaguer Jan 23, 2023
866ec10
Remove minimum size requirement
mkaguer Jan 27, 2023
d49ce31
Fixed boundary pores
mkaguer Feb 2, 2023
629f057
Trim surface solids
mkaguer Feb 2, 2023
701fddf
0.95 times the minimum radius
mkaguer Feb 2, 2023
729f0db
Fixed duplicate throats
mkaguer Feb 3, 2023
6229681
Maximum filter on distance transform
mkaguer Feb 23, 2023
8715a6d
Made new v1 file for _magnet
mkaguer May 1, 2023
11f3728
made new v2 file for magnet
mkaguer May 1, 2023
c0e0959
made new v3 file for magnet
mkaguer May 1, 2023
12ab7b5
Wrote new _magnet.py file
mkaguer May 2, 2023
e469ad7
Wrote new _magnet.py file
mkaguer Jun 16, 2023
c2b646c
Added jupyter notebook magnet example
mkaguer Jun 19, 2023
953d50b
importing func from _magnet
jgostick Sep 13, 2023
dc522fd
Merge branch 'dev' into MAGNET_Mike
jgostick Sep 13, 2023
56bd901
fixing merge, moving all magnet funcs to same file
jgostick Sep 13, 2023
c4a39f8
fixing merge, moving reduce_peaks back to filters._snow file
jgostick Sep 13, 2023
b24f7c0
fixing another merge error
jgostick Sep 13, 2023
c06fbca
moved magnet script to networks, added func to pad faces with holes
jgostick Sep 13, 2023
1faf545
adding docstrings
jgostick Sep 13, 2023
1be2a90
tightening up the merge_nearby_pores function
jgostick Sep 13, 2023
d224a97
readding -1 to dict
jgostick Sep 13, 2023
9376f48
Playing around in a standalone script
jgostick Oct 3, 2023
2000522
importing some extra stuff
jgostick Oct 3, 2023
1da9bf2
playing with no spheres
jgostick Oct 3, 2023
7bc5de0
like a charm!
jgostick Oct 4, 2023
515243f
simplifying, but no progress
jgostick Oct 4, 2023
f08e023
wip
jgostick Oct 5, 2023
06b37b9
3D working now, tighted up
jgostick Oct 8, 2023
43bb006
adding a 3D script, seems to work, not sure about K and Pc though [ci…
jgostick Oct 8, 2023
24280ca
Added magnet permeability script and berea.raw image
mkaguer Oct 12, 2023
0bcfcc1
some housekeeping
jgostick Oct 25, 2023
a1e0023
testing on blobs
jgostick Oct 28, 2023
0923740
combing through code
jgostick Nov 9, 2023
a0a6f52
Merge branch 'dev' into MAGNET_Mike
jgostick Feb 12, 2024
f27c82c
adding few changes
jgostick Feb 22, 2024
72f75e4
adding a big overall script for bentheimer
jgostick Feb 22, 2024
4c1a623
new _magnet file with changes discussed on feb 22 with Jeff
mkaguer Feb 28, 2024
62b13e8
Added get_throat_area method using random walk
mkaguer Mar 13, 2024
1939fd6
Cleaned up get_throat_area code
mkaguer Mar 19, 2024
36ab54e
Added adaptive stepping to walk by using dt
mkaguer Mar 19, 2024
9d7e724
Included throat_area calc in MAGNET wrapper
mkaguer Mar 21, 2024
803db20
Cleaned up magnet wrapper function
mkaguer Mar 23, 2024
dec1cb3
Cleaned up pore and throat properties in junctions_to_network
mkaguer Mar 23, 2024
a2d9e70
Cleaned up some remaining FIXME items in _magnet
mkaguer Mar 23, 2024
869974a
calculate inscribed throat diameter using F_approx
mkaguer Mar 25, 2024
3612bc3
Wrote walk in JIT
mkaguer Apr 4, 2024
26fce0e
Return minimum throat area with magnet extraction
mkaguer Apr 4, 2024
991b8c3
Rename clipped diameter to equivalent diameter
mkaguer Apr 4, 2024
6c243f9
Defined MAGNET arguments explicitly for easier debugging
mkaguer Apr 4, 2024
f660c99
Edited docstring on walk function
mkaguer Apr 4, 2024
f0a77c8
Measuring time it takes to calculate area and print
mkaguer Apr 4, 2024
5dcfef4
speed up dt and maximum filter by chunking
mkaguer Apr 12, 2024
1b48f80
If dt is calculated in find_throat_junctions, use parallel
mkaguer Apr 13, 2024
c5c7792
Use dt_max for finding pore diameters
mkaguer May 3, 2024
3f83286
Merge branch 'dev' into MAGNET_Mike
mkaguer Jul 10, 2024
0fd2e3e
Rmoved some scripts that were being ued to test magnet
mkaguer Jul 10, 2024
7bb2a4e
Removed a berea image
mkaguer Jul 10, 2024
a2354a9
magnet now returns a results object
mkaguer Jul 10, 2024
12580b2
Wrote a bunch of unit tests for magnet
mkaguer Jul 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 201 additions & 0 deletions examples/filters/tutorials/magnet.ipynb

Large diffs are not rendered by default.

178 changes: 178 additions & 0 deletions magnet_on_bentheimer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import pandas as pd
import porespy as ps
import openpnm as op
import numpy as np
import scipy.ndimage as spim
from edt import edt
from skimage.morphology import square, cube


# %% Set simulation parameters
np.random.seed(10)
export = False
fill_blind_pores = True
padding = None
l_max=None
bw = None
endpoints=True
name = 'Bentheimer'
res = 5.82e-6
Kx, Ky, Kz, Kavg = [], [], [], []
porosity = []

# %% Import and prepare image
f = r"C:\Users\jeff\OneDrive - University of Waterloo\Research\Elidek - Bentheimer\bentheimer_binary.npz"
imb = np.load(f)['im'][:500, :500, :500]
imb = ps.filters.fill_blind_pores(imb, conn=6, surface=True)
imb = ps.filters.trim_floating_solid(imb, conn=6, surface=True)
im = imb
porosity.append(np.sum(im)/np.product(im.shape)*100)
print(f'porosity: {np.sum(im)/np.product(im.shape)*100}')

# %% Get distance transform
dt = edt(im, parallel=8)

# %% Get Skeleton
# sk = ps.networks.skeletonize_magnet2(im)
sk, im = ps.networks.skeleton(im, padding=None, surface=True, parallel=False)
labels, N = spim.label(sk, structure=ps.tools.ps_rect(3, 3))
values, counts = np.unique(labels, return_counts=True)
if N > 1:
print(f"There are {N} separated segments in the skeleton")
print(f"Their sizes are {counts[1:]}")

# %% Find junctions and end points on skeleton
juncs, endpts = ps.networks.analyze_skeleton(sk)
pores, throats = ps.networks.partition_skeleton(sk, juncs + endpts, dt)
new_juncs, pores, new_throats =\
ps.networks.find_throat_junctions(im=im, pores=pores, throats=throats, dt=dt)
# pores, throats = ps.networks.partition_skeleton(sk, juncs + new_juncs + endpts, dt=dt)

# net = ps.networks.sk_to_network(pores, throats, dt)

# %% insert pores at junction points
pts = (pores + new_juncs) > 0
fbd = ps.networks.insert_pore_bodies(sk, dt, pts)
# convert spheres to network dictionary
net = ps.networks.spheres_to_network(
sk=sk, dt=dt, fbd=fbd, voxel_size=res, boundary_width=0)


# %% import network to openpnm
net = op.io.network_from_porespy(net)
net['pore.diameter'] = net['pore.radius']*2
net['throat.diameter'] = net['throat.radius']*2

# check network health
h = op.utils.check_network_health(net)
op.topotools.trim(net, pores=np.append(h['disconnected_pores'], h['isolated_pores']))
h = op.utils.check_network_health(net)

# add geometry models
geo = op.models.collections.geometry.cubes_and_cuboids.copy()
del geo['pore.diameter'], geo['throat.diameter']
net['pore.diameter'] = net['pore.diameter'].copy()
net['throat.diameter'] = net['throat.diameter'].copy()
net.add_model_collection(geo)
net.regenerate_models()

# add phase
phase = op.phase.Phase(network=net)
phase['pore.viscosity'] = 1e-3

# physics
phys = op.models.collections.physics.basic.copy()
phase.add_model_collection(phys)
phase.regenerate_models()

# stokes flow simulation to estimate permeability
Pin = 5e-6
Pout = 0
A = (im.shape[0]*im.shape[1]) * res**2
L = im.shape[1] * res
mu = phase['pore.viscosity'].max()

# label boundary pores
xmin = net.coords[:, 0] <= net.coords[:, 0].max()*0.02
xmax = net.coords[:, 0] >= net.coords[:, 0].max()*0.98
flow_x = op.algorithms.StokesFlow(network=net, phase=phase)
flow_x.set_value_BC(pores=xmin, values=Pin)
flow_x.set_value_BC(pores=xmax, values=Pout)
flow_x.run()

Q_x = flow_x.rate(pores=xmin, mode='group')[0]
K_x = Q_x * L * mu / (A * (Pin - Pout))/0.98e-12*1000
print(f'K_x is: {K_x:.2f} mD')

ymin = net.coords[:, 1] <= net.coords[:, 1].max()*0.02
ymax = net.coords[:, 1] >= net.coords[:, 1].max()*0.98
flow_y = op.algorithms.StokesFlow(network=net, phase=phase)
flow_y.set_value_BC(pores=ymin, values=Pin)
flow_y.set_value_BC(pores=ymax, values=Pout)
flow_y.run()

Q_y = flow_y.rate(pores=ymin, mode='group')[0]
K_y = Q_y * L * mu / (A * (Pin - Pout))/0.98e-12*1000
print(f'K_y is: {K_y:.2f} mD')

zmin = net.coords[:, 2] <= net.coords[:, 2].max()*0.02
zmax = net.coords[:, 2] >= net.coords[:, 2].max()*0.98
flow_z = op.algorithms.StokesFlow(network=net, phase=phase)
flow_z.set_value_BC(pores=zmin, values=Pin)
flow_z.set_value_BC(pores=zmax, values=Pout)
flow_z.run()

Q_z = flow_z.rate(pores=zmin, mode='group')[0]
K_z = Q_z * L * mu / (A * (Pin - Pout))/0.98e-12*1000
print(f'K_z is: {K_z:.2f} mD')

K = np.average([K_x, K_y, K_z])
print(f'K is: {K:.2f} mD')

# number of pore vs. skeleton clusters in network
from scipy.sparse import csgraph as csg
am = net.create_adjacency_matrix(fmt='coo', triu=True)
Np, cluster_num = csg.connected_components(am, directed=False)
print('Pore clusters:', Np)
# number of skeleton pieces
b = square(3) if im.ndim == 2 else cube(3)
_, Ns = spim.label(input=sk.astype('bool'), structure=b)
print('Skeleton clusters:', Ns)

print('The expected permeability is 2490 mD')

# append data
Kx.append(K_x)
Ky.append(K_y)
Kz.append(K_z)
Kavg.append(K)


# export
if export:
ps.io.to_stl(~sk, name + '-sk')
ps.io.to_stl(im, name + '-im')
net['pore.coords'] = net['pore.coords']/res
net['pore.diameter'] = net['pore.diameter']/res
net['throat.radius'] = net['throat.radius']/res
net['pore.coords'] += 10 # res
proj = net.project
op.io.project_to_xdmf(proj, filename=name + '-network')

# create and export data frame
if 0:
data = {
"Name": name,
"Resolution": res,
"boundary_width": bw,
"l_max": l_max,
"padding": str(padding),
"endpoints": endpoints,
"porosity": porosity,
"K_x": Kx,
"K_y": Ky,
"K_z": Kz,
"K": Kavg
}
df = pd.DataFrame(data=data)
df.to_csv('MAGNET Permeability.csv', index=False)
4 changes: 4 additions & 0 deletions src/porespy/filters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
filters.trim_nonpercolating_paths
filters.trim_saddle_points
filters.trim_small_clusters
filters.find_junctions
filters.find_pore_bodies
filters.find_throat_skeleton
filters.spheres_to_network

"""

Expand Down
90 changes: 45 additions & 45 deletions src/porespy/filters/_snows.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,51 +324,6 @@
return peaks


def reduce_peaks(peaks):
r"""
Any peaks that are broad or elongated are replaced with a single voxel
that is located at the center of mass of the original voxels.

Parameters
----------
peaks : ndarray
An image containing ``True`` values indicating peaks in the
distance transform

Returns
-------
image : ndarray
An array with the same number of isolated peaks as the original
image, but fewer total ``True`` voxels.

Notes
-----
The center of mass of a group of voxels is used as the new single
voxel, so if the group has an odd shape (like a horse shoe), the new
voxel may *not* lie on top of the original set.

Examples
--------
`Click here
<https://porespy.org/examples/filters/reference/reduce_peaks.html>`_
to view online example.

"""
if peaks.ndim == 2:
strel = square
else:
strel = cube
markers, N = spim.label(input=peaks, structure=strel(3))
inds = spim.measurements.center_of_mass(
input=peaks, labels=markers, index=np.arange(1, N + 1)
)
inds = np.floor(inds).astype(int)
# Centroid may not be on old pixel, so create a new peaks image
peaks_new = np.zeros_like(peaks, dtype=bool)
peaks_new[tuple(inds.T)] = True
return peaks_new


def trim_saddle_points(peaks, dt, maxiter=20):
r"""
Removes peaks that were mistakenly identified because they lied on a
Expand Down Expand Up @@ -700,7 +655,7 @@
regions = regions.map_blocks(_snow_chunked, r_max=r_max,
sigma=sigma, dtype=dt.dtype)
regions = da.overlap.trim_internal(regions, trim_depth, boundary='none')
# TODO: use dask ProgressBar once compatible w/ logging.

Check notice on line 658 in src/porespy/filters/_snows.py

View check run for this annotation

codefactor.io / CodeFactor

src/porespy/filters/_snows.py#L658

Unresolved comment '# TODO: use dask ProgressBar once compatible w/ logging.' (C100)
logger.info('Applying snow to image chunks')
regions = regions.compute(num_workers=cores)

Expand Down Expand Up @@ -809,6 +764,51 @@
return im


def reduce_peaks(peaks):
r"""
Any peaks that are broad or elongated are replaced with a single voxel
that is located at the center of mass of the original voxels.

Parameters
----------
peaks : ndarray
An image containing ``True`` values indicating peaks in the
distance transform

Returns
-------
image : ndarray
An array with the same number of isolated peaks as the original
image, but fewer total ``True`` voxels.

Notes
-----
The center of mass of a group of voxels is used as the new single
voxel, so if the group has an odd shape (like a horse shoe), the new
voxel may *not* lie on top of the original set.

Examples
--------
`Click here
<https://porespy.org/examples/filters/reference/reduce_peaks.html>`_
to view online example.

"""
if peaks.ndim == 2:
strel = square
else:
strel = cube
markers, N = spim.label(input=peaks, structure=strel(3))
inds = spim.measurements.center_of_mass(
input=peaks, labels=markers, index=np.arange(1, N + 1)
)
inds = np.floor(inds).astype(int)
# Centroid may not be on old pixel, so create a new peaks image
peaks_new = np.zeros_like(peaks, dtype=bool)
peaks_new[tuple(inds.T)] = True
return peaks_new


def _trim_internal_slice(im, chunk_shape):
r"""
Delete extra slices from image that were used to stitch two or more
Expand Down
1 change: 1 addition & 0 deletions src/porespy/networks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@
from ._getnet_orig import *
from ._getnet_para import *
from ._snow2 import *
from ._magnet import *
Loading
Loading