From 7ca422f9afea1171ac9ea863b02db2333c289eeb Mon Sep 17 00:00:00 2001 From: Cyril Pernet Date: Fri, 30 Jun 2023 14:43:44 +0200 Subject: [PATCH 01/43] define raw and derivatives.md follow the BIDS derivatives meeting --- src/derivatives/introduction.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/derivatives/introduction.md b/src/derivatives/introduction.md index c18e8d5190..7c98492fd9 100644 --- a/src/derivatives/introduction.md +++ b/src/derivatives/introduction.md @@ -1,12 +1,19 @@ # BIDS Derivatives -Derivatives are outputs of common processing pipelines, capturing data and +Derivatives are outputs of common processing pipelines, capturing data and meta-data sufficient for a researcher to understand and (critically) reuse those -outputs in subsequent processing. +outputs in subsequent processing. Standardizing derivatives is motivated by use cases where formalized -machine-readable access to processed data enables higher level processing. +machine-readable access to processed data enables higher-level processing. + +The following sections cover additions to and divergences from "raw" BIDS. Raw data are +data that have been curated to BIDS, i.e. a BIDS “raw” dataset does not have another BIDS +dataset as a source. If you are in doubt if your dataset is "raw" or +is "derivatives" ask yourself the following question: "Are my data derived from at least +one BIDS valid dataset?" if the answer is yes, then this is a BIDS derivative dataset. + +## Derivatives storage and folders structure -The following sections cover additions to and divergences from "raw" BIDS. Placement and naming conventions for derived datasets are addressed in [Storage of derived datasets][storage], and dataset-level metadata is included in [Derived dataset and pipeline description][derived-dataset-description]. From 38f40f390123a6635f111caf18a9506dd545ebd4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 12:47:18 +0000 Subject: [PATCH 02/43] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/derivatives/introduction.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/derivatives/introduction.md b/src/derivatives/introduction.md index 7c98492fd9..7258dbbccb 100644 --- a/src/derivatives/introduction.md +++ b/src/derivatives/introduction.md @@ -1,16 +1,16 @@ # BIDS Derivatives -Derivatives are outputs of common processing pipelines, capturing data and +Derivatives are outputs of common processing pipelines, capturing data and meta-data sufficient for a researcher to understand and (critically) reuse those -outputs in subsequent processing. +outputs in subsequent processing. Standardizing derivatives is motivated by use cases where formalized machine-readable access to processed data enables higher-level processing. -The following sections cover additions to and divergences from "raw" BIDS. Raw data are +The following sections cover additions to and divergences from "raw" BIDS. Raw data are data that have been curated to BIDS, i.e. a BIDS “raw” dataset does not have another BIDS dataset as a source. If you are in doubt if your dataset is "raw" or is "derivatives" ask yourself the following question: "Are my data derived from at least -one BIDS valid dataset?" if the answer is yes, then this is a BIDS derivative dataset. +one BIDS valid dataset?" if the answer is yes, then this is a BIDS derivative dataset. ## Derivatives storage and folders structure From 7dd3d17b440c7210755e6ac109dd5c66dc9059e9 Mon Sep 17 00:00:00 2001 From: Cyril Pernet Date: Fri, 30 Jun 2023 15:57:20 +0200 Subject: [PATCH 03/43] Update src/derivatives/introduction.md Co-authored-by: Yaroslav Halchenko --- src/derivatives/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/derivatives/introduction.md b/src/derivatives/introduction.md index 7258dbbccb..c6657d21cd 100644 --- a/src/derivatives/introduction.md +++ b/src/derivatives/introduction.md @@ -10,7 +10,7 @@ The following sections cover additions to and divergences from "raw" BIDS. Raw d data that have been curated to BIDS, i.e. a BIDS “raw” dataset does not have another BIDS dataset as a source. If you are in doubt if your dataset is "raw" or is "derivatives" ask yourself the following question: "Are my data derived from at least -one BIDS valid dataset?" if the answer is yes, then this is a BIDS derivative dataset. +one other valid BIDS dataset?" if the answer is yes, then this is a BIDS derivative dataset. ## Derivatives storage and folders structure From 90b887480736b3e9d80ddf13d4428bac931fe10c Mon Sep 17 00:00:00 2001 From: Cyril Pernet Date: Wed, 5 Jul 2023 20:56:25 +0200 Subject: [PATCH 04/43] Update introduction.md add examples --- src/derivatives/introduction.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/derivatives/introduction.md b/src/derivatives/introduction.md index c6657d21cd..a1d0895f44 100644 --- a/src/derivatives/introduction.md +++ b/src/derivatives/introduction.md @@ -12,6 +12,18 @@ dataset as a source. If you are in doubt if your dataset is "raw" or is "derivatives" ask yourself the following question: "Are my data derived from at least one other valid BIDS dataset?" if the answer is yes, then this is a BIDS derivative dataset. +Examples: + +A defaced T1w image would typically be made during the curation process and is thus under raw + +`sourcedata/private/sub-01/anat/sub-01_T1w.nii.gz` +`sub-01/anat/sub-01_desc-defaced_T1w.nii.gz` + +A defaced T1w image could also, in theory, be derived from a BIDS dataset and would thus be under derivatives + +`sub-01/anat/sub-01_T1w.nii.gz` +`derivatives/sub-01/anat/sub-01_desc-defaced_T1w.nii.gz` + ## Derivatives storage and folders structure Placement and naming conventions for derived datasets are addressed in From 32b6cd4b0b2441bd2c087fa6a1ba50e6cf3ea787 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 18:56:45 +0000 Subject: [PATCH 05/43] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/derivatives/introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/derivatives/introduction.md b/src/derivatives/introduction.md index a1d0895f44..bcfab302c5 100644 --- a/src/derivatives/introduction.md +++ b/src/derivatives/introduction.md @@ -16,12 +16,12 @@ Examples: A defaced T1w image would typically be made during the curation process and is thus under raw -`sourcedata/private/sub-01/anat/sub-01_T1w.nii.gz` +`sourcedata/private/sub-01/anat/sub-01_T1w.nii.gz` `sub-01/anat/sub-01_desc-defaced_T1w.nii.gz` A defaced T1w image could also, in theory, be derived from a BIDS dataset and would thus be under derivatives -`sub-01/anat/sub-01_T1w.nii.gz` +`sub-01/anat/sub-01_T1w.nii.gz` `derivatives/sub-01/anat/sub-01_desc-defaced_T1w.nii.gz` ## Derivatives storage and folders structure From 64bd1c811e42524146d48b33c7e6a4b788b955f3 Mon Sep 17 00:00:00 2001 From: Cyril Pernet Date: Mon, 10 Jul 2023 14:39:38 +0200 Subject: [PATCH 06/43] Update src/derivatives/introduction.md Co-authored-by: Chris Markiewicz --- src/derivatives/introduction.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/derivatives/introduction.md b/src/derivatives/introduction.md index bcfab302c5..1a2bd1189a 100644 --- a/src/derivatives/introduction.md +++ b/src/derivatives/introduction.md @@ -21,8 +21,10 @@ A defaced T1w image would typically be made during the curation process and is t A defaced T1w image could also, in theory, be derived from a BIDS dataset and would thus be under derivatives -`sub-01/anat/sub-01_T1w.nii.gz` -`derivatives/sub-01/anat/sub-01_desc-defaced_T1w.nii.gz` +``` +sub-01/anat/sub-01_T1w.nii.gz +derivatives/sub-01/anat/sub-01_desc-defaced_T1w.nii.gz +``` ## Derivatives storage and folders structure From 583590a83863e704fcb6877d8017871cef2be578 Mon Sep 17 00:00:00 2001 From: Cyril Pernet Date: Mon, 10 Jul 2023 14:39:57 +0200 Subject: [PATCH 07/43] Update src/derivatives/introduction.md Co-authored-by: Chris Markiewicz --- src/derivatives/introduction.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/derivatives/introduction.md b/src/derivatives/introduction.md index 1a2bd1189a..9b3b61dd49 100644 --- a/src/derivatives/introduction.md +++ b/src/derivatives/introduction.md @@ -6,11 +6,9 @@ outputs in subsequent processing. Standardizing derivatives is motivated by use cases where formalized machine-readable access to processed data enables higher-level processing. -The following sections cover additions to and divergences from "raw" BIDS. Raw data are -data that have been curated to BIDS, i.e. a BIDS “raw” dataset does not have another BIDS -dataset as a source. If you are in doubt if your dataset is "raw" or -is "derivatives" ask yourself the following question: "Are my data derived from at least -one other valid BIDS dataset?" if the answer is yes, then this is a BIDS derivative dataset. +The following sections cover additions to and divergences from "raw" BIDS. +Raw data are data that have been curated into BIDS from a non-BIDS source. +If a dataset is derived from at least one other valid BIDS dataset, then it is a derivative dataset. Examples: From 5e2f7901cef64cda32848e596dea8cb4bbd37141 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:36:28 +0200 Subject: [PATCH 08/43] [pre-commit.ci] pre-commit autoupdate (#1546) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.3.0 → 23.7.0](https://github.com/psf/black/compare/23.3.0...23.7.0) - [github.com/pre-commit/mirrors-prettier: v3.0.0-alpha.9-for-vscode → v3.0.0](https://github.com/pre-commit/mirrors-prettier/compare/v3.0.0-alpha.9-for-vscode...v3.0.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7252578bef..53baab42b6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,7 @@ repos: - id: check-added-large-files - id: check-case-conflict - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 23.7.0 hooks: - id: black files: ^tools/(?!schemacode) @@ -38,7 +38,7 @@ repos: - id: flake8 args: [--config=tools/schemacode/setup.cfg] - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.0.0-alpha.9-for-vscode + rev: v3.0.0 hooks: - id: prettier files: src/schema/.*/.*\.yaml From e05ba9321daaf9156146ed36c03fdc8e2ae1fb43 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Tue, 11 Jul 2023 10:28:42 -0400 Subject: [PATCH 09/43] [FIX] Update links to BIDS examples (#1545) --- src/appendices/qmri.md | 2 +- src/modality-specific-files/electroencephalography.md | 2 +- .../intracranial-electroencephalography.md | 2 +- .../magnetic-resonance-imaging-data.md | 4 ++-- src/modality-specific-files/magnetoencephalography.md | 2 +- src/modality-specific-files/microscopy.md | 2 +- src/modality-specific-files/motion.md | 2 +- src/modality-specific-files/near-infrared-spectroscopy.md | 2 +- .../physiological-and-other-continuous-recordings.md | 2 +- src/modality-specific-files/positron-emission-tomography.md | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/appendices/qmri.md b/src/appendices/qmri.md index dc85f678e0..d174bd6421 100644 --- a/src/appendices/qmri.md +++ b/src/appendices/qmri.md @@ -195,7 +195,7 @@ It is RECOMMENDED to share them along with the vendor outputs, whenever possible ### Example datasets You can find example file collections and qMRI maps organized according to BIDS -in the [BIDS examples](https://github.com/bids-standard/bids-examples#qmri-datasets). +in the [BIDS examples](https://bids-standard.github.io/bids-examples/#qmri). ## Metadata requirements for qMRI data diff --git a/src/modality-specific-files/electroencephalography.md b/src/modality-specific-files/electroencephalography.md index 88ea187deb..781993e1bc 100644 --- a/src/modality-specific-files/electroencephalography.md +++ b/src/modality-specific-files/electroencephalography.md @@ -6,7 +6,7 @@ Please see [Citing BIDS](../introduction.md#citing-bids) on how to appropriately credit this extension when referring to it in the context of the academic literature. -Several [example EEG datasets](https://github.com/bids-standard/bids-examples#eeg-datasets) +Several [example EEG datasets](https://bids-standard.github.io/bids-examples/#eeg) have been formatted using this specification and can be used for practical guidance when curating a new dataset. diff --git a/src/modality-specific-files/intracranial-electroencephalography.md b/src/modality-specific-files/intracranial-electroencephalography.md index 3e961ad704..56d047a6b6 100644 --- a/src/modality-specific-files/intracranial-electroencephalography.md +++ b/src/modality-specific-files/intracranial-electroencephalography.md @@ -6,7 +6,7 @@ Please see [Citing BIDS](../introduction.md#citing-bids) on how to appropriately credit this extension when referring to it in the context of the academic literature. -Several [example iEEG datasets](https://github.com/bids-standard/bids-examples#ieeg-datasets) +Several [example iEEG datasets](https://bids-standard.github.io/bids-examples/#ieeg) have been formatted using this specification and can be used for practical guidance when curating a new dataset. diff --git a/src/modality-specific-files/magnetic-resonance-imaging-data.md b/src/modality-specific-files/magnetic-resonance-imaging-data.md index 953e9f2cc9..7099836c40 100644 --- a/src/modality-specific-files/magnetic-resonance-imaging-data.md +++ b/src/modality-specific-files/magnetic-resonance-imaging-data.md @@ -852,7 +852,7 @@ JSON example: ## Arterial Spin Labeling perfusion data -Several [example ASL datasets](https://github.com/bids-standard/bids-examples#asl-datasets) +Several [example ASL datasets](https://bids-standard.github.io/bids-examples/#asl) have been formatted using this specification and can be used for practical guidance when curating a new dataset. @@ -1095,7 +1095,7 @@ For example: #### Case 1: Phase-difference map and at least one magnitude image -[Example datasets](https://github.com/bids-standard/bids-examples) +[Example datasets](https://bids-standard.github.io/bids-examples/#dataset-index) containing that type of fieldmap can be found here: - [`7t_trt`](https://github.com/bids-standard/bids-examples/tree/master/7t_trt) diff --git a/src/modality-specific-files/magnetoencephalography.md b/src/modality-specific-files/magnetoencephalography.md index 6f0b4c0baa..c85e20f7ce 100644 --- a/src/modality-specific-files/magnetoencephalography.md +++ b/src/modality-specific-files/magnetoencephalography.md @@ -12,7 +12,7 @@ and can be used for practical guidance when curating a new dataset. - [`multimodal MEG and MRI`](https://github.com/bids-standard/bids-examples/tree/master/ds000117) Further datasets are available from -the [BIDS examples repository](https://github.com/bids-standard/bids-examples). +the [BIDS examples repository](https://bids-standard.github.io/bids-examples/#meg). ## MEG recording data diff --git a/src/modality-specific-files/microscopy.md b/src/modality-specific-files/microscopy.md index 4c56cea6eb..f70e521321 100644 --- a/src/modality-specific-files/microscopy.md +++ b/src/modality-specific-files/microscopy.md @@ -8,7 +8,7 @@ on how to appropriately credit this extension when referring to it in the context of the academic literature. Microscopy datasets formatted using this specification are available on the -[BIDS examples repository](https://github.com/bids-standard/bids-examples#microscopy-datasets) +[BIDS examples repository](https://bids-standard.github.io/bids-examples/#microscopy) and can be used for practical guidance when curating a new dataset. Further Microscopy datasets are available: diff --git a/src/modality-specific-files/motion.md b/src/modality-specific-files/motion.md index 1c83de6fe0..1e151baef9 100644 --- a/src/modality-specific-files/motion.md +++ b/src/modality-specific-files/motion.md @@ -3,7 +3,7 @@ For information on how to cite this extension when referencing it in the context of the academic literature, please read [Citing BIDS](../introduction.md#citing-bids). Motion datasets formatted using this specification are available on the -[BIDS examples repository](https://github.com/bids-standard/bids-examples#motion-datasets) +[BIDS examples repository](https://bids-standard.github.io/bids-examples/#motion) and can be used as helpful guidance when curating new datasets. ## Motion recording data diff --git a/src/modality-specific-files/near-infrared-spectroscopy.md b/src/modality-specific-files/near-infrared-spectroscopy.md index 90f7eb0fd0..1947836c17 100644 --- a/src/modality-specific-files/near-infrared-spectroscopy.md +++ b/src/modality-specific-files/near-infrared-spectroscopy.md @@ -6,7 +6,7 @@ Please see [Citing BIDS](../introduction.md#citing-bids) on how to appropriately credit this extension when referring to it in the context of the academic literature. -Several [example NIRS datasets](https://github.com/bids-standard/bids-examples#nirs-datasets) +Several [example NIRS datasets](https://bids-standard.github.io/bids-examples/#nirs) have been formatted using this specification and can be used for practical guidance when curating a new dataset. ## NIRS recording data diff --git a/src/modality-specific-files/physiological-and-other-continuous-recordings.md b/src/modality-specific-files/physiological-and-other-continuous-recordings.md index 4df83b9999..72df5d4814 100644 --- a/src/modality-specific-files/physiological-and-other-continuous-recordings.md +++ b/src/modality-specific-files/physiological-and-other-continuous-recordings.md @@ -9,7 +9,7 @@ specified using two files: 1. a JSON file for storing metadata fields (see below) -[Example datasets](https://github.com/bids-standard/bids-examples) +[Example datasets](https://bids-standard.github.io/bids-examples/#dataset-index) with physiological data have been formatted using this specification and can be used for practical guidance when curating a new dataset: diff --git a/src/modality-specific-files/positron-emission-tomography.md b/src/modality-specific-files/positron-emission-tomography.md index c021f82a8a..c16d144b4f 100644 --- a/src/modality-specific-files/positron-emission-tomography.md +++ b/src/modality-specific-files/positron-emission-tomography.md @@ -6,7 +6,7 @@ Please see [Citing BIDS](../introduction.md#citing-bids) on how to appropriately credit this extension when referring to it in the context of the academic literature. -Several [example PET datasets](https://github.com/bids-standard/bids-examples#pet-datasets) +Several [example PET datasets](https://bids-standard.github.io/bids-examples/#pet) have been formatted using this specification and can be used for practical guidance when curating a new dataset. From 882a9d6b7767163ba3475580a02d0c8eff7f313b Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 11 Jul 2023 10:30:40 -0400 Subject: [PATCH 10/43] FIX: Update code fences --- src/derivatives/introduction.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/derivatives/introduction.md b/src/derivatives/introduction.md index 9b3b61dd49..a8662d67bd 100644 --- a/src/derivatives/introduction.md +++ b/src/derivatives/introduction.md @@ -14,12 +14,14 @@ Examples: A defaced T1w image would typically be made during the curation process and is thus under raw -`sourcedata/private/sub-01/anat/sub-01_T1w.nii.gz` -`sub-01/anat/sub-01_desc-defaced_T1w.nii.gz` +```Text +sourcedata/private/sub-01/anat/sub-01_T1w.nii.gz +sub-01/anat/sub-01_T1w.nii.gz +``` A defaced T1w image could also, in theory, be derived from a BIDS dataset and would thus be under derivatives -``` +```Text sub-01/anat/sub-01_T1w.nii.gz derivatives/sub-01/anat/sub-01_desc-defaced_T1w.nii.gz ``` From 915aa3eb46c79f916fe992606dc6d7e8156eb334 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 11 Jul 2023 10:32:42 -0400 Subject: [PATCH 11/43] FIX: folders -> directory For consistency --- src/derivatives/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/derivatives/introduction.md b/src/derivatives/introduction.md index a8662d67bd..9cad29a14a 100644 --- a/src/derivatives/introduction.md +++ b/src/derivatives/introduction.md @@ -26,7 +26,7 @@ sub-01/anat/sub-01_T1w.nii.gz derivatives/sub-01/anat/sub-01_desc-defaced_T1w.nii.gz ``` -## Derivatives storage and folders structure +## Derivatives storage and directory structure Placement and naming conventions for derived datasets are addressed in [Storage of derived datasets][storage], and dataset-level metadata is included From 03bec0e75a28526f3e4dc480e97fa175a4eba3f2 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 11 Jul 2023 12:00:40 -0400 Subject: [PATCH 12/43] SCHEMA: Define associated data with selectors, path components and inheritance (#1548) * SCHEMA: Add selectors to indicate when associations must be loaded * ENH: Add target and inherit fields to meta.associations --- src/schema/meta/associations.yaml | 92 +++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/schema/meta/associations.yaml diff --git a/src/schema/meta/associations.yaml b/src/schema/meta/associations.yaml new file mode 100644 index 0000000000..9658b25fa4 --- /dev/null +++ b/src/schema/meta/associations.yaml @@ -0,0 +1,92 @@ +# These rules indicate whether an association (defined in meta.context.context.associations) +# applies to a given file. These are hints to allow implementations to avoid unnecessary +# directory and file reads. +# +# Structure: +# +# - "selectors" is a sequence of expressions that apply to a file that may have an association. +# If matched, a tool MUST attempt to find the associated file. +# - "target" contains a set of path components that may be used to search for the associated file. +# These override the path components of the original file and MUST match for the associated file. +# A list of values, such as extensions, indicates multiple possible matches. +# - "inherit" is a boolean indicating whether the associated file may be found at a shallower level +# of the hierarchy. +--- +events: + selectors: + - 'task in entities' + - extension != '.json' + target: + suffix: events + extension: .tsv + inherit: true + +aslcontext: + selectors: + - suffix == 'asl' + - matches(extension, '\.nii(\.gz)?$') + target: + suffix: aslcontext + extension: .tsv + inherit: true + +m0scan: + selectors: + - suffix == 'asl' + - matches(extension, '\.nii(\.gz)?$') + target: + suffix: m0scan + extension: [.nii, .nii.gz] + inherit: false + +magnitude: + selectors: + - suffix == 'fieldmap' + - matches(extension, '\.nii(\.gz)?$') + target: + suffix: magnitude + extension: [.nii, .nii.gz] + inherit: false + +magnitude1: + selectors: + - matches(suffix, 'phase(diff|1)$') + - matches(extension, '\.nii(\.gz)?$') + target: + suffix: magnitude1 + extension: [.nii, .nii.gz] + inherit: false + +bval: + selectors: + - suffix == 'dwi' + - matches(extension, '\.nii(\.gz)?$') + target: + extension: .bval + inherit: true + +bvec: + selectors: + - suffix == 'dwi' + - matches(extension, '\.nii(\.gz)?$') + target: + extension: .bvec + inherit: true + +channels: + selectors: + - intersects([suffix], ['eeg', 'ieeg', 'meg', 'nirs', 'motion', 'optodes']) + - extension != '.json' + target: + suffix: channels + extension: .tsv + inherit: true + +coordsystem: + selectors: + - intersects([suffix], ['eeg', 'ieeg', 'meg', 'nirs', 'motion', 'electrodes', 'optodes']) + - extension != '.json' + target: + suffix: coordsystem + extension: .json + inherit: true From 061cb6f0fa133dbaf3fb62821bc34604be5da736 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Sat, 24 Jun 2023 04:58:40 +0200 Subject: [PATCH 13/43] ENH: Permit CITATION.cff as strict alternative to Authors field --- src/schema/rules/checks/dataset.yaml | 12 ++++++++++++ src/schema/rules/files/common/core.yaml | 3 +++ 2 files changed, 15 insertions(+) diff --git a/src/schema/rules/checks/dataset.yaml b/src/schema/rules/checks/dataset.yaml index 4012eca8fb..fd5ab61511 100644 --- a/src/schema/rules/checks/dataset.yaml +++ b/src/schema/rules/checks/dataset.yaml @@ -62,3 +62,15 @@ UnknownVersion: - path == 'dataset_description.json' checks: - intersects([json.BIDSVersion], schema.meta.versions) + +SingleSourceAuthors: + issue: + code: AUTHORS_AND_CITATION_FILE_MUTUALLY_EXCLUSIVE + level: error + message: | + CITATION.cff file found. The "Authors" field of dataset_description.json + must be removed to avoid inconsistency. + selectors: + - path == 'CITATION.cff' + checks: + - '!("Authors" in dataset.dataset_description)' diff --git a/src/schema/rules/files/common/core.yaml b/src/schema/rules/files/common/core.yaml index cacc3e0c41..2fad28f430 100644 --- a/src/schema/rules/files/common/core.yaml +++ b/src/schema/rules/files/common/core.yaml @@ -5,6 +5,9 @@ dataset_description: level: required path: dataset_description.json +CITATION: + level: optional + path: CITATION.cff README: level: recommended stem: README From d19363ef240bd19f9a998566a03c61b5274e31e7 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Sat, 24 Jun 2023 19:33:33 +0000 Subject: [PATCH 14/43] ENH: Add CITATION schema file and recommend preference over dataset_description --- src/modality-agnostic-files.md | 15 +++++++++++++++ src/schema/objects/files.yaml | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/src/modality-agnostic-files.md b/src/modality-agnostic-files.md index d598f76e38..b424ef52b6 100644 --- a/src/modality-agnostic-files.md +++ b/src/modality-agnostic-files.md @@ -167,6 +167,21 @@ A guide for using macros can be found at --> {{ MACROS___render_text("objects.files.README.description") }} +### `CITATION.cff` + + +{{ MACROS___render_text("objects.files.CITATION.description") }} + +For most redundant fields between `CITATION.cff` and `dataset_description.json`, +the `CITATION.cff` SHOULD take precedence. +To avoid inconsistency, metadata present in `CITATION.cff` SHOULD NOT be +be included in `dataset_description.json`, with the exception of `Name` and +`DatasetDOI`, to ensure that `CITATION.cff`-unaware tools can generate +references to the dataset. + ### `CHANGES` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Aaron Oliver-Taylor
📖

