Bokeh: grid of plots and aspect ratio - bokeh

I trying to make a grid a image and line plots, but the first image plot is stretched horizontally, apparently because of the width taken by the y-axis labels of the line plot on the second row.
Is there any way to prevent this?
# create an array of RGBA data
N = 20
img = np.empty((N, N), dtype=np.uint32)
view = img.view(dtype=np.uint8).reshape((N, N, 4))
for i in range(N):
for j in range(N):
view[i, j, 0] = int(255 * i / N)
view[i, j, 1] = 158
view[i, j, 2] = int(255 * j / N)
view[i, j, 3] = 255
#output_file("grid.html", )
p = figure(plot_width=200, plot_height=200, x_range=(0, 10), y_range=(0, 10))
p.image_rgba(image=[img], x=[0], y=[0], dw=[10], dh=[10])
p2 = figure(plot_width=200, plot_height=200, x_range=(0, 10), y_range=(0, 10))
p2.image_rgba(image=[img], x=[0], y=[0], dw=[10], dh=[10])
p3 = figure(plot_width=400, plot_height=200)
p3.line([1, 2, 3, 4, 5], np.array([6, 7, 2, 4, 5])*10000, line_width=2)
p3.xaxis.axis_label = f'Wavelength'
p3.yaxis.axis_label = f'Flux'
l = gridplot([
[p, p2],
[p3]
], sizing_mode='fixed')
show(l)

As of Bokeh 1.0.2 there is not a direct way to control the inner frame dimensions. There is an ongoing WIP Pull Request to add this capability, and others, that will land in a 1.1 release.
In the mean time, you can:
control the overall canvas width/height with plot_width and plot_height
control the minimum padding around the inner from with min_border, min_border_left, etc.
control the extent of axis ticks by controlling their rotation, formatting, or location
So, if you control the ticks (and account for any colorbar size, etc), and set appropriate min_border values that will not be exceeded, you can effectively exert control over the frame dimensions indirectly. I note that this is far from ideal, and look forward to the layout PR arriving.

Related

How can I put all graphs for different sample size `n=10, 100, 1000, 2000` in the same plot and change the color of `y=1` in red?

For a sample size n=1000, I plot the following graph based the code
n = 1000;
m = RandomVariate[GaussianOrthogonalMatrixDistribution[Sqrt[2]/Sqrt[n], n]];
{eval, evec} = Eigensystem[m];
h = evec[[All, 1]];
imin = Ordering[eval, 1][[1]];
lambda2minlambda1 = Sort[eval][[2]] - Sort[eval][[1]];
tn = 1/(4*lambda2minlambda1);
Plot the function H1 (t)
Plot[Abs[h[[imin]]]*Exp[-2*eval[[imin]]*t]/Sqrt[Sum[h[[i]]^2*Exp[-4*eval[[i]]*t], {i, 1, n}]],
{t, 0, 10*tn},
GridLines -> {{tn}, {1}},
GridLinesStyle -> Directive[{Red, Blue}, Thickness[0.008]],
PlotRange -> Full]
Question:
How can I put all graphs for different sample size n=10, 100, 1000, 2000 in the same plot and change the color of y=1 in red?**
Try
Show[Append[Table[
m=RandomVariate[GaussianOrthogonalMatrixDistribution[Sqrt[2]/Sqrt[n], n]];
{eval,evec}=Eigensystem[m];h=evec[[All,1]];imin=Ordering[eval,1][[1]];
lambda2minlambda1=Sort[eval][[2]]-Sort[eval][[1]];tn=1/(4*lambda2minlambda1);
Plot[Abs[h[[imin]]]*Exp[-2*eval[[imin]]*t]/Sqrt[Sum[h[[i]]^2*Exp[-4*eval[[i]]*t],
{i,1,n}]],{t,0,10*tn},PlotRange->{{0,60},{0,1}}],
{n,{10,100,1000,2000}}],
Plot[1,{x,0,60},ColorFunction->Function[{x,y},Red]]],
PlotRange->{{0,60},{0,1}}]
There are always at least a dozen different ways of doing anything in Mathematica. Pick one that you can remember and use without making any mistakes.

