Skip to content

Commit 380dc8c

Browse files
author
AJ Keller
committed
FIX: Bug where ganglion channel data with no scale returned array of 8 instead of 4
1 parent cef0b24 commit 380dc8c

File tree

4 files changed

+70
-27
lines changed

4 files changed

+70
-27
lines changed

Diff for: changelog.md

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
* Add new constants for emitter
66

7+
### Bug Fixes
8+
9+
* Fix bug where ganglion sample channel data when scale was false produced array of 8 values instead of 4
10+
711
# v0.2.3
812

913
### New Features

Diff for: openBCIUtilities.js

+21-12
Original file line numberDiff line numberDiff line change
@@ -1118,7 +1118,7 @@ function parsePacketStandardAccel (o) {
11181118
else sampleObject.accelDataCounts = getDataArrayAccelNoScale(o.rawDataPacket.slice(k.OBCIPacketPositionStartAux, k.OBCIPacketPositionStopAux + 1));
11191119

11201120
if (o.scale) sampleObject.channelData = getChannelDataArray(o);
1121-
else sampleObject.channelDataCounts = getChannelDataArrayNoScale(o.rawDataPacket);
1121+
else sampleObject.channelDataCounts = getChannelDataArrayNoScale(o);
11221122

11231123
if (k.getVersionNumber(process.version) >= 6) {
11241124
// From introduced in node version 6.x.x
@@ -1165,7 +1165,7 @@ function parsePacketStandardRawAux (o) {
11651165
// Store the channel data
11661166
if (k.isUndefined(o.scale) || k.isNull(o.scale)) o.scale = true;
11671167
if (o.scale) sampleObject.channelData = getChannelDataArray(o);
1168-
else sampleObject.channelDataCounts = getChannelDataArrayNoScale(o.rawDataPacket);
1168+
else sampleObject.channelDataCounts = getChannelDataArrayNoScale(o);
11691169

11701170
// Slice the buffer for the aux data
11711171
if (k.getVersionNumber(process.version) >= 6) {
@@ -1237,7 +1237,7 @@ function parsePacketTimeSyncedAccel (o) {
12371237

12381238
if (k.isUndefined(o.scale) || k.isNull(o.scale)) o.scale = true;
12391239
if (o.scale) sampleObject.channelData = getChannelDataArray(o);
1240-
else sampleObject.channelDataCounts = getChannelDataArrayNoScale(o.rawDataPacket);
1240+
else sampleObject.channelDataCounts = getChannelDataArrayNoScale(o);
12411241

12421242
// Grab the accelData only if `getFromTimePacketAccel` returns true.
12431243
if (getFromTimePacketAccel(o)) {
@@ -1296,7 +1296,7 @@ function parsePacketTimeSyncedRawAux (o) {
12961296
// Grab the channel data.
12971297
if (k.isUndefined(o.scale) || k.isNull(o.scale)) o.scale = true;
12981298
if (o.scale) sampleObject.channelData = getChannelDataArray(o);
1299-
else sampleObject.channelDataCounts = getChannelDataArrayNoScale(o.rawDataPacket);
1299+
else sampleObject.channelDataCounts = getChannelDataArrayNoScale(o);
13001300

13011301
sampleObject.valid = true;
13021302

@@ -1637,19 +1637,28 @@ function getChannelDataArray (o) {
16371637
}
16381638

16391639
/**
1640-
* @description Takes a buffer filled with 24 bit signed integers from an OpenBCI device with gain settings in
1641-
* channelSettingsArray[index].gain and converts based on settings of ADS1299... spits out an
1642-
* array of floats in VOLTS
1643-
* @param dataBuf {Buffer} - Buffer with 33 bit signed integers, number of elements is same as channelSettingsArray.length * 3
1640+
* @description Takes a buffer filled with 24 bit signed integers from an OpenBCI device converts to array of counts
1641+
* @param o {Object} - The input object
1642+
* @param o.rawDataPacket {Buffer} - The 33byte raw time synced accel packet
1643+
* @param o.channelSettings {Array} - An array of channel settings that is an Array that has shape similar to the one
1644+
* calling k.channelSettingsArrayInit(). The most important rule here is that it is
1645+
* Array of objects that have key-value pair {gain:NUMBER}
16441646
* @returns {Array} - Array filled with floats for each channel's voltage in VOLTS
16451647
* @author AJ Keller (@aj-ptw)
16461648
*/
1647-
function getChannelDataArrayNoScale (dataBuf) {
1649+
function getChannelDataArrayNoScale (o) {
1650+
if (!Array.isArray(o.channelSettings)) {
1651+
throw new Error('Error [getChannelDataArrayNoScale]: Channel Settings must be an array!');
1652+
}
16481653
let channelData = [];
1649-
// Channel data arrays are always 8 long
1650-
for (let i = 0; i < k.OBCINumberOfChannelsDefault; i++) {
1654+
let numChannels = o.channelSettings.length;
1655+
if (numChannels > k.OBCINumberOfChannelsDefault) {
1656+
numChannels = k.OBCINumberOfChannelsDefault;
1657+
}
1658+
// Channel data arrays cannot be more than 8
1659+
for (let i = 0; i < numChannels; i++) {
16511660
// Convert the three byte signed integer and convert it
1652-
channelData.push(utilitiesModule.interpret24bitAsInt32(dataBuf.slice((i * 3) + k.OBCIPacketPositionChannelDataStart, (i * 3) + k.OBCIPacketPositionChannelDataStart + 3)));
1661+
channelData.push(utilitiesModule.interpret24bitAsInt32(o.rawDataPacket.slice((i * 3) + k.OBCIPacketPositionChannelDataStart, (i * 3) + k.OBCIPacketPositionChannelDataStart + 3)));
16531662
}
16541663
return channelData;
16551664
}

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openbci-utilities",
3-
"version": "0.2.3",
3+
"version": "0.2.4",
44
"description": "The official utility package of Node.js SDK for the OpenBCI Biosensor Boards.",
55
"main": "index.js",
66
"scripts": {

Diff for: test/openBCIUtilities-test.js

+44-14
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,7 @@ describe('openBCIUtilities', function () {
11351135
it('without scale all the channels should have the same number value as their (index + 1)', function () {
11361136
packet = openBCIUtilities.samplePacketRawAuxTimeSynced(0);
11371137
let sample = openBCIUtilities.parsePacketTimeSyncedRawAux({
1138+
channelSettings: defaultChannelSettingsArray,
11381139
rawDataPacket: packet,
11391140
timeOffset: 0,
11401141
scale: false
@@ -1375,6 +1376,7 @@ describe('openBCIUtilities', function () {
13751376
});
13761377
it('should get raw aux buffer', function () {
13771378
let sample = openBCIUtilities.parsePacketTimeSyncedRawAux({
1379+
channelSettings: defaultChannelSettingsArray,
13781380
rawDataPacket: packetBuffer,
13791381
timeOffset: 0,
13801382
scale: false
@@ -1384,6 +1386,7 @@ describe('openBCIUtilities', function () {
13841386
});
13851387
it('should get board time', function () {
13861388
let sample = openBCIUtilities.parsePacketTimeSyncedRawAux({
1389+
channelSettings: defaultChannelSettingsArray,
13871390
rawDataPacket: packetBuffer,
13881391
timeOffset: 0,
13891392
scale: false
@@ -1394,6 +1397,7 @@ describe('openBCIUtilities', function () {
13941397
it('should get time stamp with offset', function () {
13951398
let timeOffset = 80;
13961399
let sample = openBCIUtilities.parsePacketTimeSyncedRawAux({
1400+
channelSettings: defaultChannelSettingsArray,
13971401
rawDataPacket: packetBuffer,
13981402
timeOffset: timeOffset,
13991403
scale: false
@@ -1755,6 +1759,46 @@ describe('openBCIUtilities', function () {
17551759
expect(openBCIUtilities.isOdd(2)).to.be.false();
17561760
});
17571761
});
1762+
describe('#getChannelDataArrayNoScale', function () {
1763+
let sampleBuf;
1764+
beforeEach(() => {
1765+
sampleBuf = openBCIUtilities.samplePacket(0);
1766+
});
1767+
it('should return length of channel settings when less then 8', function () {
1768+
let numChannels = 2;
1769+
let channelSettings = k.channelSettingsArrayInit(numChannels);
1770+
let valArray = openBCIUtilities.getChannelDataArrayNoScale({
1771+
channelSettings: channelSettings,
1772+
rawDataPacket: sampleBuf
1773+
});
1774+
expect(valArray).to.have.length(numChannels);
1775+
});
1776+
it('should return length of channel settings of 8 when cyton', function () {
1777+
let numChannels = k.OBCINumberOfChannelsCyton;
1778+
let channelSettings = k.channelSettingsArrayInit(numChannels);
1779+
let valArray = openBCIUtilities.getChannelDataArrayNoScale({
1780+
channelSettings,
1781+
rawDataPacket: sampleBuf
1782+
});
1783+
expect(valArray).to.have.length(k.OBCINumberOfChannelsDefault);
1784+
});
1785+
it('should return length of channel settings of 8 when daisy', function () {
1786+
let numChannels = k.OBCINumberOfChannelsDaisy;
1787+
let channelSettings = k.channelSettingsArrayInit(numChannels);
1788+
let valArray = openBCIUtilities.getChannelDataArrayNoScale({
1789+
channelSettings,
1790+
rawDataPacket: sampleBuf
1791+
});
1792+
expect(valArray).to.have.length(k.OBCINumberOfChannelsDefault);
1793+
});
1794+
it('should reject when channelSettingsArray is not in fact an array', function () {
1795+
expect(openBCIUtilities.getChannelDataArrayNoScale.bind(openBCIUtilities, {
1796+
rawDataPacket: sampleBuf,
1797+
channelSettings: {},
1798+
protocol: k.OBCIProtocolWifi
1799+
})).to.throw('Error [getChannelDataArrayNoScale]: Channel Settings must be an array!');
1800+
});
1801+
});
17581802
describe('#getChannelDataArray', function () {
17591803
let sampleBuf, badChanArray;
17601804
beforeEach(() => {
@@ -1878,20 +1922,6 @@ describe('openBCIUtilities', function () {
18781922
});
18791923
});
18801924
describe('Wifi', function () {
1881-
it('should multiply each channel by the ganglion scale value when num chan is 4', function () {
1882-
let chanArr = k.channelSettingsArrayInit(k.OBCINumberOfChannelsGanglion); // Not in daisy mode
1883-
let scaleFactor = 1.2 / 51.0 / (Math.pow(2, 23) - 1);
1884-
// Call the function under test
1885-
let valueArray = openBCIUtilities.getChannelDataArray({
1886-
rawDataPacket: sampleBuf,
1887-
channelSettings: chanArr,
1888-
protocol: k.OBCIProtocolWifi
1889-
});
1890-
for (let j = 0; j < k.OBCINumberOfChannelsGanglion; j++) {
1891-
// console.log(`channel data ${j + 1}: ${valueArray[j]} : actual ${scaleFactor * (j + 1)}`);
1892-
expect(valueArray[j]).to.be.closeTo(scaleFactor * (j + 1), 0.0001);
1893-
}
1894-
});
18951925
it('should multiply each channel by the cyton scale value when num chan is 8', function () {
18961926
let chanArr = k.channelSettingsArrayInit(k.OBCINumberOfChannelsDefault); // Not in daisy mode
18971927
let scaleFactor = 4.5 / 24 / (Math.pow(2, 23) - 1);

0 commit comments

Comments
 (0)