1
$\begingroup$

I want to visualize a 2D vector field, e.g.,

Table[Exp[-(x^2 + y^2)/4] {y, -x}, {x, -3, 3, 0.2}, {y, -3, 3, 0.2}]

in the following way:

  • the arrow length denotes the vector length
  • the background color indicates the local vector orientation
  • the color becomes paler when the vector length decreases

Just something like the following. How can one achieve this in Mathematica?enter image description here

Edit

Using the Hue method in the answer below, I tried the following case. There looks to be some obvious mismatch: the vectors are still quite big while the colors already decay to white.

rmax = 5.0; rmesh = 0.1;
data = Table[{{x, y}, Exp[-(x^2 + y^2)/0.5] {y, -x}}, {x, -rmax, rmax,
     rmesh}, {y, -rmax, rmax, rmesh}];
maxnorm = Max[Map[Norm[#[[2]]] &, data, {2}]]
data = MapAt[#/maxnorm &, data, {All, All, 2}];
vp2 = ListVectorPlot[data, 
  Prolog -> {Map[{If[#[[1]] == {0, 0}, Hue[0, 0, 1], 
        Hue[ArcTan[#[[2, 1]], #[[2, 2]]]/(2 \[Pi]), Norm[#[[2]]], 1]],
        Rectangle[#[[1]] - rmesh/2, #[[1]] + rmesh/2]} &, data, {2}]},
   PlotRange -> rmax {{-1, 1}, {-1, 1}}, VectorColorFunction -> None, 
  VectorScaling -> Automatic, VectorStyle -> Black]

enter image description here

$\endgroup$
2
$\begingroup$

If I understood the requirements correctly, two ways you might be able to do it are using RegionPlot + VectorPlot or Graphics + ListVectorPlot. The first way is nice because you can continuously increase the resolution. The second way uses pre-calculated, discrete values which more closely match the example graphic.

rp = RegionPlot[
    -3 <= x <= 3 \[And] -3 <= y <= 3,
    {x, -3, 3},
    {y, -3, 3},
    BoundaryStyle -> None,
    ColorFunction -> (Hue[
       ArcTan[Exp[-(#1^2 + #2^2)/
            4] #2, -Exp[-(#1^2 + #2^2)/4] #1]/(2 \[Pi]), 
       Norm[Exp[-(#1^2 + #2^2)/4]], 1] &),
    ColorFunctionScaling -> False,
    PlotPoints -> 200,
    PlotRange -> {{-3, 3}, {-3, 3}}
  ];
vp = VectorPlot[
    Exp[-(x^2 + y^2)/4] {y, -x},
    {x, -3, 3},
    {y, -3, 3},
    VectorColorFunction -> None,
    VectorScaling -> Automatic,
    VectorStyle -> Black
  ];
Show[
  rp,
  vp
]

Non-list version of colourful vector plot.

The vectors go slightly outside of the plot, but the vectors could probably be adjusted to avoid that without too much difficulty. Here, the colourful background is provided by RegionPlot, and the the specific hue is controlled by the angle of the vector at a given point with the saturation controlled by the length of the vector. The brightness is 1 in all cases. As far as I can tell, that's how it worked in the example image so I tried to replicate that here. I think the ArcTan for the hue should be fine, but I'm not sure how robust using the Norm for the saturation will be. If the length of your vectors is greater than 1, the values for saturation will be clipped to 1, so keep that in mind.

We can also create a little colour wheel. This wheel can be added to either version, but here I've only added it to the discretized version of the plot.

wheel = RegionPlot[
  x^2 + y^2 <= 1,
  {x, -1, 1},
  {y, -1, 1},
  BoundaryStyle -> None,
  ColorFunction -> (Hue[ArcTan[#1, #2]/(2 \[Pi]), Sqrt[#1^2 + #2^2], 
      1] &),
  ColorFunctionScaling -> False,
  Frame -> False,
  PlotRangePadding -> 0.15,
  Epilog -> {
    Line[{{0, 0}, {0, 1}}],
    Line[{{0, #}, {0.05, #}}] & /@ {0, 0.5, 1},
    Text[Style[ToString[#], 16], {0.1, #}, {-1, 0}] & /@ {0, 0.5, 1}
    }
  ]

enter image description here

Then create our data points, make the plots, and add the wheel:

data = Table[
   {{x, y}, Exp[-(x^2 + y^2)/4] {y, -x}},
   {x, -3, 3, 0.2},
   {y, -3, 3, 0.2}
   ];
vp2 = ListVectorPlot[
  data,
  Prolog -> {
    Map[
     {
       If[
        #[[1]] == {0, 0},
        Hue[0, 0, 1],
        Hue[ArcTan[#[[2, 1]], #[[2, 2]]]/(2 \[Pi]), Norm[#[[2]]], 1]
        ],
       Rectangle[#[[1]] - 0.1, #[[1]] + 0.1]
       } &,
     data,
     {2}
     ]
    },
  PlotRange -> {{-3, 3}, {-3, 3}},
  VectorColorFunction -> None,
  VectorScaling -> Automatic,
  VectorStyle -> Black,
  Epilog -> {
    Inset[
     wheel,
     {3, 3},
     {1.12, 1.12},
     Scaled[0.3]
     ]
    }
  ]

Discretized version of the vector plot with background.

In this one, I'm creating the background by using Prolog in the ListVectorPlot and creating a bunch of rectangles of the correct hue and saturation. Prolog plots things before the rest of the plot and Epilog plots things after everything is said and done.

EDIT:

I just realized that my ListVectorPlot wasn't actually plotting every vector. This is because Mathematica thinks that it's too crowded (it's probably not wrong). If you would like every point to plot, add VectorPoints -> All as an option in ListVectorPlot to get:

Discretized vector plot with all points.

EDIT 2:

rmax = 5.0; 
rmesh = 0.1; 
data = Table[
  {{x, y}, Exp[-(x^2 + y^2)/1] {y, -x}}, 
  {x, -rmax, rmax, rmesh}, 
  {y, -rmax, rmax, rmesh}
]; 
maxnorm = Max[Map[Norm[#[[2]]] &, data, {2}]];
data = MapAt[#/maxnorm &, data, {All, All, 2}];
vp2 = ListVectorPlot[
  data, 
  Prolog -> {Map[{If[#[[1]] == {0, 0}, Hue[0, 0, 1], 
        Hue[ArcTan[#[[2, 1]], #[[2, 2]]]/(2 \[Pi]), Norm[#[[2]]], 1]],
        Rectangle[#[[1]] - rmesh/2, #[[1]] + rmesh/2]} &, data, {2}]},
  PlotRange -> rmax {{-1, 1}, {-1, 1}}, 
  VectorColorFunction -> None, 
  VectorScaling -> Automatic, 
  VectorSizes -> {0, 1}, 
  VectorStyle -> Black
]

Vector Plot with VectorSizes -> {0, 1}.

And with the option VectorPoints -> All added to the above code:

Vector plot with VectorSizes and VectorPoints.

EDIT 3:

Adding in VectorRange:

rmax = 5.0; 
rmesh = 0.1; 
data = Table[
  {{x, y}, Exp[-(x^2 + y^2)/1] {y, -x}}, 
  {x, -rmax, rmax, rmesh}, 
  {y, -rmax, rmax, rmesh}
]; 
maxnorm = Max[Map[Norm[#[[2]]] &, data, {2}]];
data = MapAt[#/maxnorm &, data, {All, All, 2}];
vp2 = ListVectorPlot[
  data, 
  Prolog -> {Map[{If[#[[1]] == {0, 0}, Hue[0, 0, 1], 
        Hue[ArcTan[#[[2, 1]], #[[2, 2]]]/(2 \[Pi]), Norm[#[[2]]], 1]],
        Rectangle[#[[1]] - rmesh/2, #[[1]] + rmesh/2]} &, data, {2}]},
  PlotRange -> rmax {{-1, 1}, {-1, 1}}, 
  VectorColorFunction -> None, 
  VectorRange -> {0, 1},
  VectorScaling -> "Linear", 
  VectorSizes -> {0, 1}, 
  VectorStyle -> Black
]

New vector plot.

$\endgroup$
14
  • $\begingroup$ Thanks your code to show how to use Hue! $\endgroup$ – cvgmt Jan 22 at 10:08
  • $\begingroup$ @cvgmt No problem! $\endgroup$ – MassDefect Jan 22 at 10:18
  • $\begingroup$ Thank you! This is an almost perfect answer. $\endgroup$ – xiaohuamao Jan 28 at 7:23
  • $\begingroup$ Could you please help look at the following code piece using your method? It looks weird that the arrows are still very big although the color almost disappears. I add a normalization of the vector length, by the way. rmax = 5.0; rmesh = 0.1; data = Table[{{x, y}, Exp[-(x^2 + y^2)/1] {y, -x}}, {x, -rmax, rmax, rmesh}, {y, -rmax, rmax, rmesh}]; maxnorm = Max[Map[Norm[#[[2]]] &, data, {2}]] data = MapAt[#/maxnorm &, data, {All, All, 2}]; $\endgroup$ – xiaohuamao Jan 28 at 14:23
  • $\begingroup$ vp2 = ListVectorPlot[data, Prolog -> {Map[{If[#[[1]] == {0, 0}, Hue[0, 0, 1], Hue[ArcTan[#[[2, 1]], #[[2, 2]]]/(2 \[Pi]), Norm[#[[2]]], 1]], Rectangle[#[[1]] - rmesh/2, #[[1]] + rmesh/2]} &, data, {2}]}, PlotRange -> rmax {{-1, 1}, {-1, 1}}, VectorColorFunction -> None, VectorScaling -> Automatic, VectorStyle -> Black] $\endgroup$ – xiaohuamao Jan 28 at 14:25
2
$\begingroup$

Maybe like this.

ListVectorDensityPlot[
 Table[{y, -x}, {x, -3, 3, 0.2}, {y, -3, 3, 0.2}], 
 ColorFunctionScaling -> False, VectorScaling -> True, 
 ColorFunction -> 
  Function[{x, y, vx, vy, n}, 
   Hue[If[vx == vy == 0, 0, ArcTan[vx, vy]/(2 π)]]], 
 VectorStyle -> Black, VectorColorFunction -> None]

enter image description here

$\endgroup$
2
  • $\begingroup$ Hue[Arg[vx + I*vy] $\endgroup$ – cvgmt Jan 22 at 9:31
  • $\begingroup$ Thanks for the nice answer. I eventually also found this method very useful since it generates smooth colors in the background. But I notice a weird issue recently. $\endgroup$ – xiaohuamao Mar 16 at 5:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.