; IDL script to convert SeaBIRD CTD files (cnv) to ODV spreadsheet format
; either creates individual files for each station or put all station
; data from a cruise in one big file.
; cnv file names are expected to have the format CCCCSSSS.cnv (where CCCC
; equals cruise name as set and SSSS station number, both can be any length)
; Specify directories where input files are, and where output files
; should be written to. Specify cruise name.
; written by Gert van Dijken, gertvd@stanford.edu, Oct.2009
; location of CTD cnv files
indir = '/your/input/directory/'
cnv_files = file_search(indir + '*.cnv', count=n)
; output directory
outdir = '/your/output/directory/'
cruise = 'yourcruisename' ; cruise name, start of cnv file name
; options
create_one_file = 1 ; create one file or individual station
; files (1=yes, 0=no)
calc_trans = 1 ; calculate transmission from bat (1=yes, 0=no)
downcast = 1 ; downcast only (1=yes, 0=no)
if (create_one_file) then begin
outfile = outdir + cruise + '.txt'
print, 'Output to: ', outfile
openw, 10, outfile, width=1000
endif
tab = string(9B)
first = 1
for i=0,n-1 do begin
cnv_file = cnv_files(i)
; skip ladcp files
tmp = strmatch(cnv_file, '*adcp.cnv')
if (tmp eq 0) then begin
print
print, 'Opening ' + cnv_file
line = ''
cols = ''
units = ''
odv_comment = ''
openr, 1, cnv_file
; extract headers (before *END*)
while (line ne '*END*') do begin
readf, 1, line
linespl = strsplit(line, ' ', /extract, count=nspl)
if (nspl gt 1) then begin
; extract data columns (rows start with name)
if (linespl(1) eq 'name') then begin
linespl2 = strsplit(line, '=', /extract)
linespl3 = strsplit(linespl2[1], ':', /extract)
; column name after '=', before ':'
col = strtrim(linespl3[0], 2)
cols = [cols, col]
; find units (if any, between [])
unit = ''
unita = strsplit(linespl3[1], '[', /extract, count=nunit)
if (nunit gt 1) then begin
unitb = strsplit(unita[1], ']', /extract)
unit = unitb[0]
endif
units = [units, unit]
endif
; find max depth
if (strmatch(line, '*span 0 *')) then begin
tmp = strsplit(line, ',', /extract)
max_depth = strtrim(tmp(1),2)
endif
; find number of values, (lines)
if (strmatch(line, '*nvalues*')) then begin
tmp = strsplit(line, '=', /extract)
nvals = long(tmp(1))
endif
; find NMEA lat/lon/time
if (strmatch(line, '*NMEA*')) then begin
odv_comment = [odv_comment, line]
if (strmatch(line, '*Latitude*')) then begin
tmp = strsplit(line, '=', /extract)
latstr = tmp(1)
endif else begin
if (strmatch(line, '*Longitude*')) then begin
tmp = strsplit(line, '=', /extract)
lonstr =tmp(1)
endif else begin
if (strmatch(line, '*Time*')) then begin
tmp = strsplit(line, '=', /extract)
time =tmp(1)
endif
endelse
endelse
endif
; find missing value
if (strmatch(line, '*bad_flag*')) then begin
tmp = strsplit(line, '=', /extract)
missing =strtrim(tmp(1),2)
endif
; some more odv comments
if (strmatch(line, '\*\* Ship:*')) then begin
odv_comment = [odv_comment, line]
endif
if (strmatch(line, '\*\* Station:*')) then begin
odv_comment = [odv_comment, line]
endif
endif
endwhile
print, tab, 'Time: ',tab, time
print, tab, 'Latitude: ',tab, latstr
print, tab, 'Longitude: ',tab, lonstr
print, tab, 'Number of values: ', tab, nvals
print, tab, 'Max depth: ', tab, max_depth
print, tab, 'Missing value: ', tab, missing
if (downcast) then begin
print, tab, 'Downcast only'
endif
; if calculate transmission from bat add a column + unit
if (calc_trans) then begin
cols = [cols, 'Transmission']
units = [units, '%']
endif
cols = cols[1:*]
ncols = n_elements(cols)
units = units[1:*]
; read in data from cnv file
datalines = strarr(long(nvals))
dataspl = strarr(ncols,long(nvals))
j=0L
while ~ EOF(1) do begin
readf, 1, line
datalines(j) = line
tmp = strsplit(line, ' ', /extract, count=ntmp)
dataspl(0:ntmp-1,j) = tmp
j=j+1
endwhile
close, 1
; calculate transmission if set
if (calc_trans) then begin
; find bat column
bat_col = where(cols eq 'bat', nbat)
if (nbat) then begin
bat = float(dataspl(bat_col, *))
trans = 100. * exp(-1.*bat*0.25)
trans = strtrim(string(trans),2)
dataspl(ncols-1,*) = trans
endif else begin
; no bat found
dataspl(ncols-1,*) = missing
endelse
endif
; write out to odv spreadsheet format
; extract station from file name + create output file name
tmp = strsplit(cnv_file, '/', /extract, count=ntmp)
outfile = strmid(tmp(ntmp-1),0,strlen(tmp(ntmp-1))-4)
station = strmid(outfile, strlen(cruise))
outfile = outdir + outfile + '.txt'
; create required ODV column headers
odv_header = 'Cruise' + tab + 'Station' + tab + 'Type' + tab + $
'yyyy-mm-ddThh:mm:ss' + tab + 'Longitude [degrees_east]' + $
tab + $
'Latitude [degrees_north]' + tab + 'Bot. Depth [m]' + $
tab + 'Depth [m]:PRIMARYVAR'
; create data for required ODV headers (same for each line)
odv_data = cruise + tab + station
type = 'C' ; C or B
if (nvals lt 50) then type = 'B'
odv_data = odv_data + tab + type
; create Date/Time format (yyyy-mm-ddThh:mm:ss)
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', $
'Sep', 'Oct', 'Nov', 'Dec']
datespl = strsplit(time, ' ', /extract)
month = datespl(0)
mm = strtrim(string(where(months eq month) + 1),2)
mm = mm[0]
if (mm lt 10) then mm = '0' + mm
dd = datespl(1)
if (dd lt 10) then dd = '0' + dd
yyyy = datespl(2)
hhmmss = datespl(3)
dateTtime = yyyy + '-' + mm + '-' + dd + 'T' + hhmmss
; create latitude/longitude
latspl = strsplit(latstr, ' ', /extract)
lat = latspl(0) + latspl(1)/60.
if (latspl(2) eq 'S') then lat = -1.*lat
lat = strtrim(string(lat),2)
lonspl = strsplit(lonstr, ' ', /extract)
lon = lonspl(0) +lonspl(1)/60.
if (lonspl(2) eq 'W') then lon = -1.*lon
lon = strtrim(string(lon),2)
odv_data = odv_data + tab + dateTtime + tab + lon + tab + lat + $
tab + max_depth ; add depth later
; get rest of data columns
; do not include duplicate data (latitude, longitude), timeY,
; timeJ)
data_ind = where(cols ne 'latitude' and $
cols ne 'longitude' and cols ne 'timeY' and $
cols ne 'timeJ', ncols2)
; use prDM as depth
depth_ind = where(cols eq 'prDM')
; create data headers
data_header = ''
for k=0,ncols2-1 do begin
l = data_ind(k)
tmp = cols(l)
if (units(l) ne '') then begin
unit = ' [' + units(l) + ']'
tmp = tmp + unit
endif
data_header = data_header + tab + tmp
endfor
header = odv_header + data_header
; replace missing value with ODV missing (-1.e10)
missing_ind = where(datespl eq missing, nmiss)
if (nmiss gt 0) then datespl(missing_ind) = '-1.e10'
; write comments/headers out to file
if (not create_one_file) then begin
print, 'Output to: ', outfile
openw, 10, outfile, width=1000
printf, 10, '//'
for k=1,n_elements(odv_comment)-1 do begin
printf, 10, '//' + odv_comment(k)
endfor
printf, 10, '//'
printf, 10, header
endif
if (create_one_file and first) then begin
printf, 10, '//'
printf, 10, '//'
printf, 10, header
first = 0
endif
if (downcast) then begin
; find where max_depth - convert to float, max(string) = 999...
max_depth_rnd = max(float(dataspl(depth_ind,*)))
ind_md = where(float(dataspl(depth_ind,*)) eq max_depth_rnd)
; add 1 since 1 subtracted in loop
nvals = ind_md[0] + 1
endif
; output data to file
for n=0L,nvals-1L do begin
; add depth to odv_data
odv_data_line = odv_data + tab + dataspl(depth_ind, n)
ctd_data = ''
for p=0,ncols2-1 do begin
l = data_ind(p)
ctd_data = ctd_data + tab + dataspl(l,n)
endfor
printf, 10, odv_data_line + ctd_data
endfor
if (not create_one_file) then begin
close, 10
endif
endif
endfor
if (create_one_file) then begin
close, 10
endif
end