Mercurial > repos > iuc > idr_download_by_ids
comparison idr_download_by_ids.py @ 0:57aa9597cd31 draft
"planemo upload for repository https://github.com/galaxyproject/tools-iuc/tree/master/tools/idr_download commit 253efabdfea3a1fecc4c0f2c54c0e97a7d7960ab"
author | iuc |
---|---|
date | Sat, 08 Feb 2020 13:24:39 -0500 |
parents | |
children | 9340cbc7796c |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:57aa9597cd31 |
---|---|
1 import argparse | |
2 import os | |
3 import sys | |
4 | |
5 from matplotlib import pyplot as plt | |
6 from omero.gateway import BlitzGateway # noqa | |
7 from omero.constants.namespaces import NSBULKANNOTATIONS # noqa | |
8 | |
9 | |
10 def warn(message, image_identifier): | |
11 print( | |
12 'ImageSpecWarning for {0}: {1}' | |
13 .format(image_identifier, message), | |
14 file=sys.stderr | |
15 ) | |
16 | |
17 | |
18 def find_channel_index(image, channel_name): | |
19 channel_name = channel_name.lower() | |
20 for n, channel in enumerate(image.getChannels()): | |
21 if channel_name == channel.getLabel().lower(): | |
22 return n | |
23 # Check map annotation for information (this is necessary for some images) | |
24 for ann in image.listAnnotations(NSBULKANNOTATIONS): | |
25 pairs = ann.getValue() | |
26 for p in pairs: | |
27 if p[0] == "Channels": | |
28 channels = p[1].replace(" ", "").split(";") | |
29 for n, c in enumerate(channels): | |
30 for value in c.split(':'): | |
31 if channel_name == value.lower(): | |
32 return n | |
33 return -1 | |
34 | |
35 | |
36 def get_clipping_region(image, x, y, w, h): | |
37 # If the (x, y) coordinate falls outside the image boundaries, we | |
38 # cannot just shift it because that would render the meaning of | |
39 # w and h undefined (should width and height be decreased or the whole | |
40 # region be shifted to keep them fixed?). | |
41 # It may be better to abort in this situation. | |
42 if x < 0 or y < 0: | |
43 raise ValueError( | |
44 'Too small upper left coordinate ({0}, {1}) for clipping region.' | |
45 .format(x, y) | |
46 ) | |
47 size_x = image.getSizeX() | |
48 size_y = image.getSizeY() | |
49 if x >= size_x or y >= size_y: | |
50 raise ValueError( | |
51 'Upper left coordinate ({0}, {1}) of clipping region lies ' | |
52 'outside of image.' | |
53 .format(x, y) | |
54 ) | |
55 # adjust width and height to the image dimensions | |
56 if w <= 0 or x + w > size_x: | |
57 w = size_x - x | |
58 if h <= 0 or y + h > size_y: | |
59 h = size_y - y | |
60 return [x, y, w, h] | |
61 | |
62 | |
63 def confine_plane(image, z): | |
64 if z < 0: | |
65 z = 0 | |
66 else: | |
67 max_z = image.getSizeZ() - 1 | |
68 if z > max_z: | |
69 z = max_z | |
70 return z | |
71 | |
72 | |
73 def confine_frame(image, t): | |
74 if t < 0: | |
75 t = 0 | |
76 else: | |
77 max_t = image.getSizeT() - 1 | |
78 if t > max_t: | |
79 t = max_t | |
80 return t | |
81 | |
82 | |
83 def download_plane_as_tiff(image, tile, z, c, t, fname): | |
84 pixels = image.getPrimaryPixels() | |
85 selection = pixels.getTile(theZ=z, theT=t, theC=c, tile=tile) | |
86 | |
87 if fname[-5:] != '.tiff': | |
88 fname += '.tiff' | |
89 plt.imsave(fname, selection) | |
90 | |
91 | |
92 def download_image_data( | |
93 image_ids, | |
94 channel=None, z_stack=0, frame=0, | |
95 coord=(0, 0), width=0, height=0, region_spec='rectangle', | |
96 skip_failed=False | |
97 ): | |
98 | |
99 # connect to idr | |
100 conn = BlitzGateway('public', 'public', | |
101 host='idr.openmicroscopy.org', | |
102 secure=True) | |
103 conn.connect() | |
104 | |
105 try: | |
106 prefix = 'image-' | |
107 for image_id in image_ids: | |
108 if image_id[:len(prefix)] == prefix: | |
109 image_id = image_id[len(prefix):] | |
110 image_id = int(image_id) | |
111 image = conn.getObject("Image", image_id) | |
112 | |
113 if image is None: | |
114 image_warning_id = 'Image-ID: {0}'.format(image_id) | |
115 if skip_failed: | |
116 warn( | |
117 'Unable to find an image with this ID in the ' | |
118 'database. Skipping download!', | |
119 image_warning_id | |
120 ) | |
121 continue | |
122 raise ValueError( | |
123 '{0}: Unable to find an image with this ID in the ' | |
124 'database. Aborting!' | |
125 .format(image_warning_id) | |
126 ) | |
127 | |
128 image_name = os.path.splitext(image.getName())[0] | |
129 image_warning_id = '{0} (ID: {1})'.format( | |
130 image_name, image_id | |
131 ) | |
132 | |
133 if region_spec == 'rectangle': | |
134 tile = get_clipping_region(image, *coord, width, height) | |
135 elif region_spec == 'center': | |
136 tile = get_clipping_region( | |
137 image, | |
138 *_center_to_ul(*coord, width, height) | |
139 ) | |
140 else: | |
141 raise ValueError( | |
142 'Got unknown value "{0}" as region_spec argument' | |
143 .format(region_spec) | |
144 ) | |
145 if tile[2] < width or tile[3] < height: | |
146 # The downloaded image region will have smaller dimensions | |
147 # than the specified width x height. | |
148 warn( | |
149 'Downloaded image dimensions ({0} x {1}) will be smaller ' | |
150 'than the specified width and height ({2} x {3}).' | |
151 .format(tile[2], tile[3], width, height), | |
152 image_warning_id | |
153 ) | |
154 | |
155 ori_z, z_stack = z_stack, confine_plane(image, z_stack) | |
156 if z_stack != ori_z: | |
157 warn( | |
158 'Specified image plane ({0}) is out of bounds. Using {1} ' | |
159 'instead.' | |
160 .format(ori_z, z_stack), | |
161 image_warning_id | |
162 ) | |
163 | |
164 ori_frame, frame = frame, confine_frame(image, frame) | |
165 if frame != ori_frame: | |
166 warn( | |
167 'Specified image frame ({0}) is out of bounds. Using ' | |
168 'frame {1} instead.' | |
169 .format(ori_frame, frame), | |
170 image_warning_id | |
171 ) | |
172 # Get the channel index. If the index is not valid, skip the image | |
173 if channel is None: | |
174 channel_index = 0 | |
175 num_channels = image.getSizeC() | |
176 if num_channels > 1: | |
177 warn( | |
178 'No specific channel selected for multi-channel ' | |
179 'image. Using first of {0} channels.' | |
180 .format(num_channels), | |
181 image_warning_id | |
182 ) | |
183 else: | |
184 channel_index = find_channel_index(image, channel) | |
185 if channel_index == -1: | |
186 raise ValueError( | |
187 '"{0}" is not a known channel name for image {1}' | |
188 .format(channel, image.getName()) | |
189 ) | |
190 | |
191 # download and save the region as TIFF | |
192 fname = '_'.join( | |
193 [image_name, str(image_id)] + [str(x) for x in tile] | |
194 ) | |
195 download_plane_as_tiff(image, tile, z_stack, channel_index, frame, fname) | |
196 finally: | |
197 # Close the connection | |
198 conn.close() | |
199 | |
200 | |
201 def _center_to_ul(center_x, center_y, width, height): | |
202 if width > 0: | |
203 ext_x = (width - 1) // 2 | |
204 ul_x = max([center_x - ext_x, 0]) | |
205 width = center_x + ext_x + 1 - ul_x | |
206 else: | |
207 ul_x = 0 | |
208 if height > 0: | |
209 ext_y = (height - 1) // 2 | |
210 ul_y = max([center_y - ext_y, 0]) | |
211 height = center_y + ext_y + 1 - ul_y | |
212 else: | |
213 ul_y = 0 | |
214 return ul_x, ul_y, width, height | |
215 | |
216 | |
217 if __name__ == "__main__": | |
218 p = argparse.ArgumentParser() | |
219 p.add_argument( | |
220 'image_ids', nargs='*', default=[], | |
221 help='one or more IDR image ids for which to retrieve data (default: ' | |
222 'read ids from stdin).' | |
223 ) | |
224 p.add_argument( | |
225 '-c', '--channel', | |
226 help='name of the channel to retrieve data for ' | |
227 '(note: the first channel of each image will be downloaded if ' | |
228 'left unspecified)' | |
229 ) | |
230 region = p.add_mutually_exclusive_group() | |
231 region.add_argument( | |
232 '--rectangle', nargs=4, type=int, default=argparse.SUPPRESS, | |
233 help='specify a clipping region for the image as x y width height, ' | |
234 'where x and y give the upper left coordinate of the rectangle ' | |
235 'to clip to. Set width and height to 0 to extend the rectangle ' | |
236 'to the actual size of the image.' | |
237 ) | |
238 region.add_argument( | |
239 '--center', nargs=4, type=int, default=argparse.SUPPRESS, | |
240 help='specify a clipping region for the image as x y width height, ' | |
241 'where x and y define the center of a width x height rectangle. ' | |
242 'Set either width or height to 0 to extend the region to the ' | |
243 'actual size of the image along the x- or y-axis.\n' | |
244 'Note: Even values for width and height will be rounded down to ' | |
245 'the nearest odd number.' | |
246 ) | |
247 p.add_argument( | |
248 '-f', '--frame', type=int, default=0 | |
249 ) | |
250 p.add_argument( | |
251 '-z', '--z-stack', type=int, default=0 | |
252 ) | |
253 p.add_argument( | |
254 '--skip-failed', action='store_true' | |
255 ) | |
256 args = p.parse_args() | |
257 if not args.image_ids: | |
258 args.image_ids = sys.stdin.read().split() | |
259 if 'center' in args: | |
260 args.coord, args.width, args.height = ( | |
261 args.center[:2], args.center[2], args.center[3] | |
262 ) | |
263 args.region_spec = 'center' | |
264 del args.center | |
265 elif 'rectangle' in args: | |
266 args.coord, args.width, args.height = ( | |
267 args.rectangle[:2], args.rectangle[2], args.rectangle[3] | |
268 ) | |
269 args.region_spec = 'rectangle' | |
270 del args.rectangle | |
271 download_image_data(**vars(args)) |