@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,152 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Generate per-subject QC summaries for HCP Young Adult processing.
|
|
3
|
+
|
|
4
|
+
Combines fMRIPrep confounds and FreeSurfer recon-all metrics
|
|
5
|
+
to produce a unified QC summary with exclusion recommendations.
|
|
6
|
+
"""
|
|
7
|
+
import argparse
|
|
8
|
+
import csv
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Dict, List, Optional
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def load_confounds(confounds_path: Path) -> Dict[str, float]:
|
|
15
|
+
"""Extract QC metrics from fMRIPrep confounds TSV."""
|
|
16
|
+
metrics = {"fd_mean": float("nan"), "fd_max": float("nan"), "dummy_scans": 0}
|
|
17
|
+
try:
|
|
18
|
+
import pandas as pd
|
|
19
|
+
df = pd.read_csv(confounds_path, sep="\t")
|
|
20
|
+
if "framewise_displacement" in df.columns:
|
|
21
|
+
fd = df["framewise_displacement"].dropna()
|
|
22
|
+
metrics["fd_mean"] = float(fd.mean())
|
|
23
|
+
metrics["fd_max"] = float(fd.max())
|
|
24
|
+
except Exception:
|
|
25
|
+
pass
|
|
26
|
+
return metrics
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def load_freesurfer_qc(fs_dir: Path, subject_id: str) -> Dict[str, float]:
|
|
30
|
+
"""Extract FreeSurfer QC metrics for a subject."""
|
|
31
|
+
metrics = {
|
|
32
|
+
"fs_eTIV": float("nan"),
|
|
33
|
+
"fs_surface_area": float("nan"),
|
|
34
|
+
"fs_cortical_thickness": float("nan"),
|
|
35
|
+
}
|
|
36
|
+
stats_file = fs_dir / subject_id / "stats" / "aseg.stats"
|
|
37
|
+
if stats_file.exists():
|
|
38
|
+
try:
|
|
39
|
+
for line in stats_file.read_text().splitlines():
|
|
40
|
+
if "EstimatedTotalIntraCranialVol" in line:
|
|
41
|
+
parts = line.split(",")
|
|
42
|
+
if len(parts) > 4:
|
|
43
|
+
metrics["fs_eTIV"] = float(parts[4].strip())
|
|
44
|
+
except Exception:
|
|
45
|
+
pass
|
|
46
|
+
return metrics
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def check_exclusion(
|
|
50
|
+
metrics: Dict[str, float],
|
|
51
|
+
fd_threshold: float = 0.3,
|
|
52
|
+
) -> List[str]:
|
|
53
|
+
"""Check exclusion criteria and return list of reasons."""
|
|
54
|
+
reasons = []
|
|
55
|
+
if not (metrics["fd_mean"] != metrics["fd_mean"]): # not NaN
|
|
56
|
+
if metrics["fd_mean"] > fd_threshold:
|
|
57
|
+
reasons.append(f"FD mean {metrics['fd_mean']:.3f} > {fd_threshold}")
|
|
58
|
+
return reasons
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def main() -> int:
|
|
62
|
+
parser = argparse.ArgumentParser(
|
|
63
|
+
description="Generate QC summaries for HCP-YA processing."
|
|
64
|
+
)
|
|
65
|
+
parser.add_argument("--fmriprep-dir", help="Path to fMRIPrep output directory")
|
|
66
|
+
parser.add_argument("--freesurfer-dir", help="Path to FreeSurfer output directory")
|
|
67
|
+
parser.add_argument("--output", required=True, help="Output path for QC summary CSV")
|
|
68
|
+
parser.add_argument("--exclude-output", help="Output path for exclusion list CSV")
|
|
69
|
+
parser.add_argument("--fd-threshold", type=float, default=0.3,
|
|
70
|
+
help="Framewise displacement threshold (default: 0.3 mm)")
|
|
71
|
+
args = parser.parse_args()
|
|
72
|
+
|
|
73
|
+
output_path = Path(args.output).resolve()
|
|
74
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
75
|
+
|
|
76
|
+
# Discover subjects
|
|
77
|
+
subjects = set()
|
|
78
|
+
if args.fmriprep_dir:
|
|
79
|
+
fmriprep_dir = Path(args.fmriprep_dir).resolve()
|
|
80
|
+
if fmriprep_dir.exists():
|
|
81
|
+
for d in fmriprep_dir.glob("sub-*"):
|
|
82
|
+
if d.is_dir():
|
|
83
|
+
subjects.add(d.name)
|
|
84
|
+
|
|
85
|
+
if args.freesurfer_dir:
|
|
86
|
+
fs_dir = Path(args.freesurfer_dir).resolve()
|
|
87
|
+
if fs_dir.exists():
|
|
88
|
+
for d in fs_dir.iterdir():
|
|
89
|
+
if d.is_dir() and not d.name.startswith("."):
|
|
90
|
+
subjects.add(f"sub-{d.name}" if not d.name.startswith("sub-") else d.name)
|
|
91
|
+
|
|
92
|
+
if not subjects:
|
|
93
|
+
print("[WARN] No subjects found. Check directory paths.", file=sys.stderr)
|
|
94
|
+
return 1
|
|
95
|
+
|
|
96
|
+
print(f"Processing {len(subjects)} subjects...")
|
|
97
|
+
|
|
98
|
+
# Process each subject
|
|
99
|
+
results = []
|
|
100
|
+
excluded = []
|
|
101
|
+
for subj in sorted(subjects):
|
|
102
|
+
metrics = {"subject_id": subj}
|
|
103
|
+
|
|
104
|
+
# fMRIPrep confounds
|
|
105
|
+
if args.fmriprep_dir:
|
|
106
|
+
confounds_files = list(Path(args.fmriprep_dir).glob(f"{subj}/func/*_desc-confounds_timeseries.tsv"))
|
|
107
|
+
if confounds_files:
|
|
108
|
+
confounds = load_confounds(confounds_files[0])
|
|
109
|
+
metrics.update(confounds)
|
|
110
|
+
|
|
111
|
+
# FreeSurfer metrics
|
|
112
|
+
if args.freesurfer_dir:
|
|
113
|
+
fs_id = subj.replace("sub-", "")
|
|
114
|
+
fs_metrics = load_freesurfer_qc(Path(args.freesurfer_dir), fs_id)
|
|
115
|
+
metrics.update(fs_metrics)
|
|
116
|
+
|
|
117
|
+
# Check exclusion
|
|
118
|
+
exclusion_reasons = check_exclusion(metrics, args.fd_threshold)
|
|
119
|
+
metrics["excluded"] = len(exclusion_reasons) > 0
|
|
120
|
+
metrics["exclusion_reasons"] = "; ".join(exclusion_reasons)
|
|
121
|
+
|
|
122
|
+
results.append(metrics)
|
|
123
|
+
if exclusion_reasons:
|
|
124
|
+
excluded.append({"subject_id": subj, "reasons": "; ".join(exclusion_reasons)})
|
|
125
|
+
|
|
126
|
+
# Write QC summary
|
|
127
|
+
if results:
|
|
128
|
+
fieldnames = list(results[0].keys())
|
|
129
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
130
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
131
|
+
writer.writeheader()
|
|
132
|
+
writer.writerows(results)
|
|
133
|
+
print(f"\nQC Summary:")
|
|
134
|
+
print(f" Total subjects: {len(results)}")
|
|
135
|
+
print(f" Excluded: {len(excluded)}")
|
|
136
|
+
print(f" Output: {output_path}")
|
|
137
|
+
|
|
138
|
+
# Write exclusion list
|
|
139
|
+
if args.exclude_output and excluded:
|
|
140
|
+
exclude_path = Path(args.exclude_output).resolve()
|
|
141
|
+
exclude_path.parent.mkdir(parents=True, exist_ok=True)
|
|
142
|
+
with open(exclude_path, "w", newline="", encoding="utf-8") as f:
|
|
143
|
+
writer = csv.DictWriter(f, fieldnames=["subject_id", "reasons"])
|
|
144
|
+
writer.writeheader()
|
|
145
|
+
writer.writerows(excluded)
|
|
146
|
+
print(f" Exclusion list: {exclude_path}")
|
|
147
|
+
|
|
148
|
+
return 0
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
if __name__ == "__main__":
|
|
152
|
+
sys.exit(main())
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Reorganize HCP Young Adult (HCP1200) native layout to BIDS structure.
|
|
3
|
+
|
|
4
|
+
Converts HCP-YA directory layout (e.g., 100307/T1w/, 100307/MNINonLinear/)
|
|
5
|
+
to BIDS-compliant structure (sub-100307/anat/, sub-100307/func/).
|
|
6
|
+
"""
|
|
7
|
+
import argparse
|
|
8
|
+
import json
|
|
9
|
+
import shutil
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
# HCP-YA task mappings: task folder name -> BIDS task label + full name
|
|
14
|
+
TASK_MAP = {
|
|
15
|
+
"tfMRI_MOTOR": {"label": "motor", "name": "Motor"},
|
|
16
|
+
"tfMRI_EMOTION": {"label": "emotion", "name": "Emotion"},
|
|
17
|
+
"tfMRI_GAMBLING": {"label": "gambling", "name": "Gambling"},
|
|
18
|
+
"tfMRI_LANGUAGE": {"label": "language", "name": "Language"},
|
|
19
|
+
"tfMRI_RELATIONAL": {"label": "relational", "name": "Relational"},
|
|
20
|
+
"tfMRI_SOCIAL": {"label": "social", "name": "Social"},
|
|
21
|
+
"tfMRI_WM": {"label": "wm", "name": "WorkingMemory"},
|
|
22
|
+
"rfMRI_REST": {"label": "rest", "name": "RestingState"},
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def normalize_subject_id(hcp_id: str) -> str:
|
|
27
|
+
"""Convert HCP subject ID to BIDS format."""
|
|
28
|
+
return f"sub-{hcp_id.strip()}"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def find_subjects(input_dir: Path, participant_list: list = None) -> list:
|
|
32
|
+
"""Find HCP subject directories."""
|
|
33
|
+
subjects = []
|
|
34
|
+
for d in sorted(input_dir.iterdir()):
|
|
35
|
+
if d.is_dir() and d.name.isdigit():
|
|
36
|
+
if participant_list is None or d.name in participant_list:
|
|
37
|
+
subjects.append(d)
|
|
38
|
+
return subjects
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def reorganize_subject(subject_dir: Path, output_dir: Path, dry_run: bool = False) -> dict:
|
|
42
|
+
"""Reorganize a single HCP-YA subject to BIDS."""
|
|
43
|
+
hcp_id = subject_dir.name
|
|
44
|
+
bids_id = normalize_subject_id(hcp_id)
|
|
45
|
+
sub_dir = output_dir / bids_id
|
|
46
|
+
|
|
47
|
+
report = {"subject": hcp_id, "files_created": 0, "warnings": []}
|
|
48
|
+
|
|
49
|
+
if not dry_run:
|
|
50
|
+
(sub_dir / "anat").mkdir(parents=True, exist_ok=True)
|
|
51
|
+
(sub_dir / "func").mkdir(parents=True, exist_ok=True)
|
|
52
|
+
(sub_dir / "dwi").mkdir(parents=True, exist_ok=True)
|
|
53
|
+
|
|
54
|
+
# Structural MRI: T1w and T2w
|
|
55
|
+
mninonlinear = subject_dir / "MNINonLinear"
|
|
56
|
+
t1w_src = mninonlinear / "T1w.nii.gz"
|
|
57
|
+
t2w_src = mninonlinear / "T2w.nii.gz"
|
|
58
|
+
|
|
59
|
+
if t1w_src.exists():
|
|
60
|
+
dst = sub_dir / "anat" / f"{bids_id}_T1w.nii.gz"
|
|
61
|
+
if not dry_run:
|
|
62
|
+
shutil.copy2(t1w_src, dst)
|
|
63
|
+
report["files_created"] += 1
|
|
64
|
+
else:
|
|
65
|
+
report["warnings"].append("T1w not found")
|
|
66
|
+
|
|
67
|
+
if t2w_src.exists():
|
|
68
|
+
dst = sub_dir / "anat" / f"{bids_id}_T2w.nii.gz"
|
|
69
|
+
if not dry_run:
|
|
70
|
+
shutil.copy2(t2w_src, dst)
|
|
71
|
+
report["files_created"] += 1
|
|
72
|
+
else:
|
|
73
|
+
report["warnings"].append("T2w not found")
|
|
74
|
+
|
|
75
|
+
# Functional MRI
|
|
76
|
+
for task_dir_name, task_info in TASK_MAP.items():
|
|
77
|
+
task_dir = subject_dir / task_dir_name
|
|
78
|
+
if not task_dir.exists():
|
|
79
|
+
task_dir = mninonlinear / "Results" / task_dir_name
|
|
80
|
+
|
|
81
|
+
if task_dir.exists():
|
|
82
|
+
# Look for the main bold file
|
|
83
|
+
bold_candidates = list(task_dir.glob("*_bold.nii.gz"))
|
|
84
|
+
if not bold_candidates:
|
|
85
|
+
bold_candidates = list(task_dir.glob("*.nii.gz"))
|
|
86
|
+
|
|
87
|
+
for bold_src in bold_candidates:
|
|
88
|
+
run_label = "01"
|
|
89
|
+
bids_task = task_info["label"]
|
|
90
|
+
dst_name = f"{bids_id}_task-{bids_task}_run-{run_label}_bold.nii.gz"
|
|
91
|
+
dst = sub_dir / "func" / dst_name
|
|
92
|
+
if not dry_run:
|
|
93
|
+
shutil.copy2(bold_src, dst)
|
|
94
|
+
report["files_created"] += 1
|
|
95
|
+
|
|
96
|
+
# Diffusion MRI
|
|
97
|
+
dmri_dir = subject_dir / "T1w" / "Diffusion"
|
|
98
|
+
if dmri_dir.exists():
|
|
99
|
+
for suffix in ["data.nii.gz", "bval", "bvec"]:
|
|
100
|
+
src = dmri_dir / suffix
|
|
101
|
+
if src.exists():
|
|
102
|
+
bids_suffix = suffix.replace("data.nii.gz", "dwi.nii.gz")
|
|
103
|
+
dst = sub_dir / "dwi" / f"{bids_id}_{bids_suffix}"
|
|
104
|
+
if not dry_run:
|
|
105
|
+
shutil.copy2(src, dst)
|
|
106
|
+
report["files_created"] += 1
|
|
107
|
+
|
|
108
|
+
return report
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def create_dataset_description(output_dir: Path, n_subjects: int):
|
|
112
|
+
"""Create BIDS dataset_description.json."""
|
|
113
|
+
desc = {
|
|
114
|
+
"Name": "HCP Young Adult (HCP1200)",
|
|
115
|
+
"BIDSVersion": "1.8.0",
|
|
116
|
+
"DatasetType": "raw",
|
|
117
|
+
"License": "HCP Data Use Terms",
|
|
118
|
+
"Authors": ["Human Connectome Project"],
|
|
119
|
+
"Acknowledgements": "WU-Minn HCP Consortium",
|
|
120
|
+
"HowToAcknowledge": "Please cite the Human Connectome Project.",
|
|
121
|
+
"ReferencesAndLinks": [
|
|
122
|
+
"https://www.humanconnectome.org/study/hcp-young-adult",
|
|
123
|
+
"Glasser et al. (2013) NeuroImage"
|
|
124
|
+
],
|
|
125
|
+
"Subjects": n_subjects
|
|
126
|
+
}
|
|
127
|
+
with open(output_dir / "dataset_description.json", "w", encoding="utf-8") as f:
|
|
128
|
+
json.dump(desc, f, indent=2)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def main() -> int:
|
|
132
|
+
parser = argparse.ArgumentParser(
|
|
133
|
+
description="Reorganize HCP-YA native layout to BIDS."
|
|
134
|
+
)
|
|
135
|
+
parser.add_argument("--input", required=True, help="Path to HCP-YA raw directory")
|
|
136
|
+
parser.add_argument("--output", required=True, help="Output BIDS directory")
|
|
137
|
+
parser.add_argument("--participants", help="Text file with subject IDs (one per line)")
|
|
138
|
+
parser.add_argument("--dry-run", action="store_true", help="Preview without copying")
|
|
139
|
+
args = parser.parse_args()
|
|
140
|
+
|
|
141
|
+
input_dir = Path(args.input).resolve()
|
|
142
|
+
output_dir = Path(args.output).resolve()
|
|
143
|
+
|
|
144
|
+
if not input_dir.exists():
|
|
145
|
+
print(f"Input directory not found: {input_dir}", file=sys.stderr)
|
|
146
|
+
return 1
|
|
147
|
+
|
|
148
|
+
# Load participant list
|
|
149
|
+
participant_list = None
|
|
150
|
+
if args.participants:
|
|
151
|
+
p_file = Path(args.participants).resolve()
|
|
152
|
+
if not p_file.exists():
|
|
153
|
+
print(f"Participant list not found: {p_file}", file=sys.stderr)
|
|
154
|
+
return 1
|
|
155
|
+
participant_list = [line.strip() for line in p_file.read_text().splitlines() if line.strip()]
|
|
156
|
+
print(f"Subject list: {len(participant_list)} subjects")
|
|
157
|
+
|
|
158
|
+
# Find subjects
|
|
159
|
+
subjects = find_subjects(input_dir, participant_list)
|
|
160
|
+
print(f"Found {len(subjects)} subject directories in {input_dir}")
|
|
161
|
+
|
|
162
|
+
if not subjects:
|
|
163
|
+
print("No subjects found. Check input directory structure.", file=sys.stderr)
|
|
164
|
+
return 1
|
|
165
|
+
|
|
166
|
+
if not args.dry_run:
|
|
167
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
168
|
+
|
|
169
|
+
# Process each subject
|
|
170
|
+
total_files = 0
|
|
171
|
+
all_warnings = []
|
|
172
|
+
for i, sub_dir in enumerate(subjects):
|
|
173
|
+
report = reorganize_subject(sub_dir, output_dir, dry_run=args.dry_run)
|
|
174
|
+
total_files += report["files_created"]
|
|
175
|
+
if report["warnings"]:
|
|
176
|
+
all_warnings.extend([f"{report['subject']}: {w}" for w in report["warnings"]])
|
|
177
|
+
if (i + 1) % 100 == 0 or (i + 1) == len(subjects):
|
|
178
|
+
print(f" Processed {i + 1}/{len(subjects)} subjects ({total_files} files)")
|
|
179
|
+
|
|
180
|
+
# Create dataset metadata
|
|
181
|
+
if not args.dry_run:
|
|
182
|
+
create_dataset_description(output_dir, len(subjects))
|
|
183
|
+
|
|
184
|
+
# Summary
|
|
185
|
+
print(f"\nBIDS Staging Summary:")
|
|
186
|
+
print(f" Subjects: {len(subjects)}")
|
|
187
|
+
print(f" Files created: {total_files}")
|
|
188
|
+
print(f" Output: {output_dir}")
|
|
189
|
+
if args.dry_run:
|
|
190
|
+
print(" [DRY RUN - no files were copied]")
|
|
191
|
+
|
|
192
|
+
if all_warnings:
|
|
193
|
+
print(f"\n Warnings ({len(all_warnings)}):")
|
|
194
|
+
for w in all_warnings[:20]:
|
|
195
|
+
print(f" - {w}")
|
|
196
|
+
if len(all_warnings) > 20:
|
|
197
|
+
print(f" ... and {len(all_warnings) - 20} more")
|
|
198
|
+
|
|
199
|
+
return 0
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
if __name__ == "__main__":
|
|
203
|
+
sys.exit(main())
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ixi-skill
|
|
3
|
+
description: "Use this skill whenever the user wants an end-to-end workflow for the IXI (Information eXtraction from Images) dataset, including data download, BIDS organization, and multimodal processing of T1w, T2w, and MRA. Triggers include: 'IXI', 'IXI dataset', 'process IXI data', 'IXI MRI', or any request to run the IXI 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
|
+
- bids-organizer
|
|
10
|
+
- claw-shell
|
|
11
|
+
complementary_skills:
|
|
12
|
+
- nibabel-skill
|
|
13
|
+
---
|
|
14
|
+
# IXI Skill (Dataset-Orchestration Layer)
|
|
15
|
+
|
|
16
|
+
## Overview
|
|
17
|
+
|
|
18
|
+
`ixi-skill` is the NeuroClaw orchestration skill for the **IXI (Information eXtraction from Images)** dataset.
|
|
19
|
+
|
|
20
|
+
It strictly follows the NeuroClaw hierarchical design principles:
|
|
21
|
+
- This skill **only describes WHAT needs to be done** and **which tool skill to delegate to**.
|
|
22
|
+
- It contains **no implementation code or concrete commands**.
|
|
23
|
+
- All concrete execution is delegated to existing base/tool skills via `claw-shell`.
|
|
24
|
+
- Companion scripts in `scripts/` provide reference implementations for data reorganization, phenotype extraction, and QC.
|
|
25
|
+
|
|
26
|
+
**Core workflow (never bypassed):**
|
|
27
|
+
1. Identify input IXI data and target modalities.
|
|
28
|
+
2. Generate a **numbered execution plan** clearly stating WHAT needs to be done and which tool skill will handle each step.
|
|
29
|
+
3. Present the full plan, estimated runtime, resource requirements, and risks to the user and wait for explicit confirmation ("YES" / "execute" / "proceed").
|
|
30
|
+
4. On confirmation, delegate every step to the appropriate skill via `claw-shell`.
|
|
31
|
+
5. After execution, save all outputs in a clean directory structure (`ixi_output/`).
|
|
32
|
+
|
|
33
|
+
**Research use only.**
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Quick Reference
|
|
38
|
+
|
|
39
|
+
| Task | What needs to be done | Delegate to | Expected output |
|
|
40
|
+
|---|---|---|---|
|
|
41
|
+
| Data download | Download IXI from brain-development.org | `claw-shell` | Raw IXI files |
|
|
42
|
+
| BIDS staging | Reorganize IXI native layout to BIDS | `scripts/reorganize_ixi.py` | BIDS-compliant dataset |
|
|
43
|
+
| sMRI processing | Brain extraction, tissue segmentation, cortical reconstruction | `smri-skill` | `smri_output/` derivatives |
|
|
44
|
+
| MRA processing | Vessel enhancement, angiography analysis | `nibabel-skill` | MRA derivatives |
|
|
45
|
+
| QC summary | Per-subject quality control | `scripts/ixi_qc_summary.py` | QC summary + exclusion list |
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Dataset Characteristics
|
|
50
|
+
|
|
51
|
+
- **Cohort**: ~600 healthy subjects
|
|
52
|
+
- **Sites**: 3 London hospitals with different scanners
|
|
53
|
+
- **Hammersmith Hospital (HH)**: Philips 3T
|
|
54
|
+
- **Guy's Hospital (Guy)**: Philips 1.5T
|
|
55
|
+
- **Institute of Psychiatry (IOP)**: GE 1.5T
|
|
56
|
+
- **Modalities**: T1w, T2w, MRA (some subjects also have PD and DTI)
|
|
57
|
+
- **Format**: NIfTI (.nii.gz)
|
|
58
|
+
- **Access**: https://brain-development.org/ixi-dataset/
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Supported Modalities
|
|
63
|
+
|
|
64
|
+
| Modality | Description | Sites |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| T1w | High-resolution structural MRI | All 3 sites |
|
|
67
|
+
| T2w | T2-weighted structural MRI | All 3 sites |
|
|
68
|
+
| MRA | Magnetic Resonance Angiography | All 3 sites |
|
|
69
|
+
| PD | Proton Density (some subjects) | Selected sites |
|
|
70
|
+
| DTI | Diffusion Tensor Imaging (some subjects) | Selected sites |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Site-Specific Scanner Information
|
|
75
|
+
|
|
76
|
+
| Site | Scanner | Field Strength | Notes |
|
|
77
|
+
|---|---|---|---|
|
|
78
|
+
| Hammersmith Hospital (HH) | Philips | 3T | Higher resolution, smaller voxel size |
|
|
79
|
+
| Guy's Hospital (Guy) | Philips | 1.5T | Standard resolution |
|
|
80
|
+
| Institute of Psychiatry (IOP) | GE | 1.5T | Standard resolution |
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## BIDS Preparation
|
|
85
|
+
|
|
86
|
+
### Script: `scripts/reorganize_ixi.py`
|
|
87
|
+
|
|
88
|
+
Converts IXI native directory structure to BIDS-compliant layout.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
python skills/ixi-skill/scripts/reorganize_ixi.py \
|
|
92
|
+
--input /path/to/IXI/raw \
|
|
93
|
+
--output /path/to/IXI/bids
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Features:
|
|
97
|
+
- Subject ID normalization: IXI format (e.g., `IXI002`) to BIDS `sub-IXI002`
|
|
98
|
+
- Site detection from subject ID prefix
|
|
99
|
+
- Modality routing: T1w, T2w, MRA, PD, DTI
|
|
100
|
+
- Sidecar JSON generation with site-specific metadata
|
|
101
|
+
- `dataset_description.json` and `participants.tsv` generation
|
|
102
|
+
- Dry-run mode: `--dry-run` to preview without copying
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Core Workflow (Never Bypassed)
|
|
107
|
+
|
|
108
|
+
1. Identify user target: full IXI processing, imaging subset, or BIDS staging only.
|
|
109
|
+
2. Generate a numbered plan with tools, outputs, runtime, storage, and risks.
|
|
110
|
+
3. Wait for explicit confirmation (`YES` / `execute` / `proceed`).
|
|
111
|
+
4. On confirmation, run download stage first (if needed).
|
|
112
|
+
5. After download success, run BIDS preparation using `scripts/reorganize_ixi.py`.
|
|
113
|
+
6. Delegate to `smri-skill` for structural MRI processing (T1w, T2w).
|
|
114
|
+
7. Process MRA if requested (vessel enhancement, angiography).
|
|
115
|
+
8. If QC summary is requested, run `scripts/ixi_qc_summary.py`.
|
|
116
|
+
9. Save outputs into `ixi_output/`.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Modality Processing Delegation
|
|
121
|
+
|
|
122
|
+
| Modality | Delegated skill | Typical tasks | Main outputs |
|
|
123
|
+
|---|---|---|---|
|
|
124
|
+
| sMRI (T1w/T2w) | `smri-skill` | brain extraction, tissue segmentation, cortical reconstruction | `smri_output/` derivatives |
|
|
125
|
+
| MRA | `nibabel-skill` | vessel enhancement, angiography analysis | MRA derivatives |
|
|
126
|
+
| PD | `smri-skill` | proton density analysis | PD derivatives |
|
|
127
|
+
| DTI | `smri-skill` | diffusion tensor metrics | DTI derivatives |
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Standard Output Layout
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
ixi_output/
|
|
135
|
+
├── raw/ # Downloaded original IXI files
|
|
136
|
+
├── bids/ # BIDS-staged data
|
|
137
|
+
├── smri/ # Structural MRI derivatives
|
|
138
|
+
├── mra/ # MRA derivatives
|
|
139
|
+
├── qc/ # QC summaries and exclusion lists
|
|
140
|
+
└── logs/ # Processing logs
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Benchmark Adapter Guidance
|
|
146
|
+
|
|
147
|
+
For benchmark-style prompts, do not force the full orchestration when the task only asks for local IXI data staging.
|
|
148
|
+
|
|
149
|
+
- If the task starts from raw IXI data already present on disk and only asks for BIDS-style staging:
|
|
150
|
+
- Skip the mandatory download stage
|
|
151
|
+
- Default to the narrow path `local raw IXI discovery -> BIDS-style staging -> minimal metadata -> validation/report`
|
|
152
|
+
- In benchmark mode, do not require explicit confirmation before presenting the direct staging solution.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Safety and Execution Policy
|
|
157
|
+
- No execution before explicit plan confirmation.
|
|
158
|
+
- All execution must be routed via `claw-shell`.
|
|
159
|
+
- Missing dependencies must be resolved by `dependency-planner` before running.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Important Notes and Limitations
|
|
164
|
+
- IXI is a multi-site dataset with different scanners; consider site effects in analysis.
|
|
165
|
+
- Site information can be inferred from subject ID prefix (HH, Guy, IOP).
|
|
166
|
+
- MRA data is unique to IXI; vessel analysis requires specialized tools.
|
|
167
|
+
- Some subjects may have missing modalities (PD, DTI).
|
|
168
|
+
- `ixi-skill` is orchestration-only; detailed preprocessing logic remains in modality skills.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## When to Call This Skill
|
|
173
|
+
- User asks for end-to-end IXI workflow.
|
|
174
|
+
- User asks to download IXI and run structural MRI processing.
|
|
175
|
+
- User needs BIDS staging for IXI data.
|
|
176
|
+
- User asks for multi-site brain MRI analysis.
|
|
177
|
+
- User asks for MRA vessel analysis.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Complementary / Related Skills
|
|
182
|
+
- `smri-skill` → structural MRI preprocessing
|
|
183
|
+
- `nibabel-skill` → NIfTI I/O and MRA processing
|
|
184
|
+
- `bids-organizer` → BIDS validation and organization
|
|
185
|
+
- `brain-visualization` → visualization of derivatives
|
|
186
|
+
- `dependency-planner` → dependency resolution
|
|
187
|
+
- `conda-env-manager` → environment management
|
|
188
|
+
- `claw-shell` → command execution
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Reference
|
|
193
|
+
- IXI Dataset: https://brain-development.org/ixi-dataset/
|
|
194
|
+
- Brain-development.org: https://brain-development.org/
|
|
195
|
+
|
|
196
|
+
Created At: 2026-05-06 13:31 HKT
|
|
197
|
+
Last Updated At: 2026-05-06 13:31 HKT
|
|
198
|
+
Author: chengwang96
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Generate per-subject QC summaries for IXI processing.
|
|
3
|
+
|
|
4
|
+
Multi-site aware: tracks site information and applies site-specific QC criteria.
|
|
5
|
+
"""
|
|
6
|
+
import argparse
|
|
7
|
+
import csv
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Dict, List
|
|
11
|
+
|
|
12
|
+
# Site mapping
|
|
13
|
+
SITE_MAP = {
|
|
14
|
+
"HH": {"name": "Hammersmith Hospital", "scanner": "Philips", "field_strength": "3T"},
|
|
15
|
+
"Guy": {"name": "Guy's Hospital", "scanner": "Philips", "field_strength": "1.5T"},
|
|
16
|
+
"IOP": {"name": "Institute of Psychiatry", "scanner": "GE", "field_strength": "1.5T"},
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def detect_site(subject_id: str) -> str:
|
|
21
|
+
"""Detect site from subject ID."""
|
|
22
|
+
clean_id = subject_id.replace("sub-", "")
|
|
23
|
+
for prefix in SITE_MAP:
|
|
24
|
+
if clean_id.startswith(prefix):
|
|
25
|
+
return prefix
|
|
26
|
+
return "Unknown"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def load_freesurfer_qc(fs_dir: Path, subject_id: str) -> Dict[str, float]:
|
|
30
|
+
"""Extract FreeSurfer QC metrics."""
|
|
31
|
+
metrics = {"fs_eTIV": float("nan")}
|
|
32
|
+
stats_file = fs_dir / subject_id / "stats" / "aseg.stats"
|
|
33
|
+
if stats_file.exists():
|
|
34
|
+
try:
|
|
35
|
+
for line in stats_file.read_text().splitlines():
|
|
36
|
+
if "EstimatedTotalIntraCranialVol" in line:
|
|
37
|
+
parts = line.split(",")
|
|
38
|
+
if len(parts) > 4:
|
|
39
|
+
metrics["fs_eTIV"] = float(parts[4].strip())
|
|
40
|
+
except Exception:
|
|
41
|
+
pass
|
|
42
|
+
return metrics
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def check_exclusion(metrics: Dict[str, float]) -> List[str]:
|
|
46
|
+
"""Check exclusion criteria."""
|
|
47
|
+
reasons = []
|
|
48
|
+
# IXI is healthy subjects; minimal exclusion criteria
|
|
49
|
+
return reasons
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def main() -> int:
|
|
53
|
+
parser = argparse.ArgumentParser(
|
|
54
|
+
description="Generate QC summaries for IXI processing."
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument("--fmriprep-dir", help="Path to fMRIPrep output directory")
|
|
57
|
+
parser.add_argument("--freesurfer-dir", help="Path to FreeSurfer output directory")
|
|
58
|
+
parser.add_argument("--output", required=True, help="Output path for QC summary CSV")
|
|
59
|
+
parser.add_argument("--exclude-output", help="Output path for exclusion list CSV")
|
|
60
|
+
args = parser.parse_args()
|
|
61
|
+
|
|
62
|
+
output_path = Path(args.output).resolve()
|
|
63
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
64
|
+
|
|
65
|
+
# Discover subjects
|
|
66
|
+
subjects = set()
|
|
67
|
+
if args.fmriprep_dir:
|
|
68
|
+
fmriprep_dir = Path(args.fmriprep_dir).resolve()
|
|
69
|
+
if fmriprep_dir.exists():
|
|
70
|
+
for d in fmriprep_dir.glob("sub-*"):
|
|
71
|
+
if d.is_dir():
|
|
72
|
+
subjects.add(d.name)
|
|
73
|
+
|
|
74
|
+
if args.freesurfer_dir:
|
|
75
|
+
fs_dir = Path(args.freesurfer_dir).resolve()
|
|
76
|
+
if fs_dir.exists():
|
|
77
|
+
for d in fs_dir.iterdir():
|
|
78
|
+
if d.is_dir() and not d.name.startswith("."):
|
|
79
|
+
subjects.add(f"sub-{d.name}" if not d.name.startswith("sub-") else d.name)
|
|
80
|
+
|
|
81
|
+
if not subjects:
|
|
82
|
+
print("[WARN] No subjects found.", file=sys.stderr)
|
|
83
|
+
return 1
|
|
84
|
+
|
|
85
|
+
results = []
|
|
86
|
+
excluded = []
|
|
87
|
+
for subj in sorted(subjects):
|
|
88
|
+
metrics = {"subject_id": subj}
|
|
89
|
+
|
|
90
|
+
# Detect site
|
|
91
|
+
site = detect_site(subj)
|
|
92
|
+
site_info = SITE_MAP.get(site, {"name": "Unknown", "scanner": "Unknown", "field_strength": "Unknown"})
|
|
93
|
+
metrics["site"] = site_info["name"]
|
|
94
|
+
metrics["scanner"] = site_info["scanner"]
|
|
95
|
+
metrics["field_strength"] = site_info["field_strength"]
|
|
96
|
+
|
|
97
|
+
if args.freesurfer_dir:
|
|
98
|
+
fs_id = subj.replace("sub-", "")
|
|
99
|
+
metrics.update(load_freesurfer_qc(Path(args.freesurfer_dir), fs_id))
|
|
100
|
+
|
|
101
|
+
exclusion_reasons = check_exclusion(metrics)
|
|
102
|
+
metrics["excluded"] = len(exclusion_reasons) > 0
|
|
103
|
+
metrics["exclusion_reasons"] = "; ".join(exclusion_reasons)
|
|
104
|
+
|
|
105
|
+
results.append(metrics)
|
|
106
|
+
if exclusion_reasons:
|
|
107
|
+
excluded.append({"subject_id": subj, "reasons": "; ".join(exclusion_reasons)})
|
|
108
|
+
|
|
109
|
+
if results:
|
|
110
|
+
fieldnames = list(results[0].keys())
|
|
111
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
112
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
113
|
+
writer.writeheader()
|
|
114
|
+
writer.writerows(results)
|
|
115
|
+
|
|
116
|
+
# Site summary
|
|
117
|
+
site_counts = {}
|
|
118
|
+
for r in results:
|
|
119
|
+
site = r.get("site", "Unknown")
|
|
120
|
+
site_counts[site] = site_counts.get(site, 0) + 1
|
|
121
|
+
|
|
122
|
+
print(f"QC: {len(results)} subjects, {len(excluded)} excluded -> {output_path}")
|
|
123
|
+
print(f" Sites: {site_counts}")
|
|
124
|
+
|
|
125
|
+
if args.exclude_output and excluded:
|
|
126
|
+
exclude_path = Path(args.exclude_output).resolve()
|
|
127
|
+
exclude_path.parent.mkdir(parents=True, exist_ok=True)
|
|
128
|
+
with open(exclude_path, "w", newline="", encoding="utf-8") as f:
|
|
129
|
+
writer = csv.DictWriter(f, fieldnames=["subject_id", "reasons"])
|
|
130
|
+
writer.writeheader()
|
|
131
|
+
writer.writerows(excluded)
|
|
132
|
+
|
|
133
|
+
return 0
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
if __name__ == "__main__":
|
|
137
|
+
sys.exit(main())
|