Plot a complex function in Mathematica
Asked Answered
M

4

22

How can I make a Mathematica graphics that copies the behaviour of complex_plot in sage? i.e.

... takes a complex function of one variable, and plots output of the function over the specified xrange and yrange as demonstrated below. The magnitude of the output is indicated by the brightness (with zero being black and infinity being white) while the argument is represented by the hue (with red being positive real, and increasing through orange, yellow, ... as the argument increases).

Here's an example (stolen from M. Hampton of Neutral Drifts) of the zeta function with overlayed contours of absolute value:

zeta function complex_plot

In the Mathematica documentation page Functions Of Complex Variables it says that you can visualize complex functions using ContourPlot and DensityPlot "potentially coloring by phase". But the problem is in both types of plots, ColorFunction only takes a single variable equal to the contour or density at the point - so it seems impossible to make it colour the phase/argument while plotting the absolute value. Note that this is not a problem with Plot3D where all 3 parameters (x,y,z) get passed to ColorFunction.

I know that there are other ways to visualize complex functions - such as the "neat example" in the Plot3D docs, but that's not what I want.

Also, I do have one solution below (that has actually been used to generate some graphics used in Wikipedia), but it defines a fairly low level function, and I think that it should be possible with a high level function like ContourPlot or DensityPlot. Not that this should stop you from giving your favourite approach that uses a lower level construction!


Edit: There were some nice articles by Michael Trott in the Mathematica journal on:
Visualizing Riemann surfaces of algebraic functions, IIa, IIb, IIc, IId.
Visualizing Riemann surfaces demo.
The Return of Riemann surfaces (updates for Mma v6)

Of course, Michael Trott wrote the Mathematica guide books, which contain many beautiful graphics, but seem to have fallen behind the accelerated Mathematica release schedule!

Minimize answered 21/3, 2011 at 23:52 Comment(7)
I haven't read the question yet, but +1 for the lovely plot :)Melancholy
@belisarius: It's not my plot, but thanks!Minimize
Are you sure you can't pass (x, y, z) into ColorFunction in DensityPlot? I've been able to do something along the lines of DensityPlot[..., ColorFunction->Function[{x, y, z}, f[x,y,z]]]Ideology
@MikeBantegui: Note that only the x parameter in your function can be used and corresponds to the density at each point. See the first entry in the "MORE INFORMATION" section of the ColorFunction docs. It's strange that it doesn't yield a warning...Minimize
@Mike, only x is given any info, if you use ColorFunction->Function[{x,y,z}, Hue@(y/maxy)] you only get gray. But, using x/maxx gives you something.Kirtley
@Kirtley @belisarius @Brett: Do you think that it's just coincidence that Stephen Wolfram put Phase of a Complex Polynomial on the demonstration site a week after this SO question?Minimize
should probably be migrated to mathematica.stackexchange.comAdobe
C
21

Here's my attempt. I winged the color function a bit.

