@@ -22,11 +22,11 @@ module pyplot_module
2222 character (len=* ), parameter :: tmp_file = ' pyplot_module_temp_1234567890.py' ! ! Default name of the temporary file
2323 ! ! (this can also be user-specified).
2424
25- character (len=* ), parameter :: python_exe = ' python' ! ! The python executable name.
26- character (len=* ), parameter :: int_fmt = ' (I10)' ! ! integer format string
27- integer , parameter :: max_int_len = 10 ! ! max string length for integers
28- character (len=* ), parameter :: real_fmt = ' (E30.16)' ! ! real number format string
29- integer , parameter :: max_real_len = 30 ! ! max string length for reals
25+ character (len=* ), parameter :: python_exe = ' python' ! ! The python executable name.
26+ character (len=* ), parameter :: int_fmt = ' (I10)' ! ! integer format string
27+ integer , parameter :: max_int_len = 10 ! ! max string length for integers
28+ character (len=* ), parameter :: real_fmt_default = ' (E30.16)' ! ! default real number format string
29+ integer , parameter :: max_real_len = 30 ! ! max string length for reals
3030
3131 type, public :: pyplot
3232
@@ -42,6 +42,8 @@ module pyplot_module
4242 logical :: polar = .false. ! ! it is a polar plot
4343 logical :: axis_equal = .false. ! ! equal scale on each axis
4444
45+ character (len= :),allocatable :: real_fmt ! ! real number formatting
46+
4547 contains
4648
4749 ! public methods
@@ -73,7 +75,8 @@ subroutine destroy(me)
7375
7476 class(pyplot),intent (inout ) :: me ! ! pyplot handler
7577
76- if (allocated (me% str)) deallocate (me% str)
78+ if (allocated (me% str)) deallocate (me% str)
79+ if (allocated (me% real_fmt)) deallocate (me% real_fmt)
7780
7881 end subroutine destroy
7982! *****************************************************************************************
@@ -100,7 +103,7 @@ end subroutine add_str
100103
101104 subroutine initialize (me , grid , xlabel , ylabel , zlabel , title , legend , use_numpy , figsize , &
102105 font_size , axes_labelsize , xtick_labelsize , ytick_labelsize , ztick_labelsize , &
103- legend_fontsize , mplot3d , axis_equal , polar )
106+ legend_fontsize , mplot3d , axis_equal , polar , real_fmt )
104107
105108 class(pyplot), intent (inout ) :: me ! ! pyplot handler
106109 logical , intent (in ), optional :: grid ! ! activate grid drawing
@@ -120,6 +123,7 @@ subroutine initialize(me, grid, xlabel, ylabel, zlabel, title, legend, use_numpy
120123 logical , intent (in ), optional :: mplot3d ! ! set true for 3d plots (cannot use with polar)
121124 logical , intent (in ), optional :: axis_equal ! ! set true for axis = 'equal'
122125 logical , intent (in ), optional :: polar ! ! set true for polar plots (cannot use with mplot3d)
126+ character (len=* ), intent (in ), optional :: real_fmt ! ! format string for real numbers (examples: '(E30.16)' [default], '*')
123127
124128 character (len= max_int_len) :: width_str ! ! figure width dummy string
125129 character (len= max_int_len) :: height_str ! ! figure height dummy string
@@ -129,6 +133,7 @@ subroutine initialize(me, grid, xlabel, ylabel, zlabel, title, legend, use_numpy
129133 character (len= max_int_len) :: ytick_labelsize_str ! ! size of x axis tick labels dummy string
130134 character (len= max_int_len) :: ztick_labelsize_str ! ! size of z axis tick labels dummy string
131135 character (len= max_int_len) :: legend_fontsize_str ! ! size of legend font dummy string
136+
132137 character (len=* ), parameter :: default_font_size_str = ' 10' ! ! the default font size for plots
133138
134139 call me% destroy()
@@ -162,6 +167,11 @@ subroutine initialize(me, grid, xlabel, ylabel, zlabel, title, legend, use_numpy
162167 else
163168 me% axis_equal = .false.
164169 end if
170+ if (present (real_fmt)) then
171+ me% real_fmt = trim (adjustl (real_fmt))
172+ else
173+ me% real_fmt = real_fmt_default
174+ end if
165175
166176 call optional_int_to_string(font_size, font_size_str, default_font_size_str)
167177 call optional_int_to_string(axes_labelsize, axes_labelsize_str, default_font_size_str)
@@ -249,12 +259,12 @@ subroutine add_plot(me, x, y, label, linestyle, markersize, linewidth, xlim, yli
249259 if (allocated (me% str)) then
250260
251261 ! axis limits (optional):
252- if (present (xlim)) call vec_to_string(xlim, xlimstr, me% use_numpy)
253- if (present (ylim)) call vec_to_string(ylim, ylimstr, me% use_numpy)
262+ if (present (xlim)) call vec_to_string(xlim, me % real_fmt, xlimstr, me% use_numpy)
263+ if (present (ylim)) call vec_to_string(ylim, me % real_fmt, ylimstr, me% use_numpy)
254264
255265 ! convert the arrays to strings:
256- call vec_to_string(x, xstr, me% use_numpy)
257- call vec_to_string(y, ystr, me% use_numpy)
266+ call vec_to_string(x, me % real_fmt, xstr, me% use_numpy)
267+ call vec_to_string(y, me % real_fmt, ystr, me% use_numpy)
258268
259269 ! get optional inputs (if not present, set default value):
260270 call optional_int_to_string(markersize, imark, ' 3' )
@@ -298,7 +308,7 @@ end subroutine add_plot
298308!
299309! @note This requires `use_numpy` to be True.
300310
301- subroutine add_contour (me , x , y , z , label , linestyle , linewidth , levels , color )
311+ subroutine add_contour (me , x , y , z , label , linestyle , linewidth , levels , color , filled , cmap )
302312
303313 class(pyplot), intent (inout ) :: me ! ! pyplot handler
304314 real (wp),dimension (:), intent (in ) :: x ! ! x values
@@ -309,6 +319,8 @@ subroutine add_contour(me, x, y, z, label, linestyle, linewidth, levels, color)
309319 integer , intent (in ), optional :: linewidth ! ! width of the plot line
310320 real (wp),dimension (:), intent (in ), optional :: levels ! ! contour levels to plot
311321 character (len=* ), intent (in ), optional :: color ! ! color of the contour line
322+ logical , intent (in ), optional :: filled ! ! use filled control (default=False)
323+ character (len=* ), intent (in ), optional :: cmap ! ! colormap if filled=True (examples: 'jet', 'bone')
312324
313325 character (len= :), allocatable :: xstr ! ! x values strinfied
314326 character (len= :), allocatable :: ystr ! ! y values strinfied
@@ -322,14 +334,15 @@ subroutine add_contour(me, x, y, z, label, linestyle, linewidth, levels, color)
322334 character (len=* ), parameter :: yname_ = ' Y' ! ! Y variable name for contour
323335 character (len=* ), parameter :: zname_ = ' Z' ! ! Z variable name for contour
324336 character (len= :), allocatable :: extras ! ! optional stuff
337+ character (len= :), allocatable :: contourfunc ! ! 'contour' or 'contourf'
325338
326339 if (allocated (me% str)) then
327340
328341 ! convert the arrays to strings:
329- call vec_to_string(x, xstr, me% use_numpy)
330- call vec_to_string(y, ystr, me% use_numpy)
331- call matrix_to_string(z, zstr, me% use_numpy)
332- if (present (levels)) call vec_to_string(levels, levelstr, me% use_numpy)
342+ call vec_to_string(x, me % real_fmt, xstr, me% use_numpy)
343+ call vec_to_string(y, me % real_fmt, ystr, me% use_numpy)
344+ call matrix_to_string(z, me % real_fmt, zstr, me% use_numpy)
345+ if (present (levels)) call vec_to_string(levels, me % real_fmt, levelstr, me% use_numpy)
333346
334347 ! get optional inputs (if not present, set default value):
335348 call optional_int_to_string(linewidth, iline, ' 3' )
@@ -349,9 +362,16 @@ subroutine add_contour(me, x, y, z, label, linestyle, linewidth, levels, color)
349362 if (present (levels)) extras = extras// ' ,' // ' levels=' // levelstr
350363 if (present (color)) extras = extras// ' ,' // ' colors="' // color// ' "'
351364 if (present (linewidth)) extras = extras// ' ,' // ' linewidths=' // trim (adjustl (iline))
365+ if (present (cmap)) extras = extras// ' ,' // ' cmap="' // cmap// ' "'
366+
367+ ! filled or regular:
368+ contourfunc = ' contour' ! default
369+ if (present (filled)) then
370+ if (filled) contourfunc = ' contourf' ! filled contour
371+ end if
352372
353373 ! write the plot statement:
354- call me% add_str(' CS = ax.contour (' // xname_// ' ,' // yname_// ' ,' // zname_// ' ,' // &
374+ call me% add_str(' CS = ax.' // contourfunc // ' (' // xname_// ' ,' // yname_// ' ,' // zname_// ' ,' // &
355375 ' label="' // trim (label)// ' ",' // &
356376 ' linestyles="' // trim (adjustl (linestyle))// ' "' // &
357377 extras// ' )' )
@@ -396,9 +416,9 @@ subroutine add_3d_plot(me, x, y, z, label, linestyle, markersize, linewidth)
396416 if (allocated (me% str)) then
397417
398418 ! convert the arrays to strings:
399- call vec_to_string(x, xstr, me% use_numpy)
400- call vec_to_string(y, ystr, me% use_numpy)
401- call vec_to_string(z, zstr, me% use_numpy)
419+ call vec_to_string(x, me % real_fmt, xstr, me% use_numpy)
420+ call vec_to_string(y, me % real_fmt, ystr, me% use_numpy)
421+ call vec_to_string(z, me % real_fmt, zstr, me% use_numpy)
402422
403423 ! get optional inputs (if not present, set default value):
404424 call optional_int_to_string(markersize, imark, ' 3' )
@@ -466,15 +486,15 @@ subroutine add_bar(me, left, height, label, width, bottom, color, yerr, align, x
466486 if (allocated (me% str)) then
467487
468488 ! axis limits (optional):
469- if (present (xlim)) call vec_to_string(xlim, xlimstr, me% use_numpy)
470- if (present (ylim)) call vec_to_string(ylim, ylimstr, me% use_numpy)
489+ if (present (xlim)) call vec_to_string(xlim, me % real_fmt, xlimstr, me% use_numpy)
490+ if (present (ylim)) call vec_to_string(ylim, me % real_fmt, ylimstr, me% use_numpy)
471491
472492 ! convert the arrays to strings:
473- call vec_to_string(left, xstr, me% use_numpy)
474- call vec_to_string(height, ystr, me% use_numpy)
475- if (present (width)) call vec_to_string(width, wstr, me% use_numpy)
476- if (present (bottom)) call vec_to_string(bottom, bstr, me% use_numpy)
477- if (present (yerr)) call vec_to_string(yerr, yerr_str, me% use_numpy)
493+ call vec_to_string(left, me % real_fmt, xstr, me% use_numpy)
494+ call vec_to_string(height, me % real_fmt, ystr, me% use_numpy)
495+ if (present (width)) call vec_to_string(width, me % real_fmt, wstr, me% use_numpy)
496+ if (present (bottom)) call vec_to_string(bottom, me % real_fmt, bstr, me% use_numpy)
497+ if (present (yerr)) call vec_to_string(yerr, me % real_fmt, yerr_str, me% use_numpy)
478498
479499 ! write the arrays:
480500 call me% add_str(trim (xname)// ' = ' // xstr)
@@ -562,9 +582,10 @@ end subroutine integer_to_string
562582!
563583! Real vector to string.
564584
565- subroutine vec_to_string (v , str , use_numpy )
585+ subroutine vec_to_string (v , fmt , str , use_numpy )
566586
567587 real (wp), dimension (:), intent (in ) :: v ! ! real values
588+ character (len=* ), intent (in ) :: fmt ! ! real format string
568589 character (len= :), allocatable , intent (out ) :: str ! ! real values stringified
569590 logical , intent (in ) :: use_numpy ! ! activate numpy python module usage
570591
@@ -574,7 +595,11 @@ subroutine vec_to_string(v, str, use_numpy)
574595
575596 str = ' ['
576597 do i= 1 , size (v)
577- write (tmp, real_fmt, iostat= istat) v(i)
598+ if (fmt==' *' ) then
599+ write (tmp, * , iostat= istat) v(i)
600+ else
601+ write (tmp, fmt, iostat= istat) v(i)
602+ end if
578603 if (istat/= 0 ) error stop ' Error in vec_to_string'
579604 str = str// trim (adjustl (tmp))
580605 if (i< size (v)) str = str // ' ,'
@@ -592,9 +617,10 @@ end subroutine vec_to_string
592617!
593618! Real matrix (rank 2) to string.
594619
595- subroutine matrix_to_string (v , str , use_numpy )
620+ subroutine matrix_to_string (v , fmt , str , use_numpy )
596621
597622 real (wp), dimension (:,:), intent (in ) :: v ! ! real values
623+ character (len=* ), intent (in ) :: fmt ! ! real format string
598624 character (len= :), allocatable , intent (out ) :: str ! ! real values stringified
599625 logical , intent (in ) :: use_numpy ! ! activate numpy python module usage
600626
@@ -603,9 +629,9 @@ subroutine matrix_to_string(v, str, use_numpy)
603629
604630 str = ' ['
605631 do i= 1 , size (v,1 ) ! rows
606- call vec_to_string(v(i,:), tmp, use_numpy) ! one row at a time
632+ call vec_to_string(v(i,:), fmt, tmp, use_numpy) ! one row at a time
607633 str = str// trim (adjustl (tmp))
608- if (i< size (v)) str = str // ' ,'
634+ if (i< size (v, 1 )) str = str // ' ,'
609635 end do
610636 str = str // ' ]'
611637
0 commit comments