How can I hide the axes in matplotlib 3d? - plot

How can I make a 3D plot without showing the axes?
When plotting a 3d plot, Matplotlib not only draws the x, y, and z axes, it draws light gray grids on the x-y, y-z, and x-z planes. I would like to draw a "free-floating" 3D plot, with none of these elements.
Stuff I've tried:
# Doesn't work; this hides the plot, not the axes
my_3d_axes.set_visible(False)
# Doesn't do anything. Also, there's no get_zaxis() function.
my_3d_axes.get_xaxis().set_visible(False)
my_3d_axes.get_yaxis().set_visible(False)

Ben Root provided a patch that fixes this for 1.0.1. It can be found as an attachment to the last email of this thread. To quote Ben:
Ok, looks like the hiding of the 3d axes was a feature added after the v1.0 release (but before I started working on mplot3d). This patch should enable the basic feature without interfering with existing functions. To hide the axes, you would have to set the private member "_axis3don" to False, like so:
ax = plt.gca(projection='3d')
ax._axis3don = False
If you do it this way, then you will get what you want now, and your code will still be compatible with mplot3d when you upgrade (although the preferred method would be to call set_axis_on() or set_axis_off()).
I hope that helps!
Ben Root

ax.set_axis_off()
Just to provide a concrete and direct example of what was mentioned at https://stackoverflow.com/a/7363931/895245
#!/usr/bin/env python3
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
import mpl_toolkits.mplot3d.art3d as art3d
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_axis_off()
# Draw a circle on the x=0 'wall'
p = Circle((0, 0), 1, fill=False)
ax.add_patch(p)
art3d.pathpatch_2d_to_3d(p, zdir="x")
p = Circle((0, 0), 1, fill=False)
ax.add_patch(p)
art3d.pathpatch_2d_to_3d(p, zdir="z")
ax.set_xlim(-1.2, 1.2)
ax.set_ylim(-1.2, 1.2)
ax.set_zlim(-1.2, 1.2)
plt.savefig('main.png', format='png', bbox_inches='tight')
Output:
Without ax.set_axis_off() it would look like:
You will notice however that this produces an excessively large whitespace margin around the figure as it simply hides the axes but does not change the viewbox. I tried bbox_inches='tight' and it did not help as it does in 2D. How to solve that at: Remove white spaces in Axes3d (matplotlib)
Tested on matplotlib==3.2.2.

Related

How to Draw the Solution Curve in Julia with Arrow Correctly Using Plots?

I am trying to plot the solution curve from this page:
dynamicalsystem
But, I can't draw the arrow in the curve pointing to the origin, and the curve is not spiraling as well. Is something wrong with my code?
using MTH229, ForwardDiff, Plots, LaTeXStrings, SymPy
gr()
t = range(0, stop=21, length=10000)
x = #. exp(-2t)*cos(t)
y = #. exp(-2t)*sin(t)
plot(x, y, arrow = :closed, label=L"x(t)",
xlims=(-0.1,1), ylims=(-0.1,0.21))
You do not see a spiral, because the plot you have linked is not accurate (i.e. it has a wrong scale - most likely for didactic purposes). You can see that you have a spiral, by e.g. plotting the angle of the point plot(t, angle.(x + im * y)). The problem is that the plot absolute value of the points you plot gets very small very fast so these spirals are not visible.
Now the other issue is how to plot the arrow. The arrow in your case is just not visible because it is plotted at the end of your curve. I think (but maybe there are better ways to do it) that the simplest solution to pick a place to add it separately. For example after doing an initial plot add plot!(x[240:241], y[240:241], arrow=:closed) will add an extra arrow in the segment of your curve and the arrow will be visible (you just need to decide on the color of the arrow).

different element sizes with matplotlib backend

