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