matplotlib/pyplot not plotting data from specific .txt file - python

I have data saved via numpy's savetxt function and am extracting it to plot. When I plot it the script executes without errors but does not show the curves--only empty windows. This is strange because:
The same script makes a fine plot when I import .txt data from another file (also saved using savetxt).
If I create data points inside the script, e.g. with arange, it plots.
The .txt data is getting loaded--I have printed it to the screen.
I checked my backend and it is TkAgg, which the internet agrees it's supposed to be.
My code is
# this script makes the plots of the eigenvalue distributions for the AAS 17-225 paper
# import python modules
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
# set plot options
mpl.rcParams['xtick.major.size'] = 7
mpl.rcParams['xtick.major.width'] = 3.0
mpl.rcParams['ytick.major.size'] = 7
mpl.rcParams['ytick.major.width'] = 3.0
mpl.rcParams['axes.linewidth'] = 3.5
plt.rc('text',usetex=True)
mpl.rcParams['text.latex.preamble']=[r"\usepackage{amsmath}"]
plt.rc('font',family='serif')
plt.rc('axes',labelsize=24)
plt.rc('xtick',labelsize=24)
plt.rc('ytick',labelsize=24)
plt.rc('font',weight='bold')
plt.rc('axes',titlesize=20)
# plot method arguments
lw = 2 # linewidth
left_adj = 0.055 # left adjustment
right_adj = 0.985 # left adjustment
top_adj = 0.975 # left adjustment
bottom_adj = 0.075 # left adjustment
wspace = 0.205 # horizontal space between plots
hspace = 0.2 # verticle space between plots
n_suplot_rows = 2 # number of subplot rows
n_suplot_columns = 3 # number of subplot columns
# load data
dataDir ='/mnt/E0BA55A7BA557B4C/research/independent/recursivequats/paperCode/'
df1 = dataDir+'lamda_0p1_0p1.txt'
df2 = dataDir+'lamda_0.1_0.5.txt'
df3 = dataDir+'lamda_0.1_1.0.txt'
df4 = dataDir+'lamda_0.5_0.5.txt'
df5 = dataDir+'lamda_0.5_1.0.txt'
df6 = dataDir+'lamda_1.0_1.0.txt'
profile1 = np.loadtxt(df1)
profile2 = np.loadtxt(df2)
profile3 = np.loadtxt(df3)
profile4 = np.loadtxt(df4)
profile5 = np.loadtxt(df5)
profile6 = np.loadtxt(df6)
fig = plt.figure()
ax1 = fig.add_subplot(n_suplot_rows,n_suplot_columns,1)
p1, = ax1.plot(profile1[:,1],profile1[:,0],linewidth=lw)
ax2 = fig.add_subplot(n_suplot_rows,n_suplot_columns,2)
p1, = ax2.plot(profile2[:,1],profile2[:,0],linewidth=lw)
ax3 = fig.add_subplot(n_suplot_rows,n_suplot_columns,3)
p1, = ax3.plot(profile3[:,1],profile3[:,0],linewidth=lw)
ax4 = fig.add_subplot(n_suplot_rows,n_suplot_columns,4)
p1, = ax4.plot(profile4[:,1],profile4[:,0],linewidth=lw)
ax5 = fig.add_subplot(n_suplot_rows,n_suplot_columns,5)
p1, = ax5.plot(profile5[:,1],profile5[:,0],linewidth=lw)
ax6 = fig.add_subplot(n_suplot_rows,n_suplot_columns,6)
p1, = ax5.plot(profile6[:,1],profile6[:,0],linewidth=lw)
plt.subplots_adjust(left=left_adj,right=right_adj,top=top_adj,bottom=bottom_adj,wspace=wspace,hspace=hspace)
plt.show()

well, a bit more digging and the problem has been identified. The script is plotting, but the zoom on the plots is so poor that they are obscured by the thick lines on the border. So the problem was a user error.
This is why engineers shouldn't try to be artists...

Related

Issue with animating Matplotlib-Seaborn subplots?

