sfs.array

Compute positions of various secondary source distributions.

import sfs
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = 8, 4.5  # inch
plt.rcParams['axes.grid'] = True

Functions

as_secondary_source_distribution(arg, **kwargs) Create a SecondarySourceDistribution.
circular(N, R, *[, center]) Return circular secondary source distribution parallel to the xy-plane.
concatenate(*arrays) Concatenate SecondarySourceDistribution objects.
cube(N, spacing, *[, center, orientation]) Return cube-shaped secondary source distribtion.
edge(Nxy, dx, *[, center, orientation]) Return SSD along the xy-axis with sharp edge at the origin.
linear(N, spacing, *[, center, orientation]) Return linear, equidistantly sampled secondary source distribution.
linear_diff(distances, *[, center, orientation]) Return linear secondary source distribution from a list of distances.
linear_random(N, min_spacing, max_spacing, *) Return randomly sampled linear array.
load(file, *[, center, orientation]) Load secondary source distribution from file.
planar(N, spacing, *[, center, orientation]) Return planar secondary source distribtion.
rectangular(N, spacing, *[, center, orientation]) Return rectangular secondary source distribution.
rounded_edge(Nxy, Nr, dx, *[, center, …]) Return SSD along the xy-axis with rounded edge at the origin.
sphere_load(file, radius, *[, center]) Load spherical secondary source distribution from file.
weights_midpoint(positions, *, closed) Calculate loudspeaker weights for a simply connected array.

Classes

SecondarySourceDistribution Create new instance of SecondarySourceDistribution(x, n, a)
class sfs.array.SecondarySourceDistribution[source]

Create new instance of SecondarySourceDistribution(x, n, a)

take(indices)[source]

Return a sub-array given by indices.

sfs.array.as_secondary_source_distribution(arg, **kwargs)[source]

Create a SecondarySourceDistribution.

Parameters:
  • arg (sequence of between 1 and 3 array_like objects) – All elements are converted to NumPy arrays. If only 1 element is given, all normal vectors are set to NaN. If only 1 or 2 elements are given, all weights are set to 1.0.
  • **kwargs – All keyword arguments are forwarded to numpy.asarray().
Returns:

SecondarySourceDistribution – A named tuple consisting of three numpy.ndarrays containing positions, normal vectors and weights.

sfs.array.linear(N, spacing, *, center=[0, 0, 0], orientation=[1, 0, 0])[source]

Return linear, equidistantly sampled secondary source distribution.

Parameters:
  • N (int) – Number of secondary sources.
  • spacing (float) – Distance (in metres) between secondary sources.
  • center ((3,) array_like, optional) – Coordinates of array center.
  • orientation ((3,) array_like, optional) – Orientation of the array. By default, the loudspeakers have their main axis pointing into positive x-direction.
Returns:

SecondarySourceDistribution – Positions, orientations and weights of secondary sources.

Examples

x0, n0, a0 = sfs.array.linear(16, 0.2, orientation=[0, -1, 0])
sfs.plot2d.loudspeakers(x0, n0, a0)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
_images/sfs-array-2.svg
sfs.array.linear_diff(distances, *, center=[0, 0, 0], orientation=[1, 0, 0])[source]

Return linear secondary source distribution from a list of distances.

Parameters:
  • distances ((N-1,) array_like) – Sequence of secondary sources distances in metres.
  • center, orientation – See linear().
Returns:

SecondarySourceDistribution – Positions, orientations and weights of secondary sources.

Examples

x0, n0, a0 = sfs.array.linear_diff(4 * [0.3] + 6 * [0.15] + 4 * [0.3],
                                   orientation=[0, -1, 0])
sfs.plot2d.loudspeakers(x0, n0, a0)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
_images/sfs-array-3.svg
sfs.array.linear_random(N, min_spacing, max_spacing, *, center=[0, 0, 0], orientation=[1, 0, 0], seed=None)[source]

Return randomly sampled linear array.

Parameters:
  • N (int) – Number of secondary sources.
  • min_spacing, max_spacing (float) – Minimal and maximal distance (in metres) between secondary sources.
  • center, orientation – See linear().
  • seed ({None, int, array_like}, optional) – Random seed. See numpy.random.RandomState.
Returns:

SecondarySourceDistribution – Positions, orientations and weights of secondary sources.

Examples

