Visualize eigenvectors at specified points?

I am very new to Mathematica and I got stuck about visualizing eigenvectors 2D and 3D. I want to visualize my largest eigenvector field of tensor data(15x15). I wrote this code for instance :

points = {{0, 0}, {1, 0}, {2, 0}, {0, 1}, {1, 1}, {2, 1}, {0, 2}, {1,
2}, {2, 2}};

ListVectorPlot[{{{0, 0}, {1, 1}}, {{1, 0}, {1, 0}}, {{2, 0}, {0,
1}}, {{0, 1}, {1, -1}}, {{1, 1}, {1, 1}}, {{2, 1}, {-1, 1}}, {{0,
2}, {0, 1}}, {{1, 2}, {-1, 0}}, {{2, 2}, {0, -1}}}, VectorPoints -> points, FrameLabel -> {x, y}, PerformanceGoal -> "Quality", Epilog -> {Red, PointSize[Medium], Point[points]}]


But my vectors don't begin from the specified point. ListVectorPlot function locate the vector in the middle of the point. Do you think I have to use another function like Arrow and Graphics?

In addition,I want to plot my second eigenvectors from the same point. For example, I have a matrix and its eigenvectors are {{1,1},{-6,5}} or {{4,5},{-1,3}}. At the end I have to multiply these vectors with their eigenvalues({{2,4}}) and visualize like that. How can I do that at specified points at an order and different lenghts of vectors(multiply with eigenvalues)?

Below you can find a basic example data,

datax = {{{{3, 4}, {4, 3}}, {{3, 4}, {4, 3}}, {{3, 4}, {4,
3}}}, {{{3, 6}, {6, 3}}, {{3, 6}, {6, 3}}, {{3, 6}, {6,
3}}}, {{{3, 5}, {4, 3}}, {{3, 5}, {4, 3}}, {{3, 5}, {4, 3}}}};
dataxv = Table[Eigenvectors[datax[[z, t]]], {z, 1, 3}, {t, 1, 3}];
dataxva = Table[Eigenvalues[datax[[z, t]]], {z, 1, 3}, {t, 1, 3}];


• @eolin For the second part of your question, can you give example data too? Just click on edit on the left side below your question and insert it. Oct 29, 2012 at 0:02
• Regarding the positioning of the arrows, see this question. Oct 29, 2012 at 8:25
• @halirutan Thank you for your interest. I have done a bit what I have asked as a second question but I couldn't do it exactly.
– cesm
Oct 29, 2012 at 8:39
• @SimonWoods Thank you very much. As for me, It is a confusing problem that VectorPlot has.
– cesm
Oct 29, 2012 at 8:41

Solution

You could use Graphics, Arrow and s which is a scaling factor and write

