Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions cpp_package/src/data_filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,28 @@ double DataFilter::get_railed_percentage (double *data, int data_len, int gain)
return output;
}

double *DataFilter::get_activity_index (const double *accel_x, const double *accel_y,
const double *accel_z, int data_len, int period, int *output_len)
{
if ((period <= 0) || (period > data_len))
{
period = data_len;
}
int num_epochs = data_len / period;
double *output = new double[num_epochs];
int res = ::get_activity_index (accel_x, accel_y, accel_z, data_len, period, output);
if (res != (int)BrainFlowExitCodes::STATUS_OK)
{
delete[] output;
throw BrainFlowException ("unable to calculate activity index", res);
}
if (output_len != NULL)
{
*output_len = num_epochs;
}
return output;
}

std::string DataFilter::get_version ()
{
char version[64];
Expand Down
12 changes: 12 additions & 0 deletions cpp_package/src/inc/data_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,18 @@ class DataFilter
BrainFlowArray<double, 2>, BrainFlowArray<double, 2>>
perform_ica (const BrainFlowArray<double, 2> &data, int num_components);

/**
* calculate activity index from 3-axis accelerometer data
* @param accel_x input 1d array
* @param accel_y input 1d array
* @param accel_z input 1d array
* @param data_len size of array
* @param period epoch length in samples (defaults to data_len if <= 0)
* @param output_len pointer to int to store number of epochs calculated
* @return pointer to array of activity indices
*/
static double *get_activity_index (const double *accel_x, const double *accel_y,
const double *accel_z, int data_len, int period, int *output_len);

/// get brainflow version
static std::string get_version ();
Expand Down
33 changes: 32 additions & 1 deletion csharp_package/brainflow/brainflow/data_filter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using brainflow.math;
using brainflow.math;

using System;
using System.Numerics;
Expand Down Expand Up @@ -585,6 +585,37 @@ public static void write_file (double[,] data, string file_name, string file_mod
return result;
}

/// <summary>
/// calculate activity index from 3-axis accelerometer data
/// </summary>
public static double[] get_activity_index (double[] accel_x, double[] accel_y, double[] accel_z, int period = 0)
{
if (accel_x == null || accel_y == null || accel_z == null)
{
throw new BrainFlowError ((int)BrainFlowExitCodes.INVALID_ARGUMENTS_ERROR);
}
if ((accel_x.Length != accel_y.Length) || (accel_x.Length != accel_z.Length))
{
throw new BrainFlowError ((int)BrainFlowExitCodes.INVALID_ARGUMENTS_ERROR);
}
if (period <= 0)
{
period = accel_x.Length;
}
if (accel_x.Length < period)
{
throw new BrainFlowError ((int)BrainFlowExitCodes.INVALID_ARGUMENTS_ERROR);
}
int num_epochs = accel_x.Length / period;
double[] output = new double[num_epochs];
int res = DataHandlerLibrary.get_activity_index (accel_x, accel_y, accel_z, accel_x.Length, period, output);
if (res != (int)BrainFlowExitCodes.STATUS_OK)
{
throw new BrainFlowError (res);
}
return output;
}

/// <summary>
/// calculate nearest power of two
/// </summary>
Expand Down
19 changes: 18 additions & 1 deletion csharp_package/brainflow/brainflow/data_handler_library.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;

namespace brainflow
{
Expand Down Expand Up @@ -187,6 +187,8 @@ public static extern int perform_wavelet_denoising (double[] data, int data_len,
public static extern int get_heart_rate (double[] ppg_ir, double[] ppg_red, int data_size, int sampling_rate, int fft_size, double[] output);
[DllImport ("DataHandler", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int perform_ica (double[] data, int rows, int cols, int num_components, double[] w, double[] k, double[] a, double[] s);
[DllImport ("DataHandler", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int get_activity_index (double[] accel_x, double[] accel_y, double[] accel_z, int data_len, int period, double[] output);
// unsafe methods working with pointers
[DllImport ("DataHandler", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern int perform_lowpass (double* data, int len, int sampling_rate, double cutoff, int order, int filter_type, double ripple);
Expand Down Expand Up @@ -297,6 +299,8 @@ public static extern int perform_wavelet_denoising (double[] data, int data_len,
public static extern int get_heart_rate (double[] ppg_ir, double[] ppg_red, int data_size, int sampling_rate, int fft_size, double[] output);
[DllImport ("DataHandler32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int perform_ica (double[] data, int rows, int cols, int num_components, double[] w, double[] k, double[] a, double[] s);
[DllImport ("DataHandler32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int get_activity_index (double[] accel_x, double[] accel_y, double[] accel_z, int data_len, int period, double[] output);
// unsafe methods working with pointers
[DllImport ("DataHandler32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern int perform_lowpass (double* data, int len, int sampling_rate, double cutoff, int order, int filter_type, double ripple);
Expand Down Expand Up @@ -389,6 +393,19 @@ public static int perform_ica (double[] data, int rows, int cols, int num_compon
return (int)BrainFlowExitCodes.GENERAL_ERROR;
}

public static int get_activity_index (double[] accel_x, double[] accel_y, double[] accel_z, int data_len, int period, double[] output)
{
switch (PlatformHelper.get_library_environment ())
{
case LibraryEnvironment.x64:
return DataHandlerLibrary64.get_activity_index (accel_x, accel_y, accel_z, data_len, period, output);
case LibraryEnvironment.x86:
return DataHandlerLibrary32.get_activity_index (accel_x, accel_y, accel_z, data_len, period, output);
}

return (int)BrainFlowExitCodes.GENERAL_ERROR;
}

public static int perform_lowpass (double[] data, int len, int sampling_rate, double cutoff, int order, int filter_type, double ripple)
{
switch (PlatformHelper.get_library_environment ())
Expand Down
41 changes: 41 additions & 0 deletions java_package/brainflow/src/main/java/brainflow/DataFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ int get_heart_rate (double[] ppg_ir, double[] ppg_red, int len, int sampling_rat
int perform_ica (double[] data, int rows, int cols, int num_components, double[] w, double[] k, double[] a,
double[] s);

int get_activity_index (double[] accel_x, double[] accel_y, double[] accel_z, int data_len, int period,
double[] output);

int get_version_data_handler (byte[] version, int[] len, int max_len);

int log_message_data_handler (int log_level, String message);
Expand Down Expand Up @@ -1073,6 +1076,44 @@ public static double[][] read_file (String file_name) throws BrainFlowError
return reshape_data_to_2d (num_rows[0], num_cols[0], data_arr);
}

/**
* calculate activity index from 3-axis accelerometer data
*/
public static double[] get_activity_index (double[] accel_x, double[] accel_y, double[] accel_z, int period)
throws BrainFlowError
{
if (accel_x == null || accel_y == null || accel_z == null)
{
throw new BrainFlowError ("Null pointer passed", BrainFlowExitCode.INVALID_ARGUMENTS_ERROR.get_code ());
}
if ((accel_x.length != accel_y.length) || (accel_x.length != accel_z.length))
{
throw new BrainFlowError ("Array lengths do not match", BrainFlowExitCode.INVALID_ARGUMENTS_ERROR.get_code ());
}
if (period <= 0)
{
period = accel_x.length;
}
if (accel_x.length < period)
{
throw new BrainFlowError ("Data length is shorter than period", BrainFlowExitCode.INVALID_ARGUMENTS_ERROR.get_code ());
}
int num_epochs = accel_x.length / period;
double[] output = new double[num_epochs];
int ec = instance.get_activity_index (accel_x, accel_y, accel_z, accel_x.length, period, output);
if (ec != BrainFlowExitCode.STATUS_OK.get_code ())
{
throw new BrainFlowError ("Failed to calculate activity index", ec);
}
return output;
}

public static double[] get_activity_index (double[] accel_x, double[] accel_y, double[] accel_z)
throws BrainFlowError
{
return get_activity_index (accel_x, accel_y, accel_z, 0);
}

public static double[] reshape_data_to_1d (int num_rows, int num_cols, double[][] buf)
{
double[] output_buf = new double[num_rows * num_cols];
Expand Down
18 changes: 18 additions & 0 deletions julia_package/brainflow/src/data_filter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -461,3 +461,21 @@ end
psd[1], psd[2], length(psd[1]), Float64(freq_start), Float64(freq_end), band_power)
return band_power[1]
end

@brainflow_rethrow function get_activity_index(accel_x, accel_y, accel_z, period::Integer=0)
if (length(accel_x) != length(accel_y)) || (length(accel_x) != length(accel_z))
throw(BrainFlowError(string("Arrays lengths must match ", INVALID_ARGUMENTS_ERROR), Integer(INVALID_ARGUMENTS_ERROR)))
end
data_len = length(accel_x)
if period <= 0
period = data_len
end
if data_len < period
throw(BrainFlowError(string("Data length is shorter than period ", INVALID_ARGUMENTS_ERROR), Integer(INVALID_ARGUMENTS_ERROR)))
end
num_epochs = div(data_len, period)
output = Vector{Float64}(undef, num_epochs)
ccall((:get_activity_index, DATA_HANDLER_INTERFACE), Cint, (Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Cint, Cint, Ptr{Float64}),
accel_x, accel_y, accel_z, Int32(data_len), Int32(period), output)
return output
end
20 changes: 20 additions & 0 deletions matlab_package/brainflow/DataFilter.m
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,26 @@ function write_file(data, file_name, file_mode)
data = transpose(reshape(data_array.Value(1, 1:data_count.Value), [num_cols.Value, num_rows.value]));
end

function output = get_activity_index(accel_x, accel_y, accel_z, period)
% calculate activity index
if nargin < 4
period = size(accel_x, 2);
end
if period <= 0
period = size(accel_x, 2);
end
task_name = 'get_activity_index';
temp_input_x = libpointer('doublePtr', accel_x);
temp_input_y = libpointer('doublePtr', accel_y);
temp_input_z = libpointer('doublePtr', accel_z);
lib_name = DataFilter.load_lib();
num_epochs = floor(size(accel_x, 2) / period);
temp_output = libpointer('doublePtr', zeros(1, num_epochs));
exit_code = calllib(lib_name, task_name, temp_input_x, temp_input_y, temp_input_z, size(accel_x, 2), period, temp_output);
DataFilter.check_ec(exit_code, task_name);
output = temp_output.Value;
end

end

end
29 changes: 29 additions & 0 deletions nodejs_package/brainflow/data_filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class DataHandlerDLL extends DataHandlerFunctions
this.lib.func(CLike.restore_data_from_wavelet_detailed_coeffs);
this.detectPeaksZScore = this.lib.func(CLike.detect_peaks_z_score);
this.performIca = this.lib.func(CLike.perform_ica);
this.getActivityIndex = this.lib.func(CLike.get_activity_index);
this.getCsp = this.lib.func(CLike.get_csp);
this.detrend = this.lib.func(CLike.detrend);
this.calcStddev = this.lib.func(CLike.calc_stddev);
Expand Down Expand Up @@ -607,4 +608,32 @@ export class DataFilter
}
return output[0];
}

public static getActivityIndex(
accelX: number[], accelY: number[], accelZ: number[], period: number = 0): number[]
{
if (accelX.length !== accelY.length || accelX.length !== accelZ.length)
{
throw new BrainFlowError (
BrainFlowExitCodes.INVALID_ARGUMENTS_ERROR, "arrays lengths must match");
}
if (period <= 0)
{
period = accelX.length;
}
if (accelX.length < period)
{
throw new BrainFlowError (
BrainFlowExitCodes.INVALID_ARGUMENTS_ERROR, "data length is shorter than period");
}
const numEpochs = Math.trunc(accelX.length / period);
const output = [...new Array (numEpochs).fill(0)];
const res = DataHandlerDLL.getInstance().getActivityIndex(
accelX, accelY, accelZ, accelX.length, period, output);
if (res !== BrainFlowExitCodes.STATUS_OK)
{
throw new BrainFlowError (res, 'Could not calc activity index');
}
return output;
}
}
4 changes: 4 additions & 0 deletions nodejs_package/brainflow/functions.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,8 @@ export enum DataHandlerCLikeFunctions {
'int detect_peaks_z_score (double *data, int data_len, int lag, double threshold, double influence, _Inout_ double *output)',
perform_ica =
'int perform_ica (double *data, int rows, int cols, int num_components, _Inout_ double *w_mat, _Inout_ double *k_mat, _Inout_ double *a_mat, _Inout_ double *s_mat)',
get_activity_index =
'int get_activity_index (double *accel_x, double *accel_y, double *accel_z, int data_len, int period, _Inout_ double *activity_index)',
get_csp =
'int get_csp (const double *data, const double *labels, int n_epochs, int n_channels, int n_times, _Inout_ double *output_w, _Inout_ double *output_d)',
get_railed_percentage =
Expand Down Expand Up @@ -445,6 +447,8 @@ export class DataHandlerFunctions
influence: number, output: number[]) => BrainFlowExitCodes;
performIca!: (data: number[], rows: number, cols: number, numComponents: number, wMat: number[],
kMat: number[], aMat: number[], sMat: number[]) => BrainFlowExitCodes;
getActivityIndex!: (accelX: number[], accelY: number[], accelZ: number[], dataLen: number,
period: number, activityIndex: number[]) => BrainFlowExitCodes;
getCsp!: (data: number[], labels: number[], nEpochs: number, nChannels: number, nTimes: number,
outputW: number[], outputD: number[]) => BrainFlowExitCodes;
detrend!: (rawData: number[], dataLen: number, detrendOperation: number) => BrainFlowExitCodes;
Expand Down
45 changes: 45 additions & 0 deletions python_package/brainflow/data_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,17 @@ def __init__(self):
ndpointer(ctypes.c_double)
]

self.get_activity_index = self.lib.get_activity_index
self.get_activity_index.restype = ctypes.c_int
self.get_activity_index.argtypes = [
ndpointer(ctypes.c_double),
ndpointer(ctypes.c_double),
ndpointer(ctypes.c_double),
ctypes.c_int,
ctypes.c_int,
ndpointer(ctypes.c_double)
]

self.get_version_data_handler = self.lib.get_version_data_handler
self.get_version_data_handler.restype = ctypes.c_int
self.get_version_data_handler.argtypes = [
Expand Down Expand Up @@ -1293,6 +1304,40 @@ def perform_ifft(cls, data):

return output

@classmethod
def get_activity_index(cls, accel_x, accel_y, accel_z, period: int = 0):
"""get activity index from 3-axis accelerometer data

:param accel_x: acceleration X data
:type accel_x: NDArray[Shape["*"], Float64]
:param accel_y: acceleration Y data
:type accel_y: NDArray[Shape["*"], Float64]
:param accel_z: acceleration Z data
:type accel_z: NDArray[Shape["*"], Float64]
:param period: epoch length in samples (defaults to full data length if 0)
:type period: int
:return: activity index values
:rtype: NDArray[Shape["*"], Float64]
"""
check_memory_layout_row_major(accel_x, 1)
check_memory_layout_row_major(accel_y, 1)
check_memory_layout_row_major(accel_z, 1)
if not (accel_x.shape[0] == accel_y.shape[0] == accel_z.shape[0]):
raise BrainFlowError('invalid shapes', BrainFlowExitCodes.INVALID_ARGUMENTS_ERROR.value)
data_len = accel_x.shape[0]
if period <= 0:
period = data_len
if data_len < period:
raise BrainFlowError('data length is shorter than period', BrainFlowExitCodes.INVALID_ARGUMENTS_ERROR.value)
num_epochs = data_len // period
output = numpy.zeros(num_epochs).astype(numpy.float64)
res = DataHandlerDLL.get_instance().get_activity_index(
accel_x, accel_y, accel_z, data_len, period, output
)
if res != BrainFlowExitCodes.STATUS_OK.value:
raise BrainFlowError('unable to calculate activity index', res)
return output

@classmethod
def get_nearest_power_of_two(cls, value: int) -> int:
"""calc nearest power of two
Expand Down
Loading