bids-validator-deno 2.0.9__tar.gz → 2.0.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bids-validator-deno might be problematic. Click here for more details.
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/PKG-INFO +1 -1
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/deno.json +1 -1
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/pyproject.toml +1 -1
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/json.test.ts +3 -3
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/json.ts +4 -4
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/nifti.test.ts +1 -1
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/nifti.ts +2 -2
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/tsv.test.ts +3 -3
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/tsv.ts +7 -3
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/applyRules.ts +4 -1
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/associations.ts +2 -2
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/context.ts +16 -12
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/tables.test.ts +73 -0
- bids_validator_deno-2.0.10/src/schema/tables.ts +403 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/setup/options.ts +2 -2
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/bids.ts +3 -3
- bids_validator_deno-2.0.9/src/schema/tables.ts +0 -323
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/LICENSE +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/README.md +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/pdm_build.py +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/.git-meta.json +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/bids-validator.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/browser.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/browser.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/deno.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/deno.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/dwi.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/dwi.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/filetree.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/filetree.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/gzip.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/gzip.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/ignore.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/ignore.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/inheritance.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/inheritance.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/streams.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/streams.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/tiff.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/tiff.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/issues/datasetIssues.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/issues/datasetIssues.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/issues/list.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/issues/list.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/main.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/applyRules.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/context.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/entities.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/entities.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/expressionLanguage.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/expressionLanguage.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/fixtures.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/modalities.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/walk.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/walk.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/setup/loadSchema.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/setup/loadSchema.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/setup/options.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/setup/requestPermissions.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/summary/collectSubjectMetadata.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/summary/summary.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/summary/summary.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/README.md +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/bom-utf16.tsv +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/bom-utf8.json +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/generate-filenames.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/bids_examples.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/common.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/derivatives.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/empty_files.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/hed-integration.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/valid_dataset.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/valid_filenames.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/valid_headers.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/nullReadBytes.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/regression.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/schema-expression-language.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/simple-dataset.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/utils.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/check.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/columns.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/columns.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/filetree.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/issues.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/schema.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/validation-result.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/errors.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/logger.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/logger.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/memoize.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/objectPathHandler.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/output.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/bids.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/citation.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/citation.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/filenameIdentify.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/filenameIdentify.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/filenameValidate.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/filenameValidate.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/hed.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/internal/emptyFile.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/internal/unusedFile.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/json.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/validateFiles.test.ts +0 -0
- {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/version.ts +0 -0
|
@@ -40,7 +40,7 @@ Deno.test('Test JSON error conditions', async (t) => {
|
|
|
40
40
|
await loadJSON(BOMfile).catch((e) => {
|
|
41
41
|
error = e
|
|
42
42
|
})
|
|
43
|
-
assertObjectMatch(error, {
|
|
43
|
+
assertObjectMatch(error, { code: 'INVALID_JSON_ENCODING' })
|
|
44
44
|
})
|
|
45
45
|
|
|
46
46
|
await t.step('Error on UTF-16', async () => {
|
|
@@ -49,7 +49,7 @@ Deno.test('Test JSON error conditions', async (t) => {
|
|
|
49
49
|
await loadJSON(UTF16file).catch((e) => {
|
|
50
50
|
error = e
|
|
51
51
|
})
|
|
52
|
-
assertObjectMatch(error, {
|
|
52
|
+
assertObjectMatch(error, { code: 'INVALID_JSON_ENCODING' })
|
|
53
53
|
})
|
|
54
54
|
|
|
55
55
|
await t.step('Error on invalid JSON syntax', async () => {
|
|
@@ -58,6 +58,6 @@ Deno.test('Test JSON error conditions', async (t) => {
|
|
|
58
58
|
await loadJSON(badJSON).catch((e) => {
|
|
59
59
|
error = e
|
|
60
60
|
})
|
|
61
|
-
assertObjectMatch(error, {
|
|
61
|
+
assertObjectMatch(error, { code: 'JSON_INVALID' })
|
|
62
62
|
})
|
|
63
63
|
})
|
|
@@ -14,7 +14,7 @@ async function readJSONText(file: BIDSFile): Promise<string> {
|
|
|
14
14
|
}
|
|
15
15
|
return text
|
|
16
16
|
} catch (error) {
|
|
17
|
-
throw {
|
|
17
|
+
throw { code: 'INVALID_JSON_ENCODING' }
|
|
18
18
|
} finally {
|
|
19
19
|
decoder.decode() // Reset decoder
|
|
20
20
|
}
|
|
@@ -26,12 +26,12 @@ export async function loadJSON(file: BIDSFile): Promise<Record<string, unknown>>
|
|
|
26
26
|
try {
|
|
27
27
|
parsedText = JSON.parse(text)
|
|
28
28
|
} catch (error) {
|
|
29
|
-
throw {
|
|
29
|
+
throw { code: 'JSON_INVALID' } // Raise syntax errors
|
|
30
30
|
}
|
|
31
31
|
if (Array.isArray(parsedText) || typeof parsedText !== 'object') {
|
|
32
32
|
throw {
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
code: 'JSON_NOT_AN_OBJECT',
|
|
34
|
+
issueMessage: text.substring(0, 10) + (text.length > 10 ? '...' : ''),
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
return parsedText
|
|
@@ -51,7 +51,7 @@ Deno.test('Test loading nifti header', async (t) => {
|
|
|
51
51
|
const header = await loadHeader(file).catch((e) => {
|
|
52
52
|
error = e
|
|
53
53
|
})
|
|
54
|
-
assertObjectMatch(error, {
|
|
54
|
+
assertObjectMatch(error, { code: 'NIFTI_HEADER_UNREADABLE' })
|
|
55
55
|
})
|
|
56
56
|
|
|
57
57
|
await t.step('Tolerate big headers', async () => {
|
|
@@ -45,7 +45,7 @@ export async function loadHeader(file: BIDSFile): Promise<NiftiHeader> {
|
|
|
45
45
|
header.readHeader(data.buffer)
|
|
46
46
|
}
|
|
47
47
|
if (!header) {
|
|
48
|
-
throw {
|
|
48
|
+
throw { code: 'NIFTI_HEADER_UNREADABLE' }
|
|
49
49
|
}
|
|
50
50
|
const ndim = header.dims[0]
|
|
51
51
|
return {
|
|
@@ -67,6 +67,6 @@ export async function loadHeader(file: BIDSFile): Promise<NiftiHeader> {
|
|
|
67
67
|
sform_code: header.sform_code,
|
|
68
68
|
} as NiftiHeader
|
|
69
69
|
} catch (err) {
|
|
70
|
-
throw {
|
|
70
|
+
throw { code: 'NIFTI_HEADER_UNREADABLE' }
|
|
71
71
|
}
|
|
72
72
|
}
|
|
@@ -53,7 +53,7 @@ Deno.test('TSV loading', async (t) => {
|
|
|
53
53
|
try {
|
|
54
54
|
await loadTSV(file)
|
|
55
55
|
} catch (e: any) {
|
|
56
|
-
assertObjectMatch(e, {
|
|
56
|
+
assertObjectMatch(e, { code: 'TSV_EMPTY_LINE', line: 3 })
|
|
57
57
|
}
|
|
58
58
|
})
|
|
59
59
|
|
|
@@ -64,7 +64,7 @@ Deno.test('TSV loading', async (t) => {
|
|
|
64
64
|
try {
|
|
65
65
|
await loadTSV(file)
|
|
66
66
|
} catch (e: any) {
|
|
67
|
-
assertObjectMatch(e, {
|
|
67
|
+
assertObjectMatch(e, { code: 'TSV_EQUAL_ROWS', location: '/mismatched_row.tsv', line: 3 })
|
|
68
68
|
}
|
|
69
69
|
})
|
|
70
70
|
|
|
@@ -171,7 +171,7 @@ Deno.test('TSV loading', async (t) => {
|
|
|
171
171
|
await loadTSV(file)
|
|
172
172
|
assert(false, 'Expected error')
|
|
173
173
|
} catch (e: any) {
|
|
174
|
-
assertObjectMatch(e, {
|
|
174
|
+
assertObjectMatch(e, { code: 'TSV_COLUMN_HEADER_DUPLICATE', issueMessage: 'a, a' })
|
|
175
175
|
}
|
|
176
176
|
})
|
|
177
177
|
|
|
@@ -19,7 +19,11 @@ async function _loadTSV(file: BIDSFile, maxRows: number = -1): Promise<ColumnsMa
|
|
|
19
19
|
const headers = (headerRow.done || !headerRow.value) ? [] : headerRow.value.split('\t')
|
|
20
20
|
|
|
21
21
|
if (new Set(headers).size !== headers.length) {
|
|
22
|
-
throw {
|
|
22
|
+
throw {
|
|
23
|
+
code: 'TSV_COLUMN_HEADER_DUPLICATE',
|
|
24
|
+
location: file.path,
|
|
25
|
+
issueMessage: headers.join(', '),
|
|
26
|
+
}
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
// Initialize columns in array for construction efficiency
|
|
@@ -36,12 +40,12 @@ async function _loadTSV(file: BIDSFile, maxRows: number = -1): Promise<ColumnsMa
|
|
|
36
40
|
if (!value) {
|
|
37
41
|
const nextRow = await reader.read()
|
|
38
42
|
if (nextRow.done) break
|
|
39
|
-
throw {
|
|
43
|
+
throw { code: 'TSV_EMPTY_LINE', location: file.path, line: rowIndex + 2 }
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
const values = value.split('\t')
|
|
43
47
|
if (values.length !== headers.length) {
|
|
44
|
-
throw {
|
|
48
|
+
throw { code: 'TSV_EQUAL_ROWS', location: file.path, line: rowIndex + 2 }
|
|
45
49
|
}
|
|
46
50
|
columns.forEach((column, columnIndex) => {
|
|
47
51
|
// Double array size if we exceed the current capacity
|
|
@@ -94,7 +94,6 @@ export function evalCheck(src: string, context: BIDSContext) {
|
|
|
94
94
|
* We associate theys keys from a rule object to a function adds an
|
|
95
95
|
* issue to the context if the rule evaluation fails.
|
|
96
96
|
*/
|
|
97
|
-
// @ts-expect-error
|
|
98
97
|
const evalMap: Record<
|
|
99
98
|
keyof GenericRule,
|
|
100
99
|
(
|
|
@@ -105,9 +104,13 @@ const evalMap: Record<
|
|
|
105
104
|
) => boolean | void
|
|
106
105
|
> = {
|
|
107
106
|
checks: evalRuleChecks,
|
|
107
|
+
// @ts-expect-error
|
|
108
108
|
columns: evalColumns,
|
|
109
|
+
// @ts-expect-error
|
|
109
110
|
additional_columns: evalAdditionalColumns,
|
|
111
|
+
// @ts-expect-error
|
|
110
112
|
initial_columns: evalInitialColumns,
|
|
113
|
+
// @ts-expect-error
|
|
111
114
|
index_columns: evalIndexColumns,
|
|
112
115
|
fields: evalJsonCheck,
|
|
113
116
|
}
|
|
@@ -143,8 +143,8 @@ export async function buildAssociations(
|
|
|
143
143
|
// @ts-expect-error
|
|
144
144
|
associations[key] = await load(file, { maxRows: context.dataset.options?.maxRows }).catch(
|
|
145
145
|
(error: any) => {
|
|
146
|
-
if (
|
|
147
|
-
context.dataset.issues.add({
|
|
146
|
+
if (error.code) {
|
|
147
|
+
context.dataset.issues.add({ ...error, location: file.path })
|
|
148
148
|
}
|
|
149
149
|
},
|
|
150
150
|
)
|
|
@@ -210,8 +210,8 @@ export class BIDSContext implements Context {
|
|
|
210
210
|
}
|
|
211
211
|
for (const file of sidecars) {
|
|
212
212
|
const json = await loadJSON(file).catch((error) => {
|
|
213
|
-
if (error.
|
|
214
|
-
this.dataset.issues.add({
|
|
213
|
+
if (error.code) {
|
|
214
|
+
this.dataset.issues.add({ ...error, location: file.path })
|
|
215
215
|
return {}
|
|
216
216
|
} else {
|
|
217
217
|
throw error
|
|
@@ -232,8 +232,8 @@ export class BIDSContext implements Context {
|
|
|
232
232
|
) return
|
|
233
233
|
|
|
234
234
|
this.nifti_header = await loadHeader(this.file).catch((error) => {
|
|
235
|
-
if (error.
|
|
236
|
-
this.dataset.issues.add({
|
|
235
|
+
if (error.code) {
|
|
236
|
+
this.dataset.issues.add({ ...error, location: this.file.path })
|
|
237
237
|
return undefined
|
|
238
238
|
} else {
|
|
239
239
|
throw error
|
|
@@ -248,8 +248,8 @@ export class BIDSContext implements Context {
|
|
|
248
248
|
|
|
249
249
|
this.columns = await loadTSV(this.file, this.dataset.options?.maxRows)
|
|
250
250
|
.catch((error) => {
|
|
251
|
-
if (error.
|
|
252
|
-
this.dataset.issues.add({
|
|
251
|
+
if (error.code) {
|
|
252
|
+
this.dataset.issues.add({ ...error, location: this.file.path })
|
|
253
253
|
}
|
|
254
254
|
logger.warn(
|
|
255
255
|
`tsv file could not be opened by loadColumns '${this.file.path}'`,
|
|
@@ -272,8 +272,8 @@ export class BIDSContext implements Context {
|
|
|
272
272
|
return
|
|
273
273
|
}
|
|
274
274
|
this.json = await loadJSON(this.file).catch((error) => {
|
|
275
|
-
if (error.
|
|
276
|
-
this.dataset.issues.add({
|
|
275
|
+
if (error.code) {
|
|
276
|
+
this.dataset.issues.add({ ...error, location: this.file.path })
|
|
277
277
|
return {}
|
|
278
278
|
} else {
|
|
279
279
|
throw error
|
|
@@ -320,9 +320,10 @@ export class BIDSContext implements Context {
|
|
|
320
320
|
const participants_tsv = this.dataset.tree.get('participants.tsv') as BIDSFile
|
|
321
321
|
if (participants_tsv) {
|
|
322
322
|
const participantsData = await loadTSV(participants_tsv)
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
323
|
+
.catch((error) => {
|
|
324
|
+
return new Map()
|
|
325
|
+
}) as Record<string, string[]>
|
|
326
|
+
this.dataset.subjects.participant_id = participantsData['participant_id']
|
|
326
327
|
}
|
|
327
328
|
|
|
328
329
|
// Load phenotype from phenotype/*.tsv
|
|
@@ -333,7 +334,10 @@ export class BIDSContext implements Context {
|
|
|
333
334
|
const seen = new Set() as Set<string>
|
|
334
335
|
for (const file of phenotypeFiles) {
|
|
335
336
|
const phenotypeData = await loadTSV(file)
|
|
336
|
-
|
|
337
|
+
.catch((error) => {
|
|
338
|
+
return new Map()
|
|
339
|
+
}) as Record<string, string[]>
|
|
340
|
+
const participant_id = phenotypeData['participant_id']
|
|
337
341
|
if (participant_id) {
|
|
338
342
|
participant_id.forEach((id) => seen.add(id))
|
|
339
343
|
}
|
|
@@ -26,6 +26,18 @@ const schemaDefs = {
|
|
|
26
26
|
index_columns: ['filename'],
|
|
27
27
|
additional_columns: 'allowed',
|
|
28
28
|
},
|
|
29
|
+
Participants: {
|
|
30
|
+
selectors: ['path == "/participants.tsv"'],
|
|
31
|
+
initial_columns: ['participant_id'],
|
|
32
|
+
columns: {
|
|
33
|
+
participant_id: 'required',
|
|
34
|
+
age: 'recommended',
|
|
35
|
+
sex: 'recommended',
|
|
36
|
+
strain_rrid: 'recommended',
|
|
37
|
+
},
|
|
38
|
+
index_columns: ['participant_id'],
|
|
39
|
+
additional_columns: 'allowed',
|
|
40
|
+
},
|
|
29
41
|
},
|
|
30
42
|
made_up: {
|
|
31
43
|
MadeUp: {
|
|
@@ -93,6 +105,67 @@ Deno.test('tables eval* tests', async (t) => {
|
|
|
93
105
|
assertEquals(context.dataset.issues.size, 0)
|
|
94
106
|
})
|
|
95
107
|
|
|
108
|
+
await t.step('verify column override behavior', () => {
|
|
109
|
+
const context = {
|
|
110
|
+
path: '/participants.tsv',
|
|
111
|
+
extension: '.tsv',
|
|
112
|
+
sidecar: {
|
|
113
|
+
participant_id: {
|
|
114
|
+
Description: 'A participant identifier',
|
|
115
|
+
Format: 'string',
|
|
116
|
+
},
|
|
117
|
+
age: {
|
|
118
|
+
Description: 'Age in weeks',
|
|
119
|
+
Format: 'number',
|
|
120
|
+
},
|
|
121
|
+
sex: {
|
|
122
|
+
Description: 'Phenotypic sex',
|
|
123
|
+
Format: 'string',
|
|
124
|
+
Levels: {
|
|
125
|
+
'F': { Description: 'Female' },
|
|
126
|
+
'M': { Description: 'Male' },
|
|
127
|
+
'O': { Description: 'Other' },
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
strain_rrid: {
|
|
131
|
+
Description: 'Invalid override',
|
|
132
|
+
Format: 'integer',
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
sidecarKeyOrigin: {
|
|
136
|
+
participant_id: '/participants.json',
|
|
137
|
+
age: '/participants.json',
|
|
138
|
+
sex: '/participants.json',
|
|
139
|
+
strain_rrid: '/participants.json',
|
|
140
|
+
},
|
|
141
|
+
columns: {
|
|
142
|
+
participant_id: ['sub-01', 'sub-02', 'sub-03'],
|
|
143
|
+
age: ['10', '20', '30'],
|
|
144
|
+
sex: ['M', 'F', 'f'],
|
|
145
|
+
strain_rrid: ['RRID:SCR_012345', 'RRID:SCR_012345', 'n/a'],
|
|
146
|
+
},
|
|
147
|
+
dataset: { issues: new DatasetIssues() },
|
|
148
|
+
}
|
|
149
|
+
const rule = schemaDefs.rules.tabular_data.modality_agnostic.Participants
|
|
150
|
+
evalColumns(rule, context, schema, 'rules.tabular_data.modality_agnostic.Participants')
|
|
151
|
+
|
|
152
|
+
// participant_id column definition is compatible with schema
|
|
153
|
+
// age and sex may be overridden
|
|
154
|
+
// strain_rrid can't be redefined to numeric
|
|
155
|
+
let issues = context.dataset.issues.get({ code: 'TSV_COLUMN_TYPE_REDEFINED' })
|
|
156
|
+
assertEquals(issues.length, 1)
|
|
157
|
+
assertEquals(issues[0].subCode, 'strain_rrid')
|
|
158
|
+
assertEquals(issues[0].issueMessage, 'Format "integer" must be rrid')
|
|
159
|
+
|
|
160
|
+
// Overriding the default sex definition uses the provided values
|
|
161
|
+
// Values in the default definition may raise issues
|
|
162
|
+
issues = context.dataset.issues.get({ code: 'TSV_VALUE_INCORRECT_TYPE_NONREQUIRED' })
|
|
163
|
+
assertEquals(issues.length, 1)
|
|
164
|
+
assertEquals(issues[0].subCode, 'sex')
|
|
165
|
+
assertEquals(issues[0].line, 4)
|
|
166
|
+
assertEquals(issues[0].issueMessage, "'f'")
|
|
167
|
+
})
|
|
168
|
+
|
|
96
169
|
await t.step('verify column ordering', () => {
|
|
97
170
|
const context = {
|
|
98
171
|
path: '/sub-01/sub-01_scans.tsv',
|