Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into dependabot
Browse files Browse the repository at this point in the history
  • Loading branch information
Remi-Gau committed Oct 3, 2024
2 parents 0aa61cf + b34360b commit 3ee576d
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 34 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/test-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ on:
jobs:
linter-check:
runs-on: ubuntu-latest
steps:
- name: Checkout
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Python "3.10"
uses: actions/setup-python@v4
Expand All @@ -26,8 +26,8 @@ jobs:
run: black . --diff --color
- name: ruff Check
shell: bash
run: ruff src
run: ruff check src

test-suite:
runs-on: ${{ matrix.os }}
needs: linter-check
Expand All @@ -36,7 +36,7 @@ jobs:
matrix:
os: [ubuntu-latest]
python-version: ["3.10", "3.8"]

steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -51,5 +51,5 @@ jobs:
python -m pip install .[test,optional]
- name: Run Tests
shell: bash
run: |
run: |
pytest -n auto -x
4 changes: 2 additions & 2 deletions docs/denoisers.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
LLR Denosing methods
LLR Denoising Methods
=====================

Patch-denoise implemement several local-low-rank methods, based on singular values thresholding.


Singular Value thresholding
Singular Value Thresholding
---------------------------

General Procedure
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,19 @@ omit = ["*tests*"]
precision = 2
exclude_lines = ["pragma: no cover", "raise NotImplementedError"]


# Formatting using black.
[tool.black]

#linting using ruff
[tool.ruff]
src = ["src", "tests"]
select = ["E", "F", "B", "Q", "UP", "D"]

[tool.ruff.lint]
ignore = ["B905"]
exclude = ["examples/", "tests/"]
select = ["E", "F", "B", "Q", "UP", "D"]

[tool.ruff.pydocstyle]
[tool.ruff.lint.pydocstyle]
convention="numpy"

[tool.isort]
Expand Down
3 changes: 2 additions & 1 deletion src/patch_denoise/bindings/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ def main():
]:
extra_kwargs["noise_std"] = noise_map
if noise_map is None:
raise RuntimeError("A noise map must me specified for this method.")
raise RuntimeError("A noise map must be specified for this method.")

