The Problem Definition Input Class#

In the previous section, we saw an example of how we set up and run an analysis using the RAT toolbox. Every call to the toolbox has two parts: the problem definition class, where we define the model, add the data and define our contrasts, and the controls class where we tell the toolbox what type of analysis we would like to do. The reason for splitting things up in this way is that once our model is defined, we can interact with it in various ways without needing to modify the model. So, we can experiment with our data, trying out different types of analysis, and explore the landscape of solutions by simply modifying the controls class, leaving the problem class alone.

As well as having two inputs, RAT always provides two outputs, so the call to the toolbox is always of this form:-

[problem, results] = RAT(problem, controls)
problem, results = RAT.run(problem, controls)

In this case we have called our inputs problem and controls, but they can be called anything. Likewise, we have called our outputs problem and results, but we are free to call them anything we like. We will look at the outputs in more detail in the next section.

The first input, problem, is an instance of a class called project class:

>> problem = createProject(name='my project');
>> class(problem)

ans =
    'projectClass'
>>> problem = RAT.Project(name='my project')
>>> type(problem)

<class 'RAT.project.Project'>

And if we take a look at it, we can see the class contains a series of sections, where we can define our parameters, make different kinds of model, load in our data and do everything we need to set up our model.

         modelType: 'standard layers'
    experimentName: 'my project'
          geometry: 'air/substrate'


    Parameters: ---------------------------------------------------------------------------------------------- 

    p            Name             Min    Value    Max    Fit? 
    _    _____________________    ___    _____    ___    _____

    1    "Substrate Roughness"     1       3       5     true 


    Bulk In: -------------------------------------------------------------------------------------------------- 

    p      Name       Min    Value    Max    Fit? 
    _    _________    ___    _____    ___    _____

    1    "SLD Air"     0       0       0     false


    Bulk Out: ------------------------------------------------------------------------------------------------- 

    p      Name         Min       Value        Max       Fit? 
    _    _________    _______    ________    ________    _____

    1    "SLD D2O"    6.2e-06    6.35e-06    6.35e-06    false


    Scalefactors: ------------------------------------------------------------------------------------------------- 

    p         Name          Min     Value    Max     Fit? 
    _    _______________    ____    _____    ____    _____

    1    "Scalefactor 1"    0.02    0.23     0.25    false


    Backgrounds: ----------------------------------------------------------------------------------------------- 

    (a) Background Parameters: 

    p            Name             Min     Value     Max     Fit? 
    _    ____________________    _____    _____    _____    _____

    1    "Background Param 1"    1e-07    1e-06    1e-05    false

    (b) Backgrounds:  

    p         Name            Type             Value 1           Value 2    Value 3    Value 4    Value 5
    _    ______________    __________    ____________________    _______    _______    _______    _______

    1    "Background 1"    "constant"    "Background Param 1"      ""         ""         ""         ""   


    Resolutions: --------------------------------------------------------------------------------------------- 

    (a) Resolutions Parameters: 

    p           Name           Min     Value    Max     Fit? 
    _    __________________    ____    _____    ____    _____

    1    "Resolution par 1"    0.01    0.03     0.05    false

    (b) Resolutions:  

    p         Name            Type            Value 1          Value 2    Value 3    Value 4    Value 5
    _    ______________    __________    __________________    _______    _______    _______    _______

    1    "Resolution 1"    "constant"    "Resolution par 1"      ""         ""         ""         ""   


    Layers: -------------------------------------------------------------------------------------------------- 

    Name    Thickness    SLD    Roughness    Hydration    Hydrate with
    ____    _________    ___    _________    _________    ____________

     ""        ""        ""        ""           ""             ""     


    Custom Files: ------------------------------------------------------------------------------------------------------ 

    Name    Filename    Function Name    Language    Path
    ____    ________    _____________    ________    ____

     ""        ""            ""             ""        "" 


    Data: ------------------------------------------------------------------------------------------------------ 

        Name          Data       Data Range      Simulation Range   
    ____________    _________    __________    _____________________

    "Simulation"    "No Data"       "-"        "[ 0.0050 , 0.7000 ]"


   Contrasts: ----------------------------------------------------------------------------------------------- 

             p         
    ___________________

    "Name"             
    "Data"             
    "Background"       
    "Background Action"
    "Bulk in"          
    "Bulk out"         
    "Scalefactor"      
    "Resolution"       
    "Resample"         
    "Model"            
Name: ----------------------------------------------------------------------------------------------

my project

Calculation: ---------------------------------------------------------------------------------------

non polarised

Model: ---------------------------------------------------------------------------------------------

standard layers

Geometry: ------------------------------------------------------------------------------------------

air/substrate

Parameters: ----------------------------------------------------------------------------------------

+-------+---------------------+-----+-------+-----+------+------------+-----+-------+
| index |         name        | min | value | max | fit  | prior type |  mu | sigma |
+-------+---------------------+-----+-------+-----+------+------------+-----+-------+
|   0   | Substrate Roughness | 1.0 |  3.0  | 5.0 | True |  uniform   | 0.0 |  inf  |
+-------+---------------------+-----+-------+-----+------+------------+-----+-------+

Bulk In: -------------------------------------------------------------------------------------------

+-------+---------+-----+-------+-----+-------+------------+-----+-------+
| index |   name  | min | value | max |  fit  | prior type |  mu | sigma |
+-------+---------+-----+-------+-----+-------+------------+-----+-------+
|   0   | SLD Air | 0.0 |  0.0  | 0.0 | False |  uniform   | 0.0 |  inf  |
+-------+---------+-----+-------+-----+-------+------------+-----+-------+

Bulk Out: ------------------------------------------------------------------------------------------

+-------+---------+---------+----------+----------+-------+------------+-----+-------+
| index |   name  |   min   |  value   |   max    |  fit  | prior type |  mu | sigma |
+-------+---------+---------+----------+----------+-------+------------+-----+-------+
|   0   | SLD D2O | 6.2e-06 | 6.35e-06 | 6.35e-06 | False |  uniform   | 0.0 |  inf  |
+-------+---------+---------+----------+----------+-------+------------+-----+-------+

Scalefactors: --------------------------------------------------------------------------------------

+-------+---------------+------+-------+------+-------+------------+-----+-------+
| index |      name     | min  | value | max  |  fit  | prior type |  mu | sigma |
+-------+---------------+------+-------+------+-------+------------+-----+-------+
|   0   | Scalefactor 1 | 0.02 |  0.23 | 0.25 | False |  uniform   | 0.0 |  inf  |
+-------+---------------+------+-------+------+-------+------------+-----+-------+

Background Parameters: -----------------------------------------------------------------------------

+-------+--------------------+-------+-------+-------+-------+------------+-----+-------+
| index |        name        |  min  | value |  max  |  fit  | prior type |  mu | sigma |
+-------+--------------------+-------+-------+-------+-------+------------+-----+-------+
|   0   | Background Param 1 | 1e-07 | 1e-06 | 1e-05 | False |  uniform   | 0.0 |  inf  |
+-------+--------------------+-------+-------+-------+-------+------------+-----+-------+

Backgrounds: ---------------------------------------------------------------------------------------

+-------+--------------+----------+--------------------+---------+---------+---------+---------+
| index |     name     |   type   |      value 1       | value 2 | value 3 | value 4 | value 5 |
+-------+--------------+----------+--------------------+---------+---------+---------+---------+
|   0   | Background 1 | constant | Background Param 1 |         |         |         |         |
+-------+--------------+----------+--------------------+---------+---------+---------+---------+

Resolution Parameters: -----------------------------------------------------------------------------

+-------+--------------------+------+-------+------+-------+------------+-----+-------+
| index |        name        | min  | value | max  |  fit  | prior type |  mu | sigma |
+-------+--------------------+------+-------+------+-------+------------+-----+-------+
|   0   | Resolution Param 1 | 0.01 |  0.03 | 0.05 | False |  uniform   | 0.0 |  inf  |
+-------+--------------------+------+-------+------+-------+------------+-----+-------+

Resolutions: ---------------------------------------------------------------------------------------

+-------+--------------+----------+--------------------+---------+---------+---------+---------+
| index |     name     |   type   |      value 1       | value 2 | value 3 | value 4 | value 5 |
+-------+--------------+----------+--------------------+---------+---------+---------+---------+
|   0   | Resolution 1 | constant | Resolution Param 1 |         |         |         |         |
+-------+--------------+----------+--------------------+---------+---------+---------+---------+

Data: ----------------------------------------------------------------------------------------------

+-------+------------+------+------------+------------------+
| index |    name    | data | data range | simulation range |
+-------+------------+------+------------+------------------+
|   0   | Simulation |  []  |     []     |   [0.005, 0.7]   |
+-------+------------+------+------------+------------------+

We can see that the class has a number of attributes, defining all we need for our analysis. In the default case, we have no parameters or data, and have not defined any contrasts, so this will not do anything useful in RAT. Defining a model is a case of populating the sections in the project class, which we do using the methods in the project Class,:

