[postprocessor] add rule for radial sigma and 2D pwspec

This commit is contained in:
Noe Brucy
2021-04-26 15:33:24 +02:00
parent e99929b06c
commit 31bc3cc209
2 changed files with 89 additions and 1 deletions
+78 -1
View File
@@ -28,6 +28,7 @@ from pymses.analysis import (
from pymses.filters import CellsToPoints, RegionFilter
from fil_finder import FilFinder2D
from scipy import fft
import pspec_new
@@ -163,7 +164,39 @@ def find_center(distance, skeleton, i_center, j_center, i, j):
return i_center[i, j], j_center[i, j]
# PostProcessor class
# Power spectrum helpers
def pspec(map2D):
"""
Computes the 2D powerspectrum of a 2D map
Parameters
----------
map2D : square map to compute the fft from
"""
# Resolution of the map
n = map2D.shape[0]
assert map2D.shape[1] == n
# Create bin array for the wavenumber k
# (Take into account the symmetry)
kbins = np.linspace(0, n // 2, n // 4)
k_alias = np.arange(n, dtype=np.float64)
k = np.where(k_alias >= n // 2, k_alias - n, k_alias)
kx, ky = np.meshgrid(k, k, indexing="ij")
# Compute map of k
kmap = np.sqrt(kx ** 2 + ky ** 2)
# Compute fft
fmap = fft.fft2(map2D)
# Compute the power map from the fft
pmap = pspec_new.pcube(fmap)
# Use the power map and the fft to compute the powerspectrum
# This is typically an histogram of k weighted by the fourier transform value
pspec, kbins, pspec2, fbins = pspec_new.pspectrum(pmap, kmap, kbins, 1, 0)
# Return bin center and power spectrum
return 0.5 * (kbins[1:] + kbins[:-1]), pspec
class PostProcessor(HDF5Container):
@@ -1054,6 +1087,42 @@ class PostProcessor(HDF5Container):
avg_map = self.get_value("/maps/avg_map_" + name + "_" + ax_los)
return dmap / avg_map
def _dispersion_rad(self, name, ax_los="z"):
"""
Computes the dispersion in radial bins of the quantity `name`
Parameters
----------
name : name of 2D map of a scalar quantity
ax_los : axis of the line of sight
"""
# 1. Get full storage names for the map and its azimuthal avererage
map_name = f"/maps/{name}_{ax_los}"
avg_map_name = f"/maps/avg_map_{name}_{ax_los}"
# 2. Get maps from the storage
dmap = self.get_value(map_name)
avgmap = self.get_value(avg_map_name)
# 3. Get radial bins and centers
bins_on_map = self.get_value(f"/maps/bins_on_map_{ax_los}")
centers = self.get_value(f"/radial/radial_centers_{ax_los}")
# 4. Initialize dispersion array
sigma = np.zeros(len(centers))
# 5. Compute RMS in each bin
for j in range(len(centers)):
mask_bin = bins_on_map == j
sigma[j] = np.sqrt(
np.sum((dmap[mask_bin] - avgmap[mask_bin]) ** 2) / np.sum(mask_bin)
)
# 6. Returns computed RMS
return sigma
def _rad_fluct_pdf(self, name, ax_los="z", mass_weighted=False):
if mass_weighted:
fluct_map = self.get_value("/maps/mwfluct_" + name + "_" + ax_los)
@@ -1784,6 +1853,14 @@ class PostProcessor(HDF5Container):
"/maps",
dependencies=[name, "avg_map_" + name],
)
self.rules["dispersion_rad_" + name] = Rule(
self,
partial(self._dispersion_rad, name),
"radial RMS of {}".format(name),
"/radial",
dependencies=[name, "avg_map_" + name],
unit=unit,
)
self.rules["mwfluct_" + name] = Rule(
self,
partial(self._fluct_map, name, mass_weigthed=True),