A Python package for decomposition of neurophysiological time series signals using a Particle Swarm Optimised Independence Estimator for Blind Source Separation.
pip install swarm-contrastive-decompositionpip install git+https://github.com/AgneGris/swarm-contrastive-decomposition.gitgit clone https://github.com/AgneGris/swarm-contrastive-decomposition
cd swarm-contrastive-decomposition
pip install -e .python -c "import scd; print(f'SCD version: {scd.__version__}')"import scd
# Train with default configuration
dictionary, timestamps = scd.train("data/input/emg.npy")
# Save results
scd.save_results("data/output/emg.pkl", dictionary)import scd
# Use a predefined configuration
dictionary, timestamps = scd.train(
"path/to/your/data.mat",
config_name="surface" # or "default", "intramuscular"
)
scd.save_results("output.pkl", dictionary)import scd
# Override specific parameters
dictionary, timestamps = scd.train(
"data/input/emg.npy",
config_name="surface",
max_iterations=100, # override for quick testing
output_final_source_plot=True
)import scd
# Load configuration
config = scd.load_config("surface")
# Load data
neural_data = scd.load_data("data/input/emg.npy", device=config.device)
# Preprocess
neural_data = scd.preprocess_data(neural_data, config)
# Train model
dictionary, timestamps = scd.train_model(neural_data, config)
# Save results
scd.save_results("output.pkl", dictionary).mat— MATLAB files (specify the variable name withkeyparameter).npy— NumPy arrays
# For .mat files with custom variable name
dictionary, timestamps = scd.train("data.mat", key="emg_data")
# For .npy files
dictionary, timestamps = scd.train("data.npy")Data should have shape (time, channels) or (channels, time) — the loader will automatically transpose if needed.
Configurations are defined in scd/configs.json. Available presets:
| Config Name | Use Case | Sampling Rate | Description |
|---|---|---|---|
default |
General purpose | 10240 Hz | Balanced settings for most EMG data |
surface |
Surface EMG | 10240 Hz | Optimized for surface recordings |
intramuscular |
Intramuscular EMG | 10240 Hz | Higher iterations for fine-wire recordings |
| Parameter | Description | Default |
|---|---|---|
device |
"cuda" for GPU or "cpu" |
"cuda" |
acceptance_silhouette |
Quality threshold for source acceptance | 0.85 |
extension_factor |
Typically 1000 / num_channels. Higher values may improve results |
25 |
low_pass_cutoff |
Low-pass filter cutoff frequency (Hz) | 4400 |
high_pass_cutoff |
High-pass filter cutoff frequency (Hz) | 10 |
sampling_frequency |
Sampling frequency of your signal (Hz) | 10240 |
start_time |
Start time for signal trimming (s). Use 0 for beginning |
0 |
end_time |
End time for signal trimming (s). Use -1 for entire signal |
-1 |
max_iterations |
Maximum decomposition iterations | 200 |
peel_off_window_size_ms |
Window size for spike-triggered average (ms) | 20 |
output_final_source_plot |
Generate plot of final sources | false |
use_coeff_var_fitness |
Use coefficient of variation fitness. true for EMG, false for intracortical |
true |
remove_bad_fr |
Filter sources with firing rates < 2 Hz or > 100 Hz | true |
clamp_percentile |
Percentile for amplitude clamping | 0.999 |
Add your own configuration to scd/configs.json:
{
"my_experiment": {
"device": "cuda",
"acceptance_silhouette": 0.80,
"extension_factor": 30,
"sampling_frequency": 2048,
...
}
}Then use it:
dictionary, timestamps = scd.train("data.mat", config_name="my_experiment")The repository includes test data to verify your installation:
- File:
data/input/emg.npy - Type: Surface EMG
- Sampling rate: 10240 Hz
- Configuration: Use
"surface"config
import scd
# Run with test data
dictionary, timestamps = scd.train(
"data/input/emg.npy",
config_name="surface"
)
print(f"Found {len(dictionary)} motor units")We welcome contributions! Here's how you can contribute:
- Fork the repository
- Create a feature branch (
git checkout -b feature/newfeature) - Commit your changes (
git commit -m 'Add some newfeature') - Push to the branch (
git push origin feature/newfeature) - Open a pull request
This project is licensed under the CC BY-NC 4.0 License.
If you use this code in your research, please cite our paper:
@article{grison2024particle,
author={Grison, Agnese and Clarke, Alexander Kenneth and Muceli, Silvia and Ibáñez, Jaime and Kundu, Aritra and Farina, Dario},
journal={IEEE Transactions on Biomedical Engineering},
title={A Particle Swarm Optimised Independence Estimator for Blind Source Separation of Neurophysiological Time Series},
year={2024},
volume={},
number={},
pages={1-11},
doi={10.1109/TBME.2024.3446806},
keywords={Recording; Time series analysis; Sorting; Vectors; Measurement; Electrodes; Probes; Independent component analysis; particle swarm optimisation; blind source separation; intramuscular electromyography; intracortical recording}
}For questions or inquiries:
Agnese Grison
📧 agnese.grison16@imperial.ac.uk
