Using echoSMs
EchoSMs is (currently) a Python package that implements acoustic scattering models. Each different model is a separate Python class in the echoSMs package. They all inherit from a common base class that defines a common calling convention.
Installation
EchoSMs is available on PyPi as echosms
. Install it with:
pip install echosms
The prolate spheroidal modal series model in echoSMs uses spheroidal wave functions. A high-accuracy implementation of these is available in the spheroidalwavefunctions
Python package , as the functions provided by scipy are insufficient. This should be installed automatically when you install echosms, but note that spheroidalwavefunctions
is currently only available for Linux and Windows on x86_64 CPU architectures (create an issue if you want it on a system that is not currently supported).
Versions
The installed version of echosms can be printed with this code:
import importlib
print(importlib.metadata.version('echosms'))
The changelogs for echoSMs are available here. The latest version is always at the top of that list.
Model overview
Currently, the following models are available in echoSMs:
Model type | Python class name | Description |
---|---|---|
Deformed cylinder model | DCMModel | Truncated cylinders with various boundary conditions |
Elastic sphere | ESModel | Elastic spheres, such as echosounder calibration spheres |
Kirchhoff approximation | KAModel | Surfaces that are mainly convex |
Modal series solution | MSSModel | Spheres with various boundary conditions, including shells |
Prolate spheroidal modal series | PSMSModel | Prolate spheroids with various boundary conditions |
Phase-tracking distorted wave Born approximation | PTDWBAModel | Weakly scattering objects of any shape with inhomogeneous interiors |
Future models will include more types of DWBA models, the Kirchhoff-ray-mode model, the Fourier matching method, and potentially finite element and boundary element models.
Running a model
Each echoSMs model expects input parameters that define the model (e.g., size, shape, material properties, etc). These can be provided in three ways:
- A Python dictionary with an entry for each parameter,
- A Pandas DataFrame with columns for each parameter and a row for each model run,
- An Xarray DataArray with as many dimensions as parameters. The parameter values are in the DataArray coordinate variables.
To use a model, you need to know what parameters it requires. These are documented in the calculate_ts_single
function that each model has (refer to the echoSMS API reference for details). The units for numerical parameters will always follow the echoSMs unit convention. For example, the MSSModel, when simulating the scattering from a pressure release sphere, needs the following parameters:
Name | Description |
---|---|
medium_c | Sound speed in the fluid medium surrounding the target [m/s] |
medium_rho | Density of the fluid medium surrounding the target [kg/m³] |
a | Radius of the spherical target [m] |
f | Frequency to calculate the scattering at [Hz] |
boundary_type | The boundary type. Supported types are fixed rigid , pressure release , and fluid filled |
The simplest way to provide these to the model is a dictionary:
p = {'medium_rho': 1026.8,
'medium_c': 1477.4,
'a': 0.01,
'boundary_type': 'pressure release',
'f': 38000}
An instance of the model can then be created and the calculate_ts
function called with these parameters:
This will return one TS value corresponding to the parameters given. If you want to run the model for a range of parameters, the relevant dictionary items can contain multiple values:
import numpy as np
p = {'medium_rho': 1026.8,
'medium_c': 1477.4,
'a': 0.01,
'boundary_type': 'pressure release',
'f', np.arange(10, 100, 1)*1000} # [Hz]
model.calculate_ts(p)
It is also fine to have multiple items with multiple values:
p = {'medium_rho': 1026.8,
'medium_c': 1477.4,
'a': np.arange(0.01, 0.02, 0.001), # [m]
'boundary_type': ['pressure release', 'fixed rigid'],
'f': np.arange(10, 100, 1)*1000} # [Hz]
model.calculate_ts(p)
The TS will be calculated for all combinations of the parameters. To do this, echoSMs expands the parameters into a Pandas DataFrame with one column for each parameter and one row for each of the combinations. It then runs the model on each row of the DataFrame. That DataFrame, with the TS included, can be returned instead of a list of TS values by using the expand
option:
An introductory Jupyter notebook is available that covers the above concepts and a Python script that covers this and more is available here.
Using DataFrames and DataArrays directly
Instead of passing a dictionary to the calculate_ts
function, a DataFrame or DataArray can be passed instead. The crucial aspect is that the DataFrame columns must have the same names as the parameters that the model requires. For a DataArray, the coordinate dimensions must have the same names as the model parameters.
EchoSMS provides two utility functions (as_dataframe
, and as_dataarray
) to convert from a dictionary representation of model parameters to a DataFrame or DataArray, or you can construct your own, or modify those returned by the as_dataframe
and as_dataarray
functions.
The benefit of using a DataFrame is that you have fine control over what model runs will happen - it doesn't have to be the full set of combinations of input parameters. The benefit of using a DataArray is that it is easy to extract subsets of the results for further analysis and plotting.
For a DataFrame, the number of model runs will be the number of rows in the DataFrame. For a DataArray the number of models run will be the size of the DataArray (e.g., DataArray.size()
)
When passing a DataFrame to a model, you can choose whether the TS results are returned as a Series
or are added to the existing DataFrame (in a column called ts
). Use the inplace = True
parameter in the call to calculate_ts
for this. When passing a DataArray to a model, the TS results are always returned in the data part of the passed in DataArray.
More complex model parameters
Some models use parameters that are not sensibly duplicated across rows in a DataFrame or as a dimension in a DataArray (e.g., the data that specifies the three-dimensional shape of a fish swimbladder). EchoSMs allows for this with the concept of non-expandable parameters - these are not expanded into DataFrame columns or DataArray dimensions. Non-expandable parameter names are available from the models' no_expand_parameters
attribute.
But, as it is very convenient to have all the model parameters in one data structure, echoSMs will store the non-expandable parameters as a dict in the DataFrame or DataArray attributes. An example of this is the PTDWBAModel
:
from echosms import PTDWBAModel, as_dataframe
import numpy as np
model = PTDWBAModel()
m = {'volume': np.full((5,5,5), 0),
'f': np.arange(10, 100, 1)*1000,
'rho': [1024, 1025],
'c': [1500, 1501],
'voxel_size': (0.001, 0.001, 0.001),
'theta': 90,
'phi': 0}
m['volume'][3,3,3] = 1 # something to produce scatter
p = as_dataframe(m, model.no_expand_parameters)
model.calculate_ts(p, inplace=True)
print(p)
For the PTDWBA model, only theta
and phi
are expandable, so p
contains three columns (theta
, phi
, and ts
). The remaining parameters are available via:
Note that while rho
and c
look like parameters that would be expanded, they are in the list of non-expandable parameters, so are not expanded. This is because the structure of the PTDWBA model means that it it not sensible to have variable parameters for rho
and c
.
If you pass the dictionary form of the parameters to a model, this treatment of non-expanding parameters is done automatically, where
returns the same results as
Multiprocessing
This is an experimental feature.
The multiprocess = True
parameter in the call to calculate_ts
will cause echoSMs to divide the requested model runs over as many cores as your computer has. Total solution time will decrease almost linearly with the number of models runs.
Reference model definitions
Jech et al., (2015) presented reference models for a range of scattering objects: spheres, spherical shells, prolate spheroids, and finite cylinders for several boundary conditions (fixed rigid, pressure release, fluid-filled) and parameters (backscatter as a function of frequency and incident angle). These model definitions are included in echoSMs via the ReferenceModels
class, along with other objects, such as calibration spheres. For example, the names of all the model definitions are available with:
which returns:
['fixed rigid sphere',
'pressure release sphere',
'gas filled sphere',
'weakly scattering sphere',
'spherical fluid shell with pressure release interior',
'spherical fluid shell with gas interior',
'spherical fluid shell with weakly scattering interior',
'fixed rigid prolate spheroid',
'pressure release prolate spheroid',
'gas filled prolate spheroid',
'weakly scattering prolate spheroid',
'fixed rigid finite cylinder',
'pressure release finite cylinder',
'gas filled finite cylinder',
'weakly scattering finite cylinder',
'WC20 calibration sphere',
'WC21 calibration sphere',
'WC22 calibration sphere',
'WC25 calibration sphere',
'WC38.1 calibration sphere',
'WC57.2 calibration sphere',
'WC60 calibration sphere',
'WC64 calibration sphere',
'Cu13.7 calibration sphere',
'Cu23 calibration sphere',
'Cu32 calibration sphere',
'Cu42 calibration sphere',
'Cu45 calibration sphere',
'Cu60 calibration sphere',
'Cu63 calibration sphere',
'Cu64 calibration sphere']
and the specification for a particular model is given by:
which returns:
{'name': 'spherical fluid shell with weakly scattering interior',
'shape': 'sphere',
'boundary_type': 'fluid shell fluid interior',
'description': 'A fluid spherical shell with a weakly scattering shell and interior',
'a': 0.01,
'shell_thickness': 0.001,
'medium_rho': 1026.8,
'medium_c': 1477.4,
'shell_rho': 1028.9,
'shell_c': 1480.3,
'target_rho': 1031.0,
'target_c': 1483.3,
'source': 'https://doi.org/10.1121/1.4937607',
'benchmark_model': 'mss'}
Note that the specification contains more information that the model itself needs, so the subset needed for running a model is available via:
which returns:
{'boundary_type': 'fluid shell fluid interior',
'a': 0.01,
'shell_thickness': 0.001,
'medium_rho': 1026.8,
'medium_c': 1477.4,
'shell_rho': 1028.9,
'shell_c': 1480.3,
'target_rho': 1031.0,
'target_c': 1483.3}
Note that the parameters()
call does not return all of the parameters needed by a model. For example, f
is not there and needs to be added before running a model:
m['f'] = [38000, 40000, 42000]
from echosms import MSSModel
model = MSSModel()
model.calculate_ts(m)
Benchmark model TS
Jech et al., (2015) presented benchmark model runs for the reference models. The TS results from these benchmarks are available in echoSMs via the BenchMarkData
class. This class is a simple wrapper around code that reads the CSV-formatted file of benchmark values into a Pandas DataFrame, whereupon they can be accessed like this:
from echosms import BenchmarkData
bm = BenchmarkData()
bm.angle_dataset # the TS as a function of angle at 38 kHz
bm.freq_dataset # the TS as a function of frequency
The TS and frequency values for a particular benchmark are available with normal Pandas DataFrame indexing syntax. The DataFrame column names are the same as the ReferenceModels names. For example:
or for the angle dataset: