@@ -9,9 +9,13 @@ import { parseBvalBvec } from '../files/dwi.ts'
99import { walkBack } from '../files/inheritance.ts'
1010import { evalCheck } from './applyRules.ts'
1111import { expressionFunctions } from './expressionLanguage.ts'
12+ import { readEntities } from './entities.ts'
1213
1314import { readText } from '../files/access.ts'
1415
16+ type LoadFunction = ( file : BIDSFile , options : any ) => Promise < any >
17+ type MultiLoadFunction = ( files : BIDSFile [ ] , options : any ) => Promise < any >
18+
1519function defaultAssociation ( file : BIDSFile , _options : any ) : Promise < { path : string } > {
1620 return Promise . resolve ( { path : file . path } )
1721}
@@ -24,7 +28,7 @@ function defaultAssociation(file: BIDSFile, _options: any): Promise<{ path: stri
2428 *
2529 * Many associations only consist of a path; this object is for more complex associations.
2630 */
27- const associationLookup = {
31+ const associationLookup : Record < string , LoadFunction > = {
2832 events : async ( file : BIDSFile , options : { maxRows : number } ) : Promise < Events > => {
2933 const columns = await loadTSV ( file , options . maxRows )
3034 . catch ( ( e ) => {
@@ -86,11 +90,22 @@ const associationLookup = {
8690 sampling_frequency : columns . get ( 'sampling_frequency' ) ,
8791 }
8892 } ,
89- coordsystem : async ( file : BIDSFile , options : { maxRows : number } ) : Promise < { path : string , keys : string [ ] } > => {
90- const keys = Object . keys ( await loadJSON ( file ) . catch ( ( e ) => { return { } } ) )
93+ }
94+ const multiAssociationLookup : Record < string , MultiLoadFunction > = {
95+ coordsystems : async (
96+ files : BIDSFile [ ] ,
97+ options : any ,
98+ ) : Promise < { paths : string [ ] ; spaces : string [ ] ; parents : string [ ] } > => {
99+ const jsons = await Promise . allSettled (
100+ files . map ( ( f ) => loadJSON ( f ) . catch ( ( ) => ( { } as Record < string , unknown > ) ) ) ,
101+ )
102+ const parents = jsons . map ( ( j ) =>
103+ j . status === 'fulfilled' ? j . value ?. ParentCoordinateSystem : undefined
104+ ) . filter ( ( p ) => p ) as string [ ]
91105 return {
92- path : file . path ,
93- keys : keys ,
106+ paths : files . map ( ( f ) => f . path ) ,
107+ spaces : files . map ( ( f ) => readEntities ( f . name ) . entities ?. space ) ,
108+ ParentCoordinateSystems : parents ,
94109 }
95110 } ,
96111}
@@ -131,33 +146,37 @@ export async function buildAssociations(
131146 rule . target . suffix ,
132147 rule . target ?. entities ?? [ ] ,
133148 ) . next ( ) . value
134- if ( Array . isArray ( file ) ) {
135- file = file [ 0 ]
136- }
137- } catch ( error ) {
138- if (
139- error && typeof error === 'object' && 'code' in error &&
140- error . code === 'MULTIPLE_INHERITABLE_FILES'
141- ) {
142- // @ts -expect-error
149+ } catch ( error : any ) {
150+ if ( error ?. code === 'MULTIPLE_INHERITABLE_FILES' ) {
143151 context . dataset . issues . add ( error )
144- break
152+ continue
145153 } else {
146154 throw error
147155 }
148156 }
149157
150- if ( file ) {
151- // @ts -expect-error
152- const load = associationLookup [ key ] ?? defaultAssociation
153- // @ts -expect-error
154- associations [ key ] = await load ( file , { maxRows : context . dataset . options ?. maxRows } ) . catch (
155- ( error : any ) => {
156- if ( error . code ) {
157- context . dataset . issues . add ( { ...error , location : file . path } )
158- }
159- } ,
160- )
158+ if ( file && ! ( Array . isArray ( file ) && file . length === 0 ) ) {
159+ const options = { maxRows : context . dataset . options ?. maxRows }
160+ if ( key in multiAssociationLookup ) {
161+ const load = multiAssociationLookup [ key ]
162+ if ( ! Array . isArray ( file ) ) {
163+ file = [ file ]
164+ }
165+ associations [ key as keyof Associations ] = await load ( file , options )
166+ } else {
167+ const load = associationLookup [ key ] ?? defaultAssociation
168+ if ( Array . isArray ( file ) ) {
169+ file = file [ 0 ]
170+ }
171+ const location = file . path
172+ associations [ key as keyof Associations ] = await load ( file , { maxRows : context . dataset . options ?. maxRows } ) . catch (
173+ ( error : any ) => {
174+ if ( error . code ) {
175+ context . dataset . issues . add ( { ...error , location } )
176+ }
177+ } ,
178+ )
179+ }
161180 }
162181 }
163182 return Promise . resolve ( associations )
0 commit comments