MATLAB Spoken Here

Focused on Zooming 26

Posted by admin,

I'd like to welcome guest blogger Dan Sternberg from the Plotting and Exploration team. Dan will occasionally be blogging here on the Inside the MATLAB Desktop blog.

Zooming in figures has been around forever. There are a couple of neat zoom enhancements, though, that may have snuck in under your radar (you didn't read the release notes?!). Between MATLAB 7.0 (R14) and MATLAB 7.3 (R2006b) we added the ability to link two axes, constrain a zoom and customize a zoom. Here are a few examples to help you get started.

Contents

Zooming an Axes

We'll start by plotting some data. I'll use one of my favorite data sets, the magic square:

ax = axes;
p = plot(ax,magic(3));

To enter zoom mode, I can click on the toolbar button shaped like a magnifying glass.

Alternatively, I can enter the mode from the command-line.

zoom on;

For the purposes of this posting, whenever I wish to zoom, I'll do so programatically, and by a factor of two.

zoom(2);

Linking two Axes

Simply using the zoom tool, I am able to explore a data set that exists in a single axes. You might ask, however,

"What if I have two subplots with data that is related? If I zoom in on one plot, can I have the other one follow suit?"

That's an excellent question. I'm glad you asked. Let's create two sequences of data that share a domain, but but live in different ranges.

x1 = -2*pi:0.1:2*pi;
y1 = sin(x1);
x2 = -4*pi:0.1:4*pi;
y2 = cos(x2)*100;
ax(1) = subplot(1,2,1);
plot(ax(1),x1,y1);
ax(2) = subplot(1,2,2);
plot(ax(2),x2,y2);

I can now link these two axes

linkaxes(ax,'x');

From this point onwards, if the limits of one x-axis change (perhaps due to a zoom operation), the limits of the second axes will follow.

Constraining the Zoom

In addition to linking axes, we can also constrain the zoom direction. For example, I may not want to zoom the y-axis of either one of my subplots.

zoom xon;
zoom(2);

Customizing the Zoom

It may happen, however, that the two data sets I've plotted do not share a domain or range, but are correlated in some way. In this case, I need to do a bit more work to build a relationship. Let's begin by getting the zoom object for the figure.

hZoom = zoom(gcf);
get(hZoom)
      ButtonDownFilter: []
     ActionPreCallback: []
    ActionPostCallback: []
                Enable: 'on'
          FigureHandle: [1x1 figure]
                Motion: 'horizontal'
             Direction: 'in'
      RightClickAction: 'PostContextMenu'
         UIContextMenu: []

From this object, we can get some information about the state of the figure. For example, we see that zoom mode is on, and constrained to be horizontal (x-only).

There are also callbacks that may help us further customizing the zoom behavior of these two axes. When the axes were linked, I lost some information in the second axes. I would much prefer that the second axes zooms twice as much as the first and the first zooms half as much as the second. To enforce this relationship, I can use the "ActionPostCallback" property of the object.

set(hZoom,'ActionPostCallback',{@halfZoom,ax});
dbtype halfZoom.m
1     function halfZoom(fig,evd,ax) %#ok<INUSL>
2     % Zoom one axes by a factor of two from the other:
3     
4     currentAxes = evd.Axes;
5     if currentAxes == ax(1)
6         % If we are zooming the left axes, zoom the right axes by twice as
7         % much:
8         newLim = get(currentAxes,'XLim');
9         set(ax(2),'XLim',newLim*2);
10    else
11        % If we are zooming the right axes, zoom the left axes by half as much:
12        newLim = get(currentAxes,'XLim');
13        set(ax(1),'XLim',newLim/2);
14    end

The event data of the callback tells me which axes I've zoomed in on. From there, I can obtain the axes limits and perform the necessary calculations to enforce this relationship.

linkaxes(ax,'off');
set(ax,'XLimMode','auto');
zoom(2);

Using the zoom object, I am also able to prevent an axes from being zoomed or have it only zoom in a particular direction.

setAllowAxesZoom(hZoom,ax,false);

At this point, there will be no change to the figure if I attempt to zoom in either axes.

Using Zoom in a Custom Application

Using the zoom object, it is now possible to take advantage of zooming behavior in a custom application. For example, we can construct a figure containing an overview axes. Whenever I zoom in on the main axes, I am able to see where I am in my data.

overviewPlot(gcf,magic(3));
set(gcf,'Color','w');
zoom on;
zoom(2);

The code to the "overviewPlot" function can be found on the File Exchange here.

Similar features exist for the "pan" and "rotate3d" functions. What sorts of customizations would you like to be able to accomplish using these tools?

Here's a video that demonstrates how to use the overviewPlot function. Thanks to Doug (of Doug's Pick of the Week) for recording this.