ParametricPlot[
 (*just need a vis function that will allow x and y to be in the color function*)
 {x, y}, {x, -6, 3}, {y, -3, 3},

 (*color and mesh functions don't trigger refinement, so just use a big grid*)
 PlotPoints -> 50, MaxRecursion -> 0, Mesh -> 50,

 (*turn off scaling so we can do computations with the actual complex values*)
 ColorFunctionScaling -> False,

 ColorFunction -> (Hue[
     (*hue according to argument, with shift so arg(z)==0 is red*)
     Rescale[Arg[Zeta[# + I #2]], {-Pi, Pi}, {0, 1} + 0.5], 1,

     (*fudge brightness a bit: 
       0.1 keeps things from getting too dark, 
       2 forces some actual bright areas*)
     Rescale[Log[Abs[Zeta[# + I #2]]], {-Infinity, Infinity}, {0.1, 2}]] &),

 (*mesh lines according to magnitude, scaled to avoid the pole at z=1*)
 MeshFunctions -> {Log[Abs[Zeta[#1 + I #2]]] &},

 (*turn off axes, because I don't like them with frames*)
 Axes -> False
 ]

complex plot

I haven't thought of a good way to get the mesh lines to vary in color. Easiest is probably to just generate them with ContourPlot instead of MeshFunctions.

Charest answered 22/3, 2011 at 2:45 Comment(2)
Nice! It's very close to the solution that I'd seen which uses RegionPlot[True, {x, xmin, xmax}, {y, ymin, ymax}, opts...] as the base Graphics object.Minimize
@BrettChampion Nice plot! Is there an easy way to include some kind of plotlegend where hue runs from -pi to pi ?Mcdade
M
15

Here's my variation on the function given by Axel Boldt who was inspired by Jan Homann. Both of the linked to pages have some nice graphics.

ComplexGraph[f_, {xmin_, xmax_}, {ymin_, ymax_}, opts:OptionsPattern[]] := 
 RegionPlot[True, {x, xmin, xmax}, {y, ymin, ymax}, opts, 
  PlotPoints -> 100, ColorFunctionScaling -> False,
  ColorFunction -> Function[{x, y}, With[{ff = f[x + I y]}, 
    Hue[(2. Pi)^-1 Mod[Arg[ff], 2 Pi], 1, 1 - (1.2 + 10 Log[Abs[ff] + 1])^-1]]]
 ]

Then we can make the plot without the contours by running

ComplexGraph[Zeta, {-7, 3}, {-3, 3}]

Zeta without contours

We can add contours by either copying Brett by using and showing a specific plot mesh in the ComplexGraph:

ComplexGraph[Zeta, {-7, 3}, {-3, 3}, Mesh -> 30, 
 MeshFunctions -> {Log[Abs[Zeta[#1 + I #2]]] &},
 MeshStyle -> {{Thin, Black}, None}, MaxRecursion -> 0]

or by combining with a contour plot like

ContourPlot[Abs[Zeta[x + I y]], {x, -7, 3}, {y, -3, 3}, PlotPoints -> 100,
 Contours -> Exp@Range[-7, 1, .25], ContourShading -> None];
Show[{ComplexGraph[Zeta, {-7, 3}, {-3, 3}],%}]

with contours

Minimize answered 22/3, 2011 at 4:28 Comment(0)
M
8

Not a proper answer, for two reasons:

  • This is not what you asked for
  • I'm shamelessly using Brett's code

Anyway, for me the following is much more clear to interpret (brightness is ... well, just brightness):

enter image description here

Brett's code almost intact:

Plot3D[
 Log[Abs[Zeta[x + I y]]], {x, -6, 3}, {y, -3, 3},
 (*color and mesh functions don't trigger refinement,so just use a big grid*)
 PlotPoints -> 50, MaxRecursion -> 0, 
 Mesh -> 50, 
 (*turn off scaling so we can do computations with the actual complex values*)
 ColorFunctionScaling -> False, 
 ColorFunction -> (Hue[
     (*hue according to argument,with shift so arg(z)==0 is red*)
     Rescale[Arg[Zeta[# + I #2]], {-Pi, Pi}, {0, 1} + 0.5], 
     1,(*fudge brightness a bit:
     0.1 keeps things from getting too dark,
     2 forces some actual bright areas*)
     Rescale[Log[Abs[Zeta[# + I #2]]], {-Infinity, Infinity}, {0.1, 2}]] &),
     (*mesh lines according to magnitude,scaled to avoid the pole at z=1*)
     MeshFunctions -> {Log[Abs[Zeta[#1 + I #2]]] &},
     (*turn off axes,because I don't like them with frames*)
     Axes -> False]
Melancholy answered 22/3, 2011 at 4:21 Comment(1)
Not a proper answer, but I agree - it does make some aspects more clear and it is pretty! +1Minimize
G
0

For everyone interested in achieving this in Python, I created cplot. Install with

pip install cplot

This plots the domain-coloring plot of the Taylor polynomial of degree 6 of exp:

import cplot


def exp_taylor(z):
    s = 1.0
    t = 1.0
    for k in range(1, 7):
        t *= z / k
        s += t
    return s

plt = cplot.plot(
    exp_taylor,
    # or something simpler
    # lambda z: z ** 6 + 1,
    (-5, +5, 400),
    (-5, +5, 400),
)
plt.show()

enter image description here

Governor answered 20/10, 2021 at 8:57 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.