peaktools
Version:
Peak curvature tools(experimental)
214 lines (190 loc) • 5.82 kB
JavaScript
//historical copy
var regression = require('regression');
var csv = require('csv');
var fs = require('fs');
var parse = require('csv-parse');
var x = document.createElement("INPUT");
x.setAttribute("type", "file");
var parser = parse({delimiter: ',',
columns: true,
function(err, data)
{
console.log(data);
console.log(err);
}
});
var trackingSize = 15; // number of samples to use for linear regression.
var peakStartAdjust = 4;
var sensorData = [];
var sensorLatest = [];
var peakInfo = [];
var curSlope = undefined;
var curIntercept = undefined;
var curLine = undefined;
var slopeData = [];
var slopeDetect = 0.75; // abs(curSlope) >= slopeDetect triggers a peak start/stop.
var slopeLatest = [];
var peakTracking = false;
var peakAscending = false;
var peakDescending = false;
var peakStart = undefined;
var peakEnd = undefined;
var peakArea = undefined;
var peakDirection = 0;
function getTestFile()
{
var x = document.getElementById("peakTestFile");
// x.disabled = true;
return x.value;
} // getTestFile()
function startPeak()
{
console.log("Start peak");
peakTracking = true;
peakStart = sensorData[sensorData.length - peakStartAdjust - 1];
peakIdxStart = peakStart[0];
peakBaseStart = peakStart[1];
peakArea = 0;
peakDirection = Math.sign(curSlope);
if (peakDirection > 0)
{
peakAscending = true;
peakDescending = false;
}
else
{
peakDescending = true; // possible support for 'negative' peaks.... FUTURE DEVELOPMENT.
peakAscending = false;
}
for (var i = 0; i < peakStartAdjust; i++)
{
peakArea += (sensorData[peakIdxStart + i][1] - peakBaseStart);
}
} // startPeak()
function savePeak(reading)
{
console.log("SavePeak");
peakEnd = reading;
var peak = {'start': peakStart,
'end': peakEnd,
'area': peakArea,
'idxStart': peakStart[0],
'idxEnd': peakEnd [0],
'baseStart': peakStart[1],
'baseEnd': peakEnd [1]
};
console.log("Peak: " + peak);
peakInfo.push(peak);
peakTracking = false;
peakAscending = false;
peakDescending = false;
} // savePeak()
function newData(reading)
{
sensorData .push(reading);
sensorLatest.push(reading);
if (sensorLatest.length > trackingSize)
{
sensorLatest.shift();
curLine = regression.linear(sensorLatest);
curSlope = curLine.equation[0];
curIntercept = curLine.equation[1];
slopeData.push(curSlope);
if (peakTracking)
{
/*
* Collect current data.
* Check for:
* + switched direction (peak-is-ending)
* + dropped below slopeDetect (peak-has-ended)
* + switched direction again (new-peak-is-starting).
*
* QUESTION: Are 'plateaus' on the side of a peak
* a secondary peak, or just part of the current peak?
*/
peakArea += reading[1] - peakBaseStart;
if (peakAscending
&& (Math.abs(curSlope) >= slopeDetect)
&& ((Math.sign(curSlope) * peakDirection) < 0))
{
/*
* Peak has switched directions.
* Only consider it a significant change if > slopeDetect.
*/
peakAscending = false;
peakDescending = true;
}
else if (peakDescending
&& (Math.abs(curSlope) < slopeDetect))
{
/*
* Peak has ended.
* End and store the current peak.
*/
savePeak(reading);
}
else if (peakDescending
&& (Math.abs(curSlope) >= slopeDetect)
&& (Math.sign(curSlope) == peakDirection))
{
/*
* Peak has switched directions again.
* Adjacent peaks.
* End (and store) the current peak and start another.
*
* NOTE: Need to potentially adjust the area
* based on whether peakEnd sample == peakStart sample.
*/
savePeak(reading);
startPeak();
}
}
else
{
/*
*
* Start collecting peak information.
* Track the start of the peak.
* Set the direction.
* We track a peak through one reversal of direction
* back to below slopeDetect or to another reversal.
* Example:
* + to - to below slopeDetect // non-adjacent peaks.
* + to - to + // adjacent peaks.
*
*/
if (Math.abs(curSlope) >= slopeDetect)
{
startPeak();
}
}
}
} // newData()
function runPeakTest(datafile)
{
console.log("Running peak tests");
var readings = 0;
if (datafile == undefined)
{
datafile = getTestFile();
}
var data = fs.createReadStream(datafile)
.pipe(parser)
.on('data', function (data)
{
readings += 1;
console.log(readings);
newData([readings, parseFloat(data.Sensor)]);
}
)
.on('headers', function (headerList)
{
console.log('Headers: ' + headerList);
}
)
.on('end', function()
{
console.log("Slope info: " + slopeData);
}
);
} // runPeakTest()