-by Dan Sternberg, The MathWorks
This blog entry was written using the MATLAB publishing feature.


Get the MATLAB code

Published with MATLAB® 7.5

26 CommentsOldest to Newest

what about linking axes that are not both x or y?
x = magic(3)
ax(1) = subplot(4,1,1);
plot(ax(1),x(1,:),x(2,:));
ylabel(‘y1′);
ax(2) = subplot(4,1,2);
plot(ax(2),x(1,:),x(3,:));
ylabel(‘y2′)
ax(2) = subplot(4,1,[3 4]);
plot(ax(2),x(2,:),x(3,:));
xlabel(‘y1′);
ylabel(‘y2′);

so here the top two plots have the same ylim (0 to 10) but when that y data is cross-plotted at the bottom, the xlim (3 to 7) and ylim are not the same (2 to 10)?

i make plots like this quite frequently, but would like to automatically make those axes (y1 and y2) the same when they are at the top and at the bottom.

thanks,
jason.

Hi Jason,

Currently, it is not possible to link two different directions together. I have logged this as an enhancement request in our database for consideration in a future release. Currently, the closest thing to do is use the “ActionPostCallback” to ensure the relationship between the axes manually.

-Dan

What about zooming on axes that have been “dateticked” ?

dts=(now-99:now)’;w=exp(.2^2*(1:100)’/2+.2*cumsum(randn(100,1)));
figure;plot(dts,w,’linewidth’,2);datetick
zoom(2)

the ticks are lost (no automatic redraw of them)…

Good job
please tell my if can use this software to study thy number of periods in dynamic system

Linking axes and constrained zooming are both very powerful capabilities that I am used to in Simulink scopes. I always thought (and still do think) that Matlab should include additional toolbar buttons to link axes and constrained zooming, so I created the following Shortcuts on my Matlab toolbar. Each shortcut is applied to the current figure.

X Zoom
>>zoom xon

Y Zoom
>>zoom yon

