Multiple Sns plot distort in flask using savefig and sendfile - python

I have a html file that displays the images sent from the flask backend.
<body>
<h3> Count plot of data according to Lead origin.</h3>
<img src = "/graph_visualization/" alt = "graph it is" height = "300" width = "300">
<h3> Count plot of data according to cities</h3>
<img src = "/graph_visualization2/" alt = "graph it is" height = "300" width = "300">
<h3> Count plot of data according to Countries</h3>
<img src = "/graph_visualization3/" alt = "graph it is" height = "300" width = "300">
</body>
The three plots are sent as a png file from multiple functions in flask backend as below:
#app.route('/graph_visualization/')
def graph_visualization():
fig, ax = plt.subplots()
df = pd.read_csv(r'C:\Users\Admin\Downloads\export.csv')
sns.countplot(x="Lead Origin", hue="Converted", data=df)
canvas = FigureCanvas(fig)
img = BytesIO()
fig.savefig(img, format='png')
img.seek(0)
return send_file(img, mimetype='image/png', cache_timeout=-1)
#app.route('/graph_visualization2/')
def graph_visualization2():
fig1, ax = plt.subplots()
df = pd.read_csv(r'C:\Users\Admin\Downloads\export.csv')
sns.countplot(x="Cities", hue="Converted", data=df)
xticks(rotation=90)
plt.tight_layout()
canvas = FigureCanvas(fig1)
img1 = BytesIO()
fig1.savefig(img1, format='png')
img1.seek(0)
return send_file(img1, mimetype='image/png', cache_timeout=-1)
#app.route('/graph_visualization3/')
def graph_visualization3():
fig2, ax = plt.subplots()
df = pd.read_csv(r'C:\Users\Admin\Downloads\export.csv')
sns.barplot(x="Countries", y="Converted", data=df)
xticks(rotation=90)
plt.tight_layout()
plt.ylabel('Converted')
plt.xlabel('Countries')
canvas = FigureCanvas(fig2)
img2 = BytesIO()
fig2.savefig(img2, formar='png')
img2.seek(0)
return send_file(img2, mimetype='image/png', cache_timeout=-1)
Note: Individual graph shows when i comment any two functions and only keep one. The problem is when i uncomment all of them.
I have tried following methods:
Changing the figurename and image name in each functions.
plt.clf() below fig.savefig()
ax.clear() below fig, ax = plt.subplots()
Run in Incognito mode.
Note: I don't want to make multiple subplots.
Please let me know if my approach to the problem is incorrect.

Related

Animated/interactive plots for DBSCAN clustering

I have the code below. I'm trying to build an interactive DBSCAN clustering plot. When I run it, I get three plots but not interactive. Where is the problem in the code and how to fix it.
df_mv = pd.read_csv(r"https://raw.githubusercontent.com/HanaBachi/MachineLearning/main/multishape.csv") # load from Prof. Pyrcz's GitHub
df_mv.head()
text_trap = io.StringIO()
sys.stdout = text_trap
l = widgets.Text(value=' DBSCAN, Hana Bachi, The University of Texas at Austin',
layout=Layout(width='950px', height='30px'))
eps = widgets.FloatSlider(min=0, max = 2, value=0.1, step = 0.1, description = 'eps',orientation='horizontal', style = {'description_width': 'initial'}, continuous_update=False)
minPts = widgets.FloatSlider(min=0, max = 5, value=1, step = 1, description = 'minPts %',orientation='horizontal',style = {'description_width': 'initial'}, continuous_update=False)
color = ['blue','red','green','yellow','orange','white','magenta','cyan']
style = {'description_width': 'initial'}
ui = widgets.HBox([eps,minPts],)
ui2 = widgets.VBox([l,ui],)
# create activation function plots
def DBSCAN_plot(eps, minPts):
db = DBSCAN(eps=0.155, min_samples=5).fit(df_mv)
labels = db.labels_
# n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
# x = df_mv.values[:,0]
# y = df_mv.values[:,1]
# cmap = plt.cm.rainbow
#norm = mc.BoundaryNorm(labels, cmap.N)
plt.figure(figsize=(14,7))
plt.scatter(x, y, c=labels, cmap='tab10', s=50)
plt.scatter(x[np.where(labels==-1)], y[np.where(labels==-1)], c='k', marker='x', s=100)
plt.title('DBSCAN interactive plot', fontsize = 20)
plt.colorbar()
plt.show()
plt.subplots_adjust(left=0.0, bottom=0.0, right=2.0, top=1.0, wspace=0.2, hspace=0.3)
plt.show()
# create dashboard/formatting
uia = widgets.HBox([interactive_plot1],)
uia2 = widgets.VBox([eps, uia],)
uib = widgets.HBox([interactive_plot1],)
uib2 = widgets.VBox([minPts, uib],)
interactive_plot1 = widgets.interactive_output(DBSCAN_plot, {'eps': eps,'minPts':minPts})
interactive_plot1.clear_output(wait = True) #
How can I make this plot interactive in function of eps and minPts

