Yes, my oversight.

So, I only had time to take this so far, but here is partial code structured the way I would recommend, that updates the data, rather than hiding/creating entirely new things. It shows 2, then 1, then 2 radar patches, and does not leak resources. You would need to continue the work to handle the “axes”. If their positions do not change, you can do it once in `create_plot`

. Otherwise they would need the same treatment to draw glyphs once with empy sources, then update the sources later. Note I have remove the double underscores on the instance vars. This is really dis-recommended outside of a few very special cases (this coming from CPython Core Devs I work with).

In general, my best advice to you is to separate out generating data, from using that data to draw things. That decoupling will lead to a much more flexible design.

```
# CELL 1
import numpy as np
form radar import RadarGraph
from bokeh.io import output_notebook
```

```
# CELL 2
output_notebook()
```

```
# CELL 3
text1 = [
'lexical richness max :0.326',
'ratio filling pause max :0.039',
'ratio feedback max :0.305',
'taille moyenne Ipu non feedback max :8.699',
'familiar language max :5.677'
]
flist1 = [
np.array([0.45669999, 1, 0.47506903, 0.96134016, 1]),
np.array([1, 0.58196036, 1, 1, 0.37513551])
]
text2 = [
'lexical richness max :0.326',
'ratio filling pause max :0.023',
'ratio feedback max :0.305',
'taille moyenne Ipu non feedback max :8.699',
'familiar language max :2.130'
]
flist2 = [
np.array([1, 1, 1, 1, 1])
]
text3 = [
'lexical richness max :0.326',
'ratio filling pause max :0.039',
'ratio feedback max :0.305',
'taille moyenne Ipu non feedback max :8.699',
'familiar language max :5.677'
]
flist3 = [
np.array([0.45669999, 1, 0.47506903, 0.96134016, 1]),
np.array([1, 0.58196036, 1, 1, 0.37513551])
]
```

```
# CELL 4
radar = RadarGraph()
radar.show()
radar.update(text1, flist1)
time.sleep(2)
radar.update(text2, flist2)
time.sleep(2)
radar.update(text3, flist3)
time.sleep(2)
```

And here is a (partial) `radar.py`

:

```
import time
from bokeh.io import push_notebook, show
from bokeh.models import ColumnDataSource, LabelSet
from bokeh.plotting import figure
DEFAULT_COLORS=["black", "blue", "red", "yellow", "green", "purple", "white", "brown", "orange", "pink", "black"]
DEFAULT_TITLE = "radar graph"
def unit_poly_verts(theta, center):
x0, y0, r = [center] * 3
verts = [(r * np.cos(t) + x0, r * np.sin(t) + y0) for t in theta]
return verts
def radar_patch(r, theta, center):
offset = 0
yt = (r * center + offset) * np.sin(theta) + center
xt = (r * center + offset) * np.cos(theta) + center
return xt, yt
class RadarGraph(object):
def __init__(self, colors=DEFAULT_COLORS, title=DEFAULT_TITLE):
self.colors = colors
self.title = title
self.handle = None
self.center = 0.5
self.label_source = ColumnDataSource(data=dict(x=[], y=[], text=[]))
self.radar_source = ColumnDataSource(data=dict(xs=[], ys=[], color=[]))
self.segment_source = ColumnDataSource(data=dict(x1=[], y1=[]))
self.plot = self.create_plot(title, colors)
def show(self):
self.handle = show(self.plot, notebook_handle=True)
def update(self, text, flist):
# update labels data source
text = text + [""]
nbVar = len(flist[0])
theta = np.linspace(0, 2 * np.pi, nbVar, endpoint=False)
theta += np.pi / 2
verts = unit_poly_verts(theta, self.center)
x = [v[0] for v in verts]
y = [v[1] for v in verts]
self.label_source.data = {'x': x+[self.center], 'y': y+[1], 'text': text}
# update radar data source
xs, ys = [], []
for i in range(len(flist)):
xt, yt = radar_patch(flist[i], theta, self.center)
xs.append(xt)
ys.append(yt)
self.radar_source.data = dict(xs=xs, ys=ys, color=self.colors[:len(xs)])
# push the changes
push_notebook(handle=self.handle)
def create_plot(self, title, colors):
plot = figure(title=title, tools="", x_range=(0, 2), y_range=(0, 1.5))
plot.segment(x0=0.5, y0=0.5, x1='x1', y1='y1', color="black", line_width=1,
source=self.segment_source)
labels = LabelSet(x="x", y="y", text="text", source=self.label_source)
plot.add_layout(labels)
plot.patches(xs='xs', ys='ys', fill_color='color', fill_alpha=0.15,
source=self.radar_source)
return plot
# You will have to take over here:
# drawRadar(x, y, self.__plot, 10)
# def drawRadar(x1, y1, p, nbOfRulerSegment):
# origine = 0.5
# ticSize = 0.01
# for i in range(0, len(x1)):
# p.segment(x0=origine, y0=origine, x1=x1[i],
# y1=y1[i], color="black", line_width=1)
# if x1[i] == origine:
# x1[i] = origine + 0.001 # prevent deviding by 0
# if y1[i] == origine:
# y1[i] = origine + 0.001 # prevent deviding by 0
# leadingCoefficient = (y1[i]-origine)/(x1[i]-origine)
# leadingCoefficientRuler = -(1/leadingCoefficient)
# deltaX = x1[i] - origine
# deltaY = y1[i] - origine
# rulerX0 = []
# rulerX1 = []
# rulerY0 = []
# rulerY1 = []
# # some quick maths: solving (a*x)^2 +x^2 - tickSize^2 = 0 -> pythagore theorem
# a = (leadingCoefficientRuler**2)+1
# c = -(ticSize**2)
# # b is equal to 0
# delta = - (4 * a * c) # b^2 - 4*a*c
# if delta == 0: # prevent sqrt(0)
# delta = 0.001
# solution = math.sqrt(delta)/(2*a)
# for i in range(1, nbOfRulerSegment):
# centreX = origine + ((float(i)/float(nbOfRulerSegment)) * deltaX)
# centreY = origine + ((float(i)/float(nbOfRulerSegment)) * deltaY)
# rulerX0.append(centreX + solution)
# rulerX1.append(centreX - solution)
# rulerY0.append(centreY + solution * leadingCoefficientRuler)
# rulerY1.append(centreY - solution * leadingCoefficientRuler)
# p.segment(x0=rulerX0, y0=rulerY0, x1=rulerX1, y1=rulerY1, color="black", line_width=0.5)
```