Link X Axes
(I use this all the time, but unfortunately the syntax of the function requires the handles of all the subplots which may not be immediately known in order to link axes in the x or y direction. Therefore, I swiped some code out of the top of linkaxes and created a shortcut with the following code.)
>>fig = get(0,’CurrentFigure’);
>>if isempty(fig), return; end
>>ax = findobj(fig,’Type’,'Axes’);
>>nondatachild = logical([]);
>>for k=length(ax):-1:1
>>nondatachild(k) = isappdata(ax(k),’NonDataObject’);
>>end
>>ax(nondatachild) = [];
>>linkaxes(ax,’x')

Pat,

It’s not often that people talk about how the simulink scopes are more powerful than a regular figure window :-). Another option, although I am not sure if it is less work, would be to use the new toolbar editor to create icons for a toolbar in a MATLAB GUI to do the same things.

Wenjian,

You can link axes containing two images using the syntax
linkaxes(ax,’x')
where “ax” is a vector containing the handles to the two axes.

I’d really like to be able to put a zoomed in version of part of the figure inside the original figure, so that one can see the overview, as well as details of some interesting part at the same time.

I was trying to do zoom, then copy object, but zoom always affect all lines in the same plot. Maybe I should consider overlaying two plots in the same figure? Haven’t found anything about this yet.

Hi,

I have a couple of questions…

I would like to be able to zoom in and out by a factor that is much larger than 2, but sometimes it does not work. How would I be able to do that?

I have tried to zoom in by adjusting the axis range/limits (e.g. by changing the max x-axis limit from 0.14 to 10e-9), or by dragging a box using the zoom-microscope (instead of the ‘hand’ tool). However, most of the time the result is only the area I’ve selected, at its original size! How can I blow up the small area I selected to be as large as the usual figure size? How come in some cases changing the axis range/limits does not seem to work?

Perplexed,

J

@J,

It’s difficult to explain what is going on without seeing your graph or the exact commands you are using. If you are using a standard line plot, it’s possible that the zoomed in region has the same shape as the original plot. This happens a lot when you zoom in on a plot that does not have a lot of actual data points or does not vary much from point to point. One way to verify that your plot is zooming is when using the interactive tools to see the axes labels change. Depending on the range and label, it may not look like much is happening, also sometimes it can only be seen by the exponent multiplier at the edge of the axis.

Hi,

How to zoom in a graph in a specified position. I use
zoom(6) in my code now. But the default graphs that Matlab generated are not at the place where I want to see. I don’t want to drag it.

Best,
Lei

Hi,

I do lots of zooming around graph for data exploration (often with multiple linked axes). Restricted zooming is very useful. The problem is, changing the zoom direction using the context menu is quite frustrating.

I would like to use the Control and Alt modifiers to set the direction, e.g. ctrl-drag will zoom horizontally, alt-drag will zoom vertically, shift will reverse zoom direction (as it does). Alternatively – use regular keys such as “x”, “y” and “z” to change the restriction while zoom mode is on. I can’t do either one with callbacks, as far as I can tell.

Is there a way to do that? if not – please consider this a feature request…

Thanks

Adee

@Richard,
Not by itself. You can always compare x,y, and z-limits to a known value and see if they have changed from the original

@Richard,

Even though this won’t let you determine whether it was zoomed or not, but

zoom out

would allow you to reset to the initial zoom setting. But note that the initial setting can be changed by

zoom reset

@Yair, jiro, Mike. Thanks, this is all very useful info. The main reason I want to know is because I’m developing a code to automatically produce ‘tight’ figures without excess space around them for publication. I also want this code to work for subplots by getting the minimum required bounding box (based on the ‘TightInset’ and ‘Position’ properties of every axes in the figure. My problem is, if a 3D plot has been zoomed, these properties are no longer useful, and the figure should be ignored, or left as it is. 2D plots that have been zoomed are fine, as the axes stay where they are in the figure, but the whole view of the figure changes if any 3D axes have been zoomed. I have found a way to determine if an axes is 3D, using the view function. Perhaps using your tips I can get the last part.

Sir, I am creating GUI in which I plot my streaming data. So that the figure is updated everytime. I want to add zoom option in that. What should I do?

Like Adee, I search through large amounts of data using sets of Matlab subplots with linked axes. I frequently switch between horizontal zoom, vertical zoom, and unconstrained zoom. It gets very slow and tedious to constantly be right clicking to change the Zoom Options. I would very very much like to hold down a key (whether it be Ctrl, Alt, or even alphanumeric) which would set the type of zoom to be performed. This would greatly improve my efficiency.

I see that you said in April 2010 that you had submitted a feature request to allow something like this. Has there been any progress?

Thanks!
Keith

I have a 2d image and I’d like to have available the entire image to show with imshow, but initially start from the zoomed view at the selected region for all of them. For example, zoom in and show only image(100:400, 100:400) of an image that is 1024*1024.
How can I specify that in the command line ?
Thank you.

These postings are the author's and don't necessarily represent the opinions of MathWorks.