Refactoring, split into more files. Add more personalisation
This commit is contained in:
+180
-73
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user