Adam Li

📖 💻

Adam Thomas

📖

Adeen Flinker

📖

Adina S. Wagner

🎨 💻

Agah Karakuzu

💬 📖 🔣 🤔 💻

Aki Nikolaidis

📖

Alberto Lazari
📖

Alejandro de la Vega

🐛 💻 ⚠️

Alessio Giacomel

📖

Alex Rockhill

📖 🔧 💻

Alexander Jones
💻 🐛

Alexander L. Cohen

🐛 💻 📖 💬

Alexander von Lautz
📖

Alexandre Gramfort

📖 💡

Alexandre Hutton
📖

Alexandre Routier

📖

Alexandru Foias

📖 🔣

Ali Khan
📖

Ana Fouto
📓

Anders Eklund

📖 📢 💻

Andrea Pigorini
📖

Andrew Hoopes
📖

Andrew Jahn
📓

Andrew Janke

📖 💻

Anibal Sólon

💻 🐛

Anthony Galassi

📖 💻

Ariel Rokem

📖 💻

Arjen Stolk
📖

Arnaud Delorme

📖 💡 🤔

Arnaud Marcoux

📖

Arshitha Basavaraj

📖 🚇 💻

Ashley G. Gillman

📖

Athanasia Monika Mowinckel

📖

Aysegul Gunduz
📖

