Skip to content

Commit

Permalink
Update internal documentation and string formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
JensAhrens committed Nov 18, 2019
1 parent 63c3c93 commit 6f26175
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 146 deletions.
40 changes: 19 additions & 21 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,37 +26,32 @@ The following external libraries are required:
Installation
------------

For performance and convenience reasons we highly recommend to use
`Conda`_ (miniconda for simplicity) to manage your Python installation.
Once installed, you can use the following steps to create a new environment
with the *sfa* toolbox.
For performance and convenience reasons we highly recommend to use `Conda`_ (miniconda for simplicity) to manage your Python installation. Once installed, you can use the following steps to receive and use *sfa*, depending on your use case:

#. Create new Conda environment from the specified requirements:
``conda env create --file environment.yml``
A. By cloning (or downloading) the repository and setting up a new environment **[recommended]**:

#. Activate the environment:
``source activate sfa``
``git clone https://github.com/AppliedAcousticsChalmers/sound_field_analysis-py.git``

#. Install *sfa* from **either** source:
``cd sound_field_analysis-py/``

By cloning (or downloading) the repository **[recommended]**:
Create a new Conda environment from the specified requirements:
``conda env create --file environment.yml``

``git clone https://github.com/AppliedAcousticsChalmers/sound_field_analysis-py.git``
Activate the environment:
``source activate sfa``

``cd sound_field_analysis-py/``
**Optional:** Install additional requirements in case you want to locally run the *Jupyter Notebooks* with examples:
``conda env update --file environment_jupyter.yml``

``pip install -e .``
B. From PyPI **[NOT recommended - code outdated]**:

From `conda-forge`_ channel **[not recommended - code currently outdated]**:
Install into an existing environment (without example *Jupyter Notebooks*):
``pip install sound_field_analysis``

``conda install -c conda-forge sound_field_analysis``
C. From `conda-forge`_ channel **[NOT recommended - code outdated]**:

From PyPI **[Not recommended - code currently outdated]**:

``pip install sound_field_analysis``

#. **Optional:** Install additional requirements in case you want to locally run *Jupyter Notebooks*:
``conda env update --file environment_jupyter.yml``
Install into an existing environment:
``conda install -c conda-forge sound_field_analysis``


Documentation
Expand Down Expand Up @@ -113,6 +108,9 @@ miro or `SOFA`_ files.
Version history
---------------

*v2019.11.6*
* Update of internal documentation and string formatting

