Dman - 1 year ago 52

Python Question

I am trying to make a color map that 'favors' lower values, i.e. it takes longer to get out of the darker color to get to the light color. At the moment I am using this as the colormap:

`cmap = clr.LinearSegmentedColormap.from_list('custom blue', ['#ffff00','#002266'], N=256)`

I am plotting this around a cylinder to see the effect (see code for cylinder at the end of the post), this is what happens when you run the code:

As you can see this is very 'linear'. The color starts changing about halfway along the cylinder. Is there a way to increase the threshold for when the colors start to change rapidly? I.e. I want only very high numbers to have the brightest level of yellow. Thanks.

`from matplotlib import cm`

from matplotlib import pyplot as plt

from mpl_toolkits.mplot3d import Axes3D

from scipy.linalg import norm

from mpl_toolkits.mplot3d.art3d import Poly3DCollection

import numpy as np

import math

import mpl_toolkits.mplot3d.art3d as art3d

import matplotlib.colors as clr

fig = plt.figure()

ax = fig.add_subplot(111, projection='3d')

origin = [0,0,0]

#radius = R

p0 = np.array(origin)

p1 = np.array([8, 8, 8])

origin = np.array(origin)

R = 1

#vector in direction of axis

v = p1 - p0

#find magnitude of vector

mag = norm(v)

#unit vector in direction of axis

v = v / mag

#make some vector not in the same direction as v

not_v = np.array([1, 0, 0])

if (v == not_v).all():

not_v = np.array([0, 1, 0])

#make vector perpendicular to v

n1 = np.cross(v, not_v)

#normalize n1

n1 /= norm(n1)

#make unit vector perpendicular to v and n1

n2 = np.cross(v, n1)

#surface ranges over t from 0 to length of axis and 0 to 2*pi

t = np.linspace(0, mag, 600)

theta = np.linspace(0, 2 * np.pi, 100)

#use meshgrid to make 2d arrays

t, theta = np.meshgrid(t, theta)

#generate coordinates for surface

X, Y, Z = [p0[i] + v[i] * t + R * np.sin(theta) * n1[i] + R * np.cos(theta) * n2[i] for i in [0, 1, 2]]

#THIS IS WHERE THE COLOR MAP IS

cmap = clr.LinearSegmentedColormap.from_list('custom blue', ['#ffff00','#002266'], N=256)

col1 = cmap(np.linspace(0,1,600)) # linear gradient along the t-axis

col1 = np.repeat(col1[np.newaxis,:, :], 100, axis=0) # expand over the theta- axis

ax.plot_surface(X, Y,Z, facecolors = col1, shade = True,edgecolors = "None", alpha = 0.9, linewidth = 0)

ax.view_init(15,-40)

plt.show()

Answer Source

When making colormaps with `LinearSegmentedColormap.from_list`

, you can supply a list of tuples of the form (value, color) (as opposed to simply a list of colors) where the values correspond to the relative positions of colors. The values must range from `0`

to `1`

so you will have to supply an intermediate color. In your case I might try this,

```
cmap = clr.LinearSegmentedColormap.from_list('custom blue',
[(0, '#ffff00'),
(0.25, '#002266'),
(1, '#002266')], N=256)
```

and tweak color/value until satisfied. Credit goes to http://stackoverflow.com/a/25000108/5285918