arrows = {{{0, 0}, {1, 1}}, {{1, 0}, {1, 0}}, {{2, 0}, {0, 1}}, {{0,
1}, {1, -1}}, {{1, 1}, {1, 1}}, {{2, 1}, {-1, 1}}, {{0, 2}, {0,
1}}, {{1, 2}, {-1, 0}}, {{2, 2}, {0, -1}}};
s = 0.3;
Graphics[{Arrow[{#1, #1 + s*Normalize[#2]}] & @@@ arrows, Red,
PointSize[0.03], Point[#1] & @@@ arrows}, Frame -> True]


Explanation

arrows is a list where every element has the form {p, v} where p is the starting point and v is the vector to draw. The Mathematica function Arrow needs a starting point and an end point to draw something. We have the starting points explicitly, but the end-points need to be calculated. This calculation is simple: when we want to start at a point p and go along a vector v we just need to add them and we get the endpoint.

Let's further say, we want that all arrows have a constant length s than we could in a first step make v of normal length (meaning having length 1) and then we multiply v with s:

s*Normalize[v]


Therefore, if we want to define a Function taking p and v as parameter and which draws an arrow, it would look like

f = Function[{p,v}, Arrow[{p, p + s*Normalize[v]}]]


Now we want to use this function and apply it as easy as possible to your list of points and vectors l which has the structure

l = {{p1, v1}, {p2, v2}, {p3, v3}}


If possible, we want to transform this in one step into

{f[p1, v1], f[p2, v2], f[p3, v3]}


Here, Apply is very handy. The operators @@ and @@@ are infix forms for apply at level 0 and apply at level 1 respectively. What this function does is, it replaces the Head of and expression with something else. Example

Blub @@ Boing[1, 2, 3]

(* Out[7]= Blub[1, 2, 3] *)


The Head Boing was replaced by Blub. If you now consider, that {1,2,3} is nothing more than List[1,2,3] you see what happens when you do

Plus @@ {1, 2, 3}

(* Out[8]= 6 *)


With your parameter list, we need this replacement of the head inside the list, therefore we have to use @@@

Boing @@@ l

(* Out[9]= {Boing[p1, v1], Boing[p2, v2], Boing[p3, v3]} *)


If we now use f instead of Boing everything is like we want it to be:

s = 0.3;
arrows = {{{0, 0}, {1, 1}}, {{1, 0}, {1, 0}}, {{2, 0}, {0, 1}}, {{0,
1}, {1, -1}}, {{1, 1}, {1, 1}}, {{2, 1}, {-1, 1}}, {{0, 2}, {0,
1}}, {{1, 2}, {-1, 0}}, {{2, 2}, {0, -1}}};
f = Function[{p, v}, Arrow[{p, p + s*Normalize[v]}]];

f @@@ arrows

(*
{Arrow[{{0, 0}, {0.212132, 0.212132}}], Arrow[{{1, 0}, {1.3, 0.}}],
Arrow[{{2, 0}, {2., 0.3}}], ...
*)


The last thing which need explanation is, that we don't really need to define f. We can just use it by writing the code where you need it.

Function[{p, v}, Arrow[{p, p + s*Normalize[v]}]] @@@ arrows


For the Function construct there is a shorter form where you don't give the parameters names like p and v. Just write the expression and refer to the first parameter as #1 and to the second as #2 and append an & at the end:

Arrow[{#1, #1 + s*Normalize[#2]}] & @@@ arrows


Now you should be prepared to understand the first code block in every detail.

You datax is a matrix of matrices having the following form

datax = {{{{3, 4}, {4, 3}}, {{3, 4}, {4, 3}}, {{3, 4}, {4, 3}}}, {{{3,
6}, {6, 3}}, {{3, 6}, {6, 3}}, {{3, 6}, {6, 3}}}, {{{3, 5}, {4,
3}}, {{3, 5}, {4, 3}}, {{3, 5}, {4, 3}}}};
MatrixForm[MapIndexed[Tooltip[MatrixForm[#1], #2] &, datax, {2}]]


I assume you want to plot the eigenvectors of the matrix in the upper left corner at position {1,1}, the vectors of the matrix right of it at position {1,2} and so on. (Run with the mouse over the entries if you evaluate the upper code. You'll see the positions).

Since I explained the first solution in detail, I will go a bit further now. Let's say we want a function, which

• takes a matrix mat and a point point
• calculates the Eigensystem of this matrix
• plots the normalized eigenvectors scaled by its eigenvalue as Arrow
• Shows the expression as Tooltip if you run with the mouse over it

Note, that I even Normalize the list of eigenvectors {e1,e2,..} so that their values are never bigger than 1 but the length-relation is kept alive. With this, the length of the arrows never exceeds 1:

drawSystem[mat_, point_] := Module[{evec, eval},
{eval, evec} = Eigensystem[mat];
{
Tooltip[Arrow[{point, point + #1*#2}],
Row[{#1, MatrixForm[#2]}]] & @@@
Transpose[{Normalize[eval], Normalize /@ evec}],
Red, PointSize[0.02], Point[point]
}
]


Now, you could use Table in the same way you you already did (but we will not):

Table[drawSystem[datax[[z, t]], {z, t}], {z, 1, 3}, {t, 1, 3}]


instead let me introduce you to MapIndexed. MapIndexed applies a function to each element of a list (or a matrix, or a tensor in general) and gives as second parameter the position. Look at the following example:

MapIndexed[f, {{a, b}, {c, d}}, {2}]

(* {{f[a, {1, 1}], f[b, {1, 2}]}, {f[c, {2, 1}], f[d, {2, 2}]}} *)


This is exactly what we need for our situation. f is the drawing function and the matrix {{{a, b}, {c, d}} is the matrix of matrices datax:

Graphics[MapIndexed[drawSystem, datax, {2}], Frame -> True]


• Outstanding answer! Oct 28, 2012 at 23:54
• @belisarius Thanks. I was afraid, that the code itself was useless to the OP. I started to explain it and it got longer and longer.. Oct 29, 2012 at 0:03
• Oh well ... the OP posted the question and went away. So let's hope he returns to check this one! Oct 29, 2012 at 0:10
• @halirutan Thank you again, I want 's' to change at every point, how can I do that? I created a list for s and tried to apply it at every point but I couldn't succeed it.
– cesm
Oct 29, 2012 at 22:02