Is there a Cubic Spline Interpolation method implemented in J? - j

I am a new user of J and I am just wondering if there is a Cubic Spline Interpolation method implemented in J packages?

I'm not familiar myself, but I do have all the packages installed, so
$ rg -l -i spline /usr/share/j/9.02/ -g '*.ijs'
/usr/share/j/9.02/addons/math/misc/spline.ijs
/usr/share/j/9.02/addons/stats/rlibrary/manifest.ijs
/usr/share/j/9.02/addons/stats/rlibrary/splines.ijs
/usr/share/j/9.02/addons/stats/rlibrary/test_splines.ijs
/usr/share/j/9.02/addons/math/misc/manifest.ijs
/usr/share/j/9.02/addons/graphics/plot/jzplot.ijs
/usr/share/j/9.02/addons/demos/wdplot/plexam.ijs
math/misc/spline and stats/rlibrary/splines look good, the latter though is interfacing with R. The former begins with an imlementation:
NB. =========================================================
NB.*cubicspline v Calculate cubic spline
NB.
NB. y is: 2-row matrix x ,: f(x)
NB.
NB. result: x values;coefficient matrix,one row per interval.
cubicspline=: 3 : 0
...
To get this package to a location appropriate for your install of J, use the Package Manager.

Related

Does Piecewise Bezier curve pass vertical line test?

Consider a piecewise cubic Bezier curve with N segments, defined in terms of 4N control points. How can I determine whether this curve passes the Vertical Line Test? That is: do there exist points x,y1,y2 such that y1!=y2 and both (x,y1) and (x,y2) lie on the curve? Additionally, it would be nice but not essential to return the values of the points x,y1,y2 if such points exist.
In principle, one could just evaluate the curve explicitly at a large number of points, but in my application the curves can have a large number of segments so this is prohibitively slow. Thus I am looking for an algorithm that operates on the control points only, and does not rely on explicitly evaluating the curves at a large number of points.
Closed curves will fail your test by definition, so let's look at open curves: for a curve to fail your vertical line test, at least one segment in your piecewise cubic polyBezier needs to "reverse direction" along the x-axis, which means its x component needs to have extrema in the inclusive interval [0,1].
For example, this curve doesn't (the right side shows the component function for x, with global extrema in red and inflections in purple):
(Also note that we're only drawing the [0,1] interval, but if we were to extend it, those global extrema wouldn't actually be at t=0 and t=1. This is in fact critically important, and we'll see why, below)
This curve also doesn't (but only just):
But this curve does:
As does this one. Twice, in fact:
As does a curve "just past its cusp":
Which is easier to see when we exaggerate it:
This means we need to find the first derivative, find out where it's zero, and then make sure that (because Beziers can have cusps) the sign of that derivative flips at that point (or points, as there can be two).
Turns out, the derivative is trivially not-even-really-computed, so for each segment we have:
w = [x1, x2, x3, x4]
Bx(t) = w[0] * (1-t)³ + 3 * w[1] * t(1-t)² + w[2] * t²(1-t) + w[3] * t³
// bezier form of the derivative:
v = [
3 * (w[1] - w[0]),
3 * (w[2] - w[1]),
3 * (w[3] - w[2]),
]
Bx'(t) = v[0] * (1-t)² + 2 * v[1] * t(1-t) + v[2] * t²
Which we can trivially rewrite to polynomial form:
a = v[0] - 2*v[1] + v[2]
b = 2 * (v[1] - v[0])
c = v[0]
Bx'(t) = a * t² + b * t + c
So we find the roots for that, which is a matter of applying the quadratic formula, which gives us 0, 1, or 2 roots.
if (a == 0) there are no roots
denominator = 2 * a
discriminant = b * b - 2 * denominator * c
if (discriminant < 0) there are no (real) roots
d = sqrt(discriminant)
t1 = -(b + d) / denominator
if (0 ≤ t1 ≤ 1) then t1 is a valid root
t2 = (d - b) / denominator
if (0 ≤ t2 ≤ 1) then t2 is a valid root
If there are no (real) roots, then this segment does not cause the curve to fail your vertical line test, and we move on to the next segment and repeat until we've either found a failure, or we've run out of segments to test.
If it's 1 or 2 roots, we check that the signs of Bx'(t-ε) and Bx'(t+ε) for some very small value of ε differ (because we want to make sure we don't conclude that the above curve with a cusp fails the test: it has a zero derivative but it "keeps going in the same direction" across that root instead of flipping direction). If they do, this segment is (one of) the segment(s) that makes your curve fail your vertical line test.
Also, note that we're testing even if the root is at 0 or 1: the piecewise curve might inflect "across segments", and we can take advantage of the fact that we can evaluate Bx'(t) for t = -ε or t = 1+ε to see if we flip direction, even if we never draw the curve prior to t=0 or after t=1.
Leaving solution here for reference. Not especially elegant but gets the job done. Assume that the curve is parametrized from left to right. The key observation is that the curve intersects a vertical at two points if and only if there is a point at which the derivative x'(t) of the x component is strictly negative. For a cubic Bezier curve the derivative is a quadratic polynomial x'(t)=at^2+bt+c. So we just need to check whether the minimum of this quadratic over the interval 0<=t<=1 is negative, which is straightforward (if a bit tedious) using basic algebra.

