Skip to content
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

Accommodate absorption in a diamond anvil cell #1090

Merged
merged 33 commits into from
Mar 13, 2020

Conversation

benjaminhwilliams
Copy link
Member

Diamond anvil cells are commonly used to allow measurement structures under applied pressure. Both the incident and diffracted X-ray beam are attenuated by absorption in the anvils between which the sample is sandwiched. The path length of the incident beam through the diamond, and hence the amount of absorption, depends on the orientation of the cell to the incident beam. The path length of the diffracted beam depends on the orientation of the cell and the diffracted angle. Hence a non-uniform absorption factor applies to reflection intensities, which affects the fidelity of data reduction using the existing DIALS scaling tools.

By modelling the anvils as flat plates, of equal thickness and with parallel sides, the overall absorption factor can be calculated. It is a function of the incident and diffracted beam directions, the thickness of each anvil and their normal (itself a function of the mounting orientation and goniometer rotation) and the linear attenuation coefficient of the anvil material (itself a function of wavelength and the material's density).

We can thereby correct the integrated intensities for the anvil absorption and then apply the post-integration components of the data reduction pipeline as normal, just as though the sample had been measured in air.

For diamond anvil cell data, this tool should be called on the output of dials.integrate before any subsequent processing. The default anvil parameters reflect the cell design used on I19-2 at Diamond Light Source.

Calculate path lengths through the diamond anvils and boost the
integrated intensities to correct for calculated attenuation of the
incident and diffracted beam by the diamond.
When including an external PHIL scope, PHIL balks if the external scope
contains unicode.
Assign the log file name and usage string
@benjaminhwilliams
Copy link
Member Author

There are obviously no tests included here. This comes back to earlier discussions about the best way to incorporate regression data for small molecule work. My preference would be to merge this, test it in the school of hard knocks (I19-2) and make adding tests a separate task.

@rjgildea
Copy link
Contributor

For this pull request you shouldn't need a whole dataset added to dials-data - just the integrated experiments/reflections should be enough to exercise this command. To test correct_intensities_for_dac_attenuation you could probably even generate some fake experiments/reflections on the fly for the purposes of exercising the function.

@graeme-winter
Copy link
Contributor

Agree with comments from @rjgildea on tests - they can run on very small data sets, anything high pressure will be fine, just need the integrated reflection files. Looking through the changes now.

@graeme-winter
Copy link
Contributor

Not a precondition on the merge but a proposal for the future - pretty sure everything done in here could easily have been achieved with flex calculations rather than scipy/numpy stuff - which would make it slightly more in line with the rest of the dials code base, though admittedly slightly harder for the "developer in the street"

Copy link
Contributor

@graeme-winter graeme-winter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modulo comments re: testing and a handful of small suggestions is a useful improvement thank you.

Copy link
Contributor

@jbeilstenedmands jbeilstenedmands left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall. Wasn't really able to follow the maths just from reading but trust you've got this sorted :) One thing regarding multiple reflection tables, I notice you join them all together at the start, then go through selecting each one to apply the corrections individually.
I think we've shared our differing views on this issue before, but in my opinion its better to split the input reflections into a list of single-dataset tables, then have a function which runs on a single experiment and single-dataset reflection table, as the algorithm is basically doing in this case (or have a function working on an ExperimentList and list of reflection tables the same length). The tables can then be joined together at the end for output. This was probably makes it easier for the algorithm code to be more 'functional' in my opinion.

@benjaminhwilliams
Copy link
Member Author

Not a precondition on the merge but a proposal for the future - pretty sure everything done in here could easily have been achieved with flex calculations rather than scipy/numpy stuff - which would make it slightly more in line with the rest of the dials code base, though admittedly slightly harder for the "developer in the street"

I wasn't sure if there was an efficient way in flex to perform some of the arithmetic here, such as the dot product of each of an array of vectors with each of another array of vectors. This may simply be flex-ignorance on my part but sometimes life's just too short when the alternative is easy, quick and staring me in the face.

@benjaminhwilliams
Copy link
Member Author

benjaminhwilliams commented Jan 14, 2020

Looks good overall. Wasn't really able to follow the maths just from reading but trust you've got this sorted :)

Yes, I started trying to write it out in the PR description and then remembered that maths in GitHub isn't easy. Perhaps it would be better in the wiki or something. I'll finish writing it up so people can refer to it in future.

One thing regarding multiple reflection tables, I notice you join them all together at the start, then go through selecting each one to apply the corrections individually.
I think we've shared our differing views on this issue before, but in my opinion its better to split the input reflections into a list of single-dataset tables, then have a function which runs on a single experiment and single-dataset reflection table, as the algorithm is basically doing in this case (or have a function working on an ExperimentList and list of reflection tables the same length). The tables can then be joined together at the end for output. This was probably makes it easier for the algorithm code to be more 'functional' in my opinion.