x0, n0, a0 = sfs.array.linear_random(
    N=12,
    min_spacing=0.15, max_spacing=0.4,
    orientation=[0, -1, 0])
sfs.plot2d.loudspeakers(x0, n0, a0)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
_images/sfs-array-4.svg
sfs.array.circular(N, R, *, center=[0, 0, 0])[source]

Return circular secondary source distribution parallel to the xy-plane.

Parameters:
  • N (int) – Number of secondary sources.
  • R (float) – Radius in metres.
  • center – See linear().
Returns:

SecondarySourceDistribution – Positions, orientations and weights of secondary sources.

Examples

x0, n0, a0 = sfs.array.circular(16, 1)
sfs.plot2d.loudspeakers(x0, n0, a0, size=0.2, show_numbers=True)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
_images/sfs-array-5.svg
sfs.array.rectangular(N, spacing, *, center=[0, 0, 0], orientation=[1, 0, 0])[source]

Return rectangular secondary source distribution.

Parameters:
  • N (int or pair of int) – Number of secondary sources on each side of the rectangle. If a pair of numbers is given, the first one specifies the first and third segment, the second number specifies the second and fourth segment.
  • spacing (float) – Distance (in metres) between secondary sources.
  • center, orientation – See linear(). The orientation corresponds to the first linear segment.
Returns:

SecondarySourceDistribution – Positions, orientations and weights of secondary sources.

Examples

x0, n0, a0 = sfs.array.rectangular((4, 8), 0.2)
sfs.plot2d.loudspeakers(x0, n0, a0, show_numbers=True)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
_images/sfs-array-6.svg
sfs.array.rounded_edge(Nxy, Nr, dx, *, center=[0, 0, 0], orientation=[1, 0, 0])[source]

Return SSD along the xy-axis with rounded edge at the origin.

Parameters:
  • Nxy (int) – Number of secondary sources along x- and y-axis.
  • Nr (int) – Number of secondary sources in rounded edge. Radius of edge is adjusted to equdistant sampling along entire array.
  • center ((3,) array_like, optional) – Position of edge.
  • orientation ((3,) array_like, optional) – Normal vector of array. Default orientation is along xy-axis.
Returns:

SecondarySourceDistribution – Positions, orientations and weights of secondary sources.

Examples

x0, n0, a0 = sfs.array.rounded_edge(8, 5, 0.2)
sfs.plot2d.loudspeakers(x0, n0, a0)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
_images/sfs-array-7.svg
sfs.array.edge(Nxy, dx, *, center=[0, 0, 0], orientation=[1, 0, 0])[source]

Return SSD along the xy-axis with sharp edge at the origin.

Parameters:
  • Nxy (int) – Number of secondary sources along x- and y-axis.
  • center ((3,) array_like, optional) – Position of edge.
  • orientation ((3,) array_like, optional) – Normal vector of array. Default orientation is along xy-axis.
Returns:

SecondarySourceDistribution – Positions, orientations and weights of secondary sources.

Examples

x0, n0, a0 = sfs.array.edge(8, 0.2)
sfs.plot2d.loudspeakers(x0, n0, a0)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
_images/sfs-array-8.svg
sfs.array.planar(N, spacing, *, center=[0, 0, 0], orientation=[1, 0, 0])[source]

Return planar secondary source distribtion.

Parameters:
  • N (int or pair of int) – Number of secondary sources along each edge. If a pair of numbers is given, the first one specifies the number on the horizontal edge, the second one specifies the number on the vertical edge.
  • spacing (float) – Distance (in metres) between secondary sources.
  • center, orientation – See linear().
Returns:

SecondarySourceDistribution – Positions, orientations and weights of secondary sources.

Examples

x0, n0, a0 = sfs.array.planar(
    (4,3), 0.5, orientation=[0, 0, 1])  # 4 sources along y, 3 sources along x
x0, n0, a0 = sfs.array.planar(
    (4,3), 0.5, orientation=[1, 0, 0])  # 4 sources along y, 3 sources along z

x0, n0, a0 = sfs.array.planar(
    (4,3), 0.5, orientation=[0, 1, 0])  # 4 sources along x, 3 sources along z
sfs.plot2d.loudspeakers(x0, n0, a0)  # plot the last ssd in 2D
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
_images/sfs-array-9.svg
sfs.array.cube(N, spacing, *, center=[0, 0, 0], orientation=[1, 0, 0])[source]

