diff --git a/pyproject.toml b/pyproject.toml index 09796c44..ab6724ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = 'setuptools.build_meta' [project] name = "ratapi" -version = "0.0.0.dev13" +version = "0.0.0.dev14" description = "Python extension for the Reflectivity Analysis Toolbox (RAT)" readme = "README.md" requires-python = ">=3.10" diff --git a/ratapi/utils/convert.py b/ratapi/utils/convert.py index b957789c..7b3a44f7 100644 --- a/ratapi/utils/convert.py +++ b/ratapi/utils/convert.py @@ -5,7 +5,7 @@ from os import PathLike from pathlib import Path -from numpy import array, empty +from numpy import array, empty, ndarray from scipy.io.matlab import MatlabOpaque, loadmat from ratapi import Project, wrappers @@ -227,6 +227,12 @@ def fix_invalid_constraints(name: str, constrs: tuple[float, float], value: floa if isinstance(mat_project["resolNames"], str): mat_project["resolNames"] = [mat_project["resolNames"]] + if isinstance(mat_project["contrastNames"], (ndarray, list)) and len( + dict.fromkeys(mat_project["contrastNames"]) + ) != len(mat_project["contrastNames"]): + # contrast names are not unique so create unique ones + mat_project["contrastNames"] = [f"Contrast {i + 1}" for i in range(len(mat_project["contrastNames"]))] + contrasts = ClassList( [ Contrast( diff --git a/ratapi/utils/plotting.py b/ratapi/utils/plotting.py index 8225bd43..6f9debb7 100644 --- a/ratapi/utils/plotting.py +++ b/ratapi/utils/plotting.py @@ -36,7 +36,7 @@ def _extract_plot_data(event_data: PlotEventData, q4: bool, show_error_bar: bool show_error_bar : bool, default: True Controls whether the error bars are shown shift_value : float - A value between 1 and 100 that controls the spacing between the reflectivity plots for each of the contrasts + A value between 0 and 100 that controls the spacing between the reflectivity plots for each of the contrasts Returns ------- @@ -46,14 +46,14 @@ def _extract_plot_data(event_data: PlotEventData, q4: bool, show_error_bar: bool """ results = {"ref": [], "error": [], "sld": [], "sld_resample": []} - if shift_value < 1 or shift_value > 100: - raise ValueError("Parameter `shift_value` must be between 1 and 100") + if shift_value < 0 or shift_value > 100: + raise ValueError("Parameter `shift_value` must be between 0 and 100") for i, (r, data, sld) in enumerate( zip(event_data.reflectivity, event_data.shiftedData, event_data.sldProfiles, strict=False) ): # Calculate the divisor - div = 1 if i == 0 and not q4 else 10 ** ((i + 1) / 100 * shift_value) + div = 10 ** (i / 100 * shift_value) q4_data = 1 if not q4 or not event_data.dataPresent[i] else data[:, 0] ** 4 mult = q4_data / div @@ -137,7 +137,7 @@ def plot_ref_sld_helper( show_legend : bool, default: True Controls whether the legend is shown shift_value : float, default: 100 - A value between 1 and 100 that controls the spacing between the reflectivity plots for each of the contrasts + A value between 0 and 100 that controls the spacing between the reflectivity plots for each of the contrasts animated : bool, default: False Controls whether the animated property of foreground plot elements should be set. @@ -168,7 +168,7 @@ def plot_ref_sld_helper( # Plot confidence intervals if required if confidence_intervals is not None: # Calculate the divisor - div = 1 if i == 0 and not q4 else 10 ** ((i / 100) * shift_value) + div = 10 ** (i / 100 * shift_value) ref_min, ref_max = confidence_intervals["reflectivity"][i] mult = (1 if not q4 else plot_data["ref"][i][0] ** 4) / div ref_plot.fill_between(plot_data["ref"][i][0], ref_min * mult, ref_max * mult, alpha=0.6, color="grey") @@ -277,7 +277,7 @@ def plot_ref_sld( show_legend : bool, default: True Controls whether the legend is shown shift_value : float, default: 100 - A value between 1 and 100 that controls the spacing between the reflectivity plots for each of the contrasts + A value between 0 and 100 that controls the spacing between the reflectivity plots for each of the contrasts Returns ------- @@ -387,7 +387,7 @@ class BlittingSupport: show_legend : bool, default: True Controls whether the legend is shown shift_value : float, default: 100 - A value between 1 and 100 that controls the spacing between the reflectivity plots for each of the contrasts + A value between 0 and 100 that controls the spacing between the reflectivity plots for each of the contrasts """ def __init__( diff --git a/tests/test_convert.py b/tests/test_convert.py index fc6f4400..0cbd621b 100644 --- a/tests/test_convert.py +++ b/tests/test_convert.py @@ -69,6 +69,13 @@ def test_r1_to_project(file, project, path_type, request): assert getattr(output_project, class_list) == getattr(expected_project, class_list) +def test_r1_with_non_unique_contrast_names(): + """Test that R1 to Project class conversion returns the expected Project.""" + output_project = r1_to_project(pathlib.Path(TEST_DIR_PATH, "nonUniqueContrast.mat")) + assert output_project.contrasts[0].name == "Contrast 1" + assert output_project.contrasts[1].name == "Contrast 2" + + @pytest.mark.parametrize( "project", [ diff --git a/tests/test_data/nonUniqueContrast.mat b/tests/test_data/nonUniqueContrast.mat new file mode 100644 index 00000000..41375134 Binary files /dev/null and b/tests/test_data/nonUniqueContrast.mat differ diff --git a/tests/test_plotting.py b/tests/test_plotting.py index 710729a5..31049a28 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -490,8 +490,8 @@ def test_extract_plot_data(data) -> None: assert len(plot_data["ref"]) == len(data.reflectivity) assert len(plot_data["sld"]) == len(data.shiftedData) - with pytest.raises(ValueError, match=r"Parameter `shift_value` must be between 1 and 100"): - RATplot._extract_plot_data(data, False, True, 0) + with pytest.raises(ValueError, match=r"Parameter `shift_value` must be between 0 and 100"): + RATplot._extract_plot_data(data, False, True, -0.1) - with pytest.raises(ValueError, match=r"Parameter `shift_value` must be between 1 and 100"): + with pytest.raises(ValueError, match=r"Parameter `shift_value` must be between 0 and 100"): RATplot._extract_plot_data(data, False, True, 100.5)