user6972
user6972

Reputation: 911

How to keep color map scale constant and plot a colorbar

I have been working on an example plot where lat/lon data are plotted and colored based on the speed. I'd like the speed color map to be constant but each time I plot new data on it, it seems to rescale the min and max of the colormap to fit the data.

For example, I'd like the colors to be mapped between 0 and 10 (like shown on the colorbar). However it seems to be rescaling the color map to the data every time.

import numpy as np
import matplotlib.pyplot as plt

lon = np.array(
    [-155.05155, -155.05151, -155.0515, -155.05149, -155.05148, -155.05148, -155.05148, -155.05148, -155.05149,
     -155.05151, -155.05153, -155.05155, -155.05158, -155.05159, -155.05162, -155.05164, -155.05166, -155.05168,
     -155.0517, -155.05172, -155.05175, -155.05176, -155.05178, -155.0518, -155.05182, -155.05184, -155.05186,
     -155.05188, -155.0519, -155.05192, -155.05194, -155.05197, -155.05199, -155.05201, -155.05203, -155.05205,
     -155.05207, -155.05208, -155.05211, -155.05213, -155.05215, -155.05217, -155.05219, -155.05221, -155.05223,
     -155.05226, -155.05228, -155.05231, -155.05233, -155.05236, -155.05237, -155.05239, -155.05241, -155.05242,
     -155.05245, -155.05245, -155.05247, -155.05249, -155.05251, -155.05254, -155.05256, -155.05258, -155.0526,
     -155.05262, -155.05263, -155.05265, -155.05268, -155.0527, -155.05272, -155.05275, -155.05277, -155.05279,
     -155.05281, -155.05283, -155.05285, -155.05287, -155.05289, -155.0529, -155.05291, -155.05293, -155.05295,
     -155.05297, -155.05299, -155.05301, -155.05303, -155.05305, -155.05307, -155.05309, -155.05311, -155.05313,
     -155.05314, -155.05316, -155.05318, -155.0532, -155.05321, -155.05323, -155.05325, -155.05326, -155.05328,
     -155.05332])
lat = np.array(
    [19.73198, 19.73198, 19.73199, 19.73201, 19.73203, 19.73202, 19.73202, 19.73204, 19.73205, 19.73206, 19.73206,
     19.73207, 19.73208, 19.73209, 19.73211, 19.73212, 19.73214, 19.73216, 19.73218, 19.7322, 19.73222, 19.73223,
     19.73225, 19.73226, 19.73227, 19.73229, 19.7323, 19.73232, 19.73233, 19.73234, 19.73235, 19.73237, 19.73238,
     19.7324, 19.73241, 19.73243, 19.73244, 19.73246, 19.73247, 19.73248, 19.7325, 19.73251, 19.73253, 19.73254,
     19.73256, 19.73257, 19.73258, 19.73259, 19.7326, 19.73263, 19.73264, 19.73266, 19.73267, 19.73268, 19.7327,
     19.73271, 19.73272, 19.73273, 19.73275, 19.73277, 19.73278, 19.73279, 19.73281, 19.73282, 19.73284, 19.73286,
     19.73286, 19.73288, 19.73289, 19.7329, 19.73291, 19.73293, 19.73294, 19.73296, 19.73297, 19.73299, 19.73302,
     19.73304, 19.73306, 19.73308, 19.73309, 19.73311, 19.73313, 19.73315, 19.73317, 19.73317, 19.73319, 19.7332,
     19.73322, 19.73323, 19.73325, 19.73326, 19.73327, 19.73329, 19.7333, 19.73331, 19.73332, 19.73333, 19.73335,
     19.73336])