Finding probability for Discrete Binomial distribution problems

Problem Description:
In each of 4 different competitions, Jin has 60% chance of winning. Assuming that the competitions are independent of each other, what is the probability that: Jin will win at least 1 race?
Given Binomial distribution Parameters:
n=4
p=0.60
Hint:
P(x>=1)=1-P(x=0)
Use the binom.pmf() function of scipy.stats package to calculate the probability.
Below is the python code i have tried. But it is being evaluated as wrong.
from scipy import stats
n = 4
p = 0.6
p1 = 1 - p
p2 = stats.binom.pmf(1,4,p1)
print(p1)
Using the hint, all you need to do is to evaluate the PMF of the binomial distribution at x=0 and subtract the result from 1 to obtain the probability of Jin winning at least one competition:
from scipy import stats
x=0
n=4
p=0.6
p0 = stats.binom.pmf(x,n,p)
print(1-p0)

Creating a distance matrix from sets of xyz coordinates (python)

I have a list of xyz coordinates of different points from a PDB file assigned to variable x. Here is a snippet of what it looks like
[ 8.721 15.393 22.939]
[11.2 13.355 25.025]
[11.045 15.057 28.419]
[13.356 13.814 31.169]
[12.54 13.525 34.854]
[14.038 15.691 37.608]
[16.184 12.782 38.807]
[17.496 12.053 35.319]
[18.375 15.721 34.871]
[20.066 15.836 38.288]
[22.355 12.978 37.249]
[22.959 14.307 33.724]
[24.016 17.834 34.691]
[26.63 16.577 37.161]
[29.536 18.241 35.342]
[27.953 21.667 35.829]
I would like to use these points to compute a distance matrix. I have tried to use the SciPy distance_matrix function, however it does not appear to support xyz coordinates, only x and y coordinates. Is there a good way to compute this distance matrix manually?
If you can use biopython Bio.PDB to get these atoms then you can get the distance between 2 atoms by simply subtracting the two atoms distance = atom1 - atom2.
If you really want to get the distance on your own then that is also simple, by using the formula d = sqrt((x2 - x1)**2 + (y2 - y1)**2 + (z2 - z1)**2).
You just need to loop over to get a distance matrix using one of the distance method above:
dist=[[0]*len(array[0])]*len(array)
for i in range(len(array)-1):
for j in range(i+1,len(array)):
dist[i][j]=distance(array[i],array[j])

Evaluating and graphing functions in MATLAB

I am trying to graph the following Gaussian function in MATLAB (should graph in 3 dimensions) but I am making some mistakes somewhere. What is wrong?
sigma = 1
for i = 1:20
for j = 1:20
z(i,j) = (1/(2*pi*sigma^2))*exp(-(i^2+j^2)/(2*sigma^2));
end
end
surf(z)
The problem you are likely having is that you are evaluating the Gaussian over the range of 1 to 20 for both i and j. Since sigma is 1, you are only going to see a segment of one side of the Gaussian (not including the center at [i,j] = [0,0]), and the values of z from 3 to 20 in each direction are very close to 0.
Instead of using for loops, you can do things "the MATLAB way" by creating matrices of x and y values using the function MESHGRID and performing element-wise operations on them to compute and plot z:
[x,y] = meshgrid(-4:0.1:4); %# Use values from -4 to 4 in x and y directions
z = (1/(2*pi*sigma^2)).*exp(-(x.^2+y.^2)./(2*sigma^2)); %# Compute z
surf(x,y,z); %# Plot z

Metric 3d reconstruction