Azeez Adebimpe
📖

B. Nolan Nichols
📖

Balint Kincses
📖

Benjamin Beasley

📖

Benjamin Dichter
📖

Benjamin Gagl
📖

Bertrand Thirion

📖

Bradley Voytek

📖

Brett L. Foster
📖

Brian A. Wandell
📖

Brian N. Lundstrom
📖

Camille Maumet

📖

Carlo Miniussi
📖

Chloé Pasturel
📖

Chris Benjamin
📖

Chris Gahnström
📖

Chris Holdgraf

📖 🤔 💻

Chris J. Gorgolewski

📖 💻 💬 🤔 🔍 📢 📝 💡 🔌

Chris Rorden

📖 💻

Christian Büchel
📖

Christian Horea

💻 📖

Christine Rogers
🔣 📖 🤔 🚇 🔧

Christophe Phillips

📖

Christopher J. Honey

📖

Christopher J. Markiewicz

💬 🐛 💻 📖 🎨 💡 🤔 🔌 👀 🔧 📢 🔣 📋 🚧

Christopher Lee-Messer
📖

Clara Moreau
📖

Clint Hansen
📖 🤔

Cyril Pernet

💬 📝 📖 🎨 💡 📋 🤔 📢

Cyrus Eierud

📖

D. Sturgeon

💻

Dan Levitas

📖

Dan Lurie

🤔 📖 🔧 🔌 💻 💬

Daniel A. Handwerker
📖

David Alsop
📖

David Boas

📖

David Groppe

📖

David Keator

📖

David McAlpine
📖

David Thomas
📖 🔣

Dejan Draschkow
📖

Dianne Patterson

📖

Dimitri Papadopoulos Orfanos

📖 💡 🤔 💬 💻

Dmitry Petrov
📖 💻

Dora Hermes

📖 💻 🔍 🤔

Dorien Huijser

📖

Douglas N. Greve

📖

Duncan Macleod
📖 🚇

Dung Truong

📖 💻 🔧 🤔

Dylan Nielson

📖 💻 🔧

Eduard Ort

📖 💻

Eleonora Marcantoni
📖

Elizabeth Bock
📖 💡

Elizabeth DuPre

📖 💡 🔍 🤔 💬 💻

Elke Warmerdam
🔣 📖

Erdal Karaca

💻

Eric A. Earl

📖 💬 🐛 🚧 🔧 🤔 💻

Eric Achten

📖 🔣 📓

Eric Bridgeford
📖 🔧

Erin W. Dickie

📖 🤔 👀 📢 💬 💻

Ethan Blackwood
👀 📖

Eugene P. Duff

📖

Ezequiel Mikulan
📖 💻

Felipe Orihuela-Espina
📖

Fidel Alfaro Almagro
💬 📖 💡 🔌

Filip Szczepankiewicz
📖

Filippo Maria Castelli

📖 🔣

Franco Pestilli

📖 💻 🎨 💡 🤔 👀 🔧 📋 🔍 🚇

Franklin W. Feingold

📋 📝 💬 🤔 🎨 📢 👀 🚇 🖋 📆 💻

François Tadel
📖 🔌 💡

Gaia Rizzo

📖

Gang Chen

📖

Gaël Varoquaux

📖

Ghislain Vaillant

💻

Giacomo Bertazzoli
📖

Giacomo Guidali
📖

Giacomo Mazzamuto

📖 🔣

Gilles de Hollander

📖

Gio Piantoni
📖

Gitte M. Knudsen
📖

Giulio Castegnaro
📖

Giuseppe Gallitto
📖

Graham Searle
📖

Granville J. Matheson

📖

Gregory Kiar

📖 💻 🎨 🔧

Gregory Noack

📖 💻 ⚠️

Greydon Gilmore

📖 💻

Guillaume Flandin

📖 💻

Gunnar Schaefer
📖

Gustav Nilsonne

📖

Hamish Innes-Brown
📖

Hanne D. Hansen
📖

Hanzhang Lu
📖

Hao-Ting Wang

📖 🐛

Helena Cockx

📖 🤔 💬

Henk Mutsaerts

💬 🐛 💻 📖 💡 📋 🤔 📆 📢 📓

Hernando Ombao
📖

Hugo Boniface

📖 💻

Ilkay Isik

📖

Ilona Lipp

📖

International Neuroinformatics Coordinating Facility

💵 📋

Iris Groen

📖

Isla Staden
📖

Jaap von der Aar
📖

Jakub Kaczmarzyk

📖 🔧 🚇

James Gholam
📖

James Kent

💬 💻

Jan Mathijs Schoffelen

📖

Jan Petr

💬 🐛 💻 📖 🔣 💡 📋 🤔 📆 ⚠️ 📢

Jan-Mathijs Schoffelen
📖

Jean-Baptiste Poline

📖 📢 🤔 🎨 💻

Jean-Christophe Houde

📖 💻

Jean-Dominique Gallezot
📖

Jean-Philippe Lachaux
📖

Jeanette Mumford

📖

Jeffrey G. Ojemann
📖

Jeffrey S. Grethe

💬 🐛 📢 💻

JegouA

💻

Jelle Dalenberg

📖

Jeremy Moreau
📖 💡

Jessica A. Turner
📖

Jochem Rieger

📖

John Detre
📖

John Pellman
📖

John T. Wodder

💻

Joke Durnez

📖 🔧 💻

Jon Haitz Legarreta Gorroño

💻 📖

Jonathan C. Lau
📖

Jonathan Winawer

📖

Joost Kuijer

📖

Jose Manuel Saborit
📖

Joseph Wexler
📖 💡

Joseph Woods

📖

Julia Guiomar Niso Galán

🤔 🎨 🔍 👀 📋 📝 🔧 🐛 💻 🔣 💬 📖 💡 📢

Julia Sprenger

📖

Julien Cohen-Adad

📖 🔣 🤔

Julius Welzel

📖 💡 🐛 💻 🔣 🤔 💬 📓

Kai J. Miller
📖

Kangjoo Lee

📖

Katja Heuer

🔧

Kay Robbins

💻 📖 🐛

Kevin Larcher
💬

Kimberly Ray
📖 📋 🤔 📆

Kirstie Whitaker

📖 💡 🔍 🤔 📢 💬 💻

Klara Gregorova

📖

Klaus Gramann
📖 🤔

Kris Thielemans

📖

Kristofer Bouchard

📖

Kurt Schilling

📖

Laura and John Arnold Foundation
💵

Leandro Beltrachini
📖

Lee Kamentsky

📖

Lennart Walger
📖

Lennart Wittkuhn

📖

Liberty Hamilton

📖

Luca Pollonini

📖

Luis Hernandez-Garcia
📖 📓

Luke J. Edwards
📖 💬

Lyuba Zehl

📖

Mainak Jas

📖 💻

Manjari Narayan
📖

Manuel Mercier
📖 🤔

Maqsood Yaqub
📖

Marc Lalancette

📖 💻

Marco Castellaro

💬 🐛 💻 📖 💡 ⚠️ 📢 🚇

Maria de la Iglesia

📖

Marie-Hélène Bourget

📖 🔣 💻 🤔

Mark Mikkelsen

📖

Markus Morawski
📖

Marta Bortoletto
📖

Martin Craig
🔣

Martin Noergaard

📖 🔣 💻 🤔 📢

Martin Szinte

📖

Martin Wilson
📖

Martina Bulgari
📖

Mateusz Pawlik

📖 🐛 🤔 🚧 👀

Mathias Goncalves

💻 🔧 📢

Mathieu Boudreau

💬 🤔 📢

Matt Sanderson
📖 💻

Matteo Tonietto

📖

Matthias Günther
📖

Matthias Van Osch
📖

Maureen J Shader
📖

Maurice Pasternak
📓

Max A. van den Boom

💻 👀 📖 🐛

Melanie Ganz-Benjaminsen

📖 🔣 💻 🤔 📆 🔍 📢

Michael Chappell
📖 🔣 📆

Michael Hanke

📖 🤔 🔧 🐛 📢

Michael P. Harms
📖 ⚠️ 🔧

Michael P. Milham
💡 🔍

Michael P. Notter
💬 📝 📢 📖

Michael Schirner

📖

Mikaël Naveau

🐛

Nader Pouratian
📖

Natalia Petridou
📖

National Institute of Mental Health
💵

Nell Hardcastle

💻 📖 🤔 🚇 👀 💬

Nicholas Traut
📖 🔧 💻

Nick F. Ramsey
📖

Nicole C. Swann
📖

Nima Bigdely Shamlo
📖

Olivier David
📖

Orrin Devinsky
📖

Oscar Esteban

📖 🔧 🤔 💬 💻

Pamela LaMontagne
📖 💡

Parul Sethi

📖 🔧 ⚠️ 💻

Patricia Clement

