Skip to content
Snippets Groups Projects
Commit 813bf240 authored by Wuttke, Joachim's avatar Wuttke, Joachim
Browse files

[j.2] restore figures in online doc (#1127) ()

Merging branch 'j.2'  into 'main'.

See merge request !2920
parents 2c113e77 bdcc2357
No related branches found
No related tags found
1 merge request!2920restore figures in online doc (#1127)
Pipeline #198479 passed
Showing
with 646 additions and 32 deletions
......@@ -86,7 +86,8 @@ if(ALLCONFIG)
set(CONFIGURE_BINDINGS ON)
set(CONFIGURE_EXAMPLES ON)
set(CONFIGURE_DOXY ON)
# TODO what about targets 'figures', 'excopy'? see Tests/Examples/CMakeLists.txt ...
# TODO what about targets 'figures', 'excopy'? see Tests/Examples/CMakeLists.txt
# TODO what about target 'src_graph'? see Doc/graph/CMakeLists.txt
endif()
# check compatibility of options
......
......@@ -177,7 +177,7 @@ test_example(scatter2d/CoreShellNanoparticles 2e-10)
test_example(scatter2d/CoreShellNanoparticles2 2e-10)
test_example(scatter2d/CorrelatedRoughness 2e-10)
test_example(scatter2d/CosineRipplesAtRectLattice 2e-10)
test_example(scatter2d/CustomFormFactor 2e-10)
test_example(scatter2d/CustomFormfactor 2e-10)
test_example(scatter2d/Cylinders 2e-10)
test_example(scatter2d/CylindersAndPrisms 2e-10)
test_example(scatter2d/CylindersInAverageLayer 2e-10)
......@@ -192,7 +192,7 @@ test_example(scatter2d/Interference2DCenteredSquareLattice 2e-10)
test_example(scatter2d/Interference2DParacrystal 2e-10)
test_example(scatter2d/Interference2DRotatedSquareLattice 2e-10)
test_example(scatter2d/Interference2DSquareFiniteLattice 2e-10)
test_example(scatter2d/LargeParticlesFormFactor 0.05) # MC integration ==> high tolerance is ok
test_example(scatter2d/LargeParticles 0.05) # MC integration ==> high tolerance is ok
test_example(scatter2d/LatticeOrientationDistribution 2e-10)
test_example(scatter2d/MagneticCylinders1 2e-10)
test_example(scatter2d/MagneticCylinders2 2e-10)
......
#!/usr/bin/env python3
"""
Custom form factor in DWBA.
"""
import cmath
import bornagain as ba
from bornagain import ba_plot as bp, deg, angstrom, nm
def sinc(x):
if abs(x) == 0:
return 1.
return cmath.sin(x) / x
class CustomFormfactor:
"""
A custom defined form factor.
The particle is a prism of height H,
with a base in form of a Greek cross ("plus" sign) with side length L.
"""
def __init__(self, L, H):
""" arguments and initialization for the formfactor """
# parameters describing the form factor
self.L = L
self.H = H
def formfactor(self, q:'C3'):
""" main scattering function """
qzhH = 0.5 * q.z() * self.H
qxhL = 0.5 * q.x() * self.L
qyhL = 0.5 * q.y() * self.L
return (0.5 * self.H * self.L**2
* cmath.exp(complex(0., 1.) * qzhH) * sinc(qzhH)
* (sinc(0.5 * qyhL) * (sinc(qxhL) - 0.5 * sinc(0.5 * qxhL))
+ sinc(0.5 * qxhL) * sinc(qyhL)))
def spanZ(self, rotation):
""" upper and lower z-positions of a custom shape """
return ba.Span(0, self.H)
def get_sample():
"""
Sample with particles, having a custom formfactor, on a substrate.
"""
# materials
vacuum = ba.RefractiveMaterial("Vacuum", 0, 0)
material_substrate = ba.RefractiveMaterial("Substrate", 6e-6, 2e-8)
material_particle = ba.RefractiveMaterial("Particle", 6e-4, 2e-8)
# collection of particles
ff = CustomFormfactor(20*nm, 15*nm)
particle = ba.Particle(material_particle, ff)
particle_layout = ba.ParticleLayout()
particle_layout.addParticle(particle)
vacuum_layer = ba.Layer(vacuum)
vacuum_layer.addLayout(particle_layout)
substrate_layer = ba.Layer(material_substrate)
""" NOTE:
Slicing of custom formfactor is not possible.
all layers must have number of slices equal to 1.
It is a default situation; otherwise use
```
my_layer.setNumberOfSlices(1)
```
Furthermore, a custom particle should not cross layer boundaries;
that is, the z-span should be within a single layer
"""
# assemble sample
sample = ba.Sample()
sample.addLayer(vacuum_layer)
sample.addLayer(substrate_layer)
return sample
def get_simulation(sample):
beam = ba.Beam(1e9, 1*angstrom, 0.2*deg)
n = 100
det = ba.SphericalDetector(n, -1*deg, 1*deg, n, 0, 2*deg)
simulation = ba.ScatteringSimulation(beam, sample, det)
# Deactivate multithreading:
# Currently BornAgain cannot access the Python interpreter
# from a multi-threaded C++ function
simulation.options().setNumberOfThreads(1)
return simulation
if __name__ == '__main__':
sample = get_sample()
simulation = get_simulation(sample)
result = simulation.simulate()
bp.plot_simulation_result(result)
bp.plt.show()
#!/usr/bin/env python3
"""
Large cylinders in DWBA.
This example demonstrates that for large particles (~1000nm) the form factor
oscillates rapidly within one detector bin and analytical calculations
(performed for the bin center) give completely wrong intensity pattern.
In this case Monte-Carlo integration over detector bin should be used.
"""
import bornagain as ba
from bornagain import angstrom, ba_plot as bp, deg, nm
default_cylinder_radius = 10*nm
default_cylinder_height = 20*nm
def get_sample(cylinder_radius, cylinder_height):
# Materials
vacuum = ba.RefractiveMaterial("Vacuum", 0, 0)
material_substrate = ba.RefractiveMaterial("Substrate", 6e-6, 2e-8)
material_particle = ba.RefractiveMaterial("Particle", 6e-4, 2e-8)
# Particle layout
cylinder_ff = ba.Cylinder(cylinder_radius, cylinder_height)
cylinder = ba.Particle(material_particle, cylinder_ff)
particle_layout = ba.ParticleLayout()
particle_layout.addParticle(cylinder)
# Layers
vacuum_layer = ba.Layer(vacuum)
vacuum_layer.addLayout(particle_layout)
substrate_layer = ba.Layer(material_substrate)
# Sample
sample = ba.Sample()
sample.addLayer(vacuum_layer)
sample.addLayer(substrate_layer)
return sample
def get_simulation(sample, integration_flag):
"""
A GISAXS simulation with defined beam and detector.
If integration_flag=True, the simulation will integrate over detector bins.
"""
beam = ba.Beam(1, 1*angstrom, 0.2*deg)
n = 201
det = ba.SphericalDetector(n, -1.5*deg, 1.5*deg, n, 0, 3*deg)
simulation = ba.ScatteringSimulation(beam, sample, det)
simulation.options().setMonteCarloIntegration(integration_flag, 50)
if not "__no_terminal__" in globals():
simulation.setTerminalProgressMonitor()
return simulation
def simulate():
ret = []
# conditions to define cylinders scale factor and integration flag
conditions = [{
'title': "Small cylinders, analytical calculations",
'scale': 1,
'integration': False,
'zmin': 1e-5,
'zmax': 1e2
}, {
'title': "Small cylinders, Monte-Carlo integration",
'scale': 1,
'integration': True,
'zmin': 1e-5,
'zmax': 1e2
}, {
'title': "Large cylinders, analytical calculations",
'scale': 100,
'integration': False,
'zmin': 1e-5,
'zmax': 1e10
}, {
'title': "Large cylinders, Monte-Carlo integration",
'scale': 100,
'integration': True,
'zmin': 1e-5,
'zmax': 1e10
}]
# run simulation 4 times
for i_plot, condition in enumerate(conditions):
scale = condition['scale']
integration_flag = condition['integration']
sample = get_sample(default_cylinder_radius*scale,
default_cylinder_height*scale)
simulation = get_simulation(sample, integration_flag)
result = simulation.simulate()
result.setTitle(condition['title'])
ret.append(result)
return ret
if __name__ == '__main__':
results = simulate()
bp.make_plot(results, 2)
bp.plt.show()
#!/usr/bin/env python3
"""
Custom form factor in DWBA.
"""
import cmath
import bornagain as ba
from bornagain import ba_plot as bp, deg, angstrom, nm
def sinc(x):
if abs(x) == 0:
return 1.
return cmath.sin(x) / x
class CustomFormfactor:
"""
A custom defined form factor.
The particle is a prism of height H,
with a base in form of a Greek cross ("plus" sign) with side length L.
"""
def __init__(self, L, H):
""" arguments and initialization for the formfactor """
# parameters describing the form factor
self.L = L
self.H = H
def formfactor(self, q:'C3'):
""" main scattering function """
qzhH = 0.5 * q.z() * self.H
qxhL = 0.5 * q.x() * self.L
qyhL = 0.5 * q.y() * self.L
return (0.5 * self.H * self.L**2
* cmath.exp(complex(0., 1.) * qzhH) * sinc(qzhH)
* (sinc(0.5 * qyhL) * (sinc(qxhL) - 0.5 * sinc(0.5 * qxhL))
+ sinc(0.5 * qxhL) * sinc(qyhL)))
def spanZ(self, rotation):
""" upper and lower z-positions of a custom shape """
return ba.Span(0, self.H)
def get_sample():
"""
Sample with particles, having a custom formfactor, on a substrate.
"""
# materials
vacuum = ba.RefractiveMaterial("Vacuum", 0, 0)
material_substrate = ba.RefractiveMaterial("Substrate", 6e-6, 2e-8)
material_particle = ba.RefractiveMaterial("Particle", 6e-4, 2e-8)
# collection of particles
ff = CustomFormfactor(20*nm, 15*nm)
particle = ba.Particle(material_particle, ff)
particle_layout = ba.ParticleLayout()
particle_layout.addParticle(particle)
vacuum_layer = ba.Layer(vacuum)
vacuum_layer.addLayout(particle_layout)
substrate_layer = ba.Layer(material_substrate)
""" NOTE:
Slicing of custom formfactor is not possible.
all layers must have number of slices equal to 1.
It is a default situation; otherwise use
```
my_layer.setNumberOfSlices(1)
```
Furthermore, a custom particle should not cross layer boundaries;
that is, the z-span should be within a single layer
"""
# assemble sample
sample = ba.Sample()
sample.addLayer(vacuum_layer)
sample.addLayer(substrate_layer)
return sample
def get_simulation(sample):
beam = ba.Beam(1e9, 1*angstrom, 0.2*deg)
n = 100
det = ba.SphericalDetector(n, -1*deg, 1*deg, n, 0, 2*deg)
simulation = ba.ScatteringSimulation(beam, sample, det)
# Deactivate multithreading:
# Currently BornAgain cannot access the Python interpreter
# from a multi-threaded C++ function
simulation.options().setNumberOfThreads(1)
return simulation
if __name__ == '__main__':
sample = get_sample()
simulation = get_simulation(sample)
result = simulation.simulate()
plotargs = bp.parse_commandline()
bp.plot_simulation_result(result, **plotargs)
bp.export(**plotargs)
#!/usr/bin/env python3
"""
Large cylinders in DWBA.
This example demonstrates that for large particles (~1000nm) the form factor
oscillates rapidly within one detector bin and analytical calculations
(performed for the bin center) give completely wrong intensity pattern.
In this case Monte-Carlo integration over detector bin should be used.
"""
import bornagain as ba
from bornagain import angstrom, ba_plot as bp, deg, nm
default_cylinder_radius = 10*nm
default_cylinder_height = 20*nm
def get_sample(cylinder_radius, cylinder_height):
# Materials
vacuum = ba.RefractiveMaterial("Vacuum", 0, 0)
material_substrate = ba.RefractiveMaterial("Substrate", 6e-6, 2e-8)
material_particle = ba.RefractiveMaterial("Particle", 6e-4, 2e-8)
# Particle layout
cylinder_ff = ba.Cylinder(cylinder_radius, cylinder_height)
cylinder = ba.Particle(material_particle, cylinder_ff)
particle_layout = ba.ParticleLayout()
particle_layout.addParticle(cylinder)
# Layers
vacuum_layer = ba.Layer(vacuum)
vacuum_layer.addLayout(particle_layout)
substrate_layer = ba.Layer(material_substrate)
# Sample
sample = ba.Sample()
sample.addLayer(vacuum_layer)
sample.addLayer(substrate_layer)
return sample
def get_simulation(sample, integration_flag):
"""
A GISAXS simulation with defined beam and detector.
If integration_flag=True, the simulation will integrate over detector bins.
"""
beam = ba.Beam(1, 1*angstrom, 0.2*deg)
n = 201
det = ba.SphericalDetector(n, -1.5*deg, 1.5*deg, n, 0, 3*deg)
simulation = ba.ScatteringSimulation(beam, sample, det)
simulation.options().setMonteCarloIntegration(integration_flag, 50)
if not "__no_terminal__" in globals():
simulation.setTerminalProgressMonitor()
return simulation
def simulate():
ret = []
# conditions to define cylinders scale factor and integration flag
conditions = [{
'title': "Small cylinders, analytical calculations",
'scale': 1,
'integration': False,
'zmin': 1e-5,
'zmax': 1e2
}, {
'title': "Small cylinders, Monte-Carlo integration",
'scale': 1,
'integration': True,
'zmin': 1e-5,
'zmax': 1e2
}, {
'title': "Large cylinders, analytical calculations",
'scale': 100,
'integration': False,
'zmin': 1e-5,
'zmax': 1e10
}, {
'title': "Large cylinders, Monte-Carlo integration",
'scale': 100,
'integration': True,
'zmin': 1e-5,
'zmax': 1e10
}]
# run simulation 4 times
for i_plot, condition in enumerate(conditions):
scale = condition['scale']
integration_flag = condition['integration']
sample = get_sample(default_cylinder_radius*scale,
default_cylinder_height*scale)
simulation = get_simulation(sample, integration_flag)
result = simulation.simulate()
result.setTitle(condition['title'])
ret.append(result)
return ret
if __name__ == '__main__':
results = simulate()
plotargs = bp.parse_commandline()
plotargs['fontsize'] = 12
bp.make_plot(results, 2, **plotargs)
bp.export(**plotargs)
......@@ -54,4 +54,4 @@ if __name__ == '__main__':
results.append(result)
plotargs = bp.parse_commandline()
bp.make_plot_row(results, **plotargs)
bp.export()
bp.export(**plotargs)
#!/usr/bin/env python3
"""
Custom form factor in DWBA.
"""
import cmath
import bornagain as ba
from bornagain import ba_plot as bp, deg, angstrom, nm
def sinc(x):
if abs(x) == 0:
return 1.
return cmath.sin(x) / x
class CustomFormfactor:
"""
A custom defined form factor.
The particle is a prism of height H,
with a base in form of a Greek cross ("plus" sign) with side length L.
"""
def __init__(self, L, H):
""" arguments and initialization for the formfactor """
# parameters describing the form factor
self.L = L
self.H = H
def formfactor(self, q:'C3'):
""" main scattering function """
qzhH = 0.5 * q.z() * self.H
qxhL = 0.5 * q.x() * self.L
qyhL = 0.5 * q.y() * self.L
return (0.5 * self.H * self.L**2
* cmath.exp(complex(0., 1.) * qzhH) * sinc(qzhH)
* (sinc(0.5 * qyhL) * (sinc(qxhL) - 0.5 * sinc(0.5 * qxhL))
+ sinc(0.5 * qxhL) * sinc(qyhL)))
def spanZ(self, rotation):
""" upper and lower z-positions of a custom shape """
return ba.Span(0, self.H)
def get_sample():
"""
Sample with particles, having a custom formfactor, on a substrate.
"""
# materials
vacuum = ba.RefractiveMaterial("Vacuum", 0, 0)
material_substrate = ba.RefractiveMaterial("Substrate", 6e-6, 2e-8)
material_particle = ba.RefractiveMaterial("Particle", 6e-4, 2e-8)
# collection of particles
ff = CustomFormfactor(20*nm, 15*nm)
particle = ba.Particle(material_particle, ff)
particle_layout = ba.ParticleLayout()
particle_layout.addParticle(particle)
vacuum_layer = ba.Layer(vacuum)
vacuum_layer.addLayout(particle_layout)
substrate_layer = ba.Layer(material_substrate)
""" NOTE:
Slicing of custom formfactor is not possible.
all layers must have number of slices equal to 1.
It is a default situation; otherwise use
```
my_layer.setNumberOfSlices(1)
```
Furthermore, a custom particle should not cross layer boundaries;
that is, the z-span should be within a single layer
"""
# assemble sample
sample = ba.Sample()
sample.addLayer(vacuum_layer)
sample.addLayer(substrate_layer)
return sample
def get_simulation(sample):
beam = ba.Beam(1e9, 1*angstrom, 0.2*deg)
n = 11
det = ba.SphericalDetector(n, -1*deg, 1*deg, n, 0, 2*deg)
simulation = ba.ScatteringSimulation(beam, sample, det)
# Deactivate multithreading:
# Currently BornAgain cannot access the Python interpreter
# from a multi-threaded C++ function
simulation.options().setNumberOfThreads(1)
return simulation
if __name__ == '__main__':
sample = get_sample()
simulation = get_simulation(sample)
result = simulation.simulate()
plotargs = bp.parse_commandline()
bp.plot_simulation_result(result, **plotargs)
bp.export(**plotargs)
#!/usr/bin/env python3
"""
Large cylinders in DWBA.
This example demonstrates that for large particles (~1000nm) the form factor
oscillates rapidly within one detector bin and analytical calculations
(performed for the bin center) give completely wrong intensity pattern.
In this case Monte-Carlo integration over detector bin should be used.
"""
import bornagain as ba
from bornagain import angstrom, ba_plot as bp, deg, nm
default_cylinder_radius = 10*nm
default_cylinder_height = 20*nm
def get_sample(cylinder_radius, cylinder_height):
# Materials
vacuum = ba.RefractiveMaterial("Vacuum", 0, 0)
material_substrate = ba.RefractiveMaterial("Substrate", 6e-6, 2e-8)
material_particle = ba.RefractiveMaterial("Particle", 6e-4, 2e-8)
# Particle layout
cylinder_ff = ba.Cylinder(cylinder_radius, cylinder_height)
cylinder = ba.Particle(material_particle, cylinder_ff)
particle_layout = ba.ParticleLayout()
particle_layout.addParticle(cylinder)
# Layers
vacuum_layer = ba.Layer(vacuum)
vacuum_layer.addLayout(particle_layout)
substrate_layer = ba.Layer(material_substrate)
# Sample
sample = ba.Sample()
sample.addLayer(vacuum_layer)
sample.addLayer(substrate_layer)
return sample
def get_simulation(sample, integration_flag):
"""
A GISAXS simulation with defined beam and detector.
If integration_flag=True, the simulation will integrate over detector bins.
"""
beam = ba.Beam(1, 1*angstrom, 0.2*deg)
n = 21
det = ba.SphericalDetector(n, -1.5*deg, 1.5*deg, n, 0, 3*deg)
simulation = ba.ScatteringSimulation(beam, sample, det)
simulation.options().setMonteCarloIntegration(integration_flag, 500)
if not "__no_terminal__" in globals():
simulation.setTerminalProgressMonitor()
return simulation
def simulate():
ret = []
# conditions to define cylinders scale factor and integration flag
conditions = [{
'title': "Small cylinders, analytical calculations",
'scale': 1,
'integration': False,
'zmin': 1e-5,
'zmax': 1e2
}, {
'title': "Small cylinders, Monte-Carlo integration",
'scale': 1,
'integration': True,
'zmin': 1e-5,
'zmax': 1e2
}, {
'title': "Large cylinders, analytical calculations",
'scale': 100,
'integration': False,
'zmin': 1e-5,
'zmax': 1e10
}, {
'title': "Large cylinders, Monte-Carlo integration",
'scale': 100,
'integration': True,
'zmin': 1e-5,
'zmax': 1e10
}]
# run simulation 4 times
for i_plot, condition in enumerate(conditions):
scale = condition['scale']
integration_flag = condition['integration']
sample = get_sample(default_cylinder_radius*scale,
default_cylinder_height*scale)
simulation = get_simulation(sample, integration_flag)
result = simulation.simulate()
result.setTitle(condition['title'])
ret.append(result)
return ret
if __name__ == '__main__':
results = simulate()
plotargs = bp.parse_commandline()
plotargs['fontsize'] = 12
bp.make_plot(results, 2, **plotargs)
bp.export(**plotargs)
......@@ -54,4 +54,4 @@ if __name__ == '__main__':
results.append(result)
plotargs = bp.parse_commandline()
bp.make_plot_row(results, **plotargs)
bp.export()
bp.export(**plotargs)
......@@ -20,7 +20,6 @@ Download the following example script,
using the link just below the code frame.
Save the script under the name `AlternatingLayers1.py`.
{{< show-ex file="specular/AlternatingLayers1.py">}}
<p>
......
......@@ -5,6 +5,12 @@ weight = 20
### Plotting with axes in different units
*The functionality demonstrated in this example is currently broken.*
Repair is on our agenda: https://jugit.fz-juelich.de/mlz/bornagain/-/issues/716.
....
In this example we demonstrate how modify coordinate axes in 2D plots.
The example is based on the standard GISAS simulation [Cylinders in DWBA](/ref/sim/ex/gisas).
......
+++
title = "Rectangular grating"
weight = 85
+++
### Interference - Rectangular Grating
This example demonstrates how to perform a simulation of a grating using very long boxes and a 1D lattice. [Interference of a 1D lattice](/ref/sample/interference/grating/lattice1d) may provide useful background information.
{{< galleryscg >}}
{{< figscg src="/img/auto/scatter2d/RectangularGrating.png" width="4500px" caption="Intensity image">}}
{{< /galleryscg >}}
{{< show-ex file="scatter2d/RectangularGrating.py" >}}
To get rid of oscillation arising from large-particle form factors, Monte-carlo integration is used.
{{< galleryscg >}}
{{< figscg src="/img/auto/scatter2d/GratingMC.png" width="4500px" caption="Intensity image">}}
{{< /galleryscg >}}
{{< show-ex file="scatter2d/GratingMC.py" >}}
......@@ -17,8 +17,8 @@ The simulation generates four plots using different sizes of the particles, (rad
* The incident angles are $\alpha\_i = 0.2 ^{\circ}$ and $\varphi\_i = 0^{\circ}$.
{{< galleryscg >}}
{{< figscg src="/img/draw/LargeParticlesFormfactor_setup.jpg" width="700px" caption="Real-space model">}}
{{< figscg src="/img/auto/scatter2d/LargeParticlesFormfactor.png" width="350px" caption="Intensity image">}}
{{< figscg src="/img/draw/LargeParticles_setup.jpg" width="700px" caption="Real-space model">}}
{{< figscg src="/img/auto/scatter2d/LargeParticles.png" width="350px" caption="Intensity image">}}
{{< /galleryscg >}}
{{< show-ex file="scatter2d/LargeParticlesFormfactor.py" >}}
{{< show-ex file="scatter2d/LargeParticles.py" >}}
......@@ -25,4 +25,4 @@ if not "__no_terminal__" in globals():
This is used for example in
{{< show-ex file="scatter2d/GratingMC.py" >}}
{{< show-ex file="scatter2d/FindPeaks.py" >}}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment