@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,190 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Reorganize IXI native layout to BIDS structure.
|
|
3
|
+
|
|
4
|
+
Converts IXI directory layout (e.g., IXI002/, IXI002-T1.nii.gz, IXI002-T2.nii.gz)
|
|
5
|
+
to BIDS-compliant structure (sub-IXI002/anat/).
|
|
6
|
+
"""
|
|
7
|
+
import argparse
|
|
8
|
+
import json
|
|
9
|
+
import shutil
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
# Site mapping based on subject ID prefix
|
|
14
|
+
SITE_MAP = {
|
|
15
|
+
"HH": {"name": "Hammersmith Hospital", "scanner": "Philips", "field_strength": "3T"},
|
|
16
|
+
"Guy": {"name": "Guy's Hospital", "scanner": "Philips", "field_strength": "1.5T"},
|
|
17
|
+
"IOP": {"name": "Institute of Psychiatry", "scanner": "GE", "field_strength": "1.5T"},
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def detect_site(subject_id: str) -> str:
|
|
22
|
+
"""Detect site from subject ID."""
|
|
23
|
+
for prefix in SITE_MAP:
|
|
24
|
+
if subject_id.startswith(prefix):
|
|
25
|
+
return prefix
|
|
26
|
+
return "Unknown"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def normalize_subject_id(ixi_id: str) -> str:
|
|
30
|
+
"""Convert IXI subject ID to BIDS format."""
|
|
31
|
+
return f"sub-{ixi_id.strip()}"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def find_subjects(input_dir: Path) -> list:
|
|
35
|
+
"""Find IXI subject files."""
|
|
36
|
+
# IXI files are typically named IXI002-T1.nii.gz, IXI002-T2.nii.gz, etc.
|
|
37
|
+
subjects = set()
|
|
38
|
+
for f in input_dir.glob("IXI*-*.nii.gz"):
|
|
39
|
+
# Extract subject ID (e.g., IXI002 from IXI002-T1.nii.gz)
|
|
40
|
+
parts = f.stem.split("-")
|
|
41
|
+
if len(parts) >= 2:
|
|
42
|
+
subjects.add(parts[0])
|
|
43
|
+
return sorted(list(subjects))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def reorganize_subject(input_dir: Path, subject_id: str, output_dir: Path, dry_run: bool = False) -> dict:
|
|
47
|
+
"""Reorganize a single IXI subject to BIDS."""
|
|
48
|
+
bids_id = normalize_subject_id(subject_id)
|
|
49
|
+
sub_dir = output_dir / bids_id
|
|
50
|
+
report = {"subject": subject_id, "files_created": 0, "warnings": []}
|
|
51
|
+
|
|
52
|
+
if not dry_run:
|
|
53
|
+
(sub_dir / "anat").mkdir(parents=True, exist_ok=True)
|
|
54
|
+
|
|
55
|
+
# Map IXI modality suffixes to BIDS
|
|
56
|
+
modality_map = {
|
|
57
|
+
"T1": "T1w",
|
|
58
|
+
"T2": "T2w",
|
|
59
|
+
"MRA": "MRA",
|
|
60
|
+
"PD": "PD",
|
|
61
|
+
"DTI": "dwi",
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
for ixi_suffix, bids_suffix in modality_map.items():
|
|
65
|
+
src_candidates = list(input_dir.glob(f"{subject_id}-{ixi_suffix}.nii.gz"))
|
|
66
|
+
if not src_candidates:
|
|
67
|
+
src_candidates = list(input_dir.glob(f"{subject_id}-{ixi_suffix.lower()}.nii.gz"))
|
|
68
|
+
|
|
69
|
+
for src in src_candidates:
|
|
70
|
+
if bids_suffix == "dwi":
|
|
71
|
+
dst = sub_dir / "dwi" / f"{bids_id}_{bids_suffix}.nii.gz"
|
|
72
|
+
if not dry_run:
|
|
73
|
+
(sub_dir / "dwi").mkdir(parents=True, exist_ok=True)
|
|
74
|
+
shutil.copy2(src, dst)
|
|
75
|
+
else:
|
|
76
|
+
dst = sub_dir / "anat" / f"{bids_id}_{bids_suffix}.nii.gz"
|
|
77
|
+
if not dry_run:
|
|
78
|
+
shutil.copy2(src, dst)
|
|
79
|
+
report["files_created"] += 1
|
|
80
|
+
|
|
81
|
+
# Check for missing modalities
|
|
82
|
+
if report["files_created"] == 0:
|
|
83
|
+
report["warnings"].append("No modality files found")
|
|
84
|
+
|
|
85
|
+
return report
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def create_dataset_description(output_dir: Path, n_subjects: int, sites: dict):
|
|
89
|
+
"""Create BIDS dataset_description.json."""
|
|
90
|
+
desc = {
|
|
91
|
+
"Name": "IXI (Information eXtraction from Images)",
|
|
92
|
+
"BIDSVersion": "1.8.0",
|
|
93
|
+
"DatasetType": "raw",
|
|
94
|
+
"License": "CC0",
|
|
95
|
+
"Authors": ["IXI Consortium"],
|
|
96
|
+
"HowToAcknowledge": "Please cite the IXI dataset.",
|
|
97
|
+
"ReferencesAndLinks": ["https://brain-development.org/ixi-dataset/"],
|
|
98
|
+
"Subjects": n_subjects,
|
|
99
|
+
"Sites": sites,
|
|
100
|
+
}
|
|
101
|
+
with open(output_dir / "dataset_description.json", "w", encoding="utf-8") as f:
|
|
102
|
+
json.dump(desc, f, indent=2)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def create_participants_tsv(output_dir: Path, subjects: list, input_dir: Path):
|
|
106
|
+
"""Create participants.tsv with site information."""
|
|
107
|
+
with open(output_dir / "participants.tsv", "w", newline="", encoding="utf-8") as f:
|
|
108
|
+
writer = csv.DictWriter(f, fieldnames=["participant_id", "site", "scanner", "field_strength"])
|
|
109
|
+
writer.writeheader()
|
|
110
|
+
for subj in subjects:
|
|
111
|
+
site = detect_site(subj)
|
|
112
|
+
site_info = SITE_MAP.get(site, {"name": "Unknown", "scanner": "Unknown", "field_strength": "Unknown"})
|
|
113
|
+
writer.writerow({
|
|
114
|
+
"participant_id": normalize_subject_id(subj),
|
|
115
|
+
"site": site_info["name"],
|
|
116
|
+
"scanner": site_info["scanner"],
|
|
117
|
+
"field_strength": site_info["field_strength"],
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def main() -> int:
|
|
122
|
+
parser = argparse.ArgumentParser(
|
|
123
|
+
description="Reorganize IXI native layout to BIDS."
|
|
124
|
+
)
|
|
125
|
+
parser.add_argument("--input", required=True, help="Path to IXI raw directory")
|
|
126
|
+
parser.add_argument("--output", required=True, help="Output BIDS directory")
|
|
127
|
+
parser.add_argument("--dry-run", action="store_true", help="Preview without copying")
|
|
128
|
+
args = parser.parse_args()
|
|
129
|
+
|
|
130
|
+
input_dir = Path(args.input).resolve()
|
|
131
|
+
output_dir = Path(args.output).resolve()
|
|
132
|
+
|
|
133
|
+
if not input_dir.exists():
|
|
134
|
+
print(f"Input directory not found: {input_dir}", file=sys.stderr)
|
|
135
|
+
return 1
|
|
136
|
+
|
|
137
|
+
# Find subjects
|
|
138
|
+
subjects = find_subjects(input_dir)
|
|
139
|
+
print(f"Found {len(subjects)} subjects in {input_dir}")
|
|
140
|
+
|
|
141
|
+
if not subjects:
|
|
142
|
+
print("No subjects found. Check input directory structure.", file=sys.stderr)
|
|
143
|
+
return 1
|
|
144
|
+
|
|
145
|
+
if not args.dry_run:
|
|
146
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
147
|
+
|
|
148
|
+
# Process each subject
|
|
149
|
+
total_files = 0
|
|
150
|
+
all_warnings = []
|
|
151
|
+
site_counts = {}
|
|
152
|
+
|
|
153
|
+
for i, subj in enumerate(subjects):
|
|
154
|
+
report = reorganize_subject(input_dir, subj, output_dir, dry_run=args.dry_run)
|
|
155
|
+
total_files += report["files_created"]
|
|
156
|
+
if report["warnings"]:
|
|
157
|
+
all_warnings.extend([f"{report['subject']}: {w}" for w in report["warnings"]])
|
|
158
|
+
|
|
159
|
+
# Track site counts
|
|
160
|
+
site = detect_site(subj)
|
|
161
|
+
site_counts[site] = site_counts.get(site, 0) + 1
|
|
162
|
+
|
|
163
|
+
if (i + 1) % 100 == 0 or (i + 1) == len(subjects):
|
|
164
|
+
print(f" Processed {i + 1}/{len(subjects)} subjects ({total_files} files)")
|
|
165
|
+
|
|
166
|
+
# Create metadata
|
|
167
|
+
if not args.dry_run:
|
|
168
|
+
create_dataset_description(output_dir, len(subjects), site_counts)
|
|
169
|
+
import csv
|
|
170
|
+
create_participants_tsv(output_dir, subjects, input_dir)
|
|
171
|
+
|
|
172
|
+
# Summary
|
|
173
|
+
print(f"\nBIDS Staging Summary:")
|
|
174
|
+
print(f" Subjects: {len(subjects)}")
|
|
175
|
+
print(f" Files created: {total_files}")
|
|
176
|
+
print(f" Sites: {site_counts}")
|
|
177
|
+
print(f" Output: {output_dir}")
|
|
178
|
+
if args.dry_run:
|
|
179
|
+
print(" [DRY RUN - no files were copied]")
|
|
180
|
+
|
|
181
|
+
if all_warnings:
|
|
182
|
+
print(f"\n Warnings ({len(all_warnings)}):")
|
|
183
|
+
for w in all_warnings[:20]:
|
|
184
|
+
print(f" - {w}")
|
|
185
|
+
|
|
186
|
+
return 0
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
if __name__ == "__main__":
|
|
190
|
+
sys.exit(main())
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mnd-skill
|
|
3
|
+
description: "Use this skill whenever the user wants an end-to-end workflow for the Motor Neuron Disease (MND) dataset from OpenNeuro ds005874, including BIDS validation, multimodal processing of rs-fMRI and task-fMRI, phenotype extraction, and QC integration. Triggers include: 'MND', 'Motor Neuron Disease', 'ALS', 'Amyotrophic Lateral Sclerosis', 'process MND data', 'MND fMRI', or any request to run the MND multimodal pipeline."
|
|
4
|
+
license: MIT License (NeuroClaw custom skill - freely modifiable within the project)
|
|
5
|
+
layer: subagent
|
|
6
|
+
skill_type: dataset
|
|
7
|
+
dependencies:
|
|
8
|
+
- smri-skill
|
|
9
|
+
- fmri-skill
|
|
10
|
+
- bids-organizer
|
|
11
|
+
- claw-shell
|
|
12
|
+
complementary_skills:
|
|
13
|
+
- brain-visualization
|
|
14
|
+
---
|
|
15
|
+
# MND Skill (Dataset-Orchestration Layer)
|
|
16
|
+
|
|
17
|
+
## Overview
|
|
18
|
+
|
|
19
|
+
`mnd-skill` is the NeuroClaw orchestration skill for the **Motor Neuron Disease (MND)** dataset from OpenNeuro ds005874.
|
|
20
|
+
|
|
21
|
+
It strictly follows the NeuroClaw hierarchical design principles:
|
|
22
|
+
- This skill **only describes WHAT needs to be done** and **which tool skill to delegate to**.
|
|
23
|
+
- It contains **no implementation code or concrete commands**.
|
|
24
|
+
- All concrete execution is delegated to existing base/tool skills via `claw-shell`.
|
|
25
|
+
- Companion scripts in `scripts/` provide reference implementations for BIDS validation, phenotype extraction, and QC.
|
|
26
|
+
|
|
27
|
+
**Core workflow (never bypassed):**
|
|
28
|
+
1. Identify input MND data and target modalities.
|
|
29
|
+
2. Generate a **numbered execution plan** clearly stating WHAT needs to be done and which tool skill will handle each step.
|
|
30
|
+
3. Present the full plan, estimated runtime, resource requirements, and risks to the user and wait for explicit confirmation ("YES" / "execute" / "proceed").
|
|
31
|
+
4. On confirmation, delegate every step to the appropriate skill via `claw-shell`.
|
|
32
|
+
5. After execution, save all outputs in a clean directory structure (`mnd_output/`).
|
|
33
|
+
|
|
34
|
+
**Research use only.**
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Quick Reference
|
|
39
|
+
|
|
40
|
+
| Task | What needs to be done | Delegate to | Expected output |
|
|
41
|
+
|---|---|---|---|
|
|
42
|
+
| BIDS validation | Validate MND BIDS structure | `scripts/validate_mnd.py` | Validation report |
|
|
43
|
+
| sMRI processing | Brain extraction, tissue segmentation | `smri-skill` | `smri_output/` derivatives |
|
|
44
|
+
| rs-fMRI processing | Preprocessing, denoising, connectivity | `fmri-skill` | `fmri_output/` derivatives |
|
|
45
|
+
| task-fMRI processing | Motor task GLM, activation analysis | `fmri-skill` | `fmri_output/` task results |
|
|
46
|
+
| Phenotype extraction | Diagnosis, clinical measures | `scripts/extract_mnd_phenotype.py` | Merged phenotype CSV |
|
|
47
|
+
| QC summary | Per-subject quality control | `scripts/mnd_qc_summary.py` | QC summary + exclusion list |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Dataset Characteristics
|
|
52
|
+
|
|
53
|
+
- **Cohort**: 59 participants
|
|
54
|
+
- **Patient group**: Motor Neuron Disease (e.g., ALS) patients
|
|
55
|
+
- **Control group**: Healthy age-matched controls
|
|
56
|
+
- **Modalities**: rs-fMRI, task-fMRI (motor tasks)
|
|
57
|
+
- **Format**: BIDS-compliant
|
|
58
|
+
- **Access**: OpenNeuro ds005874
|
|
59
|
+
- **License**: CC0
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Supported Modalities
|
|
64
|
+
|
|
65
|
+
| Modality | Description | Tasks/Conditions |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| rs-fMRI | Resting-state functional MRI | Eyes open/closed |
|
|
68
|
+
| task-fMRI | Task-based functional MRI | Motor tasks (finger tapping, hand grip) |
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## MND Task Paradigms
|
|
73
|
+
|
|
74
|
+
| Task | Description | Duration |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| REST | Resting-state (eyes open/closed) | ~8 min |
|
|
77
|
+
| MOTOR | Motor tasks (finger tapping, hand grip) | ~5 min |
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## BIDS Preparation
|
|
82
|
+
|
|
83
|
+
### Script: `scripts/validate_mnd.py`
|
|
84
|
+
|
|
85
|
+
Validates MND BIDS structure and generates a compliance report.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python skills/mnd-skill/scripts/validate_mnd.py \
|
|
89
|
+
--input /path/to/MND/bids \
|
|
90
|
+
--output /path/to/mnd_output/qc/bids_validation.csv
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Features:
|
|
94
|
+
- BIDS directory structure validation
|
|
95
|
+
- Modality completeness check (rs-fMRI, task-fMRI)
|
|
96
|
+
- Participant group labeling (patient vs. control)
|
|
97
|
+
- Missing data identification
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Core Workflow (Never Bypassed)
|
|
102
|
+
|
|
103
|
+
1. Identify user target: full MND processing, imaging subset, phenotype extraction, or BIDS validation only.
|
|
104
|
+
2. Generate a numbered plan with tools, outputs, runtime, storage, and risks.
|
|
105
|
+
3. Wait for explicit confirmation (`YES` / `execute` / `proceed`).
|
|
106
|
+
4. On confirmation, run BIDS validation using `scripts/validate_mnd.py`.
|
|
107
|
+
5. Delegate to `smri-skill` for structural MRI processing (if available).
|
|
108
|
+
6. Delegate to `fmri-skill` for functional MRI processing (resting-state and motor task).
|
|
109
|
+
7. If phenotype extraction is requested, run `scripts/extract_mnd_phenotype.py`.
|
|
110
|
+
8. If QC summary is requested, run `scripts/mnd_qc_summary.py`.
|
|
111
|
+
9. Save outputs into `mnd_output/`.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Modality Processing Delegation
|
|
116
|
+
|
|
117
|
+
| Modality | Delegated skill | Typical tasks | Main outputs |
|
|
118
|
+
|---|---|---|---|
|
|
119
|
+
| sMRI (T1w) | `smri-skill` | brain extraction, tissue segmentation | `smri_output/` derivatives |
|
|
120
|
+
| rs-fMRI | `fmri-skill` | preprocessing, denoising, connectivity | `fmri_output/` connectivity |
|
|
121
|
+
| task-fMRI | `fmri-skill` | motor task GLM, activation analysis | `fmri_output/` task results |
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Standard Output Layout
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
mnd_output/
|
|
129
|
+
├── bids/ # BIDS-staged data (or validation report)
|
|
130
|
+
├── smri/ # Structural MRI derivatives
|
|
131
|
+
├── fmri/ # Functional MRI derivatives (rest + motor)
|
|
132
|
+
├── phenotype/ # Merged phenotype tables (diagnosis, clinical)
|
|
133
|
+
├── qc/ # QC summaries and exclusion lists
|
|
134
|
+
└── logs/ # Processing logs
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Benchmark Adapter Guidance
|
|
140
|
+
|
|
141
|
+
For benchmark-style prompts, do not force the full orchestration when the task only asks for local MND data validation.
|
|
142
|
+
|
|
143
|
+
- If the task starts from MND data already present on disk and only asks for BIDS validation:
|
|
144
|
+
- Skip the download stage
|
|
145
|
+
- Default to the narrow path `local MND discovery -> BIDS validation -> report`
|
|
146
|
+
- In benchmark mode, do not require explicit confirmation before presenting the validation solution.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Safety and Execution Policy
|
|
151
|
+
- No execution before explicit plan confirmation.
|
|
152
|
+
- All execution must be routed via `claw-shell`.
|
|
153
|
+
- Missing dependencies must be resolved by `dependency-planner` before running.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Important Notes and Limitations
|
|
158
|
+
- MND is a clinical cohort; patient data requires careful handling.
|
|
159
|
+
- Case-control matching should be verified before group comparisons.
|
|
160
|
+
- Motor tasks are designed to probe motor network function; standard motor task GLM applies.
|
|
161
|
+
- The dataset is relatively small (59 participants); statistical power may be limited.
|
|
162
|
+
- `mnd-skill` is orchestration-only; detailed preprocessing logic remains in modality skills.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## When to Call This Skill
|
|
167
|
+
- User asks for end-to-end MND workflow.
|
|
168
|
+
- User asks to process MND fMRI data.
|
|
169
|
+
- User needs BIDS validation for MND data.
|
|
170
|
+
- User asks to extract MND phenotype data (diagnosis, clinical measures).
|
|
171
|
+
- User asks for motor network analysis in MND patients.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Complementary / Related Skills
|
|
176
|
+
- `smri-skill` → structural MRI preprocessing
|
|
177
|
+
- `fmri-skill` → functional MRI preprocessing and analysis
|
|
178
|
+
- `bids-organizer` → BIDS validation and organization
|
|
179
|
+
- `brain-visualization` → visualization of derivatives
|
|
180
|
+
- `dependency-planner` → dependency resolution
|
|
181
|
+
- `conda-env-manager` → environment management
|
|
182
|
+
- `claw-shell` → command execution
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Reference
|
|
187
|
+
- OpenNeuro ds005874: https://openneuro.org/datasets/ds005874
|
|
188
|
+
|
|
189
|
+
Created At: 2026-05-06 13:31 HKT
|
|
190
|
+
Last Updated At: 2026-05-06 13:31 HKT
|
|
191
|
+
Author: chengwang96
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Extract and merge MND phenotype data.
|
|
3
|
+
|
|
4
|
+
Reads MND phenotype files (diagnosis, clinical 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 MND 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
|
+
# Diagnosis
|
|
20
|
+
"diagnosis": ["diagnosis", "Diagnosis", "Group"],
|
|
21
|
+
"diagnosis_detail": ["diagnosis_detail", "Diagnosis_Detail"],
|
|
22
|
+
"patient_control": ["patient_control", "Patient_Control"],
|
|
23
|
+
# Clinical measures
|
|
24
|
+
"alsfrs_r": ["ALSFRS_R", "alsfrs_r_score"],
|
|
25
|
+
"alsfrs_r_total": ["ALSFRS_R_Total", "alsfrs_r_total"],
|
|
26
|
+
"disease_duration": ["disease_duration", "Disease_Duration"],
|
|
27
|
+
"onset_age": ["onset_age", "Onset_Age"],
|
|
28
|
+
"onset_site": ["onset_site", "Onset_Site"],
|
|
29
|
+
# Motor measures
|
|
30
|
+
"fvc_percent": ["FVC_Percent", "fvc_percent"],
|
|
31
|
+
"als_frs_bulbar": ["ALSFRS_Bulbar", "als_frs_bulbar"],
|
|
32
|
+
"als_frs_motor": ["ALSFRS_Motor", "als_frs_motor"],
|
|
33
|
+
"als_frs_respiratory": ["ALSFRS_Respiratory", "als_frs_respiratory"],
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def load_csv(path: Path) -> List[Dict[str, str]]:
|
|
38
|
+
"""Load CSV/TSV file and return list of dicts."""
|
|
39
|
+
delimiter = "\t" if path.suffix == ".tsv" else ","
|
|
40
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
41
|
+
reader = csv.DictReader(f, delimiter=delimiter)
|
|
42
|
+
return list(reader)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def find_column(row: Dict[str, str], candidates: List[str]) -> Optional[str]:
|
|
46
|
+
"""Find the first matching column name in a row."""
|
|
47
|
+
for col in candidates:
|
|
48
|
+
if col in row:
|
|
49
|
+
return col
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def extract_phenotype(
|
|
54
|
+
phenotype_files: List[Path],
|
|
55
|
+
imaging_ids: Optional[List[str]] = None,
|
|
56
|
+
columns: Optional[List[str]] = None,
|
|
57
|
+
) -> List[Dict[str, str]]:
|
|
58
|
+
"""Extract and merge phenotype data from multiple files."""
|
|
59
|
+
all_data = []
|
|
60
|
+
for fpath in phenotype_files:
|
|
61
|
+
rows = load_csv(fpath)
|
|
62
|
+
all_data.extend(rows)
|
|
63
|
+
|
|
64
|
+
if not all_data:
|
|
65
|
+
return []
|
|
66
|
+
|
|
67
|
+
target_columns = columns if columns else list(COLUMN_MAP.keys())
|
|
68
|
+
merged = {}
|
|
69
|
+
|
|
70
|
+
for row in all_data:
|
|
71
|
+
subj_col = find_column(row, COLUMN_MAP["subject_id"])
|
|
72
|
+
if subj_col is None:
|
|
73
|
+
continue
|
|
74
|
+
subj_id = row[subj_col].strip()
|
|
75
|
+
if not subj_id:
|
|
76
|
+
continue
|
|
77
|
+
|
|
78
|
+
if subj_id not in merged:
|
|
79
|
+
merged[subj_id] = {"subject_id": subj_id}
|
|
80
|
+
|
|
81
|
+
for target_col in target_columns:
|
|
82
|
+
if target_col == "subject_id":
|
|
83
|
+
continue
|
|
84
|
+
if target_col in merged[subj_id] and merged[subj_id][target_col]:
|
|
85
|
+
continue
|
|
86
|
+
candidates = COLUMN_MAP.get(target_col, [target_col])
|
|
87
|
+
src_col = find_column(row, candidates)
|
|
88
|
+
if src_col and row.get(src_col, "").strip():
|
|
89
|
+
merged[subj_id][target_col] = row[src_col].strip()
|
|
90
|
+
|
|
91
|
+
result = list(merged.values())
|
|
92
|
+
if imaging_ids:
|
|
93
|
+
imaging_set = set(imaging_ids)
|
|
94
|
+
result = [r for r in result if r["subject_id"] in imaging_set]
|
|
95
|
+
return result
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def main() -> int:
|
|
99
|
+
parser = argparse.ArgumentParser(
|
|
100
|
+
description="Extract MND phenotype data."
|
|
101
|
+
)
|
|
102
|
+
parser.add_argument("--phenotype-files", required=True, nargs="+",
|
|
103
|
+
help="Paths to MND phenotype CSV/TSV files")
|
|
104
|
+
parser.add_argument("--output", required=True, help="Output path for merged phenotype CSV")
|
|
105
|
+
parser.add_argument("--imaging-ids", help="Text file with imaging subject IDs to filter")
|
|
106
|
+
parser.add_argument("--columns", help="Comma-separated columns to extract")
|
|
107
|
+
args = parser.parse_args()
|
|
108
|
+
|
|
109
|
+
phenotype_files = [Path(f).resolve() for f in args.phenotype_files]
|
|
110
|
+
for f in phenotype_files:
|
|
111
|
+
if not f.exists():
|
|
112
|
+
print(f"File not found: {f}", file=sys.stderr)
|
|
113
|
+
return 1
|
|
114
|
+
|
|
115
|
+
imaging_ids = None
|
|
116
|
+
if args.imaging_ids:
|
|
117
|
+
id_file = Path(args.imaging_ids).resolve()
|
|
118
|
+
if id_file.exists():
|
|
119
|
+
imaging_ids = [l.strip() for l in id_file.read_text().splitlines() if l.strip()]
|
|
120
|
+
|
|
121
|
+
columns = None
|
|
122
|
+
if args.columns:
|
|
123
|
+
columns = [c.strip() for c in args.columns.split(",")]
|
|
124
|
+
|
|
125
|
+
merged = extract_phenotype(phenotype_files, imaging_ids, columns)
|
|
126
|
+
if not merged:
|
|
127
|
+
print("[ERROR] No phenotype data extracted.", file=sys.stderr)
|
|
128
|
+
return 1
|
|
129
|
+
|
|
130
|
+
output_path = Path(args.output).resolve()
|
|
131
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
132
|
+
fieldnames = list(merged[0].keys())
|
|
133
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
134
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
135
|
+
writer.writeheader()
|
|
136
|
+
writer.writerows(merged)
|
|
137
|
+
|
|
138
|
+
print(f"Phenotype: {len(merged)} subjects, {len(fieldnames)} columns -> {output_path}")
|
|
139
|
+
return 0
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
if __name__ == "__main__":
|
|
143
|
+
sys.exit(main())
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Generate per-subject QC summaries for MND processing.
|
|
3
|
+
|
|
4
|
+
Clinical-specific: tracks diagnosis group and applies appropriate 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
|
+
|
|
13
|
+
def load_confounds(confounds_path: Path) -> Dict[str, float]:
|
|
14
|
+
"""Extract QC metrics from fMRIPrep confounds TSV."""
|
|
15
|
+
metrics = {"fd_mean": float("nan"), "fd_max": float("nan")}
|
|
16
|
+
try:
|
|
17
|
+
import pandas as pd
|
|
18
|
+
df = pd.read_csv(confounds_path, sep="\t")
|
|
19
|
+
if "framewise_displacement" in df.columns:
|
|
20
|
+
fd = df["framewise_displacement"].dropna()
|
|
21
|
+
metrics["fd_mean"] = float(fd.mean())
|
|
22
|
+
metrics["fd_max"] = float(fd.max())
|
|
23
|
+
except Exception:
|
|
24
|
+
pass
|
|
25
|
+
return metrics
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def check_exclusion(metrics: Dict[str, float], fd_threshold: float = 0.3) -> List[str]:
|
|
29
|
+
"""Check exclusion criteria."""
|
|
30
|
+
reasons = []
|
|
31
|
+
if not (metrics["fd_mean"] != metrics["fd_mean"]):
|
|
32
|
+
if metrics["fd_mean"] > fd_threshold:
|
|
33
|
+
reasons.append(f"FD mean {metrics['fd_mean']:.3f} > {fd_threshold}")
|
|
34
|
+
return reasons
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def main() -> int:
|
|
38
|
+
parser = argparse.ArgumentParser(
|
|
39
|
+
description="Generate QC summaries for MND processing."
|
|
40
|
+
)
|
|
41
|
+
parser.add_argument("--fmriprep-dir", help="Path to fMRIPrep output directory")
|
|
42
|
+
parser.add_argument("--output", required=True, help="Output path for QC summary CSV")
|
|
43
|
+
parser.add_argument("--exclude-output", help="Output path for exclusion list CSV")
|
|
44
|
+
parser.add_argument("--fd-threshold", type=float, default=0.3,
|
|
45
|
+
help="FD threshold (default: 0.3 mm)")
|
|
46
|
+
parser.add_argument("--diagnosis-file", help="CSV with subject diagnosis info")
|
|
47
|
+
args = parser.parse_args()
|
|
48
|
+
|
|
49
|
+
output_path = Path(args.output).resolve()
|
|
50
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
51
|
+
|
|
52
|
+
# Load diagnosis info if available
|
|
53
|
+
diagnosis_map = {}
|
|
54
|
+
if args.diagnosis_file:
|
|
55
|
+
diag_path = Path(args.diagnosis_file).resolve()
|
|
56
|
+
if diag_path.exists():
|
|
57
|
+
with open(diag_path, "r", encoding="utf-8") as f:
|
|
58
|
+
reader = csv.DictReader(f)
|
|
59
|
+
for row in reader:
|
|
60
|
+
subj = row.get("subject_id") or row.get("Subject", "")
|
|
61
|
+
diag = row.get("diagnosis") or row.get("Diagnosis") or row.get("Group", "")
|
|
62
|
+
if subj and diag:
|
|
63
|
+
diagnosis_map[subj] = diag
|
|
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 not subjects:
|
|
75
|
+
print("[WARN] No subjects found.", file=sys.stderr)
|
|
76
|
+
return 1
|
|
77
|
+
|
|
78
|
+
results = []
|
|
79
|
+
excluded = []
|
|
80
|
+
for subj in sorted(subjects):
|
|
81
|
+
metrics = {"subject_id": subj}
|
|
82
|
+
|
|
83
|
+
# Add diagnosis if available
|
|
84
|
+
if diagnosis_map:
|
|
85
|
+
metrics["diagnosis"] = diagnosis_map.get(subj, "unknown")
|
|
86
|
+
|
|
87
|
+
if args.fmriprep_dir:
|
|
88
|
+
confounds_files = list(Path(args.fmriprep_dir).glob(f"{subj}/func/*_desc-confounds_timeseries.tsv"))
|
|
89
|
+
if confounds_files:
|
|
90
|
+
metrics.update(load_confounds(confounds_files[0]))
|
|
91
|
+
|
|
92
|
+
exclusion_reasons = check_exclusion(metrics, args.fd_threshold)
|
|
93
|
+
metrics["excluded"] = len(exclusion_reasons) > 0
|
|
94
|
+
metrics["exclusion_reasons"] = "; ".join(exclusion_reasons)
|
|
95
|
+
|
|
96
|
+
results.append(metrics)
|
|
97
|
+
if exclusion_reasons:
|
|
98
|
+
excluded.append({"subject_id": subj, "reasons": "; ".join(exclusion_reasons)})
|
|
99
|
+
|
|
100
|
+
if results:
|
|
101
|
+
fieldnames = list(results[0].keys())
|
|
102
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
103
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
104
|
+
writer.writeheader()
|
|
105
|
+
writer.writerows(results)
|
|
106
|
+
print(f"QC: {len(results)} subjects, {len(excluded)} excluded -> {output_path}")
|
|
107
|
+
|
|
108
|
+
if args.exclude_output and excluded:
|
|
109
|
+
exclude_path = Path(args.exclude_output).resolve()
|
|
110
|
+
exclude_path.parent.mkdir(parents=True, exist_ok=True)
|
|
111
|
+
with open(exclude_path, "w", newline="", encoding="utf-8") as f:
|
|
112
|
+
writer = csv.DictWriter(f, fieldnames=["subject_id", "reasons"])
|
|
113
|
+
writer.writeheader()
|
|
114
|
+
writer.writerows(excluded)
|
|
115
|
+
|
|
116
|
+
return 0
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
if __name__ == "__main__":
|
|
120
|
+
sys.exit(main())
|