; 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, '//' + cnv_file + '' 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, '//' + indir + '' 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