Utilities

This page documents four modules, analysis, visualizers, materials, and hardware.

Some tools for analysis of sound fields and levitation traps.

levitate.analysis.dB(x, power=False)

Convert ratio to decibels.

Converting a ratio to decibels depends on whether the ratio is a ratio of amplitudes or a ratio of powers. For amplitudes the decibel value is \(20\log(|x|)\), while for power ratios the value is \(10\log(|x|)\) where \(\log\) is the base 10 logarithm.

Parameters
  • x (numeric) – Linear amplitude or radio, can be complex.

  • power (bool, default False) – Toggles if the ration is proportional to power.

Returns

L (numeric) – The decibel value.

levitate.analysis.SPL(p)

Convert sound pressure to sound pressure level.

Uses the standard reference value for airborne acoustics: 20 µPa. Note that the input is the pressure amplitude, not the RMS value.

Parameters

p (numeric, complex) – The complex sound pressure amplitude.

Returns

SPL (numeric) – The sound pressure level

levitate.analysis.SVL(u)

Convert sound particle velocity to sound velocity level.

Uses the standard reference value for airborne acoustics: 50 nm/s, which is approximately 20 µPa / c_0 / rho_0 Note that the input the velocity amplitude(s), not the RMS values.

If the first axis of the velocity input has length 3, it will be assumed to be the three Cartesian components of the velocity.

Parameters

u (numeric, complex) – The complex sound velocity amplitude, or the vector velocity.

Returns

SVL (numeric) – The sound velocity level

levitate.analysis.find_trap(array, state, position, tolerance=1e-05, time_interval=50, path_points=1, **kwargs)

Find the approximate location of a levitation trap.

Find an approximate position of a acoustic levitation trap close to a starting point. This is done by following the radiation force in the sound field using an differential equation solver. The differential equation is the un-physical equation \(d\vec x/dt = \vec F(x,t)\), i.e. interpreting the force field as a velocity field. This works for finding the location of a trap and the field line from the starting position to the trap position, but it can not be seen as a proper kinematic simulation of the system.

The solving of the above equation takes place until the whole time interval is covered, or the tolerance is met. The tolerance is evaluated using the assumption that the force is zero at the trap, evaluating the distance from the zero-force position using the force gradient.

Parameters
  • array (TransducerArray) – The transducer array to use for the solving.

  • state (complex array like) – The complex transducer amplitudes to use for the solving.

  • position (array_like, 3 elements) – The starting point for the solving.

  • tolerance (numeric, default 10e-6) – The approximate tolerance of the solution, i.e. how close should the found position be to the true position, in meters.

  • time_interval (numeric, default 50) – The un-physical time of the solution range in the differential equation above.

  • path_points (int, default 1) – Sets the number of points to return the path at. A single evaluation point will only return the found position of the trap.

Returns

trap_pos (numpy.ndarray) – The found trap position, or the path from the starting position to the trap position.

class levitate.analysis.KineticSimulation(array, t_end=1, radius=0.001, material=Styrofoam(poisson_ratio=0.35, rho=25, c=2350), force=None, force_gradient=None, **solver_kwargs)

Performs kinetic simulations for levitated spherical objects.

Initialize with the relevant parameters. Call the object with a state and a position to start the simulation. After a simulation, the object stores attributes for the results.

If the simulation is not started at the center of something resembling a trap, the energy tracking will not work properly.

Variables
  • ~KineticSimulation.t (ndarray, shape (T,)) – Time vector for the simulated positions.

  • ~KineticSimulation.position (ndarray, shape (3, T)) – Simulated positions.

  • ~KineticSimulation.velocity (ndarray, shape (3, T)) – Simulated velocities.

  • ~KineticSimulation.kinetic_energy (ndarray, shape (T,)) – Simulated kinetic energy.

  • ~KineticSimulation.potential_energy (ndarray, shape (T,)) – Approximate potential energy. Calculated from a linear approximation at the starting position.

  • ~KineticSimulation.total_energy (ndarray, shape (T,)) – Sum of kinetic and potential energy.

__call__(state, initial_position)

Call self as a function.

levitate.analysis.linear_stability_metric(array, radius, force_divergence=None, force_curl=None, material=Styrofoam(poisson_ratio=0.35, rho=25, c=2350))

A crude stability metric for traps.

This is based on considering the dynamics of a linear approximation of a trap which has equal axial stiffness. The metric is larger than one for traps which are empirically stable, and smaller than one for traps which empirically are unstable. This is not a guaranteed metric, but relies on very heavy assumptions of the trap behavior. See “Sound Field Design for Transducer Array-Based Acoustic Levitation”, Andersson, 2022, PhD thesis, for further information.

The output is a field object, which can be called with a state and a position like the other field objects in this toolbox. The implemented relation is

\[- \frac{27 \pi\mu^2}{a \rho_*} \frac{\nabla\cdot\vec{F}}{|\nabla\times\vec{F}|^2}\]

where \(F\) is the force field in the trap, \(\mu\) is the dynamic viscosity of the medium, \(\rho_*\) is the density of the object, and \(a\) its radius.

Visualization

Visualization classes based on the plotly graphing library.

class levitate.visualizers.Visualizer(array, *traces, display_scale='mm')
insert(index, value)

S.insert(index, value) – insert value before index

class levitate.visualizers.ArrayVisualizer(array, *args, **kwargs)

Visualizations of a trandcuer array.

It is possible to set an item using either just a trace specifier, e.g. “Pressure”, which create the appropriate trace with default arguments. If arguments are required or wanted, set the item to a tuple where the first element is the trace specifier, and subsequent elements are the arguments. If the last element in the tuple is a dictionary, it will be used as keyword arguments for the trace type.

__call__(*complex_transducer_amplitudes, **kwargs)

Call self as a function.

class levitate.visualizers.ForceDiagram(*args, scale_to_gravity=True, include_gravity=True, **kwargs)
__call__(*complex_transducer_amplitudes, **kwargs)

Call self as a function.

Materials

Manages material properties.

Many functions need access to some material properties. In order to ensure that the properties of a specific material is the same everywhere, they are all collected in classes here.

Pickling

Pickling materials require some special consideration. In general there should be a single set of properties defining a material, but loading some data which is saved with modified properties will create a conflict. The newly loaded material will be in a “Local” state, using modified properties different from the global ones. It is recommended to resolve this by avoiding the problem entirely by modifying the global properties before loading the old data. If this is not possible or preferable, there are three functions intended to resolve the conflict using either the global or the local properties.

Note

Updating global material properties will change the properties throughout the entire package, but some classes (notably the fields) pre-calculate a lot of material-dependent properties. These properties will NOT be updated after a material update. It is therefore highly recommended to define the material properties once in the beginning of a session.

class levitate.materials.MaterialMeta(name, bases, dct)

Metaclass for materials.

This metaclass will automatically create the properties defines in the properties variable in the class or its bases. The properties implement a local/global system, where each instance will default to use the global properties unless otherwise specified.

static class_instance_property(name, doc=None)

Create a local/global property.

class levitate.materials.Material(**kwargs)

Main base class for materials.

This class handles most of the functionality of the materials in the package. Each material is required to have (at least) a speed of sound and a density, from which the impedance and the compressibility can be calculated. In most cases there should only be a single instance of each material class, defining the properties of said material. Multiple instances might be created while pickling see the section below. If a new material of an existing material class is created with modified properties, it will also be created in a “Local” state.

property compressibility

Compressibility \({1 \over \rho c^2}\), non settable.

property impedance

(Specific) Acoustic (wave) impedance \(\rho c\), non settable.

load_from_global()

Load properties from the global state.

Useful only on materials in a local state to resolve conflicts. Replaces the current local properties with the global properties and goes to global mode, completely removing the stored values.

push_to_global()

Push the local properties to the global state.

Useful only on materials in a local state to resolve conflicts. Replaces the current global properties with the modified local ones, completely overriding the global properties for all global instances.

classmethod force_all_to_global()

Force all instances of this material to use global properties.

Useful to resolve material conflicts by choosing the global state for all instances of the material. Will never change the global properties, even if called from a locally modified instance.

property c

The (longitudinal) speed of sound in the material, in m/s.

property rho

The density of the material, in kg/m^3.

class levitate.materials.Gas(**kwargs)

Base class for ideal gases.

All ideal gases can determine the wave speed and density from the ambient temperature and pressure using more basic material constants, see update_properties.

update_properties(temperature=None, pressure=None)

Update the material properties with the ambient conditions.

Sets the material properties of air according to

\[\begin{split}c &= \sqrt{\gamma R T}\\ \rho &= {P \over R T}\end{split}\]

where \(T\) is the ambient temperature in Kelvin, \(P\) is the ambient pressure, \(\gamma\) is the adiabatic index, and \(R\) is the specific gas constant for the gas.

Parameters
  • temperature (float) – The ambient temperature, in degrees Celsius. Defaults to 20.

  • pressure (float) – The static ambient air pressure, in Pa. Defaults to 101325.

property kinematic_viscosity

Kinematic viscosity, in m^2/s.

property c

The (longitudinal) speed of sound in the material, in m/s.

property dynamic_viscosity

Dynamic viscosity, in Pa * s.

property rho

The density of the material, in kg/m^3.

class levitate.materials.Solid(**kwargs)

Base class for elastic solids.

Solids can support shear waves, which is important for some scattering problems.

property c_transversal

Transversal wave speed.

The speed of sound for transversal waves, i.e. shear waves. Calculated as \(c\sqrt{{1-2\nu}\over{2-2\nu}}\), where \(\nu\) is the Poisson’s ratio.

property c

The (longitudinal) speed of sound in the material, in m/s.

property poisson_ratio

Poisson’s ratio, related to shear wave speed.

property rho

The density of the material, in kg/m^3.

class levitate.materials.Air(**kwargs)

Properties of air.

Has default values:

c = 343.2367605312694
rho = 1.2040847588826422
property c

The (longitudinal) speed of sound in the material, in m/s.

property dynamic_viscosity

Dynamic viscosity, in Pa * s.

property rho

The density of the material, in kg/m^3.

class levitate.materials.Styrofoam(**kwargs)

Properties of styrofoam.

Has default values:

c = 2350
rho = 25
poisson_ratio = 0.35
property c

The (longitudinal) speed of sound in the material, in m/s.

property poisson_ratio

Poisson’s ratio, related to shear wave speed.

property rho

The density of the material, in kg/m^3.

Hardware

Hardware related classes and functions.

Various classes and functions to simulate and interface with physical hardware.

Disclaimer

This module is not related to Ultraleap as a company, and it not part of their SDK. It is simply a non-programmer’s way around testing everything in C++. Similarly for the other implemented arrays.

Use at your own risk!

DragonflyArray

Rectangular array with Ultraleap Dragonfly U5 layout.

AcoustophoreticBoard

data_to_cpp

Write data to a file suitable for c++.

data_from_cpp

Read data previously written for c++.

levitate.hardware.data_to_cpp(complex_values, filename)

Write data to a file suitable for c++.

Takes numpy data and writes it to a file which is simple to read from c++. Internally uses numpy.tofile for the actual write.

Parameters
  • complex_values (numpy.ndarray) – The complex transducer values for the array. The order of the transducers must match the internal order of the array.

  • filename (string) – The filename of the file to create.

Note

  • The data will be normalized to have a maximum amplitude of 1.

  • The data will be written as 64 bit complex floats, i.e. 32 bit real + 32 bit imaginary.

  • The data will be conjugated: Ultrahaptics uses a different phase convention.

levitate.hardware.data_from_cpp(file, num_transducers)

Read data previously written for c++.

This is the inverse of data_to_cpp, and is used to read data previously written with said function, or with similar conventions.

Parameters
  • file (String or open file) – The file to read. See numpy.fromfile.

  • num_transducers (int) – The number of transducers in the array. This is important to be able to reshape the data and have the correct number of states in the output.

Returns

data (numpy.ndarray) – The data read from the file. Shape (M, N) where M is the number of states in the file, and N is the number of transducers specified.

Note

  • The data is assumed to be 64 bit complex floats, i.e. 32 bit real + 32 bit imaginary.

  • The data will be conjugated: Ultrahaptics uses a different phase convention.

class levitate.hardware.AcoustophoreticBoard(id=None, linearize_amplitude=True, compensate_phase=True, normalize=False, use_phase_calibration=True, use_amplitude_calibration=False, **kwargs)
class levitate.hardware.DragonflyArray(**kwargs)

Rectangular array with Ultraleap Dragonfly U5 layout.

This is a 16x16 element array where the order of the transducer elements are the same as the iteration order in the Ultraleap SDK. Otherwise behaves exactly like a RectangularArray.