Creating a legend, and printing a graph with python

I am wanting to add a legend to the graph below and download it as a pdf. The code I have for the graph is below.
%matplotlib inline
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
mta = pd.read_csv('../project/all_mta_data_cleanded.csv') # mta data cleanded into similare catagories
cata = pd.read_csv('../project/mta_catagories_breakdown.csv') #document combining all of the catagories
weather = pd.read_csv('../project/New York Tempeture Data.csv')
mta['Total Lost Items'] = mta['Total Lost Items'] = (mta['Accessories']+ mta['Books'] + mta['Bags'] + mta['Cellphones'] + mta['Clothing'] + mta['Money'] + mta['Eletronics'] + mta['Entrainment'] + mta['Glasses'] + mta['Shoes'] + mta['Household Items'] + mta['Indentification'] + mta['Jewlery'] + mta['Keys'] + mta['Medical Equipment'] + mta['Miscellaneous'] + mta['Instruments'] + mta['NYCT Equipment'] + mta['Sports Equipment'] + mta['Tickets'] + mta['Tools'] + mta['Toys'] + mta['Wallets/Purses'])
clear = mta.iloc[[13, 40,68,92,115,138,157,176,200,222,241,245,246,250],:] #selected the last pull of each month
compl = pd.merge(clear,weather, left_on='Date',right_on='Time',how='outer').drop(columns=['Time'])
fig, ax1 = plt.subplots()
ax1.plot(compl['Date'], compl['Temp'] ,color = 'red',marker='o')
ax2= ax1.twinx()
ax2.plot(compl['Date'], compl['Total Lost Items'],color= 'purple',marker='^')
ax1.set_ylabel('Tempeture in Fahrenheit', )
for tick in ax1.get_xticklabels():
tick.set_rotation(90)
ax2.set_ylabel('Number Of Items Lost')
ax1.set_title('Average Weather In New Your City vs Total Items Lost Each Month')
plt.set_legend()
plt.figure.savefig('Project Figure.pdf')```
to add a legend to your graph you have to specify the field "label" in plt.plot(), use plt.legend() and plt.show()
fig, ax1 = plt.subplots()
l1 = ax1.plot(compl['Date'], compl['Temp'] ,color = 'red',marker='o', label = 'label_1')
ax2= ax1.twinx()
l2 = ax2.plot(compl['Date'], compl['Total Lost Items'],color= 'purple',marker='^', label = 'label_2')
ax1.set_ylabel('Temperature in Fahrenheit')
for tick in ax1.get_xticklabels():
tick.set_rotation(90)
ax2.set_ylabel('Number Of Items Lost')
ax1.set_title('Average Weather In New Your City vs Total Items Lost Each Month')
plt.legend([l1,l2],['lab1', 'lab2'])
plt.show()
plt.savefig('Project Figure.pdf')

Plotting categorial groupings in bokeh with geopandas not working? (Problem with CategoricalColorMapper)

I'm having problems plotting groupings of countries on a world map using Bokeh in combination with the geopandas package. What I want to do is colour each country in a group with a certain colour on the map. The groupings are saved in the dataframe "dataset", which is merged with the geopandas geographical info, converted to json and fed to the mapping functions. (Code below.)
The interesting thing is that no error is generated, Bokeh even reports that "BokehJS 1.4.0 successfully loaded", but no chart is shown.
I am quite convinced that the problem is with my implementation of the CategoricalColorMapper. This is evident since if I change the color mapper to to linear color mapper, the code works perfectly.
This code does not work:
from bokeh.palettes import viridis
from bokeh.models import FactorRange
dataset = gdf.merge(dataset, left_on = 'country', right_on = 'location', how = 'left')
#gdf is geopandas geo info dataframe
#Read data to json
dataset_json = json.loads(dataset.to_json())
#Convert to str like object
dataset_json_data = json.dumps(dataset_json)
#Input GeoJSON source that contains features for plotting.
geosource = GeoJSONDataSource(geojson = dataset_json_data)
catValues=list(dataset["val"].dropna().unique().astype("str"))
palette=viridis(len(catValues))
print("Palette len:", len(palette))
print("Factors:", len(catValues))
print(dataset)
color_mapper = CategoricalColorMapper(palette = palette , factors=catValues)
#Create figure object.
p = figure(title = title_string, plot_height = 600 , plot_width = 950, toolbar_location = None)
p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None
#Add patch renderer to figure.
p.patches('xs','ys', source = geosource, fill_color = {'field' :'val', 'transform' : color_mapper})
#Display figure inline in Jupyter Notebook.
output_notebook()
#Display figure.
show(p)
Calling the function prints the following, but non map is shown. The number of colors and categories seems fine to me?
Palette len: 118
Factors: 118
BokehJS 1.4.0 successfully loaded.
Replacing only the color mapper works perfectly. This code works:
def plot_map(dataset, title_string = ""):
dataset = gdf.merge(dataset, left_on = 'country', right_on = 'location', how = 'left')
#Read data to json
dataset_json = json.loads(dataset.to_json())
#Convert to str like object
dataset_json_data = json.dumps(dataset_json)
#Input GeoJSON source that contains features for plotting.
geosource = GeoJSONDataSource(geojson = dataset_json_data)
#Define a sequential multi-hue color palette.
palette = brewer['OrRd'][7]
#Reverse color order so that dark blue is highest obesity.
palette = palette[::-1]
#Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors.
color_mapper = LinearColorMapper(palette = palette, low = dataset.val.min(), high = dataset.val.max())
#Define custom tick labels for color bar.
#tick_labels = {'0': '0', '1': '1', '2':'2', '3':'3', '4':'4', '5':'5', '6':'6','7':'7'}
#Create color bar.
color_bar = ColorBar(color_mapper=color_mapper, label_standoff=7,width = 500, height = 20,
border_line_color=None,location = (0,0), orientation = 'horizontal', major_label_overrides = tick_labels)
#Create figure object.
p = figure(title = title_string, plot_height = 600 , plot_width = 950, toolbar_location = None)
p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None
#Add patch renderer to figure.
p.patches('xs','ys', source = geosource, fill_color = {'field' :'val', 'transform' : color_mapper},
line_color = 'black', line_width = 0.25, fill_alpha = 1)
#Specify figure layout.
p.add_layout(color_bar, 'below')
#Display figure inline in Jupyter Notebook.
output_notebook()
#Display figure.
show(p)

Using pptx without having to first save outputs to jpg files

I am creating a powerpoint in Python, where the slides are the output graphs from the Jupyter Notebook cells.
I am able to do this, but only if I save each output as a jpg. For example, see the code below:
data = pd.read_csv("123.csv")
data.columns = ['Color Group', 'BASE VOLUME']
x= data['BASE VOLUME']
y= data['Color Group']
data2 = data
data2['BASE VOLUME %'] = data2['BASE VOLUME']
data2 = data2.iloc[:,[0,2]]
data2['BASE VOLUME %'] = 100*data2['BASE VOLUME %']/(sum(data2['BASE VOLUME %']))
data2['Type'] = 'Total'
total = data2.copy()
plt.figure(figsize=(10,6))
clrs = ['deepskyblue' if (x > 10) else 'gray' for x in data2['BASE VOLUME %']]
ax = sns.barplot(x,y, data=data2, palette=clrs)
ax.set_xlabel('Base Volume',fontsize=15)
ax.set_ylabel('Color Group',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
for i, v in enumerate(data2['BASE VOLUME %']):
ax.text(0 + 0.01*max(data['BASE VOLUME']), i + len(data2)/50, str("{0:.1f}%".format(v)), color='black', fontweight='bold', fontsize=14)
plt.title('Total'.format(s),fontsize=15)
plt.savefig("Total.jpg",bbox_inches='tight')
#Create Powerpoint
from pptx import Presentation
from pptx.util import Inches,Pt
prs = Presentation('input.pptx')
blank_slide_layout = prs.slide_layouts[1]
img1 = 'Total.jpg'
slide = prs.slides.add_slide(blank_slide_layout)
pic = slide.shapes.add_picture(img1, Inches(0.55), Inches(2), height=Inches(4.8), width=Inches(8.8))
title = slide.shapes.title
title.text_frame.paragraphs[0].font.size=Pt(50)
title.text = "Total"
Is there a way of creating a similar line toplt.savefig("Total.jpg",bbox_inches='tight'), without saving a file - i.e calling the plot "something (say x)" that can be called back at any point? Then later I can replace the line img1 = 'Total.jpg' with img1 = x etc.

Why do I get the error, "350 is not JSON serializable"

I've been working on a project in Python using Matplotlib in tandem with Django. Right now I just want to display the graph in the webpage. Before, I saved the figure as a PNG, and the graph showed up. Unfortunately, this disables some interactive features that I had planned on including. In order to work around this, I used MPLD3's function, fig_to_html, which I saw worked in other examples. However, when I used the line in my own code, I got the error, "350 is not JSON serializable".
Here is my code:
def index(request):
# template = loader.get_template('')
noaaNmbr='11809'
#for right now, this is the only active region that I'm pulling data for. When I get the graph up and running, I will make it more interactive for the user so that he can
urlData = "http://www.lmsal.com/hek/hcr?cmd=search-events3&outputformat=json&instrument=IRIS&noaanum="+ noaaNmbr +"&hasData=true"
webUrl = urlopen(urlData)
counter = 0
data = webUrl.read().decode('utf-8')
hekJSON = json.loads(data)
getInfo(counter, hekJSON)
sort()
# Sorts the data from earliest to most recent
fig, ax = plt.subplots(figsize=(30, 30))
circle = Circle((0, 0), 980, facecolor='none', edgecolor=(0, 0.8, 0.8), linewidth=3, alpha=0.5)
ax.add_patch(circle)
# Creates circular representation of the sun on the graph because that's all I really need for now
plt.plot(xcen, ycen, color="red")
plt.plot(xcen, ycen, 'ro', color = 'blue')
#first plots the points in red, then draws lines between the points in blue
plt.xlim([setXMin(hekJSON), setXMax(hekJSON)])
plt.ylim([setYMin(hekJSON), setYMax(hekJSON)])
#sets the boundaries of the graph
ax.set_xticks(np.arange(round_multiple(setXMin(hekJSON),50), round_multiple(setXMax(hekJSON), 50), 50))
ax.set_yticks(np.arange(round_multiple(setYMin(hekJSON),50), round_multiple(setYMax(hekJSON), 50), 50))
#sets the ticks
for i in range(getNumberOfEntries(hekJSON)):
if xfov[i] != 0:
xStart = xcen[i] - xfov[i]/14
yStart = ycen[i] - yfov[i]/14
ax.add_patch(Rectangle((xStart, yStart), xfov[i]/7, yfov[i]/7, facecolor='none'))
plt.grid()
# texts = fixAnnotations(createAnnotations(hekJSON, noaaNmbr))
# adjust_text(texts, arrowprops=dict(arrowstyle="-", color='k', lw=0.5))
# canvas = FigureCanvasAgg(fig)
# response = HttpResponse(content_type='image/png')
# canvas.print_png(response)
# g = mpld3.fig_to_html(fig)
g = mpld3.display(fig)
return HttpResponse(g)
# return response
This is the section of code that uses JSON stuff:
noaaNmbr='11809'
#for right now, this is the only active region that I'm pulling data for. When I get the graph up and running, I will make it more interactive for the user so that he can
urlData = "http://www.lmsal.com/hek/hcr?cmd=search-events3&outputformat=json&instrument=IRIS&noaanum="+ noaaNmbr +"&hasData=true"
webUrl = urlopen(urlData)
counter = 0
data = webUrl.read().decode('utf-8')
hekJSON = json.loads(data)
getInfo(counter, hekJSON)
Can somebody please explain what the issue is and how to fix it?

Categories