set colorbar scale / limits - scale

I have a plot with an aberrant scale on colorbar compared to the frequency of interest. I would like to change at least the max and min values of the colorbar. How can I do that ? I did not found the parameters in colorbar ?
for ch, ax in enumerate(axes[:-1]): # for each channel
# positive clusters
_, c1, p1, _ = pcluster_test(tfr_ev.data[:, ch], tail=1, **kwargs)
# negative clusters
_, c2, p2, _ = pcluster_test(tfr_ev.data[:, ch], tail=-1, **kwargs)
=2) # combined clusters
p = np.concatenate((p1, p2)) # combined p-values
mask = c[..., p <= 0.05].any(axis=-1)
# plot TFR (ERDS map with masking)
tfr_ev.average().plot([ch], cmap="RdBu",
#cnorm=cnorm,
axes=ax,
colorbar=False, show=False, mask=mask,
mask_style="mask")
ax.set_title(epochs.ch_names[ch], fontsize=10)
ax.axvline(0, linewidth=1, color="black", linestyle=":") # event
if ch != 0:
ax.set_ylabel("")
ax.set_yticklabels("")
fig.colorbar(axes[0].images[-1], cax=axes[-1]).ax.set_yscale("linear")
fig.suptitle(f"ERDS ({event})")
plt.show()
plot_with_aberrant_scale

Related

Julia BoundsError with less information - don't know why

I have the following code:
# package for ploting functions
using Plots
# use GR
gr()
# nb points to plot
nbPts = 22
# define polar coordinates of a 30 degree (pi/6) rotation
sine = sin(pi/6)
cosine = cos(pi/6)
# scale factor
scale_factor = 0.9
#---------------------------------------
# 1. PLOT POINTS USING ROTATION MATRIX
#---------------------------------------
# define Rotation matrix ( angle = pi/6, center = (0, 0) )
R = zeros(Float64, 2, 2)
R[1,1] = R[2,2]= cosine
R[1,2] = -sine
R[2,1] = sine
# Scale matrix
### ... <-- EXERCISE 4(c): define a uniform scaling matrix (use scale_factor)
# arrays of points coords
X_mat = zeros(nbPts)
Y_mat= zeros(nbPts)
# first Point (1,0)
X_mat[1] = 1.0
Y_mat[1] = 0.0
for i in 2:nbPts
prevPoint = [X_mat[i-1], Y_mat[i-1]]
#apply rotation to previous point to obtain new point
newPoint = R * prevPoint
### ... <-- EXERCISE 4(c): apply scaling matrix
X_mat[i] = newPoint[1]
Y_mat[i] = newPoint[2]
end
# plot points in blue
plt1 = scatter(X_mat, Y_mat, color=:blue, xlim = (-1.1, 1.1), ylim = (-1.1, 1.1), label=false, title="Rotation using matrices" );
#---------------------------------------
# 2. PLOT POINTS USING COMPLEX NUMBERS
#---------------------------------------
function ComplexProduct(z, w)
(((z[1]*w[1])+(z[2]*w[2])),((z[1]*w[2])+(z[2]*w[1])))
### ... <-- EXERCISE 4(b): implement complex product z * w
end
# first point: z = 1 + 0 * i
Z = ( 1.0, 0.0 )
# second point: w = cosine( pi/6) + sine( pi/6) * i
W = ( cosine, sine )
### ... <-- EXERCISE 4(c): apply scale_factor to W
# arrays of points coords
X_comp = zeros(nbPts)
Y_comp = zeros(nbPts)
# first Point (1,0)
X_comp[1] = Z[1]
Y_comp[1] = Z[2]
for i in 2:nbPts
prevPoint = (X_comp[i-1], Y_comp[i-1])
newPoint = ComplexProduct(prevPoint[1], prevPoint[2]) ### <-- EXERCISE 4(b): compute newPoint by applying rotation to prevPoint (use complex product)
X_comp[i] = newPoint[1]
Y_comp[i] = newPoint[2]
end
# plot points in red
plt2 = scatter(X_comp, Y_comp, color=:red, xlim = (-1.1, 1.1), ylim = (-1.1, 1.1), label=false, title="Rotation using complex numbers" );
# arrange and display
display( plot( plt1, plt2, layout = (1, 2), size=(600*2, 600) ))
The Error:
The Thing I want:
I have to implement a product of complex numbers and this should be used to calculate the rotation with complex numbers.
Should look like that:
What do I have to change so that the BoundsError is fixed?
Don't know what exactly i do wrong because of the poorly information i get from this error log.
Greetings and thanks for the help.
prevPoint[1] is a scalar while your function ComplexProduct expects something that has 2 elements. Perhaps you wanted to pass prevPoint instead of prevPoint[1]?
BTW you use incorrect naming pattern. CamelNaming is discouraged for Julia.
Your variable should be named prev_point and your function should be named complex_product.
Fixed the bug by changing the following code:
newPoint = ComplexProduct(prevPoint, W)
in line 92