How to access plotted data values from GUI with mouse click in PySimpleGUI?

How to extract data point at mouse click in PySimpleGUI?
I have a collection of 2D (x,y) data points. I have plotted the 2D data using PySimpleGUI graph element and drawCircle function. Now, when I click on one circle (which represents one data point), I want to execute a function that takes this (x,y) data point as its input. I want to get the exact (x,y) data point that I plotted (not the coordinates of the location that I click) when I click anywhere on the circle.
import PySimpleGUI as sg
layout = [[sg.Graph(canvas_size=(800, 800), graph_bottom_left=
(-105, -105), graph_top_right=(105, 105), background_color='white',
key='graph', tooltip=None, enable_events=True)], ]
window = sg.Window('Network Prediction Evaluation', layout,
grab_anywhere=True).Finalize()
graph = window['graph']
# Draw axis
graph.DrawLine((-100, 0), (100, 0))
graph.DrawLine((0, -100), (0, 100))
for x in range(-100, 101, 20):
graph.DrawLine((x, -3), (x, 3))
if x != 0:
graph.DrawText(x, (x, -10), color='green')
for y in range(-100, 101, 20):
graph.DrawLine((-3, y), (3, y))
if y != 0:
graph.DrawText(y, (-10, y), color='blue')
# Draw Graph
f = open("./data/train_analysis.txt", "r")
s_id = []
true_val = []
pred_val = []
f.readline() # to remove column names
for x in f:
s = x.split()
s_id.append(float(s[0]))
true_val.append(int(round(float(s[1]) * 100)))
pred_val.append(int(round(float(s[2]) * 100)))
for i in range(len(true_val)):
# graph.DrawLine((true_val[i],0),(true_val[i],pred_val[i]))
graph.DrawCircle((true_val[i], pred_val[i]), 4, line_color='red',
fill_color='blue')
while True:
event, values = window.read()
if event is None:
break
val = values[event]
print(val)
I am able to get the coordinates of the location of the mouse click. But I want to get the exact data point when I click anywhere on the circle. How can I do that?

How to cut mesh model matching robot template

