smart_arrays_lmfit 2.0.8

  • Readme
  • Changelog
  • Example
  • Installing
  • 64

Smart Arrays LM (Levenberg-Marquart) Fit #

What the package can do for you #

The purpose of this package is to fit "experimental data" to a "fit function" representing a model for the experimental data. These must be specified as an array of x values and an an array of the respective y values.

This curve fitter is using the Levenberg-Marquardt algorithm. The Dart implementation here was derived from https://github.com/reptillicus/jsfit.

Example #

The major API functionalities #

  • Class LMfit: Usage:
    1. call constructor
    2. call fit() or lmfit() ( = async version of fit())

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_plot_polyline: Plot 1D arrays as polyline along with axes and more.

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

smart_arrays_contour_finder: Contours the three-dimensional surface represented by the values f(x,y) of a matrix.

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

smart_signal_processing: Fourier transform and more.

smart_dialogs: Easy-to-use dialogs in Web applications

Smart Arrays LM fit #

Version history #

2.0.8 - 2019-10-01 Adaptation to new version of smart_arrays_plot_polyline

2.0.0 - 2019-04-02 First version available on pub site

2.0.1 - 2019-04-04 Doc updates.

2.0.2 - 2019-04-13 Doc updates.

2.0.4 - 2019-05-06 Doc updates.

2.0.5 - 2019-08-06 Fixed health suggestions of pub.dev

2.0.6 - 2019-08-07 Fixed more health suggestions of pub.dev

2.0.7 - 2019-09-09 The computation result of the example now gets graphically displayed in the browser

example/example.dart

// Copyright (c) 2019, Dr. Bruno Guigas. All rights reserved. Use of this source
// code is governed by a BSD-style license that can be found in the LICENSE file.

import 'dart:html';
import 'dart:typed_data';
import 'dart:convert';
import 'dart:math' as math;

import 'package:smart_arrays_lmfit/smart_arrays_lmfit.dart';
import 'package:smart_arrays_plot_polyline/smart_arrays_plot_polyline.dart';

/// Demonstrates thes usage of this package by fitting data to a Gaussian.
main() async {
  // Define the "fit model" to which a data array should be fitted: a Gaussian
  double fitFunctionGAUSS(double x, List<double> params) {
    // amplitude, center, width, y offset:
    double a = params[0], c = params[1], w = params[2], y0 = params[3];
    final FGAUSS = 4 * math.log(2); // normalization constant
    return y0 + a * math.exp(-FGAUSS * ((x - c) / w) * ((x - c) / w));
  }

  final int NPOINTS = 50;

  // Compute "experimental data" to be fitted to a Gaussian:
  // We compute an exact Gaussian, then add some random noise to it.
  List<double> computeGaussianArray(List<double> params, double noiseAmpl) {
    List<double> yvals = List(NPOINTS);
    math.Random rand = math.Random();
    for (int i = 0; i < NPOINTS; i++) {
      yvals[i] = fitFunctionGAUSS(i.toDouble(), params);
      if (noiseAmpl != null) {
        double noise = (2.0 * rand.nextDouble() - 1.0) * yvals[i] * noiseAmpl;
        yvals[i] += noise;
      }
    }
    return yvals;
  }

  double a = 100, c = 25, w = 10, y0 = 10;
  final List<double> GAUSS_PARS = [a, c, w, y0];
  List<double> expGaussian = computeGaussianArray(GAUSS_PARS, 0.1);

  // initial parameters for the fit, derived from the exact parameters
  final List<double> INITIAL_PARS = [a * 0.8, c * 0.9, w * 1.2, y0];

  // use these fitting options
  Map<String, List<String>> fitOptions = {
    LMfit.FIT_OPT_TOLERANCE: ["1e-10"],
    LMfit.PARAM_DELTA_CONVERGE: ["0.0001"],
    LMfit.MAX_ITERATIONS: ["200"],
    LMfit.PAR_INFO: [null, null, null, "y0 fixed null null"]
  };

  // start fitting the "experimental data" to a Gaussian, wait till done
  LMfit lm = LMfit();
  Map<String, List<String>> fitResult = await lm.lmfit(
      fitFunctionGAUSS, null, expGaussian, INITIAL_PARS, fitOptions);

  // from the fit result, compute the Gaussian fit curve
  List<double> fittedPars = [
    double.parse(fitResult[LMfit.PARAMS][0]), // a
    double.parse(fitResult[LMfit.PARAMS][1]), // c
    double.parse(fitResult[LMfit.PARAMS][2]), // w
    double.parse(fitResult[LMfit.PARAMS][3]) // y0
  ];
  List<double> fittedGaussian = computeGaussianArray(fittedPars, null);

  // extract more fit results and prepare for printing
  List<String> fitResultPrintOut = [
    "exact Gaussian parameters (height, center, width, y offset)=${GAUSS_PARS}",
    "initial parameters for fit=${fitResult[LMfit.INITIAL_PARAMS]}",
    """fitted (iterated) parameters=[${fittedPars[0].toStringAsFixed(2)},
    ${fittedPars[1].toStringAsFixed(2)},
    ${fittedPars[2].toStringAsFixed(2)},
    ${fittedPars[3].toStringAsFixed(2)}]""",
    "iterations=${fitResult[LMfit.ITERATIONS][0]}",
    "stop reason=${fitResult[LMfit.STOP_REASON][0]}",
    "time [milliseconds]=${fitResult[LMfit.TIME][0]}",
    "chi squared=${fitResult[LMfit.CHI2][0]}",
    "",
    "Reload app to change the experimental points!"
  ];

  // show everything in the browser
  plot(expGaussian, fittedGaussian, fitResultPrintOut);
}

