Skip to content

add calc_stddev method #403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 21, 2021
Merged
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
11 changes: 11 additions & 0 deletions cpp-package/src/data_filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,3 +417,14 @@ void DataFilter::set_log_file (std::string log_file)
throw BrainFlowException ("failed to set log file", res);
}
}

double DataFilter::calc_stddev (double *data, int start_pos, int end_pos)
{
double output = 0;
int res = ::calc_stddev (data, start_pos, end_pos, &output);
if (res != (int)BrainFlowExitCodes::STATUS_OK)
{
throw BrainFlowException ("failed to calc stddev", res);
}
return output;
}
2 changes: 2 additions & 0 deletions cpp-package/src/inc/data_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,6 @@ class DataFilter
const BrainFlowArray<double, 2> &data, std::string file_name, std::string file_mode);
/// read data from file, data will be transposed to original format
static BrainFlowArray<double, 2> read_file (std::string file_name);
/// calc stddev
static double calc_stddev (double *data, int start_pos, int end_pos);
};
18 changes: 18 additions & 0 deletions csharp-package/brainflow/brainflow/data_filter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,24 @@ public static double[] perform_downsampling (double[] data, int period, int oper
return downsampled_data;
}

/// <summary>
/// calc stddev
/// </summary>
/// <param name="data"></param>
/// <param name="start_pos"></param>
/// /// <param name="end_pos"></param>
/// <returns>stddev</returns>
public static double calc_stddev (double[] data, int start_pos, int end_pos)
{
double[] output = new double[1];
int res = DataHandlerLibrary.calc_stddev (data, start_pos, end_pos, output);
if (res != (int)CustomExitCodes.STATUS_OK)
{
throw new BrainFlowException(res);
}
return output[0];
}

