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

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

# Copyright (C) 2003-2005 Peter J. Verveer 

# 

# Redistribution and use in source and binary forms, with or without 

# modification, are permitted provided that the following conditions 

# are met: 

# 

# 1. Redistributions of source code must retain the above copyright 

# notice, this list of conditions and the following disclaimer. 

# 

# 2. Redistributions in binary form must reproduce the above 

# copyright notice, this list of conditions and the following 

# disclaimer in the documentation and/or other materials provided 

# with the distribution. 

# 

# 3. The name of the author may not be used to endorse or promote 

# products derived from this software without specific prior 

# written permission. 

# 

# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 

# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 

# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 

# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 

# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 

# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 

# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 

# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 

# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

 

from __future__ import division, print_function, absolute_import 

 

import numpy 

from . import _ni_support 

from . import _nd_image 

 

__all__ = ['fourier_gaussian', 'fourier_uniform', 'fourier_ellipsoid', 

'fourier_shift'] 

 

 

def _get_output_fourier(output, input): 

if output is None: 

if input.dtype.type in [numpy.complex64, numpy.complex128, 

numpy.float32]: 

output = numpy.zeros(input.shape, dtype=input.dtype) 

else: 

output = numpy.zeros(input.shape, dtype=numpy.float64) 

elif type(output) is type: 

if output not in [numpy.complex64, numpy.complex128, 

numpy.float32, numpy.float64]: 

raise RuntimeError("output type not supported") 

output = numpy.zeros(input.shape, dtype=output) 

elif output.shape != input.shape: 

raise RuntimeError("output shape not correct") 

return output 

 

 

def _get_output_fourier_complex(output, input): 

if output is None: 

if input.dtype.type in [numpy.complex64, numpy.complex128]: 

output = numpy.zeros(input.shape, dtype=input.dtype) 

else: 

output = numpy.zeros(input.shape, dtype=numpy.complex128) 

elif type(output) is type: 

if output not in [numpy.complex64, numpy.complex128]: 

raise RuntimeError("output type not supported") 

output = numpy.zeros(input.shape, dtype=output) 

elif output.shape != input.shape: 

raise RuntimeError("output shape not correct") 

return output 

 

 

def fourier_gaussian(input, sigma, n=-1, axis=-1, output=None): 

""" 

Multi-dimensional Gaussian fourier filter. 

 

The array is multiplied with the fourier transform of a Gaussian 

kernel. 

 

Parameters 

---------- 

input : array_like 

The input array. 

sigma : float or sequence 

The sigma of the Gaussian kernel. If a float, `sigma` is the same for 

all axes. If a sequence, `sigma` has to contain one value for each 

axis. 

n : int, optional 

If `n` is negative (default), then the input is assumed to be the 

result of a complex fft. 

If `n` is larger than or equal to zero, the input is assumed to be the 

result of a real fft, and `n` gives the length of the array before 

transformation along the real transform direction. 

axis : int, optional 

The axis of the real transform. 

output : ndarray, optional 

If given, the result of filtering the input is placed in this array. 

None is returned in this case. 

 

Returns 

------- 

fourier_gaussian : ndarray 

The filtered input. 

 

Examples 

-------- 

>>> from scipy import ndimage, misc 

>>> import numpy.fft 

>>> import matplotlib.pyplot as plt 

>>> fig, (ax1, ax2) = plt.subplots(1, 2) 

>>> plt.gray() # show the filtered result in grayscale 

>>> ascent = misc.ascent() 

>>> input_ = numpy.fft.fft2(ascent) 

>>> result = ndimage.fourier_gaussian(input_, sigma=4) 

>>> result = numpy.fft.ifft2(result) 

>>> ax1.imshow(ascent) 

>>> ax2.imshow(result.real) # the imaginary part is an artifact 

>>> plt.show() 

""" 

input = numpy.asarray(input) 

output = _get_output_fourier(output, input) 

axis = _ni_support._check_axis(axis, input.ndim) 

sigmas = _ni_support._normalize_sequence(sigma, input.ndim) 

sigmas = numpy.asarray(sigmas, dtype=numpy.float64) 

if not sigmas.flags.contiguous: 

sigmas = sigmas.copy() 

 

_nd_image.fourier_filter(input, sigmas, n, axis, output, 0) 

return output 

 

 

def fourier_uniform(input, size, n=-1, axis=-1, output=None): 

""" 

Multi-dimensional uniform fourier filter. 

 

The array is multiplied with the fourier transform of a box of given 

size. 

 

Parameters 

---------- 

input : array_like 

The input array. 

size : float or sequence 

The size of the box used for filtering. 

If a float, `size` is the same for all axes. If a sequence, `size` has 

to contain one value for each axis. 

n : int, optional 

If `n` is negative (default), then the input is assumed to be the 

result of a complex fft. 

If `n` is larger than or equal to zero, the input is assumed to be the 

result of a real fft, and `n` gives the length of the array before 

transformation along the real transform direction. 

axis : int, optional 

The axis of the real transform. 

output : ndarray, optional 

If given, the result of filtering the input is placed in this array. 

None is returned in this case. 

 

Returns 

------- 

fourier_uniform : ndarray 

The filtered input. 

 

Examples 

-------- 

>>> from scipy import ndimage, misc 

>>> import numpy.fft 

>>> import matplotlib.pyplot as plt 

>>> fig, (ax1, ax2) = plt.subplots(1, 2) 

>>> plt.gray() # show the filtered result in grayscale 

>>> ascent = misc.ascent() 

>>> input_ = numpy.fft.fft2(ascent) 

>>> result = ndimage.fourier_uniform(input_, size=20) 

>>> result = numpy.fft.ifft2(result) 

>>> ax1.imshow(ascent) 

>>> ax2.imshow(result.real) # the imaginary part is an artifact 

>>> plt.show() 

""" 