/// Displays the data computed by [main] in the browser using the
/// package 'smart_arrays_plot_polyline'.
void plot(List<double> expGaussian, List<double> fittedGaussian,
    List<String> fitResultPrintOut) {
  // get divs from 'example.html' (application and plot containers)
  DivElement appDiv = (querySelector("#app_div") as DivElement);
  DivElement plotDiv = (querySelector("#plot_div") as DivElement);

  // the plot will take all available space of [appDiv] in this example
  plotDiv.style
    ..width = "${appDiv.clientWidth}px"
    ..height = "${appDiv.clientHeight}px";

  int npoints = expGaussian.length;

  // experimental Gaussian points to be plotted as circles, not as a polyline
  List<String> pointList = [POLYLINE_POINT_SHAPE_CIRCLE_EMPTY, ""];
  for (int i = 0; i < npoints; i++) {
    pointList.add("${i}");
    pointList.add("${expGaussian[i]}");
  }

  // setup some attributes for polyline, axis and legend
  List<Map<PyA, String>> polyAttr = [
    {
      PyA.YPOSITION_ZERO: "0.85",
      PyA.POINT_LIST: json.encode(pointList),
      PyA.POINT_LIST_STROKE: "red"
    },
  ];

  Map<AxA, String> xaxisAttr = {
    AxA.PHYS_X_START: "0",
    AxA.PHYS_X_WIDTH: "${npoints}",
    AxA.LEGENDTEXT: "Number of points"
  };

  Map<AxA, String> yaxisAttr = {AxA.LEGENDTEXT: "Gaussian value"};

  Map<LegA, String> legendAttr = {
    LegA.TOP_TITLE: "Fitting a Gaussian to 'experimental' points",
    LegA.SUB_TITLES: json.encode(["Fitted curve", "Experiment"]),
    LegA.X: "45",
    LegA.Y: "15"
  };

  // plot experimental points, fittedGaussian, axes, legend into plotDiv
  SimplePlot plot = SimplePlot([Float64List.fromList(fittedGaussian)], plotDiv,
      polyAttr, xaxisAttr, yaxisAttr, legendAttr, null);

  // In a 2nd legend2, we'll display the fitResultPrintOut
  Map<LegA, String> legend2Attr = {
    LegA.TOP_TITLE: "Fit result:",
    LegA.SUB_TITLES: json.encode(fitResultPrintOut),
    LegA.TEXT_COLOR: "darkgreen",
    LegA.X: "45",
    LegA.Y: "100"
  };

  // append the fitResultPrintOut legend to the plot's data area
  Legend legend2 = SimplePlot.createLegend(legend2Attr, null);
  plot.pl.dataArea.append(legend2.legendContainer);
}

Use this package as a library

1. Depend on it

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


dependencies:
  smart_arrays_lmfit: ^2.0.8

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter 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_lmfit/smart_arrays_lmfit.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
29
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
64
Learn more about scoring.

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

  • Dart: 2.6.1
  • pana: 0.12.21

Platforms

Detected platforms: Flutter, web, other

No platform restriction found in primary library package:smart_arrays_lmfit/smart_arrays_lmfit.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.5.0 <3.0.0
build_runner ^1.6.2 1.7.2
build_web_compilers ^2.1.4 2.7.1
pedantic ^1.7.0 1.8.0+1
smart_arrays_numerics ^2.0.0 2.1.1
smart_arrays_plot_polyline ^2.1.0 2.2.1
Transitive dependencies
_fe_analyzer_shared 1.0.0
analyzer 0.39.1
archive 2.0.11
args 1.5.2
async 2.4.0
bazel_worker 0.1.23
build 1.2.2
build_config 0.4.1+1
build_daemon 2.1.2
build_modules 2.7.0
build_resolvers 1.3.0
build_runner_core 4.2.0
built_collection 4.3.0
built_value 7.0.0
charcode 1.1.2
checked_yaml 1.0.2
code_builder 3.2.1
collection 1.14.12
convert 2.1.1
crypto 2.1.3
csslib 0.16.1
dart_style 1.3.3
fixnum 0.10.11
front_end 0.1.29
glob 1.2.0
graphs 0.2.0
html 0.14.0+3
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 3.0.0
kernel 0.3.29
logging 0.11.3+2
matcher 0.12.6
meta 1.1.8
mime 0.9.6+3
node_interop 1.0.3
node_io 1.0.1+2
package_config 1.1.0
package_resolver 1.0.10
path 1.6.4
pool 1.4.0
protobuf 1.0.1
pub_semver 1.4.2
pubspec_parse 0.1.5
quiver 2.1.2+1
scratch_space 0.0.4+1
shelf 0.7.5
shelf_web_socket 0.2.3
smart_arrays_base 2.1.0
smart_arrays_compress 2.1.0
smart_arrays_contour_finder 2.0.6
smart_arrays_sample_data 2.0.5
smart_lorentz_gauss 2.1.2
source_maps 0.10.8
source_span 1.5.5
stack_trace 1.9.3
stream_channel 2.0.0
stream_transform 0.0.20 1.0.0
string_scanner 1.0.5
term_glyph 1.1.0
timing 0.1.1+2
typed_data 1.1.6
watcher 0.9.7+13
web_socket_channel 1.1.0
yaml 2.2.0