In the following sections, we will look at each of these methods and see how they can be used to define our reflectivity analysis problem. (There is also a utility which will convert a RasCAL model into a projectClass for use in RAT. This means that you can use the RasCAL GUI to set up your model if you like and then use the speed of RAT to conduct your analysis.)

In terms of the outputs, note that we have called the first output problem, but we don’t need to do that. The first of the two outputs is another project Class, but updated with the results of the calculation. So, if we run a fit, the fitted parameters will be updated with the best fit values of our procedure. In giving the output the same name as the input, we’re overwriting our input with best fit values, but if you don’t want to do this, you can give the inputs and outputs different names TODO(e.g. ‘[outProblem,results] = RAT(problem,controls)’’ or whatever you like). The second output can also be called whatever you like, and this is a struct containing the simulated reflectivities, SLD’s and so on from whatever procedure you have asked RAT to do:

          reflectivity: {0x1 cell}
            simulation: {0x1 cell}
           shiftedData: {0x1 cell}
             layerSlds: {0x1 cell}
           sldProfiles: {0x1 cell}
       resampledLayers: {0x1 cell}
    calculationResults: [1x1 struct]
        contrastParams: [1x1 struct]
             fitParams: 3
              fitNames: {'Substrate Roughness'}
reflectivity = [],
simulation = [],
shiftedData = [],
layerSlds = [],
sldProfiles = [],
resampledLayers = [],
calculationResults = CalculationResults(
	chiValues = [],
	sumChi = 0.0,
),
contrastParams = ContrastParams(
	backgroundParams = [],
	scalefactors = [],
	bulkIn = [],
	bulkOut = [],
	resolutionParams = [],
	subRoughs = [],
	resample = [],
),
fitParams = [3.],
fitNames = ['Substrate Roughness'],

In the next sections, we will discuss the methods of the project class, and see how they allow us to build up a model by populating the various sections.

The Components of Project Class#

Project Defining Methods#

The first step is always to create an instance of the project class to hold our model. This is always done by assigning project Class to our variable name (we will mostly use problem in this manual, but it can be anything), which always requires a name for our project as an input:

problem = createProject(name='My Problem');
problem = RAT.Project('my project')

This creates an instance of project Class and assigns it to the variable problem, and gives it the title ‘My Problem’.

The first part of the created problem has two other settable fields: modelType and Geometry.

Geometry - This can be set to either air/substrate or substrate/liquid as below.

problem.setGeometry('air/substrate');
problem.setGeometry('substrate/liquid');
problem.geometry = 'air/substrate'
problem.geometry = 'substrate/liquid'

The effect of this parameter is in the numbering of roughness’s in layer models. In any model for n-layers, there are always n+1 associated interfaces, and hence n+1 roughness parameters required. In RAT, the bulk interface roughness is a protected parameter and always exists, and this parameter controls where this roughness is placed in the layer stack. So, for two layers defined with thickness, SLD and roughness as [d1, \(\rho_\mathrm{1}\), r1] and [d2, \(\rho_\mathrm{2}\), r2], then for the substrate/liquid geometry the substrate roughness is placed as the first roughness the beam meets, and the layer roughness’s refer to the interface after the particular layer. But in the air/substrate case, the opposite is true, and the substrate roughness is the last roughness in the stack, with the layer roughness referring to the interface before each layer.

ModelType - As is the case for RasCAL, there are three ways of defining models in RAT:-

  • Standard Layers - The model is defined in terms of parameters, which are distributed into layers, and subsequently grouped into contrasts. No external functions are needed.

  • Custom Layers - Parameters are again defined and grouped into layers, but this time the layer definitions come from a user model script. This then gives complete flexibility of how layers are defined, so allowing models to be written in terms of area per molecule or material density, for example. This custom script controls translating these input parameters into a [d, \(\rho\), r] model. This is probably the most useful operating mode for RasCAL.

  • Custom XY-Profile - This modelling mode also relies on a custom model function, but in this case does away with [d, \(\rho\), r] layers completely. Instead, the custom function uses the parameters to define a continuous SLD profile, which RAT then uses to calculate the reflectivity.

The model type of the project can be changed as follows:

problem.setModelType('standard layers');
problem.setModelType('custom layers');
problem.setModelType('custom XY');
problem.model = 'standard layers'
problem.model = 'custom layers'
problem.model = 'custom XY'

Custom modelling is described in more depth in a later section.

The Parameters Block#

Any model, whether it be layers or anything else is always defined by parameters. These appear in the parameters block and are specified by a name, a value, minimum and maximum ranges and a flag defining whether the parameter is fitted or fixed:

    p            Name             Min    Value    Max    Fit? 
    _    _____________________    ___    _____    ___    _____

    1    "Substrate Roughness"     1       3       5     true 
+-------+---------------------+-----+-------+-----+------+------------+-----+-------+
| index |         name        | min | value | max | fit  | prior type |  mu | sigma |
+-------+---------------------+-----+-------+-----+------+------------+-----+-------+
|   0   | Substrate Roughness | 1.0 |  3.0  | 5.0 | True |  uniform   | 0.0 |  inf  |
+-------+---------------------+-----+-------+-----+------+------------+-----+-------+

The substrate roughness is a protected parameter in all cases (it defines the Fresnel roughness) and cannot be renamed or deleted. Its values can be set to any numerical values however.

To add a parameter, you can just specify a name, in which case the parameter takes on default values, or specify the whole parameter at once:

problem.addParameter('My new param', 1, 2, 3);
problem.addParameter('My other new param',10,20,30,false);
problem.parameters.append(name='My new param', min=1, value=2, max=3)
problem.parameters.append(name='My other new param', min=10, value=20, max=30, fit=False)

To avoid having to make a whole load of statements for large projects with many parameters, you can define them at once in an array, and add them as a group:

pGroup = {{'Layer thick', 10, 20, 30, true};
        {'Layer SLD', 1e-6, 3e-6 5e-6, true};
        {'Layer rough', 5, 7, 10, true}};

problem.addParameterGroup(pGroup)
pGroup = [RAT.models.Parameter(name='Layer thick', min=10, value=20, max=30, fit=True),
          RAT.models.Parameter(name='Layer SLD', min=1e-6, value=3e-6, max=5e-6, fit=True),
          RAT.models.Parameter(name='Layer rough', min=5, value=7, max=10, fit=True)]

problem.parameters.extend(pGroup)

The resulting parameters block looks like this:

    p            Name              Min     Value     Max     Fit? 
    _    _____________________    _____    _____    _____    _____

    1    "Substrate Roughness"        1        3        5    true 
    2    "My new param"               1        2        3    false
    3    "My other new param"        10       20       30    false
    4    "Layer thick"               10       20       30    true 
    5    "Layer SLD"              1e-06    3e-06    5e-06    true 
    6    "Layer rough"                5        7       10    true 
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+
| index |         name        |  min  | value |  max  |  fit  | prior type |  mu | sigma |
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+
|   0   | Substrate Roughness |  1.0  |  3.0  |  5.0  |  True |  uniform   | 0.0 |  inf  |
|   1   |     My new param    |  1.0  |  2.0  |  3.0  | False |  uniform   | 0.0 |  inf  |
|   2   |  My other new param |  10.0 |  20.0 |  30.0 | False |  uniform   | 0.0 |  inf  |
|   3   |     Layer thick     |  10.0 |  20.0 |  30.0 |  True |  uniform   | 0.0 |  inf  |
|   4   |      Layer SLD      | 1e-06 | 3e-06 | 5e-06 |  True |  uniform   | 0.0 |  inf  |
|   5   |     Layer rough     |  5.0  |  7.0  |  10.0 |  True |  uniform   | 0.0 |  inf  |
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+

Note

Parameters can’t have duplicate names. Attempting to duplicate a name will throw an error. This can cause problems when loading in RasCAL-1 projects where duplicate names are allowed.

To subsequently change the values of the parameters (including names), there are a few methods you can use. For each of the methods, you can refer to the parameter by its index number. In Matlab, you can refer to a parameter by name:

problem.setParameterName('My new param', 'My changed param');
problem.setParameterLimits(2, 0.96, 3.62);
problem.setParameterValue(4, 20.22);
problem.setParameterFit('Layer rough', false);
problem.parameters[1].name = 'My changed param'
problem.parameters[1].min = 0.96
problem.parameters[1].max = 3.62
problem.parameters[3].value = 20.22
problem.parameters[5].fit = False
    p            Name              Min     Value     Max     Fit? 
    _    _____________________    _____    _____    _____    _____

    1    "Substrate Roughness"        1        3        5    true 
    2    "My changed param"        0.96        2     3.62    false
    3    "My other new param"        10       20       30    false
    4    "Layer thick"               10    20.22       30    true 
    5    "Layer SLD"              1e-06    3e-06    5e-06    true 
    6    "Layer rough"                5        7       10    false
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+
| index |         name        |  min  | value |  max  |  fit  | prior type |  mu | sigma |
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+
|   0   | Substrate Roughness |  1.0  |  3.0  |  5.0  |  True |  uniform   | 0.0 |  inf  |
|   1   |   My changed param  |  0.96 |  2.0  |  3.62 | False |  uniform   | 0.0 |  inf  |
|   2   |  My other new param |  10.0 |  20.0 |  30.0 | False |  uniform   | 0.0 |  inf  |
|   3   |     Layer thick     |  10.0 | 20.22 |  30.0 |  True |  uniform   | 0.0 |  inf  |
|   4   |      Layer SLD      | 1e-06 | 3e-06 | 5e-06 |  True |  uniform   | 0.0 |  inf  |
|   5   |     Layer rough     |  5.0  |  7.0  |  10.0 | False |  uniform   | 0.0 |  inf  |
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+

