From e33fd6d8dbd44cde69ba4c197cf4edfa711904e8 Mon Sep 17 00:00:00 2001 From: Michael Sullivan <30868085+MikeSullivan7@users.noreply.github.com> Date: Tue, 16 Jun 2026 10:25:51 +0100 Subject: [PATCH 1/3] exclude pytest==9.1.0 in pyproject.toml (#210) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ab6724ae..a2c37797 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ Repository = "https://github.com/RascalSoftware/python-RAT" [project.optional-dependencies] dev = [ - "pytest>=7.4.0", + "pytest>=7.4.0,!=9.1.0", "pytest-cov>=4.1.0", "ruff>=0.4.10" ] From c230b9a8d74d6b4e98a1ddf2a090d08e45990329 Mon Sep 17 00:00:00 2001 From: Michael Sullivan <30868085+MikeSullivan7@users.noreply.github.com> Date: Tue, 16 Jun 2026 11:31:06 +0100 Subject: [PATCH 2/3] Add a python equivalent to MATLABs smoothdata and use in Bayes plots (#208) * Add a python equivalent to MATLABs smoothdata and use in Bayes plots * suggested changes to moving_average * unit test test_moving_average * ruff fix * use ValueError if moving_average window size is out of bounds --- ratapi/utils/plotting.py | 43 +++++++++++++++++++++++------ tests/test_plotting.py | 58 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 8 deletions(-) diff --git a/ratapi/utils/plotting.py b/ratapi/utils/plotting.py index 6f9debb7..509c7a4f 100644 --- a/ratapi/utils/plotting.py +++ b/ratapi/utils/plotting.py @@ -763,7 +763,7 @@ def plot_one_hist( results: ratapi.outputs.BayesResults, param: int | str, smooth: bool = True, - sigma: float | None = None, + window_size: int = 8, estimated_density: Literal["normal", "lognor", "kernel", None] = None, axes: Axes | None = None, block: bool = False, @@ -783,9 +783,9 @@ def plot_one_hist( smooth : bool, default True Whether to apply Gaussian smoothing to the histogram. Defaults to True. - sigma: float or None, default None - If given, is used as the sigma-parameter for the Gaussian smoothing. - If None, the default (1/3rd of parameter chain standard deviation) is used. + window_size : int, default 8 + The width of the smoothing window centered around the element being averaged. + The window moves down the length of the data, computing an average over the elements within each window. estimated_density : 'normal', 'lognor', 'kernel' or None, default None If None (default), ignore. Else, add an estimated density of the given form on top of the histogram by the following estimations: @@ -826,9 +826,7 @@ def plot_one_hist( sd_y = np.std(parameter_chain) if smooth: - if sigma is None: - sigma = sd_y / 2 - counts = gaussian_filter1d(counts, sigma) + counts = moving_average(counts, window_size=window_size) axes.hist( bins[:-1], bins, @@ -1134,7 +1132,6 @@ def validate_dens_type(dens_type: str | None, param: str): results, i, smooth=smooth, - sigma=sigma, estimated_density=estimated_density.get(i), axes=ax, **hist_settings, @@ -1233,3 +1230,33 @@ def plot_bayes(project: ratapi.Project, results: ratapi.outputs.BayesResults): plot_corner(results) else: raise ValueError("Bayes plots are only available for the results of Bayesian analysis (NS or DREAM)") + + +def moving_average(data: np.ndarray, window_size: int = 8) -> list[float]: + """Calculate the moving average of an array with a given window size. + + This is a python equivalent to MATLABs smoothdata(A, 'movmean') + + Parameters + ---------- + data : np.ndarray + The input array to smooth + window_size : int + The window slides down the length of the vector, + computing an average over the elements within each window. + + """ + if not 0 <= window_size <= len(data): + raise ValueError( + "The moving average window size is out of range. Please change to a positive integer which " + "does not exceed the number of histogram bins." + ) + moving_averages = [] + + for i in range(len(data)): + start_window_ind = floor(float(i - window_size / 2)) if i - window_size / 2 > 0 else 0 + end_window_ind = floor(float(i + window_size / 2)) if i + window_size / 2 < len(data) else len(data) + window_average = np.sum(data[start_window_ind:end_window_ind]) / (end_window_ind + 0 - start_window_ind) + moving_averages.append(window_average) + + return moving_averages diff --git a/tests/test_plotting.py b/tests/test_plotting.py index 31049a28..518888fe 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -495,3 +495,61 @@ def test_extract_plot_data(data) -> None: with pytest.raises(ValueError, match=r"Parameter `shift_value` must be between 0 and 100"): RATplot._extract_plot_data(data, False, True, 100.5) + + +def test_moving_average() -> None: + """Test the moving_average function.""" + data_to_average = np.arange(0, 20) + mov_avg = RATplot.moving_average(data_to_average) + assert mov_avg == [ + 1.5, + 2.0, + 2.5, + 3.0, + 3.5, + 4.5, + 5.5, + 6.5, + 7.5, + 8.5, + 9.5, + 10.5, + 11.5, + 12.5, + 13.5, + 14.5, + 15.5, + 16.0, + 16.5, + 17.0, + ] + + mov_avg = RATplot.moving_average(data_to_average, window_size=2) + assert mov_avg == [ + 0.0, + 0.5, + 1.5, + 2.5, + 3.5, + 4.5, + 5.5, + 6.5, + 7.5, + 8.5, + 9.5, + 10.5, + 11.5, + 12.5, + 13.5, + 14.5, + 15.5, + 16.5, + 17.5, + 18.5, + ] + + with pytest.raises(ValueError): + RATplot.moving_average(data_to_average, window_size=-1) + + with pytest.raises(ValueError): + RATplot.moving_average(data_to_average, window_size=len(data_to_average) + 1) From 337eb43f0319114e8e2d1c58818933e727437be1 Mon Sep 17 00:00:00 2001 From: Michael Sullivan <30868085+MikeSullivan7@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:27:47 +0100 Subject: [PATCH 3/3] update to dev15 (#211) --- cpp/RAT | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/RAT b/cpp/RAT index a5d4d80b..e1e879c6 160000 --- a/cpp/RAT +++ b/cpp/RAT @@ -1 +1 @@ -Subproject commit a5d4d80ba63185846db678c3ebd9a85bdd82921d +Subproject commit e1e879c6eda6f1dee7a82b97dbbabd85d091017e diff --git a/pyproject.toml b/pyproject.toml index a2c37797..f2f9201c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = 'setuptools.build_meta' [project] name = "ratapi" -version = "0.0.0.dev14" +version = "0.0.0.dev15" description = "Python extension for the Reflectivity Analysis Toolbox (RAT)" readme = "README.md" requires-python = ">=3.10"