1
# emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*-
2
# vi: set ft=python sts=4 ts=4 sw=4 et:
3
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
5
# See COPYING file distributed along with the NiBabel package for the
6
# copyright and license terms.
8
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
9
# Copyright (C) 2011 Christian Haselgrove
16
from nibabel import dft
19
return cgi.escape(u.encode('utf-8'))
21
# this is the directory containing the DICOM data, or None for all cached data
22
base_dir = '/path/to/DICOM'
25
template_env = jinja2.Environment(autoescape=True)
26
template_env.filters['urlquote'] = urllib.quote
28
index_template = """<html><head><title>data</title></head>
33
{% for p in patients|sort %}
34
Patient: <a href="{{ p|urlquote }}/">{{ p }}</a>
36
{% if patients[p]|length == 1 %}
39
{{ patients[p]|length }} studies
47
patient_template = """<html><head><title>data</title></head>
49
<a href="../">Home</a> -> Patient {{ studies[0].patient_name_or_uid() }}
52
Patient name: {{ studies[0].patient_name }}
54
Patient ID: {{ studies[0].patient_id }}
56
Patient birth date: {{ studies[0].patient_birth_date }}
58
Patient sex: {{ studies[0].patient_sex }}
61
{% for s in studies %}
62
<li><a href="{{ s.date|urlquote }}_{{ s.time|urlquote }}/">Study {{ s.uid }}</a></li>
64
<li>Date: {{ s.date }}</li>
65
<li>Time: {{ s.time }}</li>
66
<li>Comments: {{ s.comments }}</li>
67
<li>Series: {{ s.series|length }}</li>
74
patient_date_time_template = """
75
<html><head><title>data</title></head>
77
<a href="../../">Home</a> -> <a href="../../{{ study.patient_name_or_uid() }}/">Patient {{ study.patient_name_or_uid() }}</a> -> Study {{ study.date}} {{ study.time }}
80
Patient name: <a href="../../{{ study.patient_name_or_uid() }}/">{{ study.patient_name }}</a>
82
Study UID: {{ study.uid }}
84
Study date: {{ study.date }}
86
Study time: {{ study.time }}
88
Study comments: {{ study.comments }}
89
{% if study.series|length == 0 %}
94
{% for s in study.series %}
95
<li>Series {{ s.number }} (<a href="{{ s.number }}/nifti">NIfTI</a>)</li>
97
<li>Series UID: {{ s.uid }}</li>
98
<li>Series description: {{ s.description }}</li>
99
<li>Series dimensions: {{ s.rows }}x{{ s.columns }}x{{ s.storage_instances|length }}</li>
101
<img src="{{ s.number }}/png" />
111
def __init__(self, status, output):
116
def application(environ, start_response):
118
(status, c_type, output) = handler(environ)
119
except HandlerError, exc:
122
c_type = 'text/plain'
124
(exc_type, exc_value, exc_traceback) = sys.exc_info()
125
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
126
status = '500 Internal Server Error'
127
output = ''.join(lines)
128
c_type = 'text/plain'
129
response_headers = [('Content-Type', c_type),
130
('Content-Length', str(len(output)))]
131
if c_type == 'image/nifti':
132
response_headers.append(('Content-Disposition', 'attachment; filename=image.nii'))
133
start_response(status, response_headers)
136
def handler(environ):
137
if environ['PATH_INFO'] == '' or environ['PATH_INFO'] == '/':
138
return ('200 OK', 'text/html', index(environ))
139
parts = environ['PATH_INFO'].strip('/').split('/')
141
return ('200 OK', 'text/html', patient(parts[0]))
143
return ('200 OK', 'text/html', patient_date_time(parts[0], parts[1]))
145
if parts[3] == 'nifti':
146
return ('200 OK', 'image/nifti', nifti(parts[0], parts[1], parts[2]))
147
elif parts[3] == 'png':
148
return ('200 OK', 'image/png', png(parts[0], parts[1], parts[2]))
149
raise HandlerError('404 Not Found', "%s not found\n" % environ['PATH_INFO'])
164
for s in dft.get_studies(base_dir):
165
patients.setdefault(s.patient_name_or_uid(), []).append(s)
166
template = template_env.from_string(index_template)
167
return template.render(patients=patients).encode('utf-8')
169
def patient(patient):
170
studies = [ s for s in dft.get_studies() if s.patient_name_or_uid() == patient ]
171
if len(studies) == 0:
172
raise HandlerError('404 Not Found', 'patient %s not found\n' % patient)
173
studies.sort(study_cmp)
174
template = template_env.from_string(patient_template)
175
return template.render(studies=studies).encode('utf-8')
177
def patient_date_time(patient, date_time):
179
for s in dft.get_studies():
180
if s.patient_name_or_uid() != patient:
182
if date_time != '%s_%s' % (s.date, s.time):
187
raise HandlerError, ('404 Not Found', 'study not found')
188
template = template_env.from_string(patient_date_time_template)
189
return template.render(study=study).encode('utf-8')
191
def nifti(patient, date_time, scan):
193
for s in dft.get_studies():
194
if s.patient_name_or_uid() != patient:
196
if date_time != '%s_%s' % (s.date, s.time):
201
raise HandlerError, ('404 Not Found', 'study not found')
203
for series in s.series:
204
if series.number != scan:
209
raise HandlerError, ('404 Not Found', 'series not found')
210
return ser.as_nifti()
212
def png(patient, date_time, scan):
214
for s in dft.get_studies():
215
if s.patient_name_or_uid() != patient:
217
if date_time != '%s_%s' % (s.date, s.time):
222
raise HandlerError, ('404 Not Found', 'study not found')
224
for series in s.series:
225
if series.number != scan:
230
raise HandlerError, ('404 Not Found', 'series not found')
231
index = len(ser.storage_instances) / 2
232
return ser.as_png(index, True)
234
if __name__ == '__main__':
235
import wsgiref.simple_server
236
httpd = wsgiref.simple_server.make_server('', 8080, application)
237
httpd.serve_forever()