Beam position methods

dials.search_beam_position searches beam position in a set of diffraction images. There are four methods implemented in this function: default, maximum, midpoint, and inversion. The default method is based on the work of Sauter et al. (please see Ref. [1]) and it is not covered here. The other three methods are based on projecting diffraction images along the x and the y axes, and we will briefly describe them here.

The three projection methods were developed to automate the processing of diffraction datasets produced at the DLS electron Bio-Imaging Centre (eBIC). They are developed primarily for electron diffraction images, although nothing prevents you from using them for other sources. They work primarily in cases when the user can quickly determine the beam center just by looking at a diffraction image, and they do not rely on some profound mathematical truths. In other words, they are not a ‘silver bullet’ to handle every dataset, but an ad hoc solution developed to work for most of the datasets obtained at eBIC. The initial idea was to use the output of these three methods to train machine learning models (with problematic datasets labeled by hand in order to catch all the cases).

It is unlikely that any of the three methods presented here will work on your data out of the box. Depending on the setup of your experiment, detector resolution, position of the beam stop etc, you will have to tune method parameters to fit your experiment. However, once you find the correct combination of parameters, the methods will work well for most your datasets. In the first example below (processing with the maximum method) we will just present the interface of the maximum method. In the second example, beside explaining the interface of the midpoint method, we will give a step by step explanation how we tuned the method parameters to work with the Singla data.

Maximum pixel intensity method

This is the simplest projection method, which is suitable for datasets where the beam is visible. Assuming we already imported our dataset with dials.import, we can run the search_beam_position on the imported experiment file

dials.search_beam_position method=maximum image_ranges=0:3 imported.expt

The search_beam_position command will compute the average diffraction image using the first three images in the dataset, and then compute the beam position using the maximum pixel intensity method. The output should be a single PNG image called beam_position.png (shown below, see Fig. 1).

Beam position computed using maximum method

Fig. 1 Beam position computed using the maximum pixel intensity method. Data provided by Peter Ercius from Lawrence Berkeley National Laboratory.

The generated plot shows the average diffraction image in the central part and two projected profiles along the x- and the y-direction in the top and right plots, respectively. The beam position in pixels (rounded to an integer) is shown in the top right, between the plotted graphs. The plotted result has additional metadata, such as the image dimensions, the minimal and maximal pixel intensity, etc. Note that all projection methods work only for single-panel detectors (for now).

Note

By default, the plotting function will try to adjust the colormap range to show high intensity regions. However, in some datasets, the pixel intensities might be unevenly distributed (imagine a dataset where the average pixel has an intensity between 0 and 10, but some bad pixels show intensities of several millions). In such cases, spotting the beam on the central image would be hard. If this is the case with your dataset, you can use the argument color_cutoff (for example, in the previously described case, you would set color_cutoff=10) to set the maximum value of the colormap range. Setting this parameter will not change the original data; it will only change how it is plotted. Pixels with intensities above the color cutoff would be set to the same color. The color_cutoff also applies to other methods (inversion and midpoint) and is not limited to the maximum method.

When projecting data from a 2D image to 1D profiles, we can either compute the average pixel intensity along an axis or find the maximal pixel along an axis (i.e., computing the maximal projection). The previous figure shows both maximal and average projections along each axis.

Because the beam is visible, one can find the pixel with maximum intensity and declare that to be the beam position without any projecting. However, this is not always correct. In some cases, bad pixels will return the maximal intensity from the trusted range by default. Also, there might be cases where the intensity of a reflection spot is higher than the intensity at the direct beam. One condition usually satisfied when the beam is visible is that the direct beam has the most extensive spread compared to other diffraction spots. Finding the broadest peak is a good starting point for computing the beam position. The next step is determining the pixel with the highest intensity within that broadest peak. Projecting the diffraction image along the x and the y is not necessary. However, it dramatically simplifies the problem by reducing it to one dimension. The downside is that there might be cases where strong reflection spot masks the direct beam in the projected profile. Averaging over few images (as in our example above) usually removes this problem.

