FFT/2d_fourie/spin_image.py
2023-04-11 21:43:46 +02:00

284 lines
10 KiB
Python

import numpy as np
import scipy
import scipy.fftpack as sfft
import scipy.signal
import tqdm
from cache import timeit
class SpinImage_Two_Phase:
resolution = 0.05
offset = 40
@timeit
def __init__(self, x_pos_low, y_pos_low, x_pos_high, y_pos_high):
assert x_pos_low.shape == y_pos_low.shape
assert x_pos_high.shape == y_pos_high.shape
assert x_pos_low.shape == x_pos_high.shape
offset_shift = self.offset * self.resolution
x_pos_low = x_pos_low - np.min(x_pos_low) + offset_shift
y_pos_low = y_pos_low - np.min(y_pos_low) + offset_shift
x_pos_high = x_pos_high - np.min(x_pos_high) + offset_shift
y_pos_high = y_pos_high - np.min(y_pos_high) + offset_shift
max_len_x = np.maximum(np.max(x_pos_low), np.max(x_pos_high))
max_len_y = np.maximum(np.max(y_pos_low), np.max(y_pos_high))
self.length_x = max_len_x + (self.offset + 1) * self.resolution
self.length_y = max_len_y + (self.offset + 1) * self.resolution
self.x_ind = np.arange(0, self.length_x, self.resolution) # angstrom
self.y_ind = np.arange(0, self.length_y, self.resolution) # angstrom
self.x_low, self.y_low = self._stuff(x_pos_low, y_pos_low)
self.x_high, self.y_high = self._stuff(x_pos_high, y_pos_high)
X, Y = np.meshgrid(self.x_ind, self.y_ind, indexing="ij")
print(X.shape, self.x_low.flatten().max(), self.y_low.flatten().max())
sigma = .1
self.low_list = []
for x, y, x_ind, y_ind in zip(
x_pos_low.flatten(),
y_pos_low.flatten(),
self.x_low.flatten(),
self.y_low.flatten(),
):
xl, yl, xu, yu = self.clean_bounds(
x_ind - self.offset,
y_ind - self.offset,
x_ind + self.offset,
y_ind + self.offset,
X.shape,
)
self.low_list.append(np.exp(-0.5 * ((X[xl:xu, yl:yu] - x) ** 2 +
(Y[xl:xu, yl:yu] - y) ** 2) / sigma**2))
self.low_list = np.array(
self.low_list, dtype=object)
#print("BEFOR:", self.low_list.shape)
#self.low_list = self.low_list.reshape((*self.x_high.shape,80,80))
#print("HIER:", self.low_list.shape)
self.high_list = []
for x, y, x_ind, y_ind in zip(
x_pos_high.flatten(),
y_pos_high.flatten(),
self.x_high.flatten(),
self.y_high.flatten(),
):
xl, yl, xu, yu = self.clean_bounds(
x_ind - self.offset,
y_ind - self.offset,
x_ind + self.offset,
y_ind + self.offset,
X.shape,
)
self.high_list.append(np.exp(-0.5 * ((X[xl:xu, yl:yu] - x) ** 2 +
(Y[xl:xu, yl:yu] - y) ** 2) / sigma**2))
self.high_list = np.array(self.high_list, dtype=object)
def clean_bounds(self, xl, yl, xu, yu, shape):
if xl < 0:
xl = 0
if yl < 0:
yl = 0
if xu > shape[0]:
xu = shape[0]
if yu > shape[1]:
yu = shape[1]
return xl, yl, xu, yu
def _stuff(self, pos_x, pos_y):
xind = np.searchsorted(self.x_ind, pos_x).astype(int)
yind = np.searchsorted(self.y_ind, pos_y).astype(int)
return xind, yind
@timeit
def apply_mask(self, maske):
mask = np.empty_like(self.x_high, dtype=bool)
mask[0::2, 0::2] = maske
mask[1::2, 0::2] = maske
mask[0::2, 1::2] = maske
mask[1::2, 1::2] = maske
mask = mask.flatten()
self.img = np.zeros((self.x_ind.size, self.y_ind.size))
print(self.img.shape)
for x, y, dat in zip(
self.x_high.flatten()[mask],
self.y_high.flatten()[mask],
self.high_list[mask],
):
xl, yl, xu, yu = self.clean_bounds(
x - self.offset,
y - self.offset,
x + self.offset,
y + self.offset,
self.img.shape,
)
self.img[x - self.offset: x + self.offset,
y - self.offset: y + self.offset] = dat
self.img[x, y] += 1
mask = np.invert(mask)
for x, y, dat in zip(
self.x_high.flatten()[mask],
self.y_high.flatten()[mask],
self.high_list[mask],
):
xl, yl, xu, yu = self.clean_bounds(
x - self.offset,
y - self.offset,
x + self.offset,
y + self.offset,
self.img.shape,
)
if self.img[xl:xu, yl:yu].shape == dat.shape:
self.img[xl:xu, yl:yu] = dat
else:
self.img[x, y] += 1
@timeit
def fft(self):
Z_fft = sfft.fft2(self.img)
Z_shift = sfft.fftshift(Z_fft)
fft_freqx = sfft.fftfreq(self.img.shape[0], self.resolution)
fft_freqy = sfft.fftfreq(self.img.shape[1], self.resolution)
fft_freqx_clean = sfft.fftshift(fft_freqx)
fft_freqy_clean = sfft.fftshift(fft_freqy)
return fft_freqx_clean, fft_freqy_clean, np.abs(Z_shift) ** 2
@timeit
def plot(self, ax, scale=None):
if scale is None:
ax.imshow(self.img)
else:
quad = np.ones((int(scale / self.resolution),
int(scale / self.resolution)))
img = scipy.signal.convolve2d(self.img, quad)
ax.imshow(img)
@timeit
def pad_it_square(self, additional_pad=0, size=None):
h = self.img.shape[0]
w = self.img.shape[1]
xx = np.maximum(h, w) + 2 * additional_pad + 1
if size is not None:
xx = np.maximum(xx, size)
yy = xx
a = (xx - h) // 2
aa = xx - a - h
b = (yy - w) // 2
bb = yy - b - w
self.img = np.pad(self.img, pad_width=(
(a, aa), (b, bb)), mode="constant")
def gaussian(self, sigma):
x = np.arange(-self.length_x / 2, self.length_x / 2, self.resolution)
y = np.arange(-self.length_y / 2, self.length_y / 2, self.resolution)
X, Y = np.meshgrid(x, y)
z = 1 / (2 * np.pi * sigma * sigma) * \
np.exp(-(X**2 / (2 * sigma**2) + Y**2 / (2 * sigma**2)))
self.img = np.multiply(self.img, z.T)
class SpinImage:
resolution = 0.05
def __init__(self, x_pos, y_pos):
x_pos = x_pos - np.min(x_pos)
y_pos = y_pos - np.min(y_pos)
self.length_x = np.max(x_pos) + self.resolution
self.length_y = np.max(y_pos) + self.resolution
self.img = self.image_from_pos(x_pos, y_pos)
def image_from_pos(self, pos_x, pos_y):
x_ind = np.arange(0, self.length_x, self.resolution) # angstrom
y_ind = np.arange(0, self.length_y, self.resolution) # angstrom
img = np.zeros((x_ind.size, y_ind.size))
xind = np.searchsorted(x_ind, pos_x)
yind = np.searchsorted(y_ind, pos_y)
img[xind, yind] = 1
return img
def image_from_pos_with_gauss(self, pos_x, pos_y, sigma=1):
x_ind = np.arange(0, self.length_x, self.resolution) # angstrom
y_ind = np.arange(0, self.length_y, self.resolution) # angstrom
img = np.zeros((x_ind.size, y_ind.size))
X, Y = np.meshgrid(y_ind, x_ind)
for px, py in tqdm.tqdm(zip(pos_x.flatten(), pos_y.flatten())):
img += np.exp(-0.5 * ((X - px) ** 2 + (Y - py) ** 2) / sigma**2)
return img
def fft(self):
Z_fft = sfft.fft2(self.img)
Z_shift = sfft.fftshift(Z_fft)
fft_freqx = sfft.fftfreq(self.img.shape[0], self.resolution)
fft_freqy = sfft.fftfreq(self.img.shape[1], self.resolution)
fft_freqx_clean = sfft.fftshift(fft_freqx)
fft_freqy_clean = sfft.fftshift(fft_freqy)
return fft_freqx_clean, fft_freqy_clean, np.abs(Z_shift) ** 2
def pad_it_square(self, additional_pad=0, size=None):
h = self.img.shape[0]
w = self.img.shape[1]
xx = np.maximum(h, w) + 2 * additional_pad + 1
if size is not None:
xx = np.maximum(xx, size)
yy = xx
self.length_x = xx * self.resolution
self.length_y = yy * self.resolution
a = (xx - h) // 2
aa = xx - a - h
b = (yy - w) // 2
bb = yy - b - w
self.img = np.pad(self.img, pad_width=(
(a, aa), (b, bb)), mode="constant")
def pad_it(self, x_size, y_size):
h = self.img.shape[0]
w = self.img.shape[1]
xx = x_size
yy = y_size
self.length_x = xx * self.resolution
self.length_y = yy * self.resolution
a = (xx - h) // 2
aa = xx - a - h
b = (yy - w) // 2
bb = yy - b - w
self.img = np.pad(self.img, pad_width=(
(a, aa), (b, bb)), mode="constant")
def percentage_gaussian(self, mask, sigma):
x = np.linspace(-self.length_x / 2, self.length_x / 2, mask.shape[0])
y = np.linspace(-self.length_y / 2, self.length_y / 2, mask.shape[1])
X, Y = np.meshgrid(x, y)
z = 1 / (2 * np.pi * sigma * sigma) * \
np.exp(-(X**2 / (2 * sigma**2) + Y**2 / (2 * sigma**2)))
return np.multiply(mask, z.T)
def gaussian(self, sigma):
x = np.arange(-self.length_x / 2, self.length_x / 2, self.resolution)
y = np.arange(-self.length_y / 2, self.length_y / 2, self.resolution)
X, Y = np.meshgrid(x, y)
z = 1 / (2 * np.pi * sigma * sigma) * \
np.exp(-(X**2 / (2 * sigma**2) + Y**2 / (2 * sigma**2)))
self.img = np.multiply(self.img, z.T)
def plot(self, ax, scale=None):
if scale is None:
ax.imshow(self.img)
else:
quad = np.ones((int(scale / self.resolution),
int(scale / self.resolution)))
img = scipy.signal.convolve2d(self.img, quad)
ax.imshow(img)
def blur(self, sigma):
self.img = scipy.ndimage.gaussian_filter(self.img, sigma)