OSCR

Memory and Resting-State Connectivity in Acute Transient Global Amnesia: A Case-Control fMRI Study.

Code ↔ Paper

5 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 5 matches
  1. [1] § Materials and Methods › Statistical Analysis ↔ analysis/functions.py, lines 129–219 · score 0.76 · Aligned Rank Transform, Post hoc, Shapiro, ART, ANOVA, scores
  2. [2] § Results › Functional MRI ↔ analysis/ICA.ipynb, lines 50–65 · score 0.73 · dorsal DMN, ventral DMN, right SN, voxel, ECN, ICA
  3. [3] § Materials and Methods › Neuropsychological Battery ↔ analysis/main_analysis.ipynb, lines 81–200 · score 0.58 · cued recall, free recall, anterograde memory, incidental, clap, Mnemosyne
  4. [4] § Materials and Methods › Statistical Analysis ↔ analysis/functions.py, lines 129–219 · score 0.58 · post hoc, Linear, predictors, variables, fitted, Model
  5. [5] § Results › Neuropsychological Results ↔ analysis/main_analysis.ipynb, lines 81–200 · score 0.54 · cued recall, free recall, Anterograde memory, incidental, AES, scores

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 · 785 lines · 34 KB · no license · 2 matches

  1. import numpy as np
  2. import math
  3. from scipy import stats
  4. import scipy
  5. import scipy.io
  6. from scipy import stats
  7. import scipy.cluster.hierarchy as sch
  8. import statsmodels.stats.api as sms
  9. import statsmodels.formula.api as smf
  10. from statsmodels.stats.anova import AnovaRM
  11. import pingouin as pg
  12. from scipy.stats import shapiro, levene, rankdata
  13. import pandas as pd
  14. import matplotlib.pyplot as plt
  15. import seaborn as sns
  16. import plotly.figure_factory as ff
  17. import os
  18. import warnings
  19. toyDict = {}
  20. # To change backslashes : follow path by .replace(os.sep, '/')
  21. cwd = os.getcwd()
  22. fMRI_dataroot = cwd + '/../data/fMRI_data'
  23. neuropsy_dataroot = cwd + '/../data/neuropsy_data/Comportement/Bases de données/'
  24. IRMs_datapath = cwd + '/../data/sMRI/ANALYSE-ICTUS-5AOUT-15_editedElias.ods'
  25. #plots_path = cwd + '/../results/plots/'
  26. plots_path = cwd + '/../plots/'
  27. #plots_path = 'C:/Users/Lenovo/Desktop/Ictus/analysis/fMRI_neuropsy_analysis/../results/plots/'
  28. def gather(param, pT1 = 'pT1', pT2 = 'pT2', pT3 = 'pT3', cT1 = 'cT1', cT2 = 'cT2', cT3 = 'cT3', trans = toyDict, df = pd.DataFrame()):
  29. translated = trans.loc[param]
  30. if translated[pT1] == 'NaN' : pT1values = [np.nan]*20
  31. else : pT1values = df[pT1][translated[pT1]]
  32. if translated[pT2] == 'NaN' : pT2values = [np.nan]*20
  33. else : pT2values = df[pT2][translated[pT2]]
  34. if translated[pT3] == 'NaN' : pT3values = [np.nan]*20
  35. else : pT3values = df[pT3][translated[pT3]]
  36. if translated[cT1] == 'NaN' : cT1values = [np.nan]*20
  37. else : cT1values = df[cT1][translated[cT1]]
  38. if translated[cT2] == 'NaN' : cT2values = [np.nan]*20
  39. else : cT2values = df[cT2][translated[cT2]]
  40. if translated[cT3] == 'NaN' : cT3values = [np.nan]*20
  41. else : cT3values = df[cT3][translated[cT3]]
  42. return [pT1values, pT2values, pT3values, cT1values, cT2values, cT3values]
  43. ## STATISTICAL ANALYSIS ##
  44. ##########################
  45. def confint(data, confidence=0.95):
  46. a = 1.0 * np.array(data)
  47. n = len(a)
  48. m, se = np.mean(a), scipy.stats.sem(a)
  49. h = se * scipy.stats.t.ppf((1 + confidence) / 2., n-1)
  50. return m, m-h, m+h
  51. def aligned_rank_transform(df, subject_col, dv, within, between):
  52. """
  53. Perform the Aligned Rank Transform on the data.
  54. Parameters:
  55. df : DataFrame
  56. Data containing the variables.
  57. subject_col : str
  58. The column name representing subjects.
  59. dv : str
  60. The dependent variable column name.
  61. within : str
  62. The within-subject factor column name.
  63. between : str
  64. The between-subject factor column name.
  65. Returns:
  66. DataFrame
  67. The transformed data with an added column for aligned ranks.
  68. """
  69. # Align the data
  70. #global overall_mean, aligned_data, within_means, between_means, cell_means
  71. overall_mean = df[dv].mean()
  72. aligned_data = df.copy()
  73. # Calculate marginal means for the main effects and interaction
  74. within_means = df.groupby(within)[dv].transform('mean')
  75. between_means = df.groupby(between)[dv].transform('mean')
  76. cell_means = df.groupby([within, between])[dv].transform('mean')
  77. # Align data for main effects and interaction
  78. #aligned_within = df[dv] - within_means + overall_mean
  79. #aligned_between = df[dv] - between_means + overall_mean
  80. #aligned_interaction = df[dv] - cell_means + overall_mean
  81. residuals = df[dv] - cell_means
  82. aligned_within = residuals + within_means - overall_mean
  83. aligned_between = residuals + between_means - overall_mean
  84. aligned_interaction = residuals + cell_means - overall_mean
  85. # Verify that each column of aligned responses sums to zero
  86. within_bool = np.isclose(aligned_within.sum(), 0), "Aligned within responses do not sum to zero"
  87. between_bool = np.isclose(aligned_between.sum(), 0), "Aligned between responses do not sum to zero"
  88. interaction_bool = np.isclose(aligned_interaction.sum(), 0), "Aligned interaction responses do not sum to zero"
  89. for boolean, name in zip((within_bool, between_bool, interaction_bool), ('within', 'betweenn', 'interaction')) :
  90. if not boolean : print('WARNING : {} alignement does not sum to zero'.format(name))
  91. # Rank the aligned data
  92. aligned_data['AlignedRankWithin'] = rankdata(aligned_within)
  93. aligned_data['AlignedRankBetween'] = rankdata(aligned_between)
  94. aligned_data['AlignedRankInteraction'] = rankdata(aligned_interaction)
  95. return aligned_data
  96. def myANOVA(data, display = False, perform_parametric_anova = False): # 2nd argument : perform regular anova whatever Shapiro's results
  97. if type(data) != type(np.array(0)) : data = np.array(data)
  98. # Flatten the array into a long format
  99. data_flat = data.flatten()
  100. # Generate the Subject, Group, and Time labels correctly
  101. subjects = np.hstack( (np.tile(np.arange(1, 21), 3), np.tile(np.arange(21, 41), 3))) # Each subject appears 6 times (3 times per group)
  102. times = np.tile(['T1']*20 + ['T2']*20 + ['T3']*20, 2) # Each time point repeats for all subjects in both groups
  103. groups = np.array(['Patient']*60 + ['Control']*60) # Each group label is repeated for 3 time points for all 20 subjects
  104. # Creating the DataFrame
  105. df = pd.DataFrame({
  106. 'Subject': subjects,
  107. 'Group': groups,
  108. 'Time': times,
  109. 'Score': data_flat
  110. })
  111. # ASSUMPTIONS CHECK
  112. ###################
  113. # Convert categorical variables to dummy variables for regression
  114. df_dummies = pd.get_dummies(df, columns=['Group', 'Time'], drop_first=True)
  115. # Fit a linear regression model with dummy variables
  116. results = pg.linear_regression(df_dummies[['Group_Patient', 'Time_T2', 'Time_T3']], df_dummies['Score'])
  117. df_dummies['predicted'] = results['coef'].values[0] + np.dot(df_dummies[['Group_Patient', 'Time_T2', 'Time_T3']], results['coef'].values[1:])
  118. df['residuals'] = df['Score'] - df_dummies['predicted']
  119. # Normality test on the residuals
  120. normality = shapiro(df['residuals'])
  121. # Homogeneity of variances test
  122. homoscedasticity = levene(df[df['Time'] == 'T1']['Score'],
  123. df[df['Time'] == 'T2']['Score'],
  124. df[df['Time'] == 'T3']['Score'])
  125. # Sphericity test using Mauchly's test in pingouin
  126. sphericity = pg.sphericity(df, dv='Score', subject='Subject', within='Time')
  127. # ART-transfrom (ranking within each combination of Group and Time for each Subject) if data non normal
  128. #if normality.pvalue < 0.05 :
  129. #df['Score'] = df.groupby(['Subject', 'Group', 'Time'])['Score'].rank(method='average')
  130. #df['Score'] = df.groupby(['Group', 'Time'])['Score'].rank(method='average')
  131. #return df, normality, homoscedasticity, sphericity
  132. # Perform the two-way repeated measures ANOVA
  133. #############################################
  134. if (normality.pvalue < 0.05 and not perform_parametric_anova) :
  135. # Apply Aligned Rank Transform
  136. print('Performing ART ANOVA...')
  137. artDf = aligned_rank_transform(df, subject_col='Subject', dv='Score', within='Time', between='Group')
  138. aov_between = pg.mixed_anova(dv='AlignedRankBetween', between='Group', within='Time', subject='Subject', data=artDf)
  139. aov_between = aov_between.loc[aov_between['Source'] == 'Group']
  140. aov_within = pg.mixed_anova(dv='AlignedRankWithin', between='Group', within='Time', subject='Subject', data=artDf)
  141. aov_within = aov_within.loc[aov_within['Source'] == 'Time']
  142. aov_interaction = pg.mixed_anova(dv='AlignedRankInteraction', between='Group', within='Time', subject='Subject', data=artDf)
  143. aov_interaction = aov_interaction.loc[aov_interaction['Source'] == 'Interaction']
  144. aov = pd.concat([aov_within, aov_between, aov_interaction], axis=0, ignore_index=True)
  145. else:
  146. dv = aov = pg.mixed_anova(dv='Score', between='Group', within='Time', subject='Subject', data=df)
  147. #df['Group_Time'] = df['Group'] + '_' + df['Time']
  148. #tukey = pg.pairwise_tukey(data=df, dv='Score', between='Group_Time')
  149. # Post-hoc tests within subjects with FDR correction (Benjamini-Hochberg)
  150. #post_hoc_within = pg.pairwise_ttests(data=df, dv='value', within='time', subject='subject', padjust='fdr_bh')
  151. # (nice but studies only one factor...)
  152. # rem to do Games-Howell post-hoc tests if homoscedasticity not met !!! (if it exists for mixed models...)
  153. if display :
  154. print("ANOVA Table:")
  155. print(aov)
  156. print("\nNormality test (Shapiro-Wilk) on residuals:")
  157. print(f"Statistic: {normality.statistic}, p-value: {normality.pvalue}")
  158. print("\nLevene's Test for Homogeneity of variances across time points:")
  159. print(f"Statistic: {homoscedasticity.statistic}, p-value: {homoscedasticity.pvalue}")
  160. print("\nSphericity test (Mauchly's):")
  161. print(f"W-value: {sphericity[0]}, p-value: {sphericity[1]}, is sphericity met: {sphericity[2]}")
  162. return aov, normality, homoscedasticity, sphericity #, tukey
  163. def cluster_corr(corr_array, inplace=False):
  164. """
  165. Rearranges the correlation matrix, corr_array, so that groups of highly
  166. correlated variables are next to eachother
  167. Parameters
  168. ----------
  169. corr_array : pandas.DataFrame or numpy.ndarray
  170. a NxN correlation matrix
  171. Returns
  172. -------
  173. pandas.DataFrame or numpy.ndarray
  174. a NxN correlation matrix with the columns and rows rearranged
  175. """
  176. pairwise_distances = sch.distance.pdist(corr_array)
  177. linkage = sch.linkage(pairwise_distances, method='complete')
  178. cluster_distance_threshold = pairwise_distances.max()/2
  179. idx_to_cluster_array = sch.fcluster(linkage, cluster_distance_threshold,
  180. criterion='distance')
  181. idx = np.argsort(idx_to_cluster_array)
  182. if not inplace:
  183. corr_array = corr_array.copy()
  184. if isinstance(corr_array, pd.DataFrame):
  185. return corr_array.iloc[idx, :].T.iloc[idx, :]
  186. return corr_array[idx, :][:, idx]
  187. #DON'T FORGET we've included data computations in the function
  188. def compute_pairwise_tests(data, anova_res, sign_threshold, nsessions):
  189. ## Determine, from ANOVA results, what comparisons should be made
  190. if not type(anova_res) == type(pd.DataFrame()) : aov = anova_res[0] # Take only anova results, without shapiro, Levene...
  191. else : aov = anova_res
  192. pvalues = np.empty((nsessions*2,nsessions*2))
  193. pvalues[:] = np.nan
  194. if ( (aov['Source'] == 'No anova provided').any() \
  195. or (aov.loc[aov['Source'] == 'Interaction']['p-unc'] < sign_threshold).any() \
  196. or ( (aov.loc[aov['Source'] == 'Time']['p-unc'] < sign_threshold).any() \
  197. and (aov.loc[aov['Source'] == 'Group']['p-unc'] < sign_threshold).any())) :
  198. indexes_to_compare = [(0,1), (1,2), (0,2), (3,4), (4,5), (3,5), (0,3), (1,4), (2,5)]
  199. comparisons = ['PxP', 'PxP', 'PxP_wide', 'CxC', 'CxC', 'CxC_wide', 'PxC', 'PxC', 'PxC']
  200. else :
  201. if ( aov.loc[aov['Source'] == 'Time']['p-unc'] < sign_threshold ).any() :
  202. indexes_to_compare = [(0,1), (1,2), (0,2), (3,4), (4,5), (3,5)]
  203. comparisons = ['PxP', 'PxP', 'PxP_wide', 'CxC', 'CxC', 'CxC_wide']
  204. elif ( aov.loc[aov['Source'] == 'Group']['p-unc'] < sign_threshold ).any() :
  205. indexes_to_compare = [(0,3), (1,4), (2,5)]
  206. comparisons = ['PxC', 'PxC', 'PxC']
  207. else :
  208. indexes_to_compare = []
  209. comparisons = []
  210. ## Perform pairwise T tests
  211. for (x, y) in indexes_to_compare : # We could use the comparisons list here
  212. if abs(x - y) >= nsessions : # Between-group comparison
  213. pvalues[(x,y)] = stats.ttest_ind(data[x], data[y], equal_var=False).pvalue
  214. else : #Within-group comparison
  215. pvalues[(x,y)] = stats.ttest_rel(data[x], data[y]).pvalue
  216. return pvalues, indexes_to_compare, comparisons
  217. def plot_pairwise_tests(data, anova_res, sign_threshold, nsessions, xPositions,
  218. plot_type, confint_upper_bounds = np.zeros(6), confint_lower_bounds = np.zeros(6), lower_controls_asterisks = 0):
  219. # Plots pairwise comparisons and returns the min and max y values of the plotted comparisons, along with the scale and scale divider
  220. if plot_type == 'boxplot' :
  221. maxvalue = np.max(data)
  222. minvalue = np.min(data)
  223. minvalue_except_pT1 = np.min(data[1:]) # We won't consider pT1 min value for plotting within-controls significativity
  224. elif plot_type == 'graphchart' :
  225. maxvalue = np.max([np.nanmean(data[i]) + confint_upper_bounds[i] for i in range(len(data))])
  226. minvalue = np.min([np.nanmean(data[i]) - confint_lower_bounds[i] for i in range(len(data))])
  227. minvalue_except_pT1 = np.min(np.nanmean(data[1:,:], axis = 1) - confint_lower_bounds[1:]) # We won't consider pT1 min value for plotting within-controls significativity
  228. else :
  229. raise ValueError('Choose a plot type between graphchart and boxplot')
  230. scale = (maxvalue - minvalue)
  231. #plt.ylim([minvalue - 0.15, maxvalue+scale/5])
  232. #plt.ylim(60)
  233. # Generic prototype supporting two sessions : [(x,y) for (x,y) in itertools.product('twice the list...') if x != y]
  234. # We want to compare :
  235. # Les p entre eux -> (0,1), (1,2), (0,2)
  236. # Les c entre eux -> (3,4), (4,5), (3,5)
  237. # Les p et c appariés -> (0,3), (1,4), (2,5)
  238. pvalues, indexes_to_compare, comparisons = compute_pairwise_tests(data, anova_res, sign_threshold, nsessions)
  239. # Determine display from pairwise comparison results
  240. y_loc_asterisk_max = 0 # will be modified if asterisks are plotted. Will determine the top limit of the y axis
  241. y_loc_asterisk_min = minvalue # will be modified if asterisks are below mean value. Legend and anova results will be plotted below if plotted
  242. scdvd = 12 #scale divider, modulates vertical spacing of significance lines
  243. for (x,y), comparison in zip(indexes_to_compare, comparisons) :
  244. pvalue = pvalues[x,y]
  245. if np.isnan(pvalue) : print('NaN pvalue')
  246. if pvalue < 0.005 : asterisk = '*\u2009*\u2009*'
  247. elif pvalue < 0.01 : asterisk = '*\u2009*'
  248. elif pvalue < 0.05 : asterisk = '*'
  249. else : asterisk = 'ns'
  250. #offset = 0.05 * (pvalue < 0.01)
  251. #y_loc_asterisk = scale/3 + max([data_means[i]+yerr[i] for i in [session, session+nsessions]])
  252. if pvalue >=0.05 :
  253. weight = 'normal'
  254. fontsize = 10
  255. else :
  256. weight = 'bold'
  257. fontsize = 12
  258. # Y_locations
  259. spacing = 1.5*scale/scdvd # Average spacing between max data points and lines, and between lines
  260. yloc_lowest_upper_line = np.array((maxvalue + scale/scdvd, maxvalue+ scale/scdvd)) \
  261. - spacing * (not any(['PxC' in comp for comp in comparisons])) # If no b/w grp comparisons we lower within-patients comparisons
  262. yloc_lower_line = np.array((minvalue_except_pT1 - scale/scdvd, minvalue_except_pT1 - scale/scdvd))
  263. if comparison == 'PxC' : # Between-group comparison
  264. yloc_line = yloc_lowest_upper_line
  265. elif comparison == 'PxP' :
  266. yloc_line = yloc_lowest_upper_line + spacing
  267. elif comparison == 'PxP_wide' :
  268. yloc_line = yloc_lowest_upper_line + 2*spacing
  269. elif comparison == 'CxC' :
  270. yloc_line = yloc_lower_line + lower_controls_asterisks
  271. elif comparison == 'CxC_wide' :
  272. yloc_line = yloc_lower_line - spacing + lower_controls_asterisks
  273. groupwise_xPositions = [xPositions[i] for i in (0,2,4,1,3,5)]# x positions ordered according to group orders in data
  274. #groupwise_xPositions = [xPositions[i] for i in (1,3,5,1,3,5)]
  275. # x_locations
  276. if comparison in ('PxP', 'CxC') :
  277. lag = 0.02 #Add some space between adjacent lines
  278. if y in (1,4) : xloc_line = ((groupwise_xPositions[x], groupwise_xPositions[y]-lag))
  279. elif x in (1,4) : xloc_line = ((groupwise_xPositions[x]+lag, groupwise_xPositions[y]))
  280. else : print('PROBLEM')
  281. else :
  282. intergroup_comp_wider = 0 # Only useful for graphcharts, see below
  283. if plot_type == "graphchart" :
  284. if abs(y - x) == 3 : # Means intergroups comparison
  285. intergroup_comp_wider = 0.03 # otherwise intergroup comparison lines too short
  286. xloc_line = ((groupwise_xPositions[x]-intergroup_comp_wider, groupwise_xPositions[y]+intergroup_comp_wider))
  287. # Colors
  288. if comparison in ('CxC', 'CxC_wide') : color = 'steelblue'
  289. elif comparison in ('PxP', 'PxP_wide') : color = 'indianred'
  290. else : color = 'black'
  291. y_loc_asterisk = yloc_line[0] + 0.2*scale/scdvd
  292. if y_loc_asterisk > y_loc_asterisk_max : y_loc_asterisk_max = y_loc_asterisk
  293. if y_loc_asterisk < y_loc_asterisk_min : y_loc_asterisk_min = y_loc_asterisk
  294. #return asterisk, weight, fontsize, color, xloc_line, yloc_line, y_loc_asterisk
  295. plt.text(sum(xloc_line)/2, y_loc_asterisk, asterisk, horizontalalignment = 'center',
  296. size = fontsize, weight = weight, color = color)
  297. plt.plot(xloc_line,
  298. yloc_line, color = color, linewidth = 1)
  299. #if y_loc_asterisk_max != 0 : plt.ylim(top = y_loc_asterisk_max + scale/scdvd )
  300. return y_loc_asterisk_min, y_loc_asterisk_max, scale, scdvd
  301. def niceGraphChart(data, title = 'Title', ylabel = 'Mean $\\rho$',
  302. xlabels = 'default', legend_loc = 'lower left', yerr = 'confint',
  303. save_as = 'do_not_save', plots_path = plots_path, show = True, sign = False,
  304. anova_res = pd.DataFrame(['No anova provided'], [0], ['Source']), sign_threshold = 0.05, fullsize=False,
  305. lower_controls_asterisks = 0, display_aov_text = False, x_aov_text = 1, y_aov_text = 1): # lower_controls_asterisk : DYI solution for lowering the comparison lines when misplaced (e.g. cross the patients data lines...). Enter negative values
  306. nsessions = int(len(data) /2)
  307. if xlabels == 'default' :
  308. if nsessions == 2 : xlabels = ('Day 0', 'Day 3')
  309. else : xlabels = ("Day 0", "Day 3", "Day 90")
  310. data_means = [np.nanmean(elem) for elem in data]
  311. pData_means=data_means[:nsessions]
  312. cData_means=data_means[nsessions:]
  313. print(pData_means)
  314. confints = []
  315. for sessionTime in range(6):
  316. confints.append(confint(data[sessionTime]))
  317. # Get the upper and lower spans from confints and mean
  318. upper_confint_spans = [confint[2] - confint[0] for confint in confints]
  319. lower_confint_spans = [confint[0] - confint[1] for confint in confints]
  320. #if yerr == 'std' : yerr = [np.std(elem) for elem in data]
  321. interstice = 0.05 # Between the two datapoints of two groups at one session
  322. if fullsize : fig = plt.figure(dpi=300)
  323. else : fig = plt.figure()
  324. Controls = plt.errorbar(
  325. x=(np.arange(nsessions) + interstice),#xlabels,
  326. y=cData_means,
  327. yerr=(lower_confint_spans[nsessions:], upper_confint_spans[nsessions:]),#yerr[nsessions:],#std_cT1vT2sign[3:],
  328. capsize=4,
  329. marker='o',
  330. color='steelblue',
  331. markersize=4,
  332. linewidth=2,
  333. zorder = 1,
  334. linestyle='-') # alternative : '--' for dashed
  335. Patients = plt.errorbar(
  336. x=xlabels,
  337. y=pData_means,
  338. yerr=(lower_confint_spans[:nsessions], upper_confint_spans[:nsessions]),#yerr[:nsessions],
  339. capsize=4,
  340. marker='s',
  341. color='indianred',
  342. markersize=4,
  343. linewidth=2,
  344. zorder = 2,
  345. linestyle='-')
  346. xPositions = [(x - interstice/2, x + interstice/2) for x in range(nsessions)]
  347. xPositions = [x for tup in xPositions for x in tup]
  348. if sign :
  349. y_loc_asterisk_min, y_loc_asterisk_max, scale, scdvd = plot_pairwise_tests(data, anova_res, sign_threshold, nsessions, xPositions,
  350. 'graphchart', upper_confint_spans, lower_confint_spans, lower_controls_asterisks )
  351. '''
  352. if sign :
  353. maxvalue = max(np.add(data_means,yerr))
  354. minvalue = min(np.subtract(data_means,yerr))
  355. scale = (maxvalue - minvalue) /5
  356. #plt.ylim([minvalue - 0.15, maxvalue+1])
  357. plt.ylim([minvalue - 0.15*scale, maxvalue+scale])
  358. for session in range(int(len(data_means)/2)):
  359. pvalue = stats.ttest_ind(data[session], data[session+nsessions], equal_var=False).pvalue
  360. if pvalue < 0.005 : asterisk = '*\u2009*\u2009*'
  361. elif pvalue < 0.01 : asterisk = '*\u2009*'
  362. elif pvalue < 0.05 : asterisk = '*'
  363. else : asterisk = 'ns'
  364. offset = 0.05 * (pvalue < 0.01)
  365. y_loc_asterisk = scale/3 + max([data_means[i]+yerr[i] for i in [session, session+nsessions]])
  366. if pvalue >=0.05 : weight = 'normal'
  367. else : weight = 'bold'
  368. plt.text(session - offset, y_loc_asterisk, asterisk, size = 12, weight = weight)
  369. '''
  370. if sign :
  371. if y_loc_asterisk_max != 0 : plt.ylim(bottom = y_loc_asterisk_min - scale/scdvd, top = y_loc_asterisk_max + scale/scdvd)
  372. plt.xlim(-0.15,nsessions -1 +0.15)
  373. legend = plt.legend((Patients, Controls),("Patients","Controls"), loc = legend_loc)
  374. #plot aov results :
  375. if display_aov_text and not (anova_res[0]['Source'] == 'No anova provided').any():
  376. aov_res = anova_res[0]
  377. aov_text_time = f"T : F({aov_res['DF1'][0]},{aov_res['DF2'][0]}) = {np.round(aov_res['F'][0], 2)}, p = {np.round(aov_res['p-unc'][0], 2)}"
  378. aov_text_group = f"G : F({aov_res['DF1'][1]},{aov_res['DF2'][1]}) = {np.round(aov_res['F'][1], 2)}, p = {np.round(aov_res['p-unc'][1], 2)}"
  379. aov_text_int = f"X : F({aov_res['DF1'][2]},{aov_res['DF2'][2]}) = {np.round(aov_res['F'][2], 2)}, p = {np.round(aov_res['p-unc'][2], 2)}"
  380. aov_text = '\n'.join([aov_text_time, aov_text_group, aov_text_int])
  381. # Place text box horizontally aligned to legend
  382. # Get the bounding box of the legend in display coordinates
  383. bbox = legend.get_window_extent()
  384. # Get the transformation to convert display coordinates to data coordinates
  385. trans = plt.gca().transData.inverted()
  386. # Transform the bounding box to data coordinates
  387. bbox_in_data = bbox.transformed(trans)
  388. # Get the coordinates of the legend (x, y, width, height) in data coordinates
  389. legend_coordinates_data = bbox_in_data.bounds
  390. y_aov_text = legend_coordinates_data[1] + legend_coordinates_data[3] / 2 # Adjust y to match the center of the legend box
  391. x_aov_text = 2.1
  392. text_box_height = legend_coordinates_data[3] # The height of the legend
  393. # Add text with a matching box height
  394. plt.text(x_aov_text, y_aov_text, aov_text, size=8, bbox=dict(facecolor='none', edgecolor='gray', boxstyle=f'round,pad={text_box_height/2}'),
  395. horizontalalignment='right', verticalalignment='center')
  396. plt.ylabel(ylabel)
  397. plt.title(title)
  398. ## widen both limits to give some whitespace to the plot
  399. #plt.ylim(-5, 105)
  400. #plt.xlim(-0.2, 3.2)
  401. # plt.savefig('Fig2.png', dpi=300, bbox_inches='tight')
  402. #plt.margins(5,5)
  403. if not save_as == 'do_not_save':
  404. plt.savefig(plots_path + save_as, dpi=300, bbox_inches='tight')
  405. print('Saved at' + str(plots_path+save_as))
  406. if show : plt.show()
  407. def niceBoxplot(data, title = 'Title', ylabel = 'Score',
  408. xlabels = 'default', legend_loc = 'lower left', yerr = 'default', scatter = True, notch = True,
  409. save_as = 'do_not_save', plots_path = plots_path, show = True, sign = False,
  410. anova_res = pd.DataFrame(['No anova provided'], [0], ['Source']),
  411. sign_threshold = 0.05, fullsize=False, lower_controls_asterisks = 0, display_aov_text = False) :
  412. nsessions = int(len(data) /2)
  413. if xlabels == 'default' :
  414. if nsessions == 2 : xlabels = ('Day 0', 'Day 3')
  415. else : xlabels = ('Day 0', 'Day 3', 'Day 90')
  416. if fullsize : fig = plt.figure(dpi=300)
  417. else : fig = plt.figure()
  418. #data = [data[i] for i in [index in tup for tup in [(0+session, 0+session +nsessions) for session in range(nsessions)] for index in tup]]
  419. nsessions = int(len(data)/2)
  420. order = [index for tup in [(0+session, 0+session +nsessions) for session in range(nsessions)] for index in tup]
  421. data_reordered = [data[index] for index in order]
  422. interstice = 0.3
  423. xPositions = [(x-interstice/2, x+interstice/2) for x in range(nsessions)]
  424. xPositions = [x for tup in xPositions for x in tup]
  425. xs = [np.random.normal(x , 0.05, len(data[0])) for x in xPositions]
  426. colored_plots = not scatter # We'll fill the boxes if we don't scatter
  427. box = plt.boxplot(data_reordered, positions = xPositions, showfliers = False, autorange = True, widths = 0.25, notch = notch, \
  428. patch_artist = colored_plots)#, labels=xlabels)
  429. palette = [color for tup in [('indianred', 'steelblue')*nsessions] for color in tup]
  430. if scatter :
  431. for x, val, c in zip(xs, data_reordered, palette):
  432. plt.scatter(x, val, alpha=0.8, color=c, s = 10)
  433. else :
  434. for patch, color in zip(box['boxes'], palette):
  435. patch.set_facecolor(color)
  436. if sign : y_loc_asterisk_min, y_loc_asterisk_max, scale, scdvd = plot_pairwise_tests(data, anova_res, sign_threshold, nsessions, xPositions, 'boxplot',
  437. lower_controls_asterisks = lower_controls_asterisks)
  438. '''
  439. if sign :
  440. maxvalue = np.max(data)
  441. minvalue = np.min(data)
  442. minvalue_except_pT1 = np.min(data[1:]) # We won't consider pT1 min value for plotting within-controls sign
  443. scale = (maxvalue - minvalue)
  444. plt.ylim([minvalue - 0.15, maxvalue+scale/5])
  445. #plt.ylim([minvalue - 0.15, maxvalue+1])
  446. #plt.ylim([minvalue - 0.15*scale, maxvalue+scale])
  447. for session in [2*i for i in range(nsessions)]:
  448. pvalue = stats.ttest_ind(data[session], data[session+1], equal_var=False).pvalue
  449. if pvalue < 0.005 : asterisk = '*\u2009*\u2009*'
  450. elif pvalue < 0.01 : asterisk = '*\u2009*'
  451. elif pvalue < 0.05 : asterisk = '*'
  452. else : asterisk = 'ns'
  453. #offset = 0.05 * (pvalue < 0.01)
  454. #y_loc_asterisk = scale/3 + max([data_means[i]+yerr[i] for i in [session, session+nsessions]])
  455. y_loc_asterisk = maxvalue + scale/10
  456. if pvalue >=0.05 : weight = 'normal'
  457. else : weight = 'bold'
  458. plt.text(int(session/2), y_loc_asterisk, asterisk, horizontalalignment = 'center', size = 12, weight = weight)
  459. plt.plot((xPositions[session], xPositions[session+1]),
  460. (maxvalue + scale/12, maxvalue+scale/12), color = 'black', linewidth = 1)
  461. '''
  462. #plt.xlim(-0.15,nsessions -1 +0.15)
  463. #plt.legend(("Patients","Controls"), colors = ('steelblue', 'indianred'), loc = legend_loc)
  464. from matplotlib.lines import Line2D
  465. colors = ('indianred', 'steelblue')
  466. lines = [Line2D([0], [0], color=c, linewidth=1, linestyle='None', marker = 'o', markersize = 3) for c in colors]
  467. labels = ['Patients', 'Controls']
  468. legend = plt.legend(lines, labels, loc = legend_loc, handletextpad = 0.1, handlelength=1, borderaxespad=0.5, fontsize = 8)
  469. if sign :
  470. if y_loc_asterisk_max != 0 and y_loc_asterisk_min < y_loc_asterisk_max:
  471. plt.ylim(bottom = y_loc_asterisk_min - scale/scdvd, top = y_loc_asterisk_max + scale/scdvd)
  472. #plt.xlim(-0.15,nsessions -1 +0.15)
  473. #legend = plt.legend((Patients, Controls),("Patients","Controls"), loc = legend_loc)
  474. #plot aov results :
  475. if display_aov_text and not (anova_res[0]['Source'] == 'No anova provided').any():
  476. aov_res = anova_res[0]
  477. aov_text_time = f"T : F({aov_res['DF1'][0]},{aov_res['DF2'][0]}) = {np.round(aov_res['F'][0], 2)}, p = {np.round(aov_res['p-unc'][0], 2)}"
  478. aov_text_group = f"G : F({aov_res['DF1'][1]},{aov_res['DF2'][1]}) = {np.round(aov_res['F'][1], 2)}, p = {np.round(aov_res['p-unc'][1], 2)}"
  479. aov_text_int = f"X : F({aov_res['DF1'][2]},{aov_res['DF2'][2]}) = {np.round(aov_res['F'][2], 2)}, p = {np.round(aov_res['p-unc'][2], 2)}"
  480. aov_text = '\n'.join([aov_text_time, aov_text_group, aov_text_int])
  481. # Place text box horizontally aligned to legend
  482. # Get the bounding box of the legend in display coordinates
  483. bbox = legend.get_window_extent()
  484. # Get the transformation to convert display coordinates to data coordinates
  485. trans = plt.gca().transData.inverted()
  486. # Transform the bounding box to data coordinates
  487. bbox_in_data = bbox.transformed(trans)
  488. # Get the coordinates of the legend (x, y, width, height) in data coordinates
  489. legend_coordinates_data = bbox_in_data.bounds
  490. y_aov_text = legend_coordinates_data[1] + legend_coordinates_data[3] / 2 # Adjust y to match the center of the legend box
  491. x_aov_text = 2.6
  492. text_box_height = legend_coordinates_data[3] # The height of the legend
  493. # Add text with a matching box height
  494. plt.text(x_aov_text, y_aov_text, aov_text, size=8, bbox=dict(facecolor='none', edgecolor='gray', boxstyle=f'round,pad={text_box_height/2}'),
  495. horizontalalignment='right', verticalalignment='center')
  496. plt.ylabel(ylabel)
  497. plt.xticks(ticks = range(len(xlabels)), labels=xlabels)
  498. plt.title(title)
  499. if not save_as == 'do_not_save' : plt.savefig(plots_path + save_as)
  500. plt.show()
  501. def RLvsRI_plot(RL, RI, RECO = np.zeros((6,20)), save_as = 'do_not_save', title = 'Title', ylabel = 'score', session = 1, nsessions = 3,
  502. need_to_add_RI_to_RL = True, sign = True):
  503. session -= 1
  504. if need_to_add_RI_to_RL :
  505. pT1_RI_sum = np.add(RI[session], RL[session])
  506. cT1_RI_sum = np.add(RI[session+nsessions], RL[session+nsessions])
  507. pT1_RECO_sum = np.add(RECO[session], pT1_RI_sum)
  508. cT1_RECO_sum = np.add(RECO[session+nsessions], cT1_RI_sum)
  509. else :
  510. pT1_RI_sum = RI[session]
  511. cT1_RI_sum = RI[session+nsessions]
  512. pT1_RECO_sum = RECO[session]
  513. cT1_RECO_sum = RECO[session+nsessions]
  514. fig, ax = plt.subplots(dpi=300)
  515. pT1_RL_data = np.mean(RL[session])
  516. cT1_RL_data = np.mean(RL[session+nsessions])
  517. pT1_RI_data = np.mean(pT1_RI_sum)
  518. cT1_RI_data = np.mean(cT1_RI_sum)
  519. pT1_RECO_data = np.mean(pT1_RECO_sum)
  520. cT1_RECO_data = np.mean(cT1_RECO_sum)
  521. ax.bar('Controls', cT1_RECO_data, color = 'moccasin')
  522. ax.bar('Controls', cT1_RI_data, color = 'orange')
  523. ax.bar('Controls', cT1_RL_data, color = 'blue')
  524. ax.bar('Patients', pT1_RECO_data, color = 'moccasin')
  525. ax.bar('Patients', pT1_RI_data, color = 'orange')
  526. ax.bar('Patients', pT1_RL_data, color = "blue")
  527. ax.legend(('RECO', 'RI', 'RL'))
  528. if sign :
  529. maxvalue = max(pT1_RI_data, cT1_RI_data)
  530. minvalue = 0
  531. scale = (maxvalue - minvalue) /5
  532. #plt.ylim([minvalue - 0.15, maxvalue+1])
  533. plt.ylim([minvalue - 0.15*scale, maxvalue+scale])
  534. pvalue = stats.ttest_ind(pT1_RI_sum, cT1_RI_sum, equal_var=False).pvalue
  535. if pvalue < 0.005 : asterisk = '*\u2009*\u2009*'
  536. elif pvalue < 0.01 : asterisk = '*\u2009*'
  537. elif pvalue < 0.05 : asterisk = '*'
  538. else : asterisk = 'ns'
  539. offset = 0.05 * (pvalue < 0.01)
  540. #y_loc_asterisk = scale/3 + max([data_means[i]+yerr[i] for i in [session, session+nsessions]])
  541. y_loc_asterisk = maxvalue + scale/2
  542. if pvalue >=0.05 : weight = 'normal'
  543. else : weight = 'bold'
  544. plt.text(0.5 - offset, y_loc_asterisk, asterisk, size = 12, weight = weight)
  545. plt.plot((0,1), (y_loc_asterisk - scale/8, y_loc_asterisk - scale/8), color = 'black')
  546. ax.set_ylabel(ylabel)
  547. ax.set_title(title)
  548. if not save_as == 'do_not_save' : plt.savefig(plots_path + save_as)
  549. plt.show()
  550. def niceScatterplot(data1, data2, plotEdges = True, title = 'Title', ylabel = 'Score', showMeans = False,
  551. xlabels = ('T1', 'T2'), legend_loc = 'upper right', yerr = 'default', zscores = False,
  552. save_as = 'do_not_save', plots_path = plots_path, show = True, sign = False, fullsize=False):
  553. fig, ax = plt.subplots(tight_layout=True, dpi = 100)
  554. #colors = ["cornflowerblue", "salmon"]
  555. #colors = ["cornflowerblue", "cornflowerblue"]
  556. colors = ['darkseagreen', 'antiquewhite', 'aqua', 'aquamarine', 'azure',
  557. 'beige', 'bisque', 'black', 'blanchedalmond', 'blue',
  558. 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse',
  559. 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson']
  560. colors = ['DarkRed', 'DarkOrange', 'DarkGreen', 'DarkCyan','DarkBlue','LightSalmon',
  561. 'LightGoldenRodYellow',
  562. 'LightGreen',
  563. 'LightSkyBlue',
  564. 'LightSlateGray',
  565. 'Salmon',
  566. 'SandyBrown',
  567. 'MediumSeaGreen',
  568. 'CornflowerBlue',
  569. 'SlateGray',
  570. 'Tomato',
  571. 'Gold',
  572. 'LimeGreen',
  573. 'SkyBlue',
  574. 'SteelBlue']
  575. width=0.3
  576. dotsize = 25
  577. #plt.xlim(-0.5, 1.5)
  578. plt.tick_params(axis='x', which='major', labelsize='10')
  579. #diffT1T2 = np.array([cDiff_T1vT2[:32], pDiff_T1vT2[:32]]).transpose()
  580. if zscores : data1, data2 = stats.zscore(data1), stats.zscore(data2)
  581. data = np.array([data1, data2])
  582. x_store = np.array([np.ones(data1.shape), np.ones(data1.shape)])
  583. y_store = np.array([np.ones(data1.shape), np.ones(data1.shape)])
  584. for i, l in enumerate(xlabels):
  585. x = np.ones(data.shape[1])*i + (np.random.rand(data.shape[1])*width-width/2.)
  586. ax.scatter(x, data[i], color=colors, s=dotsize)
  587. x_store[i] = x
  588. y_store[i] = data[i]
  589. median = np.median(data[i])#.mean()
  590. if showMeans : ax.plot([i-width/2. - 0.1, i+width/2. +0.1],[median,median], color="k")
  591. if plotEdges :
  592. for i in range(data.shape[1]):
  593. plt.plot([x_store[0][i], x_store[1][i]],[y_store[0][i], y_store[1][i]], color = colors[i])
  594. ax.set_xticks(range(len(xlabels)))
  595. ax.set_xticklabels(xlabels)
  596. ax.set_ylabel(ylabel, fontsize=11)
  597. ax.set_title(title, fontsize=12)
  598. def linregPlot(X = None, Y = None):
  599. reg = stats.linregress(X, Y)
  600. x_pred = np.arange(min(X), max(X), 0.01)
  601. y_pred = np.multiply(reg.slope, x_pred) + reg.intercept
  602. plt.scatter(X, Y)
  603. plt.plot(x_pred, y_pred, color = 'red')
  604. summary_stats = 'R² : ' + str(np.round(reg.rvalue, decimals = 2)) + '\np-value : ' + str(np.round(reg.pvalue, decimals = 2))
  605. scale = (max(X) - min(X))/4
  606. plt.text(max(X)- scale, max(Y), s = summary_stats, horizontalalignment = 'left', verticalalignment = 'top', size = 12, c = 'r')

functions.py at commit c950a5a, no license · at the source

Overview

Authors: Elias El Otmani1, Emmanuel Barbeau2, Béatrice Lemesle3, Emilie Milongo‐Rigal3, Sophie Fernandez4, Sandrine Charpentier4,5, Jean‐François Albucher1,6, Nicolas Raposo1,6, Fabrice Bonneville1,7, Patrice Péran1, Jérémie Pariente1,3
  1. ToNIC Toulouse NeuroImaging Center, UMR 1214, Universit. De Toulouse, INSERM, Paul Sabatier University (UT3) Toulouse France
  2. CNRS, Cerco Toulouse France
  3. Department of Neurology Neuroscience Centre, Toulouse‐Purpan University Hospital Toulouse Cedex France
  4. Department of Emergency Medicine University Hospital of Toulouse Toulouse France
  5. Laboratory of Epidemiology and Analyses in Public Health UMR 1295 Inserm, Toulouse University France
  6. Department of Neurolog Clinical Investigation Center, CIC1436, Toulouse University Hospital Toulouse France
  7. Department of Neuroradiology University Hospital of Toulouse Toulouse France
Journal: Annals of clinical and translational neurology, article 10.1002/acn3.70396
Dates: received 16 February 2026; accepted 21 March 2026; published online 10 April 2026; in print April 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1002/acn3.70396 · PMID 41958247 · PMCID PMC13394162 · OpenAlex W7153314802
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: fMRI (modality), human (organism), cognitive (subfield)
Methods: Preprocessing, Statistics, Smoothing, state filtering, decompositions, Connectivity, fMRI & imaging
Keywords: episodic memory, memory networks, transient global amnesia
Topic: Memory and Neural Mechanisms (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Citations: not cited yet (Europe PMC); 47 references in the paper

Abstract

Background and Objectives: Transient global amnesia (TGA) is a striking model of isolated amnesia. While hippocampal lesions are well described, the network‐level mechanisms and the precise neuropsychological profile remain debated. Our objective was thus to characterize functional and neuropsychological correlates of acute TGA and their longitudinal evolution.

Methods: Prospective, single‐center case–control study of 20 patients with acute TGA and 20 age‐ and sex‐matched healthy controls. All participants completed neuropsychological testing and underwent structural and functional MRI at three time points: acute phase (< 24 h from onset), day 3, and 3 months. Primary outcomes were neuropsychological performance across episodic, semantic, and metamemory domains and resting‐state fMRI connectivity within the episodic memory network. Secondary outcomes were functional connectivity within the Default Mode (DMN), Executive (ECN), and Salience (SN) networks.

Results: A total of 40 participants were included (20 patients with TGA, mean age 65.5 years, 45% women; 20 controls, mean age 64.3 years, 45% women). In patients, median delay from symptoms' onset to MRI was 6.67 h. Neuropsychologically, patients showed profound multimodal anterograde amnesia during the acute phase, resolving by 3 months. This deficit was largely isolated, sparing semantic memory and metamemory. Structurally, small bilateral lesions were present in most patients. Functionally, acute hypoconnectivity was observed within the extended hippocampal system, particularly between parahippocampal and cingulate cortices, normalizing by 3 months. No consistent disruption was found in large‐scale networks (default mode, executive control, salience).

Interpretation: TGA is associated with transient, selective hypoconnectivity within the mesiotemporal–cingulate episodic memory network, aligning with previous reports and further precising the functional anatomy. The finding of a profound anterograde amnesia was replicated and its recovery timecourse was elucidated. Semantic memory and metamemory remain preserved, clarifying inconsistencies in prior reports. These findings suggest that TGA reflects a transient limbic dysconnectivity syndrome rather than a diffuse network disorder, reconciling structural lesions with clinical and functional data.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repository

Its files are read in the Code ↔ Paper reader above, with 5 matches between paragraphs and lines of code.

EliasElOtmani/TGA

License: none: the authors keep all their rights
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Commit: c950a5a092e4dcf92e29236d88503057babccfae, 13 February 2026
Languages: Jupyter (10), Python (2)
Size: 1,998 files, 12 scripts
Software Heritage: not archived
Found in: “Data Availability Statement”
Holds: 3 notebooks
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Matplotlib (11 files), NumPy (11 files), pandas (9 files), SciPy (9 files), Pingouin (6 files), Plotly (6 files), seaborn (6 files), statsmodels (6 files), NiBabel (2 files), Nilearn (2 files)
Availability: 1 check, the latest on 29 September 2026: the link answers
  • 29 September 2026: the link answers
11 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:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 11 scripts, each with its path and the digest of its content;
  • 5 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 Statement

Light data such as neuropsychological data, 1st‐level preprocessed fMRI ROI‐to‐ROI data and python codes are available at https://github.com/EliasElOtmani/TGA. Heavy data such as raw fMRI, ICA and MRI data are available upon request.

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, 29 September 2026: the first record

Recorded: type, language, journal, pages, dates, 11 authors, 3 keywords, 3 funders, 45 references.

Cite

This paper

El Otmani, E., Barbeau, E., Lemesle, B., Milongo‐Rigal, E., Fernandez, S., Charpentier, S., Albucher, J., Raposo, N., Bonneville, F., Péran, P., & Pariente, J. (2026). Memory and Resting-State Connectivity in Acute Transient Global Amnesia: A Case-Control fMRI Study. Annals of clinical and translational neurology, 10.1002/acn3.70396. https://doi.org/10.1002/acn3.70396

BibTeX

@article{elotmani2026memory,
author = {El Otmani, Elias and Barbeau, Emmanuel and Lemesle, Béatrice and Milongo‐Rigal, Emilie and Fernandez, Sophie and Charpentier, Sandrine and Albucher, Jean‐François and Raposo, Nicolas and Bonneville, Fabrice and Péran, Patrice and Pariente, Jérémie},
title = {{Memory and Resting-State Connectivity in Acute Transient Global Amnesia: A Case-Control fMRI Study}},
journal = {Annals of clinical and translational neurology},
year = {2026},
month = apr,
pages = {10.1002/acn3.70396},
publisher = {Wiley},
issn = {2328-9503},
doi = {10.1002/acn3.70396},
url = {https://doi.org/10.1002/acn3.70396},
pmid = {41958247},
pmcid = {PMC13394162}
}

RIS

TY - JOUR
AU - El Otmani, Elias
AU - Barbeau, Emmanuel
AU - Lemesle, Béatrice
AU - Milongo‐Rigal, Emilie
AU - Fernandez, Sophie
AU - Charpentier, Sandrine
AU - Albucher, Jean‐François
AU - Raposo, Nicolas
AU - Bonneville, Fabrice
AU - Péran, Patrice
AU - Pariente, Jérémie
TI - Memory and Resting-State Connectivity in Acute Transient Global Amnesia: A Case-Control fMRI Study
T2 - Annals of clinical and translational neurology
J2 - Ann Clin Transl Neurol
PY - 2026
DA - 2026/04/10
SP - 10.1002/acn3.70396
SN - 2328-9503
PB - Wiley
DO - 10.1002/acn3.70396
UR - https://doi.org/10.1002/acn3.70396
LA - en
ER -

CSL-JSON

{
"id": "10.1002/acn3.70396",
"type": "article-journal",
"title": "Memory and Resting-State Connectivity in Acute Transient Global Amnesia: A Case-Control fMRI Study",
"container-title": "Annals of clinical and translational neurology",
"author": [
{
"family": "El Otmani",
"given": "Elias"
},
{
"family": "Barbeau",
"given": "Emmanuel"
},
{
"family": "Lemesle",
"given": "Béatrice"
},
{
"family": "Milongo‐Rigal",
"given": "Emilie"
},
{
"family": "Fernandez",
"given": "Sophie"
},
{
"family": "Charpentier",
"given": "Sandrine"
},
{
"family": "Albucher",
"given": "Jean‐François"
},
{
"family": "Raposo",
"given": "Nicolas"
},
{
"family": "Bonneville",
"given": "Fabrice"
},
{
"family": "Péran",
"given": "Patrice"
},
{
"family": "Pariente",
"given": "Jérémie"
}
],
"container-title-short": "Ann Clin Transl Neurol",
"page": "10.1002/acn3.70396",
"DOI": "10.1002/acn3.70396",
"PMID": "41958247",
"PMCID": "PMC13394162",
"ISSN": "2328-9503",
"publisher": "Wiley",
"URL": "https://doi.org/10.1002/acn3.70396",
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
10
]
]
}
}

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.1038/s41467-026-75662-w [code]
Distinct Roles of Deep and Superficial Cortical Layers in Tone Prediction, Comparison, and Adaptation in Human Auditory Cortices.
Journal: Nature communications
In common: Pingouin, Nilearn, NiBabel, 6 other tools, cognitive, 1 reference
[2] doi:10.1038/s41467-026-74566-z [code]
Low-dimensional and optimised representations of high-level information in the expert brain.
Journal: Nature communications
In common: Pingouin, Nilearn, Plotly, 7 other tools, cognitive
[3] doi:10.1162/imag.a.1269 [code]
From early to contemporary normative modeling: Mapping individual differences in neurophysiological signals.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: Pingouin, Nilearn, Plotly, 7 other tools
[4] doi:10.1371/journal.pbio.3003684 [code]
The retrieval of previously learned motor memories is facilitated by the reinstatement of default mode network manifold structures.
Journal: PLoS biology
In common: Pingouin, Nilearn, NiBabel, 5 other tools, fMRI, cognitive, 1 reference
[5] doi:10.1162/imag.a.105 [code]
Right posterior theta reflects human parahippocampal phase resetting by salient cues during goal-directed navigation
Journal: n/a
In common: Pingouin, Nilearn, NiBabel, 6 other tools, fMRI, cognitive
[6] doi:10.1002/agm2.70073 [code]
Foreign Language Learning in Older Adults Modifies Resting-State Functional Connectivity Between the Subcortical Structures and the Cortex.
Journal: Aging medicine (Milton (N.S.W))
In common: Nilearn, NiBabel, statsmodels, 5 other tools, fMRI, 2 references
[7] doi:10.1162/netn.a.544 [code]
Brain network reconfiguration during reward prediction error processing.
Journal: Network neuroscience (Cambridge, Mass.)
In common: Nilearn, Plotly, NiBabel, 6 other tools, fMRI, cognitive
[8] doi:10.1016/j.xcrm.2026.102793 [code]
A predictive corticospinal model for pain perception.
Journal: Cell reports. Medicine
In common: Pingouin, Nilearn, NiBabel, 6 other tools, fMRI
[9] doi:10.1038/s41597-026-07377-y [code]
An open-access multi-site fMRI dataset for investigating conscious visual perception.
Journal: Scientific data
In common: Pingouin, Nilearn, NiBabel, 6 other tools, fMRI
[10] doi:10.1162/imag.a.1321 [code]
Phase similarity between similar objects indicates representational merging across retrieval training but not sleep.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: Pingouin, Nilearn, Plotly, 6 other tools, cognitive

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.