The first step in the maximum method is to find the broadest peak in the projected profiles. This is done by scanning the average projected profile (the green curves in Fig. 1) with an averaging kernel of a certain width (see Fig. 2, below).

Explanation of the maximum method

Fig. 2 Parameters bin_width and bin_step of the maximum pixel intensity method.

The averaging kernel (the dark gray rectangle in Figure 2) sweeps over the projected profile moving in discrete steps (determined by the bin_step parameter (in pixels)). The kernel size is set with the bin_width parameter (again, in pixels). At each position during the sweep, the kernel computes the integral sum of the average projected profile beneath the kernel (the green area below the green curve in Figure 2). After sweeping the entire profile and computing profile integrals, the maximum method determines the kernel position where this integral has the maximal value. In general, this will correspond to an area where most of the projected profile intensity is located (the broadest peak). For a real-world example, see the gray shaded areas in projected profiles in Fig. 1. These are kernel positions with maximal integral, and they indeed correspond to the broadest peak. Depending on the image dimensions, the beam characteristics, etc, the user will have to fine-tune the bin_step and bin_width parameters to match the expected spread of the direct beam for the given experimental setup. To ensure the continuous sweep across the projected profile, DIALS assumes that bin_step is always smaller than bin_width, otherwise it will throw an error.

Note that most of the narrow reflection spots will disappear because we are dealing with the average projected profile when determining the broadest peak. The user can additionally remove narrow reflection peaks by increasing the maximum.convolution_width parameter, which sets the width of the convolution smoothing window before the kernel sweep. Additionally, the user can set all pixels above a certain intensity to zero in the average diffraction image (that is, before projecting onto the x and y-axis). This is done using maximum.bad_pixel_threshold parameter.

The next step after locating the broadest peak is to find the actual beam position. For this, we use the maximum projected profiles (the gray curves in Fig. 1). The maximum projected profile will contain peaks from the reflections and the direct beam. The method will find a pixel with the highest intensity within the previously determined maximum kernel (the gray-shaded areas in the projected plots in Fig. 1). The previous maximum.bad_pixel_threshold argument is applied to the central image before data is projected so that it will affect both projected profiles (average and maximum).

The image_ranges=0:3 argument uses slicing like the Numpy library, starting at the first image (index 0) up until the third image. Image ranges are selected using the Numpy slice notation, that is, start:stop:step, where any of the three numbers can be omitted. Multiple image ranges can be separated by commas (e.g., image_ranges=0:3,7:20:2,35,48) which also allows for the selection of individual images. The averaging procedure in the current method is not fully optimized, so instead of waiting for thousands of images to average, it is much faster to select only a subset of those images (assuming the beam position does not change much throughout the dataset). Similarly to the previous parameter, one can additionally use imageset_ranges to select between different imagesets (if they are present in the dataset).

Besides computing the average image and then making the projection, the user can compute beam position for each image separately using per_image=True parameter. This will produce a series of PNG images.

beam_position_imageset_00000_image_00000.png
beam_position_imageset_00000_image_00001.png
beam_position_imageset_00000_image_00002.png
beam_position_imageset_00000_image_00003.png
...

Each image will contain information about beam position. Additionally, if per_image=True, DIALS will produce beam_positions.json file with a list of computed beam positions

 [
     [
         0,
         0,
         294.0,
         261.0
     ],
     [
         1,
         0,
         296.0,
         261.0
     ],
     ...
]

Here, the first number in the four-element list is the imageset index, the second is the image index, and the third and fourth are beam positions along the x and y direction (in pixels). The JSON file will have beam positions for all images and imagesets selected using image_ranges and imageset_ranges. In contrast to PNG images, the computed positions are not converted to integers (which is not that important for the maximum method, but it is for the other two projection methods).

The user should also distinguish between method-specific parameters (such as bin_width and bin_step) and parameters such as per_image and image_ranges, which also apply to other projection methods as well (see dials.search_beam_position -h for more info on the function interface. The parameters that apply to all three projection methods are under the projection keyword). Additionally, it is important to emphasize that most parameters specific to the maximum method (and other projection methods) apply both to projections along the x and the y axis (the mini plots on the top and left in Fig. 1). Some parameters apply separately to x and y projection, and we will discuss them below.

