fortran-lang / stdlib

Fortran Standard Library
https://stdlib.fortran-lang.org
MIT License
1.07k stars 164 forks source link

Plotting #401

Open Beliavsky opened 3 years ago

Beliavsky commented 3 years ago

Many Fortranners will want to plot data from within a Fortran program, and many Fortran-callable plotting libraries have been created. I have home-grown subroutines to call Gnuplot to make graphs, and there are public packages for this. Others call Python packages such as matplotlib.

Should stdlib have subroutines with interfaces such as

call plot(x,y,backend="gnuplot")

where generic plotting subroutines are defined? To use a specific backend, it would need to be installed on the user's computer. A default backend of line graphics could be included in stdlib. People have been writing line graphics subroutines since the 1960s. Starpac has them.

Romendakil commented 3 years ago

Sounds like a good idea in general. The crucial question to me would be how stable the API towards the graphics library is, i.e. how much maintenance would be needed and version tracking w.r.t. the external libraries?

hsnyder commented 3 years ago

I think we definitely need this, but I agree that we have to be careful about pulling in a bunch of dependencies by accident. Part of the difficulty is around managing the actual window where a plot is to be drawn. If we limit the API to simply generating an image in a memory buffer or as a file on disk, and let the user worry about actually looking at it, that would simplify things a lot, but ultimately it would be more useful if the API was also able to open windows for plotting in a platform-neutral way.

Regardless of how (and whether) we address the windowing issue, if we're going to offer this API we should offer a fallback back-end that just does software rasterization. I would be willing to write this or contribute to it.

One possible approach to bringing up a window and plotting in a cross-platform way would be to use OpenGL and GLFW. GLFW is offered under a fairly permissive license which may be compatible with stdlib.

urbanjost commented 3 years ago

If you first define a low-level API, then write high-level routines to call the low-level API the high-level routines become virtually maintenance free. If one of the "devices" supported uses reads and writes of metadata then to port to a new platform just requires making a simple GUI that reads and writes the metadata and displays a window, with optional direct drivers of OpenGL/Canvas/X11Windows/MSWindows. For basic graphics this works quite well; which is good enough for basic plotting. Full GUI support is another issue. I have placed high-level graphics on top of https://github.com/urbanjost/M_draw (a Fortran module on top of a modified version of the VOGLE graphics library) for years and have graphics programs that have run unmodified for many years. I started a pixel-only look-alike at https://github.com/urbanjost/M_pixel that could do the basics but needed better font and anti-aliasing and some high-level routines added but did not see much interest. The high-level routines I have are unfortunately proprietary in large part, but there were MANY Fortran graphics libraries at one time, and NCAR had an extensive one that included an entire scripting language that I think is still available and PD, but not sure. It is frustrating that Fortran owned graphics at one time and now it is hard to find a reliable way to draw a basic plot without descending into dependency heck.

hsnyder commented 3 years ago

@urbanjost Interesting work! Is M_pixel intended to be a pure-Fortran software rendering implementation of the M_draw API?

It sounds like we are headed towards a layered approach consisting of the plotting API, a low level vector graphics API, and then whatever implementations of that API are necessary to get it actually working on multiple platforms. As a related problem, we need to handle the actual creation of windows or saving of files in image formats.

I think we should design the high level plotting API last, as that will require the most community input. But I don't see why we couldn't start brainstorming or even writing the intermediate vector API and the actual implementations. Do you think we should use M_draw/M_pixel as that intermediate API?

urbanjost commented 3 years ago

I personally find the interface simple and easy to use using basic syntax and relatively easy to rewrite in pure Fortran except for the actual X11 and MSWindows calls, and it uses a similar model to GL in many ways; the M_pixel was the beginning of a rewrite centered around PIXEL images, whereas M_draw is almost exclusively vector-based. Hershey fonts are easily displayed in a 3-dimensional space but are probably not considered acceptable for a lot of uses. But is is quite simple and highly portable and not susceptible to code rot or dependency issues. So not against starting there, as I think it would have immediate value. Long term it is not very amenable to GUI construction or 3-D hidden surfaces. It certainly would be very valuable to be able to at least be able to make some plots directly using nothing but standard (or at least "stdlib") Fortran. That is certainly long overdue.

hsnyder commented 3 years ago

I agree, I don’t see a reason not to start with what you have here. Since you already have experience implementing high level routines on top of these, would you be able to identify a subset of M_draw that you think has the most useful functionality? I can then get started fleshing out a pure Fortran software rendering implementation, beginning with what you already have with M_pixel. In parallel with that we can begin the discussion about an actual plotting API (which I think will need a lot of eyes on it).