How to add Span to figure legend in bokeh? - bokeh

So I create a figure with some lines and a span (or multiple spans).
f = figure()
f.line(x, y1, legend_label='1st set')
f.line(x, y2, legend_label='2st set')
vl = Span(location=x_point,
dimension='height',
line_dash='dotdash', line_color="black", line_alpha=0.7)
f.add_layout(vl)
I would like to add span entry to the default legend of the figure.

The default Legend works only with glyph renderers, so you cannot directly add Span to a legend.
But you can create a glyph with no data and with the same parameters as the span:
f.line([], [], legend_label='span',
line_dash='dotdash', line_color="black", line_alpha=0.7)

Related

Color grid lines in Julia

I would like to color the grid lines in a plot. Here is some reproducible code:
using Plots
Plots.plot(rand(10))
Output:
Imagine I want to have green grid lines, how can we change the color of grid lines in Julia? I check the docs, but I can only find attributes like alpha, line width and style and not the color.
Here is some code to get the green grid:
plt = Plots.plot(rand(10))
xaxis = Plots.get_axis(Plots.get_subplot(plt,1),:x)
yaxis = Plots.get_axis(Plots.get_subplot(plt,1),:y)
xaxis[:gridalpha] = 0.6
yaxis[:gridalpha] = 0.6
xaxis[:foreground_color_grid] = colorant"green"
yaxis[:foreground_color_grid] = colorant"green"
plt
Many other attributes are described in the docs page you linked to.

Add one legend to layout plot in Julia

I would like to create one legend for a layout plot in Julia. Here is some reproducible code:
using Plots
plot(rand(100, 4), layout = 4, color = [:red :blue :green :yellow])
Output:
As you can see it shows nicely a legend to each subplot, but I would like to have one shared legend, using :shared doesn't work. So I was wondering if anyone knows how to add a shared legend to a layout plot in Julia?
Maybe this answer can give an idea. I can do it by a trick (creating a transparent plot for the legend). The only problem is that I don't know how I can move the legend (actually, the transparent plot) to the location I want:
colors = [:red :blue :green :yellow]
p = [
plot(col, legend=false, color=colors[idx])
for (idx, col) in enumerate(eachcol(data))
]
p1 = plot((1:4)', legend=true, framestyle=:none, color=colors)
plot(
p...,
p1,
layout = #layout[
[
grid(2, 2)
p
] p1
],
size = (1000, 1000)
)
result of savefig:
If I change the layout like the following:
layout = #layout[
p1 [
grid(2, 2)
p
]
]
# And change the order of the plots
plot(
p1,
p...,
⋮
)
Then I get this:
Note that I cropped the redundant area of the image above.

Gadfly (Julia): how to add text annotation to a plot?

In Stata I can add text to a plot at given coordinates, e.g.:
clear
set obs 10
gen x = rnormal()
gen y = rnormal()
twoway scatter y x, text(0.8 0.8 "Some text")
The result is "Some text" at coordinates (0.8, 0.8):
I want to add a similar annotation in Julia with Gadfly. I found Guide.annotation that can add layers of graphs and I could not figure out how to apply it to text instead of shapes. The documentation mentions at the top:
Overlay a plot with an arbitrary Compose graphic.
but the Compose link shows a website in Chinese.
How can I add a text label (or caption, or annotation) with Gadfly?
You can check the guide on Compose in julia. In the example in your link they use Circle, but you just as easily can use:
text(x, y, value)
or using the linked example code:
Pkg.add.(["Gadfly", "Compose"])
using Gadfly, Compose;
plot(x = rand(10),
y = rand(10),
Guide.annotation(compose(context(), text(0.8, 0.8, "Some text"))))
in the link I provided they redirect to a source file for the comprehensive list:
These are basic constructors for the in-built forms - see src/form.jl for more constructors.
polygon(points)
rectangle(x0, y0, width, height)
circle(x, y, r)
ellipse(x, y, x_radius, y_radius)
text(x, y, value)
line(points)
curve(anchor0, ctrl0, ctrl1, anchor1)
bitmap(mime, data, x0, y0, width, height)