💬 🐛 💻 📖 🔣 💡 📋 🤔 📆 ⚠️ 📢

Patrick Park

📖 💡 💬 💻

Paule-Joanne Toussaint
📖

Peer Herholz

💬 📖 👀 🔧 📢

Petra Ritter

📖

Pierre Rioux

📖

Pieter Vandemaele

📖 💻

Pradeep Reddy Raamana

💻 🔧

R. Cameron Craddock

📖 📢

Remi Gau

📖 💻 💬 📢 🐛 💻 🚇 👀 🔧 🤔

Richard Höchenberger

📖 💻

Richard N. Henson

📖

Robert B. Innis

📖

Robert E. Smith

💻 📖

Robert Knight
📖

Robert Luke

💻

Robert Oostenveld

📖 🔧 📢 💡 ⚠️ 🤔 💬 🐛 📝 💻 🖋 🔣 🎨 📋 🚇 👀 📓 📹

Roberto Toro

🔧

Rohan Goyal
📖

Ross W. Blair

💻

Russell A. Poldrack

📖 🔍 📢

Rémi Adon

📖

Samir Das

📖

Samuel Garcia
🤔 👀 📖

Samuel Nastase

💻

Sara Elgayar
📖

Sasha D'Ambrosio
📖

Satrajit S. Ghosh

📖 💻

Scott Makeig

📖

Sein Jeung

📖 💡 🐛 💻 🔣 🤔 💬 🔧 📓

Shashank Bansal
📖

Sjoerd B. Vos

📖

Soichi Hayashi

📖 🔧 🐛

Stefan Appelhoff

📖 💬 🤔 🐛 💡 💻 👀 ⚠️ 📢 🔧 🔌 📝 🚧 🔣

Stephan Bickel
📖

Suyash Bhogawar

📖 💡 ⚠️ 🔧 💬

Sylvain Baillet

📖 🔍

Sylvain Takerkart

📖

Sébastien Tourbier

🤔 👀 📢 🐛 💻 📖

Sören Grothkopp
📖 🔣 📓

Tal Pal Attia

📖

Tal Yarkoni

💻 📖 🤔 🔍 🔌 👀 📢 🐛 🎨

Tamas Spisak

📖

Tamás Józsa
📓

Taylor Salo

💬 📖 🔌 💻

Teon L. Brooks

📖 💻 ⚠️ 💬 👀 🤔 🔧 🐛 📢

Thomas E. Nichols

📖 📢 🔧 👀 🚧 💻

Thomas Funck

📖

Thomas Kirk
📖

Thomas Okell
📖

Tibor Auer

💬 📖 💡 🔧 📢 🐛 🤔

Timo Dickscheid

📖

Timotheus Berg

📖 🤔 📓

Tobey Betthauser
📖

Tobias Bengfort

💻

Tom Hampshire
📖

Tor Wager

📖

Travis Riddle
📖 🔧 🐛

Tristan Glatard

📖 💻

Ulrike Bingel
📖

Vanessa Sochat

📖

Vasudev Raguram
💻 🎨 📖 🔧

Vince D. Calhoun

📖

Vittorio Iacovella
📖

Vladimir Litvak
📖

Wietske van der Zwaag
🔣 💬

William Clarke
📖

William Triplett
📖

Wouter V. Potters

💻 📖

Xiangrui Li

📖 💻

Yaroslav O. Halchenko

📖 📢 🔧 💬 🐛 💻

Yoni Ashar
📖

Yuan Wang
💻

Zachary Michael
📖

ezemikulan

💻

josator2

💻

monkeyman192

💻

