How to use Fortran + gnuplot to plot in real time in just one window?

Dear all,

I have quick question, in my Fortran code, I want to display my real time y vs x by plotting. After some search, it seem Gnuplot a good choice. So I just want one Gnuplot popup window, in this windows the real time y vs x is updated and displayed, like an animation. Like below,

do i = 1, 100
    x(i) = xxxxxxxxxxxxxxxxxxxxx
    y(i) = yyyyyyyyyyyyyyyyyyyyy
   -> Gnuplot(  y(1:i)  vs x(1:i)  ) keep plot y vs x in real time in just one window during the loop.
enddo

Does anyone know how to do that?
I know there is nice Fortran + Gnuplot package ogpf,

But I am not very sure if it can be done in this package. It has animation function, but it seems it needs to wait until the whole loop finished, then plot the animation of y vs x. This is great, but I wanted to plot in real time during the loop. If I just use its plot function, every time I call it, it will popup a new Gnuplot window, this is not what I want.

Thank you very much in advance!

I can think of at least three ways to do this, although I doubt it is worth the effort.

(1) Create and save a gnuplot script in each iteration as well as the data from x(1) to x(i), then run the script (say, foo.plt) with call system('gnuplot -p foo.plt' ). The gnuplot script can be easily created with standard Fortran open, write, and close commands. It should clear the screen and plot on the same window each iteration. For this to look nice you should also know the x and y range of the plot (maxval(x) and maxval(y)), and use them each time for each plot.

(2) Alternatively, you can just save all your data once, then in each iteration use a gnuplot script to plot part of it. This involves GNU/Linux commands such as awk, again called in your program with the system command. The rest of the procedure is as in (1). More sophisticated but also more complicated.

(3) Use gnuplot streams. This can be done in several ways, but the outline of the method is described here (although this is in Pearl). I played with streams in the past, and I got the result I wanted, but in the end I wasn’t sure I prefer this solution over the others, even though in theory it is more “robust”.

However, I wouldn’t call any of the above an elegant solution. Don’t get me wrong, gnuplot is excellent software, I use it all the time. But it is not ideal for what you want to do, because gnuplot is external software that has nothing to do with Fortran. Using gnuplot within a Fortran program is perfectly ok if you just want to plot some results, but becomes unnecessarily complicated when it comes to animations.
If I wanted to do something like this, I would definitely look for other, more promising solutions: PLplot comes to mind first (alone or with gtk-fortran), or Dislin. Both can be used in your program as a Fortran module, so you can be more interactive without the hassle of relying on system commands.

Last but not least, I am not sure all this is worth the effort. Unless you have serious, time consuming computations needed to be done in each loop iteration, you wouldn’t see any animation since the frames would be plotted very quickly, so you would have to sleep your program in each iteration to actually see any frame. There is a reason people just save all the results, plot them with gnuplot, then create an animation using external software such as gimp or imagemagick.

3 Likes

I have found that recipe in the book Gnuplot in Action:

plot "data" u 1:2 w l
pause 30
reread

It should update the plot every 30 seconds. Let me know if it works!

2 Likes

reread should do the trick indeed. I still doubt gnuplot is the best tool for this task however. I would go for a more Fortran-native solution such as PLplot first.

2 Likes

I agree.

1 Like

If we have to use delays in order to see any frame, then why not just save all the results, then outside this loop, use PLplot within a gtk-fortran window with a nice slider to set the delay on the fly… Not to mention it will look way more impressive. :slight_smile:

2 Likes

It’s just a question of time…

1 Like

There used to be pgplot package but it was contemporary to dinosaurs :slight_smile:

1 Like

Yes, latest version is PGPLOT 5.2.2 Released 2001-02-26. :t_rex:

PGPLOT itself is written mostly in standard Fortran-77, with a few non-standard, system-dependent subroutines. PGPLOT subroutines can be called directly from a Fortran-77 or Fortran-90 program. A C binding library (cpgplot) and header file ( cpgplot.h ) are provided that allow PGPLOT to be called from a C or C++ program; the binding library handles conversion between C and Fortran argument-passing conventions.

Latest PLplot version is 5.15.0 (June 2019):

1 Like

I explored this recently when taking a course where my instructor would use gnuplot with reread. It works quite well, but another alternative is to use pyplot-fortran which calls Python’s Matplotlib from Fortran. Here’s an example code snippet that I constructed at the time. You can combine it with an image reader that would update automatically on change of the image to do what you want (Visual Studio Code for example).

program main
  use pyplot_module
  implicit none

  real :: x(100), y(100)
  type(pyplot) :: plt

  call plt%initialize()
  do
    call random_number(x)
    call random_number(y)
    call plt%add_plot(x, y, label="", linestyle=".")
    call plt%savefig("test.png")
!    call plt%destroy()
    call sleep(1)
  end do
end program main
1 Like

Thank you all! @Pap @vmagnin @msz59 @KjellJorner
I really appreciate you suggestions.
After some checking, yes pause and reread did the trick!
After installing Gnuplot (I am on windows 10 for this test), in the second line of my code as below,


I added command,

call execute_command_line ('wgnuplot -persist ' // 'ogpf_temp_script.gp' , wait = .false.) 

where ‘ogpf_temp_script.gp’ is my Gnuplot scipt, which I just use the one generated by ogpf library, but I added

pause 1
reread

at the end, it read the data from my output file which is called LL_iter.txt, it monitors the Log likelihood (LL) .vs. iteration,
Its content is

# ogpf libray
# Rev. 0.22 of March 9th, 2018
# Licence: MIT

# gnuplot global setting
set term wxt size 1024,768 enhanced font "verdana,10" title "ogpf libray: Rev. 0.22 of March 9th, 2018"

# ogpf extra configuration
# -------------------------------------------
# color definitions
set style line 1 lc rgb "#800000" lt 1 lw 2
set style line 2 lc rgb "#ff0000" lt 1 lw 2
set style line 3 lc rgb "#ff4500" lt 1 lw 2
set style line 4 lc rgb "#ffa500" lt 1 lw 2
set style line 5 lc rgb "#006400" lt 1 lw 2
set style line 6 lc rgb "#0000ff" lt 1 lw 2
set style line 7 lc rgb "#9400d3" lt 1 lw 2

# Axes
set border linewidth 1.15
set tics nomirror

# grid
# Add light grid to plot
set style line 102 lc rgb "#d6d7d9" lt 0 lw 1
set grid back ls 102

# plot style
set style data linespoints

# -------------------------------------------

 
# plot scale
 
# Annotation: title and labels
 
# axes setting

plot "LL_iter.txt" notitle
pause 1
reread

Here is an example of my code running while display the LL vs iteration in real time,
(179) RPEM + Gnuplot display LL in real time - YouTube

3 Likes

Looks like you have a solution, but on GNU/Linux and Linux machines we used to do this a lot for quick and dirty plotting, where you could just create a FIFO file with “mkfifo GNUPLOT.fifo” and then start a “gnuplot <GNUPLOT.fifo &” command and then write gnuplot commands to the file, like so:

>set terminal x11
>set nokey
>set title " example of gnuplot data and command file generation"
>$set1 <<eod
>  1.00000000 0.649542361E-1
>  2.00000000 0.104807168
>  295.000000 -0.675299585
>  296.000000 -0.645265579
>  297.000000 -0.614199281
>  298.000000 -0.582150400
>  299.000000 -0.549170196
>  300.000000 -0.515311420
>eod
> plot $set1 with lines
>undefine $set1
>$set1 <<eod
>  1.00000000 0.139543116
>  2.00000000 0.179029584
>  3.00000000 0.218229622
>  299.000000 -0.485006154
>  300.000000 -0.449647129
>eod
>plot $set1 with lines
>undefine $set1
>quit

If can be very fast on an X11 with backing store (very common now-adays). Later we changed it to to do a popen by calling the C routine and that worked even better; and options for pausing and sleeping between frames and such as mentioned above. Usind the gnuplot here documents for the data and an optional “stats $set1 using 1:2” and such, and being able to change the plot options from other processes writing to the FIFO file was handy; did that with other line mode commands too; mkfifo is a very underused command and can be used in a safer manner than some for allowing multiple user to input into a process running under another ID and so on.

2 Likes

This skips error processing and such, but on a GNU/Linux or Unix machine this should generate around 30 000, frames in about three minutes; albeit the plot is relatively basic (a polyline with 300 points) …

 program gnuplotexample
      implicit none
      character(len=:),allocatable  ::  line  
      character(len=*),parameter    :: g='(*(g0,1x))'
      integer  ::  ierr, ios, lun
      integer  ::  i, j, k
      integer , parameter  ::  n = 300 
      real  ::  x(n) , y(n)            
      call execute_command_line('mkfifo GNUPLOT.in')
      call execute_command_line('gnuplot --persist < GNUPLOT.in',wait=.false.)
      open(file='GNUPLOT.in',newunit=lun)
      write(lun,'(a)')&
      'set terminal X11',&
      'set nokey',&
      'set title " example of gnuplot data and command file generation"'
         do j = 1 , 30000 , 1
            do i = 1 , n                            !*! set x() values as whole numbers 1 to n
               x(i) = i
               y(i) = sin(x(i)/25.0+j/40.0)
            enddo
            call plotit()
         enddo
      write (*,*) ' returned to main program' 
      close(unit=lun,status='delete')
      contains
      subroutine plotit()
      write(lun,g)'$set1 <<eod'
      do i = 1 , n
         write (lun,g)' ', x(i) , y(i) !*! write the x,y array as coordinates to be plotted.
      enddo
      write(lun,'(a)')'eod', 'plot $set1 with lines'
      end subroutine plotit
end program gnuplotexample

Not sure if mkfifo has an equivalent on MSWIndows or not, but should work in Cygwin or a POSIX subsystem of your choice. We used to do that on Cygwin a lot.

PS: I was told MSWIndows supports named pipes, so this should be possible under “native” MSWIndows, but I do not have something at the moment I can try that on.

2 Likes

Birds are modern dinosaurs. (Check with your paleontologist friends.) Maybe I am contemporary with dinosaurs: I last used pgplot yesterday, with gfortran. Although
the innards of pgplot are mostly 77, it worked perfectly well with f2003 array constructors in subroutine arguments. My main problem with pgplot is that even though it was written by an astronomer it does not offer what astronomers call pomega and Latex calls \varomega. (Looks like lower case omega with ~ on top.)

3 Likes

Good to hear we’re not alone :slight_smile:
As for the dinosaurs, cf. list of environments (OSes, compilers, APIs) for which PGPlot was prepared:

sys_XXX list
sys_aix
sys_alliant
sys_arc
sys_bsd
sys_convex
sys_cray
sys_cygwin
sys_dos
sys_epix2
sys_freebsd
sys_fujitsu
sys_gnuwin32
sys_hp
sys_irix
sys_linux
sys_mac
sys_msdos
sys_next
sys_openstep
sys_osf1
sys_salford
sys_sol2
sys_solx86
sys_sun4
sys_ultrix
sys_vms
sys_win

Some of these sound strange even to my old ear.

1 Like

I said Latex called the “lower case omega with ~ on top” \varomega. A little hunting found that TLatex does that, but TeX calls it \varpi. And I should have mentioned that another problem with PGplot and LaTeX is that the former likes to draw Postscript plots ( .ps for Linux users) but the latter wants them to be either .ps or .pdf but not both in the same document, and some publishers are fussy about wanting .eps instead.

Nothing wrong with using pgplot today. First, “modern” replacements for old packages are not necessarily better. Second, “better” is highly subjective; the best tool is the tool you are familiar with and works fine for your needs.
Last but certainly not least, some dinosaurs can fly too… probably higher than modern birds. :laughing:

1 Like