Create matrix out of list with mathematica - wolfram-mathematica

I have a problem which I try to solve with mathematica.
I am having a list with x and y coordinates from a position measurement (and also with z values of the quantity which was measured at each point). So, my list starts with
list={{-762.369,109.998,0.915951},{-772.412,109.993,0.923894},{-777.39, 109.998, 0.918108},...} (x,y,z).
Out of some reasons, I have to fill all these x,y, and z-values into a matrix. That would be easy if I have for each y-coordinate the same amount of x-coordinates (lets say 80), then I could use Partition[list,80] which produces a matrix with 80 columns (and some rows whose number is given by the number of y-coordinates with the same value).
Unfortunately, it is not so easy, the number of x-coordinates for each y is not strictly constant, as can be seen from the attached ListPlot.
Can anybody give me some suggestions, how I could fill each point of this plot / each x-y-(and z-) coordinate of my list into a matrix?
To explain better what I want to have, I indicated in the attached picture a matrix. There one can see that almost every point of my plot would fall into a cell of a matrix, only some cells would stay empty.
I used in the plot the color red for the points whose x coordinates are ascending in my list and blue for the points whose x coordinate are descending in my list (the positions are measured along a meander line). Perhaps this kind of order can be useful to solve to problem...
Here a link to my coordinates, perhaps this helps.
Well, I hope I explained my question well enough. I would appreciate every help much!

