@brainpilot/skills 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/skills/01_Meta-Skills/academic-research-hub/SKILL.md +108 -0
- package/skills/01_Meta-Skills/academic-research-hub/scripts/requirements.txt +17 -0
- package/skills/01_Meta-Skills/academic-research-hub/scripts/research.py +781 -0
- package/skills/01_Meta-Skills/beautiful-log/SKILL.md +64 -0
- package/skills/01_Meta-Skills/beautiful-log/scripts/beautiful_log.py +274 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/SKILL.md +130 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/assets/config.template.yaml +54 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/assets/top5_digest_template.md +5 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/build_top5_digest.py +300 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/common.py +137 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/merge_results.py +106 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/run_pipeline.py +177 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/search_arxiv.py +162 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/search_pubmed.py +202 -0
- package/skills/01_Meta-Skills/ethoclaw-normalize-tabular/SKILL.md +173 -0
- package/skills/01_Meta-Skills/ethoclaw-normalize-tabular/scripts/normalize_data.py +874 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/SKILL.md +134 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/references/confirmation-prompts.md +31 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/references/output-patterns.md +45 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/build_markdown_deliverables.py +41 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/build_research_log.py +84 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/build_summary_md.py +63 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/extract_pdf_bundle.py +140 -0
- package/skills/01_Meta-Skills/experiment-controller/SKILL.md +140 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/SKILL.md +366 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/entity_resolution.py +120 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/extraction_prompt_template.txt +19 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/graph_query.py +106 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/hypothesis_cli_reference.py +42 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/new_data_source_template.py +116 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/requirements.txt +15 -0
- package/skills/01_Meta-Skills/method-design/SKILL.md +61 -0
- package/skills/01_Meta-Skills/multi-search-engine/SKILL.md +119 -0
- package/skills/01_Meta-Skills/research-idea/SKILL.md +65 -0
- package/skills/05_EEG_ERP/eeg-skill/SKILL.md +197 -0
- package/skills/05_EEG_ERP/meg-skill/SKILL.md +188 -0
- package/skills/05_EEG_ERP/meg-skill/scripts/time_frequency.py +223 -0
- package/skills/05_EEG_ERP/mne-eeg-tool/SKILL.md +165 -0
- package/skills/05_EEG_ERP/mne-eeg-tool/scripts/eeg_pipeline_reference.py +231 -0
- package/skills/05_EEG_ERP/seed-iv-skill/SKILL.md +184 -0
- package/skills/05_EEG_ERP/seed-iv-skill/scripts/classify_seed_iv.py +154 -0
- package/skills/05_EEG_ERP/seed-iv-skill/scripts/extract_seed_iv_features.py +190 -0
- package/skills/05_EEG_ERP/seed-iv-skill/scripts/validate_seed_iv.py +102 -0
- package/skills/05_EEG_ERP/seed-vig-skill/SKILL.md +182 -0
- package/skills/05_EEG_ERP/seed-vig-skill/scripts/classify_seed_vig.py +165 -0
- package/skills/05_EEG_ERP/seed-vig-skill/scripts/extract_seed_vig_features.py +185 -0
- package/skills/05_EEG_ERP/seed-vig-skill/scripts/validate_seed_vig.py +88 -0
- package/skills/06_fMRI_Neuroimaging/abcd-skill/SKILL.md +308 -0
- package/skills/06_fMRI_Neuroimaging/abcd-skill/scripts/abcd_qc_summary.py +449 -0
- package/skills/06_fMRI_Neuroimaging/abcd-skill/scripts/extract_abcd_phenotype.py +292 -0
- package/skills/06_fMRI_Neuroimaging/abcd-skill/scripts/reorganize_abcd.py +387 -0
- package/skills/06_fMRI_Neuroimaging/abide-skill/SKILL.md +302 -0
- package/skills/06_fMRI_Neuroimaging/abide-skill/scripts/abide_qc_summary.py +317 -0
- package/skills/06_fMRI_Neuroimaging/abide-skill/scripts/extract_abide_phenotype.py +267 -0
- package/skills/06_fMRI_Neuroimaging/abide-skill/scripts/reorganize_abide.py +387 -0
- package/skills/06_fMRI_Neuroimaging/adhd200-skill/SKILL.md +244 -0
- package/skills/06_fMRI_Neuroimaging/adhd200-skill/scripts/adhd200_qc_summary.py +98 -0
- package/skills/06_fMRI_Neuroimaging/adhd200-skill/scripts/extract_adhd200_phenotype.py +134 -0
- package/skills/06_fMRI_Neuroimaging/adhd200-skill/scripts/reorganize_adhd200.py +206 -0
- package/skills/06_fMRI_Neuroimaging/adni-skill/SKILL.md +358 -0
- package/skills/06_fMRI_Neuroimaging/adni-skill/scripts/generate_adni_task_files.py +1305 -0
- package/skills/06_fMRI_Neuroimaging/adni-skill/scripts/generate_vqa_from_tasks.py +766 -0
- package/skills/06_fMRI_Neuroimaging/adni-skill/scripts/reorganize_adni.py +491 -0
- package/skills/06_fMRI_Neuroimaging/aibl-skill/SKILL.md +295 -0
- package/skills/06_fMRI_Neuroimaging/aibl-skill/scripts/aibl_qc_summary.py +260 -0
- package/skills/06_fMRI_Neuroimaging/aibl-skill/scripts/extract_aibl_phenotype.py +365 -0
- package/skills/06_fMRI_Neuroimaging/aibl-skill/scripts/reorganize_aibl.py +394 -0
- package/skills/06_fMRI_Neuroimaging/aomic-skill/SKILL.md +292 -0
- package/skills/06_fMRI_Neuroimaging/aomic-skill/scripts/aomic_qc_summary.py +258 -0
- package/skills/06_fMRI_Neuroimaging/aomic-skill/scripts/extract_aomic_phenotype.py +284 -0
- package/skills/06_fMRI_Neuroimaging/aomic-skill/scripts/reorganize_aomic.py +322 -0
- package/skills/06_fMRI_Neuroimaging/asl-skill/SKILL.md +168 -0
- package/skills/06_fMRI_Neuroimaging/asl-skill/scripts/compute_cbf.py +224 -0
- package/skills/06_fMRI_Neuroimaging/bids-organizer/SKILL.md +241 -0
- package/skills/06_fMRI_Neuroimaging/bold5000-skill/SKILL.md +186 -0
- package/skills/06_fMRI_Neuroimaging/bold5000-skill/scripts/bold5000_qc_summary.py +96 -0
- package/skills/06_fMRI_Neuroimaging/bold5000-skill/scripts/extract_bold5000_stimulus.py +125 -0
- package/skills/06_fMRI_Neuroimaging/bold5000-skill/scripts/reorganize_bold5000.py +102 -0
- package/skills/06_fMRI_Neuroimaging/camcan-skill/SKILL.md +213 -0
- package/skills/06_fMRI_Neuroimaging/camcan-skill/scripts/camcan_qc_summary.py +131 -0
- package/skills/06_fMRI_Neuroimaging/camcan-skill/scripts/extract_camcan_phenotype.py +145 -0
- package/skills/06_fMRI_Neuroimaging/camcan-skill/scripts/validate_camcan.py +141 -0
- package/skills/06_fMRI_Neuroimaging/cobre-skill/SKILL.md +201 -0
- package/skills/06_fMRI_Neuroimaging/cobre-skill/scripts/cobre_qc_summary.py +95 -0
- package/skills/06_fMRI_Neuroimaging/cobre-skill/scripts/extract_cobre_phenotype.py +104 -0
- package/skills/06_fMRI_Neuroimaging/cobre-skill/scripts/reorganize_cobre.py +140 -0
- package/skills/06_fMRI_Neuroimaging/conn-tool/SKILL.md +180 -0
- package/skills/06_fMRI_Neuroimaging/dcm2nii/SKILL.md +189 -0
- package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/SKILL.md +183 -0
- package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/scripts/dmt_har_med_qc_summary.py +96 -0
- package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/scripts/extract_dmt_har_med_phenotype.py +121 -0
- package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/scripts/reorganize_dmt_har_med.py +125 -0
- package/skills/06_fMRI_Neuroimaging/dwi-skill/SKILL.md +359 -0
- package/skills/06_fMRI_Neuroimaging/fmri-skill/SKILL.md +371 -0
- package/skills/06_fMRI_Neuroimaging/fmriprep-tool/SKILL.md +228 -0
- package/skills/06_fMRI_Neuroimaging/freesurfer-tool/SKILL.md +286 -0
- package/skills/06_fMRI_Neuroimaging/freesurfer-tool/scripts/freesurfer_processor.py +145 -0
- package/skills/06_fMRI_Neuroimaging/fsl-tool/SKILL.md +208 -0
- package/skills/06_fMRI_Neuroimaging/hbn-skill/SKILL.md +271 -0
- package/skills/06_fMRI_Neuroimaging/hbn-skill/scripts/extract_hbn_phenotype.py +107 -0
- package/skills/06_fMRI_Neuroimaging/hbn-skill/scripts/hbn_qc_summary.py +96 -0
- package/skills/06_fMRI_Neuroimaging/hbn-skill/scripts/reorganize_hbn.py +150 -0
- package/skills/06_fMRI_Neuroimaging/hcpa-skill/SKILL.md +210 -0
- package/skills/06_fMRI_Neuroimaging/hcpa-skill/scripts/extract_hcpa_phenotype.py +146 -0
- package/skills/06_fMRI_Neuroimaging/hcpa-skill/scripts/hcpa_qc_summary.py +120 -0
- package/skills/06_fMRI_Neuroimaging/hcpa-skill/scripts/reorganize_hcpa.py +155 -0
- package/skills/06_fMRI_Neuroimaging/hcpd-skill/SKILL.md +210 -0
- package/skills/06_fMRI_Neuroimaging/hcpd-skill/scripts/extract_hcpd_phenotype.py +148 -0
- package/skills/06_fMRI_Neuroimaging/hcpd-skill/scripts/hcpd_qc_summary.py +125 -0
- package/skills/06_fMRI_Neuroimaging/hcpd-skill/scripts/reorganize_hcpd.py +146 -0
- package/skills/06_fMRI_Neuroimaging/hcpep-skill/SKILL.md +215 -0
- package/skills/06_fMRI_Neuroimaging/hcpep-skill/scripts/extract_hcpep_phenotype.py +157 -0
- package/skills/06_fMRI_Neuroimaging/hcpep-skill/scripts/hcpep_qc_summary.py +143 -0
- package/skills/06_fMRI_Neuroimaging/hcpep-skill/scripts/reorganize_hcpep.py +146 -0
- package/skills/06_fMRI_Neuroimaging/hcppipeline-tool/SKILL.md +217 -0
- package/skills/06_fMRI_Neuroimaging/hcpya-skill/SKILL.md +214 -0
- package/skills/06_fMRI_Neuroimaging/hcpya-skill/scripts/extract_hcpya_phenotype.py +190 -0
- package/skills/06_fMRI_Neuroimaging/hcpya-skill/scripts/hcpya_qc_summary.py +152 -0
- package/skills/06_fMRI_Neuroimaging/hcpya-skill/scripts/reorganize_hcpya.py +203 -0
- package/skills/06_fMRI_Neuroimaging/ixi-skill/SKILL.md +198 -0
- package/skills/06_fMRI_Neuroimaging/ixi-skill/scripts/ixi_qc_summary.py +137 -0
- package/skills/06_fMRI_Neuroimaging/ixi-skill/scripts/reorganize_ixi.py +190 -0
- package/skills/06_fMRI_Neuroimaging/mnd-skill/SKILL.md +191 -0
- package/skills/06_fMRI_Neuroimaging/mnd-skill/scripts/extract_mnd_phenotype.py +143 -0
- package/skills/06_fMRI_Neuroimaging/mnd-skill/scripts/mnd_qc_summary.py +120 -0
- package/skills/06_fMRI_Neuroimaging/mnd-skill/scripts/validate_mnd.py +107 -0
- package/skills/06_fMRI_Neuroimaging/mschallenge-skill/SKILL.md +203 -0
- package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/analyze_lesions.py +119 -0
- package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/longitudinal_lesion.py +148 -0
- package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/mschallenge_qc_summary.py +132 -0
- package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/validate_mschallenge.py +116 -0
- package/skills/06_fMRI_Neuroimaging/nibabel-skill/SKILL.md +184 -0
- package/skills/06_fMRI_Neuroimaging/nibabel-skill/scripts/atlas_coordinate_reference.py +61 -0
- package/skills/06_fMRI_Neuroimaging/nibabel-skill/scripts/freesurfer_io_reference.py +34 -0
- package/skills/06_fMRI_Neuroimaging/nibabel-skill/scripts/nifti_inspection_reference.py +35 -0
- package/skills/06_fMRI_Neuroimaging/nifd-skill/SKILL.md +205 -0
- package/skills/06_fMRI_Neuroimaging/nifd-skill/scripts/extract_nifd_phenotype.py +132 -0
- package/skills/06_fMRI_Neuroimaging/nifd-skill/scripts/nifd_qc_summary.py +111 -0
- package/skills/06_fMRI_Neuroimaging/nifd-skill/scripts/validate_nifd.py +111 -0
- package/skills/06_fMRI_Neuroimaging/nii2dcm/SKILL.md +143 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/SKILL.md +266 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/connectome_reference.py +65 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/denoise_timeseries_reference.py +58 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/hierarchical_parcellation_reference.py +53 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/kmeans_parcellation_reference.py +53 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/preprocess_bold_reference.py +76 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/rest_dictlearning_reference.py +56 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/rest_ica_reference.py +59 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/second_level_glm_reference.py +58 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/spacenet_classifier_reference.py +59 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/svm_classifier_reference.py +60 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/task_glm_reference.py +63 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/zalff_summary_reference.py +109 -0
- package/skills/06_fMRI_Neuroimaging/nsd-skill/SKILL.md +210 -0
- package/skills/06_fMRI_Neuroimaging/nsd-skill/scripts/extract_nsd_stimulus.py +171 -0
- package/skills/06_fMRI_Neuroimaging/nsd-skill/scripts/nsd_qc_summary.py +142 -0
- package/skills/06_fMRI_Neuroimaging/nsd-skill/scripts/validate_nsd.py +142 -0
- package/skills/06_fMRI_Neuroimaging/oasis-skill/SKILL.md +205 -0
- package/skills/06_fMRI_Neuroimaging/oasis-skill/scripts/extract_oasis_phenotype.py +126 -0
- package/skills/06_fMRI_Neuroimaging/oasis-skill/scripts/oasis_qc_summary.py +115 -0
- package/skills/06_fMRI_Neuroimaging/oasis-skill/scripts/validate_oasis.py +119 -0
- package/skills/06_fMRI_Neuroimaging/pet-skill/SKILL.md +173 -0
- package/skills/06_fMRI_Neuroimaging/pet-skill/scripts/compute_suvr.py +202 -0
- package/skills/06_fMRI_Neuroimaging/pnc-skill/SKILL.md +206 -0
- package/skills/06_fMRI_Neuroimaging/pnc-skill/scripts/extract_pnc_phenotype.py +136 -0
- package/skills/06_fMRI_Neuroimaging/pnc-skill/scripts/pnc_qc_summary.py +116 -0
- package/skills/06_fMRI_Neuroimaging/pnc-skill/scripts/validate_pnc.py +120 -0
- package/skills/06_fMRI_Neuroimaging/ppmi-skill/SKILL.md +209 -0
- package/skills/06_fMRI_Neuroimaging/ppmi-skill/scripts/extract_ppmi_phenotype.py +138 -0
- package/skills/06_fMRI_Neuroimaging/ppmi-skill/scripts/ppmi_qc_summary.py +111 -0
- package/skills/06_fMRI_Neuroimaging/ppmi-skill/scripts/validate_ppmi.py +117 -0
- package/skills/06_fMRI_Neuroimaging/qsiprep-tool/SKILL.md +320 -0
- package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/SKILL.md +215 -0
- package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/extract_rest_mdd_phenotype.py +132 -0
- package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/harmonize_sites.py +152 -0
- package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/rest_mdd_qc_summary.py +124 -0
- package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/validate_rest_mdd.py +103 -0
- package/skills/06_fMRI_Neuroimaging/smri-skill/SKILL.md +302 -0
- package/skills/06_fMRI_Neuroimaging/tcp-skill/SKILL.md +204 -0
- package/skills/06_fMRI_Neuroimaging/tcp-skill/scripts/extract_tcp_phenotype.py +139 -0
- package/skills/06_fMRI_Neuroimaging/tcp-skill/scripts/tcp_qc_summary.py +111 -0
- package/skills/06_fMRI_Neuroimaging/tcp-skill/scripts/validate_tcp.py +99 -0
- package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/SKILL.md +217 -0
- package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/scripts/extract_ucla_cnp_phenotype.py +145 -0
- package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/scripts/ucla_cnp_qc_summary.py +111 -0
- package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/scripts/validate_ucla_cnp.py +113 -0
- package/skills/06_fMRI_Neuroimaging/ukb-skill/SKILL.md +310 -0
- package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/build_ukb_survival.py +210 -0
- package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/extract_ukb_cases.py +308 -0
- package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/extract_ukb_phenotype.py +232 -0
- package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/ukb_qc_summary.py +158 -0
- package/skills/06_fMRI_Neuroimaging/wmh-segmentation/SKILL.md +133 -0
- package/skills/07_Computational_Modeling/detrending/SKILL.md +118 -0
- package/skills/07_Computational_Modeling/dictlearning/SKILL.md +122 -0
- package/skills/07_Computational_Modeling/filtering/SKILL.md +121 -0
- package/skills/07_Computational_Modeling/glm/SKILL.md +153 -0
- package/skills/07_Computational_Modeling/hierarchical/SKILL.md +121 -0
- package/skills/07_Computational_Modeling/ica/SKILL.md +122 -0
- package/skills/07_Computational_Modeling/kmeans/SKILL.md +119 -0
- package/skills/07_Computational_Modeling/run_models/SKILL.md +427 -0
- package/skills/07_Computational_Modeling/spacenet/SKILL.md +122 -0
- package/skills/07_Computational_Modeling/svm/SKILL.md +120 -0
- package/skills/08_Computational_Neuroscience/brain_gnn/SKILL.md +183 -0
- package/skills/08_Computational_Neuroscience/dipy-tool/SKILL.md +239 -0
- package/skills/08_Computational_Neuroscience/dipy-tool/scripts/dti_metrics_reference.py +70 -0
- package/skills/08_Computational_Neuroscience/dipy-tool/scripts/load_and_mask_reference.py +76 -0
- package/skills/08_Computational_Neuroscience/dipy-tool/scripts/roi_stats_reference.py +59 -0
- package/skills/08_Computational_Neuroscience/fm_app/SKILL.md +195 -0
- package/skills/08_Computational_Neuroscience/neurostorm/SKILL.md +151 -0
- package/skills/13_Visualization/brain-visualization/SKILL.md +191 -0
- package/skills/13_Visualization/brain-visualization/scripts/connectome_reference.py +108 -0
- package/skills/13_Visualization/brain-visualization/scripts/freesurfer_ply_reference.py +54 -0
- package/skills/13_Visualization/brain-visualization/scripts/zalff_summary_reference.py +116 -0
- package/skills/13_Visualization/ethoclaw-paper-figure-layout/SKILL.md +78 -0
- package/skills/13_Visualization/ethoclaw-paper-figure-layout/assets/naturecomm_figures.tex +74 -0
- package/skills/13_Visualization/ethoclaw-paper-figure-layout/scripts/layout_results_foldered.py +579 -0
- package/skills/14_Writing/overleaf-skill/SKILL.md +184 -0
- package/skills/14_Writing/overleaf-skill/scripts/install.sh +30 -0
- package/skills/14_Writing/paper-writing/SKILL.md +146 -0
- package/skills/14_Writing/paper-writing/scripts/data_statement_templates.py +164 -0
- package/skills/14_Writing/paper-writing/scripts/figure_templates.py +315 -0
- package/skills/14_Writing/paper-writing/scripts/nature_figure_style.py +214 -0
- package/skills/14_Writing/paper-writing/scripts/section_phrasebank.py +246 -0
- package/skills/16_Animal_Behavior/deeplabcut/SKILL.md +154 -0
- package/skills/16_Animal_Behavior/deeplabcut/references/3d-pose.md +89 -0
- package/skills/16_Animal_Behavior/deeplabcut/references/maDLC.md +123 -0
- package/skills/16_Animal_Behavior/deeplabcut/references/modelzoo.md +98 -0
- package/skills/16_Animal_Behavior/deeplabcut/references/standard-pipeline.md +165 -0
- package/skills/16_Animal_Behavior/deeplabcut/references/utilities.md +146 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/SKILL.md +274 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/report_template_en.html +112 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/report_template_en.md +21 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/cluster-section.md +5 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/heatmap-section.md +5 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/integrated-interpretation.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/overview.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/project-summary.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/radar-section.md +5 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/raw-trajectory.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/sample-check.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/single-subject-section.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/stats-section.md +5 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/epm.md +52 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/fst.md +37 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/nor.md +39 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/oft.md +43 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/tcst.md +45 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/tst.md +36 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/input-types.md +59 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/interpretation-guardrails.md +45 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/metadata-schema.md +57 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/report-sections.md +86 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/section-selection-rules.md +169 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/scripts/build_report_manifest.py +27 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/scripts/render_report.py +34 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/scripts/report_utils.py +1121 -0
- package/skills/16_Animal_Behavior/ethoclaw-animal-grounding/SKILL.md +390 -0
- package/skills/16_Animal_Behavior/ethoclaw-animal-grounding/reference_code.py +98 -0
- package/skills/16_Animal_Behavior/ethoclaw-animal-pose-estimation/SKILL.md +336 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/README.md +21 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/SKILL.md +41 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/batch_kinematic_generator.py +663 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/config.json +19 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/generate_kinematic_parameter.py +401 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/kinematic_generator.py +265 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/SKILL.md +72 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/references/config.example.toml +56 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/scripts/cluster_all_params.py +232 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/scripts/cluster_all_params_from_config.py +236 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-radar-generate/SKILL.md +68 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-radar-generate/references/notes.md +5 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-radar-generate/scripts/plot_h5_radar.py +513 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/SKILL.md +52 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/config.toml +81 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/references/stats-rule.md +18 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/scripts/h5_inspect.py +79 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/scripts/h5_violin_batch.py +624 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/scripts/h5_violin_stats.py +438 -0
- package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/SKILL.md +280 -0
- package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/core_scripts/heatmap_trajectory.py +790 -0
- package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/core_scripts/heatmap_velocity.py +855 -0
- package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/reference_data/reference_2d.csv +101 -0
- package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/reference_data/reference_2d.h5 +0 -0
- package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/reference_data/reference_data_readme.md +126 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nsd-skill
|
|
3
|
+
description: "Use this skill whenever the user wants an end-to-end workflow for the Natural Scenes Dataset (NSD), including data access, BIDS validation, multimodal processing of task-fMRI and structural MRI, stimulus metadata extraction, and QC integration. Triggers include: 'NSD', 'Natural Scenes Dataset', 'process NSD data', 'NSD fMRI', 'visual neuroscience', or any request to run the NSD multimodal pipeline."
|
|
4
|
+
license: MIT License (NeuroClaw custom skill - freely modifiable within the project)
|
|
5
|
+
layer: subagent
|
|
6
|
+
skill_type: dataset
|
|
7
|
+
dependencies:
|
|
8
|
+
- smri-skill
|
|
9
|
+
- fmri-skill
|
|
10
|
+
- bids-organizer
|
|
11
|
+
- claw-shell
|
|
12
|
+
complementary_skills:
|
|
13
|
+
- brain-visualization
|
|
14
|
+
- nibabel-skill
|
|
15
|
+
---
|
|
16
|
+
# NSD Skill (Dataset-Orchestration Layer)
|
|
17
|
+
|
|
18
|
+
## Overview
|
|
19
|
+
|
|
20
|
+
`nsd-skill` is the NeuroClaw orchestration skill for the **Natural Scenes Dataset (NSD)**.
|
|
21
|
+
|
|
22
|
+
It strictly follows the NeuroClaw hierarchical design principles:
|
|
23
|
+
- This skill **only describes WHAT needs to be done** and **which tool skill to delegate to**.
|
|
24
|
+
- It contains **no implementation code or concrete commands**.
|
|
25
|
+
- All concrete execution is delegated to existing base/tool skills via `claw-shell`.
|
|
26
|
+
- Companion scripts in `scripts/` provide reference implementations for BIDS validation, stimulus extraction, and QC.
|
|
27
|
+
|
|
28
|
+
**Core workflow (never bypassed):**
|
|
29
|
+
1. Identify input NSD data and target modalities.
|
|
30
|
+
2. Generate a **numbered execution plan** clearly stating WHAT needs to be done and which tool skill will handle each step.
|
|
31
|
+
3. Present the full plan, estimated runtime, resource requirements, and risks to the user and wait for explicit confirmation ("YES" / "execute" / "proceed").
|
|
32
|
+
4. On confirmation, delegate every step to the appropriate skill via `claw-shell`.
|
|
33
|
+
5. After execution, save all outputs in a clean directory structure (`nsd_output/`).
|
|
34
|
+
|
|
35
|
+
**Research use only.**
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Quick Reference
|
|
40
|
+
|
|
41
|
+
| Task | What needs to be done | Delegate to | Expected output |
|
|
42
|
+
|---|---|---|---|
|
|
43
|
+
| BIDS validation | Validate NSD BIDS structure | `scripts/validate_nsd.py` | Validation report |
|
|
44
|
+
| sMRI processing | Brain extraction, tissue segmentation | `smri-skill` | `smri_output/` derivatives |
|
|
45
|
+
| task-fMRI processing | Visual task GLM, voxel-wise encoding | `fmri-skill` | `fmri_output/` task results |
|
|
46
|
+
| Stimulus extraction | COCO image metadata, annotations | `scripts/extract_nsd_stimulus.py` | Stimulus metadata CSV |
|
|
47
|
+
| QC summary | Per-subject quality control | `scripts/nsd_qc_summary.py` | QC summary + exclusion list |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Dataset Characteristics
|
|
52
|
+
|
|
53
|
+
- **Cohort**: 8 healthy adults (subj01-subj08)
|
|
54
|
+
- **Scanner**: 7T Siemens MAGNETOM
|
|
55
|
+
- **Resolution**: 1.8mm isotropic voxels
|
|
56
|
+
- **Sessions**: ~30-40 scanning sessions per subject
|
|
57
|
+
- **Total fMRI**: ~30 hours per subject
|
|
58
|
+
- **Stimuli**: ~73,000 natural scene images from COCO dataset
|
|
59
|
+
- **Access**: OSF (Open Science Framework) and Amazon S3
|
|
60
|
+
- **Reference**: Allen et al. (2021), Nature Neuroscience
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Supported Modalities
|
|
65
|
+
|
|
66
|
+
| Modality | Description | Details |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| T1w | High-resolution structural MRI | 7T anatomical scans |
|
|
69
|
+
| task-fMRI | Visual task fMRI | Natural scene viewing with fixation task |
|
|
70
|
+
| dMRI | Diffusion-weighted imaging | White matter tractography |
|
|
71
|
+
| Retinotopy | Retinotopic mapping | Visual area identification |
|
|
72
|
+
| Eye-tracking | Gaze position data | During image viewing |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## NSD Task Paradigms
|
|
77
|
+
|
|
78
|
+
| Task | Description | Duration |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| NSD | Natural scene viewing (COCO images) | ~30-40 sessions × ~15 min each |
|
|
81
|
+
| FIXATION | Fixation task during image presentation | Continuous |
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## COCO Stimulus Metadata
|
|
86
|
+
|
|
87
|
+
The NSD uses images from the COCO (Common Objects in Context) dataset:
|
|
88
|
+
- ~73,000 unique natural scene images
|
|
89
|
+
- Each image has: 5 captions, 80 object categories, segmentation masks
|
|
90
|
+
- Images are presented for 3 seconds each
|
|
91
|
+
- Subjects perform a fixation task (detect image repeat)
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## BIDS Preparation
|
|
96
|
+
|
|
97
|
+
### Script: `scripts/validate_nsd.py`
|
|
98
|
+
|
|
99
|
+
Validates NSD BIDS structure and generates a compliance report.
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
python skills/nsd-skill/scripts/validate_nsd.py \
|
|
103
|
+
--input /path/to/NSD/bids \
|
|
104
|
+
--output /path/to/nsd_output/qc/bids_validation.csv
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Features:
|
|
108
|
+
- BIDS directory structure validation
|
|
109
|
+
- Subject completeness check (8 subjects)
|
|
110
|
+
- Session count validation (~30-40 sessions per subject)
|
|
111
|
+
- Stimulus file presence verification
|
|
112
|
+
- Missing data identification
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Core Workflow (Never Bypassed)
|
|
117
|
+
|
|
118
|
+
1. Identify user target: full NSD processing, imaging subset, stimulus extraction, or BIDS validation only.
|
|
119
|
+
2. Generate a numbered plan with tools, outputs, runtime, storage, and risks.
|
|
120
|
+
3. Wait for explicit confirmation (`YES` / `execute` / `proceed`).
|
|
121
|
+
4. On confirmation, run BIDS validation using `scripts/validate_nsd.py`.
|
|
122
|
+
5. Delegate to `smri-skill` for structural MRI processing.
|
|
123
|
+
6. Delegate to `fmri-skill` for task-fMRI processing (natural scene viewing).
|
|
124
|
+
7. If stimulus extraction is requested, run `scripts/extract_nsd_stimulus.py`.
|
|
125
|
+
8. If QC summary is requested, run `scripts/nsd_qc_summary.py`.
|
|
126
|
+
9. Save outputs into `nsd_output/`.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Modality Processing Delegation
|
|
131
|
+
|
|
132
|
+
| Modality | Delegated skill | Typical tasks | Main outputs |
|
|
133
|
+
|---|---|---|---|
|
|
134
|
+
| sMRI (T1w) | `smri-skill` | brain extraction, tissue segmentation, cortical reconstruction | `smri_output/` derivatives |
|
|
135
|
+
| task-fMRI | `fmri-skill` | preprocessing, denoising, voxel-wise encoding | `fmri_output/` task results |
|
|
136
|
+
| dMRI | `fmri-skill` | diffusion preprocessing, tensor metrics | `dwi_output/` metrics |
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Standard Output Layout
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
nsd_output/
|
|
144
|
+
├── bids/ # BIDS-staged data (or validation report)
|
|
145
|
+
├── smri/ # Structural MRI derivatives
|
|
146
|
+
├── fmri/ # Functional MRI derivatives (natural scene viewing)
|
|
147
|
+
├── stimulus/ # COCO stimulus metadata
|
|
148
|
+
├── qc/ # QC summaries and exclusion lists
|
|
149
|
+
└── logs/ # Processing logs
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Benchmark Adapter Guidance
|
|
155
|
+
|
|
156
|
+
For benchmark-style prompts, do not force the full orchestration when the task only asks for local NSD data validation.
|
|
157
|
+
|
|
158
|
+
- If the task starts from NSD data already present on disk and only asks for BIDS validation:
|
|
159
|
+
- Skip the download stage
|
|
160
|
+
- Default to the narrow path `local NSD discovery -> BIDS validation -> report`
|
|
161
|
+
- In benchmark mode, do not require explicit confirmation before presenting the validation solution.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Safety and Execution Policy
|
|
166
|
+
- No execution before explicit plan confirmation.
|
|
167
|
+
- All execution must be routed via `claw-shell`.
|
|
168
|
+
- Missing dependencies must be resolved by `dependency-planner` before running.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Important Notes and Limitations
|
|
173
|
+
- NSD is a high-resolution 7T dataset; processing requires significant compute resources.
|
|
174
|
+
- 8 subjects with dense repeated measures (~30 hours of fMRI each).
|
|
175
|
+
- Visual neuroscience focus: standard task GLM may not apply; consider voxel-wise encoding models.
|
|
176
|
+
- COCO stimulus metadata is essential for stimulus-response analyses.
|
|
177
|
+
- Cortical surface-based representations using FreeSurfer outputs.
|
|
178
|
+
- `nsd-skill` is orchestration-only; detailed preprocessing logic remains in modality skills.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## When to Call This Skill
|
|
183
|
+
- User asks for end-to-end NSD workflow.
|
|
184
|
+
- User asks to process NSD task-fMRI data.
|
|
185
|
+
- User needs BIDS validation for NSD data.
|
|
186
|
+
- User asks to extract NSD stimulus metadata (COCO images, captions, categories).
|
|
187
|
+
- User asks for visual cortex analysis or voxel-wise encoding.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Complementary / Related Skills
|
|
192
|
+
- `smri-skill` → structural MRI preprocessing
|
|
193
|
+
- `fmri-skill` → functional MRI preprocessing and analysis
|
|
194
|
+
- `nibabel-skill` → NIfTI I/O and surface data
|
|
195
|
+
- `bids-organizer` → BIDS validation and organization
|
|
196
|
+
- `brain-visualization` → visualization of derivatives
|
|
197
|
+
- `dependency-planner` → dependency resolution
|
|
198
|
+
- `conda-env-manager` → environment management
|
|
199
|
+
- `claw-shell` → command execution
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Reference
|
|
204
|
+
- NSD: https://naturalscenesdataset.org/
|
|
205
|
+
- Allen et al. (2021): A massive 7T fMRI dataset to bridge cognitive neuroscience and artificial intelligence. Nature Neuroscience.
|
|
206
|
+
- COCO: https://cocodataset.org/
|
|
207
|
+
|
|
208
|
+
Created At: 2026-05-06 13:31 HKT
|
|
209
|
+
Last Updated At: 2026-05-06 13:31 HKT
|
|
210
|
+
Author: chengwang96
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Extract NSD stimulus metadata from COCO annotations.
|
|
3
|
+
|
|
4
|
+
Reads NSD stimulus information (COCO image IDs, captions, categories)
|
|
5
|
+
and produces a merged stimulus metadata table for stimulus-response analyses.
|
|
6
|
+
"""
|
|
7
|
+
import argparse
|
|
8
|
+
import csv
|
|
9
|
+
import json
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Dict, List, Optional
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def load_nsd_stimulus_info(stimulus_dir: Path) -> List[Dict]:
|
|
16
|
+
"""Load NSD stimulus info from nsd_stiminfo.tsv or equivalent."""
|
|
17
|
+
stim_info = []
|
|
18
|
+
stim_file = stimulus_dir / "nsd_stiminfo.tsv"
|
|
19
|
+
if stim_file.exists():
|
|
20
|
+
with open(stim_file, "r", encoding="utf-8") as f:
|
|
21
|
+
reader = csv.DictReader(f, delimiter="\t")
|
|
22
|
+
stim_info = list(reader)
|
|
23
|
+
return stim_info
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def load_coco_annotations(coco_dir: Path) -> Dict[int, Dict]:
|
|
27
|
+
"""Load COCO annotations (captions + categories) keyed by image_id."""
|
|
28
|
+
coco_data = {}
|
|
29
|
+
|
|
30
|
+
# Load captions
|
|
31
|
+
captions_file = coco_dir / "annotations" / "captions_train2017.json"
|
|
32
|
+
if captions_file.exists():
|
|
33
|
+
with open(captions_file, "r", encoding="utf-8") as f:
|
|
34
|
+
caps = json.load(f)
|
|
35
|
+
for ann in caps.get("annotations", []):
|
|
36
|
+
img_id = ann["image_id"]
|
|
37
|
+
if img_id not in coco_data:
|
|
38
|
+
coco_data[img_id] = {"captions": [], "categories": []}
|
|
39
|
+
coco_data[img_id]["captions"].append(ann["caption"])
|
|
40
|
+
|
|
41
|
+
# Load instances (categories)
|
|
42
|
+
instances_file = coco_dir / "annotations" / "instances_train2017.json"
|
|
43
|
+
if instances_file.exists():
|
|
44
|
+
with open(instances_file, "r", encoding="utf-8") as f:
|
|
45
|
+
instances = json.load(f)
|
|
46
|
+
# Build category id -> name map
|
|
47
|
+
cat_map = {c["id"]: c["name"] for c in instances.get("categories", [])}
|
|
48
|
+
for ann in instances.get("annotations", []):
|
|
49
|
+
img_id = ann["image_id"]
|
|
50
|
+
if img_id not in coco_data:
|
|
51
|
+
coco_data[img_id] = {"captions": [], "categories": []}
|
|
52
|
+
cat_name = cat_map.get(ann["category_id"], "unknown")
|
|
53
|
+
if cat_name not in coco_data[img_id]["categories"]:
|
|
54
|
+
coco_data[img_id]["categories"].append(cat_name)
|
|
55
|
+
|
|
56
|
+
return coco_data
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def load_subject_trials(events_dir: Path, subject: str) -> List[Dict]:
|
|
60
|
+
"""Load trial-level stimulus info from a subject's events files."""
|
|
61
|
+
trials = []
|
|
62
|
+
pattern = f"{subject}_task-nsd*_events.tsv"
|
|
63
|
+
for events_file in sorted(events_dir.glob(pattern)):
|
|
64
|
+
with open(events_file, "r", encoding="utf-8") as f:
|
|
65
|
+
reader = csv.DictReader(f, delimiter="\t")
|
|
66
|
+
for row in reader:
|
|
67
|
+
row["_source_file"] = events_file.name
|
|
68
|
+
trials.append(row)
|
|
69
|
+
return trials
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def main() -> int:
|
|
73
|
+
parser = argparse.ArgumentParser(
|
|
74
|
+
description="Extract NSD stimulus metadata from COCO annotations."
|
|
75
|
+
)
|
|
76
|
+
parser.add_argument("--nsd-dir", required=True,
|
|
77
|
+
help="Path to NSD root directory (BIDS format)")
|
|
78
|
+
parser.add_argument("--coco-dir",
|
|
79
|
+
help="Path to COCO annotations directory (optional)")
|
|
80
|
+
parser.add_argument("--output", required=True,
|
|
81
|
+
help="Output path for stimulus metadata CSV")
|
|
82
|
+
parser.add_argument("--subject", default=None,
|
|
83
|
+
help="Extract for specific subject only (e.g., subj01)")
|
|
84
|
+
args = parser.parse_args()
|
|
85
|
+
|
|
86
|
+
nsd_dir = Path(args.nsd_dir).resolve()
|
|
87
|
+
if not nsd_dir.exists():
|
|
88
|
+
print(f"NSD directory not found: {nsd_dir}", file=sys.stderr)
|
|
89
|
+
return 1
|
|
90
|
+
|
|
91
|
+
output_path = Path(args.output).resolve()
|
|
92
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
93
|
+
|
|
94
|
+
# Load NSD stimulus info
|
|
95
|
+
stim_info = load_nsd_stimulus_info(nsd_dir)
|
|
96
|
+
print(f"Loaded {len(stim_info)} stimulus entries from nsd_stiminfo.tsv")
|
|
97
|
+
|
|
98
|
+
# Load COCO annotations if available
|
|
99
|
+
coco_data = {}
|
|
100
|
+
if args.coco_dir:
|
|
101
|
+
coco_dir = Path(args.coco_dir).resolve()
|
|
102
|
+
if coco_dir.exists():
|
|
103
|
+
coco_data = load_coco_annotations(coco_dir)
|
|
104
|
+
print(f"Loaded COCO annotations for {len(coco_data)} images")
|
|
105
|
+
|
|
106
|
+
# Determine subjects to process
|
|
107
|
+
if args.subject:
|
|
108
|
+
subjects = [args.subject]
|
|
109
|
+
else:
|
|
110
|
+
subjects = sorted([
|
|
111
|
+
d.name for d in nsd_dir.glob("sub-*") if d.is_dir()
|
|
112
|
+
])
|
|
113
|
+
|
|
114
|
+
# Collect trial-level data
|
|
115
|
+
all_trials = []
|
|
116
|
+
for subj in subjects:
|
|
117
|
+
subj_dir = nsd_dir / subj / "func"
|
|
118
|
+
if not subj_dir.exists():
|
|
119
|
+
continue
|
|
120
|
+
trials = load_subject_trials(subj_dir, subj)
|
|
121
|
+
for t in trials:
|
|
122
|
+
t["subject_id"] = subj
|
|
123
|
+
all_trials.extend(trials)
|
|
124
|
+
|
|
125
|
+
# Merge stimulus info with trials
|
|
126
|
+
if stim_info and all_trials:
|
|
127
|
+
# Build lookup by stimulus index if available
|
|
128
|
+
stim_lookup = {}
|
|
129
|
+
for s in stim_info:
|
|
130
|
+
key = s.get("nsd_id") or s.get("stimulus_id") or s.get("0", "")
|
|
131
|
+
if key:
|
|
132
|
+
stim_lookup[str(key)] = s
|
|
133
|
+
|
|
134
|
+
for trial in all_trials:
|
|
135
|
+
stim_idx = trial.get("stimulus_index") or trial.get("stim_id", "")
|
|
136
|
+
if stim_idx and str(stim_idx) in stim_lookup:
|
|
137
|
+
for k, v in stim_lookup[str(stim_idx)].items():
|
|
138
|
+
if k not in trial:
|
|
139
|
+
trial[f"stim_{k}"] = v
|
|
140
|
+
|
|
141
|
+
# Enrich with COCO data if available
|
|
142
|
+
if coco_data and all_trials:
|
|
143
|
+
for trial in all_trials:
|
|
144
|
+
coco_id = trial.get("coco_id") or trial.get("stim_coco_id", "")
|
|
145
|
+
if coco_id and str(coco_id).isdigit():
|
|
146
|
+
cid = int(coco_id)
|
|
147
|
+
if cid in coco_data:
|
|
148
|
+
trial["coco_captions"] = " | ".join(coco_data[cid]["captions"][:3])
|
|
149
|
+
trial["coco_categories"] = ", ".join(coco_data[cid]["categories"])
|
|
150
|
+
|
|
151
|
+
# Output
|
|
152
|
+
if not all_trials and stim_info:
|
|
153
|
+
# Fallback: output stim_info directly
|
|
154
|
+
all_trials = stim_info
|
|
155
|
+
|
|
156
|
+
if not all_trials:
|
|
157
|
+
print("[WARN] No stimulus data found.", file=sys.stderr)
|
|
158
|
+
return 1
|
|
159
|
+
|
|
160
|
+
fieldnames = list(all_trials[0].keys())
|
|
161
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
162
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
163
|
+
writer.writeheader()
|
|
164
|
+
writer.writerows(all_trials)
|
|
165
|
+
|
|
166
|
+
print(f"Stimulus: {len(all_trials)} trials, {len(fieldnames)} columns -> {output_path}")
|
|
167
|
+
return 0
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
if __name__ == "__main__":
|
|
171
|
+
sys.exit(main())
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Generate per-subject QC summaries for NSD processing.
|
|
3
|
+
|
|
4
|
+
7T-specific QC: tracks session counts, motion metrics, and stimulus coverage.
|
|
5
|
+
"""
|
|
6
|
+
import argparse
|
|
7
|
+
import csv
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Dict, List
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def load_confounds(confounds_path: Path) -> Dict[str, float]:
|
|
14
|
+
"""Extract QC metrics from fMRIPrep confounds TSV."""
|
|
15
|
+
metrics = {
|
|
16
|
+
"fd_mean": float("nan"),
|
|
17
|
+
"fd_max": float("nan"),
|
|
18
|
+
"dvars_mean": float("nan"),
|
|
19
|
+
}
|
|
20
|
+
try:
|
|
21
|
+
import pandas as pd
|
|
22
|
+
df = pd.read_csv(confounds_path, sep="\t")
|
|
23
|
+
if "framewise_displacement" in df.columns:
|
|
24
|
+
fd = df["framewise_displacement"].dropna()
|
|
25
|
+
metrics["fd_mean"] = float(fd.mean())
|
|
26
|
+
metrics["fd_max"] = float(fd.max())
|
|
27
|
+
if "dvars" in df.columns:
|
|
28
|
+
dvars = df["dvars"].dropna()
|
|
29
|
+
metrics["dvars_mean"] = float(dvars.mean())
|
|
30
|
+
except Exception:
|
|
31
|
+
pass
|
|
32
|
+
return metrics
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def check_exclusion(metrics: Dict[str, float], fd_threshold: float = 0.3) -> List[str]:
|
|
36
|
+
"""Check exclusion criteria for NSD."""
|
|
37
|
+
reasons = []
|
|
38
|
+
if not (metrics["fd_mean"] != metrics["fd_mean"]): # not NaN
|
|
39
|
+
if metrics["fd_mean"] > fd_threshold:
|
|
40
|
+
reasons.append(f"FD mean {metrics['fd_mean']:.3f} > {fd_threshold}")
|
|
41
|
+
return reasons
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def main() -> int:
|
|
45
|
+
parser = argparse.ArgumentParser(
|
|
46
|
+
description="Generate QC summaries for NSD processing."
|
|
47
|
+
)
|
|
48
|
+
parser.add_argument("--fmriprep-dir", help="Path to fMRIPrep output directory")
|
|
49
|
+
parser.add_argument("--nsd-dir", help="Path to NSD BIDS root directory")
|
|
50
|
+
parser.add_argument("--output", required=True, help="Output path for QC summary CSV")
|
|
51
|
+
parser.add_argument("--exclude-output", help="Output path for exclusion list CSV")
|
|
52
|
+
parser.add_argument("--fd-threshold", type=float, default=0.3,
|
|
53
|
+
help="FD threshold in mm (default: 0.3, typical for 7T)")
|
|
54
|
+
args = parser.parse_args()
|
|
55
|
+
|
|
56
|
+
output_path = Path(args.output).resolve()
|
|
57
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
58
|
+
|
|
59
|
+
# Discover subjects
|
|
60
|
+
subjects = set()
|
|
61
|
+
if args.fmriprep_dir:
|
|
62
|
+
fmriprep_dir = Path(args.fmriprep_dir).resolve()
|
|
63
|
+
if fmriprep_dir.exists():
|
|
64
|
+
for d in fmriprep_dir.glob("sub-*"):
|
|
65
|
+
if d.is_dir():
|
|
66
|
+
subjects.add(d.name)
|
|
67
|
+
if args.nsd_dir:
|
|
68
|
+
nsd_dir = Path(args.nsd_dir).resolve()
|
|
69
|
+
if nsd_dir.exists():
|
|
70
|
+
for d in nsd_dir.glob("sub-*"):
|
|
71
|
+
if d.is_dir():
|
|
72
|
+
subjects.add(d.name)
|
|
73
|
+
|
|
74
|
+
if not subjects:
|
|
75
|
+
print("[WARN] No subjects found.", file=sys.stderr)
|
|
76
|
+
return 1
|
|
77
|
+
|
|
78
|
+
results = []
|
|
79
|
+
excluded = []
|
|
80
|
+
for subj in sorted(subjects):
|
|
81
|
+
metrics = {"subject_id": subj}
|
|
82
|
+
|
|
83
|
+
# Count sessions from BIDS structure
|
|
84
|
+
if args.nsd_dir:
|
|
85
|
+
nsd_dir = Path(args.nsd_dir).resolve()
|
|
86
|
+
subj_dir = nsd_dir / subj
|
|
87
|
+
if subj_dir.exists():
|
|
88
|
+
sessions = [d for d in subj_dir.glob("ses-*") if d.is_dir()]
|
|
89
|
+
metrics["n_sessions"] = len(sessions)
|
|
90
|
+
func_dir = subj_dir / "func"
|
|
91
|
+
if func_dir.exists():
|
|
92
|
+
bold_runs = list(func_dir.glob("*_task-nsd_bold.nii.gz"))
|
|
93
|
+
metrics["n_func_runs"] = len(bold_runs)
|
|
94
|
+
|
|
95
|
+
# Extract fMRIPrep confounds metrics
|
|
96
|
+
if args.fmriprep_dir:
|
|
97
|
+
confounds_files = list(
|
|
98
|
+
Path(args.fmriprep_dir).glob(f"{subj}/func/*_desc-confounds_timeseries.tsv")
|
|
99
|
+
)
|
|
100
|
+
if confounds_files:
|
|
101
|
+
# Average across runs
|
|
102
|
+
fd_means = []
|
|
103
|
+
fd_maxes = []
|
|
104
|
+
for cf in confounds_files:
|
|
105
|
+
run_metrics = load_confounds(cf)
|
|
106
|
+
if run_metrics["fd_mean"] == run_metrics["fd_mean"]: # not NaN
|
|
107
|
+
fd_means.append(run_metrics["fd_mean"])
|
|
108
|
+
fd_maxes.append(run_metrics["fd_max"])
|
|
109
|
+
if fd_means:
|
|
110
|
+
metrics["fd_mean"] = sum(fd_means) / len(fd_means)
|
|
111
|
+
metrics["fd_max"] = max(fd_maxes)
|
|
112
|
+
metrics["n_confounds_files"] = len(confounds_files)
|
|
113
|
+
|
|
114
|
+
exclusion_reasons = check_exclusion(metrics, args.fd_threshold)
|
|
115
|
+
metrics["excluded"] = len(exclusion_reasons) > 0
|
|
116
|
+
metrics["exclusion_reasons"] = "; ".join(exclusion_reasons)
|
|
117
|
+
|
|
118
|
+
results.append(metrics)
|
|
119
|
+
if exclusion_reasons:
|
|
120
|
+
excluded.append({"subject_id": subj, "reasons": "; ".join(exclusion_reasons)})
|
|
121
|
+
|
|
122
|
+
if results:
|
|
123
|
+
fieldnames = list(results[0].keys())
|
|
124
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
125
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
126
|
+
writer.writeheader()
|
|
127
|
+
writer.writerows(results)
|
|
128
|
+
print(f"QC: {len(results)} subjects, {len(excluded)} excluded -> {output_path}")
|
|
129
|
+
|
|
130
|
+
if args.exclude_output and excluded:
|
|
131
|
+
exclude_path = Path(args.exclude_output).resolve()
|
|
132
|
+
exclude_path.parent.mkdir(parents=True, exist_ok=True)
|
|
133
|
+
with open(exclude_path, "w", newline="", encoding="utf-8") as f:
|
|
134
|
+
writer = csv.DictWriter(f, fieldnames=["subject_id", "reasons"])
|
|
135
|
+
writer.writeheader()
|
|
136
|
+
writer.writerows(excluded)
|
|
137
|
+
|
|
138
|
+
return 0
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
if __name__ == "__main__":
|
|
142
|
+
sys.exit(main())
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Validate NSD BIDS structure and generate compliance report.
|
|
3
|
+
|
|
4
|
+
Checks directory structure, subject completeness, session counts,
|
|
5
|
+
and stimulus file presence for the Natural Scenes Dataset.
|
|
6
|
+
"""
|
|
7
|
+
import argparse
|
|
8
|
+
import csv
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Dict, List
|
|
12
|
+
|
|
13
|
+
# NSD expected subjects
|
|
14
|
+
NSD_SUBJECTS = [f"subj0{i}" for i in range(1, 9)] # subj01-subj08
|
|
15
|
+
|
|
16
|
+
# Expected modalities per subject
|
|
17
|
+
EXPECTED_MODALITIES = {
|
|
18
|
+
"func": ["task-nsd_bold"],
|
|
19
|
+
"anat": ["T1w"],
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def validate_subject(subject_dir: Path) -> Dict[str, any]:
|
|
24
|
+
"""Validate a single subject's NSD BIDS structure."""
|
|
25
|
+
report = {
|
|
26
|
+
"subject": subject_dir.name,
|
|
27
|
+
"anat_complete": False,
|
|
28
|
+
"func_complete": False,
|
|
29
|
+
"n_sessions": 0,
|
|
30
|
+
"n_func_runs": 0,
|
|
31
|
+
"stimulus_present": False,
|
|
32
|
+
"missing_files": [],
|
|
33
|
+
"warnings": [],
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Check anat
|
|
37
|
+
anat_dir = subject_dir / "anat"
|
|
38
|
+
if anat_dir.exists():
|
|
39
|
+
t1w_files = list(anat_dir.glob("*_T1w.nii.gz"))
|
|
40
|
+
report["anat_complete"] = len(t1w_files) > 0
|
|
41
|
+
if not t1w_files:
|
|
42
|
+
report["missing_files"].append("anat/*_T1w.nii.gz")
|
|
43
|
+
else:
|
|
44
|
+
report["missing_files"].append("anat/")
|
|
45
|
+
|
|
46
|
+
# Check func
|
|
47
|
+
func_dir = subject_dir / "func"
|
|
48
|
+
if func_dir.exists():
|
|
49
|
+
bold_files = list(func_dir.glob("*_task-nsd_bold.nii.gz"))
|
|
50
|
+
report["n_func_runs"] = len(bold_files)
|
|
51
|
+
report["func_complete"] = len(bold_files) > 0
|
|
52
|
+
|
|
53
|
+
# Count unique sessions from filenames
|
|
54
|
+
sessions = set()
|
|
55
|
+
for f in bold_files:
|
|
56
|
+
parts = f.name.split("_")
|
|
57
|
+
for p in parts:
|
|
58
|
+
if p.startswith("ses-"):
|
|
59
|
+
sessions.add(p)
|
|
60
|
+
report["n_sessions"] = len(sessions)
|
|
61
|
+
|
|
62
|
+
if not bold_files:
|
|
63
|
+
report["missing_files"].append("func/*_task-nsd_bold.nii.gz")
|
|
64
|
+
else:
|
|
65
|
+
report["missing_files"].append("func/")
|
|
66
|
+
|
|
67
|
+
# Check stimulus files
|
|
68
|
+
stim_dir = subject_dir / "func"
|
|
69
|
+
if stim_dir.exists():
|
|
70
|
+
stim_files = list(stim_dir.glob("*_events.tsv"))
|
|
71
|
+
report["stimulus_present"] = len(stim_files) > 0
|
|
72
|
+
|
|
73
|
+
# Warnings for session count
|
|
74
|
+
if report["n_sessions"] > 0 and report["n_sessions"] < 30:
|
|
75
|
+
report["warnings"].append(
|
|
76
|
+
f"Only {report['n_sessions']} sessions found (expected ~30-40)"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return report
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def main() -> int:
|
|
83
|
+
parser = argparse.ArgumentParser(
|
|
84
|
+
description="Validate NSD BIDS structure."
|
|
85
|
+
)
|
|
86
|
+
parser.add_argument("--input", required=True, help="Path to NSD BIDS directory")
|
|
87
|
+
parser.add_argument("--output", required=True, help="Output path for validation CSV")
|
|
88
|
+
args = parser.parse_args()
|
|
89
|
+
|
|
90
|
+
input_dir = Path(args.input).resolve()
|
|
91
|
+
if not input_dir.exists():
|
|
92
|
+
print(f"Input directory not found: {input_dir}", file=sys.stderr)
|
|
93
|
+
return 1
|
|
94
|
+
|
|
95
|
+
# Find subjects
|
|
96
|
+
subjects = sorted([d for d in input_dir.glob("sub-*") if d.is_dir()])
|
|
97
|
+
print(f"Found {len(subjects)} subjects in {input_dir}")
|
|
98
|
+
|
|
99
|
+
if not subjects:
|
|
100
|
+
print("[ERROR] No subjects found.", file=sys.stderr)
|
|
101
|
+
return 1
|
|
102
|
+
|
|
103
|
+
# Validate each subject
|
|
104
|
+
results = []
|
|
105
|
+
for sub_dir in subjects:
|
|
106
|
+
report = validate_subject(sub_dir)
|
|
107
|
+
results.append(report)
|
|
108
|
+
|
|
109
|
+
# Write output
|
|
110
|
+
output_path = Path(args.output).resolve()
|
|
111
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
112
|
+
|
|
113
|
+
fieldnames = [
|
|
114
|
+
"subject", "anat_complete", "func_complete",
|
|
115
|
+
"n_sessions", "n_func_runs", "stimulus_present",
|
|
116
|
+
"missing_files", "warnings",
|
|
117
|
+
]
|
|
118
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
119
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
120
|
+
writer.writeheader()
|
|
121
|
+
for r in results:
|
|
122
|
+
r["missing_files"] = "; ".join(r["missing_files"])
|
|
123
|
+
r["warnings"] = "; ".join(r["warnings"])
|
|
124
|
+
writer.writerow(r)
|
|
125
|
+
|
|
126
|
+
# Summary
|
|
127
|
+
complete_subjects = sum(1 for r in results if r["anat_complete"] and r["func_complete"])
|
|
128
|
+
print(f"\nValidation Summary:")
|
|
129
|
+
print(f" Total subjects: {len(results)}")
|
|
130
|
+
print(f" Complete (anat + func): {complete_subjects}")
|
|
131
|
+
print(f" With T1w: {sum(1 for r in results if r['anat_complete'])}")
|
|
132
|
+
print(f" With task-fMRI: {sum(1 for r in results if r['func_complete'])}")
|
|
133
|
+
print(f" With stimulus events: {sum(1 for r in results if r['stimulus_present'])}")
|
|
134
|
+
total_runs = sum(r['n_func_runs'] for r in results)
|
|
135
|
+
print(f" Total fMRI runs: {total_runs}")
|
|
136
|
+
print(f" Output: {output_path}")
|
|
137
|
+
|
|
138
|
+
return 0
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
if __name__ == "__main__":
|
|
142
|
+
sys.exit(main())
|