Skip to content

Commit

Permalink
MAINT: Convert print to logging, and add more structure to homogeneou…
Browse files Browse the repository at this point in the history
…s vs heteroegneous analysis.
  • Loading branch information
jwboth committed Nov 22, 2024
1 parent 0fa1b08 commit eb3f2a8
Showing 1 changed file with 53 additions and 6 deletions.
59 changes: 53 additions & 6 deletions src/darsia/restoration/averaging.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
"""Module with tools for volume averaging."""

from typing import Union, overload
import logging
from typing import Optional, Union, overload

import numpy as np
import scipy.ndimage

import darsia

logger = logging.getLogger(__name__)


class REV:
"""Class defining an representative elementary volume."""
Expand All @@ -32,28 +35,35 @@ def __init__(self, size: Union[float, tuple[float]], img: darsia.Image) -> None:

class VolumeAveraging:

def __init__(self, rev: REV, mask: darsia.Image) -> None:
def __init__(
self, rev: REV, mask: darsia.Image, labels: Optional[darsia.Image] = None
) -> None:
"""Constructor.
Args:
rev (REV): representative elementary volume
mask (Image): mask
labels (Image): labels; activating heterogeneous analysis, if not None
"""
self.rev_size = rev.size
"""Size of the REV."""
self.mask = mask
"""Mask."""
self.mean_pore_volume = scipy.ndimage.uniform_filter(
self.mask.astype(float).img, size=self.rev_size
self.labels = labels
"""Labels."""
self.mean_pore_volume = self._heterogeneous_uniform_filter(
self.mask.astype(float).img
)
"""Mean pore volume."""
tol = 1e-12
self.zero_indices = np.where(self.mean_pore_volume < tol)
"""Zero indices in the mean pore volume."""

# User output
print(f"Number of zero indices: {len(self.zero_indices[0])}")
logger.info(
f"Number of zero indices in pore volume identification: {len(self.zero_indices[0])}"
)

@overload # type: ignore [override]
def __call__(self, img: np.ndarray) -> np.ndarray: ...
Expand Down Expand Up @@ -83,19 +93,56 @@ def __call__(
def _average_array(self, arr: np.ndarray) -> np.ndarray:
"""Application of volume averaging to numpy array.
Apply averaging to each channel of a 3D array.
Args:
arr (np.ndarray): array
Returns:
np.ndarray: volume averaged array
"""
if arr.ndim == 2:
return self._average_array_single(arr)
elif arr.ndim == 3:
return np.stack(
[self._average_array_single(arr[..., i]) for i in range(arr.shape[-1])],
axis=-1,
)
else:
raise ValueError("Only 2D and 3D arrays are supported.")

def _average_array_single(self, arr: np.ndarray) -> np.ndarray:
"""Application of volume averaging to two-dimensional numpy array.
Args:
arr (np.ndarray): two-dimensional array
Returns:
np.ndarray: two-dimensional volume averaged array
"""
masked_data = np.multiply(arr, self.mask.img)
mean_masked_data = scipy.ndimage.uniform_filter(masked_data, size=self.rev_size)
mean_masked_data = self._heterogeneous_uniform_filter(masked_data)
result = np.divide(mean_masked_data, self.mean_pore_volume)
result[self.zero_indices] = 0
return result

def _heterogeneous_uniform_filter(self, data: np.ndarray) -> np.ndarray:
"""Application of a uniform filter to heterogeneous data.
Args:
data (np.ndarray): data
Returns:
np.ndarray: filtered data
"""
if self.labels is None:
return scipy.ndimage.uniform_filter(data, size=self.rev_size)
else:
raise NotImplementedError("Heterogeneous analysis is not yet implemented.")


def volume_average(img: darsia.Image, mask: darsia.Image, size: float) -> darsia.Image:
"""Fast-access function for volume averaging.
Expand Down

0 comments on commit eb3f2a8

Please sign in to comment.