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
9 changes: 9 additions & 0 deletions .codespellrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[codespell]
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
skip = .git,.git-meta,.gitignore,.gitattributes,.codespellrc,*.pb,optimized_models
check-hidden = true
# Ignore embedded base64 image data in Jupyter notebooks
ignore-regex = ^\s*"image/\S+": ".*
# momento - Spanish word ("moment") in Spanish-language code comment
# commun - abbreviation of "Communications" (journal: Nat Commun Biol)
ignore-words-list = momento,commun
23 changes: 23 additions & 0 deletions .github/workflows/codespell.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Codespell configuration is within .codespellrc
---
name: Codespell

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

jobs:
codespell:
name: Check for spelling errors
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v6
- name: Codespell
uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 # v2.2
48 changes: 24 additions & 24 deletions README.md

Large diffs are not rendered by default.

42 changes: 21 additions & 21 deletions aux_fcn.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def loadChunk(fid, nChannels, channels, nSamples, precision):
data = fid.read(size)

# fromstring to read the data as int16
# reshape to give it the appropiate shape (nSamples x nChannels)
# reshape to give it the appropriate shape (nSamples x nChannels)
data = np.fromstring(data, dtype=np.int16).reshape(nSamples, len(channels))
data = data[:, channels]

Expand All @@ -70,7 +70,7 @@ def bz_LoadBinary(filename, nChannels, channels, sampleSize, verbose=False):
print("fileStart ", fileStart)
status = f.seek(0, 2) # Go to the end of the file
fileStop = f.tell()
f.seek(0, 0) # Back to the begining
f.seek(0, 0) # Back to the beginning
if verbose:
print("fileStop ", fileStop)

Expand Down Expand Up @@ -102,7 +102,7 @@ def bz_LoadBinary(filename, nChannels, channels, sampleSize, verbose=False):
if verbose:
print("size data ", np.size(data, 0))

# Read all chuncks
# Read all chunks
i = 0
for j in range(nChunks):
d = loadChunk(f, nChannels, channels, nSamplesPerChunk/nChannels, sampleSize)
Expand Down Expand Up @@ -469,7 +469,7 @@ def get_predictions_index(predictions,threshold=0.5,merge_samples=0):
'''
[pred_indexes] = get_predictions_index(predictions, thershold)

Returns the begining and ending samples of the events above a given threshold
Returns the beginning and ending samples of the events above a given threshold

Inputs:
-------
Expand All @@ -479,7 +479,7 @@ def get_predictions_index(predictions,threshold=0.5,merge_samples=0):

Output:
-------
pred_indexes: Nx2, array containing the begining and ending index sample of the events
pred_indexes: Nx2, array containing the beginning and ending index sample of the events
'''
aux=np.copy(predictions)
aux[aux>=threshold]=1
Expand Down Expand Up @@ -552,7 +552,7 @@ def format_predictions(path,preds,d_sf):
return


# Performance (precission, recall, F1) metrics
# Performance (precision, recall, F1) metrics

def get_performance(pred_events, true_events, threshold=0, exclude_matched_trues=False, verbose=True):

Expand All @@ -565,7 +565,7 @@ def get_performance(pred_events, true_events, threshold=0, exclude_matched_trues
pred_events Nx2 matrix with start and end of pred events (seconds)
true_events Mx2 matrix with start and end of true events (seconds)
threshold Threshold to IoU. By default is 0
exclude_matched_trues False by defaut (one true can match many predictions)
exclude_matched_trues False by default (one true can match many predictions)

Output:
-------
Expand Down Expand Up @@ -674,12 +674,12 @@ def intersection_over_union(x, y):

elif len(x)==0:

print('x is empty. Cant perform IoU')
print("x is empty. Can't perform IoU")
return np.array([]), np.array([]), np.zeros((y.shape[0], 1))

elif len(y)==0:

print('y is empty. Cant perform IoU')
print("y is empty. Can't perform IoU")
return np.array([]), np.zeros((1, x.shape[0])), np.array([])


Expand Down Expand Up @@ -712,10 +712,10 @@ def split_data(x,GT,window_dur=60,d_sf=1250,split=0.7):
-------
x: [n X n_channels] matrix with the LFP values of the session
GT: [n events x 2] initial and end times of each events
window_dur: float, length in seconds of the chunks that will be asigned
window_dur: float, length in seconds of the chunks that will be assigned
randomly to train or validation subsets
d_sf: (int), sampling frequency of the passed data
split: float, proportion of windows that will be asigned to the
split: float, proportion of windows that will be assigned to the
train subset (the final proportion will diverge, being random)

Output:
Expand Down Expand Up @@ -771,7 +771,7 @@ def retraining_parser(arch,x_train_or,events_train,x_test,events_test,params=Non
- In 'XGBOOST': not needed
- In 'SVM':
params['Undersampler proportion']. Any value between 0 and 1. This parameter eliminates
samples where no ripple is present untill the desired proportion is achieved:
samples where no ripple is present until the desired proportion is achieved:
Undersampler proportion= Positive samples/Negative samples
- In 'LSTM', 'CNN1D' and 'CNN2D':
params['Epochs']. The number of times the training data set will be used to train the model
Expand Down Expand Up @@ -835,7 +835,7 @@ def retraining_parser(arch,x_train_or,events_train,x_test,events_test,params=Non
y_test_aux=y_test[:x_test_len-x_test_len%timesteps].reshape(-1,timesteps)
y_test=rec_signal(y_test_aux)

#Under sampler: discards windows where there is no ripples untill the desired proportion between ripple/no ripple is achieved
#Under sampler: discards windows where there is no ripples until the desired proportion between ripple/no ripple is achieved
# If no params is provided, the defect proportion will be 0.5
if params==None:
us_prop=0.5
Expand Down Expand Up @@ -1017,9 +1017,9 @@ def get_keep(self,n):
return(self.keeps[self.index+n])
def get_TP(self,n):
return(self.TP[self.index+n])
# Individual keep change, change keep to discard and viceversa for a single value
# Individual keep change, change keep to discard and vice-versa for a single value
def change_keep(self,ind):
if (self.check_index(ind)): # True if out of bounds, returns True for excetion handling
if (self.check_index(ind)): # True if out of bounds, returns True for exception handling
return True
self.keeps[self.index+ind]= not (self.keeps[self.index+ind])
# Multiple keep change, sets keep from index to index+number equal to value
Expand Down Expand Up @@ -1050,11 +1050,11 @@ def manual_curation(events,data,file_path,win_size=100,gt_events=None,sf=1250):

Inputs:
-------
events: (2,n_det) array with events begining and end times (seconds)
events: (2,n_det) array with events beginning and end times (seconds)
data: (n,n_channels) normalized array with the input data
file_path: (str) absolute path of the folder where the .txt with the
curated predictions will be saved
win_size: (int) length of the displayed ripples in miliseconds
win_size: (int) length of the displayed ripples in milliseconds
gt_events: (2,n_gt_events) ground truth events beginning and end times (seconds)
sf: (int) sampling frequency (Hz) of the data/model output.
Change if different than 1250
Expand All @@ -1067,7 +1067,7 @@ def manual_curation(events,data,file_path,win_size=100,gt_events=None,sf=1250):

Use cases:
1. If no GT events are provided, a the detected events will be provided,
you can select which ones you want to keep (highligted in green)
you can select which ones you want to keep (highlighted in green)
and which ones to discard (in red)
2. If GT events are provided, true positive detections (TP) will be
displayed in green. If for any reason you want to discard correct
Expand Down Expand Up @@ -1208,7 +1208,7 @@ def on_click(event):
row_ind,col_ind=np.argwhere(axes==ax)[0]
clicked_ind=(row_ind*int(events_in_screen/5)+col_ind)

if oIn.change_keep(clicked_ind): # If out of bounds, close early, dont change color
if oIn.change_keep(clicked_ind): # If out of bounds, close early, don't change color
return
check_colors(oIn,clicked_ind,ax)
curated_intervals=oIn.intervals[oIn.keeps]
Expand All @@ -1233,7 +1233,7 @@ def plot_all_events(t_events, lfp, sf, win=0.100, title='', savefig=''):
events (numpy array):
Array of size (#events, 1) with all times of events
lfp (numpy array):
formated lfp with all channels
formatted lfp with all channels
sf (int):
sampling frequency of the 'lfp' variable

Expand Down Expand Up @@ -1403,7 +1403,7 @@ def build_CNN2D(conf, input_shape = (50,8,1)):
def build_CNN1D(n_channels,timesteps,conf):
'''
model = build_CNN1D(n_channels, timesteps, conf)\n
Returns a 1D convolutional neural network. If the desired configuration will create problems, and exception with sugestions is thrown\n
Returns a 1D convolutional neural network. If the desired configuration will create problems, and exception with suggestions is thrown\n

Inputs:
-------
Expand Down
4 changes: 2 additions & 2 deletions examples_detection.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
"metadata": {},
"source": [
"# Get performances after detection\n",
"Every model predict, get_intervals is used automatically and the performance metric is ploted"
"Every model predict, get_intervals is used automatically and the performance metric is plotted"
]
},
{
Expand Down Expand Up @@ -321,7 +321,7 @@
"metadata": {},
"source": [
"### Data load\n",
"To ilustrate how 'interpolate_channels' can be used to extract the desired number of channels, we will be simulating two cases using the DLx1 session:\n",
"To illustrate how 'interpolate_channels' can be used to extract the desired number of channels, we will be simulating two cases using the DLx1 session:\n",
"1. We are using a recording probe that extracts 4 channels, when we need 8.\n",
"2. Some channels are dead or have to much noise."
]
Expand Down
4 changes: 2 additions & 2 deletions examples_explore/example_CNN1D.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
"* Timesteps: number of samples that the model will use to produce a single output\n",
"* Configuration: list with as many elements as layers in the model shaped [number of kernels layers, kernel size and stride ]. The length size and the kernel layer were matched to reduce design complexity.\n",
"* Epoch: number of times the training data set is used to train the model\n",
"* Training batch: number of windows that are proccessed before weight updating"
"* Training batch: number of windows that are processed before weight updating"
]
},
{
Expand Down Expand Up @@ -294,7 +294,7 @@
"# For loop iterating over the models\n",
"fig,axs=plt.subplots(n_iters,2,figsize=(10,2*n_iters),sharey='col',sharex='col')\n",
"for n_m,model in enumerate(model_arr):\n",
" F1_arr=np.zeros(shape=(len(x_val_list),len(th_arr))) #(n_val_sess x n_th) Array where the F1 val of each sesion will be stored\n",
" F1_arr=np.zeros(shape=(len(x_val_list),len(th_arr))) #(n_val_sess x n_th) Array where the F1 val of each session will be stored\n",
" for n_sess,LFP in enumerate(x_val_list):\n",
" val_pred=rippl_AI.predict(LFP,sf=1250,arch='CNN1D',new_model=model,n_channels=n_channels,n_timesteps=timesteps_arr_ploting[n_m])[0]\n",
" for i,th in enumerate(th_arr):\n",
Expand Down
6 changes: 3 additions & 3 deletions examples_explore/example_CNN2D.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"# CNN2D parameter exploration\n",
"This notebook is a template for finding the CNN2D model best suited for your needs \n",
"\n",
"This arquitecture is inspired by the UNet (https://doi.org/10.48550/arXiv.1505.04597) and YOLOR (https://doi.org/10.48550/arXiv.2105.04206)\n",
"This architecture is inspired by the UNet (https://doi.org/10.48550/arXiv.1505.04597) and YOLOR (https://doi.org/10.48550/arXiv.2105.04206)\n",
"The 1st half uses convolution and MaxPooling to reduce the dimnensinality of the input, and the late half expands it"
]
},
Expand Down Expand Up @@ -126,7 +126,7 @@
"of layers of the model according to the number of channels or timesteps, the smallest of the two: 8 channels allows 4 max Pooling steps (8 -> 4 -> 2 -> 1), 3 channels only 1 (3 ->1)\n",
"Please take it into consideration when designing models\n",
"* Epoch: number of times the training data set is used to train the model\n",
"* Training batch: number of windows that are proccessed before weight updating"
"* Training batch: number of windows that are processed before weight updating"
]
},
{
Expand Down Expand Up @@ -299,7 +299,7 @@
"# For loop iterating over the models\n",
"fig,axs=plt.subplots(n_iters,2,figsize=(10,2*n_iters),sharey='col',sharex='col')\n",
"for n_m,model in enumerate(model_arr):\n",
" F1_arr=np.zeros(shape=(len(x_val_list),len(th_arr))) #(n_val_sess x n_th) Array where the F1 val of each sesion will be stored\n",
" F1_arr=np.zeros(shape=(len(x_val_list),len(th_arr))) #(n_val_sess x n_th) Array where the F1 val of each session will be stored\n",
" for n_sess,LFP in enumerate(x_val_list):\n",
" val_pred=rippl_AI.predict(LFP,sf=1250,arch='CNN2D',new_model=model,n_channels=n_channels,n_timesteps=timesteps_arr_ploting[n_m])[0]\n",
" for i,th in enumerate(th_arr):\n",
Expand Down
8 changes: 4 additions & 4 deletions examples_explore/example_LSTM.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,13 @@
"#### Parameters:\n",
"* Channels: number of channels that will be used to train the model, extracted from the data shape defined in the previous cell\n",
"* Timesteps: number of samples that the will be processed at once\n",
"* Bidirectionality: if the model processes simutaneously the window forward and backwards\n",
"* Bidirectionality: if the model processes simultaneously the window forward and backwards\n",
"* Layers: number of LSTM layers\n",
"* Epoch: number of times the training data set is used to train the model\n",
"* Training batch: number of windows that are proccessed before weight updating\n",
"* Training batch: number of windows that are processed before weight updating\n",
"\n",
"#\n",
"LSTM contains more parameters, feel free to add your own modifications. Check the oficial documentation:\n",
"LSTM contains more parameters, feel free to add your own modifications. Check the official documentation:\n",
"https://keras.io/api/layers/recurrent_layers/lstm/"
]
},
Expand Down Expand Up @@ -288,7 +288,7 @@
"# For loop iterating over the models\n",
"fig,axs=plt.subplots(n_iters,2,figsize=(10,2*n_iters),sharey='col',sharex='col')\n",
"for n_m,model in enumerate(model_arr):\n",
" F1_arr=np.zeros(shape=(len(x_val_list),len(th_arr))) #(n_val_sess x n_th) Array where the F1 val of each sesion will be stored\n",
" F1_arr=np.zeros(shape=(len(x_val_list),len(th_arr))) #(n_val_sess x n_th) Array where the F1 val of each session will be stored\n",
" for n_sess,LFP in enumerate(x_val_list):\n",
" val_pred=rippl_AI.predict(LFP,sf=1250,arch='LSTM',new_model=model,n_channels=n_channels,n_timesteps=timesteps_arr_ploting[n_m])[0]\n",
" for i,th in enumerate(th_arr):\n",
Expand Down
2 changes: 1 addition & 1 deletion examples_explore/example_SVM.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@
"# For loop iterating over the models\n",
"fig,axs=plt.subplots(n_iters,2,figsize=(10,2*n_iters),sharey='col',sharex='col')\n",
"for n_m,model in enumerate(model_arr):\n",
" F1_arr=np.zeros(shape=(len(x_val_list),len(th_arr))) #(n_val_sess x n_th) Array where the F1 val of each sesion will be stored\n",
" F1_arr=np.zeros(shape=(len(x_val_list),len(th_arr))) #(n_val_sess x n_th) Array where the F1 val of each session will be stored\n",
" for n_sess,LFP in enumerate(x_val_list):\n",
" val_pred=rippl_AI.predict(LFP,sf=1250,arch='SVM',new_model=model,n_channels=n_channels,n_timesteps=timesteps_arr_ploting[n_m])[0]\n",
" for i,th in enumerate(th_arr):\n",
Expand Down
8 changes: 4 additions & 4 deletions examples_explore/example_XGBOOST.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,13 @@
"* Channels: number of channels that will be used to train the model, extracted from the data shape defined in the previous cell\n",
"* Timesteps: number of samples that the will be used to generate a single prediction\n",
"* Max depth: number of max layers in each tree. Too many usually causes overfitting\n",
"* Learning rate: similar to a weight used to update te predictor, a high value leads to faster computations but may not reaach a optimal value\n",
"* Learning rate: similar to a weight used to update the predictor, a high value leads to faster computations but may not reaach a optimal value\n",
"* Gamma: Minimum loss reduction required to make a partition on a leaf node. The larger gamma is, the more conservative the model will be\n",
"* Reg lamda: L2 regularization term of weight updating. Increasing this value makes the model more conservative\n",
"* Reg lambda: L2 regularization term of weight updating. Increasing this value makes the model more conservative\n",
"* Scale pos weight: controls the balance of positive and negative weights, useful for unbalanced clasess.\n",
"* Subsample: subsample ratio of the training instances. Setting it to 0.5 means that XGBoost would randomly sample half of the training data prior to growing trees. Used to prevent overfitting\n",
"#\n",
"XGBOOST contains many more parameters, feel free to add your own modifications. Check the oficial documentation: https://xgboost.readthedocs.io/en/stable/parameter.html#parameters-for-tree-booster"
"XGBOOST contains many more parameters, feel free to add your own modifications. Check the official documentation: https://xgboost.readthedocs.io/en/stable/parameter.html#parameters-for-tree-booster"
]
},
{
Expand Down Expand Up @@ -308,7 +308,7 @@
"# For loop iterating over the models\n",
"fig,axs=plt.subplots(n_iters,2,figsize=(10,2*n_iters),sharey='col',sharex='col')\n",
"for n_m,model in enumerate(model_arr):\n",
" F1_arr=np.zeros(shape=(len(x_val_list),len(th_arr))) #(n_val_sess x n_th) Array where the F1 val of each sesion will be stored\n",
" F1_arr=np.zeros(shape=(len(x_val_list),len(th_arr))) #(n_val_sess x n_th) Array where the F1 val of each session will be stored\n",
" for n_sess,LFP in enumerate(x_val_list):\n",
" val_pred=rippl_AI.predict(LFP,sf=1250,arch='XGBOOST',new_model=model,n_channels=n_channels,n_timesteps=timesteps_arr_ploting[n_m])[0]\n",
" for i,th in enumerate(th_arr):\n",
Expand Down
2 changes: 1 addition & 1 deletion examples_retraining.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@
"source": [
"### SVM\n",
"Has only one parameter: \n",
"'Undersampler proportion': It controls the number of windows with negatives (no ripples) that will be used to train the model. Following the formula: Undersampler proportion= (Positive windows)/(Negative windows). 1 means the same number of poitive and negative windows. Low values can lead to overfitting."
"'Undersampler proportion': It controls the number of windows with negatives (no ripples) that will be used to train the model. Following the formula: Undersampler proportion= (Positive windows)/(Negative windows). 1 means the same number of positive and negative windows. Low values can lead to overfitting."
]
},
{
Expand Down
Loading