*v2019.8.15*
* Change of version number scheme to CalVer
* Improvement of Exp4
Expand Down
17 changes: 8 additions & 9 deletions contribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,28 @@
## Dev environment
Given you have [anaconda](https://www.continuum.io/downloads) installed, run the following commands to clone the repository into a new folder `sound_field_analysis-py`, install necessary tools into a new conda environment and activate it:
```
git clone https://github.com/QULab/sound_field_analysis-py.git
conda create -n sfa_dev scipy numpy plotly pip ipython
source activate sfa_dev
pip install -e sound_field_analysis-py
git clone https://github.com/AppliedAcousticsChalmers/sound_field_analysis-py.git
cd sound_field_analysis-py/
conda env create --file environment.yml
source activate sfa
```
You can now work on the *sfa* toolbox inside the `sound_field_analysis-py` folder. Using `ipython`, you may use the following magic commands to ensure reload on any changes inside the package:

You can now work on the *sfa* toolbox inside the `sound_field_analysis-py` folder. Using `ipython`, you may use the following magic commands to ensure reload on any changes inside the package:
```
%load_ext autoreload
%autoreload 2
```

## Documentation
If you want to compile the documentation (pdf and/or html), you need to additionally install sphinx and sphinx_rtd_theme and clone the gh-pages branch:

```
conda install sphinx sphinx_rtd_theme
git clone --single-branch --branch gh-pages https://github.com/QULab/sound_field_analysis-py.git sound_field_analysis-docs
conda env update --file environment_gh-pages.yml
git clone --single-branch --branch gh-pages https://github.com/AppliedAcousticsChalmers/sound_field_analysis-py.git sound_field_analysis-docs
```

Now you can compile the pdf readme (given you have latex installed) and html pages by running `make latexpdf` or `make html` from the `sound_field_analysis-py\doc` directory.

If you decide on a different folder structure, you may edit the following line in `doc/Makefile` to decide on where to move the html documentation:

```
HTMLDIR = ../../sound_field_analysis-docs
```
5 changes: 5 additions & 0 deletions environment_gh-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
channels:
- defaults
dependencies:
- sphinx
- sphinx_rtd_theme
30 changes: 21 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
from setuptools import setup

version = open("sound_field_analysis/_version.py").readlines()[-1].split()[-1].strip("\"'")
from setuptools import find_packages, setup

setup(
name='sound_field_analysis',
version=version,
description='Analyze, visualize and process sound field data recorded by spherical microphone arrays.',
url='https://github.com/AppliedAcousticsChalmers/sound_field_analysis-py/',
version=open('sound_field_analysis/_version.py').readlines()[-1].split()[-1].strip('"\''),
license='GPLv3',
# license='MIT',

description='Analyze, visualize and process sound field data recorded by spherical microphone arrays.',
long_description=open('README.rst', mode='r', encoding='utf-8').read(),
keywords='sound field analysis spherical microphone array',

author='QU Lab / Christoph Hohnerlein',
# author='Chalmers University of Technology / Jens Ahrens',
author_email='[email protected]',
license='GPLv3',
# author_email='[email protected]',

classifiers=[
'Development Status :: 4 - Beta',
# 'Development Status :: 5 - Production/Stable',
'Intended Audience :: Science/Research',
'Topic :: Multimedia :: Sound/Audio',
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
'Programming Language :: Python :: 3',
# 'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3.7',
'Operating System :: OS Independent',
],
keywords='sound field analysis spherical microphone array',

python_requires='>=3.7',
install_requires=[
'scipy',
'numpy',
Expand All @@ -27,9 +37,11 @@
package_data={
'examples': ['examples'],
},

extras_require={
'plotting': ['plotly'],
'examples': ['jupyter'],
},
packages=['sound_field_analysis'],

packages=find_packages(),
)
2 changes: 1 addition & 1 deletion sound_field_analysis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from ._version import __version__

__all__ = ["io", "gen", "process", "sph", "utils", "lebedev"]
__all__ = ['io', 'gen', 'process', 'sph', 'utils', 'lebedev']

try:
import plotly
Expand Down
2 changes: 1 addition & 1 deletion sound_field_analysis/_version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""Version information."""
__version__ = '2019.8.15'
__version__ = '2019.11.7'
15 changes: 7 additions & 8 deletions sound_field_analysis/gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
`gauss_grid`
Gauss-Legendre quadrature grid and weights
`lebedev`
Lebedev quadrature grid and weigths
Lebedev quadrature grid and weights
`radial_filter`
Modal radial filter
`radial_filter_fullspec`
Expand All @@ -20,8 +20,8 @@
from scipy.special import spherical_jn

from .io import ArrayConfiguration, SphericalGrid
from .process import spatFT, iSpatFT
from .sph import sph_harm, sph_harm_all, cart2sph, array_extrapolation, kr, sphankel2, dsphankel2
from .process import iSpatFT, spatFT
from .sph import array_extrapolation, cart2sph, dsphankel2, kr, sph_harm, sph_harm_all, sphankel2


def whiteNoise(fftData, noiseLevel=80):
Expand Down Expand Up @@ -101,7 +101,7 @@ def lebedev(max_order=None, degree=None):
Returns
-------
gridData : array_like
Lebedev quadrature positions and weigths: [AZ, EL, W]
Lebedev quadrature positions and weights: [AZ, EL, W]
"""
if max_order is None and not degree:
raise ValueError('Either a maximum order or a degree have to be given.')
Expand All @@ -117,8 +117,7 @@ def lebedev(max_order=None, degree=None):
raise ValueError('Maximum order can only be between 0 and 11.')

if degree not in allowed_degrees:
raise ValueError('{} is an invalid quadrature degree. Choose one of the following: {}'.format(
degree, allowed_degrees))
raise ValueError(f'{degree} is an invalid quadrature degree. Choose one of the following: {allowed_degrees}')

from . import lebedev
leb = lebedev.genGrid(degree)
Expand Down Expand Up @@ -336,8 +335,8 @@ def sampled_wave(order, fs, NFFT, array_configuration,

# TODO : Investigate if limit_order works as intended
if max_order_fullspec > limit_order:
print('Requested wave front needs a minimum order of {} but was limited to order {}'.format(
max_order_fullspec, limit_order))
print(f'Requested wave front needs a minimum order of {max_order_fullspec} but was limited to order '
f'{limit_order}')
Pnm = ideal_wave(min(max_order_fullspec, limit_order), fs, wave_azimuth, wave_colatitude, array_configuration,
wavetype, distance, NFFT)
Pnm_resampled = spatFT(iSpatFT(Pnm, gridData), gridData, order_max=order)
Expand Down
36 changes: 11 additions & 25 deletions sound_field_analysis/io.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""
Input-Output functions"""

"""Input-Output functions"""
import sys
from collections import namedtuple

import numpy as _np
Expand Down Expand Up @@ -48,10 +47,7 @@ def __new__(cls, array_radius, array_type, transducer_type, scatter_radius=None,
return self

def __repr__(self):
return 'ArrayConfiguration(\n' + ',\n'.join(
' {0} = {1}'.format(name, repr(data).replace('\n', '\n '))
for name, data in
zip(['array_radius', 'array_type', 'transducer_type', 'scatter_radius', 'dual_radius'], self)) + ')'
return utils.get_named_tuple__repr__(self)


class TimeSignal(namedtuple('TimeSignal', 'signal fs delay')):
Expand Down Expand Up @@ -84,9 +80,7 @@ def __new__(cls, signal, fs, delay=None):
return self

def __repr__(self):
return 'TimeSignal(\n' + ',\n'.join(
' {0} = {1}'.format(name, repr(data).replace('\n', '\n '))
for name, data in zip(['signal', 'fs', 'delay'], self)) + ')'
return utils.get_named_tuple__repr__(self)


class SphericalGrid(namedtuple('SphericalGrid', 'azimuth colatitude radius weight')):
Expand Down Expand Up @@ -120,9 +114,7 @@ def __new__(cls, azimuth, colatitude, radius=None, weight=None):
return self

def __repr__(self):
return 'SphericalGrid(\n' + ',\n'.join(
' {0} = {1}'.format(name, repr(data).replace('\n', '\n '))
for name, data in zip(['azimuth', 'colatitude', 'radius', 'weight'], self)) + ')'
return utils.get_named_tuple__repr__(self)


class ArraySignal(namedtuple('ArraySignal', 'signal grid center_signal configuration temperature')):
Expand Down Expand Up @@ -154,9 +146,7 @@ def __new__(cls, signal, grid, center_signal=None, configuration=None, temperatu
return self

def __repr__(self):
return 'ArraySignal(\n' + ',\n'.join(
' {0} = {1}'.format(name, repr(data).replace('\n', '\n '))
for name, data in zip(['signal', 'grid', 'center_signal', 'configuration', 'temperature'], self)) + ')'
return utils.get_named_tuple__repr__(self)


class HrirSignal(namedtuple('HrirSignal', 'l r grid center_signal')):
Expand Down Expand Up @@ -188,9 +178,7 @@ def __new__(cls, l, r, grid, center_signal=None):
return self

def __repr__(self):
return 'HrirSignal(\n' + ',\n'.join(
' {0} = {1}'.format(name, repr(data).replace('\n', '\n '))
for name, data in zip(['l', 'r', 'grid', 'center_signal'], self)) + ')'
return utils.get_named_tuple__repr__(self)


def read_miro_struct(file_name, channel='irChOne', transducer_type='omni', scatter_radius=None,
Expand Down Expand Up @@ -236,7 +224,7 @@ def read_miro_struct(file_name, channel='irChOne', transducer_type='omni', scatt
center_signal = TimeSignal(signal=_np.squeeze(current_data['irCenter']).T,
fs=_np.squeeze(current_data['fs']))
except KeyError:
print('WARNING: Center signal not included in miro struct, use extended miro_to_struct.m!')
print('WARNING: Center signal not included in miro struct, use extended miro_to_struct.m!', file=sys.stderr)
center_signal = None

mic_grid = SphericalGrid(azimuth=_np.squeeze(current_data['azimuth']),
Expand All @@ -245,8 +233,8 @@ def read_miro_struct(file_name, channel='irChOne', transducer_type='omni', scatt
weight=_np.squeeze(current_data['quadWeight']))

if (mic_grid.colatitude < 0).any():
print("WARNING: The 'colatitude' data contains negative values, which is an indication that it is actually "
"elevation")
print('WARNING: The "colatitude" data contains negative values, which is an indication that it is actually '
'elevation', file=sys.stderr)

if _np.squeeze(current_data['scatterer']):
sphere_config = 'rigid'
Expand Down Expand Up @@ -383,7 +371,7 @@ def empty_time_signal(no_of_signals, signal_length):
.air_temperature Average temperature in [C]
"""
return _np.rec.array(_np.zeros(no_of_signals,
dtype=[('signal', str(signal_length) + 'f8'),
dtype=[('signal', f'{signal_length}f8'),
('fs', 'f8'),
('azimuth', 'f8'),
('colatitude', 'f8'),
Expand Down Expand Up @@ -447,8 +435,6 @@ def write_SSR_IRs(filename, time_data_l, time_data_r, wavformat='float32'):
ValueError
in case integer format should be exported and amplitude exceeds 1.0
"""
import sys

# make lower case and remove spaces
wavformat = wavformat.lower().strip()

Expand Down
5 changes: 3 additions & 2 deletions sound_field_analysis/lebedev.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Generate Lebedev grid and coefficients
"""
Generate Lebedev grid and coefficients
This module only exposes the function `lebGrid = lebedev.genGrid(degree)`.
lebGrid is a named tuple containing the coordinates .x, .y, .z and the weights .w
Expand Down Expand Up @@ -211,4 +212,4 @@ def genGrid(n):
lebGrid.w = leb[:, 3]
return lebGrid
except KeyError:
raise ValueError('No grid available for degree', n)
raise ValueError(f'No grid available for degree {n}')
Loading

0 comments on commit 6f26175

Please sign in to comment.