In [27]:
import gnuplot as gp
import numpy as np
from numpy import random, fft
from functools import reduce, partial
from math import pi
def _wave_number(s):
"""compute wave numbers for fourier transforms"""
N = s[0]
i = np.indices(s)
return np.where(i > N/2, i - N, i)
def _scale_filter(B, t):
"""returns discrete scale space filter, take care with units:
[res] = Mpc / pixel, [k] = 1 / Mpc, [t] = Mpc**2"""
def f(K):
return reduce(
lambda x, y: x*y,
(np.exp(t / B.res**2 * (np.cos(k * B.res) - 1)) for k in K))
return f
class Box:
"""store parameters for the box"""
def __init__(self, dim, N, L):
self.N = N
self.L = L
self.res = L/N
self.dim = dim
self.shape = (self.N,) * dim
self.size = reduce(lambda x, y: x*y, self.shape)
self.K = _wave_number(self.shape) * 2*pi / self.L
self.k = np.sqrt((self.K**2).sum(axis=0))
self.k_max = N*pi/L
self.k_min = 2*pi/L
def _K_pow(k, n):
"""raise |k| to the <n>-th power safely"""
save = np.seterr(divide = 'ignore')
a = np.where(k == 0, 0, k**n)
np.seterr(**save)
return a
B = Box(2, 512, 100.0)
# create some white noise
wn = random.normal(0, 1, B.shape)
# apply a power-spectrum
f = fft.ifftn(fft.fftn(wn) * np.sqrt(_K_pow(B.k, -2)) * _scale_filter(B, 0.1)(B.K)).real
gp.plot("unset key", "set size square",
"set xrange [-{0}:{0}] ; set yrange [-{0}:{0}]".format(B.L/2),
gp.plot_data(gp.array(f,
"dx={0} dy={0} origin=(-{1}+{0}/2,-{1}+{0}/2) with image".format(
B.L/B.N, B.L/2))))
In [39]:
from IPython.display import display, Image
import os
In [43]:
x = np.linspace(-B.L/2, B.L/2, B.N)
y = f[0]
g = gp.Gnuplot()
g("set term pdf font 'Bitstream Charter'",
"set output 'tmp.pdf'",
"set key bottom right box",
gp.plot_data(gp.record(np.c_[x, y], "t'hoi' with lines")))
g.terminate()
os.system("convert tmp.pdf tmp.png")
display(Image(filename="tmp.png"))
In [ ]: