How to draw guide lines /w bokeh? - bokeh

I draw following plot with bokeh.plotting.Figure.line.
How I can add vertical guideline to emphasize a point of Feb/14 ?
Here's another plot. This is bokeh.charts.Bar.
I'd like to add horizontal guideline to emphasize a point of 50. I searched bokeh doc but have no luck to find relevant API reference. It would be appreciate someone address me about this.

I added a vertical line to a simple line chart by creating a new set of data that corresponded to the vertical line I wanted to create.
from datetime import *
x = [date(2001,1,1), date(2002,1,1),date(2003,1,1), date(2004,1,1),
date(2005,1,1), date(2006,1,1),date(2007,1,1), date(2008,1,1),
date(2009,1,1), date(2010,1,1),date(2011,1,1)]
y = [0, 3, 2, 4, 6, 9, 15, 18, 19, 25, 28]
output_file("lines.html", title="line plot example")
p = figure(title="simple line example",x_axis_type = "datetime")
p.line(x, y)
a = [min(y),max(y)]
b = [date(2009,1,1),date(2009,1,1)]
p.line(b, a ,line_color="red")
show(p)

You can do this fairly easily with the ray glyph in bokeh. If you set the angle to be 1.57079633 (90 degrees in radians) you'll get a vertical ray. Just update the x value to be where you want the line and the length to be the height of your x axis.
p.ray(x=.5, y=0, length=1, angle=1.57079633, color='black')

You can probably use the new BoxAnnotation (new as of Bokeh 0.9.3) with zero width or height to do this, with slightly better effect:
https://docs.bokeh.org/en/latest/docs/user_guide/annotations.html#box-annotations
It's probably worth adding a LineAnnotation as well, I'll make an issue for it.

Related

Lines don't align in rastertoPolygons

I am having trouble with aligning grids on a plot I made. Basically the plots show the result of a 34x34 matrix where each point has a value of 0,1,2,3 and is colored based on this. The lines which outline the cells do not match up perfectly with the coloring of the cells. My code and image are below.
library(raster)
r<-raster(xmn=1,xmx=34,ymn=1,ymx=34,nrows=34,ncols=34)
data1<-read.csv(file ="mat_aligned.csv",row.names = 1)
numbers<-data.matrix(data1)
r[]<-numbers
breakpoints<-c(-1,0.1,1.1,2.1,3.1)
colors<-c("white","blue","green","red")
plot(r,breaks=breakpoints,col=colors)
plot(rasterToPolygons(r),add=TRUE,border='black',lwd=3)
I would appreciate any help with this!
The problem is that the base R plot and the drawing of the grid use different plotting systems. The polygons will stay constant relative to the plotting window (they will appear narrower as the window shrinks), and won't preserve their relationship to the underlying plot axes, whereas the coloured squares will resize to preserve shape. You'll probably find that you can get your grid to match better by resizing your window, but of course, this isn't ideal.
The best way to get round this is to use the specific method designed for plotting SpatialPolygonDataFrame, which is the S4 class produced by rasterToPolygons. This is, after all, how you're "meant" to create such a plot.
Here's a reprex (obviously I've had to make some random data as yours wasn't shared in the question) :
library(raster)
r <- raster(xmn = 1, xmx = 34, ymn = 1, ymx = 34, nrows = 34, ncols = 34)
r[] <- data.matrix(as.data.frame(replicate(34, sample(0:3, 34, TRUE))))
colors <- c("white","blue","green","red")
spplot(rasterToPolygons(r), at = 0:4 - 0.5, col.regions = colors)
Created on 2020-05-04 by the reprex package (v0.3.0)
It is difficult to help if you not provide a minimal self-contained reporducible example. Something like this
library(raster)
r <- raster(xmn=1,xmx=34,ymn=1,ymx=34,nrows=34,ncols=34)
values(r) <- sample(4, ncell(r), replace=T)
p <- rasterToPolygons(r)
plot(r)
lines(p)
I see what you describe, even though it is minimal. A work-around could be to only plot the polygons
colors<-c("white","blue","green","red")
plot(p, col=colors[p$layer])

Legend outside plot does not work with plotyy in Octave

I am trying to create a plot in Octave (using v4.4.1 on Windows) using plotyy and putting the legend outside the plot (because the data covers all the usable space inside the graph). The following MVCE should reproduce the issue fairly well:
% Generate some random data to reproduce the issue
data = rand(1000,10);
data(:,1:8) = data(:,1:8)-0.5;
data(:,9:10) = data(:,9:10)+30;
timedate = linspace(737310,737313,size(data,1));
data_labels={'1';'2';'3';'4';'5';'6';'7';'8';'9';'10'};
% Plot the data
figure('Name','MVCE','Position',[300 200 1000 600])
[ax,h1,h2] = plotyy(timedate,data(:,1:8),timedate,data(:,9:10));
set(h2,'Visible','on');
datetick(ax(1),'x','HH:MM:SS')
datetick(ax(2),'x','HH:MM:SS')
ylim(ax(1),[-1 1])
ylim(ax(2),[20 50])
xlabel('Date & time')
ylabel(ax(1),'Something')
ylabel(ax(2),'Something else')
title('plotyy graph with legend problem')
[hl,hlo] = legend([h1;h2],data_labels,'location','eastoutside');
grid on
This the output of the code using the gnuplot graphics toolkit:
As you can see, the legend does not go outside the plot, and the second y axis is not visible (it looks like part of the plot is actually truncated).
I have tried using the qt and fltk graphics toolkits, which give issues of their own:
With qt graphics toolkit
With fltk graphics toolkit
Can anoybody suggest a fix or at least workaround? Does the same issue also happen in MATLAB or is it Octave-specific?
EDIT
Using the suggestion in Tasos' answer, I managed to almost make it work with gnuplot:
% Plot the data
figure('Name','MVCE','Position',[300 200 1000 600])
[ax,h1,h2] = plotyy(timedate,data(:,1:8),timedate,data(:,9:10));
set(h2,'Visible','on');
datetick(ax(1),'x','HH:MM:SS')
datetick(ax(2),'x','HH:MM:SS')
ylim(ax(1),[-1 1])
ylim(ax(2),[20 50])
ax1Pos = get(ax(1), 'position');
ax2Pos = get(ax(2), 'position');
ax1Pos(3) = ax1Pos(3) * 0.73;
ax2Pos(3) = ax2Pos(3) * 0.73;
set(ax(1), 'position', ax2Pos);
set(ax(2), 'position', ax2Pos);
xlabel('Date & time')
ylabel(ax(1),'Something')
ylabel(ax(2),'Something else')
title('plotyy graph with legend problem')
[hl,hlo] = legend([h1;h2],data_labels,'location','eastoutside');
pos = get(hl,'Position');
pos(1) = 0.9;
set(hl,'Position',pos)
grid on
Which produces:
Apart from the fact that the legend overlays with the second y axis label (which it doesn't on my screen, only when printing to jpg), the problem is that Octave appears to plot two legends on top of each other for some reason: one with the first set of data attached to the first set of axes, and one with the complete set of data, for both axes right on top of the first legend. This is obviously wrong, and trying to set the Visible property of hl to off deletes both legends, not just the one.
UPDATED: deals with both legend placement and OpenGL precision affecting graph.
Regarding the problem of the legend not appearing exactly in the position you want it to, you can manually adjust the position of all axes involved in a figure, to place them exactly where you want.
Regarding the problem of OpenGL being unable to deal with the precision involved when adding small numbers to a large number, plot the graph with only the small numbers involved, and then simply adjust the xticklabels to correspond to the numbers you desire.
Full code below:
% Generate some random data to reproduce the issue
data = rand(1000,10);
data(:,1:8) = data(:,1:8)-0.5;
data(:,9:10) = data(:,9:10)+30;
t_offset = 737310;
timedate = linspace(0,3,size(data,1));
data_labels={'1';'2';'3';'4';'5';'6';'7';'8';'9';'10'};
% Plot the data
figure('Name','MVCE','Position',[300 200 1000 600])
[ax,h1,h2] = plotyy(timedate,data(:,1:8),timedate,data(:,9:10));
set(h2,'Visible','on');
ylim(ax(1),[-1 1])
ylim(ax(2),[20 50])
ylabel(ax(1),'Something')
ylabel(ax(2),'Something else')
title('plotyy graph with legend problem')
[hl,hlo] = legend([h1;h2],data_labels,'location','eastoutside');
set(hl, 'position', get(hl, 'position') .* [0.975, 1, 0.975, 1] )
grid on
ax1Pos = get(ax(1), 'position'); ax2Pos = get(ax(2), 'position');
ax1Pos(3) = ax1Pos(3) * 0.95; ax2Pos(3) = ax2Pos(3) * 0.95;
set(ax(1), 'position', ax2Pos); set(ax(2), 'position', ax2Pos);
XTicks = get(ax(1), 'xtick');
set(ax(1), 'xticklabel', datestr(XTicks + t_offset, 'HH:MM:SS'))
xlabel('Date & time')
set(ax(2), 'xtick', []);
Output:

ggplot heatmap failing to fill tiles

This (minimal, self-contained) example is broken:
require(ggplot2)
min_input = c(1, 1, 1, 2, 2, 2, 4, 4, 4)
input_range = c(4, 470, 1003, 4, 470, 1003, 4, 470, 1003)
density = c(
1.875000e-01,
5.598958e-04,
0.000000e+00,
1.250000e-02,
3.841146e-04,
0.000000e+00,
1.250000e-02,
1.855469e-04,
0.000000e+00)
df = data.frame(min_input, input_range, density)
pdf(file='problemspace.pdf')
ggplot(df, aes(x=min_input, y=input_range, fill=density)) +
geom_tile()
dev.off()
Producing:
Why are there big gaps?
There are gaps because you don't have data for all of the tiles. If you want to try to fill them in, your only option is to interpolate (assuming you don't have access to additional data). In theory, geom_raster() (a close relative of geom_tile()) supports interpolation. However, according to this github issue, that feature is not currently functional.
As a workaround, however, you can use qplot, which is just a wrapper around ggplot:
qplot(min_input, input_range, data=df, geom="raster", fill=density, interpolate=TRUE)
If there is too much space between the points that you have data for, you will still end up with blank spaces in your graph, but this will extend the range that you can estimate values for.
EDIT:
Based on the example that you posted, this will be the output
As you can see, there is a vertical band of white running through the middle, due to the lack of data points between 2 and 4.