My current goal is to animate two sets of data simultaneous on a single plot with 2 subplots. I previously asked a question here about clearing the axes data with animated seaborn graphs, but rather than clearing the data on the axes, I need to append/update them (i.e.: something like the animated plots here). To make matters more complicated, one of my sets of data are stored in numpy arrays whereas the other set is stored in a pandas dataframe.
I tried using some test data before using my actual data, but that doesn't work, especially when I try to animate the data stored in the dataframe:
import math, os
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import animation
def update(i,pass_data,fig,axes,sort_yrs,ani,x_val,y_val):
fil_pass_data = pass_data[pass_data['year'] == sort_yrs[i]]
fig.suptitle(r"Year = {}".format(sorted_yrs[i]),fontsize = 35,y = 1.000)
axes[1] = sns.lineplot(x = 'year',y = 'passengers',data = fil_pass_data,hue = 'month',
hue_order = sort_yrs,palette = 'Set1',legend = False)
ani1.set_data(x_val[:i],y_val[:i])
#Read/Generate Data
passenger_df = sns.load_dataset('flights')
yrs_of_int = ['Jan','Mar','Jun','Jul','Dec']
fil_pass_df = passenger_df[passenger_df['month'].isin(yrs_of_int)]
sorted_yrs = sorted(fil_pass_df['year'].unique())
x = np.linspace(0,2*np.pi,fil_pass_df['year'].unique().shape[0])
y = np.sin(x)
#Initialize figure and plot initial points
fig,axes = plt.subplots(ncols = 2,figsize = (15,7))
axes[0].plot(x[0],y[0],color = 'tab:red',label = 'Initial Point',marker = 'o',markersize = 5)
sns.lineplot(x = 'year',y = 'passengers',
data = fil_pass_df[fil_pass_df['year'] == sorted_yrs[0]],
hue = 'month',hue_order = yrs_of_int,palette = 'Set1')
ani1, = axes[0].plot(x[0],y[0],color = 'tab:blue',label = 'Dynamic Response')
#Formatting
axes[0].legend(loc='lower right')
axes[0].set_ylim(-1.1*np.pi,1.1*np.pi)
axes[0].set_xlim(-0.1,1.1*2*np.pi)
axes[1].set_xlim(fil_pass_df['year'].min()-1,fil_pass_df['year'].min()+1)
axes[1].set_ylim(100,700)
axes[0].set_title('Test Plot',fontsize = 15,pad = 5)
axes[1].set_title('Passengers by Month',fontsize = 15,pad = 5)
axes[0].set_ylabel(r"$\sin(x)$",fontsize = 20,labelpad = 10)
axes[0].set_xlabel(r"$x$",fontsize = 20,labelpad = 10)
axes[1].set_ylabel("Passenger Count",fontsize = 20,labelpad = 10)
axes[1].set_xlabel("Year",fontsize = 20,labelpad = 10)
#Create animation and save it
animation = animation.FuncAnimation(fig, update, fargs =
(fil_pass_df,fig,axes,sorted_yrs,ani1,x,y),
frames=range(0,len(sorted_yrs)),interval=0.5,
blit=False,repeat=True)
animation.save('test.mp4',
fps = 1, extra_args=['-vcodec', 'libx264'],dpi = 200)
The test mp4 file that is generated from here animates the left most plot (numpy array data), but fails to plot the right most plot (seaborn data). I have four theories as to why it doesn't work:
I'm not supposed to initialize the right most figure parameters before the update call. Instead, the figure parameters need to be set in update.
The fact that I'm specifying hue in the update function is somehow messing up with matplotlib's animation.
The fact that my data is either in numpy arrays or a pandas dataframe.
I'm overthinking this and forgot to one command in my code that makes this work.
I tried moving the right figure formatting into update but that didn't seem to work, so it might be bullet points #2-4.
Does anyone know why this is happening/how to solve it? For subplot animations, is there a rule as to whether everything should be stored in the same data type?

Fitting a column from a pandas dataframe to animated histogram

