Refactoring, split into more files. Add more personalisation

This commit is contained in:
Noe Brucy
2020-02-04 11:34:09 +01:00
parent beb6203d06
commit a87abeb52d
8 changed files with 1234 additions and 959 deletions
+180 -73
View File
@@ -17,8 +17,9 @@ from matplotlib.collections import PatchCollection
from functools import partial
from numpy.polynomial.polynomial import polyfit
from scipy.ndimage.filters import gaussian_filter1d
from scipy import optimize
from postprocessor import *
from comparator import *
P.rcParams["image.cmap"] = "plasma"
@@ -95,7 +96,7 @@ class Plotter(Aggregator, BaseProcessor):
)
# Get postprocesor objets for each run
self.pp_runs = self.comp.pp_runs
self.pp = self.comp.pp
# Define log prefix
self.log_id = "[plot {}] ".format(self.pp_params.out.tag)
@@ -128,7 +129,7 @@ class Plotter(Aggregator, BaseProcessor):
for run in self.runs:
for i, num in enumerate(self.nums[run]):
plot_filename = self._find_filename(name_full, run, num)
save = tables.open_file(self.pp_runs[run][num].filename)
save = tables.open_file(self.pp[run][num].filename)
try:
self._plot_rule(
rule,
@@ -182,38 +183,36 @@ class Plotter(Aggregator, BaseProcessor):
else:
self._log("Plot {} is already done, skipping...".format(plot_filename))
def _find_filename(self, name_full, run=None, num=None):
if not self.pp_params.out.tag == "":
tag_name = "_" + self.pp_params.out.tag
else:
tag_name = ""
def _find_filename(self, name_full, run=None, num=None, fmt=None):
if not run is None and not num is None:
return (
self.path_out
+ "/"
+ run
+ "/"
+ name_full
+ tag_name
+ "_"
+ format(num, "05")
+ self.pp_params.plot.out_ext
)
elif not run is None:
return (
self.path_out
+ "/"
+ run
+ "/"
+ name_full
+ tag_name
+ self.pp_params.plot.out_ext
)
else:
return (
self.path_out + "/" + name_full + tag_name + self.pp_params.plot.out_ext
)
tag_name = self.pp_params.out.tag
if fmt is None and self.pp_params.out.fmt == "":
if not self.pp_params.out.tag == "":
tag_name = "_" + tag_name
if not run is None and not num is None:
fmt = "{out}/{run}/{name}{tag}_{run}_{num:05}_{ext}"
elif not run is None:
fmt = "{out}/{run}/{name}{tag}_{run}{ext}"
else:
fmt = "{out}/{name}{tag}{ext}"
elif fmt is None:
fmt = self.pp_params.out.fmt
nml = None
if not run is None:
nml = self.comp.namelist[run]
return fmt.format(
run=run,
name=name_full,
tag=tag_name,
num=num,
nml=nml,
out=self.path_out,
ext=self.pp_params.out.ext,
)
def _label_run(self, run, node, label, nml_key):
def get_label_nml(nml_key):
@@ -226,7 +225,7 @@ class Plotter(Aggregator, BaseProcessor):
if prop_name in self.value_convert:
prop_value_str = self.value_convert[prop_name](prop_value)
elif type(prop_value) in [int, float]:
prop_value_str = "${:.6g}$".format(prop_value)
prop_value_str = convert_exp(prop_value, digits=5)
else:
prop_value_str = str(prop_value)
return r"{} = {}".format(prop_label, prop_value_str)
@@ -443,7 +442,7 @@ class Plotter(Aggregator, BaseProcessor):
**kwargs
):
node = self.save.get_node("/hist/" + name + "_" + ax_los)
node = self.save.get_node("/hist/" + name)
label, unit_old, unit = self._ax_label_unit(node, label, unit, unit_coeff)
values, centers = node.read() * unit_old.express(unit)
@@ -493,10 +492,15 @@ class Plotter(Aggregator, BaseProcessor):
yunit=None,
xunit_coeff=1.0,
yunit_coeff=1.0,
linearfit=False,
fit=None,
fitlabel=None,
smooth=0,
sigma_err=2.0,
nml_key=None,
runs=None,
yerr_kind="std",
colors=None,
nml_color=None,
**kwargs
):
@@ -514,60 +518,146 @@ class Plotter(Aggregator, BaseProcessor):
P.ylabel(ylabel)
P.grid()
yerr = None
if node_y._v_attrs.CLASS == "ARRAY":
x = node_x.read() * xunit_old.express(xunit)
y = node_y.read() * yunit_old.express(yunit)
mask = np.isfinite(y)
mask = np.isfinite(x) & np.isfinite(y)
x, y = x[mask], y[mask]
if smooth > 0:
y = gaussian_filter1d(y, sigma=smooth)
yerr = None
P.plot(x, y, "*", **kwargs)
(base_line,) = P.plot(x, y, "*", **kwargs)
elif "mean" in node_y:
x = node_x.read() * xunit_old.express(xunit)
y = node_y.mean.read() * yunit_old.express(yunit)
mask = np.isfinite(y)
x, y = x[mask], y[mask]
if smooth > 0:
y = gaussian_filter1d(y, sigma=smooth)
yerr = node_y.std.read() * yunit_old.express(yunit)
P.errorbar(x, y, yerr=yerr, fmt="*", **kwargs)
else:
yerr = None
if runs is None:
runs = self.runs
for run in runs:
x_run, y_run = node_x[run], node_y[run]
x = x_run.read() * xunit_old.express(xunit)
y = y_run.read() * yunit_old.express(yunit)
if yerr_kind == "std":
yerr = node_y.std.read() * yunit_old.express(yunit) * sigma_err
mask = np.isfinite(x) & np.isfinite(y) & np.isfinite(yerr)
x, y, yerr = x[mask], y[mask], yerr[mask]
if smooth > 0:
y = gaussian_filter1d(y, sigma=smooth)
base_line, _, _ = P.errorbar(x, y, yerr=yerr, label=label, **kwargs)
elif yerr_kind in ["min_max", "95per"]:
if yerr_kind == "min_max":
yerr_min = node_y.min.read() * yunit_old.express(yunit)
yerr_max = node_y.max.read() * yunit_old.express(yunit)
elif yerr_kind == "95per":
yerr_min = node_y.q025.read() * yunit_old.express(yunit)
yerr_max = node_y.q975.read() * yunit_old.express(yunit)
yerr = yerr_max - yerr_min
mask = (
np.isfinite(x)
& np.isfinite(y)
& np.isfinite(yerr_min)
& np.isfinite(yerr_max)
)
x, y, yerr, yerr_min, yerr_max = (
x[mask],
y[mask],
yerr[mask],
yerr_min[mask],
yerr_max[mask],
)
base_line, _, _ = P.errorbar(
x, y, yerr=[y - yerr_min, yerr_max - y], label=label, **kwargs
)
else:
mask = np.isfinite(y)
x, y = x[mask], y[mask]
if smooth > 0:
y = gaussian_filter1d(y, sigma=smooth)
(base_line,) = P.plot(x, y, "*", **kwargs)
else:
if runs is None:
runs = self.runs
for i, run in enumerate(runs):
x_run, y_run = node_x[run], node_y[run]
x = x_run.read() * xunit_old.express(xunit)
y = y_run.read() * yunit_old.express(yunit)
mask = np.isfinite(x) & np.isfinite(y)
x, y = x[mask], y[mask]
if smooth > 0:
y = gaussian_filter1d(y, sigma=smooth)
label_run = self._label_run(run, y_run, label, nml_key)
P.plot(x, y, label=label_run, **kwargs)
if colors is None:
(base_line,) = P.plot(x, y, label=label_run, **kwargs)
else:
if nml_color is None:
color = colors[i % len(colors)]
(base_line,) = P.plot(x, y, label=label_run, **kwargs)
else:
nml = self.comp.get_nml(nml_color, run)
color = colors[nml]
(base_line,) = P.plot(x, y, label=label_run, color=color, **kwargs)
P.legend()
if linearfit:
self._overlay_linearfit(x, y, yerr)
if not fit is None:
self._overlay_fit(
x,
y,
yerr,
kind=fit,
ls="--",
lw=1.5,
color=base_line.get_color(),
label=fitlabel,
)
def _overlay_linearfit(self, x, y, yerr=None, fit_order=1):
if yerr is None:
(a, b, rho, _map_rule, stderr) = linregress(x, y)
self._log(
"Linear fit y = {} x + {} with R^2 = {} and error is {}".format(
a, b, rho, stderr
def _overlay_fit(self, x, y, yerr=None, kind="linear", label=None, **kwargs):
if kind == "linear":
if yerr is None:
(a, b, rho, _map_rule, stderr) = linregress(x, y)
self._log(
"Linear fit y = {} x + {} with R^2 = {} and error is {}".format(
a, b, rho, stderr
)
)
)
else:
fit = polyfit(x, y, 1, w=[1.0 / ty for ty in yerr], full=True)
c = fit[0]
residual = fit[1][0][0]
b, a = c[0], c[1]
self._log(
"Linear fit y = {} x + {} with residual {}".format(a, b, residual)
)
P.plot(x, a * x + b, "--", linewidth=1.5)
if label is None:
label = r"Linear fit with slope ${:.3g}$ and $R^2 = {:.3f}$".format(
a, rho
)
else:
fit = polyfit(x, y, 1, w=[1.0 / ty for ty in yerr], full=True)
c = fit[0]
residual = fit[1][0][0]
b, a = c[0], c[1]
self._log(
"Linear fit y = {} x + {} with residual {}".format(a, b, residual)
)
if label is None:
label = r"Linear fit with slope ${:.3g}$".format(a)
P.plot(x, a * x + b, label=label, **kwargs)
elif kind == "power_law":
if yerr is None:
(a, b, rho, _map_rule, stderr) = linregress(np.log10(x), np.log10(y))
self._log(
"Power law fit y = x^({}) * 10^({}) with R^2 = {} and error is {}".format(
a, b, rho, stderr
)
)
else:
fitfunc = lambda p, x: p[0] + p[1] * x
errfunc = lambda p, x, y, err: (y - fitfunc(p, x)) / err
pinit = [1.0, -1.0]
out = optimize.leastsq(
errfunc,
pinit,
args=(np.log10(x), np.log10(y), yerr / y),
full_output=1,
)
c = out[0]
b, a = c[0], c[1]
residual = errfunc(c, np.log10(x), np.log10(y), yerr / y)
self._log(
"Power law fit y = x^({}) * 10^({}) with residual {}".format(
a, b, residual
)
)
if label is None:
label = r"Power-law fit with index {:.1f}".format(a)
P.plot(x, (10 ** b) * x ** a, label=label, **kwargs)
def overlay_kennicutt(self, n0, step):
P.grid(False)
@@ -650,6 +740,12 @@ class Plotter(Aggregator, BaseProcessor):
"Toomre Q parameter for a Keplerian disk",
dependencies=["Q"],
),
"rho_pdf": PlotRule(
self,
partial(self._plot_hist, "rho_pdf"),
"$\rho$-PDF",
dependencies=["rho_pdf"],
),
}
averageables = ["coldens", "rho", "T", "Q"]
@@ -767,6 +863,17 @@ class Plotter(Aggregator, BaseProcessor):
kind="series",
dependencies=["rms_from_log"],
),
"turb_power": PlotRule(
self,
partial(
self._plot,
"/series/rms_from_log/time",
"/series/rms_from_log/turb_power",
xunit=cst.Myr,
),
kind="series",
dependencies=["turb_power"],
),
"sigma": PlotRule(
self,
partial(