Matplotlib/Python: customize a Zoom-in at show call - python

I have a candlestick chart that is dinamically created for different lengths and stocks. The chart is created first (the creation of the chart is contained in a function "createChart") and not shown until the moment the user presses on the button "Show Chart", that will hence call the instruction .show() and display the plot previously created. When the user clicks on the button he gets the following result:
However, what I would like to get is a chart that is already zoomed-in, let's say, on the last 5% of data. So what I would like to get is when the user presses on the button "Show Chart" the plot (that has been already fully created into the "createChart" function) should zoom on the last couple of months, so Nov 2012 - Dec 2012, but so allowing the user to scroll back/forward:
Hence my question is: to make the chart more user-friendly and zoom-in directly on the last observations (that in finance are the most relevant), but still giving the user the possibility of slide the chart and going back or forward as he wishes, how could I customize the .show() method to get this result?

I propose you to use the navigation toolbar tools; here is an example:
from pylab import *
x=[1,2,2,3,5]
y=[2,3,4,5,6]
fig=figure() # create and store a figure
tb=fig.canvas.toolbar # get the toolbar of the figure
ax=fig.add_subplot(1,1,1) # add axes to the figure
ax.plot(x,y) # plot
tb.push_current() # save the current zoom in the view stack
ax.set_xlim([1,3]) # change xlims
ax.set_ylim([2,5]) # change ylims
tb.push_current() # save the new position in the view stack
show() # show the figure

What about xlim((from, to)) and ylim((from, to))?
It limits only the view, not what data is actually plotted. You might have to pay attention to the case where you have a whole lot of data, then the plot() or show() command takes ages to load.

Related

plot multiple figures in the same window but different "tabs" with matplotlib

I know that you can plot multiple figures in the same window by arranging them in a grid layout. However, I want to plot multiple figures, showing only one at a time and be able to move to the next or previous figure with buttons in the UI. I see arrows in the default UI which makes me think there's a way to do this.

Force update to matplotlib toolbar/status bar information

I've got a matplotlib plot in which I've modified the toolbar/status bar information much as in this question. This works just fine and the necessary information is displayed as I need it.
However, I often need to update the plot (which is done by calling draw() on the canvas object) with new data. What happens though is that the toolbar/status bar information won't update until the mouse is moved again. I'd like this information to update as soon as the canvas is redrawn because some of this information is pertinent to the new plot.
My attempt at making this happen was to force a mouse motion event to trigger. I've tried to trigger the event from the canvas via self.canvas.motion_notify_event(0,0) but that doesn't seem to work well. I can see that the toolbar itself has a mouse_move method, but I don't know how to trigger it (or even if it's what I want to trigger).
How can I force the toolbar/status bar information to update during a plot redraw without requiring the user to move their mouse slightly?
Did a lot of digging and figured it out. The motion_notify_event method was what I was looking for, I was just using it wrong. You can fake matplotlib out and trigger a MouseEvent by using this function, which will then make matplotlib call all functions that respond to MouseEvents, including updating the toolbar/status bar information.
The key here is that I needed to trigger the MouseEvent as if it happened within the axes object, not the entire figure. The input to the function is the (x,y) pixel position of the event with respect to the lower left corner of the figure window. By using (0,0) as I did in my question, I was saying the mouse event happened at the lower left corner of the figure window, not on the axes itself. Matplotlib does not show toolbar/status bar information unless the cursor is on the axes.
What you can do then is pick some random pixel position on the axes and use that as the position. A simple way to pick such a pixel position is using matplotlib transformations.
The following now works for me:
canvas.motion_notify_event(*ax.transAxes.transform([0,0]))
Of course in my case I'm not displaying the data coordinates of the mouse, so your use cases may vary.

How to recover the navigation toolbar for a figure after it has been removed?

Figure 1. is displayed with some points in it.
When the user moves the mouse cursor near one
of the points in Figure 1. and clicks the mouse
button, an image (*.png file) specific to the
value of the selected point is displayed in a
new figure. Thus, each time a point is selected
a new figure is created with a *.png file in
it (e.g. Figure 2,3,...).
I do not wish to have a navigation toolbar
displayed in Figure 1. I was able to accomplish
this with the following statement:
mpl.rcParams['toolbar'] = 'None'
Question -- How can I have a navigation toolbar
for Figure 2,3,... after it has been removed in
Figure 1.?
When displaying the figures containing the images I used:
mpl.rcParams['toolbar'] = 'toolbar2' # to restore toolbar
f, ax = plt.subplots(figsize=(5,4)) # for images
It was important to have this order in the statements; i.e., the mpl
before the figure was defined.

matplotlib gui respond to axes changes

I have created a little GUI with QT which set's up a single matplotlib figure and axes.
The GUI has controls to change just about everything to do with the appearance of the axes.
Basically, it does this by each widget emitting signals back up to the main frame and it calls the appropriate matplotlib setters on the axes and figure objects.
However, it is possible for the axes (and therefore the image displayed on the FigureCanvas) to change without input from the GUI (e.g. when autoscaling, or adding certain plots which adjust the axes automatically).
In this case, a widget controlling e.g. the limits of the x axis will now be displaying the wrong values.
I would like all the relevant widgets to update when the axes updates....how could I possible achieve this?
I'm thinking that this is a problem that has been solved before - how to enable a two-way communication between distinct objects?
fig.canvas.draw()
time.sleep(1e-2)
whenever anything writes to the plot? however it's hard to help with no code.
Showing an example of how your code is not working would help a lot.
EDIT:
I'll try this again then:
What about getting the state of the plot you are updating? I guess its what #Ajean means by updater method. I know that Artists in matplotlib have an Artist.properties() method that returns all of the properties and values.
I imagine Axes would have a similar method.
A quick look at the matplotlib docs yielded 2 interesting methods of axes:
ax.get_autoscale_on()
and
ax.set_autoscale_on().
ax.set_autoscale_on(False) will prevent plots from updating the state of the axes.

Pop-up plot label on mouse-over event in matplotlib

I am working on a python 2.7+matplotlib+tkinter project where I need to plot up to 60 plots on 1 figure (I can show/hide them then by pressing corresponding legend title and do some other interactive stuff). What I want is to get an annotation box on mouse-over event with the label of current plot. I was thinking about text annotation, but I haven't found any ways to do it interactively.
If it is crucial for an answer - I am working with step and scatter figures. I am ready to provide any information needed, for now I just can't think of something necessary to post here (in terms of source code)

Categories

Resources