/// <summary>
/// perform wavelet transform
/// </summary>
Expand Down
35 changes: 30 additions & 5 deletions csharp-package/brainflow/brainflow/data_handler_library.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ public static extern int perform_inverse_wavelet_transform (double[] wavelet_coe
public static extern int remove_environmental_noise(double[] data, int len, int sampling_rate, int noise_type);
[DllImport ("DataHandler.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int get_avg_band_powers (double[] data, int rows, int cols, int sampling_rate, int apply_filters, double[] avgs, double[] stddevs);
[DllImport ("DataHandler.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int calc_stddev (double[] data, int start_pos, int end_pos, double[] output);
}

class DataHandlerLibrary32
Expand Down Expand Up @@ -143,8 +145,10 @@ public static extern int perform_inverse_wavelet_transform (double[] wavelet_coe
public static extern int detrend (double[] data, int len, int operation);
[DllImport ("DataHandler32.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int get_avg_band_powers (double[] data, int rows, int cols, int sampling_rate, int apply_filters, double[] avgs, double[] stddevs);
[DllImport("DataHandler32.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int remove_environmental_noise(double[] data, int len, int sampling_rate, int noise_type);
[DllImport ("DataHandler32.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int remove_environmental_noise (double[] data, int len, int sampling_rate, int noise_type);
[DllImport ("DataHandler32.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int calc_stddev (double[] data, int start_pos, int end_pos, double[] output);
}

class DataHandlerLibraryLinux
Expand Down Expand Up @@ -198,8 +202,10 @@ public static extern int perform_inverse_wavelet_transform (double[] wavelet_coe
public static extern int detrend (double[] data, int len, int operation);
[DllImport ("libDataHandler.so", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int get_avg_band_powers (double[] data, int rows, int cols, int sampling_rate, int apply_filters, double[] avgs, double[] stddevs);
[DllImport("libDataHandler.so", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int remove_environmental_noise(double[] data, int len, int sampling_rate, int noise_type);
[DllImport ("libDataHandler.so", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int remove_environmental_noise (double[] data, int len, int sampling_rate, int noise_type);
[DllImport ("libDataHandler.so", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int calc_stddev (double[] data, int start_pos, int end_pos, double[] output);
}

class DataHandlerLibraryMac
Expand Down Expand Up @@ -254,7 +260,9 @@ public static extern int perform_inverse_wavelet_transform (double[] wavelet_coe
[DllImport ("libDataHandler.dylib", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int get_avg_band_powers (double[] data, int rows, int cols, int sampling_rate, int apply_filters, double[] avgs, double[] stddevs);
[DllImport("libDataHandler.dylib", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int remove_environmental_noise(double[] data, int len, int sampling_rate, int noise_type);
public static extern int remove_environmental_noise (double[] data, int len, int sampling_rate, int noise_type);
[DllImport ("libDataHandler.dylib", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int calc_stddev (double[] data, int start_pos, int end_pos, double[] output);
}

class DataHandlerLibrary
Expand Down Expand Up @@ -686,5 +694,22 @@ public static int get_psd_welch (double[] data, int data_len, int nfft, int over

return (int)CustomExitCodes.GENERAL_ERROR;
}

public static int calc_stddev (double[] data, int start_pos, int end_pos, double[] output)
{
switch (PlatformHelper.get_library_environment())
{
case LibraryEnvironment.x64:
return DataHandlerLibrary64.calc_stddev (data, start_pos, end_pos, output);
case LibraryEnvironment.x86:
return DataHandlerLibrary32.calc_stddev (data, start_pos, end_pos, output);
case LibraryEnvironment.Linux:
return DataHandlerLibraryLinux.calc_stddev (data, start_pos, end_pos, output);
case LibraryEnvironment.MacOS:
return DataHandlerLibraryMac.calc_stddev (data, start_pos, end_pos, output);
}

return (int)CustomExitCodes.GENERAL_ERROR;
}
}
}
16 changes: 16 additions & 0 deletions java-package/brainflow/src/main/java/brainflow/DataFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ int get_csp (double[] data, double[] labels, int n_epochs, int n_channels, int n

int set_log_file_data_handler (String log_file);

int calc_stddev (double[] data, int start_pos, int end_pos, double[] output);

int get_num_elements_in_file (String file_name, int[] num_elements);

int get_nearest_power_of_two (int value, int[] output);
Expand Down Expand Up @@ -161,6 +163,20 @@ public static void set_log_file (String log_file) throws BrainFlowError
}
}

/**
* calc stddev
*/
public static double calc_stddev (double[] data, int start_pos, int end_pos) throws BrainFlowError
{
double[] output = new double[1];
int ec = instance.calc_stddev (data, start_pos, end_pos, output);
if (ec != ExitCode.STATUS_OK.get_code ())
{
throw new BrainFlowError ("Error in set_log_file", ec);
}
return output[0];
}

/**
* set log level
*/
Expand Down
8 changes: 7 additions & 1 deletion julia-package/brainflow/src/data_filter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,20 @@ end
return
end


@brainflow_rethrow function get_nearest_power_of_two(value::Integer)
power_of_two = Vector{Cint}(undef, 1)
ccall((:get_nearest_power_of_two, DATA_HANDLER_INTERFACE), Cint, (Cint, Ptr{Cint}),
Int32(value), power_of_two)
return power_of_two[1]
end

@brainflow_rethrow function calc_stddev(data)
output = Vector{Float64}(undef, 1)
ccall((:calc_stddev, DATA_HANDLER_INTERFACE), Cint, (Ptr{Float64}, Cint, Cint, Ptr{Float64}),
data, 0, length(data), output)
return output[1]
end

@brainflow_rethrow function get_num_elements_in_file(file_name::String)
num_elements = Vector{Cint}(undef, 1)
ccall((:get_num_elements_in_file, DATA_HANDLER_INTERFACE), Cint, (Ptr{UInt8}, Ptr{Cint}),
Expand Down
27 changes: 27 additions & 0 deletions julia-package/brainflow/test/release_all.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using BrainFlow

# enable all possible logs from all three libs
BrainFlow.enable_dev_logger(BrainFlow.BOARD_CONTROLLER)
BrainFlow.enable_dev_logger(BrainFlow.DATA_HANDLER)
BrainFlow.enable_dev_logger(BrainFlow.ML_MODULE)

params1 = BrainFlowInputParams()
params1.other_info = "board1"
board_shim1 = BrainFlow.BoardShim(BrainFlow.SYNTHETIC_BOARD, params1)
params2 = BrainFlowInputParams()
params2.other_info = "board2"
board_shim2 = BrainFlow.BoardShim(BrainFlow.SYNTHETIC_BOARD, params2)

BrainFlow.prepare_session(board_shim1)
BrainFlow.prepare_session(board_shim2)
BrainFlow.start_stream(board_shim1)
sleep(2)
data = BrainFlow.get_current_board_data(10, board_shim1)
println(BrainFlow.calc_stddev(data[2, :]))

BrainFlow.release_all_sessions()

# calc concentration
model_params = BrainFlowModelParams(metric = "concentration", classifier = "KNN")
BrainFlow.prepare(model_params)
BrainFlow.release_all()
3 changes: 2 additions & 1 deletion julia-package/brainflow/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ include("csp.jl")
include("serialization.jl")
include("transforms.jl")
include("eeg_metrics.jl")
include("markers.jl")
include("markers.jl")
include("release_all.jl")
17 changes: 6 additions & 11 deletions matlab-package/brainflow/DataFilter.m
Original file line number Diff line number Diff line change
Expand Up @@ -222,20 +222,15 @@ function disable_data_logger()
window_data = temp_output.Value;
end

function fft_data = perform_fft(data, window)
% perform fft
task_name = 'perform_fft';
n = size(data, 2);
if(bitand(n, n - 1) ~= 0)
error('For FFT shape must be power of 2!');
end
function stddev = calc_stddev(data)
% calc stddev
task_name = 'calc_stddev';
temp_input = libpointer('doublePtr', data);
output = libpointer('doublePtr', 0);
lib_name = DataFilter.load_lib();
temp_re = libpointer('doublePtr', zeros(1, int32(n / 2 + 1)));
temp_im = libpointer('doublePtr', zeros(1, int32(n / 2 + 1)));
exit_code = calllib(lib_name, task_name, temp_input, n, window, temp_re, temp_im);
exit_code = calllib(lib_name, task_name, temp_input, 0, size(data, 2), output);
DataFilter.check_ec(exit_code, task_name);
fft_data = complex(temp_re.Value, temp_im.Value);
stddev = output.Value;
end

function data = perform_ifft(fft_data)
Expand Down
25 changes: 25 additions & 0 deletions python-package/brainflow/data_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,15 @@ def __init__(self):
ctypes.c_int
]

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

self.set_log_level_data_handler = self.lib.set_log_level_data_handler
self.set_log_level_data_handler.restype = ctypes.c_int
self.set_log_level_data_handler.argtypes = [
Expand Down Expand Up @@ -537,6 +546,22 @@ def perform_rolling_filter(cls, data: NDArray[Float64], period: int, operation:
if res != BrainflowExitCodes.STATUS_OK.value:
raise BrainFlowError('unable to smooth data', res)

@classmethod
def calc_stddev(cls, data: NDArray[Float64]):
"""calc stddev

:param data: input array
:type data: NDArray[Float64]
:return: stddev
:rtype: float
"""
check_memory_layout_row_major(data, 1)
output = numpy.zeros(1).astype(numpy.float64)
res = DataHandlerDLL.get_instance().calc_stddev(data, 0, data.shape[0], output)
if res != BrainflowExitCodes.STATUS_OK.value:
raise BrainFlowError('unable to calc stddev', res)
return output[0]

@classmethod
def perform_downsampling(cls, data: NDArray[Float64], period: int, operation: int) -> NDArray[Float64]:
"""perform data downsampling, it doesnt apply lowpass filter for you, it just aggregates several data points
Expand Down
19 changes: 19 additions & 0 deletions rust-package/brainflow/src/data_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,25 @@ pub fn perform_rolling_filter(
Ok(())
}

/// Calc stddev.
pub fn calc_stddev(
data: &mut [f64],
start_pos: usize,
end_pos: usize
) -> Result<f64> {
let mut output = 0.0 as f64;
let res = unsafe {
data_handler::calc_stddev(
data.as_mut_ptr() as *mut c_double,
start_pos as c_int,
end_pos as c_int,
&mut output,
)
};
check_brainflow_exit_code(res)?;
Ok(output as f64)
}

/// Perform data downsampling, it doesnt apply lowpass filter for you, it just aggregates several data points.
pub fn perform_downsampling(
data: &mut [f64],
Expand Down
8 changes: 8 additions & 0 deletions rust-package/brainflow/src/ffi/data_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ extern "C" {
detrend_operation: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn calc_stddev(
data: *mut f64,
start_pos: ::std::os::raw::c_int,
end_pos: ::std::os::raw::c_int,
output: *mut f64,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn get_psd_welch(
data: *mut f64,
Expand Down
22 changes: 22 additions & 0 deletions src/data_handler/data_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,28 @@ int read_file (double *data, int *num_rows, int *num_cols, const char *file_name
return (int)BrainFlowExitCodes::STATUS_OK;
}

int calc_stddev (double *data, int start_pos, int end_pos, double *output)
{
if ((data == NULL) || (output == NULL) || (end_pos - start_pos < 2))
{
return (int)BrainFlowExitCodes::INVALID_ARGUMENTS_ERROR;
}
double mean = 0;
for (int i = start_pos; i < end_pos; i++)
{
mean += data[i];
}
mean /= (end_pos - start_pos);
double stddev = 0;
for (int i = start_pos; i < end_pos; i++)
{
stddev += (data[i] - mean) * (data[i] - mean);
}
stddev /= (end_pos - start_pos);
*output = sqrt (stddev);
return (int)BrainFlowExitCodes::STATUS_OK;
}

int get_num_elements_in_file (const char *file_name, int *num_elements)
{
FILE *fp;
Expand Down
2 changes: 2 additions & 0 deletions src/data_handler/inc/data_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ extern "C"
int window_function, double *output_ampl, double *output_freq);
SHARED_EXPORT int CALLING_CONVENTION detrend (
double *data, int data_len, int detrend_operation);
SHARED_EXPORT int CALLING_CONVENTION calc_stddev (
double *data, int start_pos, int end_pos, double *output);
SHARED_EXPORT int CALLING_CONVENTION get_psd_welch (double *data, int data_len, int nfft,
int overlap, int sampling_rate, int window_function, double *output_ampl,
double *output_freq);
Expand Down
1 change: 1 addition & 0 deletions tests/python/brainflow_get_data_twice.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def main():
time.sleep(10)
board.stop_stream()
data = board.get_board_data()
print(DataFilter.calc_stddev(data[2]))
data = board.get_board_data()
print(data)
data = board.get_current_board_data(10)
Expand Down