Insert a newline character into a categorical axis factor label in BokehJS

I have a BokehJS plot with a categorical x-axis with factors that have strings that are very long. The label is being cut off by the edge of the graph and I would like to be able to insert a newline character either manually or automatically to produce a short length string (since it is now taller but narrower with a new line in the middle). I have tried the following code but it does not seem to create a change in the appearance.
p.x_range.attributes['factors'][0] = 'Some very long text string\nthat has now been cut'
Until Bokeh adds either CSS rendering for xaxis ticks or add support for new line characters. Here's a workaround that can do what you are asking for, but it isn't perfect.
Instead of using a factor range, we can plot the data like normal using a placeholder x value. Then, we can place Labels under the y_axis at those placeholder positions which can then be rendered by css which will correctly print the newline.
Here's a working example using the Bokeh server.
main.py
from bokeh.plotting import ColumnDataSource, figure
from bokeh.models import LabelSet, FixedTicker
from bokeh.io import curdoc, show
factors = ["Some very long text string\nthat has now been cut\na",
"Some very long text string\nthat has now been cut\nb"]
y = [50, 40]
# arbitrary placeholders which depends on the length and number of strings
x = [0, 2]
x_label = [0.65, 2.65] # This is offset is based on the length of the string
y_label = [-2, -2] # offset under the plot
source = ColumnDataSource(
data=dict(factors=factors, x=x, y=y, x_label=x_label, y_label=y_label))
p = figure(x_range=(-1, 3), y_range=(0, 52))
p.circle(x='x', y='y', size=15, fill_color="orange", source=source)
p.xaxis.ticker = FixedTicker(ticks=x)
p.xaxis.major_label_text_font_size = '0pt' # turn off x-axis tick labels
# p.xaxis.major_tick_line_color = None # turn off x-axis major ticks
p.xaxis.minor_tick_line_color = None # turn off x-axis minor ticks
labels = LabelSet(x='x_label', y='y_label', text='factors', source=source,
level='overlay', render_mode='css', text_align='center')
p.add_layout(labels)
curdoc().add_root(p)
styles.css
.bk-annotation-child {
white-space: pre-wrap;
text-align: center;
}
The main disadvantage of this method is that the x_labels must be manually offset on the x axis from our placeholder x values. This is because the built-in bokeh centering called from the LabelSet is calculated on the full length string and not the not the longest sub string between \n. I'm sure you could tinker with this answer and programmatically determine the correct offset for an arbitrary string instead of eyeballing it as I did.

Adding additional panel plots to an XY lattice plot

I'm looking to change the colour of a line and add an additional line in an xy plot
Distance<-c(1,2,3,4,5,6,7,8,9,10,11,12,13)
PAR<-c(1,3,5,9,15,12,11,6,5,4,3,1,0.5)
Function1<-function(Distance,param){
abs(param[1])*Distance*param[2]*exp(1)*exp(-(Distance*param[2]))
}
Function2<-function(Distance,param){
param[1]+param[2]*Distance
}
e<-c(0.05,0.1)
f<-c(4,0.9)
p1<-xyplot(PAR~Distance,data=Control,
xlab="Exponential Model", ylab=expression("C=1"),
xlim=c(0,20),
ylim=c(0,0.1),
col = ("cornsilk3"),
grid=(TRUE),
panel=function(x,y,...){
panel.xyplot(x,y,...)
panel.lines(x,(Function1(x,1,e))))}
So basically i'd like to add an additional panel line for function2 paired with the f list of parameters and have them as 2 different colours so i can differentiate between them.
Simply add another line panel.lines(x,(Function2(x,f)),col="red")
Note also, Function1(x,1,e) should be Function1(x,e) I think.
Your sample data is not in a data.frame Control. And you'll probably need to adjust ylim.
And your final )} should be }).

Resources