C# PR

【C#】ScottPlot 新バージョンがリリース 【4.1】

【C#】ScottPlot新バージョンがリリースのアイキャッチ
記事内に商品プロモーションを含む場合があります

はじめに

無料で使える高速なグラフライブラリ「ScottPlot」のメジャーアップデートがありました。
しばらくβ版として開発が続いていましたが、ようやく正式版となったようです。

4.0 から 4.1 と2桁目のバージョンアップですが、機能が大幅に追加されたのでご紹介したいと思います。

この記事の内容
  • バージョンアップ内容
  • 個人的に注目の3つの新機能
  • ① 高速描画可能な「SignalPlot」の追加
  • ② X・Y軸に第2軸 (複合グラフ)を追加する機能
  • ③ 直角で表示される「StepPlot」の追加

バージョンアップ内容

主な新機能は以下の通りです。(機械翻訳+意訳)
リリース直後だからなのか、本家サイトにリンクエラーなどがあり全ては調べられていません。
⑤⑥のレンダリングやイベント処理などは、前バージョンにはない機能なので今後調べていきたいと思います。

主な新機能
  1. 複数のX軸とY軸のサポート
  2. 軸・目盛り・グリッドの豊富で新しいカスタマイズオプション
  3. パフォーマンスとスレッドセーフを向上させるステートレスレンダリング
  4. ユーザー制御用の簡略化された共通構成モジュール
  5. UIスレッドをブロックしないレンダリングリクエストのサポート
  6. ユーザーコントロールのカスタマイズを可能にするための改善されたイベント処理

本家サイトからの引用です。

新バージョンの詳細は以下の本家サイトをご覧ください。

https://swharden.com/scottplot/cookbook/

個人的に注目の新機能

個人的にいいなと思う機能は以下の3つです。

  1. 高速描画可能な「SignalPlot」の新規追加
  2. X・Y軸に第2軸 (複合グラフ)を追加する機能
  3. 直角で表示される「StepPlot」の新規追加

① 高速描画可能な「SignalPlot」

4.0までの散布図でも十分に高速でしたが、さらに何百万点ものデータポイントをインタラクティブに表示可能「SignalPlot」が新たに追加されました。等間隔でのデータを想定しているため、Y軸は固定になっています。

以前記事を書いたリアルタイムでのグラフ描画も、さらに高速に動かせるかもしれません。
深堀して記事かしていきたいと思います。

本家CockBookから引用しています。

旧Ver.のリアルタイム記事は以下を参照ください。

② X・Y軸の第2軸 (複合グラフ)を追加する機能

以前β版の機能として紹介していた、X・Y軸に第2軸を追加する機能が正式リリースされました。

一見地味ですが、「エクセルでいつも見ている、複数データのグラフが作りたい」という時に活躍してくれる機能なので、個人的に非常にありがたいです。

β版の時に紹介した、第2軸を表示する機能の記事は以下をご覧ください。

③ 直角で表示される「StepPlot」の新規追加

個人的に、複数のI/O信号をタイミングチャートのように表示できないか?と思っていたところの新機能でした。うまく使えた場合は記事かしてご紹介したいと思います。

本家CockBookから引用しています

まとめ

無料で使える高速なグラフライブラリ「ScottPlot」のメジャーアップデートについてご紹介しました。
調べきれていない機能・コードの書き方などは、今後掘り下げて別途記事にしていきます。

お知らせ

今月号の『Software Design』はドメイン駆動設計(DDD)。実例を交えたDDDの手法の解説が特集されています。

編集:Software Design 編集部
¥1,562 (2024/03/13 12:59時点 | Amazon調べ)

質問・要望 大歓迎です

「こんな解説記事作って」「こんなことがしたいけど、〇〇で困ってる」など、コメント欄で教えてください。 質問・要望に、中の人ができる限り対応します。

使えたよ・設定できたよの一言コメントも大歓迎。気軽に足跡を残してみてください。記事を紹介したい方はブログ、SNSにバシバシ貼ってもらってOKです。

ABOUT ME
えす
現役のソフトウェアエンジニアです。 C++ C# Python を使ってます。10年ちょい設計/開発部門にいましたが、今はQAエンジニアっぽいことをしています。

POSTED COMMENT

  1. yana より:

    [ScottPlot]を使ってテキストファイルデータからDataSetにセットしグラフ表示しようとしていますが
    y軸は数値なのでList lst6 = dt0.AsEnumerable().Select(row => (double)row[6]).ToList();で変換出来ました。
    問題はX軸でDatasetにはds0.Tables[0].Rows[i][0].ToString()←ここに年月日”2021/06/15”
    ds0.Tables[0].Rows[i][1].ToString()←ここに時間(時分)”15:47”
    double指定出来ず
    List lst0 = dt0.AsEnumerable().Select(row => row[0].ToString()).ToList();
    List lst1 = dt0.AsEnumerable().Select(row => row[1].ToString()).ToList();
    で、しかも年月日と時間を連結してX軸に表示させたいです。
    また、対数スケールでしかも複数値(グラフ1、グラフ2、
    フラフ3、…)

    • えす より:

      yanaさん
      質問ありがとうございます。記事化を進めていますが、さっと調べてみましたのでお答えします。
       ・CSVから読み取った文字列型の年月日と時間を結合(「日時の文字列」とします)
       ・「日時の文字列」を、C#のDateTime型に変換
       ・DateTimeのToOADate()でDateTime型 -> Double型に変換
       ・変換したDouble型をScottPlotのX軸のデータ配列にセット。
       ・ScottPlot.Plot.XAxis.DateTimeFormat(true); でX軸を日付として設定

      とすることで、X軸に日時の文字列が表示できるようです(Ver.4.1.16で確認)
      ※ デフォルトだと、X軸の日付の期間が広いと時間が省略されてしまうようです。
      ※ 本家サイトCookBook 「Plotting DateTime Data」も参考にしてみてください。

      • えす より:

        yanaさんへの続き
        また、対数スケールで・・(グラフ1、グラフ2、フラフ3、…)以降は文字数制限(?) で見えないようです。
        お手数ですが、再度投稿いただけると助かります。

  2. yana より:

    先のX軸「日時の型」変換の回答有難う御座いました。トライしてみます。対数スケール表示での後半の質問です。
    double[] dataYsLog = ScottPlot.Tools.Log10(dataYs);
    plt.AddScatter(dataXs, dataYsLog, lineWidth: 0);
    ここで複数グラフ線(グラフ1,グラフ2,グラフ3,…)と増えた場合のコード記述はどうなりますか?

  3. yana より:

    先程の複数グラフ表示質問は解決しました。
    formsPlot1.plt.PlotScatter(x, Y1);
    formsPlot1.plt.PlotScatter(x, Y2);と増やせば表示されました。有難うございました。
    ただ、以下のようにDouble変換過程でdoubel → double[]を1行でシンプルに記述出来ないかとも思いました。

    List lst0 = new List();
    for (int i = 0; i < ds0.Tables[0].Rows.Count; i++)//ToOADate → ToDouble
    {
    string strTime1 = ds0.Tables[0].Rows[i][0] + " " + ds0.Tables[0].Rows[i][1];
    DateTime dTime1 = DateTime.Parse(strTime1);
    var oadate1 = dTime1.ToOADate();
    lst0.Add(Convert.ToDouble(oadate1));
    }
    List lst6 = dt0.AsEnumerable().Select(row => (double)row[6]).ToList();
    List lst7 = dt0.AsEnumerable().Select(row => (double)row[7]).ToList();
    List lst8 = dt0.AsEnumerable().Select(row => (double)row[8]).ToList();
    List lst9 = dt0.AsEnumerable().Select(row => (double)row[9]).ToList();

    double[] myDataY0 = lst0.Select(x => (double)x).ToArray();
    double[] myDataY6 = lst6.Select(x => (double)x).ToArray();
    double[] myDataY7 = lst7.Select(x => (double)x).ToArray();
    double[] myDataY8 = lst8.Select(x => (double)x).ToArray();
    double[] myDataY9 = lst9.Select(x => (double)x).ToArray();

    formsPlot1.plt.PlotScatter(myDataY0, myDataY6);
    formsPlot1.plt.PlotScatter(myDataY0, myDataY7);
    formsPlot1.plt.PlotScatter(myDataY0, myDataY8);
    formsPlot1.plt.PlotScatter(myDataY0, myDataY9);
    formsPlot1.plt.XAxis.DateTimeFormat(true);

  4. yana より:

    logスケールでのy軸のスタート値を0からスタートではなく
    1 10 100 1000 10000
    と表示したいがスケール変更は可能でしょうか?

  5. yana より:

    1)Y軸のLogスケールはScottPlot.Tools.Log10()にて出来ましたがlog10yのY値目盛表示を0 10 100 1000と表現可能でしょうか?
    2)X軸をformsPlot1.plt.XAxis.DateTimeFormat(true);日付時間型とすると
    X軸値={①7月1日,②7月7日,③7月19日,④8月4日}でのX軸表示は7月1日、7月2日、7月3日 …8月4日と表示されるが
    目的のx軸は①、②、③,④と表示されるようにしたい
    3)Y軸データで0データをオミット(線形を途切れるようにしたい)は可能ですか?
    double[] originalYs = { 3, double.NaN, 5, double.PositiveInfinity, double.NegativeInfinity, 4, 6 };
    double[] originalXs = { 1, 2, 3, 4, 5, 6, 7 };
    ではうまく行きません。
    以下のように個別化すれば可能ですが1万件のデータとなった場合、分別化は難しいです

    // first segment
    double[] xs1 = { 1, 2, 3 };
    double[] ys1 = { 5, 4, 8 };
    plt.AddScatter(xs1, ys1, Color.Blue);

    // second segment
    double[] xs2 = { 5, 6, 7, 8 };
    double[] ys2 = { 6, 9, 4, 7 };
    plt.AddScatter(xs2, ys2, Color.Blue);

    // third segment
    double[] xs3 = { 10, 11, 12 };
    double[] ys3 = { 8, 3, 7 };
    plt.AddScatter(xs3, ys3, Color.Blue);

    • えす より:

      yanaさん

      コメントありがとうございます。

      1) 値目盛表示を0 10 100 1000と表現

      Logスケールではなく、そのまま 10 100 1000 “だけ” を表示して、中間の値は表示させたくないということかと思います。
      動作確認までは見れていないのですが、 2) の質問と同様に Y軸のTickのManual指定でどうでしょうか?

      https://swharden.com/scottplot/cookbooks/4.1.16/category/advanced-axis-features/#manual-tick-labels

      3)Y軸データで0データをオミット(線形を途切れるようにしたい)は可能ですか?

      ScatterPlotでは線を途切れるようにする機能はないようですね。透明化での回避なども試してみましたが、
      系列(線)全体での指定しかないため、特定の点のみを無効化する(途切れさせる)のは難しいようです。
      Githubで要望をあげてみるのも良いかもしれません。

  6. yana より:

    2)X軸 日付時間型は以下にうまく行きました。すみませんでした。
    formsPlot1.plt.XAxis.ManualTickPositions

  7. yana より:

    toolTipを表示する手法はありませんか?

    • えす より:

      yanaさん、こんにちは。

      ScottPlotでは、固定の座標にテキストなどを表示する方法はあるようですが、
      カーソルやクリックされた場所に応じて動的に情報を表示する機能はないようです。

  8. yana より:

    MS Chart.HitTestメソッドのようにクリックされたグラフ要素を特定する事が出来るならテキスト表示でもOKかなと思っていますが、ScottPlotでは座標のみしか取得出来ませんよね?
    こちらでもトライしてみます。

  9. yana より:

    GetPointNearest()でトライしてみます。
    また、コメント頂いたクリックではないポイント座標の取得方法は以前に実施してみましたが線形グラフでは、うまく機能しませんでした。

  10. yana より:

    ScottPlotでの凡例の項目名はWindows Formアプリだと漢字等は表示(英数のみだと表示される)されず、逆にWPFアプリでは凡例項目名は漢字等は表示されます。また、WPFアプリだと画面サイズがWindowsformサイズより小さくなって表示されます。これを同じサイズにする方法もありますか?

  11. yana より:

    すみません!凡例の事象はScottPlotではなくOxyPlotでの事象です。OxyPlotへコメントします。

  12. kazu より:

    MS ChartだとYデータの一部に無効値としてDouble.NaNをセットするとその間が飛んでプロットできるのですが
    ScottPlotでは、例外になってプロットできませんね。
    ScottPlotで欠損値を複数箇所含むようなデータをプロットする方法はサポートされていないのでしょうか?

    • えす より:

      kazuさん、こんにちは。
      コメントありがとうございます。

      残念ながら、ScottPlotでは間を空けてプロットする機能はサポートされていません。

      次期メジャーバージョンアップ(ScottPlot5?)で再検討とのコメントが開発者からありますが、
      大分先の話になりそうですね・・・

      https://github.com/ScottPlot/ScottPlot/issues/1161
      (最後のコメントの部分)

  13. kazu より:

    開発者のコメント読みました。NaNをチェツクしながらのプロットでは速度が落ちるからとの理由のようですね。
    ですが、他の人のコメントにもありましたが、長期計測データのプロット時に機器異常によって欠測している箇所が複数存在しているデータを扱うことが多いんですよね。
    パフォーマンスが落ちるなら、通常モードとは別にNaN有りデータのプロットモード、ただし速度遅くなる ていうのが追加実装されたら嬉しいんですけど。それまでは、異常値を最低値に入れ替えて連続プロットするか、おとなしくMS Chart使うしかないようですね。

    • えす より:

      kazuさん

      >> 通常モードとは別にNaN有りデータのプロットモード、ただし速度遅くなる ていうのが追加実装されたら嬉しいんですけど。

      いいですね。描画が遅くなってもビジュアル的に分かりやすいモードがあってもいい気がします。
      (それでもMSChartより十分早くなりそうですし)

      コメントを見る限り長期的なToDo(?) には入っていそうなので、GitHubでさらにプッシュしてみるのも良いのかもしれません。
      要望も多そうですし、実現するとうれしいですね。

yana へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です