input = numpy.asarray(input) 

output = _get_output_fourier(output, input) 

axis = _ni_support._check_axis(axis, input.ndim) 

sizes = _ni_support._normalize_sequence(size, input.ndim) 

sizes = numpy.asarray(sizes, dtype=numpy.float64) 

if not sizes.flags.contiguous: 

sizes = sizes.copy() 

_nd_image.fourier_filter(input, sizes, n, axis, output, 1) 

return output 

 

 

def fourier_ellipsoid(input, size, n=-1, axis=-1, output=None): 

""" 

Multi-dimensional ellipsoid fourier filter. 

 

The array is multiplied with the fourier transform of a ellipsoid of 

given sizes. 

 

Parameters 

---------- 

input : array_like 

The input array. 

size : float or sequence 

The size of the box used for filtering. 

If a float, `size` is the same for all axes. If a sequence, `size` has 

to contain one value for each axis. 

n : int, optional 

If `n` is negative (default), then the input is assumed to be the 

result of a complex fft. 

If `n` is larger than or equal to zero, the input is assumed to be the 

result of a real fft, and `n` gives the length of the array before 

transformation along the real transform direction. 

axis : int, optional 

The axis of the real transform. 

output : ndarray, optional 

If given, the result of filtering the input is placed in this array. 

None is returned in this case. 

 

Returns 

------- 

fourier_ellipsoid : ndarray 

The filtered input. 

 

Notes 

----- 

This function is implemented for arrays of rank 1, 2, or 3. 

 

Examples 

-------- 

>>> from scipy import ndimage, misc 

>>> import numpy.fft 

>>> import matplotlib.pyplot as plt 

>>> fig, (ax1, ax2) = plt.subplots(1, 2) 

>>> plt.gray() # show the filtered result in grayscale 

>>> ascent = misc.ascent() 

>>> input_ = numpy.fft.fft2(ascent) 

>>> result = ndimage.fourier_ellipsoid(input_, size=20) 

>>> result = numpy.fft.ifft2(result) 

>>> ax1.imshow(ascent) 

>>> ax2.imshow(result.real) # the imaginary part is an artifact 

>>> plt.show() 

""" 

input = numpy.asarray(input) 

output = _get_output_fourier(output, input) 

axis = _ni_support._check_axis(axis, input.ndim) 

sizes = _ni_support._normalize_sequence(size, input.ndim) 

sizes = numpy.asarray(sizes, dtype=numpy.float64) 

if not sizes.flags.contiguous: 

sizes = sizes.copy() 

_nd_image.fourier_filter(input, sizes, n, axis, output, 2) 

return output 

 

 

def fourier_shift(input, shift, n=-1, axis=-1, output=None): 

""" 

Multi-dimensional fourier shift filter. 

 

The array is multiplied with the fourier transform of a shift operation. 

 

Parameters 

---------- 

input : array_like 

The input array. 

shift : float or sequence 

The size of the box used for filtering. 

If a float, `shift` is the same for all axes. If a sequence, `shift` 

has to contain one value for each axis. 

n : int, optional 

If `n` is negative (default), then the input is assumed to be the 

result of a complex fft. 

If `n` is larger than or equal to zero, the input is assumed to be the 

result of a real fft, and `n` gives the length of the array before 

transformation along the real transform direction. 

axis : int, optional 

The axis of the real transform. 

output : ndarray, optional 

If given, the result of shifting the input is placed in this array. 

None is returned in this case. 

 

Returns 

------- 

fourier_shift : ndarray 

The shifted input. 

 

Examples 

-------- 

>>> from scipy import ndimage, misc 

>>> import matplotlib.pyplot as plt 

>>> import numpy.fft 

>>> fig, (ax1, ax2) = plt.subplots(1, 2) 

>>> plt.gray() # show the filtered result in grayscale 

>>> ascent = misc.ascent() 

>>> input_ = numpy.fft.fft2(ascent) 

>>> result = ndimage.fourier_shift(input_, shift=200) 

>>> result = numpy.fft.ifft2(result) 

>>> ax1.imshow(ascent) 

>>> ax2.imshow(result.real) # the imaginary part is an artifact 

>>> plt.show() 

""" 

input = numpy.asarray(input) 

output = _get_output_fourier_complex(output, input) 

axis = _ni_support._check_axis(axis, input.ndim) 

shifts = _ni_support._normalize_sequence(shift, input.ndim) 

shifts = numpy.asarray(shifts, dtype=numpy.float64) 

if not shifts.flags.contiguous: 

shifts = shifts.copy() 

_nd_image.fourier_shift(input, shifts, n, axis, output) 

return output