MATLAB Answers

How to set a scale in a figure (similiar to Google Maps)

9 views (last 30 days)
Jose Rego Terol
Jose Rego Terol on 16 Feb 2020
Commented: Jose Rego Terol on 8 Mar 2020 at 19:07
Hi all,
I have the following set of data, time versus Intensity. When I plot them want to draw a scale that changes accordingly with the zoom. I want to start with a default scale of 10 second. At the moment I zoom-in the figure, I want the scale to be shorter (something like Google Maps), for example, from 10 seconds to 1 second, and 0.05 second. Also, I want the scale be fixed to the figure. Therefore, I can pan the data and match the scale to the spikes you see in the figure. I have been using a line to check the baseline drift. The line is fixed to the figure, so I can pan the data and match the line to the beggining of the spike. I want to do the same with the scale (again, something similar to Google Mpas scale).

  1 Comment

Jose Rego Terol
Jose Rego Terol on 16 Feb 2020
I cannot set this scalebar in my code
f1=figure(1);
set(f1,'units','normalized','position',[0 0 1 1],'NumberTitle','on','ToolBar', 'None');
f1.WindowState = 'maximized';
hold on;box on; grid on;
plot(x,y,'b');%axis tight;
ylabel('Amplitud (pA)');
xlabel({'Time (s)'; ['foot-Spike:' num2str(fs) ' Flicker:' num2str(fl)...
' Kiss and Run:' num2str(KnR) ' Null:' num2str(null)]})
axis([x(1) x(length(x)) min(abs(y)) max(y)]); % Update plot
title(['Select two points around a ROI Event(s) so far: ' num2str(mNum)]);
ylim([-100 200]);

Sign in to comment.

Accepted Answer

Joseph Cheng
Joseph Cheng on 16 Feb 2020
Edited: Joseph Cheng on 16 Feb 2020
I don't understand what you're doing with that line to check baseline. I'll continue to read that however here is a quick scale bar that i'll let you adjust to stay locked to one of your scale bar sizes. This should get you going and you can adjust the scale plot color, shape etc, to get it how you'd like to see it. Especially adjusting the position within the frame
function Matlabanswer()
%gen dummy data
t=0:.001:10;
intensity = rand(size(t)).^2.*rand(size(t)).^10+rand(size(t)).^100;
hfig = figure(1);clf
hax(1) = axes(hfig);
plot(hax(1),t,intensity),xlabel('time'),ylabel('instensity');
ylim([0 20])
hax(2) = axes(hfig); %create the floating box where the scaler bar will be located
scalePos = [hax(1).Position(1)...
hax(1).Position(2)+hax(1).Position(4)-.1...
.1*hax(1).Position(3)...
.1*hax(1).Position(4)]; %designate upper left corner
%and scale secondary axes to be
%1/10 the size
hax(2).Position = scalePos; %scale the 2nd axes to the first.
plot(hax(2),t,zeros(size(t))) %plot data
xlim(hax(2),hax(1).XLim) %plot line the same length as data but in the 1/10 axes
set(hax(2),'XColor', 'none','YColor','none','color','none') %make scale axes invisible
%here is the section for annotation of what the scale line is
hanno = annotation('textbox', scalePos-[0 .05 0 0], 'String', ...
['scale ' num2str(.1*(diff(hax(1).XLim))) 'x']);
hanno.LineStyle='none';
%initiate the function for what happens when zooming
hzoom = zoom(hfig);
set(hzoom,'ActionPostCallback',{@myzoomfunction,hax,hanno});
function myzoomfunction(obj,event,AX,AnnoText)
xlim(AX(2),AX(1).XLim); %update the scale axes to match up with zoomed data
AnnoText.String=['scale ' num2str(.1*(diff(AX(1).XLim))) 'x']; %update the scale annotation

  4 Comments

