How to fix double layered text on python graph - python

My python graph has odd double layered text and as a beginner I don't know how to clean this up. How would this be done?
Thanks
import matplotlib.pyplot as plt
import numpy as np
fig1 = plt.figure(1)
plt.xticks(np.arange(0, 701, 100))
plt.yticks(np.arange(0.0, 3.7, 0.5))
frame1=fig1.add_axes((0.1,0.3,.8,.6))
m, b = np.polyfit(x, y, 1)
plt.plot(x, m*x + b, '-', color='grey', alpha=0.5)
plt.plot(x,y,'.',color='navy',markersize=6)
plt.errorbar(x,y,xerr=0,yerr=yerr,linestyle="None",color='navy')
plt.ylabel('$Natural\ Log\ of\ Rate$',fontsize=17)
plt.grid(False)
frame2=fig1.add_axes((.1,.1,.8,.2))
s = m*x+b #(np.sqrt(4*np.pi*8.85E-12)/2.23E-8)*x
difference = y-s
plt.plot(x, difference, 'ro')
frame2.set_ylabel('$Residual$',fontsize=17)
plt.xlabel('$Time$ $(s)$',fontsize=17)
plt.savefig('mygraph')
plt.show()

You may want to let matplotlib automatically position the subplots using fig.add_subplot(211), where 211 means that on a grid of 2 rows and 1 column, the first (top) subplots shall be used.
Afterwards it's convenient to use the API methods to plot to an axes, ax.plot() instead of plt.plot(), and also setting all other labels and ticks using the API methods. This makes it easier to determine which elements belong to which subplot.
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0, 700, 100)
y = np.arange(0.0, 3.5, 0.5)
fig1 = plt.figure(1)
ax1=fig1.add_subplot(211)
m, b = np.polyfit(x, y, 1)
ax1.set_xticks(np.arange(0, 701, 100))
ax1.set_yticks(np.arange(0.0, 3.7, 0.5))
ax1.plot(x, m*x + b, '-', color='grey', alpha=0.5)
ax1.plot(x,y,'.',color='navy',markersize=6)
ax1.set_ylabel('$Natural\ Log\ of\ Rate$',fontsize=17)
plt.grid(False)
ax2=fig1.add_subplot(212)
s = m*x+b #(np.sqrt(4*np.pi*8.85E-12)/2.23E-8)*x
difference = y-s
ax2.plot(x, difference, 'ro')
ax2.set_ylabel('$Residual$',fontsize=17)
ax2.set_xlabel('$Time$ $(s)$',fontsize=17)
plt.show()

Related

matplotlib: Invert y axis on 3d bar graph

I created 3d bar graph with matplotlib with the following code:
fig = plt.figure()
cmap = get_cmap(len(os.listdir(conv1d_kernel_path)))
ax = fig.add_subplot(111, projection='3d')
for f in os.listdir(conv1d_kernel_path):
step = int(re.findall(r'\d+', f)[0])
conv1d_kernel_histo[f]['bins'] = convert_bins(30, min_weight, max_weight, conv1d_kernel_histo[f])
bin_counts = conv1d_kernel_histo[f]['bins'][:, 2]
width = (max_weight-min_weight)/30 #ToDo change 30 to numbins
xs = conv1d_kernel_histo[f]['bins'][:, 0] + width / 2
ax.bar(xs, list(bin_counts), width=width, zs=step, zdir='y', color=cmap(step), ec=cmap(step+20), alpha=0.8)
ax.set_xlabel('weights')
ax.set_ylabel('step')
ax.set_zlabel('count')
plt.show()
The directory and convert bins function isn't so important, just that it gives me the info I can use to define the input data that I iteratively pass to the ax.bar function. Anyways, I receive the following output:
I want to invert the axis titled 'steps', and this question seems to be nearly what I need; however, when I used ax.invert_yaxis() the axis titled 'weights' is inverted. When I alternatively use ax.invert_xaxis() the same axis is inverted. Out of curiosity, I tried ax.invert_zaxis() but that worked as one would think, and flipped the whole graph upside down. Does anybody have a solution to this problem? A different method for inverting the axis? Thanks, all help is appreciated
Well inverting the axis limits like ax.set_ylim(150,0) should work fine. Sample plot:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
# Make data.
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
# Invert Y-Axis
ax.set_ylim(4,-4)
# Customize the z axis.
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
Original:
Inverted Y-Axis:

