Fortran からの作図
forpy を使って、サンプルを元に matplotlib を呼び出します。キーワード変数などの使い方を学びます。
github.com
実行例
べき乗のグラフを片対数のグラフにプロットします。
ifort -fpp matplot.f90 forpy_mod.obj c:\IntelPython3\Libs\python36.lib
参考ページ: matplotlib の引数
プログラム
作図は、メインルーチンの最後に、block...end block 構造の中に閉じ込めることで、スッキリできます。
program matplot implicit none real, parameter :: pi = 4 * atan(1.0) real, allocatable :: x(:), y(:) integer :: i, n n = 20 x = [( 0.1 * i, i = 1, n)] y = 10.0**x block use forpy_mod integer :: ierr type(module_py) :: plt type(tuple) :: args, arg1, arg2 type(ndarray) :: x_nd, y_nd type(dict) :: kwargs !forpy ierr = forpy_initialize() if (ierr == NO_NUMPY_ERROR) stop 'numpy not found!' if (ierr /= 0) stop 'forpy initialization error!' !matplotlib ierr = import_py(plt, 'matplotlib.pyplot') if (exception_matches(ImportError)) stop 'matplotlib not found!' !main ierr = ndarray_create(x_nd, x) ierr = ndarray_create(y_nd, y) ! y-axis Log ierr = tuple_create(arg1, 1) ierr = arg1%setitem(0, "log") ierr = call_py_noret(plt, 'yscale', arg1) call arg1%destroy() ! Title ierr = tuple_create(arg1, 1) ierr = arg1%setitem(0, "Log plot") ierr = call_py_noret(plt, 'title', arg1) ! Grid x & y-axes (dasehed line) ierr = tuple_create(args, 3) ierr = args%setitem(0, .true.) ierr = args%setitem(1, "both") ierr = args%setitem(2, "both") ierr = dict_create(kwargs) ierr = kwargs%setitem("linestyle", 'dashed') ierr = call_py_noret(plt, 'grid', args, kwargs) ! set x, y data ierr = tuple_create(arg2, 2) ierr = arg2%setitem(0, x_nd) ierr = arg2%setitem(1, y_nd) ! plot ierr = call_py_noret(plt, 'plot', arg2) ierr = call_py_noret(plt, 'show') !clean up call x_nd%destroy() call y_nd%destroy() call arg1%destroy() call arg2%destroy() call args%destroy() call kwargs%destroy() call plt%destroy() ! forpy finalize call forpy_finalize() end block end program matplot
素のままでは、tuple や list や dict を用意するのがめんどくさいので、先日作ったような tuple, list 生成関数を用意して用いるのが好ましいかと思います。
それにつけても、ブラウザに作図する WebAgg サーバーが ctrl-C で中々終了しないのでイライラします。
蛇マジむかつく!
【Amazon.co.jp限定】邪神ちゃんドロップキック BOX 上巻 (初回限定版)(オリジナル映像特典ディスク付)[Blu-ray]
- 出版社/メーカー: ストロベリー・ミーツ ピクチュアズ
- 発売日: 2018/10/29
- メディア: Blu-ray
- この商品を含むブログを見る
追記 destroy 処理問題を気にしない場合
実行結果
プログラム
メインルーチン
program matplot implicit none real, parameter :: pi = 4 * atan(1.0) real, allocatable :: x(:), y(:) integer :: i, n n = 20 x = [( 0.1 * i, i = 1, n)] y = 10.0**x block use forpy_mod use m_tuple integer :: ierr type(module_py) :: plt type(ndarray) :: x_nd, y_nd !forpy ierr = forpy_initialize() if (ierr == NO_NUMPY_ERROR) stop 'numpy not found!' if (ierr /= 0) stop 'forpy initialization error!' !matplotlib ierr = import_py(plt, 'matplotlib.pyplot') if (exception_matches(ImportError)) stop 'matplotlib not found!' !main ierr = ndarray_create(x_nd, x) ierr = ndarray_create(y_nd, y) ierr = call_py_noret(plt, 'yscale', t_tuple("log")) ierr = call_py_noret(plt, 'title' , t_tuple("Matplotlib called from Fortran")) ierr = call_py_noret(plt, 'grid' , t_tuple(.true., 'both', 'both'), t_dict("linestyle", 'dashed')) ierr = call_py_noret(plt, 'plot' , t_tuple(x_nd, y_nd)) ierr = call_py_noret(plt, 'show') !clean up call x_nd%destroy() call y_nd%destroy() call plt %destroy() ! forpy finalize call forpy_finalize() end block end program matplot
tuple, list, dict 用ルーチン
module m_tuple use, intrinsic :: iso_fortran_env use forpy_mod implicit none type :: t_c class(*), pointer :: p => null() end type t_c type :: t_d character(:), pointer :: t => null() class(*) , pointer :: p => null() end type t_d contains subroutine tup_assign(tup, i, c) type(tuple), intent(in out) :: tup integer , intent(in) :: i class(*), intent(in) :: c integer :: ierr select type (c) type is (integer(int32)) ierr = tup%setitem(i, c) type is (integer(int64)) ierr = tup%setitem(i, c) type is (real(real32)) ierr = tup%setitem(i, c) type is (real(real64)) ierr = tup%setitem(i, c) type is (logical) ierr = tup%setitem(i, c) type is (character(*)) ierr = tup%setitem(i, c) type is (tuple) ierr = tup%setitem(i, c) type is (list) ierr = tup%setitem(i, c) type is (dict) ierr = tup%setitem(i, c) type is (ndarray) ierr = tup%setitem(i, c) type is (object) ierr = tup%setitem(i, c) class default stop 'error tup_assign' end select end subroutine tup_assign type(tuple) function t_tuple(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) result(tup) class(*), intent(in), optional, target :: c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15 integer :: ierr, i, n type(t_c) :: c(0:15) if (present(c0 )) c( 0)%p => c0 if (present(c1 )) c( 1)%p => c1 if (present(c2 )) c( 2)%p => c2 if (present(c3 )) c( 3)%p => c3 if (present(c4 )) c( 4)%p => c4 if (present(c5 )) c( 5)%p => c5 if (present(c6 )) c( 6)%p => c6 if (present(c7 )) c( 7)%p => c7 if (present(c8 )) c( 8)%p => c8 if (present(c9 )) c( 9)%p => c9 if (present(c10)) c(10)%p => c10 if (present(c11)) c(11)%p => c11 if (present(c12)) c(12)%p => c12 if (present(c13)) c(13)%p => c13 if (present(c14)) c(14)%p => c14 if (present(c15)) c(15)%p => c15 n = 0 do i = 0, 15 if (associated(c(i)%p)) n = n + 1 end do ierr = tuple_create(tup, n) do i = 0, 15 if (associated(c(i)%p)) call tup_assign(tup, i, c(i)%p) end do forall (i = 0:15) c(i)%p => null() end function t_tuple subroutine lis_append(lst, c) type(list), intent(in out) :: lst class(*), intent(in) :: c integer :: ierr select type (c) type is (integer(int32)) ierr = lst%append(c) type is (integer(int64)) ierr = lst%append(c) type is (real(real32)) ierr = lst%append(c) type is (real(real64)) ierr = lst%append(c) type is (logical) ierr = lst%append(c) type is (character(*)) ierr = lst%append(c) type is (tuple) ierr = lst%append(c) type is (list) ierr = lst%append(c) type is (dict) ierr = lst%append(c) type is (ndarray) ierr = lst%append(c) type is (object) ierr = lst%append(c) class default stop 'error lis_append' end select end subroutine lis_append type(list) function t_list(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) result(lst) class(*), intent(in), optional, target :: c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15 integer :: ierr, i type(t_c) :: c(0:15) if (present(c0 )) c( 0)%p => c0 if (present(c1 )) c( 1)%p => c1 if (present(c2 )) c( 2)%p => c2 if (present(c3 )) c( 3)%p => c3 if (present(c4 )) c( 4)%p => c4 if (present(c5 )) c( 5)%p => c5 if (present(c6 )) c( 6)%p => c6 if (present(c7 )) c( 7)%p => c7 if (present(c8 )) c( 8)%p => c8 if (present(c9 )) c( 9)%p => c9 if (present(c10)) c(10)%p => c10 if (present(c11)) c(11)%p => c11 if (present(c12)) c(12)%p => c12 if (present(c13)) c(13)%p => c13 if (present(c14)) c(14)%p => c14 if (present(c15)) c(15)%p => c15 ierr = list_create(lst) do i = 0, 15 if (associated(c(i)%p)) call lis_append(lst, c(i)%p) end do forall (i = 0:15) c(i)%p => null() end function t_list subroutine dic_assign(dic, t, d) type(dict), intent(in out) :: dic character(*), intent(in) :: t class(*) , intent(in) :: d integer :: ierr select type (d) type is (integer(int32)) ierr = dic%setitem(t, d) type is (integer(int64)) ierr = dic%setitem(t, d) type is (real(real32)) ierr = dic%setitem(t, d) type is (real(real64)) ierr = dic%setitem(t, d) type is (logical) ierr = dic%setitem(t, d) type is (character(*)) ierr = dic%setitem(t, d) type is (tuple) ierr = dic%setitem(t, d) type is (list) ierr = dic%setitem(t, d) type is (dict) ierr = dic%setitem(t, d) type is (ndarray) ierr = dic%setitem(t, d) type is (object) ierr = dic%setitem(t, d) class default stop 'error dic_assign' end select end subroutine dic_assign type(dict) function t_dict(t0, c0, t1, c1, t2, c2, t3, c3, t4, c4, t5, c5, t6, c6, t7, c7, t8, c8, t9, c9, & t10, c10, t11, c11, t12, c12, t13, c13, t14, c14, t15, c15) result(dct) character(*), intent(in), optional, target :: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15 class(*) , intent(in), optional, target :: c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15 integer :: ierr, i type(t_d) :: d(0:15) if (present(t0 )) d( 0)%t => t0 if (present(t1 )) d( 1)%t => t1 if (present(t2 )) d( 2)%t => t2 if (present(t3 )) d( 3)%t => t3 if (present(t4 )) d( 4)%t => t4 if (present(t5 )) d( 5)%t => t5 if (present(t6 )) d( 6)%t => t6 if (present(t7 )) d( 7)%t => t7 if (present(t8 )) d( 8)%t => t8 if (present(t9 )) d( 9)%t => t9 if (present(t10)) d(10)%t => t10 if (present(t11)) d(11)%t => t11 if (present(t12)) d(12)%t => t12 if (present(t13)) d(13)%t => t13 if (present(t14)) d(14)%t => t14 if (present(t15)) d(15)%t => t15 if (present(c0 )) d( 0)%p => c0 if (present(c1 )) d( 1)%p => c1 if (present(c2 )) d( 2)%p => c2 if (present(c3 )) d( 3)%p => c3 if (present(c4 )) d( 4)%p => c4 if (present(c5 )) d( 5)%p => c5 if (present(c6 )) d( 6)%p => c6 if (present(c7 )) d( 7)%p => c7 if (present(c8 )) d( 8)%p => c8 if (present(c9 )) d( 9)%p => c9 if (present(c10)) d(10)%p => c10 if (present(c11)) d(11)%p => c11 if (present(c12)) d(12)%p => c12 if (present(c13)) d(13)%p => c13 if (present(c14)) d(14)%p => c14 if (present(c15)) d(15)%p => c15 ierr = dict_create(dct) do i = 0, 15 if (associated(d(i)%p)) call dic_assign(dct, d(i)%t, d(i)%p) end do forall (i = 0:15) d(i)%t => null() d(i)%p => null() end forall end function t_dict end module m_tuple