Add option to have spot centers off pixel centers
Description of the change
Previously, Simulation2d.get_diffraction_pattern rounded coordinates down to nearest pixel in the output pattern, before adding a gaussian blur. This PR implements a more manual gaussian blurring, evaluating the gaussian without assuming integer spot coordinates instead of using convolution. This gives more accurate spot positions, which is important when using these patterns in external analysis tools. It is slower, but using numba made it only around 20% slower (as opposed to 800% slower without).
Progress of the PR
- [x] Docstrings for all functions
- [x] Unit tests with pytest for all lines
- [x] Clean code style by running black
Minimal example of the bug fix or new feature
# Setup
from diffpy.structure import Structure, Atom, Lattice
from orix.crystal_map import Phase
from diffsims.generators.simulation_generator import SimulationGenerator
l = Lattice(10, 10, 10, 90, 90, 90)
a = [Atom("Au", (0, 0, 0))]
s = Structure(a, l)
p = Phase(structure=s, space_group=1)
gen = SimulationGenerator()
sim = gen.calculate_diffraction2d(p)
Performance analysis:
%%timeit
sim.get_diffraction_pattern(shape=(100,100), sigma=1, fast=True)
205 µs ± 4.61 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%%timeit
sim.get_diffraction_pattern(shape=(100,100), sigma=1, fast=False)
250 µs ± 2.8 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
New is around 25% slower.
Qualitative difference in resulting plots:
from matplotlib import pyplot as plt
plt.figure()
plt.subplot(1, 2, 1)
kwargs = dict(
shape=(10, 10),
sigma=1,
normalize=False,
fast_clip_threshold=0.1,
calibration=0.001, # Very small calibration = only direct beam
)
fast = sim.get_diffraction_pattern(fast=True, **kwargs)
plt.imshow(fast, vmax=20)
plt.subplot(1, 2, 2)
slow = sim.get_diffraction_pattern(fast=False, **kwargs)
plt.imshow(slow, vmax=20)
In the example above, since the shape is 10x10, the center is not at a pixel coordinate, but at (4.5, 4.5). This is rounded to (5, 5) in the fast (current) mode.
Note that there is a bug where the direct beam is added twice to the simulations. For the fast mode, this is fine, as the intensity of each spot is set rather than summed (before blurring). For the new, however, the direct beam is twice as intense as it should. This is fixed in #232.
For reviewers
- [ ] The PR title is short, concise, and will make sense 1 year later.
- [ ] New functions are imported in corresponding
__init__.py. - [ ] New features, API changes, and deprecations are mentioned in the
unreleased section in
CHANGELOG.rst. - [ ] Contributor(s) are listed correctly in
creditsindiffsims/release_info.pyand in.zenodo.json.