function [] = choose_transect_limits(lat,lon,varargin)
%
% choose_transect_limits.m--GUI to choose indices to start and end times of
% oceanographic transects.
%
% Input arguments are latitude, longitude and (optionally) Matlab-format
% time.
%
% Output saved to user-chosen .mat file.
%
% Program uses "dial" GUI controls. If using pre-2008 Matlab version, or if
% dial controls use too much system overhead for your computer to handle,
% set the DIAL constant in the code to 0, and pushbutton controls will be
% used instead of dials.
%
% Syntax: choose_transect_limits(lat,lon,<time>)
%
% e.g., load('ctl_demodata.mat');
% choose_transect_limits(lat,lon,time)
% Developed in Matlab 7.6.0.324 (R2008a) on GLNX86.
% Kevin Bartlett (kpb@uvic.ca), 2008-06-16 16:45
%-------------------------------------------------------------------------
% Set the DIAL constant to 1 to use dial GUI controls or zero to use more
% conventional pushbuttons (dial controls won't work on pre-R2008a versions
% of Matlab, and they may use too much overhead for some computers to
% handle).
DIAL = 1;
wrongVersion = (DIAL == 1) && ...
(datenum(version('-date')) < datenum('February 10, 2008'));
if wrongVersion
error('Using pre-R2008a Matlab release; must set DIAL to 0');
end % if
% Handle input arguments.
if nargin ==2
time = [1:length(lat)];
isMtime = false;
elseif nargin == 3
time = varargin{1};
isMtime = true;
else
error([mfilename '.m--Incorrect number of input arguments.']);
end % if
if length(time)~=length(lat) || length(lon) ~= length(lat)
error([mfilename '.m--Latitude, longitude and time vectors must all be of same length.']);
end % if
% Create GUI figure.
GuiScale = 1;
DeltaFontSize = 0;
ScreenPixelsPerInch = get(0,'ScreenPixelsPerInch');
if ScreenPixelsPerInch > 80
DeltaFontSize = -1;
elseif ScreenPixelsPerInch > 100
DeltaFontSize = -2;
elseif ScreenPixelsPerInch > 110
DeltaFontSize = -3;
end % if
FigurePosition = NaN;
objHndls = ctl_makeguiobjects(GuiScale,DeltaFontSize,FigurePosition);
ctlFig = findobj(objHndls,'Tag','ctlFig');
% Keep track of whether dial controls are being used.
setappdata(ctlFig,'doUseDial',DIAL);
% Keep track of whether Matlab-format time is being used.
setappdata(ctlFig,'isMtime',isMtime);
% Customise figure depending on whether dials are being used or not.
headDialPlaceHolder = findobj(ctlFig,'Tag','headDialPlaceHolder');
tailDialPlaceHolder = findobj(ctlFig,'Tag','tailDialPlaceHolder');
if DIAL == 1
delete(findobj(ctlFig,'Tag','headForwardButton'));
delete(findobj(ctlFig,'Tag','tailForwardButton'));
delete(findobj(ctlFig,'Tag','headBackButton'));
delete(findobj(ctlFig,'Tag','tailBackButton'));
delete(findobj(ctlFig,'Tag','headLabelText'));
delete(findobj(ctlFig,'Tag','tailLabelText'));
set(headDialPlaceHolder,'units','norm');
headDialPos = get(headDialPlaceHolder,'Position');
set(tailDialPlaceHolder,'units','norm');
tailDialPos = get(tailDialPlaceHolder,'Position');
% Number of points traversed in a single rotation of the dials. Should
% agree with initial setting of powerPopUp pop-up menu.
pointsPerRot = 10;
dialRadius = 0.9;
headDial = dial('Position',headDialPos,...
'drawTicks',false,...
'pointerStyle','circle',...
'Min',1,...
'Max',length(lon),...
'Value',1,...
'refVal',1,...
'refOrientation',90*pi/180, ...
'valRangePerRotation',pointsPerRot,...
'titleStr','',...
'titlePos','top',...
'dialRadius',dialRadius,...
'VerticalAlignment','bottom',...
'Tag','headDial');
tailDial = dial('Position',tailDialPos,...
'drawTicks',false,...
'pointerStyle','circle',...
'Min',1,...
'Max',length(lon),...
'Value',1,...
'refVal',1,...
'refOrientation',90*pi/180, ...
'valRangePerRotation',pointsPerRot,...
'titleStr','',...
'titlePos','top',...
'dialRadius',dialRadius,...
'VerticalAlignment','bottom',...
'Tag','tailDial');
set(headDial.titleHndl,'position',[0 1.1 0]);
set(tailDial.titleHndl,'position',[0 1.1 0]);
else
headForwardButton = findobj(ctlFig,'Tag','headForwardButton');
setappdata(headForwardButton,'max',length(lon));
end % if
delete(headDialPlaceHolder);
delete(tailDialPlaceHolder);
% Popup menu controls the "power" or sensitivity of the dial or pushbutton
% controls.
popUpPowers = [1 2 3 4 5 10 25 50 100 250 500 750 1000 5000 10000 50000 100000 500000 1000000];
if DIAL == 1
popUpPowers(1:5) = [];
end % if
% ...Exclude power values that exceed the length of the data...actually
% allow one value to be greater than the data length.
findIndex = find(popUpPowers >= length(lon),1,'first');
if ~isempty(findIndex)
popUpPowers = popUpPowers(1:findIndex);
end % if
popUpPowerStrs = {};
for iPower = 1:length(popUpPowers)
popUpPowerStrs{iPower} = num2str(popUpPowers(iPower));
end % for
set(findobj(ctlFig,'Tag','powerPopUp'),'string',popUpPowerStrs);
% Set up map axes.
axes(findobj(ctlFig,'Tag','mapAxes'));
fullTrackLine = line(lon,lat,'color',[.6 .6 .6],'Tag','fullTrackLine',...
'lineWidth',.5);
latlonlims;
% Set zooming on.
zoomHndl = zoom(ctlFig);
set(zoomHndl,'Enable','on');
% ...After zooming, change aspect ratio so that equal distances are shown
% in x and y directions.
set(zoomHndl,'ActionPostCallback',@latlonlims);
% Make line showing current selection.
SELECTCOLOUR = [1 0 0];
selectLine = line(lon(1),lat(1),'color',SELECTCOLOUR,'Tag','selectLine','lineWidth',3);
% Make single-point line with large marker to show "head" of selected line.
headLine = line(lon(1),lat(1),'color',SELECTCOLOUR,'marker','o',...
'markerSize',9,'lineWidth',3,'Tag','headLine');
% Make single-point line with smaller marker to show "tail" of selected
% line.
tailLine = line(lon(1),lat(1),'color',SELECTCOLOUR,'marker','x',...
'markerSize',6,'lineWidth',3,'Tag','tailLine');
box on;
% Set up lat and lon time-series plots.
axes(findobj(ctlFig,'Tag','latAx'));
fullLatLine = line(time,lat,'color',[.6 .6 .6],'Tag','fullLatLine',...
'lineWidth',.5);
axis('tight');
selectLatLine = line(time(1),lat(1),'color',SELECTCOLOUR,'Tag','selectLatLine','lineWidth',3);
headLatLine = line(time(1),lat(1),'color',SELECTCOLOUR,'marker','o',...
'markerSize',9,'lineWidth',3,'Tag','headLatLine');
tailLatLine = line(time(1),lat(1),'color',SELECTCOLOUR,'marker','x',...
'markerSize',6,'lineWidth',3,'Tag','tailLatLine');
box on;
if isMtime
kdatetick;
end % if
xlabel('');
set(gca,'xticklabel',[]);
ylabel('lat');
axes(findobj(ctlFig,'Tag','lonAx'));
fullLonLine = line(time,lon,'color',[.6 .6 .6],'Tag','fullLonLine',...
'lineWidth',.5);
axis('tight');
selectLonLine = line(time(1),lon(1),'color',SELECTCOLOUR,'Tag','selectLonLine','lineWidth',3);
headLonLine = line(time(1),lon(1),'color',SELECTCOLOUR,'marker','o',...
'markerSize',9,'lineWidth',3,'Tag','headLonLine');
tailLonLine = line(time(1),lon(1),'color',SELECTCOLOUR,'marker','x',...
'markerSize',6,'lineWidth',3,'Tag','tailLonLine');
box on;
if isMtime
kdatetick;
end % if
ylabel('lon');
% Set callbacks.
if DIAL == 1
set(headDial,'callback',@head_dial_cb);
set(tailDial,'callback',@tail_dial_cb);
else
set(findobj(ctlFig,'Tag','headForwardButton'),'callback',@head_forward_cb);
set(findobj(ctlFig,'Tag','tailForwardButton'),'callback',@tail_forward_cb);
set(findobj(ctlFig,'Tag','headBackButton'),'callback',@head_back_cb);
set(findobj(ctlFig,'Tag','tailBackButton'),'callback',@tail_back_cb);
end % if
set(findobj(ctlFig,'Tag','powerPopUp'),'callback',@power_pop_cb);
set(findobj(ctlFig,'Tag','prevTransectButton'),'callback',@prev_transect_cb);
set(findobj(ctlFig,'Tag','nextTransectButton'),'callback',@next_transect_cb);
set(findobj(ctlFig,'Tag','insertButton'),'callback',@insert_transect_cb);
set(findobj(ctlFig,'Tag','deleteButton'),'callback',@delete_transect_cb);
set(findobj(ctlFig,'Tag','commentEdit'),'callback',@comment_edit_cb);
set(findobj(ctlFig,'Tag','quitMenu'),'callback',@quit_cb);
set(findobj(ctlFig,'Tag','saveMenu'),'callback',@save_cb);
set(findobj(ctlFig,'Tag','loadMenu'),'callback',@load_cb);
% Set up transect data.
setappdata(ctlFig,'transectPtr',1);
transects(1).numbers = 1;
transects(1).startIndex = 1;
transects(1).endIndex = 1;
transects(1).comments = '';
setappdata(ctlFig,'transects',transects);
setappdata(ctlFig,'changedSinceLastSave',false);
% Initialise display for first transect.
update_for_transect(ctlFig);
%-------------------------------------------------------------------------
function [] = set_current_selection(figNum)
%
% set_current_selection.m--Sets the start and end index pointed to by the
% selection controls. Works with either dial or pushbutton controls.
%
% Syntax: set_current_selection(figNum)
% Developed in Matlab 7.6.0.324 (R2008a) on GLNX86.
% Kevin Bartlett (kpb@uvic.ca), 2008-06-04 10:45
%-------------------------------------------------------------------------
transects = getappdata(figNum,'transects');
transectPtr = getappdata(figNum,'transectPtr');
doUseDial = getappdata(figNum,'doUseDial');
tailIndex = transects(transectPtr).startIndex;
headIndex = transects(transectPtr).endIndex;
if doUseDial == true
tailDial = dial.find_dial(figNum,'tailDial');
tailDial = tailDial{1};
% Setting the dial reference value and orientation prevents the dial
% moving when the value is set.
thisOrientation = get(tailDial,'orientation');
set(tailDial,'refOrientation',thisOrientation,...
'refVal',tailIndex,...
'Value',tailIndex);
headDial = dial.find_dial(figNum,'headDial');
headDial = headDial{1};
thisOrientation = get(headDial,'orientation');
set(headDial,'refOrientation',thisOrientation,...
'refVal',headIndex,...
'Value',headIndex);
else
tailForwardButton = findobj(figNum,'Tag','tailForwardButton');
setappdata(tailForwardButton,'buttonVal',tailIndex);
headForwardButton = findobj(figNum,'Tag','headForwardButton');
setappdata(headForwardButton,'buttonVal',headIndex);
end % if
%-------------------------------------------------------------------------
function [startIndex,endIndex] = get_current_selection(figNum)
%
% get_current_selection.m--Gets the start and end index of the
% currently-selected lat/lon data. Works with either dial or pushbutton
% controls.
%
% Syntax: [startIndex,endIndex] = get_current_selection(figNum)
% Developed in Matlab 7.6.0.324 (R2008a) on GLNX86.
% Kevin Bartlett (kpb@uvic.ca), 2008-06-04 10:45
%-------------------------------------------------------------------------
doUseDial = getappdata(figNum,'doUseDial');
if doUseDial == true
tailDial = dial.find_dial(figNum,'tailDial');
tailDial = tailDial{1};
startIndex = round(get(tailDial,'Value'));
headDial = dial.find_dial(figNum,'headDial');
headDial = headDial{1};
endIndex = round(get(headDial,'Value'));
else
tailForwardButton = findobj(figNum,'Tag','tailForwardButton');
startIndex = getappdata(tailForwardButton,'buttonVal');
headForwardButton = findobj(figNum,'Tag','headForwardButton');
endIndex = getappdata(headForwardButton,'buttonVal');
end % if
%-------------------------------------------------------------------------
function [] = tail_back_cb(src,eventdata)
%
% tail_back_cb.m--Callback for the "Tail back" button.
%-------------------------------------------------------------------------
buttonPower = str2num(get_popup_value(findobj(gcbf,'Tag','powerPopUp')));
tailForwardButton = findobj(gcbf,'Tag','tailForwardButton');
tailVal = getappdata(tailForwardButton,'buttonVal');
tailVal = tailVal - buttonPower;
if tailVal < 1
tailVal = 1;
end % if
setappdata(tailForwardButton,'buttonVal',tailVal);
% Change selection based on dial settings.
setappdata(gcbf,'changedSinceLastSave',true);
update_for_selection(gcbf);
%-------------------------------------------------------------------------
function [] = tail_forward_cb(src,eventdata)
%
% tail_forward_cb.m--Callback for the "Tail forward" button.
%-------------------------------------------------------------------------
buttonPower = str2num(get_popup_value(findobj(gcbf,'Tag','powerPopUp')));
tailForwardButton = findobj(gcbf,'Tag','tailForwardButton');
tailVal = getappdata(tailForwardButton,'buttonVal');
tailVal = tailVal + buttonPower;
% Don't allow tail to move past head.
headForwardButton = findobj(gcbf,'Tag','headForwardButton');
headVal = getappdata(headForwardButton,'buttonVal');
if tailVal > headVal
tailVal = headVal;
end % if
setappdata(tailForwardButton,'buttonVal',tailVal);
% Change selection based on dial settings.
setappdata(gcbf,'changedSinceLastSave',true);
update_for_selection(gcbf);
%-------------------------------------------------------------------------
function [] = head_back_cb(src,eventdata)
%
% head_back_cb.m--Callback for the "Head back" button.
%-------------------------------------------------------------------------
buttonPower = str2num(get_popup_value(findobj(gcbf,'Tag','powerPopUp')));
headForwardButton = findobj(gcbf,'Tag','headForwardButton');
headVal = getappdata(headForwardButton,'buttonVal') - buttonPower;
if headVal < 1
headVal = 1;
end % if
% Don't allow head to move before tail.
tailForwardButton = findobj(gcbf,'Tag','tailForwardButton');
tailVal = getappdata(tailForwardButton,'buttonVal');
if headVal < tailVal
headVal = tailVal;
end % if
setappdata(headForwardButton,'buttonVal',headVal);
% Change selection based on dial settings.
setappdata(gcbf,'changedSinceLastSave',true);
update_for_selection(gcbf);
%-------------------------------------------------------------------------
function [] = head_forward_cb(src,eventdata)
%
% head_forward_cb.m--Callback for the "Head forward" button.
%-------------------------------------------------------------------------
buttonPower = str2num(get_popup_value(findobj(gcbf,'Tag','powerPopUp')));
headForwardButton = findobj(gcbf,'Tag','headForwardButton');
headVal = getappdata(headForwardButton,'buttonVal') + buttonPower;
dataLength = getappdata(headForwardButton,'max');
if headVal > dataLength
headVal = dataLength;
end % if
setappdata(headForwardButton,'buttonVal',headVal);
% Change selection based on dial settings.
setappdata(gcbf,'changedSinceLastSave',true);
update_for_selection(gcbf);
%-------------------------------------------------------------------------
function [] = quit_cb(src,eventdata)
%
% quit_cb.m--Callback for the "Quit" menu item.
%-------------------------------------------------------------------------
changedSinceLastSave = getappdata(gcbf,'changedSinceLastSave');
if changedSinceLastSave
r = questdlg('Unsaved changes exist. Really quit?',...
'choose_transect_limits','Yes','No','No');
if ~strcmp(r,'Yes')
return;
end % if
end % if
close(gcbf);
%-------------------------------------------------------------------------
function [] = save_cb(src,eventdata)
%
% save_cb.m--Callback for the "Save" menu item.
%-------------------------------------------------------------------------
ctlFig = gcbf;
transects = getappdata(ctlFig,'transects');
% Include the current transect's selection data in the save.
transectPtr = getappdata(ctlFig,'transectPtr');
transects = getappdata(ctlFig,'transects');
% ...Get the control settings.
[thisStartIndex,thisEndIndex] = get_current_selection(ctlFig);
% ...Put control settings into "transects" data structure.
existingIndices = [transects(transectPtr).startIndex ...
transects(transectPtr).endIndex];
if ~isequal(existingIndices,[thisStartIndex thisEndIndex])
transects(transectPtr).startIndex = thisStartIndex;
transects(transectPtr).endIndex = thisEndIndex;
setappdata(ctlFig,'transects',transects);
setappdata(ctlFig,'changedSinceLastSave',true);
end % if
% Sort the transects according to their start times (if user has inserted
% transects out of sequence, this will make order more rational).
[unsortedStartIndices{1:length(transects)}] = deal(transects.startIndex);
unsortedStartIndices = cell2mat(unsortedStartIndices);
[dummy,sortIndex] = sort(unsortedStartIndices);
transects = transects(sortIndex);
% Don't save transect numbers. These are prone to change, and it is
% misleading to assign any sort of permanent numbering system to them.
transects = rmfield(transects,'numbers');
[filename, pathname] = uiputfile('transects.mat', 'Save transects as');
if isequal(filename,0) || isequal(pathname,0)
return;
else
fullName = fullfile(pathname, filename);
if exist(fullName,'file')
r = questdlg('Specified file already exists. Overwrite?',...
'choose_transect_limits','Yes','No','No');
if ~strcmp(r,'Yes')
return;
end % if
end % if
save(fullName,'transects');
setappdata(gcbf,'changedSinceLastSave',false);
end % if
%-------------------------------------------------------------------------
function [] = load_cb(src,eventdata)
%
% load_cb.m--Callback for the "Load" menu item.
%-------------------------------------------------------------------------
ctlFig = gcbf;
transects = getappdata(ctlFig,'transects');
isEmptyData = length(transects) == 1;
isEmptyData = isEmptyData && transects.startIndex == 1;
isEmptyData = isEmptyData && transects.endIndex == 1;
isEmptyData = isEmptyData && isempty(transects.comments);
if ~isEmptyData
r = questdlg('Loading transect information will delete existing transects. Continue?',...
'choose_transect_limits','Yes','No','No');
if ~strcmp(r,'Yes')
return;
end % if
end % if
[filename, pathname, filterIndex] = uigetfile('*.mat', 'Pick a .mat file');
if filterIndex == 0
return;
end % if
fullName = fullfile(pathname, filename);
varNames = who('-file',fullName);
if ~ismember('transects',varNames)
errordlg('Specified .mat file does not contain ''transects'' variable.','choose_transect_limits');
return;
end % if
loadData = load(fullName);
transects = loadData.transects;
if ~all(ismember({'startIndex' 'endIndex' 'comments'},fieldnames(transects)))
errordlg('''transects'' variable does not contain required fields.','choose_transect_limits');
return;
end % if
% Sort the transects according to their start times (if user has inserted
% transects out of sequence, this will make order more rational).
[unsortedStartIndices{1:length(transects)}] = deal(transects.startIndex);
unsortedStartIndices = cell2mat(unsortedStartIndices);
[dummy,sortIndex] = sort(unsortedStartIndices);
transects = transects(sortIndex);
% Add 'numbers' field. Fields of transect structured variable must be in
% right order, so make new variable from scratch.
newTransects = [];
for iTransect = 1:length(transects)
newTransects(iTransect).numbers = iTransect;
newTransects(iTransect).startIndex = transects(iTransect).startIndex;
newTransects(iTransect).endIndex = transects(iTransect).endIndex;
newTransects(iTransect).comments = transects(iTransect).comments;
end % for
transects = newTransects;
setappdata(ctlFig,'transects',transects);
setappdata(ctlFig,'transectPtr',1);
setappdata(ctlFig,'changedSinceLastSave',false);
update_for_transect(ctlFig);
%-------------------------------------------------------------------------
function [] = comment_edit_cb(src,eventdata)
%
% comment_edit_cb.m--Callback for the "comment" edit box.
%-------------------------------------------------------------------------
ctlFig = gcbf;
transectPtr = getappdata(ctlFig,'transectPtr');
transects = getappdata(ctlFig,'transects');
transects(transectPtr).comments = get(src,'string');
setappdata(ctlFig,'transects',transects);
setappdata(ctlFig,'changedSinceLastSave',true);
%-------------------------------------------------------------------------
function [] = prev_transect_cb(src,eventdata)
%
% prev_transect_cb.m--Callback for the "previous transect" control.
%-------------------------------------------------------------------------
ctlFig = gcbf;
transectPtr = getappdata(ctlFig,'transectPtr');
if transectPtr > 1
% Save the current transect's selection data before moving on to the
% previous one.
transects = getappdata(ctlFig,'transects');
% ...Get the control settings.
[thisStartIndex,thisEndIndex] = get_current_selection(ctlFig);
% ...Put control settings into "transects" data structure.
existingIndices = [transects(transectPtr).startIndex ...
transects(transectPtr).endIndex];
if ~isequal(existingIndices,[thisStartIndex thisEndIndex])
transects(transectPtr).startIndex = thisStartIndex;
transects(transectPtr).endIndex = thisEndIndex;
% Save the modified version of transects.
setappdata(ctlFig,'transects',transects);
setappdata(ctlFig,'changedSinceLastSave',true);
end % if
% Now move to previous transect.
transectPtr = transectPtr - 1;
setappdata(gcbf,'transectPtr',transectPtr);
% Set the selection controls to the new values.
set_current_selection(ctlFig);
update_for_transect(ctlFig);
end % if
%-------------------------------------------------------------------------
function [] = next_transect_cb(src,eventdata)
%
% next_transect_cb.m--Callback for the "next transect" control.
% Developed in Matlab 7.6.0.324 (R2008a) on GLNX86.
% Kevin Bartlett (kpb@uvic.ca), 2008-06-04 10:45
%-------------------------------------------------------------------------
ctlFig = gcbf;
transectPtr = getappdata(ctlFig,'transectPtr');
% Save the current transect's selection data before moving on to the next.
transects = getappdata(ctlFig,'transects');
% ...Get the control settings.
[thisStartIndex,thisEndIndex] = get_current_selection(ctlFig);
% ...Put control settings into "transects" data structure.
existingIndices = [transects(transectPtr).startIndex ...
transects(transectPtr).endIndex];
if ~isequal(existingIndices,[thisStartIndex thisEndIndex])
transects(transectPtr).startIndex = thisStartIndex;
transects(transectPtr).endIndex = thisEndIndex;
% Save the modified version of transects.
setappdata(ctlFig,'transects',transects);
setappdata(ctlFig,'changedSinceLastSave',true);
end % if
% Now move to next transect.
transectPtr = transectPtr + 1;
setappdata(ctlFig,'transectPtr',transectPtr);
% If moving beyond last transect, create new one.
if transectPtr > length(transects)
insert_transect(ctlFig);
end % if
% Set the selection controls to the new values.
set_current_selection(ctlFig);
% Update display to show new transect.
update_for_transect(ctlFig);
%-------------------------------------------------------------------------
function [] = insert_transect(figNum)
%
% insert_transect.m--Inserts a new transect at the current transect pointer
% position.
%
% Syntax: insert_transect(figNum)
%-------------------------------------------------------------------------
transectPtr = getappdata(figNum,'transectPtr');
transects = getappdata(figNum,'transects');
% Create new transect for insertion.
if transectPtr == 1
newNum = 1;
newStartIndex = 1;
newEndIndex = 1;
else
newNum = transectPtr;
% Want selection controls both to point to start of new transect (i.e.,
% to END of previous transect).
newStartIndex = transects(transectPtr-1).endIndex;
newEndIndex = transects(transectPtr-1).endIndex;
end % if
insertTransect(1).numbers = newNum;
insertTransect(1).startIndex = newStartIndex;
insertTransect(1).endIndex = newEndIndex;
insertTransect(1).comments = '';
if transectPtr > length(transects)
% If new transect at end of data, can just append.
transects(transectPtr) = insertTransect;
else
% Otherwise, need to insert new transect in middle of data.
newTransects = [transects(1:transectPtr-1) insertTransect];
% Existing transects following the new one must be renumbered.
for iTransect = (transectPtr):length(transects),
transects(iTransect).numbers = transects(iTransect).numbers + 1;
end % for
newTransects = [newTransects transects((transectPtr):end)];
transects = newTransects;
end % if
setappdata(figNum,'transects',transects);
setappdata(figNum,'changedSinceLastSave',true);
update_for_transect(figNum);
%-------------------------------------------------------------------------
function [] = delete_transect(figNum)
%
% delete_transect.m--Deletes the current transect.
%
% Syntax: delete_transect(figNum)
%-------------------------------------------------------------------------
transectPtr = getappdata(figNum,'transectPtr');
transects = getappdata(figNum,'transects');
% Delete the current transect, but only if that will not drop us back to
% zero transects.
if length(transects) > 1
transects(transectPtr) = [];
numTransects = length(transects);
% If deleted transect was the last transect, transect pointer will now
% be pointing at a non-existent transect. Fix it:
if transectPtr > numTransects
transectPtr = numTransects;
setappdata(figNum,'transectPtr',transectPtr);
end % if
% Renumber the remaining transects.
for iTransect = 1:numTransects
transects(iTransect).numbers = iTransect;
end % for
setappdata(figNum,'transects',transects);
setappdata(figNum,'changedSinceLastSave',true);
end % if
update_for_transect(figNum);
%-------------------------------------------------------------------------
function [] = insert_transect_cb(src,eventdata)
%
% insert_transect_cb.m--Callback for "Insert" button.
%-------------------------------------------------------------------------
insert_transect(gcbf);
%-------------------------------------------------------------------------
function [] = delete_transect_cb(src,eventdata)
%
% delete_transect_cb.m--Callback for "Delete" button.
%-------------------------------------------------------------------------
delete_transect(gcbf);
%-------------------------------------------------------------------------
function [] = update_for_transect(figNum)
%
% update_for_transect.m--Updates display for current transect.
%
% Syntax: update_for_transect(figNum)
%-------------------------------------------------------------------------
transectPtr = getappdata(figNum,'transectPtr');
transects = getappdata(figNum,'transects');
set(findobj(figNum,'Tag','commentEdit'),'string',transects(transectPtr).comments);
fullLonLine = findobj(figNum,'Tag','fullLonLine');
time = get(fullLonLine,'xdata');
thisTransectNumber = transects(transectPtr).numbers;
transectNumText = findobj(figNum,'Tag','transectNumText');
transectNumStr = sprintf('Transect %d/%d',thisTransectNumber,length(transects));
set(transectNumText,'string',transectNumStr);
% Set the selection controls to point to the correct indices for this
% transect.
set_current_selection(figNum);
% Update display for (possibly) newly changed selection.
update_for_selection(figNum);
%-------------------------------------------------------------------------
function [] = power_pop_cb(src,eventdata)
%
% power_pop_cb.m--Callback for the "power" pop-up control.
% Developed in Matlab 7.6.0.324 (R2008a) on GLNX86.
% Kevin Bartlett (kpb@uvic.ca), 2008-06-04 10:45
%-------------------------------------------------------------------------
% Callback only needs to do anything if dial controls are being used
% instead of pushbuttons.
doUseDial = getappdata(gcbf,'doUseDial');
if doUseDial == false;
return;
end % if
headDial = dial.find_dial(gcbf,'headDial');
headDial = headDial{1};
headIndex = round(get(headDial,'Value'));
tailDial = dial.find_dial(gcbf,'tailDial');
tailDial = tailDial{1};
tailIndex = round(get(tailDial,'Value'));
popUpPowerStrs = get(gcbo,'String');
popUpPower = str2num(popUpPowerStrs{get(gcbo,'Value')});
% Setting the valRangePerRotation property (the "power") of the dial will
% cause the dial to change its orientation unless the dial reference value
% and reference orientation are reset at the same time. Use the current
% dial value and orientation as the new reference value and reference
% orientation.
% ...First determine the current dial orientations.
tail_dialValue = get(tailDial,'Value');
tailOrientation = get(tailDial,'orientation');
head_dialValue = get(headDial,'Value');
headOrientation = get(headDial,'orientation');
% ...Now reset the dial to use its current orientation and value as its
% reference orientation and reference value, respectively. This will
% prevent the dial from moving when its valRangePerRotation property is
% modified at the same time.
set(tailDial,'valRangePerRotation',popUpPower,'refVal',tail_dialValue,'refOrientation',tailOrientation);
set(headDial,'valRangePerRotation',popUpPower,'refVal',head_dialValue,'refOrientation',headOrientation);
%-------------------------------------------------------------------------
function [] = tail_dial_cb(src,eventdata)
%
% tail_dial_cb.m--Callback for "tail" dial.
%
% Syntax: tail_dial_cb
% Developed in Matlab 7.6.0.324 (R2008a) on GLNX86.
% Kevin Bartlett (kpb@uvic.ca), 2008-06-04 10:45
%-------------------------------------------------------------------------
tailDial = dial.find_dial(gcbf,'tailDial');
tailDial = tailDial{1};
tailVal = round(get(tailDial,'Value'));
headDial = dial.find_dial(gcbf,'headDial');
headDial = headDial{1};
headVal = round(get(headDial,'Value'));
% Don't allow tail to overtake head.
if tailVal > headVal
tailVal = headVal;
set(tailDial,'Value',tailVal);
end % if
% Change selection based on dial settings.
setappdata(gcbf,'changedSinceLastSave',true);
update_for_selection(gcbf);
%-------------------------------------------------------------------------
function [] = head_dial_cb(src,eventdata)
%
% head_dial_cb.m--Callback for "head" dial.
%
% Syntax: head_dial_cb
% Developed in Matlab 7.6.0.324 (R2008a) on GLNX86.
% Kevin Bartlett (kpb@uvic.ca), 2008-06-04 10:45
%-------------------------------------------------------------------------
tailDial = dial.find_dial(gcbf,'tailDial');
tailDial = tailDial{1};
tailVal = round(get(tailDial,'Value'));
headDial = dial.find_dial(gcbf,'headDial');
headDial = headDial{1};
headVal = round(get(headDial,'Value'));
% Don't allow head to move before tail.
if headVal < tailVal
headVal = tailVal;
set(headDial,'Value',headVal);
end % if
% Change selection based on dial settings.
setappdata(gcbf,'changedSinceLastSave',true);
update_for_selection(gcbf);
%-------------------------------------------------------------------------
function [] = update_for_selection(figNum)
%
% update_for_selection.m--Updates display for new start index and/or end index.
%
% Syntax: update_for_selection(figNum)
% Developed in Matlab 7.6.0.324 (R2008a) on GLNX86.
% Kevin Bartlett (kpb@uvic.ca), 2008-06-04 10:45
%-------------------------------------------------------------------------
[tailIndex,headIndex] = get_current_selection(figNum);
fullTrackLine = findobj(figNum,'Tag','fullTrackLine');
lon = get(fullTrackLine,'xdata');
lat = get(fullTrackLine,'ydata');
tailPointsText = findobj(figNum,'Tag','tailPointsText');
%set(tailPointsText,'string',sprintf('Point %d/%d',tailIndex,length(lon)));
set(tailPointsText,'string',sprintf('Tail: point %d/%d',tailIndex,length(lon)));
headPointsText = findobj(figNum,'Tag','headPointsText');
%set(headPointsText,'string',sprintf('Point %d/%d',headIndex,length(lon)));
set(headPointsText,'string',sprintf('Head: point %d/%d',headIndex,length(lon)));
selectLine = findobj(figNum,'Tag','selectLine');
set(selectLine,'xdata',lon(tailIndex:headIndex),'ydata',lat(tailIndex:headIndex));
headLine = findobj(figNum,'Tag','headLine');
set(headLine,'xdata',lon(headIndex),'ydata',lat(headIndex));
tailLine = findobj(figNum,'Tag','tailLine');
set(tailLine,'xdata',lon(tailIndex),'ydata',lat(tailIndex));
fullLonLine = findobj(figNum,'Tag','fullLonLine');
time = get(fullLonLine,'xdata');
selectLonLine = findobj(figNum,'Tag','selectLonLine');
set(selectLonLine,'xdata',time(tailIndex:headIndex),'ydata',lon(tailIndex:headIndex));
headLonLine = findobj(figNum,'Tag','headLonLine');
set(headLonLine,'xdata',time(headIndex),'ydata',lon(headIndex));
tailLonLine = findobj(figNum,'Tag','tailLonLine');
set(tailLonLine,'xdata',time(tailIndex),'ydata',lon(tailIndex));
selectLatLine = findobj(figNum,'Tag','selectLatLine');
set(selectLatLine,'xdata',time(tailIndex:headIndex),'ydata',lat(tailIndex:headIndex));
headLatLine = findobj(figNum,'Tag','headLatLine');
set(headLatLine,'xdata',time(headIndex),'ydata',lat(headIndex));
tailLatLine = findobj(figNum,'Tag','tailLatLine');
set(tailLatLine,'xdata',time(tailIndex),'ydata',lat(tailIndex));
transects = getappdata(figNum,'transects');
transectPtr = getappdata(figNum,'transectPtr');
thisStartTime = time(tailIndex);
thisEndTime = time(headIndex);
thisDuration = thisEndTime - thisStartTime;
isMtime = getappdata(figNum,'isMtime');
if ~isMtime
durationStr = sprintf('%d points',thisDuration);
elseif thisDuration < 120/(60*60*24) % (120 seconds converted to days)
durationStr = sprintf('%d seconds',round(thisDuration*(60*60*24)));
elseif thisDuration < 120/(60*24) % (120 minutes converted to days)
durationStr = sprintf('%d minutes',round(thisDuration*(60*24)));
else
durationStr = sprintf('%.1f hours',thisDuration*24);
end % if
if isMtime
startTimeStr = datestr(thisStartTime,31);
endTimeStr = datestr(thisEndTime,31);
end % if
if thisDuration == 0
if isMtime
statusStr = sprintf('Zero-length transect beginning at %s',startTimeStr);
else
statusStr = sprintf('Zero-length transect beginning at point %d',tailIndex);
end % if
else
if isMtime
statusStr = sprintf('%s - %s (duration %s)',startTimeStr,endTimeStr,durationStr);
else
statusStr = sprintf('%d - %d (duration %s)',tailIndex,headIndex,durationStr);
end % if
end % if
set(findobj(figNum,'Tag','statusText'),'string',statusStr);
%-------------------------------------------------------------------------
function [] = dialPower_cb()
%
% dialPower_cb.m--Callback for dial power edit box.
%
% Syntax: dialPower_cb
% Developed in Matlab 7.6.0.324 (R2008a) on GLNX86.
% Kevin Bartlett (kpb@uvic.ca), 2008-06-04 10:45
%-------------------------------------------------------------------------
tailDial = dial.find_dial(gcbf,'tailDial');
tailDial = tailDial{1};
headDial = dial.find_dial(gcbf,'headDial');
headDial = headDial{1};
dialPowerStr = get(gcbo,'string');
dialPower = str2double(dialPowerStr);
% Setting the valRangePerRotation property (the "power") of the dial will
% cause the dial to change its orientation unless the dial reference value
% and reference orientation are reset at the same time. Use the current
% dial value and orientation as the new reference value and reference
% orientation.
% ...First determine the current dial orientations.
tail_dialValue = get(tailDial,'Value');
tailOrientation = get(tailDial,'orientation');
head_dialValue = get(headDial,'Value');
headOrientation = get(headDial,'orientation');
% ...Now reset the dial to use its current orientation and value as its
% reference orientation and reference value, respectively. This will
% prevent the dial from moving when its valRangePerRotation property is
% modified at the same time.
set(tailDial,'valRangePerRotation',dialPower,'refVal',tail_dialValue,'refOrientation',tailOrientation);
set(headDial,'valRangePerRotation',dialPower,'refVal',head_dialValue,'refOrientation',headOrientation);