From 31c5ae7396fa30f3b6e00de11379c295f56e62af Mon Sep 17 00:00:00 2001 From: Eric Earl Date: Thu, 13 Feb 2025 10:49:15 -0800 Subject: [PATCH 1/4] Add pheno004 example dataset Meant for the resolution of bids-spec PR 2044. --- pheno004/README.md | 23 +++++++ pheno004/dataset_description.json | 12 ++++ pheno004/participants.json | 16 +++++ pheno004/participants.tsv | 4 ++ pheno004/phenotype/ace.json | 92 ++++++++++++++++++++++++++ pheno004/phenotype/ace.tsv | 3 + pheno004/phenotype/demographics.json | 64 ++++++++++++++++++ pheno004/phenotype/demographics.tsv | 3 + pheno004/sub-01/anat/sub-01_T1w.json | 63 ++++++++++++++++++ pheno004/sub-01/anat/sub-01_T1w.nii.gz | 0 pheno004/sub-02/anat/sub-02_T1w.json | 69 +++++++++++++++++++ pheno004/sub-02/anat/sub-02_T1w.nii.gz | 0 12 files changed, 349 insertions(+) create mode 100644 pheno004/README.md create mode 100644 pheno004/dataset_description.json create mode 100644 pheno004/participants.json create mode 100644 pheno004/participants.tsv create mode 100644 pheno004/phenotype/ace.json create mode 100644 pheno004/phenotype/ace.tsv create mode 100644 pheno004/phenotype/demographics.json create mode 100644 pheno004/phenotype/demographics.tsv create mode 100644 pheno004/sub-01/anat/sub-01_T1w.json create mode 100644 pheno004/sub-01/anat/sub-01_T1w.nii.gz create mode 100644 pheno004/sub-02/anat/sub-02_T1w.json create mode 100644 pheno004/sub-02/anat/sub-02_T1w.nii.gz diff --git a/pheno004/README.md b/pheno004/README.md new file mode 100644 index 000000000..0491b65d2 --- /dev/null +++ b/pheno004/README.md @@ -0,0 +1,23 @@ +# BEP036 example dataset 04: One imaging-only, one phenotypic-only, and one with both imaging and phenotypic data + +This dataset contains imaging data and phenotypic data from one subject, only imaging data for another subject, and only phenotypic data for a third subject. Phenotype and imaging data were collected at the same session. The file tree is as follows: + +```ascii +📦pheno004 + ┣ 📂phenotype + ┃ ┣ 📜ace.json + ┃ ┣ 📜ace.tsv + ┃ ┣ 📜demographics.json + ┃ ┗ 📜demographics.tsv + ┣ 📂sub-01 + ┃ ┗ 📂anat + ┃ ┃ ┣ 📜sub-01_T1w.json + ┃ ┃ ┗ 📜sub-01_T1w.nii.gz + ┣ 📂sub-02 + ┃ ┗ 📂anat + ┃ ┃ ┣ 📜sub-02_T1w.json + ┃ ┃ ┗ 📜sub-02_T1w.nii.gz + ┣ 📜participants.json + ┣ 📜participants.tsv + ┗ 📜README.md +``` diff --git a/pheno004/dataset_description.json b/pheno004/dataset_description.json new file mode 100644 index 000000000..17c712a0d --- /dev/null +++ b/pheno004/dataset_description.json @@ -0,0 +1,12 @@ +{ + "Name": "Mixed Phenotype+Participants", + "BIDSVersion": "1.11.0", + "License": "CC0", + "Authors": [ + "Eric Earl", + "Arshitha Basavaraj", + "Samuel Guay", + "Sebastian Urchs" + ], + "Acknowledgements": "Acknowledgements" +} \ No newline at end of file diff --git a/pheno004/participants.json b/pheno004/participants.json new file mode 100644 index 000000000..8408853fd --- /dev/null +++ b/pheno004/participants.json @@ -0,0 +1,16 @@ +{ + "participant_id": { + "Description": "OpenNeuro ID of the subject." + }, + "sex": { + "Description": "Sex assigned at birth.", + "Levels": { + "m": "Male", + "f": "Female" + } + }, + "age": { + "Description": "Age of the participant.", + "Units": "years" + } +} diff --git a/pheno004/participants.tsv b/pheno004/participants.tsv new file mode 100644 index 000000000..a5c7696c6 --- /dev/null +++ b/pheno004/participants.tsv @@ -0,0 +1,4 @@ +participant_id sex age +sub-01 m 22 +sub-02 f 63 +sub-03 f 47 diff --git a/pheno004/phenotype/ace.json b/pheno004/phenotype/ace.json new file mode 100644 index 000000000..cdb90410b --- /dev/null +++ b/pheno004/phenotype/ace.json @@ -0,0 +1,92 @@ +{ + "participant_id": { + "Description": "OpenNeuro ID of the subject." + }, + "session_id": { + "Description": "ID assigned to participant's visit.", + "Levels": { + "baseline": "First in-person visit.", + "followup": "Second in-person visit." + } + }, + "b_ace_q1": { + "LongName": "ACE_HUMILIATE_HURT (question ID 176435)", + "Description": "1. Did a parent or other adult in the household often swear at you, insult you, put you down, or humiliate you, or act in a way that made you afraid that you might be physically hurt?", + "Levels": { + "1": "Yes", + "0": "No" + } + }, + "b_ace_q2": { + "LongName": "ACE_INJURE (question ID 176436)", + "Description": "2. Did a parent or other adult in the household often push, grab, slap, or throw something at you or ever hit you so hard that you had marks or were injured? ", + "Levels": { + "1": "Yes", + "0": "No" + } + }, + "b_ace_q3": { + "LongName": "ACE_TOUCH_SEX_WAY (question ID 176437)", + "Description": "3. Did an adult or person at least 5 years older than you ever touch or fondle you or have you touch their body in a sexual way or try to or actually have oral, anal, or vaginal sex with you? ", + "Levels": { + "1": "Yes", + "0": "No" + } + }, + "b_ace_q4": { + "LongName": "ACE_NO_LOVE_SUPPORT (question ID 176438)", + "Description": "4. Did you often feel that no one in your family loved you or thought you were important or special or your family didn't look out for each other, feel close to each other, or support each other? ", + "Levels": { + "1": "Yes", + "0": "No" + } + }, + "b_ace_q5": { + "LongName": "ACE_PROTECT_CARE (question ID 176439)", + "Description": "5. Did you often feel that you didn't have enough to eat, had to wear dirty clothes, and had no one to protect you or your parents were too drunk or high to take care of you or take you to the doctor if you needed it?", + "Levels": { + "1": "Yes", + "0": "No" + } + }, + "tesi_s_165": { + "LongName": "ACE_SEPARATE_DIVORCE (question ID 176440)", + "Description": "6. Were your parents ever separated or divorced?", + "Levels": { + "1": "Yes", + "0": "No" + } + }, + "b_ace_q7": { + "LongName": "ACE_MOTHER_HURT (question ID 176441)", + "Description": "7. Was your mother or stepmother: Often pushed, grabbed, slapped, or had something thrown at her? or sometimes or often kicked, bitten, hit with a fist, or hit with something hard? or ever repeatedly hit over at least a few minutes or threatened with a gun or knife? ", + "Levels": { + "1": "Yes", + "0": "No" + } + }, + "b_ace_q8": { + "LongName": "ACE_LIVE_ALCOHOL_DRUGS (question ID 176442)", + "Description": "8. Did you live with anyone who was a problem drinker or alcoholic or who used street drugs? ", + "Levels": { + "1": "Yes", + "0": "No" + } + }, + "b_ace_q9": { + "LongName": "ACE_HOUSEHOLD_DEPRESS (question ID 176443)", + "Description": "9. Was a household member depressed or mentally ill or did a household member attempt suicide? ", + "Levels": { + "1": "Yes", + "0": "No" + } + }, + "ceahd15": { + "LongName": "ACE_HOUSEHOLD_PRISON (question ID 176444)", + "Description": "10. Did a household member go to prison?", + "Levels": { + "1": "Yes", + "0": "No" + } + } +} diff --git a/pheno004/phenotype/ace.tsv b/pheno004/phenotype/ace.tsv new file mode 100644 index 000000000..e1caf0d74 --- /dev/null +++ b/pheno004/phenotype/ace.tsv @@ -0,0 +1,3 @@ +participant_id b_ace_q1 b_ace_q2 b_ace_q3 b_ace_q4 b_ace_q5 tesi_s_165 b_ace_q7 b_ace_q8 b_ace_q9 ceahd15 +sub-01 0 0 0 0 0 0 1 0 0 0 +sub-03 0 0 0 0 0 0 0 0 0 0 diff --git a/pheno004/phenotype/demographics.json b/pheno004/phenotype/demographics.json new file mode 100644 index 000000000..20edad26f --- /dev/null +++ b/pheno004/phenotype/demographics.json @@ -0,0 +1,64 @@ +{ + "participant_id": { + "Description": "OpenNeuro ID of the subject." + }, + "session_id": { + "Description": "ID assigned to participant's visit.", + "Levels": { + "onlineScreening": "First online screening visit.", + "onlineFollowup": "Online follow-up visit after 1 year of first in-person visit." + } + }, + "gender": { + "Description": "2. What sex were you assigned at birth, on your original birth certificate?", + "Levels": { + "m": "Male", + "f": "Female" + } + }, + "race": { + "LongName": "RACE_1, first endorsement", + "Description": "5. Race: (Check all that apply)", + "Levels": { + "1": "American Indian/Alaska Native", + "2": "Asian", + "3": "Hawaiian/Pacific Islander", + "4": "Black/African American", + "5": "White/Caucasian", + "6": "Multiple race", + "7": "Unknown" + } + }, + "ethnicity": { + "LongName": "ETHNICITY_1 (question ID 140032)", + "Description": "6. Ethnicity:", + "Levels": { + "0": "Not Hispanic or Latino", + "1": "Hispanic or Latino", + "2": "Unknown" + } + }, + "education": { + "LongName": "EDUCATION (question ID 58226)", + "Description": "10. Education level:", + "Levels": { + "0": "High school graduate or above", + "1": "Some college or above", + "2": "Associates degree or above", + "3": "Bachelors degree or above", + "4": "Advanced/professional degree" + } + }, + "marital_status": { + "LongName": "MARITAL_STATUS (question ID 7171)", + "Description": "11. Marital Status:", + "Levels": { + "1": "Single/Never married", + "2": "Married or living with someone as if married", + "3": "Divorced or annulled", + "4": "Separated", + "5": "Widowed", + "6": "Other" + } + } +} diff --git a/pheno004/phenotype/demographics.tsv b/pheno004/phenotype/demographics.tsv new file mode 100644 index 000000000..4e5a30396 --- /dev/null +++ b/pheno004/phenotype/demographics.tsv @@ -0,0 +1,3 @@ +participant_id gender race ethnicity education marital_status +sub-01 m 3 0 4 1 +sub-03 f 6 0 3 2 diff --git a/pheno004/sub-01/anat/sub-01_T1w.json b/pheno004/sub-01/anat/sub-01_T1w.json new file mode 100644 index 000000000..990fec775 --- /dev/null +++ b/pheno004/sub-01/anat/sub-01_T1w.json @@ -0,0 +1,63 @@ +{ + "Modality": "MR", + "MagneticFieldStrength": 3, + "ImagingFrequency": 127.695727, + "Manufacturer": "GE", + "ManufacturersModelName": "DISCOVERY MR750", + "BodyPartExamined": "BRAIN", + "PatientPosition": "HFS", + "ProcedureStepDescription": "MRI Brain", + "SoftwareVersions": "27\\LX\\MR Software release:DV26.0_R03_1831.b", + "MRAcquisitionType": "3D", + "SeriesDescription": "ORIG Anat T1w MP-RAGE 1mm (ABCD)", + "ProtocolName": "[XT-ID:17-M-0181] ADNI3", + "ScanningSequence": "RM", + "SequenceVariant": "NONE", + "ScanOptions": "EDR_GEMS\\PROMO_GEMS\\ACC_GEMS\\IR_GEMS", + "PulseSequenceName": "mprage", + "ImageType": [ + "ORIGINAL", + "PRIMARY", + "OTHER" + ], + "SeriesNumber": 40003, + "AcquisitionTime": "12:43:16.000000", + "AcquisitionNumber": 1, + "SliceThickness": 1, + "SpacingBetweenSlices": 1, + "SAR": 0.115406, + "EchoTime": 0.00292, + "RepetitionTime": 0.006952, + "InversionTime": 1.06, + "FlipAngle": 8, + "ShimSetting": [ + 3, + -2, + -13 + ], + "PrescanReuseString": "TG/s2,RN/s1", + "CoilString": "32Ch Head", + "PercentPhaseFOV": 100, + "PercentSampling": 100, + "AcquisitionMatrixPE": 256, + "ReconMatrixPE": 256, + "ParallelReductionFactorInPlane": 2, + "ParallelReductionFactorOutOfPlane": 2, + "PixelBandwidth": 244.141, + "ImageOrientationPatientDICOM": [ + 0, + 1, + 0, + 0, + 0, + -1 + ], + "InPlanePhaseEncodingDirectionDICOM": "ROW", + "BidsGuess": [ + "anat", + "_acq-EFGRE3Dp2_run-40003_T1w" + ], + "ConversionSoftware": "dcm2niix", + "ConversionSoftwareVersion": "v1.0.20240202", + "Dcm2bidsVersion": "3.1.1" +} \ No newline at end of file diff --git a/pheno004/sub-01/anat/sub-01_T1w.nii.gz b/pheno004/sub-01/anat/sub-01_T1w.nii.gz new file mode 100644 index 000000000..e69de29bb diff --git a/pheno004/sub-02/anat/sub-02_T1w.json b/pheno004/sub-02/anat/sub-02_T1w.json new file mode 100644 index 000000000..93ac35e87 --- /dev/null +++ b/pheno004/sub-02/anat/sub-02_T1w.json @@ -0,0 +1,69 @@ +{ + "Modality": "MR", + "MagneticFieldStrength": 3, + "ImagingFrequency": 127.696, + "Manufacturer": "GE", + "ManufacturersModelName": "DISCOVERY MR750", + "BodyPartExamined": "BRAIN", + "PatientPosition": "HFS", + "ProcedureStepDescription": "MRI Brain", + "SoftwareVersions": "27\\LX\\MR Software release:DV26.0_R03_1831.b", + "MRAcquisitionType": "3D", + "SeriesDescription": "ORIG Anat T1w MP-RAGE 1mm (ABCD)", + "ProtocolName": "ADNI3 FMRIF Enhanced Pro", + "ScanningSequence": "RM", + "SequenceVariant": "NONE", + "ScanOptions": "EDR_GEMS\\PROMO_GEMS\\ACC_GEMS\\IR_GEMS", + "ImageType": [ + "ORIGINAL", + "PRIMARY", + "OTHER" + ], + "SeriesNumber": 40003, + "AcquisitionTime": "15:33:5.000000", + "AcquisitionNumber": 1, + "SliceThickness": 1, + "SpacingBetweenSlices": 1, + "SAR": 0.121617, + "EchoTime": 0.00292, + "RepetitionTime": 0.006952, + "InversionTime": 1.06, + "FlipAngle": 8, + "CoilString": "32Ch Head", + "PercentPhaseFOV": 100, + "PercentSampling": 100, + "AcquisitionMatrixPE": 256, + "ReconMatrixPE": 256, + "ParallelReductionFactorInPlane": 2, + "ParallelReductionOutOfPlane": 2, + "PixelBandwidth": 244.141, + "ImageOrientationPatientDICOM": [ + 0, + 1, + 0, + 0, + 0, + -1 + ], + "InPlanePhaseEncodingDirectionDICOM": "ROW", + "ConversionSoftware": "dcm2niix", + "ConversionSoftwareVersion": "v1.0.20211006", + "Dcm2bidsVersion": "2.1.6", + "AnatomicalLandmarkCoordinates": { + "NAS": [ + 111.79899853515624, + 216.0946962158203, + 125.91931025390625 + ], + "LPA": [ + 36.48359853515625, + 138.14889621582032, + 92.27751025390626 + ], + "RPA": [ + 175.88069853515626, + 122.28609621582031, + 92.83361025390624 + ] + } +} \ No newline at end of file diff --git a/pheno004/sub-02/anat/sub-02_T1w.nii.gz b/pheno004/sub-02/anat/sub-02_T1w.nii.gz new file mode 100644 index 000000000..e69de29bb From a819d6a38cb253bedaefdf5a736c90293f3eb3c6 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Thu, 13 Feb 2025 14:04:27 -0500 Subject: [PATCH 2/4] chore(ci): Use draft schema, shield pheno004 from older validators --- .github/workflows/validate_datasets.yml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/validate_datasets.yml b/.github/workflows/validate_datasets.yml index b9d1ae6f1..086ec311d 100644 --- a/.github/workflows/validate_datasets.yml +++ b/.github/workflows/validate_datasets.yml @@ -96,12 +96,21 @@ jobs: shell: bash - name: Skip legacy validation for post-legacy datasets - run: for DS in mrs_* dwi_deriv; do touch $DS/.SKIP_VALIDATION; done + run: for DS in mrs_* dwi_deriv pheno004; do touch $DS/.SKIP_VALIDATION; done if: matrix.bids-validator == 'legacy' shell: bash - - name: Skip stable validation for datasets with unreleased features - run: for DS in dwi_deriv; do touch $DS/.SKIP_VALIDATION; done + - name: Skip stable validation for datasets with unreleased validator features + # Replace ${EMPTY} with dataset patterns, when this is needed + # Reset to "for DS in ${EMPTY}; ..." after a validator release + run: for DS in ${EMPTY}; do touch $DS/.SKIP_VALIDATION; done + if: matrix.bids-validator == 'stable' + shell: bash + + - name: Skip main validation for datasets with unreleased spec features + # Replace ${EMPTY} with dataset patterns, when this is needed + # Reset to "for DS in ${EMPTY}; ..." after a spec release + run: for DS in dwi_deriv pheno004; do touch $DS/.SKIP_VALIDATION; done if: matrix.bids-validator != 'dev' shell: bash @@ -111,7 +120,7 @@ jobs: # Update this URL to the schema.json from PRs to the spec, when needed. # If this variable is unset, dev will generally track the latest development # release of https://jsr.io/@bids/schema - run: echo BIDS_SCHEMA=https://bids-specification.readthedocs.io/en/latest/schema.json >> $GITHUB_ENV + run: echo BIDS_SCHEMA=https://bids-specification--2044.org.readthedocs.build/en/2044/schema.json >> $GITHUB_ENV - name: Validate all BIDS datasets using bids-validator run: | From 9a513a085d3334ed8e189eba79ce7f3dd0a89a15 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Thu, 13 Feb 2025 14:20:05 -0500 Subject: [PATCH 3/4] chore(ci): Use bash always to avoid Windows carve-outs --- .github/workflows/validate_datasets.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/validate_datasets.yml b/.github/workflows/validate_datasets.yml index 086ec311d..af4ab98f4 100644 --- a/.github/workflows/validate_datasets.yml +++ b/.github/workflows/validate_datasets.yml @@ -15,6 +15,10 @@ concurrency: group: ${{ github.ref }} cancel-in-progress: true +defaults: + run: + shell: bash + jobs: build: strategy: @@ -47,7 +51,6 @@ jobs: if: matrix.bids-validator == 'stable' run: | deno install -Agf -n bids-validator jsr:@bids/validator - shell: bash - name: Install BIDS validator (main) if: matrix.bids-validator == 'main' @@ -55,7 +58,6 @@ jobs: # If unmerged validator PRs are needed for testing, you can use # https://github.com//bids-validator/raw//bids-validator/src/bids-validator.ts deno install -Agf https://github.com/bids-standard/bids-validator/raw/deno-build/bids-validator.js - shell: bash - name: Install BIDS validator (dev) if: matrix.bids-validator == 'dev' @@ -63,7 +65,6 @@ jobs: git clone -b dev https://github.com/bids-standard/bids-validator/ ../bids-validator cd ../bids-validator deno compile -A -o $HOME/.deno/bin/bids-validator src/bids-validator.ts - shell: bash - name: Install BIDS validator (legacy) if: "matrix.bids-validator == 'legacy'" @@ -78,7 +79,6 @@ jobs: echo "node\n----"; node --version echo "npm\n----"; npm --version echo "bids-validator"; bids-validator --version - shell: bash - name: Check that no large files are present if: "matrix.bids-validator == 'stable'" @@ -93,26 +93,22 @@ jobs: echo "$found" exit 1; fi - shell: bash - name: Skip legacy validation for post-legacy datasets run: for DS in mrs_* dwi_deriv pheno004; do touch $DS/.SKIP_VALIDATION; done if: matrix.bids-validator == 'legacy' - shell: bash - name: Skip stable validation for datasets with unreleased validator features # Replace ${EMPTY} with dataset patterns, when this is needed # Reset to "for DS in ${EMPTY}; ..." after a validator release run: for DS in ${EMPTY}; do touch $DS/.SKIP_VALIDATION; done if: matrix.bids-validator == 'stable' - shell: bash - name: Skip main validation for datasets with unreleased spec features # Replace ${EMPTY} with dataset patterns, when this is needed # Reset to "for DS in ${EMPTY}; ..." after a spec release run: for DS in dwi_deriv pheno004; do touch $DS/.SKIP_VALIDATION; done if: matrix.bids-validator != 'dev' - shell: bash - name: Set BIDS_SCHEMA variable for dev version if: matrix.bids-validator == 'dev' @@ -126,4 +122,3 @@ jobs: run: | cat ./run_tests.sh ./run_tests.sh - shell: bash From 1d87d0dce93259e5b7af8f1b70955c55fa7095ab Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Fri, 21 Feb 2025 15:28:51 -0500 Subject: [PATCH 4/4] Apply suggestions from code review --- .github/workflows/validate_datasets.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate_datasets.yml b/.github/workflows/validate_datasets.yml index af4ab98f4..85a841f1e 100644 --- a/.github/workflows/validate_datasets.yml +++ b/.github/workflows/validate_datasets.yml @@ -116,7 +116,7 @@ jobs: # Update this URL to the schema.json from PRs to the spec, when needed. # If this variable is unset, dev will generally track the latest development # release of https://jsr.io/@bids/schema - run: echo BIDS_SCHEMA=https://bids-specification--2044.org.readthedocs.build/en/2044/schema.json >> $GITHUB_ENV + run: echo BIDS_SCHEMA=https://bids-specification.readthedocs.io/en/latest/schema.json >> $GITHUB_ENV - name: Validate all BIDS datasets using bids-validator run: |