Read binary files (.bdd) of DOP measurement devices.
The DOP measurement device series by Signal Processing implements the ultrasound Doppler velocimetry (UDV) measurement method to record velocity profiles in liquids. The measurement data can be saved in an ascii file (.ADD = ascii DOP data) or a binary file (.BDD = binary DOP data). While the ascii is human readable and relatively easy to import, it is generally larger than the binary format and does only contain the time, position and velocity information of the measurement. The binary format contains much more information (measurement parameters & settings) as well as having a more compact file-size. The downside is of course that the binary structure has to be decoded. The job of DOPpy is to read the binary data of a BDD-file and provide it for further analysis within a Python console or script.
Currently only files of the DOP2000 and DOP3000/3010 systems are supported. DOP4000 files are similar to the DOP3000 formats, but were not tested.
DOPpy was written in Python 3.6 but should be compatible with Python 2.7. Required modules are numpy
and matplotlib
.
Just copy the the DOPpy.py
file into the folder of your script or in any folder that is included in Python's PATH variable to access it from any script or a Python console.
This section is a quick overview of the features of DOPpy. For more information refer to the doc-strings of the respective functions.
Put the file DOPpy.py
somwhere Python can find it (e.g. the folder of your script or a folder listed in the PATH variable). Call the function DOP(fname)
from the module with the absolute or relative path to the BDD-file fname
. The function determines which version (DOP2000 or 3000) the file is and returns a DOP2000
or DOP3000
instance, respectively.
import DOP from DOPpy
bdd = DOP('path/to/file.bdd')
These classes have all available informations from the read file stored. They are subclasses of DOPBase
. Every parameter of the file can be retrieved either by using the method bdd.getParam(param)
or by treating the instance as a dictionary bdd[param]
, where param
is a string with the name of the parameter. All available parameters can be retrieved with the bdd.keys()
method. Since there can be a lot of parameters, a list of all parameters that contain a search string can be retrieved by calling bdd.keysSearch(searchterm)
. Channel-specific parameters are named with a prefix 'ch1_'
followed by the name (e.g. 'ch2_prf'
gives the pulse repetition frequency of channel 2). The available channel-specific parameter names can be retrieved with bdd.keysChannel(channel)
.
Additionally there are some predefined methods to retrieve often used data:
bdd.getChannels()
returns the list of channels that were used in the measurement.bdd.getProfileType(channel)
returns the profile types that where recorded in a channel.bdd.getTime(channel)
returns the timestamps of the channel in seconds.bdd.getDepth(channel)
returns the gate depths of the channel in millimeter.bdd.getVelocity(channel)
returns the measured velocity of the channel in meter per second as a 2D numpy-array. The first dimension is the time, the second dimension the depth.bdd.getEcho(channel)
returns the echo amplitude of the channel as a 2D numpy-array. The first dimension is the time, the second dimension the depth.bdd.getChannelParam(param, channel)
returns the value of the channel-specific parameter given inparam
of the channel (seebdd.keysChannel
).
For all these methods channel
can be an integer or a list of integers. In the latter case a list of values is returned. If channel
is omitted or set to None
, it defaults to all recorded channels (see bdd.getChannels
). These methods raise an error if the data is not available for at least one requested channel.
bdd.printSettings(channel)
prints relevant operation parameters that were used during the measurement with the given channel. The mandatory argumentchannel
is an integer.
While DOPpy is primarily designed to import the data into python a couple of functions for quick visualisation of the measured data are available:
DOPBase.imshow(profile, channel)
displays a color-plot of the profile with typeprofile
for the specified channel over time and depth. Seebdd.getChannels
andbdd.getProfileType
for available channels and their profile types, respectively.bdd.replay(profile, channel)
plots an animation of the profile-snapshots with typeprofile
for the specified channel over the depth. Seebdd.getChannels
andbdd.getProfileType
for available channels and their profile types, respectively.
For both methods channel
can be an integer or a list of integers. They raise an error if the data is not available for at least one requested channel.
- 2D/3D-component measurements are currently not supported.
- Very old DOP2000 file versions might not be read correctly. The script was tested with file version
'BINWDOPV4.06.1'
.
v2.13:
- Implements the new
DOPBase.imshow
method for visualisation of the measured profiles over time and depth. It is the preferred method overDOPBase.contour
to display data on an equidistant time and depth grid (faster, less memory intensive and no need for color levels). - Both
DOPBase.imshow
andDOPBase.contour
show the channel number as the axes title and the profile name (without units) as the colorbar label. - If no velocity or echo is recorded, the respective maximum value is now
set to NaN (channel parameters
'veloMax'
and'echoMax'
). This avoids KeyError messages due to a missing data entry (e.g. inDOPBase.PrintSettings
). - Improved error messages if a missing parameter is requested.
v2.12:
- The
DOPBase.printSettings
method now also prints parameters resulting from the operation parameters (maximum velocity and depth). A spelling error in the output was corrected.
v2.11:
- Corrected processing of the DOP3000
'aquisitionRate'
-parameter. - The methods
DOPBase._read
andDOPBase._refine
now raise an exception if they are called directly or are not redefined by a subclass. - Added the ability to replace parameter values from the file. See the
DOP
docstring for details.
v2.10:
- Optimized code for reading the BDD-files (for
DOP2000
andDOP3000
), which is now less memory intensive. This allows larger files to be read faster and with less possibility of anMemory Error
. The raw measurement data from the file are by default not saved any more. This behaviour can be changed by setting thesaveMeas
argument toTrue
in theDOP
-function. - Transformed certain parameters from their raw value to sensible ones used by the DOP-software. The raw parameter values are stored with an suffix
'_file'
to the parameter name. Examples: emitting power, TGC mode, sampling volume (DOP3000
only), spatial filter bandwidth, sensitivity. - Added the
DOPBase.printSettings
method to display important operation parameters used in the measurement. - Corrected axis labels in
DOPBase.contour
andDOPBase.replay
and fixed handling oftimerange
anddepthrange
arguments inDOPBase.contour
. - When decoding the comment string any character that does not fit the used codec is now ignored. This behaviour can be changed with the
decode_errors
keyword-argument for the functionDOP
.
v2.04:
- Corrected time-calculation for
DOP2000
.
v2.03:
- Imports true division from
__future__
to avoid incompatibilities for use with Python 2.7 when dividing by integers. - Corrected a typo in
keysChannel
.
v2.02:
- Fixed Doppler angle in velocity calculation of
DOP3000
and added Doppler angle in velocity calculation ofDOP2000
. - Added
DOPBase.removeAliasing
to remove aliasing effects for smooth velocity data. - Added the option to plot custom horizontal and vertical lines in the
DOPBase.replay
method (see the Keyword-Argument section in the method's documentation).
v2.01:
- Removed aliasing from echo-profile.
- Added
maxtimes
argument toDOPBase.contour
to avoid RAM overflow.
v2.00:
- Initial "release"