API Breaking Changes
MLModelnow returns an array of doubles instead a single value
- Removed and renamed old classifiers and metrics, the idea is to replace them by ONNX models
perform_wavelet_denoisingand wavelet transforms now have more arguments to tune
- In some bindings classes and structures were renamed to make naming uniform across programming languages
- Cpp: methods for FFT now has one more argument to return size
- We’ve added the support for ONNX models directly from BrainFlow code - #102
- Add method
get_custom_band_powers, it works as
get_avg_band_powersbut you can define bands by yourself
BrainFlowModelParamshas two new optional fields
max_array_size, they may be needed for ONNX
- Java: add method overloading for enums in addition to ints. e.g:
BoardIds board_id = BoardIds.SYNTHETIC_BOARD, before it had to be
int board_id = BoardIds.SYNTHETIC_BOARD.get_code()
Check BrainFlow + ONNX tutorial to get more info about use cases and current limitations.
The main feature of this release is the integration of onnxruntime inference framework directly into BrainFlow API. There were two reasons to implement it:
- It allows users to train their own classifiers and share them with others using BrainFlow API. Now you can train your models in Python and export them to other programming languages and even to other people without pushing your code into BrainFlow repo.
- Internally old classifiers did something very similar to ONNX, we trained them in Python and exported weights to C++ using different tricks. For example we called libsvm C++ API directly, implemented KNN in C++ by ourselves, etc. With ONNX it’s unified and it’s the reason why old classifiers are removed now.
Unfortunately, it was impossible to keep ML API backward compatible. ONNX models can return multiple values and usually they do, while in BrainFlow API method
predict returned a single value. So, since we already had to make a breaking change, I’ve decided to push other API breaking changes into the same release.
BoardShim class remains the same, all changes are in
DataFilter and in
Among other changes more likely you need to pay attention to start and stop frequencies in
Wavelet Transforms and Denoising
Until this release wavelet based denoising didn’t work well, mostly because some important parameters were hardcoded and not optimized properly. Now, you can tune all of them and pick between different thresholding options.
Here is the code that you can use as a reference. Arguments listed below were optimized using Synthetic board and real data, but feel free to tune them.
import time import matplotlib import numpy as np import pandas as pd matplotlib.use('Agg') import matplotlib.pyplot as plt from brainflow.board_shim import BoardShim, BrainFlowInputParams, LogLevels, BoardIds from brainflow.data_filter import DataFilter, AggOperations, WaveletTypes, NoiseEstimationLevelTypes, WaveletExtensionTypes, ThresholdTypes, WaveletDenoisingTypes def main(): BoardShim.enable_dev_board_logger() params = BrainFlowInputParams() board_id = BoardIds.SYNTHETIC_BOARD.value board = BoardShim(board_id, params) board.prepare_session() board.start_stream() time.sleep(10) data = board.get_current_board_data(500) board.stop_stream() board.release_session() eeg_channels = BoardShim.get_eeg_channels(board_id) df = pd.DataFrame(np.transpose(data)) plt.figure() df[eeg_channels].plot(subplots=True) plt.savefig('before_processing.png') for channel in enumerate(eeg_channels): DataFilter.perform_wavelet_denoising(data[channel], WaveletTypes.BIOR3_9, 3, WaveletDenoisingTypes.SURESHRINK, ThresholdTypes.HARD, WaveletExtensionTypes.SYMMETRIC, NoiseEstimationLevelTypes.FIRST_LEVEL) df = pd.DataFrame(np.transpose(data)) plt.figure() df[eeg_channels].plot(subplots=True) plt.savefig('after_processing.png') if __name__ == "__main__": main()