This page was generated from the notebook DSPC_custom_layers.ipynb found in the Python-RAT repository. Download notebook.

Note

To get the output project and results from this example in your Python session, run:

from RATapi.examples import DSPC_custom_layers
project, results = DSPC_custom_layers()

[1]:
import pathlib

import numpy as np
from IPython.display import Code

import RATapi as RAT
from RATapi.models import Parameter

Custom Layers Example for Supported DSPC layer#

Example of using Custom layers to model a DSPC supported bilayer. Start by making the project and setting it to a custom layers type:

[2]:
problem = RAT.Project(name="Orso lipid example - custom layers", model="custom layers", geometry="substrate/liquid")

For a custom layers model, rather than being forced to define our layers as [Thick SLD Rough…. etc], we can parameterise however we like and then use a function to calculate the [d \(\rho\) \(\sigma\)] arrangement for each layer. So for example, if the volume of lipid tails are known (from the literature), then all we need is the Area per molecule, because then:

\[d = \frac{V}{APM},\]

where d is the thickness and V is the volume.

Likewise, the SLD is:

\[\rho = \frac{\sum_{i}n_{i}b_{i}}{V},\]

as usual.

In this folder there is a pre-prepared Python custom model for a DSPC on a Silicon substrate. We can display it here to see what we mean:

[3]:
Code(filename='custom_bilayer_DSPC.py', language='python')
[3]:
import numpy as np


def custom_bilayer_DSPC(params, bulk_in, bulk_out, contrast):
    """CUSTOMBILAYER RAT Custom Layer Model File.

    This file accepts 3 vectors containing the values for params, bulk in and bulk out.
    The final parameter is an index of the contrast being calculated.

    The function should output a matrix of layer values, in the form...

    Output = [thick 1, SLD 1, Rough 1, Percent Hydration 1, Hydrate how 1
              ....
              thick n, SLD n, Rough n, Percent Hydration n, Hydration how n]

    The "hydrate how" parameter decides if the layer is hydrated with Bulk out or Bulk in phases.
    Set to 1 for Bulk out, zero for Bulk in.
    Alternatively, leave out hydration and just return...

    Output = [thick 1, SLD 1, Rough 1,
              ....
              thick n, SLD n, Rough n]

    The second output parameter should be the substrate roughness.
    """
    sub_rough = params[0]
    oxide_thick = params[1]
    oxide_hydration = params[2]
    lipidAPM = params[3]
    headHydration = params[4]
    bilayerHydration = params[5]
    bilayerRough = params[6]
    waterThick = params[7]

    # We have a constant SLD for the bilayer
    oxide_SLD = 3.41e-6

    # Now make the lipid layers
    # Use known lipid volume and compositions to make the layers

    # define all the neutron b's.
    bc = 0.6646e-4  # Carbon
    bo = 0.5843e-4  # Oxygen
    bh = -0.3739e-4  # Hydrogen
    bp = 0.513e-4  # Phosphorus
    bn = 0.936e-4  # Nitrogen

    # Now make the lipid groups
    COO = (4 * bo) + (2 * bc)
    GLYC = (3 * bc) + (5 * bh)
    CH3 = (2 * bc) + (6 * bh)
    PO4 = (1 * bp) + (4 * bo)
    CH2 = (1 * bc) + (2 * bh)
    CHOL = (5 * bc) + (12 * bh) + (1 * bn)

    # Group these into heads and tails:
    Head = CHOL + PO4 + GLYC + COO
    Tails = (34 * CH2) + (2 * CH3)

    # We need volumes for each. Use literature values:
    vHead = 319
    vTail = 782

    # We use the volumes to calculate the SLDs
    SLDhead = Head / vHead
    SLDtail = Tails / vTail

    # We calculate the layer thickness' from the volumes and the APM
    headThick = vHead / lipidAPM
    tailThick = vTail / lipidAPM

    # Manually deal with hydration for layers in this example.
    oxSLD = (oxide_hydration * bulk_out[contrast]) + ((1 - oxide_hydration) * oxide_SLD)
    headSLD = (headHydration * bulk_out[contrast]) + ((1 - headHydration) * SLDhead)
    tailSLD = (bilayerHydration * bulk_out[contrast]) + ((1 - bilayerHydration) * SLDtail)

    # Make the layers
    oxide = [oxide_thick, oxSLD, sub_rough]
    water = [waterThick, bulk_out[contrast], bilayerRough]
    head = [headThick, headSLD, bilayerRough]
    tail = [tailThick, tailSLD, bilayerRough]

    output = np.array([oxide, water, head, tail, tail, head])

    return output, sub_rough

