Skip to content

Commit 37301b9

Browse files
authored
Merge pull request #271 from mgxd/enh/private
enh: fallback to private siemens header
2 parents f3a7e50 + 85a718b commit 37301b9

File tree

3 files changed

+71
-3
lines changed

3 files changed

+71
-3
lines changed

heudiconv/dicoms.py

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import logging
55
from collections import OrderedDict
66
import tarfile
7-
7+
from nibabel.nicom import csareader
88
from heudiconv.external.pydicom import dcm
99

1010
from .utils import SeqInfo, load_json, set_readonly
@@ -73,6 +73,15 @@ def group_dicoms_into_seqinfos(files, file_filter, dcmfilter, grouping):
7373
lgr.info("File {} is missing any StudyInstanceUID".format(filename))
7474
file_studyUID = None
7575

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+
7685
try:
7786
series_id = (int(mw.dcm_data.SeriesNumber),
7887
mw.dcm_data.ProtocolName)
@@ -208,7 +217,7 @@ def group_dicoms_into_seqinfos(files, file_filter, dcmfilter, grouping):
208217
dcminfo.get('PatientID'),
209218
dcminfo.get('StudyDescription'),
210219
refphys,
211-
dcminfo.get('SeriesDescription'),
220+
series_desc, # We try to set this further up.
212221
sequence_name,
213222
image_type,
214223
accession_number,
@@ -232,7 +241,7 @@ def group_dicoms_into_seqinfos(files, file_filter, dcmfilter, grouping):
232241
lgr.debug("%30s %30s %27s %27s %5s nref=%-2d nsrc=%-2d %s" % (
233242
key,
234243
info.series_id,
235-
dcminfo.SeriesDescription,
244+
series_desc,
236245
dcminfo.ProtocolName,
237246
info.is_derived,
238247
len(dcminfo.get('ReferencedImageSequence', '')),
@@ -483,3 +492,37 @@ def embed_metadata_from_dicoms(bids, item_dicoms, outname, outname_bids,
483492
except Exception as exc:
484493
lgr.error("Embedding failed: %s", str(exc))
485494
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

tests/data/axasc35.dcm

374 KB
Binary file not shown.

tests/test_dicoms.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import os.path as op
2+
3+
import pytest
4+
5+
from heudiconv.external.pydicom import dcm
6+
from heudiconv.cli.run import main as runner
7+
from heudiconv.dicoms import parse_private_csa_header
8+
from .utils import TESTS_DATA_PATH
9+
10+
# Public: Private DICOM tags
11+
DICOM_FIELDS_TO_TEST = {
12+
'ProtocolName': 'tProtocolName'
13+
}
14+
15+
def test_private_csa_header(tmpdir):
16+
dcm_file = op.join(TESTS_DATA_PATH, 'axasc35.dcm')
17+
dcm_data = dcm.read_file(dcm_file)
18+
for pub, priv in DICOM_FIELDS_TO_TEST.items():
19+
# ensure missing public tag
20+
with pytest.raises(AttributeError):
21+
dcm.pub
22+
# ensure private tag is found
23+
assert parse_private_csa_header(dcm_data, pub, priv) != ''
24+
# and quickly run heudiconv with no conversion
25+
runner(['--files', dcm_file, '-c' 'none', '-f', 'reproin'])

0 commit comments

Comments
 (0)