speed = np.array([0, 3.967838351598377, 2.583851230112236, 2.909749382960718, 2.331208342745013, 1.2474565941885627,
                  1.718509515902599, 2.130757007783651, 2.1978242809567643, 2.4448938949237133, 2.3436767093957807,
                  2.848759575381383, 2.5766473883863124, 2.8348240641628335, 3.106935785732237, 2.710393576350728,
                  3.1318924699618096, 3.2117162403094186, 3.1318921186853235, 3.4486097786406074, 2.8348227783071542,
                  2.438280995718295, 2.8116095118419597, 2.571151376967635, 2.8116093167427856, 2.710391831502253,
                  2.710391728938647, 2.7103915222111485, 2.469933323878424, 2.4699332140890724, 3.1069324755437155,
                  3.106932198270919, 2.710390905821824, 2.710390701811524, 2.710390599103662, 2.710390392282518,
                  2.412473081387807, 2.892512135241831, 2.848753560195423, 2.790213897128215, 2.891431079508014,
                  2.8914309834469867, 2.790213394604523, 2.7902132941269615, 3.270251940268593, 2.949969471066445,
                  2.9499693266059097, 2.8487517553160426, 3.682304028129132, 3.7558001156185816, 2.863708779704488,
                  2.891429545784412, 2.1978198142415475, 2.8348182266776614, 2.670028369758699, 2.033029885758895,
                  2.469928992173159, 2.710387312334322, 3.5125563040959307, 3.27209759442833, 2.4699283256332825,
                  2.7103866960769962, 2.710386489344829, 2.5103517409878737, 2.9318517610212034, 3.1747757400248457,
                  3.0949516374373167, 2.8116033283715955, 2.9499648048602216, 2.848747092331349, 2.7902095754563563,
                  3.1559179547967515, 3.1559178689291647, 2.891426668096206, 2.891426572169741, 3.573651757195292,
                  3.195911973684913, 2.4562297465190186, 2.833969127195823, 2.7902078684061324, 2.7103836137458464,
                  3.131883978356872, 3.1318838043110544, 3.131883629382897, 2.7651643954244483, 2.7651643943197355,
                  2.891424460722922, 2.811600188197874, 3.4372310555788212, 3.1393162110320247, 2.513684994246323,
                  2.469922991269612, 2.710381765956584, 2.43827424877333, 2.0965975265618053, 2.4699224357346794,
                  2.1978151300488475, 2.7367352119845485, 4.0459052923177925, 3.8858032217291467])

max_speed = 10.
color = [str(item / max_speed) for item in speed]

fig = plt.figure(facecolor='0.05')
ax = plt.Axes(fig, [0., 0., 1., 1.], )

ax.set_axis_off()
fig.add_axes(ax)
sm = plt.cm.ScalarMappable(cmap='plasma', norm=plt.Normalize(vmin=0, vmax=max_speed))
sm._A = []
color_bar = plt.colorbar(sm)
cbytick_obj = plt.getp(color_bar.ax.axes, 'yticklabels')
plt.setp(cbytick_obj, color='w')

plt.scatter(lon, lat, s=2, c=color, cmap='plasma')
plt.show()

Produces a plot like the following:

example plot

Note the data values are never over the value of 4.1, yet it has rescaled the colormap to fit the data. How do I set the limits for the color mapping? And as a bonus, why is the color bar ignoring the plot window's boundary and showing up so large?

Upvotes: 1

Views: 2591

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339062

To have the same normalization in the scatter plot than you have in the colorbar, use the same normalization in the scatter plot than you have in the colorbar.

mynorm = plt.Normalize(vmin=0, vmax=10)
sm = plt.cm.ScalarMappable(cmap='plasma', norm=mynorm)
# ...
plt.scatter(lon, lat, s=2, c=color, cmap='plasma', norm=mynorm)

(This seems a bit too obvious to ask a question about, but it also seems to be the solution you're after here.)

As to why the colorbar is so large, again pretty obviously you set it so large yourself:

ax = plt.Axes(fig, [0., 0., 1., 1.]) creates an axes which is exactly as heigh as the figure. The colorbar is as heigh as the axes.
You may either choose to make the axes smaller or to create a smaller colorbar by shrinking it,

plt.colorbar(sm, shrink=0.8)

Upvotes: 2

Related Questions