I'm trying to reconstruct 3D points from 2D image correspondences. My camera is calibrated. The test images are of a checkered cube and correspondences are hand picked. Radial distortion is removed. After triangulation the construction seems to be wrong however. The X and Y values seem to be correct, but the Z values are about the same and do not differentiate along the cube. The 3D points look like as if the points were flattened along the Z-axis.
What is going wrong in the Z values? Do the points need to be normalized or changed from image coordinates at any point, say before the fundamental matrix is computed? (If this is too vague I can explain my general process or elaborate on parts)
Update
Given:
x1 = P1 * X and x2 = P2 * X
x1, x2 being the first and second image points and X being the 3d point.
However, I have found that x1 is not close to the actual hand picked value but x2 is in fact close.
How I compute projection matrices:
P1 = [eye(3), zeros(3,1)];
P2 = K * [R, t];
Update II
Calibration results after optimization (with uncertainties)
% Focal Length: fc = [ 699.13458 701.11196 ] ± [ 1.05092 1.08272 ]
% Principal point: cc = [ 393.51797 304.05914 ] ± [ 1.61832 1.27604 ]
% Skew: alpha_c = [ 0.00180 ] ± [ 0.00042 ] => angle of pixel axes = 89.89661 ± 0.02379 degrees
% Distortion: kc = [ 0.05867 -0.28214 0.00131 0.00244 0.35651 ] ± [ 0.01228 0.09805 0.00060 0.00083 0.22340 ]
% Pixel error: err = [ 0.19975 0.23023 ]
%
% Note: The numerical errors are approximately three times the standard
% deviations (for reference).
-
K =
699.1346 1.2584 393.5180
0 701.1120 304.0591
0 0 1.0000
E =
0.3692 -0.8351 -4.0017
0.3881 -1.6743 -6.5774
4.5508 6.3663 0.2764
R =
-0.9852 0.0712 -0.1561
-0.0967 -0.9820 0.1624
0.1417 -0.1751 -0.9743
t =
0.7942
-0.5761
0.1935
P1 =
1 0 0 0
0 1 0 0
0 0 1 0
P2 =
-633.1409 -20.3941 -492.3047 630.6410
-24.6964 -741.7198 -182.3506 -345.0670
0.1417 -0.1751 -0.9743 0.1935
C1 =
0
0
0
1
C2 =
0.6993
-0.5883
0.4060
1.0000
% new points using cpselect
%x1
input_points =
422.7500 260.2500
384.2500 238.7500
339.7500 211.7500
298.7500 186.7500
452.7500 236.2500
412.2500 214.2500
368.7500 191.2500
329.7500 165.2500
482.7500 210.2500
443.2500 189.2500
402.2500 166.2500
362.7500 143.2500
510.7500 186.7500
466.7500 165.7500
425.7500 144.2500
392.2500 125.7500
403.2500 369.7500
367.7500 345.2500
330.2500 319.7500
296.2500 297.7500
406.7500 341.2500
365.7500 316.2500
331.2500 293.2500
295.2500 270.2500
414.2500 306.7500
370.2500 281.2500
333.2500 257.7500
296.7500 232.7500
434.7500 341.2500
441.7500 312.7500
446.2500 282.2500
462.7500 311.2500
466.7500 286.2500
475.2500 252.2500
481.7500 292.7500
490.2500 262.7500
498.2500 232.7500
%x2
base_points =
393.2500 311.7500
358.7500 282.7500
319.7500 249.2500
284.2500 216.2500
431.7500 285.2500
395.7500 256.2500
356.7500 223.7500
320.2500 194.2500
474.7500 254.7500
437.7500 226.2500
398.7500 197.2500
362.7500 168.7500
511.2500 227.7500
471.2500 196.7500
432.7500 169.7500
400.2500 145.7500
388.2500 404.2500
357.2500 373.2500
326.7500 343.2500
297.2500 318.7500
387.7500 381.7500
356.2500 351.7500
323.2500 321.7500
291.7500 292.7500
390.7500 352.7500
357.2500 323.2500
320.2500 291.2500
287.2500 258.7500
427.7500 376.7500
429.7500 351.7500
431.7500 324.2500
462.7500 345.7500
463.7500 325.2500
470.7500 295.2500
491.7500 325.2500
497.7500 298.2500
504.7500 270.2500
Update III
See answer for corrections. Answers computed above were using the wrong variables/values.
** Note all reference are to Multiple View Geometry in Computer Vision by Hartley and Zisserman.
OK, so there were a couple bugs:
When computing the essential matrix (p. 257-259) the author mentions the correct R,t pair from the set of four R,t (Result 9.19) is the one where the 3D points lay in front of both cameras (Fig. 9.12, a) but doesn't mention how one computes this. By chance I was re-reading chapter 6 and discovered that 6.2.3 (p.162) discusses depth of points and Result 6.1 is the equation needed to be applied to get the correct R and t.
In my implementation of the optimal triangulation method (Algorithm 12.1 (p.318)) in step 2 I had T2^-1' * F * T1^-1 where I needed to have (T2^-1)' * F * T1^-1. The former translates the -1.I wanted, and in the latter, to translate the inverted the T2 matrix (foiled again by MATLAB!).
Finally, I wasn't computing P1 correctly, it should have been P1 = K * [eye(3),zeros(3,1)];. I forgot to multiple by the calibration matrix K.
Hope this helps future passerby's !
It may be that your points are in a degenerate configuration. Try to add a couple of points from the scene that don't belong to the cube and see how it goes.
More information required:
What is t? The baseline might be too small for parallax.
What is the disparity between x1 and x2?
Are you confident about the accuracy of the calibration (I'm assuming you used the Stereo part of the Bouguet Toolbox)?
When you say the correspondences are hand-picked, do you mean you selected the corresponding points on the image or did you use an interest point detector on the two images are then set the correspondences?
I'm sure we can resolve this problem :)

Resources