Given a mesh model (e.g. a box) and a robot template containing volume, aspect ratio and linkage info of sub-parts (basically cuboids), we want to have a cutting algorithm to cut the mesh model into pieces that can match the robot template. We are using Maya for the modelling job.
For example, the mesh model is a 1X1X1 volume=1 box, the robot template has a 1:1:2 volume 0.5 head link with body, and a 1:1:2 volume 0.5 body link with head, then what we need is to cut the box into half.
The matching of volume, aspect ratio and linkage are not strict, reasonable errors can be accepted.
Is there any existing algorithms that can do the job or is there any related topics on this?
Also if you have any idea to solve this problem please enlighten me. Thanks!
EDIT
The problem is, given a mesh object, and a robot template, we need to transform it to the robot.
So now my idea is first cut the object into subparts which match the template, then transform the subparts into robot using Inverse Kinematic maybe.
Sample input and output:
I'd try to just cubes to the correct dimensions by setting the aspect ratio in the cube shape
import maya.cmds as cmds
def scaled_cube(volume, w, d, h):
scale_factor = pow( float(volume) / float(h* w * d), 1.0/3)
return cmds.polyCube(w = w * scale_factor, d = d * scale_factor, h = h * scale_factor)
Edit: After the above comments, this will cut out the portion of a mesh contained in a cuboid (defined here as a maya style bounding box (minx, miny, minz, maxx, maxy, maxz - the same thing you'd get from querying the maya bbox):
def cut_to_fit_bounds(mesh, bbox):
'''
splits an existing mesh
'''
cutmesh = cmds.duplicate(mesh)
minx, miny, minz, maxx, maxy, maxz = bbox
cmds.select(cutmesh)
cmds.polyCut(pc = (minx, 0, 0), ro = (0, 90,0), df =1, ch=0 )
cmds.polyCloseBorder(ch=0)
cmds.polyCut(pc = (maxx, 0, 0), ro = (0, -90,0), df = 1, ch=0)
cmds.polyCloseBorder(ch=0)
cmds.polyCut(pc = (0, 0, minz), ro = (0, 0,0), df =1, ch=0 )
cmds.polyCloseBorder(ch=0)
cmds.polyCut(pc = (0, 0, maxz), ro = (0, 180,0), df = 1, ch=0)
cmds.polyCloseBorder(ch=0)
cmds.polyCut(pc = (0, miny, 0), ro = (-90, 0,0), df =1,ch=0 )
cmds.polyCloseBorder(ch=0)
cmds.polyCut(pc = (0, maxy, 0), ro = (90, 0,0), df = 1, ch=0)
cmds.polyCloseBorder(ch=0)
cmds.select(cutmesh)
The previous routine could be used to create appropriately sized volumes - by placing them correctly and grabbing their bounding boxes with cmds.xform(q=True, bb=True) cut volumes could be made. After that you should have a cut up copy of the original, although I'd worry about normal artifacts, sliver polys and material issues which are common when using polyCut.

Some math and animation

I have a grass texture:
I use it in my 2d-game. I want to animate it by code, without any predefined animations.
The grass should interact with wind. So when the wind is stronger, the grass should stoop into need side more.
First version of animation I made using sinusoid function, but such animation is a bit ugly, because the base of the grass moves left/right like all another part of picture. And with sinusoid I'm not able to regulate stoop of the image.
Any advices?
This is what you may get easily by shifting pixels:
Although probably not very useful for you, here is a Mathematica program:
f[l_, sh_] := Module[{c = l, k = (Dimensions#l)[[1]]},
For[i = 1, i <= k, i++,
c[[i]] = RotateRight[l[[i]], IntegerPart[(k + 1 - i)/sh]]];
Return[c];]
b = ArrayPad[ImageData#a, {{40}, {40}, {0}}, {1, 1, 1}];
Export["c:\\anim.gif",
{Image#b, Image#f[b, 7],
Image#f[b, 5], Image#f[b, 3],
Image#f[b, 5], Image#f[b, 7], Image#b}, "DisplayDurations" -> .3]
Edit
But you can get a better effect by applying a circular transform:
b = Image#ArrayPad[ImageData#a, {{40, 0}, {40}, {0}}, {1, 1, 1}];
f[image_, angleMult_] := ImageForwardTransformation[image, (
fi = ArcTan[Abs[#[[2]]/(#[[1]] - .5)]];
fi1 = angleMult fi (#[[1]]^2 + #[[2]]^2)/2;
{(1/2 - Sin[fi1] #[[2]] - Cos[fi1]/2 +
Cos[fi1] #[[1]]), -Sin[fi1]/2 + Sin[fi1] #[[1]] +
Cos[fi1] #[[2]]}) &]
t = Table[f[b, x], {x, 0, .2, .02}];
t1 = Reverse#t;
Export["c:\\anim.gif", Join[t, t1], "DisplayDurations" -> .15];
Import["c:\\anim.gif", "Animation"]
You could just shift the rows, so that e.g. every 3rd row is shifted 1px to the right, beginning with the bottom.
How are you displaying the texture? When using a billboard you could manipulate the vertices of the billboard and even triangulate the billboard for more control.

Draw fitted line (OpenCV)

I'm using OpenCV to fit a line from a set of points using cvFitLine()
cvFitLine() returns a normalized vector that is co-linear to the line and a point on the line.
See details here
Using this information how can I get the equation of a line so that I can draw the line?
If cvFitLine() returns normalized vector (vx,vy) and point (x0,y0), then the equation of the line is
(x,y) = (x0,y0) + t*(vx,vy)
where t runs from −∞ to +∞.
This is what you asked for, but probably isn't immediately helpful in drawing the line. You would want to clip it either to the screen boundaries, or perhaps the bounding box of the the original set of points. To clip a line to a rectangle, just solve for values of t where the line crosses the boundary of the rectangle.
Just draw a big line instead of solving for the boundaries. eg:
cv.Line(img, (x0-m*vx[0], y0-m*vy[0]), (x0+m*vx[0], y0+m*vy[0]), (0,0,0))
will do it for example.. for m large enough :)
This just spells out #brainjam's answer in python for any passers by.
The formula for a line using a unit vector (vx, vy) and some point on the line (x0, y0) is:
(x, y) = (x0, y0) + t*(vx, vy)
The return from cv2.fitLine() is:
np.array([vx, vy, x0, y0])
In the example case, I have a line spanning the height of my image, so I want to find the t0 and t1 that intersect with y=0 and y=img.shape[0] (the top/bottom boundaries).
# get the fitLine for your set of points in the array, `line`
fit_line = cv2.fitLine(line, cv2.DIST_L2, 0, 0.01, 0.01)
# compute t0 for y=0 and t1 for y=img.shape[0]: (y-y0)/vy
t0 = (0-fit_line[3])/fit_line[1]
t1 = (img.shape[0]-fit_line[3])/fit_line[1]
# plug into the line formula to find the two endpoints, p0 and p1
# to plot, we need pixel locations so convert to int
p0 = (fit_line[2:4] + (t0 * fit_line[0:2])).astype(np.uint32)
p1 = (fit_line[2:4] + (t1 * fit_line[0:2])).astype(np.uint32)
# draw the line. For my version of opencv, it wants tuples so we
# flatten the arrays and convert
# args: cv2.line(image, p0, p1, color, thickness)
cv2.line(img, tuple(p0.ravel()), tuple(p1.ravel()), (0, 255, 0), 10)
I used a strategy similar to Karpathy up there but used an extra function. As you can see, I'm using cvClipLine to trim the line to the size of the image, which is unnecessary but does add a little niceness.
Also the multiplier here is defined as theMult = max(img->height,img->width) so we dont get numbers that might one day overflow or something.
void drawLine(IplImage * img, float line[4], int thickness,CvScalar color)
{
double theMult = max(img->height,img->width);
// calculate start point
CvPoint startPoint;
startPoint.x = line[2]- theMult*line[0];// x0
startPoint.y = line[3] - theMult*line[1];// y0
// calculate end point
CvPoint endPoint;
endPoint.x = line[2]+ theMult*line[0];//x[1]
endPoint.y = line[3] + theMult*line[1];//y[1]
// draw overlay of bottom lines on image
cvClipLine(cvGetSize(img), &startPoint, &endPoint);
cvLine(img, startPoint, endPoint, color, thickness, 8, 0);
}
Adding to #brainjam answer:
To clip to the bounding box of original set of points:
// std::vector<Point2i> points = ...
//lineParams: [vx,vy, x0,y0]: (normalized vector, point on our contour)
Vec4f lineParams; fitLine(points, lineParams, CV_DIST_L2, 0, 0.01, 0.01);
// derive the bounding xs of points
decltype(points)::iterator minXP, maxXP;
std::tie(minXP, maxXP) = std::minmax_element(points.begin(), points.end(), [](const Point2i& p1, const Point2i& p2){ return p1.x < p2.x; });
// derive y coords of fitted line
float m = lineParams[1] / lineParams[0];
int y1 = ((minXP->x - lineParams[2]) * m) + lineParams[3];
int y2 = ((maxXP->x - lineParams[2]) * m) + lineParams[3];
line(clearTarget, Point(minXP->x, y1), Point(maxXP->x, y2), Scalar(255, 255, 255), 2);
To clip to the entire image boundaries substitute minXP->x to 0 and maxXP->x to image.cols - 1, which was originally answered in https://stackoverflow.com/a/14192660/2380455
we use a " Vec4f fitedLine;" for fitted Line
in fitLine we have 4 parameters
if we consider Line relation az bellow:
Y - Y0 = M (X - X0)
we have
Y0 = FitedLine[3];
X0 = FitedLine[2];
m = FitedLine[1]/FitedLine[0];
so we have a Line equation we can find other points on it.

Resources