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

Add better support for correcting for shift of diffraction pattern as function of probe position #746

Merged
merged 13 commits into from
Apr 3, 2021

Conversation

magnunor
Copy link
Collaborator

@magnunor magnunor commented Mar 21, 2021

Background

A common artifact in scanning electron diffraction is dscan, where the center position of the diffraction position shifts as a function of scan position. This effect is typically a slow and monotonic "shift" of the center position, in (most) cases being close to linear. There are ways of removing this effect in pyxem, for example via Diffraction2D.center_direct_beam. It works by finding the direct beam position in each scan position, and moving this to the center of the signal dimensions. This works for a large number of samples, where the direct beam is clearly visible, and fairly homogeneous.

However, for parts of some samples, the material can be so thick or heavily diffracting, that the center position of the direct beam is hard to resolve. In that situation, we can use some more ideal reference region to find the amount of dscan. Next, a linear plane can be fitted to these regions to find the dscan in the thick/heavily diffracting regions.


Changes

This pull request implements a new class, BeamShift, to handle exactly this. It inherits Signal1D, and has the beam position in the signal dimension, and the scan positions in the navigation dimensions.

  • get_direct_beam_position now return this new class
  • The class has the make_linear_plane method which fits a linear plane to the x and y beam positions, and replaces the original data with this plane. This function has a mask parameter, which is used to mask any "bad" regions.
    • This can then be passed as center_direct_beam(shifts=s_beam_shift)
  • The class also has a to_dpcsignal(), which transposes the BeamShift class, and returns a DPCSignal object (which is more focused on analysing the beam shift itself, for example magnetic or ferroelectric materials).

In addition, the pull request changes the _fit_ramp_to_image to make it more general, to facilitate the aforementioned processing.


Todo list

  • Is BeamShift a good class name?
  • Finish implementation
  • Change and add new unit tests
  • Add this functionality to a notebook

Comments

  • This type of processing might be tricky for lazy processing, as the scan positions are no longer independent from each other. Thus, currently make_linear_plane does not have a lazy version. In practice, the easiest way of doing this is by first running s_beam_shift.compute().

The functionality can also be useful for getting potentially better direct beam centering, since currently inhomogeneities in the direct beam can lead to erroneous shifting of the direct beam. For example in the image, where many of the variations are due to grain boundaries:

beam_shift_x

By replacing this "raw" direct beam position with a fitted linear plane, the effect from the grain boundaries will be diminished.


Future work

  • For larger scan areas, a linear plane isn't enough to model the dscan. For this, a vacuum scan might be necessary. There should be some functionality for handling this.

@pc494
Copy link
Member

pc494 commented Mar 22, 2021

I'm happy with the design of this. I agree that I would expect a user to be able to compute a BeamShift object (and so its methods don't need to work lazily)

- Add unit tests
- Remove old functions related to correct_ramp, which have been
replaced by new, more general functions.
- Fix a bug in center_direct_beam, when shifts was a non-lazy signal
@coveralls
Copy link

coveralls commented Mar 23, 2021

Coverage Status

Coverage increased (+0.01%) to 100.0% when pulling e5f25d1 on magnunor:beam_shift_signal into 42134d8 on pyxem:master.

@magnunor
Copy link
Collaborator Author

This should be good to go! Not sure how best to add this to a notebook. In theory having it as a part of a bigger one is nice, but I could make a new one showing some of the processing "pipeline" I've been working on.

@pc494 pc494 self-requested a review March 25, 2021 10:58
@pc494
Copy link
Member

pc494 commented Mar 25, 2021

Great, thanks @magnunor, hoping to get this reviewed by the end of the week. In terms of the notebooks, I think it fits nicely in one of the subsections of demo 10: "correcting d-scan"

Copy link
Member

@pc494 pc494 left a comment

Choose a reason for hiding this comment

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

This is basically good to go, but it needs docstrings (for make_linear_plane and the to/from dpc/beam_shift) functions and a CHANGELOG update.

@dnjohnstone
Copy link
Member

dnjohnstone commented Mar 27, 2021

Correcting for a systematic shift in the direct beam position in the diffraction pattern plane is a good feature, thanks!

But please can we tighten up the language here before this is merged, which I think is scientifically/technically dubious right now.

I don't really know what "A common artifact in scanning electron diffraction is dscan" means, partly because I've not seen "dscan" used like that (can you provide a reference for that usage?) - to me, the artifact is "a shift in the direct beam position in the diffraction plane resulting from the electron beam straying from the optical axis across a scanned region". I.e. a shift in the direct beam position resulting from imperfect electron-optical alignment rather than any property of the sample.

So I think what you're trying to do is to apply a digital correction for this case which could be considered as the case when the physical "de-scan" correction (https://www.jeol.co.jp/en/words/emterms/search_result.html?keyword=de-scan) is imperfect.

In other words, it would make more sense to me to use a phrase like "apply a digital de-scan correction" than to say "correct for a dscan artefact". Can you provide a reference justifying that this should be a linear correction on electron-optical grounds? Or should we be making clear that this is an approximation?

Am I making sense or am I being silly?

@magnunor
Copy link
Collaborator Author

This is basically good to go, but it needs docstrings (for make_linear_plane and the to/from dpc/beam_shift) functions and a CHANGELOG update.

Indeed! I'll fix that.

But please can we tighten up the language here before this is merged, which I think is scientifically/technically dubious right now.

Yeah, I agree. I wrote this perhaps a bit too colloquially, I'll make the language a bit more precise.

I don't really know what "A common artifact in scanning electron diffraction is dscan" means, partly because I've not seen "dscan" used like that (can you provide a reference for that usage?) - to me, the artifact is "a shift in the direct beam position in the diffraction plane resulting from the electron beam straying from the optical axis across a scanned region". I.e. a shift in the direct beam position resulting from imperfect electron-optical alignment rather than any property of the sample.

So I think what you're trying to do is to apply a digital correction for this case which could be considered as the case when the physical "de-scan" correction (https://www.jeol.co.jp/en/words/emterms/search_result.html?keyword=de-scan) is imperfect.

In other words, it would make more sense to me to use a phrase like "apply a digital de-scan correction" than to say "correct for a dscan artefact". Can you provide a reference justifying that this should be a linear correction on electron-optical grounds? Or should we be making clear that this is an approximation?

This type of "artefact" is very common and noticeable when doing STEM-DPC with a fast pixelated electron detector to image for example magnetic fields. It is (as you write here), an effect of the centre of the diffraction pattern changing as a function of probe position is a STEM scan. As far as I know, it is inevitable when scanning over large regions in the STEM, and it gets worse the bigger region you're scanning. Thus, it is not noticeable of you're scanning 10 x 10 nanometers, but becomes much more noticable when scanning 10 x 10 micrometers. The reason I called it an artefact, is that it is kind of an artefact when working with STEM-DPC data, as the "de-scan" will look like a magnetic or electric field. This is seen in the images here, which shows the beam shift from a magnetic STEM-DPC dataset. The ferromagnetic domains are "on top of" the slowly varying beam shift caused by the scanning system.

stem_dpc_beam_shift

As far as I know, the only way to compensate for it is having dedicated "de-scan" correction coils below the sample. However, a large number of microscopes does not have this. For example 5+ year old Jeol microscopes. In addition, for sufficiently large scan regions, even the de-scan correction coils can't remove all of this, thus requiring some type of correction in the post processing.

For medium sized regions (100-500 nm), a linear plane seems to work fine for most cases. For larger regions (1 um and upwards), quadratic or higher order planes are sometimes necessary. At some point, the best solution is to acquire a vacuum dataset, and use that as the correction.

I'll improve up the docstring texts a bit, to make them more precise.

@magnunor magnunor changed the title Add better support for removing dscan Add better support for correcting for shift of diffraction pattern as function of probe position Mar 29, 2021
@magnunor
Copy link
Collaborator Author

I added a (fairly) extensive docstring for make_linear_plane, the to_... and did some minor changes to the correct_ramp.

@dnjohnstone, do you think the make_linear_plane docstring text works better now?

@dnjohnstone dnjohnstone merged commit 2395401 into pyxem:master Apr 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants