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.

Files changed (105) hide show
  1. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/PKG-INFO +1 -1
  2. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/deno.json +1 -1
  3. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/pyproject.toml +1 -1
  4. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/json.test.ts +3 -3
  5. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/json.ts +4 -4
  6. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/nifti.test.ts +1 -1
  7. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/nifti.ts +2 -2
  8. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/tsv.test.ts +3 -3
  9. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/tsv.ts +7 -3
  10. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/applyRules.ts +4 -1
  11. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/associations.ts +2 -2
  12. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/context.ts +16 -12
  13. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/tables.test.ts +73 -0
  14. bids_validator_deno-2.0.10/src/schema/tables.ts +403 -0
  15. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/setup/options.ts +2 -2
  16. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/bids.ts +3 -3
  17. bids_validator_deno-2.0.9/src/schema/tables.ts +0 -323
  18. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/LICENSE +0 -0
  19. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/README.md +0 -0
  20. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/pdm_build.py +0 -0
  21. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/.git-meta.json +0 -0
  22. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/bids-validator.ts +0 -0
  23. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/browser.test.ts +0 -0
  24. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/browser.ts +0 -0
  25. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/deno.test.ts +0 -0
  26. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/deno.ts +0 -0
  27. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/dwi.test.ts +0 -0
  28. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/dwi.ts +0 -0
  29. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/filetree.test.ts +0 -0
  30. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/filetree.ts +0 -0
  31. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/gzip.test.ts +0 -0
  32. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/gzip.ts +0 -0
  33. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/ignore.test.ts +0 -0
  34. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/ignore.ts +0 -0
  35. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/inheritance.test.ts +0 -0
  36. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/inheritance.ts +0 -0
  37. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/streams.test.ts +0 -0
  38. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/streams.ts +0 -0
  39. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/tiff.test.ts +0 -0
  40. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/files/tiff.ts +0 -0
  41. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/issues/datasetIssues.test.ts +0 -0
  42. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/issues/datasetIssues.ts +0 -0
  43. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/issues/list.test.ts +0 -0
  44. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/issues/list.ts +0 -0
  45. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/main.ts +0 -0
  46. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/applyRules.test.ts +0 -0
  47. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/context.test.ts +0 -0
  48. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/entities.test.ts +0 -0
  49. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/entities.ts +0 -0
  50. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/expressionLanguage.test.ts +0 -0
  51. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/expressionLanguage.ts +0 -0
  52. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/fixtures.test.ts +0 -0
  53. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/modalities.ts +0 -0
  54. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/walk.test.ts +0 -0
  55. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/schema/walk.ts +0 -0
  56. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/setup/loadSchema.test.ts +0 -0
  57. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/setup/loadSchema.ts +0 -0
  58. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/setup/options.test.ts +0 -0
  59. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/setup/requestPermissions.ts +0 -0
  60. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/summary/collectSubjectMetadata.ts +0 -0
  61. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/summary/summary.test.ts +0 -0
  62. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/summary/summary.ts +0 -0
  63. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/README.md +0 -0
  64. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/bom-utf16.tsv +0 -0
  65. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/bom-utf8.json +0 -0
  66. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/generate-filenames.ts +0 -0
  67. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/bids_examples.test.ts +0 -0
  68. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/common.ts +0 -0
  69. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/derivatives.test.ts +0 -0
  70. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/empty_files.test.ts +0 -0
  71. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/hed-integration.test.ts +0 -0
  72. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/valid_dataset.test.ts +0 -0
  73. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/valid_filenames.test.ts +0 -0
  74. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/local/valid_headers.test.ts +0 -0
  75. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/nullReadBytes.ts +0 -0
  76. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/regression.test.ts +0 -0
  77. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/schema-expression-language.test.ts +0 -0
  78. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/simple-dataset.ts +0 -0
  79. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/tests/utils.ts +0 -0
  80. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/check.ts +0 -0
  81. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/columns.test.ts +0 -0
  82. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/columns.ts +0 -0
  83. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/filetree.ts +0 -0
  84. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/issues.ts +0 -0
  85. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/schema.ts +0 -0
  86. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/types/validation-result.ts +0 -0
  87. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/errors.ts +0 -0
  88. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/logger.test.ts +0 -0
  89. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/logger.ts +0 -0
  90. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/memoize.ts +0 -0
  91. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/objectPathHandler.ts +0 -0
  92. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/utils/output.ts +0 -0
  93. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/bids.test.ts +0 -0
  94. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/citation.test.ts +0 -0
  95. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/citation.ts +0 -0
  96. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/filenameIdentify.test.ts +0 -0
  97. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/filenameIdentify.ts +0 -0
  98. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/filenameValidate.test.ts +0 -0
  99. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/filenameValidate.ts +0 -0
  100. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/hed.ts +0 -0
  101. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/internal/emptyFile.ts +0 -0
  102. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/internal/unusedFile.ts +0 -0
  103. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/json.ts +0 -0
  104. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/validators/validateFiles.test.ts +0 -0
  105. {bids_validator_deno-2.0.9 → bids_validator_deno-2.0.10}/src/version.ts +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bids-validator-deno
