-
This commit makes the Python code backwards compatible down to Python 2.7. Previously it would only run on Python 3.5 and up. Problems fixed included: - `time.perf_counter()` doesn't exist - all classes need to be new-style - `functools.lru_cache` doesn't exist - only the last argument to a function call can be `*`-expanded - the `nonlocal` keyword doesn't exist - metaclasses are used with a different syntax - `yield from` doesn't exist - `tempdir.TemporaryDirectory` doesn't exist - iterators need a `next()` method
This commit makes the Python code backwards compatible down to Python 2.7. Previously it would only run on Python 3.5 and up. Problems fixed included: - `time.perf_counter()` doesn't exist - all classes need to be new-style - `functools.lru_cache` doesn't exist - only the last argument to a function call can be `*`-expanded - the `nonlocal` keyword doesn't exist - metaclasses are used with a different syntax - `yield from` doesn't exist - `tempdir.TemporaryDirectory` doesn't exist - iterators need a `next()` method
gridvisualization.py 3.83 KiB
import matplotlib.patches as patches
class Grid(object):
"""Visualizes a 2D LBM grid with matplotlib by drawing cells and pdf arrows"""
def __init__(self, xCells, yCells):
"""Create a new grid with the given number of cells in x (horizontal) and y (vertical) direction"""
self._xCells = xCells
self._yCells = yCells
self._patches = []
for x in range(xCells):
for y in range(yCells):
self._patches.append(patches.Rectangle((x, y), 1.0, 1.0, fill=False, linewidth=3, color='#bbbbbb'))
self._cellBoundaries = dict() # mapping cell to rectangle patch
self._arrows = dict() # mapping (cell, direction) tuples to arrow patches
def addCellBoundary(self, cell, **kwargs):
"""Draws a rectangle around a single cell. Keyword arguments are passed to the matplotlib Rectangle patch"""
if 'fill' not in kwargs: kwargs['fill'] = False
if 'linewidth' not in kwargs: kwargs['linewidth'] = 3
if 'color' not in kwargs: kwargs['#bbbbbb']
self._cellBoundaries[cell] = patches.Rectangle(cell, 1.0, 1.0, **kwargs)
def addCellBoundaries(self, **kwargs):
"""Draws a rectangle around all cells. Keyword arguments are passed to the matplotlib Rectangle patch"""
for x in range(self._xCells):
for y in range(self._yCells):
self.addCellBoundary((x, y), **kwargs)
def addArrow(self, cell, arrowPosition, arrowDirection, **kwargs):
"""
Draws an arrow in a cell. If an arrow exists already at this position, it is replaced.
:param cell: cell coordinate as tuple (x,y)
:param arrowPosition: each cell has 9 possible positions specified as tuple e.g. upper left (-1, 1)
:param arrowDirection: direction of the arrow as (x,y) tuple
:param kwargs: arguments passed directly to the FancyArrow patch of matplotlib
"""
cellMidpoint = (0.5 + cell[0], 0.5 + cell[1])
if 'width' not in kwargs: kwargs['width'] = 0.005
if 'color' not in kwargs: kwargs['color'] = 'k'
if arrowPosition == (0, 0):
del kwargs['width']
self._arrows[(cell, arrowPosition)] = patches.Circle(cellMidpoint, radius=0.03, **kwargs)
else:
arrowMidpoint = (cellMidpoint[0] + arrowPosition[0] * 0.25,
cellMidpoint[1] + arrowPosition[1] * 0.25)
length = 0.75
arrowStart = (arrowMidpoint[0] - arrowDirection[0] * 0.25 * length,
arrowMidpoint[1] - arrowDirection[1] * 0.25 * length)
patch = patches.FancyArrow(arrowStart[0], arrowStart[1],
0.25 * length * arrowDirection[0],
0.25 * length * arrowDirection[1],
**kwargs)
self._arrows[(cell, arrowPosition)] = patch
def fillWithDefaultArrows(self, **kwargs):
"""Fills the complete grid with the default pdf arrows"""
for x in range(self._xCells):
for y in range(self._yCells):
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
if 'color' not in kwargs: kwargs['color'] = '#bbbbbb'
if 'width' not in kwargs: kwargs['width'] = 0.006
self.addArrow((x, y), (dx, dy), (dx, dy), **kwargs)
def draw(self, ax):
"""Draw the grid into a given matplotlib axes object"""
for p in self._patches:
ax.add_patch(p)
for arrowPatch in self._arrows.values():
ax.add_patch(arrowPatch)
offset = 0.1
ax.set_xlim(-offset, self._xCells+offset)
ax.set_xlim(-offset, self._xCells + offset)
ax.set_ylim(-offset, self._yCells + offset)
ax.set_aspect('equal')
ax.set_axis_off()