diff --git a/AutomaticQC/CTDSurfaceSoakQC.m b/AutomaticQC/CTDSurfaceSoakQC.m index ad97048ae..8edfd2287 100644 --- a/AutomaticQC/CTDSurfaceSoakQC.m +++ b/AutomaticQC/CTDSurfaceSoakQC.m @@ -130,7 +130,6 @@ % transform flags to the appropriate output shape sizeData = size(data); - sizeData(sizeData == lenData) = 1; - flags = repmat(flags, sizeData); + flags = repmat(flags, [1 sizeData(2:end)]); end end \ No newline at end of file diff --git a/AutomaticQC/imosInOutWaterQC.m b/AutomaticQC/imosInOutWaterQC.m index 410fc145d..43feacf0b 100644 --- a/AutomaticQC/imosInOutWaterQC.m +++ b/AutomaticQC/imosInOutWaterQC.m @@ -157,6 +157,5 @@ % transform flags to the appropriate output shape sizeData = size(data); - sizeData(sizeData == lenData) = 1; - flags = repmat(flags, sizeData); -end \ No newline at end of file + flags = repmat(flags, [1 sizeData(2:end)]); +end diff --git a/AutomaticQC/imosRateOfChangeQC.m b/AutomaticQC/imosRateOfChangeQC.m index c2dcc315b..4c00dc340 100644 --- a/AutomaticQC/imosRateOfChangeQC.m +++ b/AutomaticQC/imosRateOfChangeQC.m @@ -8,8 +8,8 @@ % ascribed to the current data point of the set. % % Action: PARAMETER values are flagged if -% |Vi � Vi-1| + |Vi � Vi+1| > 2�(threshold) -% where Vi is the current value of the parameter, Vi�1 +% |Vi - Vi-1| + |Vi - Vi+1| > 2*(threshold) +% where Vi is the current value of the parameter, Vi-1 % is the previous and Vi+1 the next one. If % the one parameter is missing, the relative part of % the formula is omitted and the comparison term diff --git a/AutomaticQC/imosTiltVelocitySetQC.m b/AutomaticQC/imosTiltVelocitySetQC.m index d242f02dc..e9b78e714 100644 --- a/AutomaticQC/imosTiltVelocitySetQC.m +++ b/AutomaticQC/imosTiltVelocitySetQC.m @@ -186,7 +186,7 @@ if isempty(firstTiltThreshold) % couldn't find this instrument so quit the test - disp(['Info: imosTiltVelositySetQC could not be performed on ' sample_data.toolbox_input_file ... + disp(['Warning: imosTiltVelositySetQC could not be performed on ' sample_data.toolbox_input_file ... ' instrument = "' instrument '" => Fill imosTiltVelositySetQC.txt with relevant make/model information if you wish to run this test on this dataset.']); return; end diff --git a/Graph/checkMooringPlannedDepths.m b/Graph/checkMooringPlannedDepths.m index c19e58105..dde702286 100644 --- a/Graph/checkMooringPlannedDepths.m +++ b/Graph/checkMooringPlannedDepths.m @@ -291,18 +291,18 @@ function checkMooringPlannedDepths(sample_data, isQC, saveToFile, exportDir) %comparison %This could be done better, with more finesse - could allow zooming in %before going straight to the time period selection. For now, this will do. -hMsgbox = msgbox('Select the time period for comparison using the mouse', 'Time Period Selection', 'help', 'modal'); +hMsgbox = msgbox('Select (drag & drop) a time period on the top graph for comparison, preferably at the start of deployment, when the mooring is standing vertical', 'Time Period Selection', 'help', 'modal'); uiwait(hMsgbox); %select the area to use for comparison -[x,y] = select_points(hAxPress); +[x, ~] = select_points(hAxPress); %now plot the difference from planned depth data: iGood = timeVar >= x(1) & timeVar <= x(2); dataVar(~iGood) = NaN; minDep = min(dataVar,[],2); -hLineVar2 = scatter(hAxDepthDiff, ... +scatter(hAxDepthDiff, ... metaDepth, ... minDep - metaDepth, ... 15, ... diff --git a/Graph/checkMooringPresDiffs.m b/Graph/checkMooringPresDiffs.m index 51f1c8290..e9b0f8c26 100644 --- a/Graph/checkMooringPresDiffs.m +++ b/Graph/checkMooringPresDiffs.m @@ -15,7 +15,8 @@ function checkMooringPresDiffs(sample_data, iSampleMenu, isQC, saveToFile, expor % exportDir - string containing the destination folder to where the % plot is saved on disk. % -% Author: Rebecca Cowley +% Author: Rebecca Cowley +% Contributor: Guillaume Galibert % % @@ -165,7 +166,7 @@ function checkMooringPresDiffs(sample_data, iSampleMenu, isQC, saveToFile, expor set(get(hAxPressDiff, 'XLabel'), 'String', 'Time'); set(get(hAxPressDiff, 'YLabel'), 'String', ['Pressure differences (' varUnit ')'], 'Interpreter', 'none'); set(get(hAxPressDiff, 'Title'), 'String', ... - ['Pressure differences in ' varUnit ' (minus respective median over 1st quarter) between ' instrumentDesc{iCurrSam} ' (in black above) and nearest neighbours'] , 'Interpreter', 'none'); + ['Pressure differences in ' varUnit ' (minus respective median over 1st quarter) between ' instrumentDesc{iCurrSam} ' (in black above) and 4 (max) nearest neighbours'] , 'Interpreter', 'none'); set(hAxPressDiff, 'XTick', (xMin:(xMax-xMin)/4:xMax)); set(hAxPressDiff, 'XLim', [xMin, xMax]); hold(hAxPressDiff, 'on'); diff --git a/IMOS/imosParameters.txt b/IMOS/imosParameters.txt index 7c67166d1..f7b469258 100644 --- a/IMOS/imosParameters.txt +++ b/IMOS/imosParameters.txt @@ -72,8 +72,8 @@ HEIGHT_ABOVE_SENSOR, 1, height, HL, 1, surface_upward_latent_heat_flux, W m-2, , , F, 999999.0, , , float HS, 1, surface_upward_sensible_heat_flux, W m-2, , , F, 999999.0, , , float ISO17, 1, depth_of_isosurface_of_sea_water_potential_temperature, m, down, sea surface, E, 999999.0, , , float -LATITUDE, 1, latitude, degrees_north, , WGS84 coordinate reference system, , 999999.0, -90.0, 90.0, double -LONGITUDE, 1, longitude, degrees_east, , WGS84 coordinate reference system, , 999999.0, -180.0, 180.0, double +LATITUDE, 1, latitude, degrees_north, , WGS84 geographic coordinate system, , 999999.0, -90.0, 90.0, double +LONGITUDE, 1, longitude, degrees_east, , WGS84 geographic coordinate system, , 999999.0, -180.0, 180.0, double LW, 1, surface_downwelling_longwave_flux_in_air, W m-2, , , F, 999999.0, , , float LW_NET, 1, surface_net_upward_longwave_flux, W m-2, , , F, 999999.0, , , float MASS_NET, 1, upward_mass_flux_of_air, kg m-2 s-1, , , F, 999999.0, , , float diff --git a/Parser/readParadoppBinary.m b/Parser/readParadoppBinary.m index 9d7432a45..7c2da5604 100644 --- a/Parser/readParadoppBinary.m +++ b/Parser/readParadoppBinary.m @@ -191,20 +191,26 @@ isPairInconsistent = [xor(isPairInconsistent(1:end-1), isPairInconsistent(2:end)); false] & isPairInconsistent; end -% sometimes, inconsistencies are due to the file simply being corrupted -% in this case we just remove the faulty Sync (also handles the case when -% the last section has been truncated so that we don't try to read it at all) -iSync(iSync) = isSizeConsistent; - -iIds = [false; iSync(1:end-1)]; -ids = data(iIds); -uniqIds = unique(sort(ids)); - -iSizes = [false; false; iSync(1:end-2)] | [false; false; false; iSync(1:end-3)]; -sizesFromData = bytecast(data(iSizes), 'L', 'uint16', cpuEndianness)*2; % 1 word = 2 bytes - -% when size info not available from sector we replace it with its expected value -for i=1:length(noSizeIds), sizesFromData(ids == noSizeIds(i)) = noSizeSize(i); end +% now we need to deal with any fault sync detection left alone +if any(~isSizeConsistent) + iSync(iSync) = [true; isSizeConsistent(1:end-1)]; + + % we also handle the case when the last section has been truncated so + % that we don't try to read it at all + if ~isSizeConsistent(end) + iSync(iSync) = [true(sum(iSync)-1, 1); false]; + end + + iIds = [false; iSync(1:end-1)]; + ids = data(iIds); + uniqIds = unique(sort(ids)); + + iSizes = [false; false; iSync(1:end-2)] | [false; false; false; iSync(1:end-3)]; + sizesFromData = bytecast(data(iSizes), 'L', 'uint16', cpuEndianness)*2; % 1 word = 2 bytes + + % when size info not available from sector we replace it with its expected value + for i=1:length(noSizeIds), sizesFromData(ids == noSizeIds(i)) = noSizeSize(i); end +end clear iIds iSizes sizesFromSync; % now we can read data sectors by type @@ -280,8 +286,10 @@ clear dataSection; iBadChecksum = cs ~= vertcat(sect(:).Checksum); if any(iBadChecksum) - % we don't want a keep a section with erroneous data in it + % we don't want to keep a record with erroneous data in it sect(iBadChecksum) = []; + + if isempty(sect), continue; end end clear cs iBadChecksum; diff --git a/Parser/readWQMraw.m b/Parser/readWQMraw.m index bb384aa27..9b69b6954 100644 --- a/Parser/readWQMraw.m +++ b/Parser/readWQMraw.m @@ -187,7 +187,6 @@ [name, comment] = getParamDetails(varlabel{k}, params); data = wqmdata.(varlabel{k}); - data(iBadTime) = []; % some fields are not in IMOS uom - scale them so that they are switch varlabel{k} diff --git a/Parser/workhorseParse.m b/Parser/workhorseParse.m index 40c173272..4e8b0b092 100644 --- a/Parser/workhorseParse.m +++ b/Parser/workhorseParse.m @@ -130,13 +130,33 @@ cellStart + (numCells-1) * cellLength)'; % rearrange the sample data - time = datenum(... - [variable.y2kCentury*100 + variable.y2kYear,... - variable.y2kMonth,... - variable.y2kDay,... - variable.y2kHour,... - variable.y2kMinute,... - variable.y2kSecond + variable.y2kHundredth/100.0]); + instrument_firmware = strcat(num2str(fixed.cpuFirmwareVersion(1)), '.', num2str(fixed.cpuFirmwareRevision(1))); % we assume the first value is correct for the rest of the dataset + if str2double(instrument_firmware) > 8.35 + time = datenum(... + [variable.y2kCentury*100 + variable.y2kYear,... + variable.y2kMonth,... + variable.y2kDay,... + variable.y2kHour,... + variable.y2kMinute,... + variable.y2kSecond + variable.y2kHundredth/100.0]); + else + % looks like before firmware 8.35 included, Y2K compliant RTC time + % was not implemented + century = 2000; + if variable.rtcYear(1) > 70 + % first ADCP was built in the mid 1970s + % hopefully this firmware will no longer be used + % in 2070... + century = 1900; + end + time = datenum(... + [century + variable.rtcYear,... + variable.rtcMonth,... + variable.rtcDay,... + variable.rtcHour,... + variable.rtcMinute,... + variable.rtcSecond + variable.rtcHundredths/100.0]); + end timePerPing = fixed.tppMinutes*60 + fixed.tppSeconds + fixed.tppHundredths/100; timePerEnsemble = fixed.pingsPerEnsemble .* timePerPing; @@ -252,16 +272,15 @@ end - sample_data.meta.instrument_model = [model ' Workhorse ADCP']; - sample_data.meta.instrument_serial_no = serial; - sample_data.meta.instrument_sample_interval = median(diff(time*24*3600)); - sample_data.meta.instrument_average_interval = mode(timePerEnsemble); - sample_data.meta.instrument_firmware = ... - strcat(num2str(fixed.cpuFirmwareVersion(1)), '.', num2str(fixed.cpuFirmwareRevision(1))); % we assume the first value is correct for the rest of the dataset + sample_data.meta.instrument_model = [model ' Workhorse ADCP']; + sample_data.meta.instrument_serial_no = serial; + sample_data.meta.instrument_sample_interval = median(diff(time*24*3600)); + sample_data.meta.instrument_average_interval = mode(timePerEnsemble); + sample_data.meta.instrument_firmware = instrument_firmware; if all(isnan(fixed.beamAngle)) - sample_data.meta.beam_angle = 20; % http://www.hydro-international.com/files/productsurvey_v_pdfdocument_19.pdf + sample_data.meta.beam_angle = 20; % http://www.hydro-international.com/files/productsurvey_v_pdfdocument_19.pdf else - sample_data.meta.beam_angle = mode(fixed.beamAngle); % we set a static value for this variable to the most frequent value found + sample_data.meta.beam_angle = mode(fixed.beamAngle); % we set a static value for this variable to the most frequent value found end % add dimensions with their data mapped diff --git a/Preprocessing/timeDriftPP.m b/Preprocessing/timeDriftPP.m index 41339038b..b8e7cecfe 100644 --- a/Preprocessing/timeDriftPP.m +++ b/Preprocessing/timeDriftPP.m @@ -105,86 +105,88 @@ end end -f = figure(... - 'Name', 'Time start and end drift calculations in seconds',... - 'Visible', 'off',... - 'MenuBar' , 'none',... - 'Resize', 'off',... - 'WindowStyle', 'Modal',... - 'NumberTitle', 'off'); - -cancelButton = uicontrol('Style', 'pushbutton', 'String', 'Cancel'); -confirmButton = uicontrol('Style', 'pushbutton', 'String', 'Ok'); - -setCheckboxes = []; -startOffsetFields = []; -endOffsetFields = []; - -for k = 1:nSample +if ~auto + f = figure(... + 'Name', 'Time start and end drift calculations in seconds',... + 'Visible', 'off',... + 'MenuBar' , 'none',... + 'Resize', 'off',... + 'WindowStyle', 'Modal',... + 'NumberTitle', 'off'); - setCheckboxes(k) = uicontrol(... - 'Style', 'checkbox',... - 'String', descs{k},... - 'Value', 1, ... - 'UserData', k); + cancelButton = uicontrol('Style', 'pushbutton', 'String', 'Cancel'); + confirmButton = uicontrol('Style', 'pushbutton', 'String', 'Ok'); - startOffsetFields(k) = uicontrol(... - 'Style', 'edit',... - 'UserData', k, ... - 'String', num2str(startOffsets(k))); + setCheckboxes = []; + startOffsetFields = []; + endOffsetFields = []; - endOffsetFields(k) = uicontrol(... - 'Style', 'edit',... - 'UserData', k, ... - 'String', num2str(endOffsets(k))); + for k = 1:nSample + + setCheckboxes(k) = uicontrol(... + 'Style', 'checkbox',... + 'String', descs{k},... + 'Value', 1, ... + 'UserData', k); + + startOffsetFields(k) = uicontrol(... + 'Style', 'edit',... + 'UserData', k, ... + 'String', num2str(startOffsets(k))); + + endOffsetFields(k) = uicontrol(... + 'Style', 'edit',... + 'UserData', k, ... + 'String', num2str(endOffsets(k))); + + end -end - -% set all widgets to normalized for positioning -set(f, 'Units', 'normalized'); -set(cancelButton, 'Units', 'normalized'); -set(confirmButton, 'Units', 'normalized'); -set(setCheckboxes, 'Units', 'normalized'); -set(startOffsetFields, 'Units', 'normalized'); -set(endOffsetFields, 'Units', 'normalized'); - -set(f, 'Position', [0.2 0.35 0.6 0.0222 * (nSample + 1)]); % need to include 1 extra space for the row of buttons - -rowHeight = 1 / (nSample + 1); - -set(cancelButton, 'Position', [0.0 0.0 0.5 rowHeight]); -set(confirmButton, 'Position', [0.5 0.0 0.5 rowHeight]); - -for k = 1:nSample + % set all widgets to normalized for positioning + set(f, 'Units', 'normalized'); + set(cancelButton, 'Units', 'normalized'); + set(confirmButton, 'Units', 'normalized'); + set(setCheckboxes, 'Units', 'normalized'); + set(startOffsetFields, 'Units', 'normalized'); + set(endOffsetFields, 'Units', 'normalized'); + + set(f, 'Position', [0.2 0.35 0.6 0.0222 * (nSample + 1)]); % need to include 1 extra space for the row of buttons + + rowHeight = 1 / (nSample + 1); + + set(cancelButton, 'Position', [0.0 0.0 0.5 rowHeight]); + set(confirmButton, 'Position', [0.5 0.0 0.5 rowHeight]); + + for k = 1:nSample + + rowStart = 1.0 - k * rowHeight; + + set(setCheckboxes (k), 'Position', [0.0 rowStart 0.6 rowHeight]); + set(startOffsetFields (k), 'Position', [0.6 rowStart 0.2 rowHeight]); + set(endOffsetFields (k), 'Position', [0.8 rowStart 0.2 rowHeight]); + end + + % set back to pixels + set(f, 'Units', 'normalized'); + set(cancelButton, 'Units', 'normalized'); + set(confirmButton, 'Units', 'normalized'); + set(setCheckboxes, 'Units', 'normalized'); + set(startOffsetFields, 'Units', 'normalized'); + set(endOffsetFields, 'Units', 'normalized'); - rowStart = 1.0 - k * rowHeight; + % set widget callbacks + set(f, 'CloseRequestFcn', @cancelCallback); + set(f, 'WindowKeyPressFcn', @keyPressCallback); + set(setCheckboxes, 'Callback', @checkboxCallback); + set(startOffsetFields, 'Callback', @startoffsetFieldCallback); + set(endOffsetFields, 'Callback', @endoffsetFieldCallback); + set(cancelButton, 'Callback', @cancelCallback); + set(confirmButton, 'Callback', @confirmCallback); - set(setCheckboxes (k), 'Position', [0.0 rowStart 0.6 rowHeight]); - set(startOffsetFields (k), 'Position', [0.6 rowStart 0.2 rowHeight]); - set(endOffsetFields (k), 'Position', [0.8 rowStart 0.2 rowHeight]); + set(f, 'Visible', 'on'); + + uiwait(f); end -% set back to pixels -set(f, 'Units', 'normalized'); -set(cancelButton, 'Units', 'normalized'); -set(confirmButton, 'Units', 'normalized'); -set(setCheckboxes, 'Units', 'normalized'); -set(startOffsetFields, 'Units', 'normalized'); -set(endOffsetFields, 'Units', 'normalized'); - -% set widget callbacks -set(f, 'CloseRequestFcn', @cancelCallback); -set(f, 'WindowKeyPressFcn', @keyPressCallback); -set(setCheckboxes, 'Callback', @checkboxCallback); -set(startOffsetFields, 'Callback', @startoffsetFieldCallback); -set(endOffsetFields, 'Callback', @endoffsetFieldCallback); -set(cancelButton, 'Callback', @cancelCallback); -set(confirmButton, 'Callback', @confirmCallback); - -set(f, 'Visible', 'on'); - -uiwait(f); - % calculate the drift and apply to the selected datasets for k = 1:nSample diff --git a/imosToolbox.m b/imosToolbox.m index c34298d0f..00a2c19aa 100644 --- a/imosToolbox.m +++ b/imosToolbox.m @@ -4,7 +4,8 @@ function imosToolbox(auto, varargin) % This function is the entry point for the IMOS toolbox. % % Inputs: -% auto - optional String parameter - if 'auto', the toolbox is executed +% auto - optional String parameter - if 'version', the version of the +% toolbox is output. if 'auto', the toolbox is executed % automatically, with no user interaction. Any other string will % result in the toolbox being executed normally. % varargin - In 'auto' mode, any other parameters passed in are passed @@ -73,9 +74,10 @@ function imosToolbox(auto, varargin) end % Set current toolbox version -toolboxVersion = ['2.5.26 - ' computer]; +toolboxVersion = ['2.5.27 - ' computer]; switch auto - case 'auto', autoIMOSToolbox(toolboxVersion, varargin{:}); - otherwise, flowManager(toolboxVersion); + case 'auto', autoIMOSToolbox(toolboxVersion, varargin{:}); + case 'version', disp(toolboxVersion); + otherwise, flowManager(toolboxVersion); end diff --git a/imosToolbox_Linux64.bin b/imosToolbox_Linux64.bin index b17af94a2..1df4551b2 100755 Binary files a/imosToolbox_Linux64.bin and b/imosToolbox_Linux64.bin differ diff --git a/imosToolbox_Win32.exe b/imosToolbox_Win32.exe index f5ab3cc8d..a519c211f 100644 Binary files a/imosToolbox_Win32.exe and b/imosToolbox_Win32.exe differ diff --git a/imosToolbox_Win64.exe b/imosToolbox_Win64.exe index 136a30b37..257107987 100644 Binary files a/imosToolbox_Win64.exe and b/imosToolbox_Win64.exe differ