I am attempting to produce an animated histogram that uses rows of data from a data frame I created. The code I am using to produce the histogram is below. The code works with data = np.random.randn(1000) but does not animate the histogram when I replace it with data = df['GDP'] instead it outputs a non-animated histogram. I am trying to fit a column from a data frame into this code:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.path as path
import matplotlib.animation as animation
fig, ax = plt.subplots()
# histogram our data with numpy
data = np.random.randn(1000)
n, bins = np.histogram(data, 100)
# get the corners of the rectangles for the histogram
left = np.array(bins[:-1])
right = np.array(bins[1:])
bottom = np.zeros(len(left))
top = bottom + n
nrects = len(left)
# here comes the tricky part -- we have to set up the vertex and path
# codes arrays using moveto, lineto and closepoly
# for each rect: 1 for the MOVETO, 3 for the LINETO, 1 for the
# CLOSEPOLY; the vert for the closepoly is ignored but we still need
# it to keep the codes aligned with the vertices
nverts = nrects*(1+3+1)
verts = np.zeros((nverts, 2))
codes = np.ones(nverts, int) * path.Path.LINETO
codes[0::5] = path.Path.MOVETO
codes[4::5] = path.Path.CLOSEPOLY
verts[0::5,0] = left
verts[0::5,1] = bottom
verts[1::5,0] = left
verts[1::5,1] = top
verts[2::5,0] = right
verts[2::5,1] = top
verts[3::5,0] = right
verts[3::5,1] = bottom
barpath = path.Path(verts, codes)
patch = patches.PathPatch(barpath, facecolor='green', edgecolor='yellow', alpha=0.5)
ax.add_patch(patch)
ax.set_xlim(left[0], right[-1])
ax.set_ylim(bottom.min(), top.max())
def animate(i):
# simulate new data coming in
data = np.random.randn(1000)
n, bins = np.histogram(data, 100)
top = bottom + n
verts[1::5,1] = top
verts[2::5,1] = top
ani = animation.FuncAnimation(fig, animate, 100, repeat=False)
from IPython.display import HTML
HTML(ani.to_jshtml())
To fit my own data I am replacing :
# histogram our data with numpy
data = np.random.randn(1000)
and:
# simulate new data coming in
data = np.random.randn(1000)
with a column in my data frame that has 247 rows:
data = df['GDP']
The output is a histogram with my own data however it is not animated as is with data = np.random.randn(1000)

Python: Changing visual parameters of ptitprince repo derived from seaborn and matplotlib

I am using a github repository called ptitprince, which is derived from seaborn and matplotlib, to generate graphs.
For example, this is the code using the ptitprince repo:
# coding: utf8
import pandas as pd
import ptitprince as pt
import seaborn as sns
import os
import matplotlib.pyplot as plt
#sns.set(style="darkgrid")
#sns.set(style="whitegrid")
#sns.set_style("white")
sns.set(style="whitegrid",font_scale=2)
import matplotlib.collections as clt
df = pd.read_csv ("u118phag.csv", sep= ",")
df.head()
savefigs = True
figs_dir = 'figs'
if savefigs:
# Make the figures folder if it doesn't yet exist
if not os.path.isdir('figs'):
os.makedirs('figs')
#automation
f, ax = plt.subplots(figsize=(4, 5))
#f.subplots_adjust(hspace=0,wspace=0)
dx = "Treatment"; dy = "score"; ort = "v"; pal = "Set2"; sigma = .2
ax=pt.RainCloud(x = dx, y = dy, data = df, palette = pal, bw = sigma,
width_viol = .6, ax = ax, move=.2, offset=.1, orient = ort, pointplot = True)
f.show()
if savefigs:
f.savefig('figs/figure20.png', bbox_inches='tight', dpi=500)
which generates the following graph
The raw code not using ptitprince is as follows and produces the same graph as above:
# coding: utf8
import pandas as pd
import ptitprince as pt
import seaborn as sns
import os
import matplotlib.pyplot as plt
#sns.set(style="darkgrid")
#sns.set(style="whitegrid")
#sns.set_style("white")
sns.set(style="whitegrid",font_scale=2)
import matplotlib.collections as clt
df = pd.read_csv ("u118phag.csv", sep= ",")
df.head()
savefigs = True
figs_dir = 'figs'
if savefigs:
# Make the figures folder if it doesn't yet exist
if not os.path.isdir('figs'):
os.makedirs('figs')
f, ax = plt.subplots(figsize=(7, 5))
dy="Treatment"; dx="score"; ort="h"; pal = sns.color_palette(n_colors=1)
#adding color
pal = "Set2"
f, ax = plt.subplots(figsize=(7, 5))
ax=pt.half_violinplot( x = dx, y = dy, data = df, palette = pal, bw = .2, cut = 0.,
scale = "area", width = .6, inner = None, orient = ort)
ax=sns.stripplot( x = dx, y = dy, data = df, palette = pal, edgecolor = "white",
size = 3, jitter = 1, zorder = 0, orient = ort)
ax=sns.boxplot( x = dx, y = dy, data = df, color = "black", width = .15, zorder = 10,\
showcaps = True, boxprops = {'facecolor':'none', "zorder":10},\
showfliers=True, whiskerprops = {'linewidth':2, "zorder":10},\
saturation = 1, orient = ort)
if savefigs:
f.savefig('figs/figure21.png', bbox_inches='tight', dpi=500)
Now, what I'm trying to do is to figure out how to modify the graph so that I can (1) move the plots closer together, so there is not so much white space between them, and (2) shift the x-axis to the right, so that I can make the distribution (violin) plot wider without it getting cut in half by the y-axis.
I have tried to play around with subplots_adjust() as you can see in the first box of code, but I receive an error. I cannot figure out how to appropriately use this function, or even if that will actually bring the different graphs closer together.
I also know that I can increase the distribution size by increasing this value width = .6, but if I increase it too high, the distribution plot begins to being cut off by the y-axis. I can't figure out if I need to adjust the overall plot using the plt.subplots,or if I need to move each individual plot.
Any advice or recommendations on how to change the visuals of the graph? I've been staring at this for awhile, and I can't figure out how to make seaborn/matplotlib play nicely with ptitprince.
You may try to change the interval of X-axis being shown using ax.set_xbound (put a lower value than you currently have for the beginning).

