Plotting derived variables

Hi,

I am writing a function to read data from our simulation code output and plot with PyPlot. The data itself is mostly stored as an array with the 1st dimension as variable index and the rest as spatial indexes (1:nI,1:nJ, 1:nK). The output comes with a header, saving variable names as an array of strings:

filehead[1]
Dict{Symbol,Any} with 6 entries:
  :time      => 598.0
  :eqpar     => Float32[0.14, -1.0, 14.0, 1.0, 4.0e6, 2.634e6]
  :ndim      => 3
  :it        => 17939
  :wnames    => SubString{String}["qc", "divEc", "rhoS0", "rhoS1", "Bx", "By", "Bz", "Ex", "Ey", "Ez" ,…
  :nx        => Int32[45, 129, 142]

Then in the plotting wrapper function over PyPlot, my input arguments look like this:

plotdata(data[1],filehead[1],"rho",plotmode="contbar")

where the third argument of type string is used for searching in the header and find the correct variable to plot.

However, here comes the problem: if I want to plot a derived variable, say “rho/p” (density divided by pressure), how can I make it work using a generalized approach?

I have the feeling you are mixing responsibilities. It sounds like you are trying to augment the plotting function to do calculations (derived variables). In my opinion it’s not the right way to do it. Plotting should be just plotting…

Instead, a better approach IMHO would be to wrap the data in an appropriate type and then define operations on them which do additional checks (plausibility, compatibility, etc.).

Also calling a plotting function via something like plotdata(data[1],filehead[1],"rho",plotmode="contbar") exposes implementation details, which is a bit confusing and you are also exposing the internal API, which will be hard to change later on without breaking existing the codebase.

You should also have a look at https://github.com/JuliaPlots/RecipesBase.jl where you can define your own plot recipes for Plots.jl (which can use PyPlot as the plotting library).

2 Likes

I am not aware of that recipe base in Plots.jl before… Actually, I am using PyPlot directly instead of using matplotlib through Plots.jl because 1. not all features and controls are available using Plots.jl’s interface; 2. the grammars and logics in Plots.jl are somehow different from matplotlib and matlab, which makes the conversion for me a little bit difficult.

But yes, I agree with you: mixing calculations and plotting is really not a good idea, and passing arguments like plotmode to my wrapper function will become a huge limitation in the future. If I want to have full control of the plotting parameters, my current approach would need me to literally pass all parameters through the wrapper, which is not feasible. For this case the RecipesBase package would be extremely useful, and I will try to see if I can take advantage of that. At first glance I have the impression that this is the way to go, but I’m having trouble understanding the recipes and some examples seem outdated.

So I guess the basic workflow should be:

  1. Let the Plots.jl package understand my data type by dispatch

  2. Pass parameters directly through the plot function instead of creating my own wrapper

  3. Write another function which targets at generating derived variables for plotting.

Is that right?