Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .codespellrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[codespell]
skip = CHANGELOG.md
ignore-words-list = nin, notIn
92 changes: 92 additions & 0 deletions .github/workflows/test_and_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Test and Release

on:
push:
branches: [main]
pull_request:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- uses: actions/setup-python@v6
with:
python-version: "3.12"

# Install and run pre-commit
- run: |
pip install pre-commit
pre-commit install
pre-commit run --all-files

pytest:
name: Pytest ${{ matrix.config.name }} ${{ matrix.python-version }}
runs-on: ${{ matrix.config.os }}

services:
mongo:
image: mongo:7
ports:
- 27017:27017

strategy:
fail-fast: false
matrix:
python-version: ["3.12"]
config:
- { name: "Linux", os: ubuntu-latest }

defaults:
run:
shell: bash

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Install system dependencies
if: matrix.config.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y \
libsdl2-ttf-2.0-0 \
libsdl2-2.0-0

- name: Install and Run Tests
run: |
python -m pip install --upgrade pip
python -m pip install ".[dev]"
python -m pytest -s tests

release:
needs: [pre-commit, pytest]
runs-on: ubuntu-latest
if: github.event_name == 'push'
environment: release
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
contents: write # IMPORTANT: mandatory for making GitHub Releases

steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Python Semantic Release
id: release
uses: python-semantic-release/python-semantic-release@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
81 changes: 81 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
ci:
autoupdate_commit_msg: "chore: update pre-commit hooks"
autofix_commit_msg: "style: pre-commit fixes"

exclude: ^.cruft.json|.copier-answers.yml$

repos:
- repo: https://github.com/adamchainz/blacken-docs
rev: "1.19.1"
hooks:
- id: blacken-docs
additional_dependencies: [black==24.*]

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: "v5.0.0"
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-merge-conflict
- id: check-symlinks
- id: check-yaml
- id: debug-statements
- id: end-of-file-fixer
- id: mixed-line-ending
- id: name-tests-test
args: ["--pytest-test-first"]
- id: requirements-txt-fixer
- id: trailing-whitespace

- repo: https://github.com/pre-commit/pygrep-hooks
rev: "v1.10.0"
hooks:
- id: rst-backticks
- id: rst-directive-colons
- id: rst-inline-touching-normal

- repo: https://github.com/rbubley/mirrors-prettier
rev: "v3.4.2"
hooks:
- id: prettier
types_or: [yaml, markdown, html, css, scss, javascript, json]
args: [--prose-wrap=always]

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.11.9"
hooks:
- id: ruff
args: ["--fix", "--show-fixes"]
- id: ruff-format
args: ["--line-length", "120"]

- repo: https://github.com/codespell-project/codespell
rev: "v2.3.0"
hooks:
- id: codespell

- repo: https://github.com/shellcheck-py/shellcheck-py
rev: "v0.10.0.1"
hooks:
- id: shellcheck

- repo: local
hooks:
- id: disallow-caps
name: Disallow improper capitalization
language: pygrep
entry: PyBind|Numpy|Cmake|CCache|Github|PyTest
exclude: .pre-commit-config.yaml

- repo: https://github.com/abravalheri/validate-pyproject
rev: "v0.23"
hooks:
- id: validate-pyproject
additional_dependencies: ["validate-pyproject-schema-store[all]"]

- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
rev: v9.20.0
hooks:
- id: commitlint
stages: [commit-msg]
additional_dependencies: ["@commitlint/config-conventional"]
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CHANGELOG.md
48 changes: 39 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
# GirderBIDS

Girder plugin to import a BIDS database
A Girder plugin providing support for working with datasets in the Brain Imaging
Data Structure (BIDS) format. The project includes:

- A Girder plugin for managing and handling BIDS datasets within Girder.
- A command-line interface (CLI) for validating and importing BIDS datasets into
a Girder instance (with or without the plugin).

## 1. Setup

### Ubuntu 22.04:

```bash
pip install -r requirements.txt
pip install ".[cli]"
```

### MacOS

```bash
curl -fsSL https://deno.land/install.sh | sh
deno compile -ERWN -o bids-validator jsr:@bids/validator
pip install girder girder-client fire
pip install ".[cli]"
```

### Windows
Not currently supported.

BIDS Validation is not supported but you can still use the plugin and the
importer (without validation)

```bash
pip install ".[cli]"
```

## 2. Build girder front

Expand All @@ -28,11 +41,15 @@ girder build
```

### MacOS
Install npm using Homebrew :

Install npm using Homebrew :

```bash
brew install node
```

Add the following environment variable:

```bash
export NODE_OPTIONS=--openssl-legacy-provider
```
Expand All @@ -44,6 +61,7 @@ girder build
## 3. Install mongodb

### Ubuntu 22.04

To set up MongoDB 4.4 on Ubuntu 22.04 execute the following commands :

```bash
Expand All @@ -61,7 +79,9 @@ chown -R mongodb:mongodb /var/lib/mongodb/*
```

### MacOS

Add MongoDB 4.4:

```bash
brew tap mongodb/brew
brew install mongodb-community@4.4
Expand All @@ -74,7 +94,8 @@ brew services start mongodb-community@4.4
girder serve
```

You can specify a database other than "girder" by creating a girder.cfg with following content:
You can specify a database other than "girder" by creating a girder.cfg with
following content:

```
[database]
Expand All @@ -88,14 +109,23 @@ GIRDER_CONFIG=./girder.cfg girder serve
```

## 4. Create admin account with "Register" on localhost:8080

## 5. Login and create API key

## 6. Create assetstore on localhost:8080
## 7. Create a Collection and a Folder in the collection, copy the ID of the created Folder

## 7. Create a Collection copy the ID of the created collection

## 8. Import BIDS database

```bash
python tools/bids-importer.py --bids_dir ... --girder_api_url http://localhost:8080/api/v1 --girder_api_key ... --girder_folder_id ...
bids-importer --bids_dir ... --api_url http://localhost:8080/api/v1 --api_key ... --location_id ...
```

If you want to ignore the validation step, pass `--ignore_validation` on the command-line.
If you want to ignore the validation step, pass `--ignore_validation` on the
command-line. If you need to upload the dataset directly under a collection or a
user, pass `--location_type {collection / user / folder}` (default is `folder`).
If you want to import the BIDS Dataset using the Girder Plugin, pass
`--use_plugin` on the command-line. If you want to copy BIDS JSON to Girder
metadata, pass `--extract_metadata` on the command-line (works only for
`dataset_description.json` and JSON sidecars).
17 changes: 17 additions & 0 deletions bids_plugin/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from typing import Any

from girder import plugin
from girder.utility.model_importer import ModelImporter

from .api import BIDSDatasetResource, BIDSFolderResource, BIDSItemResource
from .models import BIDSDatasetModel, BIDSFolderModel, BIDSItemModel


class BIDSPlugin(plugin.GirderPlugin):
def load(self, info: dict[str, Any]) -> None:
ModelImporter.registerModel("bids_dataset", BIDSDatasetModel, plugin="bids_plugin")
info["apiRoot"].bids_dataset = BIDSDatasetResource()
ModelImporter.registerModel("bids_folder", BIDSFolderModel, plugin="bids_plugin")
info["apiRoot"].bids_folder = BIDSFolderResource()
ModelImporter.registerModel("bids_item", BIDSItemModel, plugin="bids_plugin")
info["apiRoot"].bids_item = BIDSItemResource()
5 changes: 5 additions & 0 deletions bids_plugin/api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .bids_dataset import BIDSDatasetResource
from .bids_folder import BIDSFolderResource
from .bids_item import BIDSItemResource

__all__ = ["BIDSDatasetResource", "BIDSFolderResource", "BIDSItemResource"]
Loading