import numpy as np
import pytest
from SurfaceTopography import read_container, SurfaceContainer
from SurfaceTopography.Generation import fourier_synthesis
from SurfaceTopography.Generic.Moments import (compute_iso_moment,
compute_1d_moment, )
import SurfaceTopography
SurfaceTopography.__version__
'1.3.0.dev70+gf7fb45bf.dirty'
import matplotlib.pyplot as plt
fig, axes = plt.subplots(3,1, sharex = True)
for seed in range(10):
np.random.seed(seed)
sx = 2
nx = 1024
unit = "m"
t = fourier_synthesis((nx,), physical_sizes=(sx,), hurst=0.8, rms_height=1,
short_cutoff=4 * (sx / nx),
long_cutoff=sx / 8, unit=unit).detrend(detrend_mode="center")
# Moments from full integration of the 2D spectrum of the topopography
t_varh_ciso = t.moment_power_spectrum(order=0, )
t_varhp_ciso = t.moment_power_spectrum(order=2, )
t_varhpp_ciso = t.moment_power_spectrum(order=4, )
for nb_points_per_decade in [5, 10, 20]:
# Moment of the isotropic PSD computed from the 1D power spectrum
# this means that there is resampling
c = SurfaceContainer([t, ])
c_varh_ciso = c.c1d_moment(order=0, unit=unit, nb_points_per_decade=nb_points_per_decade)
c_varhp_ciso = c.c1d_moment(order=2, unit=unit, nb_points_per_decade=nb_points_per_decade)
c_varhpp_ciso = c.c1d_moment(order=4, unit=unit, nb_points_per_decade=nb_points_per_decade)
style=dict(color="k", ls="none",marker="+")
# assert abs(1 - c_varhp_ciso / t_varhp_ciso) < 0.05
# assert abs(1 - c_varhpp_ciso / t_varhpp_ciso) < 0.05
axes[0].plot(nb_points_per_decade, abs(1 - c_varh_ciso / t_varh_ciso), **style)
axes[1].plot(nb_points_per_decade, abs(1 - c_varhp_ciso / t_varhp_ciso), **style)
axes[2].plot(nb_points_per_decade, abs(1 - c_varhpp_ciso / t_varhpp_ciso), **style)
axes[0].set_ylabel(fr"$m_0$")
axes[1].set_ylabel(fr"$m_1$")
axes[2].set_ylabel(fr"$m_2$")
for ax in axes:
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlabel("nb points per decade")
ax.label_outer()
/Users/antoines/Repositories/SurfaceTopography/SurfaceTopography/Container/Averaging.py:106: RuntimeWarning: Mean of empty slice avgresults = np.array(sorted([np.nanmean(vals, axis=0) for vals in results.values()], key=lambda x: x[0]))
c1d_moment=c._functions["c1d_moment"]
??c1d_moment
??compute_1d_moment
fig, axes = plt.subplots(3,1, sharex = True)
for seed in range(10):
np.random.seed(seed)
sx, sy = physical_sizes = 2, 3
nx, ny = nb_grid_pts = 1024, 1023
unit = "m"
t = fourier_synthesis(nb_grid_pts, physical_sizes=physical_sizes, hurst=0.8, rms_height=1,
short_cutoff=4 * (sx / nx),
long_cutoff=sx / 8, unit=unit).detrend(detrend_mode="center")
# Moments from full integration of the 2D spectrum of the topopography
t_varh_ciso = t.moment_power_spectrum(order=0, )
t_varhp_ciso = t.moment_power_spectrum(order=2, )
t_varhpp_ciso = t.moment_power_spectrum(order=4, )
for nb_points_per_decade in [5, 10, 20]:
# Moment of the isotropic PSD computed from the 1D power spectrum
# this means that there is resampling
c = SurfaceContainer([t, ])
c_varh_ciso = c.ciso_moment(order=0, unit=unit, nb_points_per_decade=nb_points_per_decade)
c_varhp_ciso = c.ciso_moment(order=2, unit=unit, nb_points_per_decade=nb_points_per_decade)
c_varhpp_ciso = c.ciso_moment(order=4, unit=unit, nb_points_per_decade=nb_points_per_decade)
style=dict(color="k", ls="none",marker="+")
# assert abs(1 - c_varhp_ciso / t_varhp_ciso) < 0.05
# assert abs(1 - c_varhpp_ciso / t_varhpp_ciso) < 0.05
axes[0].plot(nb_points_per_decade, abs(1 - c_varh_ciso / t_varh_ciso), **style)
axes[1].plot(nb_points_per_decade, abs(1 - c_varhp_ciso / t_varhp_ciso), **style)
axes[2].plot(nb_points_per_decade, abs(1 - c_varhpp_ciso / t_varhpp_ciso), **style)
axes[0].set_ylabel(fr"$m_0$")
axes[1].set_ylabel(fr"$m_1$")
axes[2].set_ylabel(fr"$m_2$")
for ax in axes:
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlabel("nb points per decade")
ax.label_outer()
ciso_moment=c._functions["ciso_moment"]
ciso_moment??
??compute_iso_moment
Computing the average PSD and than doing a trapezoidal integration leads to large errors in the PSD
Better approach: