Project Icon

chart-fx

高性能科学图表库 实现25Hz实时数据可视化

ChartFx是一款高性能科学图表库,专注于实时数据可视化。基于JavaFX开发,支持25Hz更新率,可处理大规模数据集。提供多种科学信号处理绘图类型、插件系统和参数测量功能,兼具功能丰富性和性能优化。适用于需要高速数据处理和展示的科研应用场景。

在 https://gitter.im/fair-acc/chart 加入聊天 许可证 Maven 中央仓库

代码行数 可维护性评级 Coverity 构建状态

ChartFx 横幅

ChartFx 是一个由 GSI 为 FAIR 开发的科学绘图库,专注于性能优化的实时数据可视化,可以处理每秒 25 次更新率的数据集,数据点数量从几万到 500 万不等,常用于数字信号处理应用。 基于早期在 GSI 和 CERN 使用的基于 Swing 的设计,它是对 JavaFX 默认 Chart 实现的重写,旨在保留早期和其他类似基于 Swing 库的丰富功能和可扩展性,同时解决性能瓶颈和 API 问题。 重新设计的动机已在 IPAC'19 上展示(论文海报)。您可以在 JFX Days 上观看最近的演示 这里

ChartFx 示例
示例展示了误差条和误差面表示、模拟元数据显示、`ChartPlugin` 交互器和数据参数测量指示器(此处:'Marker#0' 和 'Marker#1' 之间的 '20%-80% 上升时间')。

功能和特性

该库提供了科学信号处理领域常见的各种绘图类型、灵活的插件系统以及实验室仪器中常见的在线参数测量。其一些特性包括(详情请参见演示):

  • DataSet:基本的 XY 类型数据集,可通过 DataSetError 扩展以考虑测量不确定性,DataSetMetaDataEditableDataSetHistogramDataSet3D 接口;
  • 数学子库:FFT、小波和其他谱分析和线性代数例程,数值稳健的积分和微分,IIR 和 FIR 类型滤波,线性回归和非线性 chi-square 类型函数拟合;
  • Chart:提供欧几里得、极坐标或 3D 数据集的 2D 投影,以及可配置的图例;
  • Axis:一个或多个线性、对数、时间序列、反转、动态自动(增长)范围、基于范围的自动 SI 和时间单位转换的轴;
  • Renderer:散点图、折线图、面积图、误差条和误差面、垂直条形图、贝塞尔曲线、阶梯图、1D/2D 直方图、山脉图显示、真实等高线图、热图、淡出数据集历史、标记图表范围和指示标记、六边形图、元数据(例如用于指示常见测量错误、警告或信息,如超出或低于范围、设备或配置错误等);
  • ChartPlugin:带历史记录的数据缩放器、缩放至原点、并可选择限制为 X 和/或 Y 坐标、平移器、数据值和范围指示器、十字光标指示器、数据点工具提示、DataSet 编辑、表格视图、导出为 CSV 和系统剪贴板、在线轴编辑、数据集参数测量(如上升时间、最小值、最大值、均方根等)。

为了在使用 Canvas 作为图形后端的同时提供一些场景图级别的功能,每个模块的功能都经过扩展,可以通过直接的 API 方法以及外部 CSS 类型样式表轻松自定义。

使用示例

将库添加到您的项目中

所有 chart-fx 版本都部署到 Maven 中央仓库,对于 Maven,您可以将其添加到 pom.xml 中,如下所示:

<dependencies>
  <dependency>
    <groupId>io.fair-acc</groupId>
    <artifactId>chartfx</artifactId>
    <version>11.3.1</version>
  </dependency>
</dependencies>

或者在 build.gradle 中这样添加:

implementation 'io.fair-acc:chartfx:11.3.1'

要使用不同的构建系统或库版本,请查看 maven central 上的代码片段。

虽然大多数用户需要 io.fair-acc:chartfx 构件,但也可以独立使用来自 io.fair-acc:dataset 的数据容器和来自 io.fair-acc:math 的算法,而无需依赖较重的 UI 组件。

使用快照仓库

如果您想尝试主分支或某个特性分支中未发布的功能,无需下载源代码并自行构建 chart-fx。您可以直接使用 sonatype 快照仓库中的 <分支名>-SNAPSHOT 版本,例如通过在 pom.xml 中添加以下内容来使用当前的主分支。 所有可用的快照版本都可以在 sonatype 快照仓库 中找到。

当前主分支的 pom.xml 示例(点击展开)
<dependencies>
    <dependency>
        <groupId>io.fair-acc.chartfx</groupId>
        <artifactId>chartfx</artifactId>
        <version>main-SNAPSHOT</version>
        <!-- <version>main-20200320.180638-78</version> 固定到特定的快照构建-->
    </dependency>
</dependencies>
<repositories>
    <repository>
        <id>oss.sonatype.org-snapshot</id>
        <url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
        <releases>
            <enabled>false</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>

代码示例

以下最小工作示例可用作入门 chart-fx 的样板项目。

简单的 ChartFx 示例
相应的源代码 `ChartFxSample.java`(展开)
package com.example.chartfx;

import io.fair_acc.chartfx.XYChart;
import io.fair_acc.chartfx.axes.spi.DefaultNumericAxis;
import io.fair_acc.dataset.spi.DoubleDataSet;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class SimpleChartSample extends Application {
    private static final int N_SAMPLES = 100;

    @Override
    public void start(final Stage primaryStage) {
        final StackPane root = new StackPane();

        final XYChart chart = new XYChart(new DefaultNumericAxis(), new DefaultNumericAxis());
        root.getChildren().add(chart);

        final DoubleDataSet dataSet1 = new DoubleDataSet("数据集 #1");
        final DoubleDataSet dataSet2 = new DoubleDataSet("数据集 #2");
        // lineChartPlot.getDatasets().add(dataSet1); // 用于单个数据集
        chart.getDatasets().addAll(dataSet1, dataSet2); // 两个数据集

        final double[] xValues = new double[N_SAMPLES];
        final double[] yValues1 = new double[N_SAMPLES];
        final double[] yValues2 = new double[N_SAMPLES];
        for (int n = 0; n < N_SAMPLES; n++) {
            xValues[n] = n;
            yValues1[n] = Math.cos(Math.toRadians(10.0 * n));
            yValues2[n] = Math.sin(Math.toRadians(10.0 * n));
        }
        dataSet1.set(xValues, yValues1);
        dataSet2.set(xValues, yValues2);
final Scene scene = new Scene(root, 800, 600);
    }
    public static void main(final String[] args) {
        Application.launch(args);
    }
}
对应的构建规范(展开) pom.xml:
<project>
<groupId>com.example.chartfx</groupId>
<artifactId>chartfx-sample</artifactId>
<name>chart-fx 示例</name>
<dependencies>
  <dependency>
    <groupId>io.fair-acc</groupId>
    <artifactId>chartfx</artifactId>
    <version>11.3.0</version>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>2.0.9</version>
  </dependency>
</dependencies>
</project>
运行方式(展开)
mvn compile install
mvn exec:java

示例

chart-fx 示例子模块包含大量示例,展示了该库的功能和用法。 如果你想自己尝试,请运行:

mvn compile install
mvn exec:java

金融相关示例

金融图表是一种可视化追踪各种业务和金融指标(如流动性、价格变动、支出、现金流等)随时间变化的图表类型。金融图表是表达业务或金融市场(金融工具、金融资产)故事的绝佳方式。

chart-fx samples子模块包含金融图表和工具箱示例。

如果你想自己尝试,请运行:

mvn compile install
mvn exec:java

金融足迹图

FinancialAdvancedCandlestickSample
FinancialRealtimeFootprintSample.java(足迹实时处理)

数学和信号处理相关示例

数学示例可以通过以下命令启动:

mvn compile install
mvn exec:java@math

其他示例

还有dataset和accelerator UI子模块的示例,随着新功能的添加,这些示例将随时间扩展。

mvn compile install
mvn exec:java@dataset
mvn exec:java@acc-ui

性能比较

除了上述扩展功能外,ChartFx的优化目标还包括实现数据集从几万到500万个数据点的25 Hz实时更新率。为了优化性能并与其他图表库(尤其是功能较少的库)进行比较,我们选择了一个简化的示波器风格测试用例(参见演示中的RollingBufferSample),该用例显示两条具有独立自动调整y轴、共同滑动时间序列轴的曲线,且不使用其他ChartPlugin。下面展示了ChartFx和JavaFX图表库在25 Hz和2 Hz更新率下的测试用例和直接性能比较。

ChartFx性能对比测试用例
性能测试场景:两个独立图表,独立自动调整的y轴,以及共用的滚动时间序列轴。测试系统:Linux 4.12.14,Intel(R) Core(TM) i7 CPU 860 @2.80GHz和GeForce GTX 670 GPU(NVIDIA驱动)。
JavaFX-ChartFx 25 Hz更新率性能对比
25 Hz更新率性能对比。
JavaFX-ChartFx 2 Hz更新率性能对比
2 Hz更新率性能对比。

虽然ChartFx实现已经在功能上有所改进,并且在处理超大数据集时性能提升了两个数量级,但基本测试场景也与流行的现有Java-Swing和非Java基础UI图表框架进行了对比。下图总结了在25 Hz更新率和1k样本条件下评估的图表库。

ChartFx性能对比
流行的JavaFX、Java-Swing、C++/Qt和WebAssembly基础实现的图表性能对比:ExtJFXChartFxHanSolo ChartsJFreeChartJDataViewerQCustomPlotQt-ChartsWebAssembly。最后的`Qt Charts`条目显示了10万个数据点以25 Hz更新率的结果。

一些思考

从最初通过扩展来改进JDK的JavaFX图表功能和性能开始,然后逐步替换瓶颈,最终重新设计并替换原始实现,由此产生的ChartFx库提供了实质性的更大功能,并实现了约两个数量级的性能提升。 然而,撇开功能改进不谈,即使是JavaFX最佳场景(静态轴)与其他非JavaFX库的直接性能对比也表明,尽管经过重新设计,JavaFX原始图形性能仍落后于现有的基于Java Swing的JDataViewer,尤其是Qt Charts实现。该库将继续在GitHub上维护,并用于GSI现有和未来基于JavaFX的控制室UI。 获得的经验和接口将为计划中的基于C++的对应实现提供起点,该实现将使用Qt或其他合适的低级图表库。

处理源代码

如果你想处理chart-fx源代码,无论是想尝试样例还是为chartFX贡献一些改进,这里有一些说明,介绍如何获取源代码并使用命令行maven或eclipse进行编译。

命令行Maven

只需克隆仓库并从顶级目录运行maven。exec:java目标可用于执行样例。 Maven使用相应的选项调用java,以使JavaFX正常工作。由于项目的设置方式,只有chartfx-samples项目中的类可以通过这种方式启动。

git clone
cd chart-fx
mvn compile install
mvn exec:java

Eclipse

以下内容已在eclipse-2019-03上测试,并使用m2e maven插件。其他版本或IDE可能类似工作。 使用Import -> Existing Maven Project导入仓库。 这应该会导入父项目和四个子项目。 不幸的是,由于chartfx不使用jigsaw模块系统,而javafx使用,使用"run as Java Application"运行样例将导致错误,抱怨缺少JavaFX运行时。 作为解决方法,我们包含了一个小型辅助类LaunchJFX,可以用"run as Java Application"调用,它会启动样例应用。 它接受类名作为参数,所以如果你编辑运行配置并将${java_type_name}作为参数,它将尝试启动在项目资源管理器中选择的类作为JavaFX应用。

JavaFX jvm命令行选项

如果你无法使用前两种方法,也可以手动指定模块系统的访问规则作为jvm标志。将以下内容添加到java命令行调用或IDE的运行配置中,使所需模块可用并可被chartfx访问:

--add-modules=javafx.graphics,javafx.fxml,javafx.media
--add-reads javafx.graphics=ALL-UNNAMED
--add-opens javafx.controls/com.sun.javafx.charts=ALL-UNNAMED
--add-opens javafx.controls/com.sun.javafx.scene.control.inputmap=ALL-UNNAMED
--add-opens javafx.graphics/com.sun.javafx.iio=ALL-UNNAMED
--add-opens javafx.graphics/com.sun.javafx.iio.common=ALL-UNNAMED
--add-opens javafx.graphics/com.sun.javafx.css=ALL-UNNAMED
--add-opens javafx.base/com.sun.javafx.runtime=ALL-UNNAMED
--add-exports javafx.controls/com.sun.javafx.scene.control.behavior=ALL-UNNAMED

由于这些参数可能会随依赖项更新而改变,并根据项目设置方式的不同,如果遇到模块可访问性问题,请查看以下资源:

扩展chartfx

如果你发现缺少某些功能或无法访问特定的图表内部,通常的做法是实现自定义插件或渲染器。

插件是向chart-fx添加新可视化和交互功能的简单方法。实际上,chart-fx的许多功能(如缩放、数据编辑、测量)都是作为插件实现的,正如你在样例应用中看到的那样。 你的插件可以直接扩展ChartPlugin或扩展任何内置插件。 Plugin Base类通过getChart()提供对图表对象的访问。 你的插件应始终向chartProperty添加监听器,因为创建时不会有关联的图表,所以在创建时调用例如getChart()将返回null。 使用自定义插件归结为通过chart.getPlugins().add(new MyPlugin())将其添加到图表中。 如果你编写的插件可能对chart-fx的其他用户有用,请考虑对chart-fx进行pull请求。

渲染器是实际执行将图表组件绘制到画布上的重要组件。 可以使用chart.getRenderers().add(...)向图表添加多个渲染器 有些渲染器可视化实际数据,如ErrorDataSetRenderer,它也是默认添加到新图表的渲染器。 这些渲染器对添加到图表的所有DatasSets(chart.getDatasets.add(...))以及添加到渲染器本身的数据集进行操作。 根据经验,如果你需要可视化大量数据点或想在图表本身后面绘制内容,就需要实现自定义渲染器。

致谢

我们向JavaFX社区表示感谢,特别是CERN的@GregKrug和Vito Baggiolini,感谢他们在这个主题上提供的宝贵见解、讨论和反馈。

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

稿定AI

稿定设计 是一个多功能的在线设计和创意平台,提供广泛的设计工具和资源,以满足不同用户的需求。从专业的图形设计师到普通用户,无论是进行图片处理、智能抠图、H5页面制作还是视频剪辑,稿定设计都能提供简单、高效的解决方案。该平台以其用户友好的界面和强大的功能集合,帮助用户轻松实现创意设计。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号