1 #====================================================================== |
|
2 # L A D C P P R O C . L O A D C T D |
|
3 # doc: Thu Dec 9 18:39:01 2010 |
|
4 # dlm: Sat Jan 22 21:40:12 2011 |
|
5 # (c) 2010 A.M. Thurnherr |
|
6 # uE-Info: 174 0 NIL 0 0 72 2 2 4 NIL ofnI |
|
7 #====================================================================== |
|
8 |
|
9 # HISTORY: |
|
10 # Dec 9, 2010: - exported from LADCPproc |
|
11 # - added support for ASCII files |
|
12 # Dec 16, 2010: - BUG cnv read did not work any more |
|
13 # Jan 10, 2011: - added code to skip ANTS header |
|
14 # Jan 22, 2011: - adapted to new -g |
|
15 |
|
16 sub readCTD_ASCII($$) |
|
17 { |
|
18 my($fn,$dtaR) = @_; |
|
19 |
|
20 croak("$fn: unknown pressure field\n") unless defined($CTD_ASCII_press_field); |
|
21 croak("$fn: unknown temperature field\n") unless defined($CTD_ASCII_temp_field); |
|
22 croak("$fn: unknown salinity field\n") unless defined($CTD_ASCII_salin_field); |
|
23 unless (numberp($dtaR->{lat})) { |
|
24 croak("$fn: unknown latitude field\n") unless defined($CTD_ASCII_lat_field); |
|
25 croak("$fn: unknown longitude field\n") unless defined($CTD_ASCII_lon_field); |
|
26 } |
|
27 |
|
28 $CTD_ASCII_badval = 9e99 unless defined($CTD_ASCII_badval); |
|
29 |
|
30 open(F,$fn) || croak("$fn: $!\n"); |
|
31 my($sumLat,$sumLon); my($nPos) = 0; |
|
32 my($ds); |
|
33 while (chomp($ds = <F>)) { |
|
34 next if ($ds =~ /^#/); |
|
35 my(@rec) = split('\s+',$ds); |
|
36 push(@{$dtaR->{press}},($rec[$CTD_ASCII_press_field-1] == $CTD_ASCII_badval) ? nan : $rec[$CTD_ASCII_press_field-1]); |
|
37 push(@{$dtaR->{temp}}, ($rec[$CTD_ASCII_temp_field-1] == $CTD_ASCII_badval) ? nan : $rec[$CTD_ASCII_temp_field-1]); |
|
38 push(@{$dtaR->{salin}},($rec[$CTD_ASCII_salin_field-1] == $CTD_ASCII_badval) ? nan : $rec[$CTD_ASCII_salin_field-1]); |
|
39 unless (!defined($CTD_ASCII_lat_field) || $rec[$CTD_ASCII_lat_field-1] == $CTD_ASCII_badval) { |
|
40 $nPos++; |
|
41 $sumLat += $rec[$CTD_ASCII_lat_field-1]; |
|
42 $sumLon += $rec[$CTD_ASCII_lon_field-1]; |
|
43 } |
|
44 } |
|
45 close(F); |
|
46 |
|
47 if ($nPos > 0) { |
|
48 $dtaR->{lat} = $sumLat / $nPos; |
|
49 $dtaR->{lon} = $sumLon / $nPos; |
|
50 } |
|
51 |
|
52 $dtaR->{sampint} = 1 / $CTD_ASCII_sampfreq; |
|
53 } |
|
54 |
|
55 sub readCTD_CNV($$) |
|
56 { |
|
57 my($fn,$dtaR) = @_; |
|
58 my($CTD_nrecs,$CTD_nfields,$pressF,$tempF,$salinF); |
|
59 my($CTD_badval,$CTD_file_type); |
|
60 |
|
61 open(F,$fn) || croak("$fn: $!\n"); |
|
62 while (1) { # parse header |
|
63 my($hdr); |
|
64 chomp($hdr = <F>); |
|
65 $hdr =~ s/\r*$//; |
|
66 croak("$0: unexpected EOF (format error)\n") unless defined($hdr); |
|
67 last if ($hdr eq '*END*'); |
|
68 |
|
69 $CTD_nfields = $',next if ($hdr =~ /nquan = /); # Layout |
|
70 $CTD_nrecs = $',next if ($hdr =~ /nvalues = /); |
|
71 $pressF = $1,next if ($hdr =~ /name (\d+) = prDM:/); |
|
72 if ($opt_2) { |
|
73 $tempF = $1,next if ($hdr =~ /name (\d+) = t190C:/); |
|
74 $salinF = $1,next if ($hdr =~ /name (\d+) = sal11:/); |
|
75 } else { |
|
76 $tempF = $1,next if ($hdr =~ /name (\d+) = t090C:/); |
|
77 $salinF = $1,next if ($hdr =~ /name (\d+) = sal00:/); |
|
78 } |
|
79 |
|
80 &antsAddParams('start_time',$1),next # selected metadata |
|
81 if ($hdr =~ /start_time = (.*)/); |
|
82 |
|
83 &antsAddParams('station',$1),next |
|
84 if ($hdr =~ /Station\s*:\s*(.*)/); |
|
85 &antsAddParams('ship',$1),next |
|
86 if ($hdr =~ /Ship\s*:\s*(.*)\s*$/); |
|
87 &antsAddParams('cruise',$1),next |
|
88 if ($hdr =~ /Cruise\s*:\s*(.*)\s*$/); |
|
89 &antsAddParams('time',$1),next |
|
90 if ($hdr =~ /Time\s*:\s*(.*)/); |
|
91 &antsAddParams('date',$1),next |
|
92 if ($hdr =~ /Date\s*:\s*(.*)/); |
|
93 |
|
94 if ($hdr =~ /Latitude\s*[=:]\s*/) { |
|
95 ($deg,$min,$NS) = split(/ /,$'); |
|
96 $dtaR->{lat} = $deg + $min/60; |
|
97 $dtaR->{lat} *= -1 if ($NS eq 'S'); |
|
98 next; |
|
99 } |
|
100 if ($hdr =~ /Longitude\s*[=:]\s*/) { |
|
101 ($deg,$min,$EW) = split(/ /,$'); |
|
102 $dtaR->{lon} = $deg + $min/60; |
|
103 $dtaR->{lon} *= -1 if ($EW eq 'W'); |
|
104 next; |
|
105 } |
|
106 |
|
107 if ($hdr =~ /interval = seconds: /) { |
|
108 $dtaR->{sampint} = 1*$'; |
|
109 next; |
|
110 } |
|
111 |
|
112 $CTD_badval = $',next |
|
113 if ($hdr =~ /bad_flag = /); |
|
114 $CTD_file_type = $',next |
|
115 if ($hdr =~ /file_type = /); |
|
116 } |
|
117 |
|
118 croak("$CTD_file: cannot determine CTD file layout\n") |
|
119 unless ($CTD_nfields && $CTD_nrecs); |
|
120 croak("$CTD_file: cannot determine missing value\n") |
|
121 unless defined($CTD_badval); |
|
122 croak("$CTD_file: not a CTD time series file\n") |
|
123 unless ($dtaR->{sampint}); |
|
124 croak("$CTD_file: no pressure field\n") |
|
125 unless defined($pressF); |
|
126 croak("$CTD_file: no suitable temperature field\n") |
|
127 unless defined($tempF); |
|
128 croak("$CTD_file: no suitable salinity field\n") |
|
129 unless defined($salinF); |
|
130 |
|
131 if ($CTD_file_type eq 'ascii') { |
|
132 while (1) { |
|
133 last unless (my(@rec) = &antsFileIn(F)); |
|
134 push(@{$dtaR->{press}},($rec[$pressF] == $CTD_badval) ? nan : $rec[$pressF]); |
|
135 push(@{$dtaR->{temp}}, ($rec[$tempF] == $CTD_badval) ? nan : $rec[$tempF]); |
|
136 push(@{$dtaR->{salin}},($rec[$salinF] == $CTD_badval) ? nan : $rec[$salinF]); |
|
137 } |
|
138 } elsif ($CTD_file_type eq 'binary') { |
|
139 |
|
140 my($fbits) = 8 * length(pack('f',0)); |
|
141 croak(sprintf("$0: incompatible native CPU float representation (%d instead of 32bits)\n",fbits)) |
|
142 unless ($fbits == 32); |
|
143 |
|
144 croak("$fn: can't read binary data\n") |
|
145 unless (read(F,my($dta),4*$CTD_nfields*$CTD_nrecs) == 4*$CTD_nfields*$CTD_nrecs); |
|
146 print(STDERR "$fn: WARNING: extraneous data at EOF\n") unless eof(F); |
|
147 |
|
148 $dta = pack('V*',unpack('N*',$dta)) # big-endian CPU |
|
149 if (unpack('h*', pack('s', 1)) =~ /01/); # c.f. perlport(1) |
|
150 |
|
151 my(@dta) = unpack("f*",$dta); |
|
152 |
|
153 for (my($r)=0; $r<$CTD_nrecs; $r++) { |
|
154 push(@{$dtaR->{press}},($dta[$r*$CTD_nfields+$pressF] == $CTD_badval) ? nan : $dta[$r*$CTD_nfields+$pressF]); |
|
155 push(@{$dtaR->{temp}}, ($dta[$r*$CTD_nfields+$tempF] == $CTD_badval) ? nan : $dta[$r*$CTD_nfields+$tempF]); |
|
156 push(@{$dtaR->{salin}},($dta[$r*$CTD_nfields+$salinF] == $CTD_badval) ? nan : $dta[$r*$CTD_nfields+$salinF]); |
|
157 } |
|
158 } else { |
|
159 croak("$fn: unknown CTD file type $CTD_file_type\n"); |
|
160 } |
|
161 close(F); |
|
162 } |
|
163 |
|
164 sub readCTD($$) |
|
165 { |
|
166 my($fn,$dtaR) = @_; |
|
167 |
|
168 if (defined($CTD_ASCII_sampfreq)) { |
|
169 readCTD_ASCII($fn,$dtaR); |
|
170 } else { |
|
171 readCTD_CNV($fn,$dtaR); |
|
172 } |
|
173 |
|
174 croak("$0: unknown latitude\n") unless defined($dtaR->{lat}); |
|
175 &antsAddParams('lat',$dtaR->{lat}); |
|
176 croak("$0: unknown longitude\n") unless defined($dtaR->{lon}); |
|
177 &antsAddParams('lon',$dtaR->{lon}); |
|
178 |
|
179 &antsAddParams('CTD_sampfreq',1/$dtaR->{sampint}); |
|
180 &antsAddParams('ITS',$P{ITS} = 90); |
|
181 } |
|
182 |
|
183 1; |
|