spikertools 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- spikertools-0.1.0/PKG-INFO +232 -0
- spikertools-0.1.0/README.md +197 -0
- spikertools-0.1.0/setup.cfg +4 -0
- spikertools-0.1.0/setup.py +39 -0
- spikertools-0.1.0/spikertools/__init__.py +7 -0
- spikertools-0.1.0/spikertools/core.py +149 -0
- spikertools-0.1.0/spikertools/models.py +638 -0
- spikertools-0.1.0/spikertools/plots.py +646 -0
- spikertools-0.1.0/spikertools.egg-info/PKG-INFO +232 -0
- spikertools-0.1.0/spikertools.egg-info/SOURCES.txt +13 -0
- spikertools-0.1.0/spikertools.egg-info/dependency_links.txt +1 -0
- spikertools-0.1.0/spikertools.egg-info/requires.txt +4 -0
- spikertools-0.1.0/spikertools.egg-info/top_level.txt +1 -0
- spikertools-0.1.0/tests/test_core.py +192 -0
- spikertools-0.1.0/tests/test_plotting.py +154 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spikertools
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Python library for neuroscience data analysis of Backyard Brains SpikeRecorder files - forked from Backyard Brains github
|
|
5
|
+
Home-page: https://github.com/LeonardoFerrisi/SpikerTools
|
|
6
|
+
Author: Greg Gage
|
|
7
|
+
Author-email: gagegreg@backyardbrains.com
|
|
8
|
+
Maintainer: Leonardo Ferrisi
|
|
9
|
+
Maintainer-email: Leonardo.Ferrisi@utah.edu
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Requires-Dist: numpy
|
|
21
|
+
Requires-Dist: scipy
|
|
22
|
+
Requires-Dist: matplotlib
|
|
23
|
+
Requires-Dist: seaborn
|
|
24
|
+
Dynamic: author
|
|
25
|
+
Dynamic: author-email
|
|
26
|
+
Dynamic: classifier
|
|
27
|
+
Dynamic: description
|
|
28
|
+
Dynamic: description-content-type
|
|
29
|
+
Dynamic: home-page
|
|
30
|
+
Dynamic: maintainer
|
|
31
|
+
Dynamic: maintainer-email
|
|
32
|
+
Dynamic: requires-dist
|
|
33
|
+
Dynamic: requires-python
|
|
34
|
+
Dynamic: summary
|
|
35
|
+
|
|
36
|
+
# SpikerTools
|
|
37
|
+
|
|
38
|
+
**SpikerTools** is a Python library designed to help students analyze SpikeRecorder files from SpikerBoxes. It provides easy-to-use functions for loading, processing, and visualizing neural and EEG data, enabling students to explore neuroscience concepts through hands-on data analysis.
|
|
39
|
+
|
|
40
|
+
## Table of Contents
|
|
41
|
+
|
|
42
|
+
- [Features](#features)
|
|
43
|
+
- [Installation](#installation)
|
|
44
|
+
- [Getting Started](#getting-started)
|
|
45
|
+
- [Usage Examples](#usage-examples)
|
|
46
|
+
- [Loading Data](#loading-data)
|
|
47
|
+
- [Plotting Session Overview](#plotting-session-overview)
|
|
48
|
+
- [Event-Related Potential (ERP)](#event-related-potential-erp)
|
|
49
|
+
- [Peri-Event Time Histogram (PETH)](#peri-event-time-histogram-peth)
|
|
50
|
+
- [Spectrogram Analysis](#spectrogram-analysis)
|
|
51
|
+
- [Average Power Spectrum](#average-power-spectrum)
|
|
52
|
+
- [For Teachers](#for-teachers)
|
|
53
|
+
- [Sample Lesson Plan](#sample-lesson-plan)
|
|
54
|
+
- [Contributing](#contributing)
|
|
55
|
+
- [License](#license)
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
- Load neural and EEG data from WAV files.
|
|
60
|
+
- Handle events and neuronal spikes with timestamped annotations.
|
|
61
|
+
- Filter and normalize signal data.
|
|
62
|
+
- Compute statistical measures like inter-spike intervals and firing rates.
|
|
63
|
+
- Visualize data with various plots:
|
|
64
|
+
- Session overview with event markers.
|
|
65
|
+
- Event-Related Potentials (ERPs).
|
|
66
|
+
- Peri-Event Time Histograms (PETH) with raster plots.
|
|
67
|
+
- Spectrograms with event overlays.
|
|
68
|
+
- Average power spectra for frequency analysis.
|
|
69
|
+
- Histograms of inter-event and inter-spike intervals.
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
You can install SpikerTools using pip:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install spikertools
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Note: If SpikerTools is not yet available on PyPI, you can install it directly from the source code:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git clone https://github.com/BackyardBrains/SpikerTools.git
|
|
83
|
+
pip install -e ./SpikerTools
|
|
84
|
+
```
|
|
85
|
+
### If you are in a jupyter notebook
|
|
86
|
+
```bash
|
|
87
|
+
!pip install ./Spikertools
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Getting Started
|
|
91
|
+
|
|
92
|
+
### Prerequisites
|
|
93
|
+
|
|
94
|
+
- Python 3.6 or higher
|
|
95
|
+
- Required Python packages:
|
|
96
|
+
- numpy
|
|
97
|
+
- scipy
|
|
98
|
+
- matplotlib
|
|
99
|
+
- seaborn
|
|
100
|
+
|
|
101
|
+
Install the required packages using:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install numpy scipy matplotlib seaborn
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Usage Examples
|
|
108
|
+
|
|
109
|
+
### Loading Data
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from spikertools import Session
|
|
113
|
+
|
|
114
|
+
# Load your data file (WAV file and corresponding events file)
|
|
115
|
+
wav_file_path = 'data/neurons/rate_coding/BYB_Recording_2022-01-13_13.18.29.wav'
|
|
116
|
+
|
|
117
|
+
# Initialize the Session
|
|
118
|
+
session = Session(wav_file_path)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Plotting Channels from Session
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
# Plot the session overview with event markers
|
|
125
|
+
session.plots.plot_channels()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Event-Related Potential (ERP)
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
|
|
132
|
+
p300_wav_file = 'data/eeg/p300/BYB_Recording_2019-06-11_13.23.58.wav'
|
|
133
|
+
s = Session(p300_wav_file)
|
|
134
|
+
|
|
135
|
+
# Define events for P300 (default is '1' and '2') and add colors
|
|
136
|
+
s.events[0].name = 'standard'
|
|
137
|
+
s.events[0].color = 'blue'
|
|
138
|
+
|
|
139
|
+
s.events[1].name = 'oddball'
|
|
140
|
+
s.events[1].color = 'red'
|
|
141
|
+
|
|
142
|
+
# Assign location as name to the P300 channel (Optional)
|
|
143
|
+
s.channels[0].name = 'P4'
|
|
144
|
+
|
|
145
|
+
# Optional: Filter the P300 channel to reduce high frequency noise
|
|
146
|
+
s.channels[0].filter(ftype='lp', cutoff=10, order=3)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Peri-Event Time Histogram (PETH)
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
# Plot PETH with raster for a neuron aligned to an event
|
|
153
|
+
session.plots.plot_peth(
|
|
154
|
+
neuron=s.neurons[0], # Neuron to plot (defaults to first)
|
|
155
|
+
events=s.events, # List of Event objects (defaults to all)
|
|
156
|
+
epoch_window=(-0.5, 1.0), # 500ms before to 1000ms after event
|
|
157
|
+
bin_size=0.04, # 40ms bins
|
|
158
|
+
title="Peri-Event Time Histogram (PETH) with Raster Plots for Touch Pressure Events", # Add a custom title
|
|
159
|
+
save_path=None, # Save the plot to a file
|
|
160
|
+
show=True
|
|
161
|
+
)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Spectrogram Analysis
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
# Plot spectrogram of the EEG data with event markers
|
|
168
|
+
session.plots.plot_spectrogram(
|
|
169
|
+
channel=session.channels[0],
|
|
170
|
+
freq_range=(0, 50),
|
|
171
|
+
events=session.events
|
|
172
|
+
)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Average Power Spectrum
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
# Plot average power spectra during 'Open' and 'Close' events
|
|
179
|
+
session.plots.plot_average_power(
|
|
180
|
+
events=session.events,
|
|
181
|
+
freq_range=(0, 30),
|
|
182
|
+
epoch_window=(0, 5),
|
|
183
|
+
channel=session.channels[0]
|
|
184
|
+
)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## For Teachers
|
|
188
|
+
|
|
189
|
+
SpikerTools is designed to be an educational tool that integrates seamlessly into classroom activities. Here's how you can incorporate it into your teaching:
|
|
190
|
+
|
|
191
|
+
- **Hands-On Data Analysis**: Provide students with real neural or EEG data recordings and guide them through loading and analyzing the data using SpikerTools.
|
|
192
|
+
- **Visualization of Neural Activity**: Use the plotting functions to help students visualize neural spikes, event-related potentials, and frequency content of EEG signals.
|
|
193
|
+
- **Concept Reinforcement**: Reinforce concepts like neuronal firing rates, inter-spike intervals, and the effects of stimuli on neural activity.
|
|
194
|
+
- **Customizable Plots**: Encourage students to explore different parameters and customize plots to deepen their understanding.
|
|
195
|
+
- **Interdisciplinary Learning**: Integrate programming skills with neuroscience, promoting interdisciplinary education.
|
|
196
|
+
|
|
197
|
+
### Sample Lesson Plan
|
|
198
|
+
|
|
199
|
+
1. **Introduction to Neural Signals:**
|
|
200
|
+
- Discuss the basics of neural spikes and EEG signals.
|
|
201
|
+
- Explain the significance of events and stimuli in neural recordings.
|
|
202
|
+
|
|
203
|
+
2. **Data Loading and Preprocessing:**
|
|
204
|
+
- Show students how to load data into SpikerTools.
|
|
205
|
+
- Demonstrate filtering and normalization techniques.
|
|
206
|
+
|
|
207
|
+
3. **Data Visualization:**
|
|
208
|
+
- Guide students through plotting session overviews and ERPs.
|
|
209
|
+
- Analyze spectrograms to understand frequency components.
|
|
210
|
+
|
|
211
|
+
4. **Data Analysis:**
|
|
212
|
+
- Calculate firing rates and inter-spike intervals.
|
|
213
|
+
- Compare neural responses to different stimuli.
|
|
214
|
+
|
|
215
|
+
5. **Discussion and Interpretation:**
|
|
216
|
+
- Interpret the results and discuss their implications.
|
|
217
|
+
- Encourage students to ask questions and explore further.
|
|
218
|
+
|
|
219
|
+
## Contributing
|
|
220
|
+
|
|
221
|
+
We welcome contributions to enhance SpikerTools. If you have ideas for new features, improvements, or bug fixes, please:
|
|
222
|
+
|
|
223
|
+
1. Fork the repository.
|
|
224
|
+
2. Create a new branch for your feature or fix.
|
|
225
|
+
3. Commit your changes with clear messages.
|
|
226
|
+
4. Submit a pull request describing your changes.
|
|
227
|
+
|
|
228
|
+
Please ensure that your code follows best practices and includes appropriate tests.
|
|
229
|
+
|
|
230
|
+
## License
|
|
231
|
+
|
|
232
|
+
SpikerTools is released under the **MIT License**.
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# SpikerTools
|
|
2
|
+
|
|
3
|
+
**SpikerTools** is a Python library designed to help students analyze SpikeRecorder files from SpikerBoxes. It provides easy-to-use functions for loading, processing, and visualizing neural and EEG data, enabling students to explore neuroscience concepts through hands-on data analysis.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Features](#features)
|
|
8
|
+
- [Installation](#installation)
|
|
9
|
+
- [Getting Started](#getting-started)
|
|
10
|
+
- [Usage Examples](#usage-examples)
|
|
11
|
+
- [Loading Data](#loading-data)
|
|
12
|
+
- [Plotting Session Overview](#plotting-session-overview)
|
|
13
|
+
- [Event-Related Potential (ERP)](#event-related-potential-erp)
|
|
14
|
+
- [Peri-Event Time Histogram (PETH)](#peri-event-time-histogram-peth)
|
|
15
|
+
- [Spectrogram Analysis](#spectrogram-analysis)
|
|
16
|
+
- [Average Power Spectrum](#average-power-spectrum)
|
|
17
|
+
- [For Teachers](#for-teachers)
|
|
18
|
+
- [Sample Lesson Plan](#sample-lesson-plan)
|
|
19
|
+
- [Contributing](#contributing)
|
|
20
|
+
- [License](#license)
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
- Load neural and EEG data from WAV files.
|
|
25
|
+
- Handle events and neuronal spikes with timestamped annotations.
|
|
26
|
+
- Filter and normalize signal data.
|
|
27
|
+
- Compute statistical measures like inter-spike intervals and firing rates.
|
|
28
|
+
- Visualize data with various plots:
|
|
29
|
+
- Session overview with event markers.
|
|
30
|
+
- Event-Related Potentials (ERPs).
|
|
31
|
+
- Peri-Event Time Histograms (PETH) with raster plots.
|
|
32
|
+
- Spectrograms with event overlays.
|
|
33
|
+
- Average power spectra for frequency analysis.
|
|
34
|
+
- Histograms of inter-event and inter-spike intervals.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
You can install SpikerTools using pip:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install spikertools
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Note: If SpikerTools is not yet available on PyPI, you can install it directly from the source code:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
git clone https://github.com/BackyardBrains/SpikerTools.git
|
|
48
|
+
pip install -e ./SpikerTools
|
|
49
|
+
```
|
|
50
|
+
### If you are in a jupyter notebook
|
|
51
|
+
```bash
|
|
52
|
+
!pip install ./Spikertools
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Getting Started
|
|
56
|
+
|
|
57
|
+
### Prerequisites
|
|
58
|
+
|
|
59
|
+
- Python 3.6 or higher
|
|
60
|
+
- Required Python packages:
|
|
61
|
+
- numpy
|
|
62
|
+
- scipy
|
|
63
|
+
- matplotlib
|
|
64
|
+
- seaborn
|
|
65
|
+
|
|
66
|
+
Install the required packages using:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install numpy scipy matplotlib seaborn
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Usage Examples
|
|
73
|
+
|
|
74
|
+
### Loading Data
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from spikertools import Session
|
|
78
|
+
|
|
79
|
+
# Load your data file (WAV file and corresponding events file)
|
|
80
|
+
wav_file_path = 'data/neurons/rate_coding/BYB_Recording_2022-01-13_13.18.29.wav'
|
|
81
|
+
|
|
82
|
+
# Initialize the Session
|
|
83
|
+
session = Session(wav_file_path)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Plotting Channels from Session
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
# Plot the session overview with event markers
|
|
90
|
+
session.plots.plot_channels()
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Event-Related Potential (ERP)
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
|
|
97
|
+
p300_wav_file = 'data/eeg/p300/BYB_Recording_2019-06-11_13.23.58.wav'
|
|
98
|
+
s = Session(p300_wav_file)
|
|
99
|
+
|
|
100
|
+
# Define events for P300 (default is '1' and '2') and add colors
|
|
101
|
+
s.events[0].name = 'standard'
|
|
102
|
+
s.events[0].color = 'blue'
|
|
103
|
+
|
|
104
|
+
s.events[1].name = 'oddball'
|
|
105
|
+
s.events[1].color = 'red'
|
|
106
|
+
|
|
107
|
+
# Assign location as name to the P300 channel (Optional)
|
|
108
|
+
s.channels[0].name = 'P4'
|
|
109
|
+
|
|
110
|
+
# Optional: Filter the P300 channel to reduce high frequency noise
|
|
111
|
+
s.channels[0].filter(ftype='lp', cutoff=10, order=3)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Peri-Event Time Histogram (PETH)
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
# Plot PETH with raster for a neuron aligned to an event
|
|
118
|
+
session.plots.plot_peth(
|
|
119
|
+
neuron=s.neurons[0], # Neuron to plot (defaults to first)
|
|
120
|
+
events=s.events, # List of Event objects (defaults to all)
|
|
121
|
+
epoch_window=(-0.5, 1.0), # 500ms before to 1000ms after event
|
|
122
|
+
bin_size=0.04, # 40ms bins
|
|
123
|
+
title="Peri-Event Time Histogram (PETH) with Raster Plots for Touch Pressure Events", # Add a custom title
|
|
124
|
+
save_path=None, # Save the plot to a file
|
|
125
|
+
show=True
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Spectrogram Analysis
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
# Plot spectrogram of the EEG data with event markers
|
|
133
|
+
session.plots.plot_spectrogram(
|
|
134
|
+
channel=session.channels[0],
|
|
135
|
+
freq_range=(0, 50),
|
|
136
|
+
events=session.events
|
|
137
|
+
)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Average Power Spectrum
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
# Plot average power spectra during 'Open' and 'Close' events
|
|
144
|
+
session.plots.plot_average_power(
|
|
145
|
+
events=session.events,
|
|
146
|
+
freq_range=(0, 30),
|
|
147
|
+
epoch_window=(0, 5),
|
|
148
|
+
channel=session.channels[0]
|
|
149
|
+
)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## For Teachers
|
|
153
|
+
|
|
154
|
+
SpikerTools is designed to be an educational tool that integrates seamlessly into classroom activities. Here's how you can incorporate it into your teaching:
|
|
155
|
+
|
|
156
|
+
- **Hands-On Data Analysis**: Provide students with real neural or EEG data recordings and guide them through loading and analyzing the data using SpikerTools.
|
|
157
|
+
- **Visualization of Neural Activity**: Use the plotting functions to help students visualize neural spikes, event-related potentials, and frequency content of EEG signals.
|
|
158
|
+
- **Concept Reinforcement**: Reinforce concepts like neuronal firing rates, inter-spike intervals, and the effects of stimuli on neural activity.
|
|
159
|
+
- **Customizable Plots**: Encourage students to explore different parameters and customize plots to deepen their understanding.
|
|
160
|
+
- **Interdisciplinary Learning**: Integrate programming skills with neuroscience, promoting interdisciplinary education.
|
|
161
|
+
|
|
162
|
+
### Sample Lesson Plan
|
|
163
|
+
|
|
164
|
+
1. **Introduction to Neural Signals:**
|
|
165
|
+
- Discuss the basics of neural spikes and EEG signals.
|
|
166
|
+
- Explain the significance of events and stimuli in neural recordings.
|
|
167
|
+
|
|
168
|
+
2. **Data Loading and Preprocessing:**
|
|
169
|
+
- Show students how to load data into SpikerTools.
|
|
170
|
+
- Demonstrate filtering and normalization techniques.
|
|
171
|
+
|
|
172
|
+
3. **Data Visualization:**
|
|
173
|
+
- Guide students through plotting session overviews and ERPs.
|
|
174
|
+
- Analyze spectrograms to understand frequency components.
|
|
175
|
+
|
|
176
|
+
4. **Data Analysis:**
|
|
177
|
+
- Calculate firing rates and inter-spike intervals.
|
|
178
|
+
- Compare neural responses to different stimuli.
|
|
179
|
+
|
|
180
|
+
5. **Discussion and Interpretation:**
|
|
181
|
+
- Interpret the results and discuss their implications.
|
|
182
|
+
- Encourage students to ask questions and explore further.
|
|
183
|
+
|
|
184
|
+
## Contributing
|
|
185
|
+
|
|
186
|
+
We welcome contributions to enhance SpikerTools. If you have ideas for new features, improvements, or bug fixes, please:
|
|
187
|
+
|
|
188
|
+
1. Fork the repository.
|
|
189
|
+
2. Create a new branch for your feature or fix.
|
|
190
|
+
3. Commit your changes with clear messages.
|
|
191
|
+
4. Submit a pull request describing your changes.
|
|
192
|
+
|
|
193
|
+
Please ensure that your code follows best practices and includes appropriate tests.
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
SpikerTools is released under the **MIT License**.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# setup.py
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from setuptools import setup, find_packages
|
|
6
|
+
|
|
7
|
+
long_description = Path(__file__).parent.joinpath("README.md").read_text(encoding="utf-8")
|
|
8
|
+
|
|
9
|
+
setup(
|
|
10
|
+
name='spikertools',
|
|
11
|
+
version='0.1.0',
|
|
12
|
+
packages=find_packages(),
|
|
13
|
+
install_requires=[
|
|
14
|
+
'numpy',
|
|
15
|
+
'scipy',
|
|
16
|
+
'matplotlib',
|
|
17
|
+
'seaborn',
|
|
18
|
+
],
|
|
19
|
+
python_requires='>=3.9',
|
|
20
|
+
include_package_data=True,
|
|
21
|
+
description='A Python library for neuroscience data analysis of Backyard Brains SpikeRecorder files - forked from Backyard Brains github',
|
|
22
|
+
long_description=long_description,
|
|
23
|
+
long_description_content_type='text/markdown',
|
|
24
|
+
author='Greg Gage',
|
|
25
|
+
author_email='gagegreg@backyardbrains.com',
|
|
26
|
+
maintainer='Leonardo Ferrisi',
|
|
27
|
+
maintainer_email='Leonardo.Ferrisi@utah.edu',
|
|
28
|
+
url='https://github.com/LeonardoFerrisi/SpikerTools',
|
|
29
|
+
classifiers=[
|
|
30
|
+
'Programming Language :: Python :: 3',
|
|
31
|
+
'Programming Language :: Python :: 3.9',
|
|
32
|
+
'Programming Language :: Python :: 3.10',
|
|
33
|
+
'Programming Language :: Python :: 3.11',
|
|
34
|
+
'Programming Language :: Python :: 3.12',
|
|
35
|
+
'Operating System :: OS Independent',
|
|
36
|
+
'Intended Audience :: Science/Research',
|
|
37
|
+
'Topic :: Scientific/Engineering',
|
|
38
|
+
],
|
|
39
|
+
)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# spikertools/core.py
|
|
2
|
+
|
|
3
|
+
from spikertools.models import Event, Neuron, Channel, Session, Events, Channels
|
|
4
|
+
from spikertools.plots import Plots
|
|
5
|
+
import numpy as np
|
|
6
|
+
from scipy.io import wavfile
|
|
7
|
+
import os
|
|
8
|
+
import re
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
class Session:
|
|
12
|
+
def __init__(self, wav_file_path, events_file_path=None):
|
|
13
|
+
self.wav_file = wav_file_path
|
|
14
|
+
self.sample_rate, self.data = wavfile.read(wav_file_path)
|
|
15
|
+
print(f"Loaded WAV file: {wav_file_path}")
|
|
16
|
+
print(f"Sample rate: {self.sample_rate} Hz")
|
|
17
|
+
print(f"Data length: {len(self.data)} samples")
|
|
18
|
+
|
|
19
|
+
if events_file_path is None:
|
|
20
|
+
# Infer events file path
|
|
21
|
+
events_file = wav_file_path.replace('.wav', '-events.txt')
|
|
22
|
+
else:
|
|
23
|
+
events_file = events_file_path
|
|
24
|
+
|
|
25
|
+
print(f"Looking for events file: {events_file}")
|
|
26
|
+
|
|
27
|
+
# Initialize events and neurons before loading
|
|
28
|
+
self.events = Events([]) # Changed from list to Events
|
|
29
|
+
self.neurons = []
|
|
30
|
+
|
|
31
|
+
# Initialize the Plots class
|
|
32
|
+
self.plots = Plots(self)
|
|
33
|
+
|
|
34
|
+
if os.path.exists(events_file):
|
|
35
|
+
self._load_events(events_file)
|
|
36
|
+
print(f"Loaded {len(self.events)} events and {len(self.neurons)} neurons.")
|
|
37
|
+
else:
|
|
38
|
+
print("No events file found.")
|
|
39
|
+
|
|
40
|
+
# Initialize other attributes
|
|
41
|
+
self.channels = self._initialize_channels()
|
|
42
|
+
self.datetime = self._extract_datetime()
|
|
43
|
+
|
|
44
|
+
def _load_events(self, events_file):
|
|
45
|
+
with open(events_file, 'r') as f:
|
|
46
|
+
for line in f:
|
|
47
|
+
line = line.strip()
|
|
48
|
+
if not line or line.startswith('#'):
|
|
49
|
+
continue
|
|
50
|
+
parts = line.split(',')
|
|
51
|
+
if len(parts) != 2:
|
|
52
|
+
continue
|
|
53
|
+
name, timestamp = parts
|
|
54
|
+
name = name.strip()
|
|
55
|
+
try:
|
|
56
|
+
timestamp = float(timestamp.strip())
|
|
57
|
+
except ValueError:
|
|
58
|
+
print(f"Invalid timestamp: {timestamp} in line: {line}")
|
|
59
|
+
continue
|
|
60
|
+
self._add_event(name, timestamp)
|
|
61
|
+
|
|
62
|
+
def _add_event(self, name, timestamp):
|
|
63
|
+
# Normalize the event name by stripping leading/trailing spaces
|
|
64
|
+
name = name.strip()
|
|
65
|
+
|
|
66
|
+
# Assign colors to events and neurons
|
|
67
|
+
color = 'k' # Default color is black
|
|
68
|
+
color_map = {
|
|
69
|
+
'1': 'r', '2': 'g', '3': 'b', '4': 'c', '5': 'm',
|
|
70
|
+
'Open': 'orange', 'Close': 'purple',
|
|
71
|
+
}
|
|
72
|
+
if name in color_map:
|
|
73
|
+
color = color_map[name]
|
|
74
|
+
|
|
75
|
+
# Check if event already exists
|
|
76
|
+
if self.events.has_event(name):
|
|
77
|
+
self.events[name].timestamps.append(timestamp)
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
# Handle threshold events for neurons
|
|
81
|
+
if 'thresh' in name.lower():
|
|
82
|
+
# Use regex to parse threshold events
|
|
83
|
+
match = re.match(r'_(neuron\d+)thresh(\w+)-(\d+)', name, re.IGNORECASE)
|
|
84
|
+
if match:
|
|
85
|
+
neuron_id, thresh_type_partial, thresh_value_str = match.groups()
|
|
86
|
+
thresh_value = -int(thresh_value_str) # Assuming thresholds are negative
|
|
87
|
+
|
|
88
|
+
# Find the neuron that corresponds to this threshold
|
|
89
|
+
target_neuron = None
|
|
90
|
+
for neuron in self.neurons:
|
|
91
|
+
if neuron_id in neuron.name:
|
|
92
|
+
target_neuron = neuron
|
|
93
|
+
break
|
|
94
|
+
|
|
95
|
+
if target_neuron:
|
|
96
|
+
if 'hig' in thresh_type_partial.lower():
|
|
97
|
+
target_neuron.thresh_high = thresh_value
|
|
98
|
+
#print(f"Set high threshold for {target_neuron.name} to {thresh_value}")
|
|
99
|
+
elif 'low' in thresh_type_partial.lower():
|
|
100
|
+
target_neuron.thresh_low = thresh_value
|
|
101
|
+
#print(f"Set low threshold for {target_neuron.name} to {thresh_value}")
|
|
102
|
+
else:
|
|
103
|
+
print(f"Unknown threshold type in event name: {name}")
|
|
104
|
+
else:
|
|
105
|
+
print(f"Neuron '{neuron_id}' not found for threshold event: {name}")
|
|
106
|
+
return # Threshold event processed; exit the method
|
|
107
|
+
|
|
108
|
+
# Check if neuron already exists for spike events
|
|
109
|
+
if name.startswith('_'):
|
|
110
|
+
for neuron in self.neurons:
|
|
111
|
+
if neuron.name == name:
|
|
112
|
+
neuron.timestamps.append(timestamp)
|
|
113
|
+
return
|
|
114
|
+
|
|
115
|
+
# If not, create a new neuron
|
|
116
|
+
neuron = Neuron(name, timestamps=[timestamp], color=color)
|
|
117
|
+
self.neurons.append(neuron)
|
|
118
|
+
#print(f"Added neuron: '{name}' with initial spike at timestamp: {timestamp}")
|
|
119
|
+
else:
|
|
120
|
+
# If not a neuron, treat as a regular event
|
|
121
|
+
event = Event(name, timestamps=[timestamp], color=color)
|
|
122
|
+
self.events.append(event)
|
|
123
|
+
#print(f"Added event: '{name}' at timestamp: {timestamp}")
|
|
124
|
+
|
|
125
|
+
def _initialize_channels(self):
|
|
126
|
+
# Initialize channels based on the data
|
|
127
|
+
channels = Channels([]) # Initialize empty Channels container (this uses models.Channels)
|
|
128
|
+
if self.data.ndim == 1:
|
|
129
|
+
channel = Channel(self.data, sample_rate=self.sample_rate, number=0) # This will now use models.Channel
|
|
130
|
+
channels.append(channel)
|
|
131
|
+
else:
|
|
132
|
+
for i in range(self.data.shape[1]):
|
|
133
|
+
channel_data = self.data[:, i]
|
|
134
|
+
channel = Channel(channel_data, sample_rate=self.sample_rate, number=i) # This will now use models.Channel
|
|
135
|
+
channels.append(channel)
|
|
136
|
+
return channels
|
|
137
|
+
|
|
138
|
+
def _extract_datetime(self):
|
|
139
|
+
# Extract datetime from the filename
|
|
140
|
+
basename = os.path.basename(self.wav_file)
|
|
141
|
+
match = re.search(r'(\d{4}-\d{2}-\d{2})_(\d{2}\.\d{2}\.\d{2})', basename)
|
|
142
|
+
if match:
|
|
143
|
+
date_str, time_str = match.groups()
|
|
144
|
+
date_parts = [int(part) for part in date_str.split('-')]
|
|
145
|
+
time_parts = [int(part) for part in time_str.split('.')]
|
|
146
|
+
return datetime(*date_parts, *time_parts)
|
|
147
|
+
return None
|
|
148
|
+
|
|
149
|
+
|