Alternatively, you can set a number of properties of a given parameter at once using name/value pairs.

problem.setParameter(4, 'name', 'thick', 'min', 5, 'max', 33, 'fit', false)
problem.parameters.set_fields(3, name='thick', min=15, max=33, fit=False)
    p            Name              Min     Value     Max     Fit? 
    _    _____________________    _____    _____    _____    _____

    1    "Substrate Roughness"        1        3        5    true 
    2    "My changed param"        0.96        2     3.62    false
    3    "My other new param"        10       20       30    false
    4    "thick"                      5    20.22       33    false
    5    "Layer SLD"              1e-06    3e-06    5e-06    true 
    6    "Layer rough"                5        7       10    false
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+
| index |         name        |  min  | value |  max  |  fit  | prior type |  mu | sigma |
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+
|   0   | Substrate Roughness |  1.0  |  3.0  |  5.0  |  True |  uniform   | 0.0 |  inf  |
|   1   |   My changed param  |  0.96 |  2.0  |  3.62 | False |  uniform   | 0.0 |  inf  |
|   2   |  My other new param |  10.0 |  20.0 |  30.0 | False |  uniform   | 0.0 |  inf  |
|   3   |        thick        |  15.0 | 20.22 |  33.0 | False |  uniform   | 0.0 |  inf  |
|   4   |      Layer SLD      | 1e-06 | 3e-06 | 5e-06 |  True |  uniform   | 0.0 |  inf  |
|   5   |     Layer rough     |  5.0  |  7.0  |  10.0 | False |  uniform   | 0.0 |  inf  |
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+

You can remove a parameter from the block using its index number or name (Matlab only). Note that if you remove a parameter from the middle of the block, subsequent parameter index numbers will change. Also, if you try to remove the substrate roughness you will get an error:

problem.removeParameter(4);
del problem.parameters[3]
    p            Name              Min     Value     Max     Fit? 
    _    _____________________    _____    _____    _____    _____

    1    "Substrate Roughness"        1        3        5    true 
    2    "My changed param"        0.96        2     3.62    false
    3    "My other new param"        10       20       30    false
    4    "Layer SLD"              1e-06    3e-06    5e-06    true 
    5    "Layer rough"                5        7       10    false
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+
| index |         name        |  min  | value |  max  |  fit  | prior type |  mu | sigma |
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+
|   0   | Substrate Roughness |  1.0  |  3.0  |  5.0  |  True |  uniform   | 0.0 |  inf  |
|   1   |   My changed param  |  0.96 |  2.0  |  3.62 | False |  uniform   | 0.0 |  inf  |
|   2   |  My other new param |  10.0 |  20.0 |  30.0 | False |  uniform   | 0.0 |  inf  |
|   3   |      Layer SLD      | 1e-06 | 3e-06 | 5e-06 |  True |  uniform   | 0.0 |  inf  |
|   4   |     Layer rough     |  5.0  |  7.0  |  10.0 | False |  uniform   | 0.0 |  inf  |
+-------+---------------------+-------+-------+-------+-------+------------+-----+-------+
problem.removeParameter(1);
del problem.parameters[0]
Error using projectClass/removeParameter (line 281)
Can't remove protected parameters
1 validation error for Project
  Value error, Can't delete the protected parameters: Substrate Roughness [type=value_error]

The Layers Block (Standard Layers models only)#

For each of the custom models cases, the model building is done using a script (discussed in Custom Models). For standard layers models however, model building is done by grouping the parameters into layers, and then into contrasts (as is the case for RasCAL). The layers block is not visible when either of the two custom modes is selected. Again, layers are built using methods of the project class. As an example here, we make a new project class, add some parameters, and create some layers.

For this example, we will make two layers representing a deuterated and hydrogenated version of the same layer. So, the layers will share all their parameters except for the SLD.

Start by making a new project, and adding the parameters we will need:

problem = createProject(name='Layers Example');

params = {{'Layer Thickness', 10, 20, 30, false};
        {'H SLD', -6e-6, -4e-6, -1e-6, false};
        {'D SLD', 5e-6, 7e-6, 9e-6, true};
        {'Layer rough', 3, 5, 7, true};
        {'Layer hydr', 0, 10, 20, true}};

problem.addParameterGroup(params);
problem = RAT.Project(name='Layers Example')

params = [RAT.models.Parameter(name='Layer Thickness', min=10, value=20, max=30, fit=False),
          RAT.models.Parameter(name='H SLD', min=-6e-6, value=-4e-6, max=-1e-6, fit=False),
          RAT.models.Parameter(name='D SLD', min=5e-6, value=7e-6, max=9e-6, fit=True),
          RAT.models.Parameter(name='Layer rough', min=3, value=5, max=7, fit=True),
          RAT.models.Parameter(name='Layer hydr', min=0, value=10, max=20, fit=True)]

problem.parameters.extend(params)

A layer is defined in terms of a name, thickness, SLD, roughness and (optional) hydration, along with details of which bulk phase is hydrating the layer. The easiest way to define these is to group the parameters into cell arrays, and then add them to the project as a layers group:

% Make the layers
H_layer = {'H Layer','Layer Thickness','H SLD','Layer rough','Layer hydr','bulk out'};
D_layer = {'D Layer','Layer Thickness','D SLD','Layer rough','Layer hydr','bulk out'};

% Add them to the project - as a cell array{}
problem.addLayerGroup({H_layer, D_layer});
problem.layers.append(name='H Layer', thickness='Layer Thickness', SLD='H SLD',
                      roughness='Layer rough', hydration='Layer hydr', hydrate_with='bulk out')
problem.layers.append(name='D Layer', thickness='Layer Thickness', SLD='D SLD',
                      roughness='Layer rough', hydration='Layer hydr', hydrate_with='bulk out')

Our two layers now appear in the Layers block of the project:

    p      Name           Thickness          SLD        Roughness       Hydration      Hydrate with
    _    _________    _________________    _______    _____________    ____________    ____________

    1    "H Layer"    "Layer Thickness"    "H SLD"    "Layer rough"    "Layer hydr"     "bulk out" 
    2    "D Layer"    "Layer Thickness"    "D SLD"    "Layer rough"    "Layer hydr"     "bulk out" 
+-------+---------+-----------------+-------+-------------+------------+--------------+
| index |   name  |    thickness    |  SLD  |  roughness  | hydration  | hydrate with |
+-------+---------+-----------------+-------+-------------+------------+--------------+
|   0   | H Layer | Layer Thickness | H SLD | Layer rough | Layer hydr |   bulk out   |
|   1   | D Layer | Layer Thickness | D SLD | Layer rough | Layer hydr |   bulk out   |
+-------+---------+-----------------+-------+-------------+------------+--------------+

Note that in RAT, hydration is percent hydration between 0 and 100. It is not necessary to define a hydration at all, and we can also make layers without this parameter:

% Non hydrated layer
Dry_Layer = {'Dry Layer', 'Layer Thickness', 'D SLD', 'Layer rough'};
problem.addLayer(Dry_Layer);
problem.layers.append(name='Dry Layer', thickness='Layer Thickness', SLD='D SLD', roughness='Layer rough')
    p       Name            Thickness          SLD        Roughness       Hydration      Hydrate with
    _    ___________    _________________    _______    _____________    ____________    ____________

    1    "H Layer"      "Layer Thickness"    "H SLD"    "Layer rough"    "Layer hydr"     "bulk out" 
    2    "D Layer"      "Layer Thickness"    "D SLD"    "Layer rough"    "Layer hydr"     "bulk out" 
    3    "Dry Layer"    "Layer Thickness"    "D SLD"    "Layer rough"    ""               "bulk out" 
+-------+-----------+-----------------+-------+-------------+------------+--------------+
| index |    name   |    thickness    |  SLD  |  roughness  | hydration  | hydrate with |
+-------+-----------+-----------------+-------+-------------+------------+--------------+
|   0   |  H Layer  | Layer Thickness | H SLD | Layer rough | Layer hydr |   bulk out   |
|   1   |  D Layer  | Layer Thickness | D SLD | Layer rough | Layer hydr |   bulk out   |
|   2   | Dry Layer | Layer Thickness | D SLD | Layer rough |            |   bulk out   |
+-------+-----------+-----------------+-------+-------------+------------+--------------+

