grid_varΒΆ
plot_grid_var
plots a 2D grid function as output by Carpet. It takes as
input the variable, and the region of space where to plot it. This is defined by
giving the resolution, the lowermost leftmost coordinate (--x0
), and the
topmost rightmost one (--x1
). Optionally, it is possible to take the
logarithm base 10 and/or the absolute value. It is also possible to perform
interpolation in two different ways: one at the level of the data (slower, but
more accurate), and the other at the level of the image using the interpolations
available in matplotlib.
#!/usr/bin/env python3
# Copyright (C) 2020-2023 Gabriele Bozzola
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, see <https://www.gnu.org/licenses/>.
"""Visualize 2D grid data, optionally adding drawing the horizons.
"""
from matplotlib.pyplot import clf as clear_figure
from kuibit import argparse_helper as kah
from kuibit.simdir import SimDir
from kuibit.visualize_matplotlib import (
add_text_to_corner,
plot_color,
plot_horizon_on_plane_at_iteration,
save,
setup_matplotlib,
)
def mopi_add_custom_options(parser):
# These are the custom options that mopi will see.
parser.add_argument("--datadir", default=".", help="Data directory.")
kah.add_horizon_to_parser(parser)
parser.add_argument(
"--ignore-symlinks",
action="store_true",
help="Ignore symlinks in the data directory",
)
parser.add_argument("--pickle-file", help="Read SimDir from this file.")
kah.add_grid_to_parser(parser, dimensions=2)
kah.add_figure_to_parser(parser)
parser.add_argument(
"--variable", type=str, required=True, help="Variable to plot."
)
parser.add_argument(
"--multilinear-interpolate",
action="store_true",
help="Whether to interpolate to smooth data with multilinear"
" interpolation before plotting.",
)
parser.add_argument(
"--interpolation-method",
type=str,
default="none",
help="Interpolation method for the plot. See docs of np.imshow."
" (default: %(default)s)",
)
parser.add_argument(
"--colorbar",
action="store_true",
help="Whether to draw the color bar.",
)
parser.add_argument(
"--logscale",
action="store_true",
help="Whether to use log scale.",
)
parser.add(
"--vmin",
help=(
"Minimum value of the variable. "
"If logscale is True, this has to be the log. "
),
type=float,
)
parser.add(
"--vmax",
help=(
"Maximum value of the variable. "
"If logscale is True, this has to be the log."
),
type=float,
)
parser.add_argument(
"--absolute",
action="store_true",
help="Whether to take the absolute value.",
)
class MOPIMovie:
def __init__(self, args):
# Here we initialize all the objects that we need for all the frames.
# All the expensive stuff has to be done here.
# TODO: Automatically compute min and max if they are not specified.
self.sim = SimDir(
args.datadir,
ignore_symlinks=args.ignore_symlinks,
pickle_file=args.pickle_file,
)
self.x0, self.x1, self.res = args.origin, args.corner, args.resolution
self.shape = [self.res, self.res]
self.reader = self.sim.gridfunctions[args.plane]
self.var = self.reader[args.variable]
self.iterations = self.var.available_iterations
# Apparent horizons
self.ahs = {}
if args.ah_show:
for ah in self.sim.horizons.available_apparent_horizons:
self.ahs[ah] = self.sim.horizons.get_apparent_horizon(ah)
self.args = args
def get_frames(self):
# Here we define what is a "frame" (it is one iteration). This function
# has to return an iterable on what we want to make frames of.
return self.iterations
def make_frame(self, path, iteration):
# Here we plot a frame. This function has to take the output path and
# the identifier of what is a frame (in this case, an iteration).
setup_matplotlib(self.args.mpl_rc_file)
clear_figure()
if self.args.absolute:
data = abs(self.var[iteration])
variable = f"abs({self.args.variable})"
else:
data = self.var[iteration]
variable = self.args.variable
if self.args.logscale:
label = f"log10({variable})"
else:
label = variable
plot_color(
data,
x0=self.x0,
x1=self.x1,
shape=self.shape,
xlabel=self.args.plane[0],
ylabel=self.args.plane[1],
resample=self.args.multilinear_interpolate,
colorbar=self.args.colorbar,
logscale=self.args.logscale,
vmin=self.args.vmin,
vmax=self.args.vmax,
label=label,
interpolation=self.args.interpolation_method,
)
if self.args.ah_show:
for hor in self.ahs.values():
# Check if we have the shape at the current iteration
if iteration in hor.shape_iterations:
plot_horizon_on_plane_at_iteration(
hor,
iteration,
self.args.plane,
color=self.args.ah_color,
edgecolor=self.args.ah_edge_color,
alpha=self.args.ah_alpha,
)
time = self.var.time_at_iteration(iteration)
add_text_to_corner(rf"$t = {time:.3f}$")
save(path)
self.var.clear_cache()