PageRenderTime 134ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/Parser/SBE37Parse.m

http://imos-toolbox.googlecode.com/
Objective C | 281 lines | 235 code | 46 blank | 0 comment | 27 complexity | a2cc23747f0a4aab933f883bed2302ba MD5 | raw file
  1. function sample_data = SBE37Parse( filename )
  2. %SBE37PARSE Parse a raw '.asc' file containing SBE37 data, or SBE37-IM hex
  3. % format from OOI (USA).
  4. %
  5. % This function can read in data that has been downloaded from an SBE37
  6. % 'Microcat' temperature/conductivity/pressure sensor.
  7. %
  8. % The output format for the SBE37 is very similar to the SBE39, so this
  9. % function simply delegates the parsing to the SBE3x function, which parses
  10. % data from both instrument types.
  11. %
  12. % Inputs:
  13. % filename - name of the input file to be parsed
  14. %
  15. % Outputs:
  16. % sample_data - struct containing the sample data
  17. %
  18. % Author: Paul McCarthy <paul.mccarthy@csiro.au>
  19. % Contributor: Guillaume Galibert <guillaume.galibert@utas.edu.au>
  20. %
  21. % See SBE3x.m
  22. %
  23. %
  24. % Copyright (c) 2009, eMarine Information Infrastructure (eMII) and Integrated
  25. % Marine Observing System (IMOS).
  26. % All rights reserved.
  27. %
  28. % Redistribution and use in source and binary forms, with or without
  29. % modification, are permitted provided that the following conditions are met:
  30. %
  31. % * Redistributions of source code must retain the above copyright notice,
  32. % this list of conditions and the following disclaimer.
  33. % * Redistributions in binary form must reproduce the above copyright
  34. % notice, this list of conditions and the following disclaimer in the
  35. % documentation and/or other materials provided with the distribution.
  36. % * Neither the name of the eMII/IMOS nor the names of its contributors
  37. % may be used to endorse or promote products derived from this software
  38. % without specific prior written permission.
  39. %
  40. % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  41. % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  43. % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  44. % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  45. % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  46. % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  47. % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  48. % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  49. % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  50. % POSSIBILITY OF SUCH DAMAGE.
  51. %
  52. % ensure that there is exactly one argument,
  53. % and that it is a cell array of strings
  54. error(nargchk(1,1,nargin));
  55. if ~iscellstr(filename), error('filename must be a cell array of strings'); end
  56. % only one file supported currently
  57. filename = filename{1};
  58. if ~ischar(filename), error('filename must contain a string'); end
  59. [~, ~, ext] = fileparts(filename);
  60. % read first line in the file
  61. line = '';
  62. try
  63. fid = fopen(filename, 'rt');
  64. line = fgetl(fid);
  65. fclose(fid);
  66. catch e
  67. if fid ~= -1, fclose(fid); end
  68. rethrow(e);
  69. end
  70. if strcmpi(ext, '.DAT') && strcmp(line, '//Status Information')
  71. % try to read SBE37-IM hex format from OOI (USA)
  72. % read in every line in the file, separating
  73. % them out into each of the three sections
  74. instHeaderLines = {};
  75. dataLines = {};
  76. try
  77. fid = fopen(filename, 'rt');
  78. line = fgetl(fid);
  79. header = false;
  80. dataBody = false;
  81. while ischar(line)
  82. line = deblank(line);
  83. if isempty(line)
  84. line = fgetl(fid);
  85. continue;
  86. end
  87. if strcmp(line, '//Status Information')
  88. header = true;
  89. dataBody = false;
  90. line = fgetl(fid);
  91. continue;
  92. elseif strcmp(line, '//Begin Data')
  93. header = false;
  94. dataBody = true;
  95. line = fgetl(fid);
  96. continue;
  97. elseif strcmp(line, '//End Data')
  98. break;
  99. end
  100. if header
  101. instHeaderLines{end+1} = line;
  102. elseif dataBody
  103. dataLines{ end+1} = line;
  104. end
  105. line = fgetl(fid);
  106. end
  107. fclose(fid);
  108. catch e
  109. if fid ~= -1, fclose(fid); end
  110. rethrow(e);
  111. end
  112. % read in the raw instrument header
  113. instHeader = parseInstrumentHeader(instHeaderLines);
  114. data = readSBE37hex(dataLines, instHeader);
  115. % create sample data struct,
  116. % and copy all the data in
  117. sample_data = struct;
  118. sample_data.toolbox_input_file = filename;
  119. sample_data.meta.instHeader = instHeader;
  120. sample_data.meta.instrument_make = 'Seabird';
  121. if isfield(instHeader, 'instrument_model')
  122. sample_data.meta.instrument_model = instHeader.instrument_model;
  123. else
  124. sample_data.meta.instrument_model = 'SBE37';
  125. end
  126. if isfield(instHeader, 'instrument_firmware')
  127. sample_data.meta.instrument_firmware = instHeader.instrument_firmware;
  128. else
  129. sample_data.meta.instrument_firmware = '';
  130. end
  131. if isfield(instHeader, 'instrument_serial_no')
  132. sample_data.meta.instrument_serial_no = instHeader.instrument_serial_no;
  133. else
  134. sample_data.meta.instrument_serial_no = '';
  135. end
  136. if isfield(instHeader, 'sampleInterval')
  137. sample_data.meta.instrument_sample_interval = instHeader.sampleInterval;
  138. else
  139. sample_data.meta.instrument_sample_interval = median(diff(data.TIME*24*3600));
  140. end
  141. sample_data.dimensions = {};
  142. sample_data.variables = {};
  143. % dimensions creation
  144. sample_data.dimensions{1}.name = 'TIME';
  145. % generate time data from header information
  146. sample_data.dimensions{1}.data = data.TIME;
  147. sample_data.dimensions{2}.name = 'LATITUDE';
  148. sample_data.dimensions{2}.data = NaN;
  149. sample_data.dimensions{3}.name = 'LONGITUDE';
  150. sample_data.dimensions{3}.data = NaN;
  151. % scan through the list of parameters that were read
  152. % from the file, and create a variable for each
  153. vars = fieldnames(data);
  154. for k = 1:length(vars)
  155. if strncmp('TIME', vars{k}, 4), continue; end
  156. % dimensions definition must stay in this order : T, Z, Y, X, others;
  157. % to be CF compliant
  158. sample_data.variables{end+1}.dimensions = [1 2 3];
  159. sample_data.variables{end }.name = vars{k};
  160. sample_data.variables{end }.data = data.(vars{k});
  161. if strncmp('PRES_REL', vars{k}, 8)
  162. % let's document the constant pressure atmosphere offset previously
  163. % applied by SeaBird software on the absolute presure measurement
  164. sample_data.variables{end }.applied_offset = -14.7*0.689476;
  165. end
  166. end
  167. else
  168. % use the classic SBE3x ASCII format suggested for IMOS
  169. sample_data = SBE3x(filename);
  170. end
  171. end
  172. function header = parseInstrumentHeader(headerLines)
  173. %PARSEINSTRUMENTHEADER Parses the header lines from a SBE37-IM .DAT file.
  174. % Returns the header information in a struct.
  175. %
  176. % Inputs:
  177. % headerLines - cell array of strings, the lines of the header section.
  178. %
  179. % Outputs:
  180. % header - struct containing information that was in the header
  181. % section.
  182. %
  183. header = struct;
  184. % there's no real structure to the header information, which
  185. % is annoying. my approach is to use various regexes to search
  186. % for info we want, and to ignore everything else. inefficient,
  187. % but it's the nicest way i can think of
  188. headerExpr = 'SBE(\S+)\s+(\S+)\s+SERIAL NO.\s+(\d+)';
  189. memExpr = 'samplenumber = (\d+), free = (\d+)';
  190. sampleExpr = 'sample interval = (\d+) seconds';
  191. pressureExpr = 'PressureRange = (\d+)';
  192. outputExpr = '//Data Format: (\S+)';
  193. otherExpr = '([^\s=]+)\s*=\s*([^\s=]+)';
  194. exprs = {headerExpr memExpr sampleExpr ...
  195. pressureExpr outputExpr otherExpr};
  196. for l = 1:length(headerLines)
  197. % try each of the expressions
  198. for m = 1:length(exprs)
  199. % until one of them matches
  200. tkns = regexp(headerLines{l}, exprs{m}, 'tokens');
  201. if ~isempty(tkns)
  202. % yes, ugly, but easiest way to figure out which regex we're on
  203. switch m
  204. % header
  205. case 1
  206. header.instrument_model = ['SBE' tkns{1}{1}];
  207. header.instrument_firmware = tkns{1}{2};
  208. header.instrument_serial_no = tkns{1}{3};
  209. % mem
  210. case 2
  211. header.numSamples = str2double(tkns{1}{1});
  212. header.freeMem = str2double(tkns{1}{2});
  213. % sample
  214. case 3
  215. header.sampleInterval = str2double(tkns{1}{1});
  216. % pressure
  217. case 4
  218. header.PressureRange = str2double(tkns{1}{1});
  219. % output
  220. case 5
  221. header.outputFormat = tkns{1}{1};
  222. % name = value
  223. case 6
  224. for i=1:length(tkns)
  225. name = genvarname(tkns{i}{1});
  226. value = tkns{i}{2};
  227. if strcmpi(value(end), ','), value = value(1:end-1); end
  228. header.(name) = value;
  229. end
  230. end
  231. break;
  232. end
  233. end
  234. end
  235. end