How to change length of a side of polygon ensure the resulting polygon is similar shape

Polygon
I have a polygon that has only 90 and 45-degree angles, now I want to change the length of any side and adjust the polygon so that results should be a similar polygon.
Like this:
Shape after side change
import numpy as np
import matplotlib.pyplot as plt
# an arbitrary polygon, for example a pentagon:
P = np.array([[0.2, 0.1], [1, -0.2], [3, 1], [2, 0.7], [0.5, 1], [0.2, 0.1]])
P[-1, ] = P[0, ]
# pick a side between, say the one between vertices P[i,] and P[i+1,],
# and assume you want to make it of length a = 3:
i=2
a=3
# pick a point V0 in the plane, where a vertex P[j,] of the scaled polygon should be places:
j=1
v0 = [1,1]
# calculate the scale, which is a / (length of edge P[i,] P[i+1,]):
scale = a / np.linalg.norm(P[i+1, ] - P[i,])
# scale and position the polygon where you want it to be:
P_scaled = scale * P + (v0 - P[j,])
# plot polygon P:
plt.figure()
plt.plot(P[:,0], P[:,1])
for k in range(P.shape[0]):
plt.plot(P[k,0], P[k,1], 'ro')
# plot polygon P_scaled:
plt.plot(P_scaled[:,0], P_scaled[:,1])
for k in range(P_scaled.shape[0]):
plt.plot(P_scaled[k,0], P_scaled[k,1], 'ro')
axx = plt.gca()
axx.set_aspect('equal')
plt.show()

I'd like to extend a custom function for barplots so that I can stack the bars

I'd like to make a three-panel figure with each panel containing grouped barplots . And for the third panel I'd like to make the plot stacked. I've found excellent code here: Simplest way to do grouped barplot. I can get everything except for the stacked plot using the elegant solution at the end of this entry.
I tried many iterations of base R code to get a stacked barplot, but kept running into issues with having a dataframe and not a matrix or vector for the height argument. When I converted to a matrix though I lost the factors in my data. I'll put my working code for the other plots below and indicate where I'd like to add the stacked variable.
Here is a sample of my data
Population Sex numsnpsused numoutliers percentoutliers numoutspc1 numoutspc2
all f_and_m 8728 70 0.80 55 15
all f 6613 11 0.17 9 2
all m 9958 151 1.52 91 60
south f_and_m 7358 51 0.69 15 36
south f 6547 65 0.99 17 48
south m 8068 69 0.86 18 51
Code:
bar <- function(dv, factors, dataframe, percentage=FALSE, errbar=!percentage, half.errbar=TRUE, conf.level=.95,
xlab=NULL, ylab=NULL, main=NULL, names.arg=NULL, bar.col="black", whisker=.015,args.errbar=NULL,
legend=TRUE, legend.text=NULL, args.legend=NULL,legend.border=FALSE, box=TRUE, args.yaxis=NULL,
mar=c(5,4,3,2),...){
axes=!percentage
dv.name<-substitute(dv)
if(length(dv.name)>1) stop("'dv' only takes one variable")
dv.name<-as.character(dv.name)
dv<-dataframe[[dv.name]]
fnames<-substitute(factors)
if(length(fnames)==1){
factors<-as.character(fnames)
nf<-1
}else{
factors<-as.character(fnames[-1L])
nf<-length(factors)
}
if(nf>2) stop("This function accepts no more than 2 factors \n",
"\t-i.e., it only plots one-way or two-way designs.")
if(percentage & errbar){
warning("percentage=TRUE; error bars were not plotted")
errbar<-FALSE
}
if(!percentage) xbars<-tapply(dv, dataframe[,factors], mean, na.rm=TRUE)
else {
xbars<-tapply(dv, list(interaction(dataframe[,factors], lex.order=TRUE)), mean, na.rm=TRUE)
if(sum(na.omit(dv)!=0&na.omit(dv)!=1)>0)
stop("Data points in 'dv' need to be 0 or 1 in order to set 'percentage' to TRUE")
xbars<-rbind(xbars, 1-xbars)*100
}
if(errbar){
se<-tapply(dv, dataframe[,factors], sd, na.rm=TRUE)/sqrt(tapply(dv, dataframe[,factors], length))
conf.level=1-(1-conf.level)/2
lo.bar<-xbars-se*qnorm(conf.level)
hi.bar<-xbars+se*qnorm(conf.level)
}
extras<-list(...)
if(legend & !percentage){
if(is.null(legend.text))
legend.text<-sort(unique(dataframe[[factors[1]]]))
args.legend.temp<-list(x="topright", bty=if(!legend.border)"n" else "o",
inset=c(0,0))
if(is.list(args.legend))
args.legend<-modifyList(args.legend.temp, args.legend)
else
args.legend<-args.legend.temp
} else if(legend & percentage){
if(is.null(legend.text))
legend.text<-c("1", "0")
args.legend.temp<-list(x="topright", bty=if(!legend.border)"n" else "o",
inset=c(0,0))
if(is.list(args.legend))
args.legend<-modifyList(args.legend.temp, args.legend)
else
args.legend<-args.legend.temp
} else if(!legend){
args.legend<-NULL
legend.text<-NULL
}
if(errbar && legend && !percentage) ymax<-max(hi.bar)+max(hi.bar)/20
else if(errbar && legend && percentage) ymax<-115
else if(errbar && !legend) ymax <- max(xbars)
else if(!errbar && legend && percentage) ymax<-110
else if(!errbar) ymax<-max(xbars) + max(xbars)/20
if(!percentage){
args.barplot<-list(beside=TRUE, height=xbars, ylim=c(0, ymax), main=main, names.arg=names.arg,
col=hcl(h=seq(0,270, 270/(length(unique(dataframe[[factors[1]]]))))[-length(unique(dataframe[[factors[1]]]))]),
legend.text=legend.text, args.legend=args.legend, xpd=TRUE,
xlab=if(is.null(xlab)) factors[length(factors)] else xlab,
ylab=if(is.null(ylab)) dv.name else ylab, axes=axes)
}else{
args.barplot<-list(beside=TRUE, height=xbars, ylim=c(0, ymax), main=main, names.arg=names.arg,
col=hcl(h=seq(0,270, 270/(length(unique(dataframe[[factors[1]]]))))[-length(unique(dataframe[[factors[1]]]))]),
legend.text=legend.text, args.legend=args.legend, xpd=TRUE,
xlab=if(is.null(xlab)) " "[length(factors)] else xlab,
ylab=if(is.null(ylab)) "percentage" else ylab, axes=axes)
}
args.barplot<-modifyList(args.barplot, extras)
errbars = function(xvals, cilo, cihi, whisker, nc, args.errbar = NULL, half.errbar=TRUE) {
if(half.errbar){
cilo<-(cihi+cilo)/2
}
fixedArgs.bar = list(matlines, x=list(xvals),
y=lapply(split(as.data.frame(t(do.call("rbind",
list(cihi, cilo)))),1:nc),matrix,
nrow=2, byrow=T))
allArgs.bar = c(fixedArgs.bar, args.errbar)
whisker.len = whisker*(par("usr")[2] - par("usr")[1])/2
whiskers = rbind((xvals - whisker.len)[1,],
(xvals + whisker.len)[1,])
fixedArgs.lo = list(matlines, x=list(whiskers),
y=lapply(split(as.data.frame(t(do.call("rbind",
list(cilo, cilo)))), 1:nc), matrix, nrow=2, byrow=T))
allArgs.bar.lo = c(fixedArgs.lo, args.errbar)
fixedArgs.hi = list(matlines, x=list(whiskers),
y=lapply(split(as.data.frame(t(do.call("rbind",
list(cihi, cihi)))), 1:nc), matrix, nrow=2, byrow=T))
allArgs.bar.hi = c(fixedArgs.hi, args.errbar)
invisible(do.call(mapply, allArgs.bar))
if(!half.errbar) invisible(do.call(mapply, allArgs.bar.lo))
invisible(do.call(mapply, allArgs.bar.hi))
}
par(mar=mar)
errloc<-as.vector(do.call(barplot, args.barplot))
if(errbar){
errloc<-rbind(errloc, errloc)
lo.bar<-matrix(as.vector(lo.bar))
hi.bar<-matrix(as.vector(hi.bar))
args.errbar.temp<-list(col=bar.col, lty=1)
args.errbar<-if(is.null(args.errbar)|!is.list(args.errbar))
args.errbar.temp
else if(is.list(args.errbar))
modifyList(args.errbar.temp, args.errbar)
errbars(errloc, cilo=lo.bar, cihi=hi.bar, nc=1, whisker=whisker,
args.errbar=args.errbar, half.errbar=half.errbar)
}
if(box) box()
if(percentage){
args.yaxis.temp<-list(at=seq(0,100, 20), las=1)
args.yaxis<-if(!is.list(args.yaxis)) args.yaxis.temp else modifyList(args.yaxis.temp, args.yaxis)
do.call(axis, c(side=2, args.yaxis))
}
}
bar(dv = numsnpsused,
factors = c(Sex, Population),
dataframe = WALL,
errbar = FALSE,
col=c("red","purple","blue"),
ylab=c("Number of SNPs used in analysis"),
ylim=c(0, 12000)) #I increased the upper y-limit to accommodate the legend.
parpar(mfrow=c(2,2))
bar(dv = percentoutliers,
factors = c(Sex, Population),
dataframe = WALL,
errbar = FALSE,
col=c("red","purple","blue"),
ylab=c("% of SNPs that were outliers"),
ylim=c(0,3)) #I increased the upper y-limit to accommodate the legend.
##I want to include a second variable to stack in this plot
bar(dv = numoutspc1,
factors = c(Sex, Population),
dataframe = WALL,
errbar = FALSE,
col=c("red","purple","blue"),
ylab=c("Number of outliers associated with each PCaxis"),
ylim=c(0, 240)) #I increased the upper y-limit to accommodate the legend.
Here is the plot that I made
It's hard to provide a good answer without more details and what graph you expect as output. Here is a solution using ggplot2 that might start you off. You can imitate the grouped bar plot by merging the two grouping variables while still stacking by another variable.
df <- data.frame(y=sample(c(2000:2002),1000,T), k=sample(letters[1:3],1000,T),
g=sample(c(1:2),1000,T),
c=sample(c('t','f'),1000,T),stringsAsFactors = F)
df %>% count(y,k,g,c) %>% mutate(k1=paste0(k,g)) %>%
filter(y==2002|c!='f') %>%
ggplot(aes(k1,n,fill=c)) + geom_bar(stat='identity') + facet_wrap(~y)

Plotting raster images using custom colours in R

This might sound like a strange process, but its the best I can think of to control rasterised colour gradients with respect to discrete objects (points, lines, polygons). I'm 95% there but can't quite plot correctly.
This should illustrate proof of concept:
require(raster)
r = matrix(56:255, ncol=20) # reds
b = t(matrix(56:255, ncol=10)) # blues
col = matrix(rgb(r, 0, b, max=255), ncol=20) # matrix of colour strings
ras = raster(r) # data raster object
extent(ras) = extent(1,200,1,100) # set extent for aspect
plot(ras, col = col, axes=F, asp=T) # overwrite data with custom colours
Here I want to clip a raster to a triangle and create colour gradient of pixels inside based on their distances to one of the sides. Sorry for length but its the most minimal example I can design.
require(raster); require(reshape2); require(rgeos)
# equilateral triangle
t_s = 100 # half side
t_h = floor(tan(pi*60/180) * t_s) # height
corners = cbind(c(0, -t_s, t_s, 0), c(t_h, 0, 0, t_h))
trig = SpatialPolygons(list(Polygons(list(Polygon(corners)),"triangle")))
# line to measure pixel distances to
redline = SpatialLines(list(Lines(Line(corners[1:2,]), ID='redline')))
plot(trig); plot(redline, add=T, col='red', lwd=3)
# create a blank raster and clip to triangle
r = raster(mat.or.vec(nc = t_s*2 + 1, nr = t_h))
extent(r) = extent(-t_s, t_s, 0, t_h)
r = mask(r, trig)
image(r, asp=T)
# extract cell coordinates into d.f.
cells = as.data.frame(coordinates(rasterToPoints(r, spatial=T)))
# calculate distance of each pixel to redline with apply
dist_to_line = function(xy, line){
point = readWKT(paste('POINT(', xy[1], xy[2], ')'))
gDistance(point, line) / t_h
}
cells$dists = apply(cells, 1, dist_to_line, line=redline)
cells$cols = rgb(1 - cells$dists, 0, 0)
length(unique(cells$cols)) # count unique colours
# use custom colours to colour triangle pixels
image(r, col = cells$cols, asp=T)
plot(r, col = cells$cols, asp=T)
As you can see the plotting fails to overwrite as in the first example, but the data seems fine. Trying to convert to matrix also fails:
# try convertying colours to matrix
col_ras = acast(cells, y~x, value.var='cols')
col_ras = apply(col_ras, 1, rev) # rotate acw to match r
plot(r, col = col_ras, asp=T)
Very grateful for any assistance on what's going wrong.
Edit:
To show Spacedman's plotRGB method:
b = brick(draster, 1-draster, 1-draster)
plotRGB(b, scale=1)
plot(trig, col=NA, border='white', lwd=5, add=T)
Easy way is to go from your points to a spatial pixels data frame to a raster, then do the colour mapping...
Start with:
> head(cells)
x y dists
1 0.0000000 172.5 0.0014463709
2 0.0000000 171.5 0.0043391128
3 -0.9950249 170.5 0.0022523089
4 0.0000000 170.5 0.0072318546
5 0.9950249 170.5 0.0122114004
convert:
> coordinates(cells)=~x+y
> draster = raster(as(cells,"SpatialPixelsDataFrame"))
colourise:
> cols=draster
> cols[!is.na(draster)]= rgb(1-draster[!is.na(draster)],0,0)
> plot(cols, col=cols)
I'm not sure this is the right way to do things though, you might be better off creating an RGB raster stack and using plotRGB if you want fine colour control.

Sorting values in for plotting in R

I have a data that looks like this:
> print(dat)
cutoff tp fp
1 0.6 414 45701
2 0.7 172 16820
3 0.8 51 4326
4 0.9 49 3727
5 1.0 0 0
I want to plot them in reverse-order from smallest dat$tp to largest.
However this code plot them in order like above (i.e. largest to smallest) instead.
> fp_max <- max(dat$fp);
> tp_max <- max(dat$tp);
> op <- par(xaxs = "i", yaxs = "i")
> plot(tp ~ fp, data = dat, xlim = c(0,fp_max),ylim = c(0,tp_max), type = "n")
> with(dat, lines(c(0, fp, fp_max), c(0, tp, tp_max), lty=1, type = "l", col = "black"))
> lines( par()$usr[1:2], par()$usr[3:4], col="red" )
How can I modify the code above to address the problem?
Of course, the x-axis & y-axis coordinates should be from smallest to largest value
The following shows the result of my current code.
Notice that the line started at 0,0 and it 'goes back' to 0 again.
we want to avoid it going back to 0.
Ahh, I understand.
It's because lines draws lines between the points in the order they are given.
There are a few ways you could get around this:
do type='l' in your plot command and then with(dat,lines(...)) is not necessary:
# can also do the col='black',lty=1 in here.
plot(tp ~ fp, data = dat, xlim = c(0,fp_max),ylim = c(0,tp_max), type = "l")
Note that by definition of your fp_max and tp_max, you will include the point (fp_max,tp_max) already. And as long as you have a row with (0,0) for tp and fp in dat, you'll also get the (0,0) point.
Sort dat$tp and use that to sort dat$fp too:
plot(tp ~ fp, ..., type='n')
# sort dat$tp
obj <- sort(dat$fp,index.return=T)
# use obj$x as tp and obj$ix to sort dat$fp prior to plotting
with(dat,
lines(c(0, obj$x, fp_max), c(0, tp[obj$ix], tp_max),
lty=1, type = "l", col = "black"))
#Get order of rows
idx <- order(dat$tp)
#Select data in sorted order
sorted <- dat[idx,]

Resources