4
4
import logging
5
5
from collections import OrderedDict
6
6
import tarfile
7
-
7
+ from nibabel . nicom import csareader
8
8
from heudiconv .external .pydicom import dcm
9
9
10
10
from .utils import SeqInfo , load_json , set_readonly
@@ -73,6 +73,15 @@ def group_dicoms_into_seqinfos(files, file_filter, dcmfilter, grouping):
73
73
lgr .info ("File {} is missing any StudyInstanceUID" .format (filename ))
74
74
file_studyUID = None
75
75
76
+ # Workaround for protocol name in private siemens csa header
77
+ try :
78
+ mw .dcm_data .ProtocolName
79
+ except AttributeError :
80
+ if not getattr (mw .dcm_data , 'ProtocolName' , '' ).strip ():
81
+ mw .dcm_data .ProtocolName = parse_private_csa_header (
82
+ mw .dcm_data , 'ProtocolName' , 'tProtocolName'
83
+ ) if mw .is_csa else ''
84
+
76
85
try :
77
86
series_id = (int (mw .dcm_data .SeriesNumber ),
78
87
mw .dcm_data .ProtocolName )
@@ -208,7 +217,7 @@ def group_dicoms_into_seqinfos(files, file_filter, dcmfilter, grouping):
208
217
dcminfo .get ('PatientID' ),
209
218
dcminfo .get ('StudyDescription' ),
210
219
refphys ,
211
- dcminfo . get ( 'SeriesDescription' ),
220
+ series_desc , # We try to set this further up.
212
221
sequence_name ,
213
222
image_type ,
214
223
accession_number ,
@@ -232,7 +241,7 @@ def group_dicoms_into_seqinfos(files, file_filter, dcmfilter, grouping):
232
241
lgr .debug ("%30s %30s %27s %27s %5s nref=%-2d nsrc=%-2d %s" % (
233
242
key ,
234
243
info .series_id ,
235
- dcminfo . SeriesDescription ,
244
+ series_desc ,
236
245
dcminfo .ProtocolName ,
237
246
info .is_derived ,
238
247
len (dcminfo .get ('ReferencedImageSequence' , '' )),
@@ -483,3 +492,37 @@ def embed_metadata_from_dicoms(bids, item_dicoms, outname, outname_bids,
483
492
except Exception as exc :
484
493
lgr .error ("Embedding failed: %s" , str (exc ))
485
494
os .chdir (cwd )
495
+
496
+ def parse_private_csa_header (dcm_data , public_attr , private_attr , default = None ):
497
+ """
498
+ Parses CSA header in cases where value is not defined publicly
499
+
500
+ Parameters
501
+ ----------
502
+ dcm_data : pydicom Dataset object
503
+ DICOM metadata
504
+ public_attr : string
505
+ non-private DICOM attribute
506
+ private_attr : string
507
+ private DICOM attribute
508
+ default (optional)
509
+ default value if private_attr not found
510
+
511
+ Returns
512
+ -------
513
+ val (default: empty string)
514
+ private attribute value or default
515
+ """
516
+ # TODO: provide mapping to private_attr from public_attr
517
+ from nibabel .nicom import csareader
518
+ import dcmstack .extract as dsextract
519
+ try :
520
+ # TODO: test with attr besides ProtocolName
521
+ csastr = csareader .get_csa_header (dcm_data , 'series' )['tags' ]['MrPhoenixProtocol' ]['items' ][0 ]
522
+ csastr = csastr .replace ("### ASCCONV BEGIN" , "### ASCCONV BEGIN ### " )
523
+ parsedhdr = dsextract .parse_phoenix_prot ('MrPhoenixProtocol' , csastr )
524
+ val = parsedhdr [private_attr ].replace (' ' , '' )
525
+ except Exception as e :
526
+ lgr .debug ("Failed to parse CSA header: %s" , str (e ))
527
+ val = default if default else ''
528
+ return val
0 commit comments