AGIPD Geometry and Azimuthal Integration

This notebook will show you how to assemble the modules of the AGIPD detector into a single image and then perform azimuthal integration.

[1]:
import multiprocessing as mp
import time

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

from extra_data import RunDirectory
from pyfoamalgo.geometry import AGIPD_1MGeometry, stack_detector_modules
from pyfoamalgo import AzimuthalIntegrator, mask_image_data, nanmean

mp.cpu_count()
[1]:
72
[2]:
run = RunDirectory("/gpfs/exfel/exp/XMPL/201750/p700000/proc/r0005")

run.info()
# of trains:    156
Duration:       0:00:15.6
First train ID: 198425241
Last train ID:  198425396

16 detector modules (SPB_DET_AGIPD1M-1)
  e.g. module SPB_DET_AGIPD1M-1 0 : 512 x 128 pixels
  SPB_DET_AGIPD1M-1/DET/0CH0:xtdf
  176 frames per train, up to 27456 frames total

0 instrument sources (excluding detectors):

0 control sources: (1 entry per train)

[3]:
_, train_data = run.select('*/DET/*', 'image.data').train_from_index(100)

Assembling

Note: stack_detector_modules returns an array-like wrapper around the existing arrays which avoid the data copy.

[4]:
# Stack the detector modules into a single array.
modules_data = stack_detector_modules(train_data, 'SPB_DET_AGIPD1M-1/DET/*CH0:xtdf', 'image.data', modules=16)

modules_data.shape, modules_data.dtype
[4]:
((176, 16, 512, 128), dtype('<f4'))
[5]:
geom = AGIPD_1MGeometry.from_crystfel_geom('agipd_mar18_v11.geom')
[6]:
n_pulses = modules_data.shape[0]

# Allocate the assembled image array and reuse it as far as possible to speed up data processing.
assembled = geom.output_array_for_position_fast(extra_shape=(n_pulses,), dtype=np.float32)
assembled.shape
[6]:
(176, 1259, 1092)
[7]:
t0 = time.perf_counter()

# Assemble modules and mask tile edge pixels.
geom.position_all_modules(modules_data, out=assembled, ignore_tile_edge=True)

print(f"Assembling a train with {n_pulses} pulses takes: {1e3 * (time.perf_counter() - t0):.1f} ms")
Assembling a train with 176 pulses takes: 50.5 ms
[8]:
t0 = time.perf_counter()

# Calculate the average (taking into account nan) of the assembled image.
assembled_mean = nanmean(assembled, axis=0)

print(f"Averaging a train with {n_pulses} pulses takes: {1e3 * (time.perf_counter() - t0):.1f} ms")
Averaging a train with 176 pulses takes: 24.3 ms
[9]:
_, ax = plt.subplots(figsize=(8, 8))

ax.imshow(assembled_mean, vmin=0, vmax=1000)
[9]:
<matplotlib.image.AxesImage at 0x2ac90bd18890>
../../../_images/foam-examples_foamalgo_python_AGIPD_geometry_and_azimuthal_integration_11_1.png

Azimuthal integration

[10]:
# The mask is only required by pyFAI. pyfoamalgo can process nans without a mask.
mask = np.zeros_like(assembled_mean, dtype=bool)
# The threshold mask here is important for both libraries to have a reasonable result.
mask_image_data(assembled_mean, threshold_mask=(0, 5e4), out=mask)
[11]:
dist = 5.5  # sample distance in meter
npt = 1024  # number of integration points
cy, cx = 628, 536
pixel1, pixel2 = 200e-6, 200e-6  # pixel size (y, x) in meter
poni1, poni2 = cy * pixel1, cx * pixel2  # integration center (y, x)
wavelength = 1e-10  # Xray wavelength in meter

integrator = AzimuthalIntegrator(
    dist=dist, poni1=poni1, poni2=poni2, pixel1=pixel1, pixel2=pixel2, wavelength=1e-10)

t0 = time.perf_counter()
integrator.integrate1d(assembled_mean, npt=npt)
print(f"Azimuthal integration (including initialization) takes: {1e3 * (time.perf_counter() - t0):.1f} ms")

t0 = time.perf_counter()
q, I = integrator.integrate1d(assembled_mean, npt=npt)
print(f"Azimuthal integration takes: {1e3 * (time.perf_counter() - t0):.1f} ms")
Azimuthal integration (including initialization) takes: 16.2 ms
Azimuthal integration takes: 6.1 ms

One can benchmark the result using pyFAI if it is installed.

[12]:
HAS_PYFAI = False

try:
    from pyFAI.azimuthalIntegrator import AzimuthalIntegrator as PyfaiAzimuthalIntegrator

    HAS_PYFAI = True

    pyfai_method = 'nosplit_csr'
    pyfai_integrator = PyfaiAzimuthalIntegrator(
        dist=dist, poni1=poni1, poni2=poni2, pixel1=pixel1, pixel2=pixel2, wavelength=wavelength)

    t0 = time.perf_counter()
    pyfai_integrator.integrate1d(assembled_mean, npt,
                                 mask=mask,
                                 unit="q_A^-1",
                                 method=pyfai_method)
    print(f"Azimuthal integration (including initialization) takes: {1e3 * (time.perf_counter() - t0):.1f} ms")

    t0 = time.perf_counter()
    q_gt, I_gt = pyfai_integrator.integrate1d(assembled_mean, npt,
                                              mask=mask,
                                              unit="q_A^-1",
                                              method=pyfai_method)
    print(f"Azimuthal integration takes: {1e3 * (time.perf_counter() - t0):.1f} ms")
except ModuleNotFoundError:
    pass
WARNING:silx.opencl.common:Unable to import pyOpenCl. Please install it from: http://pypi.python.org/pypi/pyopencl
WARNING:pyFAI.ext.splitBBoxCSR:Pixel splitting desactivated !
Azimuthal integration (including initialization) takes: 201.3 ms
Azimuthal integration takes: 15.5 ms
[13]:
_, ax = plt.subplots(figsize=(12, 6))

ax.plot(1e-10 * q, I, '-', label='pyfoamalgo')
ax.set_xlabel("q (1/A)", fontsize=16)
ax.set_ylabel("I (arb.)", fontsize=16)
if HAS_PYFAI:
    ax.plot(q_gt, I_gt, '-', label='pyFAI')
    ax.legend(fontsize=16)
../../../_images/foam-examples_foamalgo_python_AGIPD_geometry_and_azimuthal_integration_17_0.png

One can also perform azimuthal integration on an array of images in a batch.

[14]:
mask_image_data(assembled, threshold_mask=(0, 5e4))

t0 = time.perf_counter()
q, I_a = integrator.integrate1d(assembled, npt=npt)
print(f"Averaging a train with {n_pulses} pulses takes: {1e3 * (time.perf_counter() - t0):.1f} ms")
Averaging a train with 176 pulses takes: 41.5 ms
[15]:
_, ax = plt.subplots(2, 2, figsize=(15, 6))

for i, axis in enumerate(ax.flatten()):
    axis.plot(1e-10 * q, I_a[i], '-')
    axis.set_xlabel("q (1/A)", fontsize=16)
    axis.set_ylabel("I (arb.)", fontsize=16)
    axis.set_title(f"Pulse {i}")

plt.tight_layout()
../../../_images/foam-examples_foamalgo_python_AGIPD_geometry_and_azimuthal_integration_20_0.png