smart_arrays_plot_polyline 2.0.0

Smart Arrays Plot Polyline #

What the package can do for you #

  • This package was designed for Web applications which need to plot 1D arrays in form of polylines (curves in the x, y plane).
  • A plot may consist of one or several polylines (scaled relative to each other if desired), optionally with x and y axes, a coordinate grid, a text legend, selection icons, and marker text.
  • Many array viewing options are provided, such as colors, fonts, zooming, scaling, shifting, rotation, layout parameters.
  • Also, lists of points represented by circles or other shapes can be drawn, e.g.to draw a curve using individual points rather than connecting the points by polylines.
  • The arrays to be plotted may have small or big sizes (even e.g. 1 million points). To achieve fast plotting without loosing information given typical screen or window sizes, a suitable data compression is applied before plotting (using the compression package listed at the end of the document).
  • Plotting is performed using Scalable Vector Graphics SVG.

The major API functionalities #

  • Class Polyline to construct a polyline plot of desired size from an array with optional layout and viewing parameters.

  • Class Axis to construct an x and/or y axis for a polyline plot.

  • Class XYGrid to construct a rectangular coordinate grid consisting of horizontal and/or vertical lines, to be used to overlay a polyline plot.

  • Class Legend to construct a legend consisting of a text line at the top ("top title") and optionally several more lines, each one preceded by a color rectangle (useful when displaying several polylines).

  • Class PhysUnits to convert between "physical units" and array indices, useful for axis annotation.

  • Classes Utils and JsonUtils providing useful helper functions.

  • Basic usage of the package: see example directory.

Detailed API #

Please view the detailed API documentation in the API reference of this package (sidebar at the right of this page).

smart_arrays_base: Basic functions for 1D and 2D arrays

smart_arrays_numerics: Numerics with 1D and 2D arrays

smart_arrays_compress: Compress 1D and 2D arrays to a smaller size.

smart_arrays_dbstore: Store 1D and 2D arrays along with metadata on the local device.

smart_arrays_peaks: Detect peaks in 1D and 2D arrays.

smart_arrays_lmfit: Fits (x, y) data given as arrays to a specified model function using the Levenberg-Marquardt algorithm.

smart_lorentz-gauss: Compute Lorentz-Gauss (pseudo-Voigt) line shapes.

smart_signal_processing: Fourier transform and more of arrays.

smart_dialogs: Easy-to-use dialogs in Web applications

Smart Arrays Plot Polyline #

Version history #

2.0.0 - 2019-07-10 First version available on pub. site.

example/example.dart

import 'dart:html';
import 'dart:svg';

import 'package:smart_arrays_plot_polyline/smart_arrays_plot_polyline.dart';
import 'dart:typed_data';
import 'dart:math' as math;

import 'sample_data.dart';

/// Demonstrates the usage of th package 'smart_arrays_plot_polyline' by displaying
/// two arrays (containing some periods of sin(x) and a sin(x)/x) as polylines
/// along with coordinate axes, a coordinate grid, a border and a legend.
/// This example can be directly executed via
/// 'https://smart.specpad.bplaced.net/smart_arrays_polyline/example.html'.
main() {
  // Fill 2 arrays with a sinc and a sine function, to be displayed later
  Float64List sinc = SampleData.genSinc(100.0, 0.0, 8, 2000, false)[1],
      sine = SampleData.genSine(20.0, 0.0, 0.0, 8, 2000, false)[1];

  // Set up the containers where the graphics is to be drawn
  computeLayout();

  // Compute the polylines for the graphical display of sinc and sine
  Polyline plSinc = Polyline(sinc, 0, sinc.length - 1, dataAreaRect.width,
      dataAreaRect.height, null, null, null, {PyA.YPOSITION_ZERO: "0.8"});

  Polyline plSine = Polyline(sine, 0, sine.length - 1, dataAreaRect.width,
      dataAreaRect.height, null, null, null, {
    PyA.YPOSITION_ZERO: "0.8", // same vertical posisition as sinc
    PyA.REFYMAX: "${plSinc.ymax}", // sine vertical scale is relative to sinc
    PyA.STROKE: "red", // draw sine in a different color
  });

  // Compute x and y axis for the sinc function (sine will be relative to sinc)
  computeAxes(plSinc);

  // Set up a legend to be displayed in addition to the polylines
  Legend legend = Legend({
    LegA.TOP_TITLE: "Example for 'smart_arrays_plot_polyline'",
    LegA.X: "45",
    LegA.Y: "15"
  }, 2);
  legend.setText("1", " 20 * sin(x)", "red");
  legend.setText("2", "100 * sin(x) / x", "blue");

  // append sinc and sine polylines and the legend to the "data area" of the layout
  dataArea.append(plSinc.polylineContainer);
  dataArea.append(plSine.polylineContainer);
  dataArea.append(legend.legendContainer);

  // append x axis, y axis and axes grid to the "plot area"  of the layout
  plotArea.append(xaxis.labelsContainer);
  plotArea.append(yaxis.labelsContainer);
  plotArea.append(xaxis.xyGrid.gridContainer);
  plotArea.append(yaxis.xyGrid.gridContainer);
}

/// These div html elements are defined in 'example.html'. [plotDiv], which is
/// embedded in [appDiv], will contain the entire graphics, taking all of the
/// remaining browser window space.
DivElement appDiv, plotDiv;

/// All graphics is drawn using SVG Scalable Vector Graphics. [plotArea] is
/// added to [plotDiv] and contains the entire plot. [dataArea] is added
/// to [plotArea] and contains the polylines and the legend. The axes are
/// drawn outside the [dataArea] but within the [plotArea].
SvgSvgElement plotArea, dataArea;

/// A frame around the 'dataArea'.
RectElement dataAreaBorder;

/// The coordinates with respect to their container
math.Rectangle<int> plotAreaRect,
    dataAreaRect,
    xaxisRect,
    yaxisRect,
    dataInsets;

/// The axes
Axis xaxis, yaxis;

/// Computes the plot layout: Sets up the graphics containers and their
/// relative coordinates and sizes.
void computeLayout() {
  // get divs from 'example.html'
  appDiv = (querySelector("#app_div") as DivElement);
  plotDiv = (querySelector("#plot_div") as DivElement);

  // the plot takes all available space
  plotDiv.style
    ..width = "${appDiv.clientWidth}px"
    ..height = "${appDiv.clientHeight}px";

  // Reserve space in pixels for the axes labels and a border around everthing.
  int xaxAreaHeight = 70, yaxAreaWidth = 80, borderAreaSize = 15;

  // will contain the entire plot
  plotAreaRect = math.Rectangle<int>(
      borderAreaSize,
      borderAreaSize,
      plotDiv.clientWidth - 2 * borderAreaSize,
      plotDiv.clientHeight - 2 * borderAreaSize);

  // all coordinates in the following rectangles are are relative to plotRect
  dataInsets = math.Rectangle<int>(borderAreaSize, borderAreaSize, 0, 0);

  // will contain the polylines and the legend
  dataAreaRect = math.Rectangle<int>(
      yaxAreaWidth,
      dataInsets.top,
      plotAreaRect.width - yaxAreaWidth - dataInsets.left,
      plotAreaRect.height - xaxAreaHeight);

  // will contain the x axis tic marks and text labels
  xaxisRect = math.Rectangle<int>(
      dataAreaRect.left,
      dataAreaRect.top + dataAreaRect.height,
      dataAreaRect.width,
      xaxAreaHeight);

  // will contain the y axis tic marks and text labels
  yaxisRect = math.Rectangle<int>(dataAreaRect.left - yaxAreaWidth,
      dataAreaRect.top, yaxAreaWidth, dataAreaRect.height);

  // will contain all axes and the data area (polylines and legend)
  plotArea = new SvgSvgElement();
  SVG.setAttr(plotArea, {
    SVG.WIDTH: "${plotAreaRect.width}",
    SVG.HEIGHT: "${plotAreaRect.height}",
  });

  // will contain polylines and legend
  dataArea = new SvgSvgElement();
  SVG.setAttr(dataArea, {
    SVG.X: "${dataAreaRect.left}",
    SVG.Y: "${dataAreaRect.top}",
    SVG.WIDTH: "${dataAreaRect.width}",
    SVG.HEIGHT: "${dataAreaRect.height}",
  });

  // a border around the data area
  dataAreaBorder = new RectElement();
  SVG.setAttr(dataAreaBorder, {
    SVG.X: "${dataAreaRect.left}",
    SVG.Y: "${dataAreaRect.top}",
    SVG.WIDTH: "${dataAreaRect.width}",
    SVG.HEIGHT: "${dataAreaRect.height}",
    SVG.FILL: "none",
    SVG.STROKE: "darkgreen",
    SVG.STROKE_WIDTH: "2"
  });

  // now stack the plot containers.
  plotDiv.append(plotArea);
  plotArea.append(dataArea);
  plotArea.append(dataAreaBorder); // draw above dataArea
} // computeLayout()

