comparison Tests/Toolbox.py @ 3:2dbba2e6aa4b

reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 17 Jun 2015 10:03:49 +0200
parents Toolbox.py@08dadea8f40a
children 292a46fe374c
comparison
equal deleted inserted replaced
2:a15734e7f0af 3:2dbba2e6aa4b
1 #!/usr/bin/python
2
3 # Orthanc - A Lightweight, RESTful DICOM Store
4 # Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
5 # Department, University Hospital of Liege, Belgium
6 #
7 # This program is free software: you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License as
9 # published by the Free Software Foundation, either version 3 of the
10 # License, or (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
21 import hashlib
22 import httplib2
23 import json
24 import os.path
25 import re
26 import subprocess
27 import time
28 import zipfile
29
30 from PIL import Image
31 from urllib import urlencode
32
33
34 HERE = os.path.dirname(__file__)
35
36
37 # http://stackoverflow.com/a/1313868/881731
38 try:
39 from cStringIO import StringIO
40 except:
41 from StringIO import StringIO
42
43
44 def DefineOrthanc(url = 'http://localhost:8042',
45 username = None,
46 password = None,
47 aet = 'ORTHANC',
48 dicomPort = 4242):
49 m = re.match(r'(http|https)://([^:]+):([^@]+)@([^@]+)', url)
50 if m != None:
51 url = m.groups()[0] + '://' + m.groups()[3]
52 username = m.groups()[1]
53 password = m.groups()[2]
54
55 if not url.endswith('/'):
56 url += '/'
57
58 return {
59 'Url' : url,
60 'Username' : username,
61 'Password' : password,
62 'DicomAet' : aet,
63 'DicomPort' : dicomPort
64 }
65
66
67 def _SetupCredentials(orthanc, http):
68 if (orthanc['Username'] != None and
69 orthanc['Password'] != None):
70 http.add_credentials(orthanc['Username'], orthanc['Password'])
71
72
73 def DoGet(orthanc, uri, data = {}, body = None, headers = {}):
74 d = ''
75 if len(data.keys()) > 0:
76 d = '?' + urlencode(data)
77
78 http = httplib2.Http()
79 _SetupCredentials(orthanc, http)
80
81 resp, content = http.request(orthanc['Url'] + uri + d, 'GET', body = body,
82 headers = headers)
83 if not (resp.status in [ 200 ]):
84 raise Exception(resp.status)
85 else:
86 try:
87 return json.loads(content)
88 except:
89 return content
90
91 def _DoPutOrPost(orthanc, uri, method, data, contentType, headers):
92 http = httplib2.Http()
93 _SetupCredentials(orthanc, http)
94
95 if isinstance(data, str):
96 body = data
97 if len(contentType) != 0:
98 headers['content-type'] = contentType
99 else:
100 body = json.dumps(data)
101 headers['content-type'] = 'application/json'
102
103 headers['expect'] = ''
104
105 resp, content = http.request(orthanc['Url'] + uri, method,
106 body = body,
107 headers = headers)
108 if not (resp.status in [ 200, 302 ]):
109 raise Exception(resp.status)
110 else:
111 try:
112 return json.loads(content)
113 except:
114 return content
115
116 def DoDelete(orthanc, uri):
117 http = httplib2.Http()
118 _SetupCredentials(orthanc, http)
119
120 resp, content = http.request(orthanc['Url'] + uri, 'DELETE')
121 if not (resp.status in [ 200 ]):
122 raise Exception(resp.status)
123 else:
124 try:
125 return json.loads(content)
126 except:
127 return content
128
129 def DoPut(orthanc, uri, data = {}, contentType = ''):
130 return DoPutOrPost(orthanc, uri, 'PUT', data, contentType)
131
132 def DoPost(orthanc, uri, data = {}, contentType = '', headers = {}):
133 return _DoPutOrPost(orthanc, uri, 'POST', data, contentType, headers)
134
135 def UploadInstance(orthanc, filename):
136 global HERE
137 p = os.path.join(HERE, '..', 'Database', filename)
138 f = open(p, 'rb')
139 d = f.read()
140 f.close()
141 return DoPost(orthanc, '/instances', d, 'application/dicom')
142
143 def UploadFolder(orthanc, path):
144 global HERE
145 p = os.path.join(HERE, 'Database', path)
146 for i in os.listdir(p):
147 try:
148 UploadInstance(orthanc, os.path.join(path, i))
149 except:
150 pass
151
152 def DropOrthanc(orthanc):
153 # Reset the Lua callbacks
154 DoPost(orthanc, '/tools/execute-script', 'function OnStoredInstance(instanceId, tags, metadata) end', 'application/lua')
155
156 DoDelete(orthanc, '/exports')
157
158 for s in DoGet(orthanc, '/patients'):
159 DoDelete(orthanc, '/patients/%s' % s)
160
161 def ComputeMD5(data):
162 m = hashlib.md5()
163 m.update(data)
164 return m.hexdigest()
165
166 def GetImage(orthanc, uri):
167 # http://www.pythonware.com/library/pil/handbook/introduction.htm
168 data = DoGet(orthanc, uri)
169 return Image.open(StringIO(data))
170
171 def GetArchive(orthanc, uri):
172 # http://stackoverflow.com/a/1313868/881731
173 s = DoGet(orthanc, uri)
174 return zipfile.ZipFile(StringIO(s), "r")
175
176 def IsDefinedInLua(orthanc, name):
177 s = DoPost(orthanc, '/tools/execute-script', 'print(type(%s))' % name, 'application/lua')
178 return (s.strip() != 'nil')
179
180 def WaitEmpty(orthanc):
181 while True:
182 if len(DoGet(orthanc, '/instances')) == 0:
183 return
184 time.sleep(0.1)
185
186 def GetDockerHostAddress():
187 route = subprocess.check_output([ '/sbin/ip', 'route' ])
188 m = re.search(r'default via ([0-9.]+)', route)
189 if m == None:
190 return 'localhost'
191 else:
192 return m.groups()[0]