author | A.M. Thurnherr <athurnherr@yahoo.com> |
Tue, 06 Dec 2022 12:36:04 -0500 | |
changeset 62 | 9e13aca980c7 |
parent 60 | 890e267a2d98 |
permissions | -rw-r--r-- |
0 | 1 |
#====================================================================== |
2 |
# R D I _ U T I L S . P L |
|
3 |
# doc: Wed Feb 12 10:21:32 2003 |
|
60
890e267a2d98
bug fix for data file with errors
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
52
diff
changeset
|
4 |
# dlm: Fri Jul 1 16:27:05 2022 |
0 | 5 |
# (c) 2003 A.M. Thurnherr |
60
890e267a2d98
bug fix for data file with errors
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
52
diff
changeset
|
6 |
# uE-Info: 69 70 NIL 0 0 72 0 2 4 NIL ofnI |
0 | 7 |
#====================================================================== |
8 |
||
9 |
# miscellaneous RDI-specific utilities |
|
10 |
||
11 |
# History: |
|
12 |
# Feb 12, 2003: - created |
|
13 |
# Feb 14, 2003: - added check for short (bad) data files |
|
14 |
# Feb 26, 2004: - added Earth-coordinate support |
|
15 |
# - added ensure_BT_RANGE() |
|
16 |
# Mar 17, 2004: - set bad BT ranges to undef in ensure_BT_RANGE |
|
17 |
# - calc mean/stddev in ensure_BT_RANGE |
|
18 |
# Mar 20, 2004: - BUG: find_seabed() could bomb when not enough |
|
19 |
# bottom guesses passed the mode_width test |
|
20 |
# Mar 30, 2004: - added &soundSpeed() |
|
21 |
# Nov 8, 2005: - WATER_DEPTH => Z_BT |
|
22 |
# Dec 1, 2005: - renamed to RDI_Utils.pl |
|
23 |
# - folded in mk_prof from [mkProfile] |
|
24 |
# Nov 30, 2007: - adapted ref_lr_w() to 3-beam solutions |
|
25 |
# Feb 1, 2008: - added comment |
|
26 |
# Feb 22, 2008: - added ssCorr() |
|
27 |
# Apr 9, 2008: - BUG: duplicate line of code (without effect) in find_seabed() |
|
28 |
# - BUG: seabed < max depth was possible |
|
29 |
# Jan 2010: - fiddled with seabed detection params (no conclusion) |
|
30 |
# May 23, 2010: - renamed Z to DEPTH |
|
2
065ea9ce12fc
before DIMES UK2 cruise
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
0
diff
changeset
|
31 |
# Sep 27, 2010: - made sure coord flags are changed correctly when data |
065ea9ce12fc
before DIMES UK2 cruise
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
0
diff
changeset
|
32 |
# are transferred to earth coords in mk_prof |
065ea9ce12fc
before DIMES UK2 cruise
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
0
diff
changeset
|
33 |
# Sep 29, 2010: - BUG: previous change was wrong, as ref_lr_w does |
065ea9ce12fc
before DIMES UK2 cruise
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
0
diff
changeset
|
34 |
# not overwrite velocities |
3 | 35 |
# Oct 20, 2010: - BUG: w is now not integrated any more across gaps longer than 5s |
36 |
# Dec 8, 2010: - changed missing w warning to happen only if gap is longer than 15s |
|
37 |
# Dec 10, 2010: - beautified gap warning |
|
5 | 38 |
# Dec 16, 2010: - BUG: gaps at end caused mk_prof to throw away profile |
6 | 39 |
# May 12, 2011: - added code to skip ensembles with built-in-test errors in mk_prof() |
40 |
# - immediately disabled this code becasue it does appear to make matters worse |
|
8 | 41 |
# Sep 21, 2011: - added calculation of RMS heave acceleration |
10 | 42 |
# Mar 27, 2013: - BUG: 3-beam solutions were not used in ref_lr_w |
43 |
# - disabled apparently unused code |
|
11 | 44 |
# Apr 12, 2013: - added $min_pctg as optional parameter to mk_prof |
12 | 45 |
# May 14, 2013: - added incident-velocity, w12 & w34 to mkProfile |
46 |
# Jun 5, 2013: - BUG: incident-flow warning was printed repeatedly |
|
47 |
# Jun 20, 2013: - BUG: warning had used &antsInfo() |
|
14 | 48 |
# Feb 13, 2014: - replaced {DEPTH_BT} by {seabed} |
49 |
# - added set_range_lim() |
|
17
591779f6df30
changed mkProfile gap heuristics & removed warning
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
14
diff
changeset
|
50 |
# Feb 22, 2014: - changed gap heuristic |
591779f6df30
changed mkProfile gap heuristics & removed warning
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
14
diff
changeset
|
51 |
# - Earth coord beam-pair warning removed |
19
e23a5fd2923a
after adapting RDI_Coords to calc w even without valid heading
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
17
diff
changeset
|
52 |
# May 29, 2014: - removed unused code (disabled warning) from ref_lr_w |
23
fb0c269b1eaa
V1.2 release candidate
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
19
diff
changeset
|
53 |
# Mar 22, 2015: - BUG: mk_prof could bomb because of division-by-zero in return statement |
31 | 54 |
# Jan 9, 2016: - renamed ref_lr_w to mk_prof_ref_lr_w because the old name conflicts |
55 |
# with a sub in LADCP_w |
|
34 | 56 |
# May 19, 2016: - adapted to new velBeamToInstrument() usage |
39 | 57 |
# Aug 7, 2017: - added abmiguity velocity |
58 |
# Aug 8, 2017: - changed transducer frequency to kHz |
|
41 | 59 |
# Nov 27, 2017: - BUG: profile-restart heuristic did not work with P6#001 |
43
b63fa355644c
commit to merge with changes from EN620
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
41
diff
changeset
|
60 |
# Mar 18, 2018: - added -ve dt consistency check |
b63fa355644c
commit to merge with changes from EN620
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
41
diff
changeset
|
61 |
# Jun 9, 2018: - added support for ENV{NO_GAP_WARNINGS} |
48
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
62 |
# Jun 16, 2019: - adapted (partiall) to support RTI ADCPs: |
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
63 |
# - made ambiguity_velocity() return nan (missing TL_distance) |
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
64 |
# - skip missing velocities in reference-layer calculation |
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
65 |
# - disable %-good screening with $min_pctg == 0 |
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
66 |
# Jun 26, 2019: - increased short-gap in mk_prof from 5s to 6s to allow processing |
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
67 |
# of RTi test file with 5s ensembles |
52
5b07a9b89aee
- adapted to work with IMPed moored ADCP data
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
49
diff
changeset
|
68 |
# Apr 13, 2020: - added $RDI_Utils::No_Gap_Warnings |
60
890e267a2d98
bug fix for data file with errors
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
52
diff
changeset
|
69 |
# Jul 1, 2020: - replaced PANIC on dt<0 with ensemble-skipping code |
0 | 70 |
|
71 |
use strict; |
|
72 |
||
52
5b07a9b89aee
- adapted to work with IMPed moored ADCP data
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
49
diff
changeset
|
73 |
$RDI_Utils::No_Gap_Warnings = 0; # set to 1 to suppress gap warnings |
5b07a9b89aee
- adapted to work with IMPed moored ADCP data
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
49
diff
changeset
|
74 |
|
0 | 75 |
#====================================================================== |
76 |
# fake_BT_RANGE(dta ptr) |
|
77 |
#====================================================================== |
|
78 |
||
79 |
# During cruise NBP0204 it was found that one of Visbeck's RDIs consistently |
|
80 |
# returns zero as the bottom-track range, even thought the BT velocities |
|
81 |
# are good. This functions calculates the ranges if they are missing. |
|
82 |
||
83 |
sub cBTR($$$) |
|
84 |
{ |
|
85 |
my($d,$e,$b) = @_; |
|
86 |
my($maxamp) = -9e99; |
|
87 |
my($maxi); |
|
88 |
||
89 |
for (my($i)=0; $i<$d->{N_BINS}; $i++) { |
|
90 |
next unless ($d->{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$i][$b] > $maxamp); |
|
91 |
$maxamp = $d->{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$i][$b]; |
|
92 |
$maxi = $i; |
|
93 |
} |
|
94 |
$d->{ENSEMBLE}[$e]->{BT_RANGE}[$b] = |
|
95 |
$d->{DISTANCE_TO_BIN1_CENTER} + $maxi * $d->{BIN_LENGTH}; |
|
96 |
} |
|
97 |
||
98 |
sub ensure_BT_RANGE($) |
|
99 |
{ |
|
100 |
my($d) = @_; |
|
101 |
for (my($e)=0; $e<=$#{$d->{ENSEMBLE}}; $e++) { |
|
102 |
my($sum) = my($n) = 0; |
|
103 |
if (defined($d->{ENSEMBLE}[$e]->{BT_VELOCITY}[0])) { |
|
104 |
for (my($b)=0; $b<4; $b++) { |
|
105 |
cBTR($d,$e,$b) |
|
106 |
unless defined($d->{ENSEMBLE}[$e]->{BT_RANGE}[$b]); |
|
107 |
$sum += $d->{ENSEMBLE}[$e]->{BT_RANGE}[$b]; $n++; |
|
108 |
} |
|
109 |
} else { |
|
110 |
for (my($b)=0; $b<4; $b++) { |
|
111 |
$d->{ENSEMBLE}[$e]->{BT_RANGE}[$b] = undef; |
|
112 |
} |
|
113 |
} |
|
114 |
$d->{ENSEMBLE}[$e]->{BT_MEAN_RANGE} = $sum/$n if ($n == 4); |
|
115 |
} |
|
116 |
} |
|
117 |
||
118 |
#====================================================================== |
|
119 |
# (seabed depth, stddev) = find_seabed(dta ptr, btm ensno, coord flag) |
|
120 |
#====================================================================== |
|
121 |
||
122 |
# NOTE FOR YOYOS: |
|
123 |
# - this routine only detects the BT around the depeest depth! |
|
124 |
# - this is on purpose, because it is used for [listBT] |
|
125 |
||
126 |
# This is a PAIN: |
|
127 |
# if the instrument is too close to the bottom, the BT_RANGE |
|
128 |
# readings are all out; the only solution is to have a sufficiently |
|
129 |
# large search width (around the max(depth) ensemble) so that |
|
130 |
# a part of the up (oops, I forgot to finish this comment one year |
|
131 |
# ago during A0304 and now I don't understand it any more :-) |
|
132 |
||
133 |
my($search_width) = 200; # # of ensembles around bottom to search |
|
134 |
my($mode_width) = 10; # max range of bottom around mode |
|
135 |
my($min_dist) = 20; # min dist to seabed for good data |
|
136 |
my($z_offset) = 10000; # shift z to ensure +ve array indices |
|
137 |
||
138 |
sub find_seabed($$$) |
|
139 |
{ |
|
140 |
my($d,$be,$beamCoords) = @_; |
|
141 |
my($i,$dd,$sd,$nd); |
|
142 |
my(@guesses); |
|
143 |
||
144 |
return undef unless ($be-$search_width >= 0 && |
|
145 |
$be+$search_width <= $#{$d->{ENSEMBLE}}); |
|
146 |
for ($i=$be-$search_width; $i<=$be+$search_width; $i++) { |
|
147 |
next unless (defined($d->{ENSEMBLE}[$i]->{DEPTH}) && |
|
148 |
defined($d->{ENSEMBLE}[$i]->{BT_RANGE}[0]) && |
|
149 |
defined($d->{ENSEMBLE}[$i]->{BT_RANGE}[1]) && |
|
150 |
defined($d->{ENSEMBLE}[$i]->{BT_RANGE}[2]) && |
|
151 |
defined($d->{ENSEMBLE}[$i]->{BT_RANGE}[3])); |
|
34 | 152 |
my(@BT) = $beamCoords ? velBeamToEarth($d,$i,@{$d->{ENSEMBLE}[$i]->{BT_VELOCITY}}) |
153 |
: velApplyHdgBias($d,$i,@{$d->{ENSEMBLE}[$i]->{BT_VELOCITY}}); |
|
0 | 154 |
next unless (abs($BT[3]) < 0.05); |
14 | 155 |
$d->{ENSEMBLE}[$i]->{seabed} = |
0 | 156 |
$d->{ENSEMBLE}[$i]->{BT_RANGE}[0]/4 + |
157 |
$d->{ENSEMBLE}[$i]->{BT_RANGE}[1]/4 + |
|
158 |
$d->{ENSEMBLE}[$i]->{BT_RANGE}[2]/4 + |
|
159 |
$d->{ENSEMBLE}[$i]->{BT_RANGE}[3]/4; |
|
14 | 160 |
next |
161 |
unless ($d->{ENSEMBLE}[$i]->{seabed} >= $min_dist); |
|
162 |
$d->{ENSEMBLE}[$i]->{seabed} *= -1 |
|
0 | 163 |
if ($d->{ENSEMBLE}[$i]->{XDUCER_FACING_UP}); |
14 | 164 |
$d->{ENSEMBLE}[$i]->{seabed} += $d->{ENSEMBLE}[$i]->{DEPTH}; |
165 |
if ($d->{ENSEMBLE}[$i]->{seabed} > $d->{ENSEMBLE}[$be]->{DEPTH}) { |
|
166 |
$guesses[int($d->{ENSEMBLE}[$i]->{seabed})+$z_offset]++; |
|
0 | 167 |
$nd++; |
168 |
} else { |
|
14 | 169 |
undef($d->{ENSEMBLE}[$i]->{seabed}); |
0 | 170 |
} |
171 |
} |
|
172 |
return undef unless ($nd>5); |
|
173 |
||
174 |
my($mode,$nmax); |
|
175 |
for ($i=0; $i<=$#guesses; $i++) { # find mode |
|
14 | 176 |
$nmax=$guesses[$i],$mode=$i-$z_offset |
0 | 177 |
if ($guesses[$i] > $nmax); |
178 |
} |
|
179 |
||
180 |
$nd = 0; |
|
181 |
for ($i=$be-$search_width; $i<=$be+$search_width; $i++) { |
|
14 | 182 |
next unless defined($d->{ENSEMBLE}[$i]->{seabed}); |
183 |
if (abs($d->{ENSEMBLE}[$i]->{seabed}-$mode) <= $mode_width) { |
|
184 |
$dd += $d->{ENSEMBLE}[$i]->{seabed}; |
|
0 | 185 |
$nd++; |
186 |
} else { |
|
14 | 187 |
$d->{ENSEMBLE}[$i]->{seabed} = undef; |
0 | 188 |
} |
189 |
} |
|
190 |
return undef unless ($nd >= 2); |
|
191 |
||
192 |
$dd /= $nd; |
|
193 |
for ($i=$be-$search_width; $i<=$be+$search_width; $i++) { |
|
14 | 194 |
next unless defined($d->{ENSEMBLE}[$i]->{seabed}); |
195 |
$sd += ($d->{ENSEMBLE}[$i]->{seabed}-$dd)**2; |
|
0 | 196 |
} |
197 |
||
198 |
return ($dd, sqrt($sd/($nd-1))); |
|
199 |
} |
|
200 |
||
14 | 201 |
#---------------------------------------------------------------------- |
202 |
# set_range_lim(d) |
|
203 |
# - set field range_lim |
|
204 |
#---------------------------------------------------------------------- |
|
205 |
||
206 |
sub set_range_lim($) |
|
207 |
{ |
|
208 |
my($d) = @_; |
|
209 |
||
210 |
for (my($e)=0; $e<=$#{$d->{ENSEMBLE}}; $e++) { |
|
211 |
my($lastGood) = 1; my($b); |
|
212 |
for ($b=0; $b<$d->{N_BINS}; $b++) { |
|
213 |
if (defined($d->{ENSEMBLE}[$e]->{VELOCITY}[$b][0]) && |
|
214 |
defined($d->{ENSEMBLE}[$e]->{VELOCITY}[$b][1]) && |
|
215 |
defined($d->{ENSEMBLE}[$e]->{VELOCITY}[$b][2]) && |
|
216 |
defined($d->{ENSEMBLE}[$e]->{VELOCITY}[$b][3])) { |
|
217 |
$lastGood = 1; |
|
218 |
} elsif ($lastGood) { |
|
219 |
$lastGood = 0; |
|
220 |
} else { |
|
221 |
last; |
|
222 |
} |
|
223 |
} |
|
224 |
||
225 |
next unless ($b>=2) && defined($d->{ENSEMBLE}[$e]->{DEPTH}); |
|
226 |
$d->{ENSEMBLE}[$e]->{range_lim} = |
|
227 |
$d->{DISTANCE_TO_BIN1_CENTER} + ($b-2) * $d->{BIN_LENGTH}; |
|
228 |
$d->{ENSEMBLE}[$e]->{range_lim} *= -1 |
|
229 |
if ($d->{ENSEMBLE}[$e]->{XDUCER_FACING_UP}); |
|
230 |
$d->{ENSEMBLE}[$e]->{range_lim} += $d->{ENSEMBLE}[$e]->{DEPTH}; |
|
231 |
} |
|
232 |
} |
|
233 |
||
0 | 234 |
#====================================================================== |
235 |
# c = soundSpeed($salin,$temp,$depth) |
|
236 |
#====================================================================== |
|
237 |
||
238 |
# Taken from the RDI BroadBand primer manual. The reference given there |
|
239 |
# is Urick (1983). |
|
240 |
||
241 |
sub soundSpeed($$$) |
|
242 |
{ |
|
243 |
my($salin,$temp,$depth) = @_; |
|
244 |
die("ERROR: soundSpeed($salin,$temp,$depth): non-numeric parameter\n") |
|
245 |
unless numberp($salin) && numberp($temp) && numberp($depth); |
|
246 |
return 1449.2 + 4.6*$temp -0.055*$temp**2 + 0.00029*$temp**3 + |
|
247 |
(1.34 - 0.01*$temp) * ($salin - 35) + 0.016*$depth; |
|
248 |
} |
|
249 |
||
250 |
#====================================================================== |
|
251 |
# fac = ssCorr($eRef,$salin,$temp,$depth) |
|
252 |
# $eRef : reference to current ensemble |
|
253 |
# $salin: * -> use instrument salinity |
|
254 |
# $temp : * -> use instrument temperature |
|
255 |
# $depth: * -> use instrument PRESSURE(!) |
|
256 |
#====================================================================== |
|
257 |
||
258 |
{ my($warned); |
|
259 |
sub ssCorr($$$$) |
|
260 |
{ |
|
261 |
my($eRef,$S,$T,$D) = @_; |
|
262 |
$S = $eRef->{SALINITY} if ($S eq '*'); |
|
263 |
$T = $eRef->{TEMPERATURE} if ($T eq '*'); |
|
264 |
if ($D eq '*') { |
|
265 |
print(STDERR "WARNING: soundspeed correction using instrument pressure instead of depth!\n") |
|
266 |
unless ($warned); |
|
267 |
$warned = 1; |
|
268 |
$D = $eRef->{PRESSURE}; |
|
269 |
} |
|
270 |
return soundSpeed($S,$T,$D) / $eRef->{SPEED_OF_SOUND}; |
|
271 |
} |
|
272 |
} |
|
39 | 273 |
|
274 |
#====================================================================== |
|
275 |
# ambiguity_velocity(transducer_freq,beam_angle,sound_speed,transmit_lag_dist) |
|
276 |
# - recipe provied by Jerry Mullison in August 2017 |
|
277 |
# - transducer_freq in kHz |
|
278 |
# - sound speed can vary with ensemble |
|
279 |
#====================================================================== |
|
280 |
||
281 |
sub ambiguity_velocity($$$$) |
|
282 |
{ |
|
283 |
my($xd_freq,$beam_angle,$speed_of_sound,$TL_distance) = @_; |
|
47
494a76548e94
before adapting to read RTI PD0 files
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
43
diff
changeset
|
284 |
return 'nan' unless ($TL_distance > 0); |
39 | 285 |
my($lambda) = $speed_of_sound / (1000*$xd_freq); |
286 |
my($D) = $speed_of_sound * cos(rad($beam_angle)) / 2; |
|
287 |
return $lambda * $D / (4 * $TL_distance); |
|
288 |
} |
|
0 | 289 |
|
290 |
#====================================================================== |
|
291 |
# ($firstgood,$lastgood,$atbottom,$w_gap_time,$zErr,$maxz) = |
|
292 |
# mk_prof($dta,$check,$filter,$lr_b0,$lr_b1,$min_corr,$max_e,$max_gap); |
|
293 |
#====================================================================== |
|
294 |
||
12 | 295 |
# calculate reference-layer vertical and incident velocities |
296 |
||
31 | 297 |
sub mk_prof_ref_lr_w($$$$$$$) |
0 | 298 |
{ |
11 | 299 |
my($dta,$ens,$rl_b0,$rl_b1,$min_corr,$max_e,$min_pctg) = @_; |
12 | 300 |
my($i,@n,@bn,@v,@vi,@vel,@veli,@bv,@w); |
301 |
my($w,$e,$nvi,$vi12,$vi43,@vbp,@velbp,@nbp,$w12,$w34,@w12,@w34); |
|
0 | 302 |
|
303 |
for ($i=$rl_b0; $i<=$rl_b1; $i++) { |
|
48
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
304 |
next unless defined($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i]); |
0 | 305 |
undef($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][0]) |
306 |
if ($dta->{ENSEMBLE}[$ens]->{CORRELATION}[$i][0] < $min_corr); |
|
307 |
undef($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][1]) |
|
308 |
if ($dta->{ENSEMBLE}[$ens]->{CORRELATION}[$i][1] < $min_corr); |
|
309 |
undef($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][2]) |
|
310 |
if ($dta->{ENSEMBLE}[$ens]->{CORRELATION}[$i][2] < $min_corr); |
|
311 |
undef($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][3]) |
|
312 |
if ($dta->{ENSEMBLE}[$ens]->{CORRELATION}[$i][3] < $min_corr); |
|
313 |
if ($dta->{BEAM_COORDINATES}) { |
|
314 |
undef($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][0]) |
|
11 | 315 |
if ($dta->{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][0] < $min_pctg); |
0 | 316 |
undef($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][1]) |
11 | 317 |
if ($dta->{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][1] < $min_pctg); |
0 | 318 |
undef($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][2]) |
11 | 319 |
if ($dta->{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][2] < $min_pctg); |
0 | 320 |
undef($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][3]) |
11 | 321 |
if ($dta->{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][3] < $min_pctg); |
34 | 322 |
@vi = velBeamToInstrument($dta,$ens,@{$dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i]}); |
12 | 323 |
@v = velInstrumentToEarth($dta,$ens,@vi); |
324 |
@vbp = velBeamToBPEarth($dta,$ens,@{$dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i]}); |
|
0 | 325 |
} else { |
48
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
326 |
if ($min_pctg > 0) { |
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
327 |
next if ($dta->{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][0] > 0 || |
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
328 |
$dta->{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][1] > 0 || |
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
329 |
$dta->{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][2] > 0 || |
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
330 |
$dta->{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][3] < $min_pctg); |
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
331 |
} |
0 | 332 |
@v = @{$dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i]}; |
333 |
} |
|
10 | 334 |
next if (defined($v[3]) && abs($v[3]) > $max_e); # allow 3-beam solutions |
0 | 335 |
|
19
e23a5fd2923a
after adapting RDI_Coords to calc w even without valid heading
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
17
diff
changeset
|
336 |
if (defined($v[2])) { # valid vertical velocity |
12 | 337 |
$vel[2] += $v[2]; $n[2]++; # vertical velocity |
338 |
$vel[3] += $v[3], $n[3]++ if defined($v[3]); # error velocity |
|
339 |
push(@w,$v[2]); # save for stderr calculation |
|
340 |
} |
|
341 |
||
342 |
if (defined($vbp[1])) { # beam-pair vertical velocities |
|
343 |
$velbp[0] += $vbp[1]; $nbp[0]++; |
|
344 |
push(@w12,$vbp[1]); |
|
345 |
} |
|
346 |
if (defined($vbp[3])) { |
|
347 |
$velbp[1] += $vbp[3]; $nbp[1]++; |
|
348 |
push(@w34,$vbp[1]); |
|
0 | 349 |
} |
350 |
||
12 | 351 |
if (defined($vi[0])) { # incident velocity |
352 |
$veli[0] += $vi[0]; |
|
353 |
$veli[1] += $vi[1]; |
|
354 |
$nvi++; |
|
355 |
} |
|
356 |
||
10 | 357 |
# The following code calculates beam-averaged ref-lr velocities. |
358 |
# I do not recall what this was implemented for. Disabled Mar 27, 2013. |
|
359 |
# |
|
360 |
# if ($dta->{BEAM_COORDINATES}) { |
|
361 |
# $bv[0] += $dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][0], $bn[0]++ |
|
362 |
# if defined($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][0]); |
|
363 |
# $bv[1] += $dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][1], $bn[1]++ |
|
364 |
# if defined($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][1]); |
|
365 |
# $bv[2] += $dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][2], $bn[2]++ |
|
366 |
# if defined($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][2]); |
|
367 |
# $bv[3] += $dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][3], $bn[3]++ |
|
368 |
# if defined($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$i][3]); |
|
369 |
# } |
|
12 | 370 |
} # loop over ref-lr bins |
371 |
||
372 |
$w = ($n[2] > 0) ? $vel[2]/$n[2] : undef; # calc means |
|
373 |
$e = ($n[3] > 0) ? $vel[3]/$n[3] : undef; |
|
374 |
if ($nvi > 0) { |
|
375 |
$vi12 = $veli[0] / $nvi; |
|
376 |
$vi43 = $veli[1] / $nvi; |
|
377 |
} else { |
|
378 |
$vi12 = $vi43 = undef; |
|
379 |
} |
|
380 |
$w12 = ($nbp[0] > 0) ? $velbp[0]/$nbp[0] : undef; |
|
381 |
$w34 = ($nbp[1] > 0) ? $velbp[1]/$nbp[1] : undef; |
|
382 |
||
383 |
if (@w12) { # w uncertainty |
|
384 |
my($sumsq) = 0; |
|
385 |
for ($i=0; $i<=$#w12; $i++) { |
|
386 |
$sumsq += ($w12-$w12[$i])**2; |
|
387 |
} |
|
388 |
$dta->{ENSEMBLE}[$ens]->{W12} = $w12; |
|
389 |
$dta->{ENSEMBLE}[$ens]->{W12_ERR} = sqrt($sumsq)/($nbp[0]-1) |
|
390 |
if ($nbp[0]>=2); |
|
0 | 391 |
} |
392 |
||
12 | 393 |
if (@w34) { # w uncertainty |
394 |
my($sumsq) = 0; |
|
395 |
for ($i=0; $i<=$#w34; $i++) { |
|
396 |
$sumsq += ($w34-$w34[$i])**2; |
|
397 |
} |
|
398 |
$dta->{ENSEMBLE}[$ens]->{W34} = $w34; |
|
399 |
$dta->{ENSEMBLE}[$ens]->{W34_ERR} = sqrt($sumsq)/($nbp[1]-1) |
|
400 |
if ($nbp[1]>=2); |
|
401 |
} |
|
402 |
||
403 |
my($sumsq) = 0; # w uncertainty |
|
0 | 404 |
for ($i=0; $i<=$#w; $i++) { |
405 |
$sumsq += ($w-$w[$i])**2; |
|
406 |
} |
|
407 |
my($stderr) = $n[2]>=2 ? sqrt($sumsq)/($n[2]-1) : undef; |
|
12 | 408 |
|
0 | 409 |
# The following stderr test introduces a huge gap near the bottom of |
410 |
# the profiles. Without it, they seem more reasonable. |
|
411 |
# next if ($stderr > 0.05); |
|
412 |
||
12 | 413 |
if (defined($w)) { # valid velocity |
0 | 414 |
$dta->{ENSEMBLE}[$ens]->{W} = $w; |
415 |
$dta->{ENSEMBLE}[$ens]->{W_ERR} = $stderr; |
|
416 |
} |
|
12 | 417 |
$dta->{ENSEMBLE}[$ens]->{ERR_VEL} = $e if (defined($e)); |
418 |
||
419 |
$dta->{ENSEMBLE}[$ens]->{W12} = $w12 if (defined($w12)); |
|
420 |
$dta->{ENSEMBLE}[$ens]->{W34} = $w34 if (defined($w34)); |
|
421 |
||
422 |
if (defined($vi12)) { |
|
423 |
$dta->{ENSEMBLE}[$ens]->{INCIDENT_VEL_T12} = $vi12; |
|
424 |
$dta->{ENSEMBLE}[$ens]->{INCIDENT_VEL_T43} = $vi43; |
|
425 |
} |
|
426 |
||
10 | 427 |
# The following code calculates beam-averaged ref-lr velocities. |
428 |
# I do not recall what this was implemented for. Disabled Mar 27, 2013. |
|
429 |
# |
|
430 |
# if ($dta->{BEAM_COORDINATES}) { |
|
431 |
# $dta->{ENSEMBLE}[$ens]->{V1} = $bn[0]>=2 ? $bv[0]/$bn[0] : undef; |
|
432 |
# $dta->{ENSEMBLE}[$ens]->{V2} = $bn[1]>=2 ? $bv[1]/$bn[1] : undef; |
|
433 |
# $dta->{ENSEMBLE}[$ens]->{V3} = $bn[2]>=2 ? $bv[2]/$bn[2] : undef; |
|
434 |
# $dta->{ENSEMBLE}[$ens]->{V4} = $bn[3]>=2 ? $bv[3]/$bn[3] : undef; |
|
435 |
# } |
|
12 | 436 |
|
0 | 437 |
} |
438 |
||
439 |
||
11 | 440 |
sub mk_prof(...) # make profile |
0 | 441 |
{ |
11 | 442 |
my($dta,$check,$filter,$lr_b0,$lr_b1,$min_corr,$max_e,$max_gap,$min_pctg) = @_; |
0 | 443 |
my($firstgood,$lastgood,$atbottom,$w_gap_time,$zErr,$maxz); |
8 | 444 |
my($rms_heave_accel_ssq,$rms_heave_accel_nsamp); |
11 | 445 |
|
446 |
$min_pctg = 100 unless defined($min_pctg); |
|
0 | 447 |
|
448 |
for (my($z)=0,my($e)=0; $e<=$#{$dta->{ENSEMBLE}}; $e++) { |
|
449 |
checkEnsemble($dta,$e) if ($check); |
|
6 | 450 |
### The following line of code, which can only have an effect if check is disabled, |
451 |
### seems reasonable but has been found to make matters worse with one particular |
|
452 |
### data file from a BB150. |
|
453 |
### next if ($dta->{ENSEMBLE}[$e]->{BUILT_IN_TEST_ERROR}); |
|
0 | 454 |
|
455 |
filterEnsemble($dta,$e) |
|
456 |
if (defined($filter) && |
|
457 |
$dta->{ENSEMBLE}[$e]->{PERCENT_GOOD}[0][0] > 0); |
|
31 | 458 |
mk_prof_ref_lr_w($dta,$e,$lr_b0,$lr_b1,$min_corr,$max_e,$min_pctg); # ref. layer w |
0 | 459 |
|
460 |
if (defined($firstgood)) { |
|
461 |
$dta->{ENSEMBLE}[$e]->{ELAPSED_TIME} = # time since start |
|
462 |
$dta->{ENSEMBLE}[$e]->{UNIX_TIME} - |
|
463 |
$dta->{ENSEMBLE}[$firstgood]->{UNIX_TIME}; |
|
464 |
} else { |
|
465 |
if (defined($dta->{ENSEMBLE}[$e]->{W})) { # start of prof. |
|
466 |
$firstgood = $lastgood = $e; |
|
467 |
$dta->{ENSEMBLE}[$e]->{ELAPSED_TIME} = 0; |
|
468 |
$dta->{ENSEMBLE}[$e]->{DEPTH} = $dta->{ENSEMBLE}[$e]->{DEPTH_ERR} = 0; |
|
469 |
} |
|
470 |
next; |
|
471 |
} |
|
472 |
||
473 |
#-------------------------------------------------- |
|
474 |
# within profile: both $firstgood and $lastgood set |
|
475 |
#-------------------------------------------------- |
|
476 |
||
477 |
if (!defined($dta->{ENSEMBLE}[$e]->{W})) { # gap |
|
478 |
$w_gap_time += $dta->{ENSEMBLE}[$e]->{UNIX_TIME} - |
|
479 |
$dta->{ENSEMBLE}[$e-1]->{UNIX_TIME}; |
|
480 |
next; |
|
481 |
} |
|
482 |
||
483 |
my($dt) = $dta->{ENSEMBLE}[$e]->{UNIX_TIME} - # time step since |
|
484 |
$dta->{ENSEMBLE}[$lastgood]->{UNIX_TIME}; # ... last good ens |
|
43
b63fa355644c
commit to merge with changes from EN620
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
41
diff
changeset
|
485 |
|
60
890e267a2d98
bug fix for data file with errors
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
52
diff
changeset
|
486 |
# die(sprintf("PANIC: negative dt = $dt between ensembles %d and %d\n", |
890e267a2d98
bug fix for data file with errors
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
52
diff
changeset
|
487 |
# $dta->{ENSEMBLE}[$lastgood]->{NUMBER},$dta->{ENSEMBLE}[$e]->{NUMBER})) |
890e267a2d98
bug fix for data file with errors
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
52
diff
changeset
|
488 |
# if ($dt < 0); |
890e267a2d98
bug fix for data file with errors
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
52
diff
changeset
|
489 |
if ($dt < 0) { |
890e267a2d98
bug fix for data file with errors
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
52
diff
changeset
|
490 |
printf(STDERR "WARNING: negative dt; ensemble #%d ignored\n", |
890e267a2d98
bug fix for data file with errors
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
52
diff
changeset
|
491 |
$dta->{ENSEMBLE}[$e]->{NUMBER}); |
890e267a2d98
bug fix for data file with errors
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
52
diff
changeset
|
492 |
next; |
890e267a2d98
bug fix for data file with errors
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
52
diff
changeset
|
493 |
} |
0 | 494 |
|
495 |
if ($dt > $max_gap) { |
|
41 | 496 |
# 2nd heuristic test added Nov 2017 for P06 profile #001 |
497 |
if ((@{$dta->{ENSEMBLE}}-$e < @{$dta->{ENSEMBLE}}/2) && |
|
498 |
($maxz > 25 && $z < $maxz/2)) { |
|
17
591779f6df30
changed mkProfile gap heuristics & removed warning
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
14
diff
changeset
|
499 |
printf(STDERR "WARNING: %.1f-s gap in 2nd half of profile is too long; profile ended at ensemble $lastgood\n",$dt); |
41 | 500 |
# printf(STDERR "\t[#ens = %d, end-of-gap = $e]\n",scalar(@{$dta->{ENSEMBLE}})); |
5 | 501 |
last; |
502 |
} |
|
43
b63fa355644c
commit to merge with changes from EN620
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
41
diff
changeset
|
503 |
printf(STDERR "WARNING: %.1f-s gap beginning at ens#%d in first half of profile is too long; profile restarted at ensemble %d\n", |
b63fa355644c
commit to merge with changes from EN620
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
41
diff
changeset
|
504 |
$dt,$dta->{ENSEMBLE}[$lastgood+1]->{NUMBER},$dta->{ENSEMBLE}[$e]->{NUMBER}); |
0 | 505 |
$firstgood = $lastgood = $e; |
506 |
$dta->{ENSEMBLE}[$e]->{ELAPSED_TIME} = 0; |
|
507 |
$z = $zErr = $maxz = 0; |
|
508 |
$dta->{ENSEMBLE}[$e]->{DEPTH} = $dta->{ENSEMBLE}[$e]->{DEPTH_ERR} = 0; |
|
509 |
$w_gap_time = 0; |
|
8 | 510 |
$rms_heave_accel_ssq = $rms_heave_accel_nsamp = 0; |
0 | 511 |
next; |
512 |
} |
|
2
065ea9ce12fc
before DIMES UK2 cruise
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
0
diff
changeset
|
513 |
|
0 | 514 |
#----------------------------------- |
515 |
# The current ensemble has a valid w |
|
516 |
#----------------------------------- |
|
8 | 517 |
|
48
cdc74ebada81
after partial adaptation to RTI files
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
43
diff
changeset
|
518 |
if ($dt < 6) { # no or short gap |
8 | 519 |
$z += $dta->{ENSEMBLE}[$lastgood]->{W} * $dt; # integrate w to get depth |
2
065ea9ce12fc
before DIMES UK2 cruise
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
0
diff
changeset
|
520 |
$zErr += ($dta->{ENSEMBLE}[$lastgood]->{W_ERR} * $dt)**2; |
8 | 521 |
$rms_heave_accel_ssq += (($dta->{ENSEMBLE}[$e]->{W}-$dta->{ENSEMBLE}[$lastgood]->{W})/$dt)**2; |
522 |
$rms_heave_accel_nsamp++; |
|
3 | 523 |
} elsif ($dt > 15) { |
43
b63fa355644c
commit to merge with changes from EN620
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
41
diff
changeset
|
524 |
printf(STDERR "WARNING: long-ish w gap at ens#%d-%d (dt=%.1fs)\n", |
b63fa355644c
commit to merge with changes from EN620
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
41
diff
changeset
|
525 |
$dta->{ENSEMBLE}[$lastgood+1]->{NUMBER},$dta->{ENSEMBLE}[$e-1]->{NUMBER},$dt) |
52
5b07a9b89aee
- adapted to work with IMPed moored ADCP data
Andreas Thurnherr <ant@ldeo.columbia.edu>
parents:
49
diff
changeset
|
526 |
unless defined($ENV{NO_GAP_WARNINGS}) || $RDI_Utils::No_Gap_Warnings; |
2
065ea9ce12fc
before DIMES UK2 cruise
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
0
diff
changeset
|
527 |
} |
065ea9ce12fc
before DIMES UK2 cruise
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
0
diff
changeset
|
528 |
|
0 | 529 |
$dta->{ENSEMBLE}[$e]->{DEPTH} = $z; |
530 |
$dta->{ENSEMBLE}[$e]->{DEPTH_ERR} = sqrt($zErr); |
|
531 |
||
532 |
$atbottom = $e, $maxz = $z if ($z > $maxz); |
|
533 |
||
534 |
$lastgood = $e; |
|
535 |
} |
|
536 |
||
537 |
filterEnsembleStats() if defined($filter); |
|
538 |
||
23
fb0c269b1eaa
V1.2 release candidate
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
19
diff
changeset
|
539 |
return ($firstgood,$lastgood,$atbottom,$w_gap_time,$zErr,$maxz, |
fb0c269b1eaa
V1.2 release candidate
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
19
diff
changeset
|
540 |
($rms_heave_accel_nsamp>0) ? sqrt($rms_heave_accel_ssq/$rms_heave_accel_nsamp) : 'nan'); |
0 | 541 |
} |
542 |
||
543 |
#---------------------------------------------------------------------- |
|
544 |
# (true|false) = numberp(var) |
|
545 |
#---------------------------------------------------------------------- |
|
546 |
||
547 |
sub numberp(@) |
|
548 |
{ return $_[0] =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/; } |
|
549 |
||
550 |
||
551 |
1; |
|
2
065ea9ce12fc
before DIMES UK2 cruise
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
0
diff
changeset
|
552 |