Source code for mesh2hrtf.Mesh2Input.EvaluationGrids.write_evaluation_grid
import os
from scipy.spatial import Delaunay, ConvexHull
import matplotlib.pyplot as plt
import pyfar as pf
[docs]def write_evaluation_grid(
points, name, start=200000, discard=None, show=False):
"""
Write evaluation grid for use in Mesh2HRTF.
Mesh2HRTF evaluation grids consist of the two text files Nodes.txt and
Elements.txt. Evaluations grids are always triangularized.
Parameters
----------
points : pyfar Coordinates, numpy array
pyfar Coordinates object or 2D numpy array containing the cartesian
points of the evaluation grid in meter. The array must be of shape
(N, 3) with N > 2.
name : str
Name of the folder under which the evaluation grid is saved. If the
folder does not exist, it is created.
start : int, optional
The nodes and elements of the evaluation grid are numbered and the
first element will have the number `start`. In Mesh2HRTF, each Node
must have a unique number. The nodes/elements of the mesh for which the
HRTFs are simulated start at 1. Thus `start` must at least be greater
than the number of nodes/elements in the evaluation grid.
discard : "x", "y", "z", optional
In case all values of the evaluation grid are constant for one
dimension, this dimension has to be discarded during the
triangularization. E.g. if all points have a z-value of 0 (or any other
constant), discarded must be "z". The default ``None`` does not discard
any dimension.
show : bool, optional
If ``True`` the evaluation grid is plotted and the plot is saved to
the folder given by `name`
Examples
--------
Generate a spherical sampling grid with pyfar and write it to the current
working directory
.. plot::
>>> import mesh2hrtf as m2h
>>> import pyfar as pf
>>>
>>> points = pf.samplings.sph_lebedev(sh_order=10)
>>> m2h.write_evaluation_grid(
... points, "Lebedev_N10", discard=None, show=True)
"""
if isinstance(points, pf.Coordinates):
points = points.get_cart()
if points.ndim != 2 or points.shape[0] < 3 \
or points.shape[1] != 3:
raise ValueError(
"points must be a 2D array of shape (N, 3) with N > 2")
# discard dimension
if discard == "x":
mask = (1, 2)
elif discard == "y":
mask = (0, 2)
elif discard == "z":
mask = (0, 1)
else:
mask = (0, 1, 2)
# triangulate
if discard is None:
tri = ConvexHull(points[:, mask])
else:
tri = Delaunay(points[:, mask])
# check output directory
if not os.path.isdir(name):
os.mkdir(name)
# write nodes
N = int(points.shape[0])
start = int(start)
nodes = f"{N}\n"
for nn in range(N):
nodes += (f"{int(start + nn)} "
f"{points[nn, 0]} "
f"{points[nn, 1]} "
f"{points[nn, 2]}\n")
with open(os.path.join(name, "Nodes.txt"), "w") as f_id:
f_id.write(nodes)
# write elements
N = int(tri.simplices.shape[0])
elems = f"{N}\n"
for nn in range(N):
elems += (f"{int(start + nn)} "
f"{tri.simplices[nn, 0] + start} "
f"{tri.simplices[nn, 1] + start} "
f"{tri.simplices[nn, 2] + start} "
"2 0 1\n")
with open(os.path.join(name, "Elements.txt"), "w") as f_id:
f_id.write(elems)
# plot the evaluation grid
if show:
points = pf.Coordinates(
points[:, 0], points[:, 1], points[:, 2]).show()
plt.savefig(os.path.join(name, "evaluation_grid.png"), dpi=300)