0001 function [data_proc, meta_proc] = processGliderData(data_pre, meta_pre, varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360 error(nargchk(2, 56, nargin, 'struct'));
0361
0362
0363 default_profiling_time = [];
0364 default_profiling_stall = 3;
0365 default_profiling_shake = 20;
0366 default_profiling_inversion = 3;
0367 default_profiling_interrupt = 180;
0368 default_profiling_length = 10;
0369 default_profiling_period = 0;
0370
0371
0372
0373 default_sensor_lag_time_list = {'time'};
0374 default_sensor_lag_depth_list = {'depth'};
0375 default_sensor_lag_flow_list = {'flow_ctd'};
0376 default_sensor_lag_flow_const = false;
0377 default_sensor_lag_estimator = @nanmedian;
0378 default_sensor_lag_minopts = struct();
0379
0380
0381
0382 default_thermal_lag_time_list = {'time_ctd' 'time'};
0383 default_thermal_lag_depth_list = {'depth_ctd' 'depth'};
0384 default_thermal_lag_flow_list = {'flow_ctd'};
0385 default_thermal_lag_flow_const = false;
0386 default_thermal_lag_estimator = @nanmedian;
0387 default_thermal_lag_minopts = struct();
0388
0389
0390
0391 options = struct();
0392 options.time_filling = false;
0393 options.position_filling = false;
0394 options.depth_filling = false;
0395 options.attitude_filling = false;
0396 options.heading_filling = false;
0397 options.waypoint_filling = false;
0398
0399 options.pressure_filtering = true;
0400 options.pressure_filter_constant = 4;
0401 options.depth_ctd_derivation = true;
0402
0403 options.profiling_list = ...
0404 struct('depth', {'depth' 'depth_ctd' 'depth_ctd'}, ...
0405 'time', {'time' 'time_ctd' 'time'});
0406
0407 options.profiling_sequence_list = [];
0408 options.profiling_sequence_filling = [];
0409 options.profile_join_same_dir = [];
0410
0411 options.profile_min_range = 10;
0412 options.profile_max_gap_ratio = 0.8;
0413
0414 options.flow_ctd_list = struct('time', {}, 'depth', {}, 'pitch', {});
0415 options.flow_ctd_pitch_value = [];
0416 options.flow_ctd_min_pitch = 0;
0417 options.flow_ctd_min_velocity = 0;
0418
0419 options.sensor_lag_list = ...
0420 struct('corrected', {}, 'original', {}, 'parameters', {});
0421
0422 options.thermal_lag_list = ...
0423 struct('conductivity_corrected', {'conductivity_corrected_thermal'}, ...
0424 'temperature_corrected', {'temperature_corrected_thermal'}, ...
0425 'conductivity_original', {'conductivity'}, ...
0426 'temperature_original', {'temperature'}, ...
0427 'pressure_original', {'pressure'}, ...
0428 'parameters', {'auto'} );
0429
0430 options.salinity_list = ...
0431 struct('salinity', {'salinity' 'salinity_corrected_thermal'}, ...
0432 'conductivity', {'conductivity' 'conductivity'}, ...
0433 'temperature', {'temperature' 'temperature_corrected_thermal'}, ...
0434 'pressure', {'pressure' 'pressure'});
0435
0436 options.density_list = ...
0437 struct('density', {'density' 'density_corrected_thermal'}, ...
0438 'salinity', {'salinity' 'salinity_corrected_thermal'}, ...
0439 'temperature', {'temperature' 'temperature'}, ...
0440 'pressure', {'pressure' 'pressure'});
0441
0442
0443
0444
0445 if isscalar(varargin) && isstruct(varargin{1})
0446
0447
0448 option_key_list = fieldnames(varargin{1});
0449 option_val_list = struct2cell(varargin{1});
0450 elseif mod(numel(varargin), 2) == 0
0451
0452 option_key_list = varargin(1:2:end);
0453 option_val_list = varargin(2:2:end);
0454 else
0455 error('glider_toolbox:processGliderData:InvalidOptions', ...
0456 'Invalid optional arguments (neither key-value pairs nor struct).');
0457 end
0458
0459 for opt_idx = 1:numel(option_key_list)
0460 opt = lower(option_key_list{opt_idx});
0461 val = option_val_list{opt_idx};
0462 if isfield(options, opt)
0463 options.(opt) = val;
0464 else
0465 error('glider_toolbox:processGliderData:InvalidOption', ...
0466 'Invalid option: %s.', opt);
0467 end
0468 end
0469
0470
0471
0472
0473 if ~isempty(options.profiling_sequence_list) ...
0474 || ~isempty(options.profiling_sequence_filling) ...
0475 || ~isempty(options.profile_join_same_dir)
0476 warning('glider_toolbox:findProfiles:DeprecatedOption', ...
0477 'Deprecated option: %s, %s and %s. See option: %s.', ...
0478 'profiling_sequence_list', 'profiling_sequence_filling', ...
0479 'profile_join_same_dir', 'profiling_list');
0480 options.profiling_list = ...
0481 struct('depth', options.profiling_sequence_list, ...
0482 'stall', options.profile_min_range, ...
0483 'interrupt', options.join * inf, ...
0484 'inversion', options.join * inf);
0485 end
0486
0487
0488
0489 data_proc = data_pre;
0490 meta_proc = meta_pre;
0491
0492
0493
0494
0495 if options.time_filling && isfield(data_proc, 'time')
0496 fprintf('Filling missing time readings...\n');
0497 data_proc.time = ...
0498 fillInvalidValues(data_proc.time, 'linear');
0499 meta_proc.time.filling = 'linear';
0500 end
0501
0502
0503
0504
0505 if options.position_filling ...
0506 && all(isfield(data_proc, {'latitude' 'longitude'})) ...
0507 && any(isfield(data_proc, {'time' 'time_position'}))
0508 fprintf('Filling missing position readings...\n');
0509 if isfield(data_proc, 'time_position')
0510 data_proc.latitude = ...
0511 fillInvalidValues(data_proc.time_position, data_proc.latitude, ...
0512 data_proc.time, nan(size(data_proc.time)), 'linear');
0513 data_proc.longitude = ...
0514 fillInvalidValues(data_proc.time_position, data_proc.longitude, ...
0515 data_proc.time, nan(size(data_proc.time)), 'linear');
0516 meta_proc.latitude.sources = ...
0517 vertcat(cellstr(meta_proc.longitude.sources), ...
0518 cellstr(meta_proc.time.sources));
0519 meta_proc.longitude.sources = ...
0520 vertcat(cellstr(meta_proc.longitude.sources), ...
0521 cellstr(meta_proc.time.sources));
0522 else
0523 data_proc.latitude = ...
0524 fillInvalidValues(data_proc.time, data_proc.latitude, 'linear');
0525 data_proc.longitude = ...
0526 fillInvalidValues(data_proc.time, data_proc.longitude, 'linear');
0527 end
0528 meta_proc.latitude.filling = 'linear';
0529 meta_proc.longitude.filling = 'linear';
0530 end
0531
0532
0533
0534
0535 if options.depth_filling && all(isfield(data_proc, {'time' 'depth'}))
0536 fprintf('Filling missing depth readings...\n');
0537 data_proc.depth = ...
0538 fillInvalidValues(data_proc.time, data_proc.depth, 'linear');
0539 meta_proc.depth.filling = 'linear';
0540 end
0541
0542
0543
0544
0545 if options.attitude_filling && ...
0546 all(isfield(data_proc, {'time' 'roll' 'pitch'}))
0547 fprintf('Filling missing attitude readings...\n');
0548 data_proc.roll = ...
0549 fillInvalidValues(data_proc.time, data_proc.roll, 'linear');
0550 data_proc.pitch = ...
0551 fillInvalidValues(data_proc.time, data_proc.pitch, 'linear');
0552 meta_proc.roll.filling = 'linear';
0553 meta_proc.pitch.filling = 'linear';
0554 end
0555
0556
0557
0558
0559 if options.heading_filling && all(isfield(data_proc, {'time' 'heading'}))
0560 fprintf('Filling missing heading readings...\n');
0561 data_proc.heading = ...
0562 fillInvalidValues(data_proc.time, data_proc.heading, 'linear');
0563 meta_proc.heading.filling = 'linear';
0564 end
0565
0566
0567
0568
0569
0570 if options.waypoint_filling ...
0571 && all(isfield(data_proc, {'waypoint_latitude' 'waypoint_longitude'}))
0572 fprintf('Filling missing commanded waypoint readings...\n');
0573 data_proc.waypoint_latitude = ...
0574 fillInvalidValues(data_proc.waypoint_latitude, 'prev');
0575 data_proc.waypoint_longitude = ...
0576 fillInvalidValues(data_proc.waypoint_longitude, 'prev');
0577 meta_proc.waypoint_latitude.filling = 'prev';
0578 meta_proc.waypoint_longitude.filling = 'prev';
0579 end
0580
0581
0582
0583 if all(isfield(data_proc, {'waypoint_latitude' 'waypoint_longitude'}))
0584 fprintf('Computing transect index by transect boundary identification...\n');
0585 data_proc.transect_index = ...
0586 findTransects(data_proc.waypoint_latitude, data_proc.waypoint_longitude);
0587 meta_proc.transect_index.sources = ...
0588 {'waypoint_latitude' 'waypoint_longitude'}';
0589 meta_proc.transect_index.method = 'findTransects';
0590 end
0591
0592
0593
0594 if all(isfield(data_proc, {'latitude' 'longitude'}))
0595 fprintf('Computing covered horizontal distance...\n');
0596 data_proc.distance_over_ground = ...
0597 computeCumulativeDistance(data_proc.latitude, data_proc.longitude);
0598 meta_proc.distance_over_ground.sources = {'latitude' 'longitude'}';
0599 meta_proc.distance_over_ground.method = 'computeCumulativeDistance';
0600 end
0601
0602
0603
0604 if isfield(data_proc, 'pressure')
0605
0606 if options.pressure_filtering
0607 if isfield(data_proc, 'time_ctd')
0608 fprintf('Filtering pressure sequence using CTD time stamp...\n');
0609 data_proc.pressure = ...
0610 applySeabirdPressureFilter(data_proc.time_ctd, data_proc.pressure, ...
0611 options.pressure_filter_constant);
0612 meta_proc.pressure.sources = ...
0613 vertcat(cellstr(meta_proc.pressure.sources), ...
0614 cellstr(meta_proc.time_ctd.sources));
0615 elseif isfield(data_proc, 'time')
0616 fprintf('Filtering pressure sequence using global time stamp...\n');
0617 data_proc.pressure = ...
0618 applySeabirdPressureFilter(data_proc.time, data_proc.pressure, ...
0619 options.pressure_filter_constant);
0620 meta_proc.pressure.sources = ...
0621 vertcat(cellstr(meta_proc.pressure.sources), ...
0622 cellstr(meta_proc.time.sources));
0623 end
0624 meta_proc.pressure.filter_method = 'applySeabirdPressureFilter';
0625 meta_proc.pressure.filter_parameters = options.pressure_filter_constant;
0626 end
0627 end
0628
0629
0630
0631 if options.depth_ctd_derivation ...
0632 && all(isfield(data_proc, {'pressure' 'latitude'}))
0633 fprintf('Deriving CTD depth from pressure and latitude readings...\n');
0634 data_proc.depth_ctd = sw_dpth(data_proc.pressure, data_proc.latitude);
0635 meta_proc.depth_ctd.sources = {'pressure' 'latitude'}';
0636 meta_proc.depth_ctd.method = 'sw_depth';
0637 end
0638
0639
0640
0641
0642
0643
0644
0645 profiling_avail = false;
0646 for profiling_option_idx = 1:numel(options.profiling_list)
0647 profiling_option = options.profiling_list(profiling_option_idx);
0648 profiling_depth = profiling_option.depth;
0649 profiling_time = default_profiling_time;
0650 profiling_stall = default_profiling_stall;
0651 profiling_shake = default_profiling_shake;
0652 profiling_inversion = default_profiling_inversion;
0653 profiling_interrupt = default_profiling_interrupt;
0654 profiling_length = default_profiling_length;
0655 profiling_period = default_profiling_period;
0656 if isfield(profiling_option, 'time') && ~isempty(profiling_option.time)
0657 profiling_time = profiling_option.time;
0658 end
0659 if isfield(profiling_option, 'stall') && ~isempty(profiling_option.stall)
0660 profiling_stall = profiling_option.stall;
0661 end
0662 if isfield(profiling_option, 'shake') && ~isempty(profiling_option.shake)
0663 profiling_shake = profiling_option.shake;
0664 end
0665 if isfield(profiling_option, 'inversion') ...
0666 && ~isempty(profiling_option.inversion)
0667 profiling_inversion = profiling_option.inversion;
0668 end
0669 if isfield(profiling_option, 'interrupt') ...
0670 && ~isempty(profiling_option.interrupt)
0671 profiling_interrupt = profiling_option.interrupt;
0672 end
0673 if isfield(profiling_option, 'length') && ~isempty(profiling_option.length)
0674 profiling_length = profiling_option.legnth;
0675 end
0676 if isfield(profiling_option, 'preiod') && ~isempty(profiling_option.period)
0677 profiling_period = profiling_option.period;
0678 end
0679 profiling_depth_avail = false;
0680 profiling_time_avail = false;
0681 if isfield(data_proc, profiling_depth) ...
0682 && ~all(isnan(data_proc.(profiling_depth)))
0683 profiling_depth_avail = true;
0684 end
0685 if isfield(data_proc, profiling_time) ...
0686 && any(data_proc.(profiling_time) > 0)
0687 profiling_time_avail = true;
0688 end
0689 if profiling_depth_avail
0690 if isempty(profiling_time)
0691 profiling_vars = {data_proc.(profiling_depth)};
0692 profiling_avail = true;
0693 break
0694 elseif profiling_time_avail
0695 profiling_vars = ...
0696 {data_proc.(profiling_time) data_proc.(profiling_depth)};
0697 profiling_avail = true;
0698 break
0699 end
0700 end
0701 end
0702
0703 if profiling_avail
0704 fprintf('Computing vertical direction and profile index with settings:\n');
0705 fprintf(' vertical sequence: %s\n', profiling_depth);
0706 if profiling_time_avail
0707 fprintf(' horizontal sequence: %s\n', profiling_time);
0708 end
0709 fprintf(' maximum profile stall : %f\n', profiling_stall);
0710 fprintf(' maximum profile shake : %f\n', profiling_shake);
0711 fprintf(' maximum profile inversion : %f\n', profiling_inversion);
0712 fprintf(' maximum profile interrupt : %f\n', profiling_interrupt);
0713 fprintf(' minimum profile length : %f\n', profiling_length);
0714 fprintf(' minimum profile period : %f\n', profiling_period);
0715
0716 [data_proc.profile_index, data_proc.profile_direction] = findProfiles( ...
0717 profiling_vars{:}, ...
0718 'stall', profiling_stall, 'shake', profiling_shake, ...
0719 'inversion', profiling_inversion, 'interrupt', profiling_interrupt, ...
0720 'length', profiling_length, 'period', profiling_period);
0721 meta_proc.profile_index.method = 'findProfiles';
0722 if profiling_time_avail
0723 meta_proc.profile_index.sources = {profiling_time profiling_depth};
0724 else
0725 meta_proc.profile_index.sources = {profiling_depth};
0726 end
0727 meta_proc.profile_index.shake = profiling_shake;
0728 meta_proc.profile_index.stall = profiling_stall;
0729 meta_proc.profile_index.inversion = profiling_inversion;
0730 meta_proc.profile_index.interrupt = profiling_interrupt;
0731 meta_proc.profile_index.length = profiling_length;
0732 meta_proc.profile_index.period = profiling_period;
0733 meta_proc.profile_direction.method = meta_proc.profile_index.method;
0734 meta_proc.profile_direction.sources = meta_proc.profile_index.sources;
0735 meta_proc.profile_direction.shake = meta_proc.profile_index.shake;
0736 meta_proc.profile_direction.stall = meta_proc.profile_index.stall;
0737 meta_proc.profile_direction.inversion = meta_proc.profile_index.inversion;
0738 meta_proc.profile_direction.interrupt = meta_proc.profile_index.interrupt;
0739 meta_proc.profile_direction.length = meta_proc.profile_index.length;
0740 meta_proc.profile_direction.period = meta_proc.profile_index.period;
0741 end
0742
0743
0744
0745
0746
0747
0748 flow_ctd_avail = false;
0749 flow_ctd_pitch_value_avail = ~isempty(options.flow_ctd_pitch_value);
0750 for flow_ctd_option_idx = 1:numel(options.flow_ctd_list)
0751 flow_ctd_option = options.flow_ctd_list(flow_ctd_option_idx);
0752 flow_ctd_time_avail = false;
0753 flow_ctd_depth_avail = false;
0754 flow_ctd_pitch_avail = false;
0755 if isfield(data_proc, flow_ctd_option.time) ...
0756 && any(data_proc.(flow_ctd_option.time) > 0)
0757 flow_ctd_time = flow_ctd_option.time;
0758 flow_ctd_time_avail = true;
0759 end
0760 if isfield(data_proc, flow_ctd_option.depth) ...
0761 && ~all(isnan(data_proc.(flow_ctd_option.depth)))
0762 flow_ctd_depth = flow_ctd_option.depth;
0763 flow_ctd_depth_avail = true;
0764 end
0765 if isfield(flow_ctd_option, 'pitch') ...
0766 && isfield(data_proc, flow_ctd_option.pitch) ...
0767 && ~all(isnan(data_proc.(flow_ctd_option.pitch)))
0768 flow_ctd_pitch = flow_ctd_option.pitch;
0769 flow_ctd_pitch_avail = true;
0770 end
0771 if flow_ctd_time_avail && flow_ctd_depth_avail ...
0772 && (flow_ctd_pitch_avail || flow_ctd_pitch_value_avail)
0773 flow_ctd_avail = true;
0774 break
0775 end
0776 end
0777 flow_ctd_prof_avail = isfield(data_proc, 'profile_index');
0778 if flow_ctd_prof_avail && flow_ctd_avail
0779 fprintf('Deriving CTD flow speed with settings:\n');
0780 fprintf(' depth sequence: %s\n', flow_ctd_depth);
0781 fprintf(' time sequence: %s\n', flow_ctd_time);
0782 if flow_ctd_pitch_avail
0783 fprintf(' pitch sequence: %s\n', flow_ctd_pitch);
0784 else
0785 fprintf(' pitch value : %f\n', options.flow_ctd_pitch_value);
0786 end
0787 fprintf(' pitch minimum threshold : %f\n', options.flow_ctd_min_pitch);
0788 fprintf(' vertical velocity minimum threshold: %f\n', options.flow_ctd_min_velocity);
0789 data_proc.flow_ctd = nan(size(data_proc.time));
0790 num_profiles = fix(max(data_proc.profile_index));
0791 for profile_idx = 1:num_profiles
0792 prof_select = (data_proc.profile_index == profile_idx);
0793 prof_time = data_proc.(flow_ctd_time)(prof_select);
0794 prof_depth = data_proc.(flow_ctd_depth)(prof_select);
0795 if flow_ctd_pitch_avail
0796 prof_pitch = data_proc.(flow_ctd_pitch)(prof_select);
0797 prof_vars = {prof_time(:) prof_pitch(:)};
0798 else
0799 prof_pitch = options.flow_ctd_pitch_value;
0800 prof_vars = {prof_time(:)};
0801 end
0802 [prof_valid, ~] = validateProfile(prof_depth(:), prof_vars{:}, ...
0803 'range', options.profile_min_range, ...
0804 'gap', options.profile_max_gap_ratio);
0805 if prof_valid
0806 data_proc.flow_ctd(prof_select) = ...
0807 computeCTDFlowSpeed(prof_time, prof_depth, prof_pitch, ...
0808 'minpitch', options.flow_ctd_min_pitch, ...
0809 'minvel', options.flow_ctd_min_velocity);
0810 end
0811 end
0812 if flow_ctd_pitch_avail
0813 meta_proc.flow_ctd.sources = ...
0814 {flow_ctd_time flow_ctd_depth flow_ctd_pitch 'profile_index'}';
0815 else
0816 meta_proc.flow_ctd.sources = ...
0817 {flow_ctd_time flow_ctd_depth 'profile_index'};
0818 meta_proc.flow_ctd.pitch_value = options.flow_ctd_pitch_value;
0819 end
0820 meta_proc.flow_ctd.method = 'computeCTDFlowSpeed';
0821 meta_proc.flow_ctd.min_pitch = options.flow_ctd_min_pitch;
0822 meta_proc.flow_ctd.min_vel = options.flow_ctd_min_velocity;
0823 end
0824
0825
0826
0827
0828 for sensor_lag_option_idx = 1:numel(options.sensor_lag_list)
0829
0830
0831
0832
0833
0834
0835 sensor_lag_option = options.sensor_lag_list(sensor_lag_option_idx);
0836 sensor_lag_cor = sensor_lag_option.corrected;
0837 sensor_lag_raw = sensor_lag_option.original;
0838 sensor_lag_params = sensor_lag_option.parameters;
0839 sensor_lag_time_list = default_sensor_lag_time_list;
0840 sensor_lag_depth_list = default_sensor_lag_depth_list;
0841 sensor_lag_flow_list = default_sensor_lag_flow_list;
0842 sensor_lag_flow_const = default_sensor_lag_flow_const;
0843 sensor_lag_estimator = default_sensor_lag_estimator;
0844 sensor_lag_minopts = default_sensor_lag_minopts;
0845 if isfield(sensor_lag_option, 'time') && ~isempty(sensor_lag_option.time)
0846 sensor_lag_time_list = sensor_lag_option.time;
0847 end
0848 if isfield(sensor_lag_option, 'depth') && ~isempty(sensor_lag_option.depth)
0849 sensor_lag_depth_list = sensor_lag_option.depth;
0850 end
0851 if isfield(sensor_lag_option, 'flow') ...
0852 && ~isempty(sensor_lag_option.flow)
0853 sensor_lag_flow_list = cellstr(sensor_lag_option.flow);
0854 end
0855 if isfield(sensor_lag_option, 'constant_flow') ...
0856 && ~isempty(sensor_lag_option.constant_flow)
0857 sensor_lag_flow_const = sensor_lag_option.constant_flow;
0858 end
0859 if isfield(sensor_lag_option, 'estimator') ...
0860 && ~isempty(sensor_lag_option.estimator)
0861
0862 if ischar(sensor_lag_option.estimator)
0863 sensor_lag_estimator = str2func(sensor_lag_option.estimator);
0864 else
0865 sensor_lag_estimator = sensor_lag_option.estimator;
0866 end
0867 end
0868 if isfield(sensor_lag_option, 'minopts') ...
0869 && ~isempty(sensor_lag_option.minopts)
0870 sensor_lag_minopts = sensor_lag_option.minopts;
0871 end
0872
0873 sensor_lag_num_params = 2;
0874 if sensor_lag_flow_const
0875 sensor_lag_num_params = 1;
0876 end
0877 if isnumeric(sensor_lag_params) && ...
0878 (numel(sensor_lag_params) == sensor_lag_num_params)
0879
0880 sensor_lag_params_avail = true;
0881 elseif strcmpi(sensor_lag_params, 'auto')
0882
0883 sensor_lag_params_avail = false;
0884 else
0885
0886 error('glider_toolbox:processGliderData:InvalidSensorLagParam', ...
0887 'Invalid sensor lag settings %d: bad parameter specification.', ...
0888 sensor_lag_option_idx);
0889 end
0890
0891 sensor_lag_prof_avail = isfield(data_proc, 'profile_index');
0892 sensor_lag_raw_avail = false;
0893 sensor_lag_time_avail = false;
0894 sensor_lag_depth_avail = false;
0895 sensor_lag_flow_avail = false;
0896 if isfield(data_proc, sensor_lag_raw) ...
0897 && ~all(isnan(data_proc.(sensor_lag_raw)))
0898 sensor_lag_raw_avail = true;
0899 end
0900 for sensor_lag_time_idx = 1:numel(sensor_lag_time_list)
0901 sensor_lag_time = sensor_lag_time_list{sensor_lag_time_idx};
0902 if isfield(data_proc, sensor_lag_time) ...
0903 && any(data_proc.(sensor_lag_time) > 0)
0904 sensor_lag_time_avail = true;
0905 break
0906 end
0907 end
0908 for sensor_lag_depth_idx = 1:numel(sensor_lag_depth_list)
0909 sensor_lag_depth = sensor_lag_depth_list{sensor_lag_depth_idx};
0910 if isfield(data_proc, sensor_lag_depth)
0911 sensor_lag_depth_avail = true;
0912 break
0913 end
0914 end
0915 for sensor_lag_flow_idx = 1:numel(sensor_lag_flow_list)
0916 sensor_lag_flow = sensor_lag_flow_list{sensor_lag_flow_idx};
0917 if isfield(data_proc, sensor_lag_flow) ...
0918 && ~all(isnan(data_proc.(sensor_lag_flow)))
0919 sensor_lag_flow_avail = true;
0920 break
0921 end
0922 end
0923
0924 if sensor_lag_prof_avail && sensor_lag_raw_avail ...
0925 && sensor_lag_time_avail && sensor_lag_depth_avail ...
0926 && (sensor_lag_flow_const || sensor_lag_flow_avail)
0927 num_profiles = fix(max(data_proc.profile_index));
0928
0929 if sensor_lag_params_avail
0930
0931 sensor_lag_constants = sensor_lag_params;
0932 else
0933 fprintf('Performing sensor lag parameter estimation %d with settings:\n', sensor_lag_option_idx);
0934 fprintf(' sensor sequence : %s\n', sensor_lag_raw);
0935 fprintf(' time sequence : %s\n', sensor_lag_time);
0936 fprintf(' depth sequence : %s\n', sensor_lag_depth);
0937 if ~sensor_lag_flow_const
0938 fprintf(' flow speed sequence: %s\n', sensor_lag_flow);
0939 end
0940 fprintf(' estimator : %s\n', func2str(sensor_lag_estimator));
0941
0942 sensor_lag_estimates = nan(num_profiles-1, sensor_lag_num_params);
0943 sensor_lag_exitflags = nan(num_profiles-1, 1);
0944 sensor_lag_residuals = nan(num_profiles-1, 1);
0945 for profile_idx = 1:(num_profiles-1)
0946 prof1_select = (data_proc.profile_index == profile_idx);
0947 [~, ~, prof1_dir] = ...
0948 find(data_proc.profile_direction(prof1_select), 1);
0949 prof1_raw = data_proc.(sensor_lag_raw)(prof1_select);
0950 prof1_time = data_proc.(sensor_lag_time)(prof1_select);
0951 prof1_depth = data_proc.(sensor_lag_depth)(prof1_select);
0952 prof2_select = (data_proc.profile_index == profile_idx + 1);
0953 [~, ~, prof2_dir] = ...
0954 find(data_proc.profile_direction(prof2_select), 1);
0955 prof2_raw = data_proc.(sensor_lag_raw)(prof2_select);
0956 prof2_time = data_proc.(sensor_lag_time)(prof2_select);
0957 prof2_depth = data_proc.(sensor_lag_depth)(prof2_select);
0958 if sensor_lag_flow_const
0959 prof1_vars = {prof1_time(:) prof1_depth(:) prof1_raw(:)};
0960 prof2_vars = {prof2_time(:) prof2_depth(:) prof2_raw(:)};
0961 else
0962 prof1_flow = data_proc.(sensor_lag_flow)(prof1_select);
0963 prof1_vars = ...
0964 {prof1_time(:) prof1_depth(:) prof1_raw(:) prof1_flow(:)};
0965 prof2_flow = data_proc.(sensor_lag_flow)(prof2_select);
0966 prof2_vars = ...
0967 {prof2_time(:) prof2_depth(:) prof2_raw(:) prof2_flow(:)};
0968 end
0969 [prof1_valid, ~, prof1_vars{:}] = ...
0970 validateProfile(prof1_depth(:), prof1_vars{:}, ...
0971 'range', options.profile_min_range, ...
0972 'gap', options.profile_max_gap_ratio);
0973 [prof2_valid, ~, prof2_vars{:}] = ...
0974 validateProfile(prof2_depth(:), prof2_vars{:}, ...
0975 'range', options.profile_min_range, ...
0976 'gap', options.profile_max_gap_ratio);
0977 prof_opposite_dir = (prof1_dir * prof2_dir < 0);
0978 if prof1_valid && prof2_valid && prof_opposite_dir
0979 try
0980 [sensor_lag_estimates(profile_idx, :), ...
0981 sensor_lag_exitflags(profile_idx), ...
0982 sensor_lag_residuals(profile_idx)] = ...
0983 findSensorLagParams(prof1_vars{:}, prof2_vars{:}, sensor_lag_minopts);
0984 if sensor_lag_exitflags(profile_idx) <= 0
0985 warning('glider_toolbox:processGliderData:SensorLagMinimizationError', ...
0986 'Minimization did not converge for casts %d and %d, residual area: %f.', ...
0987 profile_idx, profile_idx+1, sensor_lag_residuals(profile_idx));
0988 end
0989 catch exception
0990 fprintf('Sensor lag estimation failed for casts: %d and %d.\n', ...
0991 profile_idx, profile_idx+1);
0992 disp(getReport(exception, 'extended'));
0993 end
0994 end
0995 end
0996
0997 sensor_lag_constants = sensor_lag_estimator(sensor_lag_estimates);
0998 end
0999
1000 if any(isnan(sensor_lag_constants))
1001 fprintf('Omiting sensor lag correction %d (%s): %s.\n', ...
1002 sensor_lag_option_idx, sensor_lag_cor, ...
1003 'no valid parameters available');
1004 else
1005 fprintf('Performing sensor lag correction %d with settings:\n', sensor_lag_option_idx);
1006 fprintf(' output sensor sequence: %s\n', sensor_lag_cor);
1007 fprintf(' input sensor sequence : %s\n', sensor_lag_raw);
1008 fprintf(' input time sequence : %s\n', sensor_lag_time);
1009 fprintf(' input depth sequence : %s\n', sensor_lag_depth);
1010 if sensor_lag_flow_const
1011 fprintf(' parameters : %f\n', sensor_lag_constants);
1012 else
1013 fprintf(' input flow sequence : %s\n', sensor_lag_flow);
1014 fprintf(' parameters : %f %f\n', sensor_lag_constants);
1015 end
1016 data_proc.(sensor_lag_cor) = nan(size(data_proc.(sensor_lag_raw)));
1017 for profile_idx = 1:num_profiles
1018 prof_select = (data_proc.profile_index == profile_idx);
1019 prof_raw = data_proc.(sensor_lag_raw)(prof_select);
1020 prof_time = data_proc.(sensor_lag_time)(prof_select);
1021 prof_depth = data_proc.(sensor_lag_depth)(prof_select);
1022 if sensor_lag_flow_const
1023 prof_vars = {prof_time(:) prof_raw(:)};
1024 else
1025 prof_flow = data_proc.(sensor_lag_flow)(prof_select);
1026 prof_vars = {prof_time(:) prof_raw(:) prof_flow(:)};
1027 end
1028 [prof_valid, ~, prof_vars{:}] = ...
1029 validateProfile(prof_depth(:), prof_vars{:}, ...
1030 'range', options.profile_min_range, ...
1031 'gap', options.profile_max_gap_ratio);
1032 if prof_valid
1033 prof_cor = correctSensorLag(prof_vars{:}, sensor_lag_constants);
1034 data_proc.(sensor_lag_cor)(prof_select) = prof_cor;
1035 end
1036 end
1037 if sensor_lag_flow_const
1038 meta_proc.(sensor_lag_cor).sources = ...
1039 {sensor_lag_raw sensor_lag_time sensor_lag_depth 'profile_index'}';
1040 else
1041 meta_proc.(sensor_lag_cor).sources = ...
1042 {sensor_lag_raw sensor_lag_time sensor_lag_depth sensor_lag_flow 'profile_index'}';
1043 end
1044 meta_proc.(sensor_lag_cor).method = 'correctSensorLag';
1045 meta_proc.(sensor_lag_cor).parameters = sensor_lag_constants;
1046 if sensor_lag_params_avail
1047 meta_proc.(sensor_lag_cor).parameter_method = 'preset';
1048 else
1049 meta_proc.(sensor_lag_cor).parameter_method = 'findSensorLagParams';
1050 meta_proc.(sensor_lag_cor).parameter_estimator = func2str(sensor_lag_estimator);
1051 meta_proc.(sensor_lag_cor).parameter_estimates = sensor_lag_estimates;
1052 meta_proc.(sensor_lag_cor).parameter_exitflags = sensor_lag_exitflags;
1053 end
1054 meta_proc.(sensor_lag_cor).profile_min_range = options.profile_min_range;
1055 meta_proc.(sensor_lag_cor).profile_gap_ratio = options.profile_max_gap_ratio;
1056 end
1057 end
1058 end
1059
1060
1061
1062
1063
1064
1065 for thermal_lag_option_idx = 1:numel(options.thermal_lag_list)
1066
1067
1068
1069
1070
1071
1072 thermal_lag_option = options.thermal_lag_list(thermal_lag_option_idx);
1073 thermal_lag_cond_cor = thermal_lag_option.conductivity_corrected;
1074 thermal_lag_temp_cor = thermal_lag_option.temperature_corrected;
1075 thermal_lag_cond_raw = thermal_lag_option.conductivity_original;
1076 thermal_lag_temp_raw = thermal_lag_option.temperature_original;
1077 thermal_lag_pres_raw = thermal_lag_option.pressure_original;
1078 thermal_lag_params = thermal_lag_option.parameters;
1079 thermal_lag_time_list = default_thermal_lag_time_list;
1080 thermal_lag_depth_list = default_thermal_lag_depth_list;
1081 thermal_lag_flow_list = default_thermal_lag_flow_list;
1082 thermal_lag_flow_const = default_thermal_lag_flow_const;
1083 thermal_lag_estimator = default_thermal_lag_estimator;
1084 thermal_lag_minopts = default_thermal_lag_minopts;
1085 if isfield(thermal_lag_option, 'time') ...
1086 && ~isempty(thermal_lag_option.time)
1087 thermal_lag_time_list = cellstr(thermal_lag_option.time);
1088 end
1089 if isfield(thermal_lag_option, 'depth') ...
1090 && ~isempty(thermal_lag_option.depth)
1091 thermal_lag_depth_list = cellstr(thermal_lag_option.depth);
1092 end
1093 if isfield(thermal_lag_option, 'flow') ...
1094 && ~isempty(thermal_lag_option.flow)
1095 thermal_lag_flow_list = cellstr(thermal_lag_option.flow);
1096 end
1097 if isfield(thermal_lag_option, 'constant_flow') ...
1098 && ~isempty(thermal_lag_option.constant_flow)
1099 thermal_lag_flow_const = thermal_lag_option.constant_flow;
1100 end
1101 if isfield(thermal_lag_option, 'estimator');
1102
1103 if ischar(thermal_lag_option.estimator)
1104 thermal_lag_estimator = str2func(thermal_lag_option.estimator);
1105 else
1106 thermal_lag_estimator = thermal_lag_option.estimator;
1107 end
1108 end
1109 if isfield(thermal_lag_option, 'minopts');
1110 thermal_lag_minopts = thermal_lag_option.minopts;
1111 end
1112
1113 thermal_lag_num_params = 4;
1114 if thermal_lag_flow_const
1115 thermal_lag_num_params = 2;
1116 end
1117 if isnumeric(thermal_lag_params) ...
1118 && (numel(thermal_lag_params) == thermal_lag_num_params)
1119
1120 thermal_lag_params_avail = true;
1121 elseif strcmpi(thermal_lag_params, 'auto')
1122
1123 thermal_lag_params_avail = false;
1124 else
1125
1126 error('glider_toolbox:processGliderData:InvalidThermalLagParam', ...
1127 'Invalid thermal lag settings %d: bad parameter specification.', ...
1128 thermal_lag_option_idx);
1129 end
1130
1131 thermal_lag_prof_avail = isfield(data_proc, 'profile_index');
1132 thermal_lag_cond_raw_avail = false;
1133 thermal_lag_temp_raw_avail = false;
1134 thermal_lag_pres_avail = false;
1135 thermal_lag_time_avail = false;
1136 thermal_lag_depth_avail = false;
1137 thermal_lag_flow_avail = false;
1138 if isfield(data_proc, thermal_lag_cond_raw) ...
1139 && ~all(isnan(data_proc.(thermal_lag_cond_raw)))
1140 thermal_lag_cond_raw_avail = true;
1141 end
1142 if isfield(data_proc, thermal_lag_temp_raw) ...
1143 && ~all(isnan(data_proc.(thermal_lag_temp_raw)))
1144 thermal_lag_temp_raw_avail = true;
1145 end
1146 if isfield(data_proc, thermal_lag_pres_raw) ...
1147 && ~all(isnan(data_proc.(thermal_lag_pres_raw)))
1148 thermal_lag_pres_avail = true;
1149 end
1150 for thermal_lag_time_idx = 1:numel(thermal_lag_time_list)
1151 thermal_lag_time = thermal_lag_time_list{thermal_lag_time_idx};
1152 if isfield(data_proc, thermal_lag_time) ...
1153 && any(data_proc.(thermal_lag_time) > 0)
1154 thermal_lag_time_avail = true;
1155 break
1156 end
1157 end
1158 for thermal_lag_depth_idx = 1:numel(thermal_lag_depth_list)
1159 thermal_lag_depth = thermal_lag_depth_list{thermal_lag_depth_idx};
1160 if isfield(data_proc, thermal_lag_depth) ...
1161 && ~all(isnan(data_proc.(thermal_lag_depth)))
1162 thermal_lag_depth_avail = true;
1163 break
1164 end
1165 end
1166 for thermal_lag_flow_idx = 1:numel(thermal_lag_flow_list)
1167 thermal_lag_flow = thermal_lag_flow_list{thermal_lag_flow_idx};
1168 if isfield(data_proc, thermal_lag_flow) ...
1169 && ~all(isnan(data_proc.(thermal_lag_flow)))
1170 thermal_lag_flow_avail = true;
1171 break
1172 end
1173 end
1174
1175 if thermal_lag_prof_avail && thermal_lag_cond_raw_avail ...
1176 && thermal_lag_temp_raw_avail && thermal_lag_pres_avail ...
1177 && thermal_lag_time_avail && thermal_lag_depth_avail ...
1178 && (thermal_lag_flow_const || thermal_lag_flow_avail)
1179 num_profiles = fix(max(data_proc.profile_index));
1180
1181 if thermal_lag_params_avail
1182
1183 thermal_lag_constants = thermal_lag_params;
1184 else
1185 fprintf('Performing thermal lag parameter estimation %d with settings:\n', thermal_lag_option_idx);
1186 fprintf(' conductivity sequence: %s\n', thermal_lag_cond_raw);
1187 fprintf(' temperature sequence : %s\n', thermal_lag_temp_raw);
1188 fprintf(' pressure sequence : %s\n', thermal_lag_pres_raw);
1189 fprintf(' time sequence : %s\n', thermal_lag_time);
1190 fprintf(' depth sequence : %s\n', thermal_lag_depth);
1191 if ~thermal_lag_flow_const
1192 fprintf(' flow speed sequence : %s\n', thermal_lag_flow);
1193 end
1194 fprintf(' estimator : %s\n', func2str(thermal_lag_estimator));
1195
1196 thermal_lag_estimates = nan(num_profiles-1, thermal_lag_num_params);
1197 thermal_lag_residuals = nan(num_profiles-1, 1);
1198 thermal_lag_exitflags = nan(num_profiles-1, 1);
1199 for profile_idx = 1:(num_profiles-1)
1200 prof1_select = (data_proc.profile_index == profile_idx);
1201 [~, ~, prof1_dir] = ...
1202 find(data_proc.profile_direction(prof1_select), 1);
1203 prof1_cond = data_proc.(thermal_lag_cond_raw)(prof1_select);
1204 prof1_temp = data_proc.(thermal_lag_temp_raw)(prof1_select);
1205 prof1_pres = data_proc.(thermal_lag_pres_raw)(prof1_select);
1206 prof1_time = data_proc.(thermal_lag_time)(prof1_select);
1207 prof1_depth = data_proc.(thermal_lag_depth)(prof1_select);
1208 prof2_select = (data_proc.profile_index == profile_idx + 1);
1209 [~, ~, prof2_dir] = ...
1210 find(data_proc.profile_direction(prof2_select), 1);
1211 prof2_cond = data_proc.(thermal_lag_cond_raw)(prof2_select);
1212 prof2_temp = data_proc.(thermal_lag_temp_raw)(prof2_select);
1213 prof2_pres = data_proc.(thermal_lag_pres_raw)(prof2_select);
1214 prof2_time = data_proc.(thermal_lag_time)(prof2_select);
1215 prof2_depth = data_proc.(thermal_lag_depth)(prof2_select);
1216 if thermal_lag_flow_const
1217 prof1_vars = ...
1218 {prof1_time(:) prof1_cond(:) prof1_temp(:) prof1_pres(:)};
1219 prof2_vars = ...
1220 {prof2_time(:) prof2_cond(:) prof2_temp(:) prof2_pres(:)};
1221 else
1222 prof1_flow = data_proc.(thermal_lag_flow)(prof1_select);
1223 prof1_vars = ...
1224 {prof1_time(:) prof1_cond(:) prof1_temp(:) prof1_pres(:) prof1_flow(:)};
1225 prof2_flow = data_proc.(thermal_lag_flow)(prof2_select);
1226 prof2_vars = ...
1227 {prof2_time(:) prof2_cond(:) prof2_temp(:) prof2_pres(:) prof2_flow(:)};
1228 end
1229 [prof1_valid, ~, prof1_vars{:}] = ...
1230 validateProfile(prof1_depth(:), prof1_vars{:}, ...
1231 'range', options.profile_min_range, ...
1232 'gap', options.profile_max_gap_ratio);
1233 [prof2_valid, ~, prof2_vars{:}] = ...
1234 validateProfile(prof2_depth(:), prof2_vars{:}, ...
1235 'range', options.profile_min_range, ...
1236 'gap', options.profile_max_gap_ratio);
1237 prof_opposite_dir = (prof1_dir * prof2_dir < 0);
1238 if prof1_valid && prof2_valid && prof_opposite_dir
1239 try
1240 [thermal_lag_estimates(profile_idx, :), ...
1241 thermal_lag_exitflags(profile_idx), ...
1242 thermal_lag_residuals(profile_idx)] = ...
1243 findThermalLagParams(prof1_vars{:}, prof2_vars{:}, thermal_lag_minopts);
1244 if thermal_lag_exitflags(profile_idx) <= 0
1245 warning('glider_toolbox:processGliderData:ThermalLagMinimizationError', ...
1246 'Minimization did not converge for casts %d and %d, residual area: %f.', ...
1247 profile_idx, profile_idx+1, thermal_lag_residuals(profile_idx));
1248 end
1249 catch exception
1250 fprintf('Thermal lag estimation failed for casts: %d and %d.\n', ...
1251 profile_idx, profile_idx+1);
1252 disp(getReport(exception, 'extended'));
1253 end
1254 end
1255 end
1256
1257
1258 thermal_lag_constants = thermal_lag_estimator(thermal_lag_estimates);
1259 end
1260
1261 if any(isnan(thermal_lag_constants))
1262 fprintf('Omiting thermal lag correction %d (%s and %s): %s.\n', ...
1263 thermal_lag_option_idx, thermal_lag_cond_cor, ...
1264 thermal_lag_temp_cor, 'no valid parameters available');
1265 else
1266 fprintf('Performing thermal lag correction %d with settings:\n', thermal_lag_option_idx);
1267 fprintf(' output temperature sequence : %s\n', thermal_lag_temp_cor);
1268 fprintf(' output conductivity sequence: %s\n', thermal_lag_cond_cor);
1269 fprintf(' input conductivity sequence : %s\n', thermal_lag_cond_raw);
1270 fprintf(' input temperature sequence : %s\n', thermal_lag_temp_raw);
1271 fprintf(' input pressure sequence : %s\n', thermal_lag_pres_raw);
1272 fprintf(' input time sequence : %s\n', thermal_lag_time);
1273 fprintf(' input depth sequence : %s\n', thermal_lag_depth);
1274 if thermal_lag_flow_const
1275 fprintf(' parameters : %f %f\n', thermal_lag_constants);
1276 else
1277 fprintf(' input flow sequence : %s\n', thermal_lag_flow);
1278 fprintf(' parameters : %f %f %f %f\n', thermal_lag_constants);
1279 end
1280 data_proc.(thermal_lag_cond_cor) = ...
1281 nan(size(data_proc.(thermal_lag_cond_raw)));
1282 data_proc.(thermal_lag_temp_cor) = ...
1283 nan(size(data_proc.(thermal_lag_temp_raw)));
1284 for profile_idx = 1:num_profiles
1285 prof_select = (data_proc.profile_index == profile_idx);
1286 prof_cond_raw = data_proc.(thermal_lag_cond_raw)(prof_select);
1287 prof_temp_raw = data_proc.(thermal_lag_temp_raw)(prof_select);
1288 prof_time = data_proc.(thermal_lag_time)(prof_select);
1289 prof_depth = data_proc.(thermal_lag_depth)(prof_select);
1290 if thermal_lag_flow_const
1291 prof_vars = {prof_time(:) prof_cond_raw(:) prof_temp_raw(:)};
1292 else
1293 prof_flow = data_proc.(thermal_lag_flow)(prof_select);
1294 prof_vars = ...
1295 {prof_time(:) prof_cond_raw(:) prof_temp_raw(:) prof_flow(:)};
1296 end
1297 [prof_valid, ~, prof_vars{:}] = ...
1298 validateProfile(prof_depth(:), prof_vars{:}, ...
1299 'range', options.profile_min_range, ...
1300 'gap', options.profile_max_gap_ratio);
1301 if prof_valid
1302 [prof_temp_cor, prof_cond_cor] = ...
1303 correctThermalLag(prof_vars{:}, thermal_lag_constants);
1304 data_proc.(thermal_lag_temp_cor)(prof_select) = prof_temp_cor;
1305 data_proc.(thermal_lag_cond_cor)(prof_select) = prof_cond_cor;
1306 end
1307 end
1308 if thermal_lag_flow_const
1309 meta_proc.(thermal_lag_cond_cor).sources = ...
1310 {thermal_lag_cond_raw thermal_lag_temp_raw thermal_lag_pres_raw ...
1311 thermal_lag_time thermal_lag_depth 'profile_index'}';
1312 else
1313 meta_proc.(thermal_lag_cond_cor).sources = ...
1314 {thermal_lag_cond_raw thermal_lag_temp_raw thermal_lag_pres_raw ...
1315 thermal_lag_flow thermal_lag_time thermal_lag_depth 'profile_index'}';
1316 end
1317 meta_proc.(thermal_lag_cond_cor).method = 'correctThermalLag';
1318 meta_proc.(thermal_lag_cond_cor).parameters = thermal_lag_constants;
1319 if thermal_lag_params_avail
1320 meta_proc.(thermal_lag_cond_cor).parameter_method = 'preset';
1321 else
1322 meta_proc.(thermal_lag_cond_cor).parameter_method = 'findThermalLagParams';
1323 meta_proc.(thermal_lag_cond_cor).parameter_estimates = thermal_lag_estimates;
1324 meta_proc.(thermal_lag_cond_cor).parameter_exitflags = thermal_lag_exitflags;
1325 meta_proc.(thermal_lag_cond_cor).parameter_estimator = func2str(thermal_lag_estimator);
1326 end
1327 meta_proc.(thermal_lag_cond_cor).profile_min_range = options.profile_min_range;
1328 meta_proc.(thermal_lag_cond_cor).profile_gap_ratio = options.profile_max_gap_ratio;
1329 meta_proc.(thermal_lag_temp_cor) = meta_proc.(thermal_lag_cond_cor);
1330 end
1331 end
1332 end
1333
1334
1335
1336 for salinity_option_idx = 1:numel(options.salinity_list)
1337 salinity_option = options.salinity_list(salinity_option_idx);
1338 salinity_salt = salinity_option.salinity;
1339 salinity_cond = salinity_option.conductivity;
1340 salinity_temp = salinity_option.temperature;
1341 salinity_pres = salinity_option.pressure;
1342 if all(isfield(data_proc, {salinity_cond salinity_temp salinity_pres}))
1343
1344
1345
1346 fprintf('Deriving salinity %d with settings:\n', salinity_option_idx);
1347 fprintf(' output salinity sequence : %s\n', salinity_salt);
1348 fprintf(' input conductivity sequence: %s\n', salinity_cond);
1349 fprintf(' input temperature sequence : %s\n', salinity_temp);
1350 fprintf(' input pressure sequence : %s\n', salinity_pres);
1351 data_proc.(salinity_salt) = ...
1352 sw_salt(data_proc.(salinity_cond) * (10 / sw_c3515()), ...
1353 data_proc.(salinity_temp), data_proc.(salinity_pres));
1354 meta_proc.(salinity_salt).sources = ...
1355 {salinity_cond salinity_temp salinity_pres}';
1356 meta_proc.(salinity_salt).method = 'sw_salt';
1357 end
1358 end
1359
1360
1361
1362 for density_option_idx = 1:numel(options.density_list)
1363 density_option = options.density_list(density_option_idx);
1364 density_dens = density_option.density;
1365 density_salt = density_option.salinity;
1366 density_temp = density_option.temperature;
1367 density_pres = density_option.pressure;
1368 if all(isfield(data_proc, {density_salt density_temp density_pres}))
1369
1370 fprintf('Deriving density %d with settings:\n', density_option_idx);
1371 fprintf(' output density sequence : %s\n', density_dens);
1372 fprintf(' input salinity sequence : %s\n', density_salt);
1373 fprintf(' input temperature sequence: %s\n', density_temp);
1374 fprintf(' input pressure sequence : %s\n', density_pres);
1375 data_proc.(density_dens) = ...
1376 sw_dens(data_proc.(density_salt), ...
1377 data_proc.(density_temp), data_proc.(density_pres));
1378 meta_proc.(density_dens).sources = ...
1379 {density_salt density_temp density_pres}';
1380 meta_proc.(density_dens).method = 'sw_dens';
1381 end
1382 end
1383
1384 end