@@ -69,13 +69,37 @@ def populate_bids_templates(path, defaults={}):
69
69
"TODO: Provide description for the dataset -- basic details about the "
70
70
"study, possibly pointing to pre-registration (if public or embargoed)" )
71
71
72
+ populate_aggregated_jsons (path )
73
+
74
+
75
+ def populate_aggregated_jsons (path ):
76
+ """Aggregate across the entire BIDS dataset .json's into top level .json's
77
+
78
+ Top level .json files would contain only the fields which are
79
+ common to all subject[/session]/type/*_modality.json's.
80
+
81
+ ATM aggregating only for *_task*_bold.json files. Only the task- and
82
+ OPTIONAL _acq- field is retained within the aggregated filename. The other
83
+ BIDS _key-value pairs are "aggregated over".
84
+
85
+ Parameters
86
+ ----------
87
+ path: str
88
+ Path to the top of the BIDS dataset
89
+ """
72
90
# TODO: collect all task- .json files for func files to
73
91
tasks = {}
74
92
# way too many -- let's just collect all which are the same!
75
93
# FIELDS_TO_TRACK = {'RepetitionTime', 'FlipAngle', 'EchoTime',
76
94
# 'Manufacturer', 'SliceTiming', ''}
77
95
for fpath in find_files ('.*_task-.*\_bold\.json' , topdir = path ,
78
- exclude_vcs = True , exclude = "/\.(datalad|heudiconv)/" ):
96
+ exclude_vcs = True ,
97
+ exclude = "/\.(datalad|heudiconv)/" ):
98
+ #
99
+ # According to BIDS spec I think both _task AND _acq (may be more?
100
+ # _rec, _dir, ...?) should be retained?
101
+ # TODO: if we are to fix it, then old ones (without _acq) should be
102
+ # removed first
79
103
task = re .sub ('.*_(task-[^_\.]*(_acq-[^_\.]*)?)_.*' , r'\1' , fpath )
80
104
json_ = load_json (fpath )
81
105
if task not in tasks :
@@ -94,18 +118,36 @@ def populate_bids_templates(path, defaults={}):
94
118
if not op .lexists (events_file ):
95
119
lgr .debug ("Generating %s" , events_file )
96
120
with open (events_file , 'w' ) as f :
97
- f .write ("onset\t duration\t trial_type\t response_time\t stim_file\t TODO -- fill in rows and add more tab-separated columns if desired" )
121
+ f .write (
122
+ "onset\t duration\t trial_type\t response_time\t stim_file"
123
+ "\t TODO -- fill in rows and add more tab-separated "
124
+ "columns if desired" )
98
125
# extract tasks files stubs
99
126
for task_acq , fields in tasks .items ():
100
127
task_file = op .join (path , task_acq + '_bold.json' )
101
- # do not touch any existing thing, it may be precious
102
- if not op .lexists (task_file ):
103
- lgr .debug ("Generating %s" , task_file )
104
- fields ["TaskName" ] = ("TODO: full task name for %s" %
105
- task_acq .split ('_' )[0 ].split ('-' )[1 ])
106
- fields ["CogAtlasID" ] = "TODO"
107
- with open (task_file , 'w' ) as f :
108
- f .write (json_dumps_pretty (fields , indent = 2 , sort_keys = True ))
128
+ # Since we are pulling all unique fields we have to possibly
129
+ # rewrite this file to guarantee consistency.
130
+ # See https://github.com/nipy/heudiconv/issues/277 for a usecase/bug
131
+ # when we didn't touch existing one.
132
+ # But the fields we enter (TaskName and CogAtlasID) might need need
133
+ # to be populated from the file if it already exists
134
+ placeholders = {
135
+ "TaskName" : ("TODO: full task name for %s" %
136
+ task_acq .split ('_' )[0 ].split ('-' )[1 ]),
137
+ "CogAtlasID" : "TODO" ,
138
+ }
139
+ if op .lexists (task_file ):
140
+ j = load_json (task_file )
141
+ # Retain possibly modified placeholder fields
142
+ for f in placeholders :
143
+ if f in j :
144
+ placeholders [f ] = j [f ]
145
+ act = "Regenerating"
146
+ else :
147
+ act = "Generating"
148
+ lgr .debug ("%s %s" , act , task_file )
149
+ fields .update (placeholders )
150
+ save_json (task_file , fields , indent = 2 , sort_keys = True , pretty = True )
109
151
110
152
111
153
def tuneup_bids_json_files (json_files ):
0 commit comments