Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion RATapi/controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,43 +36,99 @@
}


class Controls(BaseModel, validate_assignment=True, extra="forbid"):
class Controls(BaseModel, validate_assignment=True, extra="forbid", use_attribute_docstrings=True):
"""The full set of controls parameters for all five procedures that are required for the compiled RAT code."""

# All Procedures
procedure: Procedures = Procedures.Calculate
"""Which procedure RAT should execute. Can be 'calculate', 'simplex', 'de', 'ns', or 'dream'."""

parallel: Parallel = Parallel.Single
"""How the calculation should be parallelised. Can be 'single', 'contrasts' or 'points'."""

calcSldDuringFit: bool = False
"""Whether SLD will be calculated during fit (for live plotting etc.)"""

resampleMinAngle: float = Field(0.9, le=1, gt=0)
"""The upper threshold on the angle between three sampled points for resampling, in units of radians over pi."""

resampleNPoints: int = Field(50, gt=0)
"""The number of initial points to use for resampling."""

display: Display = Display.Iter
"""How much RAT should print to the terminal. Can be 'off', 'iter', 'notify', or 'final'."""

# Simplex
xTolerance: float = Field(1.0e-6, gt=0.0)
"""[SIMPLEX] The termination tolerance for step size."""

funcTolerance: float = Field(1.0e-6, gt=0.0)
"""[SIMPLEX] The termination tolerance for change in chi-squared."""

maxFuncEvals: int = Field(10000, gt=0)
"""[SIMPLEX] The maximum number of function evaluations before the algorithm terminates."""

maxIterations: int = Field(1000, gt=0)
"""[SIMPLEX] The maximum number of iterations before the algorithm terminates."""

# Simplex and DE
updateFreq: int = 1
"""[SIMPLEX, DE] Number of iterations between printing progress updates to the terminal."""

updatePlotFreq: int = 20
"""[SIMPLEX, DE] Number of iterations between updates to live plots."""

# DE
populationSize: int = Field(20, ge=1)
"""[DE] The number of candidate solutions that exist at any time."""

fWeight: float = Field(0.5, gt=0.0)
"""[DE] The step size for how different mutations are to their parents."""

crossoverProbability: float = Field(0.8, gt=0.0, lt=1.0)
"""[DE] The probability of exchange of parameters between individuals at any iteration."""

strategy: Strategies = Strategies.RandomWithPerVectorDither
"""[DE] The algorithm used to generate new candidates."""

targetValue: float = Field(1.0, ge=1.0)
"""[DE] The value of chi-squared at which the algorithm will terminate."""

numGenerations: int = Field(500, ge=1)
"""[DE] The maximum number of iterations before the algorithm terminates."""

# NS
nLive: int = Field(150, ge=1)
"""[NS] The number of points to sample."""

nMCMC: int = Field(0, ge=0)
"""[NS] If non-zero, an MCMC process with ``nMCMC`` chains will be used instead of MultiNest."""

propScale: float = Field(0.1, gt=0.0, lt=1.0)
"""[NS] A scaling factor for the ellipsoid generated by MultiNest."""

nsTolerance: float = Field(0.1, ge=0.0)
"""[NS] The tolerance threshold for when the algorithm should terminate."""

# Dream
nSamples: int = Field(20000, ge=0)
"""[DREAM] The number of samples in the initial population for each chain."""

nChains: int = Field(10, gt=0)
"""[DREAM] The number of Markov chains to use in the algorithm."""

jumpProbability: float = Field(0.5, gt=0.0, lt=1.0)
"""[DREAM] The probability range for the size of jumps in sampling. Larger values mean more variable jumps."""

pUnitGamma: float = Field(0.2, gt=0.0, lt=1.0)
"""[DREAM] The probability that the scaling-down factor of jumps will be ignored and a larger jump will be taken."""

boundHandling: BoundHandling = BoundHandling.Reflect
"""[DREAM] How steps past the space boundaries should be handled. Can be 'off', 'reflect', 'bound', or 'fold'."""

adaptPCR: bool = True
"""[DREAM] Whether the crossover probability for differential evolution should be adapted during the run."""

# Private field for IPC file
_IPCFilePath: str = ""

