Skip to content

Commit

Permalink
Merge branch 'main' into tjlane/consistent-map-indices
Browse files Browse the repository at this point in the history
  • Loading branch information
tjlane committed Nov 3, 2024
2 parents fce43d2 + 27903be commit 498d591
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 28 deletions.
6 changes: 6 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from pathlib import Path

import numpy as np
import pytest

from meteor.testing import check_test_file_exists
Expand All @@ -25,3 +26,8 @@ def testing_mtz_file(data_dir: Path) -> Path:
path = data_dir / "scaled-test-data.mtz"
check_test_file_exists(path)
return path


@pytest.fixture(scope="session")
def np_rng() -> np.random.Generator:
return np.random.default_rng(seed=0)
24 changes: 11 additions & 13 deletions test/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
SPACE_GROUP = gemmi.find_spacegroup_by_name("P1")
CARBON1_POSITION = (5.0, 5.0, 5.0)

NP_RNG = np.random.default_rng()


@pytest.fixture
def tv_denoise_result_source_data() -> dict:
Expand All @@ -39,10 +37,10 @@ def test_map_columns() -> MapColumns:
)


def single_atom_map_coefficients(*, noise_sigma: float) -> Map:
def single_atom_map_coefficients(*, noise_sigma: float, np_rng: np.random.Generator) -> Map:
density_map = single_carbon_density(CARBON1_POSITION, SPACE_GROUP, UNIT_CELL, RESOLUTION)
density_array = np.array(density_map.grid)
grid_values = density_array + noise_sigma * NP_RNG.normal(size=density_array.shape)
grid_values = density_array + noise_sigma * np_rng.normal(size=density_array.shape)
ccp4_map = numpy_array_to_map(grid_values, spacegroup=SPACE_GROUP, cell=UNIT_CELL)

map_coefficients = Map.from_ccp4_map(ccp4_map=ccp4_map, high_resolution_limit=RESOLUTION)
Expand All @@ -60,22 +58,22 @@ def ccp4_map() -> gemmi.Ccp4Map:


@pytest.fixture
def noise_free_map() -> Map:
return single_atom_map_coefficients(noise_sigma=0.0)
def noise_free_map(np_rng: np.random.Generator) -> Map:
return single_atom_map_coefficients(noise_sigma=0.0, np_rng=np_rng)


@pytest.fixture
def noisy_map() -> Map:
return single_atom_map_coefficients(noise_sigma=0.03)
def noisy_map(np_rng: np.random.Generator) -> Map:
return single_atom_map_coefficients(noise_sigma=0.03, np_rng=np_rng)


@pytest.fixture
def very_noisy_map() -> Map:
return single_atom_map_coefficients(noise_sigma=1.0)
def very_noisy_map(np_rng: np.random.Generator) -> Map:
return single_atom_map_coefficients(noise_sigma=1.0, np_rng=np_rng)


@pytest.fixture
def random_difference_map(test_map_columns: MapColumns) -> Map:
def random_difference_map(test_map_columns: MapColumns, np_rng: np.random.Generator) -> Map:
hall = rs.utils.generate_reciprocal_asu(UNIT_CELL, SPACE_GROUP, RESOLUTION, anomalous=False)
sigma = 1.0

Expand All @@ -87,8 +85,8 @@ def random_difference_map(test_map_columns: MapColumns) -> Map:
"H": h,
"K": k,
"L": l,
test_map_columns.amplitude: sigma * NP_RNG.normal(size=number_of_reflections),
test_map_columns.phase: NP_RNG.uniform(-180, 180, size=number_of_reflections),
test_map_columns.amplitude: sigma * np_rng.normal(size=number_of_reflections),
test_map_columns.phase: np_rng.uniform(-180, 180, size=number_of_reflections),
},
spacegroup=SPACE_GROUP,
cell=UNIT_CELL,
Expand Down
12 changes: 5 additions & 7 deletions test/unit/test_iterative.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
from meteor.tv import TvDenoiseResult
from meteor.validate import negentropy

NP_RNG = np.random.default_rng()


def map_norm(map1: gemmi.Ccp4Map, map2: gemmi.Ccp4Map) -> float:
diff = np.array(map1.grid) - np.array(map2.grid)
Expand Down Expand Up @@ -46,10 +44,10 @@ def normalized_rms(x: np.ndarray, y: np.ndarray) -> float:


@pytest.mark.parametrize("scalar", [0.01, 1.0, 2.0, 100.0])
def test_projected_derivative(scalar: float) -> None:
def test_projected_derivative(scalar: float, np_rng: np.random.Generator) -> None:
n = 16
native = NP_RNG.normal(size=n) + 1j * NP_RNG.normal(size=n)
derivative = NP_RNG.normal(size=n) + 1j * NP_RNG.normal(size=n)
native = np_rng.normal(size=n) + 1j * np_rng.normal(size=n)
derivative = np_rng.normal(size=n) + 1j * np_rng.normal(size=n)
difference = derivative - native

# ensure the projection removes a scalar multiple of the native & difference
Expand All @@ -63,13 +61,13 @@ def test_projected_derivative(scalar: float) -> None:
np.testing.assert_allclose(proj_derivative, derivative)


def test_complex_derivative_from_iterative_tv() -> None:
def test_complex_derivative_from_iterative_tv(np_rng: np.random.Generator) -> None:
test_image = binary_blobs(length=64) # type: ignore[no-untyped-call]

constant_image = np.ones_like(test_image) / 2.0
constant_image_ft = np.fft.fftn(constant_image)

test_image_noisy = test_image + 0.2 * NP_RNG.normal(size=test_image.shape)
test_image_noisy = test_image + 0.2 * np_rng.normal(size=test_image.shape)
test_image_noisy_ft = np.fft.fftn(test_image_noisy)

denoised_derivative, _ = _complex_derivative_from_iterative_tv(
Expand Down
2 changes: 0 additions & 2 deletions test/unit/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
from meteor.rsmap import Map
from meteor.testing import MapColumns

NP_RNG = np.random.default_rng()


def omit_nones_in_list(input_list: list) -> list:
return [x for x in input_list if x]
Expand Down
10 changes: 4 additions & 6 deletions test/unit/test_validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,24 @@
from meteor import validate
from meteor.rsmap import Map

NP_RNG = np.random.default_rng()


def parabolic_objective(x: float) -> float:
# has a maximum of y = 0 at x = 1
return -(x**2) + 2 * x - 1


def test_negentropy_gaussian() -> None:
def test_negentropy_gaussian(np_rng: np.random.Generator) -> None:
n_samples = 10000
samples = NP_RNG.normal(size=n_samples)
samples = np_rng.normal(size=n_samples)
negentropy = validate.negentropy(samples)

# negentropy should be zero for a Gaussian sample
assert np.abs(negentropy) < 1e-2


def test_negentropy_uniform() -> None:
def test_negentropy_uniform(np_rng: np.random.Generator) -> None:
n_samples = 1000000
samples = NP_RNG.uniform(size=n_samples)
samples = np_rng.uniform(size=n_samples)
negentropy = validate.negentropy(samples)

uniform_negentropy = (1.0 / 2.0) * np.log(np.pi * np.exp(1) / 6.0)
Expand Down

0 comments on commit 498d591

Please sign in to comment.