1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 """
22 Utility methods for dealing with scripts.
23 """
24
25 import logging
26 import os
27
28 from struct import unpack
29
30 import omero.clients
31 from omero.rtypes import rdouble
32 from omero.rtypes import rint
33 from omero.rtypes import rstring
34 from omero.rtypes import unwrap
35 import omero.util.pixelstypetopython as pixelstypetopython
36
37 try:
38 import hashlib
39 hash_sha1 = hashlib.sha1
40 except:
41 import sha
42 hash_sha1 = sha.new
43
44
45 COLOURS = {'Red': (255,0,0,255), 'Green': (0,255,0,255), 'Blue': (0,0,255,255), 'Yellow': (255,255,0,255),
46 'White': (255,255,255,255), }
47
48 EXTRA_COLOURS = {'Violet': (238,133,238,255), 'Indigo': (79,6,132,255),
49 'Black': (0,0,0,255), 'Orange': (254,200,6,255), 'Gray': (130,130,130,255),}
50
51 CSV_NS = 'text/csv';
52 CSV_FORMAT = 'text/csv';
53 SU_LOG = logging.getLogger("omero.util.script_utils")
54
55 -def drawTextOverlay(draw, x, y, text, colour='0xffffff'):
56 """
57 Draw test on image.
58 @param draw The PIL Draw class.
59 @param x The x-coord to draw.
60 @param y The y-coord to draw.
61 @param text The text to render.
62 @param colour The colour as a PIL colour string to draw the text in.
63 """
64 draw.text((x,y),text, fill=colour)
65
67 """
68 Draw line on image.
69 @param draw The PIL Draw class.
70 @param x0 The x0-coord of line.
71 @param y0 The y0-coord of line.
72 @param x1 The x1-coord of line.
73 @param y1 The y1-coord of line.
74 @param colour The colour as a PIL colour fill in the line.
75 """
76 draw.line([(x0, y0),(x1,y1)], fill=colour)
77
79 """
80 Convert an R,G,B value to an int.
81 @param R the Red value.
82 @param G the Green value.
83 @param B the Blue value.
84 @return See above.
85 """
86 RGBInt = (red<<16)+(green<<8)+blue;
87 return int(RGBInt);
88
90 """
91 Convert an RGB value to a PIL colour value.
92 @param RGB the RGB value.
93 @return See above.
94 """
95 hexval = hex(int(RGB));
96 return '#'+(6-len(hexval[2:]))*'0'+hexval[2:];
97
99 """
100 Map a range to a string of numbers
101 @param range See above.
102 @return See above.
103 """
104 first = 1;
105 string = "";
106 for value in range:
107 if(first==1):
108 string = str(value);
109 first = 0;
110 else:
111 string = string + ','+str(value)
112 return string;
113
115 for name in os.listdir(dir):
116 full_name = os.path.join(dir, name)
117
118
119 if not os.access(full_name, os.W_OK):
120 os.chmod(full_name, 0600)
121 if os.path.isdir(full_name):
122 rmdir_recursive(full_name)
123 else:
124 os.remove(full_name)
125 os.rmdir(dir)
126
128 """
129 Returns a hash of the file identified by filename
130
131 @param filename: pathName of the file
132 @return: The hash of the file
133 """
134
135 fileHandle = open(filename)
136 h = hash_sha1()
137 h.update(fileHandle.read())
138 hash = h.hexdigest()
139 fileHandle.close()
140 return hash;
141
143 """
144 Calculate the Sha1 Hash from a data array
145 @param data The data array.
146 @return The Hash
147 """
148 h = hash_sha1()
149 h.update(data)
150 hash = h.hexdigest()
151 return hash;
152
155
156
157 -def createFile(updateService, filename, mimetype=None, origFilePathName=None):
158 """
159 Creates an original file, saves it to the server and returns the result
160
161 @param queryService: The query service E.g. session.getQueryService()
162 @param updateService: The update service E.g. session.getUpdateService()
163 @param filename: The file path and name (or name if in same folder). String
164 @param mimetype: The mimetype (string) or Format object representing the file format
165 @param origFilePathName: Optional path/name for the original file
166 @return: The saved OriginalFileI, as returned from the server
167 """
168
169 originalFile = omero.model.OriginalFileI();
170 if(origFilePathName == None):
171 origFilePathName = filename;
172 path, name = os.path.split(origFilePathName)
173 originalFile.setName(omero.rtypes.rstring(name));
174 originalFile.setPath(omero.rtypes.rstring(path));
175
176 try:
177 v = mimetype.getValue()
178 mt = v.getValue()
179 except:
180
181 mt = mimetype
182 if mt:
183 originalFile.mimetype = omero.rtypes.rstring(mt)
184 originalFile.setSize(omero.rtypes.rlong(os.path.getsize(filename)));
185 originalFile.setSha1(omero.rtypes.rstring(calcSha1(filename)));
186 return updateService.saveAndReturnObject(originalFile);
187
188
189 -def uploadFile(rawFileStore, originalFile, filePath=None):
190 """
191 Uploads an OriginalFile to the server
192
193 @param rawFileStore: The Omero rawFileStore
194 @param originalFile: The OriginalFileI
195 @param filePath: Where to find the file to upload. If None, use originalFile.getName().getValue()
196 """
197 rawFileStore.setFileId(originalFile.getId().getValue());
198 fileSize = originalFile.getSize().getValue();
199 increment = 10000;
200 cnt = 0;
201 if filePath == None:
202 filePath = originalFile.getName().getValue()
203 fileHandle = open(filePath, 'rb');
204 done = 0
205 while(done!=1):
206 if(increment+cnt<fileSize):
207 blockSize = increment;
208 else:
209 blockSize = fileSize-cnt;
210 done = 1;
211 fileHandle.seek(cnt);
212 block = fileHandle.read(blockSize);
213 rawFileStore.write(block, cnt, blockSize);
214 cnt = cnt+blockSize;
215 fileHandle.close();
216
217
218 -def downloadFile(rawFileStore, originalFile, filePath=None):
219 """
220 Downloads an OriginalFile from the server.
221
222 @param rawFileStore: The Omero rawFileStore
223 @param originalFile: The OriginalFileI
224 @param filePath: Where to download the file. If None, use originalFile.getName().getValue()
225 """
226 fileId = originalFile.getId().getValue()
227 rawFileStore.setFileId(fileId)
228 fileSize = originalFile.getSize().getValue()
229 maxBlockSize = 10000
230 cnt = 0
231 if filePath == None:
232 filePath = originalFile.getName().getValue()
233
234 i = 1
235 path, ext = filePath.rsplit(".", 1)
236 while os.path.exists(filePath):
237 filePath = "%s_%s.%s" % (path,i,ext)
238 i +=1
239 fileHandle = open(filePath, 'w')
240 cnt = 0;
241 fileSize = originalFile.getSize().getValue()
242 while(cnt<fileSize):
243 blockSize = min(maxBlockSize, fileSize)
244 block = rawFileStore.read(cnt, blockSize)
245 cnt = cnt+blockSize
246 fileHandle.write(block)
247 fileHandle.close()
248 return filePath
249
250
251 -def attachFileToParent(updateService, parent, originalFile, description=None, namespace=None):
252 """
253 Attaches the original file (file) to a Project, Dataset or Image (parent)
254
255 @param updateService: The update service
256 @param parent: A ProjectI, DatasetI or ImageI to attach the file to
257 @param originalFile: The OriginalFileI to attach
258 @param description: Optional description for the file annotation. String
259 @param namespace: Optional namespace for file annotataion. String
260 @return: The saved and returned *AnnotationLinkI (* = Project, Dataset or Image)
261 """
262 fa = omero.model.FileAnnotationI();
263 fa.setFile(originalFile);
264 if description:
265 fa.setDescription(omero.rtypes.rstring(description))
266 if namespace:
267 fa.setNs(omero.rtypes.rstring(namespace))
268 if type(parent) == omero.model.DatasetI:
269 l = omero.model.DatasetAnnotationLinkI()
270 elif type(parent) == omero.model.ProjectI:
271 l = omero.model.ProjectAnnotationLinkI()
272 elif type(parent) == omero.model.ImageI:
273 l = omero.model.ImageAnnotationLinkI()
274 else:
275 return
276 parent = parent.__class__(parent.id.val, False)
277 l.setParent(parent);
278 l.setChild(fa);
279 return updateService.saveAndReturnObject(l);
280
281
282 -def uploadAndAttachFile(queryService, updateService, rawFileStore, parent, localName, mimetype, description=None, namespace=None, origFilePathName=None):
283 """
284 Uploads a local file to the server, as an Original File and attaches it to the
285 parent (Project, Dataset or Image)
286
287 @param queryService: The query service
288 @param updateService: The update service
289 @param rawFileStore: The rawFileStore
290 @param parent: The ProjectI or DatasetI or ImageI to attach file to
291 @param localName: Full Name (and path) of the file location to upload. String
292 @param mimetype: The original file mimetype. E.g. "PNG". String
293 @param description: Optional description for the file annotation. String
294 @param namespace: Namespace to set for the original file
295 @param origFilePathName: The /path/to/file/fileName.ext you want on the server. If none, use output as name
296 @return: The originalFileLink child. (FileAnnotationI)
297 """
298
299 filename = localName
300 if origFilePathName == None:
301 origFilePathName = localName
302 originalFile = createFile(updateService, filename, mimetype, origFilePathName);
303 uploadFile(rawFileStore, originalFile, localName)
304 fileLink = attachFileToParent(updateService, parent, originalFile, description, namespace)
305 return fileLink.getChild()
306
307 -def createLinkFileAnnotation(conn, localPath, parent, output="Output", parenttype="Image", mimetype=None, desc=None, ns=None, origFilePathAndName=None):
308 """
309 Uploads a local file to the server, as an Original File and attaches it to the
310 parent (Project, Dataset or Image)
311
312 @param conn: The L{omero.gateway.BlitzGateway} connection.
313 @param parent: The ProjectI or DatasetI or ImageI to attach file to
314 @param localPath: Full Name (and path) of the file location to upload. String
315 @param mimetype: The original file mimetype. E.g. "PNG". String
316 @param description: Optional description for the file annotation. String
317 @param namespace: Namespace to set for the original file
318 @param
319 @param origFilePathName: The /path/to/file/fileName.ext you want on the server. If none, use output as name
320 @return: The originalFileLink child (FileAnnotationI) and a log message
321 """
322 if os.path.exists(localPath):
323 fileAnnotation = conn.createFileAnnfromLocalFile(localPath, origFilePathAndName=origFilePathAndName, mimetype=mimetype, ns=ns, desc=desc)
324 message = "%s created" % output
325 if parent is not None:
326 if parent.canAnnotate():
327 parentClass = parent.OMERO_CLASS
328 message += " and attached to %s%s %s." % (parentClass[0].lower(), parentClass[1:], parent.getName())
329 parent.linkAnnotation(fileAnnotation)
330 else:
331 message += " but could not be attached."
332 else:
333 message = "%s not created." % output
334 fileAnnotation = None
335 return fileAnnotation, message
336
338 """
339 Get the objects specified by the script parameters.
340 Assume the parameters contain the keys IDs and Data_Type
341
342 @param conn: The L{omero.gateway.BlitzGateway} connection.
343 @param params: The script parameters
344 @return: The valid objects and a log message
345 """
346
347 dataType = params["Data_Type"]
348 ids = params["IDs"]
349 objects = list(conn.getObjects(dataType,ids))
350
351 message = ""
352 if not objects:
353 message += "No %s%s found. " % (dataType[0].lower(), dataType[1:])
354 else:
355 if not len(objects) == len(ids):
356 message += "Found %s out of %s %s%s(s). " % (len(objects), len(ids), dataType[0].lower(), dataType[1:])
357
358
359 idMap = dict( [(o.id, o) for o in objects] )
360 objects = [idMap[i] for i in ids if i in idMap]
361
362 return objects, message
363
365 """
366 Add the annotation to an image.
367 @param updateService The update service to create the annotation link.
368 @param image The ImageI object that should be annotated.
369 @param annotation The annotation object
370 @return The new annotationlink object
371 """
372 l = omero.model.ImageAnnotationLinkI();
373 l.setParent(image);
374 l.setChild(annotation);
375 return updateService.saveAndReturnObject(l);
376
378 """
379 Read the OriginalFile with fileId and return it as a string.
380 @param rawFileService The RawFileService service to read the originalfile.
381 @param iQuery The Query Service.
382 @param fileId The id of the originalFile object.
383 @param maxBlockSize The block size of each read.
384 @return The OriginalFile object contents as a string
385 """
386 fileDetails = iQuery.findByQuery("from OriginalFile as o where o.id = " + str(fileId) , None);
387 rawFileService.setFileId(fileId);
388 data = '';
389 cnt = 0;
390 fileSize = fileDetails.getSize().getValue();
391 while(cnt<fileSize):
392 blockSize = min(maxBlockSize, fileSize);
393 block = rawFileService.read(cnt, blockSize);
394 data = data + block;
395 cnt = cnt+blockSize;
396 return data[0:fileSize];
397
398 -def readFileAsArray(rawFileService, iQuery, fileId, row, col, separator = ' '):
399 """
400 Read an OriginalFile with id and column separator and return it as an array.
401 @param rawFileService The RawFileService service to read the originalfile.
402 @param iQuery The Query Service.
403 @param fileId The id of the originalFile object.
404 @param row The number of rows in the file.
405 @param col The number of columns in the file.
406 @param sep the column separator.
407 @return The file as an NumPy array.
408 """
409 from numpy import fromstring, reshape
410 textBlock = readFromOriginalFile(rawFileService, iQuery, fileId);
411 arrayFromFile = fromstring(textBlock,sep = separator);
412 return reshape(arrayFromFile, (row, col));
413
415 """
416 Read the RawImageFlimFile with fileId and return it as an array [c, x, y]
417 @param rawPixelsStore The rawPixelStore service to get the image.
418 @param pixels The pixels of the image.
419 @return The Contents of the image for z = 0, t = 0, all channels;
420 """
421 from numpy import zeros
422 sizeC = pixels.getSizeC().getValue();
423 sizeX = pixels.getSizeX().getValue();
424 sizeY = pixels.getSizeY().getValue();
425 id = pixels.getId().getValue();
426 pixelsType = pixels.getPixelsType().getValue().getValue();
427 rawPixelsStore.setPixelsId(id , False);
428 cRange = range(0, sizeC);
429 stack = zeros((sizeC, sizeX, sizeY),dtype=pixelstypetopython.toNumpy(pixelsType));
430 for c in cRange:
431 plane = downloadPlane(rawPixelsStore, pixels, 0, c, 0);
432 stack[c,:,:]=plane;
433 return stack;
434
436 """
437 Download the plane [z,c,t] for image pixels. Pixels must have pixelsType loaded.
438 N.B. The rawPixelsStore must have already been initialised by setPixelsId()
439 @param rawPixelsStore The rawPixelStore service to get the image.
440 @param pixels The pixels of the image.
441 @param z The Z-Section to retrieve.
442 @param c The C-Section to retrieve.
443 @param t The T-Section to retrieve.
444 @return The Plane of the image for z, c, t
445 """
446 from numpy import array
447 rawPlane = rawPixelsStore.getPlane(z, c, t);
448 sizeX = pixels.getSizeX().getValue();
449 sizeY = pixels.getSizeY().getValue();
450 pixelType = pixels.getPixelsType().getValue().getValue();
451 convertType ='>'+str(sizeX*sizeY)+pixelstypetopython.toPython(pixelType);
452 convertedPlane = unpack(convertType, rawPlane);
453 numpyType = pixelstypetopython.toNumpy(pixelType)
454 remappedPlane = array(convertedPlane, numpyType);
455 remappedPlane.resize(sizeY, sizeX);
456 return remappedPlane;
457
458
460 """
461 Reads a local image (E.g. single plane tiff) and returns it as a numpy 2D array.
462
463 @param imagePath Path to image.
464 """
465 from numpy import asarray
466 try:
467 from PIL import Image
468 except ImportError:
469 import Image
470
471 i = Image.open(imagePath)
472 a = asarray(i)
473 if rgbIndex == None:
474 return a
475 else:
476 return a[:, :, rgbIndex]
477
478
479 -def uploadDirAsImages(sf, queryService, updateService, pixelsService, path, dataset = None):
480 """
481 Reads all the images in the directory specified by 'path' and uploads them to OMERO as a single
482 multi-dimensional image, placed in the specified 'dataset'
483 Uses regex to determine the Z, C, T position of each image by name,
484 and therefore determines sizeZ, sizeC, sizeT of the new Image.
485
486 @param path the path to the directory containing images.
487 @param dataset the OMERO dataset, if we want to put images somewhere. omero.model.DatasetI
488 """
489
490 import re
491 from numpy import zeros
492
493 regex_token = re.compile(r'(?P<Token>.+)\.')
494 regex_time = re.compile(r'T(?P<T>\d+)')
495 regex_channel = re.compile(r'_C(?P<C>.+?)(_|$)')
496 regex_zslice = re.compile(r'_Z(?P<Z>\d+)')
497
498
499
500 imageMap = {}
501 channelSet = set()
502 tokens = []
503
504
505 sizeZ = 1
506 sizeC = 1
507 sizeT = 1
508 zStart = 1
509 tStart = 1
510
511 fullpath = None
512
513 rgb = False
514
515 for f in os.listdir(path):
516 fullpath = os.path.join(path, f)
517 tSearch = regex_time.search(f)
518 cSearch = regex_channel.search(f)
519 zSearch = regex_zslice.search(f)
520 tokSearch = regex_token.search(f)
521
522 if f.endswith(".jpg"):
523 rgb = True
524
525 if tSearch == None:
526 theT = 0
527 else:
528 theT = int(tSearch.group('T'))
529
530 if cSearch == None:
531 cName = "0"
532 else:
533 cName = cSearch.group('C')
534
535 if zSearch == None:
536 theZ = 0
537 else:
538 theZ = int(zSearch.group('Z'))
539
540 channelSet.add(cName)
541 sizeZ = max(sizeZ, theZ)
542 zStart = min(zStart, theZ)
543 sizeT = max(sizeT, theT)
544 tStart = min(tStart, theT)
545 if tokSearch != None:
546 tokens.append(tokSearch.group('Token'))
547 imageMap[(theZ, cName, theT)] = fullpath
548
549 colourMap = {}
550 if not rgb:
551 channels = list(channelSet)
552
553 for i, c in enumerate(channels):
554 if c == 'rfp':
555 colourMap[i] = COLOURS["Red"]
556 if c == 'gfp':
557 colourMap[i] = COLOURS["Green"]
558 else:
559 channels = ("red", "green", "blue")
560 colourMap[0] = COLOURS["Red"]
561 colourMap[1] = COLOURS["Green"]
562 colourMap[2] = COLOURS["Blue"]
563
564 sizeC = len(channels)
565
566
567 imageName = os.path.commonprefix(tokens).strip('0T_')
568 description = "Imported from images in %s" % path
569 SU_LOG.info("Creating image: %s" % imageName)
570
571
572 if rgb:
573 plane = getPlaneFromImage(fullpath, 0)
574 else:
575 plane = getPlaneFromImage(fullpath)
576 pType = plane.dtype.name
577
578 pixelsType = queryService.findByQuery(\
579 "from PixelsType as p where p.value='%s'" % pType, None)
580 if pixelsType == None and pType.startswith("float"):
581 pixelsType = queryService.findByQuery(\
582 "from PixelsType as p where p.value='%s'" % "float", None)
583 if pixelsType == None:
584 SU_LOG.warn("Unknown pixels type for: %s" % pType)
585 return
586 sizeY, sizeX = plane.shape
587
588 SU_LOG.debug("sizeX: %s sizeY: %s sizeZ: %s sizeC: %s sizeT: %s" % (sizeX, sizeY, sizeZ, sizeC, sizeT))
589
590
591
592 channelList = range(sizeC)
593 imageId = pixelsService.createImage(sizeX, sizeY, sizeZ, sizeT, channelList, pixelsType, imageName, description)
594 params = omero.sys.ParametersI()
595 params.addId(imageId)
596 pixelsId = queryService.projection(\
597 "select p.id from Image i join i.pixels p where i.id = :id",\
598 params)[0][0].val
599
600 rawPixelStore = sf.createRawPixelsStore()
601 rawPixelStore.setPixelsId(pixelsId, True)
602 try:
603 for theC in range(sizeC):
604 minValue = 0
605 maxValue = 0
606 for theZ in range(sizeZ):
607 zIndex = theZ + zStart
608 for theT in range(sizeT):
609 tIndex = theT + tStart
610 if rgb:
611 c = "0"
612 else:
613 c = channels[theC]
614 if (zIndex, c, tIndex) in imageMap:
615 imagePath = imageMap[(zIndex, c, tIndex)]
616 if rgb:
617 SU_LOG.debug("Getting rgb plane from: %s" % imagePath)
618 plane2D = getPlaneFromImage(imagePath, theC)
619 else:
620 SU_LOG.debug("Getting plane from: %s" % imagePath)
621 plane2D = getPlaneFromImage(imagePath)
622 else:
623 SU_LOG.debug("Creating blank plane for .", theZ, channels[theC], theT)
624 plane2D = zeros((sizeY, sizeX))
625 SU_LOG.debug("Uploading plane: theZ: %s, theC: %s, theT: %s" % (theZ, theC, theT))
626
627 uploadPlane(rawPixelStore, plane2D, theZ, theC, theT)
628 minValue = min(minValue, plane2D.min())
629 maxValue = max(maxValue, plane2D.max())
630 pixelsService.setChannelGlobalMinMax(pixelsId, theC, float(minValue), float(maxValue))
631 rgba = None
632 if theC in colourMap:
633 rgba = colourMap[theC]
634 try:
635 renderingEngine = sf.createRenderingEngine()
636 resetRenderingSettings(renderingEngine, pixelsId, theC, minValue, maxValue, rgba)
637 finally:
638 renderingEngine.close()
639 finally:
640 rawPixelStore.close()
641
642
643 pixels = pixelsService.retrievePixDescription(pixelsId)
644 i = 0
645 for c in pixels.iterateChannels():
646 lc = c.getLogicalChannel()
647 lc.setName(rstring(channels[i]))
648 updateService.saveObject(lc)
649 i += 1
650
651
652 if dataset:
653 link = omero.model.DatasetImageLinkI()
654 link.parent = omero.model.DatasetI(dataset.id.val, False)
655 link.child = omero.model.ImageI(imageId, False)
656 updateService.saveAndReturnObject(link)
657
658 return imageId
659
660
661
663 """
664 Parses a single line of cecog output and saves as a roi.
665
666 Adds a Rectangle (particle) to the current OMERO image, at point x, y.
667 Uses the self.image (OMERO image) and self.updateService
668 """
669
670 objects = {}
671 roi_ids = []
672
673 import fileinput
674 for line in fileinput.input([filePath]):
675
676 theT = None
677 x = None
678 y = None
679
680 parts = line.split("\t")
681 names = ("frame", "objID", "primaryClassLabel", "primaryClassName", "centerX", "centerY", "mean", "sd", "secondaryClassabel", "secondaryClassName", "secondaryMean", "secondarySd")
682 values = {}
683 for idx, name in enumerate(names):
684 if len(parts) >= idx:
685 values[name] = parts[idx]
686
687 frame = values["frame"]
688 try:
689 frame = long(frame)
690 except ValueError:
691 SU_LOG.debug("Non-roi line: %s " % line)
692 continue
693
694 theT = frame - 1
695 objID = values["objID"]
696 className = values["primaryClassName"]
697 x = float(values["centerX"])
698 y = float(values["centerY"])
699
700 description = ""
701 for name in names:
702 description += ("%s=%s\n" % (name, values.get(name, "(missing)")))
703
704 if theT and x and y:
705 SU_LOG.debug("Adding point '%s' to frame: %s, x: %s, y: %s" % (className, theT, x, y))
706 try:
707 shapes = objects[objID]
708 except KeyError:
709 shapes = []
710 objects[objID] = shapes
711 shapes.append( (theT, className, x, y, values, description) )
712
713 for object, shapes in objects.items():
714
715
716 roi = omero.model.RoiI()
717 roi.setImage(omero.model.ImageI(imageId, False))
718 roi.setDescription(omero.rtypes.rstring("objID: %s" % object))
719
720
721 for shape in shapes:
722
723 theT, className, x, y, values, description = shape
724
725 point = omero.model.PointI()
726 point.cx = rdouble(x)
727 point.cy = rdouble(y)
728 point.theT = rint(theT)
729 point.theZ = rint(0)
730 if className:
731 point.setTextValue(rstring(className))
732
733
734 roi.addShape(point)
735
736 roi = updateService.saveAndReturnObject(point)
737 roi_ids.append(roi.id.val)
738
739 return roi_ids
740
741
742 -def split_image(client, imageId, dir, unformattedImageName = "tubulin_P037_T%05d_C%s_Z%d_S1.tif", dims = ('T', 'C', 'Z')):
743 """
744 Splits the image into component planes, which are saved as local tiffs according to unformattedImageName.
745 E.g. myLocalDir/tubulin_P037_T%05d_C%s_Z%d_S1.tif which will be formatted according to dims, E.g. ('T', 'C', 'Z')
746 Channel will be formatted according to channel name, not index.
747 @param rawPixelsStore The rawPixelStore
748 @param queryService
749 @param c The C-Section to retrieve.
750 @param t The T-Section to retrieve.
751 @param imageName the local location to save the image.
752 """
753
754 unformattedImageName = os.path.join(dir, unformattedImageName)
755
756 session = client.getSession()
757 queryService = session.getQueryService()
758 rawPixelsStore = session.createRawPixelsStore()
759 pixelsService = session.getPixelsService()
760
761 try:
762 from PIL import Image
763 except:
764 import Image
765
766 query_string = "select p from Pixels p join fetch p.image as i join fetch p.pixelsType where i.id='%s'" % imageId
767 pixels = queryService.findByQuery(query_string, None)
768 sizeZ = pixels.getSizeZ().getValue()
769 sizeC = pixels.getSizeC().getValue()
770 sizeT = pixels.getSizeT().getValue()
771 rawPixelsStore.setPixelsId(pixels.getId().getValue(), True)
772
773 channelMap = {}
774 cIndex = 0
775 pixels = pixelsService.retrievePixDescription(pixels.id.val)
776 for c in pixels.iterateChannels():
777 lc = c.getLogicalChannel()
778 channelMap[cIndex] = lc.getName() and lc.getName().getValue() or str(cIndex)
779 cIndex += 1
780
781 def formatName(unformatted, z, c, t):
782
783 dimMap = {'T': t, 'C':channelMap[c], 'Z': z}
784 dd = tuple([dimMap[d] for d in dims])
785 return unformatted % dd
786
787
788 zStart = 1
789 tStart = 1
790
791
792 for z in range(sizeZ):
793 for c in range(sizeC):
794 for t in range(sizeT):
795 imageName = formatName(unformattedImageName, z+zStart, c, t+tStart)
796 SU_LOG.debug("downloading plane z: %s c: %s t: %s to %s" % (z, c, t, imageName))
797 plane = downloadPlane(rawPixelsStore, pixels, z, c, t)
798 i = Image.fromarray(plane)
799 i.save(imageName)
800
801
818
820 """
821 Attach an array, stored as a csv file to an image. Returns the annotation.
822 @param updateService The updateService to create the annotation link.
823 @param image The image to attach the data to.
824 @param filename The name of the file.
825 @param namespace The namespace of the file.
826 @return
827 """
828 fa = omero.model.FileAnnotationI();
829 fa.setFile(file);
830 fa.setNs(omero.rtypes.rstring(nameSpace))
831 l = omero.model.ImageAnnotationLinkI();
832 l.setParent(image);
833 l.setChild(fa);
834 l = updateService.saveAndReturnObject(l);
835 return l.getChild();
836
837 -def uploadArray(rawFileStore, updateService, queryService, image, filename, namespace, array):
838 """
839 Upload the data to the server, creating the OriginalFile Object and attaching it to the image.
840 @param rawFileStore The rawFileStore used to create the file.
841 @param updateService The updateService to create the annotation link.
842 @param image The image to attach the data to.
843 @param filename The name of the file.
844 @param namespace The name space associated to the annotation.
845 @param data The data to save.
846 @return The newly created file.
847 """
848 data = arrayToCSV(array);
849 file = createFileFromData(updateService, queryService, filename, data);
850 rawFileStore.setFileId(file.getId().getValue());
851 fileSize = len(data);
852 increment = 10000;
853 cnt = 0;
854 done = 0
855 while(done!=1):
856 if(increment+cnt<fileSize):
857 blockSize = increment;
858 else:
859 blockSize = fileSize-cnt;
860 done = 1;
861 block = data[cnt:cnt+blockSize];
862 rawFileStore.write(block, cnt, blockSize);
863 cnt = cnt+blockSize;
864 return attachArrayToImage(updateService, image, file, namespace);
865
867 """
868 Convert the numpy array data to a csv file.
869 @param data the Numpy Array
870 @return The CSV string.
871 """
872 size = data.shape;
873 row = size[0];
874 col = size[1];
875 strdata ="";
876 for r in range(0,row):
877 for c in range(0, col):
878 strdata = strdata + str(data[r,c])
879 if(c<col-1):
880 strdata = strdata+',';
881 strdata = strdata + '\n';
882 return strdata;
883
884
886 """
887 Upload the plane to the server attching it to the current z,c,t of the already instantiated rawPixelStore.
888 @param rawPixelsStore The rawPixelStore which is already pointing to the data.
889 @param plane The data to upload
890 @param z The Z-Section of the plane.
891 @param c The C-Section of the plane.
892 @param t The T-Section of the plane.
893 """
894 byteSwappedPlane = plane.byteswap();
895 convertedPlane = byteSwappedPlane.tostring();
896 rawPixelsStore.setPlane(convertedPlane, z, c, t)
897
898
900 """
901 Upload the plane to the server one row at a time,
902 attching it to the current z,c,t of the already instantiated rawPixelStore.
903 @param rawPixelsStore The rawPixelStore which is already pointing to the data.
904 @param plane The data to upload
905 @param z The Z-Section of the plane.
906 @param c The C-Section of the plane.
907 @param t The T-Section of the plane.
908 """
909 byteSwappedPlane = plane.byteswap()
910
911 rowCount, colCount = plane.shape
912 for y in range(rowCount):
913 row = byteSwappedPlane[y:y+1, :]
914 convertedRow = row.tostring()
915 rawPixelsStore.setRow(convertedRow, y, z, c, t)
916
917
919 """
920 Create the renderingEngine for the pixelsId.
921 @param session The current session to create the renderingEngine from.
922 @return The renderingEngine Service for the pixels.
923 """
924 renderingEngine = session.createRenderingEngine();
925 renderingEngine.lookupPixels(pixelsId);
926 if(renderingEngine.lookupRenderingDef(pixelsId)==0):
927 renderingEngine.resetDefaults();
928 renderingEngine.lookupRenderingDef(pixelsId);
929 renderingEngine.load();
930 return renderingEngine;
931
932
934 """
935 Create the plane rendering def, for z,t
936 @param Z the Z-Section
937 @param T The T-Point.
938 @return The RenderingDef Object.
939 """
940 planeDef = omero.romio.PlaneDef()
941 planeDef.t = t;
942 planeDef.z = z;
943 planeDef.x = 0;
944 planeDef.y = 0;
945 planeDef.slice = 0;
946 return planeDef;
947
949 """
950 Get the rendered Image of the plane for the z, t with the default channels.
951 @param renderingEngine The already instantiated renderEngine.
952 @param z The Z-section.
953 @param t The Timepoint.
954 """
955 planeDef = createPlaneDef(z, t);
956 return renderingEngine.renderAsPackedInt(planeDef);
957
959 """
960 Get the rawPixelsStore for the Image with pixelsId
961 @param pixelsId The pixelsId of the object to retrieve.
962 @return The rawPixelsStore service.
963 """
964 rawPixelsStore = session.createRawPixelsStore();
965 rawPixelsStore.setPixelsId(pixelsId);
966 return rawPixelsStore;
967
969 """
970 Get the rawFileStore for the file with fileId
971 @param fileId The fileId of the object to retrieve.
972 @return The rawFileStore service.
973 """
974 rawFileStore = session.createRawFileStore();
975 rawFileStore.setFileId(fileId);
976 return rawFileStore;
977
979 """
980 Get the plane info for the pixels object returning it in order of z,t,c
981 @param iQuery The query service.
982 @param pixelsId The pixels for Id.
983 @param asOrderedList
984 @return list of planeInfoTimes or map["z:t:c:]
985 """
986 query = "from PlaneInfo as Info where pixels.id='"+str(pixelsId)+"' orderby info.deltaT"
987 infoList = iQuery.findAllByQuery(query,None)
988
989 if(asOrderedList):
990 map = {}
991 for info in infoList:
992 key = "z:"+str(info.theZ.getValue())+"t:"+str(info.theT.getValue())+"c:"+str(info.theC.getValue());
993 map[key] = info.deltaT.getValue();
994 return map;
995 else:
996 return infoList;
997
1000
1001
1003 """
1004 Simply resests the rendering settings for a pixel set, according to the min and max values
1005 The rendering engine does NOT have to be primed with pixelsId, as that is handled by this method.
1006
1007 @param renderingEngine The OMERO rendering engine
1008 @param pixelsId The Pixels ID
1009 @param minValue Minimum value of rendering window
1010 @param maxValue Maximum value of rendering window
1011 @param rgba Option to set the colour of the channel. (r,g,b,a) tuple.
1012 """
1013
1014 renderingEngine.lookupPixels(pixelsId)
1015 if not renderingEngine.lookupRenderingDef(pixelsId):
1016 renderingEngine.resetDefaults()
1017 if rgba == None:
1018 rgba=COLOURS["White"]
1019
1020 if not renderingEngine.lookupRenderingDef(pixelsId):
1021 raise Exception("Still No Rendering Def")
1022
1023 renderingEngine.load()
1024 renderingEngine.setChannelWindow(cIndex, float(minValue), float(maxValue))
1025 if rgba:
1026 red, green, blue, alpha = rgba
1027 renderingEngine.setRGBA(cIndex, red, green, blue, alpha)
1028 renderingEngine.saveCurrentSettings()
1029
1030
1031 -def createNewImage(session, plane2Dlist, imageName, description, dataset=None):
1032 """
1033 Creates a new single-channel, single-timepoint image from the list of 2D numpy arrays in plane2Dlist
1034 with each numpy 2D plane becoming a Z-section.
1035
1036 @param session An OMERO service factory or equivalent with getQueryService() etc.
1037 @param plane2Dlist A list of numpy 2D arrays, corresponding to Z-planes of new image.
1038 @param imageName Name of new image
1039 @param description Description for the new image
1040 @param dataset If specified, put the image in this dataset. omero.model.Dataset object
1041
1042 @return The new OMERO image: omero.model.ImageI
1043 """
1044 queryService = session.getQueryService()
1045 pixelsService = session.getPixelsService()
1046 rawPixelStore = session.createRawPixelsStore()
1047 renderingEngine = session.createRenderingEngine()
1048 containerService = session.getContainerService()
1049
1050 pType = plane2Dlist[0].dtype.name
1051 pixelsType = queryService.findByQuery("from PixelsType as p where p.value='%s'" % pType, None)
1052
1053 theC, theT = (0,0)
1054
1055
1056 shape = plane2Dlist[0].shape
1057 sizeY, sizeX = shape
1058 minValue = plane2Dlist[0].min()
1059 maxValue = plane2Dlist[0].max()
1060
1061
1062 channelList = [theC]
1063 sizeZ, sizeT = (len(plane2Dlist),1)
1064 iId = pixelsService.createImage(sizeX, sizeY, sizeZ, sizeT, channelList, pixelsType, imageName, description)
1065 imageId = iId.getValue()
1066 image = containerService.getImages("Image", [imageId], None)[0]
1067
1068
1069 pixelsId = image.getPrimaryPixels().getId().getValue()
1070 rawPixelStore.setPixelsId(pixelsId, True)
1071 for theZ, plane2D in enumerate(plane2Dlist):
1072 minValue = min(minValue, plane2D.min())
1073 maxValue = max(maxValue, plane2D.max())
1074 if plane2D.size > 1000000:
1075 uploadPlaneByRow(rawPixelStore, plane2D, theZ, theC, theT)
1076 else:
1077 uploadPlane(rawPixelStore, plane2D, theZ, theC, theT)
1078 pixelsService.setChannelGlobalMinMax(pixelsId, theC, float(minValue), float(maxValue))
1079 resetRenderingSettings(renderingEngine, pixelsId, theC, minValue, maxValue)
1080
1081
1082 if dataset:
1083 link = omero.model.DatasetImageLinkI()
1084 link.parent = omero.model.DatasetI(dataset.id.val, False)
1085 link.child = omero.model.ImageI(image.id.val, False)
1086 session.getUpdateService().saveObject(link)
1087
1088 renderingEngine.close()
1089 rawPixelStore.close()
1090 return image
1091
1092
1106
1107
1109 """
1110 Get the ROI from the server for the image with the namespace
1111 @param iROIService The iROIService object
1112 @param imageId The imageId to retreive ROI from.
1113 @param namespace The namespace of the ROI.
1114 @return See above.
1115 """
1116 roiOpts = omero.api.RoiOptions()
1117 if(namespace!=None):
1118 roiOpts.namespace = namespace;
1119 return iROIService.findByImage(imageId, roiOpts);
1120
1122 """
1123 Convert a list to a Comma Separated Value string.
1124 @param list The list to convert.
1125 @return See above.
1126 """
1127 lenList = len(list);
1128 cnt = 0;
1129 str = "";
1130 for item in list:
1131 str = str + item;
1132 if(cnt < lenList-1):
1133 str = str + ",";
1134 cnt = cnt +1;
1135 return str;
1136
1138 """
1139 Convert a csv string to a list of strings
1140 @param csvString The CSV string to convert.
1141 @return See above.
1142 """
1143 list = csvString.split(',');
1144 for index in range(len(list)):
1145 list[index] = list[index].strip();
1146 return list;
1147
1149 """
1150 Register a workflow with the server, if the workflow does not exist create it and returns it,
1151 otherwise it returns the already created workflow.
1152 @param iQuery The query service.
1153 @param iUpdate The update service.
1154 @param namespace The namespace of the workflow.
1155 @param keywords The keywords associated with the workflow.
1156 @return see above.
1157 """
1158 from omero.util.OmeroPopo import WorkflowData as WorkflowData
1159
1160
1161 namespace = unwrap(namespace)
1162 keywords = unwrap(keywords)
1163
1164 workflow = iQuery.findByQuery("from Namespace as n where n.name = '" + namespace+"'", None);
1165 workflowData = WorkflowData();
1166 if(workflow!=None):
1167 workflowData = WorkflowData(workflow);
1168 else:
1169 workflowData.setNamespace(namespace);
1170 splitKeywords = keywords.split(',');
1171
1172 SU_LOG.debug(workflowData.asIObject())
1173 for keyword in splitKeywords:
1174 workflowData.addKeyword(keyword);
1175 SU_LOG.debug(workflowData.asIObject())
1176 workflow = iUpdate.saveAndReturnObject(workflowData.asIObject());
1177 return WorkflowData(workflow);
1178
1180 """
1181 Finds the ROI with the given namespace linked to the image. Returns a collection of ROIs.
1182 @param roiService The ROI service.
1183 @param image The image the ROIs are linked to .
1184 @param namespace The namespace of the ROI.
1185 @return see above.
1186 """
1187 from omero.util.OmeroPopo import ROIData as ROIData
1188 roiOptions = omero.api.RoiOptions();
1189 roiOptions.namespace = omero.rtypes.rstring(namespace);
1190 results = roiService.findByImage(image, roiOptions);
1191 roiList = [];
1192 for roi in results.rois:
1193 roiList.append(ROIData(roi));
1194 return roiList;
1195