Skip to content

Pore Size

The pore size distribution answers: what fraction of the pore volume sits in pores of radius \(r\)? PoreStore defines the size of a pore at each point by its local thickness, the radius of the largest sphere that fits in the pore space and covers that point, and reports the volume-weighted distribution of that radius.

  • Measures the local thickness of every pore voxel
  • Method sphere insertion on the distance transform, with PoreSpy
  • Reports the volume-weighted distribution of pore radius, its median \(r_{50}\), and the local-thickness map
  • How to run it Pore Size in the User guide

Definition

Let \(\Omega_p\) be the pore space. The local thickness at a pore point \(\mathbf{x}\) is1

\[ \ell(\mathbf{x}) = \max\bigl\{\, r \;:\; \mathbf{x} \in B(\mathbf{y}, r) \subseteq \Omega_p \,\bigr\}, \]

the radius of the largest ball \(B(\mathbf{y}, r)\) that lies entirely in the pore space and contains \(\mathbf{x}\). A point in the middle of a big pore and a point in its corner both get the big pore's radius. That's what makes this a pore size rather than a distance to the wall, which the radial density distribution measures instead.

A 120³ synthetic sample, porosity 0.55, run through PoreStore's own analysis code. Top, from left: the middle slice, its distance to the nearest solid and its local thickness. Below: the distribution with its complementary cumulative. Hover over any panel to read its values.

How it's computed

  1. Distance transform. For every pore voxel, the Euclidean distance \(d(\mathbf{x})\) to the nearest solid voxel. The image edges aren't treated as solid, so a pore cut by the edge is measured only to the solid inside the image.
  2. Candidate radii. \(n_s\) integer radii (Radius steps), evenly spaced from 1 to \(\lfloor\max d\rfloor\) and de-duplicated.
  3. Sphere insertion, largest first. For each radius \(r\), a sphere of radius \(r\) is drawn around every voxel with \(d \ge r\), since only there does a sphere of radius \(r\) fit. Every voxel the spheres cover, and not already labelled, gets \(\ell = r\). This is PoreSpy's brute-force local thickness, without smoothing.2
  4. Histogram. Bins are centred on whole radii, with edges halfway between: one bin per voxel of radius, edges at \(0.5, 1.5, \dots, r_\text{max} + 0.5\) voxels, over every pore voxel. If that would take more than 200 bins, every bin widens to the smallest odd number of voxels that keeps the count at most 200: a largest radius of 1000 voxels gives 200 bins 5 voxels wide. An odd width keeps every centre on a whole radius. The radial density distribution uses the same bins, so the two distributions line up on any image.
\[ f(r_i) = \frac{n_i}{N_p\, \Delta r},\qquad s_i = \frac{n_i}{N_p},\qquad F(r_i) = \sum_{j \ge i} s_j , \]

where \(n_i\) is the number of pore voxels with \(\ell\) in bin \(i\), \(N_p\) is the number of pore voxels, and \(\Delta r\) is the bin width: 1 voxel unless the image needs wider bins. \(f\) is the volume-weighted density of pore radius, \(s_i\) the fraction of pore volume in bin \(i\), and \(F\) the fraction with radius at least \(r_i\), which falls from 1 to 0 as a porosimetry curve does. The median pore radius \(r_{50}\) is where \(F\) crosses 0.5.

What Radius steps does

Radius steps \(n_s\) sets how many radii are tried, not the number of bins, which PoreStore chooses as above. If \(n_s\) is at least the largest radius in the image, every integer radius is tried. If it's smaller, some radii are skipped, their voxels fall to the next smaller radius tried, and the skipped bins read zero. The default of 25 covers every radius in images whose largest pore is up to 25 voxels in radius.

Accuracy and resolution

Radii are whole voxels, so the distribution can't resolve sizes finer than one voxel. Pores under about 2 voxels in radius are poorly resolved: their spheres are a handful of voxels and their shape is mostly staircase. The local-thickness map is stored in voxels whatever the image's voxel size, and 0 in solid.

Reading the result

  • Volume-weighted. One large pore can outweigh many small ones. That's the right weighting for "where is the pore volume?", not for "how many pores are there?". For counts, use the pore sizes from network extraction.
  • Not an intrusion curve. Local thickness ignores connectivity: a big pore behind a narrow throat still counts at its full size. Mercury porosimetry applies the throat restriction, and the gap between the two curves says how much large pore volume hides behind small throats.3
  • Not distance to the wall. Every point of a pore gets the pore's size, even a point beside the wall. For distance to the nearest solid, see radial density.

References


  1. T. Hildebrand, P. Rüegsegger, "A new method for the model-independent assessment of thickness in three-dimensional images," Journal of Microscopy 185 (1997) 67–75. doi:10.1046/j.1365-2818.1997.1340694.x ↩

  2. J. T. Gostick et al., "PoreSpy: A Python toolkit for quantitative analysis of porous media images," Journal of Open Source Software 4 (2019) 1296. doi:10.21105/joss.01296 ↩

  3. B. Münch, L. Holzer, "Contradicting geometrical concepts in pore size analysis attained with electron microscopy and mercury intrusion," Journal of the American Ceramic Society 91 (2008) 4059–4067. doi:10.1111/j.1551-2916.2008.02736.x ↩