We need to add the parameters we are going to need to define the model (note that Substrate Roughness always exists as parameter 0 as before, and that we are setting a Gaussian prior on the Head Hydration here).

[4]:
parameter_list = [
    Parameter(name="Oxide Thickness", min=5.0, value=20.0, max=60.0, fit=True),
    Parameter(name="Oxide Hydration", min=0.0, value=0.2, max=0.5, fit=True),
    Parameter(name="Lipid APM", min=45.0, value=55.0, max=65.0, fit=True),
    Parameter(name="Head Hydration", min=0.0, value=0.2, max=0.5, fit=True, prior_type='gaussian', mu=0.3, sigma=0.03),
    Parameter(name="Bilayer Hydration", min=0.0, value=0.1, max=0.2, fit=True),
    Parameter(name="Bilayer Roughness", min=2.0, value=4.0, max=8.0, fit=True),
    Parameter(name="Water Thickness", min=0.0, value=2.0, max=10.0, fit=True)
]

problem.parameters.extend(parameter_list)
problem.parameters.set_fields(0, min=1.0, max=10.0)

Need to add the relevant Bulk SLD’s. Change the bulk in from air to silicon, and add two additional water contrasts:

[5]:
# Change the bulk in from air to silicon:
problem.bulk_in.set_fields(0, name="Silicon", min=2.07e-6, value=2.073e-6, max=2.08e-6, fit=False)

problem.bulk_out.append(name="SLD SMW", min=1.0e-6, value=2.073e-6, max=3.0e-6, fit=True)
problem.bulk_out.append(name="SLD H2O", min=-0.6e-6, value=-0.56e-6, max=-0.3e-6, fit=True)

problem.bulk_out.set_fields(0, min=5.0e-6, fit=True)

Now add the datafiles. We have three datasets we need to consider - the bilayer against D2O, Silicon Matched water and H2O. Load these datafiles in and put them in the data block:

[6]:
# Read in the datafiles
data_path = pathlib.Path("../data")
D2O_data = np.loadtxt(data_path / "c_PLP0016596.dat", delimiter=",")
SMW_data = np.loadtxt(data_path / "c_PLP0016601.dat", delimiter=",")
H2O_data = np.loadtxt(data_path / "c_PLP0016607.dat", delimiter=",")

# Add the data to the project - note this data has a resolution 4th column
problem.data.append(name="Bilayer / D2O", data=D2O_data, data_range=[0.013, 0.37])
problem.data.append(name="Bilayer / SMW", data=SMW_data, data_range=[0.013, 0.32996])
problem.data.append(name="Bilayer / H2O", data=H2O_data, data_range=[0.013, 0.33048])

Add the custom file to the project:

[7]:
problem.custom_files.append(name="DSPC Model", filename="custom_bilayer_DSPC.py", language="python", path=pathlib.Path.cwd().resolve())

Also, add the relevant background parameters - one each for each contrast:

[8]:
problem.background_parameters.set_fields(0, name="Background parameter D2O", min=1.0e-10, max=1.0e-5, value=1.0e-07, fit=True)

problem.background_parameters.append(name="Background parameter SMW", min=1.0e-10, value=1.0e-7, max=1.0e-5, fit=True)
problem.background_parameters.append(name="Background parameter H2O", min=1.0e-10, value=1.0e-7, max=1.0e-5, fit=True)

# And add the two new constant backgrounds
problem.backgrounds.append(name="Background SMW", type="constant", source="Background parameter SMW")
problem.backgrounds.append(name="Background H2O", type="constant", source="Background parameter H2O")

# And edit the other one
problem.backgrounds.set_fields(0, name="Background D2O", source="Background parameter D2O")

# Finally modify some of the other parameters to be more suitable values for a solid / liquid experiment
problem.scalefactors.set_fields(0, value=1.0, min=0.5, max=2.0, fit=True)

We need to use the data resolution (i.e. the fourth column of our datafiles). Do do this, we need to add a ‘Data’ resolution object to our resolutions table

[9]:
problem.resolutions.append(name="Data Resolution", type="data")

Now add the three contrasts as before:

[10]:
problem.contrasts.append(
    name="Bilayer / D2O",
    background="Background D2O",
    resolution="Data Resolution",
    scalefactor="Scalefactor 1",
    bulk_out="SLD D2O",
    bulk_in="Silicon",
    data="Bilayer / D2O",
    model=["DSPC Model"],
)

problem.contrasts.append(
    name="Bilayer / SMW",
    background="Background SMW",
    resolution="Data Resolution",
    scalefactor="Scalefactor 1",
    bulk_out="SLD SMW",
    bulk_in="Silicon",
    data="Bilayer / SMW",
    model=["DSPC Model"],
)

problem.contrasts.append(
    name="Bilayer / H2O",
    background="Background H2O",
    resolution="Data Resolution",
    scalefactor="Scalefactor 1",
    bulk_out="SLD H2O",
    bulk_in="Silicon",
    data="Bilayer / H2O",
    model=["DSPC Model"],
)

Note that the model is simply the custom file we’ve just added to the project.

Look at the complete model definition before sending it to RAT:

[11]:
print(problem)
Name: ----------------------------------------------------------------------------------------------

Orso lipid example - custom layers

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

non polarised

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

custom layers

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

substrate/liquid

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

+-------+---------------------+------+-------+------+------+------------+-----+-------+
| index |         name        | min  | value | max  | fit  | prior type |  mu | sigma |
+-------+---------------------+------+-------+------+------+------------+-----+-------+
|   0   | Substrate Roughness | 1.0  |  3.0  | 10.0 | True |  uniform   | 0.0 |  inf  |
|   1   |   Oxide Thickness   | 5.0  |  20.0 | 60.0 | True |  uniform   | 0.0 |  inf  |
|   2   |   Oxide Hydration   | 0.0  |  0.2  | 0.5  | True |  uniform   | 0.0 |  inf  |
|   3   |      Lipid APM      | 45.0 |  55.0 | 65.0 | True |  uniform   | 0.0 |  inf  |
|   4   |    Head Hydration   | 0.0  |  0.2  | 0.5  | True |  gaussian  | 0.3 |  0.03 |
|   5   |  Bilayer Hydration  | 0.0  |  0.1  | 0.2  | True |  uniform   | 0.0 |  inf  |
|   6   |  Bilayer Roughness  | 2.0  |  4.0  | 8.0  | True |  uniform   | 0.0 |  inf  |
|   7   |   Water Thickness   | 0.0  |  2.0  | 10.0 | True |  uniform   | 0.0 |  inf  |
+-------+---------------------+------+-------+------+------+------------+-----+-------+

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

+-------+---------+----------+-----------+----------+-------+------------+-----+-------+
| index |   name  |   min    |   value   |   max    |  fit  | prior type |  mu | sigma |
+-------+---------+----------+-----------+----------+-------+------------+-----+-------+
|   0   | Silicon | 2.07e-06 | 2.073e-06 | 2.08e-06 | False |  uniform   | 0.0 |  inf  |
+-------+---------+----------+-----------+----------+-------+------------+-----+-------+

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

+-------+---------+--------+-----------+----------+------+------------+-----+-------+
| index |   name  |  min   |   value   |   max    | fit  | prior type |  mu | sigma |
+-------+---------+--------+-----------+----------+------+------------+-----+-------+
|   0   | SLD D2O | 5e-06  |  6.35e-06 | 6.35e-06 | True |  uniform   | 0.0 |  inf  |
|   1   | SLD SMW | 1e-06  | 2.073e-06 |  3e-06   | True |  uniform   | 0.0 |  inf  |
|   2   | SLD H2O | -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.5 |  1.0  | 2.0 | True |  uniform   | 0.0 |  inf  |
+-------+---------------+-----+-------+-----+------+------------+-----+-------+

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

