@@ -230,6 +230,95 @@ def prep_conversion(sid, dicoms, outdir, heuristic, converter, anon_sid,
230
230
getattr (heuristic , 'DEFAULT_FIELDS' , {}))
231
231
232
232
233
+ def update_complex_name (fileinfo , this_prefix_basename , suffix ):
234
+ """
235
+ Insert `_part-<mag|phase>` entity into filename if data are from a sequence
236
+ with magnitude/phase reconstruction.
237
+ """
238
+ unsupported_types = ['_bold' , '_phase' ]
239
+ if suffix in unsupported_types :
240
+ return this_prefix_basename
241
+
242
+ # Check to see if it is magnitude or phase reconstruction:
243
+ if 'M' in fileinfo .get ('ImageType' ):
244
+ mag_or_phase = 'mag'
245
+ elif 'P' in fileinfo .get ('ImageType' ):
246
+ mag_or_phase = 'phase'
247
+ else :
248
+ mag_or_phase = suffix
249
+
250
+ # Insert reconstruction label
251
+ if not ('_part-%s' % mag_or_phase ) in this_prefix_basename :
252
+
253
+ # If "_part-" is specified, prepend the 'mag_or_phase' value.
254
+ if '_part-' in this_prefix_basename :
255
+ raise BIDSError (
256
+ "Part label for images will be automatically set, remove "
257
+ "from heuristic"
258
+ )
259
+
260
+ # If not, insert "_part-" + 'mag_or_phase' into the prefix_basename
261
+ # **before** "_run", "_echo" or "_sbref", whichever appears first:
262
+ for label in ['_run' , '_echo' , '_sbref' ]:
263
+ if (label in this_prefix_basename ):
264
+ this_prefix_basename = this_prefix_basename .replace (
265
+ label , "_part-%s%s" % (mag_or_phase , label )
266
+ )
267
+ break
268
+ return this_prefix_basename
269
+
270
+
271
+ def update_multiecho_name (fileinfo , this_prefix_basename , echo_times , suffix ):
272
+ """
273
+ Insert `_echo-<num>` entity into filename if data are from a multi-echo
274
+ sequence.
275
+ """
276
+ unsupported_types = ['_magnitude1' , '_magnitude2' , '_phasediff' , '_phase1' , '_phase2' ]
277
+ if suffix in unsupported_types :
278
+ return this_prefix_basename
279
+
280
+ # Get the EchoNumber from json file info. If not present, use EchoTime
281
+ if 'EchoNumber' in fileinfo .keys ():
282
+ echo_number = fileinfo ['EchoNumber' ]
283
+ else :
284
+ echo_number = echo_times .index (fileinfo ['EchoTime' ]) + 1
285
+
286
+ # Now, decide where to insert it.
287
+ # Insert it **before** the following string(s), whichever appears first.
288
+ for imgtype in supported_multiecho :
289
+ if (imgtype in this_prefix_basename ):
290
+ this_prefix_basename = this_prefix_basename .replace (
291
+ imgtype , "_echo-%d%s" % (echo_number , imgtype )
292
+ )
293
+ break
294
+ return this_prefix_basename
295
+
296
+
297
+ def update_uncombined_name (fileinfo , this_prefix_basename , coil_names , suffix ):
298
+ """
299
+ Insert `_channel-<num>` entity into filename if data are from a sequence
300
+ with "save uncombined".
301
+ """
302
+ # Determine the channel number
303
+ channel_number = coil_names .index (fileinfo ['CoilString' ]) + 1
304
+
305
+ # Insert it **before** the following string(s), whichever appears first.
306
+ for label in ['_run' , '_echo' , suffix ]:
307
+ if label == suffix :
308
+ prefix_suffix = this_prefix_basename .split ('_' )[- 1 ]
309
+ this_prefix_basename = this_prefix_basename .replace (
310
+ prefix_suffix , "_channel-%s_%s" % (channel_number , prefix_suffix )
311
+ )
312
+ break
313
+
314
+ if (label in this_prefix_basename ):
315
+ this_prefix_basename = this_prefix_basename .replace (
316
+ label , "_channel-%s%s" % (coil_number , label )
317
+ )
318
+ break
319
+ return this_prefix_basename
320
+
321
+
233
322
def convert (items , converter , scaninfo_suffix , custom_callable , with_prov ,
234
323
bids_options , outdir , min_meta , overwrite , symlink = True , prov_file = None ,
235
324
dcmconfig = None ):
@@ -527,78 +616,62 @@ def save_converted_files(res, item_dicoms, bids_options, outtype, prefix, outnam
527
616
# series. To do that, the most straightforward way is to read the
528
617
# echo times for all bids_files and see if they are all the same or not.
529
618
530
- # Check for varying echo times
531
- echo_times = sorted (list (set (
532
- load_json (b ).get ('EchoTime' , None )
533
- for b in bids_files
534
- if b
535
- )))
536
-
537
- is_multiecho = len (echo_times ) > 1
619
+ # Collect some metadata across all images
620
+ echo_times , channel_names , image_types = [], [], []
621
+ for b in bids_files :
622
+ if not b :
623
+ continue
624
+ metadata = load_json (b )
625
+ echo_times .append (metadata .get ('EchoTime' , None ))
626
+ channel_names .append (metadata .get ('CoilString' , None ))
627
+ image_types .append (metadata .get ('ImageType' , None ))
628
+ echo_times = [v for v in echo_times if v ]
629
+ echo_times = sorted (list (set (echo_times )))
630
+ channel_names = [v for v in channel_names if v ]
631
+ channel_names = sorted (list (set (channel_names )))
632
+ image_types = [v for v in image_types if v ]
633
+ image_types = sorted (list (set (image_types )))
634
+
635
+ is_multiecho = len (echo_times ) > 1 # Check for varying echo times
636
+ is_uncombined = len (coil_names ) > 1 # Check for uncombined data
637
+
638
+ # Determine if data are complex (magnitude + phase)
639
+ magnitude_found = ['M' in it for it in image_types ]
640
+ phase_found = ['P' in it for it in image_types ]
641
+ is_complex = magnitude_found and phase_found
538
642
539
643
### Loop through the bids_files, set the output name and save files
540
644
for fl , suffix , bids_file in zip (res_files , suffixes , bids_files ):
541
645
542
646
# TODO: monitor conversion duration
543
647
if bids_file :
544
648
fileinfo = load_json (bids_file )
649
+ print (suffix )
545
650
546
651
# set the prefix basename for this specific file (we'll modify it,
547
652
# and we don't want to modify it for all the bids_files):
548
653
this_prefix_basename = prefix_basename
549
654
550
- # _sbref sequences reconstructing magnitude and phase generate
551
- # two NIfTI files IN THE SAME SERIES, so we cannot just add
552
- # the suffix, if we want to be bids compliant:
553
- if bids_file and this_prefix_basename .endswith ('_sbref' ):
554
- # Check to see if it is magnitude or phase reconstruction:
555
- if 'M' in fileinfo .get ('ImageType' ):
556
- mag_or_phase = 'magnitude'
557
- elif 'P' in fileinfo .get ('ImageType' ):
558
- mag_or_phase = 'phase'
559
- else :
560
- mag_or_phase = suffix
561
-
562
- # Insert reconstruction label
563
- if not ("_rec-%s" % mag_or_phase ) in this_prefix_basename :
564
-
565
- # If "_rec-" is specified, prepend the 'mag_or_phase' value.
566
- if ('_rec-' in this_prefix_basename ):
567
- raise BIDSError (
568
- "Reconstruction label for multi-echo single-band"
569
- " reference images will be automatically set, remove"
570
- " from heuristic"
571
- )
572
-
573
- # If not, insert "_rec-" + 'mag_or_phase' into the prefix_basename
574
- # **before** "_run", "_echo" or "_sbref", whichever appears first:
575
- for label in ['_run' , '_echo' , '_sbref' ]:
576
- if (label in this_prefix_basename ):
577
- this_prefix_basename = this_prefix_basename .replace (
578
- label , "_rec-%s%s" % (mag_or_phase , label )
579
- )
580
- break
581
-
582
- # Now check if this run is multi-echo
655
+ # Update name if complex data
656
+ if bids_file and is_complex :
657
+ this_prefix_basename = update_complex_name (
658
+ fileinfo , this_prefix_basename , suffix
659
+ )
660
+
661
+ # Update name if multi-echo
583
662
# (Note: it can be _sbref and multiecho, so don't use "elif"):
584
663
# For multi-echo sequences, we have to specify the echo number in
585
664
# the file name:
586
665
if bids_file and is_multiecho :
587
- # Get the EchoNumber from json file info. If not present, use EchoTime
588
- if 'EchoNumber' in fileinfo .keys ():
589
- echo_number = fileinfo ['EchoNumber' ]
590
- else :
591
- echo_number = echo_times .index (fileinfo ['EchoTime' ]) + 1
592
-
593
- supported_multiecho = ['_bold' , '_phase' , '_epi' , '_sbref' , '_T1w' , '_PDT2' ]
594
- # Now, decide where to insert it.
595
- # Insert it **before** the following string(s), whichever appears first.
596
- for imgtype in supported_multiecho :
597
- if (imgtype in this_prefix_basename ):
598
- this_prefix_basename = this_prefix_basename .replace (
599
- imgtype , "_echo-%d%s" % (echo_number , imgtype )
600
- )
601
- break
666
+ this_prefix_basename = update_multiecho_name (
667
+ fileinfo , this_prefix_basename , echo_times , suffix
668
+ )
669
+
670
+ # Update name if uncombined (channel-level) data
671
+ if bids_file and is_uncombined :
672
+ this_prefix_basename = update_uncombined_name (
673
+ fileinfo , this_prefix_basename , channel_names
674
+ )
602
675
603
676
# Fallback option:
604
677
# If we have failed to modify this_prefix_basename, because it didn't fall
0 commit comments