-
Notifications
You must be signed in to change notification settings - Fork 16
BEP042 patches #268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BEP042 patches #268
Changes from all commits
0222ad4
6f11708
9bfeda7
faf1476
f2e69cc
7a37e56
c65d98d
0783938
7ed01c0
5cb3dc4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| <!-- | ||
| A new scriv changelog fragment. | ||
| Uncomment the section that is right (remove the HTML comment wrapper). | ||
| For top level release notes, leave all the headers commented out. | ||
| --> | ||
|
|
||
|
|
||
| ### Added | ||
|
|
||
| - Implement `associations.coordsystems` to collate multiple `coordsystem.json` files, | ||
| as required by BEP 042 (EMG). | ||
|
|
||
| <!-- | ||
| ### Changed | ||
| - A bullet item for the Changed category. | ||
| --> | ||
| <!-- | ||
| ### Fixed | ||
| - A bullet item for the Fixed category. | ||
| --> | ||
| <!-- | ||
| ### Deprecated | ||
| - A bullet item for the Deprecated category. | ||
| --> | ||
| <!-- | ||
| ### Removed | ||
| - A bullet item for the Removed category. | ||
| --> | ||
| <!-- | ||
| ### Security | ||
| - A bullet item for the Security category. | ||
| --> | ||
| <!-- | ||
| ### Infrastructure | ||
| - A bullet item for the Infrastructure category. | ||
| --> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,17 +3,21 @@ import type { Schema as MetaSchema } from '@bids/schema/metaschema' | |
|
|
||
| import type { BIDSFile } from '../types/filetree.ts' | ||
| import type { BIDSContext } from './context.ts' | ||
| import { loadJSON } from '../files/json.ts' | ||
| import { loadTSV } from '../files/tsv.ts' | ||
| import { parseBvalBvec } from '../files/dwi.ts' | ||
| import { readSidecars, walkBack } from '../files/inheritance.ts' | ||
| import { evalCheck } from './applyRules.ts' | ||
| import { expressionFunctions } from './expressionLanguage.ts' | ||
| import { readEntities } from './entities.ts' | ||
|
|
||
| import { readText } from '../files/access.ts' | ||
|
|
||
| interface WithSidecar { | ||
| sidecar: Record<string, unknown> | ||
| } | ||
| type LoadFunction = (file: BIDSFile, options: any) => Promise<any> | ||
| type MultiLoadFunction = (files: BIDSFile[], options: any) => Promise<any> | ||
|
|
||
| function defaultAssociation(file: BIDSFile, _options: any): Promise<{ path: string }> { | ||
| return Promise.resolve({ path: file.path }) | ||
|
|
@@ -33,7 +37,7 @@ async function constructSidecar(file: BIDSFile): Promise<Record<string, unknown> | |
| * | ||
| * Many associations only consist of a path; this object is for more complex associations. | ||
| */ | ||
| const associationLookup = { | ||
| const associationLookup: Record<string, LoadFunction> = { | ||
| events: async (file: BIDSFile, options: { maxRows: number }): Promise<Events & WithSidecar> => { | ||
| const columns = await loadTSV(file, options.maxRows) | ||
| .catch((e) => { | ||
|
|
@@ -103,6 +107,24 @@ const associationLookup = { | |
| } | ||
| }, | ||
| } | ||
| const multiAssociationLookup: Record<string, MultiLoadFunction> = { | ||
| coordsystems: async ( | ||
| files: BIDSFile[], | ||
| options: any, | ||
| ): Promise<{ paths: string[]; spaces: string[]; ParentCoordinateSystems: string[] }> => { | ||
| const jsons = await Promise.allSettled( | ||
| files.map((f) => loadJSON(f).catch(() => ({} as Record<string, unknown>))), | ||
| ) | ||
| const parents = jsons.map((j) => | ||
| j.status === 'fulfilled' ? j.value?.ParentCoordinateSystem : undefined | ||
| ).filter((p) => p) as string[] | ||
| return { | ||
| paths: files.map((f) => f.path), | ||
| spaces: files.map((f) => readEntities(f.name).entities?.space), | ||
| ParentCoordinateSystems: parents, | ||
| } | ||
| }, | ||
| } | ||
|
|
||
| export async function buildAssociations( | ||
| context: BIDSContext, | ||
|
|
@@ -134,33 +156,37 @@ export async function buildAssociations( | |
| rule.target.suffix, | ||
| rule.target?.entities ?? [], | ||
| ).next().value | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The EMG examples do not have this case, but with multiple We currently strongly assume (and implement with For now this could be noted as a limitation in the validator implementation. |
||
| if (Array.isArray(file)) { | ||
| file = file[0] | ||
| } | ||
| } catch (error) { | ||
| if ( | ||
| error && typeof error === 'object' && 'code' in error && | ||
| error.code === 'MULTIPLE_INHERITABLE_FILES' | ||
| ) { | ||
| // @ts-expect-error | ||
| } catch (error: any) { | ||
| if (error?.code === 'MULTIPLE_INHERITABLE_FILES') { | ||
| context.dataset.issues.add(error) | ||
| break | ||
| continue | ||
rwblair marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } else { | ||
| throw error | ||
| } | ||
| } | ||
|
|
||
| if (file) { | ||
| // @ts-expect-error | ||
| const load = associationLookup[key] ?? defaultAssociation | ||
| // @ts-expect-error | ||
| associations[key] = await load(file, { maxRows: context.dataset.options?.maxRows }).catch( | ||
| (error: any) => { | ||
| if (error.code) { | ||
| context.dataset.issues.add({ ...error, location: file.path }) | ||
| } | ||
| }, | ||
| ) | ||
| if (file && !(Array.isArray(file) && file.length === 0)) { | ||
| const options = { maxRows: context.dataset.options?.maxRows } | ||
| if (key in multiAssociationLookup) { | ||
| const load = multiAssociationLookup[key] | ||
| if (!Array.isArray(file)) { | ||
| file = [file] | ||
| } | ||
| associations[key as keyof Associations] = await load(file, options).catch((e: any) => {}) | ||
| } else { | ||
| const load = associationLookup[key] ?? defaultAssociation | ||
| if (Array.isArray(file)) { | ||
| file = file[0] | ||
| } | ||
| const location = file.path | ||
| associations[key as keyof Associations] = await load(file, options).catch( | ||
| (error: any) => { | ||
| if (error.code) { | ||
| context.dataset.issues.add({ ...error, location }) | ||
| } | ||
| }, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| return Promise.resolve(associations) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.