Tuesday, February 28, 2012

MATLAB: Making a zoom-in plot on top of a plot

Sometimes, it is helpful to provide a zoom-in of a portion of the original plot. While it can be easily done by making them two separate plots using the subplot function, there are times when you wish you can just make the zoom-in plot appear on top of the original plot. The good news is that it is possible, the bad news, well, it requires a work around, since there isn't a nice matlab function which you can simply call to have the job done for you.

The walk around itself is a very simple idea, you can create another axes on top of the original plot and have the zoom-in data copied over to the new axes. If you are doing it for one time only or the plots are very similar, then it may make sense just to hard code everything in and move on. However, in the case where the plots vary quite a bit, a function is probably needed to make it less of a pain.

FUNCTION DESIGN
Input(s):
  ah:  handle of the existing axes
  source_pos: the position of the portion to be zoomed in
  target_pos:  the position where the zoom-in plot will be placed

* To make the function easy to use, the positions as the input variables are based on the axes in the original plot.

Download the zoomPlot.m file from here here and run the following code to see the function in action.


figure; 
t = 0:0.001:0.1;
plot(t, cos(2*pi*50*t)); 
ah = gca; 
% location of the plot to be zoomed in. 
s_pos =[0.05 0 0.06 0.1];
% location of the zoom-in plot 
t_pos = [0.035 0.4 0.065 0.7];    

% generate a zoom-in plot. 
zoomPlot(ah, s_pos, t_pos);     


The resulting plot will look like



So what has been cover in this post is the basic idea of how to get a zoom-in plot to be on top of the original plot. There are many ways to make this basic function more robust and useful.
  • to allow user specify the positions interactively using mouse 
  • to allow user more flexibility in controlling the appearance of the zoom-in axes. 
  • etc. 




21 comments:

  1. Thank you very very much!! It is extremely useful!

    ReplyDelete
  2. Usefull tool, however I believe there is a mistake on row 52, it should be like this:
    az = axes('position', [target_pos(1), target_pos(2), target_pos(3)-target_pos(1), target_pos(4)-target_pos(2)]);

    ReplyDelete
    Replies
    1. Thanks for pointing it out. m-file and example plot corrected.

      Delete
    2. m-file still seems incorrect:

      az = axes('position', [target_pos(1), target_pos(2), target_pos(2)-target_pos(1), target_pos(4)-target_pos(3)]);

      Delete
    3. Hmm... I must have been day dreaming or something.

      Thanks again. I am sure they are corrected this time.

      Delete
  3. Awesome tool !....Thanks a lot for sharing.

    one small remark:

    axes(ah);

    should be added at the end to reset the active axis to the main plot axis, so that you can do more than one zoom per plot, or modify the main plot after calling zoomPlot.

    ReplyDelete
  4. thanks, that's useful

    ReplyDelete
  5. hi how to add the label to axis in this code? can anybody help

    ReplyDelete
    Replies
    1. You can change the function so that it returns you the handle of the axes that contains the zoom-in plot, which then should allow you to add labels and other components to the axes.

      Delete
  6. Hello,
    Its really useful.Thanks for sharing. Plz tell me how to get of x-axis label that comes in result of zoom-in plot. I already have labels for my x-axis and y-axis. But this zoom-in plot shows me an extra x-axis label right in the middle of my original graph.

    ReplyDelete
    Replies
    1. That's weird. If you run the example code, there is no x-label added to the plot. Maybe you call a xlabel after the function call?

      If that's the case, simply add axes(ah) after the function call, where ah is the handle to your original axes, so that your active axes is back to the original plot (as Mohamed suggested above).

      I will update the function so that it does that automatically.

      Thanks.

      Delete
    2. Nope. that doesn't work. axes(ah) will bring the axes to the front and cover one of the other axes.

      So that has to be done before the uistack call in the zoomPlot function.

      Please download the latest version from https://github.com/weishang/matlab-zoomPlot/blob/master/zoomPlot.m .

      Delete
    3. Even the latest version giving me the same problem. I have original title and x,y labels and when I run zoom-in plot, one more title and xlabel appear in the middle of the graph. Can you help me fix this please. This is what I am plotting.
      figure(i)
      quiver(x,y,Urecon(:,:),Vrecon(:,:), 3.5, 'color','blue')
      axis equal
      xlabel('x [mm]','FontSize',12)
      ylabel('y [mm]','FontSize',12)
      title('Reconstruction','FontSize',12)
      ah=gca;
      source_pos=[40 35 70 45];
      target_pos=[20 52 80 75];
      zoomPlot(ah,source_pos,target_pos);
      axis(ah);

      Delete
    4. Hi Ayesha,

      I was not able to reproduce what you described. Can you insert a break point before and after the zoomPlot and see if anything weird is happening? Maybe there is something going on in your code that the provided function does not take into account. Let me know.



      Delete
    5. I tried break points. The result comes out fine till title but when I introduce five lines of zoom-in plot as shown above it gives me an additional xlabel and title along with the zoom in plot. Urecon and Vrecon are velocity vectors of size 83*63. I don't know where the problem lies? May be I am not using those code lines of yours correctly. Please look if you could still help. Thanks

      Delete
    6. I randomly generated some data and used your code, but I still could not see anything wrong with the plot. Can you give the code below a try and see if it is giving you the same problem.

      Also, why the axis(ah) at the end? Should probably use axes(ah) instead. And was there anything done outside of the loop? I notice that you have the i in figure(i).

      figure(1)
      [x,y] = meshgrid( linspace(0,100, 63) , linspace(0,100,83));
      Urecon = rand(83,63);
      Vrecon = rand(83,63);
      quiver(x,y,Urecon(:,:),Vrecon(:,:), 0.5, 'color','blue')
      axis equal
      xlabel('x [mm]','FontSize',12)
      ylabel('y [mm]','FontSize',12)
      title('Reconstruction','FontSize',12)
      ah=gca;
      source_pos=[40 35 70 45];
      target_pos=[20 52 80 75];
      zoomPlot(ah,source_pos,target_pos);
      axis(ah);

      Delete
  7. Thank you very much!!!!

    ReplyDelete
  8. zoomPlot.m is running and it is giving the plot But I want to see more zoom size of the subplot. what should i do?

    ReplyDelete
    Replies
    1. zoom-size?

      It has been a while, but I believe source_pos and target_pos are the two position array you can play around with. If you want a bigger "subplot" (or the plot where you show the zoom-in), you can change the values in the target_pos. If you want the zoom-in part to be bigger, you can change the values in the source_pos.

      Hope it helps.


      Delete