function harmonic_cursors(h)
% HARMONIC_CURSORS Application M-file for harmonic_cursors
%
% Uses mouse-click input from user to set the value of the first
% harmonic, which diplays a line and lines for higher harmonics.
% Displays the value of the harmonics at the top of the axis, just
% above the axis box. You can nudge the first harmonic in small
% increments by using the right mouse button; a right-click to the
% left of the first harmonic will nudge it left, and vice-versa for
% the right. (There is a "nudge_factor" that can be adjusted to
% make the nudge delta larger or smaller for your application.
% It you want to remove the cursors, click once to get the
% crosshairs, and then click off of the axis to the left or right.
%
% EXAMPLES: Can be used simply as a function call after a plot has
% been generated:
% plot(x,y)
% harmonic_cursors(gca)
%
% Alternatively, the function can be called from the command line,
% from another function, or using a callback object by passing
% the axis handle of the plot as the argument.
%
% Written 22-Jan-2003 19:12:50 by Jeff Daniels NSWCCD - ARD
if nargin == 0 % Perform Mouse Callback Function
% Do not perform callback if zoom tool is active
state = getappdata(gcf,'ZOOMFigureState');
if ~isempty(state), break, end
% Get Axis Information and user input from mouse
yaxlim=get(gca,'YLim'); % Get Y-Axis limits
xaxlim=get(gca,'XLim'); % Get X-Axis limits
[x,y,button]=ginput(1); % Get first harmonic data point
warning off
if button==1, % if left-click, plot new cursors
% Calculated x,y position of cursors and labels
nlines = floor(xaxlim(2)/x); % Calculate number of lines to display
ypoint=yaxlim(2)+(yaxlim(2)-yaxlim(1))*0.035; % This puts the label just above the axis box, but below the title.
for i=1:nlines,
xpoint=x*i;
xmat(1:2,i)=[xpoint;xpoint];
label_h(i)=text(xpoint,ypoint,[num2str(i),'X = ',num2str(xpoint,4)],...
'Color','red','FontName','Arial','FontSize',[8.0]);
end
ymat=repmat(yaxlim',1,nlines);
% Remove cursors and labels from previous uses
try
old_line_h=findobj('Tag',['HarmonicCursor',num2str(gca)]);
old_label_h=findobj('Tag',['HarmonicLabel',num2str(gca)]);
delete(old_line_h)
delete(old_label_h)
catch
disp(lasterr)
end
% Draw Cursors and Labels
line_h=line(xmat,ymat,'Color',[1 0 0],'Tag',['HarmonicCursor',num2str(gca)],...
'LineWidth',[1.0],'LineStyle','--');
line_props=get(line_h);
set(label_h,'Tag',['HarmonicLabel',num2str(gca)])
label_props=get(label_h);
elseif button==3, % if right-click, move cursors by bin_width
try
% Find line handles from previous uses and determine position
old_line_h=findobj('Tag',['HarmonicCursor',num2str(gca)]);
old_line_h=sort(old_line_h);
old_line_props=get(old_line_h(1));
old_line_xpos=old_line_props.XData;
% This is an unsuccessful attempt to automatically scale the nudge factor.
% data_h=findobj(gca,'Type','line','Tag','');
% data_len=length(get(data_h,'XData'));
% nudge_factor=min(data_len,10000)
% This factor seems to work well for most data lengths, but can be adjusted.
nudge_factor=10000;
% Calculate bin_width value to nudge first harmonic by.
bin_width=(xaxlim(2)-xaxlim(1))/nudge_factor*sign(x-old_line_xpos(1));
% Find label handles from previous uses and determine position
old_label_h=findobj('Tag',['HarmonicLabel',num2str(gca)]);
old_label_h=sort(old_label_h);
old_label_props=get(old_label_h(1));
old_label_pos=old_label_props.Position;
% Change position of lines and labels by bin_width
new_label_pos=old_label_pos;
new_label_pos(1)=old_label_pos(1)+bin_width;
new_line_xpos=old_line_xpos+bin_width;
nlines = floor(xaxlim(2)/new_label_pos(1)); % Calculate number of lines to display
for i=1:nlines,
next_label_pos = new_label_pos;
next_label_pos(1) = new_label_pos(1)*i;
next_line_xpos = new_line_xpos*i;
set(old_line_h(i),'XData',next_line_xpos)
set(old_label_h(i),'Position',next_label_pos,'String',[num2str(i),'X = ',num2str(next_label_pos(1),4)])
end
catch
disp(lasterr)
end
end
elseif nargin == 1 % Setup Mouse Callback Function
if ishandle(h),
try
get(h,'Type')=='axes';
set(h,'ButtonDownFcn','harmonic_cursors')
catch
disp('Error: Argument is not a valid axis handle!')
end
end
end