Anterior insular co-activation patterns associated with stress markers in chronic primary pain.
The 10 matches
- [1] § Materials and methods › Resting-state functional dynamics › Co-activation patterns ↔ 02_CAPs/01_Analysis/Script_twopop_PCA_HC_ref_SH.m, lines 824–916 · score 0.87 · consensus clustering, activation patterns, reference population, events, PAC, retained frames
- [2] § Materials and methods › Demographic and clinical characteristics ↔ 01_Clinical_Measures/Demographics_Table.R, lines 87–127 · score 0.70 · hormonal contraceptives, psychotropic medications, corticosteroids, analgesics, sex, demographic
- [3] § Results › Identified aIC-based CAPs in HC ↔ 02_CAPs/01_Analysis/Script_twopop_PCA_HC_ref_SH.m, lines 824–916 · score 0.69 · MNI space, co activation, reference population, retained frames, fraction, maps
- [4] § Materials and methods › Statistical analysis ↔ 02_CAPs/02_Statistics/02_CAPs_Stat.Rmd, lines 315–334 · score 0.68 · Post hoc, linear mixed, interaction term, ID, FDR, BDI
- [5] § Materials and methods › Statistical analysis ↔ 01_Clinical_Measures/Demographics_Table.R, lines 129–167 · score 0.64 · Wilcoxon rank sum, Shapiro Wilk, Welch, variances, demographic, clinical
- [6] § Materials and methods › Demographic and clinical characteristics › Pain provocation test ↔ 01_Clinical_Measures/Demographics_Table.R, lines 211–249 · score 0.60 · peg algometry, pain intensity, ear, Algopeg
- [7] § Materials and methods › Statistical analysis ↔ 01_Clinical_Measures/Demographics_Table.R, lines 211–249 · score 0.60 · BPI severity, Peg algometry, Alpha, pain, CPP
- [8] § Materials and methods › Demographic and clinical characteristics › Salivary cortisol and alpha-amylase ↔ 01_Clinical_Measures/Cortisol_AUC_Analysis.R, lines 69–156 · score 0.58 · post awakening, cortisol, concentrations, curve, AUCI, 45 min
- [9] § Materials and methods › MRI data acquisition and preprocessing ↔ 02_CAPs/01_Analysis/Script_twopop_PCA_HC_ref_SH.m, lines 68–134 · score 0.56 · motion parameters, SPM, FD, voxel, brain
- [10] § Materials and methods › Resting-state functional dynamics › Co-activation patterns ↔ 02_CAPs/01_Analysis/Script_twopop_PCA_HC_ref_SH.m, lines 136–178 · score 0.51 · consensus clustering, selected frames, algorithm, threshold, activations, HC
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
MATLAB · 922 lines · 33 KB · no license · 4 matches
- %% Script to run the CAPs analyses without the GUI
- % In this script, we assume HC as a reference population
- % PCA included
- % Adapt:
- % - Seed
- % - The parameters in section 2 can be adaped.
- % - K_range in section 4, as well as in the section 7
- % "Parameters.KMeansClustering.MaxClusterNumber = Kmax"
- % Funtion generated by Samantha Weber:
- % - createMask_CAP_SW
- % - loadData_SW
- % - loadseed_SW
- % - MakeViolin_SW
- % Remaining Functions are from the TbCAPs Toolbox (https://github.com/MIPLabCH/TbCAPs)
- % Adaptation and additions for the CAPs in CPP Project by Salome Häuselmann
- % ([email hidden]) 2024/2025
- clear; clc;close;
- addpath(genpath(pwd));
- %% 1. Loading the data files
- RootPath = '';
- SavePath = '';
- spmPath = '';
- mkdir(SavePath);
- %% 1.1 Define your variables
- prefix = 's5w*';
- selectMask = 'Population'; % make GM Population Mask based on data
- seedName = {'Anterior_Insula_BNA_mask.nii'};
- MasksPath = '/';
- fancyName = '';
- Group = {'HC', 'CPP'};
- n_datasets = 2;
- % load HC folder;
- filelist=dir(fullfile(RootPath,Group{1}, 'P*'));
- N_HC{1}=size(filelist,1);
- myHC=cell(1,N_HC{1});
- for f=1:N_HC{1}
- myHC{f}=filelist(f).name;
- end
- clear filelist f
- % load CPP folder;
- filelist=dir(fullfile(RootPath,Group{2}, 'P*'));
- N_CPP{1}=size(filelist,1);
- myCPP=cell(1,N_CPP{1});
- for f=1:N_CPP{1}
- myCPP{f}=filelist(f).name;
- end
- clear filelist f
- mySubj = [myHC, myCPP];
- N_Subj{1} = N_HC{1} + N_CPP{1};
- % Define the folders HC
- for i = 1:N_HC{1}
- functdir1{i} = fullfile(RootPath, Group{1}, myHC{i});
- end
- % Define the folders CPP
- for i = 1 : N_CPP{1}
- functdir2{i} = fullfile(RootPath, Group{2}, myCPP{i});
- end
- %% 1. Loading the data files
- mask ={};
- brain_info ={};
- n_dataset = 0;
- % Data: cell array, each cell of size n_TP x n_masked_voxels
- % Mask: n_voxels x 1 logical vector
- % Header: the header (obtained by spm_vol) of one NIFTI file with proper
- % data dimension and .mat information
- [mask, brain_info] = createMask_CAP_SW(functdir1, prefix, selectMask);
- Tstart = clock;
- % Data HC: cell array, each cell of size n_TP x n_masked_voxels
- if exist(fullfile(SavePath,fancyName,['HCloaded_' fancyName '.mat']))
- disp(['Data HC has been loaded already !'])
- load(fullfile(SavePath,fancyName,['HCloaded_' fancyName '.mat']));
- else
- TC ={};
- FD ={};
- [TC,brain,FD] = loadData_SW(functdir1, prefix, mask, brain_info); % here the motion parameters rp_*-txt file are loaded in
- FD1 = FD{:,:};
- TC1 = TC{:,:};
- % Save intermediate steps
- if ~exist (fullfile(SavePath,fancyName))
- mkdir(fullfile(SavePath,fancyName));
- end
- save(fullfile(SavePath,fancyName,['HCloaded_' fancyName '.mat']),'TC1','brain','FD1','-v7.3')
- end
- % Data CPP: cell array, each cell of size n_TP x n_masked_voxels
- if exist(fullfile(SavePath,fancyName,['CPPloaded_' fancyName '.mat']))
- disp(['Data CPP has been loaded already !'])
- load(fullfile(SavePath,fancyName,['CPPloaded_' fancyName '.mat']));
- else
- TC ={};
- FD={};
- [TC,brain,FD] = loadData_SW(functdir2, prefix, mask, brain_info); % here the motion parameters rp_*-txt file are loaded in
- FD2 = FD{:,:};
- TC2 = TC{:,:};
- % Save intermediate steps
- if ~exist (fullfile(SavePath,fancyName))
- mkdir(fullfile(SavePath,fancyName));
- end
- save(fullfile(SavePath,fancyName,['CPPloaded_' fancyName '.mat']),'TC2','brain','FD2','-v7.3')
- end
- % Seed: a n_masked_voxels x n_seed logical vector with seed information
- if exist(fullfile(SavePath,fancyName,['Seed_' fancyName '.mat']))
- disp(' ');
- disp('-----------------------------------------------------');
- disp(['Seed has been loaded already !'])
- load(fullfile(SavePath,fancyName,['Seed_' fancyName '.mat']));
- else
- disp(' ');
- disp('-----------------------------------------------------');
- disp('Load seed...');
- [Seed] = loadseed_SW(functdir1, prefix, mask, brain_info, seedName,MasksPath);
- save(fullfile(SavePath,fancyName,['Seed_' fancyName '.mat']),'Seed');
- disp('Seed successfully loaded!');
- end
- % Computes seed maps for each subject and for the population, using the
- % data from the chosen reference population
- TC = [TC1, TC2];
- [~,AvgSeedMap] = CAP_Compute_SeedMap(TC1,Seed,1);
- %% 2. Specifying the main parameters
- % Threshold above which to select frames
- T = 0.84;
- % Selection mode ('Threshold' or 'Percentage')
- SelMode = 'Threshold';
- % Threshold of FD above which to scrub out the frame and also the t-1 and
- % t+1 frames (if you want another scrubbing setting, directly edit the
- % code)
- Tmot = 0.5;
- % Type of used seed information: select between 'Average','Union' or
- % 'Intersection'
- SeedType = 'Average';
- % Contains the information, for each seed (each row), about whether to
- % retain activation (1 0) or deactivation (0 1) time points
- switch SeedType
- case 'Union'
- Activation = [1,0];
- for s = 1:size(seedName,2)
- SignMatrix(s,:) = Activation;
- end
- case 'Average'
- SignMatrix = [1 0];
- end
- % Percentage of frames to use in each fold of consensus clustering
- Pcc = 80;
- % Number of folds we run consensus clustering for
- N = 200;%50; %120;
- % Percentage of positive-valued voxels to retain for clustering
- Pp = 100;
- % Percentage of negative-valued voxels to retain for clustering
- Pn = 100;
- % Number of repetitions of the K-means clustering algorithm
- n_rep = 50;%50;
- %% 3. Selecting the frames to analyse
- % Xon will contain the retained frames, and Indices will tag the time
- % points associated to these frames, for each subject (it contains a
- % subfield for retained frames and a subfield for scrubbed frames)
- [Xon1,p1,Indices1,idx_sep_seeds1,Xonp_scrub1] = CAP_find_activity(TC1,Seed,T,FD1,Tmot,SelMode,SeedType,SignMatrix);
- [Xon2,p2,Indices2,idx_sep_seeds2,Xonp_scrub2] = CAP_find_activity(TC2,Seed,T,FD2,Tmot,SelMode,SeedType,SignMatrix);
- % Percentage of retained frames across subjects
- RetainedPercentage{1} = p1(3,:);
- RetainedPercentage{2} = p2(3,:);
- % Indices of the frames that have been retained (used later for metrics
- % computations)
- FrameIndices{1} = Indices1;
- FrameIndices{2} = Indices2;
- tmp_toplot1 = ConcatMat(RetainedPercentage(1),1,1,N_HC,'FD');
- tmp_toplot2 = ConcatMat(RetainedPercentage(2),1,1,N_CPP,'FD');
- tmp_toplot = zeros(2,N_CPP{1});
- tmp_toplot(1,1:N_HC{1}) = tmp_toplot1;
- tmp_toplot(2,1:N_CPP{1}) = tmp_toplot2;
- tmp_toplot(tmp_toplot == 0) = NaN;
- %% Quality Checks 1 - Visualization
- % 1. Percentage of Retained Frames
- % Perform two-sample t-test between the two groups
- %[~, p_value, ci, stats] = ttest2(tmp_toplot1, tmp_toplot2, 'Vartype', 'unequal');
- % Perform unpaired non-parametric t-test (Mann-Withney U)(since in the
- % graph the do not look nomrmally distributed)
- [p_value, h, stats] = ranksum(tmp_toplot1, tmp_toplot2);
- % Displays the violin plot of subject scrubbing percentage for the
- % reference population
- TPViolin = figure;
- axes1 = axes('Parent',TPViolin);
- % Colors used in plotting of all populations
- PopColor{1} = [255,255,180; 219,224,252; 188,252,188; 230,230,230]/255;
- PopColor{2} = [130,48,48; 51,75,163; 59,113,86; 0, 0, 0]/255;
- %Create plot
- [~,~,TPViolin] = MakeViolin_SW(tmp_toplot,axes1,{'HC' 'CPP'},'Frames ret. [%]',PopColor,1,2);
- set(TPViolin,'Visible','on');
- % Add t-test results as text on the plot
- xPosition = mean(xlim); % Centered on x-axis
- yPosition = max(ylim) - 0.05 * range(ylim); % Slightly below the top of the y-axis
- text(xPosition, yPosition, sprintf('W = %.2f, p = %.4f', stats.ranksum, p_value), ...
- 'FontSize', 12, 'FontWeight', 'bold', 'HorizontalAlignment', 'center', 'Color', 'k');
- %Save plot as .jpg and .fig
- saveas(gcf,fullfile(SavePath,fancyName,'RetainedFrames.jpg'));
- saveas(gcf,fullfile(SavePath,fancyName,'RetainedFrames.fig'));
- disp('-----------------------------------------------------');
- disp(' ');
- disp(['Figure Frames retained has been saved in ' SavePath]);
- close;
- % 2. Distribution of retained frames
- % Test of data distribution homogeneity (inter-subject variability)
- % Test normal distribution around mean % of retained frames value using Kolmogorov–Smirnov test.
- % Define the mean and standard deviation for both datasets
- mu_HC = mean(tmp_toplot1);
- sigma_HC = std(tmp_toplot1);
- mu_CPP = mean(tmp_toplot2);
- sigma_CPP = std(tmp_toplot2);
- % Standardize the data (convert to Z-scores)
- z_HC = (tmp_toplot1 - mu_HC) / sigma_HC;
- z_CPP = (tmp_toplot2 - mu_CPP) / sigma_CPP;
- % Perform Kolmogorov-Smirnov Test against the standard normal distribution
- [h_HC, p_HC] = kstest(z_HC);
- [h_CPP, p_CPP] = kstest(z_CPP);
- % Coefficient of Variation (CV)
- cv_HC = sigma_HC / mu_HC;
- cv_CPP = sigma_CPP / mu_CPP;
- % Define the normal distribution curves for plotting
- x_HC = linspace(mu_HC - 4*sigma_HC, mu_HC + 4*sigma_HC, 1000);
- x_CPP = linspace(mu_CPP - 4*sigma_CPP, mu_CPP + 4*sigma_CPP, 1000);
- pdf_HC = normpdf(x_HC, mu_HC, sigma_HC);
- pdf_CPP = normpdf(x_CPP, mu_CPP, sigma_CPP);
- % Plot histogram and fitted normal distribution curves
- figure;
- hold on;
- histogram(tmp_toplot1, 20, 'Normalization', 'pdf', 'FaceAlpha', 0.5, 'DisplayName', 'HC (Histogram)');
- histogram(tmp_toplot2, 20, 'Normalization', 'pdf', 'FaceAlpha', 0.5, 'DisplayName', 'CPP (Histogram)');
- plot(x_HC, pdf_HC, 'LineWidth', 2, 'DisplayName', sprintf('Normal Fit HC (KS p=%.3f)', p_HC));
- plot(x_CPP, pdf_CPP, 'LineWidth', 2, 'DisplayName', sprintf('Normal Fit CPP (KS p=%.3f)', p_CPP));
- xlabel('Retained Frames Value');
- ylabel('Density');
- title('Data Distribution and Normal Fit (HC vs. CPP)');
- legend;
- hold off;
- % Save plot as .jpg and .fig with a new name
- saveas(gcf, fullfile(SavePath, fancyName, 'HC_CPP_Distribution.jpg'));
- saveas(gcf, fullfile(SavePath, fancyName, 'HC_CPP_Distribution.fig'));
- % Display message confirming the save
- disp('-----------------------------------------------------');
- disp(' ');
- disp(['Figure "HC_CPP_Distribution" has been saved in ' SavePath]);
- % Close the figure
- close;
- %% 4. Consensus clustering (if wished to determine the optimum K)
- % The input to PCA should have a dimensionality n_dimensions x
- % n_datapoints; since we consider a population of subjects in a cell array
- % (each cell with size n_dims x n_samples_persubj), we want to concatenate
- % these cells into one giant data matrix, which we feed to the PCA
- % function. I will denote the number of dimensions (or voxels) by V, and
- % the number of total time points across subjects by T.
- % Change dimension of Xon1 to feed into PCA
- Xon1_pca = [];
- for i = 1:N_HC{1,1}
- Xon1_pca = [Xon1_pca, Xon1{1,i}];
- end
- [U, W,Eigenvals,mu] = ComputePCA(Xon1_pca);
- %save(fullfile(SavePath,fancyName,'PCA_Outputs.mat'), 'U', 'W', 'Eigenvals');
- %[U,W] = ComputePCA(cell2mat(Xon1_pca));
- % After the call, U will have size V x T, and W will have size T x T. Be
- % careful that in our function, row i of W contain the weights, for all
- % T frames, associated to the principal direction i (contained as the i-th
- % column in U).
- % Also, notice that we want to compute only one PCA on the
- % population-wise data, not one per subject! Otherwise, we would have a
- % different dimensionality reduction for each subject, which would make our
- % life complicated...
- % You want to input "{W}" (rows = dimensions, columns = data points) to
- % CAP_ConsensusClustering. The brackets are because the function wants a
- % cell input...
- % After the consensus clustering step, you will want to feed W to your
- % k-means clustering as well instead of "cell2mat(Xon1)". Your output CAP
- % matrix will have size K x T, with K the number of CAPs. In order to go
- % back to the original space, you will apply:
- % CAP_original = (U*CAP')'
- % This will give you CAPs with a dimensionality K x V, i.e., what you would
- % have obtained using CAP analysis without PCA
- % This specifies the range of values over which to perform consensus
- % clustering: if you want to run parallel consensus clustering processes,
- % you should feed in different ranges to each call of the function
- K_range = 2:6;
- if exist(fullfile(SavePath,fancyName,['ConsensusClustering_Range' num2str(K_range(1)) '_to_' num2str(K_range(end)) '_' fancyName '.mat']))
- disp('-----------------------------------------------------');
- disp('Consensus Clustering was performed already !')
- disp('Load data...');
- load(fullfile(SavePath,fancyName,['ConsensusClustering_Range' num2str(K_range(1)) '_to_' num2str(K_range(end)) '_' fancyName '.mat']))
- disp(' ');
- disp('Data loaded successfully!');
- else
- % Have each of these run in a separate process on the server =)
- disp('Running Consensus Clustering...')
- % Umcomment if no PCA is performed
- %[Consensus] = CAP_ConsensusClustering(Xon1,K_range,'items',Pcc/100,N,'correlation');
- %Consensus clustering using PCA reduced dataset
- [Consensus] = CAP_ConsensusClustering({W},K_range,'items',Pcc/100,N,'correlation');
- %Plot Consensus Matrix
- ConsensusMatrixPlot(Consensus,SavePath,fancyName, K_range)
- % Calculates the quality metrics
- [CDF,PAC] = ComputeClusteringQuality(Consensus,K_range);
- % % Calculates the quality metrics
- % [~,Qual] = ComputeClusteringQuality(Consensus,[]);
- save(fullfile(SavePath,fancyName,['ConsensusClustering_Range' num2str(K_range(1)) '_to_' num2str(K_range(end)) '_' fancyName '.mat']))
- disp(' ');
- disp('Consensus Cluster successfully performed!');
- end
- Ttotal=etime(clock, Tstart);
- disp(['** Consensus clustering completed. Total time: ' num2str(Ttotal/60,'%3.1f') ' min.']);
- % Qual should be inspected to determine the best cluster number(s)
- CCPlot = figure;
- ax1 = axes(CCPlot);
- %set(CCPlot,'Visible','on');
- tmp_plot = bar(2:K_range(end),1-PAC);
- xlabel(get(tmp_plot(1),'Parent'),'Cluster number K');
- ylabel(get(tmp_plot(1),'Parent'),'Stability');
- xlim(get(tmp_plot(1),'Parent'),[2-0.6,K_range(end)+0.6]);
- ylim(get(tmp_plot(1),'Parent'),[0,1]);
- set(get(tmp_plot(1),'Parent'),'Box','off');
- custom_cm = cbrewer('seq','Reds',25);
- colormap(CCPlot,custom_cm(6:25,:));
- saveas(gcf,fullfile(SavePath,fancyName,'Stability.jpg'));
- saveas(gcf,fullfile(SavePath,fancyName,'Stability.fig'));
- disp(' ');
- disp('-----------------------------------------------------');
- disp(['Figure stability measures has been saved in ' SavePath]);
- disp(' ');
- disp('Please check stability measures');
- % You should fill this with the actual value
- %K_opt = 3;
- prompt = 'What is the optimal cluster size? ';
- K_opt = input(prompt);
- close;
- %% 5. Clustering into CAPs
- %[CAP,Disp,Std_Clusters,idx1,CorrDist,sfrac] = Run_Clustering(cell2mat(Xon1),...
- % K_opt,mask{1},brain_info{1},Pp,Pn,n_rep,idx_sep_seeds1,SeedType);
- % CAP_raw = CAP;
- [CAP,Disp,Std_Clusters,idx1,CorrDist,sfrac] = Run_Clustering_PCA(W,...
- K_opt,mask{1},brain_info{1},Pp,Pn,n_rep,idx_sep_seeds1,SeedType);
- %Plot
- % Computation of the similarity
- SimMat = corr(CAP',CAP');
- SimMat(isnan(SimMat))=0;
- % Similarity Plot
- imagesc(SimMat);
- tmp_cb2 = cbrewer('div','RdBu',1000,'spline'); % had to ad 'spline', otherwise error message (SH)
- tmp_cb2(tmp_cb2 < 0) = 0;
- colormap(flipud(tmp_cb2));
- % Arbitrary setting of probability scale
- caxis([-1 1]);
- axis('square','on');
- axis('on');
- % Add colorbar to the figure
- colorbar; % This adds the color scale
- saveas(gcf,fullfile(SavePath,fancyName,'Similarity.jpg'));
- saveas(gcf,fullfile(SavePath,fancyName,'Similarity.fig'));
- disp(' ');
- disp('-----------------------------------------------------');
- disp(['Figure Similarity matrix has been saved in ' SavePath]);
- disp(' ');
- close;
- %% 5.1. PCA Reconstruction
- CAP_original = (U*CAP') + mu;
- CAP = CAP_original';
- %% 6. Assignment of the frames from population 2
- % Parameter that governs the stringency of assignment: if Ap = 5%, we
- % assign a frame to a CAP if spatial correlation exceeds the 5th percentile
- % of the distribution of spatial correlations between the CAP, and its
- % constituting frames
- Ap = 5;
- idx2 = CAP_AssignFrames(CAP,cell2mat(Xon2),CorrDist,Ap)';
- %% 7. Computing metrics
- % The TR of your data in seconds
- TR = 1.3;
- [ExpressionMap1,Counts1,Entries1,Avg_Duration1,Duration1,TransitionProbabilities1,...
- From_Baseline1,To_Baseline1,Baseline_resilience1,Resilience1,Betweenness1,...
- InDegree1,OutDegree1,SubjectEntries1] = Compute_Metrics_simpler(idx1,...
- Indices1.kept.active,Indices1.scrubbedandactive,K_opt,TR);
- [ExpressionMap2,Counts2,Entries2,Avg_Duration2,Duration2,TransitionProbabilities2,...
- From_Baseline2,To_Baseline2,Baseline_resilience2,Resilience2,Betweenness2,...
- InDegree2,OutDegree2,SubjectEntries2] = Compute_Metrics_simpler(idx2,...
- Indices2.kept.active,Indices2.scrubbedandactive,K_opt,TR);
- %% Transition Probability (Visualization and Statistics)
- % 1. Plot metrics Transition matrix for all HC
- tmp_toplot = squeeze(mean(TransitionProbabilities1,3));
- tmp_toplot = tmp_toplot(3:end-1,3:end-1);
- % Make graph visible and plotting
- TMGraph=imagesc(tmp_toplot);
- tmp_cb = cbrewer('seq','Greys',1000);
- colormap(flipud(tmp_cb));
- clear tmp_toplot
- % Arbitrary setting of probability scale from 0 to 0.03
- caxis([0 0.03]);
- axis('square','on');
- axis('on');
- % Add colorbar to the figure
- colorbar; % This adds the color scale
- saveas(gcf,fullfile(SavePath,fancyName,'TransitionProbabilityMatrix_HC.jpg'));
- saveas(gcf,fullfile(SavePath,fancyName,'TransitionProbabilityMatrix_HC.fig'));
- close;
- % 2. Plot metrics Transition matrix for all CPP
- tmp_toplot = squeeze(mean(TransitionProbabilities2,3));
- tmp_toplot = tmp_toplot(3:end-1,3:end-1);
- % Make graph visible and plotting
- TMGraph=imagesc(tmp_toplot);
- tmp_cb = cbrewer('seq','Greys',1000);
- colormap(flipud(tmp_cb));
- clear tmp_toplot
- % Arbitrary setting of probability scale from 0 to 0.03
- caxis([0 0.03]);
- axis('square','on');
- axis('on');
- % Add colorbar to the figure
- colorbar; % This adds the color scale
- saveas(gcf,fullfile(SavePath,fancyName,'TransitionProbabilityMatrix_CPP.jpg'));
- saveas(gcf,fullfile(SavePath,fancyName,'TransitionProbabilityMatrix_CPP.fig'));
- close;
- disp(' ');
- disp('-----------------------------------------------------');
- disp(['Figure Transition Probability Matrix has been saved in ' SavePath]);
- disp(' ');
- %% Visualization of CAP and Frame Dynamics
- % 1. Dynamic state plotting
- % Makes the graph visible
- % Concatenates information from the different datasets
- tmp_toplot = [];
- ExpressionMap{1}=ExpressionMap1;
- ExpressionMap{2}=ExpressionMap2;
- for i = 1:n_datasets
- tmp_toplot = [tmp_toplot; ExpressionMap{i}; 0*ones(5,size(TC{1},1))];
- end
- tmp_toplot = tmp_toplot(1:end-5,:); % combines HC and CPPs and but between the dataframes 5 rows with 0, that they can be visually seperated.
- % Define custom colormap: [black for scrubbed (-1), white for non-retained (0), then CAP colors]
- custom_cm = cbrewer('qual','Set1',K_opt+1);
- custom_cm = [0.05,0.05,0.05;1,1,1;custom_cm];
- %Plot it
- imagesc(tmp_toplot);
- colormap((custom_cm));
- xlabel('Time [s]');
- ylabel('Subjects [-]');
- caxis([-1,K_opt+1]); %Adjust color axis to include scrubbed, non-retained, CAPs, and unassigned
- clear tmp_toplot
- % Generate line objects for the legend and assign colors
- L = gobjects(1, K_opt + 3); % Preallocate for legend lines (CAPs + Scrubbed + Non-retained + Unassigned)
- % Loop to create legend lines for CAPs
- for cap_idx = 1:K_opt
- % Create line for CAPs
- L(cap_idx) = line(nan(4,1), nan(4,1), 'LineWidth', 2, 'Color', custom_cm(cap_idx + 2, :)); % +2 skips black and white
- end
- % Add lines for 'Scrubbed' (-1), 'Non-retained' (0), and 'Unassigned'
- L(K_opt + 1) = line(nan(4,1), nan(4,1), 'LineWidth', 2, 'Color', custom_cm(1, :)); % Black for scrubbed (-1)
- L(K_opt + 2) = line(nan(4,1), nan(4,1), 'LineWidth', 2, 'Color', custom_cm(2, :)); % White for non-retained (0)
- L(K_opt + 3) = line(nan(4,1), nan(4,1), 'LineWidth', 2, 'Color', custom_cm(end, :)); % Last color for unassigned
- % Create the legend dynamically based on K_opt
- legend_entries = cell(1, K_opt + 3); % Preallocate cell array for legend entries (CAPs + 3 categories)
- for cap_idx = 1:K_opt
- legend_entries{cap_idx} = sprintf('CAP%d', cap_idx); % Generate CAP labels
- end
- legend_entries{K_opt + 1} = 'Scrubbed'; % Black for scrubbed (-1)
- legend_entries{K_opt + 2} = 'Non-retained'; % White for non-retained (0)
- legend_entries{K_opt + 3} = 'Unassigned'; % Color from colormap for unassigned (K_opt + 1)
- % Create the legend
- lgd = legend(L, legend_entries{:}, 'Location', 'best');
- lgd.FontSize = 10;
- lgd.Position(1) = 0.65;
- lgd.Position(2) = 0.5;
- % Ensure the legend is shown
- legend show;
- saveas(gcf,fullfile(SavePath,fancyName,'DynamicStates.jpg'));
- saveas(gcf,fullfile(SavePath,fancyName,'DynamicStates.fig'));
- close;
- disp(' ');
- disp('-----------------------------------------------------');
- disp(['Figure Dynamic States has been saved in ' SavePath]);
- disp(' ');
- % 2. Averaged by CAP HC
- % Define custom colormap using cbrewer (for example, Set1 colormap)
- custom_cm = cbrewer('qual', 'Set1', K_opt + 1); % Add 1 for an additional color if needed
- % Find unique CAPs in the matrix
- CAPs = unique(ExpressionMap1);
- % Preallocate a matrix to store the normalized sums for each column
- normalizedSums = zeros(length(CAPs), size(ExpressionMap1, 2)); % CAPs x Columns
- % Loop through each column and calculate the normalized counts
- for col = 1:size(ExpressionMap1, 2)
- for i = 1:length(CAPs)
- CAP_value = CAPs(i);
- count = sum(ExpressionMap1(:, col) == CAP_value); % Count occurrences of CAP in this column
- normalizedSums(i, col) = count / size(ExpressionMap1, 1); % Normalize by dividing by the number of rows
- end
- end
- % Exclude CAP0 and CAP-1 (if they exist)
- excludedCAPs = [-1, 0];
- validCAPs = ~ismember(CAPs, excludedCAPs); % Find CAPs that are not -1 or 0
- % Filter out rows and CAPs
- filteredNormalizedSums = normalizedSums(validCAPs, :);
- filteredCAPs = CAPs(validCAPs); % Corresponding CAP values
- % Visualization: Line plot (Only lines, no markers)
- figure;
- hold on;
- % Use custom colormap for the lines
- for i = 1:length(filteredCAPs)
- plot(1:size(ExpressionMap1, 2), filteredNormalizedSums(i, :), '-', 'LineWidth', 1.5, ...
- 'Color', custom_cm(i + 1, :), 'DisplayName', sprintf('CAP%d', filteredCAPs(i))); % +1 to skip first color if needed
- end
- hold off;
- % Customize the plot
- xlabel('Frames');
- ylabel('Average CAP expression');
- title('HC');
- legend('Location', 'best');
- grid on;
- set(gca, 'FontSize', 12);
- saveas(gcf,fullfile(SavePath,fancyName,'AverageCAPExpressionHC.jpg'));
- saveas(gcf,fullfile(SavePath,fancyName,'AverageCAPExpressionHC.fig'));
- close;
- disp(' ');
- disp('-----------------------------------------------------');
- disp(['Figure Average CAP eypression HC has been saved in ' SavePath]);
- disp(' ');
- % 3. Averaged by CAP CPP
- custom_cm2 = cbrewer('qual', 'Set1', K_opt + 1); % Add 1 for an additional color if needed
- % Find unique CAPs in the matrix
- CAPs2 = unique(ExpressionMap2);
- % Preallocate a matrix to store the normalized sums for each column
- normalizedSums2 = zeros(length(CAPs2), size(ExpressionMap2, 2)); % CAPs x Columns
- % Loop through each column and calculate the normalized counts
- for col = 1:size(ExpressionMap2, 2)
- for i = 1:length(CAPs2)
- CAP_value2 = CAPs2(i);
- count2 = sum(ExpressionMap2(:, col) == CAP_value2); % Count occurrences of CAP in this column
- normalizedSums2(i, col) = count2 / size(ExpressionMap2, 1); % Normalize by dividing by the number of rows
- end
- end
- % Exclude CAP0 and CAP-1 (if they exist)
- excludedCAPs2 = [-1, 0, K_opt+1];
- validCAPs2 = ~ismember(CAPs2, excludedCAPs2); % Find CAPs that are not -1 or 0
- % Filter out rows and CAPs
- filteredNormalizedSums2 = normalizedSums2(validCAPs2, :);
- filteredCAPs2 = CAPs2(validCAPs2); % Corresponding CAP values
- % Visualization: Line plot (Only lines, no markers)
- figure;
- hold on;
- % Use custom colormap for the lines
- for i = 1:length(filteredCAPs2)
- plot(1:size(ExpressionMap2, 2), filteredNormalizedSums2(i, :), '-', 'LineWidth', 1.5, ...
- 'Color', custom_cm2(i + 1, :), 'DisplayName', sprintf('CAP%d', filteredCAPs2(i))); % +1 to skip first color if needed
- end
- hold off;
- % Customize the plot
- xlabel('Frames');
- ylabel('Average CAP expression');
- title('CPP');
- legend('Location', 'best');
- grid on;
- set(gca, 'FontSize', 12);
- saveas(gcf,fullfile(SavePath,fancyName,'AverageCAPExpressionCPP.jpg'));
- saveas(gcf,fullfile(SavePath,fancyName,'AverageCAPExpressionCPP.fig'));
- close;
- disp(' ');
- disp('-----------------------------------------------------');
- disp(['Figure Average CAP eypression CPP has been saved in ' SavePath]);
- disp(' ');
- %% Quality Check 2 - Visualization
- % Number of subjects in each group
- nHC = size(ExpressionMap{1}, 1); % Number of HC subjects
- nCPP = size(ExpressionMap{2}, 1); % Number of CPP subjects
- % Initialize vectors for subject-wise ratios
- ratio_HC = zeros(nHC, 1);
- ratio_CPP = zeros(nCPP, 1);
- % 1. Ration unnassigned frames to assigned frames (CAPs) in Population
- % Compute ratios for CPP subjects
- for i = 1:nCPP
- assigned_frames = sum(ismember(ExpressionMap{2}(i, :), 1:K_opt)); % Assigned frames
- unassigned_frames = sum(ExpressionMap{2}(i, :) == (K_opt+1)); % Unassigned frames
- ratio_CPP(i) = (unassigned_frames / assigned_frames)
- end
- % Perform a one-sample t-test to check if the mean differs from zero
- [h, p_value1, ci, stats] = ttest(ratio_CPP);
- % Create figure
- figure;
- hold on;
- % Set X-axis position to center
- boxplot(ratio_CPP, 'Positions', 1.5, 'Labels', {'CPP'}, 'Whisker', 1.5, 'Colors', 'r', 'Symbol', 'ro', 'Widths', 0.6);
- set(findobj(gca,'Type','Line','Tag','Median'), 'Color', 'k', 'LineWidth', 2); % Highlight median
- % Scatter individual points (improved jittering for better visibility)
- x_CPP = 1.5 + 0.08 * randn(nCPP, 1); % Adjust X position for centering
- scatter(x_CPP, ratio_CPP, 90, 'r', 'filled', 'MarkerFaceAlpha', 0.6, 'MarkerEdgeColor', 'k'); % Improved dot styling
- % Formatting improvements
- ylabel('Ratio of Unassigned to Assigned Frames', 'FontSize', 14, 'FontWeight', 'bold');
- title('Subject-Level Ratio of Unassigned to Assigned Frames (CPP)', 'FontSize', 16, 'FontWeight', 'bold');
- ylim([0 1]); % Set Y-axis limit for better readability
- % Center the X-axis
- xlim([1 2]); % Set range to center the boxplot
- % Annotate p-value on the plot
- text(1.5, 9, sprintf('p = %.4f', p_value1), 'HorizontalAlignment', 'center', 'FontSize', 12, 'FontWeight', 'bold', 'Color', 'blue');
- % Remove grid for cleaner look
- grid off;
- % Save figure
- saveas(gcf, fullfile(SavePath, fancyName, 'Unassigned_to_assigned_frames_CPP.jpg'));
- saveas(gcf, fullfile(SavePath, fancyName, 'Unassigned_to_assigned_frames_CPP.fig'));
- close;
- % 2. Ration scrubbed (but active) frames to assigned frames (CAPs)
- % Compute ratios for HC subjects
- for i = 1:nHC
- assigned_frames = sum(ismember(ExpressionMap{1}(i, :), 1:K_opt)); % Assigned frames
- scrubbed_frames = sum(ExpressionMap{1}(i, :) == -1); % Scrubbed frames
- ratio_HC(i) = (scrubbed_frames / assigned_frames) * 100; % Convert to percentage
- end
- % Compute ratios for CPP subjects
- for i = 1:nCPP
- assigned_frames = sum(ismember(ExpressionMap{2}(i, :), 1:K_opt)); % Assigned frames
- scrubbed_frames = sum(ExpressionMap{2}(i, :) == -1); % Scrubbed frames
- ratio_CPP(i) = (scrubbed_frames / assigned_frames) * 100; % Convert to percentage
- end
- % Combine data and create group labels
- all_ratios = [ratio_HC; ratio_CPP]; % Merge HC and CPP ratios
- group_labels = [ones(nHC, 1); 2 * ones(nCPP, 1)]; % 1 for HC, 2 for CPP
- % Non-parametric test (Mann-Whitney U test)
- [p_value2, h, stats] = ranksum(ratio_HC, ratio_CPP);
- % Create figure
- figure;
- hold on;
- % Corrected boxplot without manual 'positions' parameter
- boxplot(all_ratios, group_labels, 'Labels', {'HC', 'CPP'}, ...
- 'Whisker', 1.5, 'Colors', 'rb', 'Symbol', 'ro', 'Widths', 0.6);
- set(findobj(gca,'Type','Line','Tag','Median'), 'Color', 'k', 'LineWidth', 2); % Highlight median
- % Scatter individual points (jittered for better visibility)
- x_HC = 1 + 0.08 * randn(nHC, 1); % Jitter HC points
- x_CPP = 2 + 0.08 * randn(nCPP, 1); % Jitter CPP points
- scatter(x_HC, ratio_HC, 90, 'b', 'filled', 'MarkerFaceAlpha', 0.6, 'MarkerEdgeColor', 'k'); % HC points
- scatter(x_CPP, ratio_CPP, 90, 'r', 'filled', 'MarkerFaceAlpha', 0.6, 'MarkerEdgeColor', 'k'); % CPP points
- % Formatting improvements
- ylabel('Ratio of Scrubbed to Assigned Frames (%)', 'FontSize', 14, 'FontWeight', 'bold');
- title('Scrubbed (but active) to Assigned Frames (HC vs. CPP)', 'FontSize', 16, 'FontWeight', 'bold');
- ylim([0 100]); % Set Y-axis limit for better readability
- yticks(0:10:100); % Set ticks at intervals of 10%
- % Annotate p-value on the plot
- text(1.5, 90, sprintf('p = %.4f', p_value2), 'HorizontalAlignment', 'center', ...
- 'FontSize', 12, 'FontWeight', 'bold', 'Color', 'blue');
- % Remove grid for cleaner look
- grid off;
- % Save figure
- saveas(gcf, fullfile(SavePath, fancyName, 'Scrubbed_to_assigned_frames_HC_CPP.jpg'));
- saveas(gcf, fullfile(SavePath, fancyName, 'Scrubbed_to_assigned_frames_HC_CPP.fig'));
- close;
- %% 7. Save Metrics
- % General information on the project
- OverallInfo.ProjectTitle = fancyName;
- OverallInfo.NumberTimePoints = size(TC{1},1);%handles.SubjSize.TP;
- OverallInfo.NumberVoxels = size(TC{1},2); %handles.SubjSize.VOX;
- OverallInfo.NumberSubjects = N_Subj; %handles.n_subjects;
- OverallInfo.TR = TR; %handles.TR;
- Parameters.Inputs.DataHeader = brain_info;%handles.brain_info;
- Parameters.Inputs.Mask = mask;
- Parameters.Inputs.Seeds = Seed;
- Parameters.SpatioTemporalSelection.IsSeedFree = 0; %handles.is_seed_free;
- Parameters.SpatioTemporalSelection.NumberSeeds = size(seedName,2); %handles.n_seed;
- Parameters.SpatioTemporalSelection.TypeEventRetainedPerSeed = SignMatrix;
- Parameters.SpatioTemporalSelection.SeedType = SeedType;
- Parameters.SpatioTemporalSelection.MotionThreshold = Tmot;
- Parameters.SpatioTemporalSelection.SelectionMode = SelMode;
- Parameters.SpatioTemporalSelection.FrameSelectionParameter = T;
- Parameters.KMeansClustering.IsConsensusRun = 1;% handles.is_consensus_clustering;
- Parameters.KMeansClustering.MaxClusterNumber = 6; %handles.Kmax; change this to the respective Kmax.
- Parameters.KMeansClustering.PercentageDataPerFold = Pcc; %handles.PCC;
- Parameters.KMeansClustering.NumberRepetitions = n_rep;
- Parameters.KMeansClustering.NumberClusters = K_opt; %handles.K;
- Parameters.KMeansClustering.PercentagePositiveValuedVoxelsClustered = Pp;
- Parameters.KMeansClustering.PercentageNegativeValuedVoxelsClustered = Pn;
- Outputs.SpatioTemporalSelection.RetainedFramesPerSeed{1} = idx_sep_seeds1;
- Outputs.SpatioTemporalSelection.RetainedFramesPerSeed{2} = idx_sep_seeds2;
- Outputs.SpatioTemporalSelection.Indices{1}=Indices1;
- Outputs.SpatioTemporalSelection.Indices{2}=Indices2; %hier war vorher eine 1
- Outputs.SpatioTemporalSelection.PercentageRetainedFrames = RetainedPercentage;
- Outputs.SpatioTemporalSelection.AverageCorrelationMap = AvgSeedMap;
- Outputs.KMeansClustering.ConsensusQuality = PAC; %handles.ConsensusQuality; CHECK IF THAT'S TRUE
- Outputs.KMeansClustering.CoActivationPatternsDispersion = Disp;
- Outputs.KMeansClustering.CoActivationPatterns = CAP;
- Outputs.KMeansClustering.CoActivationPatternsZScored = CAP_Zscore(CAP);
- Outputs.KMeansClustering.CoActivationPatternsSTD = Std_Clusters; %handles.STDCAP;
- Outputs.KMeansClustering.AssignmentsToCAPs{1} = idx1;
- Outputs.KMeansClustering.AssignmentsToCAPs{2} = idx2;
- Outputs.Metrics.CAPExpressionIndices{1} = ExpressionMap1;
- Outputs.Metrics.CAPExpressionIndices{2} = ExpressionMap2;
- Outputs.Metrics.Occurrences{1} = Counts1;
- Outputs.Metrics.Occurrences{2} = Counts2;
- Outputs.Metrics.NumberEntries{1} = Entries1;
- Outputs.Metrics.NumberEntries{2} = Entries2;
- Outputs.Metrics.AverageExpressionDuration{1} = Avg_Duration1;
- Outputs.Metrics.AverageExpressionDuration{2} = Avg_Duration2;
- Outputs.Metrics.AllExpressionDurations{1} = Duration1;
- Outputs.Metrics.AllExpressionDurations{2} = Duration2;
- Outputs.Metrics.TransitionProbabilities{1} = TransitionProbabilities1;
- Outputs.Metrics.TransitionProbabilities{2} = TransitionProbabilities2;
- Outputs.Metrics.FractionCAPFramesPerSeedCombination = sfrac;
- Outputs.Metrics.CAPEntriesFromBaseline{1} = From_Baseline1;
- Outputs.Metrics.CAPEntriesFromBaseline{2} = From_Baseline2;
- Outputs.Metrics.CAPExitsToBaseline{1} = To_Baseline1;
- Outputs.Metrics.CAPExitsToBaseline{2} = To_Baseline2;
- Outputs.Metrics.CAPResilience{1} = Resilience1;
- Outputs.Metrics.CAPResilience{2} = Resilience2;
- Outputs.Metrics.BaselineResilience{1} = Baseline_resilience1;
- Outputs.Metrics.BaselineResilience{2} = Baseline_resilience2;
- Outputs.Metrics.BetweennessCentrality{1} = Betweenness1;
- Outputs.Metrics.BetweennessCentrality{2} = Betweenness2;
- Outputs.Metrics.CAPInDegree{1} = InDegree1;
- Outputs.Metrics.CAPInDegree{2} = InDegree2;
- Outputs.Metrics.CAPOutDegree{1} = OutDegree1;
- Outputs.Metrics.CAPOutDegree{2} = OutDegree2;
- Outputs.Metrics.SubjectCounts{1} = SubjectEntries1;
- Outputs.Metrics.SubjectCounts{2} = SubjectEntries2;
- HeavyOutputs.SpatioTemporalSelection.ClusteredFrames{1} = Xon1; % Are this 3 lines necessary to be saved?
- HeavyOutputs.SpatioTemporalSelection.ClusteredFrames{2} = Xon2;%Xonp?
- HeavyOutputs.KMeansClustering.Consensus = Consensus;
- % Saves NIFTI files storing the CAPs in MNI space
- ReferencePopulation = 1;
- CAPToNIFTI(CAP,...
- mask{ReferencePopulation},brain_info{ReferencePopulation},...
- fullfile(SavePath,fancyName),['CAP_NIFTI_',fancyName]);
- CAPToNIFTI(CAP_Zscore(CAP),...
- mask{ReferencePopulation},brain_info{ReferencePopulation},...
- fullfile(SavePath,fancyName),['CAP_NIFTI_ZScored_',fancyName]);
- % Saves the different variables from the program
- save(fullfile(SavePath,fancyName),'OverallInfo','Parameters','Outputs','HeavyOutputs','brain','-v7.3');
- %save(fullfile(SavePath,fancyName),'OverallInfo','Parameters','Outputs','brain','-v7.3');
- disp('-----------------------------------------------------');
- disp('CAPs computed and saved successfully!');
- disp(' ');
- disp('Results are saved in: ');
- disp([SavePath]);
Script_twopop_PCA_HC_ref_SH.m at commit 1240c94, no license · at the source
Overview
- Psychosomatic Medicine, Department of Neurology, Inselspital, Bern University Hospital, University of Bern, 3010 Bern, Switzerland
- Graduate School of Cellular and Biomedical Sciences (GCB), University of Bern, 3012 Bern, Switzerland
- Translational Imaging Center (TIC), Swiss Institute for Translational and Entrepreneurial Medicine, 3010 Bern, Switzerland
- Department of Adult Psychiatry and Psychotherapy, University Hospital of Psychiatry Zurich, University of Zurich, 8032 Zurich, Switzerland
- Faculty of Medicine, University of Zurich, 8032 Zurich, Switzerland
- Department of Neurology, Faculty of Science and Medicine, University of Fribourg, 1700 Fribourg, Switzerland
- Veterinary Physiology, Vetsuisse Faculty, University of Bern, 3012 Bern, Switzerland
- Center for Integrative and Complementary Medicine, Department of Anesthesiology, Lausanne University Hospital, 1011 Lausanne, Switzerland
- Institute of Psychology, University of Bern, 3012 Bern, Switzerland
Abstract
Chronic primary pain occurs without an identifiable causal disease and is marked by persistent pain, emotional distress and functional disability. The anterior insular cortex, involved in salience processing and integration of sensory, emotional and cognitive aspects of pain, has been implicated in neural processes linking pain and stress responses. This study investigates whether specific brain state dynamics, using the anterior insula as a seed region, are associated with chronic primary pain and examines their associations with pain- and stress-related measures. Resting-state functional MRI, stress biomarkers (cortisol and alpha-amylase), a pain sensitivity test, as well as subjective measures of stress and pain were collected from patients with chronic primary pain (N = 30) and healthy controls (N = 30). Co-activation pattern analysis was used to identify brain states with the anterior insula as the seed region and to assess group differences in the temporal characteristics of these brain states. Partial least squares analysis was applied to investigate multivariate associations between specific temporal brain state characteristics and pain- and stress-related measures. Three anterior insula–seeded co-activation patterns (brain states) were identified in healthy controls. In the first co-activation pattern, the anterior insula co-activated with the default mode network; in the second, with the salience-somatomotor network; and in the third, with the visual network. Chronic primary pain patients and healthy controls differed significantly in temporal brain state characteristics, namely in the relative number of entries into co-activation pattern one (pFDR = 0.002) and two (pFDR = 0.022), and the relative occurrence of co-activation patterns one (pFDR = 0.022) and two (pFDR = 0.022). Furthermore, in chronic primary pain patients, perceived stress scores and cortisol were significantly associated with these specific temporal brain state characteristics (P = 0.002), whereas no associations were found with pain-related measures. Together, these findings suggest that in chronic primary pain, reduced coupling of the anterior insula with the default mode network and increased coupling of the anterior insula with salience-related networks are associated with psychophysiological stress markers. These brain state dynamics may potentially represent a neural correlate of altered stress processing in chronic primary pain.
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 10 matches between paragraphs and lines of code.
FND-ResearchGroup/CAP_in_CPP
1240c94a8fdfea5a597d5aab584649140b820c0b, 30 March 2026Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
7 files
- 01_Clinical_Measures/
Cortisol_AUC_Analysis.R , R, 158 lines, 1 match - 01_Clinical_Measures/
Demographics_Table.R , R, 436 lines, 4 matches - 02_CAPs/
01_Analysis/ , MATLAB, 922 lines, 4 matchesScript_twopop_PCA_HC_ref _SH.m - 02_CAPs/
02_Statistics/ , MATLAB, 384 lines01_CAPs_stats_vertical_2 Pop_SH.m - 02_CAPs/
02_Statistics/ , R, 755 lines, 1 match02_CAPs_Stat.Rmd - 02_CAPs/
03_Visualization/ , Jupyter, 194 linesCAPs_Visualization.ipynb - README.md, Text, 33 lines
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;
- 6 scripts, each with its path and the digest of its content;
- 10 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
The data are not publicly available but can be shared upon request. The TbCAPs toolbox is publicly available at https://
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, 28 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 12 authors, 5 keywords, 1 funder, 69 references.
Cite
This paper
Häuselmann, S., Wyss, A., Weber, S., Gninenko, N., Concetti, C., Müller, E., Bruckmaier, R., Gross, J., Bischoff, N., Berna, C., grosse Holtforth, M., & Aybek, S. (2026). Anterior insular co-activation patterns associated with stress markers in chronic primary pain. Brain communications, 8(2), fcag121. https://
BibTeX
@article{hauselmann2026a
author = {Häuselmann, Salome and Wyss, Anna and Weber, Samantha and Gninenko, Nicolas and Concetti, Cristina and Müller, Eliane and Bruckmaier, Rupert and Gross, Josef and Bischoff, Nina and Berna, Chantal and grosse Holtforth, Martin and Aybek, Selma},
title = {{Anterior insular co-activation patterns associated with stress markers in chronic primary pain}},
journal = {Brain communications},
year = {2026},
month = apr,
volume = {8},
number = {2},
pages = {fcag121},
publisher = {Oxford University Press},
issn = {2632-1297},
doi = {10.1093/
url = {https://
pmid = {41978789},
pmcid = {PMC13070617}
}
RIS
TY - JOUR
AU - Häuselmann, Salome
AU - Wyss, Anna
AU - Weber, Samantha
AU - Gninenko, Nicolas
AU - Concetti, Cristina
AU - Müller, Eliane
AU - Bruckmaier, Rupert
AU - Gross, Josef
AU - Bischoff, Nina
AU - Berna, Chantal
AU - grosse Holtforth, Martin
AU - Aybek, Selma
TI - Anterior insular co-activation patterns associated with stress markers in chronic primary pain
T2 - Brain communications
J2 - Brain Commun
PY - 2026
DA - 2026/
VL - 8
IS - 2
SP - fcag121
SN - 2632-1297
PB - Oxford University Press
DO - 10.1093/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1093/
"type": "article-journal",
"title": "Anterior insular co-activation patterns associated with stress markers in chronic primary pain",
"container-title": "Brain communications",
"author": [
{
"family": "Häuselmann",
"given": "Salome"
},
{
"family": "Wyss",
"given": "Anna"
},
{
"family": "Weber",
"given": "Samantha"
},
{
"family": "Gninenko",
"given": "Nicolas"
},
{
"family": "Concetti",
"given": "Cristina"
},
{
"family": "Müller",
"given": "Eliane"
},
{
"family": "Bruckmaier",
"given": "Rupert"
},
{
"family": "Gross",
"given": "Josef"
},
{
"family": "Bischoff",
"given": "Nina"
},
{
"family": "Berna",
"given": "Chantal"
},
{
"family": "grosse Holtforth",
"given": "Martin"
},
{
"family": "Aybek",
"given": "Selma"
}
],
"container-title-short":
"volume": "8",
"issue": "2",
"page": "fcag121",
"DOI": "10.1093/
"PMID": "41978789",
"PMCID": "PMC13070617",
"ISSN": "2632-1297",
"publisher": "Oxford University Press",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
3
]
]
}
}
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.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. ClinicalIn common: psych, rstatix, car, 11 other tools, fMRI, 1 reference
- [2] doi:10.1093/bioinformatics/btag592 [code]
- Network-based stratification of allele-specific expression reveals patient subgroups in Huntington's disease.Journal: Bioinformatics (Oxford, England)In common: multcomp, rstatix, car, 10 other tools
- [3] doi:10.1162/imag.a.1245 [code]
- Towards precision EEG connectomics: Evaluating the benefits of dense sampling.Journal: Imaging neuroscience (Cambridge, Mass.)In common: psych, rstatix, lmerTest, 11 other tools
- [4] doi:10.1093/braincomms/fcag146 [code]
- Convergent structural brain alterations in chronic pain: a multi-metric individual participant data meta-analysis.Journal: Brain communicationsIn common: multcomp, psych, car, 5 other tools, pain, 2 references
- [5] doi:10.1523/eneuro.0076-26.2026 [code]
- Exogenously Driven Neural Reactivation of Spatially Matching Visual Working-Memory Contents.Journal: eNeuroIn common: multcomp, rstatix, car, 9 other tools
- [6] doi:10.1093/cercor/bhag077 [code]
- The longitudinal development of intrinsic timescales in infancy and their relation to alpha brain rhythm.Journal: Cerebral cortex (New York, N.Y. : 1991)In common: multcomp, psych, easystats, 9 other tools
- [7] doi:10.1016/j.neuroimage.2026.122115 [code]
- Midfrontal theta power relates to response speeding following frustrative nonreward.Journal: NeuroImageIn common: psych, rstatix, easystats, 8 other tools
- [8] doi:10.1093/brain/awag080 [code]
- Early glymphatic failure in AppNL-F knock-in mice is linked to parenchymal border macrophages loss.Journal: Brain : a journal of neurologyIn common: multcomp, psych, rstatix, 7 other tools
- [9] 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: rstatix, easystats, car, 9 other tools
- [10] doi:10.1038/s41380-026-03694-1 [code]
- Targeting cortico-striatal-amygdal
ar networks via theta-band frontoparietal synchronization in opioid use disorder: a randomized tACS-fMRI Trial. Journal: Molecular psychiatryIn common: multcomp, lmerTest, lme4, 7 other tools, pain, fMRI, clinical / translational
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 1 repository of the authors' code, each at its verified commit and with its license, 6 scripts, and 10 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:fa8f92c4d79aa060…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