Return cube-shaped secondary source distribtion.

Parameters:
  • N (int or triple of int) – Number of secondary sources along each edge. If a triple of numbers is given, the first two specify the edges like in rectangular(), the last one specifies the vertical edge.
  • spacing (float) – Distance (in metres) between secondary sources.
  • center, orientation – See linear(). The orientation corresponds to the first planar segment.
Returns:

SecondarySourceDistribution – Positions, orientations and weights of secondary sources.

Examples

x0, n0, a0 = sfs.array.cube(
    N=2, spacing=0.5,
    center=[0, 0, 0], orientation=[1, 0, 0])
sfs.plot2d.loudspeakers(x0, n0, a0)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
plt.title('view onto xy-plane')
_images/sfs-array-10.svg
sfs.array.sphere_load(file, radius, *, center=[0, 0, 0])[source]

Load spherical secondary source distribution from file.

ASCII Format (see MATLAB SFS Toolbox) with 4 numbers (3 for the cartesian position vector, 1 for the integration weight) per secondary source located on the unit circle which is resized by the given radius and shifted to the given center.

Returns:SecondarySourceDistribution – Positions, orientations and weights of secondary sources.

Examples

content of example_array_6LS_3D.txt:

1 0 0 1
-1 0 0 1
0 1 0 1
0 -1 0 1
0 0 1 1
0 0 -1 1

corresponds to the 3-dimensional 6-point spherical 3-design.

x0, n0, a0 = sfs.array.sphere_load(
    '../data/arrays/example_array_6LS_3D.txt',
    radius=2,
    center=[0, 0, 0])
sfs.plot2d.loudspeakers(x0, n0, a0, size=0.25)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
plt.title('view onto xy-plane')
_images/sfs-array-11.svg
sfs.array.load(file, *, center=[0, 0, 0], orientation=[1, 0, 0])[source]

Load secondary source distribution from file.

Comma Separated Values (CSV) format with 7 values (3 for the cartesian position vector, 3 for the cartesian inward normal vector, 1 for the integration weight) per secondary source.

Returns:SecondarySourceDistribution – Positions, orientations and weights of secondary sources.

Examples

content of example_array_4LS_2D.csv:

1,0,0,-1,0,0,1
0,1,0,0,-1,0,1
-1,0,0,1,0,0,1
0,-1,0,0,1,0,1

corresponds to 4 sources at 1, j, -1, -j in the complex plane. This setup is typically used for Quadraphonic audio reproduction.

x0, n0, a0 = sfs.array.load('../data/arrays/example_array_4LS_2D.csv')
sfs.plot2d.loudspeakers(x0, n0, a0)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
_images/sfs-array-12.svg
x0, n0, a0 = sfs.array.load(
    '../data/arrays/wfs_university_rostock_2018.csv')
sfs.plot2d.loudspeakers(x0, n0, a0)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
plt.title('top view of 64 channel WFS system at university of Rostock')
_images/sfs-array-13.svg
sfs.array.weights_midpoint(positions, *, closed)[source]

Calculate loudspeaker weights for a simply connected array.

The weights are calculated according to the midpoint rule.

Parameters:
  • positions ((N, 3) array_like) – Sequence of secondary source positions.

    Note

    The loudspeaker positions have to be ordered along the contour.

  • closed (bool) – True if the loudspeaker contour is closed.

Returns:

(N,) numpy.ndarray – Weights of secondary sources.

Examples

>>> import sfs
>>> x0, n0, a0 = sfs.array.circular(2**5, 1)
>>> a = sfs.array.weights_midpoint(x0, closed=True)
>>> max(abs(a0-a))
0.0003152601902411123
sfs.array.concatenate(*arrays)[source]

Concatenate SecondarySourceDistribution objects.

Returns:SecondarySourceDistribution – Positions, orientations and weights of the concatenated secondary sources.

Examples

ssd1 = sfs.array.edge(10, 0.2)
ssd2 = sfs.array.edge(20, 0.1, center=[2, 2, 0], orientation=[-1, 0, 0])
x0, n0, a0 = sfs.array.concatenate(ssd1, ssd2)
sfs.plot2d.loudspeakers(x0, n0, a0)
plt.axis('equal')
plt.xlabel('x / m')
plt.ylabel('y / m')
_images/sfs-array-14.svg