/// Computes x and y axes for [polyline]
void computeAxes(Polyline polyline) {
  // compute x axis
  xaxis = Axis.coord(
      polyline.array.length, // # points in the polyline's data array
      polyline.xValues.first, // display the array from this index
      polyline.xValues.last, // until this index
      0, // physical unit of 1st point: we choose the point number here.
      (polyline.array.length - 1).toDouble(), // phys. axis width, in points
      true, // mode for converting point index to physical unit
      null, // no extra calibration factor of axis labels
      dataAreaRect.width, // axis length in pixels
      xaxisRect.height, // height of axis area (reserves space for the labels)
      dataAreaRect.height, // grid line length, needed if 'grid' chosen
      "point number", // x axis legend text
      "bg", // axis at "b" bottom of data area, with a "g" grid, not reversed
      polyline.xphysToXscreen, // method converting physical to screen coord.
      {
        AxA.XYGRID_STROKE: "pink",
        AxA.XYGRID_STROKE_OPACITY: "1.0",
        AxA.XYGRID_STROKE_DASH: "10"
      }, // x grid color different from default
      null // no mouse or touch interaction in this example
      );

  // set the x axis container positions as computed by [computeLayout].
  SVG.setAttr(xaxis.labelsContainer, {
    SVG.X: "${xaxisRect.left - xaxis.extra_space_for_edge_labels_x}",
    SVG.Y: "${xaxisRect.top}"
  });

  // set the x axis grid container positions as computed by [computeLayout].
  SVG.setAttr(xaxis.xyGrid.gridContainer,
      {SVG.X: "${dataAreaRect.left}", SVG.Y: "${dataAreaRect.top}"});

  // compute y axis (intensity axis)
  double firstY = polyline.yScreenToYphys(0);
  double lastY = polyline.yScreenToYphys(dataAreaRect.height);
  if (firstY == null) firstY = polyline.ymin;
  if (lastY == null) lastY = polyline.ymax;
  yaxis = Axis.intens(
      firstY / polyline.yscale, // axis range, account for [PyA.YSCALE]
      lastY / polyline.yscale,
      null, // no rescaling of y axis
      null, // like above, no rescaling of y axis
      null, // would only relevant for reversed axis
      dataAreaRect.height, // axis length in pixels
      yaxisRect.width, // height of axis area (reserves space for the labels)
      dataAreaRect.width, // grid line length, needed if 'grid' chosen
      "function value",
      "bg", // "b"=position left of data area, "g"= with a grid
      polyline.yphysToYscreen, // method converting physical to screen coord.
      null, // no extra axis attributes specfied here
      null // no mouse or touch interaction in this example
      );

  // set the y axis container positions as computed by [computeLayout].
  SVG.setAttr(yaxis.labelsContainer, {
    SVG.X: "${yaxisRect.left}",
    SVG.Y: "${yaxisRect.top - yaxis.extra_space_for_edge_labels_y}"
  });

  // set the y axis grid container positions as computed by [computeLayout].
  SVG.setAttr(yaxis.xyGrid.gridContainer,
      {SVG.X: "${dataAreaRect.left}", SVG.Y: "${dataAreaRect.top}"});
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  smart_arrays_plot_polyline: ^2.0.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:smart_arrays_plot_polyline/smart_arrays_plot_polyline.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
0
Health:
Code health derived from static analysis. [more]
79
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
42
Learn more about scoring.

We analyzed this package on Jul 15, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.4.0
  • pana: 0.12.19

Platforms

Detected platforms: web

Primary library: package:smart_arrays_plot_polyline/smart_arrays_plot_polyline.dart with components: html.

Health suggestions

Fix lib/src/polyline.dart. (-9.08 points)

Analysis of lib/src/polyline.dart reported 19 hints, including:

line 132 col 7: Don't type annotate initializing formals.

line 133 col 7: Don't type annotate initializing formals.

line 134 col 7: Don't type annotate initializing formals.

line 135 col 7: Don't type annotate initializing formals.

line 136 col 7: Don't type annotate initializing formals.

Fix lib/src/axis.dart. (-7.24 points)

Analysis of lib/src/axis.dart reported 15 hints, including:

line 280 col 7: Don't type annotate initializing formals.

line 286 col 7: Don't type annotate initializing formals.

line 317 col 7: DO use curly braces for all flow control structures.

line 511 col 11: DO use curly braces for all flow control structures.

line 620 col 13: DO use curly braces for all flow control structures.

Fix lib/src/grid.dart. (-2.48 points)

Analysis of lib/src/grid.dart reported 5 hints:

line 39 col 10: Don't type annotate initializing formals.

line 39 col 34: Don't type annotate initializing formals.

line 39 col 58: Don't type annotate initializing formals.

line 40 col 7: Don't type annotate initializing formals.

line 44 col 7: DO use curly braces for all flow control structures.

Fix lib/src/phys_units.dart. (-1.99 points)

Analysis of lib/src/phys_units.dart reported 4 hints:

line 32 col 7: DO use curly braces for all flow control structures.

line 35 col 7: DO use curly braces for all flow control structures.

line 52 col 7: DO use curly braces for all flow control structures.

line 54 col 7: DO use curly braces for all flow control structures.

Fix lib/src/legend.dart. (-1.49 points)

Analysis of lib/src/legend.dart reported 3 hints:

line 50 col 46: Don't type annotate initializing formals.

line 70 col 7: DO use curly braces for all flow control structures.

line 172 col 7: DO use curly braces for all flow control structures.

Maintenance issues and suggestions

Support latest dependencies. (-10 points)

The version constraint in pubspec.yaml does not support the latest published versions for 1 dependency (build_web_compilers).

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
build_runner ^1.1.2 1.6.1
build_web_compilers ^1.0.0 1.2.2 2.1.4
pedantic ^1.5.0 1.8.0+1
smart_arrays_base ^2.0.0 2.0.8
smart_arrays_compress ^2.0.7 2.0.7
Transitive dependencies
analyzer 0.35.4 0.37.0
archive 2.0.10
args 1.5.2
async 2.2.0
bazel_worker 0.1.21
build 1.1.5
build_config 0.4.0 0.4.1
build_daemon 1.1.0
build_modules 1.0.11 2.3.1
build_resolvers 1.0.6
build_runner_core 3.0.6
built_collection 4.2.2
built_value 6.7.0
charcode 1.1.2
code_builder 3.2.0
collection 1.14.11
convert 2.1.1
crypto 2.0.6
dart_style 1.2.4 1.2.9
fixnum 0.10.9
front_end 0.1.14 0.1.20
glob 1.1.7
graphs 0.2.0
http 0.12.0+2
http_multi_server 2.1.0
http_parser 3.1.3
io 0.3.3
js 0.6.1+1
json_annotation 2.4.0
kernel 0.3.14 0.3.20
logging 0.11.3+2
matcher 0.12.5
meta 1.1.7
mime 0.9.6+3
package_config 1.0.5
package_resolver 1.0.10
path 1.6.2
pool 1.4.0
protobuf 0.13.15
pub_semver 1.4.2
pubspec_parse 0.1.4
quiver 2.0.3
scratch_space 0.0.3+2
shelf 0.7.5
shelf_web_socket 0.2.3
source_maps 0.10.8
source_span 1.5.5
stack_trace 1.9.3
stream_channel 2.0.0
stream_transform 0.0.19
string_scanner 1.0.4
term_glyph 1.1.0
timing 0.1.1+1
typed_data 1.1.6
watcher 0.9.7+12
web_socket_channel 1.0.14
yaml 2.1.16

Admin