pyqtgraph : using AxisItem to plot time axis displaying extra axis - pyqt

When I implemented a time axis class overriding AxisItem class it is displaying an extra axis on the top of the window. How can I make that axis disappear? You can see image of this issue on google group.
Or here is the simple code
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
from PySide.QtCore import QTime
class TimeAxisItem(pg.AxisItem):
def tickStrings(self, values, scale, spacing):
return [QTime().addMSecs(value).toString('mm:ss') for value in values]
app = QtGui.QApplication([])
win = pg.GraphicsWindow()
axis = TimeAxisItem('bottom')
plot = win.addPlot(title = "sdf",axisItems={'bottom':axis})
curve = plot.plot()
QtGui.QApplication.instance().exec_()
I'd be very glad for your help.
Regards,

It's a bug!
This has been fixed in the latest develop branch on github; will appear in the next release.

Related

X and Y label being cut in matplotlib plots

I have this code:
import pandas as pd
from pandas import datetime
from pandas import DataFrame as df
import matplotlib
from pandas_datareader import data as web
import matplotlib.pyplot as plt
import datetime
start = datetime.date(2016,1,1)
end = datetime.date.today()
stock = 'fb'
fig = plt.figure(dpi=1400)
data = web.DataReader(stock, 'yahoo', start, end)
fig, ax = plt.subplots(dpi=720)
data['vol_pct'] = data['Volume'].pct_change()
data.plot(y='vol_pct', ax = plt.gca(), title = 'this is the title \n second line')
ax.set(xlabel="Date")
ax.legend(loc='upper center', bbox_to_anchor=(0.32, -0.22), shadow=True, ncol=2)
plt.savefig('Test')
This is an example of another code but the problem is the same:
At bottom of the plot you can see that the legend is being cut out. In another plot of a different code which i am working on, even the ylabel is also cut when i save the plot using plt.savefig('Test').How can i can fix this?
It's a long-standing issue with .savefig() that it doesn't check legend and axis locations before setting bounds. As a rule, I solve this with the bbox_inches argument:
plt.savefig('Test', bbox_inches='tight')
This is similar to calling plt.tight_layout(), but takes all of the relevant artists into account, whereas tight_layout will often pull some objects into frame while cutting off new ones.
I have to tell pyplot to keep it tight more than half the time, so I'm not sure why this isn't the default behavior.
plt.subplots_adjust(bottom=0.4 ......)
I think this modification will satisfy you.
Or maybe you can relocate the legend to loc="upper left"
https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplots_adjust.html
please also checked this issue which raised 8 years ago..
Moving matplotlib legend outside of the axis makes it cutoff by the figure box

I have some trouble in using the curve_fit function

I want to fit a scatter plot with the curve_fit function. But although I wrote the codes as the tutorial said, it just didn't work.Could someone please help me check the code?
import numpy as np
from matplotlib import rcParams
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
rcParams['axes.unicode_minus']=False
myfont = FontProperties(fname='/Library/Fonts/Songti.ttc',size=15)
ydata=[78,78,77.9,74,8,70.1,65.8,58.2,40,5.0,14.0,30,60,69,74,74.2,78,78]
xdata = [257.6695,257.6695,257.6695,307.7231,316.009,309.4141,310.936,312.627,314.4871,316.3472, 317.0236,317.7,319.391,321.082,322.9421, 324.464, 341.7122,426.7695]
plt.plot(xdata,ydata,'*')
plt.xlabel('磁感应强度B(mT)',fontproperties=myfont)
plt.ylabel('检波电流(μA)', fontproperties=myfont)
def func(x,amp,cen,wid):
return amp*np.exp(-(x-cen)**2/wid)
popt,pcov = curve_fit(func,xdata,ydata)
print(popt)
amp = popt[0]
cen = popt[1]
wid = popt[2]
residuals = ydata-func(xdata,amp,cen,wid)
fres = sum(residuals**2)
print(fres)
xaxis = np.linspace(250,450,100)
curve_y = func(xaxis,amp,cen,wid)
plt.plot(xaxis,curve_y)
With maplotlib.pyplot, you need to explicitly state that you want to “show” the plot in order to have it displayed.
plt.plot(x, y) will create the barebones of the graph, but there are still many changes one could make: adding additional figures or subplots, adding additional data sets to the plot for comparison or changing colours!
Until you explicitly say “show me the plot at this point in the code”, then nothing will happen. Try adding the following to the end of your code:
plt.show()

Arranging widgets in ipywidgets interactive

