Skip to content

Commit 071a71f

Browse files
committed
feat: calculate_fr now rounds to a power of 2 number of points for padding when doing fft
1 parent b53326b commit 071a71f

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

glassure/transform.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def calculate_fr(
4545
4646
:param sq_pattern: Structure factor S(Q) with lim_inf S(Q) = 1 and unit(q)=A^-1
4747
:param r: numpy array giving the r-values for which F(r) will be calculated,
48-
default is 0 to 10 with 0.01 as a step. units should be in Angstrom.
48+
default is 0.01 to 10 with 0.01 as a step. units should be in Angstrom.
4949
:param use_modification_fcn: boolean flag whether to use the Lorch modification function
5050
:param method: determines the method used for calculating fr, possible values are:
5151
- 'integral' solves the Fourier integral, by calculating the integral
@@ -54,7 +54,8 @@ def calculate_fr(
5454
:return: F(r) pattern
5555
"""
5656
if r is None:
57-
r = np.linspace(0.01, 10, 1000)
57+
r = np.arange(0.0, 10.005, 0.01)
58+
r[0] = 1e-10 # to avoid division by zero
5859

5960
q, sq = sq_pattern.data
6061
if use_modification_fcn:
@@ -75,12 +76,22 @@ def calculate_fr(
7576
r_step = r[1] - r[0]
7677

7778
n_out = np.max([len(q), int(np.pi / (r_step * q_step))])
78-
q_max_for_ifft = 2 * n_out * q_step
79-
y_for_ifft = np.concatenate(
80-
(modification * q * (sq - 1), np.zeros(2 * n_out - len(q)))
81-
)
79+
n_out = 2 ** int(np.ceil(np.log2(n_out)))
80+
81+
# find the number of q points needed to resolve the r-space
82+
q_max_target = 2 * np.pi / r_step
83+
n_target = int(np.ceil(q_max_target / q_step))
84+
85+
# Round up to the next power of 2 for fastest possible fft
86+
n_out = 2 ** int(np.ceil(np.log2(n_target)))
87+
88+
q_max_for_ifft = n_out * q_step
89+
90+
f_q = modification * q * (sq - 1)
91+
y_for_ifft = np.zeros(n_out)
92+
y_for_ifft[: len(f_q)] = f_q
8293

83-
ifft_result = np.fft.ifft(y_for_ifft) * 2 / np.pi * q_max_for_ifft
94+
ifft_result = np.fft.ifft(y_for_ifft) * 2 * q_max_for_ifft / np.pi
8495
ifft_imag = np.imag(ifft_result)[:n_out]
8596
ifft_x_step = 2 * np.pi / q_max_for_ifft
8697
ifft_x = np.arange(n_out) * ifft_x_step

0 commit comments

Comments
 (0)