Midpoint method

This method is suitable for datasets where direct beam is blocked by some obstacle (and not fully visible in the diffraction images). Fig. 3 presents one such dataset. A Singla detector consists of two panels, with a gap between them. It is common for electron beam to be positioned in this gap. Determining beam position based on the maximum pixel intensity is not possible in this case because the beam is hidden.

Singla diffraction image

Fig. 3 A diffraction image from DECTRIS Singla detector at eBIC.

First, let’s run the midpoint method on this dataset without any parameters.

dials.search_beam_position method=midpoint imported.expt

Because we did not provide per_image=True parameter, DIALS will go through all the images in the dataset, compute the average image, project that image onto x and y axis, and compute the midpoints. The output of this command is beam_position.png file.

Midpoint method

Fig. 4 Beam position determined by the midpoint method.

The midpoint method is similar to the maximum method in that the average pixel intensity is projected. This projected intensity is then smoothed using a convolution kernel (averaging intensities in a narrow window given by midpoint.convolution_width). As with the maximum method, projecting bad pixels will create unwanted peaks in the projected profile. To solve this, we introduce a parameter exclude_intensity_percent. Before DIALS projects the diffraction image, it will order all image pixels into a one-dimensional array of increasing intensity. The exclude_intensity_percent tells DIALS to discard the top percentage of these pixels (to set them to zero). For example, exclude_intensity_percent=0.1 will exclude 0.1 % of these high-intensity pixels. To further explain the midpoint method we can focus only on the projection along the y axis.

Midpoint method

Fig. 5 How midpoint method determines the beam position. The green curve is the projected average pixel intensity, while the gray shaded rectangle marks the area where direct beam is blocked by some obstacle (the beam intensity in that region goes to zero).

Fig. 5 shows the projection profile’s appearance when some obstacle impedes the direct beam. The midpoint method will draw horizontal lines and compute the intersection points between these lines and the projected profile (the blue dots). Next, it will compute the midpoints between the intersections (the red dots). The average position of the calculated midpoints will correspond to the beam position (the orange vertical dashed line in Fig. 5).

The central assumption of the midpoint method is that the projected profile is a reasonably symmetric function. If the profile is skewed, the position of the average midpoint would not correspond to the beam position. The skewness might come from hitting the detector at an angle. Fig. 5 shows the projected profile is normalized (put in the range of values between zero and one). The number of lines intersecting the projected profile is set with the intersection_range parameter. For example, by default, the intersection range is set from 0.3 to 0.9 with 0.01 distance between the intersecting lines (intersection_range=0.3,0.9,0.01). With this setting, DIALS will draw around sixty intersection lines. When using this parameter, keep in mind the normalization, so always set it in the range between zero and one.

In Fig. 4 (the projection along the y-axis on the right), we see several groups of midpoints (orange, blue, green). Each of these groups corresponds to a local peak in the projected profile. As shown in Fig. 5, each intersecting line might intersect several peaks in the projected profile. The question is: which peak is the direct one? Here, DIALS does several things. First, it groups all the midpoints into distinctive groups based on their proximity. The grouping is determined using the distance_threshold parameter (currently set to 40 pixels). The condition for a new midpoint to be included in an existing group is if it is within the distance_threshold of any known group (that is, the group average position). If the midpoint is not close to any of the existing groups, it will be added to a new group. Next, groups are ranked based on their average width. The average width is computed by averaging the widths of all the intersection lines belonging to a group (see the red horizontal lines in Fig. 5). In the final step, DIALS picks the first three groups of midpoints with the highest average width and selects the one with the highest number of midpoints. This last step ensures that we do not pick a group with only a few intersections (in most cases, the direct beam will have the highest width and number of midpoints). The beam position is then computed as the average midpoint position of the selected group.

Dealing with gap regions

By default, DIALS does not know which region of the image corresponds to the gap. For example, in the case of the Singla detector, all pixels from 512 to 550 along the y-axis are in this dead region. Our result along the y-axis in Fig. 4 was correct, but it was more a lucky coincidence. The wide convolution of the projected profile filled the gap and allowed the midpoint method to work as expected. However, if the convolution width was too narrow (or the gap was too big), the midpoint method might not work as expected. To explain what we mean, let’s run the same command, but let’s not smooth the projected data.

dials.search_beam_position method=midpoint \
                           midpoint.convolution_width=2 imported.expt
Midpoint gap

Fig. 6 Result from the midpoint method obtained with the command above.

Fig. 6 shows the wrong beam position along the y-axis. The reason for this error is simple to explain. Without any convolution, the projected gap region gets an intensity of zero. The problem here is that DIALS does not know where the gap is. It treats the two beam tails as two separate peaks (that is why there are two groups of midpoints, orange and blue). To resolve this problem, we need to tell DIALS where the gap is.

dials.search_beam_position method=midpoint \
                           midpoint.convolution_width=2 \
                           dead_pixel_range_y=505,555  imported.expt

This will produce the correct result

Midpoint dead pixel range along the y

Fig. 7 Beam position corrected with dead_pixel_range_y parameter.

Notice that the dead pixel range along the y-axis that we provided as a parameter is marked with the gray shaded rectangle in the y-projected profile in Fig. 7. Also, we set the region of dead pixels to be slightly wider than the actual region (by about five pixels on both sides). The simple explanation of the dead_pixel_range_y is that DIALS will ignore all intersections within this region. This is equivalent to filling the gap region with infinite intensity. The intersections with the two tails of the original beam are now accounted for properly, and the midpoint method works again.

Equivalently to dead_pixel_range_y, there is a parameter dead_pixel_range_x. Additionally, you can use multiple ranges like dead_pixel_range_y=a,b,c,d. This will set two regions (from a to b, and from c to d).

Inversion method

This method is suitable for datasets where one can clearly see Friedel pairs.

Friedel pairs in the diffraction image

Fig. 8 Friedel pairs (A1, A2) and (B1, B2) in the Singla diffraction image obtained at eBIC.

Sketch of the projected profile

Fig. 9 Sketch of the projected profile with Friedel pairs (no direct beam).

For example, Fig. 8 shows the previous diffraction image from Singla, emphasizing two Friedel pairs. Friedel pairs are positioned symmetrically around the direct beam. In this case, the simplest way to determine the beam position is to connect a single Friedel pair with a vector and divide that distance in half. Another approach would be spot-finding first to determine the positions of Friedel pairs and then compute the midpoints. We plan to use projection again to simplify the problem in our implementation. To explain the inversion method, let us assume we make maximum projection along the y-axis from Fig. 8, and we obtain something similar to the sketch in Fig. 9. There are four peaks corresponding to two Friedel pairs. Because of the equal distance from the direct beam to both spots in every Friedel pair, the beam position becomes the center of inversion for any projection. The question is how to find this point for four peaks in Fig. 9 automatically. One can connect the peaks with lines, compute midpoints, and average them, but which peaks should be connected? In our approach, we use a simple observation. Let’s assume the direct beam is positioned at some point called guess_position (see Fig. 9). We can then invert the projected profile around this point and obtain the pink curve. If guess_position is indeed the center of inversion, the peaks in the inverted curve and those in the original curve will overlap. If this is not the case, the peaks from one curve will overlap with some other peaks (with different intensities) or with low-intensity regions. One way to quantify the overlap between the original and the inverted curve is to multiply them for each pixel and integrate (sum) the product. If the overlap is significant, the integral will be large; if the overlap is low, the integral should be lower. Next, we repeat this procedure in some regions around the guess_position. We move the guess_position to every point within this region, multiply the two curves, and compute the integral to quantify the overlap. Ultimately, we will get a single curve that quantifies the overlap for a range of pixels. Picking the maximum of this curve as the beam position means that the computed overlap at that point is highest, so that point is very likely to be the center of inversion.

[1] Sauter et al., J.Appl.Cryst. 37, 399-409 (2004).