I have this interactive graph code using ipywidgets; but not sure how to arragne the each variable inside the interactive function in widgets. the default layout is vertical. But I want to arrange them in horizontal way.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
plt.style.use('seaborn')
%config InlineBackend.figure_format = 'svg'
from ipywidgets import interactive,interact
#function to plot the different curves
def plot_function(u=1,v=2,w=3,x=4,y=5,z=6):
time=np.arange(0,1,0.01)
df=pd.DataFrame({"Y1":np.sin(time*u*2*np.pi),"y2":np.sin(time*v*2*np.pi),"y3":np.sin(time*w*2*np.pi),
"y4":np.sin(time*x*2*np.pi),"y5":np.sin(time*y*2*np.pi),"y6":np.sin(time*z*2*np.pi)})
df.plot()
widget=interactive(plot_function,u=1,v=2,w=3,x=4,y=5,z=6)
widget
interactive is restricted to fairly simple widget layouts. Have a look at the Flexbox options if you want to customize them some more.
One simple get around is to use the interactive call to generate and link your widgets and functions, then restructure the widgets inside a HBox. Then add a layout that tells the box to wrap at line ends. I added a couple more imports and three lines at the end to achieve this.
1) controls - an HBox of your input widgets.
2) The Output widget generated by the interactive call.
3) A VBox that wraps the two together.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
plt.style.use('seaborn')
%config InlineBackend.figure_format = 'svg'
#importing the necessary items from the Ipywidgets library
from ipywidgets import interactive,interact, HBox, Layout,VBox
#function to plot the different curves
def plot_function(u=1,v=2,w=3,x=4,y=5,z=6):
time=np.arange(0,1,0.01)
df=pd.DataFrame({"Y1":np.sin(time*u*2*np.pi),"y2":np.sin(time*v*2*np.pi),"y3":np.sin(time*w*2*np.pi),
"y4":np.sin(time*x*2*np.pi),"y5":np.sin(time*y*2*np.pi),"y6":np.sin(time*z*2*np.pi)})
df.plot()
widget=interactive(plot_function,u=1,v=2,w=3,x=4,y=5,z=6)
controls = HBox(widget.children[:-1], layout = Layout(flex_flow='row wrap'))
output = widget.children[-1]
display(VBox([controls, output]))
Hi this is the decorator which I am using instead of #interact:
def interact_delayed(_InteractFactory__interact_f=None, **kwargs):
def patch(obj):
if hasattr(obj.widget, 'layout'):
obj.widget.layout = Layout(flex_flow='row wrap')
for child in obj.widget.children:
if hasattr(child, 'continuous_update'):
child.continuous_update = False
return obj
if _InteractFactory__interact_f is None:
def decorator(f):
obj = interact(f, **kwargs)
return patch(obj)
return decorator
else:
obj = interact(_InteractFactory__interact_f, **kwargs)
return patch(obj)
The patch function modifies default attributes of ipywidget object: applies the Layout suggested in the previous answer and also sets continuous_update to false which I found useful in my cases.
The if-else branches takes care about decorator versus function use-case scenarios.
There is no way to arrange widgets by adding a parameter in "interact" or interactive.

Remove Bokeh Logo in HoloViews

Is it possible to remove the Bokeh logo from plots generated with HoloViews? Nothing against it... it's just that it may not make sense to display it in certain reports. :)
I know that in Bokeh I can simply do:
p = bkp.figure(...)
...
p.toolbar.logo = None
UPDATE
Here's my import section:
import sys
import os
import numpy as np
np.random.seed(0)
import random
random.seed(0)
import pandas as pd
from bokeh.models import HoverTool
import holoviews as hv
hv.extension("bokeh", logo=False)
Currently (as of holoviews 1.9.1) the option to disable the bokeh logo in the toolbar is not directly exposed, but you can supply a so called finalize_hook which lets you modify the plot directly. You can add such a hook directly on the ElementPlot to set it globally:
def disable_logo(plot, element):
plot.state.toolbar.logo = None
hv.plotting.bokeh.ElementPlot.finalize_hooks.append(disable_logo)
or set it as a plot option:
hv.Curve(range(10)).opts(plot=dict(finalize_hooks=[disable_logo])
To remove the Bokeh logo for more complicated layouts, I think you need to render it to a Bokeh figure, and then use Bokeh's native method to remove it.
layout = C + D
plot = renderer.get_plot(layout)
p = plot.state
p.children[0].toolbar.logo = None
show(p)
hv.extension("bokeh",logo=False)
1) This is almost the same as philippjfr answer, but slightly shorter using hooks:
def remove_bokeh_logo(plot, element):
plot.state.toolbar.logo = None
hv.Scatter(df).opts(hooks=[remove_bokeh_logo])
2) And there's Andrew's answer, rendering the plot as bokeh and then removing the logo:
from bokeh.plotting import show
hv_plot = hv.Scatter(df)
bokeh_plot = hv.render(hv_plot, backend='bokeh')
bokeh_plot.toolbar.logo = None
show(bokeh_plot)

Improve speed of resizing plot (matplotlib) inside GTK-window

I have some heavy plot and it's ok that it calculating couple seconds, but when i resize window/chart - its hang up for some time and that is not obviously behavior for me. How i can fix this? There is no changes in plot data, just resizing.
Demo:
import numpy as np
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import matplotlib
matplotlib.use('GTKCairo')
from matplotlib.figure import Figure
from matplotlib.backends.backend_gtk3cairo import FigureCanvasGTK3Cairo as FigureCanvas
class MyApp:
def __init__(self):
self.Window = Gtk.Window()
graphFig = Figure()
graphCanvas = FigureCanvas(graphFig)
self.Window.add(graphCanvas)
# just example of heavy chart
subplot = graphFig.add_subplot(111)
for n in range(100):
x = np.arange(0, 100, 0.01)
y = np.sin(x) * n
subplot.plot(x, y)
return
def Run(self):
self.Window.show_all()
Gtk.main()
return
App = MyApp()
App.Run()
What options exist of fixing this issue? I wanna redraw chart only when its updated or when user pan/zoom it.
To speed up plotting, consider plotting lower resolution lines. 100 lines at 1000 samples each is a lot of drawing.
Barring that, this post has a very detailed answer that could help you improve speed.

Resources