The value of an existing layer can be changed by specifying the layer number, layer parameter to be changed and the value to change to. So for example below, changes parameter 2 (Thickness) of Layer 1 (H Layer) to the 3rd Parameter of the parameter block (H SLD):

problem.setLayerValue(1, 2, 3);

% Alternative: setLayerValue allows the use of names so the following is the same as the line above

problem.setLayerValue('H Layer', 'Thickness', 'H SLD');
problem.layers.set_fields(0, thickness='H SLD')
    p       Name            Thickness          SLD        Roughness       Hydration      Hydrate with
    _    ___________    _________________    _______    _____________    ____________    ____________

    1    "H Layer"      "H SLD"              "H SLD"    "Layer rough"    "Layer hydr"     "bulk out" 
    2    "D Layer"      "Layer Thickness"    "D SLD"    "Layer rough"    "Layer hydr"     "bulk out" 
    3    "Dry Layer"    "Layer Thickness"    "D SLD"    "Layer rough"    ""               "bulk out" 
+-------+-----------+-----------------+-------+-------------+------------+--------------+
| index |    name   |    thickness    |  SLD  |  roughness  | hydration  | hydrate with |
+-------+-----------+-----------------+-------+-------------+------------+--------------+
|   0   |  H Layer  |      H SLD      | H SLD | Layer rough | Layer hydr |   bulk out   |
|   1   |  D Layer  | Layer Thickness | D SLD | Layer rough | Layer hydr |   bulk out   |
|   2   | Dry Layer | Layer Thickness | D SLD | Layer rough |            |   bulk out   |
+-------+-----------+-----------------+-------+-------------+------------+--------------+

The layers are then used to set up the contrasts as usual with a standard layers model.

Bulk Phases#

These are treated in the same way as parameters e.g.

problem.addBulkIn('Silicon', 2.0e-6, 2.07e-6, 2.1e-6, false);
problem.addBulkOut('H2O', -0.6e-6, -0.56e-6, -0.5e-6, false);
problem.bulk_in.append(name='Silicon', min=2.0e-06, value=2.073e-06, max=2.1e-06, fit=False)
problem.bulk_out.append(name='D2O', min=-0.6e-6, value=-0.56e-6, max=-0.5e-6, fit=False)
    p      Name        Min      Value        Max      Fit? 
    _    _________    _____    ________    _______    _____

    1    "SLD Air"        0           0          0    false
    2    "Silicon"    2e-06    2.07e-06    2.1e-06    false

    p      Name         Min       Value        Max       Fit? 
    _    _________    _______    ________    ________    _____

    1    "SLD D2O"    6.2e-06    6.35e-06    6.35e-06    false
    2    "H2O"         -6e-07    -5.6e-07      -5e-07    false
+-------+---------+-------+-----------+---------+-------+------------+-----+-------+
| index |   name  |  min  |   value   |   max   |  fit  | prior type |  mu | sigma |
+-------+---------+-------+-----------+---------+-------+------------+-----+-------+
|   0   | SLD Air |  0.0  |    0.0    |   0.0   | False |  uniform   | 0.0 |  inf  |
|   1   | Silicon | 2e-06 | 2.073e-06 | 2.1e-06 | False |  uniform   | 0.0 |  inf  |
+-------+---------+-------+-----------+---------+-------+------------+-----+-------+
+-------+---------+---------+----------+----------+-------+------------+-----+-------+
| index |   name  |   min   |  value   |   max    |  fit  | prior type |  mu | sigma |
+-------+---------+---------+----------+----------+-------+------------+-----+-------+
|   0   | SLD D2O | 6.2e-06 | 6.35e-06 | 6.35e-06 | False |  uniform   | 0.0 |  inf  |
|   1   |   D2O   |  -6e-07 | -5.6e-07 |  -5e-07  | False |  uniform   | 0.0 |  inf  |
+-------+---------+---------+----------+----------+-------+------------+-----+-------+

The values of BulkIn and BulkOut can be modified as shown below:

problem.setBulkOut(1, 'value', 5.9e-6, 'fit', true);

% Similarly BulkIn can be changed
% problem.setBulkIn('Silicon', 'value', 5.9e-6, 'fit', true);
problem.bulk_out.set_fields(0, value=5.9e-6, fit=True)

# similarly bulk in can be changed
# problem.bulk_in.set_fields(0, value=5.9e-6, fit=True)

Scalefactors#

The scalefactors are another parameters block like the bulk phases. You can add and modify scalefactors similar as with the previous blocks.

problem.addScalefactor('New Scalefactor',0.9,1.0,1.1,true);
problem.setScalefactor(1,'value',1.01);
problem.scalefactors.append(name='New Scalefactor', min=0.9, value=1.0, max=1.1, fit=True)
problem.scalefactors.set_fields(0, value=1.01)

Backgrounds#

The backgrounds block is used to define the type of background applied to each contrast, and the parameters used to define the backgrounds themselves. The fittable parameters are in the ‘Background Params’ block, and the backgrounds themselves are in the ‘Backgrounds’ block:

    (a) Background Parameters: 

    p            Name             Min     Value     Max     Fit? 
    _    ____________________    _____    _____    _____    _____

    1    "Background Param 1"    1e-07    1e-06    1e-05    false

    (b) Backgrounds:  

    p         Name            Type             Value 1           Value 2    Value 3    Value 4    Value 5
    _    ______________    __________    ____________________    _______    _______    _______    _______

    1    "Background 1"    "constant"    "Background Param 1"      ""         ""         ""         ""   
+-------+--------------+----------+--------------------+---------+---------+---------+---------+
| index |     name     |   type   |      value 1       | value 2 | value 3 | value 4 | value 5 |
+-------+--------------+----------+--------------------+---------+---------+---------+---------+
|   0   | Background 1 | constant | Background Param 1 |         |         |         |         |
+-------+--------------+----------+--------------------+---------+---------+---------+---------+

The ‘Background Parameters’ is in fact another instance of the parametersClass, and there are corresponding methods to fit, set limits and so on for these.

The backgrounds can be one of three types: ‘constant’, ‘function’ or ‘data’. The three types are discussed in more detail below:

Note

Only ‘constant’ and ‘data’ are allowed in phase 1, and ‘function’ will be introduced in phase 2.

  • Constant - This is the normal background type from RasCAL-1. Each background requires one and only one Background Parameter associated with it, as follows:

problem.addBackgroundParam('My New BackPar', 1e-8, 1e-7, 1e-6, true);
problem.addBackground('My New Background','constant','My New BackPar');
problem.background_parameters.append(name='My New BackPar', min=1e-8, value=1e-7, max=1e-6, fit=True)
problem.backgrounds.append(name='My New Background', type='constant', value_1='My New BackPar')

With this code snippet we’ve made a new background, with the value taken from the (fittable) parameter called ‘My New BackPar’:

    (a) Background Parameters: 

    p            Name             Min     Value     Max     Fit? 
    _    ____________________    _____    _____    _____    _____

    1    "Background Param 1"    1e-07    1e-06    1e-05    false
    2    "My New BackPar"        1e-08    1e-07    1e-06    true 

    (b) Backgrounds:  

    p           Name               Type             Value 1           Value 2    Value 3    Value 4    Value 5
    _    ___________________    __________    ____________________    _______    _______    _______    _______

    1    "Background 1"         "constant"    "Background Param 1"      ""         ""         ""         ""   
    2    "My New Background"    "constant"    "My New BackPar"          ""         ""         ""         ""   
+-------+--------------------+-------+-------+-------+-------+------------+-----+-------+
| index |        name        |  min  | value |  max  |  fit  | prior type |  mu | sigma |
+-------+--------------------+-------+-------+-------+-------+------------+-----+-------+
|   0   | Background Param 1 | 1e-07 | 1e-06 | 1e-05 | False |  uniform   | 0.0 |  inf  |
|   1   |   My New BackPar   | 1e-08 | 1e-07 | 1e-06 |  True |  uniform   | 0.0 |  inf  |
+-------+--------------------+-------+-------+-------+-------+------------+-----+-------+
+-------+-------------------+----------+--------------------+---------+---------+---------+---------+
| index |        name       |   type   |      value 1       | value 2 | value 3 | value 4 | value 5 |
+-------+-------------------+----------+--------------------+---------+---------+---------+---------+
|   0   |    Background 1   | constant | Background Param 1 |         |         |         |         |
|   1   | My New Background | constant |   My New BackPar   |         |         |         |         |
+-------+-------------------+----------+--------------------+---------+---------+---------+---------+

This is then available to be used by any of our contrasts (see later).

  • Data - This option is used when a measured data background is available. Suppose our measured data is in a datafile loaded into the data block (see later), and called ‘My Background Data’. To define a data background, we simply specify this datafile in our background specification:

problem.addBackground('Data Background 1', 'data', 'My Background Data')
problem.backgrounds.append(name='Data Background 1', type='data', value_1='My Background Data')

This is then used in the reflectivity calculation for any contrast in which it is specified.

Note