Creating multiple rows of matplotlib x labels

import matplotlib.pyplot as plt
import numpy as np
x = np.arange(-1,5)
y = 6 - np.square(x-1)
fig, ax = plt.subplots()
ax.plot(x, y, 'b')
ax.scatter(x, y, color='m', zorder=10)
ax.set_xlabel('x')
ax.set_ylabel('y')
This creates the following:
This function is increasing for all values of x < 1 and increasing for all values of x > 1. Is there a simple way that I can put the text "Increasing" like an x label but centered below the x ticks of 0 and 1, "Decreasing" like an x label but centered below 3, and move the "x" xlabel lower such that it has a lower vertical position than "Increasing" and "Decreasing"? I'd rather not do this with ax.text() unless I absolutely have to.
Maybe use text? I have tried changing the labels but this seems cumbersome. Unfortunately you have to set the text coordinates "manually". Note that you can use newline in the ticks to move them down.
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(-1,5)
y = 6 - np.square(x-1)
fig, ax = plt.subplots()
ax.text(0.5, -4.6, 'Increasing', ha="center")
ax.text(3, -4.6, 'Decreasing', ha="center")
ax.plot(x, y, 'b')
ax.scatter(x, y, color='m', zorder=10)
ax.set_xlabel('\nx')
ax.set_ylabel('y')
which produces

Exclude grid lines from boundaries of plot in python?

I am looking for a way to remove grid lines from the axes of a plot, but unfortunately, I've not come up to a solution for this issue and neither found it anywhere else.
Is there a way to remove certain grid lines or choose which grid lines to plot without having to rely on the automatic function?
I've coded a quick example outputting a plot for illustration below and would be glad for any help.
import matplotlib.pyplot as plt
import numpy as np
def linear(x, a, b):
return a*x+b
x = np.linspace(0, 1, 20)
y = linear(x, a=1, b=2)
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(10, 6))
ax.plot(x, y, color='darkred')
ax.set_xlim(0, 1)
ax.set_ylim(2, 3)
ax.grid(which='major', axis='y', linestyle='--', color='grey', linewidth=3)
plt.savefig("Testplot.pdf", format='pdf')
The major gridlines appear at positions of the major ticks. You can set any individual gridline invisible. E.g. to set the fifth gridline off,
ax.yaxis.get_major_ticks()[5].gridline.set_visible(False)
Here is a proposition with ticks and horizontal lines. The idea is to specify the ticks (not really necessary, but why not), and then to draw horizontal dashes lines where you want your grid.
import matplotlib.pyplot as plt
import numpy as np
def linear(x, a, b):
return a*x+b
x = np.linspace(0, 1, 20)
y = linear(x, a=1, b=2)
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(10, 6))
ax.plot(x, y, color='darkred')
ax.set_xlim(0, 1)
ax.set_ylim(2, 3)
yticks = np.arange(2, 3, 0.2)
grid_lines = np.arange(2.2, 3, 0.2)
ax.set_yticks(yticks)
for grid in grid_lines:
ax.axhline(grid, linestyle='--', color='grey', linewidth=3)
Output:
Why did I include the yticks? Well you could design a function which takes in input the yticks and return the position of the grid lines accordingly. I think it could be handy depending on your needs. Good luck!

2D line not showing clearly along with surface on 3D plot

