I'm trying to make a save button that when clicked will save the plot. When I use the command plt.savefig("SiLorentzFit2.png"), it saves just fine and I can see the plot as a .png. When I try to use a function to execute the same command, the plot saves a blank .png and gives back <Figure size 432x288 with 0 Axes> after pressing the button. How do I get the plot to save normally using the button code?
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
def lorentz(x, y0, amp, cen, wid):
return y0 + (2*amp/np.pi)*(wid/(4*(x-cen)**2 + wid**2))
xtest = np.linspace(400,650,250)
y0 = 1000
amp = 10000
cen = 511
wid = 2
ytest = lorentz(xtest,y0,amp,cen, wid)
plt.plot(xtest,ytest)
plt.title("Fitting function")
plt.ylabel("Intenisty")
plt.xlabel("Raman shift (cm$^{-1}$)")
def save_plot(b):
plt.savefig("SiLorentzFit2.png")
print("File Saved!")
saveplot = Button(description="Save Plot")
saveplot.on_click(save_plot)
display(saveplot)
You can do this:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
def lorentz(x, y0, amp, cen, wid):
return y0 + (2*amp/np.pi)*(wid/(4*(x-cen)**2 + wid**2))
xtest = np.linspace(400,650,250)
y0 = 1000
amp = 10000
cen = 511
wid = 2
ytest = lorentz(xtest,y0,amp,cen, wid)
def save_plot(b):
plt.plot(xtest,ytest)
plt.title("Fitting function")
plt.ylabel("Intenisty")
plt.xlabel("Raman shift (cm$^{-1}$)")
plt.savefig(b)
print("File Saved!")
save_plot("SiLorentzFit2.png")
Related
I'm writing a GUI and part of that requires a live graph be displayed. At the moment i'm just getting a straight line being plot.
from mcculw import ul
from mcculw.enums import ULRange
from datetime import datetime as dt
from mcculw.ul import ULError
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import tkinter as Tk
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
board_num = 0
channel = 0
ai_range = ULRange.BIP5VOLTS
try:
# Get a value from the device
value = ul.a_in(board_num, channel, ai_range)
# Convert the raw value to engineering units
eng_units_value = ul.to_eng_units(board_num, ai_range, value)
# Display the raw value
print("Raw Value: " + str(value))
# Display the engineering value
print("Engineering Value: " + '{:.3f}'.format(eng_units_value))
except ULError as e:
# Display the error
print("A UL error occurred. Code: " + str(e.errorcode)
+ " Message: " + e.message)
x=[]
y=[]
fig, ax = plt.subplots()
def animate(i, x, y):
x.append(i)
y.append(eng_units_value)
ax.clear()
ax.plot(x, y)
x = x[-10:]
y = y[-10:]
ani = animation.FuncAnimation(fig, animate, fargs=(x, y), interval=100)
plt.show()
This is a snippet of the problem with the code I have.
Graph I get
No error codes - just a problem with getting a new value every time it plots i think.
Why is my code slowing down as time goes on? When the code initially starts the loop takes ~.1 second to run. By the 90th pass I am at 1+ second. I am displaying and saving the image. I noticed if I comment out fig.canvas.draw() and fig.canvas.flush_events() the code runs as expected. The issue is with displaying and updating the interactive window. Is there a variable I need to clear?
from flirpy.camera.lepton import Lepton
import matplotlib.pyplot as plt
import numpy as np
import cv2
from PIL import Image as im
import os, sys
import time
%matplotlib notebook
savefold = ('Therm')
if not os.path.exists(savefold):
os.makedirs(savefold)
camera = Lepton()
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)
def getFrame():
image = camera.grab()
fimage = np.around((image/100 - 273.15) * 9 / 5 + 32, 2)
cimage = np.around(image/100 - 273.15, 2)
kimage = np.around(image/100, 2)
cimage = np.where(cimage < 20, 20, cimage)
cimage = np.where(cimage > 30, 30, cimage)
getFrame.z = cimage
return getFrame.z
getFrame.z = None
i = 0
while True:
tic = time.perf_counter()
npimage=getFrame()
npimage=npimage
data = im.fromarray(npimage)
plt.imshow(data)
fig.canvas.draw()
fig.canvas.flush_events()
plt.imsave(os.path.join(savefold, f'test_{i:05}.png'), data)
i += 1
toc = time.perf_counter()
print(f'Time to execute: {toc - tic:0.4f} seconds')
camera.close()
Because you are adding one image for each iteration: all the previous images are still in matplotlib buffer, and they get rendered!
You need to clear the buffer. Try to use this line of code before the imshow command:
plt.gca().images.clear()
I am getting the below error when I try to plot a short time energy function, please I need your help solve this problem.
Code:
import os
from tqdm import tqdm
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.io import wavfile
from python_speech_features import mfcc
from python_speech_features import logfbank
import librosa
def plot_ste(ste):
fig, axes = plt.subplots(nrows=1, ncols=1, sharex=False,
sharey=False, figsize=(400, 50))
fig.suptitle('Short Time Energy', size=100, y=1.02)
i = 0
for x in range(1):
for y in range(1):
data = list(ste.values())[i]
x, win = data[0], data[1]
axes[x,y].set_title(list(ste.keys())[i])
axes[x,y].plot(win, x)
axes[x,y].get_xaxis().set_visible(False)
axes[x,y].get_yaxis().set_visible(False)
i+=1
def ste(x, win):
"""Compute short-time energy."""
if isinstance(win, str):
win = scipy.signal.get_window(win, max(1, len(x) // 8))
win = win / len(win)
return scipy.signal.convolve(x**2, win**2, mode="same")
df = pd.read_csv('/dir/to/a.csv')
df.set_index('fname', inplace=True)
classes = list(np.unique(df.ID))
df.reset_index(inplace=True)
ste = {}
for c in classes:
wav_file = df[df.ID==c].iloc[0, 0]
signal, rate = librosa.load('/dir/to/wav_file')
ste[c] = ste
plot_ste(ste)
plt.show()
Error:
File "/home/Desktop/Program/stft_plot_full_Dir.py", line 35, in plot_ste
x, win = data[0], data[1]
KeyError: 0
I am new to python and have created this tiny class "myclass" which is inside a module called linear_regression_example.py. It prints out a regression summary and a density plot:
import statsmodels.api as sm
import sklearn.datasets as skld
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
class myclass:
def __init__(self, result=1):
self.result = result
def myregression(self):
y_X = skld.load_boston()
y = y_X['target']
X = y_X['data']
n = y_X['feature_names']
y = pd.DataFrame(y)
X = pd.DataFrame(X, columns=n)
X = sm.add_constant(X)
mod = sm.OLS(y, X)
result = mod.fit()
if self.result == 1:
print(result.summary())
pred = mod.predict(result.params)
pred = pd.DataFrame(pred)
errors = y - pred
sns.distplot(errors)
plt.show()
I also have another file, called test.py:
import linear_regression_example as lre
test = lre.myclass()
test.myregression()
Running test.py in pycharm results in the output "Process finished with exit code 0" but no summary or plot is shown. Maybe someone here knows where the problem lies.
Best regards
Dominik
linear_regression_example.py
import statsmodels.api as sm
import sklearn.datasets as skld
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
class myclass:
def __init__(self, result=1):
self.result = result
def myregression(self):
y_X = skld.load_boston()
y = y_X['target']
X = y_X['data']
n = y_X['feature_names']
y = pd.DataFrame(y)
X = pd.DataFrame(X, columns=n)
X = sm.add_constant(X)
mod = sm.OLS(y, X)
result = mod.fit()
if self.result == 1:
print(result.summary())
pred = mod.predict(result.params)
pred = pd.DataFrame(pred)
errors = y - pred
sns.distplot(errors)
plt.show()
if __name__ == '__main__':
test = myclass()
test.myregression()
test.py
import linear_regression_example as lre
test = lre.myclass()
test.myregression()
OUTPUT (from test.py)
The code below generates a animated basemap, but not exactly the one I want: I want the scatterplot from the previous frame to disappear, but it persists through the remainder of the animation.
I suspect it has something to do with my not understanding what the basemap really is. I understand calling it on lat/lons to project them to x/y, but I don't entirely get what's going on when I call event_map.scatter().
import random
import os
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from matplotlib import animation
import pandas as pd
from IPython.display import HTML
# Enables animation display directly in IPython
#(http://jakevdp.github.io/blog/2013/05/12/embedding-matplotlib-animations/)
from tempfile import NamedTemporaryFile
VIDEO_TAG = """<video controls>
<source src="data:video/x-m4v;base64,{0}" type="video/mp4">
Your browser does not support the video tag.
</video>"""
def anim_to_html(anim):
if not hasattr(anim, '_encoded_video'):
with NamedTemporaryFile(suffix='.mp4') as f:
anim.save(f.name, fps=20, extra_args=['-vcodec', 'libx264'])
video = open(f.name, "rb").read()
anim._encoded_video = video.encode("base64")
return VIDEO_TAG.format(anim._encoded_video)
def display_animation(anim):
plt.close(anim._fig)
return HTML(anim_to_html(anim))
animation.Animation._repr_html_ = anim_to_html
FRAMES = 20
POINTS_PER_FRAME = 30
LAT_MIN = 40.5
LAT_MAX = 40.95
LON_MIN = -74.15
LON_MAX = -73.85
FIGSIZE = (10,10)
MAP_BACKGROUND = '.95'
MARKERSIZE = 20
#Make Sample Data
data_frames = {}
for i in range(FRAMES):
lats = [random.uniform(LAT_MIN, LAT_MAX) for x in range(POINTS_PER_FRAME)]
lons = [random.uniform(LON_MIN, LON_MAX) for x in range(POINTS_PER_FRAME)]
data_frames[i] = pd.DataFrame({'lat':lats, 'lon':lons})
class AnimatedMap(object):
""" An animated scatter plot over a basemap"""
def __init__(self, data_frames):
self.dfs = data_frames
self.fig = plt.figure(figsize=FIGSIZE)
self.event_map = Basemap(projection='merc',
resolution='i', area_thresh=1.0, # Medium resolution
lat_0 = (LAT_MIN + LAT_MAX)/2, lon_0=(LON_MIN + LON_MAX)/2, # Map center
llcrnrlon=LON_MIN, llcrnrlat=LAT_MIN, # Lower left corner
urcrnrlon=LON_MAX, urcrnrlat=LAT_MAX) # Upper right corner
self.ani = animation.FuncAnimation(self.fig, self.update, frames=FRAMES, interval=1000,
init_func=self.setup_plot, blit=True,
repeat=False)
def setup_plot(self):
self.event_map.drawcoastlines()
self.event_map.drawcounties()
self.event_map.fillcontinents(color=MAP_BACKGROUND) # Light gray
self.event_map.drawmapboundary()
self.scat = self.event_map.scatter(x = [], y=[], s=MARKERSIZE,marker='o', zorder=10)
return self.scat
def project_lat_lons(self, i):
df = data_frames[i]
x, y = self.event_map(df.lon.values, df.lat.values)
x_y = pd.DataFrame({'x': x, 'y': y}, index=df.index)
df = df.join(x_y)
return df
def update(self, i):
"""Update the scatter plot."""
df = self.project_lat_lons(i)
self.scat = self.event_map.scatter(x = df.x.values, y=df.y.values, marker='o', zorder=10)
return self.scat,
s = AnimatedMap(data_frames)
s.ani
It looks like you're simply adding a new scatter plot at each update. What you should do instead is change the data in the existing path collection at each update. Try something along the lines of
def update(self, i):
"""Update the scatter plot."""
df = self.project_lat_lons(i)
new_offsets = np.vstack([df.x.values, df.y.values]).T
self.scat.set_offsets(new_offsets)
return self.scat,
Note that I haven't tested this.