denoised_data, patchs_weight, noise_std_map, rank_map = denoise_func(
input_data,
patch_shape=d_par.patch_shape,
Expand Down
2 changes: 1 addition & 1 deletion src/patch_denoise/bindings/modopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def __init__(
**kwargs,
)
self.op = self._op_method
self.cost = lambda *args, **kw: np.NaN
self.cost = lambda *args, **kw: np.nan
self.time_dimension = time_dimension

def _op_method(self, data, **kwargs):
Expand Down
5 changes: 4 additions & 1 deletion src/patch_denoise/bindings/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""Common utilities for bindings."""
from dataclasses import dataclass

from __future__ import annotations

import logging
from dataclasses import dataclass

import numpy as np

Expand Down
6 changes: 4 additions & 2 deletions src/patch_denoise/space_time/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""Base Structure for patch-based denoising on spatio-temporal dimension."""

import abc
from functools import partial, cached_property
import logging

import numpy as np
from tqdm.auto import tqdm

Expand Down Expand Up @@ -43,7 +44,8 @@ def __init__(

if self._ps.size != dimensions or step.size != dimensions:
raise ValueError(
"self._ps and step must have the same number of dimensions as the input self._array."
"self._ps and step must have the same number of dimensions as the "
"input self._array."
)

# Ensure patch size is not larger than self._array size along each axis
Expand Down
27 changes: 14 additions & 13 deletions src/patch_denoise/space_time/lowrank.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Low Rank methods."""
"""Low Rank methods."""

from types import MappingProxyType

import numpy as np
Expand All @@ -9,7 +10,7 @@
from .utils import (
eig_analysis,
eig_synthesis,
marshenko_pastur_median,
marchenko_pastur_median,
svd_analysis,
svd_synthesis,
)
Expand All @@ -25,7 +26,7 @@

@fill_doc
class MPPCADenoiser(BaseSpaceTimeDenoiser):
"""Denoising using the MP-PCA threshoding.
"""Denoising using Marchenko-Pastur principal components analysis thresholding.
Parameters
----------
Expand Down Expand Up @@ -127,7 +128,7 @@ class RawSVDDenoiser(BaseSpaceTimeDenoiser):
----------
$patch_config
threshold_vlue: float
treshold value for the singular values.
threshold value for the singular values.
"""

def __init__(
Expand Down Expand Up @@ -180,7 +181,7 @@ def _patch_processing(self, patch, patch_idx=None, **kwargs):

# Equation (3) in Manjon 2013

return p_new, maxidx, np.NaN
return p_new, maxidx, np.nan


@fill_doc
Expand All @@ -204,7 +205,7 @@ def denoise(
):
"""Denoise using the NORDIC method.
Along with the input data a noise stp map or value should be provided.
Along with the input data a noise std map or value should be provided.
Parameters
----------
Expand Down Expand Up @@ -291,7 +292,7 @@ class OptimalSVDDenoiser(BaseSpaceTimeDenoiser):
----------
$patch_config
loss: str
The loss determines the choise of the optimal thresholding function
The loss determines the choice of the optimal thresholding function
associated to it. The losses `"fro"`, `"nuc"` and `"op"` are supported,
for the frobenius, nuclear and operator norm, respectively.
"""
Expand Down Expand Up @@ -335,7 +336,7 @@ def denoise(
$mask_config
$noise_std
loss: str
The loss for which the optimal thresholding is perform.
The loss for which the optimal thresholding is performed.
eps_marshenko_pastur: float
The precision with which the optimal threshold is computed.
Expand All @@ -345,7 +346,7 @@ def denoise(
Notes
-----
Reimplement of the original Matlab code [#]_ in python.
Reimplementation of the original Matlab code [#]_ in python.
References
----------
Expand All @@ -356,7 +357,7 @@ def denoise(
"""
p_s, p_o = self._get_patch_param(input_data.shape)

self.input_denoising_kwargs["mp_median"] = marshenko_pastur_median(
self.input_denoising_kwargs["mp_median"] = marchenko_pastur_median(
beta=input_data.shape[-1] / np.prod(p_s),
eps=eps_marshenko_pastur,
)
Expand Down Expand Up @@ -402,7 +403,7 @@ def _patch_processing(
maxidx = 0
p_new = np.zeros_like(patch) + p_tmean

return p_new, maxidx, np.NaN
return p_new, maxidx, np.nan


def _sure_atn_cost(X, method, sing_vals, gamma, sigma=None, tau=None):
Expand Down Expand Up @@ -500,7 +501,7 @@ def sure_tau(tau, *args):

if tau0 is None:
tau0 = np.log(np.median(sing_vals))
cost_glob = np.Inf
cost_glob = np.inf
for g in gamma0:
res_opti = minimize(
lambda x: _sure_atn_cost(
Expand Down Expand Up @@ -630,4 +631,4 @@ def _patch_processing(
maxidx = 0
p_new = np.zeros_like(patch) + p_tmean

return p_new, maxidx, np.NaN
return p_new, maxidx, np.nan
24 changes: 22 additions & 2 deletions src/patch_denoise/space_time/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Utilities for space-time denoising."""

import numpy as np
from scipy.integrate import quad
from scipy.linalg import eigh, svd
Expand Down Expand Up @@ -145,7 +146,7 @@ def eig_synthesis(data_centered, eig_vec, mean, max_val):
return ((data_centered @ eig_vec) @ eig_vec.conj().T) + mean


def marshenko_pastur_median(beta, eps=1e-7):
def marchenko_pastur_median(beta, eps=1e-7):
r"""Compute the median of the Marchenko-Pastur Distribution.
Parameters
Expand Down Expand Up @@ -204,19 +205,38 @@ def mp_pdf(x):


def estimate_noise(noise_sequence, block_size=1):
"""Estimate the temporal noise standard deviation of a noise only sequence."""
"""Estimate a noise map from a noise only sequence.
The noise map is the standard deviation of the noise in each patch.
Parameters
----------
noise_sequence : np.ndarray of shape (X, Y, Z, T)
The noise-only data.
block_size : int
The size of the patch used to estimate the noise.
Returns
-------
np.ndarray of shape (X, Y, Z)
The estimated noise map.
"""
volume_shape = noise_sequence.shape[:-1]
noise_map = np.empty(volume_shape)
patch_shape = (block_size,) * len(volume_shape)
patch_overlap = (block_size - 1,) * len(volume_shape)

for patch_tl in get_patch_locs(patch_shape, patch_overlap, volume_shape):
# Get the index of voxels in the patch
patch_slice = tuple(
slice(ptl, ptl + ps) for ptl, ps in zip(patch_tl, patch_shape)
)
# Identify the voxel in the center of the patch
patch_center_img = tuple(
slice(ptl + ps // 2, ptl + ps // 2 + 1)
for ptl, ps in zip(patch_tl, patch_shape)
)
# Set the value of the voxel in the center of the patch to the SD of
# the patch
noise_map[patch_center_img] = np.std(noise_sequence[patch_slice])
return noise_map
3 changes: 2 additions & 1 deletion tests/test_bindings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Test for the binding module."""

import os

import numpy as np
import numpy.testing as npt
import pytest
Expand All @@ -16,7 +18,6 @@
except ImportError as e:
NIPYPE_AVAILABLE = False


from patch_denoise.bindings.modopt import LLRDenoiserOperator
from patch_denoise.bindings.nipype import PatchDenoise
from patch_denoise.bindings.utils import DenoiseParameters
Expand Down
4 changes: 2 additions & 2 deletions tests/test_spacetime_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
eig_analysis,
eig_synthesis,
estimate_noise,
marshenko_pastur_median,
marchenko_pastur_median,
svd_analysis,
svd_synthesis,
)
Expand Down Expand Up @@ -55,7 +55,7 @@ def f(x):
else:
return 0

integral_median = marshenko_pastur_median(beta, eps=1e-7)
integral_median = marchenko_pastur_median(beta, eps=1e-7)

vals = np.linspace(beta_m, beta_p, n_samples)
proba = np.array(list(map(f, vals)))
Expand Down

0 comments on commit 3ee576d

Please sign in to comment.