def spindle_number(x, sampling_frequency): """ Single channel spindle detection. Returns the number of spindles in the given data """ spindles = yasa.spindles_detect(x, sampling_frequency) if spindles is None: return 0 return spindles.shape[0]
def fcn_spindle(data, sf, time, hypno): """Replace Visbrain built-in spindles detection by YASA algorithm. See http://visbrain.org/sleep.html#use-your-own-detections-in-sleep """ # Apply on the full recording # sp = spindles_detect(data, sf) # NREM sleep only sp = spindles_detect(data, sf, hypno=hypno) return (sp[['Start', 'End']].values * sf).astype(int)
def compute_spindle_features(signal, fs, low=False, ch_names=['EEG', 'EEG(sec)']): if low: thresh = { 'rel_pow': 0.1, 'corr': 0.5, 'rms': 0.8 } # low threshold config else: thresh = { 'rel_pow': 0.3, 'corr': 0.68, 'rms': 1.2 } # default config (real default is rms=1.5, but ok) if len(ch_names) == 2: sp = spindles_detect_multi(signal, fs, ch_names=ch_names, multi_only=False, thresh=thresh) else: sp = spindles_detect(data=signal, sf=fs, thresh=thresh) spindle_features = np.zeros(7) if sp is not None: spindle_features = sp[[ 'Amplitude', 'RMS', 'AbsPower', 'RelPower', 'Oscillations' ]].mean().values if len(ch_names) == 2: num_spindles_0 = np.array( [sp.loc[sp.Channel == 'EEG', 'Channel'].shape[0]]) num_spindles_1 = np.array( [sp.loc[sp.Channel == 'EEG(sec)', 'Channel'].shape[0]]) else: num_spindles_0 = np.array([sp.shape[0]]) num_spindles_1 = 0 spindle_features = np.append(spindle_features, np.append(num_spindles_0, num_spindles_1)) return spindle_features
def get_spindle_templates(signal, cam=None, fs=125, sec_before=5., sec_after=5., num_ch=2, random=False, noise_inter=0): cam_time_intrp = np.arange(signal.shape[1]) * 1 / fs cam_intrp = np.interp(cam_time_intrp, np.arange(cam.shape[0]) / (cam.shape[0] / (signal.shape[1] / fs)), cam) assert(cam_intrp.shape[0] == 2400) # just checking cam_templates = [] # thresh = {'rel_pow': 0.1, 'corr': 0.5, 'rms': 0.8} thresh = {'rel_pow': 0.3, 'corr': 0.68, 'rms': 1.5} if num_ch == 1: sp = spindles_detect(signal, fs, thresh=thresh) else: sp = spindles_detect_multi(signal, fs, multi_only=False, thresh=thresh, ch_names=['EEG', 'EEG(sec)']) if sp is not None: sp_starts = df_to_event_start(df=sp, signal=signal, fs=fs, num_ch=num_ch) sp_starts = replace_starts_with_random(random=random, starts=sp_starts, sec_before=sec_before, sec_after=sec_after, fs=fs, signal_len=cam_intrp.shape[0],noise_inter=noise_inter) cam_templates = indices_to_templates(cam_intrp, indices=sp_starts, sec_before=sec_before, sec_after=sec_after, fs=fs) return cam_templates
raw = mne.io.read_raw_edf('Land_Scoring_6_excerpt.edf', preload=True, exclude=['MagZ']) # raw.resample(100) # Downsample the data to 100 Hz # raw.filter(0.1, 40) # Apply a bandpass filter from 0.1 to 40 Hz # raw.pick_channels(['C4-A1', 'C3-A2']) # Select a subset of EEG channels raw # Outputs summary data about file #Inspect Data print('The channels are:', raw.ch_names) print('The sampling frequency is:', raw.info['sfreq']) # Let's now load the human-scored hypnogram, where each value represents a 30-sec epoch. # hypno = np.loadtxt('sub-02_hypno_30s.txt', dtype=str) # hypno # Apply the detection using yasa.spindles_detect sp = yasa.spindles_detect(raw) # Display the results using .summary() sp.summary() # We first need to specify the channel names and, optionally, the age and sex of the participant # - "raw" is the name of the variable containing the polysomnography data loaded with MNE. # - "eeg_name" is the name of the EEG channel, preferentially a central derivation (e.g. C4-M1). This is always required to run the sleep staging algorithm. # - in my case will set "eeg_name" to "LEEG3_Ch12" # - "eog_name" is the name of the EOG channel (e.g. LOC-M1). This is optional. # - in my case will set "eog_name" to "LEOG_Ch2" # - "emg_name" is the name of the EOG channel (e.g. EMG1-EMG3). This is optional. # - in my case will set "emg_name" to "LEMG_Ch5" # - "metadata" is a dictionary containing the age and sex of the participant. This is optional. sls = yasa.SleepStaging(raw, eeg_name="LEEG3_Ch12", eog_name="LEOG_Ch2", emg_name="LEMG_Ch5", metadata=dict(age=1.8, male=False))
def main(): count = 600 sn = socket.socket() hostn = 'localhost' portn = 14564 sn.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sn.bind((hostn, portn)) print('Server Started') sn.listen(5) cn, addrn = sn.accept() print('Got connection from', addrn) mapping = {0: 'Wake', 1: 'N1', 2: 'N2', 3: 'N3', 4: 'REM'} # hyp = {0: 4, 1: 2, 2: 1, 3: 0, 4: 3} channels = { 0: 'EEG-FPZ-CZ', 1: 'EEG-PZ-OZ', 2: 'EOG', 3: 'Resp-Oro-Nasal', 4: 'EMG', 5: 'Temp' } npz_file = 'SleepEDF_NPZ/SC4001E0.npz' with np.load(npz_file) as f: data = f["x"] labels = f["y"] save_path = 'data/epoch_custom.npz' save_dict = {"x": data[count, :, :], "y": labels[count]} np.savez(save_path, **save_dict) rt = RepeatedTimer(30, func, qu) # it auto-starts, no need of rt.start() while True: print("Epoch Number: ", count) save_dict = {'x': data[count, :, :], 'y': labels[count]} np.savez(save_path, **save_dict) dict_temp = qu.get() grads = dict_temp["grads"] sleepstage = dict_temp["Y_pred"] print(sleepstage) json_data = data[count, :, :] from datetime import datetime now = datetime.now() print("now =", now) root_time = strftime("%b-%d-%Y %H:%M") just_time = strftime("%H:%M:%S") json_data_eeg_fpzcz = np.transpose(np.transpose(json_data)[0][:][:]) json_data_eeg_pzoz = np.transpose(np.transpose(json_data)[1][:][:]) json_data_eeg_fpzcz = json_data_eeg_fpzcz.reshape(3000, ) json_data_eeg_pzoz = json_data_eeg_pzoz.reshape(3000, ) plt.specgram(json_data_eeg_fpzcz, Fs=100, cmap='viridis') plt.ylabel('Frequency [Hz]') plt.xlabel('Time [sec]') plt.savefig('../frontend/views/eeg_fpzcz_specgram.png', bbox_inches='tight') sf = 100 # Define window length (4 seconds) win = 4 * sf # Apply the detection using yasa.spindles_detect sp = yasa.spindles_detect(json_data_eeg_fpzcz, sf) sw = sw_detect(json_data_eeg_fpzcz, sf, include=(2, 3), freq_sw=(0.3, 2), dur_neg=(0.3, 1.5), dur_pos=(0.1, 1), amp_neg=(40, 300), amp_pos=(10, 150), amp_ptp=(75, 400), remove_outliers=False, coupling=False, freq_sp=(12, 16)) if sp is None: mask_spindles = np.zeros(len(json_data_eeg_fpzcz)) else: mask_spindles = sp.get_mask() spindles_highlight = json_data_eeg_fpzcz * mask_spindles spindles_highlight[spindles_highlight == 0] = np.nan if sw is None: mask_sw = np.zeros(len(json_data_eeg_fpzcz)) else: mask_sw = sw.get_mask() sw_highlight = json_data_eeg_fpzcz * mask_sw sw_highlight[sw_highlight == 0] = np.nan all_rows = [] for i in range(len(json_data_eeg_fpzcz)): current_time = root_time + ':{}:{}0'.format( str(math.floor(i / 100)).zfill(2), str(math.floor(i % 100)).zfill(2)) current_time = "{}".format(current_time).replace('\'', '') row = {} row["date"] = current_time row["EEG_FPZ_CZ"] = json_data_eeg_fpzcz[i] if (np.isnan(spindles_highlight[i])): row["EEG_FPZ_CZ_Spindle"] = None else: row["EEG_FPZ_CZ_Spindle"] = json_data_eeg_fpzcz[i] if (np.isnan(sw_highlight[i])): row["EEG_FPZ_CZ_Slow Waves"] = None else: row["EEG_FPZ_CZ_Slow Waves"] = json_data_eeg_fpzcz[i] all_rows.append(row) with open('../frontend/data/EEG-FPZ-CZ.json', 'w') as f: f.write(str(all_rows).replace('\'', '"').replace('None', 'null')) # Apply the detection using yasa.spindles_detect sp = yasa.spindles_detect(json_data_eeg_pzoz, sf) sw = sw_detect(json_data_eeg_pzoz, sf, include=(2, 3), freq_sw=(0.3, 2), dur_neg=(0.3, 1.5), dur_pos=(0.1, 1), amp_neg=(40, 300), amp_pos=(10, 150), amp_ptp=(75, 400), remove_outliers=False, coupling=False, freq_sp=(12, 16)) if sp is None: mask_spindles = np.zeros(len(json_data_eeg_pzoz)) else: mask_spindles = sp.get_mask() spindles_highlight = json_data_eeg_pzoz * mask_spindles spindles_highlight[spindles_highlight == 0] = np.nan if sw is None: mask_sw = np.zeros(len(json_data_eeg_pzoz)) else: mask_sw = sw.get_mask() sw_highlight = json_data_eeg_pzoz * mask_sw sw_highlight[sw_highlight == 0] = np.nan all_rows = [] for i in range(len(json_data_eeg_pzoz)): current_time = root_time + ':{}:{}0'.format( str(math.floor(i / 100)).zfill(2), str(math.floor(i % 100)).zfill(2)) current_time = "{}".format(current_time).replace('\'', '') row = {} row["date"] = current_time row["EEG_PZ_OZ"] = json_data_eeg_pzoz[i] if (np.isnan(spindles_highlight[i])): row["EEG_PZ_OZ_Spindle"] = None else: row["EEG_PZ_OZ_Spindle"] = json_data_eeg_pzoz[i] if (np.isnan(sw_highlight[i])): row["EEG_PZ_OZ_Slow Waves"] = None else: row["EEG_PZ_OZ_Slow Waves"] = json_data_eeg_pzoz[i] all_rows.append(row) with open('../frontend/data/EEG-PZ-OZ.json', 'w') as f: f.write(str(all_rows).replace('\'', '"').replace('None', 'null')) # EEG-FPZ-CZ-Grad all_rows = [] for i in range(len(json_data_eeg_fpzcz)): current_time = root_time + ':{}:{}0'.format( str(math.floor(i / 100)).zfill(2), str(math.floor(i % 100)).zfill(2)) current_time = "{}".format(current_time).replace('\'', '') row = {} row["date"] = current_time row["EEG-FPZ-CZ"] = json_data_eeg_fpzcz[i] if (grads[0, i] < 0.15): row["EEG-FPZ-CZ-Grad"] = None else: row["EEG-FPZ-CZ-Grad"] = json_data_eeg_fpzcz[i] all_rows.append(row) with open('../frontend/data/EEG-FPZ-CZ-Grad.json', 'w') as f: f.write(str(all_rows).replace('\'', '"').replace('None', 'null')) # EEG-PZ-OZ-Grad all_rows = [] for i in range(len(json_data_eeg_pzoz)): current_time = root_time + ':{}:{}0'.format( str(math.floor(i / 100)).zfill(2), str(math.floor(i % 100)).zfill(2)) current_time = "{}".format(current_time).replace('\'', '') row = {} row["date"] = current_time row["EEG-PZ-OZ"] = json_data_eeg_pzoz[i] if (grads[0, i] < 0.15): row["EEG-PZ-OZ-Grad"] = None else: row["EEG-PZ-OZ-Grad"] = json_data_eeg_pzoz[i] all_rows.append(row) with open('../frontend/data/EEG-PZ-OZ-Grad.json', 'w') as f: f.write(str(all_rows).replace('\'', '"').replace('None', 'null')) #Other channel grads for index in range(2, 6): json_data_tmp = np.transpose(np.transpose(json_data)[index][:][:]) json_data_tmp = json_data_tmp.reshape(3000, ) all_rows = [] for i in range(len(json_data_tmp)): current_time = root_time + ':{}:{}0'.format( str(math.floor(i / 100)).zfill(2), str(math.floor(i % 100)).zfill(2)) current_time = "{}".format(current_time).replace('\'', '') row = {} row["date"] = current_time row[channels[index]] = json_data_tmp[i] if (grads[0, i] < 0.15): row[channels[index] + "-Grad"] = None else: row[channels[index] + "-Grad"] = json_data_tmp[i] all_rows.append(row) with open('../frontend/data/' + channels[index] + '-Grad.json', 'w') as f: f.write( str(all_rows).replace('\'', '"').replace('None', 'null')) #Normal non-EEG channels for index in range(2, 6): json_data_tmp = np.transpose(np.transpose(json_data)[index][:][:]) json_data_tmp = json_data_tmp.reshape(3000, ) all_rows = [] for i in range(len(json_data_tmp)): current_time = root_time + ':{}:{}0'.format( str(math.floor(i / 100)).zfill(2), str(math.floor(i % 100)).zfill(2)) current_time = "{}".format(current_time).replace('\'', '') row = {} row["date"] = current_time row[channels[index]] = json_data_tmp[i] all_rows.append(row) with open('../frontend/data/' + channels[index] + '.json', 'w') as f: f.write( str(all_rows).replace('\'', '"').replace('None', 'null')) psd, freqs = psd_array_multitaper(json_data_eeg_fpzcz, sf, normalization='full', verbose=0) all_rows = [] for i in range(len(freqs[:1801])): #Upto 60Hz (Elaborate) row = {} row["Frequencies"] = freqs[i] row["PSD"] = psd[i] all_rows.append(row) with open('../frontend/data/PSD-FPZCZ.json', 'w') as f: f.write(str(all_rows).replace('\'', '"')) psd, freqs = psd_array_multitaper(json_data_eeg_pzoz, sf, normalization='full', verbose=0) all_rows = [] for i in range(len(freqs[:1801])): row = {} row["Frequencies"] = freqs[i] row["PSD"] = psd[i] all_rows.append(row) with open('../frontend/data/PSD-PZOZ.json', 'w') as f: f.write(str(all_rows).replace('\'', '"')) from scipy.fftpack import rfft, rfftfreq SAMPLE_RATE = 100 DURATION = 30 # Number of samples in normalized_tone N = SAMPLE_RATE * DURATION yf = rfft(json_data_eeg_fpzcz) xf = rfftfreq(N, 1 / SAMPLE_RATE) all_rows = [] for i in range(len(xf)): row = {} row["x"] = xf[i] row["y"] = np.abs(yf[i]) all_rows.append(row) with open('../frontend/data/FFT-FPZCZ.json', 'w') as f: f.write(str(all_rows).replace('\'', '"')) count_json = {} count_json["data"] = count with open('../frontend/data/count.json', 'w') as f: f.write(str(count_json).replace('\'', '"')) print("Sleepstage: ", mapping[sleepstage]) row = {} row["time"] = just_time row["stage"] = sleepstage + 1 print(row) with open('../frontend/data/sleepstage.json', 'w') as f: f.write(str(row).replace('\'', '"')) # nodeserv(hyp[int(sleepstage)], cn) nodeserv(int(sleepstage), cn) count += 1 qu.task_done() try: sleep(150) # your long-running job goes here finally: rt.stop( ) # better in a try/finally block to make sure the program ends
def find_spindles(data, fs): return yasa.spindles_detect(data, fs)
def find_spindles(data, fs, thresh={'rel_pow': 0.2, 'corr': 0.65, 'rms': 1.5}): return yasa.spindles_detect(data, fs, thresh = thresh)
# Define sampling frequency and time vector sf = 1000. times = np.arange(data.size) / sf # # Plot the signal # fig, ax = plt.subplots(1, 1, figsize=(14, 4)) # plt.plot(times, data, lw=1.5, color='k') # plt.xlabel('Time (seconds)') # plt.ylabel('Amplitude (uV)') # plt.xlim([times.min(), times.max()]) # plt.title('LFP NREM epoch') # sns.despine() if data.size > sf: sp = yasa.spindles_detect(data, sf) else: print('Short epoch') sp = None if sp is not None: ajalas[0, x] = 1 # averout[x,0]=sp.get_mask() summary = sp.summary() ch = pd.DataFrame(summary).to_numpy() averout[x, 0] = ch else: averout[x, 0] = [] scipy.io.savemat('YASA_PAR_spindles.mat', {'averout': averout})
def plot_cam(saved_model_name, signal_name, plot_inds, test_loader, model, cam_target, label='normal', use_grad_cam=False, use_relu=True, grad_weight=True, ds=False): label_lookup = ['Wake', 'N1', 'N2', 'N3', 'REM'] if ds: fs = 80 # [Hz] signal_len = 2400 conv0_len = 2700 # signal_len / 2 else: fs = 125 # [Hz] signal_len = 15000 conv0_len = 1875 # signal_len/(2**3) time_series, true_label, name = test_loader.dataset[0] time_series_tensor = torch.reshape(torch.tensor(time_series), (1, 2, signal_len)).to("cpu") raise NotImplementedError # this is not updated.. feature_tensor = torch.zeros(1) # todo: fix for real features logits, cam, _ = model(time_series_tensor, feature_tensor) if use_grad_cam: logits[:, cam_target].backward() gradients = model.get_activations_gradient() pooled_gradients = torch.mean(gradients, dim=[0, 2]) activations = model.get_activations().detach() if grad_weight: # weight by gradients for i in range(activations.shape[1]): # change to torch.mm later activations[:, i, :] *= pooled_gradients[i] grad_cam = torch.mean(activations, dim=1).squeeze() if use_relu: grad_cam = np.maximum(grad_cam, 0) grad_cam /= torch.max(grad_cam) else: grad_cam = (grad_cam - torch.min(grad_cam)) / ( torch.max(grad_cam) - torch.min(grad_cam)) cam = grad_cam.numpy() else: cam = np.squeeze(cam.detach().numpy())[cam_target, :] # Clip signal to baseline # cam = np.maximum(cam, Counter(cam).most_common(1)[0][0]) # cam = (cam - min(cam)) / (max(cam) - min(cam)) logits = np.squeeze(logits.detach().numpy()) # The following is from Seb's plot_class_activation_map and plot_class_activation_map_template cam_time = np.arange(cam.shape[0]) / (cam.shape[0] / 120) cam_time_intrp = np.arange(time_series.shape[1]) * 1 / fs cam_intrp = np.interp(cam_time_intrp, cam_time, cam) # relevant slice before = 60 after = 30 # time_series = time_series[:, int(before*fs): int(-after*fs)] # cam_intrp = cam_intrp[int(before*fs):int(-after*fs)] time_series_filt = time_series time_series_filt_ts = np.arange(time_series_filt.shape[1]) * 1 / fs cam_filt = cam_intrp prob = np.exp(logits) / sum(np.exp(logits)) sp1 = spindles_detect(time_series_filt[0, :], fs) if sp1 is not None: bool_spindles1 = get_bool_vector(time_series_filt[0, :], fs, sp1) spindles_highlight1 = time_series_filt[0, :] * bool_spindles1 spindles_highlight1[spindles_highlight1 == 0] = np.nan spindles_highlight1 = spindles_highlight1[:-1] sp2 = spindles_detect(time_series_filt[1, :], fs) if sp2 is not None: bool_spindles2 = get_bool_vector(time_series_filt[1, :], fs, sp2) spindles_highlight2 = time_series_filt[1, :] * bool_spindles2 spindles_highlight2[spindles_highlight2 == 0] = np.nan spindles_highlight2 = spindles_highlight2[:-1] # plt.figure(figsize=(14, 4)) # plt.plot(times, data, 'k') # plt.plot(times, spindles_highlight, 'indianred') # Setup figure fig = plt.figure(figsize=(15, 10)) fig.subplots_adjust(wspace=0, hspace=0) ax1 = plt.subplot2grid((3, 5), (0, 0), colspan=5) ax2 = plt.subplot2grid((3, 5), (1, 0), colspan=5) ax3 = plt.subplot2grid((3, 5), (2, 0), colspan=5) class_target_dict = {0: 'Wake', 1: 'N1', 2: 'N2', 3: 'N3', 4: 'REM'} title = f'{signal_name}' ax1.set_title( title + '\n' f'Truth: {label}' + '\n' + f'Predicted Label: {label_lookup[np.squeeze(np.argmax(logits))]} ' + str(np.round(prob[np.squeeze(np.argmax(logits))], 2)), fontsize=20, y=1.03) idx1 = plot_inds[0] idx2 = plot_inds[1] if plot_inds[1] < time_series_filt_ts.shape[ 0] else time_series_filt_ts.shape[0] - 1 # Plot image ax1.plot(time_series_filt_ts[idx1:idx2], time_series_filt[0, idx1:idx2], '-k', lw=1.5) if sp1 is not None: ax1.plot(time_series_filt_ts[idx1:idx2], spindles_highlight1, 'indianred') ax1.set_ylabel('Normalized Amplitude', fontsize=22) ax1.set_xlim([time_series_filt_ts[idx1], time_series_filt_ts[idx2].max()]) ax1.tick_params(labelbottom='off') ax1.yaxis.set_tick_params(labelsize=16) ax2.plot(time_series_filt_ts[idx1:idx2], time_series_filt[1, idx1:idx2], '-k', lw=1.5) if sp2 is not None: ax2.plot(time_series_filt_ts[idx1:idx2], spindles_highlight2, 'indianred') ax2.set_ylabel('Normalized Amplitude', fontsize=22) ax2.set_xlim([time_series_filt_ts[idx1], time_series_filt_ts[idx2].max()]) ax2.tick_params(labelbottom='off') ax2.yaxis.set_tick_params(labelsize=16) # Plot CAM ax3.plot(time_series_filt_ts[idx1:idx2], cam_filt[idx1:idx2], '-k', lw=1.5) ax3.set_xlabel('Time, seconds', fontsize=22) ax3.set_ylabel('Class Activation Map', fontsize=22) ax3.set_xlim([time_series_filt_ts[idx1], time_series_filt_ts[idx2].max()]) # ax2.set_ylim([cam_filt.min()-0.05, cam_filt.max()+0.05]) ax3.xaxis.set_tick_params(labelsize=16) ax3.yaxis.set_tick_params(labelsize=16) plt.show()