Expand Down
6 changes: 3 additions & 3 deletions RATapi/examples/non_polarised/DSPC_custom_XY.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


def DSPC_custom_XY():
"""Custom XY Example for Supported DSPC layer.
r"""Custom XY Example for Supported DSPC layer.

In this example, we model the same data (DSPC supported bilayer) as the Custom Layers example, but this time we will
use continuous distributions of the volume fractions of each component to build up the SLD profiles (as described in
Expand All @@ -19,15 +19,15 @@ def DSPC_custom_XY():
We can define our lipid in terms of an Area per Molecule, almost in its entirety, if we recognise that where the
volume is known, the thickness of the layer is simply given by the layer volume / APM:

$d_{\textrm{layer}} =\frac{V_{\textrm{layer}} }{{\textrm{APM}}_{\textrm{layer}}}$.
.. math:: d_{\textrm{layer}} =\frac{V_{\textrm{layer}} }{{\textrm{APM}}_{\textrm{layer}}}.

We can then define the Volume Fraction of this layer with a roughened Heaviside of length dlayer and a height of 1.
Then, the total volume occupied will be given by the sum of the volume fractions across the interface. Of course,
this does not permit any hydration, so to deal with this, we can simply scale the (full occupation) Heaviside
functions by relevant coverage parameters. When this is correctly done, we can obtain the remaining water
distribution as:

$${\textrm{VF}}_{\textrm{wat}} =1-\\sum_n {\textrm{VF}}_n$$
.. math:: {\textrm{VF}}_{\textrm{wat}} =1-\\sum_n {\textrm{VF}}_n

where VFn is the Volume Fraction of the n'th layer.
"""
Expand Down
12 changes: 10 additions & 2 deletions RATapi/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,14 @@ class Background(Signal):
The type of background (constant, function or data)
source : str
The source of the background;

- if type is 'constant', this should be the name of a background parameter.
- if type is 'data', this should be the name of a dataset defined in `Project.data`.
- if type is 'function', this should be the name of a custom function defined in `Project.custom_files`.
value_1, value_2, ..., value_5 : str

value_1, value_2, value_3, value_4, value_5 : str
Values required by the background.

- if type is 'constant', all values will be ignored.
- if type is 'data', value_1 may be the parameter name for an optional offset. Other values are ignored.
- if type is 'function', these values may be the names of up to 5 parameters which are passed to the function.
Expand Down Expand Up @@ -318,6 +321,8 @@ def set_matlab_function_name(self):
class Data(RATModel, arbitrary_types_allowed=True):
"""A dataset required for a contrast.

Parameters
----------
name : str
The name of this dataset.
data : np.ndarray[np.float64]
Expand Down Expand Up @@ -584,12 +589,15 @@ class Resolution(Signal):
The type of resolution: 'constant', 'data', or (NOT YET IMPLEMENTED) 'function'.
source : str
The source data for the resolution;

- if type is 'constant', this should be the name of a background parameter.
- if type is 'data', this should be empty (resolution data is in the contrast data).
- if type is 'function' (NOT YET IMPLEMENTED),
this should be the name of a custom function defined in `Project.custom_files`.
value_1, value_2, ..., value_5 : str

value_1, value_2, value_3, value_4, value_5 : str
Values required by the background.

- if type is 'constant' or 'data', all values will be ignored.
- if type is 'function' (NOT YET IMPLEMENTED),
these values may be the names of up to 5 parameters which are passed to the function.
Expand Down
29 changes: 28 additions & 1 deletion RATapi/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,20 +123,30 @@ def discriminate_contrasts(contrast_input):
]


class Project(BaseModel, validate_assignment=True, extra="forbid"):
class Project(BaseModel, validate_assignment=True, extra="forbid", use_attribute_docstrings=True):
"""Defines the input data for a reflectivity calculation in RAT.

This class combines the data defined in each of the pydantic models included in "models.py" into the full set of
inputs required for a reflectivity calculation.
"""

name: str = ""
"""The name of the project."""

calculation: Calculations = Calculations.Normal
"""What calculation type should be used. Can be 'normal' or 'domains'."""

