# SpearAI Beamforming Module
This beamformer module provides the following core capabilities:
- An array can be loaded by adding individual elements, indicating
their X,Y,Z coordinates
- The sampling rate and NFFT can be configured to set the effective
frequency resolution
- After setting the sampling rate and NFFT, the frequency bins can
be constrained to reduce computations and output size
- The resulting beampattern can be generated for a given set of
steering angles
- CSV files with acoustic data can be processed independently
- CSV files with pose data can be processed alongside the acoustic
data, to produce the beamformer response in a globally aligned
coordinate system
# Installation
The module can be installed using the conventional `pip` calls from the
top of the repo:
- `pip install .` for a regular installation
- `pip install -e .` for an editable-mode installation
# Usage
## Example scripts
Sample scripts are provided in the `examples` directory, which illustrate
the module usage. Relevant sample data is available in the `data` directory.
## CLI entrypoint
The entrypoint `run_beamformer` is also available via CLI, for convenience.
This call will process all data in the target files and write an NPZ file with
the results.
`run_beamformer --config_file data/beamformer_config.json --aco_file data/sample_data_22_noise.csv --pose_file data/sample_pose.csv --outdir ~/ --outfile demo_output`
## Instance configuration
### Instance configuration from scratch
The `Beamformer` class provides the core functionality of the module.
An instance can be configured from scratch as shown:
```python
bf = Beamformer()
bf.set_NFFT(1024)
# Frequency in Hz
bf.set_sample_rate_hz(10000)
bf.set_target_freq(start_freq_hz=1000, end_freq_hz=5000)
# Speed of sound in meters per second
bf.set_sound_speed_mps(1500)
# Coordinates in meters
bf.add_element(x_m=0,y_m=0,z_m=0)
bf.add_element(x_m=1)
bf.add_element(y_m=1)
bf.add_element(z_m=1)
# Set the desired steering angles, in radians
# Defaults:
# > elevation: [-30:30] deg, in 10 deg steps
# > bearings: [-180:180) deg, in 4 deg steps
bf.elevation_rad = np.array([0])
bf.bearing_rad = np.linspace(-np.pi, np.pi, 360 * 2 + 1)
# To save the current configuration (JSON):
bf.save_config('./') # use default filename
bf.save_config('./','custom_beamformer_config.json')
# To review the element coordinate matrix, print bf.P.T
print(bf.P.T)
```
The array coordinate matrix P can be accessed for verification or plotting
purposes; but should **NOT** be set directly. The `bf.add_element()` calls
ensure consistency between the reference coordinate matrix, which is kept
in array-local coordinates, and an internal copy used by the beamformer to
account for array pose updates.
### Instance configuration from file
A JSON file with an array configuration, such as the one generated via
`bf.save_config()`, can be used to instantiate the Beamformer class:
```python
# As used in examples/run_process_file*.py
bf = Beamformer.from_config_json("../data/beamformer_config.json")
```
## Beampattern generation
The module provides easy access to the array's beampattern, for a reference
arrival from a given set of steering angles.
```python
bf.get_beampattern(bearing_rad=0, elevation_rad=0)
```
## Data processing
The module provides two calls for data processing, depending on whether pose processing
is required. If the `process_file_with_pose()` function is called without a pose file,
the system will default to the `process_file()` call.
```python
# As used in examples/run_process_file.py
for b_sig in bf.process_file(
f"../data/sample_data_22_noise.csv"
):
b_sig = np.squeeze(b_sig)
# As used in examples/run_process_file_with_pose.py
for b_sig in bf.process_file_with_pose(
f"../data/sample_data_22_noise.csv",
"../data/sample_pose.csv",
):
b_sig = np.squeeze(b_sig)
```
### CSV file conventions
The acoustic data is assumed to contain a header line indicating a time reference
`timestamp_ns` followed by channel labels. The `timestamp_ns` is used for aligning
with the pose data, when given; it is otherwise dropped for FFT computations. The
channel labels are ignored; the data is assumed to contain the same number of
channels as configured for the beamformer, and the columns are mapped to the array
channels sequentially. A sample header from the files in `data/sample_data_*.csv` is
shown below:
```
timestamp_ns,ch0,ch1,ch2,ch3,ch4,ch5,ch6,ch7,ch8,ch9
```
Note that the time data is not used to infer the sampling rate, nor to verify the data
integrity. The user is responsible for identifying and setting the data sample rate
via `bf.set_sample_rate_hz()` and account for any gaps in the data prior to processing.
Unless otherwise configured, the sampling rate will be assumed to be 1 Hz (normalized
frequency).
The pose data is assumed to contain a header line indicating a time reference
`timestamp_ns` followed by columns matching `roll`, `pitch`, and `yaw`. The `timestamp_ns`
is used for aligning with the acoustic data, such that the appropriate rotations are applied
to the array prior to computing the beamformer response. A sample header from
`data/sample_pose.csv` is shown below:
```
timestamp_ns,roll,pitch,yaw
```
# Development
## Testing
`uv run pytest` will run the `pytest` module in an isolated `venv` with just the project dependencies and dev-dependencies.
## Static Type Checking
`uv run mypy ./src` will scan the project workspace with the `mypy` static type checker and report any errors.
## Linting and Formatting
`uv run ruff check ./src` will check linting and formatting.
`uv run ruff format ./src` will format the python files according to the `ruff` formatting rules.
Raw data
{
"_id": null,
"home_page": null,
"name": "spear-ai-beamformer",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "beamforming, processing, signal",
"author": null,
"author_email": "Spear AI <org@spear.ai>",
"download_url": "https://files.pythonhosted.org/packages/fc/8b/21faa7932c6316feaa9dce237f654da2e231e52077d31356c1521e884ac3/spear_ai_beamformer-0.4.0.tar.gz",
"platform": null,
"description": "# SpearAI Beamforming Module\n\nThis beamformer module provides the following core capabilities:\n\n- An array can be loaded by adding individual elements, indicating\n their X,Y,Z coordinates\n- The sampling rate and NFFT can be configured to set the effective\n frequency resolution\n- After setting the sampling rate and NFFT, the frequency bins can\n be constrained to reduce computations and output size\n- The resulting beampattern can be generated for a given set of\n steering angles\n- CSV files with acoustic data can be processed independently\n- CSV files with pose data can be processed alongside the acoustic\n data, to produce the beamformer response in a globally aligned\n coordinate system\n\n# Installation\n\nThe module can be installed using the conventional `pip` calls from the\ntop of the repo:\n\n- `pip install .` for a regular installation\n- `pip install -e .` for an editable-mode installation\n\n# Usage\n\n## Example scripts\n\nSample scripts are provided in the `examples` directory, which illustrate\nthe module usage. Relevant sample data is available in the `data` directory.\n\n## CLI entrypoint\n\nThe entrypoint `run_beamformer` is also available via CLI, for convenience.\nThis call will process all data in the target files and write an NPZ file with\nthe results.\n\n`run_beamformer --config_file data/beamformer_config.json --aco_file data/sample_data_22_noise.csv --pose_file data/sample_pose.csv --outdir ~/ --outfile demo_output`\n\n## Instance configuration\n\n### Instance configuration from scratch\n\nThe `Beamformer` class provides the core functionality of the module.\nAn instance can be configured from scratch as shown:\n\n```python\nbf = Beamformer()\nbf.set_NFFT(1024)\n\n# Frequency in Hz\nbf.set_sample_rate_hz(10000)\nbf.set_target_freq(start_freq_hz=1000, end_freq_hz=5000)\n\n# Speed of sound in meters per second\nbf.set_sound_speed_mps(1500)\n\n# Coordinates in meters\nbf.add_element(x_m=0,y_m=0,z_m=0)\nbf.add_element(x_m=1)\nbf.add_element(y_m=1)\nbf.add_element(z_m=1)\n\n# Set the desired steering angles, in radians\n# Defaults:\n# > elevation: [-30:30] deg, in 10 deg steps\n# > bearings: [-180:180) deg, in 4 deg steps\nbf.elevation_rad = np.array([0])\nbf.bearing_rad = np.linspace(-np.pi, np.pi, 360 * 2 + 1)\n\n# To save the current configuration (JSON):\nbf.save_config('./') # use default filename\nbf.save_config('./','custom_beamformer_config.json')\n\n# To review the element coordinate matrix, print bf.P.T\nprint(bf.P.T)\n```\n\nThe array coordinate matrix P can be accessed for verification or plotting\npurposes; but should **NOT** be set directly. The `bf.add_element()` calls\nensure consistency between the reference coordinate matrix, which is kept\nin array-local coordinates, and an internal copy used by the beamformer to\naccount for array pose updates.\n\n### Instance configuration from file\n\nA JSON file with an array configuration, such as the one generated via\n`bf.save_config()`, can be used to instantiate the Beamformer class:\n\n```python\n# As used in examples/run_process_file*.py\nbf = Beamformer.from_config_json(\"../data/beamformer_config.json\")\n```\n\n## Beampattern generation\n\nThe module provides easy access to the array's beampattern, for a reference\narrival from a given set of steering angles.\n\n```python\nbf.get_beampattern(bearing_rad=0, elevation_rad=0)\n```\n\n## Data processing\n\nThe module provides two calls for data processing, depending on whether pose processing\nis required. If the `process_file_with_pose()` function is called without a pose file,\nthe system will default to the `process_file()` call.\n\n```python\n# As used in examples/run_process_file.py\nfor b_sig in bf.process_file(\n f\"../data/sample_data_22_noise.csv\"\n):\n b_sig = np.squeeze(b_sig)\n\n# As used in examples/run_process_file_with_pose.py\nfor b_sig in bf.process_file_with_pose(\n f\"../data/sample_data_22_noise.csv\",\n \"../data/sample_pose.csv\",\n):\n b_sig = np.squeeze(b_sig)\n```\n\n### CSV file conventions\n\nThe acoustic data is assumed to contain a header line indicating a time reference\n`timestamp_ns` followed by channel labels. The `timestamp_ns` is used for aligning\nwith the pose data, when given; it is otherwise dropped for FFT computations. The\nchannel labels are ignored; the data is assumed to contain the same number of\nchannels as configured for the beamformer, and the columns are mapped to the array\nchannels sequentially. A sample header from the files in `data/sample_data_*.csv` is\nshown below:\n\n```\ntimestamp_ns,ch0,ch1,ch2,ch3,ch4,ch5,ch6,ch7,ch8,ch9\n```\n\nNote that the time data is not used to infer the sampling rate, nor to verify the data\nintegrity. The user is responsible for identifying and setting the data sample rate\nvia `bf.set_sample_rate_hz()` and account for any gaps in the data prior to processing.\nUnless otherwise configured, the sampling rate will be assumed to be 1 Hz (normalized\nfrequency).\n\nThe pose data is assumed to contain a header line indicating a time reference\n`timestamp_ns` followed by columns matching `roll`, `pitch`, and `yaw`. The `timestamp_ns`\nis used for aligning with the acoustic data, such that the appropriate rotations are applied\nto the array prior to computing the beamformer response. A sample header from\n`data/sample_pose.csv` is shown below:\n\n```\ntimestamp_ns,roll,pitch,yaw\n```\n\n# Development\n\n## Testing\n\n`uv run pytest` will run the `pytest` module in an isolated `venv` with just the project dependencies and dev-dependencies.\n\n## Static Type Checking\n\n`uv run mypy ./src` will scan the project workspace with the `mypy` static type checker and report any errors.\n\n## Linting and Formatting\n\n`uv run ruff check ./src` will check linting and formatting.\n\n`uv run ruff format ./src` will format the python files according to the `ruff` formatting rules.\n",
"bugtrack_url": null,
"license": null,
"summary": "A conventional beamformer",
"version": "0.4.0",
"project_urls": {
"Changelog": "https://github.com/spear-ai/beamform/tree/main/packages/beamformer/CHANGELOG.md",
"Documentation": "https://github.com/spear-ai/beamform/tree/main/packages/beamformer",
"Releases": "https://github.com/spear-ai/beamform/releases",
"Repository": "https://github.com/spear-ai/beamform"
},
"split_keywords": [
"beamforming",
" processing",
" signal"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "234ac67606ddb16810f6512280d1e6d4bd06015007e008ec725eea57404437c4",
"md5": "1de5a2edf3fa764c70e9f957bb2bb1b0",
"sha256": "cd7736eab8397f155ca877768d044e7fb8ec68df2d574fd4b8241a0baf608fc0"
},
"downloads": -1,
"filename": "spear_ai_beamformer-0.4.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "1de5a2edf3fa764c70e9f957bb2bb1b0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 10442,
"upload_time": "2024-11-25T17:52:47",
"upload_time_iso_8601": "2024-11-25T17:52:47.494966Z",
"url": "https://files.pythonhosted.org/packages/23/4a/c67606ddb16810f6512280d1e6d4bd06015007e008ec725eea57404437c4/spear_ai_beamformer-0.4.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "fc8b21faa7932c6316feaa9dce237f654da2e231e52077d31356c1521e884ac3",
"md5": "c05068f7cb3a374c0a731e4e99e280d5",
"sha256": "4e14c2ae59fb460cde28eb0696edeff5e826e1b036510c6c33f13a52ef7bbd06"
},
"downloads": -1,
"filename": "spear_ai_beamformer-0.4.0.tar.gz",
"has_sig": false,
"md5_digest": "c05068f7cb3a374c0a731e4e99e280d5",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 330991,
"upload_time": "2024-11-25T17:52:48",
"upload_time_iso_8601": "2024-11-25T17:52:48.730732Z",
"url": "https://files.pythonhosted.org/packages/fc/8b/21faa7932c6316feaa9dce237f654da2e231e52077d31356c1521e884ac3/spear_ai_beamformer-0.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-25 17:52:48",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "spear-ai",
"github_project": "beamform",
"github_not_found": true,
"lcname": "spear-ai-beamformer"
}