NodePlotLib

repository·main·Indexed 42 days ago

https://github.com/ngfelixl/nodeplotlib

A library for real-time data visualization in NodeJS that launches a webserver to serve plots via an Angular application using socket.io. It supports static plots and real-time streams using RxJS Observables, leveraging plotly.js for a wide variety of chart types including scatter, bar, pie, and 3D plots. Version 1.1.3.

Tokens
2.7K
Snippets
11
Records
21
Agent score
53%

What's inside NodePlotLib

  1. How the NodePlotLib stream implementation works

    main

    NodePlotLib uses a real-time API (such as WebSockets) to connect plot windows (apps/web) to a server.

    • Connection Logic: The server tracks the number of connected apps. If you call the plot function multiple times, a new window will only open if there is no existing active connection to an apps/web instance.
    • Data Transmission: Instead of sending a single large object, the server transmits plots one by one. This allows for real-time updates where only the specific updated plot is transmitted over the stream.
    • Plot Management: Plot streams are stored in a Plots Set. When an apps/web instance connects, it subscribes to all plots currently in that set.
  2. How nodeplotlib works behind the scenes

    main
    The library launches a webserver and opens new tabs for every plot generated. These plots are hosted at http://localhost:{{PORT}}, where PORT is a free port determined by the Express server. The server and the Angular application communicate via socket.io to enable real-time data transmission.
  3. Understand the NodePlotLib server lifecycle

    main

    The server's lifecycle is tied to the execution of the plot function and the presence of connected frontend clients:

    1. Starting: The server starts automatically when the plot function is executed, provided no active server is already running.
    2. Stopping: The server automatically stops once all apps/web instances have disconnected, provided there were active connections previously.
  4. Start NodePlotLib for development

    main

    To run the application in development mode, you need to build the web frontend with watch mode enabled and start the development server in separate processes or terminal sessions.

    npm run build web -- --watch
    npm start dev-server
  5. Run demo plots

    main

    You can run pre-built demo plots using the compiled version of nodeplotlib. The demos are located in the tools/demo/ directory. Use node to run compiled JavaScript files or ts-node to run TypeScript files directly.

    # Run a compiled scatter plot demo
    node ./tools/demo/scatter.js
    
    # Run a compiled candlestick plot demo
    node ./tools/demo/candlestick.js
    
    # Run a TypeScript scatter plot demo using ts-node
    npx ts-node ./tools/demo/scatter.ts
  6. Use PlotData and PlotDataStream for data handling

    main

    NodePlotLib uses two primary interfaces to represent plot information: a static snapshot (PlotData) and a reactive stream (PlotDataStream).

    PlotData

    Used for a single, static representation of a plot. It includes an id, the data array, and optional layout and config objects.

    PlotDataStream

    Used for real-time or reactive plotting. It includes an id and uses RxJS Observable streams for data and layout, allowing the plot to update dynamically as new data arrives. The config is a static Config object.

    // Static PlotData example
    const staticPlot: PlotData = {
      id: 1,
      data: [{ x: [1, 2], y: [3, 4], type: 'scatter' }],
      layout: { title: 'Static Plot' }
    };
    
    // Reactive PlotDataStream example
    const streamPlot: PlotDataStream = {
      id: 2,
      data: dataObservable, // Observable<Plot[]>
      layout: layoutObservable, // Observable<Layout | undefined>
      config: { responsive: true }
    };
  7. Create a realtime stream plot with RxJS

    main

    NodePlotLib supports real-time data visualization by accepting an Observable<Plot[]> as an argument to the plot function. This is achieved using the RxJS library. You can create a stream (e.g., using interval) and use operators like map to transform stream values into Plot[] arrays.

    import { plot, Plot } from 'nodeplotlib';
    import { interval, map } from 'rxjs';
    
    const stream$: Observable<Plot[]> = interval(100).pipe(
      map(createSinusPlotFromNumber)
    );
    
    function createSinusPlotFromNumber(num: number): Plot[] {
      const data: Plot[] = [
        {
          x: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
          y: Array(10)
            .fill(0)
            .map((_, i) => Math.sin(num + i)),
          type: 'scatter',
        },
      ];
      return data;
    }
    
    plot(stream$);
  8. Create a simple plot

    main

    To create a static plot, import the plot function and pass an array of Plot objects. Each Plot object defines the data (e.g., x, y) and the chart type (e.g., 'scatter', 'bar').

    import { plot, Plot } from 'nodeplotlib';
    
    const data: Plot[] = [
      {
        x: [1, 3, 4, 5],
        y: [3, 12, 1, 4],
        type: 'scatter',
      },
    ];
    
    plot(data);
  9. Use the plot function with Observables

    main

    The plot function is designed to handle both direct Plot objects and reactive streams. It can accept:

    • A Plot object.
    • An Observable<Plot> (it internally handles Plot objects by wrapping them in an RxJS of observable).