No ‘Background Parameters’ are associated with data backgrounds. Also, take care to make sure that the background and data with which it is intended to be used have the same q values, otherwise an interpolation will be carried out which will be slower.

Resolutions#

As is the case for the backgrounds, the resolutions block is also split into two parts: a parameters block which defines the fittable parameters, and then the main Resolutions block which groups these as required into actual resolutions. The three types are:

  • Constant: The default type. A resolutionParameter defines the width of a sliding Gaussian window convolution applied to the data.

  • Function: Convolution of the data with an arbitrary, user defined function (not yet implemented).

  • Data: Convolution with a sliding Gaussian defined by a fourth column of a datafile.

Note

Only ‘Constant’ and ‘Data’ are implemented in phase 1. Convolution with an arbitrary function will be introduced in phase 2.

To define a resolution parameter, we use the addResolutionParam method:

problem.addResolutionParam('My Resolution Param', 0.02, 0.05, 0.08, true)
problem.resolution_parameters.append(name='My Resolution Param', min=0.02, value=0.05, max=0.08, fit=True)
    (a) Resolutions Parameters: 

    p           Name           Min     Value    Max     Fit? 
    _    __________________    ____    _____    ____    _____

    1    "Resolution par 1"    0.01    0.03     0.05    false

    (b) Resolutions:  

    p         Name            Type            Value 1          Value 2    Value 3    Value 4    Value 5
    _    ______________    __________    __________________    _______    _______    _______    _______

    1    "Resolution 1"    "constant"    "Resolution par 1"      ""         ""         ""         ""   
+-------+--------------------+------+-------+------+-------+------------+-----+-------+
| index |        name        | min  | value | max  |  fit  | prior type |  mu | sigma |
+-------+--------------------+------+-------+------+-------+------------+-----+-------+
|   0   | Resolution Param 1 | 0.01 |  0.03 | 0.05 | False |  uniform   | 0.0 |  inf  |
+-------+--------------------+------+-------+------+-------+------------+-----+-------+
+-------+--------------+----------+--------------------+---------+---------+---------+---------+
| index |     name     |   type   |      value 1       | value 2 | value 3 | value 4 | value 5 |
+-------+--------------+----------+--------------------+---------+---------+---------+---------+
|   0   | Resolution 1 | constant | Resolution Param 1 |         |         |         |         |
+-------+--------------+----------+--------------------+---------+---------+---------+---------+

Then, we make the actual resolution referring to whichever one of the resolution parameters:

problem.addResolution('My new resolution','constant','My Resolution Param')
problem.addResolution('My Data Resolution','data')
problem.resolutions.append(name='My new resolution', type='constant', value_1='My Resolution Param')
problem.resolutions.append(name='My Data Resolution', type='data')
    (a) Resolutions Parameters: 

    p            Name             Min     Value    Max     Fit? 
    _    _____________________    ____    _____    ____    _____

    1    "Resolution par 1"       0.01    0.03     0.05    false
    2    "My Resolution Param"    0.02    0.05     0.08    true 

    (b) Resolutions:  

    p            Name               Type              Value 1           Value 2    Value 3    Value 4    Value 5
    _    ____________________    __________    _____________________    _______    _______    _______    _______

    1    "Resolution 1"          "constant"    "Resolution par 1"         ""         ""         ""         ""   
    2    "My new resolution"     "constant"    "My Resolution Param"      ""         ""         ""         ""   
    3    "My Data Resolution"    "data"        ""                         ""         ""         ""         ""   
+-------+--------------------+----------+---------------------+---------+---------+---------+---------+
| index |        name        |   type   |       value 1       | value 2 | value 3 | value 4 | value 5 |
+-------+--------------------+----------+---------------------+---------+---------+---------+---------+
|   0   |    Resolution 1    | constant |  Resolution Param 1 |         |         |         |         |
|   1   | My new resolution  | constant | My Resolution Param |         |         |         |         |
|   2   | My Data Resolution |   data   |                     |         |         |         |         |
+-------+--------------------+----------+---------------------+---------+---------+---------+---------+

Note

There are no parameters with Data resolution. Instead this tells RAT to expect a fourth column in the datafile. If no fourth column exists in the data to which this is applied, RAT will throw an error at runtime.

Data#

The data block contains the data which defines at which points in q the reflectivity is calculated at each contrast. By default, it initialises with a single ‘Simulation’ entry:

        Name          Data       Data Range      Simulation Range   
    ____________    _________    __________    _____________________

    "Simulation"    "No Data"       "-"        "[ 0.0050 , 0.7000 ]"
+-------+------------+------+------------+------------------+
| index |    name    | data | data range | simulation range |
+-------+------------+------+------------+------------------+
|   0   | Simulation |  []  |     []     |   [0.005, 0.7]   |
+-------+------------+------+------------+------------------+

For each entry in the table there are four fields:

  • Name: The name you choose to give the datafile (for reference in the contrasts block)

  • Data: An array containing the data itself (empty for Simulation).

  • Data Range: The min / max range of the data you wish to include in the fit. As is the case for RasCAL, you do not have to include all the data in the calculation of chi-squared. This range cannot lie outside the range of any data added to the second column.

  • Simulation Range: The total range of the simulation to be calculated. This can lie outside the range of the data to allow for extrapolation, but must be >= the overall data range.

To add data, we first load it into Matlab, then create a new data entry containing it:

root = getappdata(0, 'root');
myData = readmatrix(fullfile(root, '/examples/normalReflectivity/customXY/c_PLP0016596.dat'));
problem.addData('My new datafile', myData)
import numpy as np
myData = np.loadtxt('c_PLP0016596.dat', delimiter=",")
problem.data.append(name='My new datafile', data=myData)

and out new dataset appears in the table:

          Name                    Data                   Data Range            Simulation Range   
    _________________    _______________________    _____________________    _____________________

    "Simulation"         "No Data"                  "-"                      "[ 0.0050 , 0.7000 ]"
    "My new datafile"    "Data array: [146 x 4]"    "[ 0.0057 , 0.3961 ]"    "[ 0.0057 , 0.3961 ]"
+-------+-----------------+-----------------------+----------------------+----------------------+
| index |       name      |          data         |      data range      |   simulation range   |
+-------+-----------------+-----------------------+----------------------+----------------------+
|   0   |    Simulation   |           []          |          []          |     [0.005, 0.7]     |
|   1   | My new datafile | Data array: [146 x 4] | [0.0057118, 0.39606] | [0.0057118, 0.39606] |
+-------+-----------------+-----------------------+----------------------+----------------------+

Note that we did not specify data or simulation ranges, and so these default to the min / max values of the data added. To change these (or anything else about the data entry) use the ‘setData’ method. Also note that this data has a fourth column, and so can be used as a data resolution if you wish.

Putting it all together – defining contrasts#

As is the case for RasCAL, once we have defined the various aspects of our project i.e. backgrounds, data and so on, we group these together into contrasts to make out fitting project. We can add a contrast using just its name, and edit it later, or we can specify which parts of our project we want to add to the contrast using name value pairs:

problem.addContrast('name', 'D-tail/H-Head/D2O',...
                    'background', 'Background D2O',...
                    'resolution', 'Resolution 1',...
                    'scalefactor', 'Scalefactor 1',...
                    'BulkOut', 'SLD D2O',...
                    'BulkIn', 'SLD Air',...
                    'data', 'D-tail / H-head / D2O');
problem.contrasts.append(name='D-tail/H-Head/D2O', background='Background D2O', resolution='Resolution 1',
                         scalefactor='Scalefactor 1', bulk_out='SLD D2O', bulk_in='SLD Air', data='D-tail / H-head / D2O')

The values which we add must refer to names within the other blocks of the project. So, if you try to add a scalefactor called ‘scalefactor1’ when this name doesn’t exist in the scalefactors block, then an error will result.

Once we have added the contrasts, then we need to set the model, either by adding layers for a standard layers project, or a custom model file (we discuss these in Custom Models). In the case of layers, we give a list of layer names, in order from bulk in to bulk out. So for a monolayer for example, we would specify tails and then heads in as shown below:

problem.setContrastModel(1, {'Deuterated Tails','Hydrogenated heads'});
problem.contrasts.set_fields(0, model=['Deuterated Tails','Hydrogenated heads'])

The data can be either a datafile or the simulation object in the data block. Once we have defined our contrasts they appear in the contrasts block at the end of the project when it is displayed.

The Monolayer Example In Full#

In the previous sections, we showed an example of a pre-loaded problem definition class, which we used to analyse data from two contrasts of a lipid monolayer. Now, rather than loading in a pre-defined version of this problem we can use our class methods to build this from scratch, and do the same analysis as we did there, but this time from a script.

To start, we first make an instance of the project class:

problem = createProject(name='DSPC monolayers');
import RATapi as RAT
problem = RAT.Project(name='DSPC monolayers')

Then we need to define the parameters we need. We’ll do this by making a parameters block, and adding these to project class:

