@brainpilot/skills 0.0.6 → 0.0.8
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,145 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Extract and merge Cam-CAN phenotype data.
|
|
3
|
+
|
|
4
|
+
Reads Cam-CAN phenotype files (cognitive, sensory, health measures)
|
|
5
|
+
and produces a merged phenotype table aligned with imaging subject list.
|
|
6
|
+
"""
|
|
7
|
+
import argparse
|
|
8
|
+
import csv
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Dict, List, Optional
|
|
12
|
+
|
|
13
|
+
# Column mapping for Cam-CAN phenotype data
|
|
14
|
+
COLUMN_MAP = {
|
|
15
|
+
"subject_id": ["subject", "Subject", "participant_id", "SubID"],
|
|
16
|
+
"age": ["age", "Age", "Age_in_Yrs"],
|
|
17
|
+
"sex": ["sex", "Sex", "Gender"],
|
|
18
|
+
"handedness": ["handedness", "Handedness"],
|
|
19
|
+
# Cognitive measures
|
|
20
|
+
"picture_vocab": ["PictureVocab", "picture_vocab_score"],
|
|
21
|
+
"card_sorting": ["CardSort", "card_sorting_score"],
|
|
22
|
+
"flanker": ["Flanker", "flanker_score"],
|
|
23
|
+
"list_sorting": ["ListSort", "list_sorting_score"],
|
|
24
|
+
"pattern_comparison": ["PatternComp", "pattern_comparison_score"],
|
|
25
|
+
"picture_sequence": ["PictureSeq", "picture_sequence_score"],
|
|
26
|
+
"reading": ["Reading", "reading_score"],
|
|
27
|
+
# Sensory measures
|
|
28
|
+
"hearing": ["Hearing", "hearing_threshold"],
|
|
29
|
+
"vision": ["Vision", "vision_acuity"],
|
|
30
|
+
# Health measures
|
|
31
|
+
"mmse": ["MMSE", "mmse_score"],
|
|
32
|
+
"moca": ["MOCA", "moca_score"],
|
|
33
|
+
# Grip strength
|
|
34
|
+
"grip_strength_left": ["GripLeft", "grip_strength_left"],
|
|
35
|
+
"grip_strength_right": ["GripRight", "grip_strength_right"],
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def load_csv(path: Path) -> List[Dict[str, str]]:
|
|
40
|
+
"""Load CSV/TSV file and return list of dicts."""
|
|
41
|
+
delimiter = "\t" if path.suffix == ".tsv" else ","
|
|
42
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
43
|
+
reader = csv.DictReader(f, delimiter=delimiter)
|
|
44
|
+
return list(reader)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def find_column(row: Dict[str, str], candidates: List[str]) -> Optional[str]:
|
|
48
|
+
"""Find the first matching column name in a row."""
|
|
49
|
+
for col in candidates:
|
|
50
|
+
if col in row:
|
|
51
|
+
return col
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def extract_phenotype(
|
|
56
|
+
phenotype_files: List[Path],
|
|
57
|
+
imaging_ids: Optional[List[str]] = None,
|
|
58
|
+
columns: Optional[List[str]] = None,
|
|
59
|
+
) -> List[Dict[str, str]]:
|
|
60
|
+
"""Extract and merge phenotype data from multiple files."""
|
|
61
|
+
all_data = []
|
|
62
|
+
for fpath in phenotype_files:
|
|
63
|
+
rows = load_csv(fpath)
|
|
64
|
+
all_data.extend(rows)
|
|
65
|
+
|
|
66
|
+
if not all_data:
|
|
67
|
+
return []
|
|
68
|
+
|
|
69
|
+
target_columns = columns if columns else list(COLUMN_MAP.keys())
|
|
70
|
+
merged = {}
|
|
71
|
+
|
|
72
|
+
for row in all_data:
|
|
73
|
+
subj_col = find_column(row, COLUMN_MAP["subject_id"])
|
|
74
|
+
if subj_col is None:
|
|
75
|
+
continue
|
|
76
|
+
subj_id = row[subj_col].strip()
|
|
77
|
+
if not subj_id:
|
|
78
|
+
continue
|
|
79
|
+
|
|
80
|
+
if subj_id not in merged:
|
|
81
|
+
merged[subj_id] = {"subject_id": subj_id}
|
|
82
|
+
|
|
83
|
+
for target_col in target_columns:
|
|
84
|
+
if target_col == "subject_id":
|
|
85
|
+
continue
|
|
86
|
+
if target_col in merged[subj_id] and merged[subj_id][target_col]:
|
|
87
|
+
continue
|
|
88
|
+
candidates = COLUMN_MAP.get(target_col, [target_col])
|
|
89
|
+
src_col = find_column(row, candidates)
|
|
90
|
+
if src_col and row.get(src_col, "").strip():
|
|
91
|
+
merged[subj_id][target_col] = row[src_col].strip()
|
|
92
|
+
|
|
93
|
+
result = list(merged.values())
|
|
94
|
+
if imaging_ids:
|
|
95
|
+
imaging_set = set(imaging_ids)
|
|
96
|
+
result = [r for r in result if r["subject_id"] in imaging_set]
|
|
97
|
+
return result
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def main() -> int:
|
|
101
|
+
parser = argparse.ArgumentParser(
|
|
102
|
+
description="Extract Cam-CAN phenotype data."
|
|
103
|
+
)
|
|
104
|
+
parser.add_argument("--phenotype-files", required=True, nargs="+",
|
|
105
|
+
help="Paths to Cam-CAN phenotype CSV/TSV files")
|
|
106
|
+
parser.add_argument("--output", required=True, help="Output path for merged phenotype CSV")
|
|
107
|
+
parser.add_argument("--imaging-ids", help="Text file with imaging subject IDs to filter")
|
|
108
|
+
parser.add_argument("--columns", help="Comma-separated columns to extract")
|
|
109
|
+
args = parser.parse_args()
|
|
110
|
+
|
|
111
|
+
phenotype_files = [Path(f).resolve() for f in args.phenotype_files]
|
|
112
|
+
for f in phenotype_files:
|
|
113
|
+
if not f.exists():
|
|
114
|
+
print(f"File not found: {f}", file=sys.stderr)
|
|
115
|
+
return 1
|
|
116
|
+
|
|
117
|
+
imaging_ids = None
|
|
118
|
+
if args.imaging_ids:
|
|
119
|
+
id_file = Path(args.imaging_ids).resolve()
|
|
120
|
+
if id_file.exists():
|
|
121
|
+
imaging_ids = [l.strip() for l in id_file.read_text().splitlines() if l.strip()]
|
|
122
|
+
|
|
123
|
+
columns = None
|
|
124
|
+
if args.columns:
|
|
125
|
+
columns = [c.strip() for c in args.columns.split(",")]
|
|
126
|
+
|
|
127
|
+
merged = extract_phenotype(phenotype_files, imaging_ids, columns)
|
|
128
|
+
if not merged:
|
|
129
|
+
print("[ERROR] No phenotype data extracted.", file=sys.stderr)
|
|
130
|
+
return 1
|
|
131
|
+
|
|
132
|
+
output_path = Path(args.output).resolve()
|
|
133
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
134
|
+
fieldnames = list(merged[0].keys())
|
|
135
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
136
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
137
|
+
writer.writeheader()
|
|
138
|
+
writer.writerows(merged)
|
|
139
|
+
|
|
140
|
+
print(f"Phenotype: {len(merged)} subjects, {len(fieldnames)} columns -> {output_path}")
|
|
141
|
+
return 0
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
sys.exit(main())
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Validate Cam-CAN BIDS structure and generate compliance report.
|
|
3
|
+
|
|
4
|
+
Checks directory structure, modality completeness, sidecar JSON presence,
|
|
5
|
+
and participant ID consistency across modalities.
|
|
6
|
+
"""
|
|
7
|
+
import argparse
|
|
8
|
+
import csv
|
|
9
|
+
import json
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Dict, List
|
|
13
|
+
|
|
14
|
+
# Expected modalities for Cam-CAN
|
|
15
|
+
EXPECTED_MODALITIES = {
|
|
16
|
+
"anat": ["T1w"],
|
|
17
|
+
"func": ["task-rest_bold", "task-movie_bold"],
|
|
18
|
+
"meg": ["task-rest_meg", "task-auditory_meg", "task-visual_meg"],
|
|
19
|
+
"dwi": ["dwi"],
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def validate_subject(subject_dir: Path) -> Dict[str, any]:
|
|
24
|
+
"""Validate a single subject's BIDS structure."""
|
|
25
|
+
report = {
|
|
26
|
+
"subject": subject_dir.name,
|
|
27
|
+
"anat_complete": False,
|
|
28
|
+
"func_complete": False,
|
|
29
|
+
"meg_complete": False,
|
|
30
|
+
"dwi_complete": False,
|
|
31
|
+
"missing_files": [],
|
|
32
|
+
"warnings": [],
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Check anat
|
|
36
|
+
anat_dir = subject_dir / "anat"
|
|
37
|
+
if anat_dir.exists():
|
|
38
|
+
t1w_files = list(anat_dir.glob("*_T1w.nii.gz"))
|
|
39
|
+
report["anat_complete"] = len(t1w_files) > 0
|
|
40
|
+
if not t1w_files:
|
|
41
|
+
report["missing_files"].append("anat/*_T1w.nii.gz")
|
|
42
|
+
# Check sidecar JSON
|
|
43
|
+
for f in t1w_files:
|
|
44
|
+
json_file = f.with_suffix("").with_suffix(".json")
|
|
45
|
+
if not json_file.exists():
|
|
46
|
+
report["warnings"].append(f"Missing sidecar: {json_file.name}")
|
|
47
|
+
else:
|
|
48
|
+
report["missing_files"].append("anat/")
|
|
49
|
+
|
|
50
|
+
# Check func
|
|
51
|
+
func_dir = subject_dir / "func"
|
|
52
|
+
if func_dir.exists():
|
|
53
|
+
rest_bold = list(func_dir.glob("*_task-rest_bold.nii.gz"))
|
|
54
|
+
movie_bold = list(func_dir.glob("*_task-movie_bold.nii.gz"))
|
|
55
|
+
report["func_complete"] = len(rest_bold) > 0 and len(movie_bold) > 0
|
|
56
|
+
if not rest_bold:
|
|
57
|
+
report["missing_files"].append("func/*_task-rest_bold.nii.gz")
|
|
58
|
+
if not movie_bold:
|
|
59
|
+
report["missing_files"].append("func/*_task-movie_bold.nii.gz")
|
|
60
|
+
else:
|
|
61
|
+
report["missing_files"].append("func/")
|
|
62
|
+
|
|
63
|
+
# Check meg
|
|
64
|
+
meg_dir = subject_dir / "meg"
|
|
65
|
+
if meg_dir.exists():
|
|
66
|
+
meg_files = list(meg_dir.glob("*_meg.fif"))
|
|
67
|
+
if not meg_files:
|
|
68
|
+
meg_files = list(meg_dir.glob("*_meg.ds"))
|
|
69
|
+
report["meg_complete"] = len(meg_files) > 0
|
|
70
|
+
if not meg_files:
|
|
71
|
+
report["missing_files"].append("meg/*_meg.fif or .ds")
|
|
72
|
+
else:
|
|
73
|
+
report["missing_files"].append("meg/")
|
|
74
|
+
|
|
75
|
+
# Check dwi
|
|
76
|
+
dwi_dir = subject_dir / "dwi"
|
|
77
|
+
if dwi_dir.exists():
|
|
78
|
+
dwi_files = list(dwi_dir.glob("*_dwi.nii.gz"))
|
|
79
|
+
report["dwi_complete"] = len(dwi_files) > 0
|
|
80
|
+
if not dwi_files:
|
|
81
|
+
report["missing_files"].append("dwi/*_dwi.nii.gz")
|
|
82
|
+
else:
|
|
83
|
+
report["missing_files"].append("dwi/")
|
|
84
|
+
|
|
85
|
+
return report
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def main() -> int:
|
|
89
|
+
parser = argparse.ArgumentParser(
|
|
90
|
+
description="Validate Cam-CAN BIDS structure."
|
|
91
|
+
)
|
|
92
|
+
parser.add_argument("--input", required=True, help="Path to Cam-CAN BIDS directory")
|
|
93
|
+
parser.add_argument("--output", required=True, help="Output path for validation CSV")
|
|
94
|
+
args = parser.parse_args()
|
|
95
|
+
|
|
96
|
+
input_dir = Path(args.input).resolve()
|
|
97
|
+
if not input_dir.exists():
|
|
98
|
+
print(f"Input directory not found: {input_dir}", file=sys.stderr)
|
|
99
|
+
return 1
|
|
100
|
+
|
|
101
|
+
# Find subjects
|
|
102
|
+
subjects = sorted([d for d in input_dir.glob("sub-*") if d.is_dir()])
|
|
103
|
+
print(f"Found {len(subjects)} subjects in {input_dir}")
|
|
104
|
+
|
|
105
|
+
if not subjects:
|
|
106
|
+
print("[ERROR] No subjects found.", file=sys.stderr)
|
|
107
|
+
return 1
|
|
108
|
+
|
|
109
|
+
# Validate each subject
|
|
110
|
+
results = []
|
|
111
|
+
for sub_dir in subjects:
|
|
112
|
+
report = validate_subject(sub_dir)
|
|
113
|
+
results.append(report)
|
|
114
|
+
|
|
115
|
+
# Write output
|
|
116
|
+
output_path = Path(args.output).resolve()
|
|
117
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
118
|
+
|
|
119
|
+
fieldnames = ["subject", "anat_complete", "func_complete", "meg_complete", "dwi_complete", "missing_files", "warnings"]
|
|
120
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
121
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
122
|
+
writer.writeheader()
|
|
123
|
+
for r in results:
|
|
124
|
+
r["missing_files"] = "; ".join(r["missing_files"])
|
|
125
|
+
r["warnings"] = "; ".join(r["warnings"])
|
|
126
|
+
writer.writerow(r)
|
|
127
|
+
|
|
128
|
+
# Summary
|
|
129
|
+
complete_subjects = sum(1 for r in results if r["anat_complete"] and r["func_complete"])
|
|
130
|
+
print(f"\nValidation Summary:")
|
|
131
|
+
print(f" Total subjects: {len(results)}")
|
|
132
|
+
print(f" Complete (anat+func): {complete_subjects}")
|
|
133
|
+
print(f" With MEG: {sum(1 for r in results if r['meg_complete'])}")
|
|
134
|
+
print(f" With DWI: {sum(1 for r in results if r['dwi_complete'])}")
|
|
135
|
+
print(f" Output: {output_path}")
|
|
136
|
+
|
|
137
|
+
return 0
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
if __name__ == "__main__":
|
|
141
|
+
sys.exit(main())
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cobre-skill
|
|
3
|
+
description: "Use this skill whenever the user wants an end-to-end workflow for the COBRE dataset, including download, BIDS organization, and processing of sMRI and rs-fMRI data for schizophrenia research. Triggers include: 'COBRE', 'process COBRE', 'COBRE schizophrenia', 'COBRE fMRI', or any request to run the COBRE pipeline. This is the NeuroClaw dataset-orchestration layer for COBRE."
|
|
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
|
+
---
|
|
13
|
+
# COBRE Skill (Dataset-Orchestration Layer)
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
`cobre-skill` is the NeuroClaw orchestration skill for the **COBRE (Center for Biomedical Research Excellence)** dataset.
|
|
17
|
+
|
|
18
|
+
COBRE contains 147 participants: 72 schizophrenia patients and 75 healthy controls, with T1w structural and rs-fMRI data. It is commonly used as a benchmark for brain disorder classification.
|
|
19
|
+
|
|
20
|
+
It coordinates a fixed three-phase workflow:
|
|
21
|
+
1. Download COBRE data from the FCP/INDI repository.
|
|
22
|
+
2. Prepare and validate BIDS-style data organization for downstream processing.
|
|
23
|
+
3. Delegate modality pipelines to `smri-skill` and `fmri-skill`.
|
|
24
|
+
|
|
25
|
+
It also provides **phenotype extraction** and **QC integration** paths:
|
|
26
|
+
- Extract COBRE phenotype data (diagnosis, demographics, handedness).
|
|
27
|
+
- Generate per-subject QC summaries with exclusion lists.
|
|
28
|
+
|
|
29
|
+
This skill follows NeuroClaw hierarchy:
|
|
30
|
+
- Defines **WHAT to do**, not low-level implementation details.
|
|
31
|
+
- Does **not** execute direct shell commands itself.
|
|
32
|
+
- Delegates all execution via `claw-shell` to base/tool skills.
|
|
33
|
+
|
|
34
|
+
**Research use only.**
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Download Stage (Mandatory First Step)
|
|
39
|
+
|
|
40
|
+
### Source
|
|
41
|
+
COBRE data is distributed through the **FCP/INDI** repository:
|
|
42
|
+
- Website: https://fcon_1000.projects.nitrc.org/indi/retro/cobre.html
|
|
43
|
+
|
|
44
|
+
### Supported COBRE Data Packages
|
|
45
|
+
- **Imaging data**: T1w, rs-fMRI (NIfTI format)
|
|
46
|
+
- **Phenotype data**: CSV files with diagnosis, demographics, handedness
|
|
47
|
+
- **Participants**: 147 total (72 schizophrenia, 75 healthy controls)
|
|
48
|
+
|
|
49
|
+
### Delegation Rules for Download
|
|
50
|
+
- Environment/setup checks: `dependency-planner` + `conda-env-manager`
|
|
51
|
+
- Download tool installation and execution: `claw-shell`
|
|
52
|
+
- Optional raw-data organization to BIDS-style staging: `bids-organizer`
|
|
53
|
+
|
|
54
|
+
### Download Inputs to Confirm in Plan
|
|
55
|
+
- Subject list scope (full or custom subset)
|
|
56
|
+
- Whether to download raw data or preprocessed derivatives
|
|
57
|
+
- Destination directory with sufficient disk space
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Narrow Path: COBRE Raw NIfTI -> BIDS Staging
|
|
62
|
+
|
|
63
|
+
Use this path when the task only asks to reorganize raw COBRE NIfTI files into a BIDS-style dataset and does not require preprocessing or downstream analysis.
|
|
64
|
+
|
|
65
|
+
### Expected narrow-path behavior
|
|
66
|
+
1. Detect COBRE-style subject IDs (numeric) and normalize to BIDS labels such as `sub-NNNNN`.
|
|
67
|
+
2. Route modalities:
|
|
68
|
+
- T1w -> `anat/*_T1w`
|
|
69
|
+
- rs-fMRI/BOLD -> `func/*_task-rest_bold`
|
|
70
|
+
3. Preserve or rename matching JSON sidecars when available.
|
|
71
|
+
4. Emit dataset-level outputs such as `dataset_description.json`, `participants.tsv`.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Core Workflow (Never Bypassed)
|
|
76
|
+
1. Identify user target: full COBRE download, imaging subset, phenotype extraction, or BIDS staging only.
|
|
77
|
+
2. Generate a numbered plan with tools, outputs, runtime, storage, and risks.
|
|
78
|
+
3. Wait for explicit confirmation (`YES` / `execute` / `proceed`).
|
|
79
|
+
4. On confirmation, run download stage first (if needed).
|
|
80
|
+
5. After download success, run BIDS preparation using `scripts/reorganize_cobre.py`.
|
|
81
|
+
6. Delegate to modality skills:
|
|
82
|
+
- `smri-skill` for structural MRI (T1w)
|
|
83
|
+
- `fmri-skill` for resting-state fMRI (rs-fMRI)
|
|
84
|
+
7. If phenotype extraction is requested, run `scripts/extract_cobre_phenotype.py`.
|
|
85
|
+
8. If QC summary is requested, run `scripts/cobre_qc_summary.py`.
|
|
86
|
+
9. Save outputs into a COBRE-centered structure under `cobre_output/`.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## BIDS Preparation
|
|
91
|
+
|
|
92
|
+
### Script: `scripts/reorganize_cobre.py`
|
|
93
|
+
|
|
94
|
+
Converts COBRE raw directory structure to BIDS-compliant layout.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
python skills/cobre-skill/scripts/reorganize_cobre.py \
|
|
98
|
+
--input /path/to/cobre_raw \
|
|
99
|
+
--output /path/to/cobre_bids \
|
|
100
|
+
--phenotype /path/to/cobre_raw/phenotype/cobre_phenotypic.csv
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Phenotype Extraction
|
|
106
|
+
|
|
107
|
+
### Script: `scripts/extract_cobre_phenotype.py`
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
python skills/cobre-skill/scripts/extract_cobre_phenotype.py \
|
|
111
|
+
--phenotype-dir /path/to/cobre_raw/phenotype \
|
|
112
|
+
--output /path/to/cobre_output/phenotype/merged_phenotype.csv \
|
|
113
|
+
--imaging-ids /path/to/cobre_output/bids/participants.tsv
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## QC Integration
|
|
119
|
+
|
|
120
|
+
### Script: `scripts/cobre_qc_summary.py`
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
python skills/cobre-skill/scripts/cobre_qc_summary.py \
|
|
124
|
+
--fmriprep-dir /path/to/cobre_output/fmriprep \
|
|
125
|
+
--output /path/to/cobre_output/qc/qc_summary.csv \
|
|
126
|
+
--exclude-output /path/to/cobre_output/qc/exclude_list.csv \
|
|
127
|
+
--fd-threshold 0.3
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Recommended Output Layout
|
|
133
|
+
All assets should be organized under `./cobre_output/`:
|
|
134
|
+
- `cobre_output/raw/` (downloaded original COBRE files)
|
|
135
|
+
- `cobre_output/bids/` (staged BIDS data)
|
|
136
|
+
- `cobre_output/smri/` (links or copies from `smri_output/`)
|
|
137
|
+
- `cobre_output/fmri/` (links or copies from `fmri_output/`)
|
|
138
|
+
- `cobre_output/phenotype/` (merged phenotype tables)
|
|
139
|
+
- `cobre_output/qc/` (QC summaries and exclusion lists)
|
|
140
|
+
- `cobre_output/logs/` (download + orchestration logs)
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Benchmark Adapter Guidance
|
|
145
|
+
|
|
146
|
+
For benchmark-style prompts, do not force the full `download -> staging -> multimodal processing` orchestration when the task is only asking for local COBRE data staging or organization.
|
|
147
|
+
|
|
148
|
+
- If the task starts from raw COBRE data already present on disk and only asks for BIDS-style staging / organization:
|
|
149
|
+
- skip the mandatory download stage
|
|
150
|
+
- default to the narrow path `local raw COBRE discovery -> BIDS-style staging -> minimal metadata -> validation/report`
|
|
151
|
+
- In benchmark mode, do not require explicit confirmation before presenting the direct staging solution.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Safety and Execution Policy
|
|
156
|
+
- No execution before explicit plan confirmation.
|
|
157
|
+
- All execution must be routed via `claw-shell`.
|
|
158
|
+
- Missing dependencies must be resolved by `dependency-planner` before running.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Important Notes and Limitations
|
|
163
|
+
- COBRE is a single-site dataset from the University of New Mexico; no site effects to address.
|
|
164
|
+
- COBRE has a small sample size (147 subjects); cross-validation strategies should account for this.
|
|
165
|
+
- Diagnosis labels: schizophrenia (1) vs. healthy control (2).
|
|
166
|
+
- COBRE data does not include task-fMRI; only resting-state fMRI is available.
|
|
167
|
+
- `cobre-skill` is orchestration-only; detailed preprocessing logic remains in `smri-skill` and `fmri-skill`.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## When to Call This Skill
|
|
172
|
+
- User asks for end-to-end COBRE workflow.
|
|
173
|
+
- User asks to download COBRE data and then run sMRI/rs-fMRI processing.
|
|
174
|
+
- User needs BIDS staging for raw COBRE NIfTI files.
|
|
175
|
+
- User asks to extract COBRE phenotype data.
|
|
176
|
+
- User needs COBRE-specific QC summaries and exclusion lists.
|
|
177
|
+
- User wants to run schizophrenia classification with BrainGNN or other models on COBRE.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Complementary / Related Skills
|
|
182
|
+
- `smri-skill`
|
|
183
|
+
- `fmri-skill`
|
|
184
|
+
- `bids-organizer`
|
|
185
|
+
- `fmriprep-tool`
|
|
186
|
+
- `freesurfer-tool`
|
|
187
|
+
- `brain_gnn`
|
|
188
|
+
- `neurostorm`
|
|
189
|
+
- `dependency-planner`
|
|
190
|
+
- `conda-env-manager`
|
|
191
|
+
- `claw-shell`
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Reference
|
|
196
|
+
- COBRE: https://fcon_1000.projects.nitrc.org/indi/retro/cobre.html
|
|
197
|
+
- BIDS spec: https://bids.neuroimaging.io/
|
|
198
|
+
|
|
199
|
+
Created At: 2026-05-06 01:54 HKT
|
|
200
|
+
Last Updated At: 2026-05-06 01:54 HKT
|
|
201
|
+
Author: chengwang96
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Generate per-subject QC summaries and exclusion lists for COBRE."""
|
|
3
|
+
import argparse
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Dict, List, Tuple
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
import pandas as pd
|
|
10
|
+
except ImportError:
|
|
11
|
+
print("Error: pandas is required.", file=sys.stderr)
|
|
12
|
+
sys.exit(1)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def detect_delimiter(file_path: Path) -> str:
|
|
16
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
17
|
+
return "\t" if "\t" in f.readline() else ","
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def collect_fmriprep_qc(fmriprep_dir: Path) -> Dict[str, Dict[str, float]]:
|
|
21
|
+
qc = {}
|
|
22
|
+
for confounds_file in fmriprep_dir.rglob("**/*_desc-confounds_timeseries.tsv"):
|
|
23
|
+
subject_id = next((p for p in confounds_file.parts if p.startswith("sub-")), None)
|
|
24
|
+
if not subject_id:
|
|
25
|
+
continue
|
|
26
|
+
try:
|
|
27
|
+
df = pd.read_csv(confounds_file, sep=detect_delimiter(confounds_file), low_memory=False)
|
|
28
|
+
except Exception:
|
|
29
|
+
continue
|
|
30
|
+
fd_col = next((c for c in ["framewise_displacement", "fd", "FD"] if c in df.columns), None)
|
|
31
|
+
if fd_col:
|
|
32
|
+
fd = pd.to_numeric(df[fd_col], errors="coerce").dropna()
|
|
33
|
+
if len(fd) > 0:
|
|
34
|
+
metrics = {"mean_fd": float(fd.mean()), "max_fd": float(fd.max()), "n_volumes": len(df)}
|
|
35
|
+
if subject_id in qc:
|
|
36
|
+
qc[subject_id]["mean_fd"] = max(qc[subject_id].get("mean_fd", 0), metrics["mean_fd"])
|
|
37
|
+
qc[subject_id]["max_fd"] = max(qc[subject_id].get("max_fd", 0), metrics["max_fd"])
|
|
38
|
+
else:
|
|
39
|
+
qc[subject_id] = metrics
|
|
40
|
+
return qc
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def main() -> int:
|
|
44
|
+
parser = argparse.ArgumentParser(description="Generate COBRE QC summaries.")
|
|
45
|
+
parser.add_argument("--fmriprep-dir", help="Path to fMRIPrep output directory")
|
|
46
|
+
parser.add_argument("--output", required=True, help="Output path for QC summary CSV")
|
|
47
|
+
parser.add_argument("--exclude-output", help="Output path for exclusion list CSV")
|
|
48
|
+
parser.add_argument("--fd-threshold", type=float, default=0.3, help="Mean FD threshold (default: 0.3)")
|
|
49
|
+
parser.add_argument("--max-fd-threshold", type=float, default=5.0, help="Max FD threshold (default: 5.0)")
|
|
50
|
+
args = parser.parse_args()
|
|
51
|
+
|
|
52
|
+
fmriprep_qc = {}
|
|
53
|
+
if args.fmriprep_dir:
|
|
54
|
+
fp_dir = Path(args.fmriprep_dir).resolve()
|
|
55
|
+
if fp_dir.exists():
|
|
56
|
+
print(f"Collecting fMRIPrep QC from {fp_dir}...")
|
|
57
|
+
fmriprep_qc = collect_fmriprep_qc(fp_dir)
|
|
58
|
+
print(f" Found {len(fmriprep_qc)} subjects")
|
|
59
|
+
|
|
60
|
+
if not fmriprep_qc:
|
|
61
|
+
print("[ERROR] No QC data collected.", file=sys.stderr)
|
|
62
|
+
return 1
|
|
63
|
+
|
|
64
|
+
rows = []
|
|
65
|
+
excluded = []
|
|
66
|
+
for sub_id in sorted(fmriprep_qc.keys()):
|
|
67
|
+
fp = fmriprep_qc[sub_id]
|
|
68
|
+
reasons = []
|
|
69
|
+
if fp.get("mean_fd", 0) > args.fd_threshold:
|
|
70
|
+
reasons.append(f"mean_fd={fp['mean_fd']:.3f}>{args.fd_threshold}")
|
|
71
|
+
if fp.get("max_fd", 0) > args.max_fd_threshold:
|
|
72
|
+
reasons.append(f"max_fd={fp['max_fd']:.3f}>{args.max_fd_threshold}")
|
|
73
|
+
row = {"subject_id": sub_id, "mean_fd": fp.get("mean_fd"), "max_fd": fp.get("max_fd"), "n_volumes": fp.get("n_volumes"), "exclude": bool(reasons), "exclude_reasons": "; ".join(reasons)}
|
|
74
|
+
if reasons:
|
|
75
|
+
excluded.append(sub_id)
|
|
76
|
+
rows.append(row)
|
|
77
|
+
|
|
78
|
+
summary_df = pd.DataFrame(rows)
|
|
79
|
+
output_path = Path(args.output).resolve()
|
|
80
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
81
|
+
summary_df.to_csv(output_path, index=False)
|
|
82
|
+
print(f"\nQC Summary: {len(summary_df)} subjects -> {output_path}")
|
|
83
|
+
print(f" Excluded: {len(excluded)} / {len(summary_df)} ({100*len(excluded)/max(len(summary_df),1):.1f}%)")
|
|
84
|
+
|
|
85
|
+
if args.exclude_output:
|
|
86
|
+
exclude_path = Path(args.exclude_output).resolve()
|
|
87
|
+
exclude_path.parent.mkdir(parents=True, exist_ok=True)
|
|
88
|
+
summary_df[summary_df["exclude"] == True][["subject_id", "exclude_reasons"]].to_csv(exclude_path, index=False)
|
|
89
|
+
print(f" Exclusion list: {exclude_path}")
|
|
90
|
+
|
|
91
|
+
return 0
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if __name__ == "__main__":
|
|
95
|
+
sys.exit(main())
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Extract and merge COBRE phenotype tables for downstream analysis."""
|
|
3
|
+
import argparse
|
|
4
|
+
import csv
|
|
5
|
+
import re
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Dict, List, Optional
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
import pandas as pd
|
|
12
|
+
except ImportError:
|
|
13
|
+
print("Error: pandas is required.", file=sys.stderr)
|
|
14
|
+
sys.exit(1)
|
|
15
|
+
|
|
16
|
+
COLUMN_MAP = {
|
|
17
|
+
"subject": "subject_id",
|
|
18
|
+
"SUBJECT_ID": "subject_id",
|
|
19
|
+
"Subject": "subject_id",
|
|
20
|
+
"DX": "diagnosis",
|
|
21
|
+
"DX_GROUP": "diagnosis",
|
|
22
|
+
"AGE": "age",
|
|
23
|
+
"SEX": "sex",
|
|
24
|
+
"HANDEDNESS": "handedness",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def normalize_subject_id(raw_id) -> str:
|
|
29
|
+
clean = re.sub(r"[^a-zA-Z0-9]", "", str(raw_id).strip())
|
|
30
|
+
return f"sub-{clean}"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def main() -> int:
|
|
34
|
+
parser = argparse.ArgumentParser(description="Extract COBRE phenotype data.")
|
|
35
|
+
parser.add_argument("--phenotype-dir", help="Directory containing COBRE phenotype CSV files")
|
|
36
|
+
parser.add_argument("--phenotype-file", help="Direct path to COBRE phenotype CSV file")
|
|
37
|
+
parser.add_argument("--output", required=True, help="Output path for phenotype CSV")
|
|
38
|
+
parser.add_argument("--imaging-ids", help="Path to BIDS participants.tsv for filtering")
|
|
39
|
+
args = parser.parse_args()
|
|
40
|
+
|
|
41
|
+
phenotype_files = []
|
|
42
|
+
if args.phenotype_file:
|
|
43
|
+
p = Path(args.phenotype_file).resolve()
|
|
44
|
+
if p.exists():
|
|
45
|
+
phenotype_files.append(p)
|
|
46
|
+
elif args.phenotype_dir:
|
|
47
|
+
phenotype_dir = Path(args.phenotype_dir).resolve()
|
|
48
|
+
if phenotype_dir.exists():
|
|
49
|
+
phenotype_files = sorted(f for f in phenotype_dir.iterdir() if f.is_file() and f.suffix in (".csv", ".tsv"))
|
|
50
|
+
|
|
51
|
+
if not phenotype_files:
|
|
52
|
+
print("[ERROR] No phenotype files found.", file=sys.stderr)
|
|
53
|
+
return 1
|
|
54
|
+
|
|
55
|
+
print(f"Found {len(phenotype_files)} phenotype file(s)")
|
|
56
|
+
|
|
57
|
+
dataframes = []
|
|
58
|
+
for f in phenotype_files:
|
|
59
|
+
try:
|
|
60
|
+
df = pd.read_csv(f, sep=None, engine="python", low_memory=False)
|
|
61
|
+
rename = {k: v for k, v in COLUMN_MAP.items() if k in df.columns and v not in df.columns}
|
|
62
|
+
df = df.rename(columns=rename)
|
|
63
|
+
dataframes.append(df)
|
|
64
|
+
except Exception as e:
|
|
65
|
+
print(f"[WARN] Failed to read {f}: {e}")
|
|
66
|
+
|
|
67
|
+
if not dataframes:
|
|
68
|
+
print("[ERROR] No data loaded.", file=sys.stderr)
|
|
69
|
+
return 1
|
|
70
|
+
|
|
71
|
+
merged = dataframes[0]
|
|
72
|
+
for df in dataframes[1:]:
|
|
73
|
+
if "subject_id" in merged.columns and "subject_id" in df.columns:
|
|
74
|
+
new_cols = [c for c in df.columns if c not in merged.columns or c == "subject_id"]
|
|
75
|
+
merged = pd.merge(merged, df[new_cols], on="subject_id", how="outer")
|
|
76
|
+
else:
|
|
77
|
+
merged = pd.concat([merged, df], ignore_index=True)
|
|
78
|
+
|
|
79
|
+
if args.imaging_ids:
|
|
80
|
+
imaging_path = Path(args.imaging_ids).resolve()
|
|
81
|
+
if imaging_path.exists() and "subject_id" in merged.columns:
|
|
82
|
+
id_df = pd.read_csv(imaging_path, sep="\t")
|
|
83
|
+
for col in ["participant_id", "subject_id"]:
|
|
84
|
+
if col in id_df.columns:
|
|
85
|
+
imaging_ids = set(id_df[col].astype(str).str.strip())
|
|
86
|
+
normalized = {normalize_subject_id(sid) for sid in imaging_ids} | imaging_ids
|
|
87
|
+
merged["_norm"] = merged["subject_id"].apply(normalize_subject_id)
|
|
88
|
+
merged = merged[merged["_norm"].isin(normalized) | merged["subject_id"].astype(str).isin(normalized)]
|
|
89
|
+
merged = merged.drop(columns=["_norm"])
|
|
90
|
+
break
|
|
91
|
+
|
|
92
|
+
output_path = Path(args.output).resolve()
|
|
93
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
94
|
+
merged.to_csv(output_path, index=False)
|
|
95
|
+
print(f"\nWrote {len(merged)} rows x {len(merged.columns)} columns to {output_path}")
|
|
96
|
+
|
|
97
|
+
if "diagnosis" in merged.columns:
|
|
98
|
+
print(f"\nDiagnosis distribution:\n{merged['diagnosis'].value_counts().to_string()}")
|
|
99
|
+
|
|
100
|
+
return 0
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
if __name__ == "__main__":
|
|
104
|
+
sys.exit(main())
|