The basic idea behind this solution is:
all points seem to lie on a lattice, but it's not precisely a square lattice (it's slanted)
so let's find the basis vectors of the lattice, then all (most?) points will be approximate integer linear combinations of the basis vectors
the integer "coordinates" of the points along the basis vectors will be the matrix indices for the OP's matrix
(The OP emailed me the datafile. It consists of {x,y} point coordinates.)
Read in the data:
data = Import["xy.txt", "Table"];
Find the nearest 4 points to each point, and notice that they lie about distance 5 away both horizontally and vertically:
nf = Nearest[data];
In:= # - data[[100]] & /# nf[data[[100]], 5]
Out= {{0., 0.}, {-4.995, 0.}, {5.003, 0.001}, {-0.021, 5.003}, {0.204, -4.999}}
ListPlot[nf[data[[100]], 5], PlotStyle -> Red,
PlotMarkers -> Automatic, AspectRatio -> Automatic]
Generate the difference vectors between close points and keep only those that are about length 5:
vv = Select[
Join ## Table[(# - data[[k]] & /# nf[data[[k]], 5]), {k, 1, Length[data]}],
4.9 < Norm[#] < 5.1 &
];
Average the vectors out by directions they can point to, and keep two "good" ones (pointing "up" or to the "right").
In:= Mean /# GatherBy[vv, Round[ArcTan ## #, 0.25] &]
Out= {{0.0701994, -4.99814}, {-5.00094, 0.000923234}, {5.00061, -4.51807*10^-6},
{-4.99907, -0.004153}, {-0.0667469, 4.9983}, {-0.29147, 4.98216}}
In:= {u1, u2} = %[[{3, 5}]]
Out= {{5.00061, -4.51807*10^-6}, {-0.0667469, 4.9983}}
Use one random point as the point of origin, so the coordinates along the basis vectors u1 and u2 will be integers:
translatedData = data[[100]] - # & /# data;
Let's find the integer coordinates and see how good they are (how far they are from actual integers):
In:= integerIndices = LinearSolve[Transpose[{u1, u2}], #] & /# translatedData ;
In:= Max[Abs[integerIndices - Round[integerIndices]]]
Out= 0.104237
In:= ListPlot[{integerIndices, Round[integerIndices]}, PlotStyle -> {Black, Red}]
All points lie close to the integer approximations.
Offset the integer coordinates so they're all positive and can be used as matrix indices, then gather the elements into a matrix. I put the coordinates in a point object in order not to confuse SparseArray:
offset = Min /# Transpose[Round[integerIndices]]
offset = {1, 1} - offset
result =
SparseArray[
Thread[(# + offset & /# Round[integerIndices]) -> point ### data]]
result = Normal[result] /. {point -> List, 0 -> Null}
And we finally have a matrix result where each element is a coordinate-pair! (I was sloppy doing 0 -> Null here to mark missing elements: it's important that data contained no exact 0s.)
MatrixForm[result[[1 ;; 10, 1 ;; 5]]]
EDIT
Just for fun, let's look at the deviations of points from the precise integer lattice sites:
lattice = #1 u1 + #2 u2 & ### Round[integerIndices];
delta = translatedData - lattice;
delta = # - Mean[delta] & /# delta;
ListVectorPlot[Transpose[{lattice, delta}, {2, 1, 3}], VectorPoints -> 30]

Related

Area under a curve in Mathematica

Problem:
I have a two separated list of values, X={x1,x2....x2059} and Y={Y1,Y2....Y2059}. Using the Mathematica function "Transpose" i can obtain a new list Z = {{x1,y1},{x2,y2},...{x2059,y2059}}. Using ListLinePlot[Z] i made the plot.
Now, the problem is: How i can calculate the area under the plotted curve. I can't use NIntegrate, or Integrate. Can I use the interpolation function? how?
Even using the Trapezoidal Rule (implemente by me) i didn't obtain a good resul.
The data comes from an Load-deformation plot. This means that for the first half part of the data, the curve growth. From the second part of data the curve come back to zero (close to zero). In particular, X = deformation and Y=Load.
(*create a simulation for your points*)
npts = 2058;
x = Sort#RandomReal[100, npts];
y = Join[Sort#RandomReal[100, npts/2], Reverse#Sort#RandomReal[100, npts/2]];
f = Interpolation[Transpose#{x, y}, InterpolationOrder -> 1];
(*Plot and Integrate*)
Plot[f[t], {t, Min#x, Max#x}, Filling -> Axis]
NIntegrate[f[t], {t, Min#x, Max#x}, Method -> "LocalAdaptive"]
answer:
(* 5006.01 *)

How to plot a 3d graph starting from a set of points as a ground XY base

This question might seem a little strange but for my purposes is not that crazy.
Its easy but I need you to follow me.
The aim
My aim is plotting a tridimensional graph.
The problem
The problem is the material I have in my hands to start building this graph. Actually I have a collection of points in the 2D space (thus tuples of two real ordered values). Consider a moment to have these collection of points stored into an array and now consider to plot them on a 2D diagram. You will just have a nice sparse view of these points.
Well, the second step is this: consider the surface with these points and create a third axis orthogonal to the plane where those points are drawn. The aim is assigning to every point a numerical scalar value (using a function that accepts the couple and returns a numerical value). So the graph should show bars starting from every point and having a specific value according to the assignment function.
How can I achieve this in Mathematica?
A little note
Basically my points in the 2d space are also connected by a graph. Is it possible to connect the top of the bars to the top of other bars whose base point are connected together in the 2d graph?
Some other notes
My graph doesn`t have to be a surface but just a collection of bars placed on a plane in the exact place where the correspondent point they refer to is located. But if you have a good hint how to draw a surface other than bars, it will be gladly accepted.
I hope I was clear. I would like to point that I have Mathematica 8 so all functionalities are available. Thank you.
This can be done using Graphics3D primitives. Lets start with some data
(* a list of 2D coordinates *)
points2D = RandomReal[{0, Pi}, {50, 2}];
(* some edges as a list of pairs of vertex indices *)
edges = Union[Flatten[MapIndexed[Sort /# Thread[{#2[[1]],
Nearest[points2D -> Automatic, #, 4]}] &, points2D], 1]];
(* constructing list of 3D coordinates *)
f[{x_, y_}] := 2 + Sin[x y]
points3D = {##, f[{##}]} & ### points2D;
The actual plot can then be constructed as follows (width is half the width of the bars)
With[{width = .02},
Graphics3D[{{LightBlue, EdgeForm[None],
Cuboid[{#1, #2, 0} - width {1, 1, 0}, {##} + width {1, 1, 0}] & ### points3D},
{Orange,
GraphicsComplex[points3D, Line[edges]]}},
Lighting -> "Neutral",
BoxRatios -> {1, 1, .6}]]

Find frequency for non-binned, weighted data

Here is a tricky problem (or at least so I think). I need to create a histogram, but instead of having the data and it's frequency, I have repeated data (i.e. not binned) and some weight for each data.
One example:
Angle | Weight
90 .... 3/10
93 .... 2/10
180 .... 2/10
180 .... 1/10
95 .... 2/10
I want to create a histogram with bin size 10. The y-values should be the sum of weighted frequencies for angles within a range. How can I do it? Preferably Mathematica or pseudocode...
In Mathematica 9, you can do it using the WeightedData function like this:
Histogram[WeightedData[{90, 93, 180, 180, 95}, {3/10, 2/10, 2/10, 1/10, 2/10}], {10}]
You should then get a graphic like this one:
Since the expected output is not forthcoming I shall adopt Verbeia's interpretation. You might use something like this:
dat = {{90, 3/10}, {93, 1/5}, {180, 1/5}, {180, 1/10}, {95, 1/5}};
bars =
Reap[
Sow[#2, Floor[#, 10]] & ### dat,
_,
{#, Tr##2} &
][[2]]
Graphics[
Rectangle[{#, 0}, {# + 10, #2}] & ### bars,
AspectRatio -> 1/GoldenRatio,
Axes -> True,
AxesOrigin -> {Min#bars[[All, 1]], 0}
]
I did something similar for a different kind of question recently (weighting by balance sheet size).
Assuming your data is in an N * 2 matrix list, I would do something like:
{numbers,weights} = {data[[All,1]], data[[All,2]]*10};
weightednumbers = Flatten# MapThread[
Table[#1, {#2}] &, {numbers, Ceiling[weights]}];
And then use Histogram to draw the histogram on this transformed data.
There might be other ways but this works.
An important point is to make sure the weights are integers, so the Table as the correct iterator. This might require defining weights as data[[All,2]]*Min[data[[All,2]].

What algorithm determines the nearness of a point to a Bezier curve?

I wish to determine when a point (mouse position) in on, or near a curve defined by a series of B-Spline control points.
The information I will have for the B-Spline is the list of n control points (in x,y coordinates). The list of control points can be of any length (>= 4) and define a B-spline consisting of (n−1)/3 cubic Bezier curves. The Bezier curves are are all cubic. I wish to set a parameter k,(in pixels) of the distance defined to be "near" the curve. If the mouse position is within k pixels of the curve then I need to return true, otherwise false.
Is there an algorithm that gives me this information. Any solution does not need to be precise - I am working to a tolerance of 1 pixel (or coordinate).
I have found the following questions seem to offer some help, but do not answer my exact question. In particular the first reference seems to be a solution only for 4 control points, and does not take into account the nearness factor I wish to define.
Position of a point relative to a Bezier curve
Intersection between bezier curve and a line segment
EDIT:
An example curve:
e, 63.068, 127.26
29.124, 284.61
25.066, 258.56
20.926, 212.47
34, 176
38.706, 162.87
46.556, 149.82
54.393, 138.78
The description of the format is: "Every edge is assigned a pos attribute, which consists of a list of 3n + 1 locations. These are B-spline control points: points p0, p1, p2, p3 are the first Bezier spline, p3, p4, p5, p6 are the second, etc. Points are represented by two integers separated by a comma, representing the X and Y coordinates of the location specified in points (1/72 of an inch). In the pos attribute, the list of control points might be preceded by a start point ps and/or an end point pe. These have the usual position representation with a "s," or "e," prefix, respectively."
EDIT2: Further explanation of the "e" point (and s if present).
In the pos attribute, the list of control points might be preceded by a start
point ps and/or an end point pe. These have the usual position representation with a
"s," or "e," prefix, respectively. A start point is present if there is an arrow at p0.
In this case, the arrow is from p0 to ps, where ps is actually on the node’s boundary.
The length and direction of the arrowhead is given by the vector (ps −p0). If there
is no arrow, p0 is on the node’s boundary. Similarly, the point pe designates an
arrow at the other end of the edge, connecting to the last spline point.
You may do this analitically, but a little math is needed.
A Bezier curve can be expressed in terms of the Bernstein Basis. Here I'll use Mathematica, that provides good support for the math involved.
So if you have the points:
pts = {{0, -1}, {1, 1}, {2, -1}, {3, 1}};
The eq. for the Bezier curve is:
f[t_] := Sum[pts[[i + 1]] BernsteinBasis[3, i, t], {i, 0, 3}];
Keep in mind that I am using the Bernstein basis for convenience, but ANY parametric representation of the Bezier curve would do.
Which gives:
Now to find the minimum distance to a point (say {3,-1}, for example) you have to minimize the function:
d[t_] := Norm[{3, -1} - f[t]];
For doing that you need a minimization algorithm. I have one handy, so:
NMinimize[{d[t], 0 <= t <= 1}, t]
gives:
{1.3475, {t -> 0.771653}}
And that is it.
HTH!
Edit Regarding your edit "B-spline with consisting of (n−1)/3 cubic Bezier curves."
If you constructed a piecewise B-spline representation you should iterate on all segments to find the minima. If you joined the pieces on a continuous parameter, then this same approach will do.
Edit
Solving your curve. I disregard the first point because I really didn't understand what it is.
I solved it using standard Bsplines instead of the mathematica features, for the sake of clarity.
Clear["Global`*"];
(*first define the points *)
pts = {{
29.124, 284.61}, {
25.066, 258.56}, {
20.926, 212.47}, {
34, 176}, {
38.706, 162.87}, {
46.556, 149.82}, {
54.393, 138.78}};
(*define a bspline template function *)
b[t_, p0_, p1_, p2_, p3_] :=
(1-t)^3 p0 + 3 (1-t)^2 t p1 + 3 (1-t) t^2 p2 + t^3 p3;
(* define two bsplines *)
b1[t_] := b[t, pts[[1]], pts[[2]], pts[[3]], pts[[4]]];
b2[t_] := b[t, pts[[4]], pts[[5]], pts[[6]], pts[[7]]];
(* Lets see the curve *)
Show[Graphics[{Red, Point[pts], Green, Line[pts]}, Axes -> True],
ParametricPlot[BSplineFunction[pts][t], {t, 0, 1}]]
.
( Rotated ! for screen space saving )
(*Now define the distance from any point u to a point in our Bezier*)
d[u_, t_] := If[(0 <= t <= 1), Norm[u - b1[t]], Norm[u - b2[t - 1]]];
(*Define a function that find the minimum distance from any point u \
to our curve*)
h[u_] := NMinimize[{d[u, t], 0.0001 <= t <= 1.9999}, t];
(*Lets test it ! *)
Plot3D[h[{x, y}][[1]], {x, 20, 55}, {y, 130, 300}]
This plot is the (minimum) distance from any point in space to our curve (of course the value over the curve is zero):
First, render the curve to a bitmap (black and white) with your favourite algorithm. Then, whenever you need, determine the nearest pixel to the mouse position using information from this question. You can modify the searching function so that it will return distance, so you can easilly compare it with your requirements. This method gives you the distance with tolerance of 1-2 pixels, which will do, I guess.
Definition: distance from a point to a line segment = distance from the original point to the closest point still on the segment.
Assumption: an algo to compute the distance from a point to a segment is known (e.g. compute the intercept with the segment of the normal to the segment passing through the original point. If the intersection is outside the segment, pick the closest end-point of the segment)
use the deCasteljau algo and subdivide your cubics until getting to a good enough daisy-chain of linear segments. Supplementary info the "Bezier curve flattening" section
consider the minimum of the distances between your point and the resulted segments as the distance from your point to the curve. Repeat for all the curves in your set.
Refinement at point 2: don't compute the actual distance, but the square of it, getting the minimum square distance is good enough - saves a sqrt call/segment.
Computation effort: empirically a cubic curve with a maximum extent (i.e. bounding box) of 200-300 results in about 64 line segments when flattened to a maximum tolerance of 0.5 (approx good enough for the naked eye).
Each deCasteljau step requires 12 division-by-2 and 12 additions.
Flatness evaluation - 8 multiplications + 4 additions (if using the TaxiCab distance to evaluate a distance)
the evaluation of point-to-segment distance requires at max 12 multiplications and 11 additions - but this will be a rare case in the context of Bezier flattening, I'd expect an average of 6 multiplications and 9 additions.
So, assuming a very bad case (100 straight segments/cubic), you finish in finding your distance with a cost of approx 2600 multiplications + 2500 additions per considered cubic.
Disclaimers:
don't ask me for a demonstration on the numbers in
the computational effort evaluation above,
I'll answer with "Use the source-code" (note: Java implementation).
other approaches may be possible and maybe less costly.
Regards,
Adrian Colomitchi

"Center of Mass" between a set of points on a Toroidally-Wrapped Map that minimizes average distance to all points

edit As someone has pointed out, what I'm looking for is actually the point minimizing total geodesic distance between all other points
My map is topographically similar to the ones in Pac Man and Asteroids. Going past the top will warp you to the bottom, and going past the left will warp you to the right.
Say I have two points (of the same mass) on the map and I wanted to find their center of mass. I could use the classical definition, which basically is the midpoint.
However, let's say the two points are on opposite ends of the mass. There is another center of mass, so to speak, formed by wrapping "around". Basically, it is the point equidistant to both other points, but linked by "wrapping around" the edge.
Example
b . O . . a . . O .
Two points O. Their "classical" midpoint/center of mass is the point marked a. However, another midpoint is also at b (b is equidistant to both points, by wrapping around).
In my situation, I want to pick the one that has lower average distance between the two points. In this case, a has an average distance between the two points of three steps. b has an average distance of two steps. So I would pick b.
One way to solve for the two-point situation is to simply test both the classical midpoint and the shortest wrapped-around midpoint, and use the one that has a shorter average distance.
However! This does not easily generalize to 3 points, or 4, or 5, or n points.
Is there a formula or algorithm that I could use to find this?
(Assume that all points will always be of equal mass. I only use "center of mass" because it is the only term I knew to loosely describe what I was trying to do)
If my explanation is unclear, I will try to explain it better.
The notion of center of mass is a notion relevant on affine spaces. The n-dimensional torus has no affine structure.
What you want is a point which minimizes (geodesic) distance to all the other points.
I suggest the following: let x_1...x_n be a collection of points on the d-dimensional torus (or any other metric space for that purpose).
Your problem:
find a point mu such that sum(dist(mu, x_k)^2) is minimal.
In the affine-euclidian case, you get the usual notion of center of mass back.
This is a problem you will be able to solve (for instance, there are probably better options) with the conjugate gradient algorithm, which performs well in this case. Beware that you need moderate n (say n < 10^3) since the algorithm needs n^2 in space and n^3 in time.
Perhaps better suited is the Levenberg-Marquardt algorithm, which is tailored for minimization of sum of squares.
Note that if you have a good initial guess (eg. the usual center of mass of the points seen as points in R^d instead of the torus) the method will converge faster.
Edit:
If (x1...xd) and (y1...yd) are points on the torus, the distance is given by
dist(x, y)^2 = alpha1^2 + ... + alphad^2
where alphai = min((xi - yi) mod 1, (yi - xi) mod 1)
I made a little program to check the goodness of the involved functions and found that you should be very carefull with the minimization process.
Below you can see two sets of plots showing the points distribution, the function to minimize in the euclidean case, and the one corresponding to the "toric metric".
As you may see, the euclidean distance is very well-behaved, while the toric present several local minima that difficult the finding of the global minima. Also, the global minimum in the toric case is not unique.
Just in case, the program in Mathematica is:
Clear["Global`*"];
(*Define non wrapping distance for dimension n*)
nwd[p1_, p2_, n_] := (p1[[n]] - p2[[n]])^2;
(*Define wrapping distance for dimension n *)
wd[p1_, p2_, max_,n_] := (max[[n]] - Max[p1[[n]], p2[[n]]] + Min[p1[[n]], p2[[n]]])^2;
(*Define minimal distance*)
dist[p1_, p2_, max_] :=
Min[nwd[p1, p2, 1], wd[p1, p2, max, 1]] +
Min[nwd[p1, p2, 2], wd[p1, p2, max, 2]];
(*Define Euclidean distance*)
euclDist[p1_, p2_, max_] := nwd[p1, p2, 1] + nwd[p1, p2, 2];
(*Set torus dimensions *)
MaxX = 20;
MaxY = 15;
(*Examples of Points sets *)
lCircle =
Table[{10 Cos[fi] + 10, 5 Sin[fi] + 10}, {fi, 0, 2 Pi - .0001, Pi/20}];
lRect = Join[
Table[{3, y}, {y, MaxY - 1}],
Table[{MaxX - 1, y}, {y, MaxY - 1}],
Table[{x, MaxY/2}, {x, MaxY - 1}],
Table[{x, MaxY - 1}, {x, MaxX - 1}],
Table[{x, 1}, {x, MaxX - 1}]];
(*Find Euclidean Center of mass *)
feucl = FindMinimum[{Total[
euclDist[#, {a, b}, {MaxX, MaxY}] & /# lRect], 0 <= a <= MaxX,
0 <= b <= MaxY}, {{a, 10}, {b, 10}}]
(*Find Toric Center of mass *)
ftoric = FindMinimum[{Total[dist[#, {a, b}, {MaxX, MaxY}] & /# lRect],
0 <= a <= MaxX, 0 <= b <= MaxY}, {{a, 10}, {b, 10}}]
In the 1 dimensional case, your problem would be analagous to finding a mean angle.
The mean of angles a and b can be computed by
mean = remainder( a + remainder( b-a, C)/2.0, C)
where C is the measure of a whole circle (ie 2*PI if you're using radians).
If you have n angles a[], the mean can be computed by
mean = a[0];
for i=1..n mean=remainder( mean + remainder( a[i]-mean, C)/(i+1), C)
So I reckon
meanX = X[0]; meanY = Y[0]
for i=1..n
meanX = remainder( meanX + remainder( X[i]-meanX, W)/(i+1), W)
meanY = remainder( meanY + remainder( Y[i]-meanY, H)/(i+1), H)
might do the job.
But note that this will result in -W/2<=meanX
IANATopologist, and I don't know how clear I'm making myself in this, but for what it's worth, these are some thoughts on the matter:
Using mass and gravity to calculate this sort of thing might indeed be elegant -- ISTR that there are a number of libraries and efficient algorithms to find the gravity vectors for any number of masses.
If you were using a spherical map, I'd suggest finding within the sphere the actual center of gravity for your N mass points. You then draw a line from the center outward through this inner center of gravity to find the point on the sphere's surface where your mass points wish to congregate.
However, a toroidal map makes this difficult.
My suggestion, then, is to flatten and copy your map to give you a 3 x 3 quilt of maps (using an infinite field of maps will give better results, but might be overkill). I'll assign coordinates (0, 0) to (2, 2) to them, with (1, 1) being your source map. Find the point(s) to which the mass points of your inner map (1, 1) are attracted -- if they all go towards the middle of your map, fine: you found your center of gravity. If not, if one of the points close to the edge is going towards some mass accumulation outside of your inner map, say into map (2, 1), then discard this mass point when calculating your center of gravity. Instead you use the mass point from the opposite map ((0, 1) in this case) that wants to wander over into your middle map.
Adding the acceleration vectors for these mass points gives you the center of gravity on your torus.
Done.

Resources