% Define the parameters:
Parameters = {
    %       Name                min     val     max      fit?
    {'Tails Thickness',         10,     20,      30,     true};
    {'Heads Thickness',          3,     11,      16,     true};
    {'Tails Roughness',          2,     5,       9,      true};
    {'Heads Roughness',          2,     5,       9,      true};
    {'Deuterated Tails SLD',    4e-6,   6e-6,    2e-5,   true};
    {'Hydrogenated Tails SLD', -0.6e-6, -0.4e-6, 0,      true};
    {'Deuterated Heads SLD',    1e-6,   3e-6,    8e-6,   true};
    {'Hydrogenated Heads SLD',  0.1e-6, 1.4e-6,  3e-6,   true};
    {'Heads Hydration',         0,      0.3,     0.5,    true};
    };

problem.addParameterGroup(Parameters);
parameters = [RAT.models.Parameter(name='Tails Thickness', min=10, value=20, max=30, fit=True),
              RAT.models.Parameter(name='Heads Thickness', min=3, value=11, max=16, fit=True),
              RAT.models.Parameter(name='Tails Roughness', min=2, value=5, max=9, fit=True),
              RAT.models.Parameter(name='Heads Roughness', min=2, value=5, max=9, fit=True),
              RAT.models.Parameter(name='Deuterated Tails SLD', min=4e-6, value=6e-6, max=2e-5, fit=True),
              RAT.models.Parameter(name='Hydrogenated Tails SLD', min=-0.6e-6, value=-0.4e-6, max=0, fit=True),
              RAT.models.Parameter(name='Deuterated Heads SLD', min=1e-6, value=3e-6, max=8e-6, fit=True),
              RAT.models.Parameter(name='Hydrogenated Heads SLD', min=0.1e-6, value=1.4e-6, max=3e-6, fit=True),
              RAT.models.Parameter(name='Heads Hydration', min=0, value=0.3, max=0.5, fit=True)]

problem.parameters.extend(parameters)

Next we need to group the parameters into our layers. We need four layers in all, representing deuterated and hydrogenated versions of the heads and tails:

H_Heads = {'Hydrogenated Heads',...
        'Heads Thickness',...
        'Hydrogenated Heads SLD',...
        'Heads Roughness',...
        'Heads Hydration',...
        'bulk out' };

D_Heads = {'Deuterated Heads',...
        'Heads Thickness',...
        'Deuterated Heads SLD',...
        'Heads Roughness',...
        'Heads Hydration',...
        'bulk out' };

D_Tails = {'Deuterated Tails',...
        'Tails Thickness',...
        'Deuterated Tails SLD',...
        'Tails Roughness'};

H_Tails = {'Hydrogenated Tails',...
        'Tails Thickness',...
        'Hydrogenated Tails SLD',...
        'Tails Roughness'};
H_Heads = RAT.models.Layer(name='Hydrogenated Heads', thickness='Heads Thickness',
                           SLD='Hydrogenated Heads SLD', roughness='Heads Roughness',
                           hydration='Heads Hydration', hydrate_with='bulk out')

D_Heads = RAT.models.Layer(name='Deuterated Heads', thickness='Heads Thickness',
                           SLD='Deuterated Heads SLD', roughness='Heads Roughness',
                           hydration='Heads Hydration', hydrate_with='bulk out')

D_Tails = RAT.models.Layer(name='Deuterated Tails', thickness='Tails Thickness',
                           SLD='Deuterated Tails SLD', roughness='Tails Roughness')

H_Tails = RAT.models.Layer(name='Hydrogenated Tails', thickness='Tails Thickness',
                           SLD='Hydrogenated Tails SLD', roughness='Tails Roughness')

Note

The headgroups are hydrated and so share a hydration parameter, whereas the tails are not.

We now add our layers to the project:

problem.addLayerGroup({H_Heads; D_Heads; H_Tails; D_Tails});
problem.layers.extend([H_Heads, D_Heads, H_Tails, D_Tails])

We are using two different sub-phases: D2O and ACMW. We need a different constant background for each, so we need two bckground parameters. There is already one background parameter in the project as a default, so we rename this and add a second one:

problem.setBackgroundParamName(1, 'Backs Value ACMW'); % Use existing backsPar
problem.setBackgroundParamValue(1, 5.5e-6);
problem.addBackgroundParam('Backs Value D2O', 1e-8, 2.8e-6, 1e-5);
problem.background_parameters.set_fields(0, name='Backs Value ACMW')
problem.background_parameters.set_fields(0, value=5.5e-6)
problem.background_parameters.append(name='Backs Value D2O', min=1e-8, value=2.8e-6, max=1e-5)

Use these parameters to define two constant backgrounds, again using the existing default for one of them:

problem.addBackground('Background D2O', 'constant', 'Backs Value D2O');
problem.setBackground(1, 'name', 'Background ACMW', 'value1', 'Backs Value ACMW');
problem.backgrounds.append(name='Background D2O', type='constant', value_1='Backs Value D2O')
problem.backgrounds.set_fields(0, name='Background ACMW', value_1='Backs Value ACMW')

We need two sub-phases for our project. D2O is already in the project as a default, so we only need to add the bulk out for ACMW

problem.addBulkOut('SLD ACMW', -1e-6, 0.0, 1e-6, true);
problem.bulk_out.append(name='SLD ACMW', min=-0.6e-6, value=-0.56e-6, max=-0.3e-6, fit=True)

Now we need to add the data. We read in the two files into MATLAB, and put the data into the data block with appropriate names:

root = getappdata(0, 'root');
dataPath = '/examples/miscellaneous/convertRasCAL1Project/';
d13ACM = readmatrix(fullfile(root, dataPath, 'd13acmw20.dat'));
d70d2O = readmatrix(fullfile(root, dataPath, 'd70d2o20.dat'));
problem.addData('H-tail / D-head / ACMW', d13ACM);
problem.addData('D-tail / H-head / D2O', d70d2O);
import numpy as np
d13ACM = np.loadtxt('d13acmw20.dat', delimiter=",")
d70d2O = np.loadtxt('d70d2o20.dat', delimiter=",")
problem.data.append(name='H-tail / D-head / ACMW', data=d13ACM)
problem.data.append(name='D-tail / H-head / D2O', data=d70d2O)

We have everything we need to now build our contrasts. We have two contrasts in all, and we build them using name / value pairs for all the different parts of the contrasts (i.e. selecting which background and bulk phases etc we need using the names we have given them.)

problem.addContrast('name', 'D-tail/H-Head/D2O',...
                    'background', 'Background D2O',...
                    'resolution', 'Resolution 1',...
                    'scalefactor', 'Scalefactor 1',...
                    'BulkOut', 'SLD D2O',...
                    'BulkIn', 'SLD Air',...
                    'data', 'D-tail / H-head / D2O');

problem.addContrast('name', 'H-tail/D-Head/ACMW',...
                    'background', 'Background ACMW',...
                    'resolution', 'Resolution 1',...
                    'scalefactor', 'Scalefactor 1',...
                    'BulkOut', 'SLD ACMW',...
                    'BulkIn', 'SLD Air',...
                    'data', 'H-tail / D-head / ACMW');
problem.contrasts.append(name='D-tail/H-Head/D2O', background='Background D2O', resolution='Resolution 1',
                         scalefactor='Scalefactor 1', bulk_out='SLD D2O', bulk_in='SLD Air', data='D-tail / H-head / D2O')

problem.contrasts.append(name='H-tail/D-Head/ACMW', background='Background ACMW', resolution='Resolution 1',
                         scalefactor='Scalefactor 1', bulk_out='SLD ACMW', bulk_in='SLD Air', data='D-tail / H-head / D2O')

To define the models for each contrast, we add the relevant layers as appropriate:

problem.setContrastModel(1, {'Deuterated Tails','Hydrogenated heads'});
problem.setContrastModel(2, {'Hydrogenated Tails','Deuterated Heads'});
problem.contrasts.set_fields(0, model=['Deuterated Tails', 'Hydrogenated Heads'])
problem.contrasts.set_fields(1, model=['Hydrogenated Tails', 'Deuterated Heads'])

We need to make sure that we are fitting the relevant backgrounds, scalefactors and bulk phase values:

problem.setBackgroundParam(1, 'fit', true);
problem.setBackgroundParam(2, 'fit', true);
problem.setScalefactor(1, 'fit', true);
problem.setBulkOut(1, 'fit', true);
problem.background_parameters.set_fields(0, fit=True)
problem.background_parameters.set_fields(1, fit=True)
problem.scalefactors.set_fields(0, fit=True)
problem.bulk_out.set_fields(0, fit=True)

Now have a look at our project, to make sure it all looks reasonable