I may be coming round to your way of thinking on this. I'll see about refactoring it slightly.

@phyy-nx
Copy link
Member

phyy-nx commented Jan 14, 2020 via email

@benjaminhwilliams
Copy link
Member Author

benjaminhwilliams commented Jan 14, 2020

Hi, just to help out a bit :)

Ah, thanks @phyy-nx. And if I want to apply each of an array of rotation operators to each of an array of vectors, is there a flexy way to do that?

@phyy-nx
Copy link
Member

phyy-nx commented Jan 14, 2020 via email

  • Simplify the algebra to match the documentation and reduce repeat
    calculation of some arrays.
  • Add examples and reword documentation.
dials.rescale_diamond_anvil_cell → dials.anvil_correction.
  • Add `.rst` documentation.
  • Add `.svg` figure.
  • Add `.dxf` drawing from which the figure was generated, for future
    editing.
@benjaminhwilliams
Copy link
Member Author

Looks good overall. Wasn't really able to follow the maths just from reading but trust you've got this sorted :)

The changes to the docs in this branch contain details of the arithmetic, in case you want to look that over.

Crucially, catch them *before* they're deleted.
We need only correct non-null values for each integration method.
Also, woops, remove a rogue print.
@benjaminhwilliams
Copy link
Member Author

@rjgildea, this now has tests. Does it have your approval?

Copy link
Contributor

@rjgildea rjgildea left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I note that this code makes heavy use of numpy/scipy routines. I don't know whether this is something we want to encourage/discourage, particularly where there are alternative ways to accomplish the same using flex arrays. I appreciate that you probably already know how to accomplish certain things with numpy arrays, whereas you may not know how to do the same with flex arrays.

test/command_line/test_anvil_correction.py Outdated Show resolved Hide resolved
test/command_line/test_anvil_correction.py Outdated Show resolved Hide resolved
test/command_line/test_anvil_correction.py Outdated Show resolved Hide resolved
command_line/anvil_correction.py Outdated Show resolved Hide resolved
command_line/anvil_correction.py Show resolved Hide resolved
command_line/anvil_correction.py Show resolved Hide resolved
Copy link
Member

@Anthchirp Anthchirp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

humbly suggest moving the .dxf and .svg files into the dials.github.io repository (same as other images)

command_line/anvil_correction.py Outdated Show resolved Hide resolved
command_line/anvil_correction.py Outdated Show resolved Hide resolved
command_line/anvil_correction.py Outdated Show resolved Hide resolved
command_line/anvil_correction.py Outdated Show resolved Hide resolved
benjaminhwilliams and others added 12 commits March 11, 2020 11:41
Co-Authored-By: Markus Gerstel <2102431+Anthchirp@users.noreply.github.com>
Co-Authored-By: Markus Gerstel <2102431+Anthchirp@users.noreply.github.com>
Also remove redundant .optional parameter attribute.
Move from DIALS repo to dials.github.io.
Co-Authored-By: Richard Gildea <rjgildea@users.noreply.github.com>
…_anvil_cell

# Conflicts:
#	test/command_line/test_anvil_correction.py
Also make small adjustment to parameter help text.
Scopes are better than dels.
@benjaminhwilliams
Copy link
Member Author

humbly suggest moving the .dxf and .svg files into the dials.github.io repository (same as other images)

Done.

@benjaminhwilliams
Copy link
Member Author

I note that this code makes heavy use of numpy/scipy routines. I don't know whether this is something we want to encourage/discourage, particularly where there are alternative ways to accomplish the same using flex arrays. I appreciate that you probably already know how to accomplish certain things with numpy arrays, whereas you may not know how to do the same with flex arrays.

I leave this to future discussion. I appreciate the desire to keep things uniform, and I know @ndevenish has opinions about this, but I reckon that's another problem for another time.

@benjaminhwilliams
Copy link
Member Author

It looks like the only failures in the Travis builds are Python 3 build tests that seem to be completely unaffected by this PR. Otherwise I'm ready to merge...

@Anthchirp
Copy link
Member

Some sort of smtbx build failure, no clear idea why.
Travis on long-running branches can be a problem as it doesn't necessarily have the correct cctbx repository checkout for the time you branched off master.

If you rebased your branch on master this will likely be fixed.

@benjaminhwilliams benjaminhwilliams merged commit 018147c into master Mar 13, 2020
@benjaminhwilliams benjaminhwilliams deleted the diamond_anvil_cell branch March 13, 2020 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants