From 93e9d136d1f72acabe7682e33c2f465dbb33b954 Mon Sep 17 00:00:00 2001 From: Anne Heimes Date: Thu, 28 Mar 2024 09:59:36 +0100 Subject: [PATCH 1/4] remove pyfar demo --- examples/pyfar_demo.ipynb | 818 -------------------------------------- 1 file changed, 818 deletions(-) delete mode 100644 examples/pyfar_demo.ipynb diff --git a/examples/pyfar_demo.ipynb b/examples/pyfar_demo.ipynb deleted file mode 100644 index acc47a2ed..000000000 --- a/examples/pyfar_demo.ipynb +++ /dev/null @@ -1,818 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Welcome\n", - "\n", - "The **Py**thon package **f**or **A**coustics **R**esearch (pyfar) contains classes and functions for the acquisition, inspection, and processing of audio signals. This is the pyfar demo notebook and a good place for getting started. In this notebook, you will see examples of the most important pyfar functionalty. \n", - "\n", - "**Note:** This is not a substitute for the [pyfar documentation](https://pyfar.readthedocs.io/en/latest/) that provides a complete description of the pyfar functionality.\n", - "\n", - "## Contents\n", - "\n", - "[Getting started](#getting_started)\n", - "\n", - "[Handling Audio Data](#handling_audio_data)\n", - "- [FFT normalization](#fft_normalization)\n", - "- [Energy and power signals](#energy_and_power_signals)\n", - "- [Accessing Signal data](#accessing_signal_data)\n", - "- [Iterating Signals](#accessing_signal_data)\n", - "- [Signal meta data](#signal_meta_data)\n", - "- [Arithmetic operations](#arithmetic_operations)\n", - "- [Plotting](#plotting)\n", - " - [Interactive plots](#interactive_plots)\n", - " - [Manipulating plots](#manipulating_plots)\n", - "\n", - "[Coordinates](#coordinates)\n", - "- [Entering coordinate points](#coordinates_enter)\n", - "- [Retrieving coordinate points](#coordinates_retrieve)\n", - "- [Rotating coordinate points](#coordinates_rotate)\n", - "\n", - "[Orientations](#orientations)\n", - "- [Entering orientations](#entering_orientations)\n", - "- [Retrieving orientations](#retrieving_orientations)\n", - "- [Rotating orientations](#rotating_orientations)\n", - "\n", - "[Signals](#signals)\n", - "\n", - "[DSP](#dsp)\n", - "- [Filtering](#filtering)\n", - "\n", - "[In'n'out](#in_and_out)\n", - "- [Read and write workspace](#io_workspaces)\n", - "- [Read and write audio files](#io_audio_files)\n", - "- [Read SOFA files](#io_sofa)\n", - "\n", - "\n", - "Lets start with importing pyfar and numpy:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Getting started\n", - "\n", - "Please note that this is not a Python tutorial. We assume that you are aware of basic Python coding and concepts including the use of `conda` and `pip`. If you did not install pyfar already please do so by running the command\n", - "\n", - "`pip install pyfar`\n", - "\n", - "After this go to your Python editor of choice and import pyfar" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# import packages\n", - "import pyfar as pf\n", - "import numpy as np\n", - "\n", - "# set matplotlib backend for plotting\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Handling audio data\n", - "\n", - "Audio data are the basis of pyfar and there are three classes for storing and handling it. Most data will be stored in objects of the `Signal` class, which is intended for time and frequency data that was sampled at equidistant times and frequencies. Examples for this are audio recordings or single sided spectra between 0 Hz and half the sampling rate.\n", - "\n", - "The other two classes `TimeData` and `FrequencyData` are intended to store inclomplete audio data. For example time signals that were not sampled at equidistant times or frequency data that are not available for all frequencies between 0 Hz and half the sampling rate. We will only look at `Signals`, however, `TimeData`and `FrequencyData` are very similar.\n", - "\n", - "`Signals` are stored along with information about the sampling rate, the domain (`time`, or `freq`), the FFT normalization and an optional comment. Lets go ahead and create a single channel signal" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# create a dirac signal with a sampling rate of 44.1 kHz\n", - "fs = 44100\n", - "x = np.zeros(44100)\n", - "x[0] = 1\n", - "x_energy = pf.Signal(x, fs)\n", - "\n", - "# show information\n", - "x_energy" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## FFT Normalization\n", - "\n", - "Different FFT normalization are available that scale the spectrum of a Signal. Pyfar knows six normalizations: `'amplitude'`, `'rms'`, `'power'`, and `'psd'` from [Ahrens, et al. 2020](http://www.aes.org/e-lib/browse.cfm?elib=20838), `'unitary'` (only applies weights for single sided spectra as in Eq. 8 in [Ahrens, et al. 2020](http://www.aes.org/e-lib/browse.cfm?elib=20838)), and `'none'` (applies no normalization). The default normalization is `'none'`, which is useful for **energy signals**, i.e., signals with finite energy such as impulse responses. The other FFT normalizations are intended for **power signals**, i.e., samples of signals with infinite energy, such as noise or sine signals. Visit the [FFT concepts](https://pyfar.readthedocs.io/en/latest/concepts/pyfar.fft.html) for more information. Let's create a signal with a different normalization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x = np.sin(2 * np.pi * 1000 * np.arange(441) / fs)\n", - "x_power = pf.Signal(x, fs, fft_norm='rms')\n", - "x_power" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The normalization can be changed. In this case the spectral data of the signal is converted internally using `pyfar.fft.normalization()`" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x_power.fft_norm = 'amplitude'\n", - "x_power" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note the following: \n", - "\n", - "- The normalizations are only relevant for inspecting the magnitude data, i.e., in plotting. pyfar thus uses the non normalized spectra for all signal processing and arithmetic operations.\n", - "- `FrequencyData` objects do not support the FFT normalization because this requires knowledge about the sampling rate or the number of samples of the time signal. These objects thus have the `'none'` in all cases.\n", - "- `TimeData` does not support FFT normalization because it only exists in the time domain. These objects do not have the `fft_norm` attribute at all." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Energy and power signals\n", - "\n", - "You might have realized that pyfar distinguishes between energy and power signals, which is required for some operations. Signals with the FFT normalization `'none'` are considered as energy signals while all other FFT normalizations result in power signals." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Accessing Signal data\n", - "\n", - "You can access the data, i.e., the audio signal, inside a Signal object in the time and frequency domain by simply using" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "time_data = x_power.time\n", - "freq_data_normalized = x_power.freq\n", - "freq_data_raw = x_power.freq_raw" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Two things are important here:\n", - "\n", - "1. The data are mutable! That means `x_power.time` changes if you change `time_data`. If this is not what you want use `time_data = x_power.time.copy()` instead.\n", - "\n", - "2. The frequency data of signals is available without normalization from `x_power.freq_raw` and with normalization from `x_power.freq`. The latter depends on the Signal's `fft_norm`." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`Signals` and some other pyfar objects support slicing. Let's illustrate that for a two channel signal" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# generate two channel time data\n", - "time = np.zeros((2, 4))\n", - "time[0,0] = 1 # first sample of first channel\n", - "time[1,0] = 2 # first sample of second channel\n", - "\n", - "x_two_channels = pf.Signal(time, 44100)\n", - "x_first_channel = x_two_channels[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`x_first_channel` is a `Signal` object itself, which contains the first channel of `x_two_channels`:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x_first_channel.time" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A third option to access `Signals` is to copy it" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x_copy = x_two_channels.copy()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It is important to note that this returns an independent copy of `x_two_channels`. Note that `x_copy = x_two_channels` might not be wanted. In this case changes to `x_copy` will also change `x_two_channels`. The `copy()` operation is available for all pyfar objects." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Iterating Signals\n", - "\n", - "It is the aim of pyfar that all operations work on N-dimensional `signals`. Nevertheless, you can also iterate `signals` if you need to apply operations depending on the channel. Lets look at a simple example" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "signal = pf.Signal([[0, 0, 0], [1, 1, 1]], 44100) # 2-channel signal\n", - "\n", - "# iterate the signal\n", - "for n, channel in enumerate(signal):\n", - " print(f\"Channel: {n}, time data: {channel.time}\")\n", - " # do something channel dependent\n", - " channel.time = channel.time + n\n", - " # write changes to the signal\n", - " signal[n] = channel\n", - "\n", - "# q.e.d.\n", - "print(f\"\\nNew signal time data:\\n{signal.time}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`Signal` uses the standard `numpy` iterator which always iterates the first dimension. In case of a 2-D array as in the example above these are the channels." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Signal meta data\n", - "\n", - "The `Signal` object also holds useful metadata. The most important might be:\n", - "\n", - "- `Signal.n_samples`: The number of samples in each channel (`Signal.time.shape[-1]`)\n", - "- `Signal.n_bins`: The number of frequencies in each channel (`Signal.freq.shape[-1]`)\n", - "- `Signal.times`: The sampling times of `Signal.time` in seconds\n", - "- `Signal.frequencies`: The frequencies of `Signal.freq` in Hz\n", - "- `Signal.comment`: A comment for documenting the signal content\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Arithmetic operations\n", - "\n", - "The arithmetic operations `add`, `subtract`, `multiply`, `divide`, and `power` are available for `Signal` (time or frequency domain operations) as well as for `TimeData` and `FrequencyData`. The operations work on arbitrary numbers of Signals and array likes. Lets check out simple examples" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# add two signals energy signals\n", - "x_sum = pf.add((x_energy, x_energy), 'time')\n", - "x_sum.time" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this case, `x_sum` is also an energy Signal. However, this can be different for other operation as described in the documentation ([arithmetic operations](https://pyfar.readthedocs.io/en/latest/concepts/pyfar.arithmetic_operations.html)). Under the hood, the operations use numpy's [array broadcasting](https://numpy.org/doc/stable/user/basics.broadcasting.html?highlight=broadcast#module-numpy.doc.broadcasting). This means you can add scalars, vectors, and matrixes to a signal. Lets have a frequency domain example for this" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x_sum = pf.add((x_energy, 1), 'freq')\n", - "x_sum.time" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Python operators `+`, `-`, `*`, `/`, `**` and `@` are overloaded with the **frequency domain** arithmetic functions for `Signal` and `FrequencyData`. For `TimeData` they correspond to time domain operations. Thus, the example above can also be shortened to" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x_sum = x_energy + 1\n", - "x_sum.time" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Plotting\n", - "\n", - "Inspecting signals can be done with the `pyfar.plot` module, which uses common plot functions based on `Matplotlib`. For example a plot of the magnitude spectrum" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pf.plot.freq(x_power)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We set the FFT normalization to 'amplitude' before. The plot thus shows the amplitude (1, or 0 dB) of our sine wave contained in `x_power`. We can also plot the RMS ($1/\\sqrt(2)$, or $\\approx-3$ dB)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x_power.fft_norm = 'rms'\n", - "pf.plot.line.freq(x_power)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Interactive plots\n", - "\n", - "pyfar provides keyboard shortcuts for switching plots, zooming in and out, moving along the x and y axis, and for zooming and moving the range of colormaps. To do this, you need to use an interactive Matplotlib backend. This can for example be done by including\n", - "\n", - "`%matplotlib qt`\n", - "\n", - "or\n", - "\n", - "`matplotlib.use('Qt5Agg')`\n", - "\n", - "in your code. These are the available keyboard short cuts" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "shortcuts = pf.plot.shortcuts()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that additional controls are available through Matplotlib's [interactive navigation](https://matplotlib.org/3.1.1/users/navigation_toolbar.html)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Manipulating plots\n", - "\n", - "In many cases, the layout of the plot should be adjusted, which can be done using Matplotlib and the axes handle that is returned by all plot functions. For example, the range of the x-axis can be changed." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ax = pf.plot.time(x_power)\n", - "ax.set_xlim(0, 2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note: For an easy use of the pyfar plotstyle (available as 'light' and 'dark' theme) wrappers for Matplotlib's `use` and `context` are available as `pyfar.plot.use` and `pyfar.plot.context`." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Coordinates\n", - "\n", - "The `Coordinates()` class is designed for storing, manipulating, and accessing coordinate points. It supports a large variety of different coordinate conventions and the conversion between them. Examples for data that can be stored are microphone positions of a spherical microphone array and loudspeaker positions of a sound field synthesis system. Lets create an empty `Coordinates` object. Visit the [coordinate concepts](https://pyfar.readthedocs.io/en/latest/concepts/pyfar.coordinates.html) for a graphical overview of this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "c = pf.Coordinates()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Entering coordinate points\n", - "\n", - "Coordinate points can be entered manually." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "c = pf.Coordinates(np.arange(-5., 6), 0, 0)\n", - "# show general information\n", - "print(c)\n", - "# plot the sampling points\n", - "c.show()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another way to initalize `Coordinate` objects is the `pf.Coordinates(x, y, z)` constructor or for other coordinate systems classmethods like `pf.Coordinates.from_spherical_elevation(azimuth, elevation, radius)`. Visit the [coordinate class](https://pyfar.readthedocs.io/en/latest/classes/pyfar.coordinates.html) for more datails." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "c1 = pf.Coordinates.from_spherical_elevation([0, np.pi/2, np.pi], 0, 1)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Inside the `Coordinates` object, the Coordinates are stored in a cartesian coordinate system for each `x`, `y` and `z`. Information about coordinate array can be obtained by `c.cshape`, `c.csize`, and `c.cdim`. These properties are similar to numpy's `shape`, `size`, and `dim` of each `x`, `y` and `z`.\n", - "Additionally we can use available sampling schemes contained in https://spharpy.readthedocs.io/en/latest/spharpy.samplings.html." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Retrieving coordinate points\n", - "\n", - "There are different ways to retrieve points from a `Coordinates` object. All points can be obtained in cartesian, spherical, and cylindrical coordinates using the related properties `c.cartesian`, `c.sperical_evaluation` and `c.cylindrical`. Also single properties of each coordinate system convention can be accessed by e.g. `c.azimuth`, `c.radius` or `c.x`. Visit the [coordinate class](https://pyfar.readthedocs.io/en/latest/classes/pyfar.coordinates.html) for more details.\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cartesian_coordinates = c.cartesian" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Different methods are available for obtaining a specific subset of coordinates. For example, the nearest `k` point(s) can be obtained by" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "find = pf.Coordinates.from_spherical_colatitude(270/180*np.pi, 90/180*np.pi, 1)\n", - "index_out, distance = c.find_nearest(find, k=1)\n", - "c.show(index_out)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another option is to find all points in a certain area around different points. Different distance measures are available." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "index_out = c.find_within(find, distance=3, distance_measure='euclidean')\n", - "c.show(index_out)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To obtain all points within a specified euclidean distance or arc distance, you can use `c.get_nearest_cart()` and `c.get_nearest_sph()`. To obtain more complicated subsets of any coordinate, e.g., the horizontal plane with `colatitude=90` degree, you can use" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "index_out = c.colatitude == 90/180*np.pi\n", - "c.show(index_out)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Rotating coordinates\n", - "\n", - "You can apply rotations using quaternions, rotation vectors/matrixes and euler angles with `c.rotate()`, which is a wrapper for `scipy.spatial.transform.Rotation`. For example rotating around the y-axis by 45 degrees can be done with" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "c.rotate('y', 45)\n", - "c.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that this changes the points inside the `Coordinates` object, which means that you have to be careful not to apply the rotation multiple times, i.e., when evaluationg cells during debugging." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Orientations\n", - "\n", - "The `Orientations()` class is designed for storing, manipulating, and accessing orientation vectors. Examples for this are orientations of directional loudspeakers during measurements or head orientations. It is good to know that `Orientations` is inherited from `scipy.spatial.transform.Rotation` and that all methods of this class can also be used with `Orientations`.\n", - "\n", - "## Entering orientations\n", - "\n", - "Lets go ahead and create an object and show the result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "views = [[0, 1, 0],\n", - " [1, 0, 0],\n", - " [0, -1, 0]]\n", - "up = [0, 0, 1]\n", - "orientations = pf.Orientations.from_view_up(views, up)\n", - "orientations.show(show_rights=False)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It is also possible to enter `Orientations` from `Coordinates` object or mixtures of `Coordinates` objects and array likes. This is equivalent to the example above" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "azimuths = np.array([90, 0, 270]) * np.pi / 180\n", - "views_c = pf.Coordinates.from_spherical_elevation(azimuths, 0, 1)\n", - "\n", - "orientations = pf.Orientations.from_view_up(views_c, up)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Retrieving orientations\n", - "\n", - "Orientaions can be retrieved as view, up, and right-vectors and in any format supported by `scipy.spatial.transform.Rotation`. They can also be converted into any coordinate convention supported by pyfar by putting them into a `Coordinates` object. Lets only check out one way for now " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "views, ups, right, = orientations.as_view_up_right()\n", - "views" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Rotating orientations\n", - "\n", - "Rotations can be done using the methods inherited from `scipy.spatial.transform.Rotation`. You can for example rotate around the y-axis this way" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "rotation = pf.Orientations.from_euler('y', 30, degrees=True)\n", - "orientations_rot = orientations * rotation\n", - "orientations_rot.show(show_rights=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Signals\n", - "\n", - "The `pyfar.signals` module contains a variety of common audio signals including sine signals, sweeps, noise and pulsed noise. For brevity, lets have only one example\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sweep = pf.signals.exponential_sweep_time(2**12, [100, 22050])\n", - "pf.plot.time_freq(sweep)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# DSP\n", - "\n", - "`pyfar.dsp` offers lots of useful functions to manipulate audio data including\n", - "\n", - "- convolution, deconvolution, and regulated inversion\n", - "- windowing and zero-padding\n", - "- generating linear and minimum phase signals\n", - "\n", - "and many more. Have a look at the [module documentation](https://pyfar.readthedocs.io/en/latest/modules/pyfar.dsp.html) for a complete overview.\n", - "\n", - "\n", - "### Filtering\n", - "\n", - "`pyfar.dsp.filter` contains wrappers for the most common filters of `scipy.signal` as well as more audio specific filter such as shelve and bell filters. Visit the [filter types](https://pyfar.readthedocs.io/en/latest/concepts/pyfar.filter_types.html) for an overview.\n", - "\n", - "All filters can used in a similar manner, like this one\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x_filter = pf.dsp.filter.bell(x_energy, center_frequency=1e3, gain=10, quality=2)\n", - "pf.plot.line.freq(x_filter)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# In'n'out\n", - "\n", - "Now that you know what pyfar is about, let's see how you can save your work and read common data types.\n", - "\n", - "## Read and write pyfar data\n", - "\n", - "Pyfar contains functions for saving all pyfar objects and common data types such as numpy arrays using `pf.io.write()` and `pf.io.read()`. This creates .far files that also support compression.\n", - "\n", - "## Read and write audio-files\n", - "\n", - "Audio-files in wav or other formats are commonly used in the audio community to store and exchange data. You can read them with\n", - "\n", - "`signal = pf.io.read_audio(filename)`\n", - "\n", - "and write them with\n", - "\n", - "`pf.io.write_audio(signal, filename, overwrite=True)`.\n", - "\n", - "You can write any `signal` to an audio, but in some cases, clipping will occur for values > 1. Multidimensional `signals` will be reshaped to 2D arrays before writing.\n", - "\n", - "## Read SOFA files\n", - "\n", - "[SOFA files](https://www.sofaconventions.org) can be used to store spatially distributed acoustical data sets. Examples for this are room acoustic measurements at different positions in a room or a set of head-related transfer functions for different source positions. SOFA files can quickly be read by\n", - "\n", - "`signal, source, receiver = pf.io.read_sofa(filename)`\n", - "\n", - "which returns the audio data as a `Signal` or `FrequencyData` object (depending on the data in the SOFA file) and the source and receiver coordinates as a `Coordinates` object.\n", - "\n", - "`read_sofa` uses the [sofar package](https://sofar.readthedocs.io/en/latest/), which we recommend to manipulate and write SOFA files or access the detailed meta data contained in SOFA files." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "pyfar", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.4" - }, - "vscode": { - "interpreter": { - "hash": "31fda18d23bccfca635c34b8e2ae5cca9cc1e70ba24d7dd63263c3d313ebed7d" - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} From 0fbc5fd19404e0e65c11cec9e74a6a7455105326 Mon Sep 17 00:00:00 2001 From: Anne Heimes Date: Thu, 28 Mar 2024 09:59:51 +0100 Subject: [PATCH 2/4] link to gallery in readme --- README.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index f69936b86..70cf1e9b5 100644 --- a/README.rst +++ b/README.rst @@ -10,7 +10,7 @@ pyfar .. image:: https://circleci.com/gh/pyfar/pyfar.svg?style=shield :target: https://circleci.com/gh/pyfar/pyfar .. image:: https://mybinder.org/badge_logo.svg - :target: https://mybinder.org/v2/gh/pyfar/pyfar/main?filepath=examples%2Fpyfar_demo.ipynb + :target: https://mybinder.org/v2/gh/pyfar/gallery/main?filepath=docs/gallery The python package for acoustics research (pyfar) offers classes to store @@ -20,9 +20,9 @@ functions for digital audio signal processing. Getting Started =============== -Check out the `examples notebook`_ for a tour of the most important pyfar -functionality and `read the docs`_ for the complete documentation. Packages -related to pyfar are listed at `pyfar.org`_. +Check out the `pyfar.org`_ for a tour trought the pyfar +universe, including complete documentation of this package and +the other packages. Installation ============ @@ -44,7 +44,6 @@ Refer to the `contribution guidelines`_ for more information. .. _contribution guidelines: https://github.com/pyfar/pyfar/blob/develop/CONTRIBUTING.rst -.. _examples notebook: https://mybinder.org/v2/gh/pyfar/pyfar/main?filepath=examples%2Fpyfar_demo.ipynb .. _pyfar.org: https://pyfar.org .. _read the docs: https://pyfar.readthedocs.io/en/latest .. _SoundFile: https://pysoundfile.readthedocs.io/en/latest/ From 10774d362f2a2babcd618c2c83d2910a6439479f Mon Sep 17 00:00:00 2001 From: Anne Heimes Date: Thu, 28 Mar 2024 10:10:51 +0100 Subject: [PATCH 3/4] changes in contribution --- CONTRIBUTING.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index e141257bd..2575cd3d9 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -244,7 +244,7 @@ A reminder for the maintainers on how to deploy. - Commit all changes to develop - Update HISTORY.rst in develop -- Check if examples/pyfar_demo.ipynb needs to be updated +- Check if gallery needs to be updated - Merge develop into main Switch to main and run:: @@ -255,6 +255,6 @@ $ git push --follow-tags The testing platform will then deploy to PyPI if tests pass. - merge main back into develop -- check `binder`_ +- check gallery in `binder`_ -.. _binder: https://mybinder.org/v2/gh/pyfar/pyfar/main?filepath=examples%2Fpyfar_demo.ipynb +.. _binder: https://mybinder.org/v2/gh/pyfar/gallery/main?filepath=docs/gallery From b96c64d648d08ca2fc73db791050deb00da4850a Mon Sep 17 00:00:00 2001 From: Anne Heimes <64446926+ahms5@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:40:31 +0200 Subject: [PATCH 4/4] Update README.rst Co-authored-by: Pascal Palenda --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 70cf1e9b5..4d375c16e 100644 --- a/README.rst +++ b/README.rst @@ -20,7 +20,7 @@ functions for digital audio signal processing. Getting Started =============== -Check out the `pyfar.org`_ for a tour trought the pyfar +Check out `pyfar.org`_ for a tour through the pyfar universe, including complete documentation of this package and the other packages.