Étienne Bergeron
🔣 💻
+ + + + + diff --git a/Release_Protocol.md b/Release_Protocol.md index cb1363f750..5773da78e3 100644 --- a/Release_Protocol.md +++ b/Release_Protocol.md @@ -42,6 +42,10 @@ git checkout -b rel/1.2.0 upstream/master ### 2. Update the version, contributors list, previous version URLs, and the Changelog +#### 2.1 Update the version + +Update the version in CITATION.cff. + Change the "Unreleased" heading in [src/CHANGES.md](https://github.com/bids-standard/bids-specification/blob/master/src/CHANGES.md) to `v`, and link to the target ReadTheDocs URL. @@ -64,17 +68,38 @@ In the figure below, we update `v1.2.0-dev` to `v1.2.0`. Additionally, implement the same change in the version name perform above in the `src/schema/BIDS_VERSION` file. -Note: this will make our continuous integration ([CircleCI](https://circleci.com/)) fail. This fails because the URL of the new ReadTheDocs rendering has not been generated at this time. It will be generated once the GitHub release has been completed. +Note: +this will make our continuous integration ([CircleCI](https://circleci.com/)) fail. +This fails because the URL of the new ReadTheDocs rendering has not been generated at this time. +It will be generated once the GitHub release has been completed. + +#### 2.2 Update the contributors list Synchronize the [Contributors appendix](https://github.com/bids-standard/bids-specification/blob/master/src/appendices/contributors.md) with the [Contributors wiki page](https://github.com/bids-standard/bids-specification/wiki/Contributors) to ensure all contributors are duly credited. Be sure not to remove credits if both have been edited. +- add new contributors info to the `tools/new_contributors.tsv` file. +- make sure that you have installed + - all the python packages listed in `tools/requirements.txt` + - the [allcontributors](https://allcontributors.org/docs/en/cli/installation) package +- run: +```bash +make update_contributors +``` +- you may need to fix some errors in the contributions names in case of crash +- make sure to review the changes and not commit them blindly +- commit the changes + +#### 2.3 Update the previous version URLs + Please change the previous version links from GitHub to ReadTheDocs. In the figure below, we update v1.2.2. ![github-to-rtd](release_images/GitHub_to_RTD_spec_rendering.png "github-to-rtd") +#### 2.4 Update the Changelog + Review `src/CHANGES.md` to ensure that the document produces a changelog that is useful to a reader of the specification. For example, several small PRs fixing typos might be merged into a single line-item, or less @@ -214,6 +239,8 @@ on the expected next version. Additionally, the same version name set above in `mkdocs.yaml` should be set in the `src/schema/BIDS_VERSION` schema version file. +Similarly update the version in CITATION.cff with a `dev` suffix. + ### 10. Uploading the stable PDF to Zenodo 1. Open a private browser window diff --git a/src/appendices/contributors.md b/src/appendices/contributors.md index f77b860b33..e2da78c45b 100644 --- a/src/appendices/contributors.md +++ b/src/appendices/contributors.md @@ -36,283 +36,326 @@ The following individuals have contributed to the Brain Imaging Data Structure ecosystem (in alphabetical order). If you contributed to the BIDS ecosystem and your name is not listed, please add it. -- Eric Achten 📖🔣📓 -- Azeez Adebimpe 📖 -- Rémi Adon 📖 -- Fidel Alfaro Almagro 💬📖💡🔌 -- David Alsop 📖 -- Stefan Appelhoff 📖💬🤔🐛💡💻👀⚠️📢✅🔧🔌📝🚧🔣 -- Yoni Ashar 📖 -- Tal Pal Attia 📖 -- Tibor Auer 💬📖💡🔧📢🐛🤔 -- Sylvain Baillet 📖🔍 -- Shashank Bansal 📖 -- Arshitha Basavaraj 📖🚇💻 -- Ben Beasley 💻 -- Leandro Beltrachini 📖 -- Chris Benjamin 📖 -- Timo Berg 📖 -- Étienne Bergeron 🔣💻 -- Giacomo Bertazzoli 📖 -- Suyash Bhogawar 📖💡⚠️🔧💬 -- Stephan Bickel 📖 -- Ulrike Bingel 📖 -- Ethan Blackwood 👀📖 -- David Boas 📖 -- Elizabeth Bock 📖💡 -- Hugo Boniface 📖 -- Marta Bortoletto 📖 -- Kristofer Bouchard 📖 -- Mathieu Boudreau 💬🤔📢 -- Marie-Hélène Bourget 📖🔣💻🤔 -- Eric Bridgeford 📖🔧 -- Teon L. Brooks 📖💻⚠️💬👀🤔🔧🐛📢 -- Martina Bulgari 📖 -- Christian Büchel 📖 -- Vince D. Calhoun 📖 -- Giulio Castegnaro 📖 -- Marco Castellaro 💬🐛💻📖💡⚠️📢🚇 -- Filippo Maria Castelli 📖🔣 -- Michael Chappell 📖🔣📆 -- Gang Chen 📖 -- William Clarke 📖 -- Patricia Clement 💬🐛💻📖🔣💡📋🤔📆⚠️📢 -- Helena Cockx 📖 -- Alexander L. Cohen 🐛💻📖💬 -- Julien Cohen-Adad 📖🔣🤔 -- R. Cameron Craddock 📖📢 -- Martin Craig 🔣 -- Sasha D'Ambrosio 📖 -- Samir Das 📖 -- Olivier David 📖 -- Orrin Devinsky 📖 -- Gilles de Hollander 📖 -- Alejandro de la Vega 🐛💻⚠️ -- Arnaud Delorme 📖💡 -- John Detre 📖 -- Benjamin Dichter 📖 -- Erin W. Dickie 📖🤔👀📢💬 -- Timo Dickscheid 📖 -- Dejan Draschkow 📖 -- Eugene P. Duff 📖 -- Elizabeth DuPre 📖💡🔍🤔💬 -- Joke Durnez 📖🔧💻 -- Eric Earl 📖💬🐛🚧🔧🤔 -- Cyrus Eierud 💻 -- Anders Eklund 📖📢💻 -- Sara Elgayar 📖 -- Oscar Esteban 📖🔧🤔💬💻 -- Franklin W. Feingold 📋📝✅💬🤔🎨📢👀🚇🖋📆 -- Guillaume Flandin 📖💻 -- Adeen Flinker 📖 -- Alexandru Foias 📖🔣 -- Brett L. Foster 📖 -- Ana Fouto 📓 -- Benjamin Gagl 📖 -- Chris Gahnström 📖 -- Anthony Galassi 📖 -- Giuseppe Gallitto 📖 -- Melanie Ganz-Benjaminsen 📖🔣💻🤔📆🔍📢 -- Samuel Garcia 🤔👀📖 -- Remi Gau 📖💻💬📢🐛💻🚇👀🔧🤔 -- James Gholam 📖 -- Satrajit S. Ghosh 📖💻 -- Ashley G. Gillman 📖 -- Greydon Gilmore 📖 -- Tristan Glatard 📖💻 -- Mathias Goncalves 💻🔧📢 -- Krzysztof J. Gorgolewski 📖💻💬🤔🔍📢📝💡🔌 -- Rohan Goyal 💻 -- Alexandre Gramfort 📖💡 -- Klara Gregorova 📖 -- Jeffrey S. Grethe 💬🐛✅📢 -- Iris Groen 📖 -- David Groppe 📖 -- Sören Grothkopp 📖 -- Aysegul Gunduz 📖 -- Giacomo Guidali 📖 -- Matthias Günther 📖 -- Yaroslav O. Halchenko 📖📢🔧💬🐛 -- Liberty Hamilton 📖 -- Tom Hampshire 📖 -- Daniel A. Handwerker 📖 -- Michael Hanke 📖🤔🔧🐛📢 -- Nell Hardcastle 💻 🤔 🚇 💬 👀 -- Michael P. Harms 📖⚠️🔧 -- Soichi Hayashi 📖🔧🐛 -- Richard N. Henson 📖 -- Peer Herholz 💬📖👀🔧✅📢 -- Dora Hermes 📖💻✅🔍🤔 -- Luis Hernandez-Garcia 📖📓 -- Katja Heuer 🔧 -- Dorien Huijser 📖 -- Alexandre Hutton 📖 -- Richard Höchenberger 📖 -- Chris Holdgraf 📖🤔 -- Christopher J. Honey 📖 -- Andrew Hoopes 📖 -- Christian Horea 📖 -- Jean-Christophe Houde 📖 -- Vittorio Iacovella 📖 -- Maria de la Iglesia 📖 -- Ilkay Isik 📖 -- Hamish Innes-Brown 📖 -- International Neuroinformatics Coordinating Facility 💵📋 -- Andrew Jahn 📓 -- Andrew Janke 📖💻 -- Mainak Jas 📖💻 -- Sein Jeung 📖💡 -- Alexander Jones 💻🐛 -- Tamás Józsa 📓 -- Jakub Kaczmarzyk 📖🔧🚇 -- Lee Kamentsky 📖 -- Agah Karakuzu 💬📖🔣🤔 -- David Keator 📖 -- James Kent 💬💻 -- Ali Khan 📖 -- Gregory Kiar 📖💻🎨🔧 -- Balint Kincses 📖 -- Thomas Kirk 📖 -- Robert Knight 📖 -- Joost Kuijer 📖 -- Jean-Philippe Lachaux 📖 -- Marc Lalancette 📖 -- Pamela LaMontagne 📖💡 -- Kevin Larcher 💬 -- Jonathan C. Lau 📖 -- Laura and John Arnold Foundation 💵 -- Alexander von Lautz 📖 -- Alberto Lazari 📖 -- Kangjoo Lee 📖 -- Christopher Lee-Messer 📖 -- Jon Haitz Legarreta 💻📖 -- Dan Levitas 📖 -- Adam Li 📖💻 -- Xiangrui Li 📖💻 -- Ilona Lipp 📖 -- Vladimir Litvak 📖 -- Hanzhang Lu 📖 -- Robert Luke 📖 -- Brian N. Lundstrom 📖 -- Dan Lurie 🤔📖🔧🔌💻💬 -- Duncan Macleod 🚇 -- Eleonora Marcantoni 📖 -- Christopher J. Markiewicz 💬🐛💻📖🎨💡🤔🔌👀🔧📢🔣📋🚧 -- Camille Maumet 📖 -- Giacomo Mazzamuto 📖🔣 -- David McAlpine 📖 -- Manuel Mercier 📖🤔 -- Mark Mikkelsen 📖 -- Kai J. Miller 📖 -- Carlo Miniussi 📖 -- Markus Morawski 📖 -- Clara Moreau 📖 -- Jeremy Moreau 📖💡 -- Zachary Michael 📖 -- Ezequiel Mikulan 📖💻 -- Michael P. Milham 💡🔍 -- Jeanette Mumford 📖 -- Athanasia Monika Mowinckel 📖 -- Henk Mutsaerts 💬🐛💻📖💡📋🤔📆📢📓 -- Manjari Narayan 📖 -- National Institute of Mental Health 💵 -- Mikael Naveau 🐛 -- B. Nolan Nichols 📖 -- Thomas E. Nichols 📖📢🔧👀🚧 -- Dylan Nielson 📖💻🔧 -- Aki Nikolaidis 📖 -- Gustav Nilsonne 📖 -- Guiomar Niso 🤔🎨🔍👀📋📝🔧🐛💻🔣✅💬📖💡📢 -- Gregory Noack 💻 ⚠️ -- Martin Noergaard 📖🔣💻🤔📢 -- Michael P. Notter 💬📝✅📢📖 -- Jeffrey G. Ojemann 📖 -- Thomas Okell 📖 -- Aaron Oliver-Taylor 📖 -- Hernando Ombao 📖 -- Robert Oostenveld 📖🔧📢💡✅⚠️🤔💬🐛📝💻🖋🔣🎨📋🚇👀📓📹 -- Dimitri Papadopoulos Orfanos 📖💡🤔💬 -- Felipe Orihuela-Espina 📖 -- Eduard Ort 📖 -- Patrick Park 📖💡💬 -- Maurice Pasternak 📓 -- Chloé Pasturel 📖 -- Dianne Patterson 📖 -- Mateusz Pawlik 🤔 📖 🚧 👀 🐛 -- John Pellman 📖 -- Cyril Pernet 💬📝📖🎨💡📋🤔📢 -- Franco Pestilli 📖💻🎨💡🤔👀🔧📋🔍🚇 -- Jan Petr 💬🐛💻📖🔣💡📋🤔📆⚠️📢 -- Natalia Petridou 📖 -- Dmitry Petrov 📖💻 -- Christophe Phillips 📖 -- Gio Piantoni 📖 -- Andrea Pigorini 📖 -- Russell A. Poldrack 📖🔍📢 -- Jean-Baptiste Poline 📖📢🤔🎨 -- Luca Pollonini 📖 -- Wouter V. Potters 📖 -- Nader Pouratian 📖 -- Pradeep Reddy Raamana 💻🔧 -- Vasudev Raguram 💻🎨📖🔧 -- Nick F. Ramsey 📖 -- Travis Riddle 📖🔧🐛 -- Pierre Rioux 📖 -- Petra Ritter 📖 -- Kay Robbins 💻📖🐛 -- Alex Rockhill 📖🔧 -- Christine Rogers 🤔🚇📖🔣🔧 -- Ariel Rokem 📖 -- Chris Rorden 📖💻 -- Jose Manuel Saborit 📖 -- Taylor Salo 💬📖🔌 -- Matt Sanderson 📖💻 -- Gunnar Schaefer 📖 -- Michael Schirner 📖 -- Jan-Mathijs Schoffelen 📖 -- Graham Searle 📖 -- Parul Sethi 📖🔧⚠️💻 -- Maureen J Shader 📖 -- Robert E. Smith 💻📖 -- Vanessa Sochat 📖 -- Anibal Sólon 🐛 -- Tamas Spisak 📖 -- Julia Sprenger 📖 -- Isla Staden 📖 -- Arjen Stolk 📖 -- Nicole C. Swann 📖 -- Filip Szczepankiewicz 📖 -- Martin Szinte 📖 -- François Tadel 📖🔌💡 -- Sylvain Takerkart 📖 -- Bertrand Thirion 📖 -- David Thomas 📖🔣 -- Roberto Toro 🔧 -- Sébastien Tourbier 🤔👀📢🐛💻📖 -- Paule-Joanne Toussaint 📖 -- Nicholas Traut 📖🔧💻 -- William Triplett 📖 -- Jessica A. Turner 📖 -- Pieter Vandemaele 📖💻 -- Max A. van den Boom 💻👀📖🐛 -- Wietske van der Zwaag 🔣💬 -- Matthias Van Osch 📖 -- Gaël Varoquaux 📖 -- Jaap von der Aar 📖 -- Sjoerd Vos 📖 -- Bradley Voytek 📖 -- Tor Wager 📖 -- Adina S. Wagner 🎨 -- Lennart Walger 📖 -- Brian A. Wandell 📖 -- Hao Ting Wang 📖🐛 -- Yuan Wang 💻 -- Julius Welzel 📖💡 -- Joseph Wexler 📖💡 -- Kirstie Whitaker 📖💡🔍🤔📢💬 -- Martin Wilson 📖 -- Jonathan Winawer 📖 -- Lennart Wittkuhn 📖 -- Joseph Woods 📖 -- Tal Yarkoni 💻📖🤔🔍🔌👀📢🐛🎨 -- Lyuba Zehl 📖 + + +| name | contributions | +| ---------------------------------------------------- | -------------------------------------- | +| Aaron Oliver-Taylor | 📖 | +| Adam Li | 📖💻 | +| Adam Thomas | 📖 | +| Adeen Flinker | 📖 | +| Adina S. Wagner | 🎨💻 | +| Agah Karakuzu | 💬📖🔣🤔💻 | +| Aki Nikolaidis | 📖 | +| Alberto Lazari | 📖 | +| Alejandro de la Vega | 🐛💻⚠️ | +| Alessio Giacomel | 📖 | +| Alex Rockhill | 📖🔧💻 | +| Alexander Jones | 💻🐛 | +| Alexander L. Cohen | 🐛💻📖💬 | +| Alexander von Lautz | 📖 | +| Alexandre Gramfort | 📖💡 | +| Alexandre Hutton | 📖 | +| Alexandre Routier | 📖 | +| Alexandru Foias | 📖🔣 | +| Ali Khan | 📖 | +| Ana Fouto | 📓 | +| Anders Eklund | 📖📢💻 | +| Andrea Pigorini | 📖 | +| Andrew Hoopes | 📖 | +| Andrew Jahn | 📓 | +| Andrew Janke | 📖💻 | +| Anibal Sólon | 💻🐛 | +| Anthony Galassi | 📖💻 | +| Ariel Rokem | 📖💻 | +| Arjen Stolk | 📖 | +| Arnaud Delorme | 📖💡🤔 | +| Arnaud Marcoux | 📖 | +| Arshitha Basavaraj | 📖🚇💻 | +| Ashley G. Gillman | 📖 | +| Athanasia Monika Mowinckel | 📖 | +| Aysegul Gunduz | 📖 | +| Azeez Adebimpe | 📖 | +| B. Nolan Nichols | 📖 | +| Balint Kincses | 📖 | +| Benjamin Beasley | 📖 | +| Benjamin Dichter | 📖 | +| Benjamin Gagl | 📖 | +| Bertrand Thirion | 📖 | +| Bradley Voytek | 📖 | +| Brett L. Foster | 📖 | +| Brian A. Wandell | 📖 | +| Brian N. Lundstrom | 📖 | +| Camille Maumet | 📖 | +| Carlo Miniussi | 📖 | +| Chloé Pasturel | 📖 | +| Chris Benjamin | 📖 | +| Chris Gahnström | 📖 | +| Chris Holdgraf | 📖🤔💻 | +| Chris J. Gorgolewski | 📖💻💬🤔🔍📢📝💡🔌 | +| Chris Rorden | 📖💻 | +| Christian Büchel | 📖 | +| Christian Horea | 💻📖 | +| Christine Rogers | 🔣📖🤔🚇🔧 | +| Christophe Phillips | 📖 | +| Christopher J. Honey | 📖 | +| Christopher J. Markiewicz | 💬🐛💻📖🎨💡🤔🔌👀🔧📢🔣📋🚧 | +| Christopher Lee-Messer | 📖 | +| Clara Moreau | 📖 | +| Clint Hansen | 📖🤔 | +| Cyril Pernet | 💬📝📖🎨💡📋🤔📢 | +| Cyrus Eierud | 📖 | +| D. Sturgeon | 💻 | +| Dan Levitas | 📖 | +| Dan Lurie | 🤔📖🔧🔌💻💬 | +| Daniel A. Handwerker | 📖 | +| David Alsop | 📖 | +| David Boas | 📖 | +| David Groppe | 📖 | +| David Keator | 📖 | +| David McAlpine | 📖 | +| David Thomas | 📖🔣 | +| Dejan Draschkow | 📖 | +| Dianne Patterson | 📖 | +| Dimitri Papadopoulos Orfanos | 📖💡🤔💬💻 | +| Dmitry Petrov | 📖💻 | +| Dora Hermes | 📖💻✅🔍🤔 | +| Dorien Huijser | 📖 | +| Douglas N. Greve | 📖 | +| Duncan Macleod | 📖🚇 | +| Dung Truong | 📖💻🔧🤔 | +| Dylan Nielson | 📖💻🔧 | +| Eduard Ort | 📖💻 | +| Eleonora Marcantoni | 📖 | +| Elizabeth Bock | 📖💡 | +| Elizabeth DuPre | 📖💡🔍🤔💬💻 | +| Elke Warmerdam | 🔣📖 | +| Erdal Karaca | 💻 | +| Eric A. Earl | 📖💬🐛🚧🔧🤔💻 | +| Eric Achten | 📖🔣📓 | +| Eric Bridgeford | 📖🔧 | +| Erin W. Dickie | 📖🤔👀📢💬💻 | +| Ethan Blackwood | 👀📖 | +| Eugene P. Duff | 📖 | +| Ezequiel Mikulan | 📖💻 | +| Felipe Orihuela-Espina | 📖 | +| Fidel Alfaro Almagro | 💬📖💡🔌 | +| Filip Szczepankiewicz | 📖 | +| Filippo Maria Castelli | 📖🔣 | +| Franco Pestilli | 📖💻🎨💡🤔👀🔧📋🔍🚇 | +| Franklin W. Feingold | 📋📝✅💬🤔🎨📢👀🚇🖋️📆💻 | +| François Tadel | 📖🔌💡 | +| Gaia Rizzo | 📖 | +| Gang Chen | 📖 | +| Gaël Varoquaux | 📖 | +| Ghislain Vaillant | 💻 | +| Giacomo Bertazzoli | 📖 | +| Giacomo Guidali | 📖 | +| Giacomo Mazzamuto | 📖🔣 | +| Gilles de Hollander | 📖 | +| Gio Piantoni | 📖 | +| Gitte M. Knudsen | 📖 | +| Giulio Castegnaro | 📖 | +| Giuseppe Gallitto | 📖 | +| Graham Searle | 📖 | +| Granville J. Matheson | 📖 | +| Gregory Kiar | 📖💻🎨🔧 | +| Gregory Noack | 📖💻⚠️ | +| Greydon Gilmore | 📖💻 | +| Guillaume Flandin | 📖💻 | +| Gunnar Schaefer | 📖 | +| Gustav Nilsonne | 📖 | +| Hamish Innes-Brown | 📖 | +| Hanne D. Hansen | 📖 | +| Hanzhang Lu | 📖 | +| Hao-Ting Wang | 📖🐛 | +| Helena Cockx | 📖🤔💬 | +| Henk Mutsaerts | 💬🐛💻📖💡📋🤔📆📢📓 | +| Hernando Ombao | 📖 | +| Hugo Boniface | 📖💻 | +| Ilkay Isik | 📖 | +| Ilona Lipp | 📖 | +| International Neuroinformatics Coordinating Facility | 💵📋 | +| Iris Groen | 📖 | +| Isla Staden | 📖 | +| Jaap von der Aar | 📖 | +| Jakub Kaczmarzyk | 📖🔧🚇 | +| James Gholam | 📖 | +| James Kent | 💬💻 | +| Jan Mathijs Schoffelen | 📖 | +| Jan Petr | 💬🐛💻📖🔣💡📋🤔📆⚠️📢 | +| Jan-Mathijs Schoffelen | 📖 | +| Jean-Baptiste Poline | 📖📢🤔🎨💻 | +| Jean-Christophe Houde | 📖💻 | +| Jean-Dominique Gallezot | 📖 | +| Jean-Philippe Lachaux | 📖 | +| Jeanette Mumford | 📖 | +| Jeffrey G. Ojemann | 📖 | +| Jeffrey S. Grethe | 💬🐛✅📢💻 | +| JegouA | 💻 | +| Jelle Dalenberg | 📖 | +| Jeremy Moreau | 📖💡 | +| Jessica A. Turner | 📖 | +| Jochem Rieger | 📖 | +| John Detre | 📖 | +| John Pellman | 📖 | +| John T. Wodder | 💻 | +| Joke Durnez | 📖🔧💻 | +| Jon Haitz Legarreta Gorroño | 💻📖 | +| Jonathan C. Lau | 📖 | +| Jonathan Winawer | 📖 | +| Joost Kuijer | 📖 | +| Jose Manuel Saborit | 📖 | +| Joseph Wexler | 📖💡 | +| Joseph Woods | 📖 | +| Julia Guiomar Niso Galán | 🤔🎨🔍👀📋📝🔧🐛💻🔣✅💬📖💡📢 | +| Julia Sprenger | 📖 | +| Julien Cohen-Adad | 📖🔣🤔 | +| Julius Welzel | 📖💡🐛💻🔣🤔💬📓 | +| Kai J. Miller | 📖 | +| Kangjoo Lee | 📖 | +| Katja Heuer | 🔧 | +| Kay Robbins | 💻📖🐛 | +| Kevin Larcher | 💬 | +| Kimberly Ray | 📖📋🤔📆 | +| Kirstie Whitaker | 📖💡🔍🤔📢💬💻 | +| Klara Gregorova | 📖 | +| Klaus Gramann | 📖🤔 | +| Kris Thielemans | 📖 | +| Kristofer Bouchard | 📖 | +| Kurt Schilling | 📖 | +| Laura and John Arnold Foundation | 💵 | +| Leandro Beltrachini | 📖 | +| Lee Kamentsky | 📖 | +| Lennart Walger | 📖 | +| Lennart Wittkuhn | 📖 | +| Liberty Hamilton | 📖 | +| Luca Pollonini | 📖 | +| Luis Hernandez-Garcia | 📖📓 | +| Luke J. Edwards | 📖💬 | +| Lyuba Zehl | 📖 | +| Mainak Jas | 📖💻 | +| Manjari Narayan | 📖 | +| Manuel Mercier | 📖🤔 | +| Maqsood Yaqub | 📖 | +| Marc Lalancette | 📖💻 | +| Marco Castellaro | 💬🐛💻📖💡⚠️📢🚇 | +| Maria de la Iglesia | 📖 | +| Marie-Hélène Bourget | 📖🔣💻🤔 | +| Mark Mikkelsen | 📖 | +| Markus Morawski | 📖 | +| Marta Bortoletto | 📖 | +| Martin Craig | 🔣 | +| Martin Noergaard | 📖🔣💻🤔📢 | +| Martin Szinte | 📖 | +| Martin Wilson | 📖 | +| Martina Bulgari | 📖 | +| Mateusz Pawlik | 📖🐛🤔🚧👀 | +| Mathias Goncalves | 💻🔧📢 | +| Mathieu Boudreau | 💬🤔📢 | +| Matt Sanderson | 📖💻 | +| Matteo Tonietto | 📖 | +| Matthias Günther | 📖 | +| Matthias Van Osch | 📖 | +| Maureen J Shader | 📖 | +| Maurice Pasternak | 📓 | +| Max A. van den Boom | 💻👀📖🐛 | +| Melanie Ganz-Benjaminsen | 📖🔣💻🤔📆🔍📢 | +| Michael Chappell | 📖🔣📆 | +| Michael Hanke | 📖🤔🔧🐛📢 | +| Michael P. Harms | 📖⚠️🔧 | +| Michael P. Milham | 💡🔍 | +| Michael P. Notter | 💬📝✅📢📖 | +| Michael Schirner | 📖 | +| Mikaël Naveau | 🐛 | +| Nader Pouratian | 📖 | +| Natalia Petridou | 📖 | +| National Institute of Mental Health | 💵 | +| Nell Hardcastle | 💻📖🤔🚇👀💬 | +| Nicholas Traut | 📖🔧💻 | +| Nick F. Ramsey | 📖 | +| Nicole C. Swann | 📖 | +| Nima Bigdely Shamlo | 📖 | +| Olivier David | 📖 | +| Orrin Devinsky | 📖 | +| Oscar Esteban | 📖🔧🤔💬💻 | +| Pamela LaMontagne | 📖💡 | +| Parul Sethi | 📖🔧⚠️💻 | +| Patricia Clement | 💬🐛💻📖🔣💡📋🤔📆⚠️📢 | +| Patrick Park | 📖💡💬💻 | +| Paule-Joanne Toussaint | 📖 | +| Peer Herholz | 💬📖👀🔧✅📢 | +| Petra Ritter | 📖 | +| Pierre Rioux | 📖 | +| Pieter Vandemaele | 📖💻 | +| Pradeep Reddy Raamana | 💻🔧 | +| R. Cameron Craddock | 📖📢 | +| Remi Gau | 📖💻💬📢🐛💻🚇👀🔧🤔 | +| Richard Höchenberger | 📖💻 | +| Richard N. Henson | 📖 | +| Robert B. Innis | 📖 | +| Robert E. Smith | 💻📖 | +| Robert Knight | 📖 | +| Robert Luke | 💻 | +| Robert Oostenveld | 📖🔧📢💡✅⚠️🤔💬🐛📝💻🖋️🔣🎨📋🚇👀📓📹 | +| Roberto Toro | 🔧 | +| Rohan Goyal | 📖 | +| Ross W. Blair | 💻 | +| Russell A. Poldrack | 📖🔍📢 | +| Rémi Adon | 📖 | +| Samir Das | 📖 | +| Samuel Garcia | 🤔👀📖 | +| Samuel Nastase | 💻 | +| Sara Elgayar | 📖 | +| Sasha D'Ambrosio | 📖 | +| Satrajit S. Ghosh | 📖💻 | +| Scott Makeig | 📖 | +| Sein Jeung | 📖💡🐛💻🔣🤔💬🔧📓 | +| Shashank Bansal | 📖 | +| Sjoerd B. Vos | 📖 | +| Soichi Hayashi | 📖🔧🐛 | +| Stefan Appelhoff | 📖💬🤔🐛💡💻👀⚠️📢✅🔧🔌📝🚧🔣 | +| Stephan Bickel | 📖 | +| Suyash Bhogawar | 📖💡⚠️🔧💬 | +| Sylvain Baillet | 📖🔍 | +| Sylvain Takerkart | 📖 | +| Sébastien Tourbier | 🤔👀📢🐛💻📖 | +| Sören Grothkopp | 📖🔣📓 | +| Tal Pal Attia | 📖 | +| Tal Yarkoni | 💻📖🤔🔍🔌👀📢🐛🎨 | +| Tamas Spisak | 📖 | +| Tamás Józsa | 📓 | +| Taylor Salo | 💬📖🔌💻 | +| Teon L. Brooks | 📖💻⚠️💬👀🤔🔧🐛📢 | +| Thomas E. Nichols | 📖📢🔧👀🚧💻 | +| Thomas Funck | 📖 | +| Thomas Kirk | 📖 | +| Thomas Okell | 📖 | +| Tibor Auer | 💬📖💡🔧📢🐛🤔 | +| Timo Dickscheid | 📖 | +| Timotheus Berg | 📖🤔📓 | +| Tobey Betthauser | 📖 | +| Tobias Bengfort | 💻 | +| Tom Hampshire | 📖 | +| Tor Wager | 📖 | +| Travis Riddle | 📖🔧🐛 | +| Tristan Glatard | 📖💻 | +| Ulrike Bingel | 📖 | +| Vanessa Sochat | 📖 | +| Vasudev Raguram | 💻🎨📖🔧 | +| Vince D. Calhoun | 📖 | +| Vittorio Iacovella | 📖 | +| Vladimir Litvak | 📖 | +| Wietske van der Zwaag | 🔣💬 | +| William Clarke | 📖 | +| William Triplett | 📖 | +| Wouter V. Potters | 💻📖 | +| Xiangrui Li | 📖💻 | +| Yaroslav O. Halchenko | 📖📢🔧💬🐛💻 | +| Yoni Ashar | 📖 | +| Yuan Wang | 💻 | +| Zachary Michael | 📖 | +| ezemikulan | 💻 | +| josator2 | 💻 | +| monkeyman192 | 💻 | +| Étienne Bergeron | 🔣💻 | diff --git a/tools/add_contributors.py b/tools/add_contributors.py new file mode 100644 index 0000000000..8c3891d26e --- /dev/null +++ b/tools/add_contributors.py @@ -0,0 +1,567 @@ +"""Add new contributors listed in new_contributors.tsv to .tributors file + +The tributor file is then used to update +- the CITATION.cff file +- the .all-contributorsrc file +- TODO: the table of contributors in the appendix of the spec + +Contrary to the typical .tributors file, +the one here also centralizes the contributions +that would otherwise be listed in the .all-contributorsrc file. + +This can also be used to update all files if new_contributors.tsv is empty. +""" + +# TODO: handle the following cases +# - ORCID +# - affiliation +# - getting avatars + +from __future__ import annotations + +import json +import logging +from collections import OrderedDict +from pathlib import Path +from typing import Optional + +import emoji +import pandas as pd +import requests +import ruamel.yaml +from cffconvert.cli.create_citation import create_citation +from cffconvert.cli.validate_or_write_output import validate_or_write_output +from rich.logging import RichHandler +from rich.traceback import install + +INPUT_FILE = Path(__file__).parent / "new_contributors.tsv" + +LOG_LEVEL = "DEBUG" # 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL' + +# Set to True to update the avatars +# update with your github username and path to a file with github token +UPDATE_AVATARS = False +GH_USERNAME = "Remi-Gau" +TOKEN_FILE = None +RICH_STACKTRACE = False + +# Set to True to use some of the dummy data in the "new_contributors.tsv" +TEST = True + + +def logger(log_level="INFO") -> logging.Logger: + """Create log.""" + # let rich print the traceback + FORMAT = "%(asctime)s - %(message)s" + if RICH_STACKTRACE: + install(show_locals=True) + logging.basicConfig( + level=log_level, format=FORMAT, datefmt="[%X]", handlers=[RichHandler()] + ) + else: + logging.basicConfig( + level=log_level, + format=FORMAT, + datefmt="[%X]", + ) + return logging.getLogger("rich") + + +log = logger(log_level=LOG_LEVEL) + +yaml = ruamel.yaml.YAML() +yaml.indent(mapping=2, sequence=4, offset=2) + + +def root_dir() -> Path: + return Path(__file__).parent.parent + + +def emoji_map(reverse=False) -> dict[str, str]: + # https://allcontributors.org/docs/en/emoji-key + if reverse: + tmp = emoji_map() + return {v: k for k, v in tmp.items()} + + return { + "code": ":laptop:", + "doc": ":open_book:", + "ideas": ":thinking_face:", + "bug": ":bug:", + "example": ":light_bulb:", + "question": ":speech_balloon:", + "review": ":eyes:", + "plugin": ":electric_plug:", + "fundingFinding": ":magnifying_glass_tilted_left:", + "talk": ":loudspeaker:", + "design": ":artist_palette:", + "data": ":input_symbols:", + "tool": ":wrench:", + "projectManagement": ":tear-off_calendar:", + "test": ":warning:", + "eventOrganizing": ":clipboard:", + "infra": ":metro:", + "userTesting": ":notebook:", + "video": ":video_camera:", + "blog": ":memo:", + "content": ":fountain_pen:", + "tutorial": ":check_mark_button:", + "maintenance": ":construction:", + "financial": ":dollar_banknote:", + } + + +def return_this_contributor( + df: pd.DataFrame, name: str, contribution_needed=True +) -> dict[str, Optional[str]]: + """Get and validate the data for a given contributor from a panda dataframe""" + name = name.strip() + + mask = df.name == name + + github = df[mask].github.values[0] + if pd.isna(github) or not isinstance(github, (str)): + github = None + + github_username = None + if github is not None: + github_username = github.replace("https://github.com/", "") + if github_username is None: + github_username = name.lower().replace(" ", "_") + + contributions = df[mask].contributions.values[0] + log.debug(f"contributions for {name}: '{contributions}'") + if pd.isna(contributions): + contributions is None + if contribution_needed and contributions is None: + raise ValueError(f"Contributions for {name} not defined in input file.") + if contributions is not None: + contributions = listify_contributions(contributions) + validate_contributions(contributions, name) + contributions = canonicalize_contributions(contributions) + log.debug(f"kept contributions for {name}: {contributions}") + + orcid = df[mask].orcid.values[0] + if pd.isna(orcid) or not isinstance(orcid, (str)): + orcid = None + if orcid is not None: + orcid = orcid.replace("http://", "https://") + + website = df[mask].website.values[0] + affiliation = df[mask].affiliation.values[0] + email = df[mask].email.values[0] + + this_contributor = { + "name": name, + "github": github, + "github_username": github_username, + "blog": website, + "affiliation": affiliation, + "orcid": orcid, + "email": email, + "contributions": contributions, + } + + # light validation / clean up + for key, value in this_contributor.items(): + if value is None: + continue + if not isinstance(this_contributor[key], (list)) and pd.isna( + this_contributor[key] + ): + this_contributor[key] = None + elif isinstance(this_contributor[key], (str)): + this_contributor[key] = this_contributor[key].strip() + elif all(pd.isna(x) for x in this_contributor[key]): + this_contributor[key] = None + + tmp = this_contributor.copy() + for key in this_contributor: + if tmp[key] is None: + tmp.pop(key) + + return tmp + + +def listify_contributions(contributions: str): + contributions = [x.strip() for x in contributions.split(",")] + tmp = [] + for contribution_ in contributions: + tmp.extend(iter(contribution_.split(" "))) + return tmp + + +def validate_contributions(contributions: list, name: str): + allowed_contributions = list(emoji_map().keys()) + allowed_emojis = [emoji.emojize(x) for x in list(emoji_map().values())] + allowed_contributions += allowed_emojis + if any(x for x in contributions if x.replace(":", "") not in allowed_contributions): + raise ValueError( + f"Contributions must be one of {allowed_contributions}.\n" + f" Got '{contributions}' for {name}." + ) + + +def canonicalize_contributions(contributions: list) -> list: + allowed_emojis = [emoji.emojize(x) for x in list(emoji_map().values())] + for contribution_ in contributions: + if contribution_ in allowed_emojis: + demoji = emoji.demojize(contribution_) + contributions[contributions.index(contribution_)] = emoji_map( + reverse=True + ).get(demoji) + for contribution_ in contributions: + contributions[contributions.index(contribution_)] = contribution_.replace( + ":", "" + ) + contributions = sorted(list(set(contributions))) + + return contributions + + +def update_key( + contributor: dict[str, str], key: str, value: str | None +) -> dict[str, str]: + """Update a key in a contributor dict if the value is not None.""" + if value is None: + return contributor + log.info(f"updating {contributor['name']} - {key}") + if key == "contributions": + for contribution in value: + if contribution not in contributor[key]: + contributor[key].append(contribution) + else: + contributor[key] = value + return contributor + + +"""TRIBUTORS""" + + +def load_tributors(tributors_file: Path) -> dict: + """Load .tributors file.""" + with open(tributors_file, "r", encoding="utf8") as tributors_file: + return json.load(tributors_file) + + +def write_tributors(tributors_file: Path, tributors: dict[str, dict]) -> None: + """Write .tributors file.""" + tributors = sort_tributors(tributors) + with open(tributors_file, "w", encoding="utf8") as output_file: + json.dump(tributors, output_file, indent=4, ensure_ascii=False) + + +def return_missing_from_tributors(tributors_file: Path, names: list[str]) -> list[str]: + """Return list of names that are in the input file but not in the .tributors file.""" + tributors = load_tributors(tributors_file) + tributors_names = [tributors[x]["name"] for x in tributors] + for i, name in enumerate(names): + names[i] = name.strip() + missing_from_tributors = set(names) - set(tributors_names) + return sorted(list(missing_from_tributors)) + + +def sort_tributors(tributors: dict[str, dict]) -> dict[str, dict]: + """Sort tributors alphabetically by name of contributor.""" + for key in tributors: + tributors[key] = dict(OrderedDict(sorted(tributors[key].items()))) + return dict(sorted(tributors.items(), key=lambda item: item[1]["name"])) + + +def add_to_tributors( + tributors: dict[str, dict], this_contributor: dict[str, str] +) -> dict[str, dict]: + """Add contributor to .tributors""" + name = this_contributor.get("name") + + tributors_names = [tributors[x]["name"] for x in tributors] + if name in tributors_names: + return tributors + + log.info(f"adding {name}") + + user_login = this_contributor.get("github_username") + this_contributor.pop("github_username", None) + + tributors[user_login] = this_contributor + return tributors + + +def update_tributors( + tributors: dict[str, dict], this_contributor: dict[str, str] +) -> dict[str, dict]: + tributors_names = [tributors[x]["name"] for x in tributors] + + name = this_contributor["name"] + + if name not in tributors_names: + return tributors + + index_tributor = tributors_names.index(this_contributor["name"]) + tributors_keys = list(tributors.keys()) + key_tributor = tributors_keys[index_tributor] + + for key, value in this_contributor.items(): + if key == "github_username" or value is None: + continue + + if key not in tributors[key_tributor]: + tributors[key_tributor] = update_key( + contributor=tributors[key_tributor], + key=key, + value=value, + ) + + if tributors[key_tributor][key] != value: + tributors[key_tributor] = update_key( + contributor=tributors[key_tributor], + key=key, + value=value, + ) + + return tributors + + +"""ALCONTRIB""" + + +def load_allcontrib(allcontrib_file: Path) -> None: + """Load .all-contributorsrc file.""" + with open(allcontrib_file, "r", encoding="utf8") as input_file: + return json.load(input_file) + + +def write_allcontrib(allcontrib_file: Path, allcontrib: dict) -> None: + """Write .all-contributorsrc file.""" + allcontrib = sort_all_contrib(allcontrib) + with open(allcontrib_file, "w", encoding="utf8") as output_file: + json.dump(allcontrib, output_file, indent=4, ensure_ascii=False) + + +def sort_all_contrib(allcontrib: dict) -> dict: + """Sort .all-contributorsrc file alphabetically by name of contributor.""" + for i, contrib in enumerate(allcontrib["contributors"]): + allcontrib["contributors"][i] = dict(OrderedDict(sorted(contrib.items()))) + allcontrib["contributors"] = sorted( + allcontrib["contributors"], key=lambda x: x["name"] + ) + return allcontrib + + +def update_allcontrib(allcontrib: dict, this_contributor: dict[str, str]) -> dict: + """Add a contributor if not in .all-contributorsrc, or update if already in.""" + allcontrib_names = [x["name"] for x in allcontrib["contributors"]] + + if this_contributor["name"] not in allcontrib_names: + log.info(f"adding {this_contributor['name']}") + allcontrib["contributors"].append(this_contributor) + return allcontrib + + index_allcontrib = allcontrib_names.index(this_contributor["name"]) + + for key, value in this_contributor.items(): + if key not in allcontrib["contributors"][index_allcontrib]: + allcontrib["contributors"][index_allcontrib] = update_key( + contributor=allcontrib["contributors"][index_allcontrib], + key=key, + value=value, + ) + + if allcontrib["contributors"][index_allcontrib][key] != value: + allcontrib["contributors"][index_allcontrib] = update_key( + contributor=allcontrib["contributors"][index_allcontrib], + key=key, + value=value, + ) + + return allcontrib + + +def get_gh_avatar(gh_username: str, auth_username: str, auth_token: str) -> str: + """Return url of github avatar.""" + avatar_url = None + + if gh_username is None: + return avatar_url + + log.info(f"getting avatar: {gh_username}") + url = f"https://api.github.com/users/{gh_username}" + response = requests.get(url, auth=(auth_username, auth_token)) + if response.status_code == 200: + avatar_url = response.json()["avatar_url"] + + return avatar_url + + +def rename_keys_for_allcontrib(this_contributor: dict[str, str]) -> dict[str, str]: + """Rename some keys to adapt to all-contributors.""" + renaming_map = { + "name": "name", + "avatar_url": "avatar_url", + "github_username": "login", + "login": "login", + "blog": "profile", + "contributions": "contributions", + } + + renamed = { + renaming_map[key]: this_contributor[key] + for key in this_contributor + if key in renaming_map + } + return renamed + + +"""CITATION.CFF""" + + +def load_citation(citation_file: Path) -> dict: + """Load CITATION.CFF file.""" + with open(citation_file, "r", encoding="utf8") as input_file: + return yaml.load(input_file) + + +def write_citation(citation_file: Path, citation: dict) -> None: + """Write CITATION.CFF file.""" + with open(citation_file, "w", encoding="utf8") as output_file: + return yaml.dump(citation, output_file) + + +def return_author_list_for_cff(tributors_file: Path) -> list[dict[str, str]]: + """Create an dict to be used for the authors in the CITATION.CFF file.""" + tributors = load_tributors(tributors_file) + + author_list = [] + + for _, tributor in enumerate(tributors, start=1): + this_tributor = tributors[tributor] + + name = this_tributor["name"] + + # take as given name the first part of the name and anything ending with a dot + # suboptimal for people with multiple given names + given_names = name.split()[0] + str_index = 1 + while str_index < len(name.split()) and name.split()[str_index].endswith("."): + given_names += f" {name.split()[str_index]}" + str_index += 1 + + new_contrib = { + "given-names": given_names, + } + + if family_names := " ".join(name.split()[str_index:]): + new_contrib["family-names"] = family_names + + if this_tributor.get("blog") is not None: + new_contrib["website"] = this_tributor["blog"] + + if this_tributor.get("orcid") is not None: + new_contrib["orcid"] = "https://orcid.org/" + this_tributor["orcid"] + + if this_tributor.get("affiliation") is not None: + new_contrib["affiliation"] = this_tributor["affiliation"] + + if this_tributor.get("email") is not None: + new_contrib["email"] = this_tributor["email"] + + author_list.append(new_contrib) + + return author_list + + +"""MAIN""" + + +def main(): + token = None + if TOKEN_FILE is not None: + with open(Path(TOKEN_FILE)) as f: + token = f.read().strip() + + log.debug(f"Reading: {INPUT_FILE}") + df = pd.read_csv(INPUT_FILE, sep="\t", encoding="utf8") + log.debug(f"\n{df.head()}") + + tributors_file = root_dir() / ".tributors" + allcontrib_file = root_dir() / ".all-contributorsrc" + citation_file = root_dir() / "CITATION.cff" + + tributors = load_tributors(tributors_file) + tributors_names = [tributors[x]["name"] for x in tributors] + + allcontrib = load_allcontrib(allcontrib_file) + allcontrib_names = [x["name"] for x in allcontrib["contributors"]] + + citation = load_citation(citation_file) + + # sanity checks to make sure no contributor was added manually + assert len(tributors_names) == len(set(tributors_names)) + assert len(allcontrib_names) == len(set(allcontrib_names)) + assert len(tributors_names) == len(allcontrib_names) + assert len(tributors_names) == len(citation["authors"]) + + new_contrib_names = df.name.to_list() + + missing_from_tributors = return_missing_from_tributors( + tributors_file, new_contrib_names + ) + if len(missing_from_tributors) != 0: + log.info("ADDING TO .tributors") + for name in missing_from_tributors: + if not TEST and name in ( + "Margaret E. Heafield", + "Maria Salomea Skłodowska", + ): + log.info(f"skipping {name}") + continue + this_contributor = return_this_contributor(df, name) + add_to_tributors(tributors, this_contributor) + + contributors_to_update = set(new_contrib_names) - set(missing_from_tributors) + if len(contributors_to_update) != 0: + log.info("UPDATING .tributors") + for name in contributors_to_update: + if not TEST and name in ( + "Margaret E. Heafield", + "Maria Salomea Skłodowska", + ): + log.info(f"skipping {name}") + continue + this_contributor = return_this_contributor( + df=df, name=name, contribution_needed=False + ) + tributors = update_tributors(tributors, this_contributor) + + write_tributors(tributors_file, tributors) + + log.info("UPDATING .all-contributorsrc") + for github_username in tributors: + this_contributor = tributors[github_username] + this_contributor["login"] = github_username + this_contributor = rename_keys_for_allcontrib(this_contributor) + + if UPDATE_AVATARS: + avatar_url = get_gh_avatar( + this_contributor["github_username"], GH_USERNAME, token + ) + this_contributor["avatar_url"] = avatar_url + + allcontrib = update_allcontrib(allcontrib, this_contributor) + + write_allcontrib(allcontrib_file, allcontrib) + + log.info("UPDATING CITATION.cff") + citation = load_citation(citation_file) + citation["authors"] = return_author_list_for_cff(tributors_file) + write_citation(citation_file, citation) + + log.info("VALIDATING CITATION.cff") + citation = create_citation(infile=citation_file, url=None) + validate_or_write_output( + outfile=None, outputformat=None, validate_only=True, citation=citation + ) + + +if __name__ == "__main__": + main() diff --git a/tools/new_contributors.tsv b/tools/new_contributors.tsv new file mode 100644 index 0000000000..b4a5a2c11b --- /dev/null +++ b/tools/new_contributors.tsv @@ -0,0 +1,3 @@ +name email github affiliation orcid contributions bio website +Maria Salomea Skłodowska marie-curie@openscience.com MarieCurie Open-Science University, Earth 0320-4024-4203-5343 doc, ideas, :bug:, review Lorem ipsum https://example.com +Margaret E. Heafield ideas code 📖 🚧 👀 🐛 📝 diff --git a/tools/print_contributors.py b/tools/print_contributors.py new file mode 100644 index 0000000000..62f5c7cf92 --- /dev/null +++ b/tools/print_contributors.py @@ -0,0 +1,72 @@ +"""Update the table of contributors in the specification appendice. + + +Takes the content from ".all-contributorsrc" +to update the table of contributors names and contribution. + +""" + +from pathlib import Path + +import emoji +from add_contributors import emoji_map, load_allcontrib, root_dir + +output_file = Path(__file__).parent.parent / "src" / "appendices" / "contributors.md" + + +def contributor_table_header(max_name_length, max_contrib_length): + return f"""| name{" " * (max_name_length-4)} | contributions{" " * (max_contrib_length-13)} | +| {"-" * max_name_length} | {"-"*max_contrib_length} | +""" + + +def create_line_contributor( + contributor: dict[str, str], max_name_length: int, max_contrib_length: int +): + name = contributor["name"] + + line = f"| {name}{' '*(max_name_length-len(name))} | " + + nb_contrib = len(contributor["contributions"]) * 2 + for contrib in contributor["contributions"]: + line += emoji.emojize(emoji_map()[contrib]) + + line += f"{' '*(max_contrib_length-nb_contrib)} |\n" + + return line + + +def main(): + allcontrib_file = root_dir().joinpath(".all-contributorsrc") + allcontrib = load_allcontrib(allcontrib_file) + + allcontrib_names = [x["name"] for x in allcontrib["contributors"]] + + max_name_length = len(max(allcontrib_names, key=len)) + max_contrib_length = ( + max(len(x["contributions"]) for x in allcontrib["contributors"]) * 2 + ) + + with open(output_file, "r", encoding="utf8") as f: + content = f.readlines() + + with open(output_file, "w", encoding="utf8") as f: + for line in content: + if line.startswith("| name"): + break + f.write(line) + + f.write(contributor_table_header(max_name_length, max_contrib_length)) + + for name in sorted(allcontrib_names): + index_allcontrib = allcontrib_names.index(name) + this_contrib = allcontrib["contributors"][index_allcontrib] + f.write( + create_line_contributor( + this_contrib, max_name_length, max_contrib_length + ) + ) + + +if __name__ == "__main__": + main() diff --git a/tools/requirements.txt b/tools/requirements.txt index f2293605cf..34b142a36a 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -1 +1,5 @@ requests +emoji +rich +ruamel.yaml +cffconvert From d37ae4acd672fd121d9f0c2714b766c66d0ca8d2 Mon Sep 17 00:00:00 2001 From: Teon L Brooks Date: Wed, 19 Jul 2023 07:59:50 -0400 Subject: [PATCH 18/43] Update CONTRIBUTING.md (#1559) fixed a typo --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 89154c9059..40fae2e3ea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -718,7 +718,7 @@ either make a change to the part of a pull request or you can edit this [page](https://github.com/bids-standard/bids-specification/wiki/Recent-Contributors) of the specification WIKI. -The WIKI is then synced with the specification with evert new release of the specifications. +The WIKI is then synced with the specification with every new release of the specifications. ## Thank you! From 6d990c86deb4b00761fff5936eeca1ef010f8b8c Mon Sep 17 00:00:00 2001 From: bids-maintenance Date: Thu, 20 Jul 2023 13:49:56 +0000 Subject: [PATCH 19/43] [DOC] Auto-generate changelog entry for PR #1525 --- src/CHANGES.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/CHANGES.md b/src/CHANGES.md index ea1173572d..261bb25a44 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,15 @@ ## [Unreleased](https://github.com/bids-standard/bids-specification/tree/HEAD) +- \[FIX] Update links to BIDS examples [#1545](https://github.com/bids-standard/bids-specification/pull/1545) ([Remi-Gau](https://github.com/Remi-Gau)) +- \[FIX] match subject label in folder and filename in func example [#1536](https://github.com/bids-standard/bids-specification/pull/1536) ([Remi-Gau](https://github.com/Remi-Gau)) +- FIX: Trail MEG directory formats with `/` [#1534](https://github.com/bids-standard/bids-specification/pull/1534) ([effigies](https://github.com/effigies)) +- \[ENH] Permit CITATION.cff as structured alternative to some dataset_description fields [#1525](https://github.com/bids-standard/bids-specification/pull/1525) ([effigies](https://github.com/effigies)) +- \[FIX] Add missing column description in physio example [#1514](https://github.com/bids-standard/bids-specification/pull/1514) ([sappelhoff](https://github.com/sappelhoff)) +- \[ENH] Clarify that data files must be uniquely identified by entities/suffix [#1508](https://github.com/bids-standard/bids-specification/pull/1508) ([sappelhoff](https://github.com/sappelhoff)) +- DOC: Auto-generate full API docs [#1505](https://github.com/bids-standard/bids-specification/pull/1505) ([effigies](https://github.com/effigies)) +- \[INFRA] Publish schema tools API docs to additional ReadTheDocs site [#1491](https://github.com/bids-standard/bids-specification/pull/1491) ([bendhouseart](https://github.com/bendhouseart)) +- \[FIX] Remove references to unspecified aslcontext.json [#1485](https://github.com/bids-standard/bids-specification/pull/1485) ([Remi-Gau](https://github.com/Remi-Gau)) - \[FIX] Revert index (entity format) definition to be a non-negative number, permitting zero [#1482](https://github.com/bids-standard/bids-specification/pull/1482) ([TheChymera](https://github.com/TheChymera)) - ENH: Add version list to schema.meta and a warning on unknown BIDSVersion [#1472](https://github.com/bids-standard/bids-specification/pull/1472) ([effigies](https://github.com/effigies)) - \[FIX] Clean up qMRI RB1COR notes [#1465](https://github.com/bids-standard/bids-specification/pull/1465) ([lukeje](https://github.com/lukeje)) @@ -33,9 +42,12 @@ - \[ENH] Recommend gzip header fields be set to empty values [#1349](https://github.com/bids-standard/bids-specification/pull/1349) ([kousu](https://github.com/kousu)) - \[FIX] clarify TriggerChannelCount and TRIG type [#1342](https://github.com/bids-standard/bids-specification/pull/1342) ([sappelhoff](https://github.com/sappelhoff)) - \[ENH] Add qMRI fieldmap filename templates [#1336](https://github.com/bids-standard/bids-specification/pull/1336) ([Remi-Gau](https://github.com/Remi-Gau)) +- ENH: Introduce GIFTI formats in derivatives [#1333](https://github.com/bids-standard/bids-specification/pull/1333) ([effigies](https://github.com/effigies)) - \[ENH] Add ParallelReductionFactorOutOfPlane to MRI metadata [#1221](https://github.com/bids-standard/bids-specification/pull/1221) ([lukeje](https://github.com/lukeje)) - \[ENH]\[SCHEMA] Adding an OPTIONAL \_task-\