Plot showing up black in Bokeh - python

I am trying to plot radar data in bokeh from an hdf5 file. I've stored the data into a 2d array that is 1800*3600. When I try to plot the data using p.image it shows up black with some splotches which i'm assuming is where the data is greater than 0, but it doesn't conform to the palette i've specified. I'm not sure why this is occurring.
f = h5py.File(fname, 'r')
lat = f['Grid']['lat']
lon = f['Grid']['lon']
precip = f['Grid']['precipitationCal']
precip = np.transpose(precip)
d = np.empty((1800,3600))
for (x,y), value in np.ndenumerate(precip):
if value <= 0:
d[x,y]=np.nan
else:
d[x,y]=value
output_file("testimage.html", title="image.py example")
p = figure(x_range = [0, 3600], y_range=[0, 1800])
p.image(image=[d],x=[0],y=[0],dw=[3600], dh=[1800], pallete="Spectral-256")
show(p)

Two things:
First, the argument to pass to p.image is spelled "palette" not "pallete". The default palette is Grey9, which would give you the colormap you have.
Second (and the docs are sort of unclear on this), the palette argument accepts a list containing the colormap as hex values. This can be either an arbitrary list:
palette = ["#8c9494", "#8398a2", "#7c9baa"]
p.image(image=[d],x=[0],y=[0],dw=[360], dh=[180], palette=palette)
or a standard palette from Bokeh
from bokeh.palettes import Spectral6
p.image(image=[d],x=[0],y=[0],dw=[360], dh=[180], palette=Spectral6)
Note:
print(Spectral6)
> ['#3288bd', '#99d594', '#e6f598', '#fee08b', '#fc8d59', '#d53e4f']
https://docs.bokeh.org/en/latest/docs/reference/palettes.html

Related

How to correctly use colormaps for plotly express line mapbox?

I have trouble getting plotly.express.line_mapbox() present the lines with correct colors. The lines have a value 0..100%, which represents the usage of each line. From other SO questions and websites I am approaching it like this:
norm = matplotlib.colors.Normalize(0, 100)
colors = [[norm(0), "green"],[norm(60), "yellow"],[norm(100), "red"]]
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", colors)
Then I specify each color by:
RGBa = cmap(percUsage)
colors.append(f'rgb({int(255 * RGBa[0])}, {int(255 * RGBa[1])}, {int(255 * RGBa[2])})')
Where percUsage = 0..100.
In respect to that, I am building my Dataframe with each lines data and then create the figure.
df = pd.DataFrame(data=dict(name=names, lat=lats, lon=lons, load=loads, color=colors, hover=hoverText))
fig = px.line_mapbox(df, lat='lat', lon='lon', line_group='name', color='color')
But while c.test_colormap(cmap) shows the colors as expected, plotly.express.line_mapbox() behaves totally weird in terms of colors. The screenshot shows a line with the usage value of 9. I do not get, why it prints a blue color, which should not even be in my spectrum of color. Others are colored green or red but in no relation to percUsage. I seem to miss something important here.
Any help is appreciated :)
So i managed to solve my problem and would like to share my findings, in case anyone stumbles on this question. Here you find the docs.
TL;DR and my key takeaways:
Using a discrete color map(dict) with str-keys and hex-colors(str), while the dataframes's(df) "colors" column is filled with the corresponding keys used in discr_map.
from colormap import rgb2hex
import matplotlib.colors
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("gyr", [[0., 'green'], [0.5, 'yellow'], [1.0, 'red']], N=101)
discr_map = {}
for i in range(0, 101, 1):
discr_map.update({"c"+str(i): rgb2hex(int(255 * cmap(i)[0]), int(255 * cmap(i)[1]), int(255 * cmap(i)[2]))})
fig = px.line_mapbox(df, lat='lat', lon='lon', line_group='name', color='color', color_discrete_map=discr_map)
I do not really understand, why the dataframe's colors column does not work with the format rgb(255,100,0). Maybe hex format is needed here, as well - I'll check that out sometime. This was confusing, since other mapboxs can handle rgb format. For that reason it was falling back to its standard color range, which obviously confused me.
color (str or int or Series or array-like) – Either a name of a column in data_frame, or a pandas Series or array_like object. Values from this column or array_like are used to assign color to marks.
Then I looked into the color_discrete_map argument and made that finally work.
color_discrete_map (dict with str keys and str values (default {})) – String values should define valid CSS-colors Used to override color_discrete_sequence to assign a specific colors to marks corresponding with specific values. Keys in color_discrete_map should be values in the column denoted by color. Alternatively, if the values of color are valid colors, the string 'identity' may be passed to cause them to be used directly.
This is how I create the discrete colormap. I think the most important catch here, is to use N=101 (or whatever value range you need) to normalize the spectrum to values ranging from 0..100.
# initialize discrete colormap
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("gyr", [[0., 'green'], [0.5, 'yellow'], [1.0, 'red']], N=101)
discr_map = {}
for i in range(0, 101, 1):
discr_map.update({"c"+str(i): rgb2hex(int(255 * cmap(i)[0]), int(255 * cmap(i)[1]), int(255 * cmap(i)[2]))})
Which is then passed into the figures color_discrete_map argument:
fig = px.line_mapbox(df, lat='lat', lon='lon', line_group='name', color='color', color_discrete_map=discr_map)

