diff --git a/.github/workflows/publish_schema.yml b/.github/workflows/publish_schema.yml index c2528e02c4..532432e65e 100644 --- a/.github/workflows/publish_schema.yml +++ b/.github/workflows/publish_schema.yml @@ -4,6 +4,7 @@ on: push: branches: - "master" + - "maint/*" concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -34,13 +35,27 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3 + - run: env + - run: git status + - name: Determine master/maintenance branch + id: branch + run: | + if [[ "$GITHUB_REF_NAME" = "master" ]]; then + echo "branch=jsr-dist" | tee -a $GITHUB_OUTPUT + echo "mode=dev" | tee -a $GITHUB_OUTPUT + else + echo "branch=jsr-maint" | tee -a $GITHUB_OUTPUT + echo "mode=maint" | tee -a $GITHUB_OUTPUT + fi - name: Install bidsschematools run: | pip install --upgrade tools/schemacode git clean -fxd tools/schemacode - - name: Checkout jsr-dist + - name: Checkout ${{ steps.branch.outputs.branch }} run: | - git checkout -t origin/jsr-dist + git checkout -t origin/$JSR_BRANCH + env: + JSR_BRANCH: ${{ steps.branch.outputs.branch }} - name: Regenerate schema run: bst export > schema.json - name: Regenerate context types @@ -54,16 +69,23 @@ jobs: bst export-metaschema > /tmp/schema.json npx --package=json-schema-to-typescript json2ts --unknownAny /tmp/schema.json > metaschema.ts - name: Determine next version + id: version run: | BASE=$( jq -r .schema_version schema.json ) - if [[ "$BASE" =~ ^[0-9]*.[0-9]*.[0-9]*$ ]]; then + if [[ "$BASE" =~ ^[0-9]*\.[0-9]*\.[0-9]*$ ]]; then # Release, so unconditionally update version VERSION=$BASE jq ".version = \"$VERSION\"" jsr.json > tmp.json && mv tmp.json jsr.json - else + echo release=true | tee -a $GITHUB_OUTPUT + elif [[ "$BASE" =~ ^[0-9]*\.[0-9]*\.[0-9]*\.post[0-9]*$ ]]; then + # Post-release, so replace .post with + for JSR semver + VERSION=${BASE/.post/+} + jq ".version = \"$VERSION\"" jsr.json > tmp.json && mv tmp.json jsr.json + echo release=true | tee -a $GITHUB_OUTPUT + elif [[ "$GITHUB_REF_NAME" = "master" ]]; then DENOVER=$( jq -r .version jsr.json ) # Get the reference of the latest commit to touch the schema directory - HASH=$( git log -n 1 --pretty=%h $REF -- src/schema ) + HASH=$( git log -n 1 --pretty=%h $GITHUB_REF -- src/schema ) if [[ $DENOVER =~ ^"$BASE".[0-9] ]]; then PREFIX=${DENOVER%+*} let SERIAL=1+${PREFIX#$BASE.} @@ -71,19 +93,22 @@ jobs: SERIAL=1 fi VERSION="$BASE.$SERIAL+$HASH" + echo release=true | tee -a $GITHUB_OUTPUT + else + echo release=false | tee -a $GITHUB_OUTPUT fi echo VERSION=$VERSION | tee -a $GITHUB_ENV - env: - REF: ${{ github.ref }} - - name: Check for changes, set version and commit + echo version=$VERSION | tee -a $GITHUB_OUTPUT + - name: Bump version (${{ steps.version.outputs.version }}) if changed + if: steps.version.outputs.release == 'true' run: | if ! git diff -s --exit-code; then jq ".version = \"$VERSION\"" jsr.json > tmp.json && mv tmp.json jsr.json git add jsr.json schema.json context.ts metaschema.ts - git commit -m "Update schema JSR distribution" + git commit -m "Update schema JSR distribution ($VERSION)" git push fi - name: Publish to JSR - if: success() + if: success() && steps.version.outputs.release == 'true' run: | npx jsr publish diff --git a/.github/workflows/schemacode_ci.yml b/.github/workflows/schemacode_ci.yml index cff7d01d54..1515459d5b 100644 --- a/.github/workflows/schemacode_ci.yml +++ b/.github/workflows/schemacode_ci.yml @@ -4,10 +4,13 @@ on: push: branches: - "master" + - "maint/*" tags: - "schema-*" pull_request: branches: + - "master" + - "maint/*" - "*" concurrency: @@ -36,7 +39,9 @@ jobs: run: pip install --upgrade tools/schemacode[all] if: ${{ startsWith(github.ref, 'refs/tags/schema-') }} - name: "Build archive on tag" - run: pytest tools/schemacode/bidsschematools -k make_archive + run: | + python -m pytest -k make_archive + working-directory: tools/schemacode env: BIDSSCHEMATOOLS_RELEASE: 1 if: ${{ startsWith(github.ref, 'refs/tags/schema-') }} @@ -87,14 +92,15 @@ jobs: - name: "Run tests" run: | - python -m pytest -vs --pyargs bidsschematools -m "not validate_schema" \ - --cov-append --cov-report=xml --cov=bidsschematools --doctest-modules + python -m pytest -vs --doctest-modules -m "not validate_schema" \ + --cov-append --cov-report=xml --cov-report=term --cov=src/bidsschematools + working-directory: tools/schemacode - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: unit_${{ matrix.os }}_${{ matrix.python-version }} - path: coverage.xml + path: tools/schemacode/coverage.xml if: success() publish: @@ -143,13 +149,16 @@ jobs: python -m pip install -e ./tools/schemacode[all] - name: Run schema validation tests - run: python -m pytest --pyargs bidsschematools -m "validate_schema" --cov-append --cov-report=xml --cov=bidsschematools + run: | + python -m pytest -vs --doctest-modules -m "not validate_schema" \ + --cov-append --cov-report=xml --cov-report=term --cov=src/bidsschematools + working-directory: tools/schemacode - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: schema_validation - path: coverage.xml + path: tools/schemacode/coverage.xml if: success() upload_to_codecov: @@ -164,7 +173,7 @@ jobs: uses: actions/download-artifact@v4 - name: Upload to CodeCov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} # not required but might help API rate limits fail_ci_if_error: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 83f40fdbb4..80671a10d3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ # See https://pre-commit.com/hooks.html for more hooks ci: skip: [shellcheck] -exclude: 'tools/schemacode/bidsschematools/tests/data/broken_dataset_description.json' +exclude: 'tools/schemacode/src/bidsschematools/tests/data/broken_dataset_description.json' repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 @@ -16,7 +16,7 @@ repos: - id: check-added-large-files - id: check-case-conflict - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.29.4 + rev: 0.30.0 hooks: - id: check-dependabot - id: check-github-workflows @@ -89,7 +89,7 @@ repos: - types-jsonschema - jsonschema - httpx - args: ["tools/schemacode/bidsschematools"] + args: ["tools/schemacode/src"] pass_filenames: false - repo: https://github.com/koalaman/shellcheck-precommit rev: v0.10.0 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 2b3c46fdb8..0000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,49 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at `bids.maintenance+coc@gmail.com`. -The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. -The project team is obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f5d9cd972c..a6f712ebf1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,10 +8,10 @@ We hope that these guidelines are designed to make it as easy as possible to get If you have any questions that aren't discussed below, please let us know by [opening an issue](https://github.com/bids-standard/bids-specification/issues/new). -If you are not familiar with Git ansd GitHub, +If you are not familiar with Git and GitHub, check our [generic contributing guidelines](https://bids-website.readthedocs.io/en/latest/collaboration/bids_github/CONTRIBUTING.html). -If you want to contribute to the BIDS website, +If you want to contribute to the BIDS specification, make sure you also read the instructions below. ## Table of contents diff --git a/Release_Protocol.md b/Release_Protocol.md index c520fec053..f9857e715d 100644 --- a/Release_Protocol.md +++ b/Release_Protocol.md @@ -116,6 +116,10 @@ You can also make use of the `exclude-from-changelog` label. Adding this label to PRs in the GitHub web interface will prevent the changelog generator from considering this item for inclusion in the changelog. +#### 2.5 Update the schema + +Add the new version to `src/schema/meta/versions.yaml`. + ### 3. Commit changes and push to upstream By pushing `rel/` branches to the main repository, the chances of continuous integration diff --git a/readthedocs.yml b/readthedocs.yml index 5611c59505..1893f88d18 100644 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -1,12 +1,32 @@ version: 2 build: - os: ubuntu-22.04 - apt_packages: - - jq + os: ubuntu-lts-latest tools: - python: "3.11" + python: latest jobs: + # The *_create_environment and post_install steps replace RTD's virtual environment + # steps with uv, a much faster alternative to virtualenv+pip. + pre_create_environment: + # Install jq and uv + - asdf plugin add jq https://github.com/lsanwick/asdf-jq.git + - asdf plugin add uv https://github.com/asdf-community/asdf-uv.git + - asdf install jq latest + - asdf install uv latest + - asdf global jq latest + - asdf global uv latest + # Turn `python -m virtualenv` into `python -c pass` + - truncate --size 0 $( dirname $( uv python find ) )/../lib/python3*/site-packages/virtualenv/__main__.py + post_create_environment: + - uv venv $READTHEDOCS_VIRTUALENV_PATH + # Turn `python -m pip` into `python -c pass` + - truncate --size 0 $( ls -d $READTHEDOCS_VIRTUALENV_PATH/lib/python3* )/site-packages/pip.py + # post_install replaces the top-level {python: {install: [{requirements: requirements.txt}]}} + post_install: + # Use a cache dir in the same mount to halve the install time + - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH uv pip install --cache-dir $READTHEDOCS_VIRTUALENV_PATH/../../uv_cache -r requirements.txt + # Normal pre-build step to inject schema.json into the source directory + # so schema.json is hosted alongside the specification documents pre_build: - bst -v export --output src/schema.json - tools/no-bad-schema-paths.sh src/schema.json # README.md might need fixing @@ -14,7 +34,3 @@ build: mkdocs: configuration: mkdocs.yml fail_on_warning: true - -python: - install: - - requirements: requirements.txt diff --git a/src/derivatives/imaging.md b/src/derivatives/imaging.md index 4ba975824f..3a3b4bc280 100644 --- a/src/derivatives/imaging.md +++ b/src/derivatives/imaging.md @@ -229,7 +229,7 @@ vertices) or a combined volume/surface space. If the segmentation can be generated in different ways, for example, following an atlas segmentation, -the [`seg` entity](../appendices/entities.md#segmentation) MAY be used to +the [`seg` entity](../appendices/entities.md#seg) MAY be used to distinguish the name of the segmentation used. The following section describes discrete and probabilistic segmentations of @@ -293,7 +293,7 @@ In this case, the mask suffix MUST be used, the [`label` entity](../appendices/entities.md#label) SHOULD be used to specify the masked structure (see [Common image-derived labels](#common-image-derived-labels)), -and the [`seg` entity](../appendices/entities.md#segmentation) SHOULD be defined. +and the [`seg` entity](../appendices/entities.md#seg) SHOULD be defined. For example: diff --git a/src/modality-specific-files/behavioral-experiments.md b/src/modality-specific-files/behavioral-experiments.md index 70fa5ae3a6..c059383d0e 100644 --- a/src/modality-specific-files/behavioral-experiments.md +++ b/src/modality-specific-files/behavioral-experiments.md @@ -44,7 +44,7 @@ and a guide for using macros can be found at In addition to the metadata that is either: -- RECOMMENDED for sidecar JSON files for [tabular data](../common-principles.md#tabular-data), or +- RECOMMENDED for sidecar JSON files for [tabular data](../common-principles.md#tabular-files), or - REQUIRED for some data that can be found in the `beh` directory (for example `SamplingFrequency` and `StartTime` for `*_.tsv.gz` files), diff --git a/src/modality-specific-files/electroencephalography.md b/src/modality-specific-files/electroencephalography.md index 25a0fe72a2..fb15cb7710 100644 --- a/src/modality-specific-files/electroencephalography.md +++ b/src/modality-specific-files/electroencephalography.md @@ -272,7 +272,7 @@ Examples of free-form text for field `description` ### Example `*_channels.tsv` -See also the corresponding [`electrodes.tsv` example](#example-electrodestsv). +See also the corresponding [`electrodes.tsv` example](#example-_electrodestsv). ```Text name type units description reference status status_description @@ -316,7 +316,7 @@ If electrodes are repositioned, it is RECOMMENDED to use multiple sessions to in ### Example `*_electrodes.tsv` -See also the corresponding [`electrodes.tsv` example](#example-channelstsv). +See also the corresponding [`channels.tsv` example](#example-_channelstsv). ```Text name x y z type material diff --git a/src/modality-specific-files/magnetic-resonance-imaging-data.md b/src/modality-specific-files/magnetic-resonance-imaging-data.md index 2b2078fe04..a52c8f953b 100644 --- a/src/modality-specific-files/magnetic-resonance-imaging-data.md +++ b/src/modality-specific-files/magnetic-resonance-imaging-data.md @@ -11,7 +11,7 @@ MRI acquisition parameters are divided into several categories based on When adding additional metadata please use the CamelCase version of [DICOM ontology terms](https://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_d.html) whenever possible. See also -[recommendations on JSON files](../common-principles.md#keyvalue-files-dictionaries). +[recommendations on JSON files](../common-principles.md#key-value-files-dictionaries). ### Hardware information @@ -78,7 +78,7 @@ A guide for using macros can be found at 2Conveniently, for Siemens data, this value is easily obtained as `1 / (BWPPPE * ReconMatrixPE)`, where BWPPPE is the -"BandwidthPerPixelPhaseEncode" in DICOM Tag 0019, 1028 and ReconMatrixPE is +"BandwidthPerPixelPhaseEncode" in [DICOM Tag 0019, 1028](https://dicomlookup.com/dicomtags/(0019,1028)) and ReconMatrixPE is the size of the actual reconstructed data in the phase direction (which is NOT reflected in a single DICOM Tag for all possible aforementioned scan manipulations). See @@ -944,7 +944,7 @@ accompanied by two ancillary files: `*_asl.json` and `*_aslcontext.tsv`. The `*_aslcontext.tsv` table consists of a single column of labels identifying the `volume_type` of each volume in the corresponding `*_asl.nii[.gz]` file. -Volume types are defined in the following table, based on DICOM Tag 0018, 9257 `ASL Context`. +Volume types are defined in the following table, based on [DICOM Tag 0018, 9257](https://dicomlookup.com/dicomtags/(0018,9257)) `ASL Context`. Note that the volume_types `control` and `label` within BIDS only serve to specify the magnetization state of the blood and thus the ASL subtraction order. See the [ASL Appendix](../appendices/arterial-spin-labeling.md#which-image-is-control-and-which-is-label) @@ -1354,6 +1354,6 @@ See [Using `IntendedFor` metadata](#using-intendedfor-metadata) for details on the `IntendedFor` field. As for other EPI sequences, these field mapping sequences may have any of the -[in-plane spatial encoding](#in-plane-spatial-encoding) metadata keys. +[in-plane spatial encoding](#in-and-out-of-plane-spatial-encoding) metadata keys. However, please note that `PhaseEncodingDirection` and `TotalReadoutTime` keys are REQUIRED for these field mapping sequences. diff --git a/src/modality-specific-files/magnetoencephalography.md b/src/modality-specific-files/magnetoencephalography.md index ced4d6f3e7..319473b02f 100644 --- a/src/modality-specific-files/magnetoencephalography.md +++ b/src/modality-specific-files/magnetoencephalography.md @@ -187,7 +187,7 @@ A guide for using macros can be found at #### Specific EEG fields -If recorded with MEG, see [Recording EEG simultaneously with MEG](#recording-eeg-simultaneously-with-meg) +If recorded with MEG, see [Recording EEG simultaneously with MEG](#recording-ieeg-simultaneously-with-meg) SHOULD be present: