-
Notifications
You must be signed in to change notification settings - Fork 84
/
variance_generator.py
150 lines (128 loc) · 5.42 KB
/
variance_generator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# -*- coding: utf-8 -*-
# Copyright 2016-2024 The pyXem developers
#
# This file is part of pyXem.
#
# pyXem is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyXem is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyXem. If not, see <http://www.gnu.org/licenses/>.
"""Variance generators in real and reciprocal space for fluctuation electron microscopy."""
import numpy as np
from hyperspy.signals import Signal2D
from hyperspy.api import stack
from pyxem.signals import DiffractionVariance2D, ImageVariance
from pyxem.utils._signals import (
_transfer_navigation_axes_to_signal_axes,
_transfer_signal_axes,
)
from pyxem.utils._deprecated import deprecated
class VarianceGenerator:
"""Generates variance images for a specified signal and set of aperture
positions.
Parameters
----------
signal : ElectronDiffraction2D
The signal of electron diffraction patterns to be indexed.
"""
@deprecated(
since="0.15",
alternative="pyxem.signals.diffraction2d.get_variance",
removal="1.0.0",
)
def __init__(self, signal, *args, **kwargs):
self.signal = signal
self.thickness_filter = None
# add a check for calibration
@deprecated(
since="0.15",
alternative="pyxem.signals.diffraction2d.get_variance",
removal="1.0.0",
)
def get_diffraction_variance(self, dqe, set_data_type=None):
"""Calculates the variance in scattered intensity as a function of
scattering vector.
Parameters
----------
dqe : float
Detective quantum efficiency of the detector for Poisson noise
correction.
data_type : numpy data type.
For numpy data types, see
https://docs.scipy.org/doc/numpy-1.13.0/user/basics.types.html.
This is incorporated as squaring the numbers in meansq_dp results
in considerably larger than the ones in the original array. This can
result in an overflow error that is difficult to distinguish. Hence
the data can be converted to a different data type to accommodate.
Returns
-------
vardps : DiffractionVariance2D
A DiffractionVariance2D object containing the mean DP, mean
squared DP, and variance DP.
"""
dp = self.signal
mean_dp = dp.mean((0, 1))
if set_data_type is None:
meansq_dp = Signal2D(np.square(dp.data)).mean((0, 1))
else:
meansq_dp = Signal2D(np.square(dp.data.astype(set_data_type))).mean((0, 1))
normvar = (meansq_dp.data / np.square(mean_dp.data)) - 1.0
var_dp = Signal2D(normvar)
corr_var_array = var_dp.data - (np.divide(dqe, mean_dp.data))
corr_var_array[np.isinf(corr_var_array)] = 0
corr_var_array[np.isnan(corr_var_array)] = 0
corr_var = Signal2D(corr_var_array)
vardps = stack((mean_dp, meansq_dp, var_dp, corr_var))
sig_x = vardps.data.shape[1]
sig_y = vardps.data.shape[2]
dv = DiffractionVariance2D(vardps.data.reshape((2, 2, sig_x, sig_y)))
dv = _transfer_signal_axes(dv, self.signal)
return dv
@deprecated(
since="0.15",
alternative="pyxem.signals.diffraction2d.get_variance",
removal="1.0.0",
)
def get_image_variance(self, dqe):
"""Calculates the variance in scattered intensity as a function of
scattering vector. The calculated variance is normalised by the mean
squared, as is appropriate for the distribution of intensities. This
causes a problem if Poisson noise is significant in the data, resulting
in a divergence of the Poisson noise term. To in turn remove this
effect, we subtract a dqe/mean_dp term (although it is suggested that
dqe=1) from the data, creating a "poisson noise-free" corrected variance
pattern. DQE is fitted to make this pattern flat.
Parameters
----------
dqe : float
Detective quantum efficiency of the detector for Poisson noise
correction.
Returns
-------
varims : ImageVariance
A two dimensional Signal class object containing the mean DP, mean
squared DP, and variance DP, and a Poisson noise-corrected variance
DP.
"""
im = self.signal.T
mean_im = im.mean((0, 1))
meansq_im = Signal2D(np.square(im.data)).mean((0, 1))
normvar = (meansq_im.data / np.square(mean_im.data)) - 1.0
var_im = Signal2D(normvar)
corr_var_array = normvar - (np.divide(dqe, mean_im.data))
corr_var_array[np.invert(np.isfinite(corr_var_array))] = 0
corr_var = Signal2D(corr_var_array)
varims = stack((mean_im, meansq_im, var_im, corr_var))
sig_x = varims.data.shape[1]
sig_y = varims.data.shape[2]
iv = ImageVariance(varims.data.reshape((2, 2, sig_x, sig_y)))
iv = _transfer_navigation_axes_to_signal_axes(iv, self.signal)
return iv