-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable time-of-flight indexing and Laue/ToF refinement #2662
base: main
Are you sure you want to change the base?
Conversation
…r wavelength/s0 in reflection table first.
…ategy and fix typo.
…f. Added wavelength columns to refinement output.
…thm to mcd. Fix typo when checking wavelength_strategy override.
Just to make sure, is this PR for Laue data collected with ToF detectors? In other words, we cannot use this on X-ray Laue or pink beam datasets without ToF information (i.e. unknown per-spot |
raise ValueError( | ||
"Cannot find max cell for ToF and non-ToF experiments at the same time" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is the right error message. This class gets called in quite a number of places, not just by the indexer where I assume the max cell issue is coming from. So we might end up here in some other situation. Maybe it should be "Cannot create an ExperimentsPredictor for ToF and non-ToF experiments at the same time"
I've written it so you should be able to use this for any data where you have assigned wavelengths to observed reflections, and you have enough confidence in the assignment to minimise your model against them. All your data should need is a If you have any Laue data I could use a basis of a test that would be useful! |
@toastisme The only Laue dataset I found is https://zenodo.org/records/10199220. |
There are quite a lot of new classes added here, but no added tests.
I don't think it is necessary to write individual tests for all of these, as not all of the rotation equivalents of these classes are tested directly in a unit test like manner either. However, some of them are. For example, derivatives are tested versus finite difference approximations in places like A similar test vs finite-differences might be useful for There's also a test of the gradients of the target function The whole machinery of rotation method refinement is also tested against generated reflection positions using ideal geometry in |
Yes completely agree. Thanks for highlighting the key areas to test. I had some dials data / dials data files prs to add some neutron data to write these kind of tests that are now merged. I was hoping to have some X-ray Laue data too. |
Apologies for this being a large PR - it's difficult to separate out the different components. This adds indexing and refinement for time-of-flight data and Laue data more broadly. The main contributions are Laue specific refinement classes that also minimise degrees of freedom with respect to the calculated and observed wavelength of each reflection.
Usage:
dials.index imported.expt strong.refl reflections.weighting_strategy.override=<constant, statistical> reflections.weighting_strategy.wavelength_weight=<weight>
Background
The diffraction condition can be written
where$\mathbf{p^*_0}$ is the reciprocal lattice vector obtained from the candidate UB matrix for a given Miller index. For a rotation experiment we satisfy the condition by identifying the angle $\mathbf{p^*_0}$ must be rotated by to cross the Ewald sphere. For a Laue experiment, we can instead find the required wavelength by rearranging the diffraction condition to give
The target function to minimise during refinement is a weighted sum of squared residuals over all$n$ observed reflections
where$X, Y, \lambda$ correspond to calculated reflection centroid positions in the x, y panel positions, and a wavelength calculated as above, respectively. Likewise, $X_{obs}, Y_{obs}, \lambda_{obs}$ refer to the centroid positions obtained from spot finding. $w_{i,X}, w_{i,Y}, w_{i,\lambda}$ are weight coefficients based on the strategy selected by the user. $L$ has first derivatives
where$p$ refers to a degree of freedom of the model obtained from indexing (e.g. unit cell angles, lengths, panel positions etc.). To refine centroids with respect to their calculated wavelengths we need to calculate $\frac{\partial \lambda}{\partial p}$ . To do this we follow the same approach as for rotational data[1] and use the implicit function theorem. This states that if a given function $G(\lambda, p) = c$ , $\lambda(p)$ has derivatives
In this case$G$ is the diffraction condition, and hence
Terms in the numerator have already been worked out in DIALS[1], so only the denominator needs calculating.
For the first term in the denominator,
and hence
For the second term,
and so
Putting it all together
[1] D. G. Waterman, G. Winter, R. J. Gildea, J. M. Parkhurst, A. S. Brewster, N. K. Sauter, and G. Evans.
Diffraction-geometry refinement in the DIALS framework. Acta Crystallographica Section D, 72(4):558–
575, Apr 2016.
Weighting strategies
I looked at constant and statistical weighting strategies for$w_{\lambda}$ . At least for time-of-flight experiments, the variance along the wavelength direction for each spot is less obviously useful, as the spot profile typically has a long tail. Instead I used the variance in the X and Y multiplied by a constant. Results for different values are given below. exp (blue dashed line) refers to expected results for a given unit cell parameter. Looking at the average mean squared error across the datasets, statistical weighting seems generally better, with the best weighting being 1E4.