@@ -9,12 +9,15 @@ import { parseBvalBvec } from '../files/dwi.ts'
99import { readSidecars , 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
1516interface 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
1922function 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