Show 1 older comment
Jose Rego Terol
Jose Rego Terol on 16 Feb 2020
Hi again Joseph,
Thank you very much for this code. It is almost what I want. There is only few thing I wuold like to comment.
I finished implementing your code. It looks good but there are three issues that I need your help to solve them.
First, let me show you the figure:
As you can see, there are two different scales for each axis. I don't know how to remove the additional axes that your code have.
The second issue is the scale. I would like to represent the scale as a time reference. It means that the default bar length is 10 seconds, for example. In this sense, I would prefer the code from Cheng (https://de.mathworks.com/matlabcentral/fileexchange/59018-chenxinfeng4-scalebar).
Last but not least, the scale is steady to the window. This property is perfect because I can pan the plot, and the scale is attached to the figure. However, I would like to place it in the middle of the figure. Even though the code is full of comments, I tried to find the part of the code for this purpose, but I cannot find it. Where can I set the position fo the scale?
Thanks again for your time. I really appreciate the effort you did for this code.
Joseph Cheng
Joseph Cheng on 18 Feb 2020
How about this. sorry i was busy with my day job.
I simplified it instead of using an additional axis plotted into the window you can use annotations and know how it scales with the plot.
This will lock it to the center of the screen. if you don't want the text to be in that location. Just move the arrow annotation text into a new annotation text box in the location where you want it to be. As these annotation is locked to the figure it will not change when panned around. I only did the X axis however if you read up on the annotation() function you can just as easily make it for a Y scale bar too
function Matlabanswer()
%gen dummy data
t=0:.001:100;
intensity = rand(size(t)).^2.*rand(size(t)).^10+rand(size(t)).^100;
hfig = figure(1);clf
hax = axes(hfig);
plot(hax,t,intensity),xlabel('time'),ylabel('instensity');
grid minor
%here is the section for annotation of what the scale line is
initScaleLengthsec = 10;%in seconds
initScaleLengthNorm = initScaleLengthsec/diff(hax.XLim); % ratio of the scale length
%against the span of the plot limits as we'll be dealing with normalized
% % to the figure window
%generate the X and Y locations here. since these are in normalized space of the figure
%example here is scalePosX start and stop of the arrow is half the plot window size
% and half the plot window size + the ratio of the window size.
%this is then offset by Position(1) since the position(1) is the lower left corner of the
%plot in relation to the window.
%read up on the position attribute since this is the best i can describe right now.
%position attribute [lowerleftX lowerleftY width height];
scalePosX = [hax(1).Position(3)*1/2,...
hax(1).Position(3)*1/2+initScaleLengthNorm*hax(1).Position(3)]+...
hax(1).Position(1);
%set Y position of the arrow as half way up the height (position(4)) and offset by
%position of the plot axes.
scalePosY = [hax(1).Position(2)+hax(1).Position(4)/2,...
hax(1).Position(2)+hax(1).Position(4)/2];
%generate text arrow.
hanno = annotation('textarrow',scalePosX,scalePosY, 'String', ...
[num2str(initScaleLengthsec) 'seconds']);
%initiate the function for what happens when zooming
hzoom = zoom(hfig);
set(hzoom,'ActionPostCallback',{@myzoomfunction,hax,hanno});
%edit these callbacks should be in there as you can zoom with scroll mouse
%and double click which will reset the view but not trigger the update in scale
hfig.WindowButtonUpFcn={@myzoomfunction,hax,hanno};
hfig.WindowScrollWheelFcn={@myzoomfunction,hax,hanno};
function myzoomfunction(obj,event,AX,AnnoText)
%find the span of the plot
plotSpan = diff(AX.XLim);
%my attempt to set the limits of when to update annotation.
switch true
case plotSpan>50
span=10;
case plotSpan<=50 && plotSpan>25
span=5;
case plotSpan<=25 && plotSpan>10
span=2;
case plotSpan<=10 && plotSpan>2
span=.5;
case plotSpan<=2 && plotSpan>.1
span=0.05;
otherwise
span=0.01;
end
%again find the new ratio of width of plot to desired scale span
ScaleLengthNorm = span/diff(AX.XLim);
%generate again how long the arrow is
scalePosX = [AX(1).Position(3)*1/2,...
AX(1).Position(3)*1/2+ScaleLengthNorm*AX(1).Position(3)]+...
AX(1).Position(1);
scalePosY = [AX(1).Position(2)+AX(1).Position(4)/2,...
AX(1).Position(2)+AX(1).Position(4)/2];
%update the annotation's X start stop
AnnoText.X=scalePosX;
%update the annotation's Y start stop
AnnoText.Y=scalePosY;
%update the text to new span.
AnnoText.String=[num2str(span) 'seconds'];
Jose Rego Terol
Jose Rego Terol on 8 Mar 2020 at 19:07
I am so sorry Joseph. I could not respond until now.
Your code is working good. Thi is what I wanted to have. Thanks a lot.

Sign in to comment.

More Answers (0)

Sign in to answer this question.