{"id":13777072,"url":"https://github.com/fair-acc/chart-fx","last_synced_at":"2025-04-04T11:16:34.188Z","repository":{"id":40249044,"uuid":"185394887","full_name":"fair-acc/chart-fx","owner":"fair-acc","description":"A scientific charting library focused on performance optimised real-time data visualisation at 25 Hz update rates for data sets with a few 10 thousand up to 5 million data points.","archived":false,"fork":false,"pushed_at":"2024-03-08T08:01:50.000Z","size":24736,"stargazers_count":479,"open_issues_count":16,"forks_count":88,"subscribers_count":22,"default_branch":"main","last_synced_at":"2024-05-22T03:19:27.626Z","etag":null,"topics":["chart-fx","charting-libraries","data-visualisation","hacktoberfest","java","javafx","large-dataset","scientific-visualization"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fair-acc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"docs/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"docs/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-07T12:13:31.000Z","updated_at":"2024-05-20T06:05:14.000Z","dependencies_parsed_at":"2023-09-22T19:23:41.182Z","dependency_job_id":"8fa56a29-2b7c-4794-bbad-b71440f5c46d","html_url":"https://github.com/fair-acc/chart-fx","commit_stats":null,"previous_names":["gsi-cs-co/chart-fx"],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fair-acc%2Fchart-fx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fair-acc%2Fchart-fx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fair-acc%2Fchart-fx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fair-acc%2Fchart-fx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fair-acc","download_url":"https://codeload.github.com/fair-acc/chart-fx/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247166169,"owners_count":20894654,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chart-fx","charting-libraries","data-visualisation","hacktoberfest","java","javafx","large-dataset","scientific-visualization"],"created_at":"2024-08-03T18:00:37.248Z","updated_at":"2025-04-04T11:16:34.158Z","avatar_url":"https://github.com/fair-acc.png","language":"Java","funding_links":[],"categories":["Libraries, Tools and Projects"],"sub_categories":[],"readme":"[![Join the chat at https://gitter.im/fair-acc/chart](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/fair-acc/chart?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![License](https://img.shields.io/badge/License-LGPL%203.0-blue.svg)](https://opensource.org/licenses/LGPL-3.0)\n[![Maven Central](https://img.shields.io/maven-central/v/io.fair_acc/chartfx/11.svg)](https://search.maven.org/search?q=g:io.fair-acc+a:chartfx+v:11*)\n\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=fair-acc_chart-fx\u0026metric=ncloc)](https://sonarcloud.io/summary/new_code?id=fair-acc_chart-fx)\n[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=fair-acc_chart-fx\u0026metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=fair-acc_chart-fx)\n[![Coverity Build Status](https://scan.coverity.com/projects/chart-fx/badge.svg)](https://scan.coverity.com/projects/chart-fx)\n\n\u003cp align=\"center\" width=\"100%\"\u003e\n    \u003cimg t src=\"docs/banner/banner.svg\" alt=\"ChartFx banner\"\u003e\n\u003c/p\u003e\n\nChartFx is a scientific charting library developed at [GSI](https://www.gsi.de) for FAIR with focus on performance optimised real-time data visualisation at 25 Hz update rates for data sets with a few 10 thousand up to 5 million data points common in digital signal processing applications.\nBased on earlier Swing-based designs used at GSI and CERN, it is a re-write of JavaFX's default [Chart](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/chart/Chart.html) implementation and aims to preserve the feature-rich and extensible functionality of earlier and other similar Swing-based libraries while addressing the performance bottlenecks and API issues.\nThe motivation for the re-design has been presented at [IPAC'19](https://ipac19.org/) ([paper](docs/THPRB028.pdf), [poster](docs/THPRB028_poster.pdf)). You can see a recent presentation at [JFX Days](https://www.jfx-days.com/) [here](https://youtu.be/NK4pgRF9XWk).\n\n\u003cfigure\u003e\n  \u003cimg src=\"docs/pics/chartfx-example1.png\" alt=\"ChartFx example\" width=1200/\u003e\n  \u003cfigcaption\u003e\n  Example showing error-bar and error-surface representations, display of mock meta-data, `ChartPlugin` interactors and data parameter measurement indicators (here: '20%-80% rise-time' between 'Marker#0' and 'Marker#1').\n  \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n## Functionalities and Features\n\nThe library offers a wide variety of plot types common in the scientific signal processing field, a flexible plugin system as well as online parameter measurements commonly found in lab instrumentation. Some of its features include (see demos for more details):\n\n- `DataSet`: basic XY-type datasets, extendable by `DataSetError` to account for measurement uncertainties, `DataSetMetaData`, `EditableDataSet`, `Histogram`, or `DataSet3D` interfaces;\n- math sub-library: FFTs, Wavelet and other spectral and linear algebra routines, numerically robust integration and differentiation, IIR- \u0026 FIR-type filtering, linear regression and non-linear chi-square-type function fitting;\n- `Chart`: providing Euclidean, polar, or 2D projections of 3D data sets, and a configurable legend;\n- `Axis`: one or multiple axes that are linear, logarithmic, time-series, inverted, dynamic auto-(grow)-ranging, automatic range-based SI and time unit conversion;\n- `Renderer`: scatter-plot, poly-line, area-plot, error-bar and error-surfaces, vertical bar-plots, Bezier-curve, staircase, 1D/2D histograms, mountain-range display, true contour plots, heatmaps, fading DataSet history, labelled chart range and indicator marker, hexagon-map, meta data (i.e. for indicating common measurement errors, warnings or infos such as over- or under-ranging, device or configuration errors etc.);\n- `ChartPlugin`: data zoomer with history, zoom-to-origin, and option to limit this to X and/or Y coordinates, panner, data value and range indicators, cross-hair indicator, data point tool-tip, `DataSet` editing, table view, export to CSV and system clipboard, online axis editing, data set parameter measurement such as rise-time, min, max, rms, etc.\n\nIn order to provide some of the scenegraph-level functionality while using a `Canvas` as graphics backend, the functionality of each module was extended to be readily customized through direct API methods as well as through external CSS-type style sheets.\n\n## Example Usage\n\n### Add the library to your project\n\nAll chart-fx releases are deployed to maven central, for maven you can add it to your pom.xml like this:\n\n```Maven POM\n\u003cdependencies\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003eio.fair-acc\u003c/groupId\u003e\n    \u003cartifactId\u003echartfx\u003c/artifactId\u003e\n    \u003cversion\u003e11.3.1\u003c/version\u003e\n  \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\nor your build.gradle like this:\n\n```gradle\nimplementation 'io.fair-acc:chartfx:11.3.1'\n```\n\nTo use different build systems or library versions, have a look at the snippets on [maven central](https://search.maven.org/search?q=io.fair-acc%20a:chartfx\u0026core=gav).\n\nWhile most users will need the `io.fair-acc:chartfx` artifact it is also possible to use the data containers from `io.fair-acc:dataset`\nand the algorithms from `io.fair-acc:math` independently without the quite heavy UI dependencies.\n\n#### Using the snapshot repository\n\nIf you want to try out unreleased features from master or one of the feature branches, there is no need to download the source and build chart-fx yourself. You can just use the `\u003cbranchname\u003e-SNAPSHOT` releases from the sonatype snapshot repository for example by adding the following to your pom.xml if you want to use the current master.\nAll available snapshot releases can be found in the [sonatype snapshot repository](https://s01.oss.sonatype.org/content/repositories/snapshots/io/fair-acc/).\n\n\u003cdetails\u003e\u003csummary\u003e\nexample pom.xml for current master (click to expand)\n\u003c/summary\u003e\n\n```xml\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eio.fair-acc.chartfx\u003c/groupId\u003e\n        \u003cartifactId\u003echartfx\u003c/artifactId\u003e\n        \u003cversion\u003emain-SNAPSHOT\u003c/version\u003e\n        \u003c!-- \u003cversion\u003emain-20200320.180638-78\u003c/version\u003e pin to a specific snapshot build--\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n\u003crepositories\u003e\n    \u003crepository\u003e\n        \u003cid\u003eoss.sonatype.org-snapshot\u003c/id\u003e\n        \u003curl\u003ehttps://s01.oss.sonatype.org/content/repositories/snapshots\u003c/url\u003e\n        \u003creleases\u003e\n            \u003cenabled\u003efalse\u003c/enabled\u003e\n        \u003c/releases\u003e\n        \u003csnapshots\u003e\n            \u003cenabled\u003etrue\u003c/enabled\u003e\n        \u003c/snapshots\u003e\n    \u003c/repository\u003e\n\u003c/repositories\u003e\n```\n\n\u003c/details\u003e\n\n### Code Example\n\nThe following minimal working example can be used as a boilerplate project to get started with chart-fx.\n\n\u003cimg src=\"docs/pics/SimpleChartSample.png\" width=800 alt=\"simple ChartFx example\"/\u003e\n\n\u003cdetails\u003e\u003csummary\u003eThe corresponding source code `ChartFxSample.java` (expand)\u003c/summary\u003e\n\n```Java\npackage com.example.chartfx;\n\nimport io.fair_acc.chartfx.XYChart;\nimport io.fair_acc.chartfx.axes.spi.DefaultNumericAxis;\nimport io.fair_acc.dataset.spi.DoubleDataSet;\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.layout.StackPane;\nimport javafx.stage.Stage;\n\npublic class SimpleChartSample extends Application {\n    private static final int N_SAMPLES = 100;\n\n    @Override\n    public void start(final Stage primaryStage) {\n        final StackPane root = new StackPane();\n\n        final XYChart chart = new XYChart(new DefaultNumericAxis(), new DefaultNumericAxis());\n        root.getChildren().add(chart);\n\n        final DoubleDataSet dataSet1 = new DoubleDataSet(\"data set #1\");\n        final DoubleDataSet dataSet2 = new DoubleDataSet(\"data set #2\");\n        // lineChartPlot.getDatasets().add(dataSet1); // for single data set\n        chart.getDatasets().addAll(dataSet1, dataSet2); // two data sets\n\n        final double[] xValues = new double[N_SAMPLES];\n        final double[] yValues1 = new double[N_SAMPLES];\n        final double[] yValues2 = new double[N_SAMPLES];\n        for (int n = 0; n \u003c N_SAMPLES; n++) {\n            xValues[n] = n;\n            yValues1[n] = Math.cos(Math.toRadians(10.0 * n));\n            yValues2[n] = Math.sin(Math.toRadians(10.0 * n));\n        }\n        dataSet1.set(xValues, yValues1);\n        dataSet2.set(xValues, yValues2);\n\n        final Scene scene = new Scene(root, 800, 600);\n    }\n    public static void main(final String[] args) {\n        Application.launch(args);\n    }\n}\n```\n\n\u003c/details\u003e\u003cdetails\u003e\u003csummary\u003eAnd the corresponding build specification(expand)\u003c/summary\u003e\npom.xml:\n\n```Maven POM\n\u003cproject\u003e\n\u003cgroupId\u003ecom.example.chartfx\u003c/groupId\u003e\n\u003cartifactId\u003echartfx-sample\u003c/artifactId\u003e\n\u003cname\u003echart-fx Sample\u003c/name\u003e\n\u003cdependencies\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003eio.fair-acc\u003c/groupId\u003e\n    \u003cartifactId\u003echartfx\u003c/artifactId\u003e\n    \u003cversion\u003e11.3.0\u003c/version\u003e\n  \u003c/dependency\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003eorg.slf4j\u003c/groupId\u003e\n    \u003cartifactId\u003eslf4j-simple\u003c/artifactId\u003e\n    \u003cversion\u003e2.0.9\u003c/version\u003e\n  \u003c/dependency\u003e\n\u003c/dependencies\u003e\n\u003c/project\u003e\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003erun with (expand)\u003c/summary\u003e\n\n```bash\nmvn compile install\nmvn exec:java\n```\n\n\u003c/details\u003e\n\n## Examples\n\nThe chart-fx samples submodule contains a lot of samples which illustrate the capabilities and usage of the library.\nIf you want to try them yourself run:\n\n```bash\nmvn compile install\nmvn exec:java\n```\n\n\u003ctable\u003e\n\n\u003ctr\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/CategoryAxisSample.png\" alt=\"CategoryAxisSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/CategoryAxisSample.java\"\u003eCategoryAxisSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/MultipleAxesSample.png\" alt=\"MultipleAxesSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/MultipleAxesSample.java\"\u003eMultipleAxesSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/TimeAxisSample.png\" alt=\"TimeAxisSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/TimeAxisSample.java\"\u003eTimeAxisSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/LogAxisSample.png\" alt=\"LogAxisSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/LogAxisSample.java\"\u003eLogAxisSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/HistogramSample.png\" alt=\"HistogramSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/HistogramSample.java\"\u003eHistogramSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/Histogram2DimSample.png\" alt=\"Histogram2DimSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/Histogram2DimSample.java\"\u003eHistogram2DimSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/EditDataSample.png\" alt=\"EditDataSetSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/EditDataSetSample.java\"\u003eEditDataSetSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/PolarPlotSample.png\" alt=\"PolarPlotSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/PolarPlotSample.java\"\u003ePolarPlotSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/MetaDataRendererSample2.png\" alt=\"EditDataSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/MetaDataRendererSample.java\"\u003eMetaDataRendererSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/HistoryDataSetRendererSample.png\" alt=\"HistoryDataSetRendererSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/HistoryDataSetRendererSample.java\"\u003eHistoryDataSetRendererSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/MountainRangeRendererSample.png\" alt=\"MountainRangeRendererSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/MountainRangeRendererSample.java\"\u003eMountainRangeRendererSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/ChartAnatomySample.png\" alt=\"ChartAnatomySample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/ChartAnatomySample.java\"\u003eChartAnatomySample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/ErrorDataSetRendererStylingSample1.png\" alt=\"ErrorDataSetRendererStylingSample1\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/ErrorDataSetRendererStylingSample.java\"\u003eErrorDataSetRendererStylingSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/ErrorDataSetRendererStylingSample2.png\" alt=\"ErrorDataSetRendererStylingSample2\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/ErrorDataSetRendererStylingSample.java\"\u003eErrorDataSetRendererStylingSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/LabelledMarkerSample.png\" alt=\"LabelledMarkerSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/LabelledMarkerSample.java\"\u003eLabelledMarkerSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd colspan=2\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/ContourChartSample1.png\" alt=\"ContourChartSample1\" width=600/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/ContourChartSample.java\"\u003eContourChartSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/ScatterAndBubbleRendererSample1.png\" alt=\"ScatterAndBubbleRendererSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/ScatterAndBubbleRendererSample.java\"\u003eScatterAndBubbleRendererSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd colspan=2\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/ContourChartSample2.png\" alt=\"ContourChartSample\" width=600/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/ContourChartSample.java\"\u003eContourChartSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/ScatterAndBubbleRendererSample2.png\" alt=\"ScatterAndBubbleRendererSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/ScatterAndBubbleRendererSample.java\"\u003eScatterAndBubbleRendererSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd colspan=2\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/ChartIndicatorSample.png\" alt=\"ChartIndicatorSample\" width=600/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/chart/ChartIndicatorSample.java\"\u003eChartIndicatorSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd colspan=2\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/HistogramRendererTests.png\" alt=\"HistogramRendererTests\" width=600/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-chart/src/test/java/io/fair_acc/chartfx/renderer/spi/HistogramRendererTests.java\"\u003eHistogramRendererTests.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003c/table\u003e\n\n### Financial related examples\n\nFinancial charts are types of charts that visually track various business and financial metrics like liquidity, price movement, expenses, cash flow, and others over a given a period of the time. Financial charts are a great way to express a story about business or financial markets (instruments, financial assets).\n\nThe chart-fx samples submodule contains financial charts and toolbox samples.\n\nIf you want to try them yourself run:\n\n```bash\nmvn compile install\nmvn exec:java\n```\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/FinancialCandlestickSample.png\" alt=\"FinancialCandlestickSample\" width=600/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/financial/FinancialCandlestickSample.java\"\u003eFinancialCandlestickSample.java (Several Themes Supported)\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/FinancialHiLowSample.png\" alt=\"FinancialHiLowSample\" width=600/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/financial/FinancialHiLowSample.java\"\u003eFinancialHiLowSample.java (OHLC Renderer)\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/FinancialAdvancedCandlestickSample.png\" alt=\"FinancialAdvancedCandlestickSample\" width=600/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/financial/FinancialAdvancedCandlestickSample.java\"\u003eFinancialAdvancedCandlestickSample.java (Advanced PaintBars and Extension Points)\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/FinancialRealtimeCandlestickSample.png\" alt=\"FinancialAdvancedCandlestickSample\" width=600/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/financial/FinancialRealtimeCandlestickSample.java\"\u003eFinancialRealtimeCandlestickSample.java (OHLC Tick Replay Real-time processing)\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n#### Financial Footprint Chart\n\n\u003cfigure\u003e\u003cimg src=\"docs/pics/FinancialRealtimeFootprintSample.png\" alt=\"FinancialAdvancedCandlestickSample\" width=1600/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/financial/FinancialRealtimeFootprintSample.java\"\u003eFinancialRealtimeFootprintSample.java (FOOTPRINT Tick Replay Real-time processing)\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\n\n### Math- \u0026 Signal-Processing related examples\n\nThe math samples can be started by running:\n\n```bash\nmvn compile install\nmvn exec:java@math\n```\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/DataSetAverageSample.png\" alt=\"DataSetAverageSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/math/DataSetAverageSample.java\"\u003eDataSetAverageSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/DataSetFilterSample.png\" alt=\"DataSetFilterSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/math/DataSetFilterSample.java\"\u003eDataSetFilterSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/DataSetIntegrateDifferentiateSample.png\" alt=\"DataSetIntegrateDifferentiateSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/math/DataSetIntegrateDifferentiateSample.java\"\u003eDataSetIntegrateDifferentiateSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/DataSetSpectrumSample.png\" alt=\"DataSetSpectrumSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/math/DataSetSpectrumSample.java\"\u003eDataSetSpectrumSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/FourierSample.png\" alt=\"FourierSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/math/FourierSample.java\"\u003eFourierSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/FrequencyFilterSample.png\" alt=\"FrequencyFilterSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/math/FrequencyFilterSample.java\"\u003eFrequencyFilterSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/GaussianFitSample.png\" alt=\"GaussianFitSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/math/GaussianFitSample.java\"\u003eGaussianFitSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/IIRFilterSample.png\" alt=\"IIRFilterSample\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/math/IIRFilterSample.java\"\u003eIIRFilterSample.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\u003cimg src=\"docs/pics/WaveletScalogram.png\" alt=\"WaveletScalogram\" width=300/\u003e\u003cfigcaption\u003e\u003ca href=\"chartfx-samples/src/main/java/io/fair_acc/sample/math/WaveletScalogram.java\"\u003eWaveletScalogram.java\u003c/a\u003e\u003c/figcaption\u003e\u003c/figure\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Other samples\n\nThere are also samples for the dataset and the accelerator UI submodules which will be extended over time as new\nfunctionality is added.\n\n```bash\nmvn compile install\nmvn exec:java@dataset\nmvn exec:java@acc-ui\n```\n\n## Performance Comparison\n\nBesides the extended functionality outlined above, the ChartFx optimisation goal also included achieving real-time update rates of up to 25 Hz for data sets with a few 10k up to 5 million data points. In order to optimise and compare the performance with other charting libraries, especially those with only reduced functionality, a reduced simple oscilloscope-style test case has been chosen (see `RollingBufferSample` in demos) that displays two curves with independent auto-ranging y-axes, common sliding time-series axis, and without further `ChartPlugin`s. The test-case and direct performance comparison between the ChartFx and JavaFX charting library for update rates at 25 Hz and 2 Hz is shown below.\n\n\u003ctable style=\"width:100%\"\u003e\n\u003ctr\u003e\u003ctd colspan=2\u003e\u003cfigure\u003e\n\t\u003cimg src=\"docs/pics/chartfx-performance-test-case.png\" alt=\"ChartFx performance comparison test-case\" width=99%/\u003e\n  \t\u003cfigcaption\u003ePerformance test scenario with two independent graphs, independent auto-ranging y-axes, and common scrolling time-series axis. Test system: Linux, 4.12.14, Intel(R) Core(TM) i7 CPU 860 @2.80GHz and GeForce GTX 670 GPU (NVIDIA driver).\u003c/figcaption\u003e\n\u003c/figure\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cfigure\u003e\n\t\u003cimg src=\"docs/pics/chartfx-performance1a.png\" alt=\"JavaFX-ChartFx performance comparison for 25 Hz\" width=90%/\u003e\n  \t\u003cfigcaption\u003ePerformance comparison @ 25 Hz update rate.\u003c/figcaption\u003e\n\u003c/figure\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cfigure\u003e\n  \t\u003cimg src=\"docs/pics/chartfx-performance1b.png\" alt=\"JavaFX-ChartFx performance comparison for 2 Hz\" width=90%/\u003e\n  \t\u003cfigcaption\u003ePerformance comparison @ 2 Hz update rate.\u003c/figcaption\u003e\n\u003c/figure\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\nWhile the ChartFx implementation already achieved a better functionality and a by two orders of magnitude improved performance for very large datasets, the basic test scenario has also been checked against popular existing Java-Swing and non-Java based UI charting frameworks. The Figure below provides a summary of the evaluated chart libraries for update rates at 25 Hz and 1k samples.\n\n\u003cfigure\u003e\n  \u003cimg src=\"docs/pics/chartfx-performance1.png\" alt=\"ChartFx performance comparison\" width=800/\u003e\n  \u003cfigcaption\u003e\n  Chart performance comparison for popular JavaFX, Java-Swing, C++/Qt and WebAssembly-based implementations: \u003ca href=\"https://github.com/extjfx/extjfx\"\u003eExtJFX\u003c/a\u003e, \u003ca href=\"https://github.com/fair-acc/chart-fx\"\u003eChartFx\u003c/a\u003e, \u003ca href=\"https://github.com/HanSolo/charts\"\u003eHanSolo Charts\u003c/a\u003e, \u003ca href=\"http://www.jfree.org/jfreechart/\"\u003eJFreeChart\u003c/a\u003e, \u003ca href=\"https://cds.cern.ch/record/1215878\"\u003eJDataViewer\u003c/a\u003e, \u003ca href=\"https://www.qcustomplot.com/\"\u003eQCustomPlot\u003c/a\u003e, \u003ca href=\"https://doc.qt.io/qt-5/qtcharts-index.html\"\u003eQt-Charts\u003c/a\u003e, \u003ca href=\"https://doc.qt.io/qt-5/wasm.html\"\u003eWebAssembly\u003c/a\u003e. The last `Qt Charts` entries show results for 100k data points being updated at 25 Hz.\n  \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n## Some thoughts\n\nWhile starting out to improve the JDK's JavaFX Chart functionality and performance through initially extending, then gradually replacing bottle-necks, and eventually re-designing and replacing the original implementations, the resulting ChartFx library provides a substantially larger functionality and achieved an about two orders of magnitude performance improvement.\nNevertheless, improved functionality aside, a direct performance comparison even for the best-case JavaFX scenario (static axes) with other non-JavaFX libraries demonstrated the raw JavaFX graphics performance -- despite the redesign -- being still behind the existing Java Swing-based JDataViewer and most noticeable the Qt Charts implementations. The library will continued to be maintained here at GitHub and further used for existing and future JavaFX-based control room UIs at GSI.\nThe gained experience and interfaces will provide a starting point for a planned C++-based counter-part implementation using Qt or another suitable low-level charting library.\n\n## Working on the source\n\nIf you want to work on the chart-fx sourcecode, either to play with the samples or to contribute some improvements to chartFX here are some instructions how to obtain the source and compile it using maven on the command line or using eclipse.\n\n### Maven on the command line\n\nJust clone the repository and run maven from the top level directory. The `exec:java` target can be used to execute the samples.\nMaven calls java with the corresponding options so that JavaFX is working. Because of the way the project is set up, only classes in the chartfx-samples project can be started this way.\n\n```sh\ngit clone\ncd chart-fx\nmvn compile install\nmvn exec:java\n```\n\n### Eclipse\n\nThe following has been tested with eclipse-2019-03 and uses the m2e maven plugin. Other versions or IDEs might work similar.\nImport the repository using `Import -\u003e Existing Maven Project`.\nThis should import the parent project and the four sub-projects.\nUnfortunately, since chartfx does not use the jigsaw module system, but javafx does, running the samples using 'run as Java Application' will result in an error complaining about the missing JavaFX runtime.\nAs a workaround we include a small helper class `LaunchJFX`, which can be called with 'run as Java Application' and which launches the sample application.\nIt accepts a class name as an argument, so if you edit the run configuration and put `${java_type_name}` as the argument, it will try to start the class selected in the project explorer as a JavaFX application.\n\n### JavaFX jvm command line options\n\nIf you cannot use the 2 previous methods it is also possible to manually specify the access rules to the module system\nas jvm flags. Adding the following to the java command line call or your IDEs run configuration makes the required\nmodules available and accessible to chartfx:\n\n```\n--add-modules=javafx.graphics,javafx.fxml,javafx.media\n--add-reads javafx.graphics=ALL-UNNAMED\n--add-opens javafx.controls/com.sun.javafx.charts=ALL-UNNAMED\n--add-opens javafx.controls/com.sun.javafx.scene.control.inputmap=ALL-UNNAMED\n--add-opens javafx.graphics/com.sun.javafx.iio=ALL-UNNAMED\n--add-opens javafx.graphics/com.sun.javafx.iio.common=ALL-UNNAMED\n--add-opens javafx.graphics/com.sun.javafx.css=ALL-UNNAMED\n--add-opens javafx.base/com.sun.javafx.runtime=ALL-UNNAMED\n--add-exports javafx.controls/com.sun.javafx.scene.control.behavior=ALL-UNNAMED\n```\n\nAs these parameters might change as dependencies get updated and depending on the way your project is set up,\nplease check the following resources if you encounter problems with module accessibility:\n\n- [ControlsFX wiki about module visibility problems](https://github.com/controlsfx/controlsfx/wiki/Using-ControlsFX-with-JDK-9-and-above#understanding-exceptions)\n- [Blogpost with a brief explanation about the different parameters and how to use them](https://nipafx.dev/five-command-line-options-hack-java-module-system/)\n\n### Extending chartfx\n\nIf you find yourself missing some feature or not being able to access specific chart internals, the way to go is often to\nimplement a custom plugin or renderer.\n\nPlugins are a simple way to add new visualisation and interaction capabilities to chart-fx. In fact a lot of chart-fx' own features (e.g. zoom, data editing, measurements) are implemented as plugins, as you can see in the sample applications.\nYour plugin can directly extend ChartPlugin or extend any of the builtin plugins.\nThe Plugin Base class provides you with access to the chart object using `getChart()`.\nYour plugin should always add a Listener to the chartProperty, because when it is created there will not be an associated\nchart, so at creation time, calls to e.g. `getChart()` will return null.\nUsing a custom plugin boils down to adding it to the chart by doing `chart.getPlugins().add(new MyPlugin())`.\nIf you wrote a plugin which might be useful for other users of chart-fx please consider doing a pull request against chart-fx.\n\nRenderers are the components which do the actual heavy lifting in drawing the components of the graph to the canvas.\nA chart can have multiple renderers added using `chart.getRenderers().add(...)`\nThere are renderers which visualise actual data like the `ErrorDataSetRenderer` which is also the renderer added\nto new charts by default.\nThese Renderers operate on all DatasSets added to the chart (`chart.getDatasets.add(...)`) as well as on the ones added\nto the renderer itself.\nAs a rule of thumb, you need to implement a custom renderer if you need to visualize lots of data points or if you want\nto draw something behind the chart itself.\n\n### Acknowledgements\n\nWe express our thanks and gratitude to the JavaFX community, in particular to @GregKrug and Vito Baggiolini at CERN for their valuable insights, discussions and feedback on this topic.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffair-acc%2Fchart-fx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffair-acc%2Fchart-fx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffair-acc%2Fchart-fx/lists"}