NCCOOS Trac Projects: Top | Web | Platforms | Processing | Viz | Sprints | Sandbox | (Wind)

root/gliderproc/trunk/correctThermalLag.m

Revision 495 (checked in by cbc, 11 years ago)

Initial import of Stark code.

Line 
1 %
2 %  correctThermalLag.m
3 %
4 %  This function receives as input parameter a CTD profile, and applies a
5 %  thermal lag correction on it.
6 %
7 %  The correction applied uses the recursive scheme described in
8 %  Morison, J., R. Andersen, N. Larson, E. D'Asaro, and T. Boyd, 1994:
9 %  The Correction for Thermal-Lag Effects in Sea-Bird CTD Data.
10 %  Journal of Atmospheric and Oceanic Technology, vol. 11, pages 1151�1164.
11 %
12 %  Syntax:
13 %     correctedProfileData = correctThermalLag(basicProfileData)
14 %     correctedProfileData = correctThermalLag(basicProfileData, correctionParams)
15 %     [correctedProfileData, correctionParams] = correctThermalLag(basicProfileData)
16 %
17 %  Inputs:
18 %     basicProfileData - A profile structure*
19 %     correctionParams - The set of parameters to be used in the correction*
20 %     gliderVelocity - Glider velocity from the dbd files (m_speed)
21 %
22 %  Outputs:
23 %     correctedProfileData - A profile structure*
24 %     correctionParams - The set of parameters used in the correction*
25 %
26 %  Profile structure:
27 %     A struct that contains several fields, all of them column vectors with the same length:
28 %       - ptime: Present time instant at which this row was collected
29 %       - depth: Depth (pressure in decibars) measured by the CTD
30 %       - temp: Temperature measured by the CTD
31 %       - cond: Conductivity measured by the CTD
32 %       - pitch: Pitch angle of the glider (optional)
33 %     The output profile has the same information of the input plus two fields with the
34 %     corrected profile properties:
35 %       - condOutCell: corrected conductivity, removing the effects of the
36 %         temperature difference between the outer and inner parts of the
37 %         conductivity cell.
38 %       - tempInCell: corrected temperature, that is, the temperature of
39 %         the water mass lying inside the conductivity cell.
40 %
41 %     From this information, the user can choose which one of the two
42 %     corrections to use in order to compute salinity:
43 %       - Combine 'condOutCell' with 'temp' (Expected values outside of the
44 %         conductivity cell).
45 %       - Combine 'cond' with 'tempInCell' (Expected values inside of the
46 %         conductivity cell).
47 %
48 %  Correction parameters:
49 %     A vector of four elements, consisting of alpha_offset, alpha_slope,
50 %     tau_offset and tau_slope. These parameters are used to compute alpha and tau,
51 %     the amplitude and time constant respectively, which are inversely
52 %     proportional to the flow speed.
53 %
54 %  Example:
55 %     correctedProfileData = correctThermalLag(basicProfileData) corrects the
56 %     profile information contained in the input 'basicProfileData',
57 %     using Morison parameters
58 %
59 %     correctedProfileData = correctThermalLag(basicProfileData, correctionParams)
60 %     corrects the profile information contained in 'basicProfileData',
61 %     using correctionParams as the parameters to be used
62 %     during the correction.
63 %
64 %     [correctedProfileData, correctionParams] = correctThermalLag(basicProfileData)
65 %     corrects the profile information contained in 'basicProfileData', and
66 %     provides in the output the correction parameters used for the correction.
67 %
68 %  Other m-files required: none
69 %  Subfunctions: none
70 %  MAT-files required: none
71 %
72 %  See also: ADJUSTTHERMALLAGPARAMS
73 %
74 %  Author:        Bartolome Garau
75 %  Work address:  Parc Bit, Naorte, Bloc A 2ºp. pta. 3; Palma de Mallorca SPAIN. E-07121
76 %  Author e-mail: tgarau@socib.es
77 %  Website:       http://www.socib.es
78 %  Created:       17-Feb-2011
79 %
80 %//////////////////////////////////////////////////////////////////////////
81
82
83 function [correctedProfileData, varargout] = correctThermalLag(basicProfileData, varargin)
84
85     % Extract the information contained in the profile
86     time  = basicProfileData.ptime;
87     depth = basicProfileData.depth;
88     temp  = basicProfileData.temp;
89     cond  = basicProfileData.cond;
90     if isfield(basicProfileData, 'pitch'),
91         pitch = basicProfileData.pitch * pi / 180;
92     else
93         pitch = (26 * pi / 180) * ones(size(depth));
94     end;
95
96     % Copy the original fields into the output struct
97     correctedProfileData = basicProfileData;
98     if numel(time) <= 1
99         correctedProfileData.condOutCell = correctedProfileData.cond;
100         correctedProfileData.tempInCell  = correctedProfileData.temp;
101         return;
102     end;
103
104     if nargin == 1, % Only basicProfileData is provided as input
105         % These values are proposed in Morison94
106         alpha_offset = 0.0135;
107         alpha_slope  = 0.0264;
108         tau_offset = 7.1499;
109         tau_slope  = 2.7858;
110          
111     elseif nargin == 2, % offset and slope for alpha and tau are also given
112         paramVector  = varargin{1};
113         alpha_offset = paramVector(1);
114         alpha_slope  = paramVector(2);
115         tau_offset = paramVector(3);
116         tau_slope  = paramVector(4);
117        
118     % ADDED 6/13/2012 (William Stark, whs@unc.edu): Allow for glider velocity vector
119     % to be passed in.
120     elseif nargin == 3, % Glider velocity vector is also provided
121         % copy in offset and slope for alpha and tau as before...
122         paramVector  = varargin{1};
123         alpha_offset = paramVector(1);
124         alpha_slope  = paramVector(2);
125         tau_offset = paramVector(3);
126         tau_slope  = paramVector(4);       
127         % copy in glider velocity...
128         gliderVelocity = varargin{2};
129
130     else
131         disp('Incorrect number of parameters. Type ''help correctThermalLag'' for more information');
132         return;
133     end;
134  
135
136     % Some initial precomputations...
137     deltaTime    = abs(diff(time));
138     deltaTemp    =     diff(temp) ;
139     samplingFreq = 1 ./ deltaTime ;
140
141     % Calculate the surge speed from the depth rate and pitch
142     deltaDepth = abs(diff(depth)); % does not matter if downcast or upcast
143     depthRate  = deltaDepth ./ deltaTime;
144     pitchSinus = sin(pitch);
145     surgeSpeed = depthRate ./ pitchSinus(1:end-1);
146
147     % The relative coefficient between the flow speed inside and outside
148     % of the conductivity cell. This is still uncertain (ask Gordon for origin).
149     % Here are three choices for first three orders polynomial.
150     speedFactorPols = [0.00, 0.00, 0.40;  % 0th order degree
151                        0.00, 0.03, 0.45;  % 1st order degree
152                        1.58, 1.15, 0.70]; % 2nd order degree
153
154     selectedDegree = 1; % First order approximation, second row of the matrix
155     speedFactor = polyval(speedFactorPols(selectedDegree+1, :), surgeSpeed);
156
157    
158        
159     % ADDED 6/13/2012 (William Stark, whs@unc.edu): if/else statement added
160     % so that if a glider velocity was passed in it is used as the flow
161     % speed... otherwise the flow speed is calculated using the surge speed
162     % and speed factor as before.
163     if (exist('gliderVelocity')==1), % if glider velocity was passed in
164         % use gliderVelocity as the flow speed
165         flowSpeed = gliderVelocity;
166         % calculation of flow speed using surge speed and speed factor
167         % results in a flow speed vector that is one element shorter. For
168         % this reason we must trim the length of this 'passed-in' flow
169         % speed vector by one...
170         flowSpeed(end) = [];
171        
172     else;  % calculate the flow speed using surge speed and speed factor...
173         % ADDED 6/6/12 (William Stark, whs@unc.edu): set eps=0.01 TO AVOID BLOWUPS WHEN
174         % CALLING THIS FUNCTION DIRECTLY...
175         %flowSpeed = abs(speedFactor .* surgeSpeed) + eps; % Avoid division by zero
176         flowSpeed = abs(speedFactor .* surgeSpeed) + 0.01; % Avoid division by zero
177        
178     end;
179
180        
181     % The alpha and tau parameters, as suggested in the reference paper,
182     % depend on the flow with tne next expressions
183     alpha = alpha_offset + alpha_slope ./ flowSpeed ;
184     tau   =   tau_offset +   tau_slope ./ sqrt(flowSpeed);
185        
186     % Relation between a and b coefficients with respect to alpha and tau
187     coefa = 4 .* samplingFreq .* alpha .* tau ./ (1 + 4 .* samplingFreq .* tau);
188     coefb = 1 - 2 .* coefa ./ alpha;
189
190     % Sensitivity of conductivity with respect to temperature,
191     % approximation suggested by SeaBird: SBE Data Processing User�s Manual
192     % at Section 6: Data Processing Modules, Cell Thermal Mass
193     % Software Release 7.16a and later. Date: 01/18/08
194     % dCdT = 0.1 .* (1 + 0.006 .* (temp - 20));
195     dCdT = 0.088 + 0.0006 * temp;
196    
197     % Recursive processing of the corrections
198     condCorrection = zeros(size(cond));
199     tempCorrection = zeros(size(temp));
200
201     for depthLevel = 1:length(depth)-1,
202         % Compute corrections for next depth level
203         condCorrection(depthLevel+1) = ...
204           - coefb(depthLevel) .* condCorrection(depthLevel) + ...
205             coefa(depthLevel) .* dCdT(depthLevel) .* deltaTemp(depthLevel);
206         tempCorrection(depthLevel+1) = ...
207           - coefb(depthLevel) .* tempCorrection(depthLevel) + ...
208             coefa(depthLevel) .* deltaTemp(depthLevel);
209     end;
210    
211     % Apply corrections and save them as fields in the output struct
212     correctedProfileData.condOutCell = cond + condCorrection;
213     correctedProfileData.tempInCell  = temp - tempCorrection;
214    
215     if nargout == 2, % If required, output alpha and tau offsets and slopes
216         varargout{1} = [alpha_offset, alpha_slope, tau_offset, tau_slope];
217     end;
218     if nargout == 3, % If required, output also alpha and tau parameters
219         varargout{2} = [alpha, tau];
220     end;
221
222     clear gliderVelocity;
223 return;
224
Note: See TracBrowser for help on using the browser.