|
1 #!/usr/bin/perl |
|
2 #====================================================================== |
|
3 # L I S T W |
|
4 # doc: Wed Mar 24 06:45:09 2004 |
|
5 # dlm: Thu Jul 30 17:42:33 2009 |
|
6 # (c) 2004 A.M. Thurnherr |
|
7 # uE-Info: 205 53 NIL 0 0 72 2 2 4 NIL ofnI |
|
8 #====================================================================== |
|
9 |
|
10 # dump vertical velocities |
|
11 |
|
12 # NB: currently broken |
|
13 |
|
14 # HISTORY: |
|
15 # Mar 24, 2004: - created from [listens] and [mkprofile] |
|
16 # Mar 27, 2004: - added elapsed field |
|
17 # - floatized time |
|
18 # Apr 3, 2004: - cosmetics |
|
19 # Nov 8, 2005: - UNIXTIME => UNIX_TIME |
|
20 # Sep 19, 2007: - adapted to new [RDI_BB_Read.pl] (not tested) |
|
21 # Jul 30, 2009: - NaN => nan |
|
22 |
|
23 $0 =~ m{(.*)/[^/]+}; |
|
24 require "$1/WorkhorseBinRead.pl"; |
|
25 require "$1/WorkhorseCoords.pl"; |
|
26 require "$1/WorkhorseUtils.pl"; |
|
27 |
|
28 use Getopt::Std; |
|
29 |
|
30 $USAGE = "$0 @ARGV"; |
|
31 die("Usage: $0 " . |
|
32 "[-A)nts] " . |
|
33 "[-F)ilter <script>] " . |
|
34 "[bin -r)ange <bin|0,bin|*>] " . |
|
35 "[-e)rr-vel <max|0.1>] [-c)orrelation <min|70>] " . |
|
36 "[-S)alin <val|35>] [-t)emp <bias>] " . |
|
37 "[output -f)ields <field[,...]> " . |
|
38 "<RDI file>\n") |
|
39 unless (&getopts("Ac:e:F:f:r:S:t:") && @ARGV == 1); |
|
40 |
|
41 $opt_e = 0.1 unless defined($opt_e); # defaults |
|
42 $opt_c = 70 unless defined($opt_c); |
|
43 $opt_S = 35 unless defined($opt_S); |
|
44 print(STDERR "WARNING: Using uncalibrated ADCP temperature!\n"),$opt_t = 0 |
|
45 unless defined($opt_t); |
|
46 |
|
47 require $opt_F if defined($opt_F); # load filter |
|
48 |
|
49 if ($opt_f) { # additional fields |
|
50 @f = split(',',$opt_f); |
|
51 foreach $f (@f) { |
|
52 my($f) = $f; # copy it |
|
53 $f =~ s{\[.*$}{}; # remove indices |
|
54 $addFields .= " {$f}"; |
|
55 } |
|
56 } |
|
57 |
|
58 #---------------------------------------------------------------------- |
|
59 |
|
60 print(STDERR "Reading $ARGV[0]..."); # read data |
|
61 readData($ARGV[0],\%dta); |
|
62 print(STDERR "done\n"); |
|
63 |
|
64 if (defined($opt_r)) { # bin range |
|
65 ($minb,$maxb) = split(',',$opt_r); |
|
66 die("$0: can't decode -r $opt_r\n") unless defined($maxb); |
|
67 } else { |
|
68 $minb = 0; |
|
69 $maxb = $dta{N_BINS} - 1; |
|
70 } |
|
71 |
|
72 die("$ARGV[0]: not enough bins for choice of -r\n") # enough bins? |
|
73 unless ($dta{N_BINS} >= $maxb); |
|
74 |
|
75 if ($dta{BEAM_COORDINATES}) { # coords used |
|
76 $beamCoords = 1; |
|
77 } elsif (!$dta{EARTH_COORDINATES}) { |
|
78 die("$ARGV[0]: only beam and earth coordinates implemented so far\n"); |
|
79 } |
|
80 |
|
81 #---------------------------------------------------------------------- |
|
82 # Reference-Layer w (from [mkprofile]) |
|
83 # - also sets W field when valid |
|
84 #---------------------------------------------------------------------- |
|
85 |
|
86 sub ref_lr_w($) |
|
87 { |
|
88 my($ens) = @_; |
|
89 my($i,$n,$w); |
|
90 |
|
91 for ($i=$minb; $i<=$maxb; $i++) { |
|
92 next if ($dta{ENSEMBLE}[$ens]->{CORRELATION}[$i][0] < $opt_c || |
|
93 $dta{ENSEMBLE}[$ens]->{CORRELATION}[$i][1] < $opt_c || |
|
94 $dta{ENSEMBLE}[$ens]->{CORRELATION}[$i][2] < $opt_c || |
|
95 $dta{ENSEMBLE}[$ens]->{CORRELATION}[$i][3] < $opt_c); |
|
96 if ($beamCoords) { |
|
97 next if ($dta{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][0] < 100 || |
|
98 $dta{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][1] < 100 || |
|
99 $dta{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][2] < 100 || |
|
100 $dta{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][3] < 100); |
|
101 @v = velInstrumentToEarth(\%dta,$ens, |
|
102 velBeamToInstrument(\%dta, |
|
103 @{$dta{ENSEMBLE}[$ens]->{VELOCITY}[$i]})); |
|
104 } else { |
|
105 next if ($dta{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][0] > 0 || |
|
106 $dta{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][1] > 0 || |
|
107 $dta{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][2] > 0 || |
|
108 $dta{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$i][3] < 100); |
|
109 @v = @{$dta{ENSEMBLE}[$ens]->{VELOCITY}[$i]}; |
|
110 } |
|
111 next if (!defined($v[3]) || abs($v[3]) > $opt_e); |
|
112 |
|
113 if (defined($v[2])) { # valid w |
|
114 $dta{ENSEMBLE}[$ens]->{W}[$i] = $v[2]; |
|
115 $w += $v[2]; $n++; |
|
116 } |
|
117 } |
|
118 return $n ? $w/$n : undef; |
|
119 } |
|
120 |
|
121 #---------------------------------------------------------------------- |
|
122 |
|
123 print(STDERR "Generating profile by integrating w..."); |
|
124 |
|
125 for ($e=0; $e<=$#{$dta{ENSEMBLE}}; $e++) { |
|
126 checkEnsemble(\%dta,$e); # sanity checks |
|
127 filterEnsemble(\%dta,$e) # filter ensemble |
|
128 if (defined($opt_F) && |
|
129 $dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[0][0] > 0); |
|
130 |
|
131 $dta{ENSEMBLE}[$e]->{REFW} = ref_lr_w($e); |
|
132 next unless defined($dta{ENSEMBLE}[$e]->{REFW}); |
|
133 |
|
134 unless (defined($firstgood)) { # init profile |
|
135 $firstgood = $lastgood = $e; |
|
136 $depth = 0; |
|
137 } |
|
138 |
|
139 my($dt) = $dta{ENSEMBLE}[$e]->{UNIX_TIME} - # time step since |
|
140 $dta{ENSEMBLE}[$lastgood]->{UNIX_TIME}; # ... last good ens |
|
141 if ($dt > 120) { |
|
142 printf(STDERR "\nWARNING: %d-s gap too long, profile restarted at ensemble $e...",$dt); |
|
143 $firstgood = $lastgood = $e; |
|
144 $dt = $depth = 0; |
|
145 } |
|
146 |
|
147 $depth += $dta{ENSEMBLE}[$lastgood]->{REFW} * $dt # integrate depth |
|
148 if ($dt > 0); |
|
149 $dta{ENSEMBLE}[$e]->{DEPTH} = $depth; |
|
150 $atbottom = $e, $maxdepth = $depth if ($depth > $maxdepth); |
|
151 |
|
152 my($ss) = soundSpeed($opt_S, # sound-speed corr |
|
153 $dta{ENSEMBLE}[$e]->{TEMPERATURE}-$opt_t, |
|
154 $depth); |
|
155 $dta{ENSEMBLE}[$e]->{SPEED_OF_SOUND_CORRECTION} = |
|
156 $ss / $dta{ENSEMBLE}[$e]->{SPEED_OF_SOUND}; |
|
157 $dta{ENSEMBLE}[$e]->{SPEED_OF_SOUND} = $ss; |
|
158 $dta{ENSEMBLE}[$e]->{REFW} *= |
|
159 $dta{ENSEMBLE}[$e]->{SPEED_OF_SOUND_CORRECTION}; |
|
160 |
|
161 $lastgood = $e; |
|
162 } |
|
163 |
|
164 printf(STDERR "done (max depth = %.1fm, depth at end of cast = %.1fm)\n", |
|
165 $maxdepth,$depth); |
|
166 |
|
167 filterEnsembleStats() if defined($opt_F); |
|
168 |
|
169 #---------------------------------------------------------------------- |
|
170 |
|
171 print(STDERR "Writing output..."); |
|
172 |
|
173 if ($opt_A) { |
|
174 print("#ANTS# [] $USAGE\n"); |
|
175 print("#ANTS#FIELDS# {ens} {unix_time} {time} {bin} {depth} {dz} {w} {ref_w} {dw} $addFields\n"); |
|
176 printf("#ANTS#PARAMS# maxdepth{$max_depth} bottom_time{%d}\n", |
|
177 $dta{ENSEMBLE}[$atbottom]->{UNIX_TIME} - |
|
178 $dta{ENSEMBLE}[$firstgood]->{UNIX_TIME}); |
|
179 } else { |
|
180 print("# ens-no time elapsed bin-no depth dz w ref-w dw $addFields\n"); |
|
181 print("#----------------------------------------------------------------------\n"); |
|
182 } |
|
183 |
|
184 for ($e=$firstgood; $e<=$lastgood; $e++) { |
|
185 |
|
186 for ($i=$minb; $i<=$maxb; $i++) { # dump valid |
|
187 next unless defined($dta{ENSEMBLE}[$e]->{W}[$i]); |
|
188 |
|
189 printf("%d %f %f %d %.1f %.1f %g %g %g ", |
|
190 $e,$dta{ENSEMBLE}[$e]->{UNIX_TIME}, |
|
191 $dta{ENSEMBLE}[$e]->{UNIX_TIME} - |
|
192 $dta{ENSEMBLE}[$firstgood]->{UNIX_TIME},$i, |
|
193 $dta{ENSEMBLE}[$e]->{DEPTH} + |
|
194 $dta{ENSEMBLE}[$e]->{SPEED_OF_SOUND_CORRECTION} * |
|
195 ($dta{DISTANCE_TO_BIN1_CENTER} + $i*$dta{BIN_LENGTH}), |
|
196 $dta{ENSEMBLE}[$e]->{SPEED_OF_SOUND_CORRECTION} * |
|
197 ($dta{DISTANCE_TO_BIN1_CENTER} + $i*$dta{BIN_LENGTH}), |
|
198 $dta{ENSEMBLE}[$e]->{SPEED_OF_SOUND_CORRECTION} * |
|
199 $dta{ENSEMBLE}[$e]->{W}[$i], |
|
200 $dta{ENSEMBLE}[$e]->{REFW}, |
|
201 $dta{ENSEMBLE}[$e]->{SPEED_OF_SOUND_CORRECTION} * |
|
202 $dta{ENSEMBLE}[$e]->{W}[$i] - $dta{ENSEMBLE}[$e]->{REFW}, |
|
203 ); |
|
204 |
|
205 sub p($) { print(defined($_[0])?"$_[0] ":"nan "); } |
|
206 |
|
207 if (defined(@f)) { |
|
208 foreach $f (@f) { |
|
209 my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)}); |
|
210 $fn = $f unless defined($fn); |
|
211 p(eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi")); |
|
212 } |
|
213 } |
|
214 print("\n"); |
|
215 } |
|
216 } |
|
217 |
|
218 print(STDERR "done\n"); |
|
219 |
|
220 exit(0); |
|
221 |