Contributing to NiWrap
Thank you for your interest in contributing to NiWrap! This guide will help you understand how NiWrap works and how you can contribute to make it even better.
Overview
NiWrap is a collection of Boutiques descriptors for neuroimaging tools. If you've found a bug in one of the interfaces or you're missing an interface, you can either report it in the NiWrap issue tracker or attempt to fix it yourself by following this guide.
Table of Contents
- Understanding NiWrap and Boutiques
- Repository Structure
- Development Environment Setup
- Contributing Descriptors
- Working with Package Configurations
- Source Extraction
- Testing Your Changes
- Contribution Workflow
- Advanced Topics
- Getting Help
Understanding NiWrap and Boutiques
NiWrap is a collection of Boutiques descriptors for neuroimaging tools. These descriptors are used by the Styx compiler to generate type-safe language bindings in Python, TypeScript, and R.
What is Boutiques?
Boutiques is a JSON-based descriptive standard for command-line tools. It allows you to specify:
- Command-line arguments and their types
- Input and output files
- Dependencies between parameters
- Container configurations
- And much more
Boutiques descriptors serve as the "source of truth" for NiWrap, defining how each neuroimaging tool works and how users can interact with it.
Note: For a comprehensive guide to Boutiques concepts and advanced usage, see the Boutiques Guide section of this documentation.
Here's a simplified example of a Boutiques descriptor:
{
"name": "example_tool",
"description": "An example neuroimaging tool",
"tool-version": "1.0.0",
"command-line": "example_tool [INPUT] [OUTPUT] [OPTIONS]",
"inputs": [
{
"id": "input_file",
"name": "Input file",
"type": "File",
"value-key": "[INPUT]",
"optional": false
},
{
"id": "output_file",
"name": "Output file",
"type": "String",
"value-key": "[OUTPUT]",
"optional": false
},
{
"id": "verbose",
"name": "Verbose output",
"type": "Flag",
"command-line-flag": "-v",
"optional": true
}
],
"output-files": [
{
"id": "output",
"name": "Output file",
"path-template": "[OUTPUT]"
}
]
}
This descriptor defines a tool with an input file, output file, and a verbose flag. The Styx compiler transforms this into type-safe language bindings that users can call from their preferred programming language.
Repository Structure
The NiWrap repository is organized as follows:
niwrap/
├── build-templates/ # Templates used during the build process
├── build.py # Main build script for generating language bindings
├── descriptors/ # Boutiques descriptors for each tool
│ ├── afni/ # AFNI tools
│ ├── ants/ # ANTs tools
│ ├── fsl/ # FSL tools
│ └── ...
├── extraction/ # Tools for extracting parameter information
├── packages/ # Package configuration files
├── schemas/ # JSON schemas for validation
├── scripts/ # Utility scripts for maintaining descriptors
├── tests/ # Tests for descriptors
└── update_readme.py # Script to update the README with current tool coverage
Development Environment Setup
Setting up a proper development environment will make contributing to NiWrap more efficient.
Basic Setup
# Clone the repository
git clone https://github.com/styx-api/niwrap.git
cd niwrap
# Install required dependencies using pip
pip install pytest
pip install git+https://github.com/styx-api/styx.git
Note: A formal
requirements.txt
file may be added in the future. For now, installing pytest and the Styx compiler from GitHub should be sufficient for most development tasks.
VSCode JSON Schema Validation
Visual Studio Code users can enable automatic validation and autocompletion for Boutiques descriptors by configuring JSON schema validation:
- Create or open
.vscode/settings.json
in your NiWrap repository - Add the following configuration:
{
"json.schemas": [
{
"fileMatch": [
"descriptors/**/*.json"
],
"url": "./schemas/descriptor.schema.json"
}
]
}
This setup provides real-time feedback as you edit descriptor files, highlighting potential errors and offering suggestions based on the Boutiques schema.
Contributing Descriptors
The most common contribution to NiWrap is adding or improving Boutiques descriptors for neuroimaging tools.
Finding the Right Location
Descriptors are organized by tool suite in the descriptors/
directory:
descriptors/
├── afni/ # AFNI tools
├── ants/ # ANTs tools
├── fsl/ # FSL tools
├── mrtrix3/ # MRTrix3 tools
└── ...
Place your descriptor in the appropriate directory, or create a new directory if you're adding a tool from a new suite.
Fixing an Existing Descriptor
If you've found a bug in an existing tool interface, you'll need to modify its descriptor.
Example: Fixing a Parameter Type
Let's say you discovered that the fractional_intensity
parameter in FSL's BET tool should be a floating-point number between 0 and 1, but it's currently defined as an integer:
// Original descriptor (simplified)
{
"name": "bet",
"inputs": [
{
"id": "fractional_intensity",
"name": "Fractional intensity threshold",
"type": "Number",
"integer": true,
"minimum": 0,
"maximum": 1
}
]
}
To fix this, you'd change the descriptor to:
// Fixed descriptor
{
"name": "bet",
"inputs": [
{
"id": "fractional_intensity",
"name": "Fractional intensity threshold",
"type": "Number",
"integer": false,
"minimum": 0,
"maximum": 1
}
]
}
Adding a Missing Parameter
If a tool has a parameter that isn't exposed in NiWrap, you can add it to the descriptor.
Example: Adding a Missing Flag
Suppose FSL's FAST tool has a -N
flag for no bias field correction, but it's missing from the descriptor:
// Original descriptor (simplified)
{
"name": "fast",
"inputs": [
// existing parameters
]
}
You would add the new parameter:
// Updated descriptor
{
"name": "fast",
"inputs": [
// existing parameters
{
"id": "no_bias_field_correction",
"name": "No bias field correction",
"type": "Flag",
"command-line-flag": "-N",
"description": "Turns off bias field correction"
}
]
}
Creating a New Descriptor
If you want to add support for a completely new tool, you'll need to create a new descriptor from scratch.
Example: Creating a New Descriptor
Here's a simplified example of creating a descriptor for a fictional tool called brainanalyze
:
{
"name": "brainanalyze",
"tool-version": "1.0.0",
"description": "Analyzes brain structures in neuroimaging data",
"command-line": "brainanalyze [INPUT] [OUTPUT] [OPTIONS]",
"container-image": {
"image": "neuroimaging/brainanalyze:1.0.0",
"type": "docker"
},
"inputs": [
{
"id": "input_file",
"name": "Input file",
"type": "File",
"value-key": "[INPUT]",
"description": "Input neuroimaging file (NIFTI format)",
"optional": false
},
{
"id": "output_file",
"name": "Output file",
"type": "String",
"value-key": "[OUTPUT]",
"description": "Output file path",
"optional": false
},
{
"id": "smoothing",
"name": "Smoothing factor",
"type": "Number",
"value-key": "[OPTIONS]",
"command-line-flag": "-s",
"integer": false,
"minimum": 0,
"maximum": 10,
"description": "Smoothing factor (0-10)",
"optional": true,
"default-value": 2.5
}
],
"output-files": [
{
"id": "output",
"name": "Output file",
"path-template": "[OUTPUT]",
"description": "Output analysis file"
}
]
}
Working with Package Configurations
The packages/
directory contains package-level configuration files that define metadata for each neuroimaging tool suite.
Package Configuration Structure
A typical package configuration file looks like this:
{
"name": "FSL",
"author": "FMRIB Analysis Group, University of Oxford",
"url": "https://fsl.fmrib.ox.ac.uk/fsl/fslwiki",
"approach": "Manual",
"status": "Experimental",
"container": "brainlife/fsl:6.0.4-patched2",
"version": "6.0.5",
"description": "FSL is a comprehensive library of analysis tools for FMRI, MRI and diffusion brain imaging data.",
"id": "fsl",
"api": {
"endpoints": [
{
"target": "AnatomicalAverage",
"status": "done",
"descriptor": "descriptors/fsl/AnatomicalAverage.json"
},
// More endpoints...
]
}
}
The status
field in each endpoint entry can have one of three values:
"done"
: The descriptor is complete and ready for use"missing"
: The tool is identified but the descriptor is not yet created"ignore"
: The tool should be deliberately excluded from the API
Updating Package Configurations
When adding or modifying descriptors, remember to update the corresponding package configuration:
- For a new tool, add a new endpoint entry in the appropriate package file
- When updating a tool descriptor, ensure its status is set to
"done"
- If adding a new tool suite, create a new package configuration file
Source Extraction
NiWrap's extraction
directory contains specialized code that modifies the source code of neuroimaging toolboxes to programmatically extract tool information.
How Source Extraction Works
Source extraction involves:
- Modifying the original source code of a neuroimaging tool
- Adding instrumentation to dump tool information during compilation or runtime
- Capturing this information in a structured format that can be transformed into Boutiques descriptors
This is an advanced contribution area that typically requires:
- Understanding of the tool's source code and architecture
- Programming skills in the language the tool is written in
- Familiarity with the tool's command-line interface
Using LLM Prompts for Initial Descriptor Creation
The extraction
directory also contains LLM (Large Language Model) prompts that can help bootstrap the creation of descriptors:
-
Capture the help text of a neuroimaging tool:
mytool --help > tool_help.txt
-
Use the provided LLM prompts with a model like Claude or GPT to generate an initial Boutiques descriptor:
# Example prompt structure (check extraction directory for specifics) Given the following help text for a neuroimaging tool, create a Boutiques descriptor: [Paste help text]
-
Review and refine the generated descriptor to ensure accuracy
-
Place the final descriptor in the appropriate directory under
descriptors/
This approach is particularly useful for tools without structured extraction capabilities and can significantly speed up the initial descriptor creation process.
For Tool Maintainers
If you're a maintainer of a neuroimaging tool and would like to collaborate on better integration with NiWrap:
- We welcome direct collaboration on source extraction
- This can ensure that your tool's interface is accurately represented in NiWrap
- Contact the NiWrap team through GitHub issues to discuss collaboration opportunities
Testing Your Changes
After modifying or creating descriptors, you should test them to ensure they work correctly:
-
Use the NiWrap test suite:
# Run tests for a specific tool python -m pytest tests/test_descriptors.py::test_descriptor_validity::test_tool_descriptor
-
Build the project to check if your descriptors can be processed by Styx:
python build.py
Note: NiWrap does not use the original Boutiques runtime (
bosh
). All testing and validation should be done using NiWrap's own build and test utilities.
Contribution Workflow
Here's a step-by-step guide to contributing to NiWrap:
- Fork the repository: Create your own fork of NiWrap on GitHub
- Clone your fork:
git clone https://github.com/your-username/niwrap.git cd niwrap
- Create a branch:
git checkout -b fix-fsl-bet-descriptor
- Make changes: Modify or add descriptors in the appropriate directory
- Update package configuration: If necessary, update the corresponding package configuration file
- Test: Ensure your changes work correctly using the testing methods described above
- Commit your changes:
git add descriptors/fsl/bet.json packages/fsl.json git commit -m "Fix: Update FSL BET fractional intensity parameter type"
- Push your changes:
git push origin fix-fsl-bet-descriptor
- Submit a PR: Create a pull request on GitHub with a clear description of your changes
Advanced Topics
Adding a New Tool Suite
If you want to add support for an entirely new neuroimaging tool suite (e.g., adding a new package like SPM or BrainSuite):
- Create a new directory in
descriptors/
for the tool suite - Create descriptors for each tool you want to support
- Create a new package configuration file in
packages/
- Consider creating extraction scripts in the
extraction/
directory
Creating Helper Scripts
For complex tools, you might need to create helper scripts to streamline the creation of descriptors:
- Add your script to the
scripts/
directory - Document its usage in a comment at the top of the script
- Reference it in your pull request to help maintainers understand its purpose
Getting Help
If you're unsure about anything or need guidance, you can:
- Open an issue in the NiWrap issue tracker
- Check the Boutiques documentation
- Consult the Styx Book
- Review existing descriptors for similar tools as examples
Feel free to ask specific questions in your issue or pull request. The maintainers are happy to help guide you through the process.
Thank you for contributing to NiWrap and helping make neuroimaging analysis more accessible across multiple programming languages!