From e73b35a8c32d8cb52772d29e30f6b4ae0680da5c Mon Sep 17 00:00:00 2001 From: Stephen Nneji Date: Tue, 14 Oct 2025 15:35:16 +0100 Subject: [PATCH 1/3] Fixes plot bug when resample is set on a subset of contrast --- pyproject.toml | 4 ++++ ratapi/utils/plotting.py | 47 +++++++++++++++------------------------- setup.py | 6 ----- 3 files changed, 21 insertions(+), 36 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 99c65b3..ff9cd29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,10 @@ dependencies = [ "tqdm>=4.66.5", ] +[project.urls] +Documentation = "https://rascalsoftware.github.io/RAT/" +Repository = "https://github.com/RascalSoftware/python-RAT" + [project.optional-dependencies] dev = [ "pytest>=7.4.0", diff --git a/ratapi/utils/plotting.py b/ratapi/utils/plotting.py index 30ab894..3414246 100644 --- a/ratapi/utils/plotting.py +++ b/ratapi/utils/plotting.py @@ -76,9 +76,9 @@ def _extract_plot_data(event_data: PlotEventData, q4: bool, show_error_bar: bool for j in range(len(sld)): results["sld"][-1].append([sld[j][:, 0], sld[j][:, 1]]) + results["sld_resample"].append([]) if event_data.resample[i] == 1 or event_data.modelType == "custom xy": layers = event_data.resampledLayers[i][0] - results["sld_resample"].append([]) for j in range(len(event_data.resampledLayers[i])): layer = event_data.resampledLayers[i][j] if layers.shape[1] == 4: @@ -198,7 +198,7 @@ def plot_ref_sld_helper( sld_min, sld_max = confidence_intervals["sld"][i][j] sld_plot.fill_between(plot_data["sld"][i][j][0], sld_min, sld_max, alpha=0.6, color="grey") - if plot_data["sld_resample"]: + if plot_data["sld_resample"] and plot_data["sld_resample"][i]: for j in range(len(plot_data["sld_resample"][i])): sld_plot.plot( plot_data["sld_resample"][i][j][0], @@ -544,7 +544,7 @@ def update_foreground(self, data): self.figure.axes[1].draw_artist(self.figure.axes[1].lines[i]) i += 1 - if plot_data["sld_resample"]: + if plot_data["sld_resample"] and plot_data["sld_resample"][j]: for resampled in plot_data["sld_resample"][j]: self.figure.axes[1].lines[i].set_data(resampled[0], resampled[1]) self.figure.axes[1].draw_artist(self.figure.axes[1].lines[i]) @@ -982,10 +982,7 @@ def plot_contour( def panel_plot_helper( - plot_func: Callable, - indices: list[int], - fig: matplotlib.figure.Figure | None = None, - progress_callback: Callable[[int, int], None] | None = None, + plot_func: Callable, indices: list[int], fig: matplotlib.figure.Figure | None = None ) -> matplotlib.figure.Figure: """Generate a panel-based plot from a single plot function. @@ -997,9 +994,6 @@ def panel_plot_helper( The list of indices to pass into ``plot_func``. fig : matplotlib.figure.Figure, optional The figure object to use for plot. - progress_callback: Union[Callable[[int, int], None], None] - Callback function for providing progress during plot creation - First argument is current completed sub plot and second is total number of sub plots Returns ------- @@ -1011,19 +1005,21 @@ def panel_plot_helper( nrows, ncols = ceil(sqrt(nplots)), round(sqrt(nplots)) if fig is None: - fig = plt.subplots(nrows, ncols, figsize=(11, 10), subplot_kw={"visible": False})[0] + fig = plt.subplots(nrows, ncols, figsize=(11, 10))[0] else: fig.clf() - fig.subplots(nrows, ncols, subplot_kw={"visible": False}) + fig.subplots(nrows, ncols) axs = fig.get_axes() - for index, plot_num in enumerate(indices): - axs[index].tick_params(which="both", labelsize="medium") - axs[index].xaxis.offsetText.set_fontsize("small") - axs[index].yaxis.offsetText.set_fontsize("small") - axs[index].set_visible(True) - plot_func(axs[index], plot_num) - if progress_callback is not None: - progress_callback(index, nplots) + + for plot_num, index in enumerate(indices): + axs[plot_num].tick_params(which="both", labelsize="medium") + axs[plot_num].xaxis.offsetText.set_fontsize("small") + axs[plot_num].yaxis.offsetText.set_fontsize("small") + plot_func(axs[plot_num], index) + + # blank unused plots + for i in range(nplots, len(axs)): + axs[i].set_visible(False) fig.tight_layout() return fig @@ -1040,7 +1036,6 @@ def plot_hists( block: bool = False, fig: matplotlib.figure.Figure | None = None, return_fig: bool = False, - progress_callback: Callable[[int, int], None] | None = None, **hist_settings, ): """Plot marginalised posteriors for several parameters from a Bayesian analysis. @@ -1077,9 +1072,6 @@ def plot_hists( The figure object to use for plot. return_fig: bool, default False If True, return the figure as an object instead of showing it. - progress_callback: Union[Callable[[int, int], None], None] - Callback function for providing progress during plot creation - First argument is current completed sub plot and second is total number of sub plots hist_settings : Settings passed to `np.histogram`. By default, the settings passed are `bins = 25` and `density = True`. @@ -1138,7 +1130,6 @@ def validate_dens_type(dens_type: str | None, param: str): ), params, fig, - progress_callback, ) if return_fig: return fig @@ -1153,7 +1144,6 @@ def plot_chain( block: bool = False, fig: matplotlib.figure.Figure | None = None, return_fig: bool = False, - progress_callback: Callable[[int, int], None] | None = None, ): """Plot the MCMC chain for each parameter of a Bayesian analysis. @@ -1172,9 +1162,6 @@ def plot_chain( The figure object to use for plot. return_fig: bool, default False If True, return the figure as an object instead of showing it. - progress_callback: Union[Callable[[int, int], None], None] - Callback function for providing progress during plot creation - First argument is current completed sub plot and second is total number of sub plots Returns ------- @@ -1200,7 +1187,7 @@ def plot_one_chain(axes: Axes, i: int): axes.plot(range(0, nsimulations, skip), chain[:, i][0:nsimulations:skip]) axes.set_title(results.fitNames[i], fontsize="small") - fig = panel_plot_helper(plot_one_chain, params, fig, progress_callback) + fig = panel_plot_helper(plot_one_chain, params, fig=fig) if return_fig: return fig plt.show(block=block) diff --git a/setup.py b/setup.py index 3bdfea9..38947e5 100644 --- a/setup.py +++ b/setup.py @@ -151,12 +151,6 @@ def build_libraries(self, libraries): setup( name=PACKAGE_NAME, - author="", - author_email="", - url="https://github.com/RascalSoftware/python-RAT", - description="Python extension for the Reflectivity Analysis Toolbox (RAT)", - long_description=LONG_DESCRIPTION, - long_description_content_type="text/markdown", packages=find_packages(exclude=("tests",)), include_package_data=True, package_data={"": [get_shared_object_name(libevent[0])], "ratapi.examples": ["data/*.dat"]}, From 2e5a2f12146df991b7ac60582b61b9070d23c749 Mon Sep 17 00:00:00 2001 From: Stephen Nneji Date: Wed, 15 Oct 2025 10:11:12 +0100 Subject: [PATCH 2/3] revert --- ratapi/utils/plotting.py | 41 ++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/ratapi/utils/plotting.py b/ratapi/utils/plotting.py index 3414246..73e8bac 100644 --- a/ratapi/utils/plotting.py +++ b/ratapi/utils/plotting.py @@ -982,7 +982,10 @@ def plot_contour( def panel_plot_helper( - plot_func: Callable, indices: list[int], fig: matplotlib.figure.Figure | None = None + plot_func: Callable, + indices: list[int], + fig: matplotlib.figure.Figure | None = None, + progress_callback: Callable[[int, int], None] | None = None, ) -> matplotlib.figure.Figure: """Generate a panel-based plot from a single plot function. @@ -994,6 +997,9 @@ def panel_plot_helper( The list of indices to pass into ``plot_func``. fig : matplotlib.figure.Figure, optional The figure object to use for plot. + progress_callback: Union[Callable[[int, int], None], None] + Callback function for providing progress during plot creation + First argument is current completed sub plot and second is total number of sub plots Returns ------- @@ -1005,21 +1011,19 @@ def panel_plot_helper( nrows, ncols = ceil(sqrt(nplots)), round(sqrt(nplots)) if fig is None: - fig = plt.subplots(nrows, ncols, figsize=(11, 10))[0] + fig = plt.subplots(nrows, ncols, figsize=(11, 10), subplot_kw={"visible": False})[0] else: fig.clf() - fig.subplots(nrows, ncols) + fig.subplots(nrows, ncols, subplot_kw={"visible": False}) axs = fig.get_axes() - - for plot_num, index in enumerate(indices): - axs[plot_num].tick_params(which="both", labelsize="medium") - axs[plot_num].xaxis.offsetText.set_fontsize("small") - axs[plot_num].yaxis.offsetText.set_fontsize("small") - plot_func(axs[plot_num], index) - - # blank unused plots - for i in range(nplots, len(axs)): - axs[i].set_visible(False) + for index, plot_num in enumerate(indices): + axs[index].tick_params(which="both", labelsize="medium") + axs[index].xaxis.offsetText.set_fontsize("small") + axs[index].yaxis.offsetText.set_fontsize("small") + axs[index].set_visible(True) + plot_func(axs[index], plot_num) + if progress_callback is not None: + progress_callback(index, nplots) fig.tight_layout() return fig @@ -1036,6 +1040,7 @@ def plot_hists( block: bool = False, fig: matplotlib.figure.Figure | None = None, return_fig: bool = False, + progress_callback: Callable[[int, int], None] | None = None, **hist_settings, ): """Plot marginalised posteriors for several parameters from a Bayesian analysis. @@ -1072,6 +1077,9 @@ def plot_hists( The figure object to use for plot. return_fig: bool, default False If True, return the figure as an object instead of showing it. + progress_callback: Union[Callable[[int, int], None], None] + Callback function for providing progress during plot creation + First argument is current completed sub plot and second is total number of sub plots hist_settings : Settings passed to `np.histogram`. By default, the settings passed are `bins = 25` and `density = True`. @@ -1130,6 +1138,7 @@ def validate_dens_type(dens_type: str | None, param: str): ), params, fig, + progress_callback, ) if return_fig: return fig @@ -1144,6 +1153,7 @@ def plot_chain( block: bool = False, fig: matplotlib.figure.Figure | None = None, return_fig: bool = False, + progress_callback: Callable[[int, int], None] | None = None, ): """Plot the MCMC chain for each parameter of a Bayesian analysis. @@ -1162,6 +1172,9 @@ def plot_chain( The figure object to use for plot. return_fig: bool, default False If True, return the figure as an object instead of showing it. + progress_callback: Union[Callable[[int, int], None], None] + Callback function for providing progress during plot creation + First argument is current completed sub plot and second is total number of sub plots Returns ------- @@ -1187,7 +1200,7 @@ def plot_one_chain(axes: Axes, i: int): axes.plot(range(0, nsimulations, skip), chain[:, i][0:nsimulations:skip]) axes.set_title(results.fitNames[i], fontsize="small") - fig = panel_plot_helper(plot_one_chain, params, fig=fig) + fig = panel_plot_helper(plot_one_chain, params, fig, progress_callback) if return_fig: return fig plt.show(block=block) From 74760f939e1271a3385bd30f5da8aae934c2433a Mon Sep 17 00:00:00 2001 From: Stephen Nneji Date: Wed, 15 Oct 2025 10:40:20 +0100 Subject: [PATCH 3/3] Address review comments --- ratapi/utils/plotting.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/ratapi/utils/plotting.py b/ratapi/utils/plotting.py index 73e8bac..9293a1a 100644 --- a/ratapi/utils/plotting.py +++ b/ratapi/utils/plotting.py @@ -198,15 +198,14 @@ def plot_ref_sld_helper( sld_min, sld_max = confidence_intervals["sld"][i][j] sld_plot.fill_between(plot_data["sld"][i][j][0], sld_min, sld_max, alpha=0.6, color="grey") - if plot_data["sld_resample"] and plot_data["sld_resample"][i]: - for j in range(len(plot_data["sld_resample"][i])): - sld_plot.plot( - plot_data["sld_resample"][i][j][0], - plot_data["sld_resample"][i][j][1], - color=color, - linewidth=1, - animated=animated, - ) + for j in range(len(plot_data["sld_resample"][i])): + sld_plot.plot( + plot_data["sld_resample"][i][j][0], + plot_data["sld_resample"][i][j][1], + color=color, + linewidth=1, + animated=animated, + ) # Format the axis ref_plot.set_yscale("log") @@ -544,11 +543,10 @@ def update_foreground(self, data): self.figure.axes[1].draw_artist(self.figure.axes[1].lines[i]) i += 1 - if plot_data["sld_resample"] and plot_data["sld_resample"][j]: - for resampled in plot_data["sld_resample"][j]: - self.figure.axes[1].lines[i].set_data(resampled[0], resampled[1]) - self.figure.axes[1].draw_artist(self.figure.axes[1].lines[i]) - i += 1 + for resampled in plot_data["sld_resample"][j]: + self.figure.axes[1].lines[i].set_data(resampled[0], resampled[1]) + self.figure.axes[1].draw_artist(self.figure.axes[1].lines[i]) + i += 1 for i, container in enumerate(self.figure.axes[0].containers): self.adjust_error_bar(