Scattering Models
The scatteringmodel module
provides tools to calculate scattering amplitudes and form factors of multicomponent systems
consisting of spherical particles.
Overview
Particles and Layers
Particles are represented by Particle
objects composed of layers, each represented by a specific scattering length density profile.
These layers can have different scattering properties, which are
defined by the LayerProfile
interface. The module includes several predefined layer profiles:
- EmptyProfile: Represents an empty layer.
- ConstantProfile: Represents a layer with constant contrast.
- LinearProfile: Represents a layer with linearly varying contrast.
ParticleBuilder
The ParticleBuilder class is a
utility to help construct particles layer by layer. Once the desired layers are added, a
Particle instance can be created.
ScatteringModel
The ScatteringModel class
calculates scattering properties for a list of particles. It can compute various properties such
as scattering amplitudes, forward scattering amplitudes, and form factors.
Convenience Classes
There are several convenience classes provided to quickly create models for common scenarios from a given particle mixture:
- SimpleSphere: For a mixture of homogeneously scattering spheres.
- SimpleCoreShell: For a mixture of core-shell particles with a common core-to-shell ratio.
- SimpleGradient: For a mixture of particles displaying a linear gradient of the scattering length density.
Example Usage
Using ParticleBuilder to Construct Particles
The ParticleBuilder class is
used to construct particles by adding layers. Here’s an example of how to use it:
from mixscatter.scatteringmodel import (
ParticleBuilder, ConstantProfile, LinearProfile
)
# Create a ParticleBuilder instance
builder = ParticleBuilder()
# Add a layer to the builder
builder.add_layer(ConstantProfile(0, 10, 1.0))
# Add another layer to the builder
builder.add_layer(LinearProfile(10, 20, 1.0, 0.0))
# Get the constructed particle
particle = builder.get_particle()
You can do the construction in a single command by chaining the operations like this:
builder = ParticleBuilder()
particle = (
builder
.add_layer(ConstantProfile(0, 10, 1.0))
.add_layer(LinearProfile(10, 20, 1.0, 0.0))
.get_particle()
)
Accessing Single-Particle Properties
The Particle class provides methods for
displaying the scattering length density profile and for calculating the scattering amplitude and
the form factor of a single constructed particle:
profile = particle.get_profile(distance)
amplitude = particle.calculate_amplitude(wavevector)
forward_amplitude = particle.calculate_forward_amplitude()
form_factor = particle.calculate_form_factor(wavevector)
square_radius_of_gyration = particle.calculate_square_radius_of_gyration()
Using ScatteringModel
The ScatteringModel class
calculates the scattering properties from a list of particles and a matching Mixture instance.
Here’s an example of how to use it:
import numpy as np
from mixscatter.scatteringmodel import (
ScatteringModel, ParticleBuilder, ConstantProfile
)
from mixscatter.mixture import Mixture
mixture = Mixture(radius=[1.0, 2.0], number_fraction=[0.5, 0.5])
# Create particles using ParticleBuilder
builder = ParticleBuilder()
# pop_particle() obtains the constructed particle and then resets the builder
particles = [
builder.add_layer(ConstantProfile(0, radius, 1.0)).pop_particle()
for radius in mixture.radius
]
# Create a ScatteringModel instance
wavevector = np.linspace(0.01, 1.0, 100)
model = ScatteringModel(wavevector, mixture, particles)
# Calculate the average form factor
form_factor = model.average_form_factor
A ScatteringModel can contain almost any conceivable combination of particles with
totally different optical properties. This flexibility makes the tool particularly powerful.
Convenience Classes
The module includes several convenience classes to quickly create models for common particle types:
SimpleSphere
from mixscatter.scatteringmodel import SimpleSphere
# Create a simple sphere model
model = SimpleSphere(wavevector, mixture, contrast=1.0)
form_factor = model.average_form_factor
SimpleCoreShell
from mixscatter.scatteringmodel import SimpleCoreShell
# Create a core-shell model
model = SimpleCoreShell(
wavevector,
mixture,
core_to_total_ratio=0.5,
core_contrast=1.0,
shell_contrast=0.5
)
form_factor = model.average_form_factor
SimpleGradient
from mixscatter.scatteringmodel import SimpleGradient
# Create a gradient profile model
model = SimpleGradient(
wavevector, mixture, center_contrast=1.0, boundary_contrast=0.5
)
form_factor = model.average_form_factor
Implementing Your Own Model
To implement your own layer profile or scattering model from scratch, you can extend the
LayerProfile and the
ScatteringModel class. Here’s a
basic example:
from mixscatter.scatteringmodel import (
ScatteringModel, ParticleBuilder, LayerProfile
)
import numpy as np
class CustomProfile(LayerProfile):
def __init__(self, radius_inner, radius_outer, custom_param):
self.radius_inner = radius_inner
self.radius_outer = radius_outer
self.custom_param = custom_param
def calculate_amplitude(self, wavevector):
wavevector = np.asarray(wavevector)
# Custom amplitude calculation logic
amplitude = ... # Replace with actual calculation
return amplitude
def calculate_forward_amplitude(self):
# Custom forward amplitude calculation logic
forward_amplitude = ... # Replace with actual calculation
return forward_amplitude
def get_profile(self, distance):
distance = np.asarray(distance)
# Custom profile calculation logic
profile = ... # Replace with actual calculation
return profile
class CustomModel(ScatteringModel):
def __init__(self, wavevector, mixture, custom_param):
particles = []
particle_builder = ParticleBuilder()
for radius in mixture.radius:
particle = (
particle_builder
.add_layer(CustomProfile(0, radius, custom_param))
# Add as many layers as you want
.pop_particle()
)
particles.append(particle)
super().__init__(wavevector, mixture, particles)
# Using the custom model
custom_param = 1.0
model = CustomModel(wavevector, mixture, custom_param)
form_factor = model.average_form_factor