IT pass HikiWiki - [Exp2022]NetCDF データの可視化 詳しい指定 Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

((<"スケジュール表・各回資料 (08/11)"|[Exp2022]スケジュール表・各回資料#08-2F11>))

{{toc}}

((<基礎|[Exp2022]NetCDF データの可視化 基礎>))では, GPhys を用いた最低限のスクリプトを基に, 可視化の方法を説明しました.
ここでは, 描画の少し詳しい指定方法について説明します.

GPhys では様々な凝った指定が可能です.
ここでは比較的使う機会があると思われる事柄について説明します.

#============================================================================
= 描画範囲やフォントサイズの指定

下のスクリプトは,
((<基礎|[Exp2022]NetCDF データの可視化 基礎>))の最初に説明した ((<tone_xy.rb|URL:/exp/fy2022/220811/practice_gphys/tone_xy.rb>)) を基に様々な指定を追加したものです.

((<tone_xy_2.rb|URL:/exp/fy2022/220811/practice_gphys/tone_xy_2.rb>))

    01  #!/usr/bin/ruby
    02  # 使用するライブラリの読み込み. (以下 2 行は「決まり文句」.)
    03  require "numru/ggraph"
    04  include NumRu
    05
    06  # NetCDF ファイル "air.2019.nc" から変数 "air" を読み, GPhys オブジェクト gp に
    07  # 格納
    08  gp = GPhys::IO.open( "air.2019.nc", "air" )
    09
    10  # 画面を開く (open)
    11  #   引数の 1 は画面への描画を表す
    12  #          2 はファイルへの出力を表す
    13  #            (デフォルトでは出力は pdf 形式でファイル名は dcl.pdf)
    14  DCL.gropn(1)
    15
    16  # 描画に関わる各種の指定
    17  DCL.sgpset('lfull',true) # 描画範囲を最大に設定 (ウィンドウのギリギリま で使用)
    18  DCL.uzfact(0.6)          # フォントサイズ (元の値に対する比率)
    19  DCL.sgpset('lclip',true) # 軸範囲を超えた領域を描画しない
    20  DCL.glpset('lmiss',true) # 欠損値処理
    21  GGraph.set_axes('xlabelint'=>30) # x 軸にラベルを書く間隔
    22  GGraph.set_axes('ylabelint'=>30) # y 軸にラベルを書く間隔
    23
    24  # 描画画面を準備
    25  #   itr の 1 は横軸, 縦軸ともに線形を表す
    26  #          2 は横軸が線形軸, 縦軸が対数軸を表す
    27  #          3 は横軸が対数軸, 縦軸が線形軸を表す
    28  #          4 は横軸, 縦軸ともに対数軸を表す
    29  #   viewport は描画可能範囲の中での図の描画範囲を表す
    30  #            (四隅 [x1,x2,y1,y2] の全体に対する比率)
    31  #   window は描画する軸の範囲を表す (四隅 [x1,x2,y1,y2] の値)
    32  GGraph.set_fig( 'itr'=> 1, 'viewport'=>[0.1,0.9,0.2,0.55], 'window'=>[0,360,-90,90] )
    33
    34  # トーン (色付け) で描画
    35  #   第一引数は描画するデータの GPhys オブジェクト
    36  #   第二引数の true は新しい図であることの指定
    37  #   以下の指定の順番は問わない
    38  #   annotate は図の右上に書かれる情報の表示の有無の指定
    39  #   nlev は使用するトーン (色分け) の数の指定
    40  GGraph.tone( gp, true, 'annotate'=>false, 'nlev'=>30 )
    41  # カラーバーを描画
    42  GGraph.color_bar
    43
    44  # 画面を閉じる (close)
    45  DCL.grcls

追加された指定は下の箇所です.
* 17 行目では, ウィンドウのギリギリまで描画できるように設定しています.
  逆に言うと, GPhys では特に指定しない場合, それほど広い範囲に描画するわけではありません.
* 18 行目では, フォントの大きさを元の大きさに対する比率で指定しています.
* 19 行目では, 軸範囲を超えた領域を描画しない (クリップする) 設定です.
  上のスクリプトではデータが保持する範囲全体を描画しているため影響がありませんが, データ範囲のうちの一部分だけ描画する際に役に立ちます.
* 20 行目では, 欠損値処理を行うことを指定しています.
  上のスクリプトで用いているデータには欠損値がありませんので影響がありませんが, 欠損値を含むデータを描画する際に役に立ちます.
* 21, 22 行目では, それぞれ x, y 軸にラベルを書く間隔を指定しています.
* 32 行目では描画範囲と描画する軸の範囲を指定しています.
  * viewport は, 描画可能範囲の中で縦横のどのくらいの範囲に描画するかを指定します.
    * 上のスクリプトでは, 17 行目でウィンドウギリギリまで描画する設定をしていますが, 実際に図が描かれる範囲はその中で viewport で指定された範囲となります.
  * window は, 描画する軸の範囲を指定しています.
    * この指定がない場合, 与えられたデータの範囲全体を描画します. 上のスクリプトで読んでいるデータの経度範囲は 0 度から 357.5 度ですが, window によって 0 度から 360 度の範囲を指定しているため, データ範囲を若干超えた軸範囲が描画されます.
* 40 行目では, トーンで描画する際にオプションを指定しています.
  * annotate は図の右上に情報 (上の例では level=1000 milibar など) を表示するかどうかを表します. 上のスクリプトでは false としていますので表示しません.
  * nlev はトーンの数を表します.

上のスクリプトを変更して実行してみると下のような図になるでしょう.

((<URL:/exp/fy2022/220811/practice_gphys/tone_xy_2.png>))


この図は, ((<基礎|[Exp2022]NetCDF データの可視化 基礎>))の最初に説明した ((<tone_xy.rb|URL:/exp/fy2022/220811/practice_gphys/tone_xy.rb>)) で書かれる図とは描画範囲などが異なることがわかるでしょう.


#============================================================================
= 海岸線の描画

下のスクリプトは, 上のスクリプトを基に海岸線を描くように変更したものです.

((<tone_xy_coast.rb|URL:/exp/fy2022/220811/practice_gphys/tone_xy_coast.rb>))


    01  #!/usr/bin/ruby
    02  # 使用するライブラリの読み込み. (以下 2 行は「決まり文句」.)
    03  require "numru/ggraph"
    04  include NumRu
    05
    06  # NetCDF ファイル "air.2019.nc" から変数 "air" を読み, GPhys オブジェクト gp に
    07  # 格納
    08  gp = GPhys::IO.open( "air.2019.nc", "air" )
    09
    10  # 画面を開く (open)
    11  #   引数の 1 は画面への描画を表す
    12  #          2 はファイルへの出力を表す
    13  #            (デフォルトでは出力は pdf 形式でファイル名は dcl.pdf)
    14  DCL.gropn(1)
    15
    16  # 描画に関わる各種の指定
    17  DCL.sgpset('lfull',true) # 描画範囲を最大に設定 (ウィンドウのギリギリま で使用)
    18  DCL.uzfact(0.6)          # フォントサイズ (元の値に対する比率)
    19  DCL.sgpset('lclip',true) # 軸範囲を超えた領域を描画しない
    20  DCL.glpset('lmiss',true) # 欠損値処理
    21  GGraph.set_axes('xlabelint'=>30) # x 軸にラベルを書く間隔
    22  GGraph.set_axes('ylabelint'=>30) # y 軸にラベルを書く間隔
    23
    24
    25  # 描画画面を準備
    26  #   itr の 1 は横軸, 縦軸ともに線形を表す
    27  #          2 は横軸が線形軸, 縦軸が対数軸を表す
    28  #          3 は横軸が対数軸, 縦軸が線形軸を表す
    29  #          4 は横軸, 縦軸ともに対数軸を表す
    30  #          10 は正距円筒図法 (いわゆる経度-緯度座標) を表す
    31  #   viewport は描画可能範囲の中での図の描画範囲を表す
    32  #            (四隅 [x1,x2,y1,y2] の全体に対する比率)
    33  #   window は描画する軸の範囲を表す (四隅 [x1,x2,y1,y2] の値)
    34  GGraph.set_fig( 'itr'=> 10, 'viewport'=>[0.1,0.9,0.2,0.55], 'window'=>[0,360,-90,90] )
    35
    36  # 地図情報の指定. ここでは海岸線を描くように設定.
    37  GGraph.set_map( 'coast_world'=>true, 'grid'=>true )
    38
    39  # トーン (色付け) で描画
    40  #   第一引数は描画するデータの GPhys オブジェクト
    41  #   第二引数の true は新しい図であることの指定
    42  #   以下の指定の順番は問わない
    43  #   annotate は図の右上に書かれる情報の表示の有無の指定
    44  #   map_axes は正距円筒図法において軸のラベルを書くかどうかの指定
    45  #   nlev は使用するトーン (色分け) の数の指定
    46  GGraph.tone( gp, true, 'annotate'=>false, 'map_axes'=>true, 'nlev'=>30 )
    47  # カラーバーを描画
    48  GGraph.color_bar
    49
    50  # 画面を閉じる (close)
    51  DCL.grcls

追加・変更された指定は以下の箇所です.
* 34 行目では, itr を 10 としています. これは正距円筒図法を用いて描画するもので, 地図の情報を使って海岸線を描く際には itr の値を 10 以降の値にする必要があります.
* 37 行目では, 世界の海岸線 (coast_world) とグリッド (grid) の描画を指定しています.
* 46 行目では, map_axes の指定で, 正距円筒図法 (itr=>10) において軸のラベルを書くように指定しています.
  * この指定は, itr が 10 の場合にのみ必要です. 逆に言うと, itr が 10 の時, この指定がないと軸のラベル (数値) が書かれません.

上のスクリプトを変更して実行してみると下のような図になるでしょう.

((<URL:/exp/fy2022/220811/practice_gphys/tone_xy_coast.png>))


#============================================================================
= ファイルへの出力

これまでは画面に結果を描画するスクリプトについて説明してきました.
しかし, レポートや卒業論文, 修士論文, ... などでは図を論文に貼るため, 図を画像ファイルとして保存しなければならないでしょう.

図を画像ファイルとして保存するには,

    DCL.gropn(1)

に与えられた引数を下のように変更します.

    DCL.gropn(2)

こうすると, 他に指定がない場合には pdf ファイルとして dcl.pdf という名前のファイルに保存されます.

上のスクリプトを変更して, 図を pdf ファイルに保存してみましょう.

なお, debian で pdf ファイルを閲覧するには, evince というコマンドを使うことができます.

  $ evince dcl.pdf

ただし, evince は標準ではインストールされていないかもしれません. その場合には,

  $ sudo apt install evince

でインストールすると良いでしょう.

== pdf 以外の画像形式への保存

pdf 以外の画像形式 (フォーマット) への保存には二つの方法が考えられます.
一つは, GPhys のスクリプトから画像を出力する際に別の形式で保存する方法で, もう一つは, 上の方法で保存した pdf ファイルを別の形式の画像に変換する方法です.


=== pdf 以外の画像形式での出力

GPhys のスクリプトで pdf 以外のフォーマットの画像に出力するには,

  DCL.gropn(2)

の前に, 下のようにフォーマットの変更を指定します.

  DCL.swpset("ifl",1)
  DCL.gropn(2)

上の例では ifl に 1 を指定していますが, これは png の形式で出力する指定です.
他の種類としては,
* 1:png
* 2:eps
* 3:SVG
* 4:PDF
となっています.

png 形式で出力した場合, ファイル名は dcl_0001.png となります.
(もし一つのスクリプトで複数枚(ページ)の図を描くと, それぞれのページが dcl_0001.png, dcl_0002.png, ... の名前で保存されます.)

なお, debian で png ファイルを閲覧するには, eog というコマンドを使うことができます.

  $ eog dcl_0001.png

ただし, eog は標準ではインストールされていないかもしれません. その場合には,

  $ sudo apt install eog

でインストールすると良いでしょう.


=== 画像形式の変換

pdf 形式のファイルを別の画像形式に変換するには, convert コマンドを使うことができます.

convert は標準ではインストールされていないかもしれません. その場合には,

  $ sudo apt install imagemagick

でインストールすると良いでしょう. (convert は imagemagick パッケージに含まれています.)

例えば png 形式に変換するには, もっとも簡単には下のようにすることで変換できます.

  $ convert dcl.pdf dcl.png

もしここで convert に関するエラーが出るようならば, 下に書かれている「convert 使用時のエラーへの対処」を参考にしてみてください.

ただし, これでは図が横倒しになってしまいます. したがって 90 度回転させるために下のようにすると良いでしょう.

  $ convert -rotate 90 dcl.pdf dcl.png

しかし, これでは, 生成される png ファイルの背景が透明になってしまい, 場合によって大変見難い図になってしまいます.
これを解決するには下のようにオプションを指定する方法があります.

  $ convert -rotate 90 dcl.pdf  \( +clone -alpha opaque -fill white -colorize 100% \) +swap -geometry +0+0 -compose Over -composite -alpha off dcl.png

* 参考ページ
  * ((<「コマンド一発で透過 png を綺麗に非透過 png にする」|URL:https://qiita.com/iwiwi/items/fdec3466c4dea5818b3a>))

==== convert 使用時のエラーへの対処

convert を用いて pdf ファイルを別の形式に変換しようとした際に, 下のようなエラーが表示されることがあります.

  convert-im6.q16: attempt to perform an operation not allowed by the security policy `PDF' @ error/constitute.c/IsCoderAuthorized/408.

この時には, /etc/ImageMagick-6/policy.xml を編集することで, convert の設定を変更します.

  $ sudo vi /etc/ImageMagick-6/policy.xml

によって vi で policy.xml を開き,

  <policy domain="coder" rights="none" pattern="PDF" />



  <policy domain="coder" rights="read|write" pattern="PDF" />

のように変えましょう.