This utility provides a powerful zooming tool specially designed for the documentation of original and zoomed 2D graphics of images on the same plot.
It is composed of two blocks (the secondary axes and the magnifier). The secondary axes, which can be arbitrarily allocated within the limits of the figure, displays the area marked by the magnifier.
The highly versatile interface of the 'on-figure magnifier' offers a world of possibilities in a broad range of applications and fields. The Keyboard/mouse or programmatic configuration of this tool allows the user to set her or his own graphic style, to suit the requirements of any publication's editor. More details on interfacing and properties can be found in the .m file.
EXAMPLE: (for usage examples, run 'magnifyOnFigure_examples.m')
'edgeWidth' Color of the box surrounding the secondary
axes, magnifier and link. Default 1
'edgeColor': Color of the box surrounding the secondary
axes, magnifier and link. Default 'black'
'displayLinkStyle': Style of the link. 'none', 'straight' or
'edges', with 'straight' as default.
'mode': 'manual' or 'interactive' (allowing
adjustments through mouse/keyboard). Default
'units' Units in which the position vectors are
given. Only 'pixels' currently supported
'initialPositionSecondaryAxes': Initial position vector ([left bottom width height])
of secondary axes, in pixels
'initialPositionMagnifier': Initial position vector ([left bottom width height])
of magnifier, in pixels
'secondaryAxesXLim': Initial XLim value of the secondary axes
'secondaryAxesYLim': Initial YLim value of the secondary axes
HOT KEYS (active if 'mode' set to 'interactive')
-In a figure with multiple magnigier instances
'Tab': Switch the focus from one magnifier instance
to the next one on the current figure.
'Mouse pointer on secondary axes or magnifier of a tool+double left click'
-On the focused magnifier instance
'up arrow': Moves magnifier 1 pixel upwards
'down arrow': Moves magnifier 1 pixel downwards
'left arrow': Moves magnifier 1 pixel to the left
'right arrow': Moves magnifier 1 pixel to the right
'Shift+up arrow': Expands magnifier 10% on the Y-axis
'Shift+down arrow': Compress magnifier 10% on the -axis
'Shift+left arrow': Compress magnifier 10% on the X-axis
'Shift+right arrow': Expands magnifier 10% on the X-axis
'Control+up arrow': Moves secondary axes 1 pixel upwards
'Control+down arrow': Moves secondary axes 1 pixel downwards
'Control+left arrow': Moves secondary axes 1 pixel to the left
'Control+right arrow': Moves secondary axes 1 pixel to the right
'Alt+up arrow': Expands secondary axes 10% on the Y-axis
'Alt+down arrow': Compress secondary axes 10% on the Y-axis
'Alt+left arrow': Compress secondary axes 10% on the X-axis
'Alt+right arrow': Expands secondary axes 10% on the X-axis
'PageUp': Increase additional zooming factor on X-axis
'PageDown': Decrease additional zooming factor on X-axis
'Shift+PageUp': Increase additional zooming factor on Y-axis
'Shift+PageDown': Decrease additional zooming factor on Y-axis
'Control+Q': Resets the additional zooming factors to 0
'Control+A': Displays position of secondary axes and
magnifier in the command window
'Control+D': Deletes the focused tool
'Mouse pointer on magnifier+left click' Drag magnifier to any
'Mouse pointer on secondary axes+left click' Drag secondary axes in any
User interface not very useful. Would be very nice if a user could input the coordinates that are to be zoomed, and the coordinates of where to put the second axes. Some debugging on newer versions is also necessary.
Update - to customize each magnifier on subplots, just press tab, so as to handle different magnifiers.
To handle subplots, just comment the command: appDataStruct.mainAxesHandle = childHandle( iAxes(end) ); (line 176 I think)
and use: appDataStruct.mainAxesHandle = gca;
The only negative thing is that the interactive mode is only restricted to the magnifier of the last plot. A ...lazy solution is to just pause the code for each subplot's magnifier, so as to customize it.
I got the same error as batterie amine. Any suggestions?
Undefined operator '+' for input
arguments of type 'matlab.ui.Figure'.
Error in magnifyOnFigure (line 433)
toolId = appDataStruct.figureHandle
Struct contents reference from a
non-struct array object.
Error while evaluating Figure WindowButtonMotionFcn
Struct contents reference from a
non-struct array object.
It don't works if datetime on axis.
Just missing update the zoomed figure when you move the area with the keyboard and change the line (that connect the area with the zoomed figure) when you move the area.
When you move the zoomed figure works normally.
Thank you very much !!!
It's very useful !!!
Excellent tool box. I see some people have problems with subplots. It is easy to solve. Subplots can also defined as Fighandlers with fighandler = subplot (); And then pass this handler to the function.
I was facing some issue in line 433. Error message:
"Undefined function 'plus' for input arguments of type 'matlab.ui.Figure'."
so I just changed the code to:
toolId = 1234 % pretty much any thing here would do
Hope this helps people who got this error!
When i use semilogx the zoom box is not placed correctly on the graph.
How can i overcome this problem ?
Very user friendly! Also no problem to save the figure in eps-format.
Thanks for sharing this function. But when I save the plot, the magnifier becomes small and moves outside of the figure , somewhere in the southwest outside corner. Does anyone know why?
All, On Matlab 2014 I am trying to use this function replacing piece of code as mentioned by Hugo & chaks. But I receive an error message "Undefined function 'plusmof' for input arguments..."
Can someone help me here?
Very good! One problem I meet is that when I save the figure and reopen the .fig file, I cannot operate the magnifiers again.
I run the program on MATLAB 2015a, one error was occuring "Error using plot
There is no LineSmooth property on the Line class." at line 20.
If we replace the line plot(rand(100,1), 'b'); plot(rand(300, 1), 'r', 'LineSmooth','on'); with
plot(rand(100,1), 'b'); plot(rand(300, 1), 'r');
The code works fine.
@Timo, thank you for your contribution. It really works!
Following his instruction, the final form in the m file magnifyOnFigure.m is:
%Compute unique ID of this magnifying tool, from handles of its elements
toolId = plusmof(appDataStruct.figureHandle,appDataStruct.figureHandle);
toolId = plusmof(toolId,appDataStruct.mainAxesHandle);
toolId = plusmof(toolId,appDataStruct.magnifierHandle);
toolId = plusmof(toolId,appDataStruct.linkHandle);
toolId = plusmof(toolId,appDataStruct.secondaryAxesHandle);
@Jamal Ahmad, if you are running 2014b or newer (as me), the '+' operator does not work on figure handles anymore, as figure handles are no more seen as integers. Some searches on google got me a solution, you can 'overload' the builtin function 'plus' (which is called when you use the + operator). The beauty is that the overloaded 'plus' function is only called when the builtin function gets an error (as it does right now), so in normal cases you won't have any performance losses.
function out = plus(A,B)
% This function overloads the default plus function, but only if the
% default plus function can't solve it. Usefull to fix the function
% magnifyOnFigure.m, in which the '+' operator is used on figure handles,
% but after matlab 2014b these aren't seen as integers anymore.
out = double(A) + double(B);
%Fail with the built-in
Thanks for the effort.
why I get this error:
Undefined operator '+' for input arguments of type
Error in magnifyOnFigure (line 433)
toolId = appDataStruct.figureHandle +...
Awesome. I placed three instances on the plot and used "File", "Generate Code" to get the position vector of the magnified boxes. How do I convert the normalized position vector to pixels required by this function? And is there an easier way to do it than this?
Nice... I have been using this alot... its been very handy... thanks for sharing it...
Very useful. Thanks for sharing this.
But I have a problem now.
I want to export figures in pdf format. And I used the following line to export.
print -r0 -dpdf test.pdf
The figure was exported well, but one problem was that magnifier has been shifted to leftside.
Is there any solution?
Matthew thank you it works!
Great submission. Thanks for posting.
Panayiotis: You can hack this to work by changing line 433 to read: "toolId = now;"
Indeed a great tool. Unfortunately it works up until MATLAB 2014a. I have recently installed MATLAB 2014b and when I ran the example file I get the following error:
Undefined function 'plus' for input arguments of type 'matlab.ui.Figure'.
Error in magnifyOnFigure (line 433)
toolId = appDataStruct.figureHandle +...
Error in magnifyOnFigure_examples (line 23)
Is there a way around this? I am aware that in MATLAB 2014b some changes have been implemented with respect to figure plotting. I am not sure if this is related to the error.
Thank you in advance!
I have found a temporary fix for the exporting as eps problem. When you export, do not "Save As" but instead use "Export Setup". Under "Rendering" in Properties, choose the Resolution as "Screen" (do NOT use Auto). This should keep the magnifying square where it should be.
This a great function!
Just one question, if a new instance of the magnifier is called then it is created on top of the existing one. is there a possibility to adjust the code so that it "resets" previous instances of the magnifier once the magnifier function is called?
Very good work.Genius of you!
This is pretty genius - thanks
I made an account to rate this great tool, works like a charm!
thanks a lot sir, you really helped me and i appreciate it very much. wish you the best.
Thank you very much! It is very useful!
Brilliant job! Thanks a lot! I can create my figure easily by using it.
But there are some bugs in it. When I saved the figure as a .eps file, it accidentally created something like a black rectangle on the south-west corner. Hope anyone can fix that.
Thanks in advance!
Fantastic work, very useful
Great tool!! I join my voice in the issue of the magnifier window disappearing on export though. A solution would be amazing!
This is a really nice tool, thanks! I would like to echo Daly's comment about the known bug regarding the position of the magnifier window after printing the figure. This function is perfect for what I am doing, but I need to be able to export the figure and it seems impossible without a fix for the magnifier window position problem. Do you have any suggestions for work-arounds? Thanks again.
Thanks for the tool! I have a small question. I have 5 subplots in one figure window. When I use the code either in manual or interactive mode, the zoom window gets stuck in the first subplot. Even when I give the coordinates for the zoom window inside the second subplot, it is located near the border of the first subplot. I am using Matlab R2012b on Ubuntu 12.04. Do you have any idea on this issue?
Thanks in advance!
Amazing tool. Congratulations!!
Good tool. Could you add a keypress action to disable the tool i.e. press 'Esc'? Also I notice that when I zoom the magnify plot the box outine on the original axes doesn't change. This causes a disconnect between the inset and the box outline. The tool would be nearly perfect if those two issue were addressed. As it stands right now there doesn't appear to be a good way to exit the tool. Maybe I've missed something?
Very attractive! Just a problem that i I have encountered when i try to export the figure in eps format with print function. The magnifier shrink and move out the axes to the right corner of the generates image. The link between the magnifier and the secondary axes is not affected and it kept its position. The only problem is with the magnifier. Can anyone helps me please.
Thanks for Mr David and all they contribute here.
Thank you for sharing your code.
I hade used this code.
Initial position vector ([left bottom width height]),the unit is 'pixels' ,the width and height can be right,but left and bottom are wrong. the same problem is with 'initialPositionMagnifier'.
[Tempfirst,rect] = imcrop(Picfirst);
figure(2);imshow(Picfirst);title('Picfirst and Tempfirst');
'mode','interactive','edgeWidth', 3,'edgeColor', 'red');
this tool is exactly what I had been looking for. However, I found issues with magnifying 3D plots. Can you please check and update it for 3D plots with an example?
Many, many Thanks!!.... I have never seen better script!... I love it!
Very nice and helpful
and thank a lot for this function! It works really well. Only one thing - and I'm not sure whether I'm doing something wrong or if it's actually a small bug in your code: When I select the 'DisplayLinkStyle' to be 'edges' I get an error in line 1918 (version 1.17 on MATLAB 2009b). I made a little change to the code to fix this problem (at least for me):
linkHandle = appDataStruct.linkHandle;
linkhandle = appDataStruct.linkHandle;
That was a typo, I guess! And
if isempty( appDataStruct.linkHandle )
if isempty( appDataStruct.linkHandle ) || length(appDataStruct.linkHandle<4)
Maybe this is of use for anyone... :)
Cheers from Germany and regards,
Thanks for sharing this nice code.
A bug: when the figure is saved as an .eps the rectangle framing the section of curve to be enlarged disappears in the saved version.
how I can enlarge and display in a window Figure
its very useful
Very nice work.
its very useful..
i'm sorry if this feature is already added but i couldn't see.
how can i magnify on subplots?
i added between the subplots but it couldn't work.
This is Amazing!
I wish you added support for more units (The axis units would be great).
Cheers to the great work. I have a couple of questions to ask. i) How do I set the Y limits of the magnifier to match the plot area height? ii) Can I use the magnifier as a push button callback in a GUI? Thanks in advance.
1. You can easily change the color of the border of the magnifier and secondary axis through the property 'edgeColor', which by default is set to black.
2. At this moment, the tool does not provide a handle at calling time. However, there are several supported Hot Key combinations that might be useful for your purpose. 'Control+D', for instance, can be used to delete the tool from the current figure.
I hope that helps!
This is great! Two simple questions:
1. If I wanted to change the color of the borders of the magnifier and the secondary axis, where in the code would I make the change? As is, they're showing as black, and my images are predominantly black, making them difficult to see.
2. I'm integrating the magnifier as part of a GUI, and would like to be able to toggle it on and off. It's not clear to me how to remove the magnifier once it has been initialized. Is it possible to create a handle when the magnifier starts, which can be used as an argument to a delete() call?
Everything is great, except for the fact than when semilogy is used instead of plot, the zoom box is not placed correctly on the graph. Is is misplaced a little bit lower than it should be.
Any changes to overcome this problem?
Please feel free to mail me at theoxarhs at google.com if a simple change could resolve this bug(?).
Thanks in advance.
While this looks like a nice tool, I experienced problems with it due to its method of use of the figure's userdata field. It appears that the tool ignores the possibility that another application might already be using the userdata and hence when it encounters unexpected data in the field it crashes. I've always tried to treat userdata as shared space - when I read it I assume that there might be data there that I did not put there and I alway try to leave existing data unchanged when I resave to userdata. This would be a useful upgrade for this script.
The functionality you request is already available in the tool.
In interactive mode, if you hit 'control + A', you will get information about the current position of secondary axes and magnifier on the command window of MATLAB.
After that, you only need to set the properties 'PositionSecondaryAxes' and 'PositionMagnifier' to the given values on the next call to this function.
I hope this answers your request :)
First of all, Thank you for your great work :)
After plotting the magnifier, if we are in interactive mode, we can change the size of magnifier and secondary axes.
Is it possible to add a key to script, when we press it it would show "final PositionSecondaryAxes" and "final PositionMagnifier"?
Thank you for the response. Regarding switching from one inset to another, indeed, 'tab' does activate the next inset, regardless of the axes; however, the situation I envision is having say, three insets on one subplot, two insets on another subplot, three insets on yet a third subplot--for whatever reason and despite aesthetics. Maybe now the problem becomes evident. If, say, I am on the third subplot and the 8th inset, in order to access the 7th inset, I have either to (i) cycle through the other 7 insets, or (ii) use my mouse to double-click. I, personally, like shortcuts and avoid using my mouse (habit), thus, I find it more convenient to cluster my insets by axis and, for the active axes, I cycle between my 'local' insets. Further, depending on the order of placing insets on whatever axes, two insets on an axes may not be next to each other in the 'tab' order. Third, a shortcut for activating axes allows for placing insets, not necessarily even activating insets, on different axes, without mouse-clicks. And finally, I usually do most things GUI-based, in which I provide tags for each axes/inset and then provide dialogs (e.g., listboxes, etc) to allow the user to select specific axes and/or insets for manipulation. But, of course, this is my preference.
As for other notes:
(i) I like shortcuts, but, for other users, they love their mouse. Hence, an easy extension is simply to provide a 'uicontextmenu' for each created axes, in which the menu, say, for the 'magnifier' provides the various shortcuts/commands particular to that axes (resize, magnification, etc), and similarly for the inset. A user may then right-click an inset and simply select to resize or expand or whatever. And further, by listing 'Increase X-Mag (alt++)', or whatever the shortcut is, the user has a reference to remind his/herself of the various shortcuts.
(ii) Another extension may be the ability to synchronize two insets. For example, suppose I have two subplots and one inset per subplot. Further, the two subplots contain related information, and I would like to magnify a single region in both subplots. In this implementation, I have to individually drag each magnifier to the desired region separately, and then manually attempt to align the two axes. This may, or may not, be easy depending on the length of the displayed data and the resolution of the axes. A nice extension would be (yet another shortcut!) to link two insets together, such that they move in step. A similar concept has been implemented by 'Dual Cursors', which may be found on the Central File Exchange. Or, another possibility is two insets on the same axes, but separated by a given spacer. If I link them, then when I move one axis to the left by 10 units, the second axis also moves to the left exactly 10 units. Similarly for magnification, resizing, et cetera. Hence, having the ability to apply shortcuts/operations to more than one inset at a time, accomplished either using 'loops' or the 'set' function. Of course, if performance was already an issue, this suggestion would only compound matters.
Thanks again for the fixes and comments. Great work.
Kris, thanks a lot to you too for your comments. In version 1.16, you could already switch from one inset to the next one in a figure( by pressing 'tab' of doble-clicking the inset to focus), regardless they are on the same axes or not.
Maybe this feature could already suit your needs.
I'm currently working on the performance issue, which is not an easy one. I'll let you know the status. Please don't hesitate to report any other issue/bug you might find.
Thank you for addressing the issues reported earlier. The various bug fixes, additional support, and increased functionality are greatly appreciated.
Perhaps a further generality might be the following:
- Multiple insets across multiple subplots within the same figure. I have addressed this by including another shortcut which activates the next (or previous) axes.
Very nice work. A few things:
(i) Hack: in order to delete the magnifier, secondary axes, and link, I simply added a new keyboard shortcut (alt+C), and then directed to a sub-function which deleted the desired axes handles and restored the figure and main axes default settings.
(ii) Problem: I have noticed the following correlation. When the figure window is small, say, 10 in x 8 in, the magnification, motion, and shortcuts work wonderfully. This changes, however, when I expand the figure window so it is maximized (i.e., roughly, 24 in by 11 in). Each time I attempt to used the magnification function on the expanded figure window, my Matlab session crashes, and if this system is able to remain responsive, I receive repetitive warnings that I have exceeded by 'listener recursion limit'. This issue is not alleviated when I reset the recursion limit to something extreme (e.g., from 500 to 10000). Hence, something within the configuration, perhaps the 'buttonmotionfcn' or some other callback which continuously updates/has eventdata, seems to find the increased window size rather disagreeable.
This stated, I was curious if you have a possible workaround for issue (ii).
(iii) Generalization: a nice, albeit more complicated, addition would be the ability to incorporate more than one plot inset for a given axes and/or figure. Possibly, by including another shortcut command, one could cycle between making a given secondary axes/magnifier active and inactive. For example, store all axes within a figure, and then upon the shortcut command, provide a 'listdlg' to allow the user to choose which axes to make active (which may or may not be a magnifier). If a magnifier axes is selected, then make the associated handles active, et cetera.
The function has outstanding functionality and use, and I am eager to have it fully and smoothly incorporated in my GUI. Thank you for this submission.
Tool identification feature added. Now, 'Control+I' shows/hides the tool identifier (red background color when the tool has the focus, black otherwise)
Improved help documentation
Solved bug when resizing the host figure
Added 'delete' functionality.
Solved bug when the contents of the target axes are other than 'line' or 'image'
Solved bug when axis mode is set to other than 'normal'.
Solved bug appearing when any of the axes are reversed. It also works on images now.
Added possibility to select target axes in a multiaxes figure
Solved bug when 'displayLinkStyle' is set to 'edges'