Newer
Older
gael.alory_legos.obs-mip.fr
committed
function [error] = corTsgGradient(hMainFig, PARA, dateMin, dateMax)
% Correct the TSG salinity time series with the Water sample.
% The correction is a linear interpolation of the sample/tsg difference
% between 2 dates as a function of salinity or temperature (NOT time)
% Only adviced when the sample/tsg difference shifts suddenly when
% crossing a strong salinity gradient, to avoid a correction discontinuity
%
% Input
% hMainFig ..... Handle to the main GUI
% PARA ..........Cell array
% PARA{1} contains the characters (SSP, SSJT, SSTP)
% PARA{2} contains either the cahracters (SSPS, SSJT, SSTP)
% or (SSPS_CAL, SSJT_CAL, SSTP_CAL)
% dateMin ...... the correction is applied between dateMin and date Max
% dateMax ...... the correction is applied between dateMin and date Max
%
% Output
% Error ........ 1 everything OK
% ........ -1 dateMax <= date Min
%
% 2009/12/01 G. Alory
% This method is adapted from G. Reverdin, and used when Nuka Arctica
% crosses the salinity front at the southern tip of Groenland
%
gael.alory_legos.obs-mip.fr
committed
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
% Get application data
% --------------------
tsg = getappdata( hMainFig, 'tsg_data');
SAMPLE = tsg.plot.sample;
% -------------------------------------------------------------------------
% Get from the checkbox the QC code on which the correction will be applied
% -------------------------------------------------------------------------
% get list of keys from hashtable tsg.qc.hash, defined inside
% tsg_initialisation.m
% -----------------------------------------------------------
qc_list = keys(tsg.qc.hash);
% TODO: define size of keptCode
% -----------------------------
%keptCode = zeros(numel(qc_list), 1);
% iterate (loop) on each key store inside hastable
% ------------------------------------------------
keptCode = [];
nKeptCode = 0;
for key = qc_list
% get handle of checkbox
% ----------------------
hCb = findobj(hMainFig, 'tag', ['TAG_CHECK_CORRECTION_' char(key)]);
if get( hCb, 'value' )
nKeptCode = nKeptCode + 1;
keptCode(nKeptCode) = tsg.qc.hash.(key).code;
end
end
% Get PROBABLY_GOOD, PROBABLY_BAD and VALUE_CHANGED codes
% -------------------------------------------------------
PROBABLY_GOOD = tsg.qc.hash.PROBABLY_GOOD.code;
PROBABLY_BAD = tsg.qc.hash.PROBABLY_BAD.code;
VALUE_CHANGED = tsg.qc.hash.VALUE_CHANGED.code;
% Intialisation
% 01/09/2009 : intialisation to NaN for real and 0 for byte (QC)
% BE CAREFUL:
% netcdf toolbox failed with assertion when we write NaN to ncbyte variable
% -------------------------------------------------------------------------
if isempty( tsg.([PARA{1} '_ADJUSTED_ERROR']) )
tsg.([PARA{1} '_ADJUSTED']) = NaN*ones(size(tsg.(PARA{1})));
tsg.([PARA{1} '_ADJUSTED_QC']) = zeros(size(tsg.([PARA{1} '_QC'])));
tsg.([PARA{1} '_ADJUSTED_ERROR']) = NaN*ones(size(tsg.(PARA{1})));
end
if dateMax > dateMin
% Find samples within TIME_WINDOWS with Good, probably Good, QC
% -------------------------------------------------------------
ind = find( tsg.DAYD_EXT >= dateMin & tsg.DAYD_EXT <= dateMax &...
tsg.([SAMPLE '_EXT_QC']) <= PROBABLY_GOOD);
if ~isempty(ind)
% detect NaN in sample.SSPS_DIF due to bad QC code for tsg.SSPS
% -------------------------------------------------------------
ind2 = find(~isnan(tsg.EXT_DIF(ind)));
if ~isempty(ind2) && length(ind2) >= 2
% Locate front with big shift in TSG/sample difference
% -------------------------------------------------------------
% tsg_diff=diff(tsg.EXT_SMOOTH(ind(ind2)));
% corr_diff=diff(tsg.EXT_DIF(ind(ind2)));
% The correction is applied to the TSG between dateMin and dateMax using
% a linear interpolation only on measurements with keptCode Quality Codes
% ------------------------------------------------------------------------
dtTsgQCkept=[];
for icode = 1 : length( keptCode )
dtTsg = find( tsg.DAYD >= tsg.DAYD_EXT(ind(ind2(1))) & tsg.DAYD <= tsg.DAYD_EXT(ind(ind2(end))) &...
tsg.([PARA{1} '_QC']) == keptCode( icode ));
if ~isempty( dtTsg )
dtTsgQCkept=[dtTsgQCkept; dtTsg];
% Compute the correction + the error
% ----------------------------------
tsg_diff=diff(tsg.EXT_SMOOTH(ind(ind2)));
for iint=1:(length(ind2)-1)
% in each interval between 2 samples, the correction is a linear interpolation
% of the sample/tsg difference as a function of Tsg SSPS or SSTP,
% the error an interpolation of 0.5*abs(sample/tsg diff.)
dtTsg2 = find( tsg.DAYD(dtTsg) >= tsg.DAYD_EXT(ind(ind2(iint))) &...
tsg.DAYD(dtTsg) <= tsg.DAYD_EXT(ind(ind2(iint+1))) &...
tsg.([PARA{1} '_QC'])(dtTsg) == keptCode( icode ));
if ~isempty(dtTsg2)
gael.alory_legos.obs-mip.fr
committed
tsg_rel=(tsg.(PARA{2})(dtTsg(dtTsg2))-tsg.EXT_SMOOTH(ind(ind2(iint))))/tsg_diff(iint);
gael.alory_legos.obs-mip.fr
committed
tsg_rel(tsg_rel<0)=0;
tsg_rel(tsg_rel>1)=1;
tsg.([PARA{1} '_ADJUSTED'])(dtTsg(dtTsg2)) =...
gael.alory_legos.obs-mip.fr
committed
(1-tsg_rel)*tsg.EXT_DIF(ind(ind2(iint))) + tsg_rel*tsg.EXT_DIF(ind(ind2(iint+1)));
gael.alory_legos.obs-mip.fr
committed
tsg.([PARA{1} '_ADJUSTED_ERROR'])(dtTsg(dtTsg2)) =...
gael.alory_legos.obs-mip.fr
committed
(1-tsg_rel)*abs(tsg.EXT_DIF(ind(ind2(iint)))/2) + tsg_rel*abs(tsg.EXT_DIF(ind(ind2(iint+1)))/2);
gael.alory_legos.obs-mip.fr
committed
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
% Compute the corrected value : original value + correction
% ---------------------------------------------------------
tsg.([PARA{1} '_ADJUSTED'])(dtTsg(dtTsg2)) =...
tsg.(PARA{2})(dtTsg(dtTsg2)) + tsg.([PARA{1} '_ADJUSTED'])(dtTsg(dtTsg2));
end
end
% Transfer the QC
% ---------------
tsg.([PARA{1} '_ADJUSTED_QC'])(dtTsg) = tsg.([PARA{1} '_QC'])(dtTsg);
end
end
% The error minimum cannot be lower than the sensor accuracy
% ----------------------------------------------------------
accuracy= tsg_accuracy(hMainFig, PARA{1},dtTsgQCkept );
error_too_small=find(abs(tsg.([PARA{1} '_ADJUSTED_ERROR'])(dtTsgQCkept)) < accuracy);
if ~isempty(error_too_small)
if length(ind2) > 2
tsg.([PARA{1} '_ADJUSTED_ERROR'])(dtTsgQCkept(error_too_small))=accuracy(error_too_small);
else
tsg.([PARA{1} '_ADJUSTED_ERROR'])(dtTsgQCkept(error_too_small))=-accuracy(error_too_small);
end
end
% Case with 1 sample only: we can't apply this correction
% --------------------------------------------------------------------------
gael.alory_legos.obs-mip.fr
committed
else
gael.alory_legos.obs-mip.fr
committed
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
msgbox( {'Function corTsgGradient'; ' '; ...
'At least 2 samples are needed';...
'The soft cannot make the interpolation'},...
'Correction Method', 'warn');
error = -1;
return
end
end
% Update tsg application data
% ---------------------------
setappdata( hMainFig, 'tsg_data', tsg);
% everything OK
% -------------
error = 1;
else
% DateMax <= DateMin
% ------------------
error = -1;
end