Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New scattering freefield implementation #12

Open
wants to merge 33 commits into
base: develop
Choose a base branch
from

Conversation

ahms5
Copy link
Member

@ahms5 ahms5 commented Feb 24, 2023

Changes proposed in this pull request:

  • implement scattering coefficient calculation from freefield measurements/simulations

replaces #8

@ahms5 ahms5 mentioned this pull request Feb 24, 2023
@ahms5 ahms5 self-assigned this Mar 10, 2023
imkar/scattering/coefficient.py Outdated Show resolved Hide resolved
imkar/scattering/coefficient.py Outdated Show resolved Hide resolved
imkar/scattering/coefficient.py Outdated Show resolved Hide resolved
imkar/scattering/coefficient.py Outdated Show resolved Hide resolved
imkar/scattering/coefficient.py Outdated Show resolved Hide resolved
Comment on lines 123 to 125
Defines the incidence directions of each `scattering_coefficients` in a
Coordinates object. Its cshape need to be (#angle1, #angle2). In
sperical coordinates the radii need to be constant.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the code, this is a little confusing. Do I understand it correctly that it needs to be a spherical sampling incl. weights? Why shaped to (#angle1, #angle2)? What is angle1 and angle2?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its wrong, its a leftover, thanks

imkar/scattering/coefficient.py Outdated Show resolved Hide resolved
imkar/scattering/coefficient.py Outdated Show resolved Hide resolved
raise ValueError("incident_positions have to be None or Coordinates")

theta = incident_positions.get_sph().T[1]
weight = np.cos(theta) * incident_positions.weights
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can it be ensured, that the incident_positions.weights are meaningful?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in the docs

def test_freefield_1(frequencies):
mics = pf.samplings.sph_gaussian(42)
mics = mics[mics.get_sph().T[1] <= np.pi/2] # delete lower part of sphere
p_sample = stub_utils.frequency_data_from_shape(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the pyfar "rules", this is not how stub utils should be used. Please create the stubs in conftest.py, not within the tests itself. Maybe the stub_utils are even obsolete then (which would be favorable)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@ahms5 ahms5 requested a review from sikersten April 16, 2023 19:04
@ahms5
Copy link
Member Author

ahms5 commented Apr 16, 2023

ready to review

@ahms5 ahms5 requested a review from pingelit April 28, 2023 11:16
Copy link
Member

@pingelit pingelit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Except for some minor doc string change, I would approve.

"same cshape.")
if microphone_weights.shape[0] != sample_pressure.cshape[-1]:
raise ValueError(
"the last dimension of sample_pressure need be same as the "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"the last dimension of sample_pressure need be same as the "
"the last dimension of sample_pressure needs to be the be same as the "

imkar/utils/utils.py Outdated Show resolved Hide resolved
imkar/utils/utils.py Outdated Show resolved Hide resolved
need to be (..., #incident_directions)
incident_directions : pyfar.Coordinates
Defines the incidence directions of each `coefficients` in a
Coordinates object. Its cshape need to be (#incident_directions). In
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Coordinates object. Its cshape need to be (#incident_directions). In
Coordinates object. Its cshape needs to be (#incident_directions). In

Returns
-------
random_coefficient : pyfar.FrequencyData
The random-incidence scattering coefficient.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how common the Paris formula is, but it might be nice to add a citation here as well.

ahms5 and others added 4 commits May 23, 2023 17:58
Co-authored-by: Pascal Palenda <pingelit@users.noreply.github.com>
Co-authored-by: Pascal Palenda <pingelit@users.noreply.github.com>
@ahms5 ahms5 requested a review from pingelit May 23, 2023 22:42
@ahms5
Copy link
Member Author

ahms5 commented May 23, 2023

ready for review

@@ -0,0 +1,7 @@
imkar.scattering
================

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A brief general description of the module in a sentence or two might be nice to add.

Comment on lines +1 to +2
import numpy as np
import pyfar as pf
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See issue - dependencies must be added to setup.py

Comment on lines 8 to 9
Calculate the free-field scattering coefficient for each incident direction
using the Mommertz correlation method [1]_:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we go full Zen of Python and start with a one liner without reference? I would also not use incident direction, since this is not passed and seems to be implicitly contained in the input data.

Suggested change
Calculate the free-field scattering coefficient for each incident direction
using the Mommertz correlation method [1]_:
Calculate the direction dependent free-field scattering coefficient.
Uses the Mommertz correlation method [1]_ to calculate the scattering
coefficient separately for each channel of the input data:


.. math::
s(\vartheta_S,\varphi_S) = 1 -
\frac{|\sum \underline{p}_{sample}(\vartheta_R,\varphi_R) \cdot
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For readability I would suggest to use text in the subscripts, e.g.: p_{\text{sample}}

Comment on lines 19 to 20
with the ``sample_pressure``, the ``reference_pressure``, and the
area weights ``weights_microphones``. See
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I would focus more on explaining the formula, e.g., with the sample pressure p_{\text{sample}} and not refer to the variable names here. To me that was clear due to the verbose variable names already.

  • Can we use \sum_w and w(phi_R, theta_R) to make things more clear?

Comment on lines 118 to 120
Coordinates object. Its cshape needs to be (#source_directions). In
sperical coordinates the radii needs to be constant. The weights need
to reflect the area weights.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • A cross reference to pyfar.Coordinates would be convenient.
  • 'Points contained in incident_directions must hace the same radii' would sound more clear to me.
  • I would suggest to explicitly refer to incident_directions.weights to be more clear

"""
random_scattering = utils.paris_formula(
scattering_coefficients, incident_directions)
random_scattering.comment = 'random-incidence scattering coefficient'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above for question about using/not using comments

Comment on lines 7 to 16
Calculate the random-incidence coefficient
according to Paris formula [2]_.

.. math::
c_{rand} = \sum c(\vartheta_S,\varphi_S) \cdot cos(\vartheta_S) \cdot w

with the ``coefficients``, and the
area weights ``w`` from the ``incident_directions``.
Note that the incident directions should be
equally distributed to get a valid result.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See general docstring comments in scattering.random

----------
sample_pressure : pyfar.FrequencyData
Reflected sound pressure or directivity of the test sample. Its cshape
needs to be (..., #microphones).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'#microphones' is a bit informal. Should we use variable_name.size? Would also affect the remaining docstrings.

Comment on lines 24 to 27
Defines the incidence directions of each `coefficients` in a
Coordinates object. Its cshape needs to be (#incident_directions). In
sperical coordinates the radii needs to be constant. The weights need
to reflect the area weights.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment in scattering.random

Copy link
Member

@f-brinkmann f-brinkmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the effort. I had one big questions:

  • Should we make the functions work with pyfar.Signal objects. I think yes - but what would be a clean, simple, and comprehensive way? This would require filtering in octaves and maybe in som cases different processing in the functions

In the docstrings

  • it would be safer to number the references implicitly (I think using [#]_ , there should be examples in the pyfar code base)
  • parameters should be written in italic unsing only a single `

@ahms5 ahms5 requested a review from f-brinkmann June 26, 2023 08:48
Copy link
Member

@f-brinkmann f-brinkmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the effort. Only had a few comments left and I was wondering if the public utils model should be added to the docs.

imkar/scattering/scattering.py Outdated Show resolved Hide resolved
Reflected sound pressure or directivity of the
reference sample. Needs to have the same cshape and frequencies as
`sample_pressure`.
microphone_weights : numpy.ndarray
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there constraints on the weights that should be mentioned? E.g., should they sum to 1?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to be normalized or just area weights, but mybe i could mention it

imkar/scattering/scattering.py Outdated Show resolved Hide resolved
import pyfar as pf


def paris_formula(coefficients, incident_directions):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name of the function and module suggests that it is public. In this case should we add it to the docs as well?

imkar/utils/utils.py Outdated Show resolved Hide resolved
Comment on lines 18 to 19
and :math:`\vartheta` and :math:`\varphi` are the incidence
angle and azimuth angles. Note that the incident directions should be
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the term 'incedence angle and azimuth anges' is a bit confusing to me. Could we use only 'incidence angles'?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved it, by directly refering to the pyfar.Coordinates angles

the reference sample (same dimension as the sample under investigation,
but with flat surface) :math:`\underline{p}_{\text{reference}}`, the
area weights of the sampling :math:`w`, and :math:`\vartheta` and
:math:`\varphi` are the incidence angle and azimuth angles. See
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment in utils on the names of the angles.

needs to be (..., microphone_weights.csize).
reference_pressure : :py:class:`~pyfar.classes.audio.FrequencyData`
Reflected sound pressure or directivity of the
reference sample. Needs to have the same cshape and frequencies as
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we link to pyfar audio concepts when refering to cshape? Otherwise people less familiar with pyfar might be confused.

ahms5 and others added 4 commits August 7, 2023 13:40
Co-authored-by: Fabian Brinkmann <fabian.brinkmann@mailbox.org>
Co-authored-by: Fabian Brinkmann <fabian.brinkmann@mailbox.org>
Co-authored-by: Fabian Brinkmann <fabian.brinkmann@mailbox.org>
@ahms5 ahms5 requested a review from f-brinkmann August 7, 2023 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants