changes axis of scatter plot with slider matplotlib python - python

I have a very large data set and want the user to be able to slide along the axis to view sections of the data. I'm trying to leverage off of the slider example but I'm unsure of how to update the graph. Hoping someone can explain some of the behinds the scenes with this.
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Slider, Button, RadioButtons
fig = plt.figure()
ax = fig.add_subplot(111)
fig.subplots_adjust(left=0.25, bottom=0.25)
min0 = 0
max0 = 10
x = np.arange(10)
y = np.arange(10)
im1 = plt.scatter(x,y, s=3, c=u'b', edgecolor='None',alpha=.75)
#most examples here return something iterable
plt.ylim([0,10])#initial limits
axcolor = 'lightgoldenrodyellow'
axmin = fig.add_axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
axmax = fig.add_axes([0.25, 0.15, 0.65, 0.03], axisbg=axcolor)
smin = Slider(axmin, 'Min', 0, 10, valinit=min0)
smax = Slider(axmax, 'Max', 0, 10, valinit=max0)
def update(val):
plt.ylim([smin.val,smax.val])
ax.canvas.draw()#unsure on this
smin.on_changed(update)
smax.on_changed(update)
plt.show()

The graph updates itself when you set new limits. You just don't see this because you update wrong subplot. Just select right subplot to update:
def update(val):
plt.subplot(111)
plt.ylim([smin.val,smax.val])
(this work for me)
or maybe even:
def update(val):
plt.ylim([smin.val,smax.val])
plt.subplot(111)
smin.on_changed(update)
smax.on_changed(update)
if you don`t do anything with it elsewhere
UPD: also in matplotlib examples you can find fig.canvas.draw_idle()

Related

Why cant i use sliders in google colab?

Im trying to make a plot with a slider to adjust the variables to visualize changes in lines.
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
x = list(range(0,11))
y = [10] * 11
fig, ax = plt.subplots()
plt.subplots_adjust(left=0.1, bottom=0.35)
p, =plt.plot(x,y, linewidth=2, color='blue')
plt.axis([0,10, 0, 100])
axSlider1 = plt.axes([0.1,0.2, 0.8, 0.05])
slder1 = Slider(axSlider1, 'Slider 1', valmin=0, valmax=100)
axSlider2 =plt.axes([0.1,0.1, 0.8, 0.05])
slder2 = Slider( ax=axSlider2,
label='Slider2',
valmin=0,
valmax=100,
valinit=30,
valfmt='%1.2f',
closedmax=False)
i used this code and itll plot perfectly but i cant slide the slider in colab.

Matplotlib more efficient way to update chart when using slider to scroll through chart?

I want to be able to scroll through a lengthy chart. Is there a more efficient/faster way than having to clear the axis and replot the whole thing every time the scroll bar moves?
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
import random
x=[c for c in range(300)]
y=[random.randint(1,10) for c in range(300)]
showbars=100
fig = plt.figure()
ax = plt.subplot(111)
ax.bar(x[:showbars],y[:showbars])
def slidebar(pos):
pos = int(pos)
ax.clear()
ax.bar(x[pos:pos+showbars],y[pos:pos+showbars])
slidebarpos = plt.axes([0.1, 0.01, 0.5, 0.03], facecolor="skyblue")
slider = Slider(slidebarpos, '', 0, len(x)-showbars, valinit=0)
slider.on_changed(slidebar)
slidebar(0)
plt.show()
This is slow on my computer
First of all you could plot the bars only once, and use the slider just to change the range that is shown, i.e. the limits of the x-axis.
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
import numpy as np
x=np.arange(300)
y=np.random.randint(1,10, size=300)
showbars=100
fig, ax = plt.subplots()
ax.bar(x,y)
def slidebar(pos):
ax.set_xlim(pos-1, pos+showbars+1)
slidebarpos = plt.axes([0.1, 0.01, 0.5, 0.03], facecolor="skyblue")
slider = Slider(slidebarpos, '', 0, len(x)-showbars, valinit=0)
slider.on_changed(slidebar)
slidebar(0)
plt.show()
One could also keep the same bar's in place, but change their height and fake the ticks and labels in such a way that the bars look like being updated.
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
from matplotlib.ticker import AutoLocator
import numpy as np
x=np.arange(300)
y=np.random.randint(1,10, size=300)
showbars=100
fig, ax = plt.subplots()
bars = ax.bar(x[:showbars],y[:showbars])
loc = AutoLocator()
def slidebar(pos):
pos = int(pos)
for bar, yi in zip(bars, y[pos:showbars+pos]):
bar.set_height(yi)
ticks = loc.tick_values(pos, showbars+pos)
ax.set_xticks(ticks-pos)
ax.set_xticklabels(ticks)
slidebarpos = plt.axes([0.1, 0.01, 0.5, 0.03], facecolor="skyblue")
slider = Slider(slidebarpos, '', 0, len(x)-showbars, valinit=0)
slider.on_changed(slidebar)
slidebar(0)
plt.show()

Jupyter Notebook matplotlib notebook makes plot not show up, inline makes it not interactive

I have one python file Vis.py with the following two functions:
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
def update(val): #needed for slider function of plot_test
pos = spos.val
ax.axis([pos,pos+10,-1,1])
fig.canvas.draw_idle()
def plot_test(data):
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
plt.plot(data)
plt.axis([0, 10, -1, 1])
axcolor = 'lightgoldenrodyellow'
axpos = plt.axes([0.2, 0.1, 0.65, 0.03], facecolor=axcolor)
spos = Slider(axpos, 'Pos', 0.1, 90.0)
spos.on_changed(update)
plt.show();
and I am trying to use the plot_test function in a separate ipynb file:
%matplotlib notebook
from Vis import *
import numpy as np
t = np.arange(0.0, 200.0, 0.1)
s = np.sin(2*np.pi*t)
plot_test(s)
However, the plot doesn't show up, not even an empty white space. I tried running %matplotlib inline before plot_test(s). That makes the plot show up, but it also gets rid of the interactiveness of the plot.
The updating function references ax, which is out of scope. A solution is to put the updating function inside the plot_test function.
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
def plot_test(data):
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
plt.plot(data)
plt.axis([0, 10, -1, 1])
axcolor = 'lightgoldenrodyellow'
axpos = plt.axes([0.2, 0.1, 0.65, 0.03], facecolor=axcolor)
spos = Slider(axpos, 'Pos', 0.1, 90.0)
def update(val): #needed for slider function of plot_test
pos = spos.val
ax.axis([pos,pos+10,-1,1])
fig.canvas.draw_idle()
spos.on_changed(update)
plt.show()
Then, keeping the notebook part unchanged,
%matplotlib notebook
from Vis import *
import numpy as np
t = np.arange(0.0, 200.0, 0.1)
s = np.sin(2*np.pi*t)
plot_test(s)
results in the desired interactive figure for me.

Matplotlib plot with scalable/updatable x-axis

Is it possible to create a plot where a slider can update the length/location of the x-axis?
Here is an example of the type of slider required.
A somewhat similar matplotlib slider can be found here. Unfortunately, as you can see there is no documentation/explanation of how it works - this makes it rather difficult to understand/adapt!
The type of plot I would like to add this to is quite simple, here is a small, random example:
import matplotlib.pyplot as plt
import random
li = []
for x in xrange(100):
li.append(random.randint(0,20))
plt.plot(li)
plt.show()
Here's something to get you started. It's adapted directly from your second example in the matplotlib docs - using the slider to update the plot bounds, rather than to scale the data.
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
import numpy as np
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
t = np.arange(0.0, 1.0, 0.001)
s = np.sin(5*np.pi*t)
l, = plt.plot(t,s)
viewwindow = 0.1
axpos = plt.axes([0.25, 0.1, 0.65, 0.03])
axslider = Slider(axpos, '', t[0]+viewwindow, t[-1]-viewwindow, valinit=(t[-1]+t[0])/2.0)
def update(val):
new_pos = axslider.val
ax.set_xbound(new_pos-viewwindow, new_pos+viewwindow)
fig.canvas.draw_idle()
update(axslider.val)
axslider.on_changed(update)
plt.show()

Adding image to a plot -matplotlib PYTHON

I am trying to insert a .png image to the right side of the plot and following the code mentioned here:
Combine picture and plot with Python Matplotlib
Here is what I have tried:
import numpy as np
from matplotlib.colors import LinearSegmentedColormap
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.cbook as cbook
from matplotlib._png import read_png
from matplotlib.offsetbox import OffsetImage
cmap = mpl.cm.hot
norm = mpl.colors.Normalize(vmin=-1 * outlier, vmax=outlier)
cmap.set_over('green')
cmap.set_under('green')
cmap.set_bad('green')
plt.xlim(0,35)
plt.ylim(0,35)
fig, ax = plt.subplots()
ax.set_aspect('equal')
cb_ax=fig.add_axes([0.85, 0.1, 0.03, 0.8])
img = ax.imshow(np.ma.masked_values(data, outlier), cmap=cmap, norm=norm, interpolation='none',vmax=outlier)
cb = mpl.colorbar.ColorbarBase(cb_ax, cmap=cmap, norm=norm, extend='both')
##axim = plt.subplot2grid(shape, loc, rowspan=1)
## phlo tree
image_file = cbook.get_sample_data('mytree.png',asfileobj=False)
image = plt.imread(image_file)
phyl_ax=fig.add_axes([0.10,0.1, 0.03, 0.8])
phyl_ax.imshow(image,interpolation='nearest')
Th heat map would be on the left side and the image of a tree will be inserted on the right side. With the above code here is what I get...
There is something being added to the right side but obviously it isn't the way it should look like.
At first I thought I was setting the dimensions of phyl_ax too small but when I try to increase it, even the previous "something" is also not being added.
Could someone point at where I am going wrong with it?
You are calling both subplots, which, by default, gives you a single axes, and also adding axes via add_axes. You should do one or the other, e.g.
...
fig = plt.figure()
ht_ax = fig.add_axes([0.1, 0.1, 0.3, 0.8])
cb_ax = fig.add_axes([0.45, 0.3, 0.02, 0.4])
phyl_ax = fig.add_axes([0.6, 0.1, 0.3, 0.8])
...
--or--
...
fig, ax = plt.subplots(1,2)
fig.subplots_adjust(left=0.15)
ht_ax = ax[0]
phyl_ax = ax[1]
cb_ax=fig.add_axes([0.05, 0.3, 0.02, 0.4])
...
You can use subplots_adjust and set_aspect to adjust the layout. You can also use colorbar.make_axes to get an appropriately sized colorbar axes. Here I also used grid_spec to get the plots to be a size ratio I liked
gs = gridspec.GridSpec(1, 2, width_ratios=[3, 2])
ht_ax = plt.subplot(gs[0])
phyl_ax = plt.subplot(gs[1])
cb_ax, kw = mpl.colorbar.make_axes(ht_ax, shrink=0.55)
...
cb = mpl.colorbar.ColorbarBase(ax=cb_ax, cmap=cmap, norm=norm, extend='both', **kw)

Categories

Resources