Rectangular detector

In this example we demonstrate the difference between GISAS simulation using default spherical detector and using special rectangular detector. The later provides more accurate representation of real experimental detectors.

See the Detector types tutorial for detailed explanations about various detector types in BornAgain.

  • As an example we take typical PILATUS detector ($981\times1043$ pixels) placed at the distance $2000$ mm from sample origin. The detector is perpendicular to the $x$-axis of sample reference frame, as shown on the plot.
  • Scattering from monodisperse distribution of cylindrical particles in DWBA is simulated.
  • Two detectors are defined in the code: a spherical detector (line 42) and rectangular detector (line 58). They parameters are selected to represent a real PILATUS detector as close as possible.
  • We run two simulations for two different detectors independently, and then compare results. Both simulations looks very much alike. The relative difference plot indicates the difference on the level $10^{-1}-10^{-3}$.
  • The difference is coming from the fact, that detector pixel shapes, as well as coordinates of pixel centers in $\phi_f$, $\alpha_f$ space, are slighly different in the case of spherical and rectangular detectors.

Real-space model

Intensity image

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""
Simulation with rectangular detector. Pilatus3-1M detector is used as an example.
Results will be compared against simulation with spherical detector.
"""
import numpy
import bornagain as ba
from bornagain import deg, angstrom, nm
import matplotlib
from matplotlib import pyplot as plt

detector_distance = 1000.0  # in mm
pilatus_pixel_size = 0.172  # in mm
pilatus_npx, pilatus_npy = 981, 1043  # number of pixels


def get_sample():
    """
    Returns a sample with cylindrical particles on a substrate.
    """
    # defining materials
    m_ambience = ba.HomogeneousMaterial("Air", 0.0, 0.0)
    m_substrate = ba.HomogeneousMaterial("Substrate", 6e-6, 2e-8)
    m_particle = ba.HomogeneousMaterial("Particle", 6e-4, 2e-8)

    # collection of particles
    edge = 40*nm
    ff = ba.FormFactorBox(edge, edge, edge)
    cylinder = ba.Particle(m_particle, ff)
    particle_layout = ba.ParticleLayout()
    particle_layout.addParticle(cylinder, 1.0)

    air_layer = ba.Layer(m_ambience)
    air_layer.addLayout(particle_layout)
    substrate_layer = ba.Layer(m_substrate)

    multi_layer = ba.MultiLayer()
    multi_layer.addLayer(air_layer)
    multi_layer.addLayer(substrate_layer)
    return multi_layer


def get_spherical_detector():
    """
    Returns a spherical detector roughly approximating our PILATUS detector
    """
    n_phi = pilatus_npx
    n_alpha = pilatus_npy
    width = pilatus_npx*pilatus_pixel_size
    height = pilatus_npy*pilatus_pixel_size
    phi_min = numpy.arctan(-width/2./detector_distance)
    phi_max = numpy.arctan(width/2./detector_distance)
    alpha_min = 0.0
    alpha_max = numpy.arctan(height/detector_distance)
    return ba.SphericalDetector(
        n_phi, phi_min, phi_max, n_alpha, alpha_min, alpha_max)


def get_rectangular_detector():
    """
    Returns a rectangular detector representing our PILATUS detector
    """
    width = pilatus_npx*pilatus_pixel_size
    height = pilatus_npy*pilatus_pixel_size
    detector = ba.RectangularDetector(pilatus_npx, width, pilatus_npy, height)
    detector.setPerpendicularToSampleX(detector_distance, width/2., 0.0)
    return detector


def get_simulation():
    """
    Return a GISAXS simulation with defined beam
    """
    simulation = ba.GISASSimulation()
    simulation.setBeamParameters(10*angstrom, 0.2*deg, 0.0*deg)
    return simulation


def plot(results):
    """
    Plots results of two simulations and their relative difference on one canvas
    """
    from matplotlib import colors
    fig = plt.figure(figsize=(13.6, 5.12))

    # showing  result of spherical detector simulation
    plt.subplot(1, 3, 1)
    ba.plot_colormap(results['spherical'], title="Spherical detector",
                     xlabel=r'$\phi_f ^{\circ}$', ylabel=r'$\alpha_f ^{\circ}$',
                     zlabel="")

    # showing  result of rectangular detector simulation
    plt.subplot(1, 3, 2)
    ba.plot_colormap(results['rectangular'], title="Rectangular detector",
                     xlabel='X, mm', ylabel='Y, mm', zlabel="")

    # show relative difference between two plots (sph[i]-rect[i])/rect[i]
    # for every detector pixel
    sph_array = results['spherical'].array()
    rect_array = results['rectangular'].array()
    rel_diff = 2.0 * numpy.abs(sph_array - rect_array)/(sph_array + rect_array)
    plt.subplot(1, 3, 3)
    im = plt.imshow(rel_diff, norm=colors.LogNorm(1e-6, 1.0), aspect='auto')
    cb = plt.colorbar(im, pad=0.025)
    plt.xlabel('X, bins', fontsize=14)
    plt.ylabel('Y, bins', fontsize=14)
    plt.title("Relative difference")

    plt.subplots_adjust(left=0.05, right=0.92, top=0.88, bottom=0.12)
    plt.tight_layout()
    plt.show()


def run_simulation():
    """
    Run two simulations for two different detectors and plot results
    """
    results = {}

    sample = get_sample()
    simulation = get_simulation()
    simulation.setSample(sample)

    # runs simulation for spherical detector
    simulation.setDetector(get_spherical_detector())
    simulation.runSimulation()
    results['spherical'] = simulation.result()

    # runs simulation for rectangular detector
    simulation.setDetector(get_rectangular_detector())
    simulation.runSimulation()
    results['rectangular'] = simulation.result()

    return results


if __name__ == '__main__':
    results = run_simulation()
    plot(results)
RectangularDetector.py