+-------+--------------------------+-------+-------+-------+------+------------+-----+-------+
| index |           name           |  min  | value |  max  | fit  | prior type |  mu | sigma |
+-------+--------------------------+-------+-------+-------+------+------------+-----+-------+
|   0   | Background parameter D2O | 1e-10 | 1e-07 | 1e-05 | True |  uniform   | 0.0 |  inf  |
|   1   | Background parameter SMW | 1e-10 | 1e-07 | 1e-05 | True |  uniform   | 0.0 |  inf  |
|   2   | Background parameter H2O | 1e-10 | 1e-07 | 1e-05 | True |  uniform   | 0.0 |  inf  |
+-------+--------------------------+-------+-------+-------+------+------------+-----+-------+

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

+-------+----------------+----------+--------------------------+---------+---------+---------+---------+
| index |      name      |   type   |         value 1          | value 2 | value 3 | value 4 | value 5 |
+-------+----------------+----------+--------------------------+---------+---------+---------+---------+
|   0   | Background D2O | constant | Background parameter D2O |         |         |         |         |
|   1   | Background SMW | constant | Background parameter SMW |         |         |         |         |
|   2   | Background H2O | constant | Background parameter H2O |         |         |         |         |
+-------+----------------+----------+--------------------------+---------+---------+---------+---------+

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 |         |         |         |         |
|   1   | Data Resolution |   data   |                    |         |         |         |         |
+-------+-----------------+----------+--------------------+---------+---------+---------+---------+

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

+-------+------------+------------------------+---------------------+----------+-------------------------------------------------------------------------+
| index |    name    |        filename        |    function name    | language |                                   path                                  |
+-------+------------+------------------------+---------------------+----------+-------------------------------------------------------------------------+
|   0   | DSPC Model | custom_bilayer_DSPC.py | custom_bilayer_DSPC |  python  | /mnt/c/Users/gnn85523/projects/python-RAT/RATapi/examples/non_polarised |
+-------+------------+------------------------+---------------------+----------+-------------------------------------------------------------------------+

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

+-------+---------------+-----------------------+------------------+----------------------+
| index |      name     |          data         |    data range    |   simulation range   |
+-------+---------------+-----------------------+------------------+----------------------+
|   0   |   Simulation  |           []          |        []        |     [0.005, 0.7]     |
|   1   | Bilayer / D2O | Data array: [146 x 4] |  [0.013, 0.37]   | [0.0057118, 0.39606] |
|   2   | Bilayer / SMW |  Data array: [97 x 4] | [0.013, 0.32996] | [0.0076029, 0.32996] |
|   3   | Bilayer / H2O | Data array: [104 x 4] | [0.013, 0.33048] | [0.0063374, 0.33048] |
+-------+---------------+-----------------------+------------------+----------------------+

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

+-------+---------------+---------------+----------------+-------------------+---------+----------+---------------+-----------------+----------+------------+
| index |      name     |      data     |   background   | background action | bulk in | bulk out |  scalefactor  |    resolution   | resample |   model    |
+-------+---------------+---------------+----------------+-------------------+---------+----------+---------------+-----------------+----------+------------+
|   0   | Bilayer / D2O | Bilayer / D2O | Background D2O |        add        | Silicon | SLD D2O  | Scalefactor 1 | Data Resolution |  False   | DSPC Model |
|   1   | Bilayer / SMW | Bilayer / SMW | Background SMW |        add        | Silicon | SLD SMW  | Scalefactor 1 | Data Resolution |  False   | DSPC Model |
|   2   | Bilayer / H2O | Bilayer / H2O | Background H2O |        add        | Silicon | SLD H2O  | Scalefactor 1 | Data Resolution |  False   | DSPC Model |
+-------+---------------+---------------+----------------+-------------------+---------+----------+---------------+-----------------+----------+------------+


To run it, we need to make a controls block

[12]:
controls = RAT.Controls()
print(controls)
+------------------+-----------+
|     Property     |   Value   |
+------------------+-----------+
|    procedure     | calculate |
|     parallel     |   single  |
| calcSldDuringFit |   False   |
| resampleMinAngle |    0.9    |
| resampleNPoints  |     50    |
|     display      |    iter   |
+------------------+-----------+

… and send this to RAT

[13]:
problem, results = RAT.run(problem, controls)
RAT.plotting.plot_ref_sld(problem, results)
Starting RAT ───────────────────────────────────────────────────────────────────────────────────────────────────────────

Elapsed time is 0.020 seconds

Finished RAT ───────────────────────────────────────────────────────────────────────────────────────────────────────────

../../_images/python_examples_notebooks_DSPC_custom_layers_24_1.png