Skip to content

Commit 745ed90

Browse files
chaselgrovemih
authored andcommitted
Import the data format tools
published as v0.2 on http://www.nitrc.org/projects/dft/
1 parent 2fcc28c commit 745ed90

File tree

3 files changed

+887
-0
lines changed

3 files changed

+887
-0
lines changed

bin/dicomfs

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
#!/usr/bin/python
2+
3+
# see LICENSE file for copyright and full license
4+
5+
import sys
6+
import os
7+
import stat
8+
import errno
9+
import time
10+
import fuse
11+
import dft
12+
13+
uid = os.getuid()
14+
gid = os.getgid()
15+
16+
fuse.fuse_python_api = (0, 2)
17+
18+
class FileHandle:
19+
20+
def __init__(self, fno):
21+
self.fno = fno
22+
# self.keep_cache = True
23+
# self.direct_io = True
24+
return
25+
26+
def __str__(self):
27+
return 'FileHandle(%d)' % self.fno
28+
29+
class DICOMFS(fuse.Fuse):
30+
31+
def __init__(self, *args, **kwargs):
32+
fuse.Fuse.__init__(self, *args, **kwargs)
33+
self.fhs = {}
34+
return
35+
36+
def get_paths(self):
37+
paths = {}
38+
for study in dft.get_studies(self.dicom_path):
39+
paths.setdefault(study.patient_name, {})
40+
pd = paths[study.patient_name]
41+
patient_info = 'patient information\n'
42+
patient_info = 'name: %s\n' % study.patient_name
43+
patient_info += 'ID: %s\n' % study.patient_id
44+
patient_info += 'birth date: %s\n' % study.patient_birth_date
45+
patient_info += 'sex: %s\n' % study.patient_sex
46+
pd['INFO'] = patient_info.encode('ascii', 'replace')
47+
study_datetime = '%s_%s' % (study.date, study.time)
48+
study_info = 'study info\n'
49+
study_info += 'UID: %s\n' % study.uid
50+
study_info += 'date: %s\n' % study.date
51+
study_info += 'time: %s\n' % study.time
52+
study_info += 'comments: %s\n' % study.comments
53+
d = {'INFO': study_info.encode('ascii', 'replace')}
54+
for series in study.series:
55+
series_info = 'series info\n'
56+
series_info += 'UID: %s\n' % series.uid
57+
series_info += 'number: %s\n' % series.number
58+
series_info += 'description: %s\n' % series.description
59+
series_info += 'rows: %d\n' % series.rows
60+
series_info += 'columns: %d\n' % series.columns
61+
series_info += 'bits allocated: %d\n' % series.bits_allocated
62+
series_info += 'bits stored: %d\n' % series.bits_stored
63+
series_info += 'storage instances: %d\n' % len(series.storage_instances)
64+
d[series.number] = {'INFO': series_info.encode('ascii', 'replace'),
65+
'%s.nii' % series.number: (series.nifti_size, series.as_nifti),
66+
'%s.png' % series.number: (series.png_size, series.as_png)}
67+
pd[study_datetime] = d
68+
return paths
69+
70+
def match_path(self, path):
71+
wd = self.get_paths()
72+
if path == '/':
73+
print 'return root'
74+
return wd
75+
for part in path.lstrip('/').split('/'):
76+
print path, part
77+
if part not in wd:
78+
return None
79+
wd = wd[part]
80+
print 'return'
81+
return wd
82+
83+
def readdir(self, path, fh):
84+
print 'readdir'
85+
print path
86+
matched_path = self.match_path(path)
87+
if matched_path is None:
88+
return -errno.ENOENT
89+
print 'match', matched_path
90+
fnames = [ k.encode('ascii', 'replace') for k in matched_path.keys() ]
91+
fnames.append('.')
92+
fnames.append('..')
93+
return [ fuse.Direntry(f) for f in fnames ]
94+
95+
def getattr(self, path):
96+
print 'getattr'
97+
print 'path:', path
98+
matched_path = self.match_path(path)
99+
print matched_path
100+
now = time.time()
101+
st = fuse.Stat()
102+
if isinstance(matched_path, dict):
103+
st.st_mode = stat.S_IFDIR | 0755
104+
st.st_ctime = now
105+
st.st_mtime = now
106+
st.st_atime = now
107+
st.st_uid = uid
108+
st.st_gid = gid
109+
st.st_nlink = len(matched_path)
110+
return st
111+
if isinstance(matched_path, str):
112+
st.st_mode = stat.S_IFREG | 0644
113+
st.st_ctime = now
114+
st.st_mtime = now
115+
st.st_atime = now
116+
st.st_uid = uid
117+
st.st_gid = gid
118+
st.st_size = len(matched_path)
119+
st.st_nlink = 1
120+
return st
121+
if isinstance(matched_path, tuple):
122+
st.st_mode = stat.S_IFREG | 0644
123+
st.st_ctime = now
124+
st.st_mtime = now
125+
st.st_atime = now
126+
st.st_uid = uid
127+
st.st_gid = gid
128+
st.st_size = matched_path[0]()
129+
st.st_nlink = 1
130+
return st
131+
return -errno.ENOENT
132+
133+
def open(self, path, flags):
134+
print 'open'
135+
print path
136+
matched_path = self.match_path(path)
137+
if matched_path is None:
138+
return -errno.ENOENT
139+
for i in xrange(1, 10):
140+
if i not in self.fhs:
141+
if isinstance(matched_path, str):
142+
self.fhs[i] = matched_path
143+
elif isinstance(matched_path, tuple):
144+
self.fhs[i] = matched_path[1]()
145+
else:
146+
raise -errno.EFTYPE
147+
return FileHandle(i)
148+
raise -errno.ENFILE
149+
150+
# not done
151+
def read(self, path, size, offset, fh):
152+
print 'read'
153+
print path
154+
print size
155+
print offset
156+
print fh
157+
return self.fhs[fh.fno][offset:offset+size]
158+
159+
def release(self, path, flags, fh):
160+
print 'release'
161+
print path
162+
print fh
163+
del self.fhs[fh.fno]
164+
return
165+
166+
progname = os.path.basename(sys.argv[0])
167+
if len(sys.argv) != 3:
168+
sys.stderr.write('usage: %s <directory containing DICOMs> <mount point>\n' % progname)
169+
sys.exit(1)
170+
171+
fs = DICOMFS(dash_s_do='setsingle')
172+
fs.parse(['-f', '-s', sys.argv[2]])
173+
fs.dicom_path = sys.argv[1]
174+
try:
175+
fs.main()
176+
except fuse.FuseError:
177+
# fuse prints the error message
178+
sys.exit(1)
179+
180+
sys.exit(0)
181+
182+
# eof

0 commit comments

Comments
 (0)