python scatter plot with errorbars and colors mapping a physical quantity

I'm trying to do a quite simple scatter plot with error bars and semilogy scale. What is a little bit different from tutorials I have found is that the color of the scatterplot should trace a different quantity. On one hand, I was able to do a scatterplot with the errorbars with my data, but just with one color. On the other hand, I realized a scatterplot with the right colors, but without the errorbars.
I'm not able to combine the two different things.
Here an example using fake data:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
n=100
Lx_gas = 1e40*np.random.random(n) + 1e37
Tx_gas = np.random.random(n) + 0.5
Lx_plus_error = Lx_gas
Tx_plus_error = Tx_gas/2.
Tx_minus_error = Tx_gas/4.
#actually positive numbers, this is the quantity that should be traced by the
#color, in this example I use random numbers
Lambda = np.random.random(n)
#this is actually different from zero, but I want to be sure that this simple
#code works with the log axis
Lx_minus_error = np.zeros_like(Lx_gas)
#normalize the color, to be between 0 and 1
colors = np.asarray(Lambda)
colors -= colors.min()
colors *= (1./colors.max())
#build the error arrays
Lx_error = [Lx_minus_error, Lx_plus_error]
Tx_error = [Tx_minus_error, Tx_plus_error]
##--------------
##important part of the script
##this works, but all the dots are of the same color
#plt.errorbar(Tx_gas, Lx_gas, xerr = Tx_error,yerr = Lx_error,fmt='o')
##this is what is should be in terms of colors, but it is without the error bars
#plt.scatter(Tx_gas, Lx_gas, marker='s', c=colors)
##what I tried (and failed)
plt.errorbar(Tx_gas, Lx_gas, xerr = Tx_error,yerr = Lx_error,\
color=colors, fmt='o')
ax = plt.gca()
ax.set_yscale('log')
plt.show()
I even tried to plot the scatterplot after the errorbar, but for some reason everything plotted on the same window is put in background with respect to the errorplot.
Any ideas?
Thanks!
You can set the color to the LineCollection object returned by the errorbar as described here.
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
n=100
Lx_gas = 1e40*np.random.random(n) + 1e37
Tx_gas = np.random.random(n) + 0.5
Lx_plus_error = Lx_gas
Tx_plus_error = Tx_gas/2.
Tx_minus_error = Tx_gas/4.
#actually positive numbers, this is the quantity that should be traced by the
#color, in this example I use random numbers
Lambda = np.random.random(n)
#this is actually different from zero, but I want to be sure that this simple
#code works with the log axis
Lx_minus_error = np.zeros_like(Lx_gas)
#normalize the color, to be between 0 and 1
colors = np.asarray(Lambda)
colors -= colors.min()
colors *= (1./colors.max())
#build the error arrays
Lx_error = [Lx_minus_error, Lx_plus_error]
Tx_error = [Tx_minus_error, Tx_plus_error]
sct = plt.scatter(Tx_gas, Lx_gas, marker='s', c=colors)
cb = plt.colorbar(sct)
_, __ , errorlinecollection = plt.errorbar(Tx_gas, Lx_gas, xerr = Tx_error,yerr = Lx_error, marker = '', ls = '', zorder = 0)
error_color = sct.to_rgba(colors)
errorlinecollection[0].set_color(error_color)
errorlinecollection[1].set_color(error_color)
ax = plt.gca()
ax.set_yscale('log')
plt.show()

