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))