Dynamic neuronal ensembles encode burst-suppression revealed by cortex-wide optical-electrical interfaces.
The 7 matches
- [1] § Methods › Prediction of neuronal calcium dynamics from multi-channel ECoG signals during burst-suppression and awake states › ECoG features extraction ↔ extra_utils_for_scaling_analysis/utils_ym.py, lines 122–151 · score 0.97 · spectral centroid, spectral entropy, crest factor, dominant frequency, zero crossings, waveform factor
- [2] § Methods › Prediction of neuronal calcium dynamics from multi-channel ECoG signals during burst-suppression and awake states › Calcium signal dimensionality reduction via shared variance component anal ↔ extra_utils_for_population_coding/dimred.py, lines 26–113 · score 0.92 · removed temporal alignment, Shared Variance Component, cross validation, Covariance matrices, Neuronal populations, subsets
- [3] § Methods › Prediction of neuronal calcium dynamics from multi-channel ECoG signals during burst-suppression and awake states › Prediction of SVCs from ECoG features using reduced rank regression (RRR) ↔ extra_utils_for_scaling_analysis/predict.py, lines 162–237 · score 0.78 · reduced rank regression, predicted neural activity, canonical, linear, covariance, behavioral
- [4] § Methods › Prediction of neuronal calcium dynamics from multi-channel ECoG signals during burst-suppression and awake states › Prediction of SVCs from ECoG features using reduced rank regression (RRR) ↔ extra_utils_for_scaling_analysis/utils_ym.py, lines 744–832 · score 0.78 · reduced rank regression, combined training, canonical, validation, zero, rastermap
- [5] § Methods › Prediction of neuronal calcium dynamics from multi-channel ECoG signals during burst-suppression and awake states › Calcium signal dimensionality reduction via shared variance component anal ↔ extra_utils_for_scaling_analysis/svca.py, lines 19–92 · score 0.70 · reliable variance, utilized, SVCA, subsets, checkerboard, shuffled
- [6] § Methods › Transparent electrode array fabrication and characterization › Signal-to-Noise Ratio (SNR) calculation for ECoG signals ↔ extra_utils_for_scaling_analysis/utils_ym.py, lines 122–151 · score 0.55 · power spectral density, Welch, channel
- [7] § Results › Cross-modal signal prediction using shared variance components ↔ Predict_All.ipynb, lines 438–526 · score 0.50 · explainable variance, reliable variance, predicting, SVCs, mice
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Python · 832 lines · 35 KB · GPL-3.0 · 3 matches
- """
- Some misc. utilities.
- """
- import numpy as np
- import matplotlib.pyplot as plt
- import os
- import numpy as np
- import pandas as pd
- from scipy import signal
- from scipy.stats import zscore
- from rastermap import Rastermap
- from scipy.stats import skew, kurtosis
- from scipy.signal import welch
- from tqdm import tqdm
- from scipy.signal import savgol_filter
- from PopulationCoding.predict import canonical_cov
- import logging
- DEFAULT_N_JOBS = 8
- def plot_neurons_behavior_ym(
- neurons, ECoG_fp, normalized_pupil_area, t, clim=[-0.3, 1.5], zspacing=10
- ):
- fig = plt.figure(figsize=(8, 6))
- #
- ax = plt.subplot(10, 1, (1, 5))
- ax.imshow(
- neurons.T, cmap="viridis", aspect="auto", clim=clim, interpolation="bicubic"
- )
- ax.set_xticks([])
- ax.set_ylabel("Neuron #")
- #
- ax = plt.subplot(10, 1, (6, 9))
- time_indices = np.linspace(0, len(t) - 1, ECoG_fp.shape[0])
- for i in range(ECoG_fp.shape[1]):
- ax.plot(time_indices,ECoG_fp[:, i] - zspacing * i, color="k")
- ax.set_xlim([0, len(t) - 1])
- ax.set_xticks([])
- ax.set_yticks([])
- ax.set_ylabel("ECoG")
- #
- ax = plt.subplot(10, 1, 10)
- ax.plot(t, normalized_pupil_area, color="k")
- ax.set_xlim([t[0], t[-1]])
- ax.set_yticks([])
- ax.set_ylabel("Normalized\npupil area")
- ax.set_xlabel("Time (sec)")
- return fig
- def bandstop_filter(data, order=3, fs=1000, stopbands=[[2, 3], [4, 6], [49, 51]]):
- if data.ndim == 1:
- data = np.expand_dims(data, axis=0)
- filtered_data = data.copy()
- for freq_stop in stopbands:
- b, a = signal.butter(order, [f / (fs / 2) for f in freq_stop], btype='bandstop')
- filtered_data = signal.filtfilt(b, a, filtered_data, axis=1)
- if data.shape[0] == 1:
- filtered_data = np.squeeze(filtered_data, axis=0)
- return filtered_data
- def preprocess_calcium_data(res_path, load_path, threshold=50):
- denoised_data = np.load(os.path.join(res_path, "neuron_denoised_records_whole_brain.npy"))
- position_x = pd.read_csv(os.path.join(load_path, "valid_neuron_x.csv"))
- position_y = pd.read_csv(os.path.join(load_path, "valid_neuron_y.csv"))
- denoised_data[denoised_data > threshold] = threshold
- neurons = zscore(denoised_data).T
- centers = np.hstack((position_x, position_y)).T
- return neurons, centers
- def preprocess_ecog_data(load_path, kbd1, evt06):
- fp_32chs = pd.read_csv(os.path.join(load_path, "ele_signal_burst_supp_fp01-fp32.csv")).values.T
- mean_across_channels = np.mean(fp_32chs, axis=0)
- fp_32chs_filtered = np.zeros_like(fp_32chs)
- for ch in range(fp_32chs.shape[0]):
- signal_without_mean = fp_32chs[ch] - mean_across_channels
- fp_32chs_filtered[ch] = bandstop_filter(signal_without_mean)
- #
- second_start_Ele = kbd1 - 120 # s
- second_stop_Ele = second_start_Ele + 900 # s
- fhz_Ele = 1000 # Hz
- t_idx_Ele = np.arange(int(fhz_Ele * second_start_Ele), int(fhz_Ele * second_stop_Ele))
- fp_32chs_example = zscore(fp_32chs_filtered.T[t_idx_Ele, :32])
- return fp_32chs_example
- def perform_rastermap_analysis(neurons, kbd1, evt06, perform_rastermap):
- second_start_Ca = kbd1 - evt06 - 120
- second_stop_Ca = second_start_Ca + 900
- fhz_Ca = 10
- t_idx_Ca = np.arange(int(fhz_Ca * second_start_Ca), int(fhz_Ca * second_stop_Ca))
- neurons_example = zscore(neurons[t_idx_Ca, :])
- neurons_example_sorted = None
- if perform_rastermap:
- model = Rastermap(n_PCs=32, n_clusters=8).fit(neurons_example.T)
- neurons_example_sorted = neurons_example[:, model.isort]
- return neurons_example, neurons_example_sorted
- def downsample_signal(fp_32chs_example, factor=100):
- fp_32chs_downsampled = fp_32chs_example.reshape(-1, factor, fp_32chs_example.shape[1]).mean(axis=1)
- assert fp_32chs_downsampled.shape[0] == 9000
- return fp_32chs_downsampled
- def extract_features(channel_data):
- mean = np.mean(channel_data)
- std_dev = np.std(channel_data)
- variance = np.var(channel_data)
- max_val = np.max(channel_data)
- min_val = np.min(channel_data)
- median = np.median(channel_data)
- ptp = np.ptp(channel_data)
- iqr = np.percentile(channel_data, 75) - np.percentile(channel_data, 25)
- energy = np.sum(channel_data ** 2) / len(channel_data)
- skewness = skew(channel_data)
- kurt = kurtosis(channel_data)
- rms = np.sqrt(np.mean(channel_data**2))
- waveform_factor = rms / np.mean(np.abs(channel_data))
- crest_factor = max_val / rms
- zero_crossings = np.where(np.diff(np.signbit(channel_data)))[0].size
- freqs, psd = welch(channel_data, fs=1000, nperseg=len(channel_data))
- dominant_freq = freqs[np.argmax(psd)]
- spectral_centroid = np.sum(freqs * psd) / np.sum(psd)
- spectral_entropy = -np.sum((psd/np.sum(psd)) * np.log2(psd/np.sum(psd)))
- bandwidth = np.sqrt(np.sum(psd * (freqs - spectral_centroid)**2) / np.sum(psd))
- features = [
- mean, std_dev, variance, max_val, min_val, median,
- ptp, iqr, energy, skewness, kurt, waveform_factor, crest_factor,
- zero_crossings, dominant_freq, spectral_centroid, spectral_entropy, bandwidth
- ]
- return features
- def extract_all_features(fp_32chs_example, num_windows, num_channels):
- features_per_channel = 18
- output_matrix = np.zeros((num_windows, num_channels * features_per_channel))
- for window_idx in tqdm(range(num_windows)):
- start_idx = window_idx * 100
- end_idx = start_idx + 100
- window_data = fp_32chs_example[start_idx:end_idx, :]
- feature_vector = []
- for channel_idx in range(num_channels):
- channel_data = window_data[:, channel_idx]
- features = extract_features(channel_data)
- feature_vector.extend(features)
- output_matrix[window_idx, :] = feature_vector
- return output_matrix
- def zscore_and_visualize_ecog_features(ECoG_Extracted_Features, output_directory, savefigs_1):
- ECoG_Extracted_Features = zscore(zscore(ECoG_Extracted_Features.T).T)
- if savefigs_1:
- model_ECoG = Rastermap(n_PCs=32, n_clusters=8).fit(ECoG_Extracted_Features.T)
- fig, axs = plt.subplots(2, 1, figsize=(12, 8))
- clim1 = [-0.3, 100]
- clim2 = [-0.3, 3]
- axs[0].imshow(
- ECoG_Extracted_Features[:, model_ECoG.isort].T, cmap="viridis", aspect="auto", clim=clim1, interpolation="bicubic"
- )
- axs[0].set_xticks([])
- axs[0].set_ylabel("Neuron #")
- axs[0].set_title('Original TrainX')
- axs[1].imshow(
- ECoG_Extracted_Features[:, model_ECoG.isort].T, cmap="viridis", aspect="auto", clim=clim2, interpolation="bicubic"
- )
- axs[1].set_xticks([])
- axs[1].set_ylabel("Neuron #")
- axs[1].set_title('Original TrainX')
- output_path_tif = os.path.join(output_directory, "fig6", "ECoG_Features.tif")
- output_path_png = os.path.join(output_directory, "fig6", "ECoG_Features.png")
- fig.savefig(output_path_tif, dpi=600, format='tif')
- fig.savefig(output_path_png, dpi=600, format='png')
- plt.close(fig)
- def get_list_shape(lst):
- if isinstance(lst, list):
- return (len(lst),) + get_list_shape(lst[0])
- else:
- return ()
- def plot_svc_time_series(neurons_example, ex_u, ex_v, ex_ntrain, ex_ntest, t_start, t_end, res_path, filename, n_nneur=-1):
- svc_indices = [0, 7, 15, 63, 255, 511] # SVC 1, 8, 16, 64, 256, 512
- plt.figure(figsize=(12, 18))
- for i, svc_index in enumerate(svc_indices):
- neurons_subset_train = neurons_example[t_start*10:t_end*10, ex_ntrain[n_nneur]]
- svc_time_series_train = np.dot(neurons_subset_train, ex_u[n_nneur][:, svc_index])
- neurons_subset_test = neurons_example[t_start*10:t_end*10, ex_ntest[n_nneur]]
- svc_time_series_test = np.dot(neurons_subset_test, ex_v[n_nneur][:, svc_index])
- correlation = np.corrcoef(svc_time_series_train, svc_time_series_test)[0, 1]
- plt.subplot(len(svc_indices), 1, i + 1)
- time_axis = np.arange(svc_time_series_train.shape[0])/10
- plt.plot(time_axis, svc_time_series_train, label=f'Training Set SVC {svc_index + 1}', color='blue')
- plt.plot(time_axis, svc_time_series_test, label=f'Testing Set SVC {svc_index + 1}', color='orange')
- plt.text(0.05, 0.95, f'Correlation: {correlation:.2f}', transform=plt.gca().transAxes,
- fontsize=10, verticalalignment='top', bbox=dict(facecolor='white', alpha=0.5))
- plt.xlabel('Time')
- plt.ylabel('SVC Value')
- plt.title(f'SVC {svc_index + 1} Time Series')
- plt.legend()
- plt.tight_layout()
- save_dir = os.path.join(res_path, "SVCA set1 and set2")
- os.makedirs(save_dir, exist_ok=True)
- output_path_png = os.path.join(save_dir, f"1_8_16_64_256_512_{filename}.png",)
- plt.savefig(output_path_png, format='png')
- plt.close()
- def compare_and_plot(model, trainX, testX, u_sub, v_sub, vp_train, vp_test, ll, kk, res_path, base_path, centers):
- dictpath = os.path.join(res_path, "predicted_neurons_versus_trainX_testX", base_path)
- os.makedirs(dictpath, exist_ok=True)
- plot_filename_png = f"neurons_l{ll}_k{kk}.png"
- plot_filepath_png = os.path.join(dictpath, plot_filename_png)
- plot_filename_tif = f"neurons_l{ll}_k{kk}.tif"
- plot_filepath_tif = os.path.join(dictpath, plot_filename_tif)
- trainX_approximation = vp_train.T @ u_sub.T
- testX_approximation = vp_test.T @ v_sub.T
- trainX_approximation = np.real(trainX_approximation)
- testX_approximation = np.real(testX_approximation)
- trainX_approximation = zscore(zscore(trainX_approximation.T).T)
- testX_approximation = zscore(zscore(testX_approximation.T).T)
- real = np.hstack((trainX, testX))
- predicted = np.hstack((trainX_approximation, testX_approximation))
- plot_neuron_correlation(real, predicted, centers, res_path, f"{base_path}l{ll}k{kk}")
- fig, axs = plt.subplots(2, 1, figsize=(12, 8))
- clim = [-0.3, 1.5]
- axs[0].imshow(
- real[:, model.isort].T, cmap="viridis", aspect="auto", clim=clim, interpolation="bicubic"
- )
- axs[0].set_xticks([])
- axs[0].set_ylabel("Neuron #")
- axs[0].set_title('Original')
- axs[1].imshow(
- predicted[:, model.isort].T, cmap="viridis", aspect="auto", clim=clim, interpolation="bicubic"
- )
- axs[1].set_xticks([])
- axs[1].set_ylabel("Neuron #")
- axs[1].set_title('Predicted')
- for ax in axs.flat:
- ax.set(xlabel='Time', ylabel='Neurons')
- plt.tight_layout()
- plt.savefig(plot_filepath_png)
- plt.savefig(plot_filepath_tif)
- plt.close(fig)
- print(f"Plot saved at {dictpath}")
- import pickle
- def plot_quantitative_statistics(correlations, res_path, suffix):
- sorted_indices = np.argsort(correlations)[::-1]
- top_1000_indices = sorted_indices[:1000]
- top_1000_correlations = [correlations[i] for i in top_1000_indices]
- all_average_correlation = np.mean(correlations)
- top_1000_average_correlation = np.mean(top_1000_correlations)
- all_std_error = np.std(correlations) / np.sqrt(len(correlations))* 1.96
- top_1000_std_error = np.std(top_1000_correlations) / np.sqrt(len(top_1000_correlations)) * 1.96
- # Prepare data to save
- data_to_save = {
- 'correlations':correlations,
- 'sorted_indices': sorted_indices,
- 'top_1000_indices': top_1000_indices,
- 'top_1000_correlations': top_1000_correlations,
- 'all_average_correlation': all_average_correlation,
- 'top_1000_average_correlation': top_1000_average_correlation,
- 'all_std_error': all_std_error,
- 'top_1000_std_error': top_1000_std_error
- }
- # Save variables to a file using pickle
- save_dir = os.path.join(res_path, "neuron_correlation_statistics")
- os.makedirs(save_dir, exist_ok=True)
- with open(os.path.join(save_dir, f"variables_{suffix}.pkl"), 'wb') as f:
- pickle.dump(data_to_save, f)
- # Plotting
- plt.figure(figsize=(8, 6))
- labels = ['All Neurons', 'Top 1000 Neurons']
- averages = [all_average_correlation, top_1000_average_correlation]
- errors = [all_std_error, top_1000_std_error]
- plt.bar(labels, averages, yerr=errors, color=['blue', 'green'], alpha=0.7, capsize=5)
- plt.ylabel('Average Pearson Correlation')
- plt.title('Comparison of Average Correlation with Error Bars')
- plt.savefig(os.path.join(save_dir, f"neuron_correlation_statistics_{suffix}.png"), dpi=300)
- plt.savefig(os.path.join(save_dir, f"neuron_correlation_statistics_{suffix}.pdf"))
- plt.close()
- def plot_neuron_correlation(real_activity, predicted_activity, centers, res_path, suffix):
- correlations = []
- for i in range(real_activity.shape[1]):
- if np.std(real_activity[:, i]) == 0 or np.std(predicted_activity[:, i]) == 0:
- correlations.append(0)
- else:
- corr = np.corrcoef(real_activity[:, i], predicted_activity[:, i])[0, 1]
- correlations.append(corr)
- correlations = np.nan_to_num(correlations, nan=0)
- correlations = np.maximum(correlations, 0)
- s = max(2, 100 / np.sqrt(centers.shape[1]))
- np.save(os.path.join(res_path, f'correlations_{suffix}.npy'), {
- 'correlations': correlations,
- })
- np.save(os.path.join(res_path, f'real_predicted_activity_centers_{suffix}.npy'), {
- 'real_activity': real_activity,
- 'predicted_activity': predicted_activity,
- 'centers': centers,
- })
- # Plotting scatter plots
- for vmax_value in [0.6, 1]:
- plt.figure(figsize=(10, 8))
- scatter = plt.scatter(
- centers[0, :],
- centers[1, :],
- c=correlations,
- cmap='Reds',
- s=10,
- alpha=correlations,
- edgecolors='none',
- vmin=0,
- vmax=vmax_value
- )
- cbar = plt.colorbar(scatter)
- cbar.set_label('Pearson Correlation')
- plt.xlabel('X Position')
- plt.ylabel('Y Position')
- plt.title(f'Neuron Activity Correlation ({suffix})')
- save_dir = os.path.join(res_path, "neuron_correlation_maps")
- os.makedirs(save_dir, exist_ok=True)
- plt.savefig(os.path.join(save_dir, f"neuron_correlation_{suffix}_{vmax_value}.png"), dpi=300)
- plt.savefig(os.path.join(save_dir, f"neuron_correlation_{suffix}_{vmax_value}.pdf"))
- plt.close()
- # Calculate distance from center
- center_point = np.mean(centers, axis=1)
- distances = np.linalg.norm(centers.T - center_point, axis=1)
- # Define a threshold to separate central and peripheral neurons
- threshold_distance = np.percentile(distances, 50) # Median distance as separation
- central_correlations = correlations[distances <= threshold_distance]
- peripheral_correlations = correlations[distances > threshold_distance]
- # Plot average correlation
- plt.figure()
- plt.bar(['Central', 'Peripheral'], [np.mean(central_correlations), np.mean(peripheral_correlations)])
- plt.ylabel('Average Pearson Correlation')
- plt.title('Average Correlation: Central vs Peripheral Neurons')
- plt.savefig(os.path.join(save_dir, f"average_correlation_central_vs_peripheral_{suffix}.png"), dpi=300)
- plt.savefig(os.path.join(save_dir, f"average_correlation_central_vs_peripheral_{suffix}.pdf"))
- plt.close()
- # Plot correlation vs distance
- plt.figure()
- plt.scatter(distances, correlations, c=correlations, cmap='Reds')
- plt.colorbar(label='Pearson Correlation')
- plt.xlabel('Distance from Center')
- plt.ylabel('Pearson Correlation')
- plt.title('Correlation vs Distance from Center')
- plt.savefig(os.path.join(save_dir, f"correlation_vs_distance_{suffix}.png"), dpi=300)
- plt.savefig(os.path.join(save_dir, f"correlation_vs_distance_{suffix}.pdf"))
- plt.close()
- plot_quantitative_statistics(correlations, res_path, suffix)
- # def plot_neuron_correlation(real_activity, predicted_activity, centers, res_path, suffix):
- # correlations = []
- # for i in range(real_activity.shape[1]):
- # if np.std(real_activity[:, i]) == 0 or np.std(predicted_activity[:, i]) == 0:
- # correlations.append(0)
- # else:
- # corr = np.corrcoef(real_activity[:, i], predicted_activity[:, i])[0, 1]
- # correlations.append(corr)
- # correlations = np.nan_to_num(correlations, nan=0)
- # correlations = np.maximum(correlations, 0)
- # s = max(2, 100 / np.sqrt(centers.shape[1]))
- # np.save(os.path.join(res_path, f'correlations_{suffix}.npy'), {
- # 'correlations': correlations,
- # })
- # np.save(os.path.join(res_path, f'real_predicted_activity_centers_{suffix}.npy'), {
- # 'real_activity': real_activity,
- # 'predicted_activity': predicted_activity,
- # 'centers': centers,
- # })
- # plt.figure(figsize=(10, 8))
- # scatter = plt.scatter(
- # centers[0, :],
- # centers[1, :],
- # c=correlations,
- # cmap='Reds',
- # s=10,
- # alpha=correlations,
- # edgecolors='none',
- # vmin=0,
- # vmax=0.6
- # )
- # cbar = plt.colorbar(scatter)
- # cbar.set_label('Pearson Correlation')
- # plt.xlabel('X Position')
- # plt.ylabel('Y Position')
- # plt.title(f'Neuron Activity Correlation ({suffix})')
- # save_dir = os.path.join(res_path, "neuron_correlation_maps")
- # os.makedirs(save_dir, exist_ok=True)
- # plt.savefig(os.path.join(save_dir, f"neuron_correlation_{suffix}_0.6.png"), dpi=300)
- # plt.savefig(os.path.join(save_dir, f"neuron_correlation_{suffix}_0.6.pdf"))
- # plt.close()
- # plt.figure(figsize=(10, 8))
- # scatter = plt.scatter(
- # centers[0, :],
- # centers[1, :],
- # c=correlations,
- # cmap='Reds',
- # s=10,
- # alpha=correlations,
- # edgecolors='none',
- # vmin=0,
- # vmax=1
- # )
- # cbar = plt.colorbar(scatter)
- # cbar.set_label('Pearson Correlation')
- # plt.xlabel('X Position')
- # plt.ylabel('Y Position')
- # plt.title(f'Neuron Activity Correlation ({suffix})')
- # save_dir = os.path.join(res_path, "neuron_correlation_maps")
- # os.makedirs(save_dir, exist_ok=True)
- # plt.savefig(os.path.join(save_dir, f"neuron_correlation_{suffix}_1.png"), dpi=300)
- # plt.savefig(os.path.join(save_dir, f"neuron_correlation_{suffix}_1.pdf"))
- # plt.close()
- # plot_quantitative_statistics(correlations, res_path, suffix)
- def reduced_rank_regressions_ym(ranks, ECoG_Extracted_Features, projs1, projs2, lams, res_path,
- ex_itrain, ex_itest, ex_u, ex_v, nsvc_predict, trainX, testX, centers):
- nrank1 = ranks[ranks <= ECoG_Extracted_Features.shape[1]]
- print("nrank1:", nrank1)
- n_nneurs = 0
- t_start_plot = 50
- t_end_plot = 400
- for l in tqdm(range(len(lams))): # try various regularization
- atrain, btrain, _, _ = canonical_cov(
- projs1[ex_itrain[n_nneurs], :], ECoG_Extracted_Features[ex_itrain[n_nneurs], :], lams[l], npc=max(nrank1)
- )
- atest, btest, _, _ = canonical_cov(
- projs2[ex_itrain[n_nneurs], :], ECoG_Extracted_Features[ex_itrain[n_nneurs], :], lams[l], npc=max(nrank1)
- )
- for k in tqdm(range(len(nrank1))): # try various ranks
- vp_train = (
- atrain[:, :nrank1[k]] @ btrain[:, :nrank1[k]].T @ ECoG_Extracted_Features.T
- )
- vp_test = atest[:, :nrank1[k]] @ btest[:, :nrank1[k]].T @ ECoG_Extracted_Features.T
- window_length = 51
- polyorder = 11
- vp_train_filtered = savgol_filter(vp_train.T, window_length=window_length, polyorder=polyorder, axis=0).T
- vp_test_filtered = savgol_filter(vp_test.T, window_length=window_length, polyorder=polyorder, axis=0).T
- vp_train = vp_train_filtered
- vp_test = vp_test_filtered
- print("vp_train:", vp_train.shape)
- print("vp_test:", vp_test.shape)
- print("projs1:", projs1.shape)
- print("projs2:", projs2.shape)
- plot_components = [0, 1, 2, 3, 4, 5, 6, 7, 15, 31, 63]
- def save_plots(proj, vp, filepath_suffix, filename_suffix):
- fig, axes = plt.subplots(len(plot_components), 1, figsize=(15, 25))
- for i, vec_idx in enumerate(plot_components):
- ax = axes[i]
- ax.plot(proj[t_start_plot*10:t_end_plot*10, vec_idx], color='b', alpha=0.5, label='real')
- ax.plot(vp.T[t_start_plot*10:t_end_plot*10, vec_idx], color='r', alpha=0.5, label='predicted')
- ax.set_title(f'SVC {vec_idx + 1}')
- ax.legend()
- ax.set_xlabel('time')
- ax.set_ylabel('SVCs')
- plt.tight_layout()
- filename_png = f"SVCs_l{l}_k{k}_nneur{n_nneurs}_{filename_suffix}.png"
- filename_pdf = f"SVCs_l{l}_k{k}_nneur{n_nneurs}_{filename_suffix}.pdf"
- directory_path = os.path.join(res_path, "predicted_SVCs", filepath_suffix)
- os.makedirs(directory_path, exist_ok=True)
- filepath_png = os.path.join(directory_path, filename_png)
- filepath_pdf = os.path.join(directory_path, filename_pdf)
- plt.savefig(filepath_png)
- plt.savefig(filepath_pdf, format='pdf')
- fig.clf()
- def center_data(data, axis=0):
- mean = np.mean(data, axis=axis, keepdims=True)
- centered_data = data - mean
- return centered_data
- vp_train_filtered=center_data(vp_train_filtered,axis=1)
- vp_test_filtered =center_data(vp_test_filtered, axis=1)
- # Save plots using the defined helper function
- save_plots(projs1, vp_train_filtered, "Train_And_Test", "projs_1")
- save_plots(projs1[ex_itrain[n_nneurs]], vp_train_filtered[:, ex_itrain[n_nneurs]], "Train_Only" , "projs_1")
- save_plots(projs1[ex_itest[n_nneurs]], vp_train_filtered[:, ex_itest[n_nneurs]], "Test_Only", "projs_1")
- save_plots(projs2, vp_test_filtered, "Train_And_Test", "projs_2")
- save_plots(projs2[ex_itrain[n_nneurs]], vp_test_filtered[:, ex_itrain[n_nneurs]], "Train_Only" , "projs_2")
- save_plots(projs2[ex_itest[n_nneurs]], vp_test_filtered[:, ex_itest[n_nneurs]], "Test_Only", "projs_2")
- u_sub = ex_u[n_nneurs][:, :nsvc_predict]
- v_sub = ex_v[n_nneurs][:, :nsvc_predict]
- model = Rastermap(n_PCs=32, n_clusters=8).fit(np.hstack((trainX, testX)).T)
- if (l==len(lams)-1) and (k==len(nrank1)-1):
- np.save(os.path.join(res_path, 'vp_train_test__projs1_2.npy'), {
- 'vp_train': vp_train,
- 'vp_test': vp_test,
- 'projs1': projs1,
- 'projs2':projs2
- })
- plot_burst=1
- KBD1=191.4
- burst_start=[241, 244.2, 247.3, 252.2, 255.5, 258.8, 265, 270, 279.1, 280, 286.9, 301.9, 311.8, 317.5, 323.4, 334.1, 338.7, 350.6, 368.5, 376.6]
- supp_start=[243.5, 246.1, 248.8, 254, 257.8, 260, 270, 275.4, 280, 283.4, 289.8, 304, 312.5, 318.5, 324.4, 334.5, 339.5, 351.4, 369.5, 377.7]
- burst_start = np.array(burst_start)
- supp_start = np.array(supp_start)
- burst_start=burst_start-KBD1+120
- supp_start=supp_start-KBD1+120
- sampling_rate = 10
- def calculate_intervals(start_times, end_times):
- return [
- (int(start * sampling_rate), int(end * sampling_rate))
- for start, end in zip(start_times, end_times)
- ]
- if plot_burst == 1:
- # Burst time intervals
- burst_intervals = calculate_intervals(burst_start, supp_start)
- selected_indices = np.concatenate([np.arange(start, end) for start, end in burst_intervals])
- else:
- # Supp time intervals, excluding the last-to-first transition
- supp_intervals = calculate_intervals(supp_start[:-1], burst_start[1:])
- selected_indices = np.concatenate([np.arange(start, end) for start, end in supp_intervals])
- # Function to slice data using indices
- def get_sliced_data(data, indices):
- return data[indices, :]
- # Plotting logic
- compare_and_plot(
- model,
- get_sliced_data(trainX, selected_indices),
- get_sliced_data(testX, selected_indices),
- u_sub,
- v_sub,
- vp_train[:, selected_indices],
- vp_test[:, selected_indices],
- l,
- k,
- res_path,
- "Train_And_Test",
- centers
- )
- # Filter the indices for test and train specifically within selected_indices
- selected_test_indices = ex_itest[n_nneurs][np.isin(ex_itest[n_nneurs], selected_indices)]
- selected_train_indices = ex_itrain[n_nneurs][np.isin(ex_itrain[n_nneurs], selected_indices)]
- compare_and_plot(
- model,
- trainX[selected_test_indices, :],
- testX[selected_test_indices, :],
- u_sub,
- v_sub,
- vp_train[:, selected_test_indices],
- vp_test[:, selected_test_indices],
- l,
- k,
- res_path,
- "Test_Only",
- centers
- )
- compare_and_plot(
- model,
- trainX[selected_train_indices, :],
- testX[selected_train_indices, :],
- u_sub,
- v_sub,
- vp_train[:, selected_train_indices],
- vp_test[:, selected_train_indices],
- l,
- k,
- res_path,
- "Train_Only",
- centers
- )
- break
- plot_ane=1
- if plot_ane:
- compare_and_plot(model, trainX[ex_itest[n_nneurs][(ex_itest[n_nneurs] >= 500) & (ex_itest[n_nneurs] <= 4000)], :],
- testX[ex_itest[n_nneurs][(ex_itest[n_nneurs] >= 500) & (ex_itest[n_nneurs] <= 4000)], :],
- u_sub, v_sub,
- vp_train[:, ex_itest[n_nneurs][(ex_itest[n_nneurs] >= 500) & (ex_itest[n_nneurs] <= 4000)]],
- vp_test[:, ex_itest[n_nneurs][(ex_itest[n_nneurs] >= 500) & (ex_itest[n_nneurs] <= 4000)]],
- l, k, res_path, "Test_Only", centers)
- break
- compare_and_plot(model, trainX[500:4000, :], testX[500:4000, :], u_sub, v_sub, vp_train[:, 500:4000], vp_test[:, 500:4000], l, k, res_path, "Train_And_Test", centers)
- compare_and_plot(model, trainX[ex_itrain[n_nneurs][(ex_itrain[n_nneurs] >= 500) & (ex_itrain[n_nneurs] <= 4000)], :],
- testX[ex_itrain[n_nneurs][(ex_itrain[n_nneurs] >= 500) & (ex_itrain[n_nneurs] <= 4000)], :],
- u_sub, v_sub,
- vp_train[:, ex_itrain[n_nneurs][(ex_itrain[n_nneurs] >= 500) & (ex_itrain[n_nneurs] <= 4000)]],
- vp_test[:, ex_itrain[n_nneurs][(ex_itrain[n_nneurs] >= 500) & (ex_itrain[n_nneurs] <= 4000)]],
- l, k, res_path, "Train_Only", centers)
- else:
- new_start1 = 0
- new_end1 = 500
- new_start2 = 4000
- new_end2 = 9000
- combined_slice = np.r_[new_start1:new_end1, new_start2:new_end2]
- compare_and_plot(model,
- trainX[combined_slice, :],
- testX[combined_slice, :],
- u_sub, v_sub,
- vp_train[:, combined_slice],
- vp_test[:, combined_slice],
- l, k, res_path,
- "Train_And_Test", centers)
- test_condition = ((ex_itest[n_nneurs] >= new_start1) & (ex_itest[n_nneurs] < new_end1)) | \
- ((ex_itest[n_nneurs] >= new_start2) & (ex_itest[n_nneurs] < new_end2))
- selected_test_indices = ex_itest[n_nneurs][test_condition]
- compare_and_plot(model,
- trainX[selected_test_indices, :],
- testX[selected_test_indices, :],
- u_sub, v_sub,
- vp_train[:, selected_test_indices],
- vp_test[:, selected_test_indices],
- l, k, res_path,
- "Test_Only", centers)
- break
- train_condition = ((ex_itrain[n_nneurs] >= new_start1) & (ex_itrain[n_nneurs] < new_end1)) | \
- ((ex_itrain[n_nneurs] >= new_start2) & (ex_itrain[n_nneurs] < new_end2))
- selected_train_indices = ex_itrain[n_nneurs][train_condition]
- compare_and_plot(model,
- trainX[selected_train_indices, :],
- testX[selected_train_indices, :],
- u_sub, v_sub,
- vp_train[:, selected_train_indices],
- vp_test[:, selected_train_indices],
- l, k, res_path,
- "Train_Only", centers)
- def center_data(data, axis=0):
- mean = np.mean(data, axis=axis, keepdims=True)
- centered_data = data - mean
- return centered_data
- def reduced_rank_regressions_ym_2(ranks, ECoG_Extracted_Features, projs1, projs2, lams, res_path,
- ex_itrain, ex_itest, ex_u, ex_v, nsvc_predict, trainX, testX, centers):
- nrank1 = ranks[ranks <= ECoG_Extracted_Features.shape[1]]
- print("nrank1:", nrank1)
- n_nneurs = 0
- t_start_plot = 50
- t_end_plot = 400
- for l in tqdm(range(len(lams))):
- vp_combined_train = np.zeros((projs1.shape[1], ECoG_Extracted_Features.shape[0]))
- vp_combined_test = np.zeros_like(vp_combined_train)
- # cross1: use ex_itrain as training set, use ex_itest as test set
- atrain_p1, btrain_p1, _, _ = canonical_cov(
- projs1[ex_itrain[n_nneurs], :], ECoG_Extracted_Features[ex_itrain[n_nneurs], :], lams[l], npc=max(nrank1)
- )
- atest_p1, btest_p1, _, _ = canonical_cov(
- projs2[ex_itrain[n_nneurs], :], ECoG_Extracted_Features[ex_itrain[n_nneurs], :], lams[l], npc=max(nrank1)
- )
- # cross2: use ex_itest as training set, use ex_itrain as test set
- atrain_p2, btrain_p2, _, _ = canonical_cov(
- projs1[ex_itest[n_nneurs], :], ECoG_Extracted_Features[ex_itest[n_nneurs], :], lams[l], npc=max(nrank1)
- )
- atest_p2, btest_p2, _, _ = canonical_cov(
- projs2[ex_itest[n_nneurs], :], ECoG_Extracted_Features[ex_itest[n_nneurs], :], lams[l], npc=max(nrank1)
- )
- for k in tqdm(range(len(nrank1))): # try various ranks
- vp_train_p1 = (
- atrain_p1[:, :nrank1[k]] @ btrain_p1[:, :nrank1[k]].T @ ECoG_Extracted_Features[ex_itest[n_nneurs]].T
- )
- vp_test_p1 = atest_p1[:, :nrank1[k]] @ btest_p1[:, :nrank1[k]].T @ ECoG_Extracted_Features[ex_itest[n_nneurs]].T
- vp_train_p1=center_data(vp_train_p1,axis=1)
- vp_test_p1 =center_data(vp_test_p1, axis=1)
- vp_combined_train[:, ex_itest[n_nneurs]] = zscore(vp_train_p1.T).T
- vp_combined_test[:, ex_itest[n_nneurs]] = zscore(vp_test_p1.T).T
- vp_train_p2 = (
- atrain_p2[:, :nrank1[k]] @ btrain_p2[:, :nrank1[k]].T @ ECoG_Extracted_Features[ex_itrain[n_nneurs]].T
- )
- vp_test_p2 = atest_p2[:, :nrank1[k]] @ btest_p2[:, :nrank1[k]].T @ ECoG_Extracted_Features[ex_itrain[n_nneurs]].T
- vp_train_p2=center_data(vp_train_p2,axis=1)
- vp_test_p2 =center_data(vp_test_p2, axis=1)
- vp_combined_train[:, ex_itrain[n_nneurs]] = zscore(vp_train_p2.T).T
- vp_combined_test[:, ex_itrain[n_nneurs]] = zscore(vp_test_p2.T).T
- # filter
- window_length = 51
- polyorder = 11
- vp_combined_train_filtered = savgol_filter(vp_combined_train.T, window_length, polyorder, axis=0).T
- vp_combined_test_filtered = savgol_filter(vp_combined_test.T, window_length, polyorder, axis=0).T
- # plot and save
- plot_components = [0, 1, 2, 3, 4, 5, 6, 7, 15, 31, 63]
- def save_plots(proj, vp, filepath_suffix, filename_suffix):
- fig, axes = plt.subplots(len(plot_components), 1, figsize=(15, 25))
- for i, vec_idx in enumerate(plot_components):
- ax = axes[i]
- ax.plot(proj[t_start_plot*10:t_end_plot*10, vec_idx], color='b', alpha=0.5, label='real')
- ax.plot(vp.T[t_start_plot*10:t_end_plot*10, vec_idx], color='r', alpha=0.5, label='predicted')
- ax.set_title(f'SVC {vec_idx + 1}')
- ax.legend()
- ax.set_xlabel('time')
- ax.set_ylabel('SVCs')
- plt.tight_layout()
- filename_png = f"SVCs_l{l}_k{k}_nneur{n_nneurs}_{filename_suffix}.png"
- filename_pdf = f"SVCs_l{l}_k{k}_nneur{n_nneurs}_{filename_suffix}.pdf"
- directory_path = os.path.join(res_path, "predicted_SVCs", filepath_suffix)
- os.makedirs(directory_path, exist_ok=True)
- filepath_png = os.path.join(directory_path, filename_png)
- filepath_pdf = os.path.join(directory_path, filename_pdf)
- plt.savefig(filepath_png)
- plt.savefig(filepath_pdf, format='pdf')
- fig.clf()
- save_plots(projs1, vp_combined_train_filtered, "2-fold cross validation", "projs_1")
- save_plots(projs2, vp_combined_test_filtered, "2-fold cross validation", "projs_2")
- u_sub = ex_u[n_nneurs][:, :nsvc_predict]
- v_sub = ex_v[n_nneurs][:, :nsvc_predict]
- model = Rastermap(n_PCs=32, n_clusters=8).fit(np.hstack((trainX, testX)).T)
- # test_indices = ex_itest[n_nneurs][(ex_itest[n_nneurs] >= 500) & (ex_itest[n_nneurs] <= 4000)]
- compare_and_plot(model, trainX[500:4000], testX[500:4000], u_sub, v_sub,
- vp_combined_train_filtered[:, 500:4000], vp_combined_test_filtered[:, 500:4000],
- l, k, res_path, "2-fold cross validation")
utils_ym.py at commit 30759da, under GPL-3.0 · at the source
Overview
- Beijing National Research Center for Information Science and Technology, Tsinghua University, Beijing, China
- Department of Automation, Tsinghua University, Beijing, China
- Institute for Brain and Cognitive Sciences, Tsinghua University, Beijing, China
- School of Biomedical Engineering, Tsinghua University, Beijing, China
- Key Laboratory of Polymer Chemistry and Physics of Ministry of Education, School of Materials Science and Engineering, Peking University, Beijing, China
- IDG/McGovern Institute for Brain Research, Tsinghua University, Beijing, China
Abstract
Burst suppression is widely observed across cortical regions during reversible or pathological unconsciousness, yet its neuronal organization remains incompletely understood. Here we present an integrated Cortex-wide Optical-electrical Dual-modal Explorer (CODE) system to examine neuronal dynamics during burst suppression under isoflurane anesthesia in the mouse. We identified distinct cortex-wide neuronal ensembles that alternately associate with burst or suppression events, exhibiting dynamic neuronal recruitment and reactivation during anesthesia. Burst events were marked by highly synchronized neuronal activity early in the burst phase with high functional connectivity, whereas suppression events displayed more asynchronous, temporally distributed activity with reduced connectivity. Transitions between these states involved sequential, directionally organized propagation across cortical regions. ECoG bursts propagated from bilateral sensory cortices to motor areas within tens of milliseconds with increasing synchrony with calcium activity. Furthermore, we established a robust metric linking ECoG and calcium signals, revealing state-dependent interpretability. These findings reveal the single-neuron-to-populat
Reproduced under the paper's license (CC BY), from the paper cited above.
Repositories
Its files are read in the Code ↔ Paper reader above, with 7 matches between paragraphs and lines of code.
Zenodo 18295118
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
- 30 September 2026: the link answers (HTTP 200)
10 files
- 01_data_pre-processing/
011_find_burst_timestamp , Jupyter, 48 liness.ipynb - 01_data_pre-processing/
012_data_processing_and_ , Jupyter, 578 linesclassification.ipynb - 02_burst_generation_anal
ysis/ , Jupyter, 116 lines021_active_neuron_counts .ipynb - 02_burst_generation_anal
ysis/ , Jupyter, 153 lines022_event_durations_vs_a ctive_neuron_counts.ipyn b - 02_burst_generation_anal
ysis/ , Jupyter, 155 lines023_active_neuron_map.ip ynb - 02_burst_generation_anal
ysis/ , Jupyter, 652 lines024_sorted_neurons_and_s tatistics.ipynb - 03_burst_propagation_ana
lysis/ , Jupyter, 176 lines031_ecog_and_calcium_tra ce.ipynb - 03_burst_propagation_ana
lysis/ , Jupyter, 205 lines032_multiple_channels_an alysis.ipynb - 04_supplementary_figures
/ , Jupyter, 210 linesm05_multiple_channels_an alysis.ipynb - 04_supplementary_figures
/ , Jupyter, 654 linesm05_sorted_neurons_and_s tatistics.ipynb - repository limit reached (2,000 files or 30 MB): the rest is at the source
YangMoTsinghua/Predict_Calcium_From_ECoG
30759da57e27e02008b29f378ed0405ab04e8da7, 13 August 2025Availability: 1 check, the latest on 30 September 2026: the link answers
- 30 September 2026: the link answers
9 files
- Predict_All.ipynb, Jupyter, 530 lines, 1 match
- correlation maps.ipynb, Jupyter, 235 lines
- extra_utils_for_populati
on_coding/ , Python, 470 lines, 1 matchdimred.py - extra_utils_for_scaling_
analysis/ , Python, 464 lines, 1 matchpredict.py - extra_utils_for_scaling_
analysis/ , Python, 452 lines, 1 matchsvca.py - extra_utils_for_scaling_
analysis/ , Python, 832 lines, 3 matchesutils_ym.py - LICENSE.md, License, 674 lines
- README.md, Text, 24 lines
- README.txt, Text, 33 lines
IrisRegion/Burst_suppression_analysis_based_on_cortex-wide_neural_optoelectronic_interface
382be8ac1fa8e3a312618c2cf085321528d1183f, 26 September 2024Availability: 1 check, the latest on 30 September 2026: the link answers
- 30 September 2026: the link answers
10 files
- 01_data_pre-processing/
011_find_burst_timestamp , Jupyter, 48 liness.ipynb - 01_data_pre-processing/
012_data_processing_and_ , Jupyter, 578 linesclassification.ipynb - 02_burst_generation_anal
ysis/ , Jupyter, 116 lines021_active_neurons_in_fi xed_duration.ipynb - 02_burst_generation_anal
ysis/ , Jupyter, 153 lines022_duration_vs_active_n eurons.ipynb - 02_burst_generation_anal
ysis/ , Jupyter, 155 lines023_neuron_map_plot.ipyn b - 02_burst_generation_anal
ysis/ , Jupyter, 652 lines024_sorting_neurons_and_ statistics.ipynb - 02_burst_generation_anal
ysis/ , Jupyter, 916 lines025_neurons_transition.i pynb - 03_burst_propagation_ana
lysis/ , Jupyter, 176 lines031_plot_ecog_and_calc_t race.ipynb - 03_burst_propagation_ana
lysis/ , Jupyter, 205 lines032_multi_channels_analy sis.ipynb - 04_supplementary_figures
/ , Jupyter, 210 linesm05_multi_channels_analy sis.ipynb - repository limit reached (2,000 files or 30 MB): the rest is at the source (6 files)
Code availability
All custom code used for data analysis is available at the following repositories: https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 3 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 26 scripts, each with its path and the digest of its content;
- 7 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
Datasets cited
- zenodo:18324142, at Zenodo; found in “Data availability”
Data availability
The calcium imaging raw data supporting the findings of this study exceed 100 TB in size. To facilitate access, representative demo data used for the analyses are available at 10.5281/
Reproduced under the paper's license (CC BY), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 30 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 18 authors, 3 keywords, 8 MeSH terms, 2 funders, 64 references.
Cite
This paper
Xiao, G., Yang, M., Li, L., Yao, X., Xie, J., Wang, X., Zang, J., Zhao, Y., Fang, T., Wu, S., Qi, W., Lin, S., Sun, W., Lei, T., Hong, B., Wu, J., Dai, Q., & Dai, X. (2026). Dynamic neuronal ensembles encode burst-suppression revealed by cortex-wide optical-electrical interfaces. Nature communications, 17(1), 5872. https://
BibTeX
@article{xiao2026dynamic
author = {Xiao, Guihua and Yang, Mo and Li, Lingbo and Yao, Xintong and Xie, Jingyu and Wang, Xinyue and Zang, Jinyu and Zhao, Yan and Fang, Tianyi and Wu, Shuying and Qi, Wandi and Lin, Shipeng and Sun, Wenxi and Lei, Ting and Hong, Bo and Wu, Jiamin and Dai, Qionghai and Dai, Xiaochuan},
title = {{Dynamic neuronal ensembles encode burst-suppression revealed by cortex-wide optical-electrical interfaces}},
journal = {Nature communications},
year = {2026},
month = apr,
volume = {17},
number = {1},
pages = {5872},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/
url = {https://
pmid = {42056115},
pmcid = {PMC13333928}
}
RIS
TY - JOUR
AU - Xiao, Guihua
AU - Yang, Mo
AU - Li, Lingbo
AU - Yao, Xintong
AU - Xie, Jingyu
AU - Wang, Xinyue
AU - Zang, Jinyu
AU - Zhao, Yan
AU - Fang, Tianyi
AU - Wu, Shuying
AU - Qi, Wandi
AU - Lin, Shipeng
AU - Sun, Wenxi
AU - Lei, Ting
AU - Hong, Bo
AU - Wu, Jiamin
AU - Dai, Qionghai
AU - Dai, Xiaochuan
TI - Dynamic neuronal ensembles encode burst-suppression revealed by cortex-wide optical-electrical interfaces
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/
VL - 17
IS - 1
SP - 5872
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1038/
"type": "article-journal",
"title": "Dynamic neuronal ensembles encode burst-suppression revealed by cortex-wide optical-electrical interfaces",
"container-title": "Nature communications",
"author": [
{
"family": "Xiao",
"given": "Guihua"
},
{
"family": "Yang",
"given": "Mo"
},
{
"family": "Li",
"given": "Lingbo"
},
{
"family": "Yao",
"given": "Xintong"
},
{
"family": "Xie",
"given": "Jingyu"
},
{
"family": "Wang",
"given": "Xinyue"
},
{
"family": "Zang",
"given": "Jinyu"
},
{
"family": "Zhao",
"given": "Yan"
},
{
"family": "Fang",
"given": "Tianyi"
},
{
"family": "Wu",
"given": "Shuying"
},
{
"family": "Qi",
"given": "Wandi"
},
{
"family": "Lin",
"given": "Shipeng"
},
{
"family": "Sun",
"given": "Wenxi"
},
{
"family": "Lei",
"given": "Ting"
},
{
"family": "Hong",
"given": "Bo"
},
{
"family": "Wu",
"given": "Jiamin"
},
{
"family": "Dai",
"given": "Qionghai"
},
{
"family": "Dai",
"given": "Xiaochuan"
}
],
"container-title-short":
"volume": "17",
"issue": "1",
"page": "5872",
"DOI": "10.1038/
"PMID": "42056115",
"PMCID": "PMC13333928",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
29
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.7554/elife.109717 [code]
- Retrosplenial cortex enables context-dependent goal-directed sensorimotor transformation.Journal: eLifeIn common: tifffile, OpenCV, h5py, 7 other tools, systems, mouse, 3 references
- [2] doi:10.1038/s41592-026-03154-2 [code]
- Simultaneous single-cell calcium imaging of neuronal population activity and brain-wide BOLD fMRI.Journal: Nature methodsIn common: tifffile, OpenCV, h5py, 5 other tools, mouse, 3 references
- [3] doi:10.1016/j.xcrm.2026.102766 [code]
- A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.Journal: Cell reports. MedicineIn common: tifffile, NetworkX, OpenCV, 8 other tools
- [4] doi:10.1038/s41598-026-57519-w [code]
- Automated segmentation of neurons and spinal cord structures in immunofluorescence images using SpineDL.Journal: Scientific reportsIn common: tifffile, NetworkX, OpenCV, 7 other tools, mouse
- [5] doi:10.7554/elife.100880 [code]
- An applicable and efficient retrograde monosynaptic circuit mapping tool for larval zebrafish.Journal: eLifeIn common: tifffile, NetworkX, OpenCV, 7 other tools, systems
- [6] doi:10.1016/j.isci.2026.116206 [code]
- Gut distension evokes rapid neural dynamics in vagal and hindbrain populations of larval zebrafish.Journal: iScienceIn common: tifffile, NetworkX, OpenCV, 7 other tools, systems
- [7] doi:10.3389/fnsys.2026.1822122 [code]
- Convergence-divergence circuits for multimodal integration of innate and learned opponent valences.Journal: Frontiers in systems neuroscienceIn common: tifffile, NetworkX, h5py, 7 other tools, systems
- [8] doi:10.1016/j.isci.2026.116825 [code]
- Social hierarchy shapes behavioral and transcriptional responses to chronic stress and ketamine in male mice.Journal: iScienceIn common: NetworkX, OpenCV, h5py, 7 other tools, systems, mouse
- [9] doi:10.1038/s41593-026-02232-0 [code]
- Entorhinal cortex represents task-relevant remote locations independently of CA1.Journal: Nature neuroscienceIn common: NetworkX, OpenCV, h5py, 7 other tools, systems, mouse
- [10] doi:10.1038/s41467-026-74976-z [code]
- Real-time robust autofocus method enabling sustained intravital scanning light field imaging.Journal: Nature communicationsIn common: tifffile, OpenCV, NumPy, mouse, 1 reference, author Jiamin Wu
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 3 repositories of the authors' code, each at its verified commit and with its license, 26 scripts, and 7 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:c6f74f0fad1bfe09…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