disp(problem)
print(problem)
         modelType: 'standard layers'
    experimentName: 'DSPC monolayers'
          geometry: 'air/substrate'


    Parameters: ---------------------------------------------------------------------------------------------- 

    p               Name               Min       Value      Max     Fit? 
    __    ________________________    ______    _______    _____    _____

     1    "Substrate Roughness"            1          3        5    true 
     2    "Tails Thickness"               10         20       30    true 
     3    "Heads Thickness"                3         11       16    true 
     4    "Tails Roughness"                2          5        9    true 
     5    "Heads Roughness"                2          5        9    true 
     6    "Deuterated Tails SLD"       4e-06      6e-06    2e-05    true 
     7    "Hydrogenated Tails SLD"    -6e-07     -4e-07        0    true 
     8    "Deuterated Heads SLD"       1e-06      3e-06    8e-06    true 
     9    "Hydrogenated Heads SLD"     1e-07    1.4e-06    3e-06    true 
    10    "Heads Hydration"                0        0.3      0.5    true 


    Bulk In: -------------------------------------------------------------------------------------------------- 

    p      Name       Min    Value    Max    Fit? 
    _    _________    ___    _____    ___    _____

    1    "SLD Air"     0       0       0     false


    Bulk Out: ------------------------------------------------------------------------------------------------- 

    p       Name         Min       Value        Max       Fit? 
    _    __________    _______    ________    ________    _____

    1    "SLD D2O"     6.2e-06    6.35e-06    6.35e-06    true 
    2    "SLD ACMW"     -1e-06           0       1e-06    true 


    Scalefactors: ------------------------------------------------------------------------------------------------- 

    p         Name          Min     Value    Max     Fit? 
    _    _______________    ____    _____    ____    _____

    1    "Scalefactor 1"    0.02    0.23     0.25    true 


    Backgrounds: ----------------------------------------------------------------------------------------------- 

    (a) Background Parameters: 

    p           Name            Min      Value      Max     Fit? 
    _    __________________    _____    _______    _____    _____

    1    "Backs Value ACMW"    1e-07    5.5e-06    1e-05    true 
    2    "Backs Value D2O"     1e-08    2.8e-06    1e-05    true 

    (b) Backgrounds:  

    p          Name              Type            Value 1          Value 2    Value 3    Value 4    Value 5
    _    _________________    __________    __________________    _______    _______    _______    _______

    1    "Background ACMW"    "constant"    "Backs Value ACMW"      ""         ""         ""         ""   
    2    "Background D2O"     "constant"    "Backs Value D2O"       ""         ""         ""         ""   


    Resolutions: --------------------------------------------------------------------------------------------- 

    (a) Resolutions Parameters: 

    p           Name           Min     Value    Max     Fit? 
    _    __________________    ____    _____    ____    _____

    1    "Resolution par 1"    0.01    0.03     0.05    false

    (b) Resolutions:  

    p         Name            Type            Value 1          Value 2    Value 3    Value 4    Value 5
    _    ______________    __________    __________________    _______    _______    _______    _______

    1    "Resolution 1"    "constant"    "Resolution par 1"      ""         ""         ""         ""   


    Layers: -------------------------------------------------------------------------------------------------- 

    p            Name                Thickness                  SLD                   Roughness            Hydration        Hydrate with
    _    ____________________    _________________    ________________________    _________________    _________________    ____________

    1    "Hydrogenated Heads"    "Heads Thickness"    "Hydrogenated Heads SLD"    "Heads Roughness"    "Heads Hydration"     "bulk out" 
    2    "Deuterated Heads"      "Heads Thickness"    "Deuterated Heads SLD"      "Heads Roughness"    "Heads Hydration"     "bulk out" 
    3    "Hydrogenated Tails"    "Tails Thickness"    "Hydrogenated Tails SLD"    "Tails Roughness"    ""                    "bulk out" 
    4    "Deuterated Tails"      "Tails Thickness"    "Deuterated Tails SLD"      "Tails Roughness"    ""                    "bulk out" 


    Custom Files: ------------------------------------------------------------------------------------------------------ 

    Name    Filename    Function Name    Language    Path
    ____    ________    _____________    ________    ____

     ""        ""            ""             ""        "" 


    Data: ------------------------------------------------------------------------------------------------------ 

              Name                       Data                  Data Range            Simulation Range   
    ________________________    ______________________    _____________________    _____________________

    "Simulation"                "No Data"                 "-"                      "[ 0.0050 , 0.7000 ]"
    "H-tail / D-head / ACMW"    "Data array: [51 x 3]"    "[ 0.0518 , 0.5888 ]"    "[ 0.0518 , 0.5888 ]"
    "D-tail / H-head / D2O"     "Data array: [51 x 3]"    "[ 0.0518 , 0.5888 ]"    "[ 0.0518 , 0.5888 ]"


   Contrasts: ----------------------------------------------------------------------------------------------- 

             p                        1                          2            
    ___________________    _______________________    ________________________

    "Name"                 "D-tail/H-Head/D2O"        "H-tail/D-Head/ACMW"    
    "Data"                 "D-tail / H-head / D2O"    "H-tail / D-head / ACMW"
    "Background"           "Background D2O"           "Background ACMW"       
    "Background Action"    "add"                      "add"                   
    "Bulk in"              "SLD Air"                  "SLD Air"               
    "Bulk out"             "SLD D2O"                  "SLD ACMW"              
    "Scalefactor"          "Scalefactor 1"            "Scalefactor 1"         
    "Resolution"           "Resolution 1"             "Resolution 1"          
    "Resample"             "false"                    "false"                 
    "Model"                "Deuterated Tails"         "Hydrogenated Tails"    
    ""                     "Hydrogenated Heads"       "Deuterated Heads"      
Name: ----------------------------------------------------------------------------------------------

DSPC monolayers

Calculation: ---------------------------------------------------------------------------------------

non polarised

Model: ---------------------------------------------------------------------------------------------

standard layers

Geometry: ------------------------------------------------------------------------------------------

air/substrate

Parameters: ----------------------------------------------------------------------------------------

+-------+------------------------+--------+---------+-------+------+------------+-----+-------+
| index |          name          |  min   |  value  |  max  | fit  | prior type |  mu | sigma |
+-------+------------------------+--------+---------+-------+------+------------+-----+-------+
|   0   |  Substrate Roughness   |  1.0   |   3.0   |  5.0  | True |  uniform   | 0.0 |  inf  |
|   1   |    Tails Thickness     |  10.0  |   20.0  |  30.0 | True |  uniform   | 0.0 |  inf  |
|   2   |    Heads Thickness     |  3.0   |   11.0  |  16.0 | True |  uniform   | 0.0 |  inf  |
|   3   |    Tails Roughness     |  2.0   |   5.0   |  9.0  | True |  uniform   | 0.0 |  inf  |
|   4   |    Heads Roughness     |  2.0   |   5.0   |  9.0  | True |  uniform   | 0.0 |  inf  |
|   5   |  Deuterated Tails SLD  | 4e-06  |  6e-06  | 2e-05 | True |  uniform   | 0.0 |  inf  |
|   6   | Hydrogenated Tails SLD | -6e-07 |  -4e-07 |  0.0  | True |  uniform   | 0.0 |  inf  |
|   7   |  Deuterated Heads SLD  | 1e-06  |  3e-06  | 8e-06 | True |  uniform   | 0.0 |  inf  |
|   8   | Hydrogenated Heads SLD | 1e-07  | 1.4e-06 | 3e-06 | True |  uniform   | 0.0 |  inf  |
|   9   |    Heads Hydration     |  0.0   |   0.3   |  0.5  | True |  uniform   | 0.0 |  inf  |
+-------+------------------------+--------+---------+-------+------+------------+-----+-------+

Bulk In: -------------------------------------------------------------------------------------------

+-------+---------+-----+-------+-----+-------+------------+-----+-------+
| index |   name  | min | value | max |  fit  | prior type |  mu | sigma |
+-------+---------+-----+-------+-----+-------+------------+-----+-------+
|   0   | SLD Air | 0.0 |  0.0  | 0.0 | False |  uniform   | 0.0 |  inf  |
+-------+---------+-----+-------+-----+-------+------------+-----+-------+

Bulk Out: ------------------------------------------------------------------------------------------

+-------+----------+---------+----------+----------+------+------------+-----+-------+
| index |   name   |   min   |  value   |   max    | fit  | prior type |  mu | sigma |
+-------+----------+---------+----------+----------+------+------------+-----+-------+
|   0   | SLD D2O  | 6.2e-06 | 6.35e-06 | 6.35e-06 | True |  uniform   | 0.0 |  inf  |
|   1   | SLD ACMW |  -6e-07 | -5.6e-07 |  -3e-07  | True |  uniform   | 0.0 |  inf  |
+-------+----------+---------+----------+----------+------+------------+-----+-------+

Scalefactors: --------------------------------------------------------------------------------------

+-------+---------------+------+-------+------+------+------------+-----+-------+
| index |      name     | min  | value | max  | fit  | prior type |  mu | sigma |
+-------+---------------+------+-------+------+------+------------+-----+-------+
|   0   | Scalefactor 1 | 0.02 |  0.23 | 0.25 | True |  uniform   | 0.0 |  inf  |
+-------+---------------+------+-------+------+------+------------+-----+-------+

Background Parameters: -----------------------------------------------------------------------------