I'm trying to accomplish a heatmap color bar to add extra info about the kdims in my heatmap. (Like the colSideColors option if you are familiar with R's heatmap.2 package.)
I can get a nice result with bokeh backend, but don't know how to get custom (different) element sizes when using matplotlib backend.
Can anyone tell me how to make the strip plot "shorter" (less "high") in the matplotlib backend example?
Setup
import pandas as pd
import numpy as np
import holoviews as hv
hv.extension('bokeh', 'matplotlib')
# dummy data
samples = ['sample{}'.format(x) for x in range(5)]
df = pd.DataFrame(np.random.rand(5, 5),columns=samples, index=samples).reset_index()
df = df.melt(id_vars='index', var_name='y').rename(columns={'index': 'x'})
# column means
df_strip = df.groupby('x').mean().reset_index()
df_strip['y'] = 'dummy'
# make plots
heatmap = hv.HeatMap(df, kdims=['x','y'])
strip = hv.HeatMap(df_strip, kdims=['x','y'])
Result with bokeh
%%output size=100 backend='bokeh'
(strip.options(xaxis=None, yaxis=None, height=50) +
heatmap.options(xrotation=90)).cols(1)
Result with matplotlib backend
%%output size=100 backend='matplotlib'
%%opts Layout [sublabel_format='' vspace=0.1]
(strip.options(xaxis=None, yaxis=None, aspect=1) +
heatmap.options(xrotation=90, aspect=1)).cols(1)
hv.__version__
'1.10.8'
The sizing unfortunately works very differently in the two backends, which means it can be somewhat difficult to get the same behavior. In this particular case you will want to set a larger aspect on the strip plot while also telling the Layout that it should weight the aspect when computing the size of the plots. Doing that looks something like this:
%%output size=100 backend='matplotlib'
%%opts Layout [sublabel_format='' vspace=0.1 aspect_weight=1]
(strip.options(xaxis=None, yaxis=None, aspect=5) +
heatmap.options(xrotation=90, aspect=1)).cols(1)

Custom art in NetworkX graph

Is anyone aware of a way to put in an image (vector or raster) in place of a text label for a node or edge in a NetworkX graph visualization?
I prefer a solution that uses the matplotlib plot engine rather than the graphviz, but will take either solution.
In principle, the below should work. I transform the points into pixel coordinates, and then use figimage to put the image at that point.
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.image as image
im = image.imread('Lower_case_a.png')
G=nx.fast_gnp_random_graph(2,1)
pos = nx.spring_layout(G)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.patch.set_alpha(0)
ax.axis(xmin=-1,xmax=2,ymin=-1,ymax=2)
for node in G.nodes():
x,y = pos[node]
trans_x, trans_y = ax.transData.transform((x,y))
fig.figimage(im,trans_x,trans_y) #could use custom image for each node
nx.draw_networkx_edges(G,pos)
plt.savefig('tmp.png')
It almost works for me. I get:
I think that's because of some weird issue on my computer. When I run the code provided at matplotlib.org to explain transData.transform, it should give me, but instead I get
So I feel like the offset I'm seeing may be a problem on my machine and I'd like to try another computer. At any rate, let me know if this works for you and hopefully it at least points you in the right direction.

Drawing scatter graph using matlibplot.pyplot when points are duplicate

I want to generate a scatter graph using matlibplot.pyplot and a lot of points are duplicate. So when I simply draw a graph use pyplot.scatter method, many points are overdrawn on one dot. In order to consider the number of points on that position, I think I need to set a different point size, like a bigger circle if the spot contains more data points.
Can someone give me a pointer on how to do this? Thanks!
The easiest way to do this is to set a low alpha, and then when the points plot on top of each other they look darker.
import numpy as np
import matplotlib.pyplot as plt
data = [i for i in range(8) for j in range(np.random.randint(10))]
x, y = np.array(data), np.array(data)
plt.scatter(x, y, alpha=.1, s=400)
plt.show()
Of course, you can also change the size of the point or the color directly. To do this, you need to find the number of overlapping points and then set the size (using the s scatter plot parameter) or the color (using c) or both. (But setting alpha is easiest since it doesn't require explicitly counting the overlaps.)

How do I show logarithmically spaced grid lines at all ticks on a log-log plot using Matplotlib?

I'm trying to plot a log-log graph that shows logarithmically spaced grid lines at all of the ticks that you see along the bottom and left hand side of the plot. I've been able to show some gridlines by using matplotlib.pyplot.grid(True), but this is only showing grid lines for me at power of 10 intervals. So as an example, here is what I'm currently getting:
I'd really like something with grid lines looking more like this, where the gridlines aren't all evenly spaced:
How would I go about achieving this in Matplotlib?
Basically, you just need to put in the parameter which="both" in the grid command so that it becomes:
matplotlib.pyplot.grid(True, which="both")
Other options for which are 'minor' and 'major' which are the major ticks (which are shown in your graph) and the minor ticks which you are missing. If you want solid lines then you can use ls="-" as a parameter to grid() as well.
Here is an example for kicks:
import numpy as np
from matplotlib import pyplot as plt
x = np.arange(0, 100, .5)
y = 2 * x**3
plt.loglog(x, y)
plt.grid(True, which="both", ls="-")
plt.show()
which generates:
More details on the Matplotlib Docs
As #Bryce says, in older version of matplotlib correct kwarg is which=majorminor. I think that solid lines with a lighter color can be better than the dotted lines.
plt.grid(True, which="majorminor", ls="-", color='0.65')
Note that in the latest version of matplotlib this argument is replaced by 'both'.
plt.grid(True, which="both", ls="-", color='0.65')

Resources