個人的にはWPF用のグラフ作成ライブラリとして一押しのScottPlotですが、最近Pythonの記事に集中していたせいで、ScottPlot のバージョンアップをフォローしきれていませんでした。
以前のデモプログラムに最新版のScotPlot Nuget でインストールしたところ、結構仕様が変わっていて修正が必要でした。
そこで、今回は ScottPlot 4.1 用に書き直したデモプログラムの紹介と、 旧バージョン(4.0)との違いについて触れたいと思います。
尚、ScottPlot 4.1で本格的にグラフを描く上で必要な情報(軸タイトル指定、凡例、上限下限の設定、任意の文字列表示など)については、【WPF】いちばんやさしいScottPlot の使い方(WindowsForm共通)の記事でサンプルを公開しています。
ScottPlotで簡単にグラフを描画できるようにユーザーコントロール化もしていますので、コピペしてすぐに使いたい方は下記の記事をご活用下さい。
【WPF】C#+ScottPlotで折れ線グラフのユーザーコントロールを作る! |
【WPF】ScottPlot 4.1でY2軸に対応した複合グラフのユーザーコントロールを作る! |
【WPF】C#+ScottPlotで円グラフのユーザーコントロールを作る! |
より深い情報が必要な際は、ScottPlotの公式ページに各グラフの画像とソースコードが掲載されていますので、こちらも参考にして下さい。
デモプログラムの概要
今回のデモプログラムの画面は次の様になります。
タブが3つあって、各タブに4グラフ、合計12種類のグラフを表示します。
タブを切り替えることで、下記のグラフが表示されます。
ScottPlotの構造
ScotPlot は、ScottPlot.Plot でインスタンスを生成し、そのインスタンスに対して折線グラフや棒グラフを追加していきます。
各グラフの太さや色、表示する軸(X,Yども2軸まで表示可能)は、グラフのメソッドを読んだ時に返されるオブジェクトに対して行います。
1 2 3 4 |
plt = new ScottPlot.Plot(600, 400) var sig = plt.AddSignal(DataGen.Sin(51, mult: 1)); sig.YAxisIndex = 0; chart.Render(); |
ScottPlot 4.0 までは、グラフ作成メソッドに色や太さなどの引数があったのですが、ScottPlot 4.1 から上記の仕様変更が行われたため、引数がかなり省略されています。
下図は、ScottPlotクラスの内部構造のイメージ図となります。
ちなみに、デモプログラムでは ScottPlotをコントロールとして画面に張り付け、"uxChart" という名を付けており、この場合は以下のような記述になります。
1 2 3 4 |
plt = uxChart.Plot; var sig = plt.AddSignal(DataGen.Sin(51, mult: 1)); sig.YAxisIndex = 0; chart.Render(); |
ScottPlot 4.1 のインストール方法
今回は Visual Studio 2022 を前提とした解説になりますが、Visual Studio の過去バージョン(2019,2017)をお使いの方でも共通です。
まず、NuGetから「scottplot」というキーワードで検索し、「ScottPlot.WPF」を自分のプロジェクトにインストールします。
WindowsFormで利用されたい方は、その下の「ScottPlot.WinForms」をお選びください。
デモプログラムの紹介
参考までにデモプログラムのソースコードを公開しますが、ScottPlotは入っていません。
リビルドを行う場合は、事前にNuGetを使ってインストールをお願いします。
デモプログラムのソースコードダウンロードURL
デモプログラムのソースコードはこちらからダウンロードできます。
ScottPlot Ver 4.1 デモプログラムソースコード一式
XAMLのソースコード
XAMLのソースコードは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<Window x:Class="ScotPlotTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ScotPlotTest" mc:Ignorable="d" Title="MainWindow" Height="450" Width="1320"> <Grid> <TabControl> <TabItem Header="チャート1"> <Grid> <WpfPlot x:Name="uxChart1" HorizontalAlignment="Left" Height="315" Margin="27,53,0,0" VerticalAlignment="Top" Width="300"/> <WpfPlot x:Name="uxChart2" HorizontalAlignment="Left" Height="315" Margin="345,53,0,0" VerticalAlignment="Top" Width="300"/> <WpfPlot x:Name="uxChart3" HorizontalAlignment="Left" Height="315" Margin="664,53,0,0" VerticalAlignment="Top" Width="300"/> <WpfPlot x:Name="uxChart4" HorizontalAlignment="Left" Height="315" Margin="987,53,0,0" VerticalAlignment="Top" Width="300"/> <Button Content="描画" HorizontalAlignment="Left" Margin="1212,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click" Height="21"/> </Grid> </TabItem> <TabItem Header="チャート2"> <Grid> <Button Content="描画" HorizontalAlignment="Left" Margin="1212,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/> <WpfPlot x:Name="uxChart5" HorizontalAlignment="Left" Height="315" Margin="27,53,0,0" VerticalAlignment="Top" Width="300"/> <WpfPlot x:Name="uxChart6" HorizontalAlignment="Left" Height="315" Margin="345,53,0,0" VerticalAlignment="Top" Width="300"/> <WpfPlot x:Name="uxChart7" HorizontalAlignment="Left" Height="315" Margin="664,53,0,0" VerticalAlignment="Top" Width="300"/> <WpfPlot x:Name="uxChart8" HorizontalAlignment="Left" Height="315" Margin="987,53,0,0" VerticalAlignment="Top" Width="300"/> </Grid> </TabItem> <TabItem Header="チャート3"> <Grid> <Button Content="描画" HorizontalAlignment="Left" Margin="1212,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/> <WpfPlot x:Name="uxChart9" HorizontalAlignment="Left" Height="315" Margin="27,53,0,0" VerticalAlignment="Top" Width="300"/> <WpfPlot x:Name="uxChart10" HorizontalAlignment="Left" Height="315" Margin="345,53,0,0" VerticalAlignment="Top" Width="300"/> <WpfPlot x:Name="uxChart11" HorizontalAlignment="Left" Height="315" Margin="664,53,0,0" VerticalAlignment="Top" Width="300"/> <WpfPlot x:Name="uxChart12" HorizontalAlignment="Left" Height="315" Margin="987,53,0,0" VerticalAlignment="Top" Width="300"/> </Grid> </TabItem> </TabControl> </Grid> </Window> |
C#のソースコード
C#側のソースコードは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
using ScottPlot; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace ScotPlotTest { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { Random rand = new Random(); //折れ線グラフのデータ作成 double[] xs = Enumerable.Range(0, 100).Select(i => (double)i).ToArray(); double[] ys = Enumerable.Range(0, 100).Select(i => (double)(i + rand.Next(0,100) * ((rand.Next(1,2) == 1) ? 1 : -1))).ToArray(); double[] ys1 = Enumerable.Range(0, 100).Select(i => Math.Sin(i * 0.1)).ToArray(); double[] ys2 = Enumerable.Range(0, 100).Select(i => 2 + Math.Cos(i * 0.1)).ToArray(); double[] ys3 = Enumerable.Range(0, 100).Select(i => 4 + Math.Sin(i * 0.1) * Math.Cos(i * 0.1)).ToArray(); double[] ys4 = Enumerable.Range(0, 100).Select(i => 1000 + Math.Sin(i * 0.1) * Math.Cos(i * 0.1)).ToArray(); //グラフの描画 DrawLine(uxChart1,"折れ線グラフ",xs, ys); List<(string legend, double[] xs, double[] ys,int axis)> linedata = new List<(string legend, double[] xs, double[] ys,int axis)>(); linedata.Add(("legend1", xs, ys1,0)); linedata.Add(("legend2", xs, ys2,0)); linedata.Add(("legend3", xs, ys3,0)); linedata.Add(("legend4", xs, ys4,1)); DrawLine(uxChart2, "折れ線グラフ(複数)", linedata); //散布図 DrawScatt(uxChart3, "散布図", xs, ys); //円グラフ double[] values = { 778, 43, 283, 76, 184 }; string[] labels = { "C#", "JAVA", "Python", "F#", "PHP" }; DrawPie(uxChart4, "円グラフ", labels, values); //縦棒グラフ DrawColumn(uxChart5, "縦棒グラフ", labels, values); //横棒グラフ DrawBar(uxChart6, "横棒グラフ", labels, values); //グルーピングのデータ作成 string[] items = { "コア数", "クロック数", "スレッド数", "キャッシュ", "価格" }; List<(string, double[])> datas = new List<(string, double[])>(); datas.Add(("Core-i7", new double[] { 8, 3.6, 16, 64, 70 })); datas.Add(("Core-i5", new double[] { 6, 2.8, 12, 32, 50 })); datas.Add(("Core-i3", new double[] { 4, 2.0, 8, 16, 30 })); datas.Add(("Pentium", new double[] { 2, 1.8, 4, 8, 10 })); datas.Add(("Celeron", new double[] { 2, 1.5, 4, 8, 5 })); //棒グラフ(グルーピング) DrawGroupColumn(uxChart7, "グループ", items, datas); //積み上げグラフ DrawStack(uxChart8, "積み上げ", items, datas); //レーダーチャート DrawRadar(uxChart9, "レーダー", items, datas); //箱ひげ図 DrawPopulations(uxChart10, "箱ひげ", ys); //散布図と回帰直線 DrawRegression(uxChart11, "回帰", xs, ys); ///ヒストグラム DrawHistgram(uxChart12, "ヒストグラム", ys,20); } /// <summary> /// 折れ線グラフ /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="xs"></param> /// <param name="ys"></param> private void DrawLine(WpfPlot chart, string title, double[] xs,double[] ys) { chart.Plot.Clear(); chart.Plot.Title(title); chart.Plot.AddSignalXY(xs,ys); chart.Render(); } /// <summary> /// 折れ線グラフ(複数) /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="datas"></param> private void DrawLine(WpfPlot chart, string title, List<(string legend,double[] xs, double[] ys,int axis)> datas) { chart.Plot.Clear(); chart.Plot.Title(title); foreach (var data in datas) { var sig = chart.Plot.AddSignalXY(data.xs, data.ys, label: data.legend); sig.YAxisIndex = data.axis; } //data.axis に1つでも1以上があれば2軸を表示 chart.Plot.YAxis2.Ticks(datas.Count(i=>i.axis > 0) > 0); chart.Plot.Legend(location: Alignment.UpperRight); chart.Render(); } /// <summary> /// 散布図 /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="xs"></param> /// <param name="ys"></param> private void DrawScatt(WpfPlot chart,string title, double[] xs, double[] ys) { chart.Plot.Clear(); chart.Plot.Title(title); chart.Plot.AddScatter(xs, ys, lineWidth: 0); chart.Render(); } /// <summary> /// 円グラフ /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="labels"></param> /// <param name="values"></param> private void DrawPie(WpfPlot chart, string title, string[] labels,double[] values) { chart.Plot.Clear(); chart.Plot.Title(title); var pie = chart.Plot.AddPie(values); pie.SliceLabels = labels; pie.ShowLabels = true; chart.Render(); } /// <summary> /// 縦棒グラフ /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="labels"></param> /// <param name="ys"></param> private void DrawColumn(WpfPlot chart, string title, string[] labels, double[] ys) { chart.Plot.Clear(); chart.Plot.Title(title); chart.Plot.AddBar(ys,DataGen.Consecutive(ys.Length)); chart.Plot.XTicks(labels); chart.Render(); } /// <summary> /// 横棒グラフ /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="labels"></param> /// <param name="ys"></param> private void DrawBar(WpfPlot chart, string title, string[] labels, double[] ys) { chart.Plot.Clear(); chart.Plot.Title(title); var bar = chart.Plot.AddBar(ys,DataGen.Consecutive(ys.Length)); bar.Orientation = ScottPlot.Orientation.Horizontal; chart.Plot.YTicks(labels); chart.Render(); } /// <summary> /// 箱ひげ図 /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="ys"></param> private void DrawPopulations(WpfPlot chart, string title, double[] ys) { chart.Plot.Clear(); chart.Plot.Title(title); chart.Plot.AddPopulation(new ScottPlot.Statistics.Population(ys)); chart.Plot.XAxis.Ticks(false); chart.Render(); } /// <summary> /// 散布図と回帰直線 /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="xs"></param> /// <param name="ys"></param> private void DrawRegression(WpfPlot chart,string title, double[] xs, double[] ys) { var model = new ScottPlot.Statistics.LinearRegressionLine(xs, ys); chart.Plot.Clear(); chart.Plot.Title((title != "") ? title : "Y = {model.slope:0.0000}x + {model.offset:0.0}\nR² = {model.rSquared:0.0000}"); chart.Plot.AddScatter(xs, ys, lineWidth: 0); chart.Plot.AddLine(model.slope, model.offset, (xs.Min(), xs.Max()), lineWidth: 2); chart.Render(); } /// <summary> /// 縦棒グラフ(グループ) /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="labels"></param> /// <param name="values"></param> private void DrawGroupColumn(WpfPlot chart, string title, string[] labels, List<(string legend,double[] ys)> values) { chart.Plot.Clear(); chart.Plot.Title(title); var datas = Enumerable.Range(0, values[0].ys.Length).Select(y => Enumerable.Range(0, values.Count).Select(x => values[x].ys[y]).ToArray()).ToArray(); chart.Plot.AddBarGroups(values.Select(i => i.legend).ToArray(), labels, datas,null); chart.Plot.Legend(location: Alignment.UpperRight); chart.Render(); } /// <summary> /// 積み上げグラフ /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="labels"></param> /// <param name="values"></param> private void DrawStack(WpfPlot chart, string title, string[] labels, List<(string legend, double[] ys)> values) { //チャートエリアのクリア chart.Plot.Clear(); //タイトルの設定 chart.Plot.Title(title); //X軸のデータを生成 var x = Enumerable.Range(0, labels.Length).Select(i => (double)i).ToArray(); //積み上げ用配列の初期化と合計計算 var sum = values.Select(i => i.ys.Sum()).ToArray(); //積み上げグラフ作成(トップから順に描画) for(int n = 0;n < values.Count;n ++) { var bar = chart.Plot.AddBar(sum.ToArray(),x); bar.Label = labels[n]; Enumerable.Range(0, sum.Length).Select(i => sum[i] = sum[i] - values[i].ys[n]).ToArray(); } //凡例と軸の設定 chart.Plot.Legend(location: Alignment.UpperRight); chart.Plot.XTicks(values.Select(i=>i.legend).ToArray()); //レンダリング chart.Render(); } /// <summary> /// レーダーチャート /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="labels"></param> /// <param name="values"></param> private void DrawRadar(WpfPlot chart, string title, string[] labels, List<(string legend, double[] ys)> values) { chart.Plot.Clear(); chart.Plot.Title(title); double[,] plots = new double[values.Count,values[0].ys.Length]; Enumerable.Range(0, plots.GetLength(0)).Select(i => Enumerable.Range(0, plots.GetLength(1)).Select(j => plots[i, j] = values[i].ys[j]).ToArray()).ToArray(); var radar = chart.Plot.AddRadar(plots); radar.CategoryLabels = labels; radar.OutlineWidth = 3; radar.GroupLabels = values.Select(i => i.legend).ToArray(); chart.Plot.Legend(location: Alignment.UpperRight); chart.Plot.Grid(); chart.Render(); } /// <summary> /// ヒストグラム /// </summary> /// <param name="chart"></param> /// <param name="title"></param> /// <param name="ys"></param> /// <param name="backet"></param> private void DrawHistgram(WpfPlot chart, string title, double[] ys,int backet = 10) { double max = ys.Max(); double min = ys.Min(); var bin = Math.Abs(max - min) / backet; (double[] counts, double[] binEdges) = ScottPlot.Statistics.Common.Histogram(ys,min: min, max:max, binSize: bin); double[] leftEdges = binEdges.Take(binEdges.Length - 1).ToArray(); chart.Plot.Clear(); chart.Plot.Title(title); var bar = chart.Plot.AddBar(values: counts,positions: leftEdges); bar.BarWidth = bin; chart.Render(); } // https://scottplot.net/cookbook/4.1/ } } |
デモプログラムに記載されているグラフ描画関数の一覧
今回のデモプログラムは再利用しやすいように関数化しています。
チャート(グラフ)名 | 関数(メソッド)名 | 内容 |
---|---|---|
折れ線グラフ | DrawLine | 単一の折れ線グラフを描画 |
折れ線グラフ(複数) | DrawLine | 複数の折れ線グラフを描画 |
散布図 | DrawScatt | 散布図を描画 |
円グラフ | DrawPie | 円グラフを描画 |
縦棒グラフ | DrawColumn | 縦棒グラフを描画 |
横棒グラフ | DrawBar | 横棒グラフを描画 |
棒グラフ(グルーピング) | DrawGroupColumn | 複数の棒グラフをグルーピングして描画 |
積み上げグラフ | DrawStack | 積み上げグラフを描画 |
レーダーチャート | DrawRadar | レーダーチャートを描画 |
箱ひげ図 | DrawPopulations | 箱ひげ図とベルカーブを同時描画 |
散布図と回帰直線 | DrawRegression | 散布図と回帰直線を同時描画 |
ヒストグラム | DrawHistgram | ヒストグラムを描画 |
第一引数には画面に張り付けたScottPlotコントロールを、第二引数にはグラフのタイトルを、第三引数以降に描画データ(プロットデータ)を渡すとグラフが描画されます。
例えば、コントロールに "uxChart1" という名前を付けて、xs にX方向のデータ、ysにY方向のデータが格納されていると仮定すると
1 2 |
//グラフの描画 DrawLine(uxChart1,"折れ線グラフ",xs, ys); |
という具合です。
第三引数のプロットデータについては、大きく分けて2つの形式があります。
折れ線や棒グラフ、円グラフ、散布図は引数にプロットデータの配列を渡す仕様ですが、複数の折れ線グラフ、レーダーチャート、グルーピングした棒グラフ、積み上げグラフは複数の項目をグルーピングする形になるため、タプルをリスト形式で渡すようにしました。
詳しくはソースコードを見て頂くとして、ここでは簡単にポイントだけ説明しておきます。
単独の折れ線グラフ、散布図、散布図と回帰直線、箱ひげ図、ヒストグラムの描画関数
これらはプロットデータを配列データとして、1つまたは2つ引数に渡します。
例えば、折れ線グラフの場合は次の様になります。
1 |
DrawLine(uxChart1,"折れ線グラフ",xs, ys); |
複数の折れ線グラフの描画関数
タプルのリスト形式で描画データを指定します。
タプルで、凡例タイトル(legend)、X座標の配列、y座標の配列を1まとまりにして、リストに追加していき、そのリストを引数に渡します。
1 2 3 4 5 6 |
List<(string legend, double[] xs, double[] ys)> linedata = new List<(string legend, double[] xs, double[] ys)>(); linedata.Add(("legend1", xs, ys1)); linedata.Add(("legend2", xs, ys2)); linedata.Add(("legend3", xs, ys3)); DrawLine(uxChart2, "折れ線グラフ(複数)", linedata); |
縦棒グラフ、横棒グラフの描画関数
縦棒グラフ、横棒グラフともプロットデータとして2つ渡すのは折れ線や散布図と同じですが、横軸がdouble型配列ではなく、文字列配列になっているところが異なる点です。
1 2 |
//棒グラフ DrawBar(uxChart6, "横棒グラフ", labels, values); |
円グラフの描画関数
円グラフは、ラベルと対応する値の配列を描画データとして渡します。
1 2 3 4 5 6 |
//円グラフのデータ double[] values = { 778, 43, 283, 76, 184 }; string[] labels = { "C#", "JAVA", "Python", "F#", "PHP" }; //円グラフの描画 DrawPie(uxChart4, "円グラフ", labels, values); |
縦棒グラフ(グルーピング)、積み上げグラフ、レーダーチャートの描画関数
これらは複数の値をグループ化して、まとめて表示するグラフであるため、タプルのリスト形式でプロットデータを設定します。
グループ化が少し分かりづらいかもしれませんが、項目名と内訳と考えてもらえれば分かりやすいかと思います。
ScottPlot をそのまま使う場合、少し面倒な値の渡し方をする必要があるので、項目名と内訳という考え方でプロットデータをセットすれば良いようにしています。
1 2 3 4 5 6 7 8 9 10 11 |
//グルーピングのデータ作成 string[] group = { "コア数", "クロック数", "スレッド数", "キャッシュ", "価格" }; List<(string, double[])> datas = new List<(string, double[])>(); datas.Add(("Core-i7", new double[] { 8, 3.6, 16, 64, 70 })); datas.Add(("Core-i5", new double[] { 6, 2.8, 12, 32, 50 })); datas.Add(("Core-i3", new double[] { 4, 2.0, 8, 16, 30 })); datas.Add(("Pentium", new double[] { 2, 1.8, 4, 8, 10 })); datas.Add(("Celeron", new double[] { 2, 1.5, 4, 8, 5 })); //棒グラフ(グルーピング) DrawGroupColumn(uxChart1, "グループ", group, datas); |
このサンプルソース上では group という変数名を使っていますが、明細(detail) とか、内訳(breakdown) という変数名の方が良かったかもしれません。
4.0→4.1の変更点
既に旧バージョンのScottPlotを使っており、最新バージョンに置き換えようと考えている方のために、修正点を簡単に解説しておきます。
WpfPlotの plt プロパティが Plot に変わった
ScottPlot は、WpfPlot の plt プロパティからオブジェクトを取得し、このオブジェクトに備わっている各グラフ描画メソッドを呼び出すことでグラフ描画します。
今回は、このプロパティの名前が Plot に変更されています。
1 2 3 4 |
//従来 var plt = uxChart.plt; //Ver 4.1 var plt = uxChart.Plot; |
グラフ描画メソッドの名前が変わった
従来のグラフ描画メソッドは、PlotBar、PlotScatter、PlotLineなど、先頭にPlotが付いていました。
Ver 4.1 からは AddBar、AddScatter、AddLine の様に先頭がAddに代わっています。
1 2 3 4 |
//従来 chart.plt.PlotSignalXY(data.xs, data.ys, label: data.legend); //Ver 4.1 chart.Plot.AddSignalXY(data.xs, data.ys, label: data.legend); |
グラフ描画メソッドの引数が変わった
冒頭にも説明しましたが、今までは幅や色などグラフのデザインを指定する場合は、各グラフ描画メソッドの引数を使っていました。
Ver 4.1 からは、引数で指定するのではなく、グラフ描画メソッドが返すオブジェクトに対してデザインを指定します。
この仕様変更により引数が見直されており、全てではありませんが多くのメソッドにおいて、引数の名前や引数の並び変わったり、廃止されています。
1 2 3 4 |
//従来(第1引数にX軸データを指定) chart.plt.PlotBar(xs,ys); //Ver 4.1(第2引数にX軸データを指定) chart.Plot.AddBar(ys,xs); |
Legendのロケーション指定が変わった
凡例の表示を行うLegendメソッドには、凡例をグラフのどこに表示するかを指定する location 引数があります。
Ver 4.1 では、この location 引数の指定が enum Location から enum Alignment に変更されています。
1 2 3 4 |
//従来 chart.plt.Legend(location: Location.upperRight); //Ver 4.1 chart.Plot.Legend(location: Alignment.UpperRight); |
これは Legend に限ったものではなく、その他のメソッドにおいても同様です。
Y第2軸が指定できるようになった
これは大変うれしい拡張機能です。
指定の方法は簡単で、グラフ描画メソッドの戻り値にあるYAxis2に、表示したい軸を設定し、最後に 2軸表示用のメソッドを呼ぶだけです。
1 2 3 4 5 6 7 8 |
//折線グラフ描画メソッドを呼び出し、返されるオブジェクトのYAxisIndexに軸の番号=0を指定 var sig1 = chart.Plot.AddSignalXY(~); sig1.YAxisIndex =0; //折線グラフ描画メソッドを呼び出し、返されるオブジェクトのYAxisIndexに軸の番号=1を指定 var sig2 = chart.Plot.AddSignalXY(~); sig2.YAxisIndex =1; //Y2軸を表示 chart.Plot.YAxis2.Ticks(true); |
実は、X軸、Y軸とも3軸まで指定できるようになっています。
ただ、今までにX軸を3軸を使うグラフはあまり見たことが無いので、今回は取り扱いませんでしたが、XAxisIndexに使いたいX軸を指定し、XAxis3.Tick(true) とするだけです。
HistGram用のデータ集計を行うメソッドが変わった
まず名前空間の階層が次の様に変わっています。
ScottPlot.Statictics.Histogram ⇒ ScottPlot.Statistics.Common.Histogram
また、データの最大、最小、ビンサイズを指定するようになっていて、バケット数(階級をいくつに分割するか)やバーの太さなどの引数が無くなりました。
1 2 3 4 5 6 7 8 |
//従来 var hist = new ScottPlot.Statistics.Histogram(ys,binCount:backet); chart.plt.PlotBar(hist.bins, hist.counts, barWidth: hist.binSize, outlineWidth: 0); //Ver 4.1 (double[] counts, double[] binEdges) = ScottPlot.Statistics.Common.Histogram(ys,min: min, max:max, binSize: bin); double[] leftEdges = binEdges.Take(binEdges.Length - 1).ToArray(); var bar = chart.Plot.AddBar(values: counts,positions: leftEdges); bar.BarWidth = bin; |
まとめ
今回は ScottPlot 4.1 をWPFで使う方法について、デモプログラムを交えて解説しました。
こまごまとした仕様変更が行われているため、旧バージョンから乗り換える場合はそれなりの修正が必要となります。
しかし、この記事を読んでいただければ、大枠で変更のポイントが分かるので、そんなに時間は掛からないのではないかと思います。
新しいグラフも追加されているので、それらを使いたい場合、もしくは2軸が使いたい場合は、是非ScottPlot 4.1 をご活用下さい。
コメント