Using the Code* operators
This page provides detailed information about the Code and Code - Time series operators. On this page, Code* refers collectively to both operators.
If you are unfamiliar with the Code* operators, we recommend you first complete the Introduction to the Code operator tutorial or watch the Introduction to the Code operator: A Python interface for Echoview video.
Note: In Echoview 16, the acoustic ping object formerly named Measurement is now Ping. Time series operands expose TimeSeriesMeasurement.
- Creating a Code variable
- Creating a Code - Time series variable
- Setting up and executing a Code* variable
- Inputting operands into the Code* operator
- Arguments
- Processing pings with the Code* operator
- Selecting the matched ping
- Using the window of measurements
- Processing ping data or metadata
- Returning Code ping data to Echoview
- Returning Code - Time series data to Echoview
- The data type of the Code operator
- The Echoview Python package
- Importing Python packages
- Error handling
- No data handling
- Performance considerations
- Example Python source files
- See also
Creating a Code variable
A Code variable is an acoustic virtual variable with ping geometry and measurement times based on Operand 1. Its sample values are calculated by a Python script.
- On the Dataflow window, click on an existing raw or virtual acoustic variable to preselect it.
- Select the Code operator from the Dataflow Toolbox (under the All category), then drag and drop it onto the Dataflow window. This creates a new Code operator virtual variable with the variable that you preselected as Operand 1.
- Select the Code object, right-click and select Variable Properties.
- On the Operands page, use Add New Operand to specify additional acoustic or time series operands.
- On the Code page, click New to create and assign a default Echoview Python source file, or click the browse button to select an existing file. After a source file is assigned, New becomes Edit.
Creating a Code - Time series variable
A Code - Time series variable outputs a virtual time series with measurement times based on the ping times of Operand 1. Its measurement values and output data type are determined by a Python script.
- On the Dataflow window, click on an existing raw or virtual acoustic variable to preselect it.
- Select the Code - Time series operator from the Dataflow Toolbox (under the All category), then drag and drop it onto the Dataflow window. This creates a new Code - Time series virtual variable with the preselected variable as Operand 1.
- Select the Code - Time series object, right-click and select Time Series Properties.
- On the Operands page, use Add New Operand to specify additional time series operands.
- On the Code - Time Series page, click New to create and assign a default Echoview Python source file, or click the browse button to select an existing file. After a source file is assigned, New becomes Edit.
Setting up and executing a Code* variable
- First create a Code variable or create a Code - Time series variable.
- On the Code page or Code - Time Series page, specify:
- An Echoview Python source file containing the Python program for the operator, including an __init__ parameter corresponding to each argument configured on the Code or Code - Time Series page.
- Window size (pings), specifying the number of Operand 1 pings supplied during each iteration.
- Arguments, including their Name and Value settings.
- Configure any other settings on the Variable Properties dialog box or the Time Series Properties dialog box.
To execute a Code* variable, double-click its dataflow object. This executes the commands in its Echoview Python source file.
- For a Code variable, an echogram displays the result.
- For a Code - Time series variable, a graph displays the result.
While the echogram or graph for a Code* variable is open, Echoview re-executes the variable whenever you save changes to its Echoview Python source file.
Refer to error handling if you see a uniformly black echogram or empty graph.
Note: When browsing for a Python source file, the file selection dialog retains the previously specified filename to assist with file selection if the original path is no longer valid.
Inputting operands into the Code* operator
You can input multiple operands on the Operands page of the Code operator’s Variable Properties dialog box or the Code - Time series operator's Time Series Properties dialog box.
For both operators, Operand 1 must be acoustic. For the Code operator, it defines the output ping geometry and measurement times. For the Code - Time series operator, its ping times define the output measurement times.
- For the Code operator, Operands 2 and beyond must be acoustic or time series.
- For the Code - Time series operator, Operands 2 and beyond must be time series.
For acoustic operands, pings are matched in time as usual (see Using multiple operands). For time series operands, Echoview estimates a value for each ping in the Operand 1 window (interpolating or extrapolating according to the operand’s interpolation mode—linear, circular, or stepped). In the script, inputs[k].measurement is a TimeSeriesMeasurement (not a Ping), and inputs[k].window_measurements is a list of TimeSeriesMeasurement values – one per ping in the window.
Each operand of a Code* variable is an OperandInput object. Echoview passes the operands to the eval method in a Python list.
For example, in this extract
def eval(self, inputs: List[ev.OperandInput]): first_input = inputs[0] second_input = inputs[1] third_input = inputs[2] ... ...
Operand 1 is inputs[0], Operand 2 is inputs[1] and Operand 3 is inputs[2] in the Echoview Python source file.
Operands 2 and beyond may include time series variables, such as speed, heading, or GPS data. Echoview passes these to a Code* variable in the same way as acoustic operands, and their measurements can be accessed using the same attributes (measurement, window_measurements, etc.). For time series operands, the measurement is a TimeSeriesMeasurement object rather than a Ping object, but it has similar fields such as datetime, value, and status.
Arguments
Arguments allow multiple Code or Code - Time series variables to use the same Python source file with different parameter values. Echoview passes each configured argument as a named value to the Operator class’s __init__ method.
Each argument configured on the Code or Code - Time Series page must have a corresponding parameter in __init__. Echoview does not automatically add parameters to the Python source file.
Argument names
An argument name must:
- contain only letters, numbers, and underscores;
- not begin with a number;
- not contain spaces or punctuation, including commas;
- not be a Python reserved word; and
- contain fewer than 255 characters.
Arguments are matched to __init__ parameters by name, so the order of the parameters does not have to match the order displayed in Echoview.
Argument values
Enter a numeric value without spaces or a string enclosed in double quotation marks. The Python source file is responsible for interpreting and, where necessary, converting the value.
For examples of accepted values and how they are passed to Python, see the Arguments setting on the Code page.
Notes:
- If an argument configured in Echoview does not have a corresponding parameter in __init__, the script cannot run and Echoview reports an error.
- Parameters in __init__ may have default values. A default is used only when the corresponding argument is not configured in Echoview.
- A configured argument with a blank value is passed as an empty string. It overrides any default value declared for the corresponding __init__ parameter and may cause a type mismatch or an unexpected result.
Example
The Biomass density estimator can be modified to accept its M and Nv thresholds as configurable arguments. The following values could be entered on the Code page:
| Name | Value |
| m_threshold | 0.7 |
| nv_threshold | 0.04 |
The __init__ method receives and stores the values:
def __init__(self, m_threshold, nv_threshold): self.m_threshold = m_threshold self.nv_threshold = nv_threshold
The script can then use the stored values in its calculations:
return np.logical_and( nv < self.nv_threshold, M < self.m_threshold ).filled(False)
Processing pings with the Code* operator
This section describes acoustic (operand 1) ping processing. For time series operands, use the TimeSeriesMeasurement fields (datetime, value, status, etc.) referenced earlier.
A Code* operator iterates through the pings of Operand 1. Each ping in the Code operator is an object of the Ping class. The current Operand 1 ping is called the matched ping. It corresponds to the current output ping for a Code variable and determines the measurement time of the current output measurement for a Code - Time series variable.
(Note that for optimization reasons, a Code* operator may not process the pings in sequence.)
Selecting the matched ping
Use the measurement attribute of the OperandInput class to select the matched ping in the Echoview Python source file. For example,
def eval(self, inputs: List[ev.OperandInput]): first_input = inputs[0] matched_ping = first_input.measurement ... ...
Note that the measurement attribute in the above snippet provides a shorthand syntax to identify the matched ping in the window of measurements. An equivalent way to select the matched ping uses the window_measurements and window_index attributes of the OperandInput,
def eval(self, inputs: List[ev.OperandInput]): first_input = inputs[0] matched_ping = first_input.window_measurements[first_input.window_index] ... ...
The window_index attribute is especially useful to ensure you identify the sample data for the matched ping to return to Echoview (refer to the returning ping data to Echoview section below). Refer to the multibeam fish detection filter example for an illustration.
Using the window of measurements
The Window size (pings) setting allows you to read pings adjacent to the matched ping into the Code operator. Then use the window_measurements attribute of the OperandInput class to access all the pings in the window. For example,
def eval(self, inputs: List[ev.OperandInput]): first_input = inputs[0] first_input_window = first_input.window_measurements ... ...
Note that first_input_window in the above snippet is the window of measurements. It is a Python list.
While the matched ping is typically the item in the center of the window_measurements list, this rule does not apply at the ends of the input operand's echogram. Here, the window truncates as required to accommodate the deficiency in pings into the Code operator—meaning the matched ping is no longer in the center.
To obtain the value of the Window size (pings) setting use self.window_size.
Processing ping data or metadata
Each ping in the window of measurements is an object of the Ping class. The attributes of this class correspond to various aspects of a ping, such as the recorded
- ping sample data,
- start/stop range,
- heading, and more.
Refer to the list of attributes of the Ping class for a full list.
The (Python) data type of each attribute depends on the attribute itself. For example, the ping sample data are in a NumPy array, whereas the ping timestamp is a Python datetime object.
Ping sample data in the Code operator
This section presents some details on the data attribute of the Ping class, i.e., the sample data for the pings in the window of measurements.
The Code operator grants you access to modify and compute the ping samples of an echogram according to an algorithm of your design. To access the ping's samples, use the data attribute. For example, to obtain the ping samples for the matched ping
def eval(self, inputs: List[ev.OperandInput]): first_input = inputs[0] matched_ping = first_input.measurement matched_ping_data = matched_ping.data ... ...
The ping sample data—or matched_ping_data in the above example—is stored in a Python NumPy array, and corresponds to the sample value as a function of range.
While you can manipulate the array and its contents, you must return a NumPy array of the same shape as the input. For example,
return matched_ping_data[0]
will cause an error (assuming the ping has more than 1 sample), as the return statement is only communicating the first ping sample to Echoview.
Multibeam support
For multibeam data the data attribute is a 2D NumPy array.
The first axis corresponds to the sample value as a function of range, and the second axis is the sample value as a function of beam.
Single beam data derived from multibeam data points in the direction of the transducer.
Wideband support
The data_complex (refer to the Ping class) attribute exposes the underlying complex number ping samples for these wideband data types
- Complex power dB
- Complex Sv
- Complex TS
- Complex angular position
The complex values are underlying data from the wideband raw variables, prior to any processing (e.g., calculation of Sv and TS). However, note that the complex values have been pulse compressed for these wideband variables
- Pulse compressed complex power dB
- Pulse compressed complex Sv
- Pulse compressed complex TS
- Pulse compressed complex angular position
When returning complex values in eval, you must specify the result_type method (refer to OperatorBase) in your Echoview Python source file. Echoview converts the Code operator to the corresponding data type (as applicable). For more information, refer to the data type of the Code operator section below.
Applying calibration with the Code operator
Use the cal method of the Ping class to obtain the value of the calibration setting to use in your computations.
Refer to the biomass density estimator example for an illustration.
Returning Code ping data to Echoview
Use the return statement of the eval method to communicate the results from Python to Echoview via the Code operator. Refer to understanding the default Echoview Python source file for an example.
The results must be in a NumPy array of the same shape as the matched ping.
The data type of the Code operator
By default, the Code operator adopts the data type of Operand 1.
The data types of the input operands are objects of the MeasurementType class. Refer to the attributes and methods of this class (for the syntax to use in the Echoview Python source file) to query the data types of the operands into the Code operator, or to set the data type of the Code operator.
Use the result_type method in the Echoview Python source file to set the data type of the Code operator. You can also use TIME_SERIES_TYPES attributes and the is_time_series() method on MeasurementType to detect whether an input type represents a time series.
For example, to choose the data type of Operand 3, return the data type of the third element (index 2) in the input_types list.
def result_type(self, input_types): return input_types[2]
Or change the data type to single beam boolean, if you are returning an array of truth values
def result_type(self, input_types): return ev.MeasurementType.SINGLE_BEAM_BOOLEAN
Note that result_type does not perform any computations to convert the data values from one to another. For example, you cannot convert wideband complex values to pulse compressed by simply specifying a pulse compressed MeasurementType.
Returning Code - Time series data to Echoview
The result_type method specifies the output time series data type. When it specifies an Unspecified time series, it must also specify a TimeSeriesInterpolationMode.
The eval method returns the output measurement value together with its TimeSeriesStatus.
The default source file generated using New defines an Operator class derived from OperatorBase. It returns a Line measurement type. For each matched Operand 1 ping, it calculates the depth of the maximum sample and returns that depth with a status of GOOD.
class Operator(ev.OperatorBase): ... def result_type(self, inputs): return ev.MeasurementType.LINE ... def eval(self, inputs): ... return bottom_range, ev.TimeSeriesStatus.GOOD
For an Unspecified time series example, see the TimeSeriesInterpolationMode class. For a walkthrough of the generated source file, see Understanding the default Echoview Python source file: Code - Time series.
Importing Python packages
Echoview comes installed with the Echoview, NumPy and SciPy Python packages. It is mandatory to import the Echoview Python package in your Echoview Python source file.
import echoview as ev
You can also import the NumPy and SciPy packages,
import numpy as np import scipy
or any of the other packages from the Python Standard Library (https://docs.python.org/3/library/site.html). You can immediately import these in your Echoview Python source file.
If you wish to use other Python packages, you need to install them first.
Installing a package
Follow this procedure to install Python packages that are available from the Python Package Index (PyPI) using pip—the Python package installer.
- Installing pip for Echoview (needed only once for your version of Echoview M.m)
The following steps require Administrator privileges.
- Download and save https://bootstrap.pypa.io/get-pip.py into C:\Program Files\Echoview Software\Echoview M.m\Echoview\
- Open the Windows Command prompt as the administrator, and
- navigate to the Echoview Python interpreter location
cd C:\Program Files\Echoview Software\Echoview M.m\Echoview\
- install pip for the Echoview Python interpreter
python get-pip.py
You may receive a WARNING from the installer that the scripts pip*.exe are not on PATH. Ignore this, as the packages you install will be for Echoview only and not any external Python environment.
- navigate to the Echoview Python interpreter location
- Installing a Python package from PyPI
With the Windows Command prompt
- navigate to the Echoview Python interpreter location
cd C:\Program Files\Echoview Software\Echoview M.m\Echoview\
- set the destination to install the package
SET PYTHONUSERBASE=%LOCALAPPDATA%\Echoview Software\Echoview64\M.m\
- install PACKAGE with the Echoview Python interpreter via pip
python -m pip install --user PACKAGE
- navigate to the Echoview Python interpreter location
Using other packages with Echoview
Each time you want to use Echoview and other Python packages (other than those installed with Echoview), you need to specify a Windows Environment variable and then start Echoview.
Under the Windows Command prompt use:
cd C:\Program Files\Echoview Software\Echoview M.m\Echoview\
SET PYTHONUSERBASE=%LOCALAPPDATA%\Echoview Software\Echoview64\M.m\
Echoview.exe
Reloading an imported package or library
If you update a package or library, you may need to
- close and reopen the EV file,
- close and restart Echoview, or
- use reload
for the change to take effect for the Code* operator.
Error handling
The Code variable's echogram is displayed as black or a Code - Time series variable's graph is blank when:
- Echoview encounters an error with the Code variable or the Code - Time series variable
- there is an error in the Python source file
- the Echoview Python source file is either not specified or cannot be found
In these instances, an error message from Echoview or Python is sent to the Messages dialog box.
Notes:
- Changes to NumPy array and type behavior: NumPy 2.4.0 notes.
The changed behavior may affect scripts that handle both single beam and multibeam ping data.
Under NumPy 1.x, the following code works for both single beam and multibeam data. Under NumPy 2.x, it produces an error for single beam data because a sequence cannot be assigned to a scalar value.
ping_data[219] = np.copy(inputs[0].measurement.start_depth)
A workaround in NumPy 2.x that handles both single beam and multibeam data may look like this:
ping_data[219] = np.copy(inputs[0].measurement.start_depth)[0] if is_single_beam else np.copy(inputs[0].measurement.start_depth)
No data handling
The Code operator supports Echoview no data sample values using NumPy masked arrays or numpy.nan, as applicable.
For a Code - Time series variable, the eval method returns each measurement value together with its TimeSeriesStatus, which indicates the status of the returned measurement.
Performance considerations
Follow these guidelines to improve the speed of your Code* operator programs:
- Set Window size (pings) to the minimum that you need. This conserves the amount of data that will be loaded into memory.
- NumPy and SciPy (see Importing Python packages) contain highly optimized routines that can replace loops, conditional statements and mathematical operations.
Example Echoview Python source files
The following example Python source files serve to demonstrate some uses of the Code operator. These source files use the UTF-8 character encoding format.
You may need to configure the color scheme, grid, analysis and display settings and thresholds when viewing the Code variable echogram.
|
Echoview Python source file |
Description |
|
Generates a bitmap where all samples in pings from Operand 1 around (±1 hour) dawn and dusk are True. For use with single or multibeam data. |
|
|
This is a multifrequency categorization technique (see Jech and Michaels, 2006) for echosounder data analysis. It implements an algorithm that classifies the Sv responses that register above a threshold, from each frequency. For use with single beam data. |
|
|
Generates a mask, as a bitmap, that indicates if the biomass density is low enough to obtain reliable in situ TS values. This is accomplished by calculating the number of fish in the acoustic sampling volume (Nv, Sawada et al., 1993; see also Gauthier and Rose, 2001) and ratio of multiple echoes when measuring a single target (M) and then testing the resulting values against their respective threshold values (nv_threshold and m_threshold respectively). |
|
|
Calculates the normal deviate (Z-score) for walleye pollock (Theragra chalcogramma) as detailed in De Robertis et al. 2010 from three Sv inputs with the frequencies 38kHz, 120kHz, and 200kHz respectively. For use with single beam data. |
|
|
Demonstrates methods of diagnosing issues in your custom Code operator. For use with single beam data. |
|
|
Generates a bitmap that assists fish identification in multibeam echosounders (e.g., DIDSON or ARIS sonars). For use with multibeam data. |
|
|
Uses the Window Size property of the Code operator to smooth multibeam data in three dimensions. The smoothing is performed as a mean in the linear domain, using the Window size to define the number of samples in each dimension to include in the calculation. For use with multibeam data. |
See also
About the Code operators
About the Echoview Python source file
Code operator
Code - Time series operator
Code - Time Series page