docs/SKILL.md
Guidance skill for PydFC tutorial workflows, copy-paste examples, and evidence-based scientific response style.
npx skillsauth add neurodatascience/dfc docsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this file as the primary context for interactive help about pydfc.
Never modify source code in this repo (including pydfc/*, notebooks, scripts, configs, or tests) while using this skill.
pydfc files.nilearn).This skill is for guidance and copy-paste examples only, not codebase modification.
Help the user:
pydfcexamples/dFC_methods_demo.pyTIME_SERIES objects (BOLD or BOLD_multi)Keep the interaction simple and copy-paste oriented.
Refer to docs/DFC_METHODS_CONTEXT.md for:
Always ground answers in this document.
Also use docs/PAPER_KNOWLEDGE_BASE.md for paper-based implementation details, assumptions, and pros/cons.
When user asks about methods:
Use precise, evidence-based, and appropriately uncertain language.
Follow this sequence:
State-free method (single subject; fastest start), orState-based method (multi-subject; requires fitting)BOLD or BOLD_multi).Which dFC method would you like to use?Are there any other methods you are curious about?.ipynb or .py file.README.rst for install commandsexamples/dFC_methods_demo.py for data download and method examplesdocs/DFC_METHODS_CONTEXT.md for assumptions and interpretation guidancedocs/PAPER_KNOWLEDGE_BASE.md for paper-grounded method tradeoffsWhen generating download commands or loading snippets:
examples/dFC_methods_demo.py.Rationale: Nilearn confound loading relies on BIDS-compatible naming and co-location.
num_select_nodes) as practical tradeoffs, not universal defaults.Content in this repository is derived from:
Torabi et al., 2024 On the variability of dynamic functional connectivity assessment methods GigaScience https://doi.org/10.1093/gigascience/giae009
If answering questions about dFC methods or assumptions, cite Torabi et al., 2024 when relevant.
Share this first when needed:
conda create --name pydfc_env python=3.11
conda activate pydfc_env
pip install pydfc
Use this in notebook cells before method-specific code:
from pydfc import data_loader
import numpy as np
import warnings
warnings.simplefilter("ignore")
If the user is in Jupyter, provide exactly:
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0001/func/sub-0001_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz?versionId=UfCs4xtwIEPDgmb32qFbtMokl_jxLUKr -o sample_data/sub-0001_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0001/func/sub-0001_task-restingstate_acq-mb3_desc-confounds_regressors.tsv?versionId=biaIJGNQ22P1l1xEsajVzUW6cnu1_8lD -o sample_data/sub-0001_task-restingstate_acq-mb3_desc-confounds_regressors.tsv
If they are using a terminal, remove the leading !.
BOLDBOLD = data_loader.nifti2timeseries(
nifti_file="sample_data/sub-0001_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz",
n_rois=100,
Fs=1 / 0.75,
subj_id="sub-0001",
confound_strategy="no_motion", # no_motion, no_motion_no_gsr, or none
standardize=False,
TS_name=None,
session=None,
)
BOLD.visualize(start_time=0, end_time=1000, nodes_lst=range(10))
Ask exactly (or very close):
Which dFC method would you like to use to assess dFC? (SW or TF for the simple state-free path)
Before that, ask:
Would you like a brief description of SW vs TF before choosing?
If yes, give a short description:
SW (Sliding Window): computes connectivity in overlapping time windows. Simple and commonly used; key tradeoff is temporal resolution vs stability, controlled mainly by window length W.TF (Time-Frequency): estimates dynamic relationships in a time-frequency representation (here WTC). Can capture frequency-specific changes but is heavier computationally and has more runtime settings (e.g., n_jobs).from pydfc.dfc_methods import SLIDING_WINDOW
params_methods = {
"W": 44, # window length (seconds): larger = smoother/more stable FC, smaller = more temporal sensitivity
"n_overlap": 0.5, # fraction overlap between consecutive windows: higher = denser sampling but more redundancy
"sw_method": "pear_corr",# FC estimator inside each window (e.g., Pearson correlation)
"tapered_window": True, # whether to taper window edges to reduce boundary artifacts
"normalization": True, # normalize data/features internally before estimation (improves comparability across nodes/subjects)
"num_select_nodes": None,# optional subset of ROIs for speed/memory (e.g., 50)
}
measure = SLIDING_WINDOW(**params_methods)
dFC = measure.estimate_dFC(time_series=BOLD)
dFC.visualize_dFC(TRs=dFC.TR_array[:], normalize=False, fix_lim=False)
Optional summary plot:
import matplotlib.pyplot as plt
avg_dFC = np.mean(np.mean(dFC.get_dFC_mat(), axis=1), axis=1)
plt.figure(figsize=(10, 3))
plt.plot(dFC.TR_array, avg_dFC)
plt.show()
from pydfc.dfc_methods import TIME_FREQ
params_methods = {
"TF_method": "WTC", # time-frequency estimator variant (WTC in the demo)
"n_jobs": 2, # parallel workers; increase for speed if CPU allows
"verbose": 0, # joblib verbosity level
"backend": "loky", # parallel backend used by joblib
"normalization": True, # normalize before estimation
"num_select_nodes": None, # optional ROI subset for speed/memory
}
measure = TIME_FREQ(**params_methods)
dFC = measure.estimate_dFC(time_series=BOLD)
TRs = dFC.TR_array[np.arange(29, 480 - 29, 29)]
dFC.visualize_dFC(TRs=TRs, normalize=True, fix_lim=False)
State-based methods require fitting FC states on multiple subjects first.
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0001/func/sub-0001_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz?versionId=UfCs4xtwIEPDgmb32qFbtMokl_jxLUKr -o sample_data/sub-0001_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0001/func/sub-0001_task-restingstate_acq-mb3_desc-confounds_regressors.tsv?versionId=biaIJGNQ22P1l1xEsajVzUW6cnu1_8lD -o sample_data/sub-0001_task-restingstate_acq-mb3_desc-confounds_regressors.tsv
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0002/func/sub-0002_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz?versionId=fUBWmUTg6vfe2n.ywDNms4mOAW3r6E9Y -o sample_data/sub-0002_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0002/func/sub-0002_task-restingstate_acq-mb3_desc-confounds_regressors.tsv?versionId=2zWQIugU.J6ilTFObWGznJdSABbaTx9F -o sample_data/sub-0002_task-restingstate_acq-mb3_desc-confounds_regressors.tsv
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0003/func/sub-0003_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz?versionId=dfNd8iV0V68yuOibes6qiHxjBgQXhPxi -o sample_data/sub-0003_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0003/func/sub-0003_task-restingstate_acq-mb3_desc-confounds_regressors.tsv?versionId=8OpKFrs_8aJ5cVixokBmuTVKNslgtOXb -o sample_data/sub-0003_task-restingstate_acq-mb3_desc-confounds_regressors.tsv
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0004/func/sub-0004_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz?versionId=0Le8eFwJbcLKaMTQat39bzWcGFhRiyP5 -o sample_data/sub-0004_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0004/func/sub-0004_task-restingstate_acq-mb3_desc-confounds_regressors.tsv?versionId=welg1B.VkXHGv06iV56Vp7ezpVTFh2eX -o sample_data/sub-0004_task-restingstate_acq-mb3_desc-confounds_regressors.tsv
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0005/func/sub-0005_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz?versionId=Vwo2YcFvhwbhZktBrPUqi_5BWiR7zcTl -o sample_data/sub-0005_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz
!curl --create-dirs https://s3.amazonaws.com/openneuro.org/ds002785/derivatives/fmriprep/sub-0005/func/sub-0005_task-restingstate_acq-mb3_desc-confounds_regressors.tsv?versionId=FoBZLbFTZaE3ZjOLZI_4hN4OkEKEZTVf -o sample_data/sub-0005_task-restingstate_acq-mb3_desc-confounds_regressors.tsv
BOLD_multisubj_id_list = ["sub-0001", "sub-0002", "sub-0003", "sub-0004", "sub-0005"]
nifti_files_list = []
for subj_id in subj_id_list:
nifti_files_list.append(
"sample_data/"
+ subj_id
+ "_task-restingstate_acq-mb3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz"
)
BOLD_multi = data_loader.multi_nifti2timeseries(
nifti_files_list,
subj_id_list,
n_rois=100,
Fs=1 / 0.75,
confound_strategy="no_motion",
standardize=False,
TS_name=None,
session=None,
)
Ask exactly (or very close):
Which dFC method would you like to use to assess dFC? (CAP, SWC, CHMM, DHMM, or WINDOWLESS)
Before that, ask:
Would you like a brief description of these state-based methods before choosing?
If yes, give a short description:
CAP: clusters high-activity/co-activation patterns into states; intuitive and often a good first state-based method.SWC: computes sliding-window FC then clusters those windows into recurring states.CHMM: continuous HMM-based state model; models temporal transitions directly in continuous observations.DHMM: discrete HMM variant, often built on discretized/windowed observations; can need more data for stable fitting.WINDOWLESS: state-based method without explicit sliding windows; useful when avoiding window-size dependence.from pydfc.dfc_methods import CAP
params_methods = {
"n_states": 12, # number of FC states to estimate; central modeling choice (too low merges states, too high fragments)
"n_subj_clstrs": 20, # subject-level clustering granularity used before group state estimation
"normalization": True, # normalize before estimation
"num_subj": None, # optional subject subsampling for faster debugging/prototyping
"num_select_nodes": None,# optional ROI subset for speed/memory
}
measure = CAP(**params_methods)
measure.estimate_FCS(time_series=BOLD_multi)
dFC = measure.estimate_dFC(time_series=BOLD_multi.get_subj_ts(subjs_id="sub-0001"))
TRs = dFC.TR_array[np.arange(29, 480 - 29, 29)]
dFC.visualize_dFC(TRs=TRs, normalize=True, fix_lim=False)
from pydfc.dfc_methods import SLIDING_WINDOW_CLUSTR
params_methods = {
"W": 44, # sliding window length (seconds)
"n_overlap": 0.5, # overlap fraction between windows
"sw_method": "pear_corr", # FC estimator inside each window
"tapered_window": True, # taper window edges to reduce edge effects
"clstr_base_measure": "SlidingWindow", # base measure used to generate features for clustering
"n_states": 12, # number of clustered FC states
"n_subj_clstrs": 5, # subject-level clustering granularity before group clustering
"normalization": True, # normalize before estimation
"num_subj": None, # optional subject subsampling
"num_select_nodes": None, # optional ROI subset for speed/memory
}
measure = SLIDING_WINDOW_CLUSTR(**params_methods)
measure.estimate_FCS(time_series=BOLD_multi)
dFC = measure.estimate_dFC(time_series=BOLD_multi.get_subj_ts(subjs_id="sub-0001"))
dFC.visualize_dFC(TRs=dFC.TR_array[:], normalize=True, fix_lim=False)
from pydfc.dfc_methods import HMM_CONT
params_methods = {
"hmm_iter": 20, # number of HMM training iterations; more can improve convergence but costs time
"n_states": 12, # number of hidden states
"normalization": True, # normalize before estimation
"num_subj": None, # optional subject subsampling
"num_select_nodes": None,# optional ROI subset for speed/memory
}
measure = HMM_CONT(**params_methods)
measure.estimate_FCS(time_series=BOLD_multi)
dFC = measure.estimate_dFC(time_series=BOLD_multi.get_subj_ts(subjs_id="sub-0001"))
TRs = dFC.TR_array[np.arange(29, 480 - 29, 29)]
dFC.visualize_dFC(TRs=TRs, normalize=True, fix_lim=False)
Note: the demo notebook warns that 5 subjects is too small to fit DHMM well; a warning is expected.
from pydfc.dfc_methods import HMM_DISC
params_methods = {
"W": 44, # sliding window length (seconds) used to create observations
"n_overlap": 0.5, # overlap fraction for sliding windows
"sw_method": "pear_corr", # FC estimator per window
"tapered_window": True, # taper window edges
"clstr_base_measure": "SlidingWindow", # base measure for discretization pipeline
"hmm_iter": 20, # HMM training iterations
"dhmm_obs_state_ratio": 16 / 24, # ratio controlling observation-state discretization relative to hidden states
"n_states": 12, # number of hidden states
"n_subj_clstrs": 5, # subject-level clustering granularity
"normalization": True, # normalize before estimation
"num_subj": None, # optional subject subsampling
"num_select_nodes": 50, # ROI subset (demo uses 50 here to reduce cost)
}
measure = HMM_DISC(**params_methods)
measure.estimate_FCS(time_series=BOLD_multi)
dFC = measure.estimate_dFC(time_series=BOLD_multi.get_subj_ts(subjs_id="sub-0001"))
dFC.visualize_dFC(TRs=dFC.TR_array[:], normalize=True, fix_lim=False)
from pydfc.dfc_methods import WINDOWLESS
params_methods = {
"n_states": 12, # number of states to estimate
"normalization": True, # normalize before estimation
"num_subj": None, # optional subject subsampling
"num_select_nodes": None,# optional ROI subset for speed/memory
}
measure = WINDOWLESS(**params_methods)
measure.estimate_FCS(time_series=BOLD_multi)
dFC = measure.estimate_dFC(time_series=BOLD_multi.get_subj_ts(subjs_id="sub-0001"))
TRs = dFC.TR_array[np.arange(29, 480 - 29, 29)]
dFC.visualize_dFC(TRs=TRs, normalize=True, fix_lim=False)
SW first (state-free, simplest).Are there any other methods you are curious about?Would you like me to extract all code from this chat into a Jupyter notebook (.ipynb) or a Python script (.py)?If the user reports an error:
python --version, package versions)pip install -U pydfc, dependency install)num_select_nodes, num_subj, n_jobs)SW before state-based methods)testing
Create, edit, improve, or audit AgentSkills. Use when creating a new skill from scratch or when asked to improve, review, audit, tidy up, or clean up an existing skill or SKILL.md file. Also use when editing or restructuring a skill directory (moving files to references/ or scripts/, removing stale content, validating against the AgentSkills spec). Triggers on phrases like "create a skill", "author a skill", "tidy up a skill", "improve this skill", "review the skill", "clean up the skill", "audit the skill".
testing
Host security hardening and risk-tolerance configuration for OpenClaw deployments. Use when a user asks for security audits, firewall/SSH/update hardening, risk posture, exposure review, OpenClaw cron scheduling for periodic checks, or version status checks on a machine running OpenClaw (laptop, workstation, Pi, VPS).
testing
Create, edit, improve, or audit AgentSkills. Use when creating a new skill from scratch or when asked to improve, review, audit, tidy up, or clean up an existing skill or SKILL.md file. Also use when editing or restructuring a skill directory (moving files to references/ or scripts/, removing stale content, validating against the AgentSkills spec). Triggers on phrases like "create a skill", "author a skill", "tidy up a skill", "improve this skill", "review the skill", "clean up the skill", "audit the skill".
testing
Host security hardening and risk-tolerance configuration for OpenClaw deployments. Use when a user asks for security audits, firewall/SSH/update hardening, risk posture, exposure review, OpenClaw cron scheduling for periodic checks, or version status checks on a machine running OpenClaw (laptop, workstation, Pi, VPS).