Visualizing Complex-Valued Functions Using Python (or Wolfram)
Tags: python, mathematics, visualization, github
Published: 2024-02-19 08:31:46

Today I was pouring through my "Complex Variables and Analytic Functions" book (written by the esteemed Bengt Fornberg and Cecile Piret), trying my best to wrap my mind around how complex function work and how to visualize them. The visualization part is extra difficult given that such a function takes a real and an imaginary input component, and outputs two such components as well. Therefore, a single 3D plot is not sufficient to "see" how the function behaves. Rather, we split the output into either an imaginary and real part, or into the magnitude and the argument/angle.

The plots in the book were helpful, but I wanted to be able to play around some more. Wolfram Mathematica is an excellent tool for such visual explorations.

# Wolfram Language

```
plotComplexFunction[f_]:=Module[{z,rePlot,imPlot,magPlot,phasePlot},z=x+I y;

rePlot = Plot3D[Re[f[z]],{x,-2,2},{y,-2,2},AxesLabel->{"Re(z)","Im(z)","Re(f(z))"},Mesh->None];

imPlot = Plot3D[Im[f[z]],{x,-2,2},{y,-2,2},
	AxesLabel->{"Re(z)","Im(z)","Im(f(z))"},
	Mesh->None];

magPlot = Plot3D[Abs[f[z]], {x, -2, 2}, {y, -2, 2}, 
  	AxesLabel -> {"Re(z)", "Im(z)", "Abs(f(z))"}, 
  	Mesh -> None, 
  	ColorFunction -> Function[{x, y, z}, ColorData["Rainbow"][Rescale[Arg[x + I y], {-Pi, Pi}]]], 
  	ColorFunctionScaling -> False];
  
phasePlot=DensityPlot[Arg[f[z]],{x,-2,2},{y,-2,2},
	ColorFunction->"Rainbow",
	PlotLegends->Automatic,
	AxesLabel->{"Re(z)","Im(z)"},
	PlotLabel->"Phase"];

GraphicsGrid[{{rePlot,imPlot},{magPlot,phasePlot}},ImageSize->800]];

f[z_]:=(1/2)*(z+1/z);
plotComplexFunction[f]
```
https://github.com/dreamchef/complex-functions-visualization

I wrote the above Mathematica code to produce a grid of plots showing the function in both ways just described. On the top, the imaginary and real parts of the function 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5jvem791tkemxu40g4of.png)

are shown, and on the bottom, and the magnitude, and the phase shown in color.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d4mzcyp7ze0ri1auv976.png)

After playing around with a few functions using this code and convincing myself that it made sense why other functions looked the way they did, I wanted to do the same in Python as an exercise.

# Python, PyPlot and complex-plotting-tools

I found an excellent project on GitHub (https://github.com/artmenlope/complex-plotting-tools) which I decided to use as a starting point, and potentially contribute to in the future. The repo provided a very easy interface for plotting complex-valued functions in a variety of ways. For example, after importing `numpy`, `matplotlib`, and the repo's `cplotting_tools module`, defining the function and calling `cplt.complex_plot3D(x, y, f, log_mode=False)` produces the following:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yfx2gjgehfsjhhazy9tu.png)

These are all for the same f(z) as above. To view the side-by-side imaginary and real parts of the function, use `cplt.plot_re_im(x, y, f, cmap="twilight", contour=False, alpha=0.9)`:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hdrfj132bx02rhckk4i7.png)

Additionally, the library provides other cool ways to study functions, including a stream plot:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3up50c941h7w31frmtzt.png)

# Future Direction

The library shows a lot of promise and is relatively easy to use! It does require a `pts` variable to be defined for a given function which encodes the poles and zeros of the function. Wolfram does not require this because it figures out this information under the hood, and it would be really nice if complex-plotting-tools had this functionality as well. Hopefully, I'll be able to figure out an implementation for this in the future and submit that change.

In the meantime, have fun plotting with Wolfram and Python, and send any questions or ideas for development my way!

Cheers!
Dani