Skip to content

Commit f2e69cc

Browse files
committed
feat: Enable multi-file associations, load coordsystems
1 parent faf1476 commit f2e69cc

File tree

1 file changed

+44
-26
lines changed

1 file changed

+44
-26
lines changed

src/schema/associations.ts

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ import { parseBvalBvec } from '../files/dwi.ts'
99
import { readSidecars, walkBack } from '../files/inheritance.ts'
1010
import { evalCheck } from './applyRules.ts'
1111
import { expressionFunctions } from './expressionLanguage.ts'
12+
import { readEntities } from './entities.ts'
1213

1314
import { readText } from '../files/access.ts'
1415

1516
interface WithSidecar {
1617
sidecar: Record<string, unknown>
1718
}
19+
type LoadFunction = (file: BIDSFile, options: any) => Promise<any>
20+
type MultiLoadFunction = (files: BIDSFile[], options: any) => Promise<any>
1821

1922
function defaultAssociation(file: BIDSFile, _options: any): Promise<{ path: string }> {
2023
return Promise.resolve({ path: file.path })
@@ -34,7 +37,7 @@ async function constructSidecar(file: BIDSFile): Promise<Record<string, unknown>
3437
*
3538
* Many associations only consist of a path; this object is for more complex associations.
3639
*/
37-
const associationLookup = {
40+
const associationLookup: Record<string, LoadFunction> = {
3841
events: async (file: BIDSFile, options: { maxRows: number }): Promise<Events & WithSidecar> => {
3942
const columns = await loadTSV(file, options.maxRows)
4043
.catch((e) => {
@@ -103,11 +106,22 @@ const associationLookup = {
103106
sidecar: await constructSidecar(file),
104107
}
105108
},
106-
coordsystem: async (file: BIDSFile, options: { maxRows: number }): Promise<{path: string, keys: string[]}> => {
107-
const keys = Object.keys(await loadJSON(file).catch((e) => {return {}}))
109+
}
110+
const multiAssociationLookup: Record<string, MultiLoadFunction> = {
111+
coordsystems: async (
112+
files: BIDSFile[],
113+
options: any,
114+
): Promise<{ paths: string[]; spaces: string[]; parents: string[] }> => {
115+
const jsons = await Promise.allSettled(
116+
files.map((f) => loadJSON(f).catch(() => ({} as Record<string, unknown>))),
117+
)
118+
const parents = jsons.map((j) =>
119+
j.status === 'fulfilled' ? j.value?.ParentCoordinateSystem : undefined
120+
).filter((p) => p) as string[]
108121
return {
109-
path: file.path,
110-
keys: keys,
122+
paths: files.map((f) => f.path),
123+
spaces: files.map((f) => readEntities(f.name).entities?.space),
124+
ParentCoordinateSystems: parents,
111125
}
112126
},
113127
}
@@ -142,33 +156,37 @@ export async function buildAssociations(
142156
rule.target.suffix,
143157
rule.target?.entities ?? [],
144158
).next().value
145-
if (Array.isArray(file)) {
146-
file = file[0]
147-
}
148-
} catch (error) {
149-
if (
150-
error && typeof error === 'object' && 'code' in error &&
151-
error.code === 'MULTIPLE_INHERITABLE_FILES'
152-
) {
153-
// @ts-expect-error
159+
} catch (error: any) {
160+
if (error?.code === 'MULTIPLE_INHERITABLE_FILES') {
154161
context.dataset.issues.add(error)
155-
break
162+
continue
156163
} else {
157164
throw error
158165
}
159166
}
160167

161-
if (file) {
162-
// @ts-expect-error
163-
const load = associationLookup[key] ?? defaultAssociation
164-
// @ts-expect-error
165-
associations[key] = await load(file, { maxRows: context.dataset.options?.maxRows }).catch(
166-
(error: any) => {
167-
if (error.code) {
168-
context.dataset.issues.add({ ...error, location: file.path })
169-
}
170-
},
171-
)
168+
if (file && !(Array.isArray(file) && file.length === 0)) {
169+
const options = { maxRows: context.dataset.options?.maxRows }
170+
if (key in multiAssociationLookup) {
171+
const load = multiAssociationLookup[key]
172+
if (!Array.isArray(file)) {
173+
file = [file]
174+
}
175+
associations[key as keyof Associations] = await load(file, options)
176+
} else {
177+
const load = associationLookup[key] ?? defaultAssociation
178+
if (Array.isArray(file)) {
179+
file = file[0]
180+
}
181+
const location = file.path
182+
associations[key as keyof Associations] = await load(file, { maxRows: context.dataset.options?.maxRows }).catch(
183+
(error: any) => {
184+
if (error.code) {
185+
context.dataset.issues.add({ ...error, location })
186+
}
187+
},
188+
)
189+
}
172190
}
173191
}
174192
return Promise.resolve(associations)

0 commit comments

Comments
 (0)