model: LayerModels = LayerModels.StandardLayers
"""What layer model should be used. Can be 'standard layers', 'custom layers', or 'custom xy'."""

geometry: Geometries = Geometries.AirSubstrate
"""What geometry should be used. Can be 'air/substrate' or 'substrate/liquid'"""

absorption: bool = False
"""Whether imaginary SLD (absorption) should be accounted for."""

parameters: ClassList[RATapi.models.Parameter] = ClassList()
"""The list of parameters used in the layers of a model."""

bulk_in: ClassList[RATapi.models.Parameter] = ClassList(
RATapi.models.Parameter(
Expand All @@ -150,6 +160,7 @@ class Project(BaseModel, validate_assignment=True, extra="forbid"):
sigma=np.inf,
),
)
"""The list of parameters for SLD of the entry interfaces of a model."""

bulk_out: ClassList[RATapi.models.Parameter] = ClassList(
RATapi.models.Parameter(
Expand All @@ -163,6 +174,7 @@ class Project(BaseModel, validate_assignment=True, extra="forbid"):
sigma=np.inf,
),
)
"""The list of parameters for SLD of the exit interfaces of a model."""

scalefactors: ClassList[RATapi.models.Parameter] = ClassList(
RATapi.models.Parameter(
Expand All @@ -176,6 +188,7 @@ class Project(BaseModel, validate_assignment=True, extra="forbid"):
sigma=np.inf,
),
)
"""The list of parameters for scale factors to handle systematic error in model data."""

domain_ratios: ClassList[RATapi.models.Parameter] = ClassList(
RATapi.models.Parameter(
Expand All @@ -189,6 +202,7 @@ class Project(BaseModel, validate_assignment=True, extra="forbid"):
sigma=np.inf,
),
)
"""The list of parameters for weighting between domains of a domains model."""

background_parameters: ClassList[RATapi.models.Parameter] = ClassList(
RATapi.models.Parameter(
Expand All @@ -202,10 +216,12 @@ class Project(BaseModel, validate_assignment=True, extra="forbid"):
sigma=np.inf,
),
)
"""The list of parameters for models of backgrounds."""

backgrounds: ClassList[RATapi.models.Background] = ClassList(
RATapi.models.Background(name="Background 1", type=TypeOptions.Constant, source="Background Param 1"),
)
"""The list of models for background noise in the project."""

resolution_parameters: ClassList[RATapi.models.Parameter] = ClassList(
RATapi.models.Parameter(
Expand All @@ -219,13 +235,19 @@ class Project(BaseModel, validate_assignment=True, extra="forbid"):
sigma=np.inf,
),
)
"""The list of parameters for models of resolutions."""

resolutions: ClassList[RATapi.models.Resolution] = ClassList(
RATapi.models.Resolution(name="Resolution 1", type=TypeOptions.Constant, source="Resolution Param 1"),
)
"""The list of models for instrument resolution in the project."""

custom_files: ClassList[RATapi.models.CustomFile] = ClassList()
"""Handles for custom files used by the project."""

data: ClassList[RATapi.models.Data] = ClassList()
"""Experimental data for a model."""

layers: Union[
Annotated[ClassList[RATapi.models.Layer], Tag("no_abs")],
Annotated[ClassList[RATapi.models.AbsorptionLayer], Tag("abs")],
Expand All @@ -238,7 +260,11 @@ class Project(BaseModel, validate_assignment=True, extra="forbid"):
custom_error_context={"discriminator": "absorption_or_no"},
),
)
"""The layers of a standard layer model."""

domain_contrasts: ClassList[RATapi.models.DomainContrast] = ClassList()
"""The groups of layers required by each domain in a domains model."""

contrasts: Union[
Annotated[ClassList[RATapi.models.Contrast], Tag("no_ratio")],
Annotated[ClassList[RATapi.models.ContrastWithRatio], Tag("ratio")],
Expand All @@ -251,6 +277,7 @@ class Project(BaseModel, validate_assignment=True, extra="forbid"):
custom_error_context={"discriminator": "ratio_or_no_ratio"},
),
)
"""All groups of components used to define each model in the project."""

_all_names: dict
_contrast_model_field: str
Expand Down
Loading