Repository: kookma/ogpf
Branch: master
Commit: bd18021949be
Files: 11
Total size: 187.6 KB
Directory structure:
gitextract_axg7b2oj/
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── doc/
│ └── readme.txt
├── example/
│ └── demo.f90
├── fpm.toml
├── meson.build
├── revision.txt
├── sample_script.gp
└── src/
└── ogpf.f90
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# fpm build directory
build*
bin*
================================================
FILE: LICENSE
================================================
Copyright (c) 2012-2018 Mohammad Rahmani
! Author: Mohammad Rahmani
! Chem Eng Dep., Amirkabir Uni. of Tech
! Tehran, Ir
! url: aut.ac.ir/m.rahmani
! github: github.com/kookma
! email: m[dot]rahmani[at]aut[dot]ac[dot]ir
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: Makefile
================================================
#
# This Makefile was generated by Code::Blocks IDE.
#
SRCS_f90d1 = \
ogpf.f90
SRCS_f90d2 = \
demo.f90
OBJS_f90d1 = \
ogpf.o
OBJS_f90d2 = \
demo.o
SRC_DIR_f90d1 = \
./src/
SRC_DIR_f90d2 = \
./example/
OBJS_DIR = ./obj/Debug/
EXE_DIR = ./bin/Debug/
EXE = ogpf.exe
FC = gfortran.exe
LD = gfortran.exe
IDIR =
CFLAGS = -Wall -std=f2008 -Wl, -J$(OBJS_DIR) $(IDIR)
LFLAGS =
LIBS =
VPATH = $(SRC_DIR_f90d1):$(OBJS_DIR):$(SRC_DIR_f90d2)
OBJS = $(addprefix $(OBJS_DIR), $(OBJS_f90d1) $(OBJS_f90d2))
all : $(EXE)
$(EXE) : $(OBJS_f90d1) $(OBJS_f90d2)
@mkdir -p $(EXE_DIR)
$(LD) -o $(EXE_DIR)$(EXE) $(OBJS) $(LFLAGS) $(LIBS)
$(OBJS_f90d1):
@mkdir -p $(OBJS_DIR)
$(FC) $(CFLAGS) -c $(SRC_DIR_f90d1)$(@:.o=.f90) -o $(OBJS_DIR)$@
$(OBJS_f90d2):
@mkdir -p $(OBJS_DIR)
$(FC) $(CFLAGS) -c $(SRC_DIR_f90d2)$(@:.o=.f90) -o $(OBJS_DIR)$@
clean :
rm -f $(OBJS_DIR)*.*
rm -f $(EXE_DIR)$(EXE)
# Dependencies of files
demo.o: \
demo.f90 \
ogpf.o
ogpf.o: \
ogpf.f90
================================================
FILE: README.md
================================================
# ogpf
Object Based Interface to GnuPlot from Fortran (ogpf)
## Installation
__Prerequisite:__ [gnuplot](http://www.gnuplot.info/) must be installed on your system.
### Zero Installation Library
The ogpf is a **zero installation library**! Just copy and paste the `ogpf.f90` in your project folder or in your library folder and use it! No any further step is required. However if you like to add ogpf to your projects through package managers, builders, installers see below options!
###
Fortran Package Manager (fpm)
>To use ogpf with your [fpm](https://github.com/fortran-lang/fpm) project, add the following to your package manifest file (`fpm.toml`):
>
>```toml
>[dependencies]
>ogpf = { git = "https://github.com/kookma/ogpf.git" }
>```
>
>You can then `use` the package as normal in your Fortran program with `use ogpf`.
>
>To run the example program in this package with fpm:
>
>```sh
>$ git clone https://github.com/kookma/ogpf.git
>$ cd ogpf
>$ fpm build
>$ fpm run --example
>```
###
Meson Builder
>The alternative is through the use of the [Meson builder](https://mesonbuild.com/index.html), which is
>multiplatform and multi source language build system. You can just use the ogpf git repo as a
>subproject in your own meson project. If you're unfamiliar with it, just read this
>[begginer's guide](https://mesonbuild.com/SimpleStart.html).
>
>After learning the basics, you can create a folder called subprojects on the root of your project
>and create a file inside with the following content:
>
>```
>[wrap-git]
>url=https://github.com/kookma/ogpf
>revision=head
>```
>
>Then on the meson.build file you have to import the subproject and grab the library variable.
>This is a sample meson.build file:
>
>```python
>project('research','fortran')
>
>ogpf_proj = subproject('ogpf')
>ogpf_dep = ogpf_proj.get_variable('ogpf_dep')
>
>executable('research',
> dependencies: ogpf_dep)
>```
>and all the compiler flags will be handled.
# Usage
Make sure you have a working version of [gnuplot](http://www.gnuplot.info/) must be installed on your system. Start with provideed examples.
## 2D Plots
Simple plot | Animation
:-----------------------------:|:------------------------------------:
 | 
## 3D Plots
Surface | Contour
:-----------------------------:|:------------------------------------:
 | 
### GnuPlot Interface
Purpose: Object Based Interface to GnuPlot from Fortran (ogpf)
Platform: Windows XP/Vista/7/10, Linux
(It should work on other platforms, e.g Mac see the finalize_plot subroutine in ogpf.f90)
Language: Fortran 2003 and 2008
Requires: 1. Fortran 2003 compiler (e.g gfortran 4.7, IVF 12.1, and later ...)
There is only two more features needs Fortran 2008 standard
execute_command_line and passing internal function as argument.
2. gnuplot 5 and higher (other previous version can be used)
Author: Mohammad Rahmani
Chem Eng Dep., Amirkabir Uni. of Tech
Tehran, Ir
url: aut.ac.ir/m.rahmani
github: github.com/kookma
email: m[dot]rahmani[at]aut[dot]ac[dot]ir
License: MIT. Please always give a link to this repo
## PLotting Capabilities
### 2D Plots
* plot(v)
* plot(x,y)
* plot(x,y, linespec)
* plot(x1,y1,ls1, x2,y2,ls2, x3,y3,ls3, x4,y4,ls4)
* plot(x, M)
* semilogx(x,y)
* semilogy(x,y)
* loglog(x,y)
### 3D Plots
* surf(x,y,z)
* surf(x,y,z,lspec)
* surf(x,y,z, palette)
* surf(z, palette)
* contour(x,y,z,palette)
* contour(z,palette)
### Animation
* animation_start(delay)
* animation_show()
### Multiplot
* multiplot(rows, cols)
## Mathematical Utility Functions
* linspace(a,b,n)
* linspace(a,b)
* arange(a,b,dx)
* meshgrid(X,Y, xgv,ygv)
* meshgrid(X,Y, xgv)
## Color palette
Nine different color palettes are available. See [Ann Schnider](https://github.com/aschn/gnuplot-colorbrewer) gnuplot color palettes and [Gnuplotting](https://github.com/Gnuplotting/gnuplot-palettes).
These color palettes can be used with:
> `surf(x,y,z,palette='plt-name')`
> `contour(x,y,z,palette='plt-name')`
* set1
* set2
* set3
* palette1
* palette2
* paired
* dark2
* accent
* jet
## The ogpf library other features
There are plenty of commands to customise the plots. This includes:
* Plot annotation (e.g. title, xlabel, ylabel, and zlabel)
* Axes setting (e.g. xrange, yrange, zrange, and grid)
```fortran
call gp%axis([-1.0,+1.0]) ! Sets xrange
call gp%axis([-1.0,+1.0,-2.0,+2.0]) ! Sets both xrange and yrange
call gp%axis([-1.0,+1.0,-2.0,+2.0,-3.0,+3.0]) ! Sets all axis at same time
call gp%xlim([-1.0,+1.0]) ! Sets only the xrange
call gp%ylim([-2.0,+3.0]) ! Sets only the yrange
call gp%zlim([-3.0,+3.0]) ! Sets only the zrange
```
* Line and marker color and style
* Gnuplot options (e.g. fonts, tics format, frame format,... )
### The ogpf options command
The option command is a very powerful command and can be used to customize the gnuplot in many ways. Options can be set by calling the ogpf options.
In every call, it is possible to set several options separated by semicolon or options can be set by several calls. Below shows few samples:
* **Sample 1**
Set the legend (key) at the right bottom of window
`call gp%options('set key bottom right')`
* **Sample 2**
Define a new line style
`call gp%options('set style line 1 lc rgb "blue" lt 1 lw 2 pt 6 ps 1.5')`
* **Sample 3**
Use several options each uses separate command
`call gp%options('set tics')`
`call gp%options('set tics font ",8"') ! font size for tics`
* **Sample 4**
Set several options at the same time using semicolon as delimiter
`call gp%options('unset tics; unset colorbox') `
# Demo
There is a collection of examples in demo.f90 to show the capabilities of ogpf.
### Easy to use
To use ogpf in your project, add the library file to your fortran project (code)
* ogpf.f90 (the main library)
For details see 'demo.f90'
##### Important Note
To use ogpf on other operating system, you may need to modify the terminal type and fonts
in the section of **Configuration Parameters**.
A Makefile has been provided to build the demo from command line.
### Example codes
This section shows selected example codes from **demo.f90**
* **Example 1**
```fortran
SUBROUTINE Exmp01
!...............................................................................
!Example 1: A very basic example
!...............................................................................
TYPE(gpf):: gp
INTEGER, PARAMETER:: n=17
Real(wp):: x(n)
Real(wp):: y(n)
! Input data
x=dble([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])
y=dble([66,51,38,27,18,11,6,3,2,3,6,11,18,27,38,51,66])
! Annotation: set title, xlabel, ylabel
CALL gp%title('Example 1. A simple xy plot')
CALL gp%xlabel('my x axis ...')
CALL gp%ylabel('my y axis ...')
Call gp%options('set style data linespoints')
!Call Plot to draw a vector against a vector of data
CALL gp%plot(x, y)
END SUBROUTINE Exmp01
```
Will produce

* **Example 04**
Plot several data series at the same time
```fortran
subroutine exmp04
type(gpf):: gp
integer, parameter:: n=50
integer, parameter:: m=65
real(wp):: x(n)
real(wp):: y(n)
real(wp):: xv(m)
real(wp):: yv(m)
real(wp), parameter :: pi=4.d0*atan(1.d0)
! Input data
x=linspace(-pi,pi,n) !linspace is a utility function from module ogpf
y=sin(x)
xv=linspace(0.d0, 2.d0*pi,m)
yv=cos(2.d0*xv)
! This is the maximum number of plot can be drawn at the same time
! If you have more data see, you can plot can be used with matrices!
call gp%title('Example 4. Plot four data sets using gnuplot')
call gp%options('set key top left; set grid')
call gp%plot(x,y, 'title "sin(x)"', &
xv,yv, 'with lp lt 6 title "cos(2x)"', &
xv, 2.d0*yv, 'title "2cos(2x)" lt 7', &
xv, 0.5d0*yv, 'title "0.5cos(2x)" with points pt 8')
! Another example with keyboard arguments
call gp%plot(x1=x,y1=y,x2=xv,y2=yv)
end subroutine exmp04
```
Will produce


* **Example 05**
```fortran
SUBROUTINE Exmp05
!...............................................................................
! Example 5: Use line style and legends
!...............................................................................
TYPE(gpf):: gplot
INTEGER, PARAMETER:: n=50
Real(wp):: x(n)
Real(wp):: ys(n)
Real(wp):: yc(n)
Real(wp):: ysc(n)
Real(wp), PARAMETER :: pi=4.d0*atan(1.d0)
! Input data
x=linspace(-2.d0*pi,2.d0*pi,n) !linspace is a utility function from module Utils
ys=sin(x)
yc=exp(-0.1d0*x)*cos(x)
ysc=sin(x/2.d0)*cos(2.d0*x)
! Annotation, set title, xlabel, ylabel
CALL gplot%title('Example 5. A sample with style and legends')
CALL gplot%xlabel('x, rad')
CALL gplot%ylabel('y, dimensionless')
! Plot to draw three set of data
CALL gplot%plot(x,ys,'title "sin" with lines lt 5 lc rgb "#0008B0"', &
x,yc,'title "cos" with points lt 6 lc rgb "#FF1100"', &
x,ysc,'title "sin(x/2)cos(2x)" with lp lt 7 lc rgb "#00AA04"' )
END SUBROUTINE Exmp05
```
Will produce

* **Example 06**
```fortran
subroutine exmp06
type(gpf):: gplot
integer, parameter:: n=125
real(wp):: x(n)
real(wp):: y(n)
real(wp), parameter :: pi=4.d0*atan(1.d0)
! Input data
x=linspace(0.d0,pi*2.d0,n) !linspace is a utility function from module Utils
y=sin(6.d0*x)*exp(-x)
! Annotation, set title, xlabel, ylabel
call gplot%title('Example 6. A sample shows sin(x) and its zero on the plot')
call gplot%xlabel('x, rad')
call gplot%ylabel('sin(x), dimensionless')
call gplot%options('set grid')
! Plot to draw two set of data, a series and a single point
call gplot%plot(x,y,'title "sin(x)" with lines lt 2 lw 3', &
[pi],[0.d0],'title "zero" with points pt 7 ps 3 lc rgb "#FF0000"')
end subroutine exmp06
```
Will produce

* **Example 08**
Plotting matrix against a vector with customized linestyles
```fortran
subroutine exmp08
type(gpf):: matplot
integer, parameter:: n=25, m=6
integer :: i
real(wp):: tf
real(wp):: vo
real(wp):: g
real(wp):: t(n)
real(wp):: y(n,m)
!Create data
tf=10.d0
g=32.d0;
t=linspace(0.d0,tf,n)
do i = 1, m
vo = 25.0d0 * i
y(:, i) = vo*t-0.5d0*g*t**2
end do
!Draw the matrix y againest vector x
call matplot%title('Example 8. Plotting a Matrix against a vector')
call matplot%xlabel ('t, sec')
call matplot%ylabel ('y, feet')
call matplot%options('set xrange[0:10];set yrange [0:400];')
call matplot%plot(t, y)
!Another Matrix plot with legends and line specification
call matplot%title('Example 8.2: Matrix plot, legends and linespec')
call matplot%plot(t, 2.0d0*y(:,3:4), &
lspec='t "vo=100" w lp lt 6 ps 3 lw 2;&
& t "v=125" w lp lt 7 ps 3 lw 2 lc rgb "#ad6000"')
end subroutine exmp08
```
Will produce


* **Example 9**
Animation with 2D plot
```fortran
subroutine exmp09
type(gpf):: gp
integer, parameter:: n = 35
real(wp), parameter :: pi = 4.d0*atan(1.d0)
real(wp):: x(n)
real(wp):: y(n), z(n)
integer :: i
x=linspace(-pi, pi,n)
y = 0.0_wp
z = 0.0_wp
call gp%animation_start(1.0) ! start animation, set delay is one second between frames
call gp%axis([-pi, pi, -1.2_wp, 1.2_wp])
call gp%options('set grid')
! add frames
do i=1, n, 10
y(i) = sin(x(i))
z(i) = cos(x(i))
! each plot command adds one frame
call gp%plot(x(1:i),y(1:i), 'w lines lc "red" lw 2', &
x(i:i), y(i:i),'w points ps 3 pt 7 lc "red"', &
x(1:i),z(1:i), 'w lines lc "blue" lw 2', &
x(i:i), z(i:i), 'w points ps 3 pt 7 lc "blue"' )
end do
! finalize and show frames one by one with delay between them
! as set by animation_start
call gp%animation_show()
end subroutine exmp09
```
will produce

* **Example 10**
Use options
```fortran
subroutine exmp10()
type(gpf):: mp
real(wp):: x(15)
real(wp):: y(15)
!Options is a dynamic length string and can set all kind of gnuplot
call mp%options('set style line 1 lc rgb "#0060ad" lt 1 lw 2 pt 5 ps 1.5 # --- blue')
call mp%options('set style line 2 lc rgb "#ad6000" lt 2 lw 2 pt 6 ps 1.5 # --- red')
call mp%options('set style line 3 lc rgb "#00ad00" lt 2 lw 2 pt 7 ps 1.5 # --- green')
! this is a multipart string spanned over several lines
call mp%options('&
&set style data linespoints;&
&set xrange [0.1:100];&
&set yrange [0.01:10000];&
&set autoscale')
call mp%options('set key top left') ! set the key location
x=linspace(0.1d0,100d0,15);
y=x**2;
call mp%title("Example 10. x vs. x^2")
call mp%plot(x1=x, y1=1.50*y, ls1='t "y=1.5x^2" ls 1', &
x2=x, y2=2.00*y, ls2='t "y=2.0x^2" ls 2', &
x3=x, y3=2.50*y, ls3='t "y=2.5x^2" ls 3')
call mp%reset()
call mp%title('Reset to initial setting')
call mp%plot(x,2*y)
end subroutine exmp10
```
The first output is:

* **Example 11**
```fortran
subroutine exmp11
type(gpf):: gp
integer, parameter :: n=125
real(wp):: t(n)
real(wp):: r(n)
real(wp):: pi=4.d0*atan(1.d0)
!1. reset gplot
!!! CALL gp%reset()
! TODOD: There is a problem with reset, persist is off by reset
!2. set option, and set plot as polar
call gp%options("&
&set polar;&
&set trange [-pi:pi]")
! 3. create data
t=linspace(-pi,pi,n)
r=sin(3.d0*t)
!Annotation, set title, xlabel, ylabel
call gp%title("Example 11: simple polar plot")
call gp%xlabel("x,...")
call gp%ylabel("y,...")
!Call plot method
call gp%plot(t,r, 'title "sin(3t)"')
call gp%plot(t, cos(4*t))
end subroutine exmp11
```
Will produce


### Logarithmic scale
* **Example 13**
```fortran
subroutine exmp13
type(gpf):: gp
integer, parameter :: n=25
real(wp):: x(n)
real(wp):: y(n)
! 1. create data
x=linspace(0.1d0,10.d0,n)
y=5.d0*x**3+4.d0*x**2+3.d0*x+1.d0
!Annotation, set title, xlabel, ylabel
call gp%title("Example 13: A simple matrix plot with semi-log y")
call gp%ylabel("y,logarithmic scale")
call gp%xlabel("x, normal scale")
! plot a matrix against vector in logarithmic y axis with line specification
call gp%semilogy(x,reshape([y,10.d0*y],[n,2]), 'with lines lt 8; with points pt 7')
end subroutine exmp13
```
will produce

* **Example 14**
```fortran
subroutine exmp14
type(gpf):: gp
integer, parameter :: n=75
real(wp):: x(n)
real(wp):: y(n)
real(wp):: pi=4.d0*atan(1.d0)
! 1. create data
x=exp(linspace(0.d0,2.d0*pi,n))
y=50.d0+exp( 3.d0* linspace(0.d0,2.d0*pi,n) )
! 2. Annotation, set title, xlabel, ylabel
call gp%title("Example 14: A loglog plot")
call gp%xlabel("x,logarithmic scale")
call gp%ylabel("y,logarithmic scale")
! 3. Set grid on
call gp%options('set grid xtics ytics mxtics')
! 4. Call plot method
call gp%loglog(x,y)
end subroutine exmp14
```
will produce

* **Example 16**
Save the script file for future use
```fortran
subroutine exmp16()
type(gpf):: gp
real(wp):: pi=4.d0*atan(1.d0)
integer, parameter :: n=100
real(wp) :: x(n)
real(wp) :: y(n)
real(wp) :: z(n)
! create data
x = linspace(-pi, 3.0d0*pi)
y = sin(2.0d0*x)*exp(-x/5.0d0)
z = cos(2.0d0*x)*exp(-x/5.0d0)
! several gnuplot optuons
call gp%options('set border linewidth 1.5')
call gp%options('set style line 1 lc rgb "#ad6009" lt 1 lw 2 pt 7 ps 1.5 # --- red like')
call gp%options('set style line 2 lc rgb "#00ad09" lt 2 lw 2 pt 6 ps 1.5 # --- green like')
call gp%options('unset key')
call gp%options('set grid')
call gp%options('set ytics 1')
call gp%options('set tics scale 0.75')
call gp%title("Example 16. Save the script into file for future use")
call gp%xlabel("x...")
call gp%ylabel("y...")
! save the script into a file
call gp%filename("Example16.gp")
call gp%plot(x, y, ls1='with lp ls 1', x2=x, y2=z, ls2='with lp ls 2')
print* ! empty line
print*, 'Plot commands were written in Example16.gp successfully'
print*, 'Open gnuplot and load this script file to plot the results!'
print* ! empty line
end subroutine exmp16
```
will produce

* **Example 17**
Use add_script and run_script to do versatile operation with gnuplot
```fortran
subroutine exmp17()
! Script is used to create multi window plots
! Each "set term wxt " creates a new window
type(gpf):: gp
call gp%add_script('set term wxt 0 title "My first plot" size 640,480')
call gp%add_script('set title "Example 17. Multi windows plot using script"')
call gp%add_script('plot x*x+2*x+1')
call gp%add_script('set term wxt 1 title "My second plot"')
call gp%add_script('set ylabel "xsin(x)"')
call gp%add_script('plot x*sin(x)')
call gp%run_script()
end subroutine exmp17
```
will produce


* **Example 18**
```fortran
subroutine exmp18()
!Use gnuplot script
!to send a special external script file to gnuplot
!the file is an external file here is called "simple.plt"
type(gpf):: gp
! add some options and commands
call gp%title("Example 18. Running an external script file")
call gp%add_script('load "sample_script.gp" ')
! run script
call gp%run_script()
end subroutine exmp18
```
Will produce

* **Example 20**
Scatter plot
```fortran
subroutine exmp20()
!...............................................................................
! Example 20: Making a scatter plot
!...............................................................................
type(gpf):: gp
integer, parameter :: n=750
real(wp) :: x(n), y(n), ym(n), noise(n), d(n)
real(wp) :: a, b
! generate data
a = 00.0_wp
b = 05.0_wp
! 1. generate the model data
x = linspace(a,b,n)
ym = sqrt(x) ! model data
! 2. generate the measured data with noise (ensembles the experimental data)
call random_number(noise) ! generate noise in [0, 1]
d = (b-a)/100.0_wp * (x-a)**2 ! define the deviation function
d = 2.0_wp*(noise - 0.5_wp) * d ! distribute noise around y=0
y = ym + d
call gp%title('Example 20. Scatter plot')
call gp%xlabel('x,....')
call gp%options('set key top left')
call gp%options('set autoscale fix')
call gp%options('set style line 1 lc rgb "blue" lt 1 lw 2 pt 6 ps 1.5')
call gp%plot(x, y, 't "exp data" with points pt 6 ps 1.2 lc rgb "#ad2060"', &
x, ym, 't "mode: y=sqrt(x)" w lines lt 1 lw 3 lc "blue"')
! plot only the experimental data
call gp%title('Example 20. Scatter plot: data with noise')
call gp%plot(x,y,'w l lc "blue"', x, ym, 'w l lc "dark-red" lw 2')
end subroutine exmp20
```
Will produce


* **Example 21**
Stem plot
```fortran
subroutine exmp21()
!...............................................................................
! Example 21: Making a stem plot
!...............................................................................
type(gpf):: gp
integer, parameter :: n=50
real(wp) :: x(n), y(n)
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
! generate data
x = linspace(0.0_wp, 4.0_wp*pi, n)
y = exp(-x/4.0)*sin(x)
call gp%title('Example 21. Stem plot')
! making plot
call gp%plot(x,y, 'with impulses lw 2.5', &
x, y, 'with points pt 7')
end subroutine exmp21
```
Will produce

* **Example 22**
Animation with stem plot
```fortran
subroutine exmp22()
!...............................................................................
! Example 22: Stem plot animation
!...............................................................................
type(gpf):: gp
integer, parameter :: n=50
real(wp) :: x(n), y(n)
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
integer :: i
! generate data
x = linspace(0.0_wp, 4.0_wp*pi, n)
y = exp(-x/4.0)*sin(x)
! important, set the xy axis range
call gp%axis([0.0_wp, 4.0_wp*pi, -1.0_wp, 1.0_wp])
! start animation
call gp%animation_start(delay=1.) ! one second delay between frames
do i=1,n ! add frames
! each plot command adds one frame
call gp%plot(x(1:i), y(1:i), 'with impulses lw 2', &
x(1:i), y(1:i), 'with points pt 6')
end do
! finalize and show all frames in ornithological order with pause as
! set by animation_start
call gp%animation_show()
end subroutine exmp22
```
Will produce

* **Example 25**
Multiplot layout
```fortran
subroutine exmp25()
type(gpf):: gp
integer, parameter :: n=25
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
real(wp) :: x(n), y(n,4)
integer :: i
x=linspace(-pi, pi, n)
y(:,1) = sin(x)
y(:,2) = sin(x)*cos(x)
y(:,3) = (1-x)*sin(x)
y(:,4) = (1-x)*cos(x)
! general options
call gp%options('set tics font ",8"')
call gp%multiplot(2,2)
do i=1, 4
call gp%plot(x, y(:,i), 'lt 4 pt 6')
end do
! a new window will be started when all places in the multiplot
! layout is occupied. The multiplot window will be closed
call gp%plot(x,y)
end subroutine exmp25
```
Will produce


## 3D plots: surf and contour
* **Example 101**
Using different color palettes
```fortran
subroutine exmp101
type(gpf):: gp
real(wp), allocatable:: x(:,:)
real(wp), allocatable:: y(:,:)
real(wp), allocatable:: z(:,:)
real(wp):: a=0.5d0
real(wp):: b=2.0d0
real(wp), allocatable :: xgrid(:)
real(wp), allocatable :: ygrid(:)
integer:: m
integer:: n
! create 3D data
m=55 ! number of grid points in y direction
n=25 ! number of grid points in x direction
xgrid=linspace(-10.0_wp, 10.0_wp, m)
ygrid=linspace(0.0_wp, 5.0_wp, n)
allocate( z(m,n) )
call meshgrid(x, y, xgrid, ygrid) ! generate the 2D grid data
z=(x**2/a - y**2/b)
! annotation
call gp%title('Example 101: Simple 3D plot')
call gp%xlabel('x-axis,...')
call gp%ylabel('y-axis,...')
call gp%zlabel('z-axis,...')
!plot the 3D data
call gp%surf(x, y, z, lspec='t "default color spec"' ) ! color palette: gnuplot default
call gp%surf(x, y, z, lspec='t "Ann Schnider set1"', palette='set1' ) ! color palette: set1
call gp%surf(x, y, z, lspec='t "Matlab Jet"', palette='jet' ) ! color palette: Matlab jet
end subroutine exmp101
```
Will produce



* **Example 102**
Simple surface plot with color palette
```fortran
subroutine exmp102()
type(gpf):: gp
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
real(wp), allocatable:: x(:,:)
real(wp), allocatable:: y(:,:)
real(wp), allocatable:: z(:,:)
integer:: m
integer:: n
! generate data
call meshgrid(x, y, linspace(-0.75_wp*pi, 0.75_wp*pi, 35) ) ! xgrid == ygrid
m=size(x,1)
n=size(x,2)
allocate( z(m,n) )
!z= sin(x) * cos (y)
where (x**2 + y**2 == 0.0_wp)
z=1.0_wp
elsewhere
z=sin(x**2+y**2)/(x**2+y**2)
end where
call gp%title('Example 102: Simple 3D plot with color palette')
call gp%xlabel('x-axis,...')
call gp%ylabel('y-axis,...')
call gp%options('set style data lines')
!plot the 3D data
CALL gp%surf(X,Y,Z, palette='jet')
end subroutine exmp102
```
Will produce

* **Example 103**
A beautiful surface and contour plot
```fortran
subroutine exmp103()
type(gpf):: gp
real(wp), allocatable:: x(:,:)
real(wp), allocatable:: y(:,:)
real(wp), allocatable:: z(:,:)
real(wp):: a=-0.5_wp
real(wp):: b= 0.5_wp
real(wp):: pi= 4.0_wp * atan(1.0_wp)
integer:: m
integer:: n
! create 3D data
call meshgrid( x, y, linspace(a, b, 55) )
m=size(x,1)
n=size(x,2)
allocate( z(m,n) )
z= cos(2.0*pi*x) * sin(2.0*pi*y)
! annotation
call gp%title('Example 103: A beautiful surface plot with hidden details')
call gp%options('set hidden3d')
call gp%options('unset key')
!plot the 3D data
call gp%surf(x, y, z, palette='jet' ) ! color palette: Matlab jet
! contour
call gp%contour(x,y,z, palette='set1')
end subroutine exmp103
```
Will produce


* **Example 104**
Cylindrical mapping
```fortran
subroutine exmp104()
type(gpf):: gp
integer, parameter :: m = 35
integer, parameter :: n = 15
real(wp) :: xv(m), yv(n)
real(wp), dimension(:,:), allocatable:: x,y,z
real(wp):: pi= 4.0_wp * atan(1.0_wp)
xv = linspace(0.0_wp, pi, m)
yv = linspace(0.0_wp, pi, n)
call meshgrid(x,y, xv, yv)
allocate( z(size(x,dim=1), size(x, dim=2)) )
z = sin(y)
! advanced options
call gp%options('set mapping cylindrical')
call gp%options('unset tics')
call gp%options('unset border')
call gp%options('set view 147,312')
call gp%options('set hidden3d')
!
call gp%title('Example 104. Cylindrical Mapping')
call gp%surf(x,y,z)
end subroutine exmp104
```
Will produce

* **Example 105**
Contour plot and surface plot with color palette
```fortran
subroutine exmp105()
type(gpf):: gp
real(wp), allocatable:: x(:,:)
real(wp), allocatable:: y(:,:)
real(wp), allocatable:: z(:,:)
integer:: m
integer:: n
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
! create the xyz data
call meshgrid(x, y, linspace(-2.0_wp,2.0_wp, 65), linspace(-2.0_wp,3.0_wp, 65) )
m=size(x,1)
n=size(x,2)
allocate( z(m,n) )
z = x * exp(-x**2 - y**2)
call gp%options('unset key')
call gp%options('unset surface')
call gp%axis([real(wp):: -2, 2, -2, 3])
!plot the contour
call gp%title('Example 105: Contour plot')
call gp%options('unset border; unset tics')
call gp%surf(x,y,z, palette='accent')
call gp%contour(x,y,z, palette='jet')
end subroutine exmp105
```
Will produce


* **Example 106**
Animation with 3D plots
```fortran
subroutine exmp106()
type(gpf):: gp
integer, parameter :: n=25, m=55
real(wp) :: xv(m), yv(n), t
real(wp), allocatable :: x(:,:), y(:,:), z(:,:)
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
! generate data
xv = linspace(0.0_wp, 2.0_wp*pi, m)
yv = linspace(0.0_wp, 2.0_wp*pi, n)
call meshgrid(x, y, xv, yv)
z = sin(x) + cos(y)
call gp%title('Example 106. Animation of surface plot')
call gp%axis([0.0_wp, 2.0*pi, 0.0_wp, 2.0*pi])
call gp%options('unset colorbox')
call gp%options('set ticslevel 0')
call gp%axis([0.0_wp, 2.0*pi, 0.0_wp, 2.0*pi, -2.0_wp, 2.0_wp])
call gp%animation_start(1.0)
t=0.050_wp
do
! add frames
call gp%surf(x, y, sin(t*pi/2.0)*z, palette='jet')
t=t+0.1_wp
if (t > 1.0_wp) exit
end do
! show frames in ornithological order with a pause set in
! animation_start
call gp%animation_show()
end subroutine exmp106
```
Will produce

* **Example 107**
Multiplot layout for 3D plots
```fortran
subroutine exmp107()
!...............................................................................
!Example 107: Multiplot layout in 3D and Contour plot
!...............................................................................
type(gpf):: gp
real(wp), allocatable:: x(:,:)
real(wp), allocatable:: y(:,:)
real(wp), allocatable:: z1(:,:)
real(wp), allocatable:: z2(:,:)
integer:: m
integer:: n
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
! create the xyz data
call meshgrid(x, y, linspace(-pi,pi, 60) )
m=size(x,1)
n=size(x,2)
allocate( z1(m,n) )
allocate( z2(m,n) )
z1 = sin(x) + cos(y)
z2 = sin(x) * cos(y)
call gp%options('unset key')
call gp%axis([-pi,pi,-pi,pi])
call gp%options('unset colorbox')
call gp%options('set autoscale fix')
call gp%options('unset tics')
!plot the contour
call gp%title('Example 105: Contour plot')
call gp%multiplot(1,2)
call gp%surf(x,y,z1)
call gp%surf(x,y,z2)
call gp%multiplot(2,1)
call gp%options('set colorbox')
call gp%options('set tics')
call gp%options('set tics font ",8"') ! font size for tics
call gp%contour(x,y,z1, palette='jet')
call gp%contour(x,y,z2, palette='set1')
end subroutine exmp107
```
Will produce

================================================
FILE: doc/readme.txt
================================================
This folder contains some outputs generated by demo.f90
Rev 0.2
March 1st, 2018
================================================
FILE: example/demo.f90
================================================
!-------------------------------------------------------------------------------
! GnuPlot Interface
!-------------------------------------------------------------------------------
! Purpose: Object Based Interface to GnuPlot from Fortran (ogpf)
! Platform: Windows XP/Vista/7/10
! (It should work on other platforms, see the Write2GnuPlot subroutine below)
! Language: Fortran 2003 and 2008
! Requires: 1. Fortran 2003 compiler (e.g gfortran 4.7, IVF 12.1, ...) or 2008
! 2. gnuplot 4.5 and higher (other previous version can be used
! Author: Mohammad Rahmani
! Chem Eng Dep., Amirkabir Uni of Tech
! Tehran, Ir
! url: aut.ac.ir/m.rahmani
! email: m[dot]rahmani[at]aut[dot]ac[dot]ir
! License: MIT
! This file demonstrate the capability of ogpf module
! An object based Fortran interface to gnuplot
!
! Acknowledgement:
! Special thanks to Hagen Wierstorf (http://www.gnuplotting.org)
! For vluable codes and examples on using gnuplot
! Some examples and color palletes are provided by gnuplotting.
!
!
! Revision 0.22
! Date: Mar 9th, 2018
! - see ogpf.f90 for details
! - more examples to reflect the new features
! Revision: 0.20
! Date: Feb 20th, 2018
! - more examples
! - animation of 2D and 3D plots
! Revision: 0.19
! Date: Jan 15th, 2018
! - new contour plot procedure
! Revision: 0.18
! Date: Dec 22th, 2017
! More example based on ogpf 0.18
! Version: 0.17
! Date: Dec 18th, 2017
! Minor corrections
! - Multi window plots using script
! Version: 0.16
! Date: Feb 11th, 2016
! Minor corrections
! Correct the lspec processing in plot2D_matrix_vs_vector
! Some examples revised!
! Version: 0.15
! Date: Apr 20th, 2012
! Minor corrections
! Use of select_precision module and working precision: wp
! Version: 0.14
! Date: Mar 28th, 2012
! Minor corrections
! use of import keyboard and removing ogpf precision module
! Version: 0.13
! Date: Feb 12th, 2012
! Minor corrections
! Added more samples
! Use ogpf precision module
! Version: 0.12
! Date: Feb 9th, 2012
! New examples for semilogx, semilogy, loglog
! New set options method
! Version: 0.11
! Date: Feb 9th, 2012
program demo
use ogpf
implicit none
! parameters
! local variables
integer:: i=0
mainloop: do
print* ! empty line
print*, "gpf: gnuplot from Fortran Demonstration"
print*, "Example 1: Demo for xy plot"
print*, "Example 2: Line specification"
print*, "Example 3: Plot several data series at the same time"
print*, "Example 4: Plot four data series at the same time"
print*, "Example 5: Use line style, line colors and more..."
print*, "Example 6: An interesting plot, sin(x) and its zero on the same plot"
print*, "Example 7: Plot a matrix against a vector"
print*, "Example 8: Plot a matrix against a vector and set the linespec and legend"
print*, "Example 9: Use gnuplot for animation"
print*, "Example 10: Use ogpf options"
print*, "Example 11: simple polar plot"
print*, "Example 12: A plot with logarithmic x axis"
print*, "Example 13: A matrix plot with logarithmic y axis"
print*, "Example 14: A loglog plot"
print*, "Example 15: Plotting a function"
print*, "Example 16: Save the gnuplot script into a file for future use"
print*, "Example 17: Multi window plots, using script"
print*, "Example 18: Running an external script file"
print*, "Example 19: Multiple linestyle in matrix plot"
print*, "Example 20: Scatter plot"
print*, "Example 21: Stem plot"
print*, "Example 22: Stem plot animation"
print*, "Example 23: Another animation using matrix plot"
print*, "Example 24: Multiplot layout"
print*, "Example 25: Multiplot layout followed by simple plot"
print*, "Example 26: Plot matrix vs. matrix"
print*, "Example 27: Using secondary y axis"
print*, "Example 28: Using secondary x and y axis"
print*, "Example 29: Using color and size for title and labels"
print*, "Example 30: More on labels color and size with secondary axes"
print*
print*, "*** Surface and Contour Plots ***"
print*
print*, "Example 101: Simple 3D plot using surf"
print*, "Example 102: Surface plot and color palette "
print*, "Example 103: Surface plot with hidden details and its contour"
print*, "Example 104: Cylindrical mapping"
print*, "Example 105: More contour plot"
print*, "Example 106: Animation of 3D plots"
print*, "Example 106: Multiplot layout in 3D"
print*, "Example 107: Multiplot layout for 3D data"
print*, "Example 108: Plot a 2D grid"
print*, "Example 109: Plot a 2D grid with random data, but use zlim to select a zrange"
print*
write (unit=*, fmt='(a)') "2D plots: select an example: 1 through 30"
write (unit=*, fmt='(a)') "3D plots: select an example: 101 through 109"
write (unit=*, fmt='(a)', advance='no') "enter 0 for exit: "
read*, i
select case(i)
case(1)
call exmp01
case(2)
call exmp02
case(3)
call exmp03
case(4)
call exmp04
case(5)
call exmp05
case(6)
call exmp06
case(7)
call exmp07
case(8)
call exmp08
case(9)
call exmp09
case(10)
call exmp10
case(11)
call exmp11
case(12)
call exmp12
case(13)
call exmp13
case(14)
call exmp14
case(15)
call exmp15
case(16)
call exmp16
case(17)
call exmp17
case(18)
call exmp18
case(19)
call exmp19
case(20)
call exmp20
case(21)
call exmp21
case(22)
call exmp22
case(23)
call exmp23
case(24)
call exmp24
case(25)
call exmp25
case(26)
call exmp26
case(27)
call exmp27
case(28)
call exmp28
case(29)
call exmp29
case(30)
call exmp30
! 3D plots
case(101)
call exmp101
case(102)
call exmp102
case(103)
call exmp103
case(104)
call exmp104
case(105)
call exmp105
case(106)
call exmp106
case(107)
call exmp107
case(108)
call exmp108
case(109)
call exmp109
case (0)
print*, "Program terminated successfully"
exit mainloop
case default
print*, "Try again, use a valid example number"
print*, "Enter 0 to exit"
end select
print*
print*, "press any key to continue..."
read*
end do mainloop
contains
!...............................................................................
!Example 1: A very basic example
!...............................................................................
subroutine exmp01
type(gpf):: gp
integer, parameter:: n=17
real(wp):: x(n)
real(wp):: y(n)
! Input data
! x=dble([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])
x=dble([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])
x= abs(x) + 5
y=dble([66,51,38,27,18,11,6,3,2,3,6,11,18,27,38,51,66])
! Annotation: set title, xlabel, ylabel
call gp%title('Example 1. A simple xy plot','#990011')
call gp%xlabel('my x axis ...','#99aa33',font_name="Tahoma")
! call gp%ylabel('my y axis ...')
call gp%options('set border lc "#99aa33"; set ylabel "my label..." tc "#99aa33"')
call gp%options('set logscale y2')
call gp%plot(x, y)
end subroutine exmp01
!...............................................................................
!Example 2: Set line specification and legends
!...............................................................................
subroutine exmp02
type(gpf):: gp
integer, parameter:: n=17
real(wp):: x(n)
real(wp):: y(n)
! Input data
x=dble([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])
y=dble([66,51,38,27,18,11,6,3,2,3,6,11,18,27,38,51,66])
! Annotation: set title, xlabel, ylabel, line specification
call gp%title('Example 2. A simple xy plot')
call gp%xlabel('my x axis ...')
call gp%ylabel('my y axis ...')
!Call Plot to draw a vector against a vector of data
!The last argument defines the line specification
call gp%plot(x,y,'with linespoints lt 2 pt 4')
end subroutine exmp02
!...............................................................................
! Example 3: Plot several data set at the same time
!...............................................................................
subroutine exmp03
type(gpf):: g
integer, parameter:: n = 50
integer, parameter:: m = 65
real(wp):: x(n)
real(wp):: y(n)
real(wp):: xv(m)
real(wp):: yv(m)
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
! Input data
x=linspace(-pi,pi,n) !linspace is a utility function in ogpf module
y=sin(x) !linspace(a,b,n) create a linear vector in [a,b] with n elements
xv=linspace(0.d0, 2.d0*pi,m)
yv=cos(2.d0*xv)
! Annotation, set title, xlabel, ylabel
call g%title('Example 3. Plot two data series using gnuplot')
call g%xlabel(' x axis ...')
call g%ylabel(' y axis ...')
call g%options('set key top left')
! Sample 1: Plot to draw two set of data
call g%plot(x,y,'title "sin"','', xv,yv,'title "cos"')
!Sample 2: Use keyword arguments to plot the same example as above
call g%title('Example 3. Another plot using keyword arguments...')
call g%plot(x1=x,y1=y,ls1='pt 8',x2=xv,y2=yv,ls2='title "cos(2x)"')
! Sample 3: An xy plot with line specification no legends
call g%title('Example 3. Another plot without keyword arguments...')
call g%plot(x,y,'title "sin(x)" with points pt 6 lc "blue"', '',xv,yv,'title "cos(2x)" pt 7 lc rgb "#993300"')
end subroutine exmp03
!...............................................................................
! Example 4: Plot four data series, the maximum number of data series can be plotted!
!...............................................................................
subroutine exmp04
type(gpf):: gp
integer, parameter:: n=50
integer, parameter:: m=65
real(wp):: x(n)
real(wp):: y(n)
real(wp):: xv(m)
real(wp):: yv(m)
real(wp), parameter :: pi=4.d0*atan(1.d0)
! Input data
x=linspace(-pi,pi,n) !linspace is a utility function from module ogpf
y=sin(x)
xv=linspace(0.d0, 2.d0*pi,m)
yv=cos(2.d0*xv)
! This is the maximum number of plot can be drawn at the same time
! If you have more data see, you can plot can be used with matrices!
call gp%title('Example 4. Plot four data sets using gnuplot')
call gp%options('set key top left; set grid')
call gp%plot(x,y, 'title "sin(x)"', '', &
xv,yv, 'with lp lt 6 title "cos(2x)"', '', &
xv, 2.d0*yv, 'title "2cos(2x)" lt 7', '', &
xv, 0.5d0*yv, 'title "0.5cos(2x)" with points pt 8')
! Another example with keyboard arguments
call gp%plot(x1=x,y1=y,x2=xv,y2=yv)
end subroutine exmp04
!...............................................................................
! Example 5: Use line style, line color and moree
!...............................................................................
subroutine exmp05
type(gpf):: gplot
integer, parameter:: n=50
real(wp):: x(n)
real(wp):: ys(n)
real(wp):: yc(n)
real(wp):: ysc(n)
real(wp), parameter :: pi=4.d0*atan(1.d0)
! Input data
x=linspace(-2.d0*pi,2.d0*pi,n) !linspace is a utility function from module Utils
ys= sin(x)
yc= exp(-0.1d0*x)*cos(x)
ysc= sin(x/2.d0)*cos(2.d0*x)
! Annotation, set title, xlabel, ylabel
call gplot%title('Example 5. A sample with customized line style')
call gplot%xlabel('x, rad')
call gplot%ylabel('y, dimensionless')
! Plot to draw three set of data
call gplot%plot( &
x,ys, 'title "sin" with lines lt 5 lc rgb "#0008B0"', '', &
x,yc, 'title "cos" with points lt 6 lc rgb "#FF1100"', '', &
x,ysc,'title "sin(x/2)cos(2x)" with lp lt 7 lc rgb "#00AA04"' )
end subroutine exmp05
!...............................................................................
! Example 6: Plot a single point along with a series of data
!...............................................................................
subroutine exmp06
type(gpf):: gplot
integer, parameter:: n=125
real(wp):: x(n)
real(wp):: y(n)
real(wp), parameter :: pi=4.d0*atan(1.d0)
! Input data
x=linspace(0.d0,pi*2.d0,n) !linspace is a utility function from module Utils
y=sin(6.d0*x)*exp(-x)
! Annotation, set title, xlabel, ylabel
call gplot%title('Example 6. A sample shows f(x) and its zero on the plot')
call gplot%xlabel('x, rad')
call gplot%ylabel('f(x) = sin(6x)exp(-x) dimensionless')
call gplot%options('set grid')
! Plot to draw two set of data, a series and a single point
call gplot%plot(x,y,'title "sin(6x)exp(-x)" with lines lt 2 lw 3', '', &
[pi],[0.d0],'title "zero" with points pt 7 ps 3 lc rgb "#FF0000"')
end subroutine exmp06
!...............................................................................
! Example 7: Plot a matrix against a vector
!...............................................................................
subroutine exmp07
type(gpf):: g
integer, parameter:: n=25
real(wp), parameter :: pi=4.d0*atan(1.d0)
real(wp):: x(n)
real(wp):: y(n,6)
!Create data
x=linspace(-pi,pi,n)
y(:,1)=sin(x)
y(:,2)=cos(x)
y(:,3)=cos(0.5d0*x)
y(:,4)=sin(0.5d0*x)
y(:,5)=sin(x)*cos(x)
y(:,6)=sin(x)*exp(-x**2)
!Draw the matrix y against vector x
call g%title ('Example 7. Plotting a Matrix against a vector')
call g%xlabel ('my x axis')
call g%ylabel ('my y axis')
call g%plot (x, y)
end subroutine exmp07
!...............................................................................
! Example 08. Plot a matrix against a vector and set the linespec and legend (key)
!...............................................................................
subroutine exmp08
type(gpf):: matplot
integer, parameter:: n=25, m=6
integer :: i
real(wp):: tf
real(wp):: vo
real(wp):: g
real(wp):: t(n)
real(wp):: y(n,m)
!Create data
tf=10.d0
g=32.d0;
t=linspace(0.d0,tf,n)
do i = 1, m
vo = 25.0d0 * i
y(:, i) = vo*t-0.5d0*g*t**2
end do
!Draw the matrix y againest vector x
call matplot%title('Example 8. Plotting a Matrix against a vector')
call matplot%xlabel ('t, sec')
call matplot%ylabel ('y, feet')
call matplot%options('set xrange[0:10];set yrange [0:400];')
call matplot%plot(t, y)
!Another Matrix plot with legends and line specification
call matplot%title('Example 8.2: Matrix plot, legends and linespec')
call matplot%plot(t, 2.0d0*y(:,3:4), &
lspec='t "vo=100" w lp lt 6 ps 3 lw 2;&
& t "v=125" w lp lt 7 ps 3 lw 2 lc rgb "#ad6000"')
end subroutine exmp08
!...............................................................................
! Example 09: Use gnuplot for annimation
!...............................................................................
subroutine exmp09
type(gpf):: gp
integer, parameter:: n = 35
real(wp), parameter :: pi = 4.d0*atan(1.d0)
real(wp):: x(n)
real(wp):: y(n), z(n)
integer :: i
x=linspace(-pi, pi,n)
y = 0.0_wp
z = 0.0_wp
call gp%animation_start(1.) ! start animation, set delay is one second between frames
call gp%axis([-pi, pi, -1.2_wp, 1.2_wp])
call gp%title('A beautiful animation using ogpf library', textcolor='#aa5500')
! add frames
do i=1, n, 1
y(i) = sin(x(i))
z(i) = cos(x(i))
! each plot command adds one frame
call gp%plot(x(1:i),y(1:i), 'w lines lc "red" lw 2','', &
x(i:i), y(i:i),'w points ps 3 pt 7 lc "red"','', &
x(1:i),z(1:i), 'w lines lc "blue" lw 2', '',&
x(i:i), z(i:i), 'w points ps 3 pt 7 lc "blue"' )
end do
! finalize and show frames one by one with delay between them
! as set by animation_start
call gp%animation_show()
end subroutine exmp09
!...............................................................................
! Example 10: Use gnuplot options
!...............................................................................
subroutine exmp10()
type(gpf):: mp
real(wp):: x(15)
real(wp):: y(15)
!Options is a dynamic length string and can set all kind of gnuplot
call mp%options('set style line 1 lc rgb "#0060ad" lt 1 lw 2 pt 5 ps 1.5 # --- blue')
call mp%options('set style line 2 lc rgb "#ad6000" lt 2 lw 2 pt 6 ps 1.5 # --- red')
call mp%options('set style line 3 lc rgb "#00ad00" lt 2 lw 2 pt 7 ps 1.5 # --- green')
! this is a multipart string spanned over several lines
call mp%options('&
&set style data linespoints;&
&set xrange [0.1:100];&
&set yrange [0.01:10000];&
&set autoscale')
call mp%options('set key top left') ! set the key location
x=linspace(0.1d0,100d0,15);
y=x**2;
call mp%title("Example 10. x vs. x^2")
call mp%plot(x1=x, y1=1.50*y, ls1='t "y=1.5x^2" ls 1', &
x2=x, y2=2.00*y, ls2='t "y=2.0x^2" ls 2', &
x3=x, y3=2.50*y, ls3='t "y=2.5x^2" ls 3')
call mp%reset()
call mp%title('Reset to initial setting')
call mp%plot(x,2*y)
end subroutine exmp10
!...............................................................................
! Example 11: A simple polar plot
!...............................................................................
subroutine exmp11
type(gpf):: gp
integer, parameter :: n=125
real(wp):: t(n)
real(wp):: r(n)
real(wp):: pi=4.d0*atan(1.d0)
!1. reset gplot
!!! CALL gp%reset()
! TODOD: There is a problem with reset, persist is off by reset
!2. set option, and set plot as polar
call gp%options("&
&set polar;&
&set trange [-pi:pi]")
! 3. create data
t=linspace(-pi,pi,n)
r=sin(3.d0*t)
!Annotation, set title, xlabel, ylabel
call gp%title("Example 11: simple polar plot")
call gp%xlabel("x,...")
call gp%ylabel("y,...")
!Call plot method
call gp%plot(t,r, 'title "sin(3t)"')
call gp%plot(t, cos(4*t))
end subroutine exmp11
!...............................................................................
! Example 12: A simple plot with logarithmic x axis
!...............................................................................
subroutine exmp12
type(gpf):: gp
integer, parameter :: n=70
real(wp):: x(n)
real(wp):: y(n)
! 1. create data
x=linspace(0.0d0,10.d0,n)
y=10**(exp(-x/2.d0)*sin(2.d0*x))
!Annotation, set title, xlabel, ylabel
call gp%title("Example 12: A semi-log x plot")
call gp%xlabel("x,logarithmic scale")
call gp%ylabel("y, normal scale")
!Sample 1
call gp%semilogx(y,x)
end subroutine exmp12
!...............................................................................
! Example 13: A simple matrix plot with logarithmic y axis
!...............................................................................
subroutine exmp13
type(gpf):: gp
integer, parameter :: n=25
real(wp):: x(n)
real(wp):: y(n)
! 1. create data
x=linspace(0.1d0,10.d0,n)
y=5.d0*x**3+4.d0*x**2+3.d0*x+1.d0
!Annotation, set title, xlabel, ylabel
call gp%title("Example 13: A simple matrix plot with semi-log y")
call gp%ylabel("y,logarithmic scale")
call gp%xlabel("x, normal scale")
! plot a matrix against vector in logarithmic y axis with line specification
call gp%semilogy(x,reshape([y,10.d0*y],[n,2]), 'with lines lt 8; with points pt 7')
end subroutine exmp13
!...............................................................................
! Example 14: A simple plot with logarithmic xy axes
!...............................................................................
subroutine exmp14
type(gpf):: gp
integer, parameter :: n=75
real(wp):: x(n)
real(wp):: y(n)
real(wp):: pi=4.d0*atan(1.d0)
! 1. create data
x=exp(linspace(0.d0,2.d0*pi,n))
y=50.d0+exp( 3.d0* linspace(0.d0,2.d0*pi,n) )
! 2. Annotation, set title, xlabel, ylabel
call gp%title("Example 14: A loglog plot")
call gp%xlabel("x,logarithmic scale")
call gp%ylabel("y,logarithmic scale")
! 3. Set grid on
call gp%options('set grid xtics ytics mxtics')
! 4. Call plot method
call gp%loglog(x,y)
end subroutine exmp14
!...............................................................................
! Example 15: Plotting a function
!...............................................................................
subroutine exmp15()
type(gpf):: gp
real(wp):: pi=4.d0*atan(1.d0)
call gp%title("Example 15. Plotting a function using fplot")
call gp%xlabel("x...")
call gp%ylabel("y...")
! call fplot to plot a function in range of [a, b] with n points
call gp%fplot(myfun,[0d0,15.d0*pi],150)
end subroutine exmp15
function myfun(x)
! The function to be plotted
! see example 15
real(wp), intent(in) :: x
real(wp):: myfun
myfun=x*sin(x)
end function myfun
!...............................................................................
! Example 16: Save the gnuplot script into a file for future use
!...............................................................................
subroutine exmp16()
type(gpf):: gp
real(wp):: pi=4.d0*atan(1.d0)
integer, parameter :: n=100
real(wp) :: x(n)
real(wp) :: y(n)
real(wp) :: z(n)
! create data
x = linspace(-pi, 3.0d0*pi)
y = sin(2.0d0*x)*exp(-x/5.0d0)
z = cos(2.0d0*x)*exp(-x/5.0d0)
! several gnuplot optuons
call gp%options('set border linewidth 1.5')
call gp%options('set style line 1 lc rgb "#ad6009" lt 1 lw 2 pt 7 ps 1.5 # --- red like')
call gp%options('set style line 2 lc rgb "#00ad09" lt 2 lw 2 pt 6 ps 1.5 # --- green like')
call gp%options('unset key')
call gp%options('set grid')
call gp%options('set ytics 1')
call gp%options('set tics scale 0.75')
call gp%title("Example 16. Save the script into file for future use")
call gp%xlabel("x...")
call gp%ylabel("y...")
! save the script into a file
call gp%filename("Example16.gp")
call gp%plot(x, y, ls1='with lp ls 1', x2=x, y2=z, ls2='with lp ls 2')
print* ! empty line
print*, 'Plot commands were written in Example16.gp successfully'
print*, 'Open gnuplot and load this script file to plot the results!'
print* ! empty line
end subroutine exmp16
!...............................................................................
! Example 17: Plot in two separate windows using script
!...............................................................................
subroutine exmp17()
! Script is used to create multi window plot
! Each "set term wxt " creates a new window
type(gpf):: gp
call gp%add_script('set term wxt 0 title "My first plot" size 640,480')
call gp%add_script('set title "Example 17. Multi windows plot using script"')
call gp%add_script('plot x*x+2*x+1')
call gp%add_script('set term wxt 1 title "My second plot"')
call gp%add_script('set ylabel "xsin(x)"')
call gp%add_script('plot x*sin(x)')
call gp%run_script()
end subroutine exmp17
!...............................................................................
! Example 18: Running an external script file
!...............................................................................
subroutine exmp18()
!Use gnuplot script
!to send a special external script file to gnuplot
!the file is an external file here is called "simple.plt"
type(gpf):: gp
! add some options and commands
call gp%title("Example 18. Running an external script file")
call gp%add_script('load "sample_script.gp" ')
! run script
call gp%run_script()
end subroutine exmp18
!...............................................................................
!Example 19: USE multiple linespec in plotting a matrix vs a vector
!...............................................................................
subroutine exmp19
! see also example 8
type(gpf):: gp
integer, parameter:: n=17
real(wp):: x(n)
real(wp):: y(n,8)
integer :: j
! Input data
x=linspace(0.d0,10.d0,17)
do j=1, 8
y(:,j)=dble(3*j)
end do
!Annotation, set title, xlabel, ylabel
call gp%title('Example 19. Matrix plot with different line specification')
call gp%xlabel('my x axis ...')
call gp%ylabel('my y axis ...')
call gp%options('set key bottom right')
call gp%axis([-2.d0,20.d0,-2.d0,20.d0])
!Call Plot to draw a matrix against a vector of data
call gp%plot(x,y,lspec='with linespoints lt 1 title "lt 1";&
& with lp lt 2 title "lt 2";&
& with lp lt 3 title "lt 3";&
& with lp lt 4 title "lt 4";&
& with lp lt 5 title "lt 5";&
& with lp lt 6 title "lt 6";&
& with lp lt 7 title "lt 7";&
& with lp lt 8 title "lt 8"')
end subroutine exmp19
!...............................................................................
! Example 20: Making a scatter plot
!...............................................................................
subroutine exmp20()
type(gpf):: gp
integer, parameter :: n=750
real(wp) :: x(n), y(n), ym(n), noise(n), d(n)
real(wp) :: a, b
! generate data
a = 00.0_wp
b = 05.0_wp
! 1. generate the model data
x = linspace(a,b,n)
ym = sqrt(x) ! model data
! 2. generate the measured data with noise (ensembles the experimental data)
call random_number(noise) ! generate noise in [0, 1]
d = (b-a)/100.0_wp * (x-a)**2 ! define the deviation function
d = 2.0_wp*(noise - 0.5_wp) * d ! distribute noise around y=0
y = ym + d
call gp%title('Example 20. Scatter plot')
call gp%xlabel('x,....')
call gp%options('set key top left')
call gp%options('set autoscale fix')
call gp%options('set style line 1 lc rgb "blue" lt 1 lw 2 pt 6 ps 1.5')
call gp%plot(x, y, 't "exp data" with points pt 6 ps 1.2 lc rgb "#ad2060"', &
x2=x, y2=ym, ls2='t "mode: y=sqrt(x)" w lines lt 1 lw 3 lc "blue"')
! plot only the experimental data
call gp%title('Example 20. Scatter plot: data with noise')
call gp%plot(x,y,'w l lc "blue"', x2=x, y2=ym, ls2='w l lc "dark-red" lw 2')
end subroutine exmp20
!...............................................................................
! Example 21: Making a stem plot
!...............................................................................
subroutine exmp21()
type(gpf):: gp
integer, parameter :: n=50
real(wp) :: x(n), y(n)
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
! generate data
x = linspace(0.0_wp, 4.0_wp*pi, n)
y = exp(-x/4.0)*sin(x)
call gp%title('Example 21. Stem plot')
! making plot
call gp%plot(x,y, 'with impulses lw 2.5', &
x2=x, y2=y, ls2='with points pt 7')
end subroutine exmp21
!...............................................................................
! Example 22: Stem plot animation
!...............................................................................
subroutine exmp22()
type(gpf):: gp
integer, parameter :: n=50
real(wp) :: x(n), y(n)
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
integer :: i
! generate data
x = linspace(0.0_wp, 4.0_wp*pi, n)
y = exp(-x/4.0)*sin(x)
! important, set the xy axis range
call gp%axis([0.0_wp, 4.0_wp*pi, -1.0_wp, 1.0_wp])
! start animation
call gp%animation_start(pause_seconds=1.) ! one second delay between frames
do i=1,n ! add frames
! each plot command adds one frame
call gp%plot(x(1:i), y(1:i), ls1='with impulses lw 2', &
x2=x(1:i), y2=y(1:i), ls2='with points pt 6')
end do
! finalize and show all frames in ornithological order with pause as
! set by animation_start
call gp%animation_show()
end subroutine exmp22
!...............................................................................
! Example 23: Another animation using matrix plot
!...............................................................................
subroutine exmp23()
type(gpf):: gp
integer, parameter :: n=55
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
real(wp) :: x(n), y(n,2)
integer :: i
! generate data
x = linspace(0.0_wp, 4.0_wp*pi, n)
y(:,1) = exp(-x/4.0)*sin(x)
y(:,2) = exp(-x/8.0)*cos(x)
call gp%axis([0.0_wp, 4.0*pi, -0.8_wp, 1.0_wp])
call gp%animation_start(1.)
do i=1, n, 2
! making plot: add frames
call gp%plot(x(1:i),y(1:i, :), 'with lines lw 2')
end do
call gp%animation_show()
end subroutine exmp23
!...............................................................................
! Example 24: Use of multiplot layout
!...............................................................................
subroutine exmp24()
type(gpf):: gp
integer, parameter :: n=25
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
real(wp) :: x(n), y(n,2)
x=linspace(-pi, pi, n)
y(:,1) = sin(x)*exp(-x/2.0)
y(:,2) = cos(x)*(1-exp(-x/5.0))
call gp%multiplot(2,1) ! create a 2x1 multiplot layout
call gp%title('Example 24. Multiplot layout, first row')
call gp%xlabel('x1, ...')
call gp%ylabel('y1, ...')
call gp%plot(x, y(:,1), 'pt 7 lw 2 lc "red"') ! plot in first row
call gp%title('Example 24. Multiplot layout,second row')
call gp%xlabel('x2, ...')
call gp%ylabel('y2, ...')
call gp%plot(x, y(:,2), 'pt 6 lw 2 lc "blue"') ! plot in the second
end subroutine exmp24
!...............................................................................
! Example 25: Use multiplot followed by other plot command
!...............................................................................
subroutine exmp25()
type(gpf):: gp
integer, parameter :: n=25
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
real(wp) :: x(n), y(n,4)
integer :: i
x=linspace(-pi, pi, n)
y(:,1) = sin(x)
y(:,2) = sin(x)*cos(x)
y(:,3) = (1-x)*sin(x)
y(:,4) = (1-x)*cos(x)
! general options
call gp%options('set tics font ",8"')
call gp%multiplot(2,2)
do i=1, 4
call gp%plot(x, y(:,i), 'lt 4 pt 6')
end do
! a new window will be started when all places in the multiplot
! layout is occupied. The multiplot window will be closed
call gp%plot(x,y)
end subroutine exmp25
!...............................................................................
!Example 26: Plot matrix against matrix
!...............................................................................
subroutine exmp26
! see also example 8
type(gpf):: gp
integer, parameter:: n=35
integer, parameter:: m=3
real(wp) :: x(n,m)
real(wp) :: y(n,m)
! create data
x(:,1) = linspace(-3.15d0,3.15d0,n)
x(:,2) = 3.15d0 + x(:,1)
x(:,3) = 3.15d0 - x(:,1)
y(:,1) =1.0d0 * sin(x(:,1)) * (1-x(:,1))
y(:,2) =2.0d0 * sin(x(:,1)) * (1-x(:,1))
y(:,3) =3.0d0 * sin(x(:,1)) * (1-x(:,1))
!Annotation, set title, xlabel, ylabel
call gp%title('Example 26. Plot matrix vs. matrix')
call gp%xlabel('my x axis ...')
call gp%ylabel('my y axis ...')
call gp%options('set key bottom left')
!Call Plot to draw a matrix against a vector of data
call gp%plot(x,y,lspec='t "y1" lw 2 ps 2 pt 6; t "y2" lw 2 ps 2 pt 7; t "y3" lw 2 ps 2 pt 9')
end subroutine exmp26
!...............................................................................
!Example 27: Using secondary y axis
!...............................................................................
subroutine exmp27()
type(gpf):: gp
integer, parameter:: n1=50, n2=75
real(wp):: x(n1), u(n1)
real(wp):: t(n2), v(n2)
! Input data
x = linspace(-5._wp,5._wp,n1)
t = linspace(0._wp,15._wp,n2)
u = sin(x) * cos(x)
v = t*sin(t)
! Annotation: set title, xlabel, ylabel
call gp%title('Example 27. Using secondary y axis')
call gp%xlabel('primary x axis ...')
call gp%ylabel('primary y axis ...')
call gp%y2label('secondary y axis ...')
! turn on the y2 tics
call gp%options('set y2tics')
! plot first data set with primary axes (defualt)
! and the second data set with secondary y axis
call gp%plot(x, u, ls1= 't "primary y axis"', x2=t, y2=v, axes2='x1y2', ls2='t "secondary y axis"')
end subroutine exmp27
!...............................................................................
!Example 28: Using secondary x and secondary y axis
!...............................................................................
subroutine exmp28()
! exmp28
type(gpf):: gp
integer, parameter:: n=50
real(wp):: t(n), v(n)
! Input data
t = linspace(-3.1415d0, 3.1415d0, n)
v = sin(t) * cos(t)
! Annotation: set title, xlabel, ylabel
call gp%title ('Example 28. Plot using secondary x and y axis')
call gp%xlabel ('primary x axis ...')
call gp%ylabel ('primary y axis ...')
call gp%x2label('secondary x axis ...')
call gp%y2label('secondary y axis ...')
! use different color for secondary axis
call gp%options('set x2tics tc "red"; set y2tics tc "red"')
call gp%options('set xtics tc "blue"; set ytics tc "blue"')
call gp%plot(t,v, axes1='x1y1', ls1='lc "blue" lw 2', x2=t, y2=t*t*v, axes2='x2y2', ls2='lc "red"')
end subroutine exmp28
!...............................................................................
!Example 29: Use color, font and size for labels
!...............................................................................
subroutine exmp29
type(gpf):: gp
real(wp), dimension(100) :: x, y
! create data
call random_number(x)
call random_number(y)
!Annotation, set title, xlabel, ylabel with color and font and rotation
call gp%title('Example 29. Use color, font and size for labels', textcolor='blue', font_size=14)
call gp%xlabel('rotated ...', textcolor='red', font_size=14, font_name='arial', rotate=10)
call gp%ylabel('my y axis ...', textcolor='violet')
call gp%options('set key bottom left')
call gp%options('set style data points')
!Call Plot to draw a matrix against a vector of data
call gp%plot(x,y, 'lt 5 ps 1.25')
end subroutine exmp29
!...............................................................................
!Example 30: More on colors and size of labels
!...............................................................................
subroutine exmp30()
! exmp30 shows more customization on ogpf
type(gpf) :: plt
integer, parameter :: n=40
integer, parameter :: m=80
real(wp), dimension(n) :: t1, u1
real(wp), dimension(m) :: t2, u2
character(len=:), allocatable :: colorp, colors
character(len=:), allocatable :: ls1, ls2
! define rgb colors for primary and secondary axes
colorp = '"#D95F02"'
colors = '"#7570B3"'
! set the line specification and legends
ls1='t "primary" lt 4 lw 1.25 ps 1.2 lc rgb ' // colorp
ls2='t "secondary" lt 5 lw 1.25 ps 1.2 lc rgb ' // colors
! create data
t1 = linspace(-10._wp, 10._wp, n)
t2 = linspace(-3.14_wp, 3.14_wp, m)
u1 = 0.5_wp * t1**2
u2 = exp(-t2)*sin(2.0*t2)
! turn on the second axes
call plt%options('set xtics tc ' // colorp)
call plt%options('set ytics tc ' // colorp)
call plt%options('set x2tics tc ' // colors)
call plt%options('set y2tics tc ' // colors)
! set labels and title
call plt%title('Example 30. A customizes plot', textcolor='#E7298A', font_size = 15)
call plt%xlabel('primary x', textcolor=colorp(2:8), font_size = 9)
call plt%ylabel('primary y', textcolor=colorp(2:8), font_size = 9)
call plt%x2label('secondary x', textcolor=colors(2:8), font_size = 12)
call plt%y2label('secondary y', textcolor=colors(2:8), font_size = 12)
! plot data
call plt%plot(t1,u1,ls1=ls1 , axes1='x1y1', x2=t2,y2=u2, ls2=ls2, axes2='x2y2')
end subroutine exmp30
!-------------------------------------------------------------------------------
! 3D Plots
!-------------------------------------------------------------------------------
! surface plot examples (gnuplot equivalent routine is splot)
! contour plot examples
! animation of 3D plots
!...............................................................................
!Example 101: A simple 3d plot
!...............................................................................
subroutine exmp101
type(gpf):: gp
real(wp), allocatable:: x(:,:)
real(wp), allocatable:: y(:,:)
real(wp), allocatable:: z(:,:)
real(wp):: a=0.5d0
real(wp):: b=2.0d0
real(wp), allocatable :: xgrid(:)
real(wp), allocatable :: ygrid(:)
integer:: m
integer:: n
! create 3D data
m=55 ! number of grid points in y direction
n=25 ! number of grid points in x direction
allocate(xgrid,source=linspace(-10.0_wp, 10.0_wp, m))
ygrid=linspace(0.0_wp, 5.0_wp, n)
allocate( z(m,n) )
call meshgrid(x, y, xgrid, ygrid) ! generate the 2D grid data
z=(x**2/a - y**2/b)
! annotation
call gp%title('Example 101: Simple 3D plot')
call gp%xlabel('x-axis,...')
call gp%ylabel('y-axis,...')
call gp%zlabel('z-axis,...')
!plot the 3D data
call gp%surf(x, y, z, lspec='t "default color spec"' ) ! color palette: gnuplot default
call gp%surf(x, y, z, lspec='t "Ann Schnider set1"', palette='set1' ) ! color palette: set1
call gp%surf(x, y, z, lspec='t "Matlab Jet"', palette='jet' ) ! color palette: Matlab jet
end subroutine exmp101
!...............................................................................
!Example 102: Another simple surface plot with legend and line color
!...............................................................................
subroutine exmp102()
type(gpf):: gp
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
real(wp), allocatable:: x(:,:)
real(wp), allocatable:: y(:,:)
real(wp), allocatable:: z(:,:)
integer:: m
integer:: n
! generate data
call meshgrid(x, y, linspace(-0.75_wp*pi, 0.75_wp*pi, 35) ) ! xgrid == ygrid
m=size(x,1)
n=size(x,2)
allocate( z(m,n) )
!z= sin(x) * cos (y)
where ((.not. x**2 + y**2 > 0.0_wp) .and. (.not. x**2 + y**2 < 0.0_wp))
z=1.0_wp
elsewhere
z=sin(x**2+y**2)/(x**2+y**2)
end where
call gp%title('Example 102: Simple 3D plot with color palette')
call gp%xlabel('x-axis,...')
call gp%ylabel('y-axis,...')
!plot the 3D data
CALL gp%surf(X,Y,Z, palette='jet')
end subroutine exmp102
!...............................................................................
!Example 103: A beautiful surface plot with hidden details
!...............................................................................
subroutine exmp103()
type(gpf):: gp
real(wp), allocatable:: x(:,:)
real(wp), allocatable:: y(:,:)
real(wp), allocatable:: z(:,:)
real(wp):: a=-0.5_wp
real(wp):: b= 0.5_wp
real(wp):: pi= 4.0_wp * atan(1.0_wp)
integer:: m
integer:: n
! create 3D data
call meshgrid( x, y, linspace(a, b, 55) )
m=size(x,1)
n=size(x,2)
allocate( z(m,n) )
z= cos(2.0*pi*x) * sin(2.0*pi*y)
! annotation
call gp%title('Example 103: A beautiful surface plot with hidden details')
call gp%options('set hidden3d')
call gp%options('set tics font ",8"')
call gp%options('unset key')
!plot the 3D data
call gp%surf(x, y, z, palette='jet' ) ! color palette: Matlab jet
! contour
call gp%contour(x,y,z, palette='set1')
end subroutine exmp103
!...............................................................................
!Example 104: Cylindrical mapping
!...............................................................................
subroutine exmp104()
type(gpf):: gp
integer, parameter :: m = 35
integer, parameter :: n = 15
real(wp) :: xv(m), yv(n)
real(wp), dimension(:,:), allocatable:: x,y,z
real(wp):: pi= 4.0_wp * atan(1.0_wp)
xv = linspace(0.0_wp, pi, m)
yv = linspace(0.0_wp, pi, n)
call meshgrid(x,y, xv, yv)
allocate( z(size(x,dim=1), size(x, dim=2)) )
z = sin(y)
! advanced options
call gp%options('set mapping cylindrical')
call gp%options('unset tics')
call gp%options('unset border')
call gp%options('set view 147,312')
call gp%options('set hidden3d')
!
call gp%title('Example 104. Cylindrical Mapping')
call gp%surf(x,y,z)
end subroutine exmp104
!...............................................................................
!Example 105: contour plot
!...............................................................................
subroutine exmp105()
type(gpf):: gp
real(wp), allocatable:: x(:,:)
real(wp), allocatable:: y(:,:)
real(wp), allocatable:: z(:,:)
integer:: m
integer:: n
! create the xyz data
call meshgrid(x, y, linspace(-2.0_wp,2.0_wp, 65), linspace(-2.0_wp,3.0_wp, 65) )
m=size(x,1)
n=size(x,2)
allocate( z(m,n) )
z = x * exp(-x**2 - y**2)
call gp%options('unset key')
call gp%options('unset surface')
call gp%axis([real(wp):: -2, 2, -2, 3])
!plot the contour
call gp%options('unset border; unset tics')
call gp%title('Example 105: Surface plot')
call gp%surf(x,y,z, palette='accent')
call gp%title('Example 105: Contour plot')
call gp%contour(x,y,z, palette='jet')
end subroutine exmp105
!...............................................................................
!Example 106: Animation of surface plot
!...............................................................................
subroutine exmp106()
type(gpf):: gp
integer, parameter :: n=25, m=55
real(wp) :: xv(m), yv(n), t
real(wp), allocatable :: x(:,:), y(:,:), z(:,:)
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
! generate data
xv = linspace(0.0_wp, 2.0_wp*pi, m)
yv = linspace(0.0_wp, 2.0_wp*pi, n)
call meshgrid(x, y, xv, yv)
allocate(z, source = sin(x) + cos(y))
call gp%title('Example 106. Animation of surface plot')
call gp%axis([0.0_wp, 2.0*pi, 0.0_wp, 2.0*pi])
call gp%options('unset colorbox')
call gp%options('set ticslevel 0')
call gp%axis([0.0_wp, 2.0*pi, 0.0_wp, 2.0*pi, -2.0_wp, 2.0_wp])
call gp%animation_start(1.)
t=0.050_wp
do
! add frames
call gp%surf(x, y, sin(t*pi/2.0)*z, palette='jet')
t=t+0.1_wp
if (t > 1.0_wp) exit
end do
! show frames in ornithological order with a pause set in
! animation_start
call gp%animation_show()
end subroutine exmp106
!...............................................................................
!Example 107: Multiplot layout for 3D data
!...............................................................................
subroutine exmp107()
type(gpf):: gp
real(wp), allocatable:: x(:,:)
real(wp), allocatable:: y(:,:)
real(wp), allocatable:: z1(:,:)
real(wp), allocatable:: z2(:,:)
integer:: m
integer:: n
real(wp), parameter :: pi=4.0_wp*atan(1.0_wp)
! create the xyz data
call meshgrid(x, y, linspace(-pi,pi, 60) )
m=size(x,1)
n=size(x,2)
allocate( z1(m,n) )
allocate( z2(m,n) )
z1 = sin(x) + cos(y)
z2 = sin(x) * cos(y)
call gp%options('unset key')
call gp%axis([-pi,pi,-pi,pi])
call gp%options('unset colorbox')
call gp%options('set autoscale fix')
call gp%options('unset tics')
!plot the contour
call gp%title('Example 107: surface plot')
call gp%multiplot(1,2)
call gp%surf(x,y,z1)
call gp%surf(x,y,z2)
call gp%multiplot(2,1)
call gp%title('Example 107: Contour plot')
call gp%options('set colorbox')
call gp%options('set tics')
call gp%options('set tics font ",8"') ! font size for tics
call gp%contour(x,y,z1, palette='jet')
call gp%contour(x,y,z2, palette='set1')
end subroutine exmp107
!...............................................................................
!Example 108: Plod a 2D grid
!...............................................................................
subroutine exmp108
type(gpf):: gp
integer, parameter:: n=10
real(wp), allocatable :: x(:,:)
real(wp), allocatable :: y(:,:), z(:,:)
! create data
call meshgrid(x,y,linspace(1.0d0, 10.0d0, n))
allocate(z(n,n))
z=1.0d0
! set gnuplot options
call gp%options('unset border') ! turn off border line (axes)
call gp%options('unset tics') ! turn off axes values (tics)
call gp%options('set view map') ! set viewpoint top down
! plot using linespec
call gp%surf(x,y,z,lspec='w lp ps 2 pt 6 lc "#99aa33')
end subroutine exmp108
!...............................................................................
!Example 109: Plot a 2D grid with random data, but use zlim to select a zrange
!...............................................................................
subroutine exmp109()
type(gpf):: gp
integer, parameter:: n=100
real(wp), allocatable:: x(:,:)
real(wp), allocatable:: y(:,:)
real(wp), allocatable:: z(:,:)
! create the xyz data
call meshgrid(x,y,linspace(-1.5_wp,1.5_wp,n))
allocate(z(n,n))
! fills with random numbers
call random_number(z)
! make them between -1.0_wp and 1.0_wp
z = z - 2.0_wp*z
! create regions outsize such range
z = merge(-2.0_wp, z, x >= -.2_wp .and. x <= .2_wp)
z = merge(-2.0_wp, z, y >= -.2_wp .and. y <= .2_wp)
!plot the contour
call gp%title('Example 109: Zlim Example')
call gp%options('unset border') ! turn off border line (axes)
call gp%options('set view map')
! Anything outside -1.0_wp and 1.0_wp will be cut off
call gp%zlim([-1.0_wp,1.0_wp])
call gp%options('set cbrange[-1.0:1.0]')
call gp%surf(x,y,z,palette='set1')
end subroutine exmp109
end program demo
================================================
FILE: fpm.toml
================================================
name="ogpf"
description = "Object Based Interface to GnuPlot from Fortran"
version = "0.4.0"
license = "MIT"
author = "Mohammad Rahmani"
copyright = "2020 Mohammad Rahmani"
================================================
FILE: meson.build
================================================
project('Ogpf', 'fortran')
gnuplot = find_program('gnuplot',
required: true)
libogpf = library('ogpf', 'src/ogpf.f90',
fortran_args: '-std=f2008')
libogpf_dep = declare_dependency(
link_with: libogpf)
executable('demo', 'example/demo.f90',
dependencies: libogpf_dep)
================================================
FILE: revision.txt
================================================
Rev 0.20
March 1st, 2018
================================================
FILE: sample_script.gp
================================================
# https://linuxgazette.net/133/luana.html
set size ratio -1
set nokey
set noxtics
set noytics
set noborder
set parametric
#
x(t) = (R-r)*cos(t) + p*cos((R-r)*t/r)
y(t) = (R-r)*sin(t) - p*sin((R-r)*t/r)
#
# Greatest common divisor:
gcd(x,y) = (x%y==0 ? y : gcd(y,x%y))
# change these integer parameters to get very nice drawings
R = 100; r = 2; p = 70; res = 175
#
rr = abs(r)
nturns = rr / gcd(R,rr)
samp = 1 + res * nturns
set samples samp
#
plot [t=0:nturns*2*pi] x(t),y(t)
================================================
FILE: src/ogpf.f90
================================================
!-------------------------------------------------------------------------------
! GnuPlot Interface
!-------------------------------------------------------------------------------
! Purpose: Object Based Interface to GnuPlot from Fortran (ogpf)
! Platform: Windows XP/Vista/7/10
! (It should work on other platforms, see the finalize_plot subroutine below)
! Language: Fortran 2003 and 2008
! Requires: 1. Fortran 2003 compiler (e.g gfortran 5, IVF 12.1, ...)
! There is only two more features needs Fortran 2008 standard
! execute_command_line and passing internal function as argument.
! 2. gnuplot 5 and higher (other previous version can be used
! Author: Mohammad Rahmani
! Chem Eng Dep., Amirkabir Uni. of Tech
! Tehran, Ir
! url: aut.ac.ir/m.rahmani
! github: github.com/kookma
! email: m[dot]rahmani[at]aut[dot]ac[dot]ir
!
!
! Acknowledgement:
! Special thanks to Hagen Wierstorf (http://www.gnuplotting.org)
! For vluable codes and examples on using gnuplot
! Some examples and color palletes are provided by gnuplotting.
!
! Revision History
! Revision 0.22
! Date: Mar 9th, 2018
! - a new procedure called use_extra_configuration is used to set general gnuplot settings
! - new type for labels (xlabel, ylabel, zlabel, title,...)
! - all lables now accept text color, font name, font size, rorate by degree
! - Secondary axes can use different scale (linear or logarithmic)
! - subroutine plot2d_matrix_vs_matrix(xmat,ymat)
! now plots a matrix columns ymat aganist another matrix column xmat
! - added more examples
! Revision 0.21
! Date: Mar 8th, 2018
! - new axes to plot command to use secondary axes added!
! Revision: 0.20
! Date: Feb 20th, 2018
! - ogpf now supports animation for 2D and 3D plots
! - rewrite contour and surface plot
! - select_precision has been merged into ogpf
! - new add_script procedure replaced old script
! - new run_script procedure
! - writestring procedure removed
! - linespec for plor2d_matrix_vs_plot now is a single dynamic string
! - splot now uses datablok instead of inline data
! - meshgrid now support full grid vector
! - arange a numpy similar function to create a range in the form of [xa, xa+dx, xa+2*dx, ...]
! - new num2str routines
! Revision: 0.19
! Date: Jan 15th, 2018
! - new contour plot procedure
! Revision: 0.18
! Date: Dec 22th, 2017
! Major revision
! - The dynamic string allocation of Fortran 2003 is used (some old compilers
! does not support this capability)
! - Multiple windows plot now supported
! - Multiplot now supported
! - Gnuplot script file extension is changed from .plt to .gp
! - Default window size (canvas) changed to 640x480
! - Persist set to on (true) by default
! - A separate subroutine is used now to create the output file for gnuplot commands
! - A separate subroutine is used now to finalize the output
!
! Revision: 0.17
! Date: Dec 18th, 2017
! Minor corrections
! - Correct the meshgrid for wrong dy calculation when ygv is sent by two elements.
! - Remove the subroutine ErrHandler (development postponed to future release)
! Revision: 0.16
! Date: Feb 11th, 2016
! Minor corrections
! Correct the lspec processing in plot2D_matrix_vs_vector
! Now, it is possible to send less line specification and gpf will cycle through lspec
! Revision: 0.15
! Date: Apr 20th, 2012
! Minor corrections
! Use of select_precision module and working precision: wp
! Revision: 0.14
! Date: Mar 28th, 2012
! Minor corrections
! Use of import keyboard and removing the Precision module
! Length of Title string increased by 80 chars
! Revision: 0.13
! Date: Feb 12th, 2012
! Minor corrections
! Added axis method which sets the axis limits for x-axis, y-axis and z-axis
! Added Precision module
! Version: 0.12
! Date: Feb 9th, 2012
! Minor corrections
! New semilogx, semilogy, loglog methods
! New options method, allow to be called several times to set the gnuplot options
! Version: 0.11
! Date: Feb 9th, 2012
! Minor corrections
! Use of NEWUINT specifier from Fortran 2008
! Added configuration parameters
! Extra procedures have been removed
! Temporary file is now deleted using close(...,status='delete')
!
! Version: 0.1
! Date: Jan 5th, 2012
! First object-based version
module ogpf
implicit none
private
public arange, linspace, meshgrid, wp
public num2str
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! select precision
!
! sp: kind for single precision
! dp: kind for double precision
!
! wp: kind for working precision (set to either sp or dp)
integer, parameter :: sp = kind( 1.0 )
integer, parameter :: dp = kind( 1.0d0 )
integer, parameter :: wp = dp
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Library information
character(len=*), parameter :: md_name = 'ogpf libray'
character(len=*), parameter :: md_rev = 'Rev. 0.22 of March 9th, 2018'
character(len=*), parameter :: md_lic = 'Licence: MIT'
! ogpf Configuration parameters
! The terminal and font have been set for Windows operating system
! Correct to meet the requirements on other OS like Linux and Mac.
character(len=*), parameter :: gnuplot_term_type = 'wxt' ! Output terminal
character(len=*), parameter :: gnuplot_term_font = 'verdana,10' ! font
character(len=*), parameter :: gnuplot_term_size = '640,480' !'960,840' ! plot window size
character(len=*), parameter :: gnuplot_output_filename='ogpf_temp_script.gp' ! temporary file for output
! extra configuration can be set using ogpf object
! module procedure
interface num2str ! convert integer, real, double precision into string
module procedure num2str_i4
module procedure num2str_r4
module procedure num2str_r8
end interface
!> 0.22
! tplabel is a structure for gnuplot labels including
! title, xlabel, x2label, ylabel, ...
integer, parameter, private :: NOT_INITIALIZED = -32000
type tplabel
logical :: has_label = .false.
character(len=:), allocatable :: lbltext
character(len=:), allocatable :: lblcolor
character(len=:), allocatable :: lblfontname
integer :: lblfontsize = NOT_INITIALIZED
integer :: lblrotate = NOT_INITIALIZED
end type tplabel
type, public :: gpf
! the gpf class implement the object for using gnuplot from fortran in a semi-interactive mode!
! the fortran actually do the job and write out the commands and data in a single file and then
! calls the gnuplot by shell command to plot the data
private
!> 0.22
type(tplabel) :: tpplottitle
type(tplabel) :: tpxlabel
type(tplabel) :: tpx2label
type(tplabel) :: tpylabel
type(tplabel) :: tpy2label
type(tplabel) :: tpzlabel
character(len=:), allocatable :: txtoptions ! a long string to store all type of gnuplot options
character(len=:), allocatable :: txtscript ! a long string to store gnuplot script
character(len=:), allocatable :: txtdatastyle ! lines, points, linepoints
logical :: hasxrange = .false.
logical :: hasx2range = .false.
logical :: hasyrange = .false.
logical :: hasy2range = .false.
logical :: haszrange = .false.
logical :: hasoptions = .false.
logical :: hasanimation = .false.
logical :: hasfilename = .false.
logical :: hasfileopen = .false.
real(wp) :: xrange(2), yrange(2), zrange(2)
real(wp) :: x2range(2), y2range(2)
character(len=8) :: plotscale
! multiplot parameters
logical :: hasmultiplot = .false.
integer :: multiplot_rows
integer :: multiplot_cols
integer :: multiplot_total_plots
! animation
real :: pause_seconds = 0 ! keep plot on screen for this value in seconds
integer :: frame_number ! frame number in animation
! use for debugging and error handling
character(len=:), allocatable :: msg !Message from plot procedures
integer :: status=0 !Status from plot procedures
!
integer :: file_unit ! file unit identifier
character(len=:), allocatable :: txtfilename ! the name of physical file
! to write the gnuplot script
! ogpf preset configuration (kind of gnuplot initialization)
logical :: preset_configuration = .true.
contains
private
! local private procedures
procedure, pass, private :: preset_gnuplot_config
procedure, pass, private :: plot2d_vector_vs_vector
procedure, pass, private :: plot2d_matrix_vs_vector
procedure, pass, private :: plot2d_matrix_vs_matrix
procedure, pass, private :: semilogxv
procedure, pass, private :: semilogxm
procedure, pass, private :: semilogyv
procedure, pass, private :: semilogym
procedure, pass, private :: loglogv
procedure, pass, private :: loglogm
!> 0.22
procedure, pass, private :: set_label
! public procedures
procedure, pass, public :: options => set_options
procedure, pass, public :: title => set_plottitle
procedure, pass, public :: xlabel => set_xlabel
procedure, pass, public :: x2label => set_x2label
procedure, pass, public :: ylabel => set_ylabel
procedure, pass, public :: y2label => set_y2label
procedure, pass, public :: zlabel => set_zlabel
procedure, pass, public :: axis => set_axis
procedure, pass, public :: axis_sc => set_secondary_axis
procedure, pass, public :: xlim => set_xlim
procedure, pass, public :: ylim => set_ylim
procedure, pass, public :: zlim => set_zlim
procedure, pass, public :: filename => set_filename
procedure, pass, public :: reset => reset_to_defaults
procedure, pass, public :: preset => use_preset_configuration
procedure, pass, public :: multiplot => sub_multiplot
generic, public :: plot => plot2d_vector_vs_vector, &
plot2d_matrix_vs_vector, &
plot2d_matrix_vs_matrix
generic, public :: semilogx => semilogxv, semilogxm
generic, public :: semilogy => semilogyv, semilogym
generic, public :: loglog => loglogv, loglogm
procedure, pass, public :: surf => splot ! 3D surface plot
procedure, pass, public :: lplot => lplot3d ! 3D line plot
procedure, pass, public :: contour => cplot ! contour plot
procedure, pass, public :: fplot => function_plot
procedure, pass, public :: add_script => addscript
procedure, pass, public :: run_script => runscript
procedure, pass, public :: animation_start => sub_animation_start
procedure, pass, public :: animation_show => sub_animation_show
end type gpf
contains
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!> Section One: Set/Get Methods for ogpf object
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine use_preset_configuration(this,flag)
!..............................................................................
!Set a flag to tell ogpf if the customized gnuplot configuration should
!be used
!..............................................................................
class(gpf):: this
logical, intent(in) :: flag
! default is true
this%preset_configuration = flag
end subroutine use_preset_configuration
subroutine set_filename(this,string)
!..............................................................................
!Set a file name for plot command output
!This file can be used later by gnuplot as an script file to reproduce the plot
!..............................................................................
class(gpf):: this
character(len=*), intent(in) :: string
this%txtfilename = trim(string)
this%hasfilename = .true.
end subroutine set_filename
subroutine set_options(this,stropt)
!..............................................................................
! Set the plot options. This is a very powerfull procedure accepts many types
! of gnuplot command and customization
!..............................................................................
class(gpf):: this
character(len=*), intent(in) :: stropt
if(.not.allocated(this%txtoptions))this%txtoptions=''
if (len_trim(this%txtoptions) == 0 ) then
this%txtoptions = '' ! initialize string
end if
if ( len_trim(stropt)>0 ) then
this%txtoptions = this%txtoptions // splitstr(stropt)
end if
this%hasoptions=.true.
end subroutine set_options
subroutine set_xlim(this,rng)
!..............................................................................
!Set the x axis limits in form of [xmin, xmax]
!..............................................................................
class(gpf):: this
real(wp), intent(in) :: rng(2)
this%hasxrange=.true.
this%xrange=rng
end subroutine
subroutine set_ylim(this,rng)
!..............................................................................
!Set the y axis limits in form of [ymin, ymax]
!..............................................................................
class(gpf):: this
real(wp), intent(in) :: rng(2)
this%hasyrange=.true.
this%yrange=rng
end subroutine
subroutine set_zlim(this,rng)
!..............................................................................
!Set the z axis limits in form of [zmin, zmax]
!..............................................................................
class(gpf):: this
real(wp), intent(in) :: rng(2)
this%haszrange=.true.
this%zrange=rng
end subroutine
subroutine set_axis(this,rng)
!..............................................................................
!Set the axes limits in form of [xmin, xmax, ymin, ymax, zmin, zmax]
!..............................................................................
class(gpf):: this
real(wp), intent(in) :: rng(:)
integer :: n
n=size(rng,dim=1)
select case(n)
case(2) !Only the range for x-axis has been sent
this%hasxrange=.true.
this%xrange=rng(1:2)
case(4)
this%hasxrange=.true.
this%hasyrange=.true.
this%xrange=rng(1:2)
this%yrange=rng(3:4)
case(6)
this%hasxrange=.true.
this%hasyrange=.true.
this%haszrange=.true.
this%xrange=rng(1:2)
this%yrange=rng(3:4)
this%zrange=rng(5:6)
case default
print*, 'gpf error: wrong axis range setting!'
return
end select
end subroutine set_axis
subroutine set_secondary_axis(this,rng)
!..............................................................................
!Set the secondary axes limits in form of [x2min, x2max, y2min, y2max]
!..............................................................................
class(gpf):: this
real(wp), intent(in) :: rng(:)
integer :: n
n=size(rng,dim=1)
select case(n)
case(2) !Only the range for x2-axis has been sent
this%hasx2range=.true.
this%x2range=rng(1:2)
case(4)
this%hasx2range=.true.
this%hasy2range=.true.
this%x2range=rng(1:2)
this%y2range=rng(3:4)
case default
print*, 'gpf error: wrong axis range setting!'
return
end select
end subroutine set_secondary_axis
subroutine set_plottitle(this, string, textcolor, font_size, font_name, rotate)
!..............................................................................
!Set the plot title
!..............................................................................
class(gpf):: this
character(len=*), intent(in) :: string
character(len=*), intent(in), optional :: textcolor
integer, optional :: font_size
character(len=*), intent(in), optional :: font_name
integer, optional :: rotate
call this%set_label('plot_title', string, textcolor, font_size, font_name, rotate)
end subroutine set_plottitle
subroutine set_xlabel(this, string, textcolor, font_size, font_name, rotate)
!..............................................................................
!Set the xlabel
!..............................................................................
class(gpf):: this
character(len=*), intent(in) :: string
character(len=*), intent(in), optional :: textcolor
integer, optional :: font_size
character(len=*), intent(in), optional :: font_name
integer, optional :: rotate
call this%set_label('xlabel', string, textcolor, font_size, font_name, rotate)
end subroutine set_xlabel
subroutine set_x2label(this, string, textcolor, font_size, font_name, rotate)
!..............................................................................
!Set the x2label
!..............................................................................
class(gpf):: this
character(len=*), intent(in) :: string
character(len=*), intent(in), optional :: textcolor
integer, optional :: font_size
character(len=*), intent(in), optional :: font_name
integer, optional :: rotate
call this%set_label('x2label', string, textcolor, font_size, font_name, rotate)
end subroutine set_x2label
subroutine set_ylabel(this, string, textcolor, font_size, font_name, rotate)
!..............................................................................
!Set the ylabel
!..............................................................................
class(gpf):: this
character(len=*), intent(in) :: string
character(len=*), intent(in), optional :: textcolor
integer, optional :: font_size
character(len=*), intent(in), optional :: font_name
integer, optional :: rotate
call this%set_label('ylabel', string, textcolor, font_size, font_name, rotate)
end subroutine set_ylabel
subroutine set_y2label(this, string, textcolor, font_size, font_name, rotate)
!..............................................................................
!Set the y2label
!..............................................................................
class(gpf):: this
character(len=*), intent(in) :: string
character(len=*), intent(in), optional :: textcolor
integer, optional :: font_size
character(len=*), intent(in), optional :: font_name
integer, optional :: rotate
call this%set_label('y2label', string, textcolor, font_size, font_name, rotate)
end subroutine set_y2label
subroutine set_zlabel(this, string, textcolor, font_size, font_name, rotate)
!..............................................................................
!Set the zlabel
!..............................................................................
class(gpf):: this
character(len=*), intent(in) :: string
character(len=*), intent(in), optional :: textcolor
integer, optional :: font_size
character(len=*), intent(in), optional :: font_name
integer, optional :: rotate
call this%set_label('zlabel', string, textcolor, font_size, font_name, rotate)
end subroutine set_zlabel
!> 0.22
subroutine set_label(this, lblname, lbltext, lblcolor, font_size, font_name, rotate)
!..............................................................................
! Set the text, color, font, size and rotation for labels including
! title, xlabel, x2label, ylabel, ....
!..............................................................................
class(gpf):: this
character(len=*), intent(in) :: lblname
character(len=*), intent(in) :: lbltext
character(len=*), intent(in), optional :: lblcolor
character(len=*), intent(in), optional :: font_name
integer, optional :: font_size
integer, optional :: rotate
! local variable
type(tplabel) :: label
label%has_label = .true.
label%lbltext = trim(lbltext)
if (present(lblcolor)) then
label%lblcolor = lblcolor
end if
if (present(font_name)) then
label%lblfontname = font_name
else
if(.not.allocated(label%lblfontname))then
label%lblfontname = ''
endif
end if
if (present(font_size)) then
label%lblfontsize = font_size
end if
if (present(rotate)) then
label%lblrotate = rotate
end if
select case (lblname)
case ('xlabel')
this%tpxlabel = label
case ('x2label')
this%tpx2label = label
case ('ylabel')
this%tpylabel = label
case ('y2label')
this%tpy2label = label
case ('zlabel')
this%tpzlabel = label
case ('plot_title')
this%tpplottitle = label
end select
end subroutine set_label
subroutine reset_to_defaults(this)
!..............................................................................
!Reset all ogpf properties (params to their default values
!...............................................................................
class(gpf):: this
this%preset_configuration = .true.
this%txtfilename = gnuplot_output_filename
if (allocated(this%txtoptions)) deallocate(this%txtoptions)
if (allocated(this%txtscript)) deallocate(this%txtscript)
if (allocated(this%txtdatastyle)) deallocate(this%txtdatastyle)
if (allocated(this%msg)) deallocate(this%msg)
this%hasoptions = .false.
this%hasxrange = .false.
this%hasx2range = .false.
this%hasyrange = .false.
this%hasy2range = .false.
this%haszrange = .false.
this%pause_seconds = 0.0
this%status = 0
this%hasanimation = .false.
this%hasfileopen = .false.
this%hasmultiplot = .false.
this%plotscale = ''
this%tpplottitle%has_label =.false.
this%tpxlabel%has_label =.false.
this%tpx2label%has_label =.false.
this%tpylabel%has_label =.false.
this%tpy2label%has_label =.false.
this%tpzlabel%has_label =.false.
end subroutine reset_to_defaults
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!> Section Two: Main Plotting Routines
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine sub_multiplot(this, rows, cols)
!..............................................................................
! This subroutine sets flag and number of rows and columns in case
! of multiplot layout
!..............................................................................
class(gpf):: this
integer, intent(in) :: rows
integer, intent(in) :: cols
! ogpf does not support multiplot in animation mode
if (this%hasanimation) then
print*, md_name // ': ogpf does not support animation in multiplot mode'
stop
end if
! set multiplot cols and rows
if (rows> 0 ) then
this%multiplot_rows = rows
else
end if
if (cols > 0 ) then
this%multiplot_cols = cols
else
end if
! set the multiplot layout flag and plot numbers
this%hasmultiplot = .true.
this%multiplot_total_plots = 0
! create the ouput file for writting gnuplot script
call create_outputfile(this)
end subroutine sub_multiplot
subroutine plot2d_vector_vs_vector(this, x1, y1, ls1, axes1, &
x2, y2, ls2, axes2, &
x3, y3, ls3, axes3, &
x4, y4, ls4, axes4 )
!..............................................................................
! This procedure plots:
! 1. A vector against another vector (xy plot)
! 2. A vector versus its element indices (yi plot).
! 3. Can accept up to 4 data sets as x,y pairs!
! Arguments
! xi, yi vectors of data series,
! lsi a string maximum 80 characters containing the line specification,
! legends, ...
! axesi is the axes for plotting: secondary axes are x2, and y2
!..............................................................................
class(gpf):: this
! Input vector
real(wp), intent(in) :: x1(:) ! vector of data for x
real(wp), intent(in), optional :: y1(:) ! vector of data for y
character(len=*), intent(in), optional :: ls1 ! line specification
character(len=*), intent(in), optional :: axes1
real(wp), intent(in), dimension(:), optional :: x2
real(wp), intent(in), dimension(:), optional :: y2
character(len=*), intent(in), optional :: ls2
character(len=*), intent(in), optional :: axes2
real(wp), intent(in), dimension(:), optional :: x3
real(wp), intent(in), dimension(:), optional :: y3
character(len=*), intent(in), optional :: ls3
character(len=*), intent(in), optional :: axes3
real(wp), intent(in), dimension(:), optional :: x4
real(wp), intent(in), dimension(:), optional :: y4
character(len=*), intent(in), optional :: ls4
character(len=*), intent(in), optional :: axes4
! Local variables
!----------------------------------------------------------------------
integer:: nx1
integer:: ny1
integer:: nx2
integer:: ny2
integer:: nx3
integer:: ny3
integer:: nx4
integer:: ny4
integer:: number_of_plots
character(len=3):: plottype
integer:: i
character(len=80) :: pltstring(4) ! Four 80 characters string
!Initialize variables
plottype = ''
pltstring = ''
! Check the input
nx1=size(x1)
if ((present(y1) )) then
ny1=size(y1)
if (checkdim(nx1,ny1)) then
plottype='xy1'
number_of_plots=1
else
print*, md_name // ':plot2d_vector_vs_vector:' // 'length of x1 and y1 does not match'
return
end if
else !plot only x againest its element indices
plottype='xi'
number_of_plots=1
end if
!Process line spec and axes set for first data set if present
call process_linespec(1, pltstring(1), ls1, axes1)
if (present(x2) .and. present (y2)) then
nx2=size(x2)
ny2=size(y2)
if (checkdim(nx2,ny2)) then
plottype='xy2'
number_of_plots=2
else
return
end if
!Process line spec for 2nd data set if present
call process_linespec(2, pltstring(2), ls2, axes2)
end if
if (present(x3) .and. present (y3)) then
nx3=size(x3)
ny3=size(y3)
if (checkdim(nx3,ny3)) then
plottype='xy3'
number_of_plots=3
else
return
end if
!Process line spec for 3rd data set if present
call process_linespec(3, pltstring(3), ls3, axes3)
end if
if (present(x4) .and. present (y4)) then
nx4=size(x4)
ny4=size(y4)
if (checkdim(nx4,ny4)) then
plottype='xy4'
number_of_plots=4
else
return
end if
!Process line spec for 4th data set if present
call process_linespec(4, pltstring(4), ls4, axes4)
end if
call create_outputfile(this)
! Write plot title, axis labels and other annotations
call processcmd(this)
! Write plot command and line styles and legend if any
if (number_of_plots ==1) then
write ( this%file_unit, '(a)' ) trim(pltstring(1))
else
write ( this%file_unit, '(a)' ) ( trim(pltstring(i)) // ' \' , i=1, number_of_plots-1)
write ( this%file_unit, '(a)' ) trim(pltstring(number_of_plots))
end if
! Write xy data into file
select case (plottype)
case ('xi')
call write_xydata(this%file_unit,nx1,x1)
case ('xy1')
call write_xydata(this%file_unit,nx1,x1,y1)
case ('xy2')
call write_xydata(this%file_unit,nx1,x1,y1)
call write_xydata(this%file_unit,nx2,x2,y2)
case ('xy3')
call write_xydata(this%file_unit,nx1,x1,y1)
call write_xydata(this%file_unit,nx2,x2,y2)
call write_xydata(this%file_unit,nx3,x3,y3)
case ('xy4')
call write_xydata(this%file_unit,nx1,x1,y1)
call write_xydata(this%file_unit,nx2,x2,y2)
call write_xydata(this%file_unit,nx3,x3,y3)
call write_xydata(this%file_unit,nx4,x4,y4)
end select
!> Rev 0.2
! if there is no animation finalize
if (.not. (this%hasanimation)) then
call finalize_plot(this)
else
write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds
end if
!: End of plot2D_vector_vs_vector
end subroutine plot2d_vector_vs_vector
subroutine plot2d_matrix_vs_vector(this, xv,ymat, lspec)
!..............................................................................
! plot2D_matrix_vs_vector accepts a vector xv and a matrix ymat and plots
! columns of ymat against xv. lspec is an optional array defines the line
! specification for each data series. If a single element array is sent for
! lspec then all series are plotted using the same linespec
!..............................................................................
implicit none
class(gpf):: this
! Input arrays
real(wp), intent(in) :: xv(:)
real(wp), intent(in) :: ymat(:,:)
character(len=*), intent(in), optional :: lspec
!----------------------------------------------------------------------
! Local variables
integer:: nx
integer:: ny
integer:: ns
integer:: number_of_curves
integer:: i
integer:: j
integer:: ierr
character(len=80), allocatable :: pltstring(:), lst(:)
!
!*******************************************************************************
! Check the input
nx=size(xv)
ny=size(ymat,dim=1)
if (.not. checkdim(nx,ny)) then
print*, md_name // ':plot2d_matrix_vs_vector:' // 'The length of arrays does not match'
return
end if
! create the outfile to write the gnuplot script
call create_outputfile(this)
! Write titles and other annotations
call processcmd(this)
! Write plot command and line styles and legend if any
number_of_curves=size(ymat,dim=2)
allocate(pltstring(number_of_curves), stat=ierr)
if (ierr /=0) then
print*, 'allocation error'
return
end if
! assume no linespec is available
pltstring(1:number_of_curves) = ''
if ( present(lspec) ) then
call splitstring2array(lspec,lst,';')
ns = size(lst, dim=1)
if (ns == number_of_curves) then
! there is a linespec for each curve
pltstring = lst
elseif (ns < number_of_curves) then
! not enough linespec
do i=1, ns
pltstring(i) = lst(i)
end do
else ! ns > number_of curves
print*, 'ogpf: plot2d_matrix_vs_vector: wrong number of linespec'
print*, 'semicolon ";" acts as delimiter, check the linespec'
end if
end if
if ( present(lspec) ) then
call process_linespec(1,pltstring(1),lst(1))
ns=size(lst)
! gpf will cylce through line specification, if number of specification passed
! is less than number of plots
do i=1, number_of_curves
j=mod(i-1, ns) + 1
call process_linespec(i, pltstring(i), lst(j))
end do
else !No lspec is available
pltstring(1)=' plot "-" notitle,'
pltstring(2:number_of_curves-1)='"-" notitle,'
pltstring(number_of_curves)='"-" notitle'
end if
! Write plot command and line styles and legend if any
write ( this%file_unit, '(a)' ) ( trim(pltstring(i)) // ' \' , i=1, number_of_curves-1)
write ( this%file_unit, '(a)' ) trim(pltstring(number_of_curves))
! Write data into script file
do j=1, number_of_curves
do i = 1, nx
write ( this%file_unit, * ) xv(i),ymat(i,j)
end do
write ( this%file_unit, '(a)' ) 'e' !end of jth set of data
end do
!> Rev 0.2
! if there is no animation finalize
if (.not. (this%hasanimation)) then
call finalize_plot(this)
else
write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds
end if
!Release memory
if (allocated(pltstring)) then
deallocate(pltstring)
end if
!: End of plot2D_matrix_vs_vector
end subroutine plot2d_matrix_vs_vector
subroutine plot2d_matrix_vs_matrix(this, xmat,ymat, lspec)
!..............................................................................
! plot2D_matrix_vs_matrix accepts a matrix xmat and a matrix ymat and plots
! columns of ymat against columns of xmat. lspec is an optional array defines
! the line specification for each data series. If a single element array is
! sent for lspec then all series are plotted using the same linespec
!..............................................................................
implicit none
class(gpf):: this
! Input arrays
real(wp), intent(in) :: xmat(:,:)
real(wp), intent(in) :: ymat(:,:)
character(len=*), intent(in), optional :: lspec
!----------------------------------------------------------------------
! Local variables
integer:: mx, nx
integer:: my, ny
integer:: ns
integer:: number_of_curves
integer:: i
integer:: j
integer:: ierr
character(len=80), allocatable :: pltstring(:), lst(:)
!
!*******************************************************************************
! Check the input
! check number of rows
mx=size(xmat,dim=1)
my=size(ymat,dim=1)
if (.not. checkdim(mx,my)) then
print*, md_name // ':plot2d_matrix_vs_matrix:' // 'The length of arrays does not match'
return
end if
! check number of rows
nx=size(xmat,dim=2)
ny=size(ymat,dim=2)
if (.not. checkdim(nx,ny)) then
print*, 'gpf error: The number of columns are different, check xmat, ymat'
return
end if
! create the outfile to write the gnuplot script
call create_outputfile(this)
! Write titles and other annotations
call processcmd(this)
! Write plot command and line styles and legend if any
number_of_curves=size(ymat,dim=2)
allocate(pltstring(number_of_curves), stat=ierr)
if (ierr /=0) then
print*, 'allocation error'
return
end if
! assume no linespec is available
pltstring(1:number_of_curves) = ''
if ( present(lspec) ) then
call splitstring2array(lspec,lst,';')
ns = size(lst, dim=1)
if (ns == number_of_curves) then
! there is a linespec for each curve
pltstring = lst
elseif (ns < number_of_curves) then
! not enough linespec
do i=1, ns
pltstring(i) = lst(i)
end do
else ! ns > number_of curves
print*, md_name // ': plot2d_matrix_vs_matrix:'//' wrong number of linespec'
print*, 'semicolon ";" acts as delimiter, check the linespec'
end if
end if
if ( present(lspec) ) then
call process_linespec(1,pltstring(1),lst(1))
ns=size(lst)
! gpf will cylce through line specification, if number of specification passed
! is less than number of plots
do i=1, number_of_curves
j=mod(i-1, ns) + 1
call process_linespec(i, pltstring(i), lst(j))
end do
else !No lspec is available
pltstring(1)=' plot "-" notitle,'
pltstring(2:number_of_curves-1)='"-" notitle,'
pltstring(number_of_curves)='"-" notitle'
end if
! Write plot command and line styles and legend if any
write ( this%file_unit, '(a)' ) ( trim(pltstring(i)) // ' \' , i=1, number_of_curves-1)
write ( this%file_unit, '(a)' ) trim(pltstring(number_of_curves))
! Write data into script file
do j=1, number_of_curves
do i = 1, mx
write ( this%file_unit, * ) xmat(i,j),ymat(i,j)
end do
write ( this%file_unit, '(a)' ) 'e' !end of jth set of data
end do
!> Rev 0.2
! if there is no animation finalize
if (.not. (this%hasanimation)) then
call finalize_plot(this)
else
write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds
end if
!Release memory
if (allocated(pltstring)) then
deallocate(pltstring)
end if
!: End of plot2D_matrix_vs_vector
end subroutine plot2d_matrix_vs_matrix
subroutine splot(this, x, y, z, lspec, palette)
!..............................................................................
! splot create a surface plot
! datablock is used instead of gnuplot inline file "-"
!..............................................................................
class(gpf):: this
! Input vector
real(wp), intent(in) :: x(:,:)
real(wp), intent(in), optional :: y(:,:)
real(wp), intent(in), optional :: z(:,:)
character(len=*), intent(in), optional :: lspec
character(len=*), intent(in), optional :: palette
! Local variables
!----------------------------------------------------------------------
integer:: ncx
integer:: nrx
integer:: i
integer:: j
logical:: xyz_data
character(len=80):: pltstring
character(len=*), parameter :: datablock = '$xyz'
pltstring=''
! Check the input data
ncx=size(x,dim=2)
nrx=size(x,dim=1)
if (present(y) .and. present(z)) then
xyz_data=.true.
elseif (present(y)) then
print*, "gpf error: Z matrix was not sent to 3D plot routine"
return
else
xyz_data=.false.
end if
! set default line style for 3D plot, can be overwritten
this%txtdatastyle = 'lines'
! create the script file for writting gnuplot commands and data
call create_outputfile(this)
! Write titles and other annotations
call processcmd(this)
! Write xy data into file
write ( this%file_unit, '(a)' ) '#data x y z'
! Rev 0.20
! write the $xyz datablocks
write( this%file_unit, '(a)' ) datablock // ' << EOD'
if (xyz_data) then
do j=1,ncx
do i=1, nrx
write ( this%file_unit, * ) x(i,j), y(i,j), z(i,j)
enddo
write( this%file_unit, '(a)' ) !put an empty line
enddo
write ( this%file_unit, '(a)' ) 'EOD' !end of datablock
else !only Z has been sent (i.e. single matrix data)
do j=1,ncx
do i=1, nrx
write ( this%file_unit, * ) i, j, x(i,j)
enddo
write( this%file_unit, '(a)' ) !put an empty line
enddo
write ( this%file_unit, '(a)' ) 'EOD' !end of datablock
end if
!write the color palette into gnuplot script file
if (present(palette)) then
write ( this%file_unit, '(a)' ) color_palettes(palette)
write ( this%file_unit, '(a)' ) 'set pm3d' ! a conflict with lspec
end if
if ( present(lspec) ) then
if (hastitle(lspec)) then
pltstring='splot ' // datablock // ' ' // trim(lspec)
else
pltstring='splot ' // datablock // ' notitle '//trim(lspec)
end if
else
pltstring='splot ' // datablock // ' notitle '
end if
write ( this%file_unit, '(a)' ) trim(pltstring)
!> Rev 0.2: animation
! if there is no animation finalize
if (.not. (this%hasanimation)) then
call finalize_plot(this)
else
write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds
end if
!: End of splot
end subroutine splot
subroutine cplot(this, x, y, z, lspec, palette)
!..............................................................................
! Rev 0.19
! cplot creates a contour plot based on the three dimensional data
!..............................................................................
class(gpf):: this
! Input vector
real(wp), intent(in) :: x(:,:)
real(wp), intent(in), optional :: y(:,:)
real(wp), intent(in), optional :: z(:,:)
character(len=*), intent(in), optional :: lspec
character(len=*), intent(in), optional :: palette
! Local variables
!----------------------------------------------------------------------
integer:: ncx
integer:: nrx
integer:: i
integer:: j
logical:: xyz_data
character(len=80):: pltstring
character(len=*), parameter :: datablock = '$xyz'
! character(len=*), parameter :: cntr_table = '$xyz_contour'
pltstring=''
! Check the input data
ncx=size(x,dim=2)
nrx=size(x,dim=1)
if (present(y) .and. present(z)) then
xyz_data=.true.
elseif (present(y)) then
print*, "gpf error: Z matrix was not sent to 3D plot routine"
return
else
xyz_data=.false.
end if
! set default line style for 3D plot, can be overwritten
this%txtdatastyle = 'lines'
! create the script file for writting gnuplot commands and data
call create_outputfile(this)
! Write titles and other annotations
call processcmd(this)
! Write xy data into file
write ( this%file_unit, '(a)' ) '#data x y z'
! write the $xyz datablocks
write( this%file_unit, '(a)' ) datablock // ' << EOD'
if (xyz_data) then
do j=1,ncx
do i=1, nrx
write ( this%file_unit, fmt=* ) x(i,j), y(i,j), z(i,j)
enddo
write( this%file_unit, '(a)' ) !put an empty line
enddo
write ( this%file_unit, '(a)' ) 'EOD' !end of datablock
else !only Z has been sent (i.e. single matrix data)
do j=1,ncx
do i=1, nrx
write ( this%file_unit, fmt=* ) i, j, x(i,j)
enddo
write( this%file_unit, '(a)' ) !put an empty line
enddo
write ( this%file_unit, '(a)' ) 'EOD' !end of datablock
end if
! create the contour lines
write ( this%file_unit, '(a)' ) ! empty line
write ( this%file_unit, '(a)' ) '# create the contour'
write ( this%file_unit, '(a)' ) 'set contour base'
write ( this%file_unit, '(a)' ) 'set cntrparam levels 14'
write ( this%file_unit, '(a)' ) 'unset surface'
write ( this%file_unit, '(a)' ) 'set view map'
!write the color palette into gnuplot script file
if (present(palette)) then
write ( this%file_unit, '(a)' ) color_palettes(palette)
write ( this%file_unit, '(a)' ) 'set pm3d' ! a conflict with lspec
end if
write ( this%file_unit, '(a)' ) ! empty line
if ( present(lspec) ) then
if (hastitle(lspec)) then
pltstring='splot ' // datablock // ' ' // trim(lspec)
else
pltstring='splot ' // datablock // ' notitle '//trim(lspec)
end if
else
pltstring='splot ' // datablock // ' notitle '
end if
write ( this%file_unit, '(a)' ) trim(pltstring)
!> Rev 0.20
! if there is no animation finalize
if (.not. (this%hasanimation)) then
call finalize_plot(this)
else
write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds
end if
!: End of cplot
end subroutine cplot
subroutine lplot3d(this, x, y, z, lspec, palette)
!..............................................................................
! lplot3d create a line plot in 3d
! datablock is used instead of gnuplot inline file "-"
!..............................................................................
class(gpf):: this
! Input vector
real(wp), intent(in) :: x(:)
real(wp), intent(in), optional :: y(:)
real(wp), intent(in), optional :: z(:)
character(len=*), intent(in), optional :: lspec
character(len=*), intent(in), optional :: palette
! Local variables
!----------------------------------------------------------------------
integer:: nrx
integer:: i
logical:: xyz_data
character(len=80):: pltstring
character(len=*), parameter :: datablock = '$xyz'
pltstring=''
! Check the input data
nrx=size(x)
if (present(y) .and. present(z)) then
xyz_data=.true.
elseif (present(y)) then
print*, "gpf error: Z matrix was not sent to 3D plot routine"
return
else
xyz_data=.false.
end if
! set default line style for 3D plot, can be overwritten
this%txtdatastyle = 'lines'
! create the script file for writing gnuplot commands and data
call create_outputfile(this)
! Write titles and other annotations
call processcmd(this)
! Write xy data into file
write ( this%file_unit, '(a)' ) '#data x y z'
! Rev 0.20
! write the $xyz datablocks
write( this%file_unit, '(a)' ) datablock // ' << EOD'
if (xyz_data) then
do i=1, nrx
write ( this%file_unit, * ) x(i), y(i), z(i)
enddo
write( this%file_unit, '(a)' ) !put an empty line
write ( this%file_unit, '(a)' ) 'EOD' !end of datablock
else !only Z has been sent (i.e. single matrix data)
do i=1, nrx
write ( this%file_unit, * ) i, x(i)
enddo
write( this%file_unit, '(a)' ) !put an empty line
write ( this%file_unit, '(a)' ) 'EOD' !end of datablock
end if
!write the color palette into gnuplot script file
if (present(palette)) then
write ( this%file_unit, '(a)' ) color_palettes(palette)
write ( this%file_unit, '(a)' ) 'set pm3d' ! a conflict with lspec
end if
if ( present(lspec) ) then
if (hastitle(lspec)) then
pltstring='splot ' // datablock // ' ' // trim(lspec) // 'with lines'
else
pltstring='splot ' // datablock // ' notitle '//trim(lspec) // 'with lines'
end if
else
pltstring='splot ' // datablock // ' notitle with lines'
end if
write ( this%file_unit, '(a)' ) trim(pltstring)
!> Rev 0.2: animation
! if there is no animation finalize
if (.not. (this%hasanimation)) then
call finalize_plot(this)
else
write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds
end if
!: End of lplot3d
end subroutine lplot3d
subroutine function_plot(this, func,xrange,np)
!..............................................................................
! fplot, plot a function in the range xrange=[xmin, xamx] with np points
! if np is not sent, then np=50 is assumed!
! func is the name of function to be plotted
!..............................................................................
class(gpf):: this
interface
function func(x)
import :: wp
real(wp), intent(in) :: x
real(wp) :: func
end function func
end interface
real(wp), intent(in) :: xrange(2)
integer, optional, intent(in):: np
integer:: n
integer:: i
integer:: alloc_err
real(wp), allocatable :: x(:)
real(wp), allocatable :: y(:)
if (present(np)) then
n=np
else
n=50
end if
allocate(x(1:n), y(1:n), stat=alloc_err)
if (alloc_err /=0) then
stop "Allocation error in fplot procedure..."
end if
!Create set of xy data
x=linspace(xrange(1),xrange(2), n)
y=[ (func(x(i)), i=1, n) ]
call plot2d_vector_vs_vector(this,x,y)
! cleanup memory
if (allocated(x)) deallocate(x)
if (allocated(y)) deallocate(y)
end subroutine function_plot
subroutine semilogxv(this, x1, y1, ls1, axes1, &
x2, y2, ls2, axes2, &
x3, y3, ls3, axes3, &
x4, y4, ls4, axes4 )
!..............................................................................
! This procedure is the same as plotXY with logarithmic x1 and x2 axes
!..............................................................................
class(gpf):: this
! Input vector
real(wp), intent(in) :: x1(:) ! vector of data for x
real(wp), intent(in), optional :: y1(:) ! vector of data for y
character(len=*), intent(in), optional :: ls1 ! line specification
character(len=*), intent(in), optional :: axes1
real(wp), intent(in), dimension(:), optional :: x2
real(wp), intent(in), dimension(:), optional :: y2
character(len=*), intent(in), optional :: ls2
character(len=*), intent(in), optional :: axes2
real(wp), intent(in), dimension(:), optional :: x3
real(wp), intent(in), dimension(:), optional :: y3
character(len=*), intent(in), optional :: ls3
character(len=*), intent(in), optional :: axes3
real(wp), intent(in), dimension(:), optional :: x4
real(wp), intent(in), dimension(:), optional :: y4
character(len=*), intent(in), optional :: ls4
character(len=*), intent(in), optional :: axes4
this%plotscale='semilogx'
call plot2d_vector_vs_vector(this, &
x1, y1, ls1, axes1, &
x2, y2, ls2, axes2, &
x3, y3, ls3, axes3, &
x4, y4, ls4, axes4 )
! Set the plot scale as linear. It means log scale is off
this%plotscale='linear'
end subroutine semilogxv
!..............................................................................
subroutine semilogyv(this, x1, y1, ls1, axes1, &
x2, y2, ls2, axes2, &
x3, y3, ls3, axes3, &
x4, y4, ls4,axes4 )
!..............................................................................
! This procedure is the same as plotXY with logarithmic y1 and y2 axes
!..............................................................................
class(gpf):: this
! Input vector
real(wp), intent(in) :: x1(:) ! vector of data for x
real(wp), intent(in), optional :: y1(:) ! vector of data for y
character(len=*), intent(in), optional :: ls1 ! line specification
character(len=*), intent(in), optional :: axes1
real(wp), intent(in), dimension(:), optional :: x2
real(wp), intent(in), dimension(:), optional :: y2
character(len=*), intent(in), optional :: ls2
character(len=*), intent(in), optional :: axes2
real(wp), intent(in), dimension(:), optional :: x3
real(wp), intent(in), dimension(:), optional :: y3
character(len=*), intent(in), optional :: ls3
character(len=*), intent(in), optional :: axes3
real(wp), intent(in), dimension(:), optional :: x4
real(wp), intent(in), dimension(:), optional :: y4
character(len=*), intent(in), optional :: ls4
character(len=*), intent(in), optional :: axes4
this%plotscale='semilogy'
call plot2d_vector_vs_vector(this, &
x1, y1, ls1, axes1, &
x2, y2, ls2, axes2, &
x3, y3, ls3, axes3, &
x4, y4, ls4, axes4 )
! Set the plot scale as linear. It means log scale is off
this%plotscale='linear'
end subroutine semilogyv
subroutine loglogv(this, x1, y1, ls1, axes1, &
x2, y2, ls2, axes2, &
x3, y3, ls3, axes3, &
x4, y4, ls4, axes4 )
!..............................................................................
! This procedure is the same as plotXY with logarithmic x1, y1, x2, y2 axes
!..............................................................................
class(gpf):: this
! Input vector
real(wp), intent(in) :: x1(:) ! vector of data for x
real(wp), intent(in), optional :: y1(:) ! vector of data for y
character(len=*), intent(in), optional :: ls1 ! line specification
character(len=*), intent(in), optional :: axes1
real(wp), intent(in), dimension(:), optional :: x2
real(wp), intent(in), dimension(:), optional :: y2
character(len=*), intent(in), optional :: ls2
character(len=*), intent(in), optional :: axes2
real(wp), intent(in), dimension(:), optional :: x3
real(wp), intent(in), dimension(:), optional :: y3
character(len=*), intent(in), optional :: ls3
character(len=*), intent(in), optional :: axes3
real(wp), intent(in), dimension(:), optional :: x4
real(wp), intent(in), dimension(:), optional :: y4
character(len=*), intent(in), optional :: ls4
character(len=*), intent(in), optional :: axes4
this%plotscale='loglog'
call plot2d_vector_vs_vector(this, &
x1, y1, ls1, axes1, &
x2, y2, ls2, axes2, &
x3, y3, ls3, axes3, &
x4, y4, ls4, axes4 )
! Set the plot scale as linear. It means log scale is off
this%plotscale='linear'
end subroutine loglogv
subroutine semilogxm(this, xv, ymat, lspec)
!..............................................................................
!Plots a matrix against a vector with logarithmic x-axis
!For more information see plot2D_matrix_vs_vector procedure
!Everything is the same except the x-axis scale
!..............................................................................
implicit none
class(gpf) :: this
! Input arrays
real(wp), intent(in) :: xv(:)
real(wp), intent(in) :: ymat(:,:)
character(len=*), intent(in), optional :: lspec
this%plotscale='semilogx'
call plot2d_matrix_vs_vector(this, xv,ymat, lspec)
! Set the plot scale as linear. It means log scale is off
this%plotscale='linear'
end subroutine semilogxm
subroutine semilogym(this, xv,ymat, lspec)
!..............................................................................
!Plots a matrix against a vector with logarithmic y-axis
!For more information see plot2D_matrix_vs_vector procedure
!Everything is the same except the x-axis scale
!..............................................................................
implicit none
class(gpf) :: this
! Input arrays
real(wp), intent(in) :: xv(:)
real(wp), intent(in) :: ymat(:,:)
character(len=*), intent(in), optional :: lspec
this%plotscale='semilogy'
call plot2d_matrix_vs_vector(this, xv,ymat, lspec)
! Set the plot scale as linear. It means log scale is off
this%plotscale='linear'
end subroutine semilogym
subroutine loglogm(this, xv,ymat, lspec)
!..............................................................................
!Plots a matrix against a vector with logarithmic x-axis and y-axis
!For more information see plot2D_matrix_vs_vector procedure
!Everything is the same except the axes scale
!..............................................................................
implicit none
class(gpf) :: this
! Input arrays
real(wp), intent(in) :: xv(:)
real(wp), intent(in) :: ymat(:,:)
character(len=*), intent(in), optional :: lspec
this%plotscale='loglog'
call plot2d_matrix_vs_vector(this, xv,ymat, lspec)
! Set the plot scale as linear. It means log scale is off
this%plotscale='linear'
end subroutine loglogm
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!> Section Three: Animation Routines
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine sub_animation_start(this, pause_seconds)
!-------------------------------------------------------------------------------
! sub_animation_start: set the setting to start an animation
! it simply set flags and open a script file to write data
!-------------------------------------------------------------------------------
class(gpf) :: this
real, intent(in), optional :: pause_seconds
! ogpf does not support multiplot with animation at the same time
if (this%hasmultiplot) then
print*, md_name // ': does not support animation in multiplot mode!'
stop
end if
if (present(pause_seconds)) then
this%pause_seconds = pause_seconds
else
this%pause_seconds = 2 ! delay in second
end if
this%frame_number = 0
! create the ouput file for writting gnuplot script
call create_outputfile(this)
this%hasfileopen = .true.
this%hasanimation = .true.
end subroutine sub_animation_start
subroutine sub_animation_show(this)
!-------------------------------------------------------------------------------
! sub_animation_show: simply resets the animation flags
! and finalize the plotting.
!-------------------------------------------------------------------------------
class(gpf) :: this
this%frame_number = 0
this%hasanimation = .false.
call finalize_plot(this)
end subroutine sub_animation_show
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!> Section Four: Gnuplot direct scriptting
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine addscript(this,strcmd)
!..............................................................................
! addscript: accepts all type of gnuplot command as a string and store it
! in global txtscript to be later sent to gnuplot
!..............................................................................
class(gpf) :: this
character(len=*), intent(in) :: strcmd
if (.not.allocated(this%txtscript)) this%txtscript=''
if (len_trim(this%txtscript) == 0 ) then
this%txtscript = '' ! initialize string
end if
if ( len_trim(strcmd)>0 ) then
this%txtscript = this%txtscript // splitstr(strcmd)
end if
end subroutine addscript
subroutine runscript(this)
!..............................................................................
! runscript sends the the script string (txtstring) into a script
! file to be run by gnuplot
!..............................................................................
class(gpf):: this
!REV 0.18: a dedicated subroutine is used to create the output file
call create_outputfile(this)
!write the script
call processcmd(this)
write(unit=this%file_unit, fmt='(a)') this%txtscript
! close the file and call gnuplot
call finalize_plot(this)
end subroutine runscript
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!> Section Five: gnuplot command processing and data writing to script file
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine process_axes_set(axes_set, axes)
!..............................................................................
! process_axesspec accepts the axes set and interpret it into
! a format to be sent to gnuplot.
! the axes set can be one of the following set
! x1y1, x1y2, x2y1, x2y2
!..............................................................................
character(len=*), intent(in) :: axes_set
character(len=4), intent(out) :: axes
if (len_trim (adjustl(axes_set)) == 0) then
axes=''
return
end if
select case ( lcase(trim (adjustl (axes_set) ) ) )
case ('x1y1')
axes='x1y1'
case ('x1y2')
axes='x1y2'
case ('x2y1')
axes='x2y1'
case ('x2y2')
axes='x2y2'
case default ! wrong strings
print*, md_name // ':process_axes_set:' // ' wrong axes set is sent.'// new_line(' ') &
// 'axes set can be on of: x1y1, x1y2, x2y1, x2y2'
axes=''
return
end select
end subroutine process_axes_set
subroutine process_linespec(order, lsstring, lspec, axes_set)
!..............................................................................
! process_linespec accepts the line specification and interpret it into
! a format to be sent to gnuplot
!..............................................................................
integer, intent(in) :: order !1 for the first data series
character(len=*), intent(out) :: lsstring
character(len=*), intent(in), optional :: lspec
character(len=*), intent(in), optional :: axes_set
!local variables
character(len=4) :: axes
character(len=10) :: axes_setting
!check the axes set
axes_setting = ''
if ( present (axes_set)) then
call process_axes_set(axes_set, axes)
if (len(trim(axes))> 0 ) then
axes_setting = ' axes ' // axes
end if
end if
select case(order)
case(1)
if ( present(lspec) ) then
if (hastitle(lspec)) then
lsstring='plot "-" '//trim(lspec) // axes_setting
else
lsstring='plot "-" notitle '//trim(lspec) // axes_setting
end if
else
lsstring='plot "-" notitle' // axes_setting
end if
case default !e.g. 2, 3, 4, ...
if (present(lspec)) then
if (hastitle(lspec)) then
lsstring=', "-" '// trim(lspec) // axes_setting
else
lsstring=', "-" notitle '// trim(lspec) // axes_setting
end if
else
lsstring=', "-" notitle' // axes_setting
end if
end select
end subroutine process_linespec
subroutine processcmd(this)
!..............................................................................
! This subroutine writes all the data into plot file
! to be read by gnuplot
!..............................................................................
class(gpf) :: this
! write the plot style for data
! this is used only when 3D plots (splot, cplot) is used
if (allocated(this%txtdatastyle)) then
write ( this%file_unit, '("set style data ", a)' ) this%txtdatastyle
write ( this%file_unit, '(a)' )
end if
! Write options
if ( this%hasoptions ) then
write ( this%file_unit, '(" ")' )
write ( this%file_unit, '("# options")' )
write ( this%file_unit, '(a)' ) this%txtoptions
write ( this%file_unit, '(a)' )
end if
! Check with plot scale: i.e linear, logx, logy, or log xy
write( this%file_unit, '(" ")' )
write( this%file_unit, '("# plot scale")' )
select case (this%plotscale)
case ('semilogx')
write ( this%file_unit, '("set logscale x")' )
case ('semilogy')
write ( this%file_unit, '("set logscale y")' )
case ('loglog')
write ( this%file_unit, '("set logscale xy")' )
case default !for no setting
!pass
end select
!!>0.22
! write annotation
write ( this%file_unit, '(" ")' )
write ( this%file_unit, '("# Annotation: title and labels")' )
call write_label(this, 'plot_title')
call write_label(this, 'xlabel' )
call write_label(this, 'x2label' )
call write_label(this, 'ylabel' )
call write_label(this, 'y2label' )
call write_label(this, 'zlabel' )
! axes range
write ( this%file_unit, '(" ")')
write ( this%file_unit, '("# axes setting")')
if (this%hasxrange) then
write ( this%file_unit, '("set xrange [",G0,":",G0,"]")' ) this%xrange
end if
if (this%hasyrange) then
write ( this%file_unit, '("set yrange [",G0,":",G0,"]")' ) this%yrange
end if
if (this%haszrange) then
write ( this%file_unit, '("set zrange [",G0,":",G0,"]")' ) this%zrange
end if
! secondary axes range
if (this%hasx2range) then
write ( this%file_unit, '("set x2range [",G0,":",G0,"]")' ) this%x2range
end if
if (this%hasy2range) then
write ( this%file_unit, '("set y2range [",G0,":",G0,"]")' ) this%y2range
end if
! finish by new line
write ( this%file_unit, '(a)' ) ! emptyline
end subroutine processcmd
subroutine write_label(this, lblname)
!..............................................................................
! This subroutine writes the labels into plot file
! to be read by gnuplot
!..............................................................................
! write_label
class(gpf) :: this
character(len=*) :: lblname
! local var
character(len=:), allocatable :: lblstring
character(len=:), allocatable :: lblset
type(tplabel) :: label
select case (lblname)
case ('xlabel')
if (.not. (this%tpxlabel%has_label) ) then
return ! there is no label
end if
lblset = 'set xlabel "'
label = this%tpxlabel
case ('x2label')
if (.not. (this%tpx2label%has_label) ) then
return ! there is no label
end if
lblset = 'set x2label "'
label = this%tpx2label
case ('ylabel')
if (.not. (this%tpylabel%has_label) ) then
return ! there is no label
end if
lblset = 'set ylabel "'
label = this%tpylabel
case ('y2label')
if (.not. (this%tpy2label%has_label) ) then
return ! there is no label
end if
lblset = 'set y2label "'
label = this%tpy2label
case ('zlabel')
if (.not. (this%tpzlabel%has_label) ) then
return ! there is no label
end if
lblset = 'set zlabel "'
label = this%tpzlabel
case ('plot_title')
if (.not. (this%tpplottitle%has_label) ) then
return ! there is no label
end if
lblset = 'set title "'
label = this%tpplottitle
end select
lblstring = ''
! if there is a label continue to set it
lblstring = lblstring // lblset // trim(label%lbltext)//'"'
if (allocated(label%lblcolor)) then
lblstring = lblstring // ' tc "' //trim(label%lblcolor) // '"'
end if
! set font and size
if (allocated(this%tpxlabel%lblfontname)) then
lblstring = lblstring // ' font "'// trim(label%lblfontname) // ','
if (label%lblfontsize /= NOT_INITIALIZED) then
lblstring = lblstring // num2str(label%lblfontsize) //'"'
else
lblstring = lblstring //'"'
end if
else ! check if only font size has been given
if (label%lblfontsize /= NOT_INITIALIZED ) then
lblstring = lblstring // ' font ",' // num2str(label%lblfontsize) //'"'
end if
end if
! set rotation
if (label%lblrotate /= NOT_INITIALIZED ) then
lblstring = lblstring // ' rotate by ' // num2str(label%lblrotate )
end if
! write to ogpf script file
write ( this%file_unit, '(a)' ) lblstring
end subroutine write_label
function color_palettes(palette_name) result(str)
!...............................................................................
! color_palettes create color palette as a
! string to be written into gnuplot script file
! the palettes credit goes to: Anna Schnider (https://github.com/aschn) and
! Hagen Wierstorf (https://github.com/hagenw)
!...............................................................................
character(len=*), intent(in) :: palette_name
character(len=:), allocatable :: str
! local variables
character(len=1) :: strnumber
character(len=11) :: strblank
integer :: j
integer :: maxcolors
! define the color palettes
character(len=:), allocatable :: pltname
character(len=7) :: palette(9) ! palettes with maximum 9 colors
maxcolors = 8 ! default number of discrete colors
palette=''
select case ( lcase(trim(adjustl(palette_name))) )
case ('set1')
pltname='set1'
palette(1:maxcolors)=[&
"#E41A1C", "#377EB8", "#4DAF4A", "#984EA3", &
"#FF7F00", "#FFFF33", "#A65628", "#F781BF" ]
case ('set2')
pltname='set2'
palette(1:maxcolors)=[&
"#66C2A5", "#FC8D62", "#8DA0CB", "#E78AC3", &
"#A6D854", "#FFD92F", "#E5C494", "#B3B3B3" ]
case ('set3')
pltname='set3'
palette(1:maxcolors)=[&
"#8DD3C7", "#FFFFB3", "#BEBADA", "#FB8072", &
"#80B1D3", "#FDB462", "#B3DE69", "#FCCDE5" ]
case ('palette1')
pltname='palette1'
palette(1:maxcolors)=[&
"#FBB4AE", "#B3CDE3", "#CCEBC5", "#DECBE4", &
"#FED9A6", "#FFFFCC", "#E5D8BD", "#FDDAEC" ]
case ('palette2')
pltname='palette2'
palette(1:maxcolors)=[&
"#B3E2CD", "#FDCDAC", "#CDB5E8", "#F4CAE4", &
"#D6F5C9", "#FFF2AE", "#F1E2CC", "#CCCCCC" ]
case ('paired')
pltname='paired'
palette(1:maxcolors)=[&
"#A6CEE3", "#1F78B4", "#B2DF8A", "#33A02C", &
"#FB9A99", "#E31A1C", "#FDBF6F", "#FF7F00" ]
case ('dark2')
pltname='dark2'
palette(1:maxcolors)=[&
"#1B9E77", "#D95F02", "#7570B3", "#E7298A", &
"#66A61E", "#E6AB02", "#A6761D", "#666666" ]
case ('accent')
pltname='accent'
palette(1:maxcolors)=[&
"#7FC97F", "#BEAED4", "#FDC086", "#FFFF99", &
"#386CB0", "#F0027F", "#BF5B17", "#666666" ]
case ('jet')
! Matlab jet palette
maxcolors = 9
pltname='jet'
palette(1:maxcolors)=[&
'#000090', '#000fff', '#0090ff', '#0fffee', &
'#90ff70', '#ffee00', '#ff7000', '#ee0000', '#7f0000' ]
case default
print*, md_name // ": color_palettes: wrong palette name"
print*, 'gnuplot default palette will be used!'
str=' ' ! empty palette is returned!
return
end select
! generate the gnuplot palette as a single multiline string
str = '# Define the ' // pltname // ' pallete' // new_line(' ')
str = str // 'set palette defined ( \' // new_line(' ')
strblank = ' ' ! pad certain number of paces
do j=1, maxcolors - 1
write(unit =strnumber, fmt='(I1)' ) j-1
str = str // strblank // strnumber // ' "' // palette(j) // '",\' // new_line(' ')
end do
j =maxcolors
write(strnumber, fmt='(I1)') j
str = str // strblank // strnumber // ' "' // palette(j) // '" )' // new_line(' ')
end function color_palettes
subroutine write_xydata(file_unit,ndata,x,y)
!..............................................................................
! Writes set of xy data into a file
!..............................................................................
integer, intent(in) :: file_unit
integer, intent(in) :: ndata
real(wp), intent(in) :: x(:)
real(wp), intent(in), optional :: y(:)
integer:: i
! TODO (Mohammad#1#12/22/17): The format string shall be modified to write the
! number in more suitable form
! Rev 0.18
if (present(y) ) then !both x and y are present, data are xy set
do i = 1, ndata
write ( file_unit, * ) x(i), y(i)
end do
else !only x is passed, data are index-x set
do i = 1, ndata
write ( file_unit, * ) x(i)
end do
end if
write ( file_unit, '(a)' ) 'e' !end of set of data
end subroutine write_xydata
subroutine create_outputfile(this)
!..............................................................................
! Create an output file, assign a file_unit
! for writing the gnuplot commands
!..............................................................................
! Rev 0.18
class(gpf), intent(inout) :: this
if (this%hasfileopen) then
! there is nothing to do, file has been already open!
return
end if
!> Rev 0.2 animation
! animation handling
if (this%hasanimation ) then
this%frame_number = this%frame_number + 1 ! for future use
end if
! Open the output file
if (.not. (this%hasfilename)) then ! check if no file has been set by user
this%txtfilename=gnuplot_output_filename
end if
open ( newunit = this%file_unit, file = this%txtfilename, status = 'replace', iostat = this%status )
if (this%status /= 0 ) then
print*, "md_helperproc, create_outputfile: cannot open file for output"
stop
end if
! Set the gnuplot terminal, write ogpf configuration (customized setting)
! Can be overwritten by options
! write signature
write ( this%file_unit, '(a)' ) '# ' // md_name
write ( this%file_unit, '(a)' ) '# ' // md_rev
write ( this%file_unit, '(a)' ) '# ' // md_lic
write ( this%file_unit, '(a)' ) ! emptyline
! write the global settings
write ( this%file_unit, '(a)' ) '# gnuplot global setting'
write(unit=this%file_unit, fmt='(a)') 'set term ' // gnuplot_term_type // &
' size ' // gnuplot_term_size // ' enhanced font "' // &
gnuplot_term_font // '"' // &
' title "' // md_name // ': ' // md_rev //'"' ! library name and version
! write the preset configuration for gnuplot (ogpf customized settings)
if (this%preset_configuration) then
call this%preset_gnuplot_config()
end if
! write multiplot setting
if (this%hasmultiplot) then
write(this%file_unit, fmt='(a, I2, a, I2)') 'set multiplot layout ', &
this%multiplot_rows, ',', this%multiplot_cols
end if
! set flag true for file is opened
this%hasfileopen = .true.
end subroutine create_outputfile
subroutine preset_gnuplot_config(this)
!..............................................................................
! To write the preset configuration for gnuplot (ogpf customized settings)
!..............................................................................
class(gpf) :: this
write(this%file_unit, fmt='(a)')
write(this%file_unit, fmt='(a)') '# ogpf extra configuration'
write(this%file_unit, fmt='(a)') '# -------------------------------------------'
! color definition
write(this%file_unit, fmt='(a)') '# color definitions'
write(this%file_unit, fmt='(a)') 'set style line 1 lc rgb "#800000" lt 1 lw 2'
write(this%file_unit, fmt='(a)') 'set style line 2 lc rgb "#ff0000" lt 1 lw 2'
write(this%file_unit, fmt='(a)') 'set style line 3 lc rgb "#ff4500" lt 1 lw 2'
write(this%file_unit, fmt='(a)') 'set style line 4 lc rgb "#ffa500" lt 1 lw 2'
write(this%file_unit, fmt='(a)') 'set style line 5 lc rgb "#006400" lt 1 lw 2'
write(this%file_unit, fmt='(a)') 'set style line 6 lc rgb "#0000ff" lt 1 lw 2'
write(this%file_unit, fmt='(a)') 'set style line 7 lc rgb "#9400d3" lt 1 lw 2'
write(this%file_unit, fmt='(a)')
! axes setting
write(this%file_unit, fmt='(a)') '# Axes'
write(this%file_unit, fmt='(a)') 'set border linewidth 1.15'
write(this%file_unit, fmt='(a)') 'set tics nomirror'
write(this%file_unit, fmt='(a)')
write(this%file_unit, fmt='(a)') '# grid'
write(this%file_unit, fmt='(a)') '# Add light grid to plot'
write(this%file_unit, fmt='(a)') 'set style line 102 lc rgb "#d6d7d9" lt 0 lw 1'
write(this%file_unit, fmt='(a)') 'set grid back ls 102'
write(this%file_unit, fmt='(a)')
! set the plot style
write(this%file_unit, fmt='(a)') '# plot style'
write(this%file_unit, fmt='(a)') 'set style data linespoints'
write(this%file_unit, fmt='(a)')
write(this%file_unit, fmt='(a)') '# -------------------------------------------'
write(this%file_unit, fmt='(a)') ''
end subroutine preset_gnuplot_config
subroutine finalize_plot(this)
!..............................................................................
! To finalize the writing of gnuplot commands/data and close the output file.
!..............................................................................
class(gpf) :: this
! check for multiplots
if (this%hasmultiplot) then
if (this%multiplot_total_plots < this%multiplot_rows * this%multiplot_cols - 1 ) then
! increment the number of plots
this%multiplot_total_plots = this%multiplot_total_plots + 1
return ! do not finalize plot, still there is places in multiplot
else
! close multiplot
write(this%file_unit, fmt='(a)') 'unset multiplot'
! reset multiplot flag
this%hasmultiplot = .false.
end if
end if
close ( unit = this%file_unit ) ! close the script file
this%hasfileopen = .false. ! reset file open flag
this%hasanimation = .false.
! Use shell command to run gnuplot
if (get_os_type() == 1) then
call execute_command_line ('wgnuplot -persist ' // this%txtfilename) ! Now plot the results
else
call execute_command_line ('gnuplot -persist ' // this%txtfilename) ! Now plot the results
end if
contains
integer function get_os_type() result(r)
!! Returns one of OS_WINDOWS, others
!! At first, the environment variable `OS` is checked, which is usually
!! found on Windows.
!! Copy from fpm/fpm_environment: https://github.com/fortran-lang/fpm/blob/master/src/fpm_environment.f90
character(len=32) :: val
integer :: length, rc
integer, parameter :: OS_OTHERS = 0
integer, parameter :: OS_WINDOWS = 1
r = OS_OTHERS
! Check environment variable `OS`.
call get_environment_variable('OS', val, length, rc)
if (rc == 0 .and. length > 0 .and. index(val, 'Windows_NT') > 0) then
r = OS_WINDOWS
return
end if
end function
end subroutine finalize_plot
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!> Section Six: Utility and helper procedures
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function hastitle(string)
!..............................................................................
! check to see if the plot title (used as legend = key)
!..............................................................................
character(len=*), intent(in) :: string
logical:: hastitle
integer:: idx1
integer:: idx2
idx1=index( lcase(string),'title') !Check if title is passed
idx2=index(' ' // lcase(string),' t ') !Check if the abbreviated title 't' is passed. Extra space is added
! at the beginning of string to find starting 't'
if (idx1 /=0 .or. idx2 /=0 ) then
hastitle=.true.
else
hastitle=.false.
end if
end function hastitle
function checkdim(nx,ny)
!..............................................................................
! checkdim checks the equality of dimensions of two vector
!..............................................................................
integer, intent(in):: nx
integer, intent(in):: ny
logical:: checkdim
if (nx/=ny) then
checkdim=.false.
else
checkdim=.true.
end if
end function checkdim
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!> Section Seven: String utility Routines
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pure function splitstr(str) result(spstr)
!..............................................................................
!splitstr, separate a string using ";" delimiters
!..............................................................................
character(len=*), intent(in) :: str
! local variables
character, parameter :: delimiter=';'
character(len=:), allocatable :: spstr
integer :: n
integer :: m
integer :: k
k=len_trim(str) !length with removed trailing blanks
n=scan(str,delimiter)
if (n==0) then ! This is a single statement
spstr = adjustl(str) // new_line(' ')
return
end if
! for two or more statements separated by ;
spstr = ''
m=1
do while (n/=0 .and. m=65 .and. n <= 90) then
lcase(i:i)=char(n+32)
else
lcase(i:i)=chr
end if
end do
end function lcase
function num2str_i4(number_in)
!..............................................................................
! num2str_int: converts integer number to string
!..............................................................................
integer(kind=kind(1)), intent(in) :: number_in
character(len=:), allocatable :: num2str_i4
! local variable
character(len=range(number_in)) :: strnm
write(unit=strnm, fmt='(I0)') number_in
num2str_i4 = trim(strnm)
end function num2str_i4
function num2str_r4(number_in, strfmt)
!..............................................................................
! num2str_r4: converts single precision real number to string
! strfmt is the optional format string
!..............................................................................
real(kind=sp), intent(in) :: number_in
character(len=*), intent(in), optional :: strfmt
character(len=:), allocatable :: num2str_r4
! local variable
character(len=range(number_in)) :: strnm
if (present(strfmt)) then
write(unit=strnm, fmt= '('//trim(strfmt)//')' ) number_in
else
write(unit=strnm, fmt='(G0)') number_in
end if
num2str_r4 = trim(strnm)
end function num2str_r4
function num2str_r8(number_in, strfmt)
!..............................................................................
! num2str_real: converts double precision real number to string
! strfmt is the optional format string
!..............................................................................
real(kind=dp), intent(in) :: number_in
character(len=*), intent(in), optional :: strfmt
character(len=:), allocatable :: num2str_r8
! local variable
character(len=range(number_in)) :: strnm
if (present(strfmt)) then
write(unit=strnm, fmt= '('//trim(strfmt)//')' ) number_in
else
write(unit=strnm, fmt='(G0)') number_in
end if
num2str_r8 = trim(strnm)
end function num2str_r8
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!> Section Eight: Math helper function
!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function arange(xa, xb, dx)
!..............................................................................
! returns a vector in the form of [xa, xa+dx, xa+2*dx, ...]
! the number of elements is calculated as m = n+ 1,
! where n= int ( (xa-xb)/dx) ).
! arange is similar to colon in Matlab and arange in Python!
!
! NOTE:
! - If n calculated as zero, result is [xa]
! - If n calculated as Inf (dx=0), a fatal error will be raised
! - If n calculated as negative value (e.g xa 0.0 "
stop
end if
else
dxl = 1.0_wp
end if
if ( (xa < xb) .and. (dx < 0.0_wp) ) then
print*, "arange procedure: Fatal Error: wrong dx, use a dx > 0.0 "
stop
end if
n = int( (xb-xa)/ dxl) ! n+1 is the number of elements
allocate(arange(n), stat=ierr)
if (ierr /= 0) then
print*, "arange procedure: Fatal Error, allocation failed in arange function"
stop
end if
arange = [(xa + i*dxl, i=0, n)]
end function arange
function linspace(a,b,n_elements)
!..............................................................................
! returns a linearly spaced vector with n points in [a, b]
! if n is omitted, 100 points will be considered
!..............................................................................
real(wp), intent(in) :: a
real(wp), intent(in) :: b
integer, intent(in), optional :: n_elements
real(wp), allocatable :: linspace(:)
! Local vars
real(wp) :: dx
integer :: i
integer :: n
integer :: ierr
if (present(n_elements)) then
if (n_elements <=1 ) then
print*, "linspace procedure: Error: wrong value of n_elements, use an n_elements > 1"
stop
end if
n=n_elements
else
n=100
end if
allocate(linspace(n), stat=ierr)
if (ierr /= 0) then
print*, "linspace procedure: Fatal Error, Allocation failed in linspace function"
stop
end if
dx=(b-a)/real((n-1),wp)
linspace=[(i*dx+a, i=0,n-1)]
end function linspace
subroutine meshgrid(x,y,xgv,ygv, ierr)
!..............................................................................
!meshgrid generate mesh grid over a rectangular domain of [xmin xmax, ymin, ymax]
! Inputs:
! xgv, ygv are grid vectors in form of full grid data
! Outputs:
! X and Y are matrix each of size [ny by nx] contains the grid data.
! The coordinates of point (i,j) is [X(i,j), Y(i,j)]
! ierr: The error flag
! """
! # Example
! # call meshgrid(X, Y, [0.,1.,2.,3.],[5.,6.,7.,8.])
! # X
! # [0.0, 1.0, 2.0, 3.0,
! # 0.0, 1.0, 2.0, 3.0,
! # 0.0, 1.0, 2.0, 3.0,
! # 0.0, 1.0, 2.0, 3.0]
! #
! #Y
! #[ 5.0, 5.0, 5.0, 5.0,
! # 6.0, 6.0, 6.0, 6.0,
! # 7.0, 7.0, 7.0, 7.0,
! # 8.0, 8.0, 8.0, 8.0]
!..............................................................................
! Rev 0.2, Feb 2018
! New feature added: xgv and ygv as full grid vector are accepted now
! Arguments
real(wp), intent(out), allocatable :: x(:,:)
real(wp), intent(out), allocatable :: y(:,:)
real(wp), intent(in) :: xgv(:) ! x grid vector [start, stop, step] or [start, stop]
real(wp), intent(in), optional :: ygv(:) ! y grid vector [start, stop, step] or [start, stop]
integer, intent(out), optional :: ierr ! the error value
! Local variables
integer:: sv
integer:: nx
integer:: ny
logical:: only_xgv_available
! Initial setting
only_xgv_available = .false.
sv=0 !Assume no error
nx=size(xgv, dim=1)
if (present(ygv)) then
ny = size(ygv, dim=1)
else
only_xgv_available=.true.
ny=nx
end if
allocate(x(ny,nx),y(ny,nx),stat=sv)
if (sv /=0) then
print*, "allocataion erro in meshgrid"
stop
end if
x(1,:) = xgv
x(2:ny,:) = spread(xgv, dim=1, ncopies=ny-1)
if (only_xgv_available) then
y=transpose(x)
else
y(:,1) = ygv
y(:,2:nx) = spread(ygv,dim=2,ncopies=nx-1)
end if
if (present(ierr)) then
ierr=sv
end if
end subroutine meshgrid
!End of ogpf
end module ogpf