Skip to content

Commit 7d31533

Browse files
committed
Added a tool to sort unsorted dicomfiles to the 3-digit SeriesNumber-SeriesDescription format as in /raw
1 parent e627cfd commit 7d31533

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

bidscoiner/dicomsort.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!/usr/bin/env python
2+
"""
3+
Sorts DICOM files into local subdirectories with a (3-digit) SeriesNumber-SeriesDescription directory name (i.e. following the same listing as on the scanner console)
4+
"""
5+
6+
import os
7+
import re
8+
import bids
9+
import warnings
10+
11+
12+
def sortsession(sessionfolder, pattern):
13+
"""
14+
Sorts dicomfiles into (3-digit) SeriesNumber-SeriesDescription subfolders (e.g. '003-T1MPRAGE')
15+
16+
:param str sessionfolder: The name of the folder that contains the dicom files
17+
:param str pattern: The regular expression pattern used in re.match() to select the dicom files
18+
:return: Nothing
19+
:rtype: NoneType
20+
"""
21+
22+
# Input checking
23+
sessionfolder = os.path.abspath(os.path.expanduser(sessionfolder))
24+
seriesdirs = []
25+
print('> Sorting: ' + sessionfolder)
26+
27+
# Map all dicomfiles and move them to series folders
28+
for dicomfile in [os.path.join(sessionfolder,dcmfile) for dcmfile in os.listdir(sessionfolder) if re.match(pattern, dcmfile)]:
29+
30+
# Extract the SeriesDescription and SeriesNumber from the dicomfield
31+
seriesnr = bids.get_dicomfield('SeriesNumber', dicomfile)
32+
seriesdescr = bids.get_dicomfield('SeriesDescription', dicomfile)
33+
if not seriesdescr:
34+
seriesdescr = bids.get_dicomfield('ProtocolName', dicomfile)
35+
if not seriesdescr:
36+
seriesdescr = 'unknown_protocol'
37+
warnings.warn('No SeriesDecription or ProtocolName found for: ' + dicomfile)
38+
39+
# Create the series subfolder
40+
seriesdir = '{:03d}-{}'.format(seriesnr, seriesdescr)
41+
if seriesdir not in seriesdirs: # We have a new series
42+
if not os.path.isdir(os.path.join(sessionfolder, seriesdir)):
43+
print('Creating: ' + os.path.join(sessionfolder, seriesdir))
44+
os.makedirs(os.path.join(sessionfolder, seriesdir))
45+
seriesdirs.append(seriesdir)
46+
47+
# Move the dicomfile to the series subfolder
48+
os.rename(dicomfile, os.path.join(sessionfolder, seriesdir, os.path.basename(dicomfile)))
49+
50+
51+
def sortsessions(rawfolder, subjectid='', sessionid='', pattern='.*\.(IMA|dcm)$'):
52+
"""
53+
54+
:param rawfolder: The root folder containing the source [sub/][ses/]dicomfiles
55+
:param subjectid: The prefix of the sub folders in rawfolder
56+
:param sessionid: The prefix of the ses folders in sub folder
57+
:param pattern: The regular expression pattern used in re.match() to select the dicom files
58+
:return: Nothing
59+
:rtype: NoneType
60+
"""
61+
62+
if subjectid:
63+
for subfolder in bids.lsdirs(os.path.join(rawfolder, subjectid + '*')):
64+
if sessionid:
65+
for sesfolder in bids.lsdirs(os.path.join(subfolder, sessionid + '*')):
66+
sortsession(sesfolder, pattern)
67+
else:
68+
sortsession(subfolder, pattern)
69+
else:
70+
sortsession(rawfolder, pattern)
71+
72+
73+
# Shell usage
74+
if __name__ == "__main__":
75+
76+
# Parse the input arguments and run the sortsessions(args)
77+
import argparse
78+
import textwrap
79+
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
80+
description=textwrap.dedent(__doc__),
81+
epilog='examples:\n rawmapper.py -r /project/3022026.01/raw\n rawmapper.py -d AcquisitionDate /project/3022026.01/raw\n ')
82+
parser.add_argument('rawfolder', help='The root folder containing the source [sub/][ses/]dicomfiles')
83+
parser.add_argument('--subjectid', help='The prefix of the subject folders in rawfolder (empty value means no recursive search)', default='')
84+
parser.add_argument('--sessionid', help='The prefix of the session folders in the subject folder (empty value means no recursive search)', default='')
85+
parser.add_argument('--pattern', help='The regular expression pattern used in re.match() to select the dicom files', default='.*\.(IMA|dcm)$')
86+
args = parser.parse_args()
87+
88+
sortsessions(rawfolder=args.rawfolder, subjectid=args.subjectid, sessionid=args.sessionid, pattern=args.pattern)

0 commit comments

Comments
 (0)