diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..2c0cbe3c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,45 @@ +name: Build and upload to PyPI + +on: + release: + types: + - published + workflow_dispatch: + +jobs: + build_wheels: + uses: RascalSoftware/python-RAT/.github/workflows/build_wheel.yml@main + + build_sdist: + name: Build source distribution + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build sdist + run: | + pip install pybind11 + python setup.py sdist + - uses: actions/upload-artifact@v4 + with: + name: sdist + path: dist/*.tar.gz + + upload_pypi: + needs: [build_wheels, build_sdist] + runs-on: ubuntu-latest + environment: release + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v4 + with: + path: dist + merge-multiple: true + - name: Publish to TestPyPi + if: github.event_name == 'workflow_dispatch' + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + - name: Publish + if: github.event_name == 'release' + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/RAT/__init__.py b/RAT/__init__.py deleted file mode 100644 index 98d87986..00000000 --- a/RAT/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -import os - -from RAT import models -from RAT.classlist import ClassList -from RAT.controls import set_controls -from RAT.project import Project -from RAT.run import run - -__all__ = ["ClassList", "Project", "run", "set_controls", "models"] - -dir_path = os.path.dirname(os.path.realpath(__file__)) -os.environ["RAT_PATH"] = os.path.join(dir_path, "") diff --git a/RATpy/__init__.py b/RATpy/__init__.py new file mode 100644 index 00000000..be072602 --- /dev/null +++ b/RATpy/__init__.py @@ -0,0 +1,8 @@ +from RATpy import events, models +from RATpy.classlist import ClassList +from RATpy.controls import set_controls +from RATpy.project import Project +from RATpy.run import run +from RATpy.utils import plotting + +__all__ = ["ClassList", "Project", "run", "set_controls", "models", "events", "plotting"] diff --git a/RAT/classlist.py b/RATpy/classlist.py similarity index 100% rename from RAT/classlist.py rename to RATpy/classlist.py diff --git a/RAT/controls.py b/RATpy/controls.py similarity index 97% rename from RAT/controls.py rename to RATpy/controls.py index 093687d5..be54ab89 100644 --- a/RAT/controls.py +++ b/RATpy/controls.py @@ -4,8 +4,8 @@ import prettytable from pydantic import BaseModel, Field, ValidationError, field_validator -from RAT.utils.custom_errors import custom_pydantic_validation_error -from RAT.utils.enums import BoundHandling, Display, Parallel, Procedures, Strategies +from RATpy.utils.custom_errors import custom_pydantic_validation_error +from RATpy.utils.enums import BoundHandling, Display, Parallel, Procedures, Strategies @dataclass(frozen=True) diff --git a/RAT/events.py b/RATpy/events.py similarity index 90% rename from RAT/events.py rename to RATpy/events.py index d5679984..310203b9 100644 --- a/RAT/events.py +++ b/RATpy/events.py @@ -1,6 +1,7 @@ +import os from typing import Callable, List, Union -from RAT.rat_core import EventBridge, EventTypes, PlotEventData, ProgressEventData +from RATpy.rat_core import EventBridge, EventTypes, PlotEventData, ProgressEventData def notify(event_type: EventTypes, data: Union[str, PlotEventData, ProgressEventData]) -> None: @@ -63,5 +64,7 @@ def clear() -> None: __event_callbacks[key] = set() +dir_path = os.path.dirname(os.path.realpath(__file__)) +os.environ["RAT_PATH"] = os.path.join(dir_path, "") __event_impl = EventBridge(notify) __event_callbacks = {EventTypes.Message: set(), EventTypes.Plot: set(), EventTypes.Progress: set()} diff --git a/RAT/examples/__init__.py b/RATpy/examples/__init__.py similarity index 100% rename from RAT/examples/__init__.py rename to RATpy/examples/__init__.py diff --git a/RAT/examples/absorption/__init__.py b/RATpy/examples/absorption/__init__.py similarity index 100% rename from RAT/examples/absorption/__init__.py rename to RATpy/examples/absorption/__init__.py diff --git a/RAT/examples/absorption/absorption.py b/RATpy/examples/absorption/absorption.py similarity index 98% rename from RAT/examples/absorption/absorption.py rename to RATpy/examples/absorption/absorption.py index 35f9a057..01b9e194 100644 --- a/RAT/examples/absorption/absorption.py +++ b/RATpy/examples/absorption/absorption.py @@ -5,8 +5,7 @@ import numpy as np -import RAT -import RAT.utils.plotting +import RATpy as RAT problem = RAT.Project( name="Absorption example", @@ -146,4 +145,4 @@ # Run the code and plot the results problem, results = RAT.run(problem, controls) -RAT.utils.plotting.plot_ref_sld(problem, results, True) +RAT.plotting.plot_ref_sld(problem, results, True) diff --git a/RAT/examples/absorption/volume_thiol_bilayer.py b/RATpy/examples/absorption/volume_thiol_bilayer.py similarity index 100% rename from RAT/examples/absorption/volume_thiol_bilayer.py rename to RATpy/examples/absorption/volume_thiol_bilayer.py diff --git a/RAT/examples/data/D2O_spin_down.dat b/RATpy/examples/data/D2O_spin_down.dat similarity index 100% rename from RAT/examples/data/D2O_spin_down.dat rename to RATpy/examples/data/D2O_spin_down.dat diff --git a/RAT/examples/data/D2O_spin_up.dat b/RATpy/examples/data/D2O_spin_up.dat similarity index 100% rename from RAT/examples/data/D2O_spin_up.dat rename to RATpy/examples/data/D2O_spin_up.dat diff --git a/RAT/examples/data/DSPC_D2O.dat b/RATpy/examples/data/DSPC_D2O.dat similarity index 100% rename from RAT/examples/data/DSPC_D2O.dat rename to RATpy/examples/data/DSPC_D2O.dat diff --git a/RAT/examples/data/DSPC_SMW.dat b/RATpy/examples/data/DSPC_SMW.dat similarity index 100% rename from RAT/examples/data/DSPC_SMW.dat rename to RATpy/examples/data/DSPC_SMW.dat diff --git a/RAT/examples/data/H2O_spin_down.dat b/RATpy/examples/data/H2O_spin_down.dat similarity index 100% rename from RAT/examples/data/H2O_spin_down.dat rename to RATpy/examples/data/H2O_spin_down.dat diff --git a/RAT/examples/data/H2O_spin_up.dat b/RATpy/examples/data/H2O_spin_up.dat similarity index 100% rename from RAT/examples/data/H2O_spin_up.dat rename to RATpy/examples/data/H2O_spin_up.dat diff --git a/RAT/examples/data/__init__.py b/RATpy/examples/data/__init__.py similarity index 100% rename from RAT/examples/data/__init__.py rename to RATpy/examples/data/__init__.py diff --git a/RAT/examples/data/c_PLP0016596.dat b/RATpy/examples/data/c_PLP0016596.dat similarity index 100% rename from RAT/examples/data/c_PLP0016596.dat rename to RATpy/examples/data/c_PLP0016596.dat diff --git a/RAT/examples/data/c_PLP0016601.dat b/RATpy/examples/data/c_PLP0016601.dat similarity index 100% rename from RAT/examples/data/c_PLP0016601.dat rename to RATpy/examples/data/c_PLP0016601.dat diff --git a/RAT/examples/data/c_PLP0016607.dat b/RATpy/examples/data/c_PLP0016607.dat similarity index 100% rename from RAT/examples/data/c_PLP0016607.dat rename to RATpy/examples/data/c_PLP0016607.dat diff --git a/RAT/examples/domains/__init__.py b/RATpy/examples/domains/__init__.py similarity index 100% rename from RAT/examples/domains/__init__.py rename to RATpy/examples/domains/__init__.py diff --git a/RAT/examples/domains/alloy_domains.py b/RATpy/examples/domains/alloy_domains.py similarity index 100% rename from RAT/examples/domains/alloy_domains.py rename to RATpy/examples/domains/alloy_domains.py diff --git a/RAT/examples/domains/domains_XY_model.py b/RATpy/examples/domains/domains_XY_model.py similarity index 100% rename from RAT/examples/domains/domains_XY_model.py rename to RATpy/examples/domains/domains_XY_model.py diff --git a/RAT/examples/domains/domains_custom_XY.py b/RATpy/examples/domains/domains_custom_XY.py similarity index 95% rename from RAT/examples/domains/domains_custom_XY.py rename to RATpy/examples/domains/domains_custom_XY.py index 75665898..68380862 100644 --- a/RAT/examples/domains/domains_custom_XY.py +++ b/RATpy/examples/domains/domains_custom_XY.py @@ -2,8 +2,7 @@ import pathlib -import RAT -import RAT.utils.plotting +import RATpy as RAT problem = RAT.Project(calculation="domains", model="custom xy", geometry="substrate/liquid") @@ -67,4 +66,4 @@ controls = RAT.set_controls() problem, results = RAT.run(problem, controls) -RAT.utils.plotting.plot_ref_sld(problem, results, True) +RAT.plotting.plot_ref_sld(problem, results, True) diff --git a/RAT/examples/domains/domains_custom_layers.py b/RATpy/examples/domains/domains_custom_layers.py similarity index 94% rename from RAT/examples/domains/domains_custom_layers.py rename to RATpy/examples/domains/domains_custom_layers.py index eff1b7ba..279137e1 100644 --- a/RAT/examples/domains/domains_custom_layers.py +++ b/RATpy/examples/domains/domains_custom_layers.py @@ -2,8 +2,7 @@ import pathlib -import RAT -import RAT.utils.plotting +import RATpy as RAT problem = RAT.Project(calculation="domains", model="custom layers", geometry="substrate/liquid") @@ -44,4 +43,4 @@ controls = RAT.set_controls() problem, results = RAT.run(problem, controls) -RAT.utils.plotting.plot_ref_sld(problem, results, True) +RAT.plotting.plot_ref_sld(problem, results, True) diff --git a/RAT/examples/domains/domains_standard_layers.py b/RATpy/examples/domains/domains_standard_layers.py similarity index 96% rename from RAT/examples/domains/domains_standard_layers.py rename to RATpy/examples/domains/domains_standard_layers.py index 3ec4fd55..533dce16 100644 --- a/RAT/examples/domains/domains_standard_layers.py +++ b/RATpy/examples/domains/domains_standard_layers.py @@ -1,5 +1,4 @@ -import RAT -import RAT.utils.plotting +import RATpy as RAT problem = RAT.Project(calculation="domains") @@ -73,4 +72,4 @@ controls = RAT.set_controls() problem, results = RAT.run(problem, controls) -RAT.utils.plotting.plot_ref_sld(problem, results, True) +RAT.plotting.plot_ref_sld(problem, results, True) diff --git a/RAT/examples/languages/__init__.py b/RATpy/examples/languages/__init__.py similarity index 100% rename from RAT/examples/languages/__init__.py rename to RATpy/examples/languages/__init__.py diff --git a/RAT/examples/languages/custom_bilayer.cpp b/RATpy/examples/languages/custom_bilayer.cpp similarity index 100% rename from RAT/examples/languages/custom_bilayer.cpp rename to RATpy/examples/languages/custom_bilayer.cpp diff --git a/RAT/examples/languages/custom_bilayer.m b/RATpy/examples/languages/custom_bilayer.m similarity index 100% rename from RAT/examples/languages/custom_bilayer.m rename to RATpy/examples/languages/custom_bilayer.m diff --git a/RAT/examples/languages/custom_bilayer.py b/RATpy/examples/languages/custom_bilayer.py similarity index 100% rename from RAT/examples/languages/custom_bilayer.py rename to RATpy/examples/languages/custom_bilayer.py diff --git a/RAT/examples/languages/run_custom_file_languages.py b/RATpy/examples/languages/run_custom_file_languages.py similarity index 82% rename from RAT/examples/languages/run_custom_file_languages.py rename to RATpy/examples/languages/run_custom_file_languages.py index c1b37e3b..279d5c98 100644 --- a/RAT/examples/languages/run_custom_file_languages.py +++ b/RATpy/examples/languages/run_custom_file_languages.py @@ -5,7 +5,7 @@ import setup_problem -import RAT.utils.plotting +import RATpy as RAT path = pathlib.Path(__file__).parent.resolve() @@ -18,7 +18,7 @@ end = time.time() print(f"Python time is: {end-start}s\n") -RAT.utils.plotting.plot_ref_sld(project, results) +RAT.plotting.plot_ref_sld(project, results) # Matlab project.custom_files.set_fields(0, filename="custom_bilayer.m", language="matlab", path=path) @@ -28,7 +28,7 @@ end = time.time() print(f"Matlab time is: {end-start}s\n") -RAT.utils.plotting.plot_ref_sld(project, results) +RAT.plotting.plot_ref_sld(project, results) # C++ project.custom_files.set_fields(0, filename="custom_bilayer.dll", language="cpp", path=path) @@ -38,4 +38,4 @@ end = time.time() print(f"C++ time is: {end-start}s\n") -RAT.utils.plotting.plot_ref_sld(project, results) +RAT.plotting.plot_ref_sld(project, results) diff --git a/RAT/examples/languages/setup_problem.py b/RATpy/examples/languages/setup_problem.py similarity index 99% rename from RAT/examples/languages/setup_problem.py rename to RATpy/examples/languages/setup_problem.py index a7ed17f8..4fde3122 100644 --- a/RAT/examples/languages/setup_problem.py +++ b/RATpy/examples/languages/setup_problem.py @@ -8,7 +8,7 @@ import numpy as np -import RAT +import RATpy as RAT def make_example_problem(): diff --git a/RAT/examples/non_polarised/DSPC_custom_XY.py b/RATpy/examples/non_polarised/DSPC_custom_XY.py similarity index 99% rename from RAT/examples/non_polarised/DSPC_custom_XY.py rename to RATpy/examples/non_polarised/DSPC_custom_XY.py index feb87688..324cd41c 100644 --- a/RAT/examples/non_polarised/DSPC_custom_XY.py +++ b/RATpy/examples/non_polarised/DSPC_custom_XY.py @@ -28,8 +28,7 @@ import numpy as np -import RAT -import RAT.utils.plotting +import RATpy as RAT # Start by making the class and setting it to a custom layers type: problem = RAT.Project(name="Orso lipid example - custom XY", model="custom xy", geometry="substrate/liquid") diff --git a/RAT/examples/non_polarised/DSPC_custom_layers.py b/RATpy/examples/non_polarised/DSPC_custom_layers.py similarity index 99% rename from RAT/examples/non_polarised/DSPC_custom_layers.py rename to RATpy/examples/non_polarised/DSPC_custom_layers.py index 13cc9cca..3516a42f 100644 --- a/RAT/examples/non_polarised/DSPC_custom_layers.py +++ b/RATpy/examples/non_polarised/DSPC_custom_layers.py @@ -8,8 +8,7 @@ import numpy as np -import RAT -import RAT.utils.plotting +import RATpy as RAT problem = RAT.Project(name="Orso lipid example - custom layers", model="custom layers", geometry="substrate/liquid") diff --git a/RAT/examples/non_polarised/DSPC_standard_layers.py b/RATpy/examples/non_polarised/DSPC_standard_layers.py similarity index 98% rename from RAT/examples/non_polarised/DSPC_standard_layers.py rename to RATpy/examples/non_polarised/DSPC_standard_layers.py index 8799710b..eac1d017 100644 --- a/RAT/examples/non_polarised/DSPC_standard_layers.py +++ b/RATpy/examples/non_polarised/DSPC_standard_layers.py @@ -5,8 +5,7 @@ import numpy as np -import RAT -import RAT.utils.plotting +import RATpy as RAT problem = RAT.Project( name="original_dspc_bilayer", @@ -356,4 +355,4 @@ controls = RAT.set_controls() problem, results = RAT.run(problem, controls) -RAT.utils.plotting.plot_ref_sld(problem, results, True) +RAT.plotting.plot_ref_sld(problem, results, True) diff --git a/RAT/examples/non_polarised/__init__.py b/RATpy/examples/non_polarised/__init__.py similarity index 100% rename from RAT/examples/non_polarised/__init__.py rename to RATpy/examples/non_polarised/__init__.py diff --git a/RAT/examples/non_polarised/custom_XY_DSPC.py b/RATpy/examples/non_polarised/custom_XY_DSPC.py similarity index 100% rename from RAT/examples/non_polarised/custom_XY_DSPC.py rename to RATpy/examples/non_polarised/custom_XY_DSPC.py diff --git a/RAT/examples/non_polarised/custom_bilayer_DSPC.py b/RATpy/examples/non_polarised/custom_bilayer_DSPC.py similarity index 100% rename from RAT/examples/non_polarised/custom_bilayer_DSPC.py rename to RATpy/examples/non_polarised/custom_bilayer_DSPC.py diff --git a/RAT/inputs.py b/RATpy/inputs.py similarity index 91% rename from RAT/inputs.py rename to RATpy/inputs.py index 3c64ceef..519356c2 100644 --- a/RAT/inputs.py +++ b/RATpy/inputs.py @@ -5,16 +5,18 @@ import pathlib from typing import Callable, Union -import RAT -import RAT.controls -import RAT.wrappers -from RAT.rat_core import Cells, Checks, Control, Limits, Priors, ProblemDefinition -from RAT.utils.enums import Calculations, Languages, LayerModels, TypeOptions +import RATpy +import RATpy.controls +import RATpy.wrappers +from RATpy.rat_core import Cells, Checks, Control, Limits, Priors, ProblemDefinition +from RATpy.utils.enums import Calculations, Languages, LayerModels, TypeOptions def make_input( - project: RAT.Project, - controls: Union[RAT.controls.Calculate, RAT.controls.Simplex, RAT.controls.DE, RAT.controls.NS, RAT.controls.Dream], + project: RATpy.Project, + controls: Union[ + RATpy.controls.Calculate, RATpy.controls.Simplex, RATpy.controls.DE, RATpy.controls.NS, RATpy.controls.Dream + ], ) -> tuple[ProblemDefinition, Cells, Limits, Priors, Control]: """Constructs the inputs required for the compiled RAT code using the data defined in the input project and controls. @@ -68,7 +70,7 @@ def make_input( limits = Limits() priors = Priors() - for class_list in RAT.project.parameter_class_lists: + for class_list in RATpy.project.parameter_class_lists: setattr(checks, checks_field[class_list], [int(element.fit) for element in getattr(project, class_list)]) setattr( limits, @@ -87,11 +89,11 @@ def make_input( priors.qzshift = [] priors.priorNames = [ - param.name for class_list in RAT.project.parameter_class_lists for param in getattr(project, class_list) + param.name for class_list in RATpy.project.parameter_class_lists for param in getattr(project, class_list) ] priors.priorValues = [ [prior_id[param.prior_type], param.mu, param.sigma] - for class_list in RAT.project.parameter_class_lists + for class_list in RATpy.project.parameter_class_lists for param in getattr(project, class_list) ] @@ -103,7 +105,7 @@ def make_input( return problem, cells, limits, priors, cpp_controls -def make_problem(project: RAT.Project) -> ProblemDefinition: +def make_problem(project: RATpy.Project) -> ProblemDefinition: """Constructs the problem input required for the compiled RAT code. Parameters @@ -181,25 +183,25 @@ def make_problem(project: RAT.Project) -> ProblemDefinition: problem.numberOfDomainContrasts = len(project.domain_contrasts) problem.fitParams = [ param.value - for class_list in RAT.project.parameter_class_lists + for class_list in RATpy.project.parameter_class_lists for param in getattr(project, class_list) if param.fit ] problem.fitLimits = [ [param.min, param.max] - for class_list in RAT.project.parameter_class_lists + for class_list in RATpy.project.parameter_class_lists for param in getattr(project, class_list) if param.fit ] problem.otherParams = [ param.value - for class_list in RAT.project.parameter_class_lists + for class_list in RATpy.project.parameter_class_lists for param in getattr(project, class_list) if not param.fit ] problem.otherLimits = [ [param.min, param.max] - for class_list in RAT.project.parameter_class_lists + for class_list in RATpy.project.parameter_class_lists for param in getattr(project, class_list) if not param.fit ] @@ -209,7 +211,7 @@ def make_problem(project: RAT.Project) -> ProblemDefinition: return problem -def make_resample(project: RAT.Project) -> list[int]: +def make_resample(project: RATpy.Project) -> list[int]: """Constructs the "resample" field of the problem input required for the compiled RAT code. Parameters @@ -226,7 +228,7 @@ def make_resample(project: RAT.Project) -> list[int]: return [contrast.resample for contrast in project.contrasts] -def make_data_present(project: RAT.Project) -> list[int]: +def make_data_present(project: RATpy.Project) -> list[int]: """Constructs the "dataPresent" field of the problem input required for the compiled RAT code. Parameters @@ -282,7 +284,7 @@ def check_indices(problem: ProblemDefinition) -> None: ) -def make_cells(project: RAT.Project) -> Cells: +def make_cells(project: RATpy.Project) -> Cells: """Constructs the cells input required for the compiled RAT code. Note that the order of the inputs (i.e, f1 to f20) has been hard--coded into the compiled RAT code. @@ -353,9 +355,9 @@ def make_cells(project: RAT.Project) -> Cells: if custom_file.language == Languages.Python: file_handles.append(get_python_handle(custom_file.filename, custom_file.function_name, custom_file.path)) elif custom_file.language == Languages.Matlab: - file_handles.append(RAT.wrappers.MatlabWrapper(full_path).getHandle()) + file_handles.append(RATpy.wrappers.MatlabWrapper(full_path).getHandle()) elif custom_file.language == Languages.Cpp: - file_handles.append(RAT.wrappers.DylibWrapper(full_path, custom_file.function_name).getHandle()) + file_handles.append(RATpy.wrappers.DylibWrapper(full_path, custom_file.function_name).getHandle()) # Populate the set of cells cells = Cells() @@ -418,7 +420,9 @@ def get_python_handle(file_name: str, function_name: str, path: Union[str, pathl def make_controls( - controls: Union[RAT.controls.Calculate, RAT.controls.Simplex, RAT.controls.DE, RAT.controls.NS, RAT.controls.Dream], + controls: Union[ + RATpy.controls.Calculate, RATpy.controls.Simplex, RATpy.controls.DE, RATpy.controls.NS, RATpy.controls.Dream + ], checks: Checks, ) -> Control: """Converts the controls object to the format required by the compiled RAT code. @@ -436,7 +440,7 @@ def make_controls( The controls object used in the compiled RAT code. """ - full_controls = RAT.controls.Controls(**controls.model_dump()) + full_controls = RATpy.controls.Controls(**controls.model_dump()) cpp_controls = Control() cpp_controls.procedure = full_controls.procedure diff --git a/RAT/models.py b/RATpy/models.py similarity index 99% rename from RAT/models.py rename to RATpy/models.py index 2ec9aa21..e18ab992 100644 --- a/RAT/models.py +++ b/RATpy/models.py @@ -6,7 +6,7 @@ import numpy as np from pydantic import BaseModel, Field, ValidationInfo, field_validator, model_validator -from RAT.utils.enums import BackgroundActions, Hydration, Languages, Priors, TypeOptions +from RATpy.utils.enums import BackgroundActions, Hydration, Languages, Priors, TypeOptions try: from enum import StrEnum diff --git a/RAT/outputs.py b/RATpy/outputs.py similarity index 97% rename from RAT/outputs.py rename to RATpy/outputs.py index 6ed51bc2..fc41ae16 100644 --- a/RAT/outputs.py +++ b/RATpy/outputs.py @@ -5,8 +5,8 @@ import numpy as np -import RAT.rat_core -from RAT.utils.enums import Procedures +import RATpy.rat_core +from RATpy.utils.enums import Procedures @dataclass @@ -110,8 +110,8 @@ class BayesResults(Results): def make_results( procedure: Procedures, - output_results: RAT.rat_core.OutputResult, - bayes_results: Optional[RAT.rat_core.BayesResults] = None, + output_results: RATpy.rat_core.OutputResult, + bayes_results: Optional[RATpy.rat_core.BayesResults] = None, ) -> Union[Results, BayesResults]: """Initialise a python Results or BayesResults object using the outputs from a RAT calculation.""" calculation_results = CalculationResults( diff --git a/RAT/project.py b/RATpy/project.py similarity index 90% rename from RAT/project.py rename to RATpy/project.py index 46b2b224..9911415d 100644 --- a/RAT/project.py +++ b/RATpy/project.py @@ -9,10 +9,10 @@ import numpy as np from pydantic import BaseModel, ValidationError, ValidationInfo, field_validator, model_validator -import RAT.models -from RAT.classlist import ClassList -from RAT.utils.custom_errors import custom_pydantic_validation_error -from RAT.utils.enums import Calculations, Geometries, LayerModels, Priors, TypeOptions +import RATpy.models +from RATpy.classlist import ClassList +from RATpy.utils.custom_errors import custom_pydantic_validation_error +from RATpy.utils.enums import Calculations, Geometries, LayerModels, Priors, TypeOptions # Map project fields to pydantic models model_in_classlist = { @@ -109,7 +109,7 @@ class Project(BaseModel, validate_assignment=True, extra="forbid", arbitrary_typ parameters: ClassList = ClassList() bulk_in: ClassList = ClassList( - RAT.models.Parameter( + RATpy.models.Parameter( name="SLD Air", min=0.0, value=0.0, @@ -122,7 +122,7 @@ class Project(BaseModel, validate_assignment=True, extra="forbid", arbitrary_typ ) bulk_out: ClassList = ClassList( - RAT.models.Parameter( + RATpy.models.Parameter( name="SLD D2O", min=6.2e-6, value=6.35e-6, @@ -135,7 +135,7 @@ class Project(BaseModel, validate_assignment=True, extra="forbid", arbitrary_typ ) scalefactors: ClassList = ClassList( - RAT.models.Parameter( + RATpy.models.Parameter( name="Scalefactor 1", min=0.02, value=0.23, @@ -148,7 +148,7 @@ class Project(BaseModel, validate_assignment=True, extra="forbid", arbitrary_typ ) domain_ratios: ClassList = ClassList( - RAT.models.Parameter( + RATpy.models.Parameter( name="Domain Ratio 1", min=0.4, value=0.5, @@ -161,7 +161,7 @@ class Project(BaseModel, validate_assignment=True, extra="forbid", arbitrary_typ ) background_parameters: ClassList = ClassList( - RAT.models.Parameter( + RATpy.models.Parameter( name="Background Param 1", min=1e-7, value=1e-6, @@ -174,11 +174,11 @@ class Project(BaseModel, validate_assignment=True, extra="forbid", arbitrary_typ ) backgrounds: ClassList = ClassList( - RAT.models.Background(name="Background 1", type=TypeOptions.Constant, value_1="Background Param 1"), + RATpy.models.Background(name="Background 1", type=TypeOptions.Constant, value_1="Background Param 1"), ) resolution_parameters: ClassList = ClassList( - RAT.models.Parameter( + RATpy.models.Parameter( name="Resolution Param 1", min=0.01, value=0.03, @@ -191,7 +191,7 @@ class Project(BaseModel, validate_assignment=True, extra="forbid", arbitrary_typ ) resolutions: ClassList = ClassList( - RAT.models.Resolution(name="Resolution 1", type=TypeOptions.Constant, value_1="Resolution Param 1"), + RATpy.models.Resolution(name="Resolution 1", type=TypeOptions.Constant, value_1="Resolution Param 1"), ) custom_files: ClassList = ClassList() @@ -229,7 +229,7 @@ def check_class(cls, value: ClassList, info: ValidationInfo) -> ClassList: if info.field_name == "contrasts" and info.data["calculation"] == Calculations.Domains: model_name = "ContrastWithRatio" - model = getattr(RAT.models, model_name) + model = getattr(RATpy.models, model_name) if not all(isinstance(element, model) for element in value): raise ValueError(f'"{info.field_name}" ClassList contains objects other than "{model_name}"') return value @@ -243,32 +243,32 @@ def model_post_init(self, __context: Any) -> None: layer_field = self.layers if not hasattr(layer_field, "_class_handle"): if self.absorption: - layer_field._class_handle = RAT.models.AbsorptionLayer + layer_field._class_handle = RATpy.models.AbsorptionLayer else: - layer_field._class_handle = RAT.models.Layer + layer_field._class_handle = RATpy.models.Layer contrast_field = self.contrasts if not hasattr(contrast_field, "_class_handle"): if self.calculation == Calculations.Domains: - contrast_field._class_handle = RAT.models.ContrastWithRatio + contrast_field._class_handle = RATpy.models.ContrastWithRatio else: - contrast_field._class_handle = RAT.models.Contrast + contrast_field._class_handle = RATpy.models.Contrast for field_name, model in model_in_classlist.items(): field = getattr(self, field_name) if not hasattr(field, "_class_handle"): - field._class_handle = getattr(RAT.models, model) + field._class_handle = getattr(RATpy.models, model) if "Substrate Roughness" not in self.parameters.get_names(): self.parameters.insert( 0, - RAT.models.ProtectedParameter( + RATpy.models.ProtectedParameter( name="Substrate Roughness", min=1.0, value=3.0, max=5.0, fit=True, - prior_type=RAT.models.Priors.Uniform, + prior_type=RATpy.models.Priors.Uniform, mu=0.0, sigma=np.inf, ), @@ -277,10 +277,10 @@ def model_post_init(self, __context: Any) -> None: # If substrate roughness is included as a standard parameter replace it with a protected parameter substrate_roughness_values = self.parameters[self.parameters.index("Substrate Roughness")].model_dump() self.parameters.remove("Substrate Roughness") - self.parameters.insert(0, RAT.models.ProtectedParameter(**substrate_roughness_values)) + self.parameters.insert(0, RATpy.models.ProtectedParameter(**substrate_roughness_values)) if "Simulation" not in self.data.get_names(): - self.data.insert(0, RAT.models.Data(name="Simulation", simulation_range=[0.005, 0.7])) + self.data.insert(0, RATpy.models.Data(name="Simulation", simulation_range=[0.005, 0.7])) self._all_names = self.get_all_names() self._contrast_model_field = self.get_contrast_model_field() @@ -336,28 +336,28 @@ def set_calculation(self) -> "Project": handle = self.contrasts._class_handle.__name__ if self.calculation == Calculations.Domains and handle == "Contrast": for contrast in self.contrasts: - contrast_list.append(RAT.models.ContrastWithRatio(**contrast.model_dump())) + contrast_list.append(RATpy.models.ContrastWithRatio(**contrast.model_dump())) self.contrasts.data = contrast_list self.domain_ratios.data = [ - RAT.models.Parameter( + RATpy.models.Parameter( name="Domain Ratio 1", min=0.4, value=0.5, max=0.6, fit=False, - prior_type=RAT.models.Priors.Uniform, + prior_type=RATpy.models.Priors.Uniform, mu=0.0, sigma=np.inf, ), ] - self.contrasts._class_handle = RAT.models.ContrastWithRatio + self.contrasts._class_handle = RATpy.models.ContrastWithRatio elif self.calculation != Calculations.Domains and handle == "ContrastWithRatio": for contrast in self.contrasts: contrast_params = contrast.model_dump() del contrast_params["domain_ratio"] - contrast_list.append(RAT.models.Contrast(**contrast_params)) + contrast_list.append(RATpy.models.Contrast(**contrast_params)) self.contrasts.data = contrast_list - self.contrasts._class_handle = RAT.models.Contrast + self.contrasts._class_handle = RATpy.models.Contrast return self @model_validator(mode="after") @@ -400,16 +400,16 @@ def set_absorption(self) -> "Project": handle = self.layers._class_handle.__name__ if self.absorption and handle == "Layer": for layer in self.layers: - layer_list.append(RAT.models.AbsorptionLayer(**layer.model_dump())) + layer_list.append(RATpy.models.AbsorptionLayer(**layer.model_dump())) self.layers.data = layer_list - self.layers._class_handle = RAT.models.AbsorptionLayer + self.layers._class_handle = RATpy.models.AbsorptionLayer elif not self.absorption and handle == "AbsorptionLayer": for layer in self.layers: layer_params = layer.model_dump() del layer_params["SLD_imaginary"] - layer_list.append(RAT.models.Layer(**layer_params)) + layer_list.append(RATpy.models.Layer(**layer_params)) self.layers.data = layer_list - self.layers._class_handle = RAT.models.Layer + self.layers._class_handle = RATpy.models.Layer return self @model_validator(mode="after") @@ -463,7 +463,7 @@ def check_protected_parameters(self) -> "Project": """Protected parameters should not be deleted. If this is attempted, raise an error.""" for class_list in parameter_class_lists: protected_parameters = [ - param.name for param in getattr(self, class_list) if isinstance(param, RAT.models.ProtectedParameter) + param.name for param in getattr(self, class_list) if isinstance(param, RATpy.models.ProtectedParameter) ] # All previously existing protected parameters should be present in new list if not all(element in protected_parameters for element in self._protected_parameters[class_list]): @@ -493,7 +493,7 @@ def get_all_protected_parameters(self): """Record the protected parameters defined in the project.""" return { class_list: [ - param.name for param in getattr(self, class_list) if isinstance(param, RAT.models.ProtectedParameter) + param.name for param in getattr(self, class_list) if isinstance(param, RATpy.models.ProtectedParameter) ] for class_list in parameter_class_lists } @@ -605,17 +605,17 @@ def write_script(self, obj_name: str = "problem", script: str = "project_script. ) # Need imports - f.write("import RAT\nfrom RAT.models import *\nfrom numpy import array, inf\n\n") + f.write("import RATpy\nfrom RATpy.models import *\nfrom numpy import array, inf\n\n") f.write( - f"{obj_name} = RAT.Project(\n{indent}name='{self.name}', calculation='{self.calculation}'," + f"{obj_name} = RATpy.Project(\n{indent}name='{self.name}', calculation='{self.calculation}'," f" model='{self.model}', geometry='{self.geometry}', absorption={self.absorption},\n", ) for class_list in class_lists: contents = getattr(self, class_list).data if contents: - f.write(f"{indent}{class_list}=RAT.ClassList({contents}),\n") + f.write(f"{indent}{class_list}=RATpy.ClassList({contents}),\n") f.write(f"{indent})\n") def _classlist_wrapper(self, class_list: ClassList, func: Callable): diff --git a/RAT/run.py b/RATpy/run.py similarity index 79% rename from RAT/run.py rename to RATpy/run.py index f654420e..aa706e1d 100644 --- a/RAT/run.py +++ b/RATpy/run.py @@ -1,6 +1,6 @@ -import RAT.rat_core -from RAT.inputs import make_input -from RAT.outputs import make_results +import RATpy.rat_core +from RATpy.inputs import make_input +from RATpy.outputs import make_results def run(project, controls): @@ -17,7 +17,7 @@ def run(project, controls): problem_definition, cells, limits, priors, cpp_controls = make_input(project, controls) - problem_definition, output_results, bayes_results = RAT.rat_core.RATMain( + problem_definition, output_results, bayes_results = RATpy.rat_core.RATMain( problem_definition, cells, limits, @@ -28,7 +28,7 @@ def run(project, controls): results = make_results(controls.procedure, output_results, bayes_results) # Update parameter values in project - for class_list in RAT.project.parameter_class_lists: + for class_list in RATpy.project.parameter_class_lists: for index, value in enumerate(getattr(problem_definition, parameter_field[class_list])): getattr(project, class_list)[index].value = value diff --git a/RAT/utils/__init__.py b/RATpy/utils/__init__.py similarity index 100% rename from RAT/utils/__init__.py rename to RATpy/utils/__init__.py diff --git a/RAT/utils/custom_errors.py b/RATpy/utils/custom_errors.py similarity index 100% rename from RAT/utils/custom_errors.py rename to RATpy/utils/custom_errors.py diff --git a/RAT/utils/enums.py b/RATpy/utils/enums.py similarity index 100% rename from RAT/utils/enums.py rename to RATpy/utils/enums.py diff --git a/RAT/utils/plotting.py b/RATpy/utils/plotting.py similarity index 95% rename from RAT/utils/plotting.py rename to RATpy/utils/plotting.py index 99748f27..3cd76fd3 100644 --- a/RAT/utils/plotting.py +++ b/RATpy/utils/plotting.py @@ -6,10 +6,10 @@ import numpy as np from matplotlib.axes._axes import Axes -import RAT -import RAT.inputs -import RAT.outputs -from RAT.rat_core import PlotEventData, makeSLDProfileXY +import RATpy +import RATpy.inputs +import RATpy.outputs +from RATpy.rat_core import PlotEventData, makeSLDProfileXY class Figure: @@ -177,8 +177,8 @@ def plot_ref_sld_helper(data: PlotEventData, fig: Optional[Figure] = None, delay def plot_ref_sld( - project: RAT.Project, - results: Union[RAT.outputs.Results, RAT.outputs.BayesResults], + project: RATpy.Project, + results: Union[RATpy.outputs.Results, RATpy.outputs.BayesResults], block: bool = False, ): """Plots the reflectivity and SLD profiles. @@ -200,9 +200,9 @@ def plot_ref_sld( data.shiftedData = results.shiftedData data.sldProfiles = results.sldProfiles data.resampledLayers = results.resampledLayers - data.dataPresent = RAT.inputs.make_data_present(project) + data.dataPresent = RATpy.inputs.make_data_present(project) data.subRoughs = results.contrastParams.subRoughs - data.resample = RAT.inputs.make_resample(project) + data.resample = RATpy.inputs.make_resample(project) figure = Figure(1, 2) diff --git a/RAT/wrappers.py b/RATpy/wrappers.py similarity index 96% rename from RAT/wrappers.py rename to RATpy/wrappers.py index 3a7b72e9..1b90d2ec 100644 --- a/RAT/wrappers.py +++ b/RATpy/wrappers.py @@ -4,7 +4,7 @@ import numpy as np from numpy.typing import ArrayLike -import RAT.rat_core +import RATpy.rat_core class MatlabWrapper: @@ -78,7 +78,7 @@ class DylibWrapper: """ def __init__(self, filename, function_name) -> None: - self.engine = RAT.rat_core.DylibEngine(filename, function_name) + self.engine = RATpy.rat_core.DylibEngine(filename, function_name) def getHandle(self) -> Callable[[ArrayLike, ArrayLike, ArrayLike, int, int], Tuple[ArrayLike, float]]: """Returns a wrapper for the custom dynamic library function diff --git a/setup.py b/setup.py index 3eedf681..9c1de762 100644 --- a/setup.py +++ b/setup.py @@ -9,14 +9,17 @@ from setuptools.command.build_ext import build_ext __version__ = "0.0.0" +PACKAGE_NAME = "RATpy" +with open("README.md") as f: + LONG_DESCRIPTION = f.read() libevent = ("eventManager", {"sources": ["cpp/RAT/events/eventManager.cpp"], "include_dirs": ["cpp/RAT/events/"]}) ext_modules = [ Extension( - "RAT.rat_core", + "RATpy.rat_core", sources=["cpp/rat.cpp", *glob("cpp/RAT/*.c*")], include_dirs=[ # Path to pybind11 headers @@ -91,15 +94,15 @@ def build_extensions(self): def run(self): super().run() build_py = self.get_finalized_command("build_py") - package_dir = f"{build_py.build_lib}/RAT/" + package_dir = f"{build_py.build_lib}/{PACKAGE_NAME}/" for p in Path(package_dir).glob("**/*"): if p.suffix in {".exp", ".a", ".lib"}: p.unlink() if self.inplace: obj_name = get_shared_object_name(libevent[0]) - src = f"{build_py.build_lib}/RAT/{obj_name}" - dest = f'{build_py.get_package_dir("RAT")}/{obj_name}' + src = f"{build_py.build_lib}/{PACKAGE_NAME}/{obj_name}" + dest = f"{build_py.get_package_dir(PACKAGE_NAME)}/{obj_name}" build_py.copy_file(src, dest) @@ -107,7 +110,7 @@ class BuildClib(build_clib): def initialize_options(self): super().initialize_options() build_py = self.get_finalized_command("build_py") - self.build_clib = f"{build_py.build_lib}/RAT" + self.build_clib = f"{build_py.build_lib}/{PACKAGE_NAME}" def build_libraries(self, libraries): # bug in distutils: flag not valid for c++ @@ -147,17 +150,17 @@ def build_libraries(self, libraries): setup( - name="RAT", + name=PACKAGE_NAME, version=__version__, author="", author_email="", url="https://github.com/RascalSoftware/python-RAT", description="Python extension for the Reflectivity Analysis Toolbox (RAT)", - long_description=open("README.md").read(), # noqa: SIM115 + long_description=LONG_DESCRIPTION, long_description_content_type="text/markdown", packages=find_packages(), include_package_data=True, - package_data={"": [get_shared_object_name(libevent[0])], "RAT.examples": ["data/*.dat"]}, + package_data={"": [get_shared_object_name(libevent[0])], "RATpy.examples": ["data/*.dat"]}, cmdclass={"build_clib": BuildClib, "build_ext": BuildExt}, libraries=[libevent], ext_modules=ext_modules, diff --git a/tests/conftest.py b/tests/conftest.py index 60dad927..25d36853 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,15 +1,15 @@ import numpy as np import pytest -import RAT -import RAT.outputs -import RAT.rat_core +import RATpy +import RATpy.outputs +import RATpy.rat_core @pytest.fixture def reflectivity_calculation_output_results(): """The C++ results object for a reflectivity calculation of the project set out in "DSPC_standard_layers.py".""" - results = RAT.rat_core.OutputResult() + results = RATpy.rat_core.OutputResult() results.reflectivity = [ np.array( [ @@ -259,10 +259,10 @@ def reflectivity_calculation_output_results(): ], ] results.resampledLayers = [[np.array([[0.0, 0.0, 0.0]])], [np.array([[0.0, 0.0, 0.0]])]] - results.calculationResults = RAT.rat_core.Calculation() + results.calculationResults = RATpy.rat_core.Calculation() results.calculationResults.chiValues = np.array([202.83057377, 1641.4024969]) results.calculationResults.sumChi = 1844.2330706690975 - results.contrastParams = RAT.rat_core.ContrastParams() + results.contrastParams = RATpy.rat_core.ContrastParams() results.contrastParams.backgroundParams = np.array([2.23e-06, 3.38e-06]) results.contrastParams.scalefactors = np.array([0.1, 0.15]) results.contrastParams.bulkIn = np.array([2.073e-06, 2.073e-06]) @@ -319,7 +319,7 @@ def reflectivity_calculation_output_results(): @pytest.fixture def reflectivity_calculation_results(): """The python results object for a reflectivity calculation of the project set out in "DSPC_standard_layers.py".""" - return RAT.outputs.Results( + return RATpy.outputs.Results( reflectivity=[ np.array( [ @@ -569,11 +569,11 @@ def reflectivity_calculation_results(): ], ], resampledLayers=[[np.array([[0.0, 0.0, 0.0]])], [np.array([[0.0, 0.0, 0.0]])]], - calculationResults=RAT.outputs.CalculationResults( + calculationResults=RATpy.outputs.CalculationResults( chiValues=np.array([202.83057377, 1641.4024969]), sumChi=1844.2330706690975, ), - contrastParams=RAT.outputs.ContrastParams( + contrastParams=RATpy.outputs.ContrastParams( backgroundParams=np.array([2.23e-06, 3.38e-06]), scalefactors=np.array([0.1, 0.15]), bulkIn=np.array([2.073e-06, 2.073e-06]), @@ -634,7 +634,7 @@ def dream_output_results(): This optimisation used the parameters: nSamples=1, nChains=1. However, the calculationResults, contrastParams, and fitParams are taken from an optimisation with the parameters: nSamples=50000, nChains=10. """ - results = RAT.rat_core.OutputResult() + results = RATpy.rat_core.OutputResult() results.reflectivity = [ np.array( [ @@ -892,10 +892,10 @@ def dream_output_results(): ], ] results.resampledLayers = [[np.array([[0.0, 0.0, 0.0]])], [np.array([[0.0, 0.0, 0.0]])]] - results.calculationResults = RAT.rat_core.Calculation() + results.calculationResults = RATpy.rat_core.Calculation() results.calculationResults.chiValues = (np.array([4.6077885, 7.00028098]),) results.calculationResults.sumChi = 11.608069475997699 - results.contrastParams = RAT.rat_core.ContrastParams() + results.contrastParams = RATpy.rat_core.ContrastParams() results.contrastParams.backgroundParams = np.array([2.37113128e-06, 1.99006694e-06]) results.contrastParams.scalefactors = np.array([0.1, 0.15]) results.contrastParams.bulkIn = np.array([2.073e-06, 2.073e-06]) @@ -955,8 +955,8 @@ def dream_bayes(): This optimisation used the parameters: nSamples=1, nChains=1. """ - bayes = RAT.rat_core.BayesResults() - bayes.predictionIntervals = RAT.rat_core.PredictionIntervals() + bayes = RATpy.rat_core.BayesResults() + bayes.predictionIntervals = RATpy.rat_core.PredictionIntervals() bayes.predictionIntervals.reflectivity = [ np.array( [ @@ -2437,7 +2437,7 @@ def dream_bayes(): 1.46133559e16, ], ) - bayes.confidenceIntervals = RAT.rat_core.ConfidenceIntervals() + bayes.confidenceIntervals = RATpy.rat_core.ConfidenceIntervals() bayes.confidenceIntervals.percentile65 = np.array( [ [ @@ -2550,7 +2550,7 @@ def dream_bayes(): ], ], ) - bayes.dreamParams = RAT.rat_core.DreamParams() + bayes.dreamParams = RATpy.rat_core.DreamParams() bayes.dreamParams.nParams = 18.0 bayes.dreamParams.nChains = 1.0 bayes.dreamParams.nGenerations = 1.0 @@ -2570,7 +2570,7 @@ def dream_bayes(): bayes.dreamParams.IO = 0 bayes.dreamParams.storeOutput = 0 bayes.dreamParams.R = np.array([[0.0]]) - bayes.dreamOutput = RAT.rat_core.DreamOutput() + bayes.dreamOutput = RATpy.rat_core.DreamOutput() bayes.dreamOutput.allChains = np.array( [ [ @@ -2628,7 +2628,7 @@ def dream_bayes(): ], ) bayes.dreamOutput.CR = np.array([[1.00000000, 0.33333333, 0.33333333, 0.33333333]]) - bayes.nestedSamplerOutput = RAT.rat_core.NestedSamplerOutput() + bayes.nestedSamplerOutput = RATpy.rat_core.NestedSamplerOutput() bayes.nestedSamplerOutput.logZ = 0.0 bayes.nestedSamplerOutput.nestSamples = np.array([[0.0, 0.0]]) bayes.nestedSamplerOutput.postSamples = np.array([[0.0, 0.0]]) @@ -2687,7 +2687,7 @@ def dream_results(): This optimisation used the parameters: nSamples=1, nChains=1. However, the calculationResults, contrastParams, and fitParams are taken from an optimisation with the parameters: nSamples=50000, nChains=10. """ - return RAT.outputs.BayesResults( + return RATpy.outputs.BayesResults( reflectivity=[ np.array( [ @@ -2945,11 +2945,11 @@ def dream_results(): ], ], resampledLayers=[[np.array([[0.0, 0.0, 0.0]])], [np.array([[0.0, 0.0, 0.0]])]], - calculationResults=RAT.outputs.CalculationResults( + calculationResults=RATpy.outputs.CalculationResults( chiValues=np.array([4.6077885, 7.00028098]), sumChi=11.608069475997699, ), - contrastParams=RAT.outputs.ContrastParams( + contrastParams=RATpy.outputs.ContrastParams( backgroundParams=np.array([2.37113128e-06, 1.99006694e-06]), scalefactors=np.array([0.1, 0.15]), bulkIn=np.array([2.073e-06, 2.073e-06]), @@ -3000,7 +3000,7 @@ def dream_results(): "D2O", "SMW", ], - predictionIntervals=RAT.outputs.PredictionIntervals( + predictionIntervals=RATpy.outputs.PredictionIntervals( reflectivity=[ np.array( [ @@ -4482,7 +4482,7 @@ def dream_results(): ], ), ), - confidenceIntervals=RAT.outputs.ConfidenceIntervals( + confidenceIntervals=RATpy.outputs.ConfidenceIntervals( percentile65=np.array( [ [ @@ -4596,7 +4596,7 @@ def dream_results(): ], ), ), - dreamParams=RAT.outputs.DreamParams( + dreamParams=RATpy.outputs.DreamParams( nParams=18.0, nChains=1.0, nGenerations=1.0, @@ -4617,7 +4617,7 @@ def dream_results(): storeOutput=False, R=np.array([[0.0]]), ), - dreamOutput=RAT.outputs.DreamOutput( + dreamOutput=RATpy.outputs.DreamOutput( allChains=np.array( [ [ @@ -4676,7 +4676,7 @@ def dream_results(): ), CR=np.array([[1.0, 0.33333333, 0.33333333, 0.33333333]]), ), - nestedSamplerOutput=RAT.outputs.NestedSamplerOutput( + nestedSamplerOutput=RATpy.outputs.NestedSamplerOutput( logZ=0.0, nestSamples=np.array([[0.0, 0.0]]), postSamples=np.array([[0.0, 0.0]]), diff --git a/tests/test_classlist.py b/tests/test_classlist.py index 4839fb4a..7ebe98d5 100644 --- a/tests/test_classlist.py +++ b/tests/test_classlist.py @@ -7,7 +7,7 @@ import pytest -from RAT.classlist import ClassList +from RATpy.classlist import ClassList from tests.utils import InputAttributes, SubInputAttributes diff --git a/tests/test_controls.py b/tests/test_controls.py index be37401d..0f806374 100644 --- a/tests/test_controls.py +++ b/tests/test_controls.py @@ -5,8 +5,8 @@ import pydantic import pytest -from RAT.controls import DE, NS, Calculate, Dream, Simplex, set_controls -from RAT.utils.enums import BoundHandling, Display, Parallel, Procedures, Strategies +from RATpy.controls import DE, NS, Calculate, Dream, Simplex, set_controls +from RATpy.utils.enums import BoundHandling, Display, Parallel, Procedures, Strategies class TestCalculate: diff --git a/tests/test_custom_errors.py b/tests/test_custom_errors.py index a96cbf37..39f049ff 100644 --- a/tests/test_custom_errors.py +++ b/tests/test_custom_errors.py @@ -5,7 +5,7 @@ import pytest from pydantic import ValidationError, create_model -import RAT.utils.custom_errors +import RATpy.utils.custom_errors @pytest.fixture @@ -43,7 +43,7 @@ def test_custom_pydantic_validation_error( try: TestModel(int_field="string", str_field=5) except ValidationError as exc: - custom_error_list = RAT.utils.custom_errors.custom_pydantic_validation_error(exc.errors(), custom_errors) + custom_error_list = RATpy.utils.custom_errors.custom_pydantic_validation_error(exc.errors(), custom_errors) with pytest.raises(ValidationError, match=re.escape(expected_error_message)): raise ValidationError.from_exception_data("TestModel", custom_error_list) diff --git a/tests/test_events.py b/tests/test_events.py index 3f2ac881..5033a00b 100644 --- a/tests/test_events.py +++ b/tests/test_events.py @@ -2,60 +2,60 @@ import pytest -import RAT.events +import RATpy.events -@pytest.mark.skip() def test_event_register() -> None: first_callback = mock.Mock() second_callback = mock.Mock() with pytest.raises(ValueError): - RAT.events.register("Message", first_callback) + RATpy.events.register("Message", first_callback) - RAT.events.register(RAT.events.EventTypes.Message, first_callback) - result = RAT.events.get_event_callback(RAT.events.EventTypes.Message) + RATpy.events.register(RATpy.events.EventTypes.Message, first_callback) + result = RATpy.events.get_event_callback(RATpy.events.EventTypes.Message) assert result == [first_callback] - RAT.events.register(RAT.events.EventTypes.Plot, second_callback) - assert RAT.events.get_event_callback(RAT.events.EventTypes.Plot) == [second_callback] + RATpy.events.register(RATpy.events.EventTypes.Plot, second_callback) + assert RATpy.events.get_event_callback(RATpy.events.EventTypes.Plot) == [second_callback] - RAT.events.register(RAT.events.EventTypes.Message, second_callback) + RATpy.events.register(RATpy.events.EventTypes.Message, second_callback) # the list is not guaranteed to be in the same order as inputted hence the set - assert set(RAT.events.get_event_callback(RAT.events.EventTypes.Message)) == set([first_callback, second_callback]) + assert set(RATpy.events.get_event_callback(RATpy.events.EventTypes.Message)) == set( + [first_callback, second_callback] + ) - RAT.events.clear() - assert RAT.events.get_event_callback(RAT.events.EventTypes.Plot) == [] - assert RAT.events.get_event_callback(RAT.events.EventTypes.Message) == [] + RATpy.events.clear() + assert RATpy.events.get_event_callback(RATpy.events.EventTypes.Plot) == [] + assert RATpy.events.get_event_callback(RATpy.events.EventTypes.Message) == [] -@pytest.mark.skip() def test_event_notify() -> None: first_callback = mock.Mock() second_callback = mock.Mock() third_callback = mock.Mock() - RAT.events.register(RAT.events.EventTypes.Message, first_callback) - RAT.events.register(RAT.events.EventTypes.Plot, second_callback) - RAT.events.register(RAT.events.EventTypes.Progress, third_callback) + RATpy.events.register(RATpy.events.EventTypes.Message, first_callback) + RATpy.events.register(RATpy.events.EventTypes.Plot, second_callback) + RATpy.events.register(RATpy.events.EventTypes.Progress, third_callback) - RAT.events.notify(RAT.events.EventTypes.Message, "Hello World") + RATpy.events.notify(RATpy.events.EventTypes.Message, "Hello World") first_callback.assert_called_once_with("Hello World") second_callback.assert_not_called() - data = RAT.events.PlotEventData() - RAT.events.notify(RAT.events.EventTypes.Plot, data) + data = RATpy.events.PlotEventData() + RATpy.events.notify(RATpy.events.EventTypes.Plot, data) first_callback.assert_called_once() second_callback.assert_called_once_with(data) - data = RAT.events.ProgressEventData() - RAT.events.notify(RAT.events.EventTypes.Progress, data) + data = RATpy.events.ProgressEventData() + RATpy.events.notify(RATpy.events.EventTypes.Progress, data) first_callback.assert_called_once() second_callback.assert_called_once() third_callback.assert_called_once_with(data) - RAT.events.clear() - RAT.events.notify(RAT.events.EventTypes.Message, "Hello World") - RAT.events.notify(RAT.events.EventTypes.Plot, data) + RATpy.events.clear() + RATpy.events.notify(RATpy.events.EventTypes.Message, "Hello World") + RATpy.events.notify(RATpy.events.EventTypes.Plot, data) assert first_callback.call_count == 1 assert second_callback.call_count == 1 assert third_callback.call_count == 1 diff --git a/tests/test_inputs.py b/tests/test_inputs.py index 286a84f3..100af9a0 100644 --- a/tests/test_inputs.py +++ b/tests/test_inputs.py @@ -7,11 +7,11 @@ import numpy as np import pytest -import RAT -import RAT.wrappers -from RAT.inputs import check_indices, make_cells, make_controls, make_input, make_problem -from RAT.rat_core import Cells, Checks, Control, Limits, Priors, ProblemDefinition -from RAT.utils.enums import ( +import RATpy +import RATpy.wrappers +from RATpy.inputs import check_indices, make_cells, make_controls, make_input, make_problem +from RATpy.rat_core import Cells, Checks, Control, Limits, Priors, ProblemDefinition +from RATpy.utils.enums import ( BoundHandling, Calculations, Display, @@ -27,8 +27,8 @@ @pytest.fixture def standard_layers_project(): """Add parameters to the default project for a non polarised calculation.""" - test_project = RAT.Project( - data=RAT.ClassList([RAT.models.Data(name="Test Data", data=np.array([[1.0, 1.0, 1.0]]))]), + test_project = RATpy.Project( + data=RATpy.ClassList([RATpy.models.Data(name="Test Data", data=np.array([[1.0, 1.0, 1.0]]))]), ) test_project.parameters.append(name="Test Thickness") test_project.parameters.append(name="Test SLD") @@ -61,9 +61,9 @@ def standard_layers_project(): @pytest.fixture def domains_project(): """Add parameters to the default project for a domains calculation.""" - test_project = RAT.Project( + test_project = RATpy.Project( calculation=Calculations.Domains, - data=RAT.ClassList([RAT.models.Data(name="Test Data", data=np.array([[1.0, 1.0, 1.0]]))]), + data=RATpy.ClassList([RATpy.models.Data(name="Test Data", data=np.array([[1.0, 1.0, 1.0]]))]), ) test_project.parameters.append(name="Test Thickness") test_project.parameters.append(name="Test SLD") @@ -94,7 +94,7 @@ def domains_project(): @pytest.fixture def custom_xy_project(): """Add parameters to the default project for a non polarised calculation and use the custom xy model.""" - test_project = RAT.Project(model=LayerModels.CustomXY) + test_project = RATpy.Project(model=LayerModels.CustomXY) test_project.parameters.append(name="Test Thickness") test_project.parameters.append(name="Test SLD") test_project.parameters.append(name="Test Roughness") @@ -378,17 +378,17 @@ def non_polarised_priors(): """The expected priors object from "standard_layers_project" and "custom_xy_project".""" priors = Priors() priors.param = [ - ["Substrate Roughness", RAT.utils.enums.Priors.Uniform, 0.0, np.inf], - ["Test Thickness", RAT.utils.enums.Priors.Uniform, 0.0, np.inf], - ["Test SLD", RAT.utils.enums.Priors.Uniform, 0.0, np.inf], - ["Test Roughness", RAT.utils.enums.Priors.Uniform, 0.0, np.inf], + ["Substrate Roughness", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf], + ["Test Thickness", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf], + ["Test SLD", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf], + ["Test Roughness", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf], ] - priors.backgroundParam = [["Background Param 1", RAT.utils.enums.Priors.Uniform, 0.0, np.inf]] + priors.backgroundParam = [["Background Param 1", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf]] priors.qzshift = [] - priors.scalefactor = [["Scalefactor 1", RAT.utils.enums.Priors.Uniform, 0.0, np.inf]] - priors.bulkIn = [["SLD Air", RAT.utils.enums.Priors.Uniform, 0.0, np.inf]] - priors.bulkOut = [["SLD D2O", RAT.utils.enums.Priors.Uniform, 0.0, np.inf]] - priors.resolutionParam = [["Resolution Param 1", RAT.utils.enums.Priors.Uniform, 0.0, np.inf]] + priors.scalefactor = [["Scalefactor 1", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf]] + priors.bulkIn = [["SLD Air", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf]] + priors.bulkOut = [["SLD D2O", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf]] + priors.resolutionParam = [["Resolution Param 1", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf]] priors.domainRatio = [] priors.priorNames = [ "Substrate Roughness", @@ -421,18 +421,18 @@ def domains_priors(): """The expected priors object from "domains_project".""" priors = Priors() priors.param = [ - ["Substrate Roughness", RAT.utils.enums.Priors.Uniform, 0.0, np.inf], - ["Test Thickness", RAT.utils.enums.Priors.Uniform, 0.0, np.inf], - ["Test SLD", RAT.utils.enums.Priors.Uniform, 0.0, np.inf], - ["Test Roughness", RAT.utils.enums.Priors.Uniform, 0.0, np.inf], + ["Substrate Roughness", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf], + ["Test Thickness", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf], + ["Test SLD", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf], + ["Test Roughness", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf], ] - priors.backgroundParam = [["Background Param 1", RAT.utils.enums.Priors.Uniform, 0.0, np.inf]] + priors.backgroundParam = [["Background Param 1", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf]] priors.qzshift = [] - priors.scalefactor = [["Scalefactor 1", RAT.utils.enums.Priors.Uniform, 0.0, np.inf]] - priors.bulkIn = [["SLD Air", RAT.utils.enums.Priors.Uniform, 0.0, np.inf]] - priors.bulkOut = [["SLD D2O", RAT.utils.enums.Priors.Uniform, 0.0, np.inf]] - priors.resolutionParam = [["Resolution Param 1", RAT.utils.enums.Priors.Uniform, 0.0, np.inf]] - priors.domainRatio = [["Domain Ratio 1", RAT.utils.enums.Priors.Uniform, 0.0, np.inf]] + priors.scalefactor = [["Scalefactor 1", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf]] + priors.bulkIn = [["SLD Air", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf]] + priors.bulkOut = [["SLD D2O", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf]] + priors.resolutionParam = [["Resolution Param 1", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf]] + priors.domainRatio = [["Domain Ratio 1", RATpy.utils.enums.Priors.Uniform, 0.0, np.inf]] priors.priorNames = [ "Substrate Roughness", "Test Thickness", @@ -623,16 +623,16 @@ def test_make_input(test_project, test_problem, test_cells, test_limits, test_pr with mock.patch.dict( "sys.modules", {"matlab": mocked_matlab_module, "matlab.engine": mocked_matlab_module.engine}, - ), mock.patch.object(RAT.rat_core, "DylibEngine", mock.MagicMock()), mock.patch.object( - RAT.inputs, + ), mock.patch.object(RATpy.rat_core, "DylibEngine", mock.MagicMock()), mock.patch.object( + RATpy.inputs, "get_python_handle", mock.MagicMock(return_value=dummy_function), ), mock.patch.object( - RAT.wrappers.MatlabWrapper, + RATpy.wrappers.MatlabWrapper, "getHandle", mock.MagicMock(return_value=dummy_function), - ), mock.patch.object(RAT.wrappers.DylibWrapper, "getHandle", mock.MagicMock(return_value=dummy_function)): - problem, cells, limits, priors, controls = make_input(test_project, RAT.set_controls()) + ), mock.patch.object(RATpy.wrappers.DylibWrapper, "getHandle", mock.MagicMock(return_value=dummy_function)): + problem, cells, limits, priors, controls = make_input(test_project, RATpy.set_controls()) check_problem_equal(problem, test_problem) check_cells_equal(cells, test_cells) @@ -762,15 +762,15 @@ def test_make_cells(test_project, test_cells, request) -> None: with mock.patch.dict( "sys.modules", {"matlab": mocked_matlab_module, "matlab.engine": mocked_matlab_module.engine}, - ), mock.patch.object(RAT.rat_core, "DylibEngine", mock.MagicMock()), mock.patch.object( - RAT.inputs, + ), mock.patch.object(RATpy.rat_core, "DylibEngine", mock.MagicMock()), mock.patch.object( + RATpy.inputs, "get_python_handle", mock.MagicMock(return_value=dummy_function), ), mock.patch.object( - RAT.wrappers.MatlabWrapper, + RATpy.wrappers.MatlabWrapper, "getHandle", mock.MagicMock(return_value=dummy_function), - ), mock.patch.object(RAT.wrappers.DylibWrapper, "getHandle", mock.MagicMock(return_value=dummy_function)): + ), mock.patch.object(RATpy.wrappers.DylibWrapper, "getHandle", mock.MagicMock(return_value=dummy_function)): cells = make_cells(test_project) check_cells_equal(cells, test_cells) @@ -778,14 +778,14 @@ def test_make_cells(test_project, test_cells, request) -> None: def test_get_python_handle(): path = pathlib.Path(__file__).parent.resolve() - assert RAT.inputs.get_python_handle("utils.py", "dummy_function", path).__code__ == dummy_function.__code__ + assert RATpy.inputs.get_python_handle("utils.py", "dummy_function", path).__code__ == dummy_function.__code__ def test_make_controls(standard_layers_controls, test_checks) -> None: """The controls object should contain the full set of controls parameters, with the appropriate set defined by the input controls. """ - controls = make_controls(RAT.set_controls(), test_checks) + controls = make_controls(RATpy.set_controls(), test_checks) check_controls_equal(controls, standard_layers_controls) diff --git a/tests/test_models.py b/tests/test_models.py index 657868f8..00cc098f 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -7,20 +7,24 @@ import pydantic import pytest -import RAT.models +import RATpy.models @pytest.mark.parametrize( ["model", "model_name", "model_params"], [ - (RAT.models.Background, "Background", {}), - (RAT.models.Contrast, "Contrast", {}), - (RAT.models.CustomFile, "Custom File", {}), - (RAT.models.Data, "Data", {}), - (RAT.models.DomainContrast, "Domain Contrast", {}), - (RAT.models.Layer, "Layer", {"thickness": "Test Thickness", "SLD": "Test SLD", "roughness": "Test Roughness"}), - (RAT.models.Parameter, "Parameter", {}), - (RAT.models.Resolution, "Resolution", {}), + (RATpy.models.Background, "Background", {}), + (RATpy.models.Contrast, "Contrast", {}), + (RATpy.models.CustomFile, "Custom File", {}), + (RATpy.models.Data, "Data", {}), + (RATpy.models.DomainContrast, "Domain Contrast", {}), + ( + RATpy.models.Layer, + "Layer", + {"thickness": "Test Thickness", "SLD": "Test SLD", "roughness": "Test Roughness"}, + ), + (RATpy.models.Parameter, "Parameter", {}), + (RATpy.models.Resolution, "Resolution", {}), ], ) def test_default_names(model: Callable, model_name: str, model_params: dict) -> None: @@ -41,15 +45,15 @@ def test_default_names(model: Callable, model_name: str, model_params: dict) -> @pytest.mark.parametrize( ["model", "model_params"], [ - (RAT.models.Background, {}), - (RAT.models.Contrast, {}), - (RAT.models.ContrastWithRatio, {}), - (RAT.models.CustomFile, {}), - (RAT.models.Data, {}), - (RAT.models.DomainContrast, {}), - (RAT.models.Layer, {"thickness": "Test Thickness", "SLD": "Test SLD", "roughness": "Test Roughness"}), + (RATpy.models.Background, {}), + (RATpy.models.Contrast, {}), + (RATpy.models.ContrastWithRatio, {}), + (RATpy.models.CustomFile, {}), + (RATpy.models.Data, {}), + (RATpy.models.DomainContrast, {}), + (RATpy.models.Layer, {"thickness": "Test Thickness", "SLD": "Test SLD", "roughness": "Test Roughness"}), ( - RAT.models.AbsorptionLayer, + RATpy.models.AbsorptionLayer, { "thickness": "Test Thickness", "SLD_real": "Test SLD", @@ -57,8 +61,8 @@ def test_default_names(model: Callable, model_name: str, model_params: dict) -> "roughness": "Test Roughness", }, ), - (RAT.models.Parameter, {}), - (RAT.models.Resolution, {}), + (RATpy.models.Parameter, {}), + (RATpy.models.Resolution, {}), ], ) class TestModels: @@ -100,7 +104,7 @@ def test_data_eq() -> None: """If we use the Data.__eq__ method with an object that is not a pydantic BaseModel, we should return "NotImplemented". """ - assert RAT.models.Data().__eq__("data") == NotImplemented + assert RATpy.models.Data().__eq__("data") == NotImplemented @pytest.mark.parametrize( @@ -113,7 +117,7 @@ def test_data_dimension(input_data: np.ndarray[float]) -> None: """The "data" field of the "Data" model should be a two-dimensional numpy array with at least three values in the second dimension. """ - test_data = RAT.models.Data(data=input_data) + test_data = RATpy.models.Data(data=input_data) assert (test_data.data == input_data).all() @@ -132,7 +136,7 @@ def test_data_too_few_dimensions(input_data: np.ndarray[float]) -> None: pydantic.ValidationError, match='1 validation error for Data\ndata\n Value error, "data" must ' "have at least two dimensions", ): - RAT.models.Data(data=input_data) + RATpy.models.Data(data=input_data) @pytest.mark.parametrize( @@ -151,7 +155,7 @@ def test_data_too_few_values(input_data: np.ndarray[float]) -> None: pydantic.ValidationError, match='1 validation error for Data\ndata\n Value error, "data" must ' "have at least three columns", ): - RAT.models.Data(data=input_data) + RATpy.models.Data(data=input_data) @pytest.mark.parametrize( @@ -162,8 +166,8 @@ def test_data_too_few_values(input_data: np.ndarray[float]) -> None: ) def test_data_ranges(input_range: list[float]) -> None: """The "data_range" and "simulation_range" fields of the "Data" model should contain exactly two values.""" - assert RAT.models.Data(data_range=input_range).data_range == input_range - assert RAT.models.Data(simulation_range=input_range).simulation_range == input_range + assert RATpy.models.Data(data_range=input_range).data_range == input_range + assert RATpy.models.Data(simulation_range=input_range).simulation_range == input_range @pytest.mark.parametrize( @@ -184,7 +188,7 @@ def test_two_values_in_data_range(input_range: list[float]) -> None: f'at {"least" if len(input_range) < 2 else "most"} 2 items ' f'after validation, not {len(input_range)}', ): - RAT.models.Data(data_range=input_range) + RATpy.models.Data(data_range=input_range) @pytest.mark.parametrize( @@ -205,7 +209,7 @@ def test_two_values_in_simulation_range(input_range: list[float]) -> None: f'have at {"least" if len(input_range) < 2 else "most"} 2 items ' f'after validation, not {len(input_range)}', ): - RAT.models.Data(simulation_range=input_range) + RATpy.models.Data(simulation_range=input_range) @pytest.mark.parametrize( @@ -224,14 +228,14 @@ def test_min_max_in_range(field: str) -> None: match=f"1 validation error for Data\n{field}\n Value error, {field} " f'"min" value is greater than the "max" value', ): - RAT.models.Data(**{field: [1.0, 0.0]}) + RATpy.models.Data(**{field: [1.0, 0.0]}) def test_default_ranges() -> None: """If "data" is specified but either the "data_range" or "simulation_range" fields are not, we set the ranges to the minimum and maximum values of the first column of the data. """ - test_data = RAT.models.Data(data=np.array([[1.0, 0.0, 0.0], [3.0, 0.0, 0.0]])) + test_data = RATpy.models.Data(data=np.array([[1.0, 0.0, 0.0], [3.0, 0.0, 0.0]])) assert test_data.data_range == [1.0, 3.0] assert test_data.simulation_range == [1.0, 3.0] @@ -256,7 +260,7 @@ def test_data_range(test_range) -> None: f"the min/max values of the data: [1.0, 3.0]", ), ): - RAT.models.Data(data=np.array([[1.0, 0.0, 0.0], [3.0, 0.0, 0.0]]), data_range=test_range) + RATpy.models.Data(data=np.array([[1.0, 0.0, 0.0], [3.0, 0.0, 0.0]]), data_range=test_range) @pytest.mark.parametrize( @@ -280,7 +284,7 @@ def test_simulation_range(test_range) -> None: f"[1.0, 3.0]", ), ): - RAT.models.Data(data=np.array([[1.0, 0.0, 0.0], [3.0, 0.0, 0.0]]), simulation_range=test_range) + RATpy.models.Data(data=np.array([[1.0, 0.0, 0.0], [3.0, 0.0, 0.0]]), simulation_range=test_range) @pytest.mark.parametrize( @@ -301,4 +305,4 @@ def test_parameter_range(minimum: float, value: float, maximum: float) -> None: f"{float(value)} is not within the defined range: " f"{float(minimum)} <= value <= {float(maximum)}", ): - RAT.models.Parameter(min=minimum, value=value, max=maximum) + RATpy.models.Parameter(min=minimum, value=value, max=maximum) diff --git a/tests/test_outputs.py b/tests/test_outputs.py index ef08f302..60f56759 100644 --- a/tests/test_outputs.py +++ b/tests/test_outputs.py @@ -5,10 +5,10 @@ import pytest -import RAT -import RAT.outputs -import RAT.rat_core -from RAT.utils.enums import Procedures +import RATpy +import RATpy.outputs +import RATpy.rat_core +from RATpy.utils.enums import Procedures from tests.utils import check_results_equal @@ -26,6 +26,6 @@ def test_make_results(test_procedure, test_output_results, test_bayes, test_resu test_bayes = request.getfixturevalue(test_bayes) test_results = request.getfixturevalue(test_results) - results = RAT.outputs.make_results(test_procedure, test_output_results, test_bayes) + results = RATpy.outputs.make_results(test_procedure, test_output_results, test_bayes) check_results_equal(test_results, results) diff --git a/tests/test_plotting.py b/tests/test_plotting.py index 95e03ffd..aa758733 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -6,8 +6,8 @@ import matplotlib.pyplot as plt import pytest -from RAT.rat_core import PlotEventData -from RAT.utils.plotting import Figure, plot_ref_sld_helper +from RATpy.rat_core import PlotEventData +from RATpy.utils.plotting import Figure, plot_ref_sld_helper TEST_DIR_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data") @@ -125,7 +125,7 @@ def test_eventhandler_variable_update(fig: Figure) -> None: assert fig._close_clicked -@patch("RAT.utils.plotting.plt.waitforbuttonpress") +@patch("RATpy.utils.plotting.plt.waitforbuttonpress") def test_wait_for_close(mock: MagicMock, fig: Figure) -> None: """Tests the _wait_for_close method stops the while loop when _esc_pressed is True. @@ -140,7 +140,7 @@ def mock_wait_for_button_press(timeout): assert fig._esc_pressed -@patch("RAT.utils.plotting.makeSLDProfileXY") +@patch("RATpy.utils.plotting.makeSLDProfileXY") def test_sld_profile_function_call(mock: MagicMock) -> None: """Tests the makeSLDProfileXY function called with correct args. diff --git a/tests/test_project.py b/tests/test_project.py index 1afaba82..950d5b69 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -10,8 +10,8 @@ import pydantic import pytest -import RAT -from RAT.utils.enums import Calculations, LayerModels +import RATpy +from RATpy.utils.enums import Calculations, LayerModels layer_params = {"thickness": "Test Thickness", "SLD": "Test SLD", "roughness": "Test Roughness"} absorption_layer_params = { @@ -25,8 +25,8 @@ @pytest.fixture def test_project(): """Add parameters to the default project, so each ClassList can be tested properly.""" - test_project = RAT.Project( - data=RAT.ClassList([RAT.models.Data(name="Simulation", data=np.array([[1.0, 1.0, 1.0]]))]), + test_project = RATpy.Project( + data=RATpy.ClassList([RATpy.models.Data(name="Simulation", data=np.array([[1.0, 1.0, 1.0]]))]), ) test_project.parameters.append(name="Test Thickness") test_project.parameters.append(name="Test SLD") @@ -122,11 +122,11 @@ def default_project_repr(): def test_project_script(): return ( '# THIS FILE IS GENERATED FROM RAT VIA THE "WRITE_SCRIPT" ROUTINE. IT IS NOT PART OF THE RAT CODE.\n\n' - "import RAT\nfrom RAT.models import *\nfrom numpy import array, inf\n\n" - "problem = RAT.Project(\n" + "import RATpy\nfrom RATpy.models import *\nfrom numpy import array, inf\n\n" + "problem = RATpy.Project(\n" " name='', calculation='non polarised', model='standard layers', geometry='air/substrate'," " absorption=False,\n" - " parameters=RAT.ClassList(" + " parameters=RATpy.ClassList(" "[ProtectedParameter(name='Substrate Roughness', min=1.0, value=3.0, max=5.0, fit=True, prior_type='uniform'," " mu=0.0, sigma=inf)," " Parameter(name='Test Thickness', min=0.0, value=0.0, max=0.0, fit=False, prior_type='uniform', mu=0.0," @@ -135,27 +135,27 @@ def test_project_script(): " Parameter(name='Test Roughness', min=0.0, value=0.0, max=0.0, fit=False, prior_type='uniform', mu=0.0," " sigma=inf)" "]),\n" - " background_parameters=RAT.ClassList([Parameter(name='Background Param 1', min=1e-07, value=1e-06," + " background_parameters=RATpy.ClassList([Parameter(name='Background Param 1', min=1e-07, value=1e-06," " max=1e-05, fit=False, prior_type='uniform', mu=0.0, sigma=inf)]),\n" - " scalefactors=RAT.ClassList([Parameter(name='Scalefactor 1', min=0.02, value=0.23, max=0.25, fit=False," + " scalefactors=RATpy.ClassList([Parameter(name='Scalefactor 1', min=0.02, value=0.23, max=0.25, fit=False," " prior_type='uniform', mu=0.0, sigma=inf)]),\n" - " bulk_in=RAT.ClassList([Parameter(name='SLD Air', min=0.0, value=0.0, max=0.0, fit=False," + " bulk_in=RATpy.ClassList([Parameter(name='SLD Air', min=0.0, value=0.0, max=0.0, fit=False," " prior_type='uniform', mu=0.0, sigma=inf)]),\n" - " bulk_out=RAT.ClassList([Parameter(name='SLD D2O', min=6.2e-06, value=6.35e-06, max=6.35e-06, fit=False," + " bulk_out=RATpy.ClassList([Parameter(name='SLD D2O', min=6.2e-06, value=6.35e-06, max=6.35e-06, fit=False," " prior_type='uniform', mu=0.0, sigma=inf)]),\n" - " resolution_parameters=RAT.ClassList([Parameter(name='Resolution Param 1', min=0.01, value=0.03, max=0.05," - " fit=False, prior_type='uniform', mu=0.0, sigma=inf)]),\n" - " backgrounds=RAT.ClassList([Background(name='Background 1', type='constant', value_1='Background Param 1'," - " value_2='', value_3='', value_4='', value_5='')]),\n" - " resolutions=RAT.ClassList([Resolution(name='Resolution 1', type='constant', value_1='Resolution Param 1'," - " value_2='', value_3='', value_4='', value_5='')]),\n" - " custom_files=RAT.ClassList([CustomFile(name='Test Custom File', filename='', function_name=''," + " resolution_parameters=RATpy.ClassList([Parameter(name='Resolution Param 1', min=0.01, value=0.03," + " max=0.05, fit=False, prior_type='uniform', mu=0.0, sigma=inf)]),\n" + " backgrounds=RATpy.ClassList([Background(name='Background 1', type='constant'," + " value_1='Background Param 1', value_2='', value_3='', value_4='', value_5='')]),\n" + " resolutions=RATpy.ClassList([Resolution(name='Resolution 1', type='constant'," + " value_1='Resolution Param 1', value_2='', value_3='', value_4='', value_5='')]),\n" + " custom_files=RATpy.ClassList([CustomFile(name='Test Custom File', filename='', function_name=''," " language='python', path='')]),\n" - " data=RAT.ClassList([Data(name='Simulation', data=array([[1., 1., 1.]]), data_range=[1.0, 1.0]," + " data=RATpy.ClassList([Data(name='Simulation', data=array([[1., 1., 1.]]), data_range=[1.0, 1.0]," " simulation_range=[1.0, 1.0])]),\n" - " layers=RAT.ClassList([Layer(name='Test Layer', thickness='Test Thickness', SLD='Test SLD'," + " layers=RATpy.ClassList([Layer(name='Test Layer', thickness='Test Thickness', SLD='Test SLD'," " roughness='Test Roughness', hydration='', hydrate_with='bulk out')]),\n" - " contrasts=RAT.ClassList([Contrast(name='Test Contrast', data='Simulation', background='Background 1'," + " contrasts=RATpy.ClassList([Contrast(name='Test Contrast', data='Simulation', background='Background 1'," " background_action='add', bulk_in='SLD Air', bulk_out='SLD D2O', scalefactor='Scalefactor 1'," " resolution='Resolution 1', resample=False, model=['Test Layer'])]),\n" " )\n" @@ -173,7 +173,7 @@ def test_classlists(test_project) -> None: """The ClassLists in the "Project" model should contain instances of the models given by the dictionary "model_in_classlist". """ - for key, value in RAT.project.model_in_classlist.items(): + for key, value in RATpy.project.model_in_classlist.items(): class_list = getattr(test_project, key) assert class_list._class_handle.__name__ == value @@ -182,7 +182,7 @@ def test_classlists_specific_cases() -> None: """The ClassLists in the "Project" model should contain instances of specific models given various non-default options. """ - project = RAT.Project(calculation=Calculations.Domains, absorption=True) + project = RATpy.Project(calculation=Calculations.Domains, absorption=True) assert project.layers._class_handle.__name__ == "AbsorptionLayer" assert project.contrasts._class_handle.__name__ == "ContrastWithRatio" @@ -190,15 +190,15 @@ def test_classlists_specific_cases() -> None: @pytest.mark.parametrize( ["input_model", "model_params"], [ - (RAT.models.Background, {}), - (RAT.models.Contrast, {}), - (RAT.models.ContrastWithRatio, {}), - (RAT.models.CustomFile, {}), - (RAT.models.Data, {}), - (RAT.models.DomainContrast, {}), - (RAT.models.Layer, layer_params), - (RAT.models.AbsorptionLayer, absorption_layer_params), - (RAT.models.Resolution, {}), + (RATpy.models.Background, {}), + (RATpy.models.Contrast, {}), + (RATpy.models.ContrastWithRatio, {}), + (RATpy.models.CustomFile, {}), + (RATpy.models.Data, {}), + (RATpy.models.DomainContrast, {}), + (RATpy.models.Layer, layer_params), + (RATpy.models.AbsorptionLayer, absorption_layer_params), + (RATpy.models.Resolution, {}), ], ) def test_initialise_wrong_classes(input_model: Callable, model_params: dict) -> None: @@ -209,14 +209,14 @@ def test_initialise_wrong_classes(input_model: Callable, model_params: dict) -> '"parameters" ClassList contains objects other than ' '"Parameter"', ): - RAT.Project(parameters=RAT.ClassList(input_model(**model_params))) + RATpy.Project(parameters=RATpy.ClassList(input_model(**model_params))) @pytest.mark.parametrize( ["input_model", "model_params", "absorption", "actual_model_name"], [ - (RAT.models.Layer, layer_params, True, "AbsorptionLayer"), - (RAT.models.AbsorptionLayer, absorption_layer_params, False, "Layer"), + (RATpy.models.Layer, layer_params, True, "AbsorptionLayer"), + (RATpy.models.AbsorptionLayer, absorption_layer_params, False, "Layer"), ], ) def test_initialise_wrong_layers( @@ -234,14 +234,14 @@ def test_initialise_wrong_layers( f'"layers" ClassList contains objects other than ' f'"{actual_model_name}"', ): - RAT.Project(absorption=absorption, layers=RAT.ClassList(input_model(**model_params))) + RATpy.Project(absorption=absorption, layers=RATpy.ClassList(input_model(**model_params))) @pytest.mark.parametrize( ["input_model", "calculation", "actual_model_name"], [ - (RAT.models.Contrast, Calculations.Domains, "ContrastWithRatio"), - (RAT.models.ContrastWithRatio, Calculations.NonPolarised, "Contrast"), + (RATpy.models.Contrast, Calculations.Domains, "ContrastWithRatio"), + (RATpy.models.ContrastWithRatio, Calculations.NonPolarised, "Contrast"), ], ) def test_initialise_wrong_contrasts(input_model: Callable, calculation: Calculations, actual_model_name: str) -> None: @@ -254,35 +254,35 @@ def test_initialise_wrong_contrasts(input_model: Callable, calculation: Calculat f'"contrasts" ClassList contains objects other than ' f'"{actual_model_name}"', ): - RAT.Project(calculation=calculation, contrasts=RAT.ClassList(input_model())) + RATpy.Project(calculation=calculation, contrasts=RATpy.ClassList(input_model())) @pytest.mark.parametrize( "input_parameter", [ - (RAT.models.Parameter(name="Test Parameter")), - (RAT.models.Parameter(name="Substrate Roughness")), + (RATpy.models.Parameter(name="Test Parameter")), + (RATpy.models.Parameter(name="Substrate Roughness")), ], ) def test_initialise_without_substrate_roughness(input_parameter: Callable) -> None: """If the "Project" model is initialised without "Substrate Roughness as a protected parameter, add it to the front of the "parameters" ClassList. """ - project = RAT.Project(parameters=RAT.ClassList(RAT.models.Parameter(name="Substrate Roughness"))) - assert project.parameters[0] == RAT.models.ProtectedParameter(name="Substrate Roughness") + project = RATpy.Project(parameters=RATpy.ClassList(RATpy.models.Parameter(name="Substrate Roughness"))) + assert project.parameters[0] == RATpy.models.ProtectedParameter(name="Substrate Roughness") @pytest.mark.parametrize( ["field", "wrong_input_model", "model_params"], [ - ("backgrounds", RAT.models.Resolution, {}), - ("contrasts", RAT.models.Layer, layer_params), - ("domain_contrasts", RAT.models.Parameter, {}), - ("custom_files", RAT.models.Data, {}), - ("data", RAT.models.Contrast, {}), - ("layers", RAT.models.DomainContrast, {}), - ("parameters", RAT.models.CustomFile, {}), - ("resolutions", RAT.models.Background, {}), + ("backgrounds", RATpy.models.Resolution, {}), + ("contrasts", RATpy.models.Layer, layer_params), + ("domain_contrasts", RATpy.models.Parameter, {}), + ("custom_files", RATpy.models.Data, {}), + ("data", RATpy.models.Contrast, {}), + ("layers", RATpy.models.DomainContrast, {}), + ("parameters", RATpy.models.CustomFile, {}), + ("resolutions", RATpy.models.Background, {}), ], ) def test_assign_wrong_classes(test_project, field: str, wrong_input_model: Callable, model_params: dict) -> None: @@ -291,16 +291,16 @@ def test_assign_wrong_classes(test_project, field: str, wrong_input_model: Calla pydantic.ValidationError, match=f"1 validation error for Project\n{field}\n Value error, " f'"{field}" ClassList contains objects other than ' - f'"{RAT.project.model_in_classlist[field]}"', + f'"{RATpy.project.model_in_classlist[field]}"', ): - setattr(test_project, field, RAT.ClassList(wrong_input_model(**model_params))) + setattr(test_project, field, RATpy.ClassList(wrong_input_model(**model_params))) @pytest.mark.parametrize( ["wrong_input_model", "model_params", "absorption", "actual_model_name"], [ - (RAT.models.Layer, layer_params, True, "AbsorptionLayer"), - (RAT.models.AbsorptionLayer, absorption_layer_params, False, "Layer"), + (RATpy.models.Layer, layer_params, True, "AbsorptionLayer"), + (RATpy.models.AbsorptionLayer, absorption_layer_params, False, "Layer"), ], ) def test_assign_wrong_layers( @@ -310,33 +310,33 @@ def test_assign_wrong_layers( actual_model_name: str, ) -> None: """If we assign incorrect classes to the "Project" model, we should raise a ValidationError.""" - project = RAT.Project(absorption=absorption) + project = RATpy.Project(absorption=absorption) with pytest.raises( pydantic.ValidationError, match=f"1 validation error for Project\nlayers\n Value error, " f'"layers" ClassList contains objects other than ' f'"{actual_model_name}"', ): - project.layers = RAT.ClassList(wrong_input_model(**model_params)) + project.layers = RATpy.ClassList(wrong_input_model(**model_params)) @pytest.mark.parametrize( ["wrong_input_model", "calculation", "actual_model_name"], [ - (RAT.models.Contrast, Calculations.Domains, "ContrastWithRatio"), - (RAT.models.ContrastWithRatio, Calculations.NonPolarised, "Contrast"), + (RATpy.models.Contrast, Calculations.Domains, "ContrastWithRatio"), + (RATpy.models.ContrastWithRatio, Calculations.NonPolarised, "Contrast"), ], ) def test_assign_wrong_contrasts(wrong_input_model: Callable, calculation: Calculations, actual_model_name: str) -> None: """If we assign incorrect classes to the "Project" model, we should raise a ValidationError.""" - project = RAT.Project(calculation=calculation) + project = RATpy.Project(calculation=calculation) with pytest.raises( pydantic.ValidationError, match=f"1 validation error for Project\ncontrasts\n Value error, " f'"contrasts" ClassList contains objects other than ' f'"{actual_model_name}"', ): - project.contrasts = RAT.ClassList(wrong_input_model()) + project.contrasts = RATpy.ClassList(wrong_input_model()) @pytest.mark.parametrize( @@ -353,7 +353,7 @@ def test_assign_wrong_contrasts(wrong_input_model: Callable, calculation: Calcul ) def test_assign_models(test_project, field: str, model_params: dict) -> None: """If the "Project" model is initialised with models rather than ClassLists, we should raise a ValidationError.""" - input_model = getattr(RAT.models, RAT.project.model_in_classlist[field]) + input_model = getattr(RATpy.models, RATpy.project.model_in_classlist[field]) with pytest.raises( pydantic.ValidationError, match=f"1 validation error for Project\n{field}\n Input should be " f"an instance of ClassList", @@ -375,7 +375,7 @@ def test_wrapped_routines(test_project) -> None: "extend", "set_fields", ] - for class_list in RAT.project.class_lists: + for class_list in RATpy.project.class_lists: attribute = getattr(test_project, class_list) for methodName in wrapped_methods: assert hasattr(getattr(attribute, methodName), "__wrapped__") @@ -402,7 +402,7 @@ def test_set_domain_contrasts(project_parameters: dict) -> None: """If we are not running a domains calculation with standard layers, the "domain_contrasts" field of the model should always be empty. """ - project = RAT.Project(**project_parameters) + project = RATpy.Project(**project_parameters) assert project.domain_contrasts == [] project.domain_contrasts.append(name="New Domain Contrast") assert project.domain_contrasts == [] @@ -417,7 +417,7 @@ def test_set_domain_contrasts(project_parameters: dict) -> None: ) def test_set_layers(project_parameters: dict) -> None: """If we are not using a standard layers model, the "layers" field of the model should always be empty.""" - project = RAT.Project(**project_parameters) + project = RATpy.Project(**project_parameters) assert project.layers == [] project.layers.append(name="New Layer", thickness="Test Thickness", SLD="Test SLD", roughness="Test Roughness") assert project.layers == [] @@ -426,8 +426,8 @@ def test_set_layers(project_parameters: dict) -> None: @pytest.mark.parametrize( ["input_calculation", "input_contrast", "new_calculation", "new_contrast_model", "num_domain_ratios"], [ - (Calculations.NonPolarised, RAT.models.Contrast, Calculations.Domains, "ContrastWithRatio", 1), - (Calculations.Domains, RAT.models.ContrastWithRatio, Calculations.NonPolarised, "Contrast", 0), + (Calculations.NonPolarised, RATpy.models.Contrast, Calculations.Domains, "ContrastWithRatio", 1), + (Calculations.Domains, RATpy.models.ContrastWithRatio, Calculations.NonPolarised, "Contrast", 0), ], ) def test_set_calculation( @@ -440,7 +440,7 @@ def test_set_calculation( """When changing the value of the calculation option, the "contrasts" ClassList should switch to using the appropriate Contrast model. """ - project = RAT.Project(calculation=input_calculation, contrasts=RAT.ClassList(input_contrast())) + project = RATpy.Project(calculation=input_calculation, contrasts=RATpy.ClassList(input_contrast())) project.calculation = new_calculation assert project.calculation is new_calculation @@ -505,13 +505,13 @@ def test_check_contrast_model_length( """If we are not running a domains calculation with standard layers, the "domain_contrasts" field of the model should always be empty. """ - test_domain_ratios = RAT.ClassList(RAT.models.Parameter(name="Test Domain Ratio")) - test_contrasts = RAT.ClassList(RAT.models.ContrastWithRatio(model=test_contrast_model)) + test_domain_ratios = RATpy.ClassList(RATpy.models.Parameter(name="Test Domain Ratio")) + test_contrasts = RATpy.ClassList(RATpy.models.ContrastWithRatio(model=test_contrast_model)) with pytest.raises( pydantic.ValidationError, match=f"1 validation error for Project\n Value error, {error_message}", ): - RAT.Project( + RATpy.Project( calculation=Calculations.Domains, model=input_model, domain_ratios=test_domain_ratios, @@ -522,8 +522,8 @@ def test_check_contrast_model_length( @pytest.mark.parametrize( ["input_layer", "model_params", "input_absorption", "new_layer_model"], [ - (RAT.models.Layer, layer_params, False, "AbsorptionLayer"), - (RAT.models.AbsorptionLayer, absorption_layer_params, True, "Layer"), + (RATpy.models.Layer, layer_params, False, "AbsorptionLayer"), + (RATpy.models.AbsorptionLayer, absorption_layer_params, True, "Layer"), ], ) def test_set_absorption( @@ -535,16 +535,16 @@ def test_set_absorption( """When changing the value of the absorption option, the "layers" ClassList should switch to using the appropriate Layer model. """ - project = RAT.Project( + project = RATpy.Project( absorption=input_absorption, - parameters=RAT.ClassList( + parameters=RATpy.ClassList( [ - RAT.models.Parameter(name="Test Thickness"), - RAT.models.Parameter(name="Test SLD"), - RAT.models.Parameter(name="Test Roughness"), + RATpy.models.Parameter(name="Test Thickness"), + RATpy.models.Parameter(name="Test SLD"), + RATpy.models.Parameter(name="Test Roughness"), ], ), - layers=RAT.ClassList(input_layer(**model_params)), + layers=RATpy.ClassList(input_layer(**model_params)), ) project.absorption = not input_absorption @@ -564,7 +564,7 @@ def test_set_absorption( ) def test_check_protected_parameters(delete_operation) -> None: """If we try to remove a protected parameter, we should raise an error.""" - project = RAT.Project() + project = RATpy.Project() with pytest.raises( pydantic.ValidationError, @@ -596,7 +596,7 @@ def test_rename_models(test_project, model: str, field: str) -> None: in the project. """ getattr(test_project, model).set_fields(-1, name="New Name") - attribute = RAT.project.model_names_used_in[model].attribute + attribute = RATpy.project.model_names_used_in[model].attribute assert getattr(getattr(test_project, attribute)[-1], field) == "New Name" @@ -614,14 +614,14 @@ def test_allowed_backgrounds(field: str) -> None: """If the "value" fields of the Background model are set to values that are not specified in the background parameters, we should raise a ValidationError. """ - test_background = RAT.models.Background(**{field: "undefined"}) + test_background = RATpy.models.Background(**{field: "undefined"}) with pytest.raises( pydantic.ValidationError, match=f"1 validation error for Project\n Value error, The value " f'"undefined" in the "{field}" field of "backgrounds" must be ' f'defined in "background_parameters".', ): - RAT.Project(backgrounds=RAT.ClassList(test_background)) + RATpy.Project(backgrounds=RATpy.ClassList(test_background)) @pytest.mark.parametrize( @@ -636,7 +636,7 @@ def test_allowed_layers(field: str) -> None: """If the "thickness", "SLD", or "roughness" fields of the Layer model are set to values that are not specified in the parameters, we should raise a ValidationError. """ - test_layer = RAT.models.Layer(**{**layer_params, field: "undefined"}) + test_layer = RATpy.models.Layer(**{**layer_params, field: "undefined"}) with pytest.raises( pydantic.ValidationError, @@ -644,16 +644,16 @@ def test_allowed_layers(field: str) -> None: f'"undefined" in the "{field}" field of "layers" must be ' f'defined in "parameters".', ): - RAT.Project( + RATpy.Project( absorption=False, - parameters=RAT.ClassList( + parameters=RATpy.ClassList( [ - RAT.models.Parameter(name="Test Thickness"), - RAT.models.Parameter(name="Test SLD"), - RAT.models.Parameter(name="Test Roughness"), + RATpy.models.Parameter(name="Test Thickness"), + RATpy.models.Parameter(name="Test SLD"), + RATpy.models.Parameter(name="Test Roughness"), ], ), - layers=RAT.ClassList(test_layer), + layers=RATpy.ClassList(test_layer), ) @@ -670,7 +670,7 @@ def test_allowed_absorption_layers(field: str) -> None: """If the "thickness", "SLD_real", "SLD_imaginary", or "roughness" fields of the AbsorptionLayer model are set to values that are not specified in the parameters, we should raise a ValidationError. """ - test_layer = RAT.models.AbsorptionLayer(**{**absorption_layer_params, field: "undefined"}) + test_layer = RATpy.models.AbsorptionLayer(**{**absorption_layer_params, field: "undefined"}) with pytest.raises( pydantic.ValidationError, @@ -678,16 +678,16 @@ def test_allowed_absorption_layers(field: str) -> None: f'"undefined" in the "{field}" field of "layers" must be ' f'defined in "parameters".', ): - RAT.Project( + RATpy.Project( absorption=True, - parameters=RAT.ClassList( + parameters=RATpy.ClassList( [ - RAT.models.Parameter(name="Test Thickness"), - RAT.models.Parameter(name="Test SLD"), - RAT.models.Parameter(name="Test Roughness"), + RATpy.models.Parameter(name="Test Thickness"), + RATpy.models.Parameter(name="Test SLD"), + RATpy.models.Parameter(name="Test Roughness"), ], ), - layers=RAT.ClassList(test_layer), + layers=RATpy.ClassList(test_layer), ) @@ -705,14 +705,14 @@ def test_allowed_resolutions(field: str) -> None: """If the "value" fields of the Resolution model are set to values that are not specified in the background parameters, we should raise a ValidationError. """ - test_resolution = RAT.models.Resolution(**{field: "undefined"}) + test_resolution = RATpy.models.Resolution(**{field: "undefined"}) with pytest.raises( pydantic.ValidationError, match=f"1 validation error for Project\n Value error, The value " f'"undefined" in the "{field}" field of "resolutions" must be ' f'defined in "resolution_parameters".', ): - RAT.Project(resolutions=RAT.ClassList(test_resolution)) + RATpy.Project(resolutions=RATpy.ClassList(test_resolution)) @pytest.mark.parametrize( @@ -730,14 +730,14 @@ def test_allowed_contrasts(field: str, model_name: str) -> None: """If the fields of the Contrast model are set to values not specified in the other respective models of the project, we should raise a ValidationError. """ - test_contrast = RAT.models.Contrast(**{field: "undefined"}) + test_contrast = RATpy.models.Contrast(**{field: "undefined"}) with pytest.raises( pydantic.ValidationError, match=f"1 validation error for Project\n Value error, The value " f'"undefined" in the "{field}" field of "contrasts" must be ' f'defined in "{model_name}".', ): - RAT.Project(calculation=Calculations.NonPolarised, contrasts=RAT.ClassList(test_contrast)) + RATpy.Project(calculation=Calculations.NonPolarised, contrasts=RATpy.ClassList(test_contrast)) @pytest.mark.parametrize( @@ -756,14 +756,14 @@ def test_allowed_contrasts_with_ratio(field: str, model_name: str) -> None: """If the fields of the ContrastWithRatio model are set to values not specified in the other respective models of the project, we should raise a ValidationError. """ - test_contrast = RAT.models.ContrastWithRatio(**{field: "undefined"}) + test_contrast = RATpy.models.ContrastWithRatio(**{field: "undefined"}) with pytest.raises( pydantic.ValidationError, match=f"1 validation error for Project\n Value error, The value " f'"undefined" in the "{field}" field of "contrasts" must be ' f'defined in "{model_name}".', ): - RAT.Project(calculation=Calculations.Domains, contrasts=RAT.ClassList(test_contrast)) + RATpy.Project(calculation=Calculations.Domains, contrasts=RATpy.ClassList(test_contrast)) @pytest.mark.parametrize( @@ -772,37 +772,37 @@ def test_allowed_contrasts_with_ratio(field: str, model_name: str) -> None: ( Calculations.Domains, LayerModels.StandardLayers, - RAT.models.ContrastWithRatio(name="Test Contrast", model=["undefined", "undefined"]), + RATpy.models.ContrastWithRatio(name="Test Contrast", model=["undefined", "undefined"]), "domain_contrasts", ), ( Calculations.Domains, LayerModels.CustomLayers, - RAT.models.ContrastWithRatio(name="Test Contrast", model=["undefined"]), + RATpy.models.ContrastWithRatio(name="Test Contrast", model=["undefined"]), "custom_files", ), ( Calculations.Domains, LayerModels.CustomXY, - RAT.models.ContrastWithRatio(name="Test Contrast", model=["undefined"]), + RATpy.models.ContrastWithRatio(name="Test Contrast", model=["undefined"]), "custom_files", ), ( Calculations.NonPolarised, LayerModels.StandardLayers, - RAT.models.Contrast(name="Test Contrast", model=["undefined", "undefined", "undefined"]), + RATpy.models.Contrast(name="Test Contrast", model=["undefined", "undefined", "undefined"]), "layers", ), ( Calculations.NonPolarised, LayerModels.CustomLayers, - RAT.models.Contrast(name="Test Contrast", model=["undefined"]), + RATpy.models.Contrast(name="Test Contrast", model=["undefined"]), "custom_files", ), ( Calculations.NonPolarised, LayerModels.CustomXY, - RAT.models.Contrast(name="Test Contrast", model=["undefined"]), + RATpy.models.Contrast(name="Test Contrast", model=["undefined"]), "custom_files", ), ], @@ -810,7 +810,7 @@ def test_allowed_contrasts_with_ratio(field: str, model_name: str) -> None: def test_allowed_contrast_models( input_calc: Calculations, input_model: LayerModels, - test_contrast: "RAT.models", + test_contrast: "RATpy.models", field_name: str, ) -> None: """If any value in the model field of the contrasts is set to a value not specified in the appropriate part of the @@ -822,26 +822,26 @@ def test_allowed_contrast_models( f'"{", ".join(test_contrast.model)}" in the "model" field of ' f'"contrasts" must be defined in "{field_name}".', ): - RAT.Project(calculation=input_calc, model=input_model, contrasts=RAT.ClassList(test_contrast)) + RATpy.Project(calculation=input_calc, model=input_model, contrasts=RATpy.ClassList(test_contrast)) def test_allowed_domain_contrast_models() -> None: """If any value in the model field of the domain_contrasts is set to a value not specified in the "layers" field of the project, we should raise a ValidationError. """ - test_contrast = RAT.models.DomainContrast(name="Test Domain Contrast", model=["undefined"]) + test_contrast = RATpy.models.DomainContrast(name="Test Domain Contrast", model=["undefined"]) with pytest.raises( pydantic.ValidationError, match="1 validation error for Project\n Value error, The values: " '"undefined" in the "model" field of "domain_contrasts" must be ' 'defined in "layers".', ): - RAT.Project(calculation=Calculations.Domains, domain_contrasts=RAT.ClassList(test_contrast)) + RATpy.Project(calculation=Calculations.Domains, domain_contrasts=RATpy.ClassList(test_contrast)) def test_repr(default_project_repr: str) -> None: """We should be able to print the "Project" model as a formatted list of the fields.""" - assert repr(RAT.Project()) == default_project_repr + assert repr(RATpy.Project()) == default_project_repr def test_get_all_names(test_project) -> None: @@ -886,7 +886,7 @@ def test_get_all_protected_parameters(test_project) -> None: ) def test_check_allowed_values(test_value: str) -> None: """We should not raise an error if string values are defined and on the list of allowed values.""" - project = RAT.Project.model_construct(backgrounds=RAT.ClassList(RAT.models.Background(value_1=test_value))) + project = RATpy.Project.model_construct(backgrounds=RATpy.ClassList(RATpy.models.Background(value_1=test_value))) assert project.check_allowed_values("backgrounds", ["value_1"], ["Background Param 1"]) is None @@ -898,7 +898,7 @@ def test_check_allowed_values(test_value: str) -> None: ) def test_check_allowed_values_not_on_list(test_value: str) -> None: """If string values are defined and are not included on the list of allowed values we should raise a ValueError.""" - project = RAT.Project.model_construct(backgrounds=RAT.ClassList(RAT.models.Background(value_1=test_value))) + project = RATpy.Project.model_construct(backgrounds=RATpy.ClassList(RATpy.models.Background(value_1=test_value))) with pytest.raises( ValueError, match=f'The value "{test_value}" in the "value_1" field of "backgrounds" must be ' @@ -918,8 +918,8 @@ def test_check_contrast_model_allowed_values(test_values: list[str]) -> None: """We should not raise an error if values are defined in a non-empty list and all are on the list of allowed values. """ - project = RAT.Project.model_construct( - contrasts=RAT.ClassList(RAT.models.Contrast(name="Test Contrast", model=test_values)), + project = RATpy.Project.model_construct( + contrasts=RATpy.ClassList(RATpy.models.Contrast(name="Test Contrast", model=test_values)), ) assert project.check_contrast_model_allowed_values("contrasts", ["Test Layer"], "layers") is None @@ -935,8 +935,8 @@ def test_check_allowed_contrast_model_not_on_list(test_values: list[str]) -> Non """If string values are defined in a non-empty list and any of them are not included on the list of allowed values we should raise a ValueError. """ - project = RAT.Project.model_construct( - contrasts=RAT.ClassList(RAT.models.Contrast(name="Test Contrast", model=test_values)), + project = RATpy.Project.model_construct( + contrasts=RATpy.ClassList(RATpy.models.Contrast(name="Test Contrast", model=test_values)), ) with pytest.raises( ValueError, @@ -961,7 +961,7 @@ def test_get_contrast_model_field(input_calc: Calculations, input_model: LayerMo """Each combination of calculation and model determines the field where the values of "model" field of "contrasts" are defined. """ - project = RAT.Project(calculation=input_calc, model=input_model) + project = RATpy.Project(calculation=input_calc, model=input_model) assert project.get_contrast_model_field() == expected_field_name @@ -983,6 +983,7 @@ def test_write_script(test_project, temp_dir, test_project_script, input_filenam # Test the contents of the file are as expected with open(script_path) as f: script = f.read() + print(script) assert script == test_project_script @@ -990,7 +991,7 @@ def test_write_script(test_project, temp_dir, test_project_script, input_filenam exec(script) new_project = locals()["problem"] - for class_list in RAT.project.class_lists: + for class_list in RATpy.project.class_lists: assert getattr(new_project, class_list) == getattr(test_project, class_list) @@ -1043,7 +1044,7 @@ def test_wrap_set(test_project, class_list: str, field: str) -> None: match=f'1 validation error for Project\n Value error, The value ' f'"undefined" in the "{field}" field of "{class_list}" must be ' f'defined in ' - f'"{RAT.project.values_defined_in[f"{class_list}.{field}"]}".', + f'"{RATpy.project.values_defined_in[f"{class_list}.{field}"]}".', ): test_attribute.set_fields(0, **{field: "undefined"}) @@ -1075,7 +1076,7 @@ def test_wrap_del(test_project, class_list: str, parameter: str, field: str) -> pydantic.ValidationError, match=f"1 validation error for Project\n Value error, The value " f'"{parameter}" in the "{field}" field of ' - f'"{RAT.project.model_names_used_in[class_list].attribute}" ' + f'"{RATpy.project.model_names_used_in[class_list].attribute}" ' f'must be defined in "{class_list}".', ): del test_attribute[index] @@ -1112,14 +1113,14 @@ def test_wrap_iadd(test_project, class_list: str, field: str, model_params: dict """If we add a model containing undefined values to a ClassList, we should raise a ValidationError.""" test_attribute = getattr(test_project, class_list) orig_class_list = copy.deepcopy(test_attribute) - input_model = getattr(RAT.models, RAT.project.model_in_classlist[class_list]) + input_model = getattr(RATpy.models, RATpy.project.model_in_classlist[class_list]) with pytest.raises( pydantic.ValidationError, match=f'1 validation error for Project\n Value error, The value ' f'"undefined" in the "{field}" field of "{class_list}" must be ' f'defined in ' - f'"{RAT.project.values_defined_in[f"{class_list}.{field}"]}".', + f'"{RATpy.project.values_defined_in[f"{class_list}.{field}"]}".', ): test_attribute += [input_model(**{**model_params, field: "undefined"})] @@ -1155,14 +1156,14 @@ def test_wrap_append(test_project, class_list: str, field: str, model_params: di """If we append a model containing undefined values to a ClassList, we should raise a ValidationError.""" test_attribute = getattr(test_project, class_list) orig_class_list = copy.deepcopy(test_attribute) - input_model = getattr(RAT.models, RAT.project.model_in_classlist[class_list]) + input_model = getattr(RATpy.models, RATpy.project.model_in_classlist[class_list]) with pytest.raises( pydantic.ValidationError, match=f'1 validation error for Project\n Value error, The value ' f'"undefined" in the "{field}" field of "{class_list}" must be ' f'defined in ' - f'"{RAT.project.values_defined_in[f"{class_list}.{field}"]}".', + f'"{RATpy.project.values_defined_in[f"{class_list}.{field}"]}".', ): test_attribute.append(input_model(**{**model_params, field: "undefined"})) @@ -1198,14 +1199,14 @@ def test_wrap_insert(test_project, class_list: str, field: str, model_params: di """If we insert a model containing undefined values into a ClassList, we should raise a ValidationError.""" test_attribute = getattr(test_project, class_list) orig_class_list = copy.deepcopy(test_attribute) - input_model = getattr(RAT.models, RAT.project.model_in_classlist[class_list]) + input_model = getattr(RATpy.models, RATpy.project.model_in_classlist[class_list]) with pytest.raises( pydantic.ValidationError, match=f'1 validation error for Project\n Value error, The value ' f'"undefined" in the "{field}" field of "{class_list}" must be ' f'defined in ' - f'"{RAT.project.values_defined_in[f"{class_list}.{field}"]}".', + f'"{RATpy.project.values_defined_in[f"{class_list}.{field}"]}".', ): test_attribute.insert(0, input_model(**{**model_params, field: "undefined"})) @@ -1238,7 +1239,7 @@ def test_wrap_insert_type_error(test_project, class_list: str, field: str) -> No """If we raise a TypeError using the wrapped insert routine, we should re-raise the error.""" test_attribute = getattr(test_project, class_list) orig_class_list = copy.deepcopy(test_attribute) - input_model = getattr(RAT.models, RAT.project.model_in_classlist[class_list]) + input_model = getattr(RATpy.models, RATpy.project.model_in_classlist[class_list]) with pytest.raises(TypeError): test_attribute.insert(input_model) @@ -1271,7 +1272,7 @@ def test_wrap_pop(test_project, class_list: str, parameter: str, field: str) -> pydantic.ValidationError, match=f"1 validation error for Project\n Value error, The value " f'"{parameter}" in the "{field}" field of ' - f'"{RAT.project.model_names_used_in[class_list].attribute}" ' + f'"{RATpy.project.model_names_used_in[class_list].attribute}" ' f'must be defined in "{class_list}".', ): test_attribute.pop(index) @@ -1303,7 +1304,7 @@ def test_wrap_remove(test_project, class_list: str, parameter: str, field: str) pydantic.ValidationError, match=f"1 validation error for Project\n Value error, The value " f'"{parameter}" in the "{field}" field of ' - f'"{RAT.project.model_names_used_in[class_list].attribute}" ' + f'"{RATpy.project.model_names_used_in[class_list].attribute}" ' f'must be defined in "{class_list}".', ): test_attribute.remove(parameter) @@ -1335,7 +1336,7 @@ def test_wrap_clear(test_project, class_list: str, parameter: str, field: str) - pydantic.ValidationError, match=f"1 validation error for Project\n Value error, The value " f'"{parameter}" in the "{field}" field of ' - f'"{RAT.project.model_names_used_in[class_list].attribute}" ' + f'"{RATpy.project.model_names_used_in[class_list].attribute}" ' f'must be defined in "{class_list}".', ): test_attribute.clear() @@ -1372,14 +1373,14 @@ def test_wrap_extend(test_project, class_list: str, field: str, model_params: di """If we extend a ClassList with model containing undefined values, we should raise a ValidationError.""" test_attribute = getattr(test_project, class_list) orig_class_list = copy.deepcopy(test_attribute) - input_model = getattr(RAT.models, RAT.project.model_in_classlist[class_list]) + input_model = getattr(RATpy.models, RATpy.project.model_in_classlist[class_list]) with pytest.raises( pydantic.ValidationError, match=f'1 validation error for Project\n Value error, The value ' f'"undefined" in the "{field}" field of "{class_list}" must be ' f'defined in ' - f'"{RAT.project.values_defined_in[f"{class_list}.{field}"]}".', + f'"{RATpy.project.values_defined_in[f"{class_list}.{field}"]}".', ): test_attribute.extend([input_model(**{**model_params, field: "undefined"})]) diff --git a/tests/test_run.py b/tests/test_run.py index 115fc971..312519e7 100644 --- a/tests/test_run.py +++ b/tests/test_run.py @@ -8,10 +8,10 @@ import numpy as np import pytest -import RAT -import RAT.outputs -import RAT.rat_core -from RAT.utils.enums import Calculations, Geometries, LayerModels, Procedures +import RATpy +import RATpy.outputs +import RATpy.rat_core +from RATpy.utils.enums import Calculations, Geometries, LayerModels, Procedures from tests.utils import check_results_equal @@ -20,7 +20,7 @@ def input_project(): """A cut-down version of the input Project object for a reflectivity calculation set out in "DSPC_standard_layers.py". """ - project = RAT.Project( + project = RATpy.Project( name="original_dspc_bilayer", calculation="non polarised", model="standard layers", @@ -268,7 +268,7 @@ def reflectivity_calculation_problem(): """The output C++ ProblemDefinition object for a reflectivity calculation of the project set out in "DSPC_standard_layers.py". """ - problem = RAT.rat_core.ProblemDefinition() + problem = RATpy.rat_core.ProblemDefinition() problem.TF = Calculations.NonPolarised problem.modelType = LayerModels.StandardLayers problem.geometry = Geometries.SubstrateLiquid @@ -405,7 +405,7 @@ def dream_problem(): This optimisation used the parameters: nSamples=50000, nChains=10. """ - problem = RAT.rat_core.ProblemDefinition() + problem = RATpy.rat_core.ProblemDefinition() problem.TF = Calculations.NonPolarised problem.modelType = LayerModels.StandardLayers problem.geometry = Geometries.SubstrateLiquid @@ -560,11 +560,11 @@ def test_run(test_procedure, test_output_problem, test_output_results, test_baye test_results = request.getfixturevalue(test_results) with mock.patch.object( - RAT.rat_core, + RATpy.rat_core, "RATMain", mock.MagicMock(return_value=(test_output_problem, test_output_results, test_bayes)), ): # Use default project as we patch RATMain to give the desired outputs - project, results = RAT.run(input_project, RAT.set_controls(procedure=test_procedure)) + project, results = RATpy.run(input_project, RATpy.set_controls(procedure=test_procedure)) check_results_equal(test_results, results) diff --git a/tests/test_wrappers.py b/tests/test_wrappers.py index aa135c34..db8f7f38 100644 --- a/tests/test_wrappers.py +++ b/tests/test_wrappers.py @@ -3,20 +3,20 @@ import pytest -import RAT.wrappers +import RATpy.wrappers def test_matlab_wrapper() -> None: with mock.patch.dict("sys.modules", {"matlab": mock.MagicMock(side_effect=ImportError)}), pytest.raises( ImportError, ): - RAT.wrappers.MatlabWrapper("demo.m") + RATpy.wrappers.MatlabWrapper("demo.m") mocked_matlab_module = mock.MagicMock() mocked_engine = mock.MagicMock() mocked_matlab_module.engine.start_matlab.return_value = mocked_engine with mock.patch.dict("sys.modules", {"matlab": mocked_matlab_module, "matlab.engine": mocked_matlab_module.engine}): - wrapper = RAT.wrappers.MatlabWrapper("demo.m") + wrapper = RATpy.wrappers.MatlabWrapper("demo.m") assert wrapper.function_name == "demo" mocked_engine.cd.assert_called_once() assert pathlib.Path(mocked_engine.cd.call_args[0][0]).samefile(".") @@ -38,8 +38,8 @@ def test_matlab_wrapper() -> None: def test_dylib_wrapper() -> None: mocked_engine = mock.MagicMock() - with mock.patch("RAT.wrappers.RAT.rat_core.DylibEngine", mocked_engine): - wrapper = RAT.wrappers.DylibWrapper("demo.dylib", "demo") + with mock.patch("RATpy.wrappers.RATpy.rat_core.DylibEngine", mocked_engine): + wrapper = RATpy.wrappers.DylibWrapper("demo.dylib", "demo") mocked_engine.assert_called_once_with("demo.dylib", "demo") wrapper.engine.invoke.return_value = ([2], 5) diff --git a/tests/utils.py b/tests/utils.py index 03833ee3..a8301826 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,6 +1,6 @@ import numpy as np -import RAT.outputs +import RATpy.outputs class InputAttributes: @@ -42,8 +42,11 @@ def check_results_equal(actual_results, expected_results) -> None: "resample", ] - assert (isinstance(actual_results, RAT.outputs.Results) and isinstance(expected_results, RAT.outputs.Results)) or ( - isinstance(actual_results, RAT.outputs.BayesResults) and isinstance(expected_results, RAT.outputs.BayesResults) + assert ( + isinstance(actual_results, RATpy.outputs.Results) and isinstance(expected_results, RATpy.outputs.Results) + ) or ( + isinstance(actual_results, RATpy.outputs.BayesResults) + and isinstance(expected_results, RATpy.outputs.BayesResults) ) # The first set of fields are either 1D or 2D python lists containing numpy arrays. @@ -71,7 +74,9 @@ def check_results_equal(actual_results, expected_results) -> None: for field in contrast_param_fields: assert (getattr(actual_results.contrastParams, field) == getattr(expected_results.contrastParams, field)).all() - if isinstance(actual_results, RAT.outputs.BayesResults) and isinstance(expected_results, RAT.outputs.BayesResults): + if isinstance(actual_results, RATpy.outputs.BayesResults) and isinstance( + expected_results, RATpy.outputs.BayesResults + ): check_bayes_fields_equal(actual_results, expected_results)