I am trying to plot a 1D line along with a 2D surface in matplotlib with Axes3D:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-1., 1.1, 0.1)
y = x.copy()
X, Y = np.meshgrid(x, y)
Z = np.abs(X) + np.abs(Y)
plt.close('all')
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(np.zeros_like(y), y, 1, color='k')
ax.plot(x, np.zeros_like(x), 1, color='k')
surf = ax.plot_surface(X, Y, Z, color='w')
plt.show(block=False)
but the 2D plot somehow hides the lines:
If I comment the surf = plot_surface(...) code line, the 1D lines show correctly:
How can I have the lines showing correctly along with the surface?
Axes3D.plot_surface() apparently accepts a transparency (alpha) argument, which actually gets forwarded to a base class, Poly3DCollection.
And of course the line plot() calls accept a linewidth argument.
So if you render the line plots with thicker lines and you render the surface with some transparency, you should be able to find a combination of settings which let you see both the lines and the surface in a balanced way.
https://matplotlib.org/tutorials/toolkits/mplot3d.html#mpl_toolkits.mplot3d.Axes3D.plot_surface
https://matplotlib.org/api/_as_gen/mpl_toolkits.mplot3d.art3d.Poly3DCollection.html#mpl_toolkits.mplot3d.art3d.Poly3DCollection
You can also achieve this by using the zorder in the plot_surface and plot commands to make the lines sit on top of the surface. E.g.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(-1., 1.1, 0.1)
y = x.copy()
X, Y = np.meshgrid(x, y)
Z = np.abs(X) + np.abs(Y)
plt.close('all')
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, color='w', zorder=1)
ax.plot(np.zeros_like(y), y, 1, color='k', zorder=10)
ax.plot(x, np.zeros_like(x), 1, color='k', zorder=11)
plt.show(block=False)

Colorbar makes subplot smaller in size than rest

I'm trying to make a subplot with three plots next to each other, and then a colorbar on the right side of the last plot (see figure).
I'm doing it with this code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams
from mpl_toolkits.axes_grid1 import make_axes_locatable
x = np.linspace(1, 100, 100)
y = np.linspace(0.1, 10, 100)
z = x[:, np.newaxis] + y[np.newaxis, :]
fig, ax = plt.subplots(1, 3, figsize=(12, 4))
ax[0].contourf(x, y, z)
ax[0].set_xlabel('x')
ax[0].set_ylabel('y')
ax[1].contourf(x, y, z)
ax[1].set_xlabel('x')
ax[1].set_ylabel('y')
plt.contourf(x, y, z)
ax[2].set_xlabel('x')
ax[2].set_ylabel('y')
divider = make_axes_locatable(plt.gca())
cax = divider.append_axes("right", "10%", pad="3%")
plt.colorbar(cax=cax)
plt.tight_layout()
plt.show()
My problem is that 1) I don't think the first two plots are completely square (which I would like them to be), 2) the last plot that includes the colorbar is smaller in width than the two others. Is there some easy trick to fix this, or do I manually have to go in and give one a little more padding than the other an so on.
If you don't want the subplot to eat into the third axes, already create an extra axes for it when you make the subplots.
To make the plots square, you need to set the aspect ratio: axes.set_aspect(10).
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(1, 100, 100)
y = np.linspace(0.1, 10, 100)
z = x[:, np.newaxis] + y[np.newaxis, :]
gridspec = {'width_ratios': [1, 1, 1, 0.1]}
fig, ax = plt.subplots(1, 4, figsize=(12, 4), gridspec_kw=gridspec)
ax[0].contourf(x, y, z)
ax[0].set_xlabel('x')
ax[0].set_ylabel('y')
ax[1].contourf(x, y, z)
ax[1].set_xlabel('x')
ax[1].set_ylabel('y')
plt.sca(ax[2])
plt.contourf(x, y, z)
ax[2].set_xlabel('x')
ax[2].set_ylabel('y')
for axes in ax[:3]:
axes.set_aspect(10)
cax = ax[3]
plt.colorbar(cax=cax)
plt.tight_layout()
plt.show()

Categories