Niriel
Niriel

Reputation: 2695

How do I change the color of the axes of a matplotlib 3D plot?

I have set

import matplotlib as mpl
AXES_COLOR = '#333333'
mpl.rc('axes', edgecolor=AXES_COLOR, labelcolor=AXES_COLOR, grid=True)
mpl.rc('xtick', color=AXES_COLOR)
mpl.rc('ytick', color=AXES_COLOR)
mpl.rc('grid', color=AXES_COLOR)

The color of the axes labels and the ticks are properly set both in 2D and in 3D. However, the edgecolor doesn't apply to 3D axes and they remain black. Likewise, the grid isn't affected.

I think figured out how to access the individual axes of a 3D plot:

import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d # Needed for 3d projection.
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.w_zaxis # <- the z axis

The documentation mentions a property that we can use until the developers have finished refactoring their 3D code:

import pprint
pprint.pprint(ax.w_xaxis._AXINFO)

{'x': {'color': (0.95, 0.95, 0.95, 0.5),
       'i': 0,
       'juggled': (1, 0, 2),
       'tickdir': 1},
 'y': {'color': (0.9, 0.9, 0.9, 0.5),
       'i': 1,
       'juggled': (0, 1, 2),
       'tickdir': 0},
 'z': {'color': (0.925, 0.925, 0.925, 0.5),
       'i': 2,
       'juggled': (0, 2, 1),
       'tickdir': 0}}

However, the color parameter changes the color of the background of the axes planes (between the wired of the grid), not the color of the edges of these planes.

Am I digging too deep ?

Upvotes: 2

Views: 7332

Answers (3)

Jānis Lazovskis
Jānis Lazovskis

Reputation: 198

For posterity, here is a method to change each individual axis color, the grid color, the tick color and the tick label colors.

import numpy as np
from matplotlib import pyplot as plt

# Grid color (here in RGBA, also named colors as strings work)
plt.rcParams['grid.color'] = (0.5, 0.5, 0.5, 0.2)

# Figure
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.scatter(np.random.rand(10),np.random.rand(10),np.random.rand(10))

# Axes colors
ax.xaxis.line.set_color('C1')
ax.yaxis.line.set_color('C2')
ax.zaxis.line.set_color('C3')

# Tick colors
ax.tick_params(axis='x', colors='C4')
ax.tick_params(axis='y', colors='C5')
ax.tick_params(axis='z', colors='C6')

# Label colors
for i,tick in enumerate(ax.get_xticklabels()):
    tick.set_color(f"C{i}") 
for i,tick in enumerate(ax.get_yticklabels()):
    tick.set_color(f"C{i+1}") 
for i,tick in enumerate(ax.get_zticklabels()):
    tick.set_color(f"C{i+2}")     
    
# Show
plt.show()

A 3d scatter plot made in matplotlib demonstrating different styling options

I'm not sure if it's possible to change each individual tick color, the method from 2d plots (for example here) does not work. Answers taken from here for axis color, here for grid color, here for tick color, here for tick label color.

Upvotes: 0

Vadym
Vadym

Reputation: 59

Instead of changing axis3d.py try this: ax.w_xaxis.line.set_color("red")

Upvotes: 5

Niriel
Niriel

Reputation: 2695

Turns out it's impossible since these values are hard-coded. This archived email from the matplotlib-users mailing list helped me. Here's the relevant part:

Unfortunately, you have stumbled upon one of the ugliness of the mplot3d implementation. I am hoping to have more control available for the next release. But right now, there is no way to turn off the axes spines (because they aren't implemented as spines). If you really want to dig into the source code, you could change the color argument to the Line2D call in the init3d() method in matplotlib/lib/mpl_toolkits/axis3d.py

Although this answer was addressing another concern, it sent me to the direction of axis3d.py. I found it in /usr/lib/pymodules/python2.7/mpl_toolkits/mplot3d. I made a backup of the original axis3d.py and I moved axis3d.pyc away.

Since the code is pretty short and fairly well written it didn't take long to locate the two lines I had to change.

  • To change the color of the edges of the individual axes, I modified the self.line=... in __init__: just replace color=(0, 0, 0, 1) by color=(1, 0, 0, 1) for a horribly flashy red. Components of the tuple are red, green, blue, alpha, all floats from 0 to 1.
  • To change the color of the grid, I modified the draw method. I replaced the color self.gridlines.set_color([(0.9,0.9,0.9,1)] * len(lines)) by something of my choosing.

And that's it, it just works. Not the most convenient, but it's not more work than editing a rc configuration file.

I did not recreate a .pyc file. It does not recreate itself because I do not run my python code as root. I don't mind the extra milliseconds that python needs to recompile the .py each time.

Upvotes: 2

Related Questions