[discretizers.builtin] allow to set the aspect ratio in matplotlib plots

parent 24a707d5
Pipeline #68663 failed with stages
in 23 minutes and 42 seconds
......@@ -10,7 +10,7 @@ from ipywidgets import HTML, HBox, widgets, Layout
import matplotlib.pyplot as plt
from pymor.core.config import config
from pymor.discretizers.builtin.gui.matplotlib import MatplotlibPatchAxes, Matplotlib1DAxes
from pymor.discretizers.builtin.gui.matplotlib import MatplotlibPatchAxes, Matplotlib1DAxes, figsize
from pymor.vectorarrays.interface import VectorArray
......@@ -47,9 +47,17 @@ class MPLPlotBase:
do_animation = not separate_axes and len(U[0]) > 1
# Setting the aspect ratio in figure() only works by specifying absolute values for figsize, which we calculate
# using figsize (matplotlib.figure.figaspect does not do exactly what we want). To ensure a correct aspect
# ratio in the respective axes created by base classes, we also need to provide a correct bounding_box.
if bounding_box is None:
bounding_box = grid.bounding_box()
assert len(bounding_box) == 2 and all(len(b) == 2 for b in bounding_box)
aspect_ratio = (bounding_box[1][1] - bounding_box[0][1]) / (bounding_box[1][0] - bounding_box[0][0])
if separate_plots:
for i, (vmin, vmax, u) in enumerate(zip(self.vmins, self.vmaxs, U)):
figure = plt.figure(self.fig_ids[i])
figure = plt.figure(self.fig_ids[i], figsize=figsize(aspect_ratio))
sync_timer = sync_timer or figure.canvas.new_timer()
if grid.dim == 2:
plot = MatplotlibPatchAxes(U=u, figure=figure, sync_timer=sync_timer, grid=grid, vmin=vmin, vmax=vmax,
......@@ -63,7 +71,7 @@ class MPLPlotBase:
self.plots.append(plot)
# plt.tight_layout()
else:
figure = plt.figure(self.fig_ids[0])
figure = plt.figure(self.fig_ids[0], figsize=figaspect(aspect_ratio))
sync_timer = sync_timer or figure.canvas.new_timer()
if grid.dim == 2:
plot = MatplotlibPatchAxes(U=U, figure=figure, sync_timer=sync_timer, grid=grid, vmin=self.vmins,
......@@ -94,7 +102,7 @@ class MPLPlotBase:
def visualize_patch(grid, U, bounding_box=([0, 0], [1, 1]), codim=2, title=None, legend=None,
def visualize_patch(grid, U, bounding_box=None, codim=2, title=None, legend=None,
separate_colorbars=False, rescale_colorbars=False, columns=2):
"""Visualize scalar data associated to a two-dimensional |Grid| as a patch plot.
......@@ -111,7 +119,7 @@ def visualize_patch(grid, U, bounding_box=([0, 0], [1, 1]), codim=2, title=None,
provided, in which case a subplot is created for each entry of the tuple. The
lengths of all arrays have to agree.
bounding_box
A bounding box in which the grid is contained.
A bounding box in which the grid is contained (defaults to grid.bounding_box()).
codim
The codimension of the entities the data in `U` is attached to (either 0 or 2).
title
......
......@@ -17,9 +17,21 @@ from pymor.discretizers.builtin.grids.constructions import flatten_grid
from pymor.discretizers.builtin.grids.referenceelements import triangle, square
def figsize(height_over_width):
# figaspect increases the width, but we want to adjust the height
from matplotlib.figure import figaspect
w, h = figaspect(height_over_width)
from matplotlib import rcParams
reference_width = rcParams["figure.figsize"][0]
scaling = reference_width/w
return reference_width, h*scaling
class MatplotlibAxesBase:
def __init__(self, figure, sync_timer, grid, U=None, vmin=None, vmax=None, codim=2, separate_axes=False, columns=2):
def __init__(self, figure, sync_timer, grid, U=None, vmin=None, vmax=None, codim=2, separate_axes=False, columns=2,
aspect_ratio=1):
# aspect_ratio is height/width
self.vmin = vmin
self.vmax = vmax
self.codim = codim
......@@ -29,9 +41,10 @@ class MatplotlibAxesBase:
if len(U) == 1:
columns = 1 # otherwise we get a sep axes object with 0 data
rows = int(np.ceil(len(U) / columns))
self.ax = figure.subplots(rows, columns, squeeze=False).flatten()
self.ax = figure.subplots(rows, columns, squeeze=False, figsize=figsize(aspect_ratio)).flatten()
else:
self.ax = (figure.gca(),)
self.ax[0].set_aspect(aspect_ratio)
self.figure = figure
self.codim = codim
self.grid = grid
......@@ -87,8 +100,13 @@ class MatplotlibPatchAxes(MatplotlibAxesBase):
self.colorbar = colorbar
self.animate = self.set
if bounding_box is None:
bounding_box = grid.bounding_box()
assert len(bounding_box) == 2 and all(len(b) == 2 for b in bounding_box)
aspect_ratio = (bounding_box[1][1] - bounding_box[0][1]) / (bounding_box[1][0] - bounding_box[0][0])
super().__init__(U=U, figure=figure, grid=grid, vmin=vmin, vmax=vmax, codim=codim, columns=columns,
sync_timer=sync_timer)
sync_timer=sync_timer, aspect_ratio=aspect_ratio)
def _plot_init(self):
if self.codim == 2:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment