Mercurial > hg > orthanc-tests
annotate Plugins/WSI/Run.py @ 351:429cc9d03610
test access to the configuration of one single peer or modality
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 03 Dec 2020 10:43:41 +0100 |
parents | bb01670b3b79 |
children | 79ce0f7a9714 |
rev | line source |
---|---|
251 | 1 #!/usr/bin/python |
2 # -*- coding: utf-8 -*- | |
3 | |
4 | |
5 # Orthanc - A Lightweight, RESTful DICOM Store | |
6 # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
7 # Department, University Hospital of Liege, Belgium | |
260
943166deebcb
upgrade to year 2020
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
253
diff
changeset
|
8 # Copyright (C) 2017-2020 Osimis S.A., Belgium |
251 | 9 # |
10 # This program is free software: you can redistribute it and/or | |
11 # modify it under the terms of the GNU General Public License as | |
12 # published by the Free Software Foundation, either version 3 of the | |
13 # License, or (at your option) any later version. | |
14 # | |
15 # This program is distributed in the hope that it will be useful, but | |
16 # WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 # General Public License for more details. | |
19 # | |
20 # You should have received a copy of the GNU General Public License | |
21 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
22 | |
23 | |
24 import argparse | |
25 import os | |
26 import pprint | |
27 import re | |
28 import subprocess | |
29 import sys | |
30 import tempfile | |
31 import unittest | |
32 from shutil import copyfile | |
33 | |
34 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'Tests')) | |
35 from Toolbox import * | |
36 | |
37 | |
38 ## | |
39 ## Parse the command-line arguments | |
40 ## | |
41 | |
42 parser = argparse.ArgumentParser(description = 'Run the integration tests for the WSI Dicomizer.') | |
43 | |
44 parser.add_argument('--server', | |
45 default = 'localhost', | |
46 help = 'Address of the Orthanc server to test') | |
47 parser.add_argument('--rest', | |
48 type = int, | |
49 default = 8042, | |
50 help = 'Port to the REST API') | |
51 parser.add_argument('--username', | |
52 default = 'alice', | |
53 help = 'Username to the REST API') | |
54 parser.add_argument('--password', | |
55 default = 'orthanctest', | |
56 help = 'Password to the REST API') | |
57 parser.add_argument('--dicomizer', | |
58 default = '/home/jodogne/Subversion/orthanc-wsi/Applications/i/OrthancWSIDicomizer', | |
59 help = 'Password to the REST API') | |
60 parser.add_argument('--to-tiff', | |
61 default = '/home/jodogne/Subversion/orthanc-wsi/Applications/i/OrthancWSIDicomToTiff', | |
62 help = 'Password to the REST API') | |
252 | 63 parser.add_argument('--valgrind', help = 'Use valgrind while running the DICOM-izer', |
64 action = 'store_true') | |
251 | 65 parser.add_argument('--force', help = 'Do not warn the user', |
66 action = 'store_true') | |
67 parser.add_argument('options', metavar = 'N', nargs = '*', | |
68 help='Arguments to Python unittest') | |
69 | |
70 args = parser.parse_args() | |
71 | |
72 if not args.force: | |
73 print(""" | |
74 WARNING: This test will remove all the content of your | |
75 Orthanc instance running on %s! | |
76 | |
77 Are you sure ["yes" to go on]?""" % args.server) | |
78 | |
79 if sys.stdin.readline().strip() != 'yes': | |
80 print('Aborting...') | |
81 exit(0) | |
82 | |
83 | |
84 | |
85 | |
86 ## | |
87 ## The tests | |
88 ## | |
89 | |
90 ORTHANC = DefineOrthanc(server = args.server, | |
91 username = args.username, | |
92 password = args.password, | |
93 restPort = args.rest) | |
94 | |
253 | 95 def CallCommand(command): |
252 | 96 prefix = [] |
97 if args.valgrind: | |
98 prefix = [ 'valgrind' ] | |
99 | |
253 | 100 log = subprocess.check_output(prefix + command, |
252 | 101 stderr=subprocess.STDOUT) |
253 | 102 |
252 | 103 # If using valgrind, only print the lines from the log starting |
104 # with '==' (they contain the report from valgrind) | |
105 if args.valgrind: | |
106 print('\n'.join(filter(lambda x: x.startswith('=='), log.splitlines()))) | |
251 | 107 |
253 | 108 |
109 def CallDicomizer(suffix): | |
110 CallCommand([ args.dicomizer, | |
111 '--username=%s' % args.username, | |
112 '--password=%s' % args.password ] + suffix) | |
113 | |
114 | |
115 def CallDicomToTiff(suffix): | |
316 | 116 CallCommand([ args.to_tiff, |
117 '--username=%s' % args.username, | |
118 '--password=%s' % args.password ] + suffix) | |
253 | 119 |
120 | |
121 def CallTiffInfoOnSeries(series): | |
122 with tempfile.NamedTemporaryFile(delete = False) as temp: | |
123 temp.close() | |
124 CallDicomToTiff([ series, temp.name ]) | |
316 | 125 try: |
126 tiff = subprocess.check_output([ 'tiffinfo', temp.name ]) | |
127 except: | |
128 print('\ntiffinfo is probably not installed => sudo apt-get install libtiff-tools\n') | |
129 tiff = None | |
130 | |
253 | 131 os.unlink(temp.name) |
132 | |
133 return tiff | |
134 | |
251 | 135 |
136 class Orthanc(unittest.TestCase): | |
137 def setUp(self): | |
138 if (sys.version_info >= (3, 0)): | |
139 # Remove annoying warnings about unclosed socket in Python 3 | |
140 import warnings | |
141 warnings.simplefilter("ignore", ResourceWarning) | |
142 | |
143 DropOrthanc(ORTHANC) | |
144 | |
145 | |
146 def test_single(self): | |
147 CallDicomizer([ GetDatabasePath('Lena.jpg') ]) | |
148 | |
149 i = DoGet(ORTHANC, '/instances') | |
150 self.assertEqual(1, len(i)) | |
151 | |
152 tags = DoGet(ORTHANC, '/instances/%s/tags?simplify' % i[0]) | |
153 self.assertEqual(1, int(tags['NumberOfFrames'])) | |
154 self.assertEqual(512, int(tags['Columns'])) | |
155 self.assertEqual(512, int(tags['Rows'])) | |
156 self.assertEqual('YBR_FULL_422', tags['PhotometricInterpretation']) | |
157 | |
158 s = DoGet(ORTHANC, '/series') | |
159 self.assertEqual(1, len(s)) | |
160 | |
161 pyramid = DoGet(ORTHANC, '/wsi/pyramids/%s' % s[0]) | |
162 self.assertEqual(s[0], pyramid['ID']) | |
163 self.assertEqual(1, len(pyramid['Resolutions'])) | |
164 self.assertEqual(1, len(pyramid['Sizes'])) | |
165 self.assertEqual(1, len(pyramid['TilesCount'])) | |
166 self.assertEqual(1, pyramid['Resolutions'][0]) | |
167 self.assertEqual(512, pyramid['Sizes'][0][0]) | |
168 self.assertEqual(512, pyramid['Sizes'][0][1]) | |
169 self.assertEqual(512, pyramid['TileWidth']) | |
170 self.assertEqual(512, pyramid['TileHeight']) | |
171 self.assertEqual(512, pyramid['TotalWidth']) | |
172 self.assertEqual(512, pyramid['TotalHeight']) | |
173 self.assertEqual(1, pyramid['TilesCount'][0][0]) | |
174 self.assertEqual(1, pyramid['TilesCount'][0][1]) | |
175 | |
253 | 176 tiff = CallTiffInfoOnSeries(s[0]) |
177 p = filter(lambda x: 'Photometric Interpretation' in x, tiff.splitlines()) | |
178 self.assertEqual(1, len(p)) | |
179 self.assertTrue('YCbCr' in p[0]) | |
180 | |
251 | 181 |
182 def test_grayscale_pyramid(self): | |
183 CallDicomizer([ GetDatabasePath('LenaGrayscale.png'), '--tile-width=64', '--tile-height=64' ]) | |
184 | |
185 i = DoGet(ORTHANC, '/instances') | |
186 self.assertEqual(4, len(i)) | |
187 | |
188 for j in range(4): | |
189 tags = DoGet(ORTHANC, '/instances/%s/tags?simplify' % i[j]) | |
190 self.assertEqual(64, int(tags['Columns'])) | |
191 self.assertEqual(64, int(tags['Rows'])) | |
192 self.assertEqual('MONOCHROME2', tags['PhotometricInterpretation']) | |
193 | |
194 s = DoGet(ORTHANC, '/series') | |
195 self.assertEqual(1, len(s)) | |
196 | |
197 pyramid = DoGet(ORTHANC, '/wsi/pyramids/%s' % s[0]) | |
198 self.assertEqual(s[0], pyramid['ID']) | |
199 self.assertEqual(4, len(pyramid['Resolutions'])) | |
200 self.assertEqual(4, len(pyramid['Sizes'])) | |
201 self.assertEqual(4, len(pyramid['TilesCount'])) | |
202 self.assertEqual(1, pyramid['Resolutions'][0]) | |
203 self.assertEqual(2, pyramid['Resolutions'][1]) | |
204 self.assertEqual(4, pyramid['Resolutions'][2]) | |
205 self.assertEqual(8, pyramid['Resolutions'][3]) | |
206 self.assertEqual(512, pyramid['Sizes'][0][0]) | |
207 self.assertEqual(512, pyramid['Sizes'][0][1]) | |
208 self.assertEqual(256, pyramid['Sizes'][1][0]) | |
209 self.assertEqual(256, pyramid['Sizes'][1][1]) | |
210 self.assertEqual(128, pyramid['Sizes'][2][0]) | |
211 self.assertEqual(128, pyramid['Sizes'][2][1]) | |
212 self.assertEqual(64, pyramid['Sizes'][3][0]) | |
213 self.assertEqual(64, pyramid['Sizes'][3][1]) | |
214 self.assertEqual(64, pyramid['TileWidth']) | |
215 self.assertEqual(64, pyramid['TileHeight']) | |
216 self.assertEqual(512, pyramid['TotalWidth']) | |
217 self.assertEqual(512, pyramid['TotalHeight']) | |
218 self.assertEqual(8, pyramid['TilesCount'][0][0]) | |
219 self.assertEqual(8, pyramid['TilesCount'][0][1]) | |
220 self.assertEqual(4, pyramid['TilesCount'][1][0]) | |
221 self.assertEqual(4, pyramid['TilesCount'][1][1]) | |
222 self.assertEqual(2, pyramid['TilesCount'][2][0]) | |
223 self.assertEqual(2, pyramid['TilesCount'][2][1]) | |
224 self.assertEqual(1, pyramid['TilesCount'][3][0]) | |
225 self.assertEqual(1, pyramid['TilesCount'][3][1]) | |
253 | 226 |
227 tiff = CallTiffInfoOnSeries(s[0]) | |
228 p = filter(lambda x: 'Photometric Interpretation' in x, tiff.splitlines()) | |
229 self.assertEqual(4, len(p)) | |
230 for j in range(4): | |
231 self.assertTrue('min-is-black' in p[j]) | |
232 | |
233 | |
234 def test_import_tiff_grayscale(self): | |
235 CallDicomizer([ GetDatabasePath('WSI/LenaGrayscaleJpeg.tiff') ]) | |
236 | |
237 s = DoGet(ORTHANC, '/series') | |
238 self.assertEqual(1, len(s)) | |
239 | |
240 pyramid = DoGet(ORTHANC, '/wsi/pyramids/%s' % s[0]) | |
241 self.assertEqual(4, len(pyramid['Resolutions'])) | |
242 | |
243 tiff = CallTiffInfoOnSeries(s[0]) | |
244 p = filter(lambda x: 'Photometric Interpretation' in x, tiff.splitlines()) | |
245 self.assertEqual(4, len(p)) | |
246 for j in range(4): | |
247 self.assertTrue('min-is-black' in p[j]) | |
248 | |
249 | |
250 def test_import_tiff_ycbcr(self): | |
251 CallDicomizer([ GetDatabasePath('WSI/LenaColorJpegYCbCr.tiff') ]) | |
252 | |
253 s = DoGet(ORTHANC, '/series') | |
254 self.assertEqual(1, len(s)) | |
255 | |
256 pyramid = DoGet(ORTHANC, '/wsi/pyramids/%s' % s[0]) | |
257 self.assertEqual(4, len(pyramid['Resolutions'])) | |
258 | |
259 tiff = CallTiffInfoOnSeries(s[0]) | |
260 p = filter(lambda x: 'Photometric Interpretation' in x, tiff.splitlines()) | |
261 self.assertEqual(4, len(p)) | |
262 for j in range(4): | |
263 self.assertTrue('YCbCr' in p[j]) | |
264 | |
265 | |
266 def test_import_tiff_rgb(self): | |
267 CallDicomizer([ GetDatabasePath('WSI/LenaColorJpegRGB.tiff') ]) | |
268 | |
269 s = DoGet(ORTHANC, '/series') | |
270 self.assertEqual(1, len(s)) | |
271 | |
272 pyramid = DoGet(ORTHANC, '/wsi/pyramids/%s' % s[0]) | |
273 self.assertEqual(4, len(pyramid['Resolutions'])) | |
274 | |
275 tiff = CallTiffInfoOnSeries(s[0]) | |
276 p = filter(lambda x: 'Photometric Interpretation' in x, tiff.splitlines()) | |
277 self.assertEqual(4, len(p)) | |
278 for j in range(4): | |
279 self.assertTrue('RGB' in p[j]) | |
280 | |
251 | 281 |
282 try: | |
283 print('\nStarting the tests...') | |
284 unittest.main(argv = [ sys.argv[0] ] + args.options) | |
285 | |
286 finally: | |
287 print('\nDone') |