OSCR

AI-Driven Mapping of Seizure Spread Patterns.

Code ↔ Paper

7 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 7 matches
  1. [1] § Materials and Methods › Generalized Linear Models to Quantify the Relationship Between Structural Connectivity and Timing of Spread ↔ papers/white_matter_iEEG/REVELL_MDPHD_THESIS_WORK.py, lines 580–641 · score 0.68 · linear_model, Tweedie regressor, power
  2. [2] § Materials and Methods › Generalized Linear Models to Quantify the Relationship Between Structural Connectivity and Timing of Spread ↔ papers/white_matter_iEEG/white_matter_iEEG.py, lines 613–674 · score 0.68 · linear_model, Tweedie regressor, power
  3. [3] § Materials and Methods › Validation of Seizure Spread Algorithms: Median Rank Percent of Seizure Onset Contacts ↔ papers/seizureSpread/Script_08_seizure_model_comparisons.py, lines 274–332 · score 0.64 · median ranking, absolute slope, CNN, LSTM, broadband, seizure spread
  4. [4] § Materials and Methods › Structural Connectivity › Structural Network Generation ↔ papers/brainAtlas/brainAtlasAnalysis.py, lines 178–202 · score 0.62 · tractography generates, DSI Studio, tracts, structural connectivity, atlas, network
  5. [5] § Materials and Methods › Structural Connectivity › Structural Network Generation ↔ papers/brainAtlas/structure_function_correlation.py, lines 15–160 · score 0.61 · DSI Studio, atlas regions, structural connectivity, tracking, transformed, log
  6. [6] § Materials and Methods › Validation of Seizure Spread Algorithms: Median Rank Percent of Seizure Onset Contacts ↔ papers/seizureSpread/Script_04_seizure_spread_vs_SOZ.py, lines 885–925 · score 0.57 · median ranking, absolute slope, CNN, LSTM, broadband, seizure spread
  7. [7] § Materials and Methods › Pre‐Processing of EEG ↔ packages/dataclass/dataclass_iEEG_metadata.py, lines 175–228 · score 0.53 · pre whitened, bipolar, downsampled, filtered, interictal, channel

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 · 1,423 lines · 68 KB · no license · 1 match

  1. """
  2. Andy Revell's MD/PHD thesis work
  3. 2021
  4. """
  5. #%% 1/4 Imports
  6. import sys
  7. import os
  8. import json
  9. import copy
  10. import time
  11. import bct
  12. import glob
  13. import math
  14. import random
  15. import pickle
  16. import pingouin
  17. import pkg_resources
  18. import pandas as pd
  19. import numpy as np
  20. import seaborn as sns
  21. import nibabel as nib
  22. import multiprocessing
  23. import networkx as nx
  24. import statsmodels.api as sm
  25. from scipy import signal, stats
  26. from itertools import repeat
  27. from matplotlib import pyplot as plt
  28. from matplotlib import gridspec
  29. from scipy import interpolate
  30. from scipy.integrate import simps
  31. from scipy.stats import pearsonr, spearmanr
  32. from os.path import join, splitext, basename
  33. from pathos.multiprocessing import ProcessingPool as Pool
  34. #revellLab
  35. #utilities, constants/parameters, and thesis helper functions
  36. from revellLab.packages.utilities import utils
  37. from revellLab.MDPHD_THESIS import constants_parameters as params
  38. from revellLab.MDPHD_THESIS import constants_plotting as plot
  39. from revellLab.paths import constants_paths as paths
  40. from revellLab.MDPHD_THESIS.helpers import thesis_helpers as helper
  41. #package functions
  42. from revellLab.packages.dataclass import dataclass_atlases, dataclass_iEEG_metadata
  43. from revellLab.packages.eeg.ieegOrg import downloadiEEGorg
  44. from revellLab.packages.atlasLocalization import atlasLocalizationFunctions as atl
  45. from revellLab.packages.eeg.echobase import echobase
  46. from revellLab.packages.imaging.tractography import tractography
  47. from revellLab.packages.imaging.makeSphericalRegions import make_spherical_regions
  48. #plotting
  49. from revellLab.MDPHD_THESIS.plotting import plot_GMvsWM
  50. from revellLab.MDPHD_THESIS.plotting import plot_seizure_distributions
  51. #% 2/4 Paths and File names
  52. with open(paths.METADATA_IEEG_DATA) as f: JSON_iEEG_metadata = json.load(f)
  53. with open(paths.ATLAS_FILES_PATH) as f: JSON_atlas_files = json.load(f)
  54. with open(paths.IEEG_USERNAME_PASSWORD) as f: IEEG_USERNAME_PASSWORD = json.load(f)
  55. #data classes
  56. atlases = dataclass_atlases.dataclass_atlases(JSON_atlas_files)
  57. metadata_iEEG = dataclass_iEEG_metadata.dataclass_iEEG_metadata(JSON_iEEG_metadata)
  58. #% 3/4 Paramters
  59. #ieeg.org username and password
  60. USERNAME = IEEG_USERNAME_PASSWORD["username"]
  61. PASSWORD = IEEG_USERNAME_PASSWORD["password"]
  62. #montaging
  63. MONTAGE = params.MONTAGE_BIPOLAR
  64. SAVE_FIGURES = plot.SAVE_FIGURES[1]
  65. #Frequencies
  66. FREQUENCY_NAMES = params.FREQUENCY_NAMES
  67. FREQUENCY_DOWN_SAMPLE = params.FREQUENCY_DOWN_SAMPLE
  68. #Functional Connectivity
  69. FC_TYPES = params.FC_TYPES
  70. #States
  71. STATE_NAMES = params.STATE_NAMES
  72. STATE_NUMBER = params.STATE_NUMBER_TOTAL
  73. #Imaging
  74. SESSION = params.SESSION_IMPLANT
  75. SESSION_RESEARCH3T = params.SESSION_RESEARCH3T
  76. ACQ = params.ACQUISITION_RESEARCH3T_T1_MPRAGE
  77. IEEG_SPACE = params.IEEG_SPACE
  78. #Tissue definitions
  79. TISSUE_DEFINITION = params.TISSUE_DEFINITION_PERCENT
  80. TISSUE_DEFINITION_NAME = TISSUE_DEFINITION[0]
  81. TISSUE_DEFINITION_GM = TISSUE_DEFINITION[1]
  82. TISSUE_DEFINITION_WM = TISSUE_DEFINITION[2]
  83. WM_DEFINITION_SEQUENCE = TISSUE_DEFINITION[3]
  84. WM_DEFINITION_SEQUENCE_IND = TISSUE_DEFINITION[4]
  85. #% 4/4 General Parameter calculation
  86. # get all the patients with annotated seizures
  87. patientsWithseizures = metadata_iEEG.get_patientsWithSeizuresAndInterictal()
  88. N = len(patientsWithseizures)
  89. iEEGpatientList = np.unique(list(patientsWithseizures["subject"]))
  90. iEEGpatientList = ["sub-" + s for s in iEEGpatientList]
  91. #%% Graphing summary statistics of seizures and patient population
  92. #plot distribution of seizures per patient
  93. plot_seizure_distributions.plot_distribution_seizures_per_patient(patientsWithseizures)
  94. utils.save_figure(f"{paths.FIGURES}/seizureSummaryStats/seizureCounts2.pdf", save_figure = True)
  95. #plot distribution of seizure lengths
  96. plot_seizure_distributions.plot_distribution_seizure_length(patientsWithseizures)
  97. utils.save_figure(f"{paths.FIGURES}/seizureSummaryStats/seizureLengthDistribution2.pdf", save_figure = True)
  98. #%% Electrode and atlas localization
  99. atl.atlasLocalizationBIDSwrapper(iEEGpatientList, paths.BIDS, "PIER", SESSION, IEEG_SPACE, ACQ, paths.BIDS_DERIVATIVES_RECONALL, paths.BIDS_DERIVATIVES_ATLAS_LOCALIZATION,
  100. paths.ATLASES, paths.ATLAS_LABELS, paths.MNI_TEMPLATE, paths.MNI_TEMPLATE_BRAIN, multiprocess=False, cores=12, rerun=False)
  101. #%% EEG download and preprocessing of electrodes
  102. for i in range(len(patientsWithseizures)):
  103. metadata_iEEG.get_precitalIctalPostictal(patientsWithseizures["subject"][i], "Ictal", patientsWithseizures["idKey"][i], USERNAME, PASSWORD,
  104. BIDS=paths.BIDS, dataset="derivatives/iEEGorgDownload", session = SESSION, secondsBefore=180, secondsAfter=180, load=False)
  105. # get intertical
  106. associatedInterictal = metadata_iEEG.get_associatedInterictal(patientsWithseizures["subject"][i], patientsWithseizures["idKey"][i])
  107. metadata_iEEG.get_iEEGData(patientsWithseizures["subject"][i], "Interictal", associatedInterictal, USERNAME, PASSWORD,
  108. BIDS=paths.BIDS, dataset="derivatives/iEEGorgDownload", session= SESSION, startKey="Start", load=False)
  109. #%% Power analysis
  110. ###################################
  111. #WM power as a function of distance
  112. fname = join(paths.DATA, "GMvsWM",f"power_{MONTAGE}_{params.TISSUE_DEFINITION_DISTANCE[0]}_GM_{params.TISSUE_DEFINITION_DISTANCE[1]}_WM_{params.TISSUE_DEFINITION_DISTANCE[2]}.pickle")
  113. if utils.checkIfFileDoesNotExist(fname): #if power analysis already computed, then don't run
  114. powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM = helper.power_analysis(patientsWithseizures, np.array(range(3, N)), metadata_iEEG, USERNAME, PASSWORD, SESSION, FREQUENCY_DOWN_SAMPLE, MONTAGE, paths, params.TISSUE_DEFINITION_DISTANCE[0] , params.TISSUE_DEFINITION_DISTANCE[1], params.TISSUE_DEFINITION_DISTANCE[2] )
  115. utils.save_pickle( [powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM], fname)
  116. powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM = utils.open_pickle(fname)
  117. #Plots
  118. #show figure for paper: Power vs Distance and SNR
  119. plot_GMvsWM.plot_power_vs_distance_and_SNR(powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM)
  120. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"heatmap_pwr_vs_Distance_and_SNR_{MONTAGE}_{params.TISSUE_DEFINITION_DISTANCE[0]}_GM_{params.TISSUE_DEFINITION_DISTANCE[1]}_WM_{params.TISSUE_DEFINITION_DISTANCE[2]}.png"), save_figure= SAVE_FIGURES)
  121. #Show summary figure
  122. plot_GMvsWM.plotUnivariate(powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM)
  123. #boxplot comparing GM vs WM for the different seizure states (interictal, preictal, ictal, postictal)
  124. plot_GMvsWM.plot_boxplot_tissue_power_differences(powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM, plot.COLORS_TISSUE_LIGHT_MED_DARK[1], plot.COLORS_TISSUE_LIGHT_MED_DARK[2])
  125. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"boxplot_GM_vs_WM_seizure_state_{MONTAGE}_{params.TISSUE_DEFINITION_DISTANCE[0]}_GM_{params.TISSUE_DEFINITION_DISTANCE[1]}_WM_{params.TISSUE_DEFINITION_DISTANCE[2]}.pdf"), save_figure= SAVE_FIGURES)
  126. #statistics
  127. helper.power_analysis_stats(powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM)
  128. ####################################
  129. #WM power as a function of WM percent
  130. fname = join(paths.DATA, "GMvsWM",f"power_{MONTAGE}_{params.TISSUE_DEFINITION_PERCENT[0]}_GM_{params.TISSUE_DEFINITION_PERCENT[1]}_WM_{params.TISSUE_DEFINITION_PERCENT[2]}.pickle")
  131. if utils.checkIfFileDoesNotExist(fname): #if power analysis already computed, then don't run
  132. powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM = helper.power_analysis(patientsWithseizures, np.array(range(3, N)), metadata_iEEG, USERNAME, PASSWORD, SESSION, FREQUENCY_DOWN_SAMPLE, MONTAGE, paths, params.TISSUE_DEFINITION_PERCENT[0] , params.TISSUE_DEFINITION_PERCENT[1],params.TISSUE_DEFINITION_PERCENT[2] )
  133. utils.save_pickle( [powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM], fname)
  134. powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM = utils.open_pickle(fname)
  135. #Plots
  136. #Show summary figure
  137. plot_GMvsWM.plotUnivariatePercent(powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM)
  138. #boxplot comparing GM vs WM for the different seizure states (interictal, preictal, ictal, postictal)
  139. plot_GMvsWM.plot_boxplot_tissue_power_differences(powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM, plot.COLORS_TISSUE_LIGHT_MED_DARK[1], plot.COLORS_TISSUE_LIGHT_MED_DARK[2])
  140. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"boxplot_GM_vs_WM_seizure_state_{MONTAGE}_{params.TISSUE_DEFINITION_PERCENT[0]}_GM_{params.TISSUE_DEFINITION_PERCENT[1]}_WM_{params.TISSUE_DEFINITION_PERCENT[2]}.pdf"), save_figure= SAVE_FIGURES)
  141. #statistics
  142. helper.power_analysis_stats(powerGMmean, powerWMmean, powerDistAvg, SNRAll, distAll, paientList, powerGM, powerWM)
  143. #%% Calculating functional connectivity for whole seizure segment
  144. for fc in range(len(FC_TYPES)):
  145. for i in range(3, N):
  146. sub = patientsWithseizures["subject"][i]
  147. functionalConnectivityPath = join(paths.BIDS_DERIVATIVES_FUNCTIONAL_CONNECTIVITY_IEEG, f"sub-{sub}")
  148. utils.checkPathAndMake(functionalConnectivityPath, functionalConnectivityPath)
  149. metadata_iEEG.get_FunctionalConnectivity(patientsWithseizures["subject"][i], idKey = patientsWithseizures["idKey"][i], username = USERNAME, password = PASSWORD,
  150. BIDS =paths.BIDS, dataset ="derivatives/iEEGorgDownload", session = SESSION,
  151. functionalConnectivityPath = functionalConnectivityPath,
  152. secondsBefore=180, secondsAfter=180, startKey = "EEC",
  153. fsds = FREQUENCY_DOWN_SAMPLE, montage = MONTAGE, FCtype = FC_TYPES[fc])
  154. #%%
  155. #Combine FC from the above saved calculation, and calculate differences
  156. summaryStatsLong, FCtissueAll, seizure_number = helper.combine_functional_connectivity_from_all_patients_and_segments(patientsWithseizures, np.array(range(3, N)), metadata_iEEG, MONTAGE, FC_TYPES,
  157. STATE_NUMBER, FREQUENCY_NAMES, USERNAME, PASSWORD, FREQUENCY_DOWN_SAMPLE,
  158. paths, SESSION, params.TISSUE_DEFINITION_PERCENT[0], params.TISSUE_DEFINITION_PERCENT[1], params.TISSUE_DEFINITION_PERCENT[2])
  159. patient_outcomes_good = ["RID0238", "RID0267", "RID0279", "RID0294", "RID0307", "RID0309", "RID0320", "RID0365", "RID0440", "RID0424"]
  160. patient_outcomes_poor = ["RID0274", "RID0278", "RID0371", "RID0382", "RID0405", "RID0442", "RID0322"]
  161. patients = patient_outcomes_good + patient_outcomes_poor
  162. summaryStatsLong = helper.add_outcomes_to_summaryStatsLong(summaryStatsLong, patient_outcomes_good, patient_outcomes_poor)
  163. #%%
  164. #bootstrap
  165. medians_list = []
  166. means_deltaT_list = []
  167. cores = 12
  168. iterations = 12
  169. total = 409
  170. func = 2
  171. freq = 7
  172. for i in range(total):
  173. simulation = helper.deltaT_multicore_wrapper(cores, iterations, summaryStatsLong,
  174. FCtissueAll, STATE_NUMBER,seizure_number, FREQUENCY_NAMES,
  175. FC_TYPES,func ,freq , max_connections = 50)
  176. medians_list.append([a_tuple[0] for a_tuple in simulation])
  177. medians = [item for sublist in medians_list for item in sublist]
  178. means_deltaT_list.append([a_tuple[1] for a_tuple in simulation])
  179. means_deltaT = [item for sublist in means_deltaT_list for item in sublist]
  180. if i+1 ==total:
  181. medians = np.dstack(medians)
  182. means_deltaT = np.vstack(means_deltaT)
  183. utils.printProgressBar(i +1 , total)
  184. len(means_deltaT)
  185. fig, axes = utils.plot_make(c = STATE_NUMBER, size_length = 12, sharey = True)
  186. for x in range(STATE_NUMBER):
  187. data = pd.DataFrame( dict( gm = medians[0, x, :], wm = medians[1, x, :]))
  188. xlim = [math.floor(data.to_numpy().min() * 1000)/1000 , math.ceil(data.to_numpy().max() * 1000)/1000]
  189. sns.histplot(data =data, palette = plot.COLORS_TISSUE_LIGHT_MED_DARK[1], kde = True, ax = axes[x], bins = 10, line_kws=dict(linewidth = 8), edgecolor = None)
  190. #sns.kdeplot(data =data, palette = plot.COLORS_TISSUE_LIGHT_MED_DARK[1], ax = axes[x], linewidth = 10)
  191. axes[x].set_xlim(xlim)
  192. #axes[x].set_ylim([0,350])
  193. print(stats.wilcoxon(data["gm"], data["wm"])[1])
  194. axes[x].spines['top'].set_visible(False)
  195. axes[x].spines['right'].set_visible(False)
  196. pvalue = stats.wilcoxon(data["gm"], data["wm"])[1]
  197. axes[x].set_title(pvalue)
  198. #print(stats.mannwhitneyu(data["gm"], data["wm"])[1])
  199. utils.save_figure(join(paths.FIGURES, "GM_vs_WM",
  200. f"22boot_ECDF_all_patients_GMvsWM_ECDF2_{MONTAGE}_{params.TISSUE_DEFINITION_PERCENT[0]}_GM_{params.TISSUE_DEFINITION_PERCENT[1]}_WM_{params.TISSUE_DEFINITION_PERCENT[2]}.pdf"),
  201. save_figure=False)
  202. data = pd.DataFrame(means_deltaT, columns = STATE_NAMES)
  203. fig, axes = utils.plot_make()
  204. sns.histplot(data =data, palette = plot.COLORS_STATE4[1], kde = True, ax = axes, binwidth = 0.001, binrange = [-0.002,0.025],
  205. line_kws = dict(lw = 2), kde_kws = dict(bw_method = 1), edgecolor = None)
  206. #sns.kdeplot(data =data, palette = plot.COLORS_STATE4[1], ax = axes, lw = 5)
  207. data.mean()
  208. axes.set_xlim([-0.002,0.022])
  209. axes.spines['top'].set_visible(False)
  210. axes.spines['right'].set_visible(False)
  211. axes.set_title(f"{stats.wilcoxon(data['preictal'], data['ictal'])[1]} {stats.ttest_1samp(data['ictal'], 0)[1]}")
  212. for k in range(len(data.mean())):
  213. axes.axvline(x=data.mean()[k], color = plot.COLORS_STATE4[1][k], linestyle='--')
  214. axes.legend([],[], frameon=False)
  215. utils.save_figure(join(paths.FIGURES, "GM_vs_WM",
  216. f"22BOOTSTRAP_all_patients_GMvsWM_ECDF2_{MONTAGE}_{params.TISSUE_DEFINITION_PERCENT[0]}_GM_{params.TISSUE_DEFINITION_PERCENT[1]}_WM_{params.TISSUE_DEFINITION_PERCENT[2]}.pdf"),
  217. save_figure=False)
  218. FCtissueAll_bootstrap_flatten,_ = helper.FCtissueAll_flatten(FCtissueAll, STATE_NUMBER, func = 2 ,freq = 7, max_connections = 50)
  219. plot_GMvsWM.plot_FC_all_patients_GMvsWM_ECDF(FCtissueAll_bootstrap_flatten, STATE_NUMBER , plot)
  220. utils.save_figure(join(paths.FIGURES, "GM_vs_WM",
  221. f"2ECDF_all_patients_GMvsWM_ECDF2_{MONTAGE}_{params.TISSUE_DEFINITION_PERCENT[0]}_GM_{params.TISSUE_DEFINITION_PERCENT[1]}_WM_{params.TISSUE_DEFINITION_PERCENT[2]}.pdf"),
  222. save_figure=False)
  223. plot_GMvsWM.plot_boxplot_single_FC_deltaT(summaryStatsLong, FREQUENCY_NAMES, FC_TYPES, 2, 5, plot)
  224. utils.save_figure(join(paths.FIGURES, "GM_vs_WM",
  225. f"boxplot2_single_FC_deltaT_{MONTAGE}_{params.TISSUE_DEFINITION_PERCENT[0]}_GM_{params.TISSUE_DEFINITION_PERCENT[1]}_WM_{params.TISSUE_DEFINITION_PERCENT[2]}.pdf"),
  226. save_figure=False)
  227. plot_GMvsWM.plot_boxplot_all_FC_deltaT(summaryStatsLong, FREQUENCY_NAMES, FC_TYPES, plot.COLORS_STATE4[0], plot.COLORS_STATE4[1])
  228. utils.save_figure(join(paths.FIGURES, "GM_vs_WM",
  229. f"boxplot2_all_FC_deltaT_Supplement_{MONTAGE}_{params.TISSUE_DEFINITION_PERCENT[0]}_GM_{params.TISSUE_DEFINITION_PERCENT[1]}_WM_{params.TISSUE_DEFINITION_PERCENT[2]}.pdf"),
  230. save_figure=False)
  231. #%%
  232. #% Plot FC distributions for example patient
  233. #for i in range(3,N):
  234. i=43
  235. func = 2
  236. freq = 7
  237. state = 2
  238. sub = patientsWithseizures["subject"][i]
  239. FC_type = FC_TYPES[func]
  240. FC, channels, localization, localization_channels, dist, GM_index, WM_index, dist_order, FC_tissue = helper.get_functional_connectivity_and_tissue_subnetworks_for_single_patient(patientsWithseizures,
  241. i, metadata_iEEG, SESSION, USERNAME, PASSWORD, paths,
  242. FREQUENCY_DOWN_SAMPLE, MONTAGE, FC_TYPES,
  243. params.TISSUE_DEFINITION_PERCENT[0], params.TISSUE_DEFINITION_PERCENT[1], params.TISSUE_DEFINITION_PERCENT[2],
  244. func, freq)
  245. plot_GMvsWM.plot_FC_example_patient_ADJ(sub, FC, channels, localization, localization_channels, dist, GM_index, WM_index, dist_order, FC_tissue, FC_TYPES, FREQUENCY_NAMES, state ,func, freq, TISSUE_DEFINITION_GM, TISSUE_DEFINITION_WM, plot)
  246. plot_GMvsWM.plot_FC_example_patient_GMWMall(sub, FC, channels, localization, localization_channels, dist, GM_index, WM_index, dist_order,
  247. FC_tissue, FC_TYPES, FREQUENCY_NAMES, state ,func, freq, TISSUE_DEFINITION_GM, TISSUE_DEFINITION_WM, plot,
  248. xlim = [0,0.6])
  249. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"hist_GM_vs_WM_distribution_of_FC_GMWM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.pdf"), save_figure=SAVE_FIGURES)
  250. plot_GMvsWM.plot_FC_example_patient_GMvsWM(sub, FC, channels, localization, localization_channels, dist, GM_index, WM_index, dist_order,
  251. FC_tissue, FC_TYPES, FREQUENCY_NAMES, state ,func, freq, TISSUE_DEFINITION_GM, TISSUE_DEFINITION_WM, plot,
  252. xlim = [0,0.6])
  253. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"hist_GM_vs_WM_distribution_of_FC_GMvsWM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.pdf"), save_figure=SAVE_FIGURES)
  254. plot_GMvsWM.plot_FC_example_patient_GMvsWM_ECDF(sub, FC, channels, localization, localization_channels, dist, GM_index, WM_index, dist_order, FC_tissue, FC_TYPES, FREQUENCY_NAMES, state ,func, freq, TISSUE_DEFINITION_GM, TISSUE_DEFINITION_WM, plot)
  255. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"ECDF_GM_vs_WM_distribution_of_FC_GMvsWM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.pdf"), save_figure=SAVE_FIGURES)
  256. #GM-to-WM connections
  257. plot_GMvsWM.plot_FC_example_patient_GMWM(sub, FC, channels, localization, localization_channels, dist, GM_index, WM_index, dist_order,
  258. FC_tissue, FC_TYPES, FREQUENCY_NAMES, state ,func, freq, TISSUE_DEFINITION_GM, TISSUE_DEFINITION_WM, plot,
  259. xlim = [0,0.6])
  260. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"hist_GM_to_WM_distribution_of_FC_GMWM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.pdf"), save_figure=SAVE_FIGURES)
  261. plot_GMvsWM.plot_FC_example_patient_GMWM_ECDF(sub, FC, channels, localization, localization_channels, dist, GM_index, WM_index, dist_order, FC_tissue, FC_TYPES, FREQUENCY_NAMES, state ,func, freq, TISSUE_DEFINITION_GM, TISSUE_DEFINITION_WM, plot)
  262. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"ECDF_GM_to_WM_distribution_of_FC_GMvsWM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.pdf"), save_figure=SAVE_FIGURES)
  263. #%% Calculate FC as a function of purity
  264. save_directory = join(paths.DATA, "GMvsWM")
  265. func = 2; freq = 0; state = 2
  266. ## WM definition = distance
  267. summaryStats_Wm_FC = helper.get_FC_vs_tissue_definition(save_directory, patientsWithseizures, range(3,5), MONTAGE, params.TISSUE_DEFINITION_DISTANCE,
  268. 0, FC_TYPES, FREQUENCY_NAMES, metadata_iEEG, SESSION, USERNAME, PASSWORD, paths, FREQUENCY_DOWN_SAMPLE, save_pickle = False , recalculate = False)
  269. summaryStats_Wm_FC_bootstrap_func_freq_long_state, result_lin = helper.bootstrap_FC_vs_WM_cutoff_summaryStats_Wm_FC(iterations, summaryStats_Wm_FC, FC_TYPES, FREQUENCY_NAMES, STATE_NAMES, func, freq, state, print_results = True)
  270. plot_GMvsWM.plot_FC_vs_contact_distance(summaryStats_Wm_FC_bootstrap_func_freq_long_state)
  271. plot_GMvsWM.plot_FC_vs_WM_cutoff(summaryStats_Wm_FC_bootstrap_func_freq_long_state)
  272. ## WM definition = percent
  273. summaryStats_Wm_FC = helper.get_FC_vs_tissue_definition(save_directory, patientsWithseizures, range(3,5), MONTAGE, params.TISSUE_DEFINITION_PERCENT,
  274. 1, FC_TYPES, FREQUENCY_NAMES, metadata_iEEG, SESSION, USERNAME, PASSWORD, paths, FREQUENCY_DOWN_SAMPLE, save_pickle = False , recalculate = False)
  275. summaryStats_Wm_FC_bootstrap_func_freq_long_state, result_lin = helper.bootstrap_FC_vs_WM_cutoff_summaryStats_Wm_FC(iterations, summaryStats_Wm_FC, FC_TYPES, FREQUENCY_NAMES, STATE_NAMES, func, freq, state, print_results = True)
  276. plot_GMvsWM.plot_FC_vs_contact_distance(summaryStats_Wm_FC_bootstrap_func_freq_long_state,xlim = [15,80] ,ylim = [0.02,0.2])
  277. plot_GMvsWM.plot_FC_vs_WM_cutoff(summaryStats_Wm_FC_bootstrap_func_freq_long_state)
  278. #%%
  279. ##################################################################
  280. ##################################################################
  281. ##################################################################
  282. ##################################################################
  283. ##################################################################
  284. #Structure-function Analysis
  285. #%% DWI correction and tractography
  286. #get patients in patientsWithseizures that have dti
  287. sfc_patient_list = tractography.get_patients_with_dwi(np.unique(patientsWithseizures["subject"]), paths, dataset = "PIER", SESSION_RESEARCH3T = SESSION_RESEARCH3T)
  288. cmd = tractography.print_dwi_image_correction_QSIprep(sfc_patient_list, paths, dataset = "PIER")
  289. tractography.get_tracts_loop_through_patient_list(sfc_patient_list, paths, SESSION_RESEARCH3T = SESSION_RESEARCH3T)
  290. tractography.get_tracts_loop_through_patient_list(['RID0682'], paths, SESSION_RESEARCH3T = SESSION_RESEARCH3T)
  291. make_spherical_regions.make_spherical_regions(sfc_patient_list, SESSION, paths, radius = 7, rerun = False, show_slices = False)
  292. #%%
  293. #Analyzing SFC
  294. means_list = []
  295. means_delta_corr_list = []
  296. cores = 24
  297. iterations = 24
  298. total = 416
  299. func = 2
  300. freq = 7
  301. for i in range(total):
  302. utils.printProgressBar(i, total)
  303. simulation = helper.multicore_sfc_wrapper(cores,iterations, params.TISSUE_TYPE_NAMES2, STATE_NUMBER, patientsWithseizures, sfc_patient_list, paths,
  304. FC_TYPES, STATE_NAMES, FREQUENCY_NAMES, metadata_iEEG, SESSION, USERNAME, PASSWORD,FREQUENCY_DOWN_SAMPLE, MONTAGE,
  305. params.TISSUE_DEFINITION_PERCENT[0], params.TISSUE_DEFINITION_PERCENT[1], params.TISSUE_DEFINITION_PERCENT[2],
  306. ratio_patients = 5, max_seizures = 1,
  307. func = 2, freq = 0, print_pvalues = False )
  308. means_list.append([a_tuple[0] for a_tuple in simulation])
  309. means = [item for sublist in means_list for item in sublist]
  310. means_delta_corr_list.append([a_tuple[1] for a_tuple in simulation])
  311. means_delta_corr = [item for sublist in means_delta_corr_list for item in sublist]
  312. utils.printProgressBar(i+1, total)
  313. if i+1 == total:
  314. means = np.dstack(means)
  315. means_delta_corr = np.vstack(means_delta_corr)
  316. cols = pd.MultiIndex.from_product([ params.TISSUE_TYPE_NAMES2, STATE_NAMES])
  317. means_df = pd.DataFrame(columns = ["tissue", "state", "SFC"])
  318. for t in range(len(params.TISSUE_TYPE_NAMES)):
  319. df_tissue = pd.DataFrame(means[:,t,:].T, columns = STATE_NAMES)
  320. df_tissue = pd.melt(df_tissue, var_name = ["state"], value_name = "SFC")
  321. df_tissue["tissue"] = params.TISSUE_TYPE_NAMES2[t]
  322. means_df = pd.concat([means_df, df_tissue])
  323. wm_preictal = means_df.query('tissue == "WM" and state == "preictal"')["SFC"]
  324. wm_ictal = means_df.query('tissue == "WM" and state == "ictal"')["SFC"]
  325. stats.ttest_rel(means_df.query('tissue == "WM" and state == "ictal"')["SFC"] ,means_df.query('tissue == "WM" and state == "preictal"')["SFC"])[1]
  326. print(stats.wilcoxon(wm_preictal, wm_ictal)[1])
  327. print(stats.mannwhitneyu(wm_preictal, wm_ictal)[1])
  328. palette_long = ["#808080", "#808080", "#282828", "#808080"] + ["#a08269", "#a08269", "#675241", "#a08269"] + ["#8a6ca1", "#8a6ca1", "#511e79", "#8a6ca1"]+ ["#76afdf", "#76afdf", "#1f5785", "#76afdf"]
  329. palette = ["#bbbbbb", "#bbbbbb", "#282828", "#bbbbbb"] + ["#cebeb1", "#cebeb1", "#675241", "#cebeb1"] + ["#cdc0d7", "#cdc0d7", "#511e79", "#cdc0d7"] + ["#b6d4ee", "#b6d4ee", "#1f5785", "#b6d4ee"]
  330. fig, axes = utils.plot_make()
  331. sns.boxplot(data = means_df , x = "tissue", y = "SFC", hue = "state", ax = axes, showfliers=False, order = ["Full Network", "GM", "GM-WM", "WM"])
  332. plt.setp(axes.lines, zorder=100); plt.setp(axes.collections, zorder=100, label="")
  333. #sns.stripplot(data= means_df, x = "tissue", y = "SFC", hue = "state", dodge=True, color = "#444444", ax = axes,s = 1, order = ["Full Network", "GM", "GM-WM", "WM"])
  334. axes.spines['top'].set_visible(False)
  335. axes.spines['right'].set_visible(False)
  336. axes.legend([],[], frameon=False)
  337. for a in range(len( axes.artists)):
  338. mybox = axes.artists[a]
  339. # Change the appearance of that box
  340. mybox.set_facecolor(palette[a])
  341. mybox.set_edgecolor(palette[a])
  342. #mybox.set_linewidth(3)
  343. count = 0
  344. a = 0
  345. for line in axes.get_lines():
  346. line.set_color(palette[a])
  347. count = count + 1
  348. if count % 5 ==0:
  349. a = a +1
  350. if count % 5 ==0: #set mean line
  351. line.set_color("#222222")
  352. #line.set_ls("-")
  353. #line.set_lw(2.5)
  354. axes.spines['top'].set_visible(False)
  355. axes.spines['right'].set_visible(False)
  356. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"2SFC_bootstrap_10000.pdf"), save_figure=True)
  357. confidence_intervals = pd.DataFrame(columns = ["tissue", "state", "ci_lower", "ci_upper"])
  358. for t in range(len(params.TISSUE_TYPE_NAMES)):
  359. for s in range(len(STATE_NAMES)):
  360. df_ci = means_df.query(f'tissue == "{params.TISSUE_TYPE_NAMES2[t]}" and state == "{STATE_NAMES[s]}"')["SFC"]
  361. ci = stats.t.interval(alpha=0.95, df=len(df_ci)-1, loc=np.mean(df_ci), scale=stats.sem(df_ci))
  362. confidence_intervals = confidence_intervals.append(dict(tissue = params.TISSUE_TYPE_NAMES[t], state = STATE_NAMES[s], ci_lower = ci[0], ci_upper = ci[1] ),ignore_index=True)
  363. palette2 = ["#bbbbbb" , "#cebeb1" , "#b6d4ee", "#cdc0d7"]
  364. palette3 = ["#808080" , "#a08269" , "#76afdf", "#8a6ca1"]
  365. #reorder for plotting
  366. df = pd.DataFrame(means_delta_corr, columns =params.TISSUE_TYPE_NAMES )
  367. order = [params.TISSUE_TYPE_NAMES[i] for i in [3,1,2,0]]
  368. df = df[order]
  369. palette2_reorder = [palette2[i] for i in [3,1,2,0]]
  370. palette3_reorder = [palette3[i] for i in [0,2,1,3]] #idk why but seaborn and python are so stupid in their plotting. Makes no sense.
  371. fig, axes = utils.plot_make()
  372. sns.histplot(data = df, palette = palette2_reorder, ax = axes, binwidth = 0.01 , line_kws = dict(lw = 5), alpha=1 , edgecolor=None, kde = True)
  373. #sns.kdeplot(data = df, palette = palette3_reorder, ax = axes , lw = 5, bw_method = 0.1)
  374. axes.set_xlim([-0.025, 0.14])
  375. axes.spines['top'].set_visible(False)
  376. axes.spines['right'].set_visible(False)
  377. axes.legend([],[], frameon=False)
  378. for l in range(len(axes.lines)):
  379. axes.lines[l].set_color(palette3_reorder[l])
  380. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"2SFC_bootstrap_delta_histogram_10000bootstrap.pdf"), save_figure=False)
  381. stats.t.interval(alpha=0.95, df=len(df)-1, loc=np.mean(df), scale=stats.sem(df))
  382. #%%#%%
  383. df_long, delta_corr = helper.get_tissue_SFC(patientsWithseizures, sfc_patient_list, paths,
  384. FC_TYPES, STATE_NAMES, FREQUENCY_NAMES, metadata_iEEG, SESSION, USERNAME, PASSWORD,FREQUENCY_DOWN_SAMPLE, MONTAGE,
  385. params.TISSUE_DEFINITION_PERCENT[0], params.TISSUE_DEFINITION_PERCENT[1], params.TISSUE_DEFINITION_PERCENT[2],
  386. ratio_patients = 5, max_seizures = 1,
  387. func = 2, freq = 0, print_pvalues = True)
  388. palette = ["#bbbbbb", "#808080", "#282828", "#808080"] + ["#cebeb1", "#a08269", "#675241", "#a08269"] + ["#cdc0d7", "#8a6ca1", "#511e79", "#8a6ca1"] + ["#b6d4ee", "#76afdf", "#1f5785", "#76afdf"]
  389. palette = ["#bbbbbb", "#bbbbbb", "#282828", "#bbbbbb"] + ["#cebeb1", "#cebeb1", "#675241", "#cebeb1"] + ["#cdc0d7", "#cdc0d7", "#511e79", "#cdc0d7"] + ["#b6d4ee", "#b6d4ee", "#1f5785", "#b6d4ee"]
  390. palette2 = ["#808080", "#808080", "#282828", "#808080"] + ["#a08269", "#a08269", "#675241", "#a08269"] + ["#8a6ca1", "#8a6ca1", "#511e79", "#8a6ca1"]+ ["#76afdf", "#76afdf", "#1f5785", "#76afdf"]
  391. #%%
  392. fig, axes = utils.plot_make(size_length = 5, size_height = 4)
  393. meanprops={"marker":"o", "markerfacecolor":"white", "markeredgecolor":"black", "markersize":"10"}
  394. sns.boxplot(data = df_long, x = "tissue", y = "FC", hue = "state", ax = axes , whis = 1,showmeans=True , meanline=True)
  395. axes.legend([],[], frameon=False)
  396. for a in range(len( axes.artists)):
  397. mybox = axes.artists[a]
  398. # Change the appearance of that box
  399. mybox.set_facecolor(palette[a])
  400. mybox.set_edgecolor(palette[a])
  401. #mybox.set_linewidth(3)
  402. axes.spines['top'].set_visible(False)
  403. axes.spines['right'].set_visible(False)
  404. count = 0
  405. a = 0
  406. for line in axes.get_lines():
  407. line.set_color(palette2[a])
  408. count = count + 1
  409. if count % 7 ==0:
  410. a = a +1
  411. if count % 7 ==5: #set median line
  412. line.set_color("white")
  413. line.set_ls("--")
  414. line.set_lw(1)
  415. if count % 7 ==6: #set mean line
  416. line.set_color("#970707")
  417. line.set_ls("-")
  418. line.set_lw(2.5)
  419. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"SFC_{FC_type}_{FREQUENCY_NAMES[freq]}.pdf"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = 0)
  420. #%%
  421. fig, axes = utils.plot_make()
  422. binrange = [-0.3,0.3]
  423. binwidth = 0.01
  424. sns.histplot( delta_corr[:,1], ax = axes , binrange = binrange, binwidth = binwidth, kde = True, color = "red" )
  425. sns.histplot( delta_corr[:,2], ax = axes , binrange = binrange, binwidth = binwidth , kde = True, color = "blue" )
  426. sns.histplot( delta_corr[:,3], ax = axes , binrange = binrange, binwidth = binwidth , kde = True, color = "purple" )
  427. func = 2
  428. freq = 0
  429. i=83 #3, 21, 51, 54, 63, 75, 78, 103, 104, 105, 109, 110, 111, 112, 113, 116
  430. for s in range(STATE_NUMBER):
  431. SC_order, SC_order_gm, SC_order_wm, SC_order_gmwm, adj, adj_gm, adj_wm, adj_gmwm = helper.get_SC_and_FC_adj(patientsWithseizures,
  432. i, metadata_iEEG, SESSION, USERNAME, PASSWORD, paths,
  433. FREQUENCY_DOWN_SAMPLE, MONTAGE, FC_TYPES,
  434. TISSUE_DEFINITION_NAME,
  435. TISSUE_DEFINITION_GM,
  436. 0.5,
  437. func = func, freq = freq, state = s )
  438. if s == 0:
  439. interictal = [SC_order, SC_order_gm, SC_order_wm, SC_order_gmwm, adj, adj_gm, adj_wm, adj_gmwm]
  440. if s == 1:
  441. preictal = [SC_order, SC_order_gm, SC_order_wm, SC_order_gmwm, adj, adj_gm, adj_wm, adj_gmwm]
  442. if s == 2:
  443. ictal = [SC_order, SC_order_gm, SC_order_wm, SC_order_gmwm, adj, adj_gm, adj_wm, adj_gmwm]
  444. if s == 3:
  445. postictal = [SC_order, SC_order_gm, SC_order_wm, SC_order_gmwm, adj, adj_gm, adj_wm, adj_gmwm]
  446. #109 116, 111 104? 78
  447. def plot_adj_heatmap(adj, vmin = 0, vmax = 1, center = 0.5, cmap = "mako" ):
  448. fig, axes = plt.subplots(1, 1, figsize=(4, 4), dpi=300)
  449. sns.heatmap(adj, vmin = vmin, vmax =vmax, center = center, cmap = cmap , ax = axes, square=True , cbar = False, xticklabels = False, yticklabels = False )
  450. cmap_structural = sns.cubehelix_palette(start=2.8, rot=-0.1, dark=.2, light=0.95, hue = 1, gamma = 4, reverse=True, as_cmap=True)
  451. plot_adj_heatmap(SC_order, cmap = cmap_structural, center = 0.5)
  452. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_SC_FULL_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = 0)
  453. plot_adj_heatmap(SC_order_gm, cmap = cmap_structural, center = 0.5)
  454. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_SC_GM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = 0)
  455. plot_adj_heatmap(SC_order_wm, cmap = cmap_structural, center = 0.5)
  456. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_SC_WM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = 0)
  457. plot_adj_heatmap(SC_order_gmwm, cmap = cmap_structural, center = 0.5)
  458. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_SC_GMWM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = 0)
  459. pad = 0.015
  460. cmap_functional = sns.cubehelix_palette(start=0.7, rot=-0.1, dark=0, light=0.95, hue = 0.8, gamma = 0.8, reverse=True, as_cmap=True)
  461. t = 4
  462. plot_adj_heatmap(interictal[t], cmap = cmap_functional, center = 0.5)
  463. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_0_FULL_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  464. plot_adj_heatmap(preictal[t], cmap = cmap_functional, center = 0.5)
  465. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_1_FULL_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  466. plot_adj_heatmap(ictal[t], cmap = cmap_functional, center = 0.5)
  467. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_2_FULL_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  468. plot_adj_heatmap(postictal[t], cmap = cmap_functional, center = 0.5)
  469. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_3_FULL_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  470. t = 5
  471. plot_adj_heatmap(interictal[t], cmap = cmap_functional, center = 0.5)
  472. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_0_GM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  473. plot_adj_heatmap(preictal[t], cmap = cmap_functional, center = 0.5)
  474. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_1_GM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  475. plot_adj_heatmap(ictal[t], cmap = cmap_functional, center = 0.5)
  476. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_2_GM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  477. plot_adj_heatmap(postictal[t], cmap = cmap_functional, center = 0.5)
  478. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_3_GM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  479. t = 6
  480. plot_adj_heatmap(interictal[t], cmap = cmap_functional, center = 0.5)
  481. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_0_WM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  482. plot_adj_heatmap(preictal[t], cmap = cmap_functional, center = 0.5)
  483. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_1_WM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  484. plot_adj_heatmap(ictal[t], cmap = cmap_functional, center = 0.5)
  485. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_2_WM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  486. plot_adj_heatmap(postictal[t], cmap = cmap_functional, center = 0.5)
  487. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_3_WM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  488. t = 7
  489. plot_adj_heatmap(interictal[t], cmap = cmap_functional, center = 0.5)
  490. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_0_GMWM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  491. plot_adj_heatmap(preictal[t], cmap = cmap_functional, center = 0.5)
  492. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_1_GMWM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  493. plot_adj_heatmap(ictal[t], cmap = cmap_functional, center = 0.5)
  494. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_2_GMWM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  495. plot_adj_heatmap(postictal[t], cmap = cmap_functional, center = 0.5)
  496. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"adj_FC_3_GMWM_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.png"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  497. from sklearn import linear_model
  498. reg = linear_model.TweedieRegressor(power=1, alpha=0)
  499. #reg = linear_model.LinearRegression()
  500. states_SFC = [interictal, preictal, ictal, postictal]
  501. fig, axes = utils.plot_make(c =STATE_NUMBER, size_length = 16, size_height = 3, sharey = True)
  502. for s in range(STATE_NUMBER):
  503. matrix = states_SFC[s]
  504. x = utils.getUpperTriangle(SC_order)
  505. y = utils.getUpperTriangle(matrix[4])
  506. reg.fit(x.reshape(-1, 1), y)
  507. y_predict = reg.predict(x.reshape(-1, 1))
  508. sns.lineplot(x = x[1::10], y = y_predict[1::10], ax= axes[s], color = plot.COLORS_STATE4[1][s], lw = 5, alpha = 0.7);
  509. sns.scatterplot(x = x[1::2], y = y[1::2], ax= axes[s], s = 5, color = plot.COLORS_STATE4[1][s], linewidth=0, alpha = 0.3)
  510. axes[s].title.set_text( np.round( spearmanr(utils.getUpperTriangle(SC_order), utils.getUpperTriangle(matrix[4]))[0],2) )
  511. axes[s].set_ylim([0,1])
  512. axes[s].spines['top'].set_visible(False)
  513. axes[s].spines['right'].set_visible(False)
  514. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"GLM_SFC_{sub}_{FC_type}_{FREQUENCY_NAMES[freq]}.pdf"), save_figure=SAVE_FIGURES, bbox_inches = "tight", pad_inches = pad)
  515. #%%
  516. #analysis of determining how good vs poor outcome have diff GM-GM activity
  517. patient_outcomes_good = ["RID0238", "RID0267", "RID0279", "RID0294", "RID0307", "RID0309", "RID0320", "RID0365", "RID0440", "RID0424"]
  518. patient_outcomes_poor = ["RID0274", "RID0278", "RID0371", "RID0382", "RID0405", "RID0442", "RID0322"]
  519. original_array_list = []
  520. test_statistic_array_list = []
  521. ratio_patients = 5
  522. cores = 12
  523. iterations = 12
  524. total = 200
  525. max_seizures= 2
  526. func = 2
  527. freq = 7
  528. for i in range(total):
  529. simulation = helper.mutilcore_permute_wrapper(cores, iterations, summaryStatsLong, FCtissueAll, seizure_number,
  530. patient_outcomes_good, patient_outcomes_poor,
  531. FC_TYPES, FREQUENCY_NAMES, STATE_NAMES,
  532. ratio_patients = ratio_patients, max_seizures = max_seizures, func = func, freq = freq)
  533. original_array_list.append([a_tuple[0] for a_tuple in simulation])
  534. original_array = [item for sublist in original_array_list for item in sublist]
  535. test_statistic_array_list.append([a_tuple[1] for a_tuple in simulation])
  536. test_statistic_array = [item for sublist in test_statistic_array_list for item in sublist]
  537. Tstat = np.array(original_array)
  538. permute = np.array(test_statistic_array)
  539. pvalue = len( np.where(permute >= Tstat.mean()) [0]) / len(Tstat)
  540. print(f"{i}/{total}: {pvalue}")
  541. is_abs = 0
  542. Tstat = np.array(original_array)
  543. permute = np.array(test_statistic_array)
  544. binrange = [ np.floor(np.min([Tstat, permute]) ), np.ceil(np.max([Tstat, permute]) ) ]
  545. if is_abs == 1:
  546. Tstat = abs(Tstat)
  547. permute = abs(permute)
  548. binrange = [0, 3]
  549. binwidth = 0.1
  550. fig, axes = utils.plot_make()
  551. sns.histplot(Tstat, kde = True, ax = axes, color = "#222222", binwidth = binwidth, binrange = binrange, edgecolor = None)
  552. sns.histplot(permute, kde = True, ax = axes, color = "#bbbbbb", binwidth = binwidth, binrange = binrange ,edgecolor = None)
  553. axes.axvline(x=abs(Tstat).mean(), color='k', linestyle='--')
  554. axes.set_xlim(binrange)
  555. axes.spines['top'].set_visible(False)
  556. axes.spines['right'].set_visible(False)
  557. pvalue = len( np.where(permute >= Tstat.mean()) [0]) / len(Tstat)
  558. axes.set_title(f"{Tstat.mean()} {pvalue}" )
  559. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"good_vs_poor_FC_deltaT_PVALUES_PERMUTATION_morePatients3.pdf"), save_figure=False,
  560. bbox_inches = "tight", pad_inches = 0.1)
  561. ###############################################################
  562. ###############################################################
  563. ###############################################################
  564. ###############################################################
  565. original,summaryStatsLong_bootstrap_outcome = permute_resampling_pvalues(summaryStatsLong, patient_outcomes_good, patient_outcomes_poor, ratio_patients = ratio_patients, max_seizures = max_seizures)
  566. fig, axes = utils.plot_make(size_length = 4, size_height = 4)
  567. sns.boxplot(data = summaryStatsLong_bootstrap_outcome, x = "state", y = "FC_deltaT", hue = "outcome", ax = axes,showfliers=False , palette = plot.COLORS_GOOD_VS_POOR)
  568. sns.stripplot(data = summaryStatsLong_bootstrap_outcome, x = "state", y = "FC_deltaT", hue = "outcome", ax = axes, palette = plot.COLORS_GOOD_VS_POOR,
  569. dodge=True, size=3)
  570. axes.legend([],[], frameon=False)
  571. axes.spines['top'].set_visible(False)
  572. axes.spines['right'].set_visible(False)
  573. s = 2
  574. v1 = summaryStatsLong_bootstrap_outcome[(summaryStatsLong_bootstrap_outcome["state"]==STATE_NAMES[s])&(summaryStatsLong_bootstrap_outcome["outcome"]<="good")].dropna()["FC_deltaT"]
  575. v2 = summaryStatsLong_bootstrap_outcome[(summaryStatsLong_bootstrap_outcome["state"]==STATE_NAMES[s])&(summaryStatsLong_bootstrap_outcome["outcome"]<="poor")].dropna()["FC_deltaT"]
  576. stats.mannwhitneyu(v1, v2)[1]
  577. axes.set_title(f" {stats.mannwhitneyu(v1, v2)[1] }" )
  578. #axes.set_title(f" {stats.ttest_ind(v1, v2, equal_var=False)[1] }" )
  579. print(f" {stats.ttest_ind(v1, v2, equal_var=True)[1] }" )
  580. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"good_vs_poor_FC_deltaT_morePatient2.pdf"), save_figure=False,
  581. bbox_inches = "tight", pad_inches = 0.1)
  582. ######################################################
  583. ######################################################
  584. ######################################################
  585. FCtissueAll_bootstrap_outcomes = [FCtissueAll_bootstrap_good, FCtissueAll_bootstrap_poor]
  586. tissue_distribution = [None] * 2
  587. for o in range(2):
  588. tissue_distribution[o] = [None] * 4
  589. for t in range(4):
  590. tissue_distribution[o][t] = [None] * 4
  591. OUTCOME_NAMES = ["good", "poor"]
  592. TISSUE_TYPE_NAMES = ["Full Network", "GM-only", "WM-only", "GM-WM"]
  593. for o in range(2):
  594. for t in range(4):
  595. for s in range(4):
  596. FCtissueAll_bootstrap_outcomes_single = FCtissueAll_bootstrap_outcomes[o]
  597. fc_patient = []
  598. for i in range(len(FCtissueAll_bootstrap_outcomes_single)):
  599. fc = utils.getUpperTriangle(FCtissueAll_bootstrap_outcomes_single[i][func][freq][t][s])
  600. fc_patient.append(fc)
  601. tissue_distribution[o][t][s] = np.array([item for sublist in fc_patient for item in sublist])
  602. ######################################################
  603. ######################################################
  604. ######################################################
  605. for s in [1,2]:
  606. fig, axes = utils.plot_make(c = 2, r = 2, size_height = 5)
  607. axes = axes.flatten()
  608. for t in range(4):
  609. sns.ecdfplot(data = tissue_distribution[0][t][s], ax = axes[t], color = plot.COLORS_GOOD_VS_POOR[0], lw = 6)
  610. sns.ecdfplot(data = tissue_distribution[1][t][s], ax = axes[t], color = plot.COLORS_GOOD_VS_POOR[1], lw = 6, ls = "-")
  611. axes[t].set_title(f"{TISSUE_TYPE_NAMES[t]}, {STATE_NAMES[s]} {stats.ks_2samp( tissue_distribution[0][t][s], tissue_distribution[1][t][s] )[1]*16 }" )
  612. axes[t].spines['top'].set_visible(False)
  613. axes[t].spines['right'].set_visible(False)
  614. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"good_vs_poor_{STATE_NAMES[s]}.pdf"), save_figure=False,
  615. bbox_inches = "tight", pad_inches = 0.0)
  616. #good vs poor -- delta
  617. fig, axes = utils.plot_make()
  618. sns.ecdfplot(data = tissue_distribution[0][t][2] - tissue_distribution[0][t][1], ax = axes, color = "blue")
  619. sns.ecdfplot(data = tissue_distribution[1][t][2] - tissue_distribution[1][t][1], ax = axes, color = "red")
  620. #good vs poor -- ictal
  621. stats.ks_2samp( tissue_distribution[0][t][2], tissue_distribution[1][t][2])
  622. #good vs poor -- preictal
  623. stats.ks_2samp( tissue_distribution[0][t][1], tissue_distribution[0][t][1])
  624. #good vs poor -- delta
  625. stats.ks_2samp( tissue_distribution[0][t][2] - tissue_distribution[0][t][1], tissue_distribution[1][t][2] - tissue_distribution[1][t][1] )
  626. t = 1
  627. outcomes_good_tissue_preictal = []
  628. outcomes_good_tissue_ictal = []
  629. for i in range(len(FCtissueAll_bootstrap_good)):
  630. outcomes_good_tissue_preictal.append(utils.getUpperTriangle(FCtissueAll_bootstrap_good[i][func][freq][t][1]))
  631. outcomes_good_tissue_ictal.append( utils.getUpperTriangle(FCtissueAll_bootstrap_good[i][func][freq][t][2]))
  632. outcomes_good_tissue_preictal = np.array([item for sublist in outcomes_good_tissue_preictal for item in sublist])
  633. outcomes_good_tissue_ictal = np.array([item for sublist in outcomes_good_tissue_ictal for item in sublist])
  634. outcomes_poor_tissue_preictal = []
  635. outcomes_poor_tissue_ictal = []
  636. for i in range(len(FCtissueAll_bootstrap_poor)):
  637. outcomes_poor_tissue_preictal.append( utils.getUpperTriangle(FCtissueAll_bootstrap_poor[i][func][freq][t][1]))
  638. outcomes_poor_tissue_ictal.append( utils.getUpperTriangle(FCtissueAll_bootstrap_poor[i][func][freq][t][2]))
  639. outcomes_poor_tissue_preictal = np.array([item for sublist in outcomes_poor_tissue_preictal for item in sublist])
  640. outcomes_poor_tissue_ictal = np.array([item for sublist in outcomes_poor_tissue_ictal for item in sublist])
  641. fig, axes = utils.plot_make()
  642. sns.ecdfplot(data = outcomes_good_tissue_ictal, ax = axes, color = "blue")
  643. sns.ecdfplot(data = outcomes_poor_tissue_ictal, ax = axes, color = "red")
  644. fig, axes = utils.plot_make()
  645. sns.ecdfplot(data = outcomes_good_tissue_ictal - outcomes_good_tissue_preictal, ax = axes, color = "blue")
  646. sns.ecdfplot(data = outcomes_poor_tissue_ictal - outcomes_poor_tissue_preictal, ax = axes, color = "red")
  647. stats.ks_2samp( outcomes_good_tissue_ictal, outcomes_poor_tissue_ictal)
  648. stats.ks_2samp( outcomes_good_tissue_preictal, outcomes_poor_tissue_preictal)
  649. stats.ks_2samp( outcomes_good_tissue_ictal - outcomes_good_tissue_preictal, outcomes_poor_tissue_ictal - outcomes_poor_tissue_preictal)
  650. fig, axes = utils.plot_make()
  651. sns.ecdfplot(data = outcomes_good_tissue_preictal, ax = axes, color = "blue")
  652. sns.ecdfplot(data = outcomes_poor_tissue_preictal, ax = axes, color = "red")
  653. fig, axes = utils.plot_make()
  654. sns.ecdfplot(data = outcomes_good_tissue_preictal, ax = axes, color = "blue")
  655. sns.ecdfplot(data = outcomes_good_tissue_ictal, ax = axes, color = "red")
  656. #%%
  657. #patient outcomes good vs poor
  658. max_seizures=1
  659. func = 2
  660. freq = 7
  661. test_statistic_array_delta_list = []
  662. test_statistic_array_delta_permutation_list = []
  663. ratio_patients = 5
  664. cores = 10
  665. iterations = 10
  666. total = 6
  667. for i in range(total):
  668. simulation = helper.multicore_wm_good_vs_poor_wrapper(cores, iterations,
  669. summaryStatsLong, patient_outcomes_good, patient_outcomes_poor,
  670. patientsWithseizures, metadata_iEEG, SESSION, USERNAME, PASSWORD, paths,
  671. FREQUENCY_DOWN_SAMPLE, MONTAGE, FC_TYPES, TISSUE_DEFINITION_NAME, TISSUE_DEFINITION_GM, TISSUE_DEFINITION_WM, ratio_patients = ratio_patients, max_seizures = 1, func = 2, freq = 7,
  672. permute = False, closest_wm_threshold = 85, avg = 0)
  673. test_statistic_array_delta_list.append([a_tuple[0] for a_tuple in simulation])
  674. test_statistic_array_delta = [item for sublist in test_statistic_array_delta_list for item in sublist]
  675. test_statistic_array_delta_permutation_list.append([a_tuple[1] for a_tuple in simulation])
  676. test_statistic_array_delta_permutation = [item for sublist in test_statistic_array_delta_permutation_list for item in sublist]
  677. Tstat = np.array(test_statistic_array_delta)
  678. permute = np.array(test_statistic_array_delta_permutation)
  679. pvalue = len( np.where(permute >= Tstat.mean()) [0]) / len(Tstat)
  680. print(f"{i}/{total}: {pvalue}")
  681. is_abs = 0
  682. Tstat = np.array(test_statistic_array_delta)
  683. permute = np.array(test_statistic_array_delta_permutation)
  684. binrange = [ np.floor(np.min([Tstat, permute]) ), np.ceil(np.max([Tstat, permute]) ) ]
  685. if is_abs == 1:
  686. Tstat = abs(Tstat)
  687. permute = abs(permute)
  688. binrange = [0, 15]
  689. binwidth = 1#0.05
  690. fig, axes = utils.plot_make()
  691. sns.histplot(Tstat, kde = True, ax = axes, color = "#222222", binwidth = binwidth, binrange = binrange, edgecolor = None)
  692. sns.histplot(permute, kde = True, ax = axes, color = "#bbbbbb", binwidth = binwidth, binrange = binrange ,edgecolor = None)
  693. axes.axvline(x=abs(Tstat).mean(), color='k', linestyle='--')
  694. axes.set_xlim(binrange)
  695. axes.spines['top'].set_visible(False)
  696. axes.spines['right'].set_visible(False)
  697. pvalue = len( np.where(permute >= Tstat.mean()) [0]) / len(Tstat)
  698. axes.set_title(f"{Tstat.mean()} {pvalue}" )
  699. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"good_vs_poor_PERMUTE_delta_morePatients5_19.pdf"), save_figure=False,
  700. bbox_inches = "tight", pad_inches = 0.0)
  701. binwidth = 0.005
  702. binrange = [-0.5,0.5]
  703. fig, axes = utils.plot_make()
  704. sns.histplot(abs(test_statistic_array_ablated), kde = True, ax = axes, color = "#222222", binwidth = binwidth, binrange = binrange)
  705. sns.histplot(abs(test_statistic_array_ablated_permutation), kde = True, ax = axes, color = "#bbbbbb", binwidth = binwidth, binrange = binrange)
  706. axes.axvline(x=abs(test_statistic_array_ablated.mean()), color='k', linestyle='--')
  707. axes.set_xlim([-0,0.3])
  708. axes.spines['top'].set_visible(False)
  709. axes.spines['right'].set_visible(False)
  710. pvalue = len( np.where(test_statistic_array_ablated_permutation <= np.mean(test_statistic_array_ablated ) )[0]) / iterations
  711. pvalue = len( np.where( abs(test_statistic_array_ablated_permutation ) >= np.mean(abs(test_statistic_array_ablated )) )[0]) / iterations
  712. axes.set_title(f" {np.mean(abs(test_statistic_array_ablated) )}, {pvalue}" )
  713. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"good_vs_poor_FC_ABLATION_PVALUES_PERMUTATION2.pdf"), save_figure=False,
  714. bbox_inches = "tight", pad_inches = 0.1)
  715. #%%
  716. summaryStatsLong_bootstrap_good, summaryStatsLong_bootstrap_poor, seizure_number_bootstrap_good, seizure_number_bootstrap_poor, delta, gm_to_wm_all_ablated, gm_to_wm_all_ablated_closest_wm, gm_to_wm_all_ablated_closest_wm_gradient = helper.wm_vs_gm_good_vs_poor(summaryStatsLong, patient_outcomes_good, patient_outcomes_poor,
  717. patientsWithseizures, metadata_iEEG, SESSION, USERNAME, PASSWORD, paths,
  718. FREQUENCY_DOWN_SAMPLE, MONTAGE, FC_TYPES, TISSUE_DEFINITION_NAME, TISSUE_DEFINITION_GM, TISSUE_DEFINITION_WM,
  719. ratio_patients = 2, max_seizures = 2, func = func, freq = freq,
  720. closest_wm_threshold = 85)
  721. #delta is the change in FC of the ablated contacts to wm
  722. delta_mean = []
  723. delta_mean = np.zeros(len(delta))
  724. for x in range(len(delta)):
  725. #delta_mean.append(sum(x)/len(x))
  726. #delta_mean[x] = np.nanmedian(delta[x])
  727. delta_mean[x] = np.nanmean(delta[x])
  728. #good = np.concatenate(delta[:7])
  729. #poor = np.concatenate(delta[8:])
  730. good = delta[:len(seizure_number_bootstrap_good)]
  731. poor = delta[len(seizure_number_bootstrap_good):]
  732. #good = delta_mean[:len(patient_inds_good)]
  733. #poor = delta_mean[len(patient_inds_good):]
  734. #df_good = pd.DataFrame(dict(good = good))
  735. #df_poor = pd.DataFrame(dict(poor = poor))
  736. good = delta_mean[:len(seizure_number_bootstrap_good)]
  737. poor = delta_mean[len(seizure_number_bootstrap_good):]
  738. df_good = pd.DataFrame(dict(good = good))
  739. df_poor = pd.DataFrame(dict(poor = poor))
  740. #test_statistic_array2[it] = stats.ttest_ind(good,poor)[0]
  741. ##################################
  742. ##################################
  743. df_patient = pd.concat([pd.melt(df_good), pd.melt(df_poor)] )
  744. fig, axes = plt.subplots(1, 1, figsize=(4, 4), dpi=300)
  745. sns.boxplot(data = df_patient, x= "variable", y = "value", ax = axes, palette = plot.COLORS_GOOD_VS_POOR , showfliers = False)
  746. sns.swarmplot(data = df_patient, x= "variable", y = "value", ax = axes, palette = plot.COLORS_GOOD_VS_POOR,s = 3)
  747. axes.spines['top'].set_visible(False)
  748. axes.spines['right'].set_visible(False)
  749. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"good_vs_poor_ABLATION_delta_morePatients3.pdf"), save_figure=False,
  750. bbox_inches = "tight", pad_inches = 0.0)
  751. print(stats.mannwhitneyu(poor,good))
  752. print(stats.ttest_ind(poor,good))
  753. stats.ttest_ind(good,poor)
  754. #shows the distributions of all the ablated channels and their connectivity to WM
  755. difference_gm_to_wm_ablated = []
  756. for l in range(len(gm_to_wm_all_ablated)):
  757. difference_gm_to_wm_ablated.append(np.array(gm_to_wm_all_ablated[l][1] )- np.array(gm_to_wm_all_ablated[l][0]))
  758. difference_gm_to_wm_good_ablated = difference_gm_to_wm_ablated[:len(seizure_number_bootstrap_good)]
  759. difference_gm_to_wm_poor_ablated = difference_gm_to_wm_ablated[len(seizure_number_bootstrap_good):]
  760. difference_gm_to_wm_good_ablated = [item for sublist in difference_gm_to_wm_good_ablated for item in sublist]
  761. difference_gm_to_wm_poor_ablated = [item for sublist in difference_gm_to_wm_poor_ablated for item in sublist]
  762. fig, axes = utils.plot_make()
  763. sns.ecdfplot(difference_gm_to_wm_good_ablated, ax = axes, color = plot.COLORS_GOOD_VS_POOR[0], lw = 5)
  764. sns.ecdfplot(difference_gm_to_wm_poor_ablated, ax = axes, color = plot.COLORS_GOOD_VS_POOR[1], lw = 5)
  765. axes.set_xlim([-0.1,0.5])
  766. axes.spines['top'].set_visible(False)
  767. axes.spines['right'].set_visible(False)
  768. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"good_vs_poor_ABLATION_difference_all_connecions_morePatients3.pdf"), save_figure=False,
  769. bbox_inches = "tight", pad_inches = 0)
  770. #Closest gradient
  771. closest_wm_threshold_gradient = np.arange(15, 125,5 )
  772. difference_gm_to_wm_ablated_closest_gradient = []
  773. for l in range(len(gm_to_wm_all_ablated_closest_wm_gradient)):
  774. grad_tmp = []
  775. for gr in range(len(closest_wm_threshold_gradient)):
  776. grad_tmp.append(np.array(gm_to_wm_all_ablated_closest_wm_gradient[l][1][gr] )- np.array(gm_to_wm_all_ablated_closest_wm_gradient[l][0][gr]))
  777. difference_gm_to_wm_ablated_closest_gradient.append(grad_tmp)
  778. difference_gm_to_wm_good_ablated_closest_gradient = difference_gm_to_wm_ablated_closest_gradient[:len(seizure_number_bootstrap_good)]
  779. difference_gm_to_wm_poor_ablated_closest_gradient = difference_gm_to_wm_ablated_closest_gradient[len(seizure_number_bootstrap_good):]
  780. gradient_good = []
  781. for gr in range(len(closest_wm_threshold_gradient)):
  782. grad_tmp = []
  783. for l in range(len(difference_gm_to_wm_good_ablated_closest_gradient)):
  784. grad_tmp.append(difference_gm_to_wm_good_ablated_closest_gradient[l][gr])
  785. gradient_good.append( [item for sublist in grad_tmp for item in sublist])
  786. gradient_poor = []
  787. for gr in range(len(closest_wm_threshold_gradient)):
  788. grad_tmp = []
  789. for l in range(len(difference_gm_to_wm_poor_ablated_closest_gradient)):
  790. grad_tmp.append(difference_gm_to_wm_poor_ablated_closest_gradient[l][gr])
  791. gradient_poor.append( [item for sublist in grad_tmp for item in sublist])
  792. #[np.nanmean(i) for i in gradient_good]
  793. #[np.nanmean(i) for i in gradient_poor]
  794. df_good_gradient = pd.DataFrame(gradient_good).transpose()
  795. df_poor_gradient = pd.DataFrame(gradient_poor).transpose()
  796. df_good_gradient.columns = closest_wm_threshold_gradient
  797. df_poor_gradient.columns = closest_wm_threshold_gradient
  798. df_good_gradient_long = pd.melt(df_good_gradient, var_name = "distance", value_name = "FC")
  799. df_poor_gradient_long = pd.melt(df_poor_gradient, var_name = "distance", value_name = "FC")
  800. #fig, axes = utils.plot_make()
  801. #sns.regplot(data = df_good_gradient_long, x= "distance", y = "FC", ax = axes, color = "blue", ci=95,x_estimator=np.mean, scatter_kws={"s": 10})
  802. #sns.regplot(data = df_poor_gradient_long, x= "distance", y = "FC", ax = axes, color = "red", ci=95,x_estimator=np.mean, scatter_kws={"s": 10})
  803. fig, axes = utils.plot_make(size_length = 10)
  804. sns.lineplot(data = df_good_gradient_long, x= "distance", y = "FC", ax = axes, color = plot.COLORS_GOOD_VS_POOR[0], ci=None, err_style="bars")
  805. sns.lineplot(data = df_poor_gradient_long, x= "distance", y = "FC", ax = axes, color = plot.COLORS_GOOD_VS_POOR[1], ci=None, err_style="bars")
  806. sns.lineplot(data = df_good_gradient_long, x= "distance", y = "FC", ax = axes, color = plot.COLORS_GOOD_VS_POOR[0], ci=95)
  807. sns.lineplot(data = df_poor_gradient_long, x= "distance", y = "FC", ax = axes, color = plot.COLORS_GOOD_VS_POOR[1], ci=95)
  808. axes.spines['top'].set_visible(False)
  809. axes.spines['right'].set_visible(False)
  810. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"good_vs_poor_ABLATION_gradient_morePatient18.pdf"), save_figure=False,
  811. bbox_inches = "tight", pad_inches = 0)
  812. #%%
  813. #REDONE
  814. pt = 0
  815. func = 2
  816. freq = 7
  817. summaryStatsLong_mean = summaryStatsLong.groupby(by=["patient", 'state', "frequency", "FC_type", "outcome", "seizure_number"]).mean().reset_index()
  818. summaryStatsLong_outcome = summaryStatsLong_mean.query(f'outcome != "NA" and FC_type == "{FC_TYPES[func]}" and frequency == "{FREQUENCY_NAMES[freq]}" ')
  819. summaryStatsLong_outcome_seizures_not_combined = copy.deepcopy(summaryStatsLong_outcome)
  820. summaryStatsLong_outcome = summaryStatsLong_outcome.groupby(by=["patient", 'state', "frequency", "FC_type", "outcome"]).mean().reset_index()
  821. fig, axes = utils.plot_make( size_length = 4, size_height = 6.5)
  822. sns.pointplot(data=summaryStatsLong_outcome, x="state", y="FC_deltaT", hue = "outcome",
  823. ax = axes, palette = plot.COLORS_GOOD_VS_POOR4, order = STATE_NAMES,join=False, dodge=0.4, errwidth = 7,capsize = 0.3, linestyles = ["-","--"], scale = 1.1)
  824. plt.setp(axes.lines, zorder=100); plt.setp(axes.collections, zorder=100, label="")
  825. sns.stripplot(data=summaryStatsLong_outcome, x="state", y="FC_deltaT", hue = "outcome", ax = axes, palette = plot.COLORS_GOOD_VS_POOR2, dodge=True,
  826. size=7, order = STATE_NAMES, zorder=1, jitter = 0.25)
  827. axes.spines['top'].set_visible(False)
  828. axes.spines['right'].set_visible(False)
  829. axes.legend([],[], frameon=False)
  830. T = helper.compute_T(summaryStatsLong_outcome, group = False, i =0)
  831. print(T)
  832. print(p_val := helper.compute_T(summaryStatsLong_outcome, group = False, i =1, alternative = "two-sided"))
  833. axes.set_title(f" {p_val}" )
  834. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"good_vs_poor_ABLATION_delta_by_seizure.pdf"), save_figure=False,
  835. bbox_inches = "tight", pad_inches = 0)
  836. T_star_list = []
  837. cores = 16
  838. iterations = 16
  839. total = 1
  840. print(iterations*total)
  841. for i in range(total):
  842. simulation = helper.mutilcore_permute_deltaT_wrapper(cores, iterations, summaryStatsLong_outcome)
  843. T_star_list.extend(simulation)
  844. utils.printProgressBar(i+1, total)
  845. T_star = np.array(T_star_list)
  846. binrange = [-8,10]
  847. binwidth = 0.25
  848. fig, axes = utils.plot_make()
  849. axes.axvline(x=T, color='black', linestyle='--', lw = 5)
  850. sns.histplot(T_star, kde = True, ax = axes, color = "#bbbbbbbb", binwidth = binwidth, binrange = binrange, edgecolor = None, line_kws=dict(linewidth = 10))
  851. for line in axes.get_lines():
  852. line.set_color("#333333")
  853. axes.set_xlim([-3,3])
  854. print(T_nonabs := len(np.where(T_star > T)[0]) / len(T_star))
  855. print(T_abs := len(np.where(abs(T_star) > T)[0]) / len(T_star))
  856. print(len(T_star))
  857. axes.spines['top'].set_visible(False)
  858. axes.spines['right'].set_visible(False)
  859. axes.set_title(f" {T_nonabs}, {T_abs}" )
  860. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"2_good_vs_poor_delta_perm_by_patient.pdf"), save_figure=False,
  861. bbox_inches = "tight", pad_inches = 0)
  862. ##############################################
  863. df = pd.DataFrame(columns = ["iteration", "state", "outcome", "FC_deltaT"])
  864. cores = 17
  865. iterations = 17
  866. total = 1
  867. for i in range(total):
  868. simulation = helper.mutilcore_deltaT_wrapper(cores, iterations, summaryStatsLong_outcome)
  869. df = df.append(simulation)
  870. utils.printProgressBar(i+1, total)
  871. df = df.query( f"state == 'ictal'")
  872. fig, axes = utils.plot_make()
  873. sns.histplot(data = df, x = "FC_deltaT", hue = "outcome", binrange = [-0.005,0.05], binwidth = 0.001, kde = True, palette = plot.COLORS_GOOD_VS_POOR, line_kws=dict(linewidth = 10), edgecolor = None)
  874. axes.axvline(x=df.query(f"outcome == 'good' and state == 'ictal' ")["FC_deltaT"].mean(), color='k', linestyle='--')
  875. axes.axvline(x=df.query(f"outcome == 'poor' and state == 'ictal' ")["FC_deltaT"].mean(), color='k', linestyle='--')
  876. print(len(df)/2)
  877. print(helper.compute_T(df, state = "ictal", i = 0, equal_var=True, group = False))
  878. print(helper.compute_T(df, state = "ictal", i = 1, equal_var=True, group = False))
  879. axes.spines['top'].set_visible(False)
  880. axes.spines['right'].set_visible(False)
  881. axes.legend([],[], frameon=False)
  882. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"2_good_vs_poor_delta_boot_by_patient.pdf"), save_figure=False,
  883. bbox_inches = "tight", pad_inches = 0)
  884. #%%
  885. #ablation
  886. delta, gm_to_wm_all , gm_to_wm_all_ablated, gm_to_wm_all_ablated_closest_wm, gm_to_wm_all_ablated_closest_wm_gradient= helper.wm_vs_gm_good_vs_poor_redone(summaryStatsLong,
  887. patientsWithseizures, metadata_iEEG, SESSION, USERNAME, PASSWORD, paths,
  888. FREQUENCY_DOWN_SAMPLE, MONTAGE, FC_TYPES, TISSUE_DEFINITION_NAME, TISSUE_DEFINITION_GM, TISSUE_DEFINITION_WM , func = 2, freq = 7,
  889. closest_wm_threshold = 40)
  890. #get the median ablated-wm connectivity for all ablated channels in a patient, then take the avg of those
  891. delta_mean = pd.DataFrame(columns = delta.columns)
  892. for x in range(len(delta)):
  893. delta_mean = delta_mean.append(copy.deepcopy(delta.iloc[x]))
  894. chans = delta.iloc[x]["delta"]
  895. chans_means = np.nanmean(np.nanmedian(chans, axis = 1)) #take median FC values, and then take means of those channels
  896. delta_mean.loc[ (delta_mean["patient"] == delta_mean.iloc[x]["patient"]) & (delta_mean["seizure_number"] == delta_mean.iloc[x]["seizure_number"] ) , "delta"]= chans_means
  897. delta_mean.delta = delta_mean.delta.astype(float)
  898. delta_means_patients = delta_mean.groupby(by=["patient", "outcome"]).mean().reset_index()
  899. fig, axes = plt.subplots(1, 1, figsize=(4, 4.2), dpi=300)
  900. sns.pointplot(data = delta_mean, x= "outcome", y = "delta", ax = axes, palette = plot.COLORS_GOOD_VS_POOR4,
  901. join=False, dodge=0.4, errwidth = 7,capsize = 0.3, linestyles = ["-","--"], scale = 1.3)
  902. plt.setp(axes.lines, zorder=100); plt.setp(axes.collections, zorder=100, label="")
  903. sns.stripplot(data = delta_mean, x= "outcome", y = "delta",ax = axes, palette = plot.COLORS_GOOD_VS_POOR2,s = 8, zorder=1, jitter = 0.3)
  904. axes.spines['top'].set_visible(False)
  905. axes.spines['right'].set_visible(False)
  906. pval = helper.compute_T_no_state(delta_mean, group = False, i = 1, var = "delta", alternative = "two-sided")
  907. axes.set_title(f"{pval}" )
  908. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"2_good_vs_poor_ABLATION_delta_by_patient.pdf"), save_figure=False,
  909. bbox_inches = "tight", pad_inches = 0.0)
  910. ###########################3
  911. good = []
  912. poor = []
  913. for x in range(len(gm_to_wm_all_ablated)):
  914. outcome = gm_to_wm_all_ablated["outcome"][x]
  915. if outcome == "good":
  916. good.extend(list(np.array(gm_to_wm_all_ablated["gm_to_wm_all_ablated"][x][1]) - np.array(gm_to_wm_all_ablated["gm_to_wm_all_ablated"][x][0])))
  917. if outcome == "poor":
  918. poor.extend(list(np.array(gm_to_wm_all_ablated["gm_to_wm_all_ablated"][x][1]) - np.array(gm_to_wm_all_ablated["gm_to_wm_all_ablated"][x][0])))
  919. if x+1 == len(gm_to_wm_all_ablated):
  920. good = np.array(good)
  921. poor = np.array(poor)
  922. fig, axes = utils.plot_make()
  923. sns.ecdfplot(good, ax = axes, color = plot.COLORS_GOOD_VS_POOR[0], lw = 5)
  924. sns.ecdfplot(poor, ax = axes, color = plot.COLORS_GOOD_VS_POOR[1], lw = 5)
  925. axes.set_xlim([-0.1,0.8])
  926. axes.spines['top'].set_visible(False)
  927. axes.spines['right'].set_visible(False)
  928. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"2_good_vs_poor_ABLATION_difference_all_connecions_morePatients.pdf"), save_figure=False,
  929. bbox_inches = "tight", pad_inches = 0)
  930. #% permute delta
  931. delta_mean
  932. T = helper.compute_T_no_state(delta_mean, group = True, i = 0, var = "delta")
  933. print(T)
  934. print(helper.compute_T_no_state(delta_mean, group = True, i = 1, var = "delta"))
  935. T_star_list = []
  936. cores = 16
  937. iterations = 16
  938. total = 1
  939. print(iterations*total)
  940. for i in range(total):
  941. simulation = helper.mutilcore_permute_deltaT_wrapper(cores, iterations, delta_mean, state_bool = False, group = True, var = "FC_deltaT")
  942. T_star_list.extend(simulation)
  943. utils.printProgressBar(i+1, total)
  944. T_star = np.array(T_star_list)
  945. binrange = [-8,10]
  946. binwidth = 0.25
  947. fig, axes = utils.plot_make()
  948. axes.axvline(x=T, color='black', linestyle='--', lw = 5)
  949. sns.histplot(T_star, kde = True, ax = axes, color = "#bbbbbbbb", binwidth = binwidth, binrange = binrange, edgecolor = None, line_kws=dict(linewidth = 10))
  950. for line in axes.get_lines():
  951. line.set_color("#333333")
  952. axes.set_xlim([-5,6])
  953. print(T_nonabs := len(np.where(T_star > T)[0]) / len(T_star))
  954. print(T_abs := len(np.where(abs(T_star) > T)[0]) / len(T_star))
  955. print(len(T_star))
  956. axes.spines['top'].set_visible(False)
  957. axes.spines['right'].set_visible(False)
  958. axes.set_title(f" {T_nonabs}, {T_abs}" )
  959. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"2_good_vs_poor_ABLATION_perm_by_patient.pdf"), save_figure=False,
  960. bbox_inches = "tight", pad_inches = 0)
  961. ##############################################
  962. #boostrap delta
  963. df = pd.DataFrame(columns = ["iteration","outcome", "delta"])
  964. cores = 16
  965. iterations = 16
  966. total = 1
  967. for i in range(total):
  968. simulation = helper.mutilcore_delta_mean_wrapper(cores, iterations, delta_mean)
  969. df = df.append(simulation)
  970. utils.printProgressBar(i+1, total)
  971. binrange = [-0.005,1]
  972. binwidth = 0.01
  973. fig, axes = utils.plot_make()
  974. sns.histplot(data = df, x = "delta", hue = "outcome", binrange =binrange, binwidth =binwidth, kde = True, palette = plot.COLORS_GOOD_VS_POOR, line_kws=dict(linewidth = 10), edgecolor = None)
  975. axes.axvline(x=df.query(f"outcome == 'good' ")["delta"].mean(), color='k', linestyle='--')
  976. axes.axvline(x=df.query(f"outcome == 'poor' ")["delta"].mean(), color='k', linestyle='--')
  977. axes.set_xlim([-0.0005, 0.25])
  978. print(len(df)/2)
  979. print(helper.compute_T_no_state(df, i = 0, equal_var=True, group = False, var = "delta"))
  980. print(helper.compute_T_no_state(df, i = 1, equal_var=True, group = False, var = "delta"))
  981. axes.spines['top'].set_visible(False)
  982. axes.spines['right'].set_visible(False)
  983. axes.legend([],[], frameon=False)
  984. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"2_good_vs_poor_ABLATION_boot_by_patient.pdf"), save_figure=False,
  985. bbox_inches = "tight", pad_inches = 0)
  986. ######################################################
  987. ######################################################
  988. ######################################################
  989. seizure_number_good = summaryStatsLong.query(f"outcome == 'good' ")["seizure_number"].unique()
  990. seizure_number_poor = summaryStatsLong.query(f"outcome == 'poor' ")["seizure_number"].unique()
  991. FCtissueAll_ind_good = np.intersect1d(seizure_number_good, seizure_number, return_indices=True )[2]
  992. FCtissueAll_ind_poor = np.intersect1d(seizure_number_poor, seizure_number, return_indices=True )[2]
  993. FCtissueAll_good = [FCtissueAll[i] for i in FCtissueAll_ind_good]
  994. FCtissueAll_poor = [FCtissueAll[i] for i in FCtissueAll_ind_poor]
  995. FCtissueAll_outcomes = [FCtissueAll_good, FCtissueAll_poor]
  996. tissue_distribution = [None] * 2
  997. for o in range(2):
  998. tissue_distribution[o] = [None] * 4
  999. for t in range(4):
  1000. tissue_distribution[o][t] = [None] * 4
  1001. OUTCOME_NAMES = ["good", "poor"]
  1002. TISSUE_TYPE_NAMES = ["Full Network", "GM-only", "WM-only", "GM-WM"]
  1003. for o in range(2):
  1004. for t in range(4):
  1005. for s in range(4):
  1006. FCtissueAll_outcomes_single = FCtissueAll_outcomes[o]
  1007. fc_patient = []
  1008. for i in range(len(FCtissueAll_outcomes_single)):
  1009. fc = utils.getUpperTriangle(FCtissueAll_outcomes_single[i][func][freq][t][s])
  1010. fc_patient.append(fc)
  1011. tissue_distribution[o][t][s] = np.array([item for sublist in fc_patient for item in sublist])
  1012. for s in [1,2]:
  1013. fig, axes = utils.plot_make(c = 2, r = 2, size_height = 5)
  1014. axes = axes.flatten()
  1015. for t in range(4):
  1016. sns.ecdfplot(data = tissue_distribution[0][t][s], ax = axes[t], color = plot.COLORS_GOOD_VS_POOR[0], lw = 6)
  1017. sns.ecdfplot(data = tissue_distribution[1][t][s], ax = axes[t], color = plot.COLORS_GOOD_VS_POOR[1], lw = 6, ls = "-")
  1018. axes[t].set_title(f"{TISSUE_TYPE_NAMES[t]}, {STATE_NAMES[s]} {stats.ks_2samp( tissue_distribution[0][t][s], tissue_distribution[1][t][s] )[1]*16 }" )
  1019. axes[t].spines['top'].set_visible(False)
  1020. axes[t].spines['right'].set_visible(False)
  1021. axes[t].set_xlim([0,1])
  1022. utils.save_figure(join(paths.FIGURES, "GM_vs_WM", f"good_vs_poor_{STATE_NAMES[s]}.pdf"), save_figure=False,
  1023. bbox_inches = "tight", pad_inches = 0.0)
  1024. #good vs poor -- delta

