diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..7818d877 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,12 @@ +FROM ghcr.io/nipreps/petprep:main + +# Install sudo, git, vim, and htop (add any other dev or quality of life tools you'd like here) +RUN apt-get install -y sudo git vim htop + + +# Add petprep user to sudoers group and configure passwordless sudo for a more useful dev environment +RUN if id -u petprep > /dev/null 2>&1; then \ + usermod -aG sudo petprep 2>/dev/null || usermod -aG wheel petprep 2>/dev/null || true; \ + echo "petprep ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/petprep; \ + chmod 0440 /etc/sudoers.d/petprep; \ + fi diff --git a/.devcontainer/README.rst b/.devcontainer/README.rst new file mode 100644 index 00000000..bcfe75eb --- /dev/null +++ b/.devcontainer/README.rst @@ -0,0 +1,145 @@ +Development Container Setup +============================ + +This directory contains configuration files for running PETPrep in a Docker-based development container. +The devcontainer provides a pre-configured environment with all PETPrep dependencies, allowing you to +develop and test PETPrep without manually setting up the environment. For more information about devcontainers, see the `VS Code Dev Containers documentation +`__. or `Containers.dev `__. + +Prerequisites +------------- + +* VS Code or a VS Code-based IDE (such as Cursor, GitHub Codespaces, etc.) +* Docker Desktop installed and running +* The `Dev Containers` extension installed in VS Code +* A FreeSurfer license file (obtain one for free at https://surfer.nmr.mgh.harvard.edu/registration.html) + +Quick Start +----------- + +1. **Copy the example configuration:** + + .. code-block:: bash + + cp .devcontainer/example.devcontainer.json .devcontainer/devcontainer.json + +2. **Edit the mount points in ``.devcontainer/devcontainer.json``:** + + Open the file and update the following lines in the ``mounts`` array: + + * **Data directory mount** (line 8): Replace ``/FullPath/to/the/data/directory/contaning/your/bids/data`` + with the absolute path to directory containing bids data on your host machine. + + * **FreeSurfer license mount** (line 9): Replace ``/FullPath/to/your/freesurfer/license.txt`` + with the absolute path to your FreeSurfer license file on your host machine. + + Example for macOS: + + .. code-block:: json + + "mounts": [ + "source=/Users/yourusername/Data/my_bids_dataset,target=/data,type=bind,consistency=cached", + "source=/Applications/freesurfer/7.4.1/license.txt,target=/opt/freesurfer/license.txt,type=bind,consistency=cached,readonly=true" + ] + + Example for Linux: + + .. code-block:: json + + "mounts": [ + "source=/home/yourusername/data/my_bids_dataset,target=/data,type=bind,consistency=cached", + "source=/opt/freesurfer/license.txt,target=/opt/freesurfer/license.txt,type=bind,consistency=cached,readonly=true" + ] + +3. **Open the project in VS Code:** + + * Open VS Code + * Open the PETPrep repository folder + * VS Code should detect the ``.devcontainer/devcontainer.json`` file and prompt you to reopen in container + * Click "Reopen in Container" when prompted + + Alternatively, you can manually trigger the container: + + * Press ``Ctrl+Shift+P`` (or ``Cmd+Shift+P`` on macOS) to open the command palette + * Type "Dev Containers: Reopen in Container" and select it + +4. **Wait for the container to build and initialize:** + + * The first time will take longer as Docker downloads the PETPrep image + * The ``postCreateCommand`` will install PETPrep in editable mode with development dependencies + * You'll see progress in the VS Code terminal + +What's Included +--------------- + +The devcontainer provides: + +* **Pre-configured Python environment** with all PETPrep dependencies +* **Development tools**: ruff (linter), black (formatter), pytest (testing) +* **VS Code extensions**: Python, Pylance, Ruff, Black Formatter +* **Mounted data directory**: Your BIDS dataset accessible at ``/data`` +* **FreeSurfer license**: Automatically mounted for FreeSurfer workflows +* **TemplateFlow cache**: Pre-cached templates at ``/home/petprep/.cache/templateflow`` + +Configuration Details +--------------------- + +The devcontainer configuration includes: + +* **Image**: Uses the official PETPrep Docker image (``ghcr.io/nipreps/petprep:main``) +* **User**: Runs as ``petprep`` user (non-root for security) +* **Workspace**: Your code is mounted at ``/workspace`` +* **Python path**: ``/opt/conda/envs/petprep/bin/python`` +* **Environment variables**: + * ``TEMPLATEFLOW_HOME``: Set to ``/home/petprep/.cache/templateflow`` + * ``PYTHONPATH``: Includes ``/workspace`` for editable installs + +Troubleshooting +--------------- + +**Container won't start:** + * Ensure Docker Desktop is running + * Check that the paths in your ``devcontainer.json`` are correct and accessible + * Try rebuilding: Command Palette → "Dev Containers: Rebuild Container" + +**Permission errors:** + * The container runs as the ``petprep`` user + * If you need to install packages, use ``--user`` flag: ``pip install --user package_name`` + +**TemplateFlow path errors:** + * If you see errors about templateflow paths from your host machine, delete the ``work/`` directory: + ``rm -rf work/`` + * The container has templates pre-cached, so you don't need to mount your host templateflow cache + +**FreeSurfer license not found:** + * Verify the license file path in ``devcontainer.json`` is correct + * Ensure the file exists and is readable + * Check that the mount uses ``readonly=true`` for security + +**Package installation conflicts:** + * The container already has all runtime dependencies installed + * Use ``--no-deps`` when installing packages to avoid conflicts + * Development dependencies are installed via ``postCreateCommand`` + +Rebuilding the Container +------------------------ + +If you need to rebuild the container (e.g., after changing ``devcontainer.json``): + +1. Command Palette → "Dev Containers: Rebuild Container" +2. Or for a clean rebuild: "Dev Containers: Rebuild Container Without Cache" + +The container will be rebuilt and the ``postCreateCommand`` will run again. + +Additional Notes +---------------- + +* The ``devcontainer.json`` file is gitignored to prevent committing personal paths +* The ``example.devcontainer.json`` serves as a template for new users +* All changes made inside the container persist until you rebuild it +* The container uses the same image as the production PETPrep Docker image for consistency +* If you need to change the PETPrep version, you can change the image in the ``devcontainer.json`` file or +rebuild and tag the container with the same name and tag as the official PETPrep Docker image (``ghcr.io/nipreps/petprep:main``). + +For more information about devcontainers, see the `VS Code Dev Containers documentation +`__. diff --git a/.devcontainer/example.devcontainer.json b/.devcontainer/example.devcontainer.json new file mode 100644 index 00000000..5c2604ca --- /dev/null +++ b/.devcontainer/example.devcontainer.json @@ -0,0 +1,42 @@ +{ + "name": "PETPrep Development", + "image": "ghcr.io/nipreps/petprep:main", + "runArgs": [ + "--privileged" + ], + "mounts": [ + "source=/FullPath/to/the/data/directory/contaning/your/bids/data,target=/data,type=bind,consistency=cached", + "source=/FullPath/to/your/freesurfer/license.txt,target=/opt/freesurfer/license.txt,type=bind,consistency=cached" + ], + "overrideCommand": true, + "workspaceFolder": "/workspace", + "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind", + "remoteUser": "petprep", + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python", + "ms-python.debugpy", + "ms-python.vscode-pylance", + "charliermarsh.ruff", + "ms-python.black-formatter" + ], + "settings": { + "python.defaultInterpreterPath": "/opt/conda/envs/petprep/bin/python", + "python.terminal.activateEnvironment": false, + "python.linting.enabled": true, + "python.linting.ruffEnabled": true, + "python.formatting.provider": "black", + "editor.formatOnSave": true, + "files.eol": "\n" + } + } + }, + "postCreateCommand": "bash -c 'cd /workspace && pip install --user --ignore-installed --no-cache-dir -e .[dev,test]'", + "postStartCommand": "", + "remoteEnv": { + "PATH": "/home/petprep/.local/bin:/opt/conda/envs/petprep/bin:${containerEnv:PATH}", + "PYTHONPATH": "/workspace:${containerEnv:PYTHONPATH}", + "TEMPLATEFLOW_HOME": "/home/petprep/.cache/templateflow" + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index a06e6a49..74ec7823 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ dist/ .idea/ .env .envrc +.devcontainer/devcontainer.json # Additional .ipynb_checkpoints/