How to do calculation on zoomed plot area

I have a time series plot along with a scatter plot on top to indicate some points of the series with certain characteristics. On jupyter notebook I am using %matplotlib notebook to get interaction plot and zoom.
Is it possible to calculate all points
EDIT:
The following code is a dummy example of ploting radnom data and marking with red dots those point where their value is above a certain threshold.
%matplotlib notebook
# generate random data [0, 10]
random_data = np.random.randint(10, size = 20)
# implement rule --> i.e. check which data point is > 3
index = np.where([random_data > 3])[1]
value = np.where([random_data > 3])[0]
# plot data and mark data point where rule applies
plt.plot(random_data)
plt.scatter(index, random_data[index], c = 'r')
This generates the plot below.
Is it possible to to get a result that calculates the red dots every time i zoom in the plot
So after a lot of search I came up with the following solution.
%matplotlib notebook
# generate random data [0, 10]
random_data = np.random.randint(10, size = 20)
# implement rule --> i.e. check which data point is > 3
index = np.where([random_data > 3])[1]
value = np.where([random_data > 3])[0]
# plot data and mark data point where rule applies
fig, ax = plt.subplots(1,1)
ax.plot(random_data)
ax.scatter(index, random_data[index], c = 'r')
global scatter_index
scatter_data = index
def on_xlims_change(axes):
d1, d2 = axes.get_xlim()
number_of_points = index[np.where((index > d1 )& (index < d2))].shape[0]
axes.legend([f'{ number_of_points } numbers of points in area' ])
# use a maplotlib callback to do the calculation
ax.callbacks.connect('xlim_changed', on_xlims_change)
The idea is that you can use a callback to get the new axis limits and filter data based on those limits. Hope

Show "Heat Map" image with alpha values - Matplotlib / Python

I'm trying to plot some data to analyze them.
My data is defined as below:
class Data(object):
def __init__(self, rows=200, cols=300):
"""
The Data constructor
"""
# The data grid
self.cols = cols
self.rows = rows
# The 2D data structure
self.data = numpy.zeros((rows, cols), float)
At first, I had this method:
def generate_data_heat_map(data, x_axis_label, y_axis_label, plot_title, file_path):
plt.figure()
plt.title(plot_title)
fig = plt.imshow(data.data, extent=[0, data.cols, data.rows, 0])
plt.xlabel(x_axis_label)
plt.ylabel(y_axis_label)
plt.colorbar(fig)
plt.savefig(file_path + '.png')
plt.close()
This gives me something as a heat map image (second figure), 'cause I'm passing to it an MxN [luminance (grayscale, float array only)]. And don't know why this doesn't generate a grayscale image, but so far I didn't worry about it 'cause that is the result I wanted.
After some more calculation, I had this method to visualize my data, using the data_property as RGB and data_uncertaity as alpha:
def generate_data_uncertainty_heat_map(data_property, data_uncertainty, x_axis_label, y_axis_label, plot_title, file_path):
plt.figure()
uncertainty = numpy.zeros((data_property.rows, data_property.cols, 4))
uncertainty[..., :3] = data_property.data[..., numpy.newaxis]
uncertainty[..., 3] = data_uncertainty.data
plt.title(plot_title)
fig = plt.imshow(uncertainty.data, extent=[0, data_property.cols, data_property.rows, 0])
plt.xlabel(x_axis_label)
plt.ylabel(y_axis_label)
plt.colorbar(fig)
plt.savefig(file_path + '.png')
plt.close()
But, of course, this give me a grayscale image with alpha values, since I am repeating the same values for R, G and B. But what I really would like to have was the first method result (colored) with some alpha values calculated as uncertainty about the data.
I've noticed that my color bar has nothing about my data too (it's in RGB, I can't use it to analyze my data)
I don't know how to achieve the result that I want, which is to a have a "heat map" plot with merged the alpha values defined with my uncertainty_data and a color bar representing this uncertainty. Like merging this two images above:
This as my color:
This as my alpha:
With the conversion presented by #BlazBratanic, I guess I can see a little bit of color (not sure about it), but its far of what I was expecting.
All my values is between 0.0 and 1.0.
Thank you in advance.
Use Matplotlib cm module to map your grayscale to color values. If i remember correctly "jet" is the default colormap. So you would do something like:
uncertainty = plt.cm.jet(data_property.data)
uncertainty[..., 3] = data_uncertainty.data

