unexpected xlim behavior - where is the documentation/code for how xlim gets updated

Is the way that the xlim property of an axes changes documented? I have some code that waits a bit - via a timer - after a series of axes manipulations are done, before finally updating a plot (see pseudocode below). I found however that if I wait to replot after zooming out, the algorithm decides that my data doesn't encompass the wide range that I zoomed out to, and then shrinks the xlim values accordingly.
In other words, let's say the original data spans from 0 to 100. Then I zoom from 30 to 60. When plotting for xlim = [30 60], I only plot data from 30 to 60. Then I zoom back out to 0 to 100 via a zoom reset (mouse double click). A timer is started in the xlim change callback. If the change is stable, then I'll replot things from 0 to 100. However, if another xlim change occurs, perhaps from quick zooming or panning, then I hold off on rerendering until all the input stops, at which point I use the latest xlim value.
This is the rough pseudocode:
xlim_changed_callback: %Responding to xlim postset listener for axes
delete(old_timer)
start(new_timer)
timer_callback:
updatePlot
However, by waiting to plot, the xlim algorithm appears to check the resulting data span (somehow) and determines that the data doesn't encompass the region of 0 to 100, and changes its value again, so that it fits the data (which has yet to be updated). Thus the latest xlim value that I have to work with is close to being back to 30 to 60, even though at one point the value was changed to the proper value of 0 to 100.
Issue 2: As a workaround I quickly plot a temporary line on every callback that spans the xlim range, so that the algorithm doesn't decide to change the xlim value. When the timer actually executes, I then replot the lines with valid data.
However, this causes a slight adjustment of the xlim values. In the example above, my xlim value of [0 100] will change to [0.000001 100]. What is causing this? Can I prevent this from happening? My current workaround is to check for this "small" change and to ignore setting the new timer if this occurs.
Any incite into this whole process or suggestions would be much appreciated.
Thanks, Jim

Answers (1)

Try setting:
hAxes.XLimMode = 'manual';
for an axes handle object hAxes. This should stop any automated changing of the x limits and leave it entirely up to you to set them.
Obviously you can switch between this and 'auto' for occasions where you do want the limits to be calculated for you (e.g. when you first plot).
I'm not sure if this will solve your second issue or not, but I would hope that eliminating auto xlim changes should stop behaviour like that also.

5 Comments

I would like to keep the automatic behavior. Seeing the value to manual would only work if:
1) I could set it to manual temporarily and then set the property back to automatic, allowing me to keep the automatic limit behavior but somehow avoiding it when I don't want it. I think this might be tricky.
2) I emulate the automatic behavior, ignoring the parts that are causing problems. This might be possible, but it would be nice to not have to do this. If I did have to do this, it would be nice to have a basis from which to start this approach (i.e. documentation of the current approach).
I'm not sure exactly what algorithm it uses. Clearly it is based on your data, but equally it tends to round up to the nearest multiple of e.g. 10 or 100 or whatever it deems suitable for your data range. I haven't seen any documentation of it though.
I generally set XLim myself because I want it tight around my data.
So long as there is a point in your code where you can insert the
hAxes.XLimMode = 'auto';
code though you can switch between modes as often as you like and there shouldn't be any noticeable performance cost.
I've never really worked with timer functionality though so I don't know if this throws insurmountable problems in the way of this approach.
As your workaround, how come you choose to plot a line to force the xlim range rather than just manually reset xlim to what you want after it has been auto resized? That often works too, but can sometimes cause an unpleasant visual effect of you seeing the auto range before it changes back to your specified range.
This code is being developed to interface with the user. I don't think I have anyway of easily knowing if the last xlim callback was from a user's request or from Matlab trying to make things look nice.
I guess you bring up a potentially valid alternative if the following question can be answered.
Can you tell what is causing a change in the x-limits (user or Matlab)? If you could identify this difference then you could still respect the user's wishes while only allowing Matlab to auto size things to within reason ... I think.
As a short term remedy I've taken to adding on the first and last data points, in all plots, so that the limits of the data never change. This seems to solve most of the problems.
This blog post may help:
I was looking for something similar a few months ago, needing to know whether an axes had been zoomed or not in order to retain settings on changing the plot. This worked great for me in R2014a, but the particular implementation I used broke for me in R2014b (always a danger with undocumented functionality) and I couldn't work out how to fix it easily.
The general concept still works, just one part of it in my implementation that didn't (related to an initial zoom reset that happened in my GUI's OpeningFcn - used to work in R2014a, but doesn't in R2014b).
Thanks. I tried using the 'matlab_graphics_resetplotview' property, but it can change for reasons that are unclear to me, thus the request for documentation. I'll probably end up contacting tech support directly as to why the value might change.

Sign in to comment.

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Asked:

on 23 Oct 2014

Commented:

on 24 Oct 2014

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!