REVELL_MDPHD_THESIS_WORK.py at commit 942cd91, no license · at the source

Overview

Authors: Andrew Y Revell1,2,3, Marc Jaskir1,4, Akash R Pattnaik3,4, William K S Ojemann3,4, Erin Conrad3,5, Nishant Sinha3,4, Brittany H Scheid3,4, Alfredo Lucas3,4, John M Bernabei3,4, John Beckerle6, Joel M Stein3,5, Sandhitsu R Das3,7, Brian Litt3,4,5, Kathryn A Davis1,3,5
  1. Department of Neuroscience, Perelman School of Medicine, University of Pennsylvania, Philadelphia, PA, USA
  2. Department of Radiology, Brigham and Women's Hospital, Harvard University, Boston, MA, USA
  3. Center for Neuroengineering and Therapeutics, University of Pennsylvania, Philadelphia, PA, USA
  4. Department of Bioengineering, School of Engineering and Applied Science, University of Pennsylvania, Philadelphia, PA, USA
  5. Department of Neurology, Perelman School of Medicine, University of Pennsylvania, Philadelphia, PA, USA
  6. Department of Neuroscience, The Warren Alpert Medical School, Brown University, Providence, RI, USA
  7. Department of Radiology, Perelman School of Medicine, University of Pennsylvania, Philadelphia, PA, USA
Institutions: Brigham and Women's Hospital (United States); Harvard University (United States); University of Pennsylvania (United States); Brown University (United States)
Journal: Annals of neurology, volume 100, issue 1, pages 59-73
Dates: received 23 January 2024; accepted 24 February 2026; published online 8 May 2026; in print July 2026
Type: Research article · Language: English
License: CC BY-NC
Identifiers: DOI 10.1002/ana.78203 · PMID 42101065 · PMCID PMC13327593 · OpenAlex W7160626242
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: structural MRI / diffusion (modality), EEG (modality), human (organism), epilepsy (population)
Methods: Preprocessing, Connectivity, Spectral & time-frequency, Machine learning, Statistics, Physiology & signal measures, fMRI & imaging
MeSH: Brain Mapping*, Deep Learning*, Epilepsy*, Seizures*, Adult, Algorithms, Brain, Diffusion Magnetic Resonance Imaging, Electroencephalography, Female, Humans, Male (* major topic)
Topic: Functional Brain Connectivity Studies (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: Clinical Center (1R01MH112847, 1R01NS099348, 1R01NS085211, 1R01NS116504, 5‐T32‐NS‐091006‐07); Pennsylvania Tobacco Fund; Sloan Foundation; Thornton Foundation; CLC NIH HHS (1R01NS085211, 1R01NS099348, 5-T32-NS-091006-07, 1R01MH112847, 1R01NS116504); Alfred P. Sloan Foundation; Mirowski Family Foundation; John D. and Catherine T. MacArthur Foundation; Paul Allen Foundation; Institute for Scientific Interchange; ISI Foundation
Citations: not cited yet (Europe PMC); 50 references in the paper

Abstract

Objective: The focus of epilepsy research has largely been on seizure onset; however, physicians typically examine the patterns of seizure spread past seizure onset as well. This study aims to align automated seizure analysis with clinical practice, leverage deep learning to standardize seizure annotations that varies among physicians, and understand common seizure spread patterns across patients.

Methods: We developed deep learning algorithms on a small subset of patients to detect seizure activity and deployed these algorithms across 275 seizures in 71 patients to analyze the patterns of seizure spread (extent, timing, surgical outcomes, and common patterns) along with incorporating diffusion‐weighted imaging to understand how these patterns relate to the structural connections of the brain.

Results: Deep learning algorithms outperform single features (line length, absolute slope, and power) in ranking seizure onset contacts using physician annotations as a benchmark. We also find that poor outcome patients have more extensive brain regions involved in their seizures while also having more rapid spread between temporal lobes. Incorporating diffusion‐weighted imaging, we find that an increase in structural connectivity between temporal lobes is associated with quicker seizure spread. Finally, we identify clusters of spread patterns common across patients based on spread timing, location, and extent.

Interpretation: Analyzing seizure spread can reveal new insights into seizure evolution and its relationship with surgical outcomes in patients with epilepsy. The findings also suggest that focusing beyond seizure onset is crucial for understanding and treating epilepsy. ANN NEUROL 2026;100:59–73

Reproduced under the paper's license (CC BY-NC), 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.

andrewyrevell/revellLab

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: 942cd9101906388fe38ea4f4c0373b2f496f3897, 15 July 2022
Languages: Python (178), JavaScript (7), R (6), C/C++ (6), Shell (1)
Size: 925 files, 198 scripts
Software Heritage: not archived
Found in: the text, “Deep Learning Algorithms”
Holds: README, environment (environment/environment.yml, environment/environment2.yml, packages/atlasLocalization/environment.yaml, papers/white_matter_iEEG/environment/environment_wm_iEEG.yml, packages/eeg/ieegOrg/ieegpy/setup.py)
Not found: license file, CITATION.cff, tests, continuous integration, documentation
Tools: NumPy (138 files), pandas (117 files), Matplotlib (80 files), SciPy (64 files), seaborn (60 files), NiBabel (42 files), Brain Connectivity Toolbox (33 files), scikit-learn (29 files), statsmodels (24 files), NetworkX (22 files), Pingouin (21 files), TensorFlow (16 files), Keras (15 files), cowplot (6 files), ggplot2 (6 files), FSL (5 files), ggpubr (3 files), QSIPrep (3 files), scikit-image (3 files), Pillow (1 file), PyTorch (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
199 files

andyrevell/revellLab

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: 942cd9101906388fe38ea4f4c0373b2f496f3897, 15 July 2022
Languages: Python (178), JavaScript (7), R (6), C/C++ (6), Shell (1)
Size: 925 files, 198 scripts
Software Heritage: not archived
Found in: the text, “Python Packages and Versions”
Holds: README, environment (environment/environment.yml, environment/environment2.yml, packages/atlasLocalization/environment.yaml, papers/white_matter_iEEG/environment/environment_wm_iEEG.yml, packages/eeg/ieegOrg/ieegpy/setup.py)
Not found: license file, CITATION.cff, tests, continuous integration, documentation
Tools: NumPy (138 files), pandas (117 files), Matplotlib (80 files), SciPy (64 files), seaborn (60 files), NiBabel (42 files), Brain Connectivity Toolbox (33 files), scikit-learn (29 files), statsmodels (24 files), NetworkX (22 files), Pingouin (21 files), TensorFlow (16 files), Keras (15 files), cowplot (6 files), ggplot2 (6 files), FSL (5 files), ggpubr (3 files), QSIPrep (3 files), scikit-image (3 files), Pillow (1 file), PyTorch (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
199 files

The paper's code and data availability statement is in the Data section.

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:

  • 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 396 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

No dataset and no data link were found in the paper.

Data Availability

All analysis code used in this study is publicly available at the repository cited in the manuscript. The underlying intracranial EEG and structural/diffusion MRI data have been curated in Brain Imaging Data Structure (BIDS) format. Because these raw data contain potentially identifiable patient information (including facial features on MRI), they cannot be deposited in an open public repository under the terms of our institutional review board approval. De‐identified derivative data supporting the findings of this study (eg, seizure‐spread metrics, regional activation times, and connectivity matrices) are available from the corresponding author. BIDS‐formatted raw data can be shared with qualified investigators for non‐commercial research purposes upon reasonable request and completion of a data‐use agreement approved by the University of Pennsylvania Institutional Review Board.

Reproduced under the paper's license (CC BY-NC), 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 2, 28 September 2026

  • Publisher: n/a → Wiley

Version 1, 28 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 14 authors, 12 MeSH terms, 11 funders, 45 references.

Cite

This paper

Revell, A. Y., Jaskir, M., Pattnaik, A. R., Ojemann, W. K. S., Conrad, E., Sinha, N., Scheid, B. H., Lucas, A., Bernabei, J. M., Beckerle, J., Stein, J. M., Das, S. R., Litt, B., & Davis, K. A. (2026). AI-Driven Mapping of Seizure Spread Patterns. Annals of neurology, 100(1), 59-73. https://doi.org/10.1002/ana.78203

BibTeX

@article{revell2026ai,
author = {Revell, Andrew Y and Jaskir, Marc and Pattnaik, Akash R and Ojemann, William K S and Conrad, Erin and Sinha, Nishant and Scheid, Brittany H and Lucas, Alfredo and Bernabei, John M and Beckerle, John and Stein, Joel M and Das, Sandhitsu R and Litt, Brian and Davis, Kathryn A},
title = {{AI-Driven Mapping of Seizure Spread Patterns}},
journal = {Annals of neurology},
year = {2026},
month = may,
volume = {100},
number = {1},
pages = {59--73},
publisher = {Wiley},
issn = {0364-5134},
doi = {10.1002/ana.78203},
url = {https://doi.org/10.1002/ana.78203},
pmid = {42101065},
pmcid = {PMC13327593}
}

RIS

TY - JOUR
AU - Revell, Andrew Y
AU - Jaskir, Marc
AU - Pattnaik, Akash R
AU - Ojemann, William K S
AU - Conrad, Erin
AU - Sinha, Nishant
AU - Scheid, Brittany H
AU - Lucas, Alfredo
AU - Bernabei, John M
AU - Beckerle, John
AU - Stein, Joel M
AU - Das, Sandhitsu R
AU - Litt, Brian
AU - Davis, Kathryn A
TI - AI-Driven Mapping of Seizure Spread Patterns
T2 - Annals of neurology
J2 - Ann Neurol
PY - 2026
DA - 2026/05/08
VL - 100
IS - 1
SP - 59
EP - 73
SN - 0364-5134
PB - Wiley
DO - 10.1002/ana.78203
UR - https://doi.org/10.1002/ana.78203
LA - en
ER -

CSL-JSON

{
"id": "10.1002/ana.78203",
"type": "article-journal",
"title": "AI-Driven Mapping of Seizure Spread Patterns",
"container-title": "Annals of neurology",
"author": [
{
"family": "Revell",
"given": "Andrew Y"
},
{
"family": "Jaskir",
"given": "Marc"
},
{
"family": "Pattnaik",
"given": "Akash R"
},
{
"family": "Ojemann",
"given": "William K S"
},
{
"family": "Conrad",
"given": "Erin"
},
{
"family": "Sinha",
"given": "Nishant"
},
{
"family": "Scheid",
"given": "Brittany H"
},
{
"family": "Lucas",
"given": "Alfredo"
},
{
"family": "Bernabei",
"given": "John M"
},
{
"family": "Beckerle",
"given": "John"
},
{
"family": "Stein",
"given": "Joel M"
},
{
"family": "Das",
"given": "Sandhitsu R"
},
{
"family": "Litt",
"given": "Brian"
},
{
"family": "Davis",
"given": "Kathryn A"
}
],
"container-title-short": "Ann Neurol",
"volume": "100",
"issue": "1",
"page": "59-73",
"DOI": "10.1002/ana.78203",
"PMID": "42101065",
"PMCID": "PMC13327593",
"ISSN": "0364-5134",
"publisher": "Wiley",
"URL": "https://doi.org/10.1002/ana.78203",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
8
]
]
}
}

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.1093/nc/niag029 [code]
A data-driven approach to identifying and evaluating connectivity-based neural correlates of conscious visual perception.
Journal: Neuroscience of consciousness
In common: Pingouin, FSL, NetworkX, 12 other tools, 1 reference
[2] doi:10.1371/journal.pcbi.1014571 [code]
SynAPSeg: A novel dataset and image analysis framework for deep learning-based synapse detection and quantification.
Journal: PLoS computational biology
In common: Pingouin, Keras, TensorFlow, 11 other tools, 1 reference
[3] doi:10.1038/s42003-026-10957-8 [code]
Brain defence by the extracellular matrix protein Cochlin.
Journal: Communications biology
In common: Keras, TensorFlow, NetworkX, 12 other tools
[4] doi:10.1016/j.xcrm.2026.102766 [code]
A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.
Journal: Cell reports. Medicine
In common: Keras, TensorFlow, NetworkX, 11 other tools
[5] doi:10.1038/s41398-026-04081-8 [code]
Functional system-specific brain aging across the Alzheimer's disease continuum.
Journal: Translational psychiatry
In common: QSIPrep, Pingouin, Keras, 9 other tools, structural MRI / diffusion
[6] doi:10.1016/j.nicl.2026.104012 [code]
Structural-functional multilayer brain network properties and outcome of combined repetitive transcranial magnetic stimulation and psychotherapy for obsessive-compulsive disorder.
Journal: NeuroImage. Clinical
In common: Brain Connectivity Toolbox, Pingouin, NetworkX, 10 other tools, structural MRI / diffusion
[7] doi:10.7554/elife.103097 [code]
Canonical neurodevelopmental trajectories of structural and functional manifolds.
Journal: eLife
In common: Brain Connectivity Toolbox, Pingouin, cowplot, 8 other tools, structural MRI / diffusion, 1 reference
[8] doi:10.1002/alz.71649 [code]
Postmortem brain MRI reveals differential associations of subcortical and limbic volumes with cortical thinning and neurodegenerative pathologies.
Journal: Alzheimer's & dementia : the journal of the Alzheimer's Association
In common: Pingouin, FSL, scikit-image, 10 other tools, structural MRI / diffusion
[9] doi:10.3389/fnsys.2026.1822122 [code]
Convergence-divergence circuits for multimodal integration of innate and learned opponent valences.
Journal: Frontiers in systems neuroscience
In common: Keras, TensorFlow, NetworkX, 10 other tools
[10] doi:10.1186/s12880-026-02481-2 [code]
Deep learning-based neuroanatomical profiling reveals population-specific brain changes in multiple sclerosis: a large-scale Middle Eastern study.
Journal: BMC medical imaging
In common: Keras, TensorFlow, FSL, 9 other tools, structural MRI / diffusion

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.

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.