Coloring a vtkUnstructuredGrid by vector magnitude

I'm trying to display an EnSight file in a Qt/VTK application. More precisely, I want to display a specific EnSight part and color it by the magnitude of one of the vector variables. As far as I understand, the output of the VTK reader is a vtkMultiBlockDataSet, with one block per part. Each block is a vtkUnstructuredGrid and the variables are specific arrays in the pointdata.
The code I have so far is below. Unfortunately, it shows a uniform color (when the same file loaded in ParaView it shows some local variations).
Obviously I'm missing something, but I can't figure where. I'd be grateful for any hints.
casefile = "data/Results/exported/blahblah.case"
part_id = 0
var_id = 2
reader = vtk.vtkGenericEnSightReader()
reader.SetCaseFileName(casefile)
reader.Update()
# Color map
colormap = vtk.vtkLookupTable()
colormap.SetHueRange(0.667, 0.0)
colormap.SetVectorModeToMagnitude()
colormap.Build()
multiblock = reader.GetOutput()
ugrid = multiblock.GetBlock(part_id)
pointdata = ugrid.GetPointData()
data = pointdata.GetArray(var_id)
data_range = data.GetRange(-1)
mesh_mapper = vtk.vtkDataSetMapper()
mesh_mapper.SetInput(ugrid)
mesh_mapper.SetColorModeToDefault()
mesh_mapper.SetScalarRange(data_range)
mesh_mapper.SetScalarVisibility(True)
mesh_mapper.SetLookupTable(colormap)
#
mesh_actor = vtk.vtkActor()
mesh_actor.SetMapper(mesh_mapper)
mesh_actor.GetProperty().SetDiffuseColor(1., 1., 1.)
renderer = vtk.vtkRenderer()
renderer.AddActor(mesh_actor)
renderer.AddActor2D(colorbar)
colormap = vtk.vtkLookupTable()
colormap.SetHueRange(0.667, 0.0)
colormap.SetVectorModeToMagnitude()
colormap.Build()
Will generate a lookuptable with a range between 0 and 1. Is this the data range from your example data?
If not, set the data range to the min/max values in the data_range tuple and then call Build() - I think this should help - do you have example data?

creating a color coded time chart using colorbar and colormaps in python

