How to create own cmap? - python-3.x

I tried the following code, but the matching name is used wrong. How to give a name to the created colour map, please?
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
cMap = []
for value, colour in zip([28800, 29000, 29200, 29400, 29600, 29800, 30000],["darkblue", "mediumblue", "royalblue", "cornflowerblue", "dodgerblue", "skyblue", "paleturquoise"]):
cMap.append((value, colour))
customColourMap = LinearSegmentedColormap.from_list("pri_c", cMap)
x=np.arange(9)
y=[9,2,8,4,5,7,6,8,7]
plt.scatter(x,y, c=y,cmap='pri_c')
plt.xlabel("X")
plt.ylabel("Y")
plt.title("Scatter Plot with Virdis colormap")
plt.colorbar()
plt.show()

If you are working with matplotlib >= 3.5 then you can register the color map with plt.colormaps.register.
If you are using an older version, use plt.register_cmap.
You need to map you color values between 0 and 1 so your code would look something like
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
color_values = np.array([28800, 29000, 29200, 29400, 29600, 29800, 30000])
color_values -= color_values[0]
color_values = color_values / color_values[-1]
color_names = ["darkblue", "mediumblue", "royalblue",
"cornflowerblue", "dodgerblue", "skyblue",
"paleturquoise"]
cMap = list(zip(color_values, color_names))
customColourMap = LinearSegmentedColormap.from_list("pri_c", cMap)
# if mpl >= 3.5
plt.colormaps.register(customColourMap)
# if mpl < 3.5
# plt.register_cmap(cmap=customColourMap)
x=np.arange(9)
y=[9,2,8,4,5,7,6,8,7]
plt.scatter(x,y, c=y,cmap='pri_c')
plt.xlabel("X")
plt.ylabel("Y")
plt.title("Scatter Plot with Virdis colormap")
plt.colorbar()
plt.show()

Related

How to add color and legend by points' label one by one in python?

I want to divide and color points,val_lab(611,3) by their labels,pred_LAB(611,)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = plt.axes(projection = '3d')
ax.set_xlabel('L')
ax.set_ylabel('A')
ax.set_zlabel('B')
for i in range(0, len(val_lab)):
ax.scatter3D(
val_lab[i,0],
val_lab[i,1],
val_lab[i,2],
s = 8,
marker='o',
c = pred_LAB
#cmap = 'rainbow'
)
#ax.legend(*points.legend_elements(), title = 'clusters')
plt.show()
The problem is it shows error,
c' argument has 611 elements, which is not acceptable for use with 'x'
with size 1, 'y' with size 1.
However, if the dataset only have ten points,it can show the figure correctly, I don't know how to solve this problem, besides, how to add legend of this figure?
In your solution you would want to replace c = pred_LAB with c = pred_LAB[i]. But you do not have to use a for loop to plot the data. You can just use the following:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# generate random input data
val_lab = np.random.randint(0,10,(611,3))
pred_LAB = np.random.uniform(0,1, (611,))
# plot data
fig = plt.figure()
ax = plt.axes(projection = '3d')
ax.set_xlabel('L')
ax.set_ylabel('A')
ax.set_zlabel('B')
# create one 3D scatter plot - no for loop
ax.scatter3D(
val_lab[:,0],
val_lab[:,1],
val_lab[:,2],
s = 8,
marker='o',
c = pred_LAB,
cmap = 'rainbow',
label='my points'
)
# add legend
plt.legend()
plt.show()

How to plot 3d rgb histogram of a colored image in python

I want to plot a 3d histogram of a colored image but I can only plot R and G value. what am I doing wrong here? or is there an easier way to do so
import numpy as np
import matplotlib.image as mpimg
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
img = mpimg.imread('model/obj4__0.png')
pixels = img.shape[0]*img.shape[1]
channels = 3
data = np.reshape(img[:, :, :channels], (pixels, channels))
histo_rgb, _ = np.histogramdd(data, bins=256)
histo_rg = np.sum(histo_rgb, 2)
levels = np.arange(256)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for g in levels:
ax.bar(levels, histo_rg[:, g], zs=g, zdir='y', color='r')
ax.set_xlabel('Red')
ax.set_ylabel('Green')
ax.set_zlabel('Number of pixels')
plt.show()
If I understand your question well, I have the same issue, and found this: https://www.bogotobogo.com/python/OpenCV_Python/python_opencv3_image_histogram_calcHist.php
Here is the code for your question:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('images/GoldenGateSunset.png', -1)
cv2.imshow('GoldenGate',img)
color = ('b','g','r')
for channel,col in enumerate(color):
histr = cv2.calcHist([img],[channel],None,[256],[0,256])
plt.plot(histr,color = col)
plt.xlim([0,256])
plt.title('Histogram for color scale picture')
plt.show()
while True:
k = cv2.waitKey(0) & 0xFF
if k == 27: break # ESC key to exit
cv2.destroyAllWindows()
Note that this use cv2 functions but you can convert it to works with Numpy.
I will try to figure out with numpy and give you an update.

Colorbar shows auto ticks in addition to the one I specify

I'm trying to add my own ticks to my colorbar. However, in addition to the ticks that I specify matplotlib continues to print its own ticks.
Minimal example:
import numpy as np
import matplotlib.cm as cmx
import matplotlib.colors as colors
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.gridspec as gridspec
from mpl_toolkits.axes_grid1 import ImageGrid
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig, ax = plt.subplots()
data = np.linspace(-5, 5, 100)
ax.plot(data)
cm = plt.get_cmap('viridis')
cNorm = colors.LogNorm(vmin=1, vmax=10)
divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad=0.05)
cbar = mpl.colorbar.ColorbarBase(
cax, cmap=cm, norm=cNorm, orientation='vertical')
cbar.set_ticks([1,3,10])
cbar.set_ticklabels(["one", "three", "ten"])
cbar.set_label("awesome cbar")
fig.savefig("test.png", dpi=300)
plt.show()
Output with Matplotlib 3.2.0: Output
I only want the ticks that I specified ("one", "three", "ten").

