Master Project-ADCPTool
Master Project-ADCPTool
Master Project-ADCPTool
Reference Manual
Jakob Steidl
Clemens Dorfmann
Accoustic Doppler Current Profiler allows measuring discharges and velocities in fuids. However
the software used for prostprocessing this data is specialized for the area of initial usage of the
ADCP method.
This project aims to bypass this problem by creating a framework (you could also call it a Swiss
army knife) for postprocessing ADCP measuring data.
ii
Contents
1 Introduction to ADCPtool 1
1.1 What is it? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2.1 Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2.2 Installing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 How to use it . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
3 Program description 5
3.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.2 In-Depth Module Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.2.1 Initial Processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.2.2 Outlier Detection and Removal . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2.3 Velocity Averaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2.4 Roughness and Shear Stress Estimation . . . . . . . . . . . . . . . . . . . . . 11
3.2.5 Extrapolation of cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.2.6 Profile Visualisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.2.7 Export Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4 Tutorial 19
4.1 Required . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.1.1 Import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.1.2 Geo-Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.2 Optional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.2.1 Outlier Removal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.2.2 Averaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.2.3 Roughness and Shear Stress Estimation . . . . . . . . . . . . . . . . . . . . . 23
4.2.4 Velocity Extrapolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.3 Recommended . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.3.1 Profile Visualisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.3.2 Export in other Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.3.3 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
iii
1 Introduction to ADCPtool
ADCPtool is as piece of software to post process discharge data produced with an ADCP, written in
Python. It can read measurement files exported from WinRiver in ASCII format and represent the
data as a Python object. This Python object can then be processed and exported to other formats.
Currently the following features are available for postprocessing:
1.2.1 Requirements
1
It was tested with version 2.7.3 and 3.2.3
2
Tested with version 1.1.1 and 1.2.0
1
1.3 How to use it
Python and the extra modules should run on any Operating System. Users of other Operating
Systems than Windows should consult the corresponding manual on how to install Python and
Python packages4 .
Windows users new to Python could use a pre-packaged Python distribution, which includes all the
required software5 .
1.2.2 Installing
ADCPtool doesnt have a GUI (yet), nor is it a command line program which one has to pass dozens
of parameters to it. Instead it has to be imagined like a toolbox that can be used with Python.
To actually use ADCPtool one can either create a python script like in the tutorial in Chapter 4 or for
experimenting, run it from the interactive Python console.
3
Tested with 1.6.2 and 1.7.0-beta2
4
Its much easier actually than on Windows
5
A list of such distributions can be found on http://www.python.org/download/
The Acoustic Doppler Current Profiler is a device developed to measure currents in open waters. It
relies on the Doppler-Effect, which describes the change of wavelengths when waves are reflected
by a body with a relative velocity to the receiver:
∆v
∆f = f0
c
where
∆f observed frequency shift
∆v relative velocity between sender and reflector
f0 emitted frequency
c speed of wave propagation
If the emitter and the receiver are on the same location, the relative movement of objects reflecting
the waves can be determined.
With the assumption that all particles (reflecting objects) are moving in the same direction, one can
emit waves (beams) in three different directions to compute their three-dimensional movement in
space. Most ADCP devices use four beams to detect deviations and to allow a report of quality of
the measurement.
When further assuming a constant wave propagation velocity, the distance of the reflecting object
to the emitter can also be recorded by measuring the signal reflection time. This allows the ADCP
device to measure velocities in (almost) all depths. However there are limits for the time measuring
method, which is why the water column under the ADCP device is divided into cells (also bins).
A much deeper introduction can be found in “ADCP: Principles of Operation - A Practical Primer”
[5].
Profile
Profile is a virtual line over a river (or similar) spanning from reach to reach. It is where the ADCP
measurement boat ideally should cruise.
3
2.2 Conventions and Definitions
Ensemble
The ADCP continously takes measurements on different positions. All measurements on the same
position are summarized in one ensemble.
In practice the device can not measure infinitesimal areas, so cubic areas are summarized (aver-
aged, etc) into one cell.
Profile
Ensemble
Cell
3.1 Overview
ADCP TOOL is to be understood as a set of functions and objects written in Python that can be either
called from the interactive Python shell or from within a control file. The tool introduces two main
objects:
1. RawProfileObj: represents data in the raw form and in the same units as in the WinRiver
ASCII file.
2. ProcessedRawObj: represents the measurement data in a processed form.
A Note on Units
It should also be noted, that in the ProcessedRawObj all values are in the base SI-Units. This
includes values that are usually given in other units, like the bed roughness which is stored in [m]
instead of the more common [mm].
5
3.2 In-Depth Module Description
After the WinRiver ASCII file has been successfully imported, the data needs to be geo-referenced.
This includes the definition of a profile in global coordinates and how the measured data is positioned
on it.
Technically this is done by the following line of code:
profile_stage0 = adcpprocess.ProcessedProfileObj(raw_profile, processing_settings,
startingpoint)
While raw profile is self explaining, processing settings (it is a Python dictionary object) holds
configuration on how data is being converted. With startingpoint (also a Python dictionary) the
profile is being defined1 .
startingpoint
The profile can be imagined as virtual cross section of a river. To geo-reference it, the user can
define one of the following options:
In the first case the direction angle of the profile is taken from the first and last points of the measured
data.
The profile direction vector is computed like this:
xend −xstart
|xend −xstart | for options 1 and 3
prof iledir = " #
cos α
for option 2
sin α
offset
In case where the first ensemble is too far away from from the ideal profile line, this approach would
give a wrong direction angle. Therefore one can define an offset, which -for computing the direction
angle- corrects the position of the first ensemble. See Fig. 3.1(b).
processing settings
Besides other things (see Table 3.2), the configuration variables inside processing settings con-
trol how the ensembles are ”glued” on the profile discussed above.
1
One can also rename startingpoint to something that reflects its content more precise.
1
Y start
X
offset vector
(a) Profile defini- (b) Offset vector definition
tion
Projection Method
3 3'
3 3
2'
Y 2
2 2
1 1'
1 1
X
S S S
Algorithm Principle
The algorithm is based on analyzing the relative deviation of each velocity component in every cell.
For each velocity vi (ci ) component in each cell ci the following procedure is performing:
1. make a collection of neighbouring cells that are closer or equal the horizontal and vertical
distance of rh and rv , which should describe a rectangle of the shape (2rh + 1) × (2rv + 1).
4. if di is greater than the defined limit α, the velocity component ci is spotted as outlier
5. mark this velocity component as void in a separate matrix which will be used for replacing the
outliers with values interpolated from its neighbors.
It should be mentioned, that in preparation for this algorithm, the velocity data are extracted to a
NumPy array with the size m × n × 3 (m . . . number of ensembles, n . . . maximum number of cells
in an ensemble)for optimized processing time.
In a more sophisticated setup one could save computing time by reusing matrices that are required
for both outliers and data averaging. For that, the functions inside outliers.interpolate outliers()
are being called directly:
#
# outliers
import outliers, averaging, interpolation
# ProcessedCellObjs in a matrix
cm = outliers.get_cell_matrix(p)
# velocity components matrix, including a matrix that can be used to mask the first
one
vm, vgm = outliers.get_valuematrix_from_cellmatrix(cm, ’.velocity.v’)
# interpolation
from interpolation import interpolate
# interpolated velocity matrix (olm has to be "flipped" (0-->1, 1-->0))
ivm = interpolation.interpolate(vm, ~olm)
#
# averaging
vma = averaging.get_moving_average(ivm, vgm, dict(order=51))
Data averaging can be useful to reduce the effect of random measurement errors, eg. when results
shall be compared to numerical analysis.
Algorithm principle
Similar to the outlier detection the algorithm walks through every velocity component:
1. if current velocity component is marked in the velocity matrix mask: create matrix of neigh-
bors with width defined in config parameter order
2. compute average of values in created matrix
3. assign this average as value of current velocity
Simple Usage
Advanced Usage
To use this, it is first required to create a velocity matrix, like mentioned in Chap. 3.2.2. It is longer
to type, but saves a few seconds of life time.
import outliers
velocity_matrix, velocity_matrix_mask = outliers.get_valuematrix_from_cellmatrix(cm,
’.velocity.v’)
vma = averaging.get_moving_average(velocity_matrix, velocity_matrix_mask,
cfg_averaging)
profile.update_velocities(vma, velocity_matrix_mask)
The estimation of bed roughness ks , bed shear stress τ0 and shear velocities v0 is based on following
formula, which describes a logarithmic velocity distribution in open channels (see [4]):
v(z) 1 z
∗
= ln
v κ z0
where
v(z) velocity
z depth of channel starting from river bed
1
z0 depth of channel where v = 0; for hydraulically rough flows: z0 = 30 ks
v∗ shear velocity
κ VON K ÁRM ÁN constant: 0.40
ks bed roughness
With this formula and the measured velocities (magnitude of x and y component) the unknowns ks ,
v ∗ can be determined via the method of least squares.
v(z) 1
∗
= (ln z − ln z0 )
v κ
κ
ln z = ∗ v + ln z0
v
To finally get a least square solution, the N UM P Y function linalg.lstsq() is used. It returns a, b
of the equation y = ax + b. With these, the unknowns ks , v ∗ can be determined:
κ
v∗ =
b
ks = 30ea
τ0 = v ∗ 2 ρwater
Usage
In order to fill the gaps in be unmeasured areas below water surface and above river bed, extrapo-
lation methods are being used. While this can not produce any new or additional information about
the unmeasured zone, extrapolation can be useful when estimating total discharge.
Usage
Extrapolation Algorithms
y z+
The algorithm used for the area near water surface (referred as free surface
d
“zone T”) can be described as follows: y2 T
z-
topcells
1. take the topcells topmost cells and fit a linear function in it.
2. use this function to create additional velocity components
Is done for each velocity component seperatly.
0.2 * d
For the area near river bed, a number of different methods, depend- y1
B
ing on available data is being used (See Figure 3.4). v
The simplest one makes use of ks and v∗. If a log law velocity
Figure 3.3: Variables within ve-
distribution is assumed.
locity extrapolation
30
1. compute velocity magnitude with v = v ∗ · 2.5 · ln
ks (d + z)
While a could also be derived from bed roughness and shear stress, it isn’t necessary for extrapo-
lation.
Similar to WinRiver [6], ADCPtool first tries to find cells at 0.2 · d to determine a with:
v(0.2 · d)
a=
yb
Otherwise a will be determined by equalizing the measured discharge with the discharge in the
measured area using the power law velocity distribution:
X
QADCP = vi · di
i
y2
y2b+1 − y1b+1
Z
QP L = ay b dy = a
y1 b+1
QP L = QADCP
P
vi · di
i
a= b+1
y2 − y1b+1
b+1
It is worth mentioning, that this algorithm also works on the magnitude velocities, which require to
be split up into its components.
power law
linear & log-law
cells above no
0.2 * d?
linear extrapolation
Start in zone T
yes
get v (0.2d)
M
determine "a" that
through interpolation Q =Q
PL M
no ensemble has
valid cells?
ensmble has no
roughness data?
yes determine parameter no
"a" that forcepowerlaw == True?
v (0.2d) = v (0.2d)
yes
PL M
yes yes
forcepowerlaw == True?
For a quick visual feedback profile data can be plotted. For this two functions in the module quickviz
exist:
plot profile 2d(p, cfg) plot the plan view of the profile including depth averaged velocities
plot profile 3d(p, cfg) plot a cross section view trough the profile showing data specified inside
cfg (See Table 3.8)
The second function provides a few features that require explanation:
Virtually any data inside an ProcessedCellObj can be displayed. (See the datatype variable in
Table 3.8). If “custom” is provided, then cellattr has to be filled with the cell attributes (including
the dot at the beginning) to be plotted. See Section 4.2 for examples.
If more than one data is being selected, it is possible to display it as a vector field2 . If two or more
attributes are selected and a display style other than “vector” is used, the “length” of the attributes
will be displayed: qX
a= a2i
2
Please note: If it is desired to plot secondary currents, it is strongly recommended to use the uv rot option when
creating the ProcessedProfileObj
For passing on the data to other software, the following export functions are available:
The names should be mostly self explaining. Only some parts of the names need explanation:
2D will export data (usually depth averaged velocities) stored directly in the ensemble
3D will export data stored directly in the cells
BlueKenue Output for BlueKenueTM [2]
Paraview Output for ParaView [1]
DXF famous CAD drawing exchange file format
where
profile the ProcessedProfileObj to be exported
f the output file
format a format string. See Sec. 3.2.7
vel scale a scaling value for displaying velocities.
If 1, a velocity of 1[m/s] will be drawn with the length of 1
f depth4Beams filename for storing all beams
f depth4Beam1-4 filename for storing beam 1-4
The functions writeAscii2D() and writeAscii3D() allow the user to define which information is
being written and how it is formatted.
They will be called with:
# for ensemble data
writeAscii2D(profile, formatstring, f, header)
where
profile is the ProcessedProfileObj to be exported
formatstrting Python format string for the print() function
f output file name
h string as file header, optional
As one might expect, the definition of the format can be defined in formatstrting, which itself will
be parsed by Python’s .format() method 3 .
Essentially, a format string contains the variables to be printe d in curly brackets surrounded by white
space:
formatstrting = "{vx}, {vy}, {vz}"
The a list of available variables can be found in Table 3.10. Usage examples can be found in Section
4.3.2
3
See http://docs.python.org/2/tutorial/inputoutput.html#fancier-output-formatting and http://docs.
python.org/2/library/string.html#formatspec
Variable 2D 3D Description
x • • X coordinate of cell or ensemble
y • • Y coordinate of cell or ensemble
z • • Z coordinate of cell or ensemble
vx • • x component of velocity
vy • • y component of velocity
vz • • z component of velocity
vmag • • magnitude of x and y components of velocity
vmag3d • • magnitude of all components of velocity
artificial ◦ • True, if this is an extrapolated cell
ks ◦ • bed roughness
tau shear ◦ • bed shear stress
v shear ◦ • shear velocity
depth • ◦ averaged depth reading of ensemble
four depths 1 • ◦ depth reading of beam 1 for ensemble
four depths 2 • ◦ depth reading of beam 2 for ensemble
four depths 3 • ◦ depth reading of beam 3 for ensemble
four depths 4 • ◦ depth reading of beam 4 for ensemble
In this tutorial, we will demonstrate all features of ADCP TOOL. We will be using the P YTHON inter-
active shell, because it is the easiest way to play with the ADCP data1 . Of course it is also possible
to start the commands from a Python script file. See also missioncontrol.py or mc advanced.py
for examples.
Since ADCPtool isn’t installed inside the Python directory, we can’t start it directly. So we either
have to
• add the directory where ADCP TOOL is installed to the Python path, or
• start the Python shell in the corresponding directory.
For Windows users the easiest way is probably to open the folder in Explorer, and then with
[shift]+[right mouse button] an extended context menu appears, where we can select “Open com-
mand window here”, which should open up cmd.exe, the windows command line. In that window,
the Python shell can finally be started with typing: python.
In order to have access to all the modules provided by ADCP TOOL it is recommended to import
(load) them with the adcploader script:
>>> from adcploader import *
>>>
Something that applies for everything from now on: If there is no text output, everything worked
fine.
1
We will use Windows as operating system. If you are running a different OS, then you are probably capable of opening
a python shell on your own anyway.
19
4.1 Required
4.1 Required
4.1.1 Import
The basis for every processing is to convert the original WinRiver ASCII file into a Python object
with:
>>> p_raw = RawProfileObj(’../testfiles/demodata.txt’)
4.1.2 Geo-Mapping
Geo-Mapping is required per definition, because the ensembles need to have some coordinates
later on. But since we don’t want have any reference coordinates, and don’t care about profile
projection we use the following settings:
>>> startingpoint = dict(start=Vector(0,0,0))
>>> processing_settings = dict(proj_method=3)
See Fig. 4.2 for how the output can look like. If you want to save the graphic, either use the floppy
symbol found in the window. Or if you want to save the graphic without displaying it, specify that in
the cfg:
The following should give two profiles, both pointing upwards and the second with less ensembles
remaining. However, comparing with the output in Fig. 4.3 the second, (b) the profile is pointing
downwards! This can be explained by how the projection method 3 works.2
700 0
600 100
500 200
y coordinate [m]
y coordinate [m]
400 300
300 400
200 500
100 600
0 velocity: 0.001 [m/s] 700 velocity: 0.001 [m/s]
100 400 200 0 200 400 800 400 200 0 200 400
x coordinate [m] x coordinate [m]
Figure 4.3: Demonstration of thin out() and different projection methods and profile definitions
For comparison with the following steps, we also want to take a look at the velocities:
2
As seen in Fig. 4.2 the measurement boat actually moved downwards, so the ensembles will be projected on the
”negative” end of the profile, which is defined by a starting point, but however internally it is extending infinite in both
directions
0 section view
0.36
1
0.32
2 0.28
profile depth [m]
3 0.24
4 0.20
0.16
5
0.12
6
0.08
7 0.04
80 100 200 300 400 500 600 700
profile station [m]
4.2 Optional
0 section view
0.32
1
0.28
2
0.24
profile depth [m]
3
0.20
4 0.16
5 0.12
6 0.08
7 0.04
80 100 200 300 400 500 600 700
profile station [m]
4.2.2 Averaging
0 section view
0.225
1
0.200
2
0.175
profile depth [m]
3 0.150
4 0.125
5 0.100
6 0.075
7 0.050
0.025
80 100 200 300 400 500 600 700
profile station [m]
This topic is a bit tricky, because the results heavily depend on the input data, which require mea-
surements below 0.2 · depth, which is not always the case. In order to give judge the quality of the
output data, we need to introduce a previously undocumented function: plot logfit profile()
which can be found inside quickviz.py.
Starting the roughness estimation is easy however:
>>> cfg_logfit = {’logheight’:0.30, ’component’:3}
>>> p4 = logfit_profile(p3, cfg_logfit)
>>> plot_logfit_profile(p4, cfg=cfg_logfit)
The result of plot logfit profile can be seen in Fig. 4.7. It is left to the user, if they trust these
results.
0
depth
1 # of cells used
existing cell
depth [m], # of used cells
3
4
5
6
7
80 100 200 300 400 500
100 800
ks
700 tau_shear
80 600
tau_shear [N/m^2]
500
60
400
ks [m]
300
40
200
20 100
0
00 100 200 300 400 500 100
1.2
1.0
correlation coefficient
0.8
0.6
0.4
0.2
0.0
0.20 100 200 300 400 500
Note that in this example, we used forepowerlaw=True, because the roughness values were not
realistic and matplotlib would run into numerical problems.
0 section view
0.225
1
0.200
2 0.175
profile depth [m]
3 0.150
4 0.125
0.100
5
0.075
6
0.050
7 0.025
80 100 200 300 400 500 600 700 0.000
profile station [m]
4.3 Recommended
plot profile 3d
So far we have only seen one way to visualize profile data. Now lets see the others:
>>> plot_profile_3d(p3, cfg=dict(style=’contour’, saveas=’../testfiles/tut_demo6a.pdf
’, title=’contour demo’))
When trying to plot secondary flows it is recommended to make sure the y-axis for velocities is
aligned parallel to the profile. For optical reasons, one would probably want to thin out the data a
bit:
It should also be noted, that the demo measuremend data are not really suited, to demonstrate this
effect, but it was demonstrated how it could work.
0 vector demo
1
2
profile depth [m]
3
4
5
6
7
80 100 200 300 400 500 600 700
profile station [m]
The different output formats have already been discussed in Sec. 3.2.7 and they are pretty similar,
so we just want to demonstrate it for DXF and custom ASCII output.
DXF Output
In a first example, we want to export the cell coordinates and their velocity components.
>>> writeAscii3D(p5, ’{x} {y} {z} {vx} {vy} {vz}’, ’../testfiles/tut_demo8_velocities
.txt’)
...
0.0 0.0 -3.44 0.0487707013245 0.00411604185165 -0.00629261246467
-0.0352388493007 0.138668689947 -0.19 0.0809096270561 -0.00156761831666 -0.011711294767
-0.0352388493007 0.138668689947 -0.44 0.0798823693507 -0.00154771527109 -0.0115626039594
-0.0352388493007 0.138668689947 -0.69 0.0787844753962 -0.00152644365317 -0.0114036888811
...
Therefore we use the specify the space each argument is allowed to fill and the number of decimals:
>>> import datetime
>>> header=’# generated on: {} \n# x y z v_x v_y v_z \n’.format(datetime.datetime.now
().strftime(’%x %X’))
>>> writeAscii3D(p5, ’{x:6.2f} {y:6.2f} {z:6.2f} {vx:9.2e} {vy:9.2e} {vz:9.2e}’, ’../
testfiles/tut_demo8_velocities_awesome.txt’, header=header)
The roughness values are now ready for further processing in other programs. Note that values of −999 are
invalid values. This was set with voidtext=-999.
4.3.3 Conclusion
This chapter has provided everything needed to use ADCPtool. For developing and testing own scripts, it
is recommended to comment out the plot functions, as they consume a significant amount of time. Also
Pythons pickel module is a good alternative way to re-compute data every run by storing temporary results
(all Python objects, variables) on hard disk.
27
List of Figures
3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2 Available projection methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.3 Variables within velocity extrapolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.4 Flow chart for extrapolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
28
List of Tables
29