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, spacing, *[, 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, spacing, *[, 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(x, n, a)

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

class sfs.array.SecondarySourceDistribution(x, n, a)[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, spacing, *, 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.

  • spacing (float) – Distance (in metres) between secondary sources.

  • 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, spacing, *, 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.

  • spacing (float) – Distance (in metres) between secondary sources.

  • 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