0.0.112 • Published 3 years ago
needle-haystack-1d v0.0.112
needle-haystack-1d
fuzzy-matching between a 1-d "needle" time series and a "haystack" time series. find scaled+shifted copies of the "needle" within the "haystack".
similar to phase-align but with multiple fuzzy results and limited to 1-d data.
Installation
npm i needle-haystack-1dUsage
var {getNeedleScaleShift, getMSE, getNeedleHaystackData, removeOverlaps} = require('needle-haystack-1d');
var needle = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var haystack = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0,0,0,0,0,0,0,0,0,0,0];
haystack = haystack.map(f=>f*10+5); //scale+shift the haystack
var doRemoveOverlaps = false; //default false
var res = getNeedleHaystackData(needle, haystack, doRemoveOverlaps);
console.log(res);
//doRemoveOverlaps = false
// {
//     indicesWithCorrelations: [  // [hitIndex, normalized correlation] sorted by correlation
//         [ 21, 2.251800553427485 ],
//         [ 20, 2.2069626632689396 ],
//         [ 22, 2.1621247731103908 ],
//         ...
// }
//doRemoveOverlaps = true
// {
//     indicesWithCorrelations: [
//         [ 21, 2.251800553427485 ],
//         [ 10, -0.5281486364024173 ],
//         [ 31, -0.6447271508146415 ]
//     ]
// }
//note - correlations are normalized by npm `ndarray-normalize` to have mean zero and std 1 
//extract the top "hit" from the haystack
var futurePeriods = 0; //add extra 'future' periods to the results?
var [topHitIndex, topCorrelation] = res.indicesWithCorrelations[0];
var shifted = getNeedleScaleShift(needle, haystack, topHitIndex, futurePeriods);
console.log(shifted);
// {
//     slope: 10,
//     yIntercept: -5,
//     extractedHaystackSection: [ //original data from haystack
//          5, 15, 25, 35, 45,
//          55, 65, 75, 85, 95
//     ],
//     extractedHaystackSectionRescaled: [ //data scaled and shifted to resemble needle
//         1, 2, 3, 4,  5,
//         6, 7, 8, 9, 10
//     ]
// }
//now we get the mean squared error [MSE] between
// the original needle and the extracted, scaled+shifted needle
var mse = getMSE(needle, shifted.extractedHaystackSectionRescaled);
console.log({mse})
// { mse: 0 }
//remove overlaps in existing results: 
//var windowSize = needle.length;
//res = removeOverlaps(res, windowSize); See Also
- phase-align
- ndarray-convolve - the correlatefunction does most of the work here for us