X axis relative to 1 not 0 in gap.barplot, how can I change this?

I have altered the sample code that from the help file for gap.barplot.
twogrp<-c(0, 4, 5, 7, 2,3, 1, 7, 18, 22, 25, 26, 28)
gap.barplot(twogrp,gap=c(8,16),xlab="Index",ytics=c(3,6,17,20),
ylab="Group values",main="Barplot with gap")
When I plot the above code, the resulting plot makes a 0 value appear to be a negative value, and a value of 1 look like zero. Is there any way to change this so that if my vector contains a zero value, nothing is plotted, and if there is a value of one then I see a raised bar. I have noticed that the sample files avoid ones and zeros, and that the plots resulting from the sample files have the x axis at y=1.
There is clearly a typo in gap.barplot (plotrix version 3.5-5). Right now it is setting the bottom of the bars to the minimum x value rather than the minimum y value. Here's some code that will copy that function and change that line (if found)
gap.barplot2<-gap.barplot
if (deparse(body(gap.barplot2)[[c(20,4,4)]])==
"botgap <- ifelse(gap[1] < 0, gap[1], xlim[1])") {
body(gap.barplot2)[[c(20,4,4)]] <-
quote(botgap <- ifelse(gap[1] < 0, gap[1], ylim[1]))
} else {
stop("line not found")
}
Then you can run
gap.barplot2(twogrp,gap=c(8,16),xlab="Index",ytics=c(3,6,17,20),
ylab="Group values",main="Barplot with gap")
to get
There appears to be no easy way to set the ylim[1]=0 without also setting ylim[2] (the max y-value). Lattice plotting functions would allow ylim=c(0,NA). Which would be nice to force a zero line but let the rest of the function figure out what the default max should be.
So you can use this alternative for now. I would contact the package authors to let them know about this error. You can send them a link to this question if you like.

Add Points to Image using Jpeg Device

I would like to add some points to an image I have created using image.plot. Here's my code with needed libraries. It places the .jpg in my working directory. Problem is my points are not showing up on the image. Any ideas not sure what I'm missing? Is it possible that the device is closing before points are added? Generic data is included below.
install.packages("RColorBrewer")
install.packages("fields")
library("RColorBrewer", lib.loc="...../R-2.15.2/library")
library("fields", lib.loc="...../R-2.15.2/library")
jpeg(paste("Steamflow", "timestep", ".jpg",sep = ''), width = 640,
height = 441,quality = 75)
image.plot(streamflux, zlim=c(-1,1), col=brewer.pal(11, "RdBu"),
yaxt="n", xaxt="n", main=paste("Stress Period ", "timestep", sep = ""))
points(WLX,WLY)
dev.off()
And here are datasets WLX, WLY and streamflux
WLY=c(9, 6, 9, 13, 17, 20, 22)
WLX=c(8, 19, 29, 20, 13, 20, 21)
streamflux=matrix(1:1452,44,33, byrow=FALSE)
The code I posted before is functional however I didn't configure my data correctly. The libraries needed to run the code have been added to the original question. I used image.plot but I believe you would run into the same problems using the base image. If you only specify a matrix of z values the image is plotted with axis c(0,1). If you specify x,y,z for each cell I don't think you will run into the problem I did where points were being plotted out of bounds. If you decide that you specifying a matrix of z values is easier than specify x,y,z, as I did, to keep your points from being plotted out of bounds you will need to scale your point data. In my case WLX=WLX/44 and WLY=WLY/33. As a side note you probably want to specify x,y,z if you're not using regularly spaced data.

Resources