以前の記事でいくつかのタイプの「データ出力」方法を見ました。 その時点では、シミュレーション結果をチャート(グラフ)で出力するのは別途 GUI アプリケーションを作成してサポートするつもりでしたが、やはりシミュレーション結果を手軽にチャートとして見ることができないのは苛立たしいので、JFreeChart の力を借りて画像ファイルとして出力できるようにしました。 あまり細かくチャートを設定できるようにはしてませんが、シミュレーション結果を手軽にチャートで確認するには充分かと。
チャート出力の基本
では、まず最低限必要なデータ出力の設定を見てみましょう。 SimulationBuilder の simulation ノードに以下のような png ノードを付加します:
new SimulationBuilder().simulation{ ... png(fileName:'chart1.png', overwrite:true){ chart(title:'Time-Temperature Chart'){ point(label:'Temperature', x:'time', y:'T') } } }
ちょっとノードが無駄にネストされてる感じもしますがご了承を。 以下、それぞれのノードを簡単に説明します:
- png ノードは出力する画像ファイルに関する設定。 png ノードは PNG 形式の画像を出力します。 fileName, overwrite 属性は説明の必要なしかと。
- chart ノードは出力するチャートに関する設定。 ここではチャートのタイトルを設定しています。
- point ノードはプロットするデータに関する設定。 label 属性は凡例に表示されるラベル、x, y はプロットに使うデータです。
この設定でチャートを出力すると以下のような PNG 画像が chart1.png というファイルで作成されます:
なかなかいい感じでは? 以下では、各ノードで設定できる項目をもう少し詳しく見ていきます。
png, jpeg / jpg ノード
上記の例では PNG ファイルで出力するために png ノードを使用しましたが、他にも JPEG 形式の画像としても出力できます。 この場合は jpeg / jpg ノードに同様の設定を書くだけです。 png ノードだけ、もしくは jpeg / jpg ノードだけに特有の設定項目はありません。
chart ノード
chart ノードではチャートの設定を行います。 上記の例ではチャートのタイトルを設定していましたが、他にも軸の設定が行えます。 例えば 軸のラベルや表示範囲を設定するには以下のようにします:
new SimulationBuilder().simulation{ ... png(fileName:'chart2.png', overwrite:true){ chart(title:'Time-Temperature Chart', domainLabel:'time', domain:[0d, 2d], rangeLabel:'Temperature', range:[0d, 85d]){ point(label:'Temperature', x:'time', y:'T') } } }
ここでは
- domainLabel 属性は x 軸のラベル(XLabel 属性でも可)、rangeLabel 属性は y 軸のラベル(YLabel でも可)です。
- domain 属性は x 軸の表示範囲、range 属性は y 軸の表示範囲です(どちらも Double のリスト)。
の設定を行っています。 チャートを出力するとこうなります:
他に設定できる項目は、org.jfree.chart.ChartFactory#createScatterPlot() メソッドに設定できる項目です:
- orientation : PlotOrientation
- legend : boolean
- tooltips : boolean
- url : boolean
詳しくは JFreeChart の ChartFactory のドキュメントを参照してください(こちら)。
point ノード
いちばん最下層のノードである point ノードはチャートにプロットする点を設定します。 このノードは data ノードでも構いません。 基本的にはデータ系列のラベル(凡例に使用)と x, y 座標に用いるデータ(物理量の名前。 もちろん登録されている必要があります)を設定するだけですが、x, y 属性にはクロージャを設定して、プロットする点をイジることができます。 例えば、最初のチャートで、温度に 10 を加えた値をプロットしたい場合は以下のようにします(2つ目の point ノード):
new SimulationBuilder().simulation{ ... png(fileName:'chart3.png', overwrite:true){ chart(title:'Time-Temperature Chart'){ point(label:'T', x:'time', y:'T') point(label:'T+10', x:'time', y:{ it.T+10d }) } } }
このクロージャには、観測量を保持している DataStore オブジェクトが渡されるので、プロパティアクセス(例では it.T)のようにして観測量のデータにアクセスできます。 これをプロットしたデータは以下のようになります:
言い忘れてましたが、point ノードを複数書けば、複数の系列のデータがプロットできます!
日本語を使う
最後に、ノードとは直接関係ありませんが、チャートのタイトルや軸ラベルに日本語を使いたい場合は、(通常の JFreeChart の場合と同様)ChartFatory.chartTheme プロパティを設定する必要があります:
import org.jfree.chart.StandardChartTheme import org.jfree.chart.ChartFactory // 日本語対応にするための設定 ChartFactory.chartTheme = StandardChartTheme.createLegacyTheme() new SimulationBuilder().simulation{ ... png(fileName:'japanese-chart.png', overwrite:true){ chart(title:'時間-温度 図', domainLabel:'時間', rangeLabel:'温度', ){ point(label:'温度', x:'time', y:'T') } } }
チャートを出力するとこうなります:
動くサンプルコード
以上をまとめて動くサンプルをどうぞ。 groops-core のバージョンは 0.1-beta にアップしてください:
@GrabResolver('https://github.com/waman/groops-core/tree/master/repo') @Grab('org.waman.groops:groops-core:0.1-beta') import org.waman.groops.builder.SimulationBuilder import org.waman.groops.simulation.system.* new SimulationBuilder().simulation{ system(new CoolSystem(), dt:0.1, T_room:17.0d, r:1.0d) initialConditions(time:0.0, T:82.3d) systemObservableSet() observe(continueWhile:{ it.T >= 30d }) png(fileName:'chart1.png', overwrite:true){ chart(title:'Time-Temperature Chart'){ point(label:'Temperature', x:'time', y:'T') } } png(fileName:'chart2.png', overwrite:true){ chart(title:'Time-Temperature Chart', domainLabel:'time', domain:[0d, 2d], rangeLabel:'Temperature', range:[0d, 85d]){ point(label:'Temperature', x:'time', y:'T') } } png(fileName:'chart3.png', overwrite:true){ chart(title:'Time-Temperature Chart'){ point(label:'T', x:'time', y:'T') point(label:'T+10', x:'time', y:{ it.T+10d }) } } }.simulate() /** Physical System subject to Newton's low of cooling. */ class CoolSystem extends AnnotationPhysicalSystem{ @State BigDecimal time @State double T @Parameter BigDecimal dt @Parameter T_room @Parameter r @Override void evolve(Map<String, Object> params){ time += dt T += -r*(T - T_room)*dt.doubleValue() } }
コードはこちらからダウンロードできます:
- 作者: ハーベイゴールド,ジャントボチニク,Harvey Gould,Jan Tobochnik,鈴木増雄,石川正勝,溜渕継博,宮島佐介
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2000/12
- メディア: 単行本
- クリック: 5回
- この商品を含むブログ (45件) を見る