How does one control whitespace around a figure in matplotlib?(plt.tight_layout does not work)

I have a matplotlib figure with 3 sub-plots. The consensus from stackexchange seems to be to use the plt.tight_layout in order to get rid of the whitespace around the figure. This does not solve the problem in my case.
My code is as follows:
import numpy as np
import os
import pandas as pd
import matplotlib as mpl
from matplotlib import pyplot as plt
my_dpi = 1500
plt.ion()
index = np.linspace(0,5,10)
combined = np.linspace(0,1,10)
case1 = np.linspace(0,1,10)
case2 = np.linspace(0,1,10)
case3 = np.linspace(0,1,10)
tsfont = {'fontname':'Times-Roman'}
mpl.rcParams.update({'font.size': 18})
mpl.rc('font',family='Arial')
ms = 0
f = plt.figure()
f.set_size_inches(7.5,10)
f.axison=False
lw = 2
asp = 5
axarr1 = plt.subplot(3,1,1, adjustable='box',aspect = asp)
axarr1.set_xlim(0,5,10)
axarr1.set_ylim(0,1)
axarr1.set_ylabel('y')
axarr1.set_xlabel('$\\tau$', fontsize =25)
p = axarr1.plot(index,combined,color='navy', linewidth=lw, label = "Healthy")
axarr1.xaxis.set_label_coords(0.5, -0.05)
'''
Duct 2
'''
axarr2 = plt.subplot(3,1,2, adjustable='box',aspect = asp)
#axarr2.set_aspect('auto')
axarr2.set_xlim(0,5,10)
axarr2.set_ylim(0,1)
axarr2.set_ylabel('y')
axarr2.set_xlabel('$\\tau$', fontsize = 25)
g = axarr2.plot(index,combined,color='navy', linewidth=lw)
axarr2.xaxis.set_label_coords(0.5, -0.05)
'''
Duct 3
'''
axarr3 = plt.subplot(3,1,3, adjustable='box',aspect = asp)
axarr3.set_xlim(0,5,10)
axarr3.set_ylim(0,1)
axarr3.set_ylabel('y')
axarr3.set_xlabel('$\\tau$', fontsize = 25)
w = axarr3.plot(index,combined,color='navy', linewidth=lw)
axarr3.xaxis.set_label_coords(0.5, -0.05)
#plt.tight_layout()
plt.show()
Without using plt.tight_layout() I get the following result
Uncommenting the relevant line gives me
As is obvious, while the vertical spacing changes, the horizontal spacing does not
I'd like to know how to get rid of the horizontal whitespacing to the left and right.
The tight_layout option places the images closer to the borders. However, in your case, there is nothing to fill this empty space with, so it doesn't work.
If you want a narrower figure, you should change the horizontal dimension, e.g.:
plt.figure(..., tight_layout=True, figsize=(12, 5))
This is in inches, experiment with the numbers until it looks good.
You could also use 2 by 2 subplots to keep a square figure and use the space better:
plt.subplot(2, 2, ...)
although this may look suboptimal with a prime number of figures.

Categories