python-ternary icon indicating copy to clipboard operation
python-ternary copied to clipboard

Scatter plot colorbar and normalization

Open Alejobep opened this issue 6 years ago • 6 comments

Hi. Thanks for developing this. This has been a life-saver. I just had a couple of questions that may or may not be related to python-ternary. I am making some scatter plots. I have a table with 3 parameters that add up to 100. I have also a 4th parameter and was planning to color the markers with a color depending on the value.

What I did not manage to see is to get the colorbar displayed (I set the boolean to True).

Also, my 4th parameter cover different orders of magnitude which means I need to log-normalize and set vmin/vmax, do you know how I could do that?

Alejobep avatar Apr 04 '19 21:04 Alejobep

Hi, take a look at #75 for an example on how to color individual points. As for the normalization, you'll need to do that before plotting.

I'm not sure why you don't see a colorbar. Can you post your code?

marcharper avatar Apr 05 '19 23:04 marcharper

Hi,

Thanks for your reply.

I wused one of the examples in github and though I managed to get a colorbar, I am confused about all the kwargs I included since I just copied someone else's code without fully comprehending the meaining of each parameter and whether they were necessary or not.

Why is it necessary to declare cm=, c= and colormap=. If I remove some I miss the colorbar.

Regarding the normalization I used the logarithm because i could not figure out how to do it.

Thanks. Pasting my code below

import ternary
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import random

cm = plt.cm.get_cmap('viridis')


dat=pd.DataFrame(columns=list('XYZV'))

dat['X']=random.sample(range(45),10)
dat['Y']=random.sample(range(45),10)
dat['Z']=100-(dat['X']+dat['Y'])
dat['V']=10**np.random.randint(0,high=10,size=10)/1e5



# sc = plt.scatter(dat.X, dat.Y, c=dat.V, vmin=0, vmax=7, s=35, cmap=cm)



scale=100



fig, tax = ternary.figure(scale=scale)
fig.set_size_inches(10, 9)

points=dat[['X','Y','Z']].values


minv=np.log10(dat.V.min())
maxv=np.log10(dat.V.max())

tax.scatter(points,s=60,vmin=minv,vmax=maxv,colormap=plt.cm.viridis,colorbar=True,c=np.log10(dat['V'].values),cmap=plt.cm.viridis)


# Decoration.
tax.boundary(linewidth=1)
tax.gridlines(multiple=10, color="gray")
tax.ticks(axis='lbr', linewidth=1, multiple=20)
tax.get_axes().axis('off')

Alejobep avatar Apr 08 '19 19:04 Alejobep

Why is it necessary to declare cm=, c= and colormap=.

It's probably just an oversight because cm is passed through to matplotlib. You need c for the colors, colormap for the spectrum, and colorbar=True to show the side colorbar, but I can probably make it so that just one of cm and colormap is required.

marcharper avatar Apr 10 '19 00:04 marcharper

Thanks a lot,

I have reworked my code and managed to do what I intended. Since my coloring parameter varies in several orders of magnitude, I decided to plot the logarithm 10 of such parameter.

One reason is because it is easier to look at the colors. But another reason is that even if I manage to normalize the colormap to logarithmic scale, I am not able to have the colorbar in logarithmic scale.

I have pasted the new code. On the left side I am plotting the logarithm of the values, and on the right the values with a log-normalized colormap. In that way you see that the ternary plot are plotting the same things. Nevertheless I still do not figure out how to make the colorbar in the correct scale.


import ternary
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import random
import matplotlib.colors as colors

cm = plt.cm.get_cmap('viridis')


group=pd.DataFrame(columns=list('XYZV'))

size=4

group['X']=random.sample(range(45),size)
group['Y']=random.sample(range(45),size)
group['Z']=100-(group['X']+group['Y'])
group['V']=10**np.random.randint(0,high=5,size=size)/1e5



# sc = plt.scatter(dat.X, dat.Y, c=dat.V, vmin=0, vmax=7, s=35, cmap=cm)


name_dic={'almenningen2017':'Almenningen et al. (2017)','almenningen2016':'Almenningen et al. (2016)'}




scale=100

fig,ax=plt.subplots(ncols=2)
tax = ternary.TernaryAxesSubplot(ax=ax[0],scale=scale)
tax2 = ternary.TernaryAxesSubplot(ax=ax[1],scale=scale)
fig.set_size_inches(15, 6)
# fig2.set_size_inches(8, 6)
points=group[['X','Y','Z']].values


norm=colors.LogNorm(vmin=1e-5,vmax=1e-0)


log_c=np.log10(group['V'].values)
c=group['V'].values

cb_kwargs = {"shrink" : 0.6,
         "pad" : 0.05,
         "aspect" : 30}


tax.scatter(points,c=log_c,s=60,
            vmin=-5,vmax=0,colorbar=True,colormap='jet',cbarlabel='$log10 (Parameter)$',
            cb_kwargs=cb_kwargs,zorder=3,cmap='jet')


tax2.scatter(points,c=c,s=60,
            vmin=1e-5,vmax=1e0,colorbar=True,colormap='jet',cbarlabel='$Parameter$',
            cb_kwargs=cb_kwargs,zorder=3,cmap='jet',norm=norm)



# Axis labels. (See below for corner labels.)
fontsize = 10
offset = 0.08
tax.left_axis_label("X", fontsize=fontsize, offset=offset)
tax.right_axis_label("Y", fontsize=fontsize, offset=offset)
tax.bottom_axis_label("Z", fontsize=fontsize, offset=-offset)
tax.set_title('Example', fontsize=14)


# Decoration.
tax.boundary(linewidth=1)
tax.gridlines(multiple=10, color="gray")
tax.ticks(axis='lbr', linewidth=1, multiple=20)
tax.get_axes().axis('off')


# Axis labels. (See below for corner labels.)
tax2.left_axis_label("X", fontsize=fontsize, offset=offset)
tax2.right_axis_label("Y", fontsize=fontsize, offset=offset)
tax2.bottom_axis_label("Z", fontsize=fontsize, offset=-offset)
tax2.set_title('Example', fontsize=14)


# Decoration.
tax2.boundary(linewidth=1)
tax2.gridlines(multiple=10, color="gray")
tax2.ticks(axis='lbr', linewidth=1, multiple=20)
tax2.get_axes().axis('off')


Alejobep avatar Apr 10 '19 13:04 Alejobep

Thanks for the report. The reason is that ternary does a bit of a hack to get the colorbar on the plot and doesn't expect a norm to be passed in. However it can probably look for one in the keyword args so that option 2 works as you'd expect.

marcharper avatar Apr 11 '19 00:04 marcharper

Thanks for this issue. It help me solve my plotting issue of a scatter with colors and a colorbar.

I now understand that we need having both: cmap = 'jet' (for matplotlib to do its job of coloring the scatter dots) colormap= 'jet' (for ternary's hack to place the colorbar with the right color)

I had only colormap, and was wondering why my dots where not getting the right colors!

ntropy-esa avatar Dec 02 '22 15:12 ntropy-esa