I'm trying to make a time tracking chart based on a daily time tracking file that I used. I wrote code that crawls through my files and generates a few lists.
endTimes is a list of times that a particular activity ends in minutes going from 0 at midnight the first day of the month to however many minutes are in a month.
labels is a list of labels for the times listed in endTimes. It is one shorter than endtimes since the trackers don't have any data about before 0 minute. Most labels are repeats.
categories contains every unique value of labels in order of how well I regard that time.
I want to create a colorbar or a stack of colorbars (1 for eachday) that will depict how I spend my time for a month and put a color associated with each label. Each value in categories will have a color associated. More blue for more good. More red for more bad. It is already in order for the jet colormap to be right, but I need to get desecrate color values evenly spaced out for each value in categories. Then I figure the next step would be to convert that to a listed colormap to use for the colorbar based on how the labels associated with the categories.
I think this is the right way to do it, but I am not sure. I am not sure how to associate the labels with color values.
Here is the last part of my code so far. I found one function to make a discrete colormaps. It does, but it isn't what I am looking for and I am not sure what is happening.
Thanks for the help!
# now I need to develop the graph
import numpy as np
from matplotlib import pyplot,mpl
import matplotlib
from scipy import interpolate
from scipy import *
def contains(thelist,name):
# checks if the current list of categories contains the one just read
for val in thelist:
if val == name:
return True
return False
def getCategories(lastFile):
'''
must determine the colors to use
I would like to make a gradient so that the better the task, the closer to blue
bad labels will recieve colors closer to blue
read the last file given for the information on how I feel the order should be
then just keep them in the order of how good they are in the tracker
use a color range and develop discrete values for each category by evenly spacing them out
any time not found should assume to be sleep
sleep should be white
'''
tracker = open(lastFile+'.txt') # open the last file
# find all the categories
categories = []
for line in tracker:
pos = line.find(':') # does it have a : or a ?
if pos==-1: pos=line.find('?')
if pos != -1: # ignore if no : or ?
name = line[0:pos].strip() # split at the : or ?
if contains(categories,name)==False: # if the category is new
categories.append(name) # make a new one
return categories
# find good values in order of last day
newlabels=[]
for val in getCategories(lastDay):
if contains(labels,val):
newlabels.append(val)
categories=newlabels
# convert discrete colormap to listed colormap python
for ii,val in enumerate(labels):
if contains(categories,val)==False:
labels[ii]='sleep'
# create a figure
fig = pyplot.figure()
axes = []
for x in range(endTimes[-1]%(24*60)):
ax = fig.add_axes([0.05, 0.65, 0.9, 0.15])
axes.append(ax)
# figure out the colors to use
# stole this function to make a discrete colormap
# http://www.scipy.org/Cookbook/Matplotlib/ColormapTransformations
def cmap_discretize(cmap, N):
"""Return a discrete colormap from the continuous colormap cmap.
cmap: colormap instance, eg. cm.jet.
N: Number of colors.
Example
x = resize(arange(100), (5,100))
djet = cmap_discretize(cm.jet, 5)
imshow(x, cmap=djet)
"""
cdict = cmap._segmentdata.copy()
# N colors
colors_i = np.linspace(0,1.,N)
# N+1 indices
indices = np.linspace(0,1.,N+1)
for key in ('red','green','blue'):
# Find the N colors
D = np.array(cdict[key])
I = interpolate.interp1d(D[:,0], D[:,1])
colors = I(colors_i)
# Place these colors at the correct indices.
A = zeros((N+1,3), float)
A[:,0] = indices
A[1:,1] = colors
A[:-1,2] = colors
# Create a tuple for the dictionary.
L = []
for l in A:
L.append(tuple(l))
cdict[key] = tuple(L)
# Return colormap object.
return matplotlib.colors.LinearSegmentedColormap('colormap',cdict,1024)
# jet colormap goes from blue to red (good to bad)
cmap = cmap_discretize(mpl.cm.jet, len(categories))
cmap.set_over('0.25')
cmap.set_under('0.75')
#norm = mpl.colors.Normalize(endTimes,cmap.N)
print endTimes
print labels
# make a color list by matching labels to a picture
#norm = mpl.colors.ListedColormap(colorList)
cb1 = mpl.colorbar.ColorbarBase(axes[0],cmap=cmap
,orientation='horizontal'
,boundaries=endTimes
,ticks=endTimes
,spacing='proportional')
pyplot.show()
It sounds like you want something like a stacked bar chart with the color values mapped to a given range? In that case, here's a rough example:
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
# Generate data....
intervals, weights = [], []
max_weight = 5
for _ in range(30):
numtimes = np.random.randint(3, 15)
times = np.random.randint(1, 24*60 - 1, numtimes)
times = np.r_[0, times, 24*60]
times.sort()
intervals.append(np.diff(times) / 60.0)
weights.append(max_weight * np.random.random(numtimes + 1))
# Plot the data as a stacked bar chart.
for i, (interval, weight) in enumerate(zip(intervals, weights)):
# We need to calculate where the bottoms of the bars will be.
bottoms = np.r_[0, np.cumsum(interval[:-1])]
# We want the left edges to all be the same, but increase with each day.
left = len(interval) * [i]
patches = plt.bar(left, interval, bottom=bottoms, align='center')
# And set the colors of each bar based on the weights
for val, patch in zip(weight, patches):
# We need to normalize the "weight" value between 0-1 to feed it into
# a given colorbar to generate an actual color...
color = cm.jet(float(val) / max_weight)
patch.set_facecolor(color)
# Setting the ticks and labels manually...
plt.xticks(range(0, 30, 2), range(1, 31, 2))
plt.yticks(range(0, 24 + 4, 4),
['12am', '4am', '8am', '12pm', '4pm', '8pm', '12am'])
plt.xlabel('Day')
plt.ylabel('Hour')
plt.axis('tight')
plt.show()

Categories