From 722ecadb1a03ceeb27145fbfb120f2d1ecf72849 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 25 Apr 2024 16:59:50 -0400 Subject: [PATCH 1/5] Enable stems to be globs --- bids-validator/src/deps/path.ts | 3 +++ bids-validator/src/validators/filenameIdentify.ts | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/bids-validator/src/deps/path.ts b/bids-validator/src/deps/path.ts index a19d88058..de21eb5e6 100644 --- a/bids-validator/src/deps/path.ts +++ b/bids-validator/src/deps/path.ts @@ -9,3 +9,6 @@ export { parse, SEPARATOR, } from 'https://deno.land/std@0.217.0/path/mod.ts' +export { + globToRegExp, +} from 'https://deno.land/std@0.217.0/path/glob_to_regexp.ts' diff --git a/bids-validator/src/validators/filenameIdentify.ts b/bids-validator/src/validators/filenameIdentify.ts index 5cfbdc6cc..c3a0ac060 100644 --- a/bids-validator/src/validators/filenameIdentify.ts +++ b/bids-validator/src/validators/filenameIdentify.ts @@ -12,7 +12,7 @@ * object in the schema for reference. */ // @ts-nocheck -import { SEPARATOR } from '../deps/path.ts' +import { SEPARATOR, globToRegExp } from '../deps/path.ts' import { GenericSchema, Schema } from '../types/schema.ts' import { BIDSContext } from '../schema/context.ts' import { lookupModality } from '../schema/modalities.ts' @@ -56,7 +56,7 @@ function findRuleMatches(schema, context) { export function _findRuleMatches(node, path, context) { if ( ('path' in node && context.file.name.endsWith(node.path)) || - ('stem' in node && context.file.name.startsWith(node.stem)) || + ('stem' in node && context.file.name.match(globToRegExp(node.stem + '*'))) || ('suffixes' in node && node.suffixes.includes(context.suffix)) ) { context.filenameRules.push(path) From 2e84f817fa89aba6c951e9296cdd862f85ccbf4a Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 25 Apr 2024 21:11:40 -0400 Subject: [PATCH 2/5] feat: Accept phenotype as a pseudo-datatype --- .../src/validators/filenameIdentify.ts | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/bids-validator/src/validators/filenameIdentify.ts b/bids-validator/src/validators/filenameIdentify.ts index c3a0ac060..e19754205 100644 --- a/bids-validator/src/validators/filenameIdentify.ts +++ b/bids-validator/src/validators/filenameIdentify.ts @@ -74,27 +74,18 @@ export function _findRuleMatches(node, path, context) { export async function datatypeFromDirectory(schema, context) { const subEntity = schema.objects.entities.subject.name - const subFormat = schema.objects.formats[subEntity.format] const sesEntity = schema.objects.entities.session.name - const sesFormat = schema.objects.formats[sesEntity.format] const parts = context.file.path.split(SEPARATOR) - let datatypeIndex = 2 - if (parts[0] !== '') { - // we assume paths have leading '/' - } - // Ignoring associated data for now - const subParts = parts[1].split('-') - if (!(subParts.length === 2 && subParts[0] === subEntity)) { - // first directory must be subject - } - if (parts.length < 3) { + let datatypeIndex = parts.length - 2 + if (datatypeIndex < 1) { return Promise.resolve() } - const sesParts = parts[2].split('-') - if (sesParts.length === 2 && sesParts[0] === sesEntity) { - datatypeIndex = 3 - } const dirDatatype = parts[datatypeIndex] + if (dirDatatype === 'phenotype') { + // Phenotype is a pseudo-datatype for now. + context.datatype = dirDatatype + return Promise.resolve() + } for (let key in schema.rules.modalities) { if (schema.rules.modalities[key].datatypes.includes(dirDatatype)) { context.modality = key From 9822199eecfb85cd9751d9cfa373a6e14c524752 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 25 Apr 2024 21:46:50 -0400 Subject: [PATCH 3/5] fix: Check if rule.entities exists before accessing keys --- bids-validator/src/validators/filenameIdentify.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bids-validator/src/validators/filenameIdentify.ts b/bids-validator/src/validators/filenameIdentify.ts index e19754205..0816cf638 100644 --- a/bids-validator/src/validators/filenameIdentify.ts +++ b/bids-validator/src/validators/filenameIdentify.ts @@ -145,9 +145,9 @@ function entitiesExtensionsInRule( ): boolean { const rule = schema[path] const fileEntities = Object.keys(context.entities) - const ruleEntities = Object.keys(rule.entities).map((key) => + const ruleEntities = rule.entities ? Object.keys(rule.entities).map((key) => lookupEntityLiteral(key, schema), - ) + ) : [] const extInRule = !rule.extensions || (rule.extensions && rule.extensions.includes(context.extension)) From 0dc469157bd9139fe8ab2843d027efe0dbb053c8 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Mon, 22 Apr 2024 16:01:14 -0400 Subject: [PATCH 4/5] FIX: Expect multiple rule matches for events.json This test is a bit weird; it seems to have been relying on arbitrary pruning. There's nothing in the rules or code that now (as of #1940) should prevent multiple rules from being returned. If we do want a test to verify pruning, we should come up with a new one. --- bids-validator/src/validators/filenameIdentify.test.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bids-validator/src/validators/filenameIdentify.test.ts b/bids-validator/src/validators/filenameIdentify.test.ts index c765311a0..64a78adfc 100644 --- a/bids-validator/src/validators/filenameIdentify.test.ts +++ b/bids-validator/src/validators/filenameIdentify.test.ts @@ -74,7 +74,7 @@ Deno.test('test hasMatch', async (t) => { hasMatch(schema, context) }) - await t.step('No match', async () => { + await t.step('No match', async () => { const fileName = Deno.makeTempFileSync().split('/')[2] const file = new BIDSFileDeno('/tmp', fileName, ignore) @@ -87,7 +87,7 @@ Deno.test('test hasMatch', async (t) => { true, ) }) - await t.step('1+ matched, datatype match', async () => { + await t.step('2 matches, no pruning', async () => { const path = `${PATH}/../bids-examples/fnirs_automaticity` const fileName = 'events.json' const file = new BIDSFileDeno(path, fileName, ignore) @@ -97,7 +97,6 @@ Deno.test('test hasMatch', async (t) => { 'rules.files.raw.task.events__pet', ] await hasMatch(schema, context) - assertEquals(context.filenameRules.length, 1) - assertEquals(context.filenameRules[0], 'rules.files.raw.task.events__mri') + assertEquals(context.filenameRules.length, 2) }) }) From 173ecc25a616ff2eb0ce7b41be355af7b76779b1 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Wed, 24 Apr 2024 23:13:35 -0400 Subject: [PATCH 5/5] feat: Add values to associations.bvals, fix misnamed variables --- bids-validator/src/schema/associations.ts | 13 +++++++------ bids-validator/src/types/context.ts | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/bids-validator/src/schema/associations.ts b/bids-validator/src/schema/associations.ts index db42a6732..e6ccaabaf 100644 --- a/bids-validator/src/schema/associations.ts +++ b/bids-validator/src/schema/associations.ts @@ -82,11 +82,12 @@ const associationLookup = { inherit: true, load: async (file: BIDSFile): Promise => { const contents = await file.text() - const columns = parseBvalBvec(contents) + const rows = parseBvalBvec(contents) return { path: file.path, - n_cols: columns ? columns[0].length : 0, - n_rows: columns ? columns.length : 0, + n_cols: rows ? rows[0].length : 0, + n_rows: rows ? rows.length : 0, + values: rows[0], } }, }, @@ -96,11 +97,11 @@ const associationLookup = { inherit: true, load: async (file: BIDSFile): Promise => { const contents = await file.text() - const columns = parseBvalBvec(contents) + const rows = parseBvalBvec(contents) return { path: file.path, - n_cols: columns ? columns[0].length : 0, - n_rows: columns ? columns.length : 0, + n_cols: rows ? rows[0].length : 0, + n_rows: rows ? rows.length : 0, } }, }, diff --git a/bids-validator/src/types/context.ts b/bids-validator/src/types/context.ts index 4b03fcbee..de2c1ac69 100644 --- a/bids-validator/src/types/context.ts +++ b/bids-validator/src/types/context.ts @@ -44,6 +44,7 @@ export interface ContextAssociationsBval { path: string n_cols: number n_rows: number + values: number[] } export interface ContextAssociationsBvec { path: string