The layer stack

The sample and the surrounding medium are described by a stack of layers. The layers are stacked along the positive z-axis. The first layer in the stack is used to describe the medium above the top sample surface and the last layer in the stack is used to describe the medium bellow the bottom sample surfaces.

The classes that allow definition of individual layers and forming of layer stacks can be found in the xopto.mcml.mclayer.layer module. The module is for convenience also imported into the main simulator module xopto.mcml.mc.

A layer is an instance of xopto.mcml.mclayer.layer.Layer. The constructor takes several parameters that define the geometry and optical properties of the layer material.

  1. The layer thickness is defined by parameter d (m).

  2. The refractive index is defined by parameter n.

  3. The scattering coefficient is defined by parameter mus (m -1).

  4. The absorption coefficient is defined by parameter mua (m -1).

  5. The scattering phase function is defined by parameter pf that can be any instance of xopto.mcbase.mcpf.pfbase.PfBase.

The following example creates a layer with a refractive index 1.33, absorption coefficient 1 cm -1 , scattering coefficient 50 cm -1, thickness 10 mm and Henyey-Greenstein scattering phase function with anisotropy 0.9.

from xopto.mcml import mc

layer = mc.mclayer.Layer(d=0.01, n=1.33, mua=1.0e2, mus=50.0e2, pf=mc.mcpf.Hg(0.9))

All the optical and geometrical properties of a layer that were set through the constructor xopto.mcml.mclayer.layer.Layer() can be later changed through accessing the instance properties. In case of the scattering phase function, first access the pf layer property and from there any of the properties implemented by the scattering phase function model. Note that the Henyey-Greenstein scattering phase function from this example exposes only the anisotropy g.

layer.mua = 0.5e2
layer.mus = 40.0e2
layer.d = 0.015
layer.n = 1.452
layer.pf.g = 0.9

The individual layers are then combined into a stack through the Layers(). The constructor takes a list of Layer. The created instance manages the transfer of data between the host and the OpenCL device.

layers = mc.mclayer.Layers(
    [
        mc.mclayer.Layer(d=0.0, n=1.0, mua=0.0e2, mus=0.0e2,  pf=mc.mcpf.Hg(0.0)),
        mc.mclayer.Layer(d=0.1, n=1.3, mua=1.0e2, mus=50.0e2, pf=mc.mcpf.Hg(0.9)),
        mc.mclayer.Layer(d=0.0, n=1.0, mua=0.0e2, mus=0.0e2,  pf=mc.mcpf.Hg(0.0))
    ]
)

Note

The first and last layer in the stack represent the surrounding medium. The absorption coefficient mua, scattering coefficient mus and the scattering phase function pf of the topmost and bottommost layers are not used in the MC simulations, since the photon packets are not propagated through the surrounding medium. However, the refractive index n of the two outermost layers is used to properly refract/reflect the photon packet at the layer boundaries when launched by the source or when escaping the sample.

The properties of layers in the layer stack can be modified at any time through accessing the individual layers and from there the layer properties. The number of layers (including the two layers of the surrounding medium) can be determined through the builtin len(). The individual layers can be accessed using the [] operator or layer() method.

layers[1].mua = 0.5e2
layers.layer(1).mua = 0.5e2

num_layers = len(layers)

The Layers and Layer produce an informative human-readable output when used with the print() builtin.

Applying print() to an individual layer (instances of Layer) will produce the following output:

print(layers[1])
Layer(d=0.1, n=1.3, mua=100.0, mus=5000.0, pf=Hg(g=0.9)) # id 0x7F15B4CEF820.

Applying print() to a layer stack (instance of Layers) will produce the following output:

print(layers)
Layers([
    Layer(d=0.0, n=1.0, mua=0.0, mus=0.0, pf=Hg(g=0.0)),  # medium above the sample,
    Layer(d=0.1, n=1.3, mua=100.0, mus=5000.0, pf=Hg(g=0.9)),
    Layer(d=0.0, n=1.0, mua=0.0, mus=0.0, pf=Hg(g=0.0))   # medium bellow the sample
]) # id 0x7F15B4CEFD30.