npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ml-ngmca

v1.0.0

Published

non-negative Generalized Morphological Component Analysis

Downloads

436

Readme

nGMCA - non-negative Generalized Morphological Component Analysis

Instalation

$ npm install ml-ngmca

Usage

import { nGMCA } from 'ml-ngmca';

const result = nGMCA(dataMatrix, options);

As a CommonJS module

const { nGMCA } = require('ml-ngmca');

const result = nGMCA(dataMatrix, options);

API Documentation

This algorithm is based on the article Jérémy Rapin, Jérôme Bobin, Anthony Larue, Jean-Luc Starck. Sparse and Non-negative BSS for Noisy Data, IEEE Transactions on Signal Processing, 2013.IEEE Transactions on Signal Processing, vol. 61, issue 22, p. 5620-5632, 2013.

In order to get a general idea of the problem you could also check the Wikipedia article.

Examples

You will be able to separate the components of a mixture if you have a series of measurements correlated by a composition profile e.g NMR or mass spectra coming from a chromatographic coupled technique of two or more close retention times. So you will have a matrix with a number of rows equal or greater than the number of pure components of the mixture.

import { Matrix } from 'ml-matrix';
import { nGMCA } from 'ml-ngmca';

let pureSpectra = new Matrix([[1, 0, 1, 0]]);
let composition = new Matrix([[1, 2, 3, 2, 1]]);

// matrix = composition.transpose().mmul(pureSpectra)
let matrix = new Matrix([
  [1, 0, 1, 0],
  [2, 0, 2, 0],
  [3, 0, 3, 0],
  [2, 0, 2, 0],
  [1, 0, 1, 0],
]);

const options = {
  maximumIteration: 200,
  phaseRatio: 0.4,
};
const result = nGMCA(matrix, 1, options);
const { A, S } = result;
console.log(`A = ${A.to2DArray()} S =${S.to2DArray()}`);
/**
A = [
    [ 0.22941573387056177 ],
    [ 0.45883146774112354 ],
    [ 0.6882472016116853 ],
    [ 0.45883146774112354 ],
    [ 0.22941573387056177 ]
  ]
S = [ [ 4.358898943540674, 0, 4.358898943540674, 0 ] ]

if you reescale both S maxS and A with 1/maxS.
*/

let maxByRow = [];
for (let i = 0; i < S.rows; i++) {
  maxByRow.push(S.maxRow(i));
}

S.scale('row', { scale: maxByRow });
A.scale('column', {
  scale: maxByRow.map((e) => 1 / e),
});

/**
S = [ [ 1, 0, 1, 0 ] ]
A = [
  [1.0000000000000002],
  [2.0000000000000004],
  [3.0000000000000004],
  [2.0000000000000004],
  [1.0000000000000002]
  ]
*/

const estimatedMatrix = A.mmul(S);
const diff = Matrix.sub(matrix, estimatedMatrix);

Here is a second example:

let matrix = new Matrix([
  [0, 0, 1, 1, 1],
  [0, 0, 1, 1, 1],
  [2, 2, 2, 0, 0],
  [2, 2, 2, 0, 0],
]);

const options = {
  maximumIteration: 200,
  phaseRatio: 0.4,
};
const result = nGMCA(matrix, 1, options);
const { A, S } = result;
console.log(`A = ${A} S =${S}`);
/**
 A = [
  [
    0.707107 0       
    0.707107 0       
    2.26e-17 0.707107
    2.26e-17 0.707107
  ]
]
S = [
  [
    9.86e-32 9.86e-32 1.41421 1.41421 1.41421
    2.82843  2.82843  2.82843 0       0       
  ]
]
note: 9.86e-32 and 2.26e-17 is practically zero
so if you reescale both S maxS and A with 1/maxS.
*/

let maxByRow = [];
for (let i = 0; i < S.rows; i++) {
  maxByRow.push(S.maxRow(i));
}

S.scale('row', { scale: maxByRow });
A.scale('column', {
  scale: maxByRow.map((e) => 1 / e),
});

console.log(`A = ${A} S =${S}`);
/**
 A = [
  [
    1 0       
    1 0       
    0 1
    0 1
  ]
]
S = [
  [
    0 0 1 1 1
    2 2 2 0 0       
  ]
]
*/

The result has the matrices A and S, the estimated matrices of compositions and pureSpectra respectively. It's possible that the matrices A and S have not the same scale than pureSpectra and composition matrices because of AS has an infinity of combination to get the target matrix.

License

MIT