Setting independent colorbar scale to y-values of plot using matplotlib and proplot - matplotlib

I have a series of histograms that I plot over the top of each other using a for loop:
import matplotlib as plt
import proplot as pplt
cmap = colormap
fig = pplt.figure(figsize=(12, 10), dpi=300)
jj = [ 4, 3, 2, 1, 0]
for j in jj:
plt.fill_between(p[:,j], s[:, j], y2=0, alpha = 0.6, color = colormap[:,4-j], edgecolor=[0,0,0], linewidth=1.5)
The colormap in question is a manually specified list of RGB triplets (from Fabio Crameri's 'lajolla' map):
0.64566 0.823453 0.895061 0.924676 0.957142
0.277907 0.386042 0.526882 0.657688 0.803006
0.259453 0.301045 0.317257 0.331596 0.408285
Each color corresponds to data recorded under different conditions. I want the colorbar to have manually specified ticks corresponding to this variable (e.g. c = 30, 35, 40, 45, 50), but I can't seem to configure the colormap to not just pull the indices of the cmap matrix (0, 1, 2, 3, 4) as the values of the mapped variable. Trying to set the ticks outside of this range just result in them not being shown.
cbar = fig.colorbar(np.transpose(cmap))
cbar.set_ticks([30, 35, 40, 45, 50])
cbar.set_ticklabels([30, 35, 40, 45, 50])
Any idea how I can resolve this?
Tried shifting indices of colormap but this doesn't seem to work.
Trying to get the colorbar with ticks corresponding to the '30, 35, 40, 45, 50' values quoted above.

Related

Place Colorbar to One Side of GeoAxes Plot

I am generating a irregular gridded plot with a globe projection and am utilizing both xarray and CartoPy to achieve this. The following minimal code produces the first image below, note that I am leaving out calling specific packages and specifically defined cmap/norm options, as they remain outside the bounds of my question:
file = '/path/to/data/griddeddata.tif'
da = rxr.open_rasterio(file)
da = ((da * 1.8) + 32)
ny, nx = len(da['y']), len(da['x'])
x, y = np.meshgrid(da['x'], da['y'])
fig = plt.figure(figsize=(14,8))
ax = plt.subplot(projection=crs.LambertConformal())
ax.set_extent([-75.500000, -72.000000, 40.500000, 43.000000], crs=crs.LambertConformal())
im = ax.pcolormesh(x, y, da.variable.data[0], cmap=cmap, norm=norm)
plt.gcf().set_size_inches((14, 8))
plt.gca().set_position([0, 0, 1, 1])
When I add the following code plt.colorbar(im, ax=ax, pad=0.01, ticks=[-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120], aspect=40), I get a colorbar that appears inside the map plot itself, whereas I would like this colorbar to be oriented vertically to the right.
I suspect that this has to do with the sharing of a georeferenced axis (map plot) and an unreferenced colorbar axis, though I am unsure how to correct the issue. What additional steps are recommended to take in order to achieve the desired result? Thanks!
I would suggest you create additonal axis besides the plot for the colorbar.
The following code can be adjusted to your need.
Define the position
cbar_pos = [0.90, 0.30, 0.03, 0.45] #axis for colorbar left, bottom, width, height
Create the axis
cbar_ax = fig.add_axes(cbar_pos)
cbar_ax.get_xaxis().set_visible(False)
cbar_ax.yaxis.set_ticks_position('right')
cbar_ax.set_yticklabels([])
cbar_ax.tick_params(size=0)`
Pass the cbar_ax into your colorbar function
plt.colorbar(im, cax=cbar_ax, pad=0.01, ticks=[-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120], aspect=40)

matplotlib asymmetric errorbar showing wrong information

I am trying to plot a grouped barplot with asymmetrical errobars. When the error bars a symmetrical, it's producing the correct chart. However, for the asymmetric version, the length of the error bar is wrong.
Here is a minimally reproducible code:
# test with code from documentation
men_means, men_std = (20, 35, 30, 35, 27), (2, 3, 4, 1, 2)
women_means, women_std = (25, 32, 34, 20, 25), (3, 5, 2, 3, 3)
# dummy dataframe similar to what I will be using
avg = [20, 35, 30, 35, 27]
men_std_l = [19,33,28,34,25]
men_std_u = [22,37,31,39,29]
df = pd.DataFrame({'avg' :avg, 'low':men_std_l, 'high':men_std_u})
ind = np.arange(df.shape[0]) # the x locations for the groups
width = 0.35 # the width of the bars
fig, ax = plt.subplots()
rects1 = ax.bar(ind - width/2, df['avg'], width, yerr=[df['low'].values,df['high'].values], label='Men')
rects2 = ax.bar(ind + width/2, women_means, width, yerr=women_std,label='Women')
# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Scores')
ax.set_title('error bar is wrong for asymmetrical, correct otherwise')
ax.legend()
fig.tight_layout()
plt.show()
I have tried the solutions from Asymmetrical errorbar with pandas (getting ValueError: In safezip, len(args[0])=5 but len(args1)=1) and plotting asymmetric errorbars using matplotlib (getting TypeError: Cannot cast array data from dtype('< U1') to dtype('float64') according to the rule 'safe')
Any help is much appreciated.
Answering my own question as I could not understand from the documentation what those lower and upper bounds of errors were. In the hindsight, it should have been clearer if I were not so used to with ggplot in r.
The matplotlib version of asymmetrical errorbar requires the the values to add and subtract from the height of the bars. It does not want the user to provide the upper and lower values, rather the numbers that should be added and subtracted. Therefore, I needed the following:
xel = df['avg'].values - df['low'].values
xeh = df['high'].values - df['avg'].values

Plotting points with different colors using corresponding list of labels

I have the following matrix and vector of labels:
The idea is to plot the points within points according to the labels (1 and -1) in y. assume the calculation of the function true_label works.
M = [5, 10, 15, 25, 70]
for m in M:
points = np.random.multivariate_normal(np.zeros(2), np.eye(2), m)
true_labels = true_label(points)
y = np.where(true_labels, 1, -1)
fig, ax = plt.subplots(1, 1)
colors = ['green', 'red', 'blue']
plt.plot(points, c=y, cmap=matplotlib.colors.ListedColormap(colors))
# red is 1, blue is -1
plt.show()
However I can't seem to get this to work..
AttributeError: Unknown property cmap
is what I keep getting. I've updated matplotlib so I dont really understand why this doesnt work. Any advice on how to get this done easily?

Get desired wspace and subplots appropriately sized?

I'm trying to make a plot with one panel up top (colspan = 2) and two plots below, with a controlled amount of space between them. I'd like the bounds of the plots to be in alignment. Here's what I'm starting with:
import cartopy
from matplotlib import pyplot
from matplotlib.gridspec import GridSpec
gs = GridSpec(2, 2, height_ratios=[2, 1], hspace=0, wspace=0)
ax0 = pyplot.subplot(gs[0, :], projection=cartopy.crs.LambertConformal())
ax0.add_feature(cartopy.feature.COASTLINE)
ax0.set_extent([-120, -75, 20, 52], cartopy.crs.Geodetic())
ax1 = pyplot.subplot(gs[1, 0], projection=cartopy.crs.LambertConformal())
ax1.add_feature(cartopy.feature.COASTLINE)
ax1.set_extent([-90, -75, 20, 30], cartopy.crs.Geodetic())
ax2 = pyplot.subplot(gs[1, 1], projection=cartopy.crs.LambertConformal())
ax2.add_feature(cartopy.feature.COASTLINE)
ax2.set_extent([-90, -75, 20, 30], cartopy.crs.Geodetic())
pyplot.show()
First problem is that the wspace=0 parameter doesn't take.
Second problem is (at least this is my guess on how to proceed) calculating a height ratio that will make the width of the upper subplot equal the combined width of the lower subplots (plus any wspace).

Correlate a Radial Distance to a 2D mgrid on python

I have two 1D arrays. One containing temperature and the other radial distance (for each respective temperature). I want to produce a heat map type plot using this information.
Here is where I'm running into issues:
1. If I create a 2d numpy grid, how do I correlate a radial distance to each one? Say the radial distance is 5 units, how to I find all grid squares that are 5 units from the center?
2. Then how to I correlate to each temperature its respective set of grid points. So say the temperate is 20 degrees at radial distance 5, how do I express this as it is 20 degrees at the following set of x,y grid squares?
Thanks for any assistance.
meshgrid is your friend here. First set up the grid plus x and y coordinate grids (you will have two 5 by 5 arrays):
import numpy as np
x, y = np.meshgrid(np.arange(-2, 3), np.arange(-2, 3))
heatmap = 0 * x # easy way to get shape right
Now, fake some data:
r = np.array((0, 0.5, 1.5, 2.5)) # Your radial distance
T = np.array((100, 90, 70, 40)) # Your temperature at distance
Overlay the data from the inside outward, starting from middle (assuming r is monotonically increasing):
r2 = r**2
xy2 = x**2 + y**2
for ii in range(r.size):
heatmap[np.where(xy2 >= r2[ii])] = T[ii]
That's it. Here's the resulting heatmap:
array([[ 40, 70, 70, 70, 40],
[ 70, 90, 90, 90, 70],
[ 70, 90, 100, 90, 70],
[ 70, 90, 90, 90, 70],
[ 40, 70, 70, 70, 40]])