3
- Version: 2.0.9
3
+ Version: 2.0.10
4
4
  Summary: Typescript implementation of the BIDS validator
5
5
  Keywords: BIDS,BIDS validator
6
6
  Author: bids-standard developers
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bids/validator",
3
- "version": "2.0.9",
3
+ "version": "2.0.10",
4
4
  "exports": {
5
5
  ".": "./src/bids-validator.ts",
6
6
  "./main": "./src/main.ts",
@@ -18,7 +18,7 @@ keywords = [
18
18
  "BIDS validator",
19
19
  ]
20
20
  dynamic = []
21
- version = "2.0.9"
21
+ version = "2.0.10"
22
22
 
23
23
  [project.license]
24
24
  text = "MIT"
@@ -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, { key: 'INVALID_JSON_ENCODING' })
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, { key: 'INVALID_JSON_ENCODING' })
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, { key: 'JSON_INVALID' })
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 { key: 'INVALID_JSON_ENCODING' }
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 { key: 'JSON_INVALID' } // Raise syntax errors
29
+ throw { code: 'JSON_INVALID' } // Raise syntax errors
30
30
  }
31
31
  if (Array.isArray(parsedText) || typeof parsedText !== 'object') {
32
32
  throw {
33
- key: 'JSON_NOT_AN_OBJECT',
34
- evidence: text.substring(0, 10) + (text.length > 10 ? '...' : ''),
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, { key: 'NIFTI_HEADER_UNREADABLE' })
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 { key: 'NIFTI_HEADER_UNREADABLE' }
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 { key: 'NIFTI_HEADER_UNREADABLE' }
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, { key: 'TSV_EMPTY_LINE', line: 3 })
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, { key: 'TSV_EQUAL_ROWS', line: 3 })
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, { key: 'TSV_COLUMN_HEADER_DUPLICATE', evidence: 'a, a' })
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 { key: 'TSV_COLUMN_HEADER_DUPLICATE', evidence: headers.join(', ') }
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 { key: 'TSV_EMPTY_LINE', line: rowIndex + 2 }
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 { key: 'TSV_EQUAL_ROWS', line: rowIndex + 2 }
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 (key in error) {
147
- context.dataset.issues.add({ code: error.key, location: file.path })
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.key) {
214
- this.dataset.issues.add({ code: error.key, location: file.path })
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.key) {
236
- this.dataset.issues.add({ code: error.key, location: this.file.path })
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.key) {
252
- this.dataset.issues.add({ code: error.key, location: this.file.path })
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.key) {
276
- this.dataset.issues.add({ code: error.key, location: this.file.path })
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
- this.dataset.subjects.participant_id = participantsData[
324
- 'participant_id'
325
- ] as string[]
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
- const participant_id = phenotypeData['participant_id'] as string[]
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',