Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f8f12b6
fix implementation mistakes
MrGranddy Jun 24, 2024
c856c31
Revert "fix implementation mistakes"
Jun 24, 2024
5d49fa9
fix implementation mistakes
MrGranddy Jun 24, 2024
df3b04c
fix edge penalty line and add test data
MrGranddy Jun 24, 2024
133c69f
update tests, add official code comparison test
MrGranddy Jun 24, 2024
d5d69f8
added conjugate gradient option for faster computation and tests
MrGranddy Jun 24, 2024
a90840c
add docs
MrGranddy Jun 24, 2024
abb2a26
add requirements, fix format
MrGranddy Jun 25, 2024
3111199
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 25, 2024
8278db3
fix capital letter variable name
MrGranddy Jun 25, 2024
bb696b4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 25, 2024
3c414f4
Update monai/data/ultrasound_confidence_map.py
MrGranddy Jun 25, 2024
2d438cf
revert commented out requirement
MrGranddy Jun 25, 2024
3ff9fe9
remove residual examination code piece
MrGranddy Jun 25, 2024
da02700
add official code link to docstring
MrGranddy Jun 25, 2024
460c5e2
add additional information to docstring
MrGranddy Jun 25, 2024
2867b96
fix cg parameter name
MrGranddy Jun 25, 2024
a2b3881
Merge branch 'dev' into dev
MrGranddy Jun 25, 2024
6b409bc
fix long lines
MrGranddy Jun 25, 2024
661a0c3
Merge branch 'dev' of github.com:MrGranddy/MONAI into dev
MrGranddy Jun 25, 2024
2a66079
Merge branch 'dev' into dev
KumoLiu Jun 26, 2024
fcaac79
Merge branch 'dev' into dev
ericspod Jun 27, 2024
d965a9f
Merge branch 'dev' into dev
KumoLiu Jun 28, 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
1 change: 1 addition & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ onnx>=1.13.0
onnxruntime; python_version <= '3.10'
zarr
huggingface_hub
pyamg>=5.0.0
2 changes: 1 addition & 1 deletion docs/source/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,6 @@ Since MONAI v0.2.0, the extras syntax such as `pip install 'monai[nibabel]'` is
```

which correspond to `nibabel`, `scikit-image`,`scipy`, `pillow`, `tensorboard`,
`gdown`, `pytorch-ignite`, `torchvision`, `itk`, `tqdm`, `lmdb`, `psutil`, `cucim`, `openslide-python`, `pandas`, `einops`, `transformers`, `mlflow`, `clearml`, `matplotlib`, `tensorboardX`, `tifffile`, `imagecodecs`, `pyyaml`, `fire`, `jsonschema`, `ninja`, `pynrrd`, `pydicom`, `h5py`, `nni`, `optuna`, `onnx`, `onnxruntime`, `zarr`, `lpips`, `nvidia-ml-py`, and `huggingface_hub` respectively.
`gdown`, `pytorch-ignite`, `torchvision`, `itk`, `tqdm`, `lmdb`, `psutil`, `cucim`, `openslide-python`, `pandas`, `einops`, `transformers`, `mlflow`, `clearml`, `matplotlib`, `tensorboardX`, `tifffile`, `imagecodecs`, `pyyaml`, `fire`, `jsonschema`, `ninja`, `pynrrd`, `pydicom`, `h5py`, `nni`, `optuna`, `onnx`, `onnxruntime`, `zarr`, `lpips`, `nvidia-ml-py`, `huggingface_hub` and `pyamg` respectively.

- `pip install 'monai[all]'` installs all the optional dependencies.
45 changes: 38 additions & 7 deletions monai/data/ultrasound_confidence_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
cv2, _ = optional_import("cv2")
csc_matrix, _ = optional_import("scipy.sparse", "1.7.1", min_version, "csc_matrix")
spsolve, _ = optional_import("scipy.sparse.linalg", "1.7.1", min_version, "spsolve")
cg, _ = optional_import("scipy.sparse.linalg", "1.7.1", min_version, "cg")
hilbert, _ = optional_import("scipy.signal", "1.7.1", min_version, "hilbert")
ruge_stuben_solver, _ = optional_import("pyamg", "5.0.0", min_version, "ruge_stuben_solver")


class UltrasoundConfidenceMap:
Expand All @@ -30,22 +32,43 @@ class UltrasoundConfidenceMap:
It generates a confidence map by setting source and sink points in the image and computing the probability
for random walks to reach the source for each pixel.

The official code is available at:
https://campar.in.tum.de/Main/AthanasiosKaramalisCode

Args:
alpha (float, optional): Alpha parameter. Defaults to 2.0.
beta (float, optional): Beta parameter. Defaults to 90.0.
gamma (float, optional): Gamma parameter. Defaults to 0.05.
mode (str, optional): 'RF' or 'B' mode data. Defaults to 'B'.
sink_mode (str, optional): Sink mode. Defaults to 'all'. If 'mask' is selected, a mask must be when calling
the transform. Can be 'all', 'mid', 'min', or 'mask'.
use_cg (bool, optional): Use Conjugate Gradient method for solving the linear system. Defaults to False.
cg_tol (float, optional): Tolerance for the Conjugate Gradient method. Defaults to 1e-6.
Will be used only if `use_cg` is True.
cg_maxiter (int, optional): Maximum number of iterations for the Conjugate Gradient method. Defaults to 200.
Will be used only if `use_cg` is True.
"""

def __init__(self, alpha: float = 2.0, beta: float = 90.0, gamma: float = 0.05, mode="B", sink_mode="all"):
def __init__(
self,
alpha: float = 2.0,
beta: float = 90.0,
gamma: float = 0.05,
mode="B",
sink_mode="all",
use_cg=False,
cg_tol=1e-6,
cg_maxiter=200,
):
# The hyperparameters for confidence map estimation
self.alpha = alpha
self.beta = beta
self.gamma = gamma
self.mode = mode
self.sink_mode = sink_mode
self.use_cg = use_cg
self.cg_tol = cg_tol
self.cg_maxiter = cg_maxiter

# The precision to use for all computations
self.eps = np.finfo("float64").eps
Expand Down Expand Up @@ -228,17 +251,18 @@ def confidence_laplacian(self, padded_index: NDArray, padded_image: NDArray, bet
s = self.normalize(s)

# Horizontal penalty
s[:vertical_end] += gamma
# s[vertical_end:diagonal_end] += gamma * np.sqrt(2) # --> In the paper it is sqrt(2)
# since the diagonal edges are longer yet does not exist in the original code
s[vertical_end:] += gamma
# Here there is a difference between the official MATLAB code and the paper
# on the edge penalty. We directly implement what the official code does.

# Normalize differences
s = self.normalize(s)

# Gaussian weighting function
s = -(
(np.exp(-beta * s, dtype="float64")) + 1.0e-6
) # --> This epsilon changes results drastically default: 1.e-6
(np.exp(-beta * s, dtype="float64")) + 1e-5
) # --> This epsilon changes results drastically default: 10e-6
# Please notice that it is not 1e-6, it is 10e-6 which is actually different.

# Create Laplacian, diagonal missing
lap = csc_matrix((s, (i, j)))
Expand All @@ -256,7 +280,14 @@ def confidence_laplacian(self, padded_index: NDArray, padded_image: NDArray, bet
return lap

def _solve_linear_system(self, lap, rhs):
x = spsolve(lap, rhs)

if self.use_cg:
lap_sparse = lap.tocsr()
ml = ruge_stuben_solver(lap_sparse, coarse_solver="pinv")
m = ml.aspreconditioner(cycle="V")
x, _ = cg(lap, rhs, tol=self.cg_tol, maxiter=self.cg_maxiter, M=m)
else:
x = spsolve(lap, rhs)

return x

Expand Down
27 changes: 25 additions & 2 deletions monai/transforms/intensity/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -2789,21 +2789,42 @@ class UltrasoundConfidenceMapTransform(Transform):
It generates a confidence map by setting source and sink points in the image and computing the probability
for random walks to reach the source for each pixel.

The official code is available at:
https://campar.in.tum.de/Main/AthanasiosKaramalisCode

Args:
alpha (float, optional): Alpha parameter. Defaults to 2.0.
beta (float, optional): Beta parameter. Defaults to 90.0.
gamma (float, optional): Gamma parameter. Defaults to 0.05.
mode (str, optional): 'RF' or 'B' mode data. Defaults to 'B'.
sink_mode (str, optional): Sink mode. Defaults to 'all'. If 'mask' is selected, a mask must be when
calling the transform. Can be one of 'all', 'mid', 'min', 'mask'.
use_cg (bool, optional): Use Conjugate Gradient method for solving the linear system. Defaults to False.
cg_tol (float, optional): Tolerance for the Conjugate Gradient method. Defaults to 1e-6.
Will be used only if `use_cg` is True.
cg_maxiter (int, optional): Maximum number of iterations for the Conjugate Gradient method. Defaults to 200.
Will be used only if `use_cg` is True.
"""

def __init__(self, alpha: float = 2.0, beta: float = 90.0, gamma: float = 0.05, mode="B", sink_mode="all") -> None:
def __init__(
self,
alpha: float = 2.0,
beta: float = 90.0,
gamma: float = 0.05,
mode="B",
sink_mode="all",
use_cg=False,
cg_tol: float = 1.0e-6,
cg_maxiter: int = 200,
):
self.alpha = alpha
self.beta = beta
self.gamma = gamma
self.mode = mode
self.sink_mode = sink_mode
self.use_cg = use_cg
self.cg_tol = cg_tol
self.cg_maxiter = cg_maxiter

if self.mode not in ["B", "RF"]:
raise ValueError(f"Unknown mode: {self.mode}. Supported modes are 'B' and 'RF'.")
Expand All @@ -2813,7 +2834,9 @@ def __init__(self, alpha: float = 2.0, beta: float = 90.0, gamma: float = 0.05,
f"Unknown sink mode: {self.sink_mode}. Supported modes are 'all', 'mid', 'min' and 'mask'."
)

self._compute_conf_map = UltrasoundConfidenceMap(self.alpha, self.beta, self.gamma, self.mode, self.sink_mode)
self._compute_conf_map = UltrasoundConfidenceMap(
self.alpha, self.beta, self.gamma, self.mode, self.sink_mode, self.use_cg, self.cg_tol, self.cg_maxiter
)

def __call__(self, img: NdarrayOrTensor, mask: NdarrayOrTensor | None = None) -> NdarrayOrTensor:
"""Compute confidence map from an ultrasound image.
Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ zarr
lpips==0.1.4
nvidia-ml-py
huggingface_hub
pyamg>=5.0.0
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ all =
lpips==0.1.4
nvidia-ml-py
huggingface_hub
pyamg>=5.0.0
nibabel =
nibabel
ninja =
Expand Down Expand Up @@ -162,6 +163,8 @@ pynvml =
# MetricsReloaded @ git+https://github.com/Project-MONAI/MetricsReloaded@monai-support#egg=MetricsReloaded
huggingface_hub =
huggingface_hub
pyamg =
pyamg>=5.0.0

[flake8]
select = B,C,E,F,N,P,T4,W,B9
Expand Down
Loading