Implementing ipywidget slider for time

I am trying to create a slider for time in Jupyter Notebook using ipywidgets. I would like to take the tabulated experimental data (see figure below) and control the value bounds with the help of a slider. The graph should be a force-displacement graph, evolving in time:
This is my python code:
from ipywidgets import IntSlider, interact, FloatSlider
u = fdat1['C_1_Weg_R4[mm]'].values
f = fdat1['C_1_Kraft_R4[kN]'].values
t = fdat1['S/No'].values
#interact(t = IntSlider(min = 0, max = max(fdat0['S/No'].values)))
def aa_(t):
plt.plot(f[t],u[t])
plt.grid()
plt.xlabel("force [kN]")
plt.ylabel("displacement [mm]")
plt.title("Load-displacement curve for \nexperiment")
fdat1 is the name of the tabulated data. I have also considered using "C_1_Zeit[s]" column as my slider values, but these are not integer values.
The problem is that nothing gets plotted, but the slider works and the graph changes scale.
I have been searching online for some time now and would really appreciate some help.
Thank you in advance!
Edit:
from ipywidgets import IntSlider, interact, FloatSlider
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.DataFrame.from_records(
[np.linspace(0,30, num=30), np.linspace(0,20, num=30), ]).T
df.columns=['A', 'B']
#interact(t = IntSlider(min = 0, max = 21))
def aa_(t):
plt.scatter(df['A'], df['B'])
plt.grid()
plt.xlabel("force [kN]")
plt.ylabel("displacement [mm]")
plt.title("Load-displacement curve for \nexperiment")
plt.xlim(0, 30)
plt.ylim(0, 30)
Inside your plotting function, create a slice of your results dataframe that slices based on the slider value.
from ipywidgets import IntSlider, interact, FloatSlider
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
results = pd.DataFrame.from_records(
[np.linspace(0,30, num=30), np.linspace(0,20, num=30), ]).T
results.columns=['A', 'B']
#interact(t = IntSlider(min = 0, max = 21))
def aa_(t):
df = results.iloc[:t] # make the slice here
plt.scatter(df['A'], df['B'])
plt.grid()
plt.xlabel("force [kN]")
plt.ylabel("displacement [mm]")
plt.title("Load-displacement curve for \nexperiment")
plt.xlim(0, 30)
plt.ylim(0, 30)
So, basically, this should have been the correct code:
from ipywidgets import IntSlider, interact, FloatSlider
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
u = fdat1['C_1_Weg_R4[mm]'].values #loads displacement values from fdat1
f = fdat1['C_1_Kraft_R4[kN]'].values #loads force values from fdat1
df = pd.DataFrame.from_dict([u,f]).T #creates a dataframe
df.columns=['A', 'B']
#interact(t = IntSlider(min = 0, max = df.shape[0])) #interactive scatterplot with a slider for time
def scatterplot_(t):
plt.scatter(df.loc[0:t,'A'], df.loc[0:t,'B'])
plt.grid()
plt.xlabel("force [kN]")
plt.ylabel("displacement [mm]")
plt.title("Load-displacement curve for \nexperiment")
plt.xlim(-5, 5)
plt.ylim(-25, 25)

Seaborn Heatmap Colorbar Label as Percentage

Given this heat map:
import numpy as np; np.random.seed(0)
import seaborn as sns; sns.set()
uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data)
How would I go about making the color bar values display in percent format?
Also, what if I just wanted to show the first and last values on the color bar?
Thanks in advance!
iterating on the solution of #mwaskom, without creating the colorbar yourself:
import numpy as np
import seaborn as sns
data = np.random.rand(8, 12)
ax = sns.heatmap(data, vmin=0, vmax=1)
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, .2, .75, 1])
cbar.set_ticklabels(['low', '20%', '75%', '100%'])
Well, I had a similar problem and figured out how to properly set a formatter. Your example would become something like:
import numpy as np; np.random.seed(0)
import seaborn as sns; sns.set()
uniform_data = np.random.rand(10, 12)
uniform_data = 100 * uniform_data
sns.heatmap(uniform_data,
cbar_kws={'format': '%.0f%%'})
So, what you have to do is to pass an old-style string formatter to add percentages to colorbar labels. Not exactly what I would name self-evident, but works...
To show only the first and last, then you add vmax, vmin and an extra parameter to cbar_kws:
sns.heatmap(uniform_data,
cbar_kws={'format': '%.0f%%', 'ticks': [0, 100]},
vmax=100,
vmin=0)
You should get the colour bar object and then get the relevant axis object:
import matplotlib.pyplot as plt
from matplotlib.ticker import PercentFormatter
fig, ax = plt.subplots()
sns.heatmap(df, ax=ax, cbar_kws={'label': 'My Label'})
cbar = ax.collections[0].colorbar
cbar.ax.yaxis.set_major_formatter(PercentFormatter(1, 0))
You need to be able to access the colorbar object. It might be buried in the figure object somewhere, but I couldn't find it, so the easy thing to do is just to make it yourself:
import numpy as np; np.random.seed(0)
import seaborn as sns; sns.set()
uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data, cbar=False, vmin=0, vmax=1)
cbar = ax.figure.colorbar(ax.collections[0])
cbar.set_ticks([0, 1])
cbar.set_ticklabels(["0%", "100%"])

Resources