+-------+------------------+-------+---------+-------+------+------------+-----+-------+
| index |       name       |  min  |  value  |  max  | fit  | prior type |  mu | sigma |
+-------+------------------+-------+---------+-------+------+------------+-----+-------+
|   0   | Backs Value ACMW | 1e-07 | 5.5e-06 | 1e-05 | True |  uniform   | 0.0 |  inf  |
|   1   | Backs Value D2O  | 1e-08 | 2.8e-06 | 1e-05 | True |  uniform   | 0.0 |  inf  |
+-------+------------------+-------+---------+-------+------+------------+-----+-------+

Backgrounds: ---------------------------------------------------------------------------------------

+-------+-----------------+----------+------------------+---------+---------+---------+---------+
| index |       name      |   type   |     value 1      | value 2 | value 3 | value 4 | value 5 |
+-------+-----------------+----------+------------------+---------+---------+---------+---------+
|   0   | Background ACMW | constant | Backs Value ACMW |         |         |         |         |
|   1   |  Background D2O | constant | Backs Value D2O  |         |         |         |         |
+-------+-----------------+----------+------------------+---------+---------+---------+---------+

Resolution Parameters: -----------------------------------------------------------------------------

+-------+--------------------+------+-------+------+-------+------------+-----+-------+
| index |        name        | min  | value | max  |  fit  | prior type |  mu | sigma |
+-------+--------------------+------+-------+------+-------+------------+-----+-------+
|   0   | Resolution Param 1 | 0.01 |  0.03 | 0.05 | False |  uniform   | 0.0 |  inf  |
+-------+--------------------+------+-------+------+-------+------------+-----+-------+

Resolutions: ---------------------------------------------------------------------------------------

+-------+--------------+----------+--------------------+---------+---------+---------+---------+
| index |     name     |   type   |      value 1       | value 2 | value 3 | value 4 | value 5 |
+-------+--------------+----------+--------------------+---------+---------+---------+---------+
|   0   | Resolution 1 | constant | Resolution Param 1 |         |         |         |         |
+-------+--------------+----------+--------------------+---------+---------+---------+---------+

Data: ----------------------------------------------------------------------------------------------

+-------+------------------------+----------------------+---------------------+---------------------+
| index |          name          |         data         |      data range     |   simulation range  |
+-------+------------------------+----------------------+---------------------+---------------------+
|   0   |       Simulation       |          []          |          []         |     [0.005, 0.7]    |
|   1   | H-tail / D-head / ACMW | Data array: [51 x 3] | [0.051793, 0.58877] | [0.051793, 0.58877] |
|   2   | D-tail / H-head / D2O  | Data array: [51 x 3] | [0.051793, 0.58877] | [0.051793, 0.58877] |
+-------+------------------------+----------------------+---------------------+---------------------+

Layers: --------------------------------------------------------------------------------------------

+-------+--------------------+-----------------+------------------------+-----------------+-----------------+--------------+
| index |        name        |    thickness    |          SLD           |    roughness    |    hydration    | hydrate with |
+-------+--------------------+-----------------+------------------------+-----------------+-----------------+--------------+
|   0   | Hydrogenated Heads | Heads Thickness | Hydrogenated Heads SLD | Heads Roughness | Heads Hydration |   bulk out   |
|   1   |  Deuterated Heads  | Heads Thickness |  Deuterated Heads SLD  | Heads Roughness | Heads Hydration |   bulk out   |
|   2   | Hydrogenated Tails | Tails Thickness | Hydrogenated Tails SLD | Tails Roughness |                 |   bulk out   |
|   3   |  Deuterated Tails  | Tails Thickness |  Deuterated Tails SLD  | Tails Roughness |                 |   bulk out   |
+-------+--------------------+-----------------+------------------------+-----------------+-----------------+--------------+

Contrasts: -----------------------------------------------------------------------------------------

+-------+--------------------+-----------------------+-----------------+-------------------+---------+----------+---------------+--------------+----------+--------------------+
| index |        name        |          data         |    background   | background action | bulk in | bulk out |  scalefactor  |  resolution  | resample |       model        |
+-------+--------------------+-----------------------+-----------------+-------------------+---------+----------+---------------+--------------+----------+--------------------+
|   0   | D-tail/H-Head/D2O  | D-tail / H-head / D2O |  Background D2O |        add        | SLD Air | SLD D2O  | Scalefactor 1 | Resolution 1 |  False   |  Deuterated Tails  |
|       |                    |                       |                 |                   |         |          |               |              |          | Hydrogenated Heads |
|   1   | H-tail/D-Head/ACMW | D-tail / H-head / D2O | Background ACMW |        add        | SLD Air | SLD ACMW | Scalefactor 1 | Resolution 1 |  False   | Hydrogenated Tails |
|       |                    |                       |                 |                   |         |          |               |              |          |  Deuterated Heads  |
+-------+--------------------+-----------------------+-----------------+-------------------+---------+----------+---------------+--------------+----------+--------------------+

Now we’ll calculate this to check the agreement with the data. We need an instance of the controls class, with the procedure attribute set to calculate (the default):

controls = controlsClass();
disp(controls)
controls = RAT.Controls();
print(controls)
  controlsClass with properties:

            parallel: 'single'
           procedure: 'calculate'
    calcSldDuringFit: 0
             display: 'iter'
    resampleMinAngle: 0.9000
     resampleNPoints: 50
+------------------+-----------+
|     Property     |   Value   |
+------------------+-----------+
|    procedure     | calculate |
|     parallel     |   single  |
| calcSldDuringFit |   False   |
| resampleMinAngle |    0.9    |
| resampleNPoints  |     50    |
|     display      |    off    |
+------------------+-----------+

We then send all of this to RAT, and plot the output:

[problem,results] = RAT(problem,controls);
problem, results = RAT.run(problem, controls)
Starting RAT ________________________________________________________________________________________________

Elapsed time is 0.005719 seconds.

Finished RAT ______________________________________________________________________________________________ 

figure(1); clf;
plotRefSLD(problem, results)

Displays reflectivity and SLD plot

To do a fit, we change the procedure attribute of the controls class to simplex. We will also change the ‘parallel’ option to ‘contrasts’, so that each contrast gets its own calculation thread, and modify the output to only display the final result (rather than each iteration) and then run our fit and plot the results:

controls.procedure = 'simplex';
controls.parallel = 'contrasts';
controls.display = 'final';
[problem, results] = RAT(problem, controls)
controls = RAT.Controls(procedure='simplex', parallel='contrasts', display='final')
problem, results = RAT.run(problem, controls)
Starting RAT ________________________________________________________________________________________________


Running simplex


Exiting: Max iterations reached
Elapsed time is 0.210978 seconds.

Finished RAT ______________________________________________________________________________________________ 
Starting RAT ───────────────────────────────────────────────────────────────────────────────────────────────────────────


Running simplex


Exiting: Max iterations reached
Elapsed time is 0.281 seconds

Finished RAT ───────────────────────────────────────────────────────────────────────────────────────────────────────────
disp(results)
print(results)
          reflectivity: {2x1 cell}
            simulation: {2x1 cell}
           shiftedData: {2x1 cell}
             layerSlds: {2x1 cell}
           sldProfiles: {2x1 cell}
       resampledLayers: {2x1 cell}
    calculationResults: [1x1 struct]
        contrastParams: [1x1 struct]
             fitParams: [15x1 double]
              fitNames: {15x1 cell}
reflectivity = [Data array: [51 x 2], Data array: [51 x 2]],
simulation = [Data array: [51 x 2], Data array: [51 x 2]],
shiftedData = [Data array: [51 x 3], Data array: [51 x 3]],
layerSlds = [[Data array: [2 x 3]], [Data array: [2 x 3]]],
sldProfiles = [[Data array: [178 x 2]], [Data array: [178 x 2]]],
resampledLayers = [[Data array: [1 x 3]], [Data array: [1 x 3]]],
calculationResults = CalculationResults(
	chiValues = [15.32099818 76.08846334],
	sumChi = 91.4094615197768,
),
contrastParams = ContrastParams(
	backgroundParams = [3.52601782e-07 5.84837824e-06],
	scalefactors = [0.2478306 0.2478306],
	bulkIn = [0. 0.],
	bulkOut = [ 6.31672040e-06 -5.52469914e-07],
	resolutionParams = [0.03 0.03],
	subRoughs = [2.9962268 2.9962268],
	resample = [0. 0.],
),
fitParams = [2.9962268],
fitNames = ['Substrate Roughness', 'Tails Thickness', 'Heads Thickness', 'Tails Roughness', 'Heads Roughness', 'Deuterated Tails SLD', 'Hydrogenated Tails SLD', 'Deuterated Heads SLD', 'Hydrogenated Heads SLD', 'Heads Hydration', 'Backs Value ACMW', 'Backs Value D2O', 'Scalefactor 1', 'SLD D2O', 'SLD ACMW'],

We can now plot the results of our fit:

figure; clf;
plotRefSLD(out,results)
RAT.plotting.plot_ref_sld(problem, results)
Displays reflectivity and SLD plot