1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 import os
16 THISPATH = os.path.dirname(os.path.abspath(__file__))
17
18 import warnings
19 from types import IntType, LongType, UnicodeType, ListType, TupleType, StringType, StringTypes
20 from datetime import datetime
21 from cStringIO import StringIO
22 import ConfigParser
23
24 import omero
25 import omero.clients
26 from omero.util.decorators import timeit
27 from omero.cmd import DoAll
28 from omero.api import Save
29 from omero.gateway.utils import ServiceOptsDict, GatewayConfig
30 import omero.scripts as scripts
31
32 import Ice
33 import Glacier2
34
35 import traceback
36 import time
37 import array
38 import math
39 import re
40 from decimal import Decimal
41
42 from gettext import gettext as _
43
44 import logging
45 logger = logging.getLogger(__name__)
46
47 try:
48 from PIL import Image, ImageDraw, ImageFont
49 except:
50 try:
51 import Image, ImageDraw, ImageFont
52 except:
53 logger.error('No Pillow installed, line plots and split channel will fail!')
54 from math import sqrt
55
56 from omero.rtypes import rstring, rint, rlong, rbool, rtime, rlist, rdouble, unwrap
59 """
60 Converts rtypes from static factory methods:
61 - StringType to rstring
62 - UnicodeType to rstring
63 - IntType to rint
64 - LongType to rlong
65
66 elswere return the argument itself
67
68 :param val: value
69 :rtype: omero.rtype
70 :return: matched RType or value
71 """
72
73 if isinstance(val, StringType):
74 return rstring(val)
75 elif isinstance(val, UnicodeType):
76 return rstring(val.encode('utf-8'))
77 elif isinstance(val, IntType):
78 return rint(val)
79 elif isinstance(val, LongType):
80 return rlong(val)
81 else:
82 return val
83
85 """
86 Reads everything from fin, in chunks of bufsize.
87
88
89 :type fin: file
90 :param fin: filelike readable object
91 :type fsize: int
92 :param fsize: total number of bytes to read
93 :type bufsize: int
94 :param fsize: size of each chunk of data read from fin
95 :rtype: string
96 :return: string buffer holding the contents read from the file
97 """
98
99 p = 0
100 rv = ''
101 while p < fsize:
102 s = min(bufsize, fsize-p)
103 rv += fin.read(p,s)
104 p += s
105 fin.close()
106 return rv
107
110 """
111 Generator helper function that yields chunks of the file of size fsize.
112
113 :type fin: file
114 :param fin: filelike readable object
115 :type fsize: int
116 :param fsize: total number of bytes to read
117 :type bufsize: int
118 :param fsize: size of each chunk of data read from fin that gets yielded
119 :rtype: generator
120 :return: generator of string buffers of size up to bufsize read from fin
121 """
122 p = 0
123 while p < fsize:
124 s = min(bufsize, fsize-p)
125 yield fin.read(p,s)
126 p += s
127 fin.close()
128
130 """
131 Object wrapper class which provides various methods for hierarchy traversing,
132 saving, handling permissions etc.
133 This is the 'abstract' super class which is subclassed by
134 E.g. _ProjectWrapper, _DatasetWrapper etc.
135 All ojbects have a reference to the L{BlitzGateway} connection, and therefore all services are
136 available for handling calls on the object wrapper. E.g listChildren() uses queryservice etc.
137 """
138
139 OMERO_CLASS = None
140 LINK_CLASS = None
141 LINK_CHILD = 'child'
142 CHILD_WRAPPER_CLASS = None
143 PARENT_WRAPPER_CLASS = None
144
145 @staticmethod
148
149 - def __init__ (self, conn=None, obj=None, cache=None, **kwargs):
150 """
151 Initialises the wrapper object, setting the various class variables etc
152
153 :param conn: The L{omero.gateway.BlitzGateway} connection.
154 :type conn: L{omero.gateway.BlitzGateway}
155 :param obj: The object to wrap. E.g. omero.model.Image
156 :type obj: omero.model object
157 :param cache: Cache which is passed to new child wrappers
158 """
159 self.__bstrap__()
160 self._obj = obj
161 self._cache = cache
162 if self._cache is None:
163 self._cache = {}
164 self._conn = conn
165 self._creationDate = None
166 if conn is None:
167 return
168 if hasattr(obj, 'id') and obj.id is not None:
169 self._oid = obj.id.val
170 if not self._obj.loaded:
171 self._obj = self._conn.getQueryService().get(self._obj.__class__.__name__, self._oid, self._conn.SERVICE_OPTS)
172 self.__prepare__ (**kwargs)
173
175 """
176 Returns true if the object is of the same type and has same id and name
177
178 :param a: The object to compare to this one
179 :return: True if objects are same - see above
180 :rtype: Boolean
181 """
182 return type(a) == type(self) and self._obj.id == a._obj.id and self.getName() == a.getName()
183
185 """ Initialisation method which is implemented by subclasses to set their class variables etc. """
186 pass
187
189 """ Initialisation method which is implemented by subclasses to handle various init tasks """
190 pass
191
193 """
194 Returns a String representation of the Object, including ID if set.
195
196 :return: String E.g. '<DatasetWrapper id=123>'
197 :rtype: String
198 """
199 if hasattr(self, '_oid'):
200 return '<%s id=%s>' % (self.__class__.__name__, str(self._oid))
201 return super(BlitzObjectWrapper, self).__repr__()
202
204 """
205 Used for building queries in generic methods such as getObjects("Project")
206 """
207 return "select obj from %s obj join fetch obj.details.owner as owner join fetch obj.details.group "\
208 "join fetch obj.details.creationEvent" % self.OMERO_CLASS
209
211 """
212 Returns the wrapper class of children of this object.
213 Checks that this is one of the Wrapper objects in the L{omero.gateway} module
214 Raises NotImplementedError if this is not true or class is not defined (None)
215 This is used internally by the L{listChildren} and L{countChildren} methods.
216
217 :return: The child wrapper class. E.g. omero.gateway.DatasetWrapper.__class__
218 :rtype: class
219 """
220 if self.CHILD_WRAPPER_CLASS is None:
221 raise NotImplementedError('%s has no child wrapper defined' % self.__class__)
222 if type(self.CHILD_WRAPPER_CLASS) is type(''):
223
224 if hasattr(omero.gateway, self.CHILD_WRAPPER_CLASS):
225 self.__class__.CHILD_WRAPPER_CLASS = self.CHILD_WRAPPER_CLASS = getattr(omero.gateway, self.CHILD_WRAPPER_CLASS)
226 else:
227 raise NotImplementedError
228 return self.CHILD_WRAPPER_CLASS
229
231 """
232 Returns the wrapper classes of the parent of this object.
233 This is used internally by the L{listParents} method.
234
235 :return: List of parent wrapper classes. E.g. omero.gateway.DatasetWrapper.__class__
236 :rtype: class
237 """
238 if self.PARENT_WRAPPER_CLASS is None:
239 raise NotImplementedError
240 pwc = self.PARENT_WRAPPER_CLASS
241 if not isinstance(pwc, ListType):
242 pwc = [pwc,]
243 for i in range(len(pwc)):
244 if isinstance(pwc[i], StringTypes):
245
246 g = globals()
247 if not pwc[i] in g:
248 raise NotImplementedError
249 pwc[i] = g[pwc[i]]
250
251
252
253
254
255
256
257
258 if pwc != self.PARENT_WRAPPER_CLASS or pwc != self.__class__.PARENT_WRAPPER_CLASS:
259 self.__class__.PARENT_WRAPPER_CLASS = self.PARENT_WRAPPER_CLASS = pwc
260 return self.PARENT_WRAPPER_CLASS
261
263 """
264 Loads the object that is wrapped by this class. This includes linked objects.
265 This method can be overwritten by subclasses that want to specify how/which linked objects
266 are loaded.
267 """
268 self._obj = self._conn.getContainerService().loadContainerHierarchy(self.OMERO_CLASS, (self._oid,), None, self._conn.SERVICE_OPTS)[0]
269
271 """
272 Moves this object from a parent container (first one if there are more than one) to a new parent.
273 TODO: might be more useful if it didn't assume only 1 parent - option allowed you to specify the oldParent.
274
275 :param newParent: The new parent Object Wrapper.
276 :return: True if moved from parent to parent.
277 False if no parent exists or newParent has mismatching type
278 :rtype: Boolean
279 """
280 p = self.getParent()
281
282 if p.OMERO_CLASS == newParent.OMERO_CLASS:
283 link = self._conn.getQueryService().findAllByQuery("select l from %s as l where l.parent.id=%i and l.child.id=%i" % (p.LINK_CLASS, p.id, self.id), None, self._conn.SERVICE_OPTS)
284 if len(link):
285 link[0].parent = newParent._obj
286 self._conn.getUpdateService().saveObject(link[0], self._conn.SERVICE_OPTS)
287 return True
288 logger.debug("## query didn't return objects: 'select l from %s as l where l.parent.id=%i and l.child.id=%i'" % (p.LINK_CLASS, p.id, self.id))
289 else:
290 logger.debug("## %s != %s ('%s' - '%s')" % (type(p), type(newParent), str(p), str(newParent)))
291 return False
292
294 """
295 Find the first child object with a matching name, and description if specified.
296
297 :param name: The name which must match the child name
298 :param description: If specified, child description must match too
299 :return: The wrapped child object
300 :rtype: L{BlitzObjectWrapper}
301 """
302 for c in self.listChildren():
303 if c.getName() == name:
304 if description is None or omero_type(description) == omero_type(c.getDescription()):
305 return c
306 return None
307
309 """
310 Gets the details of the wrapped object
311
312 :return: L{omero.gateway.DetailsWrapper} or None if object not loaded
313 :rtype: L{DetailsWrapper}
314 """
315 if self._obj.loaded:
316 return omero.gateway.DetailsWrapper (self._conn, self._obj.getDetails())
317 return None
318
319
321 """
322 Returns the object's acquisitionDate, or creation date (details.creationEvent.time)
323
324 :return: A L{datetime.datetime} object
325 :rtype: datetime
326 """
327
328 try:
329 if self._obj.acquisitionDate.val is not None and self._obj.acquisitionDate.val > 0:
330 t = self._obj.acquisitionDate.val
331 return datetime.fromtimestamp(t/1000)
332 except:
333
334 pass
335
336 return self.creationEventDate()
337
338
350
352 """
353 Save this object, keeping the object owner the same as the one on provided details
354 If the current user is an admin but is NOT the owner specified in 'details',
355 then create a new connection for that owner, clone the current object under that
356 connection and save.
357 Otherwise, simply save.
358
359 :param details: The Details specifying owner to save to
360 :type details: L{DetailsWrapper}
361 :return: None
362 """
363 if self._conn.isAdmin():
364 d = self.getDetails()
365 if d.getOwner() and \
366 d.getOwner().omeName == details.getOwner().omeName and \
367 d.getGroup().name == details.getGroup().name:
368 return self.save()
369 else:
370 newConn = self._conn.suConn(details.getOwner().omeName, details.getGroup().name)
371
372
373
374
375
376
377
378 clone = self.__class__(newConn, self._obj)
379 clone.save()
380 self._obj = clone._obj
381 return
382 else:
383 return self.save()
384
386 """
387 Delegates to the connection L{BlitzGateway.canWrite} method
388
389 :rtype: Boolean
390 """
391 return self._conn.canWrite(self)
392
394 """
395 Delegates to the connection L{BlitzGateway.canWrite} method
396
397 :rtype: Boolean
398 :return: True if the objects's permissions allow owner to write
399 """
400 return self._conn.canOwnerWrite(self)
401
403 """
404 Returns True if the object owner is the same user specified in the connection's Event Context
405
406 :rtype: Boolean
407 :return: True if current user owns this object
408 """
409 return (self._obj.details.owner.id.val == self._conn.getUserId())
410
412 """
413 Returns True if the group that this object belongs to is lead by the currently logged-in user
414
415 :rtype: Boolean
416 :return: see above
417 """
418 g = self._obj.details.group or self._obj.details
419 if g.id.val in self._conn.getEventContext().leaderOfGroups:
420 return True
421 return False
422
424 """
425 Determines if the object permissions are world readable, ie permissions.isWorldRead()
426
427 :rtype: Boolean
428 :return: see above
429 """
430 g = self.getDetails().getGroup()
431 g = g and g.details or self._obj.details
432 return g.permissions.isWorldRead()
433
435 """
436 Determines if the object is sharable between groups (but not public)
437
438 :rtype: Boolean
439 :return: True if the object is not L{public<isPublic>} AND the
440 object permissions allow group read.
441 """
442 if not self.isPublic():
443 g = self.getDetails().getGroup()
444 g = g and g.details or self._obj.details
445 return g.permissions.isGroupRead()
446 return False
447
449 """
450 Determines if the object is private
451
452 :rtype: Boolean
453 :returns: True if the object is not L{public<isPublic>} and not
454 L{shared<isShared>} and permissions allow user to read.
455 """
456 if not self.isPublic() and not self.isShared():
457 g = self.getDetails().getGroup()
458 g = g and g.details or self._obj.details
459 return g.permissions.isUserRead()
460 return False
461
463 """
464 Determines if the current user can Edit (E.g. name, description) link (E.g. Project, Dataset, Image etc)
465 or Delete this object. The canEdit() property is set on the permissions of every object as
466 it is read from the server, based on the current user, event context and group permissions.
467
468 :rtype: Boolean
469 :return: True if user can Edit this object Delete, link etc.
470 """
471 return self.getDetails().getPermissions().canEdit()
472
478
480 """
481 Determines whether user can create 'hard' links (Not annotation links).
482 E.g. Between Project/Dataset/Image etc.
483 Previously (4.4.6 and earlier) we only allowed this for object owners, but now we delegate
484 to what the server will allow.
485 """
486 return self.getDetails().getPermissions().canLink()
487
489 """
490 Determines if the current user can annotate this object: ie create annotation links.
491 The canAnnotate() property is set on the permissions of every object as
492 it is read from the server, based on the current user, event context and group permissions.
493
494 :rtype: Boolean
495 :return: True if user can Annotate this object
496 """
497 return self.getDetails().getPermissions().canAnnotate()
498
500 """
501 Specifies whether the current user can move this object to another group.
502 Web client will only allow this for the data Owner.
503 Admin CAN move other user's data, but we don't support this in Web yet.
504 """
505 return self.isOwned()
506
508 """
509 Counts available number of child objects.
510
511 :return: The number of child objects available
512 :rtype: Long
513 """
514
515 childw = self._getChildWrapper()
516 klass = "%sLinks" % childw().OMERO_CLASS.lower()
517
518 self._cached_countChildren = self._conn.getContainerService().getCollectionCount(self.OMERO_CLASS, klass, [self._oid], None, self._conn.SERVICE_OPTS)[self._oid]
519 return self._cached_countChildren
520
522 """
523 countChildren, but caching the first result, useful if you need to call this multiple times in
524 a single sequence, but have no way of storing the value between them.
525 It is actually a hack to support django template's lack of break in for loops
526
527 :return: The number of child objects available
528 :rtype: Long
529 """
530
531 if not hasattr(self, '_cached_countChildren'):
532 return self.countChildren()
533 return self._cached_countChildren
534
536 """
537 Lists available child objects.
538
539 :rtype: generator of Ice client proxy objects for the child nodes
540 :return: child objects.
541 """
542 if not params:
543 params = omero.sys.Parameters()
544 if not params.map:
545 params.map = {}
546 params.map["dsid"] = omero_type(self._oid)
547 query = "select c from %s as c" % self.LINK_CLASS
548 if ns is not None:
549 params.map["ns"] = omero_type(ns)
550 query += """ join fetch c.child as ch
551 left outer join fetch ch.annotationLinks as ial
552 left outer join fetch ial.child as a """
553 query += " where c.parent.id=:dsid"
554 if ns is not None:
555 query += " and a.ns=:ns"
556 if val is not None:
557 if isinstance(val, StringTypes):
558 params.map["val"] = omero_type(val)
559 query +=" and a.textValue=:val"
560 query += " order by c.child.name"
561 for child in ( x.child for x in self._conn.getQueryService().findAllByQuery(query, params, self._conn.SERVICE_OPTS) ):
562 yield child
563
565 """
566 Lists available child objects.
567
568 :rtype: generator of L{BlitzObjectWrapper} objs
569 :return: child objects.
570 """
571 childw = self._getChildWrapper()
572 for child in self._listChildren(ns=ns, val=val, params=params):
573 yield childw(self._conn, child, self._cache)
574
576 """
577 List a single parent, if available.
578
579 While the model suports many to many relationships between most objects, there are
580 implementations that assume a single project per dataset, a single dataset per image,
581 etc. This is just a shortcut method to return a single parent object.
582
583 :type withlinks: Boolean
584 :param withlinks: if true result will be a tuple of (linkobj, obj)
585 :rtype: L{BlitzObjectWrapper} ( or tuple(L{BlitzObjectWrapper}, L{BlitzObjectWrapper}) )
586 :return: the parent object with or without the link depending on args
587 """
588
589 rv = self.listParents(withlinks=withlinks)
590 return len(rv) and rv[0] or None
591
593 """
594 Lists available parent objects.
595
596 :type withlinks: Boolean
597 :param withlinks: if true each yielded result will be a tuple of (linkobj, obj)
598 :rtype: list of L{BlitzObjectWrapper} ( or tuple(L{BlitzObjectWrapper}, L{BlitzObjectWrapper}) )
599 :return: the parent objects, with or without the links depending on args
600 """
601 if self.PARENT_WRAPPER_CLASS is None:
602 return ()
603 parentw = self._getParentWrappers()
604 param = omero.sys.Parameters()
605 parentnodes = []
606 for pwc in parentw:
607 pwck = pwc()
608 if withlinks:
609 parentnodes.extend([(pwc(self._conn, pwck.LINK_PARENT(x), self._cache), BlitzObjectWrapper(self._conn, x)) for x in self._conn.getQueryService().findAllByQuery("from %s as c where c.%s.id=%i" % (pwck.LINK_CLASS, pwck.LINK_CHILD, self._oid), param, self._conn.SERVICE_OPTS)])
610 else:
611 t = self._conn.getQueryService().findAllByQuery("from %s as c where c.%s.id=%i" % (pwck.LINK_CLASS, pwck.LINK_CHILD, self._oid), param, self._conn.SERVICE_OPTS)
612 parentnodes.extend([pwc(self._conn, pwck.LINK_PARENT(x), self._cache) for x in t])
613 return parentnodes
614
616 """
617 Get a list of Ancestors. First in list is parent of this object.
618 TODO: Assumes getParent() returns a single parent.
619
620 :rtype: List of L{BlitzObjectWrapper}
621 :return: List of Ancestor objects
622 """
623 rv = []
624 p = self.getParent()
625 while p:
626 rv.append(p)
627 p = p.getParent()
628 return rv
629
631 """
632 Get a list of parent objects links.
633
634 :param pids: List of parent IDs
635 :type pids: L{Long}
636 :rtype: List of L{BlitzObjectWrapper}
637 :return: List of parent object links
638 """
639
640 if self.PARENT_WRAPPER_CLASS is None:
641 raise AttributeError("This object has no parent objects")
642 parentwrappers = self._getParentWrappers()
643 link_class = None
644 for v in parentwrappers:
645 link_class = v().LINK_CLASS
646 if link_class is not None:
647 break
648 if link_class is None:
649 raise AttributeError(
650 "This object has no parent objects with a link class!")
651 query_serv = self._conn.getQueryService()
652 p = omero.sys.Parameters()
653 p.map = {}
654 p.map["child"] = rlong(self.id)
655 sql = "select pchl from %s as pchl " \
656 "left outer join fetch pchl.parent as parent " \
657 "left outer join fetch pchl.child as child " \
658 "where child.id=:child" % link_class
659 if isinstance(pids, list) and len(pids) > 0:
660 p.map["parent"] = rlist([rlong(pa) for pa in pids])
661 sql+=" and parent.id in (:parent)"
662 for pchl in query_serv.findAllByQuery(sql, p, self._conn.SERVICE_OPTS):
663 yield BlitzObjectWrapper(self, pchl)
664
666 """
667 Get a list of child objects links.
668
669 :param chids: List of children IDs
670 :type chids: L{Long}
671 :rtype: List of L{BlitzObjectWrapper}
672 :return: List of child object links
673 """
674
675 if self.CHILD_WRAPPER_CLASS is None:
676 raise AttributeError("This object has no child objects")
677 query_serv = self._conn.getQueryService()
678 p = omero.sys.Parameters()
679 p.map = {}
680 p.map["parent"] = rlong(self.id)
681 sql = "select pchl from %s as pchl left outer join fetch pchl.child as child \
682 left outer join fetch pchl.parent as parent where parent.id=:parent" % self.LINK_CLASS
683 if isinstance(chids, list) and len(chids) > 0:
684 p.map["children"] = rlist([rlong(ch) for ch in chids])
685 sql+=" and child.id in (:children)"
686 for pchl in query_serv.findAllByQuery(sql, p, self._conn.SERVICE_OPTS):
687 yield BlitzObjectWrapper(self, pchl)
688
690 """ Loads the annotation links for the object (if not already loaded) and saves them to the object """
691 if not hasattr(self._obj, 'isAnnotationLinksLoaded'):
692 raise NotImplementedError
693
694 ctx = self._conn.SERVICE_OPTS.copy()
695 ctx.setOmeroGroup(self.details.group.id.val)
696 if not self._obj.isAnnotationLinksLoaded():
697 query = "select l from %sAnnotationLink as l join fetch l.details.owner join fetch l.details.creationEvent "\
698 "join fetch l.child as a join fetch a.details.owner join fetch a.details.creationEvent "\
699 "where l.parent.id=%i" % (self.OMERO_CLASS, self._oid)
700 links = self._conn.getQueryService().findAllByQuery(query, None, ctx)
701 self._obj._annotationLinksLoaded = True
702 self._obj._annotationLinksSeq = links
703
704
706 """
707 Checks links are loaded and returns a list of Annotation Links filtered by
708 namespace if specified
709
710 :param ns: Namespace
711 :type ns: String
712 :return: List of Annotation Links on this object
713 :rtype: List of Annotation Links
714 """
715 self._loadAnnotationLinks()
716 rv = self.copyAnnotationLinks()
717 if ns is not None:
718 rv = filter(lambda x: x.getChild().getNs() and x.getChild().getNs().val == ns, rv)
719 return rv
720
721
723 """
724 Uses updateService to unlink annotations, with specified ns
725
726 :param ns: Namespace
727 :type ns: String
728 """
729 dcs = []
730 for al in self._getAnnotationLinks(ns=ns):
731 dcs.append(omero.cmd.Delete(
732 "/%s" % al.ice_id().split("::")[-1],
733 al.id.val, None))
734
735
736
737 if len(dcs):
738 doall = omero.cmd.DoAll()
739 doall.requests = dcs
740 handle = self._conn.c.sf.submit(doall, self._conn.SERVICE_OPTS)
741 try:
742 self._conn._waitOnCmd(handle)
743 finally:
744 handle.close()
745 self._obj.unloadAnnotationLinks()
746
748 """
749 Uses the delete service to delete annotations, with a specified ns,
750 and their links on the object and any other objects. Will raise a
751 L{omero.LockTimeout} if the annotation removal has not finished in
752 5 seconds.
753
754 :param ns: Namespace
755 :type ns: String
756 """
757 ids = list()
758 for al in self._getAnnotationLinks(ns=ns):
759 a = al.child
760 ids.append(a.id.val)
761 if len(ids):
762 handle = self._conn.deleteObjects('/Annotation', ids)
763 try:
764 self._conn._waitOnCmd(handle)
765 finally:
766 handle.close()
767 self._obj.unloadAnnotationLinks()
768
769
771 """
772 Gets the first annotation on the object, filtered by ns if specified
773
774 :param ns: Namespace
775 :type ns: String
776 :return: L{AnnotationWrapper} or None
777 """
778 rv = self._getAnnotationLinks(ns)
779 if len(rv):
780 return AnnotationWrapper._wrap(self._conn, rv[0].child, link=rv[0])
781 return None
782
784 """
785 List annotations in the ns namespace, linked to this object
786
787 :return: Generator yielding L{AnnotationWrapper}
788 :rtype: L{AnnotationWrapper} generator
789 """
790 for ann in self._getAnnotationLinks(ns):
791 yield AnnotationWrapper._wrap(self._conn, ann.child, link=ann)
792
794 """
795 Retrieve all Annotations not linked to the given Project, Dataset, Image,
796 Screen, Plate, Well ID controlled by the security system.
797
798 :param o_type: type of Object
799 :type o_type: String
800 :param oid: Object ID
801 :type oid: Long
802 :return: Generator yielding Tags
803 :rtype: L{AnnotationWrapper} generator
804 """
805
806 return self._conn.listOrphanedAnnotations(self.OMERO_CLASS, [self.getId()], eid, ns, anntype, addedByMe)
807
808
810 """
811 Saves the object to DB if needed - setting the permissions manually.
812 Creates the object link and saves it, setting permissions manually.
813 TODO: Can't set permissions manually in 4.2 - Assumes world & group writable
814
815 :param obj: The object to link
816 :type obj: L{BlitzObjectWrapper}
817 """
818 ctx = self._conn.SERVICE_OPTS.copy()
819 ctx.setOmeroGroup(self.details.group.id.val)
820 if not obj.getId():
821
822 obj = obj.__class__(self._conn, self._conn.getUpdateService().saveAndReturnObject(obj._obj, ctx))
823 lnk = getattr(omero.model, lnkobjtype)()
824 lnk.setParent(self._obj.__class__(self._obj.id, False))
825 lnk.setChild(obj._obj.__class__(obj._obj.id, False))
826 self._conn.getUpdateService().saveObject(lnk, ctx)
827 return obj
828
830 """
831 Saves the annotation to DB if needed - setting the permissions manually.
832 Creates the annotation link and saves it, setting permissions manually.
833 TODO: Can't set permissions manually in 4.2 - Assumes world & group writable
834
835 :param ann: The annotation object
836 :type ann: L{AnnotationWrapper}
837 """
838 return self._linkObject(ann, "%sAnnotationLinkI" % self.OMERO_CLASS)
839
841 """
842 Link the annotation to this object.
843
844 :param ann: The Annotation object
845 :type ann: L{AnnotationWrapper}
846 :param sameOwner: If True, try to make sure that the link is created by the object owner
847 :type sameOwner: Boolean
848 :return: The annotation
849 :rtype: L{AnnotationWrapper}
850 """
851
852 """
853 My notes (will) to try and work out what's going on!
854 If sameOwner:
855 if current user is admin AND they are not the object owner,
856 if the object owner and annotation owner are the same:
857 use the Annotation connection to do the linking
858 else use a new connection for the object owner (?same owner as ann?)
859 do linking
860 else:
861 try to switch the current group of this object to the group of the annotation - do linking
862 else - just do linking
863
864 """
865 if sameOwner:
866 d = self.getDetails()
867 ad = ann.getDetails()
868 if self._conn.isAdmin() and self._conn.getUserId() != d.getOwner().id:
869
870 if ad.getOwner() and d.getOwner().omeName == ad.getOwner().omeName and d.getGroup().name == ad.getGroup().name:
871 newConn = ann._conn
872 else:
873
874
875 group = None
876 if d.getGroup():
877 group = d.getGroup().name
878
879 newConn = self._conn.suConn(d.getOwner().omeName, group)
880
881
882
883
884 clone = self.__class__(newConn, self._obj)
885 ann = clone._linkAnnotation(ann)
886 if newConn != self._conn:
887 newConn.seppuku()
888 elif d.getGroup():
889
890
891 self._conn.setGroupForSession(d.getGroup().getId())
892 ann = self._linkAnnotation(ann)
893 self._conn.revertGroupForSession()
894 else:
895 ann = self._linkAnnotation(ann)
896 else:
897 ann = self._linkAnnotation(ann)
898 self.unloadAnnotationLinks()
899 return ann
900
901
903 """
904 Creates a dict representation of this object.
905 E.g. for Image::
906
907 {'description': '', 'author': 'Will Moore', 'date': 1286332557.0,
908 'type': 'Image', 'id': 3841L, 'name': 'cb_4_w500_t03_z01.tif'}
909
910 :param xtra: A dict of extra keys to include. E.g. 'childCount'
911 :type xtra: Dict
912 :param parents: If True, include a list of ancestors (in
913 simpleMarshal form) as 'parents'
914 :type parents: Boolean
915 :return: A dict representation of this object
916 :rtype: Dict
917 """
918 rv = {'type': self.OMERO_CLASS,
919 'id': self.getId(),
920 'name': self.getName(),
921 'description': self.getDescription(),
922 }
923 if hasattr(self, '_attrs'):
924
925
926
927
928
929
930
931
932
933
934 for k in self._attrs:
935 if ';' in k:
936 s = k.split(';')
937 k = s[0]
938 rk = ';'.join(s[1:])
939 else:
940 rk = k
941 if '|' in k:
942 s = k.split('|')
943 if rk == k:
944 rk = s[0]
945 k = s[0]
946 wrapper = '|'.join(s[1:])
947 else:
948 wrapper = None
949
950 if k.startswith('()'):
951 if k == rk:
952 rk = k[2:]
953 k = k[2:]
954 getter = True
955 else:
956 getter = False
957
958 if k.startswith('#'):
959 k = k[1:]
960 unwrapit = True
961 else:
962 unwrapit = False
963
964 if getter:
965 v = getattr(self, 'get'+k[0].upper()+k[1:])()
966 else:
967 v = getattr(self, k)
968 if unwrapit and v is not None:
969 v = v._value
970 if wrapper is not None and v is not None:
971 if wrapper == '':
972 if isinstance(v, ListType):
973 v = map(lambda x: x.simpleMarshal(), v)
974 else:
975 v = v.simpleMarshal()
976 else:
977 v = getattr(omero.gateway, wrapper)(self._conn, v).simpleMarshal()
978
979 rv[rk] = v
980 if xtra:
981 if 'childCount' in xtra:
982 rv['child_count'] = self.countChildren()
983 if parents:
984 rv['parents'] = map(lambda x: x.simpleMarshal(), self.getAncestry())
985 return rv
986
987
988
989
990
991
993 """
994 Attempts to return the named attribute of this object. E.g. image.__getattr__('name') or 'getName'
995 In cases where the attribute E.g. 'getImmersion' should return an enumeration, this is specified by the
996 attr name starting with '#' #immersion.
997 In cases where the attribute E.g. 'getLightSource' should return a wrapped object, this is handled
998 by the parent encoding the wrapper in the attribute name. E.g 'lightSource|LightSourceWrapper'
999 In both cases this returns a method that will return the object.
1000 In addition, lookup of methods that return an rtype are wrapped to the method instead returns a primitive type.
1001 E.g. image.getArchived() will return a boolean instead of rbool.
1002
1003 :param attr: The name of the attribute to get
1004 :type attr: String
1005 :return: The named attribute.
1006 :rtype: method, value (string, long etc)
1007 """
1008
1009
1010 if attr != 'get' and attr.startswith('get') and hasattr(self, '_attrs'):
1011 tattr = attr[3].lower() + attr[4:]
1012 attrs = filter(lambda x: tattr in x, self._attrs)
1013 for a in attrs:
1014 if a.startswith('#') and a[1:] == tattr:
1015 v = getattr(self, tattr)
1016 if v is not None:
1017 v = v._value
1018 def wrap ():
1019 return v
1020 return wrap
1021 if len(a) > len(tattr) and a[len(tattr)] == '|':
1022 def wrap ():
1023 return getattr(omero.gateway, a[len(tattr)+1:])(self._conn, getattr(self, tattr))
1024 return wrap
1025
1026
1027 if attr != 'get' and attr.startswith('get'):
1028 attrName = attr[3].lower() + attr[4:]
1029 if hasattr(self._obj, attrName):
1030 def wrap():
1031 rv = getattr(self._obj, attrName)
1032 if hasattr(rv, 'val'):
1033 return isinstance(rv.val, StringType) and rv.val.decode('utf8') or rv.val
1034 elif isinstance(rv, omero.model.IObject):
1035 return BlitzObjectWrapper(self._conn, rv)
1036 return rv
1037 return wrap
1038
1039
1040
1041 if not hasattr(self._obj, attr) and hasattr(self._obj, '_'+attr):
1042 attr = '_' + attr
1043 if hasattr(self._obj, attr):
1044 rv = getattr(self._obj, attr)
1045 if hasattr(rv, 'val'):
1046 return isinstance(rv.val, StringType) and rv.val.decode('utf8') or rv.val
1047 return rv
1048 raise AttributeError("'%s' object has no attribute '%s'" % (self._obj.__class__.__name__, attr))
1049
1050
1051
1052
1054 """
1055 Gets this object ID
1056
1057 :return: Long or None
1058 """
1059 oid = self._obj.getId()
1060 if oid is not None:
1061 return oid.val
1062 return None
1063
1065 """
1066 Gets this object name
1067
1068 :return: String or None
1069 """
1070 if hasattr(self._obj, 'name'):
1071 if hasattr(self._obj.name, 'val'):
1072 return self._obj.getName().val
1073 else:
1074 return self._obj.getName()
1075 else:
1076 return None
1077
1079 """
1080 Gets this object description
1081
1082 :return: String
1083 """
1084 rv = hasattr(self._obj, 'description') and self._obj.getDescription() or None
1085 return rv and rv.val or ''
1086
1088 """
1089 Gets user who is the owner of this object.
1090
1091 :return: _ExperimenterWrapper
1092 """
1093 return self.getDetails().getOwner()
1094
1096 """
1097 Gets full name of the owner of this object.
1098
1099 :return: String or None
1100 """
1101 try:
1102 lastName = self.getDetails().getOwner().lastName
1103 firstName = self.getDetails().getOwner().firstName
1104 middleName = self.getDetails().getOwner().middleName
1105
1106 if middleName is not None and middleName != '':
1107 name = "%s %s. %s" % (firstName, middleName, lastName)
1108 else:
1109 name = "%s %s" % (firstName, lastName)
1110 return name
1111 except:
1112 logger.error(traceback.format_exc())
1113 return None
1114
1116 """
1117 Gets omeName of the owner of this object.
1118
1119 :return: String
1120 """
1121 return self.getDetails().getOwner().omeName
1122
1123
1125 """
1126 Gets event time in timestamp format (yyyy-mm-dd hh:mm:ss.fffffff) when object was created.
1127
1128 :return: The datetime for object creation
1129 :rtype: datetime.datetime
1130 """
1131
1132 if self._creationDate is not None:
1133 return datetime.fromtimestamp(self._creationDate/1000)
1134
1135 try:
1136 if self._obj.details.creationEvent._time is not None:
1137 self._creationDate = self._obj.details.creationEvent._time.val
1138 else:
1139 self._creationDate = self._conn.getQueryService().get("Event", self._obj.details.creationEvent.id.val, self._conn.SERVICE_OPTS).time.val
1140 except:
1141 self._creationDate = self._conn.getQueryService().get("Event", self._obj.details.creationEvent.id.val, self._conn.SERVICE_OPTS).time.val
1142 return datetime.fromtimestamp(self._creationDate/1000)
1143
1144
1146 """
1147 Gets event time in timestamp format (yyyy-mm-dd hh:mm:ss.fffffff) when object was updated.
1148
1149 :return: The datetime for object update
1150 :rtype: datetime.datetime
1151 """
1152
1153 try:
1154 if self._obj.details.updateEvent.time is not None:
1155 t = self._obj.details.updateEvent.time.val
1156 else:
1157 t = self._conn.getQueryService().get("Event", self._obj.details.updateEvent.id.val, self._conn.SERVICE_OPTS).time.val
1158 except:
1159 t = self._conn.getQueryService().get("Event", self._obj.details.updateEvent.id.val, self._conn.SERVICE_OPTS).time.val
1160 return datetime.fromtimestamp(t/1000)
1161
1162
1163
1164
1166 """
1167 Sets the name of the object
1168
1169 :param value: New name
1170 :type value: String
1171 """
1172 self._obj.setName(omero_type(value))
1173
1175 """
1176 Sets the description of the object
1177
1178 :param value: New description
1179 :type value: String
1180 """
1181 self._obj.setDescription(omero_type(value))
1182
1186 """ A dummy placeholder to indicate that proxies haven't been created """
1188 raise Ice.ConnectionLostException
1189
1192
1194 """
1195 Connection wrapper. Handles connecting and keeping the session alive, creation of various services,
1196 context switching, security privilidges etc.
1197 """
1198
1199 """
1200 Holder for class wide configuration properties.
1201 """
1202 ICE_CONFIG = None
1203 """
1204 ICE_CONFIG - Defines the path to the Ice configuration
1205 """
1206
1207 - def __init__ (self, username=None, passwd=None, client_obj=None, group=None, clone=False, try_super=False, host=None, port=None, extra_config=None, secure=False, anonymous=True, useragent=None):
1208 """
1209 Create the connection wrapper. Does not attempt to connect at this stage
1210 Initialises the omero.client
1211
1212 :param username: User name.
1213 :type username: String
1214 :param passwd: Password.
1215 :type passwd: String
1216 :param client_obj: omero.client
1217 :param group: name of group to try to connect to
1218 :type group: String
1219 :param clone: If True, overwrite anonymous with False
1220 :type clone: Boolean
1221 :param try_super: Try to log on as super user ('system' group)
1222 :type try_super: Boolean
1223 :param host: Omero server host.
1224 :type host: String
1225 :param port: Omero server port.
1226 :type port: Integer
1227 :param extra_config: Dictionary of extra configuration
1228 :type extra_config: Dict
1229 :param secure: Initial underlying omero.client connection type (True=SSL/False=insecure)
1230 :type secure: Boolean
1231 :param anonymous:
1232 :type anonymous: Boolean
1233 :param useragent: Log which python clients use this connection. E.g. 'OMERO.webadmin'
1234 :type useragent: String
1235 """
1236
1237 if extra_config is None: extra_config = []
1238 super(_BlitzGateway, self).__init__()
1239 self.CONFIG = GatewayConfig()
1240 self.c = client_obj
1241 if not type(extra_config) in (type(()), type([])):
1242 extra_config=[extra_config]
1243 self.extra_config = extra_config
1244 self.ice_config = [self.ICE_CONFIG]
1245 self.ice_config.extend(extra_config)
1246 self.ice_config = map(lambda x: os.path.abspath(str(x)), filter(None, self.ice_config))
1247
1248 self.host = host
1249 self.port = port
1250 self.secure = secure
1251 self.useragent = useragent
1252
1253 self._sessionUuid = None
1254 self._session_cb = None
1255 self._session = None
1256 self._lastGroupId = None
1257 self._anonymous = anonymous
1258 self._defaultOmeroGroup = None
1259 self._defaultOmeroUser = None
1260 self._maxPlaneSize = None
1261
1262 self._connected = False
1263 self._user = None
1264 self._userid = None
1265 self._proxies = NoProxies()
1266 if self.c is None:
1267 self._resetOmeroClient()
1268 else:
1269
1270 self._connected = True
1271 self._createProxies()
1272 self.SERVICE_OPTS = self.createServiceOptsDict()
1273 if try_super:
1274 self.group = 'system'
1275 else:
1276 self.group = group and group or None
1277
1278
1279 self.setIdentity(username, passwd, not clone)
1280
1286
1288 self._defaultOmeroGroup = defaultOmeroGroup
1289
1291 self._defaultOmeroUser = defaultOmeroUser
1292
1294 return self._defaultOmeroGroup
1295
1297 return self._defaultOmeroUser
1298
1300 """
1301 Returns the maximum plane size the server will allow for an image to not be considered big
1302 i.e. width or height larger than this will trigger image pyramids to be calculated.
1303
1304 This is useful for the client to filter images based on them needing pyramids or not, without
1305 the full rendering engine overhead.
1306
1307 :return: tuple holding (max_plane_width, max_plane_height) as set on the server
1308 :rtype: Tuple
1309 """
1310 if self._maxPlaneSize is None:
1311 c = self.getConfigService()
1312 self._maxPlaneSize = (int(c.getConfigValue('omero.pixeldata.max_plane_width')),
1313 int(c.getConfigValue('omero.pixeldata.max_plane_height')))
1314 return self._maxPlaneSize
1315
1317 """
1318 Returns the anonymous flag
1319
1320 :return: Anonymous
1321 :rtype: Boolean
1322 """
1323 return not not self._anonymous
1324
1326 """
1327 Returns named property of the wrapped omero.client
1328
1329 :return: named client property
1330 """
1331 return self.c.getProperty(k)
1332
1334 """
1335 Returns a new instance of this class, with all matching properties.
1336 TODO: Add anonymous and userAgent parameters?
1337
1338 :return: Clone of this connection wrapper
1339 :rtype: L{_BlitzGateway}
1340 """
1341 return self.__class__(self._ic_props[omero.constants.USERNAME],
1342 self._ic_props[omero.constants.PASSWORD],
1343 host = self.host,
1344 port = self.port,
1345 extra_config=self.extra_config,
1346 clone=True,
1347 secure=self.secure,
1348 anonymous=self._anonymous,
1349 useragent=self.useragent)
1350
1351
1352 - def setIdentity (self, username, passwd, _internal=False):
1353 """
1354 Saves the username and password for later use, creating session etc
1355
1356 :param username: User name.
1357 :type username: String
1358 :param passwd: Password.
1359 :type passwd: String
1360 :param _internal: If False, set _anonymous = False
1361 :type _internal: Booelan
1362 """
1363 self._ic_props = {omero.constants.USERNAME: username,
1364 omero.constants.PASSWORD: passwd}
1365 if not _internal:
1366 self._anonymous = False
1367
1368 - def suConn (self, username, group=None, ttl=60000):
1369 """
1370 If current user isAdmin, return new connection owned by 'username'
1371
1372 :param username: Username for new connection
1373 :type username: String
1374 :param group: If specified, try to log in to this group
1375 :type group: String
1376 :param ttl: Timeout for new session
1377 :type ttl: Int
1378 :return: Clone of this connection, with username's new Session
1379 :rtype: L{_BlitzGateway} or None if not admin or username unknown
1380 """
1381 if self.isAdmin():
1382 if group is None:
1383 e = self.getObject("Experimenter", attributes={'omeName': username})
1384 if e is None:
1385 return
1386 group = e._obj._groupExperimenterMapSeq[0].parent.name.val
1387 p = omero.sys.Principal()
1388 p.name = username
1389 p.group = group
1390 p.eventType = "User"
1391 newConnId = self.getSessionService().createSessionWithTimeout(p, ttl)
1392 newConn = self.clone()
1393 newConn.connect(sUuid=newConnId.getUuid().val)
1394 return newConn
1395
1397 """
1398 Keeps service alive.
1399 Returns True if connected. If connection was lost, reconnecting.
1400 If connection failed, returns False and error is logged.
1401
1402 :return: True if connection alive.
1403 :rtype: Boolean
1404 """
1405
1406 try:
1407 if self.c.sf is None:
1408 logger.debug('... c.sf is None, reconnecting')
1409 return self.connect()
1410 return self.c.sf.keepAlive(self._proxies['admin']._getObj())
1411 except Ice.ObjectNotExistException:
1412
1413 logger.debug(traceback.format_exc())
1414 logger.debug("... reset, not reconnecting")
1415 return False
1416 except Ice.ConnectionLostException:
1417
1418 logger.debug(traceback.format_exc())
1419 logger.debug("... lost, reconnecting")
1420
1421 return False
1422 except Ice.ConnectionRefusedException:
1423
1424 logger.debug(traceback.format_exc())
1425 logger.debug("... refused, not reconnecting")
1426 return False
1427 except omero.SessionTimeoutException:
1428
1429 logger.debug(traceback.format_exc())
1430 logger.debug("... reset, not reconnecting")
1431 return False
1432 except omero.RemovedSessionException:
1433
1434 logger.debug(traceback.format_exc())
1435 logger.debug("... session has left the building, not reconnecting")
1436 return False
1437 except Ice.UnknownException, x:
1438
1439 logger.debug(traceback.format_exc())
1440 logger.debug('Ice.UnknownException: %s' % str(x))
1441 logger.debug("... ice says something bad happened, not reconnecting")
1442 return False
1443 except:
1444
1445 logger.debug(traceback.format_exc())
1446 logger.debug("... error not reconnecting")
1447 return False
1448
1449 - def seppuku (self, softclose=False):
1450 """
1451 Terminates connection with killSession(). If softclose is False, the session is really
1452 terminate disregarding its connection refcount.
1453
1454 :param softclose: Boolean
1455 """
1456 self._connected = False
1457 oldC = self.c
1458 if oldC is not None:
1459 try:
1460 if softclose:
1461 try:
1462 r = oldC.sf.getSessionService().getReferenceCount(self._sessionUuid)
1463 oldC.closeSession()
1464 if r < 2:
1465 self._session_cb and self._session_cb.close(self)
1466 except Ice.OperationNotExistException:
1467 oldC.closeSession()
1468 else:
1469 self._closeSession()
1470 finally:
1471 oldC.__del__()
1472 oldC = None
1473 self.c = None
1474
1475 self._proxies = NoProxies()
1476 logger.info("closed connecion (uuid=%s)" % str(self._sessionUuid))
1477
1478
1479
1480
1482 """
1483 Creates proxies to the server services. Called on connection or security switch.
1484 Doesn't actually create any services themselves. Created if/when needed.
1485 If proxies have been created already, they are resynced and reused.
1486 """
1487
1488 if not isinstance(self._proxies, NoProxies):
1489 logger.debug("## Reusing proxies")
1490 for k, p in self._proxies.items():
1491 p._resyncConn(self)
1492 else:
1493 logger.debug("## Creating proxies")
1494 self._proxies = {}
1495 self._proxies['admin'] = ProxyObjectWrapper(self, 'getAdminService')
1496 self._proxies['config'] = ProxyObjectWrapper(self, 'getConfigService')
1497 self._proxies['container'] = ProxyObjectWrapper(self, 'getContainerService')
1498 self._proxies['delete'] = ProxyObjectWrapper(self, 'getDeleteService')
1499 self._proxies['ldap'] = ProxyObjectWrapper(self, 'getLdapService')
1500 self._proxies['metadata'] = ProxyObjectWrapper(self, 'getMetadataService')
1501 self._proxies['query'] = ProxyObjectWrapper(self, 'getQueryService')
1502 self._proxies['pixel'] = ProxyObjectWrapper(self, 'getPixelsService')
1503 self._proxies['projection'] = ProxyObjectWrapper(self, 'getProjectionService')
1504 self._proxies['rawpixels'] = ProxyObjectWrapper(self, 'createRawPixelsStore')
1505 self._proxies['rendering'] = ProxyObjectWrapper(self, 'createRenderingEngine')
1506 self._proxies['rendsettings'] = ProxyObjectWrapper(self, 'getRenderingSettingsService')
1507 self._proxies['thumbs'] = ProxyObjectWrapper(self, 'createThumbnailStore')
1508 self._proxies['rawfile'] = ProxyObjectWrapper(self, 'createRawFileStore')
1509 self._proxies['repository'] = ProxyObjectWrapper(self, 'getRepositoryInfoService')
1510 self._proxies['roi'] = ProxyObjectWrapper(self, 'getRoiService')
1511 self._proxies['script'] = ProxyObjectWrapper(self, 'getScriptService')
1512 self._proxies['search'] = ProxyObjectWrapper(self, 'createSearchService')
1513 self._proxies['session'] = ProxyObjectWrapper(self, 'getSessionService')
1514 self._proxies['share'] = ProxyObjectWrapper(self, 'getShareService')
1515 self._proxies['sharedres'] = ProxyObjectWrapper(self, 'sharedResources')
1516 self._proxies['timeline'] = ProxyObjectWrapper(self, 'getTimelineService')
1517 self._proxies['types'] = ProxyObjectWrapper(self, 'getTypesService')
1518 self._proxies['update'] = ProxyObjectWrapper(self, 'getUpdateService')
1519 self._userid = None
1520 self._user = None
1521 self._ctx = None
1522
1523 if self._session_cb:
1524 if self._was_join:
1525 self._session_cb.join(self)
1526 else:
1527 self._session_cb.create(self)
1528
1530 """
1531 Switches between SSL and insecure (faster) connections to Blitz.
1532 The gateway must already be connected.
1533
1534 :param secure: If False, use an insecure connection
1535 :type secure: Boolean
1536 """
1537 if hasattr(self.c, 'createClient') and (secure ^ self.c.isSecure()):
1538 oldC = self.c
1539 self.c = oldC.createClient(secure=secure)
1540 oldC.__del__()
1541 self._createProxies()
1542 self.secure = secure
1543
1545 """ Returns 'True' if the underlying omero.clients.BaseClient is connected using SSL """
1546 return hasattr(self.c, 'isSecure') and self.c.isSecure() or False
1547
1550
1570
1572 """
1573 Close session.
1574 """
1575 self._session_cb and self._session_cb.close(self)
1576 try:
1577 if self.c:
1578 try:
1579 self.c.getSession()
1580 except omero.ClientError:
1581 return
1582 self.c.killSession()
1583 except Glacier2.SessionNotExistException:
1584 pass
1585 except:
1586 logger.warn(traceback.format_exc())
1587
1589 """
1590 Creates new omero.client object using self.host or self.ice_config (if host is None)
1591 Also tries to setAgent for the client
1592 """
1593 logger.debug(self.host)
1594 logger.debug(self.port)
1595 logger.debug(self.ice_config)
1596
1597 if self.c is not None:
1598 self.c.__del__()
1599 self.c = None
1600
1601 if self.host is not None:
1602 if self.port is not None:
1603 self.c = omero.client(host=str(self.host), port=int(self.port), args=['--Ice.Config='+','.join(self.ice_config)])
1604 else:
1605 self.c = omero.client(host=str(self.host), args=['--Ice.Config='+','.join(self.ice_config)])
1606 else:
1607 self.c = omero.client(args=['--Ice.Config='+','.join(self.ice_config)])
1608
1609 if hasattr(self.c, "setAgent"):
1610 if self.useragent is not None:
1611 self.c.setAgent(self.useragent)
1612 else:
1613 self.c.setAgent("OMERO.py.gateway")
1614
1616 """
1617 Creates or retrieves connection for the given sessionUuid.
1618 Returns True if connected.
1619
1620 :param sUuid: omero_model_SessionI
1621 :return: Boolean
1622 """
1623
1624 logger.debug("Connect attempt, sUuid=%s, group=%s, self.sUuid=%s" % (str(sUuid), str(self.group), self._sessionUuid))
1625 if not self.c:
1626 self._connected = False
1627 logger.debug("Ooops. no self._c")
1628 return False
1629 try:
1630 if self._sessionUuid is None and sUuid:
1631 self._sessionUuid = sUuid
1632 if self._sessionUuid is not None:
1633 try:
1634 logger.debug('connected? %s' % str(self._connected))
1635 if self._connected:
1636 self._connected = False
1637 logger.debug("was connected, creating new omero.client")
1638 self._resetOmeroClient()
1639 s = self.c.joinSession(self._sessionUuid)
1640 s.detachOnDestroy()
1641 self.SERVICE_OPTS = self.createServiceOptsDict()
1642 logger.debug('Joined Session OK with Uuid: %s' % (self._sessionUuid,))
1643 self._was_join = True
1644 except Ice.SyscallException:
1645 raise
1646 except Exception, x:
1647 logger.debug("Error: " + str(x))
1648 self._sessionUuid = None
1649 if sUuid:
1650 return False
1651 if self._sessionUuid is None:
1652 if sUuid:
1653 logger.debug("Uncaptured sUuid failure!")
1654 if self._connected:
1655 self._connected = False
1656 try:
1657 logger.debug("Closing previous connection...creating new client")
1658
1659
1660 self._closeSession()
1661 self._resetOmeroClient()
1662
1663 except Glacier2.SessionNotExistException:
1664 pass
1665 for key, value in self._ic_props.items():
1666 if isinstance(value, unicode):
1667 value = value.encode('utf_8')
1668 self.c.ic.getProperties().setProperty(key, value)
1669 if self._anonymous:
1670 self.c.ic.getImplicitContext().put(omero.constants.EVENT, 'Internal')
1671 if self.group is not None:
1672 self.c.ic.getImplicitContext().put(omero.constants.GROUP, self.group)
1673 try:
1674 logger.debug("Creating Session...")
1675 self._createSession()
1676 logger.debug("Session created")
1677 except omero.SecurityViolation:
1678 if self.group is not None:
1679
1680 logger.debug("## User not in '%s' group" % self.group)
1681 self.group = None
1682 self._closeSession()
1683 self._sessionUuid = None
1684 self._connected=True
1685 return self.connect()
1686 else:
1687 logger.debug("BlitzGateway.connect().createSession(): " + traceback.format_exc())
1688 logger.info('first create session threw SecurityViolation, retry (but only once)')
1689
1690 try:
1691 self._createSession()
1692 except omero.SecurityViolation:
1693 if self.group is not None:
1694
1695 logger.debug("## User not in '%s' group" % self.group)
1696 self.group = None
1697 self._connected=True
1698 return self.connect()
1699 else:
1700 raise
1701 except Ice.SyscallException:
1702 raise
1703 except:
1704 logger.info("Failed to create session.")
1705 logger.debug("BlitzGateway.connect().createSession(): " + traceback.format_exc())
1706
1707 self._createSession()
1708
1709 self._last_error = None
1710 self._createProxies()
1711 self._connected = True
1712 logger.info('created connection (uuid=%s)' % str(self._sessionUuid))
1713 except Ice.SyscallException:
1714 logger.debug('This one is a SyscallException', exc_info=True)
1715 raise
1716 except Ice.LocalException, x:
1717 logger.debug("connect(): " + traceback.format_exc())
1718 self._last_error = x
1719 return False
1720 except Exception, x:
1721 logger.debug("connect(): " + traceback.format_exc())
1722 self._last_error = x
1723 return False
1724 logger.debug(".. connected!")
1725 return True
1726
1728 """
1729 Returns error if thrown by _BlitzGateway.connect connect.
1730
1731 :return: String
1732 """
1733
1734 return self._last_error
1735
1737 """
1738 Returns last status of connection.
1739
1740 :return: Boolean
1741 """
1742
1743 return self._connected
1744
1745
1746
1747
1748 - def getEventContext (self):
1749 """
1750 Returns omero_System_ice.EventContext.
1751 It containes::
1752 shareId, sessionId, sessionUuid, userId, userName,
1753 groupId, groupName, isAdmin, isReadOnly,
1754 eventId, eventType, eventType,
1755 memberOfGroups, leaderOfGroups
1756 Also saves context to self._ctx
1757
1758 :return: Event Context from admin service.
1759 :rtype: L{omero.sys.EventContext}
1760 """
1761 if self._ctx is None:
1762 self._ctx = self._proxies['admin'].getEventContext()
1763 return self._ctx
1764
1766 """
1767 Returns current experimenter id
1768
1769 :return: Current Experimenter id
1770 :rtype: long
1771 """
1772 if self._userid is None:
1773 self._userid = self.getEventContext().userId
1774 return self._userid
1775
1777 """
1778 Sets current experimenter id
1779 """
1780 self._userid = uid
1781 self._user = None
1782
1784 """
1785 Returns current Experimenter.
1786
1787 :return: Current Experimenter
1788 :rtype: L{ExperimenterWrapper}
1789 """
1790 if self._user is None:
1791 uid = self.getUserId()
1792 if uid is not None:
1793 self._user = self.getObject("Experimenter", self._userid) or None
1794 return self._user
1795
1797 """
1798 Returns Experimenters with administration privileges.
1799
1800 :return: Current Experimenter
1801 :return: Generator of L{BlitzObjectWrapper} subclasses
1802 """
1803 sysGroup = self.getObject("ExperimenterGroup", self.getAdminService().getSecurityRoles().systemGroupId)
1804 for gem in sysGroup.copyGroupExperimenterMap():
1805 yield ExperimenterWrapper(self, gem.child)
1806
1808 """
1809 Returns current omero_model_ExperimenterGroupI.
1810
1811 :return: omero.model.ExperimenterGroupI
1812 """
1813 admin_service = self.getAdminService()
1814 group = admin_service.getGroup(self.getEventContext().groupId)
1815 return ExperimenterGroupWrapper(self, group)
1816
1818 """
1819 Checks if a user has administration privileges.
1820
1821 :return: Boolean
1822 """
1823
1824 return self.getEventContext().isAdmin
1825
1827 """
1828 Is the current group (or a specified group) led by the current user?
1829
1830 :return: True if user leads the current group
1831 :rtype: Boolean
1832 """
1833 if gid is None:
1834 gid = self.getEventContext().groupId
1835 if not isinstance(gid, LongType) or not isinstance(gid, IntType):
1836 gid = long(gid)
1837 if gid in self.getEventContext().leaderOfGroups:
1838 return True
1839 return False
1840
1842 """
1843 Checks if a user is in system group, i.e. can have administration privileges.
1844
1845 :return: Boolean
1846 """
1847 return 0 in self.getEventContext().memberOfGroups
1848
1859
1861 """
1862 Returns isUserWrite() from the object's permissions
1863
1864 :param obj: Given object
1865 :return: True if the objects's permissions allow owner to write
1866 """
1867 return obj.getDetails().getPermissions().isUserWrite()
1868
1870 """
1871 Returns the existing session, or creates a new one if needed
1872
1873 :return: The session from session service
1874 :rtype: L{omero.model.session}
1875 """
1876 if self._session is None:
1877 ss = self.c.sf.getSessionService()
1878 self._session = ss.getSession(self._sessionUuid)
1879 return self._session
1880
1881
1882
1883
1884
1885
1886
1888 """
1889 Looks up the group by name, then delegates to L{setGroupForSession}, returning the result
1890
1891 :param group: Group name
1892 :type group: String
1893 :return: True if group set successfully
1894 :rtype: Boolean
1895 """
1896 a = self.getAdminService()
1897 g = a.lookupGroup(group)
1898 return self.setGroupForSession(g.getId().val)
1899
1901 """
1902 Sets the security context of this connection to the specified group
1903
1904 :param groupid: The ID of the group to switch to
1905 :type groupid: Long
1906 :rtype: Boolean
1907 :return: True if the group was switched successfully
1908 """
1909 if self.getEventContext().groupId == groupid:
1910 return None
1911 if groupid not in self._ctx.memberOfGroups and 0 not in self._ctx.memberOfGroups:
1912 return False
1913 self._lastGroupId = self._ctx.groupId
1914 self._ctx = None
1915 if hasattr(self.c.sf, 'setSecurityContext'):
1916
1917 for s in self.c.getStatefulServices():
1918 s.close()
1919 self.c.sf.setSecurityContext(omero.model.ExperimenterGroupI(groupid, False))
1920 else:
1921 self.getSession()
1922 self._session.getDetails().setGroup(omero.model.ExperimenterGroupI(groupid, False))
1923 self._session.setTimeToIdle(None)
1924 self.getSessionService().updateSession(self._session)
1925 return True
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1943 """ Switches the group to the previous group """
1944 if self._lastGroupId is not None:
1945 self.setGroupForSession(self._lastGroupId)
1946 self._lastGroupId = None
1947
1948
1949
1950
1952 """
1953 Gets reference to the admin service from ProxyObjectWrapper.
1954
1955 :return: omero.gateway.ProxyObjectWrapper
1956 """
1957
1958 return self._proxies['admin']
1959
1961 """
1962 Gets reference to the query service from ProxyObjectWrapper.
1963
1964 :return: omero.gateway.ProxyObjectWrapper
1965 """
1966 return self._proxies['query']
1967
1969 """
1970 Gets reference to the container service from ProxyObjectWrapper.
1971
1972 :return: omero.gateway.ProxyObjectWrapper
1973 """
1974
1975 return self._proxies['container']
1976
1978 """
1979 Gets reference to the pixels service from ProxyObjectWrapper.
1980
1981 :return: omero.gateway.ProxyObjectWrapper
1982 """
1983
1984 return self._proxies['pixel']
1985
1994
1996 """
1997 Gets ROI service.
1998
1999 :return: omero.gateway.ProxyObjectWrapper
2000 """
2001
2002 return self._proxies['roi']
2003
2005 """
2006 Gets script service.
2007
2008 :return: omero.gateway.ProxyObjectWrapper
2009 """
2010
2011 return self._proxies['script']
2012
2014 """
2015 Creates a new raw file store.
2016 This service is special in that it does not get cached inside BlitzGateway so every call to this function
2017 returns a new object, avoiding unexpected inherited states.
2018
2019 :return: omero.gateway.ProxyObjectWrapper
2020 """
2021
2022 return self._proxies['rawfile']
2023
2025 """
2026 Gets reference to the repository info service from ProxyObjectWrapper.
2027
2028 :return: omero.gateway.ProxyObjectWrapper
2029 """
2030
2031 return self._proxies['repository']
2032
2034 """
2035 Gets reference to the share service from ProxyObjectWrapper.
2036
2037 :return: omero.gateway.ProxyObjectWrapper
2038 """
2039
2040 return self._proxies['share']
2041
2043 """
2044 Gets reference to the sharedresources from ProxyObjectWrapper.
2045
2046 :return: omero.gateway.ProxyObjectWrapper
2047 """
2048
2049 return self._proxies['sharedres']
2050
2052 """
2053 Gets reference to the timeline service from ProxyObjectWrapper.
2054
2055 :return: omero.gateway.ProxyObjectWrapper
2056 """
2057
2058 return self._proxies['timeline']
2059
2061 """
2062 Gets reference to the types service from ProxyObjectWrapper.
2063
2064 :return: omero.gateway.ProxyObjectWrapper
2065 """
2066
2067 return self._proxies['types']
2068
2070 """
2071 Gets reference to the config service from ProxyObjectWrapper.
2072
2073 :return: omero.gateway.ProxyObjectWrapper
2074 """
2075
2076 return self._proxies['config']
2077
2079 """
2080 Creates a new rendering engine.
2081 This service is special in that it does not get cached inside BlitzGateway so every call to this function
2082 returns a new object, avoiding unexpected inherited states.
2083
2084 :return: omero.gateway.ProxyObjectWrapper
2085 """
2086
2087 rv = self._proxies['rendering']
2088 if rv._tainted:
2089 rv = self._proxies['rendering'] = rv.clone()
2090 rv.taint()
2091 return rv
2092
2094 """
2095 Gets reference to the rendering settings service from ProxyObjectWrapper.
2096
2097 :return: omero.gateway.ProxyObjectWrapper
2098 """
2099
2100 return self._proxies['rendsettings']
2101
2103 """
2104 Creates a new raw pixels store.
2105 This service is special in that it does not get cached inside BlitzGateway so every call to this function
2106 returns a new object, avoiding unexpected inherited states.
2107
2108 :return: omero.gateway.ProxyObjectWrapper
2109 """
2110
2111 return self._proxies['rawpixels']
2112
2114 """
2115 Gets a reference to the thumbnail store on this connection object or creates a new one
2116 if none exists.
2117
2118 :rtype: omero.gateway.ProxyObjectWrapper
2119 :return: The proxy wrapper of the thumbnail store
2120 """
2121
2122 return self._proxies['thumbs']
2123
2125 """
2126 Gets a reference to the searching service on this connection object or creates a new one
2127 if none exists.
2128
2129 :return: omero.gateway.ProxyObjectWrapper
2130 """
2131 return self._proxies['search']
2132
2134 """
2135 Gets reference to the update service from ProxyObjectWrapper.
2136
2137 :return: omero.gateway.ProxyObjectWrapper
2138 """
2139 return self._proxies['update']
2140
2142 """
2143 Gets reference to the delete service from ProxyObjectWrapper.
2144
2145 :return: omero.gateway.ProxyObjectWrapper
2146 """
2147 return self._proxies['delete']
2148
2150 """
2151 Gets reference to the session service from ProxyObjectWrapper.
2152
2153 :return: omero.gateway.ProxyObjectWrapper
2154 """
2155 return self._proxies['session']
2156
2158 """
2159 New instance of non cached Exporter, wrapped in ProxyObjectWrapper.
2160
2161 :return: omero.gateway.ProxyObjectWrapper
2162 """
2163 return ProxyObjectWrapper(self, 'createExporter')
2164
2165
2166
2167
2169 """
2170 List every Project controlled by the security system.
2171
2172 :param eid: Filters Projects by owner ID
2173 :rtype: L{ProjectWrapper} list
2174 """
2175
2176 params = omero.sys.Parameters()
2177 params.theFilter = omero.sys.Filter()
2178
2179
2180
2181 if eid is not None:
2182 params.theFilter.ownerId = rlong(eid)
2183
2184 return self.getObjects("Project", params=params)
2185
2187 """
2188 List every Screens controlled by the security system.
2189
2190 :param eid: Filters Screens by owner ID
2191 :rtype: L{ProjectWrapper} list
2192 """
2193
2194 params = omero.sys.Parameters()
2195 params.theFilter = omero.sys.Filter()
2196
2197
2198
2199 if eid is not None:
2200 params.theFilter.ownerId = rlong(eid)
2201
2202 return self.getObjects("Screen", params=params)
2203
2204 - def listOrphans (self, obj_type, eid=None, params=None):
2205 """
2206 List orphaned Datasets, Images, Plates controlled by the security system,
2207 Optionally filter by experimenter 'eid'
2208
2209 :param obj_type: 'Dataset', 'Image', 'Plate'
2210 :param eid: experimenter id
2211 :type eid: Long
2212 :param params: omero.sys.ParametersI, can be used for pagination, filtering etc.
2213 :param attributes: Map of key-value pairs to filter results by. Key must be attribute of obj_type. E.g. 'name', 'ns'
2214 :return: Generator yielding Datasets
2215 :rtype: L{DatasetWrapper} generator
2216
2217 """
2218
2219 links = {'Dataset':('ProjectDatasetLink', DatasetWrapper),
2220 'Image':('DatasetImageLink', ImageWrapper),
2221 'Plate':('ScreenPlateLink', PlateWrapper)}
2222
2223 if params is None:
2224 params = omero.sys.ParametersI()
2225
2226 if eid is not None:
2227 params.exp(eid)
2228
2229 query, params, wrapper = self.buildQuery(obj_type, params=params)
2230 query += "where" not in query and " where " or " and "
2231 query += " not exists (select obl from %s as obl where " \
2232 "obl.child=obj.id) " % ( links[obj_type][0])
2233
2234 if obj_type == 'Image':
2235 query += " and not exists ( select ws from WellSample as ws "\
2236 "where ws.image=obj.id "
2237 if eid is not None:
2238 query += " and ws.details.owner.id=:eid "
2239 query += ")"
2240
2241 result = self.getQueryService().findAllByQuery(query, params, self.SERVICE_OPTS)
2242 for r in result:
2243 yield wrapper(self, r)
2244
2245
2246
2247
2248
2250 """
2251 Look up all experimenters and related groups.
2252 Groups are also loaded
2253
2254 :return: All experimenters
2255 :rtype: L{ExperimenterWrapper} generator
2256 """
2257
2258 admin_serv = self.getAdminService()
2259 for exp in admin_serv.lookupGroups():
2260 yield ExperimenterGroupWrapper(self, exp)
2261
2263 """
2264 Retrieve the default group for the given user id.
2265
2266 :param eid: Experimenter ID
2267 :type eid: Long
2268 :return: The default group for user
2269 :rtype: L{ExperimenterGroupWrapper}
2270 """
2271
2272 admin_serv = self.getAdminService()
2273 dgr = admin_serv.getDefaultGroup(long(eid))
2274 return ExperimenterGroupWrapper(self, dgr)
2275
2277 """
2278 Fetch all groups of which the given user is a member.
2279 The returned groups will have all fields filled in and all collections unloaded.
2280
2281 :param eid: Experimenter ID
2282 :type eid: Long
2283 :return: Generator of groups for user
2284 :rtype: L{ExperimenterGroupWrapper} generator
2285 """
2286
2287 admin_serv = self.getAdminService()
2288 for gr in admin_serv.containedGroups(long(eid)):
2289 yield ExperimenterGroupWrapper(self, gr)
2290
2292 """
2293 Look up Groups where current user is a leader of.
2294
2295 :return: Groups that current user leads
2296 :rtype: L{ExperimenterGroupWrapper} generator
2297 """
2298
2299 q = self.getQueryService()
2300 p = omero.sys.Parameters()
2301 p.map = {}
2302 p.map["ids"] = rlist([rlong(a) for a in self.getEventContext().leaderOfGroups])
2303 sql = "select e from ExperimenterGroup as e where e.id in (:ids)"
2304 for e in q.findAllByQuery(sql, p,self.SERVICE_OPTS):
2305 yield ExperimenterGroupWrapper(self, e)
2306
2308 """
2309 Look up Groups where current user is a member of (except "user" group).
2310
2311 :return: Current users groups
2312 :rtype: L{ExperimenterGroupWrapper} generator
2313 """
2314
2315 q = self.getQueryService()
2316 p = omero.sys.Parameters()
2317 p.map = {}
2318 p.map["ids"] = rlist([rlong(a) for a in self.getEventContext().memberOfGroups])
2319 sql = "select e from ExperimenterGroup as e where e.id in (:ids)"
2320 for e in q.findAllByQuery(sql, p,self.SERVICE_OPTS):
2321 if e.name.val == "user":
2322 pass
2323 else:
2324 yield ExperimenterGroupWrapper(self, e)
2325
2326
2327 - def createGroup(self, name, owner_Ids=None, member_Ids=None, perms=None, description=None):
2328 """
2329 Creates a new ExperimenterGroup. Must have Admin permissions to call this.
2330
2331 :param name: New group name
2332 :param owner_Ids: Option to add existing Experimenters as group owners
2333 :param member_Ids: Option to add existing Experimenters as group members
2334 :param perms: New group permissions. E.g. 'rw----' (private), 'rwr---'(read-only), 'rwrw--'
2335 :param description: Group description
2336 """
2337 admin_serv = self.getAdminService()
2338
2339 group = omero.model.ExperimenterGroupI()
2340 group.name = rstring(str(name))
2341 group.description = (description!="" and description is not None) and rstring(str(description)) or None
2342 if perms is not None:
2343 group.details.permissions = omero.model.PermissionsI(perms)
2344
2345 gr_id = admin_serv.createGroup(group)
2346
2347 if owner_Ids is not None:
2348 group_owners = [owner._obj for owner in self.getObjects("Experimenter", owner_Ids)]
2349 admin_serv.addGroupOwners(omero.model.ExperimenterGroupI(gr_id, False), group_owners)
2350
2351 if member_Ids is not None:
2352 group_members = [member._obj for member in self.getObjects("Experimenter", member_Ids)]
2353 for user in group_members:
2354 admin_serv.addGroups(user, [omero.model.ExperimenterGroupI(gr_id, False)])
2355
2356 return gr_id
2357
2358
2359
2361 """
2362 Return a generator for all Experimenters whose omeName starts with 'start'.
2363 Experimenters ordered by omeName.
2364
2365 :param start: omeName must start with these letters
2366 :type start: String
2367 :return: Generator of experimenters
2368 :rtype: L{ExperimenterWrapper} generator
2369 """
2370
2371 if isinstance(start, UnicodeType):
2372 start = start.encode('utf8')
2373 params = omero.sys.Parameters()
2374 params.map = {'start': rstring('%s%%' % start.lower())}
2375 q = self.getQueryService()
2376 rv = q.findAllByQuery("from Experimenter e where lower(e.omeName) like :start", params,self.SERVICE_OPTS)
2377 rv.sort(lambda x,y: cmp(x.omeName.val,y.omeName.val))
2378 for e in rv:
2379 yield ExperimenterWrapper(self, e)
2380
2382 """
2383 Fetch all users contained in this group.
2384 The returned users will have all fields filled in and all collections unloaded.
2385
2386 :param gid: Group ID
2387 :type gid: Long
2388 :return: Generator of experimenters
2389 :rtype: L{ExperimenterWrapper} generator
2390 """
2391
2392 admin_serv = self.getAdminService()
2393 for exp in admin_serv.containedExperimenters(long(gid)):
2394 yield ExperimenterWrapper(self, exp)
2395
2397 """
2398 Look up users who are a member of the current user active group.
2399 Returns None if the group is private and isn't lead by the current user
2400
2401 :return: Generator of Experimenters or None
2402 :rtype: L{ExperimenterWrapper} generator
2403 """
2404
2405 default = self.getObject("ExperimenterGroup", self.getEventContext().groupId)
2406 if not default.isPrivate() or self.isLeader():
2407 for d in default.copyGroupExperimenterMap():
2408 if d is None:
2409 continue
2410 if d.child.id.val != self.getUserId():
2411 yield ExperimenterWrapper(self, d.child)
2412
2414 """
2415 Returns lists of 'leaders' and 'members' of the specified group (default is current group)
2416 as a dict with those keys.
2417
2418 :return: {'leaders': list L{ExperimenterWrapper}, 'colleagues': list L{ExperimenterWrapper}}
2419 :rtype: dict
2420 """
2421
2422 if gid is None:
2423 gid = self.getEventContext().groupId
2424 userId = None
2425 if exclude_self:
2426 userId = self.getUserId()
2427 colleagues = []
2428 leaders = []
2429 default = self.getObject("ExperimenterGroup", gid)
2430 if not default.isPrivate() or self.isLeader(gid) or self.isAdmin():
2431 for d in default.copyGroupExperimenterMap():
2432 if d is None or d.child.id.val == userId:
2433 continue
2434 if d.owner.val:
2435 leaders.append(ExperimenterWrapper(self, d.child))
2436 else:
2437 colleagues.append(ExperimenterWrapper(self, d.child))
2438 else:
2439 if self.isLeader():
2440 leaders = [self.getUser()]
2441 else:
2442 colleagues = [self.getUser()]
2443 return {"leaders": leaders, "colleagues": colleagues}
2444
2446 """
2447 Look up users who are members of groups lead by the current user.
2448
2449 :return: Members of groups lead by current user
2450 :rtype: L{ExperimenterWrapper} generator
2451 """
2452
2453 q = self.getQueryService()
2454 p = omero.sys.Parameters()
2455 p.map = {}
2456 p.map["gids"] = rlist([rlong(a) for a in set(self.getEventContext().leaderOfGroups)])
2457 sql = "select e from Experimenter as e where " \
2458 "exists ( select gem from GroupExperimenterMap as gem where gem.child = e.id " \
2459 "and gem.parent.id in (:gids)) order by e.omeName"
2460 for e in q.findAllByQuery(sql, p,self.SERVICE_OPTS):
2461 if e.id.val != self.getUserId():
2462 yield ExperimenterWrapper(self, e)
2463
2465 """
2466 Looks up owned groups for the logged user.
2467
2468 :return: Groups owned by current user
2469 :rtype: L{ExperimenterGroupWrapper} generator
2470 """
2471
2472 exp = self.getUser()
2473 for gem in exp.copyGroupExperimenterMap():
2474 if gem is None:
2475 continue
2476 if gem.owner.val:
2477 yield ExperimenterGroupWrapper(self, gem.parent)
2478
2480 """
2481 Returns the free or available space on this file system
2482 including nested subdirectories.
2483
2484 :return: Free space in bytes
2485 :rtype: Int
2486 """
2487
2488 rep_serv = self.getRepositoryInfoService()
2489 return rep_serv.getFreeSpaceInKilobytes() * 1024
2490
2492 """
2493 Gets summary of Original Files that are part of the FS Fileset linked to images
2494 Returns a dict of files 'count' and sum of 'size'
2495
2496 :param imageIds: Image IDs list
2497 :return: Dict of files 'count' and 'size'
2498 """
2499
2500 params = omero.sys.ParametersI()
2501 params.addIds(imageIds)
2502 query = "select distinct(fse) from FilesetEntry as fse "\
2503 "left outer join fse.fileset as fs "\
2504 "left outer join fetch fse.originalFile as f "\
2505 "left outer join fs.images as image where image.id in (:ids)"
2506 queryService = self.getQueryService()
2507 fsinfo = queryService.findAllByQuery(query, params, self.SERVICE_OPTS)
2508 fsCount = len(fsinfo)
2509 fsSize = sum([f.originalFile.getSize().val for f in fsinfo])
2510 filesetFileInfo = {'count': fsCount, 'size': fsSize}
2511 return filesetFileInfo
2512
2514 """
2515 Gets summary of Original Files that are archived from OMERO 4 imports
2516 Returns a dict of files 'count' and sum of 'size'
2517
2518 :param imageIds: Image IDs list
2519 :return: Dict of files 'count' and 'size'
2520 """
2521
2522 params = omero.sys.ParametersI()
2523 params.addIds(imageIds)
2524 query = "select distinct(link) from PixelsOriginalFileMap as link "\
2525 "left outer join fetch link.parent as f "\
2526 "left outer join link.child as pixels "\
2527 "where pixels.image.id in (:ids)"
2528 queryService = self.getQueryService()
2529 fsinfo = queryService.findAllByQuery(query, params, self.SERVICE_OPTS)
2530 fsCount = len(fsinfo)
2531 fsSize = sum([f.parent.getSize().val for f in fsinfo])
2532 filesetFileInfo = {'count': fsCount, 'size': fsSize}
2533 return filesetFileInfo
2534
2535
2536
2537
2538
2540 """
2541 List images based on their creation times.
2542 If both tfrom and tto are None, grab the most recent batch.
2543
2544 :param tfrom: milliseconds since the epoch for start date
2545 :param tto: milliseconds since the epoch for end date
2546 :param limit: maximum number of results
2547 :param only_owned: Only owned by the logged user. Boolean.
2548 :return: Generator yielding _ImageWrapper
2549 :rtype: L{ImageWrapper} generator
2550 """
2551
2552 tm = self.getTimelineService()
2553 p = omero.sys.Parameters()
2554 f = omero.sys.Filter()
2555 if only_owned:
2556 f.ownerId = rlong(self.getEventContext().userId)
2557 f.groupId = rlong(self.getEventContext().groupId)
2558 else:
2559 f.ownerId = rlong(-1)
2560 f.groupId = None
2561 f.limit = rint(limit)
2562 p.theFilter = f
2563 if tfrom is None and tto is None:
2564 for e in tm.getMostRecentObjects(['Image'], p, False)["Image"]:
2565 yield ImageWrapper(self, e)
2566 else:
2567 if tfrom is None:
2568 tfrom = 0
2569 if tto is None:
2570 tto = time.time() * 1000
2571 for e in tm.getByPeriod(['Image'], rtime(long(tfrom)), rtime(long(tto)), p, False)['Image']:
2572 yield ImageWrapper(self, e)
2573
2574
2575
2576
2577
2578 - def getObject (self, obj_type, oid=None, params=None, attributes=None):
2579 """
2580 Retrieve single Object by type E.g. "Image" or None if not found.
2581 If more than one object found, raises ome.conditions.ApiUsageException
2582 See L{getObjects} for more info.
2583
2584 :param obj_type: Object type. E.g. "Project" see above
2585 :type obj_type: String
2586 :param ids: object IDs
2587 :type ids: List of Long
2588 :param params: omero.sys.Parameters, can be used for pagination, filtering etc.
2589 :param attributes: Map of key-value pairs to filter results by. Key must be attribute of obj_type. E.g. 'name', 'ns'
2590 :return:
2591 """
2592 oids = (oid!=None) and [oid] or None
2593 query, params, wrapper = self.buildQuery(obj_type, oids, params, attributes)
2594 result = self.getQueryService().findByQuery(query, params, self.SERVICE_OPTS)
2595 if result is not None:
2596 return wrapper(self, result)
2597
2598 - def getObjects (self, obj_type, ids=None, params=None, attributes=None, respect_order=False):
2599 """
2600 Retrieve Objects by type E.g. "Image"
2601 Returns generator of appropriate L{BlitzObjectWrapper} type. E.g. L{ImageWrapper}.
2602 If ids is None, all available objects will be returned. i.e. listObjects()
2603 Filter objects by attributes. E.g. attributes={'name':name}
2604
2605 :param obj_type: Object type. E.g. "Project" see above
2606 :type obj_type: String
2607 :param ids: object IDs
2608 :type ids: List of Long
2609 :param params: omero.sys.Parameters, can be used for pagination, filtering etc.
2610 :param attributes: Map of key-value pairs to filter results by. Key must be attribute of obj_type. E.g. 'name', 'ns'
2611 :param respect_order: Returned items will be ordered according to the order of ids
2612 :return: Generator of L{BlitzObjectWrapper} subclasses
2613 """
2614 query, params, wrapper = self.buildQuery(obj_type, ids, params, attributes)
2615 result = self.getQueryService().findAllByQuery(query, params, self.SERVICE_OPTS)
2616 if respect_order and ids is not None:
2617 idMap = {}
2618 for r in result:
2619 idMap[r.id.val] = r
2620 ids = unwrap(ids)
2621 result = [idMap.get(i) for i in ids if i in idMap]
2622 for r in result:
2623 yield wrapper(self, r)
2624
2625 - def buildQuery (self, obj_type, ids=None, params=None, attributes=None):
2626 """
2627 Prepares a query for iQuery. Also prepares params and determines appropriate wrapper for result
2628 Returns (query, params, wrapper) which can be used with the appropriate query method.
2629 Used by L{getObjects} and L{getObject} above.
2630
2631 :param obj_type: Object type. E.g. "Project" see above
2632 :type obj_type: String
2633 :param ids: object IDs
2634 :type ids: List of Long
2635 :param params: omero.sys.Parameters, can be used for pagination, filtering etc.
2636 :param attributes: Map of key-value pairs to filter results by. Key must be attribute of obj_type. E.g. 'name', 'ns'
2637 :return: (query, params, wrapper)
2638 """
2639
2640 if isinstance(obj_type, StringTypes):
2641 wrapper = KNOWN_WRAPPERS.get(obj_type.lower(), None)
2642 if wrapper is None:
2643 raise KeyError("obj_type of %s not supported by getOjbects(). E.g. use 'Image' etc" % obj_type)
2644 else:
2645 raise AttributeError("getObjects uses a string to define obj_type, E.g. 'Image' not %r" % obj_type)
2646
2647 if params is None:
2648 params = omero.sys.Parameters()
2649 if params.map is None:
2650 params.map = {}
2651
2652
2653 query = wrapper()._getQueryString()
2654
2655 clauses = []
2656
2657 if ids != None:
2658 clauses.append("obj.id in (:ids)")
2659 params.map["ids"] = rlist([rlong(a) for a in ids])
2660
2661
2662 if params.theFilter and params.theFilter.ownerId and obj_type.lower() not in ["experimentergroup", "experimenter"]:
2663 clauses.append("owner.id = (:eid)")
2664 params.map["eid"] = params.theFilter.ownerId
2665
2666
2667 if attributes != None:
2668 for k,v in attributes.items():
2669 clauses.append('obj.%s=:%s' % (k, k) )
2670 params.map[k] = omero_type(v)
2671
2672 if clauses:
2673 query += " where " + (" and ".join(clauses))
2674
2675 return (query, params, wrapper)
2676
2677
2679 """
2680 Lists FileAnnotations created by users, filtering by namespaces if specified.
2681 If NO namespaces are specified, then 'known' namespaces are excluded by default,
2682 such as original files and companion files etc.
2683 File objects are loaded so E.g. file name is available without lazy loading.
2684
2685 :param eid: Filter results by this owner Id
2686 :param toInclude: Only return annotations with these namespaces. List of strings.
2687 :param toExclude: Don't return annotations with these namespaces. List of strings.
2688 :return: Generator of L{FileAnnotationWrapper}s - with files loaded.
2689 """
2690
2691 params = omero.sys.Parameters()
2692 params.theFilter = omero.sys.Filter()
2693 if eid is not None:
2694 params.theFilter.ownerId = rlong(eid)
2695
2696 if len(toInclude) == 0 and len(toExclude) == 0:
2697 toExclude.append(omero.constants.namespaces.NSCOMPANIONFILE)
2698 toExclude.append(omero.constants.annotation.file.ORIGINALMETADATA)
2699 toExclude.append(omero.constants.namespaces.NSEXPERIMENTERPHOTO)
2700 toExclude.append(omero.constants.analysis.flim.NSFLIM)
2701
2702 anns = self.getMetadataService().loadSpecifiedAnnotations("FileAnnotation", toInclude, toExclude, params, self.SERVICE_OPTS)
2703
2704 for a in anns:
2705 yield(FileAnnotationWrapper(self, a))
2706
2707
2708 - def getAnnotationLinks (self, parent_type, parent_ids=None, ann_ids=None, ns=None, params=None):
2709 """
2710 Retrieve Annotation Links by parent_type E.g. "Image". Not Ordered.
2711 Returns generator of L{AnnotationLinkWrapper}
2712 If parent_ids is None, all available objects will be returned. i.e. listObjects()
2713
2714 :param obj_type: Object type. E.g. "Project" see above
2715 :type obj_type: String
2716 :param ids: object IDs
2717 :type ids: List of Long
2718 :return: Generator yielding wrapped objects.
2719 """
2720
2721 if parent_type.lower() not in KNOWN_WRAPPERS:
2722 wrapper_types = ", ".join(KNOWN_WRAPPERS.keys())
2723 err_msg = "getAnnotationLinks() does not support type: '%s'. Must be one of: %s" % (parent_type, wrapper_types)
2724 raise AttributeError(err_msg)
2725 wrapper = KNOWN_WRAPPERS.get(parent_type.lower(), None)
2726 class_string = wrapper().OMERO_CLASS
2727 if class_string is None and "annotation" in parent_type.lower():
2728 class_string = "Annotation"
2729
2730 query = "select annLink from %sAnnotationLink as annLink join fetch annLink.details.owner as owner " \
2731 "join fetch annLink.details.creationEvent " \
2732 "join fetch annLink.child as ann join fetch ann.details.owner join fetch ann.details.creationEvent "\
2733 "join fetch annLink.parent as parent" % class_string
2734
2735 q = self.getQueryService()
2736 if params is None:
2737 params = omero.sys.Parameters()
2738 if params.map is None:
2739 params.map = {}
2740
2741 clauses = []
2742 if parent_ids:
2743 clauses.append("parent.id in (:pids)")
2744 params.map["pids"] = rlist([rlong(a) for a in parent_ids])
2745
2746 if ann_ids:
2747 clauses.append("ann.id in (:ann_ids)")
2748 params.map["ann_ids"] = rlist([rlong(a) for a in ann_ids])
2749
2750 if ns:
2751 clauses.append("ann.ns in (:ns)")
2752 params.map["ns"] = rstring(ns)
2753
2754 if params.theFilter and params.theFilter.ownerId:
2755 clauses.append("owner.id = (:eid)")
2756 params.map["eid"] = params.theFilter.ownerId
2757
2758 if len(clauses) > 0:
2759 query += " where %s" % (" and ".join(clauses))
2760
2761 result = q.findAllByQuery(query, params,self.SERVICE_OPTS)
2762 for r in result:
2763 yield AnnotationLinkWrapper(self, r)
2764
2765
2767 """
2768 Retrieve all Annotations not linked to the given parents: Projects, Datasets, Images,
2769 Screens, Plates OR Wells etc.
2770
2771 :param parent_type: E.g. 'Dataset', 'Image' etc.
2772 :param parent_ids: IDs of the parent.
2773 :param eid: Optional filter by Annotation owner
2774 :param ns: Filter by annotation namespace
2775 :param anntype: Optional specify 'Text', 'Tag', 'File', 'Long', 'Boolean'
2776 :return: Generator yielding AnnotationWrappers
2777 :rtype: L{AnnotationWrapper} generator
2778 """
2779
2780 if anntype is not None:
2781 if anntype.title() not in ('Text', 'Tag', 'File', 'Long', 'Boolean'):
2782 raise AttributeError('Use annotation type: Text, Tag, File, Long, Boolean')
2783 sql = "select an from %sAnnotation as an " % anntype.title()
2784 else:
2785 sql = "select an from Annotation as an " \
2786
2787 if anntype.title() == "File":
2788 sql += " join fetch an.file "
2789
2790 p = omero.sys.Parameters()
2791 p.map = {}
2792
2793 filterlink = ""
2794 if addedByMe:
2795 userId = self.getUserId()
2796 filterlink = " and link.details.owner.id=:linkOwner"
2797 p.map["linkOwner"] = rlong(userId)
2798
2799 q = self.getQueryService()
2800 wheres = []
2801
2802 if len(parent_ids) == 1:
2803
2804 p.map["oid"] = rlong(parent_ids[0])
2805 wheres.append("not exists ( select link from %sAnnotationLink as link "\
2806 "where link.child=an.id and link.parent.id=:oid%s)" % (parent_type, filterlink))
2807 else:
2808
2809 p.map["oids"] = omero.rtypes.wrap(parent_ids)
2810 query = "select link.child.id, count(link.id) from %sAnnotationLink link where link.parent.id in (:oids)%s group by link.child.id" % (parent_type, filterlink)
2811
2812 usedAnnIds = [e[0].getValue() for e in q.projection(query,p,self.SERVICE_OPTS) if e[1].getValue() == len(parent_ids)]
2813 if len(usedAnnIds) > 0:
2814 p.map["usedAnnIds"] = omero.rtypes.wrap(usedAnnIds)
2815 wheres.append("an.id not in (:usedAnnIds)")
2816
2817 if ns is None:
2818 wheres.append("an.ns is null")
2819 else:
2820 p.map["ns"] = rlist([rstring(n) for n in ns])
2821 wheres.append("(an.ns not in (:ns) or an.ns is null)")
2822 if eid is not None:
2823 wheres.append("an.details.owner.id=:eid")
2824 p.map["eid"] = rlong(eid)
2825
2826 if len(wheres) > 0:
2827 sql += "where " + " and ".join(wheres)
2828
2829 for e in q.findAllByQuery(sql,p,self.SERVICE_OPTS):
2830 yield AnnotationWrapper._wrap(self, e)
2831
2832 - def createImageFromNumpySeq (self, zctPlanes, imageName, sizeZ=1, sizeC=1, sizeT=1, description=None, dataset=None, sourceImageId=None, channelList=None):
2833 """
2834 Creates a new multi-dimensional image from the sequence of 2D numpy arrays in zctPlanes.
2835 zctPlanes should be a generator of numpy 2D arrays of shape (sizeY, sizeX) ordered
2836 to iterate through T first, then C then Z.
2837 Example usage:
2838 original = conn.getObject("Image", 1)
2839 sizeZ = original.getSizeZ()
2840 sizeC = original.getSizeC()
2841 sizeT = original.getSizeT()
2842 clist = range(sizeC)
2843 zctList = []
2844 for z in range(sizeZ):
2845 for c in clist:
2846 for t in range(sizeT):
2847 zctList.append( (z,c,t) )
2848 def planeGen():
2849 planes = original.getPrimaryPixels().getPlanes(zctList)
2850 for p in planes:
2851 # perform some manipulation on each plane
2852 yield p
2853 createImageFromNumpySeq (planeGen(), imageName, sizeZ=sizeZ, sizeC=sizeC, sizeT=sizeT, sourceImageId=1, channelList=clist)
2854
2855 :param session An OMERO service factory or equivalent with getQueryService() etc.
2856 :param zctPlanes A generator of numpy 2D arrays, corresponding to Z-planes of new image.
2857 :param imageName Name of new image
2858 :param description Description for the new image
2859 :param dataset If specified, put the image in this dataset. omero.model.Dataset object
2860 :param sourceImageId If specified, copy this image with metadata, then add pixel data
2861 :param channelList Copies metadata from these channels in source image (if specified). E.g. [0,2]
2862 :return The new OMERO image: omero.model.ImageI
2863 """
2864 queryService = self.getQueryService()
2865 pixelsService = self.getPixelsService()
2866 rawPixelsStore = self.c.sf.createRawPixelsStore()
2867 containerService = self.getContainerService()
2868 updateService = self.getUpdateService()
2869
2870 import numpy
2871
2872 def createImage(firstPlane, channelList):
2873 """ Create our new Image once we have the first plane in hand """
2874 convertToType = None
2875 sizeY, sizeX = firstPlane.shape
2876 if sourceImageId is not None:
2877 if channelList is None:
2878 channelList = range(sizeC)
2879 iId = pixelsService.copyAndResizeImage(sourceImageId, rint(sizeX), rint(sizeY), rint(sizeZ), rint(sizeT), channelList, None, False, self.SERVICE_OPTS)
2880
2881 img = self.getObject("Image", iId.getValue())
2882 newPtype = img.getPrimaryPixels().getPixelsType().getValue()
2883 omeroToNumpy = {'int8':'int8', 'uint8':'uint8', 'int16':'int16', 'uint16':'uint16', 'int32':'int32', 'uint32':'uint32', 'float':'float32', 'double':'double'}
2884 if omeroToNumpy[newPtype] != firstPlane.dtype.name:
2885 convertToType = getattr(numpy, omeroToNumpy[newPtype])
2886 img._obj.setName(rstring(imageName))
2887 updateService.saveObject(img._obj, self.SERVICE_OPTS)
2888 else:
2889
2890 pTypes = {'int8':'int8', 'int16':'int16', 'uint16':'uint16', 'int32':'int32', 'float_':'float', 'float8':'float',
2891 'float16':'float', 'float32':'float', 'float64':'double', 'complex_':'complex', 'complex64':'complex'}
2892 dType = firstPlane.dtype.name
2893 if dType not in pTypes:
2894 pType = dType
2895 else:
2896 pType = pTypes[dType]
2897 pixelsType = queryService.findByQuery("from PixelsType as p where p.value='%s'" % pType, None)
2898 if pixelsType is None:
2899 raise Exception("Cannot create an image in omero from numpy array with dtype: %s" % dType)
2900 channelList = range(sizeC)
2901 iId = pixelsService.createImage(sizeX, sizeY, sizeZ, sizeT, channelList, pixelsType, imageName, description, self.SERVICE_OPTS)
2902
2903 imageId = iId.getValue()
2904 return containerService.getImages("Image", [imageId], None, self.SERVICE_OPTS)[0], convertToType
2905
2906 def uploadPlane(plane, z, c, t, convertToType):
2907
2908 if convertToType is not None:
2909 p = numpy.zeros(plane.shape, dtype=convertToType)
2910 p += plane
2911 plane = p
2912 byteSwappedPlane = plane.byteswap()
2913 convertedPlane = byteSwappedPlane.tostring();
2914 rawPixelsStore.setPlane(convertedPlane, z, c, t, self.SERVICE_OPTS)
2915
2916 image = None
2917 dtype = None
2918 channelsMinMax = []
2919 exc = None
2920 try:
2921 for theZ in range(sizeZ):
2922 for theC in range(sizeC):
2923 for theT in range(sizeT):
2924 plane = zctPlanes.next()
2925 if image == None:
2926 image, dtype = createImage(plane, channelList)
2927 pixelsId = image.getPrimaryPixels().getId().getValue()
2928 rawPixelsStore.setPixelsId(pixelsId, True, self.SERVICE_OPTS)
2929 uploadPlane(plane, theZ, theC, theT, dtype)
2930
2931 minValue = plane.min()
2932 maxValue = plane.max()
2933 if len(channelsMinMax) < (theC +1):
2934 channelsMinMax.append( [minValue, maxValue] )
2935 else:
2936 channelsMinMax[theC][0] = min(channelsMinMax[theC][0], minValue)
2937 channelsMinMax[theC][1] = max(channelsMinMax[theC][1], maxValue)
2938 except Exception, e:
2939 logger.error("Failed to setPlane() on rawPixelsStore while creating Image", exc_info=True)
2940 exc = e
2941 try:
2942 rawPixelsStore.close(self.SERVICE_OPTS)
2943 except Exception, e:
2944 logger.error("Failed to close rawPixelsStore", exc_info=True)
2945 if exc is None:
2946 exc = e
2947 if exc is not None:
2948 raise exc
2949
2950 try:
2951 zctPlanes.next()
2952 except StopIteration:
2953 pass
2954
2955 for theC, mm in enumerate(channelsMinMax):
2956 pixelsService.setChannelGlobalMinMax(pixelsId, theC, float(mm[0]), float(mm[1]), self.SERVICE_OPTS)
2957
2958
2959
2960 if dataset:
2961 link = omero.model.DatasetImageLinkI()
2962 link.parent = omero.model.DatasetI(dataset.getId(), False)
2963 link.child = omero.model.ImageI(image.id.val, False)
2964 updateService.saveObject(link, self.SERVICE_OPTS)
2965
2966 return ImageWrapper(self, image)
2967
2968
2970 """
2971 Applies the rendering settings from one image to others.
2972 Returns a dict of success { True:[ids], False:[ids] }
2973
2974 :param fromid: ID of Image to copy settings from.
2975 :param toids: List of Image IDs to apply setting to.
2976 :param to_type: toids refers to Images by default, but can refer to
2977 Project, Dataset, Image, Plate, Screen, Pixels
2978 """
2979 json_data = False
2980 fromimg = self.getObject("Image", fromid)
2981 frompid = fromimg.getPixelsId()
2982 if to_type is None:
2983 to_type="Image"
2984 if to_type.lower() == "acquisition":
2985 to_type = "Plate"
2986 to_type = to_type.title()
2987 if fromimg.canAnnotate():
2988 ctx = self.SERVICE_OPTS.copy()
2989 ctx.setOmeroGroup(fromimg.getDetails().getGroup().getId())
2990 rsettings = self.getRenderingSettingsService()
2991 json_data = rsettings.applySettingsToSet(frompid, to_type, list(toids), ctx)
2992 if fromid in json_data[True]:
2993 del json_data[True][json_data[True].index(fromid)]
2994 return json_data
2995
2997 """
2998 Sets and saves new names for channels of specified Images.
2999 If an image has fewer channels than the max channel index in nameDict, then
3000 the channel names will not be set for that image.
3001
3002 :param data_type: 'Image', 'Dataset', 'Plate'
3003 :param ids: Image, Dataset or Plate IDs
3004 :param nameDict: A dict of index:'name' ** 1-based ** E.g. {1:"DAPI", 2:"GFP"}
3005 :param channelCount: If specified, only rename images with this number of channels
3006 :return: {'imageCount':totalImages, 'updateCount':updateCount}
3007 """
3008
3009 if data_type == "Image":
3010 imageIds = [long(i) for i in ids]
3011 elif data_type == "Dataset":
3012 images = self.getContainerService().getImages("Dataset", ids, None, self.SERVICE_OPTS)
3013 imageIds = [i.getId().getValue() for i in images]
3014 elif data_type == "Plate":
3015 imageIds = []
3016 plates = self.getObjects("Plate", ids)
3017 for p in plates:
3018 for well in p._listChildren():
3019 for ws in well.copyWellSamples():
3020 imageIds.append(ws.image.id.val)
3021 else:
3022 raise AttributeError("setChannelNames() supports data_types 'Image', 'Dataset', 'Plate' only, not '%s'" % data_type)
3023
3024 queryService = self.getQueryService()
3025 params = omero.sys.Parameters()
3026 params.map = {'ids': omero.rtypes.wrap( imageIds )}
3027
3028
3029 query = "select p from Pixels p left outer join fetch p.channels as c join fetch c.logicalChannel as lc join fetch p.image as i where i.id in (:ids)"
3030 pix = queryService.findAllByQuery(query, params, self.SERVICE_OPTS)
3031
3032 maxIdx = max(nameDict.keys())
3033 toSave = set()
3034 updateCount = 0
3035 ctx = self.SERVICE_OPTS.copy()
3036 for p in pix:
3037 sizeC = p.getSizeC().getValue()
3038 if sizeC < maxIdx:
3039 continue
3040 if channelCount is not None and channelCount != sizeC:
3041 continue
3042 updateCount += 1
3043 group_id = p.details.group.id.val
3044 ctx.setOmeroGroup(group_id)
3045 for i, c in enumerate(p.iterateChannels()):
3046 if i+1 not in nameDict:
3047 continue
3048 lc = c.logicalChannel
3049 lc.setName(rstring(nameDict[i+1]))
3050 toSave.add(lc)
3051
3052 toSave = list(toSave)
3053 self.getUpdateService().saveCollection(toSave, ctx)
3054 return {'imageCount':len(imageIds), 'updateCount':updateCount}
3055
3056
3058 """
3059 Creates a L{OriginalFileWrapper} from a local file.
3060 File is uploaded to create an omero.model.OriginalFileI.
3061 Returns a new L{OriginalFileWrapper}
3062
3063 :param conn: Blitz connection
3064 :param fo: The file object
3065 :param path: The file path
3066 :param name: The file name
3067 :param fileSize: The file size
3068 :param mimetype: The mimetype of the file. String. E.g. 'text/plain'
3069 :param ns: The file namespace
3070 :return: New L{OriginalFileWrapper}
3071 """
3072 updateService = self.getUpdateService()
3073 rawFileStore = self.createRawFileStore()
3074
3075
3076 originalFile = omero.model.OriginalFileI()
3077 originalFile.setName(rstring(name))
3078 originalFile.setPath(rstring(path))
3079 if mimetype:
3080 originalFile.mimetype = rstring(mimetype)
3081 originalFile.setSize(rlong(fileSize))
3082
3083 try:
3084 import hashlib
3085 hash_sha1 = hashlib.sha1
3086 except:
3087 import sha
3088 hash_sha1 = sha.new
3089 fo.seek(0)
3090 h = hash_sha1()
3091 h.update(fo.read())
3092 shaHast = h.hexdigest()
3093 originalFile.setHash(rstring(shaHast))
3094 originalFile = updateService.saveAndReturnObject(originalFile)
3095
3096
3097 fo.seek(0)
3098 try:
3099 rawFileStore.setFileId(originalFile.getId().getValue())
3100 buf = 10000
3101 for pos in range(0,long(fileSize),buf):
3102 block = None
3103 if fileSize-pos < buf:
3104 blockSize = fileSize-pos
3105 else:
3106 blockSize = buf
3107 fo.seek(pos)
3108 block = fo.read(blockSize)
3109 rawFileStore.write(block, pos, blockSize)
3110 originalFile = rawFileStore.save()
3111 finally:
3112 rawFileStore.close();
3113 return OriginalFileWrapper(self, originalFile)
3114
3116 """
3117 Creates a L{OriginalFileWrapper} from a local file.
3118 File is uploaded to create an omero.model.OriginalFileI.
3119 Returns a new L{OriginalFileWrapper}
3120
3121 :param conn: Blitz connection
3122 :param localPath: Location to find the local file to upload
3123 :param origFilePathAndName: Provides the 'path' and 'name' of the OriginalFile. If None, use localPath
3124 :param mimetype: The mimetype of the file. String. E.g. 'text/plain'
3125 :param ns: The namespace of the file.
3126 :return: New L{OriginalFileWrapper}
3127 """
3128 if origFilePathAndName is None:
3129 origFilePathAndName = localPath
3130 path, name = os.path.split(origFilePathAndName)
3131 fileSize = os.path.getsize(localPath)
3132 fileHandle = open(localPath, 'rb')
3133 try:
3134 return self.createOriginalFileFromFileObj (fileHandle, path, name, fileSize, mimetype, ns)
3135 finally:
3136 fileHandle.close()
3137
3139 """
3140 Class method to create a L{FileAnnotationWrapper} from a local file.
3141 File is uploaded to create an omero.model.OriginalFileI referenced from this File Annotation.
3142 Returns a new L{FileAnnotationWrapper}
3143
3144 :param conn: Blitz connection
3145 :param localPath: Location to find the local file to upload
3146 :param origFilePathAndName: Provides the 'path' and 'name' of the OriginalFile. If None, use localPath
3147 :param mimetype: The mimetype of the file. String. E.g. 'text/plain'
3148 :param ns: The namespace of the file.
3149 :param desc: A description for the file annotation.
3150 :return: New L{FileAnnotationWrapper}
3151 """
3152 updateService = self.getUpdateService()
3153
3154
3155 originalFile = self.createOriginalFileFromLocalFile(localPath, origFilePathAndName, mimetype, ns)
3156
3157
3158 fa = omero.model.FileAnnotationI()
3159 fa.setFile(originalFile._obj)
3160 if desc:
3161 fa.setDescription(rstring(desc))
3162 if ns:
3163 fa.setNs(rstring(ns))
3164 fa = updateService.saveAndReturnObject(fa)
3165 return FileAnnotationWrapper(self, fa)
3166
3168 """
3169 Retrieve objects linked to the given annotation IDs
3170 controlled by the security system.
3171
3172 :param annids: Annotation IDs
3173 :type annids: L{Long}
3174 :return: Generator yielding Objects
3175 :rtype: L{BlitzObjectWrapper} generator
3176 """
3177
3178 wrapper = KNOWN_WRAPPERS.get(obj_type.lower(), None)
3179 if not wrapper:
3180 raise AttributeError("Don't know how to handle '%s'" % obj_type)
3181
3182 sql = "select ob from %s ob " \
3183 "left outer join fetch ob.annotationLinks obal " \
3184 "left outer join fetch obal.child ann " \
3185 "where ann.id in (:oids)" % wrapper().OMERO_CLASS
3186
3187 q = self.getQueryService()
3188 p = omero.sys.Parameters()
3189 p.map = {}
3190 p.map["oids"] = rlist([rlong(o) for o in set(annids)])
3191 for e in q.findAllByQuery(sql,p,self.SERVICE_OPTS):
3192 yield wrapper(self, e)
3193
3194
3195
3196
3197
3199 """
3200 Get all enumerations by class
3201
3202 :param klass: Class
3203 :type klass: Class or string
3204 :return: Generator of Enumerations
3205 :rtype: L{EnumerationWrapper} generator
3206 """
3207
3208 types = self.getTypesService()
3209 for e in types.allEnumerations(str(klass)):
3210 yield EnumerationWrapper(self, e)
3211
3213 """
3214 Get enumeration by class and value
3215
3216 :param klass: Class
3217 :type klass: Class or string
3218 :param string: Enum value
3219 :type string: String
3220 :return: Enumeration or None
3221 :rtype: L{EnumerationWrapper}
3222 """
3223
3224 types = self.getTypesService()
3225 obj = types.getEnumeration(str(klass), str(string))
3226 if obj is not None:
3227 return EnumerationWrapper(self, obj)
3228 else:
3229 return None
3230
3232 """
3233 Get enumeration by class and ID
3234
3235 :param klass: Class
3236 :type klass: Class or string
3237 :param eid: Enum ID
3238 :type eid: Long
3239 :return: Enumeration or None
3240 :rtype: L{EnumerationWrapper}
3241 """
3242
3243 query_serv = self.getQueryService()
3244 obj = query_serv.find(klass, long(eid), self.SERVICE_OPTS)
3245 if obj is not None:
3246 return EnumerationWrapper(self, obj)
3247 else:
3248 return None
3249
3251 """
3252 Gets original enumerations. Returns a dictionary of enumeration class: list of Enumerations
3253
3254 :return: Original enums
3255 :rtype: Dict of <string: L{EnumerationWrapper} list >
3256 """
3257
3258 types = self.getTypesService()
3259 rv = dict()
3260 for e in types.getOriginalEnumerations():
3261 if rv.get(e.__class__.__name__) is None:
3262 rv[e.__class__.__name__] = list()
3263 rv[e.__class__.__name__].append(EnumerationWrapper(self, e))
3264 return rv
3265
3267 """
3268 Gets list of enumeration types
3269
3270 :return: List of enum types
3271 :rtype: List of Strings
3272 """
3273
3274 types = self.getTypesService()
3275 return types.getEnumerationTypes()
3276
3278 """
3279 Get enumeration types, with lists of Enum entries
3280
3281 :return: Dictionary of type: entries
3282 :rtype: Dict of <string: L{EnumerationWrapper} list >
3283 """
3284
3285 types = self.getTypesService()
3286 rv = dict()
3287 for key, value in types.getEnumerationsWithEntries().items():
3288 r = list()
3289 for e in value:
3290 r.append(EnumerationWrapper(self, e))
3291 rv[key+"I"] = r
3292 return rv
3293
3295 """
3296 Deletes an enumeration object
3297
3298 :param obj: Enumeration object
3299 :type obj: omero.model.IObject
3300 """
3301
3302 types = self.getTypesService()
3303 types.deleteEnumeration(obj)
3304
3306 """
3307 Create an enumeration with given object
3308
3309 :param obj: Object
3310 :type obj: omero.model.IObject
3311 """
3312
3313 types = self.getTypesService()
3314 types.createEnumeration(obj)
3315
3317 """
3318 Resets the enumerations by type
3319
3320 :param klass: Type of enum to reset
3321 :type klass: String
3322 """
3323
3324 types = self.getTypesService()
3325 types.resetEnumerations(klass)
3326
3328 """
3329 Updates enumerations with new entries
3330
3331 :param new_entries: List of objects
3332 :type new_entries: List of omero.model.IObject
3333 """
3334
3335 types = self.getTypesService()
3336 types.updateEnumerations(new_entries)
3337
3338
3339
3340
3342 """
3343 Directly Delete object (removes row from database).
3344 This may fail with various constraint violations if the object is linked to others in the database
3345
3346 :param obj: Object to delete
3347 :type obj: IObject"""
3348
3349 u = self.getUpdateService()
3350 u.deleteObject(obj, self.SERVICE_OPTS)
3351
3353 """
3354 Retrieves the current set of delete commands with type (graph spec)
3355 and options filled.
3356 :return: Exhaustive list of available delete commands.
3357 :rtype: L{omero.api.delete.DeleteCommand}
3358 """
3359 return self.getDeleteService().availableCommands()
3360
3361 - def deleteObjects(self, graph_spec, obj_ids, deleteAnns=False,
3362 deleteChildren=False):
3363 """
3364 Generic method for deleting using the delete queue. Options allow to
3365 delete 'independent' Annotations (Tag, Term, File) and to delete
3366 child objects.
3367
3368 :param graph_spec: String to indicate the object type or graph
3369 specification. Examples include:
3370 * 'Project'
3371 * 'Dataset'
3372 * 'Image'
3373 * 'Screen'
3374 * 'Plate'
3375 * 'Well'
3376 * 'Annotation'
3377 * '/OriginalFile'
3378 * '/Image+Only'
3379 * '/Image/Pixels/Channel'
3380 As of OMERO 4.4.0 the correct case is now
3381 explicitly required, the use of 'project'
3382 or 'dataset' is no longer supported.
3383 :param obj_ids: List of IDs for the objects to delete
3384 :param deleteAnns: If true, delete linked Tag, Term and File
3385 annotations
3386 :param deleteChildren: If true, delete children. E.g. Delete Project
3387 AND it's Datasets & Images.
3388 :return: Delete handle
3389 :rtype: L{omero.api.delete.DeleteHandle}
3390 """
3391
3392 if not isinstance(obj_ids, list) and len(obj_ids) < 1:
3393 raise AttributeError('Must be a list of object IDs')
3394
3395 if not graph_spec.startswith('/'):
3396 graph_spec = '/%s' % graph_spec
3397 logger.debug('Received object type, using "%s"' % graph_spec)
3398
3399 op = dict()
3400 if not deleteAnns and graph_spec not in ["/Annotation",
3401 "/TagAnnotation"]:
3402 op["/TagAnnotation"] = "KEEP"
3403 op["/TermAnnotation"] = "KEEP"
3404 op["/FileAnnotation"] = "KEEP"
3405
3406 childTypes = {'/Project':['/Dataset', '/Image'],
3407 '/Dataset':['/Image'],
3408 '/Image':[],
3409 '/Screen':['/Plate'],
3410 '/Plate':['/Image'],
3411 '/Well':[],
3412 '/Annotation':[] }
3413
3414 if not deleteChildren:
3415 try:
3416 for c in childTypes[graph_spec]:
3417 op[c] = "KEEP"
3418 except KeyError:
3419 pass
3420
3421 dcs = list()
3422 logger.debug('Deleting %s [%s]. Options: %s' % \
3423 (graph_spec, str(obj_ids), op))
3424 for oid in obj_ids:
3425 dcs.append(omero.cmd.Delete(
3426 graph_spec, long(oid), op))
3427 doall = omero.cmd.DoAll()
3428 doall.requests = dcs
3429 handle = self.c.sf.submit(doall, self.SERVICE_OPTS)
3430 return handle
3431
3432 - def _waitOnCmd(self, handle, loops=10, ms=500,
3433 failonerror=True,
3434 failontimeout=False,
3435 closehandle=False):
3436
3437 return self.c.waitOnCmd(handle, loops=loops, ms=ms,
3438 failonerror=failonerror,
3439 failontimeout=failontimeout,
3440 closehandle=closehandle)
3441
3443 """
3444 Change the permissions of a particluar Group.
3445 Returns the proxy 'prx' handle that can be processed like this:
3446 callback = CmdCallbackI(self.gateway.c, prx)
3447 callback.loop(20, 500)
3448 rsp = prx.getResponse()
3449 """
3450 chmod = omero.cmd.Chmod(type="/ExperimenterGroup", id=group_Id, permissions=permissions)
3451 prx = self.c.sf.submit(chmod)
3452 return prx
3453
3454
3455 - def chgrpObjects(self, graph_spec, obj_ids, group_id, container_id=None):
3456 """
3457 Change the Group for a specified objects using queue.
3458
3459 :param graph_spec: String to indicate the object type or graph
3460 specification. Examples include:
3461 * '/Image'
3462 * '/Project' # will move contents too.
3463 * NB: Also supports 'Image' etc for convenience
3464 :param obj_ids: IDs for the objects to move.
3465 :param group_id: The group to move the data to.
3466 """
3467
3468 if not graph_spec.startswith('/'):
3469 graph_spec = '/%s' % graph_spec
3470 logger.debug('chgrp Received object type, using "%s"' % graph_spec)
3471
3472
3473 parentLinkClasses = {"/Image": (omero.model.DatasetImageLinkI, omero.model.ImageI, omero.model.DatasetI),
3474 "/Dataset": (omero.model.ProjectDatasetLinkI, omero.model.DatasetI, omero.model.ProjectI),
3475 "/Plate": (omero.model.ScreenPlateLinkI, omero.model.PlateI, omero.model.ScreenI)}
3476 da = DoAll()
3477 requests = []
3478 saves = []
3479 for obj_id in obj_ids:
3480 obj_id = long(obj_id)
3481 logger.debug('DoAll Chgrp: type: %s, id: %s, grp: %s' % (graph_spec, obj_id, group_id))
3482 chgrp = omero.cmd.Chgrp(type=graph_spec, id=obj_id, options=None, grp=group_id)
3483 requests.append(chgrp)
3484 if container_id is not None and graph_spec in parentLinkClasses:
3485
3486 link_klass = parentLinkClasses[graph_spec][0]
3487 link = link_klass()
3488 link.child = parentLinkClasses[graph_spec][1](obj_id, False)
3489 link.parent = parentLinkClasses[graph_spec][2](container_id, False)
3490 save = Save()
3491 save.obj = link
3492 saves.append(save)
3493
3494 requests.extend(saves)
3495 da.requests = requests
3496 ctx = self.SERVICE_OPTS.copy()
3497 ctx.setOmeroGroup(group_id)
3498 prx = self.c.sf.submit(da, ctx)
3499 return prx
3500
3501
3502
3503
3504
3505 - def searchObjects(self, obj_types, text, created=None, fields=(), batchSize=1000, page=0, searchGroup=None, ownedBy=None,
3506 useAcquisitionDate=False):
3507 """
3508 Search objects of type "Project", "Dataset", "Image", "Screen", "Plate"
3509 Returns a list of results
3510
3511 :param obj_types: E.g. ["Dataset", "Image"]
3512 :param text: The text to search for
3513 :param created: L{omero.rtime} list or tuple (start, stop)
3514 :param useAcquisitionDate if True, then use Image.acquisitionDate rather than import date for queries.
3515 :return: List of Object wrappers. E.g. L{ImageWrapper}
3516 """
3517 if not text:
3518 return []
3519 if isinstance(text, UnicodeType):
3520 text = text.encode('utf8')
3521 if obj_types is None:
3522 types = (ProjectWrapper, DatasetWrapper, ImageWrapper)
3523 else:
3524 def getWrapper(obj_type):
3525 if obj_type.lower() not in ["project", "dataset", "image", "screen", "plate", "well"]:
3526 raise AttributeError("%s not recognised. Can only search for 'Project', 'Dataset', 'Image', 'Screen', 'Plate', 'Well'" % obj_type)
3527 return KNOWN_WRAPPERS.get(obj_type.lower(), None)
3528 types = [getWrapper(o) for o in obj_types]
3529 search = self.createSearchService()
3530
3531 ctx = self.SERVICE_OPTS.copy()
3532 if searchGroup is not None:
3533 ctx.setOmeroGroup(searchGroup)
3534
3535 search.setBatchSize(batchSize, ctx)
3536 if ownedBy is not None:
3537 ownedBy = long(ownedBy)
3538 if ownedBy >= 0:
3539 details = omero.model.DetailsI()
3540 details.setOwner(omero.model.ExperimenterI(ownedBy, False))
3541 search.onlyOwnedBy(details, ctx)
3542
3543
3544 search.setAllowLeadingWildcard(True)
3545 search.setCaseSentivice(False)
3546
3547 def parse_time(c, i):
3548 try:
3549 t = c[i]
3550 t = unwrap(t)
3551 if t is not None:
3552 t = time.localtime(t / 1000)
3553 t = time.strftime("%Y%m%d", t)
3554 return t
3555 except:
3556 pass
3557 return None
3558
3559 d_from = parse_time(created, 0)
3560 d_to = parse_time(created, 1)
3561 d_type = useAcquisitionDate and "acquisitionDate" or "details.creationEvent.time"
3562
3563 try:
3564 rv = []
3565 for t in types:
3566 def actualSearch ():
3567 search.onlyType(t().OMERO_CLASS, ctx)
3568 search.byLuceneQueryBuilder(
3569 ",".join(fields),
3570 d_from, d_to, d_type,
3571 text, ctx)
3572
3573 timeit(actualSearch)()
3574
3575 def searchProcessing ():
3576 return search.results(ctx)
3577 p = 0
3578
3579 while search.hasNext(ctx):
3580 results = timeit(searchProcessing)()
3581 if p == page:
3582 rv.extend(map(lambda x: t(self, x), results))
3583 break;
3584 p += 1
3585
3586 finally:
3587 search.close()
3588 return rv
3589
3592 """
3593 Function or method wrapper that handles certain types of server side
3594 exceptions and debugging of errors.
3595 """
3596
3597 - def __init__(self, proxyObjectWrapper, attr, f):
3598 """
3599 Initialises the function call wrapper.
3600
3601 :param attr: Function name
3602 :type attr: String
3603 :param f: Function to wrap
3604 :type f: Function
3605 """
3606 self.proxyObjectWrapper = proxyObjectWrapper
3607 self.attr = attr
3608 self.f = f
3609 try:
3610 self.__f__name = f.im_self.ice_getIdentity().name
3611 except:
3612 self.__f__name = "unknown"
3613
3614 - def debug(self, exc_class, args, kwargs):
3615 logger.warn("%s on %s to <%s> %s(%r, %r)",
3616 exc_class, self.__class__, self.__f__name, self.attr,
3617 args, kwargs, exc_info=True)
3618
3620 """
3621 Exception handler that is expected to be overridden by sub-classes.
3622 The expected behaviour is either to handle a type of exception and
3623 return the server side result or to raise the already thrown
3624 exception. The calling context is an except block and the original
3625 \*args and \**kwargs from the wrapped function or method are provided
3626 to allow re-execution of the original.
3627
3628 :param e: The exception that has already been raised.
3629 :type e: Exception
3630 """
3631 raise
3632
3634 try:
3635 return self.f(*args, **kwargs)
3636 except Exception, e:
3637 self.debug(e.__class__.__name__, args, kwargs)
3638 return self.handle_exception(e, *args, **kwargs)
3639
3640
3641
3642
3643
3644 SafeCallWrapper = OmeroGatewaySafeCallWrapper
3645
3646 BlitzGateway = _BlitzGateway
3650 """ splits an hex stream of characters into an array of bytes in format (R,G,B,A).
3651 - abc -> (0xAA, 0xBB, 0xCC, 0xFF)
3652 - abcd -> (0xAA, 0xBB, 0xCC, 0xDD)
3653 - abbccd -> (0xAB, 0xBC, 0xCD, 0xFF)
3654 - abbccdde -> (0xAB, 0xBC, 0xCD, 0xDE)
3655
3656 :param color: Characters to split.
3657 :return: rgba
3658 :rtype: list of Ints
3659 """
3660 try:
3661 out = []
3662 if len(color) in (3,4):
3663 c = color
3664 color = ''
3665 for e in c:
3666 color += e + e
3667 if len(color) == 6:
3668 color += 'FF'
3669 if len(color) == 8:
3670 for i in range(0, 8, 2):
3671 out.append(int(color[i:i+2], 16))
3672 return out
3673 except:
3674 pass
3675 return None
3676
3679 """
3680 Wrapper for services. E.g. Admin Service, Delete Service etc.
3681 Maintains reference to connection.
3682 Handles creation of service when requested.
3683 """
3684
3685 - def __init__ (self, conn, func_str, cast_to=None, service_name=None):
3686 """
3687 Initialisation of proxy object wrapper.
3688
3689 :param conn: The L{BlitzGateway} connection
3690 :type conn: L{BlitzGateway}
3691 :param func_str: The name of the service creation method. E.g 'getAdminService'
3692 :type func_str: String
3693 :param cast_to: the checkedCast function to call with service name (only if func_str is None)
3694 :type cast_to: function
3695 :param service_name: Service name to use with cast_to (only if func_str is None)
3696
3697 """
3698 self._obj = None
3699 self._func_str = func_str
3700 self._cast_to = cast_to
3701 self._service_name = service_name
3702 self._resyncConn(conn)
3703 self._tainted = False
3704
3706 """
3707 Creates and returns a new L{ProxyObjectWrapper} with the same connection
3708 and service creation method name as this one.
3709
3710 :return: Cloned service wrapper
3711 :rtype: L{ProxyObjectWrapper}
3712 """
3713
3714 return ProxyObjectWrapper(self._conn, self._func_str, self._cast_to, self._service_name)
3715
3717 """
3718 Returns True if connected. If connection OK, wrapped service is also created.
3719
3720 :param forcejoin: if True forces the connection to only succeed if we can
3721 rejoin the current sessionid
3722 :type forcejoin: Boolean
3723
3724 :return: True if connection OK
3725 :rtype: Boolean
3726 """
3727 logger.debug("proxy_connect: a");
3728 if forcejoin:
3729 sUuid = self._conn._sessionUuid
3730 else:
3731 sUuid = None
3732 if not self._conn.connect(sUuid=sUuid):
3733 logger.debug('connect failed')
3734 logger.debug('/n'.join(traceback.format_stack()))
3735 return False
3736 logger.debug("proxy_connect: b");
3737 self._resyncConn(self._conn)
3738 logger.debug("proxy_connect: c");
3739 self._obj = self._create_func()
3740 logger.debug("proxy_connect: d");
3741 return True
3742
3744 """ Sets the tainted flag to True """
3745 self._tainted = True
3746
3748 """ Sets the tainted flag to False """
3749 self._tainted = False
3750
3752 """
3753 Closes the underlaying service, so next call to the proxy will create a new
3754 instance of it.
3755 """
3756
3757 if self._obj and isinstance(self._obj, omero.api.StatefulServiceInterfacePrx):
3758 self._obj.close()
3759 self._obj = None
3760
3762 """
3763 Reset refs to connection and session factory. Resets session creation function.
3764 Attempts to reload the wrapped service - if already created (doesn't create service)
3765
3766 :param conn: Connection
3767 :type conn: L{BlitzGateway}
3768 """
3769
3770 self._conn = conn
3771 self._sf = conn.c.sf
3772 def cf ():
3773 if self._func_str is None:
3774 return self._cast_to(self._sf.getByName(self._service_name))
3775 else:
3776 return getattr(self._sf, self._func_str)()
3777 self._create_func = cf
3778 if self._obj is not None:
3779 try:
3780 logger.debug("## - refreshing %s" % (self._func_str or self._service_name))
3781 obj = conn.c.ic.stringToProxy(str(self._obj))
3782 self._obj = self._obj.checkedCast(obj)
3783 except Ice.ObjectNotExistException:
3784 self._obj = None
3785
3787 """
3788 Returns the wrapped service. If it is None, service is created.
3789
3790 :return: The wrapped service
3791 :rtype: omero.api.ServiceInterface subclass
3792 """
3793
3794 if not self._obj:
3795 try:
3796 self._obj = self._create_func()
3797 except Ice.ConnectionLostException:
3798 logger.debug('... lost, reconnecting (_getObj)')
3799 self._connect()
3800
3801 else:
3802 self._ping()
3803 return self._obj
3804
3806 """
3807 For some reason, it seems that keepAlive doesn't, so every so often I need to recreate the objects.
3808 Calls serviceFactory.keepAlive(service). If this returns false, attempt to create service.
3809
3810 :return: True if no exception thrown
3811 :rtype: Boolean
3812 """
3813
3814 try:
3815 if not self._sf.keepAlive(self._obj):
3816 logger.debug("... died, recreating ...")
3817 self._obj = self._create_func()
3818 except Ice.ObjectNotExistException:
3819
3820 logger.debug("... reset, reconnecting")
3821 self._connect()
3822 return False
3823 except Ice.ConnectionLostException:
3824
3825 logger.debug(traceback.format_stack())
3826 logger.debug("... lost, reconnecting (_ping)")
3827 self._conn._connected = False
3828 self._connect()
3829 return False
3830 except Ice.ConnectionRefusedException:
3831
3832 logger.debug(traceback.format_stack())
3833 logger.debug("... refused, reconnecting")
3834 self._connect()
3835 return False
3836 except omero.RemovedSessionException:
3837
3838 logger.debug(traceback.format_stack())
3839 logger.debug("... session has left the building, reconnecting")
3840 self._connect()
3841 return False
3842 except Ice.UnknownException:
3843
3844 logger.debug(traceback.format_stack())
3845 logger.debug("... ice says something bad happened, reconnecting")
3846 self._connect()
3847 return False
3848 return True
3849
3851 """
3852 Returns named attribute of the wrapped service.
3853 If attribute is a method, the method is wrapped to handle exceptions, connection etc.
3854
3855 :param attr: Attribute name
3856 :type attr: String
3857 :return: Attribute or wrapped method
3858 """
3859
3860 obj = self._obj or self._getObj()
3861 rv = getattr(obj, attr)
3862 if callable(rv):
3863 rv = SafeCallWrapper(self, attr, rv)
3864
3865 return rv
3866
3868 """
3869 omero_model_AnnotationI class wrapper extends BlitzObjectWrapper.
3870 """
3871 registry = {}
3872 OMERO_TYPE = None
3873
3875 """
3876 Initialises the Annotation wrapper and 'link' if in kwargs
3877 """
3878 super(AnnotationWrapper, self).__init__(*args, **kwargs)
3879 self.link = kwargs.get('link')
3880 if self._obj is None and self.OMERO_TYPE is not None:
3881 self._obj = self.OMERO_TYPE()
3882
3884 """
3885 Returns true if type, id, value and ns are equal
3886
3887 :param a: The annotation to compare
3888 :return: True if annotations are the same - see above
3889 :rtype: Boolean
3890 """
3891 return type(a) == type(self) and self._obj.id == a._obj.id and self.getValue() == a.getValue() and self.getNs() == a.getNs()
3892
3894 """
3895 Used for building queries in generic methods such as getObjects("Annotation")
3896 """
3897 return "select obj from Annotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
3898 "join fetch obj.details.creationEvent"
3899
3900 @classmethod
3902 """
3903 Adds the AnnotationWrapper regklass to class registry
3904 :param regklass: The wrapper class, E.g. L{DoubleAnnotationWrapper}
3905 :type regklass: L{AnnotationWrapper} subclass
3906 """
3907
3908 klass.registry[regklass.OMERO_TYPE] = regklass
3909
3910 @classmethod
3911 - def _wrap (klass, conn=None, obj=None, link=None):
3912 """
3913 Class method for creating L{AnnotationWrapper} subclasses based on the type of
3914 annotation object, using previously registered mapping between OMERO types and wrapper classes
3915
3916 :param conn: The L{BlitzGateway} connection
3917 :type conn: L{BlitzGateway}
3918 :param obj: The OMERO annotation object. E.g. omero.model.DoubleAnnotation
3919 :type obj: L{omero.model.Annotation} subclass
3920 :param link: The link for this annotation
3921 :type link: E.g. omero.model.DatasetAnnotationLink
3922 :return: Wrapped AnnotationWrapper object or None if obj.__class__ not registered
3923 :rtype: L{AnnotationWrapper} subclass
3924 """
3925 if obj is None:
3926 return AnnotationWrapper()
3927 if obj.__class__ in klass.registry:
3928 kwargs = dict()
3929 if link is not None:
3930 kwargs['link'] = BlitzObjectWrapper(conn, link)
3931 return klass.registry[obj.__class__](conn, obj, **kwargs)
3932 else:
3933 return None
3934
3935 @classmethod
3936 - def createAndLink (klass, target, ns, val=None, sameOwner=False):
3937 """
3938 Class method for creating an instance of this AnnotationWrapper, setting ns and value
3939 and linking to the target.
3940
3941 :param target: The object to link annotation to
3942 :type target: L{BlitzObjectWrapper} subclass
3943 :param ns: Annotation namespace
3944 :type ns: String
3945 :param val: Value of annotation. E.g Long, Text, Boolean etc.
3946 """
3947
3948 this = klass()
3949 this.setNs(ns)
3950 if val is not None:
3951 this.setValue(val)
3952 target.linkAnnotation(this, sameOwner=sameOwner)
3953
3955 """
3956 Gets annotation namespace
3957
3958 :return: Namespace or None
3959 :rtype: String
3960 """
3961
3962 return self._obj.ns is not None and self._obj.ns.val or None
3963
3965 """
3966 Sets annotation namespace
3967
3968 :param val: Namespace value
3969 :type val: String
3970 """
3971
3972 self._obj.ns = omero_type(val)
3973
3975 """ Needs to be implemented by subclasses """
3976 raise NotImplementedError
3977
3979 """ Needs to be implemented by subclasses """
3980 raise NotImplementedError
3981
3983 ptype = ptype.title().replace("Plateacquisition", "PlateAcquisition")
3984 if not ptype in ('Project', 'Dataset', 'Image', 'Screen', 'Plate', 'Well', 'PlateAcquisition'):
3985 raise AttributeError("getParentLinks(): ptype '%s' not supported" % ptype)
3986 p = omero.sys.Parameters()
3987 p.map = {}
3988 p.map["aid"] = rlong(self.id)
3989 sql = "select oal from %sAnnotationLink as oal left outer join fetch oal.child as ch " \
3990 "left outer join fetch oal.parent as pa " \
3991 "where ch.id=:aid " % (ptype)
3992 if pids is not None:
3993 p.map["pids"] = rlist([rlong(ob) for ob in pids])
3994 sql+=" and pa.id in (:pids)"
3995
3996 for al in self._conn.getQueryService().findAllByQuery(sql, p, self._conn.SERVICE_OPTS):
3997 yield AnnotationLinkWrapper(self._conn, al)
3998
4000 """
4001 omero_model_AnnotationLinkI class wrapper extends omero.gateway.BlitzObjectWrapper.
4002 """
4003
4006
4008 """
4009 Gets the parent (Annotated Object) as a L{BlitzObjectWrapper }, but attempts
4010 to wrap it in the correct subclass using L{KNOWN_WRAPPERS}, E.g. ImageWrapper
4011 """
4012 modelClass = self.parent.__class__.__name__[:-1].lower()
4013 if modelClass in KNOWN_WRAPPERS:
4014 return KNOWN_WRAPPERS[modelClass](self._conn, self.parent)
4015 return BlitzObjectWrapper(self._conn, self.parent)
4016
4017 AnnotationLinkWrapper = _AnnotationLinkWrapper
4018
4019 from omero_model_FileAnnotationI import FileAnnotationI
4022 """
4023 omero_model_FileAnnotatio class wrapper extends AnnotationWrapper.
4024 """
4025
4026 OMERO_TYPE = FileAnnotationI
4027
4028 _attrs = ('file|OriginalFileWrapper',)
4029
4031 """
4032 Used for building queries in generic methods such as getObjects("FileAnnotation")
4033 """
4034 return "select obj from FileAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
4035 "join fetch obj.details.creationEvent join fetch obj.file"
4036
4038 """ Not implemented """
4039 pass
4040
4042 """ Not implemented """
4043 pass
4044
4045 - def setFile (self, originalfile):
4049
4054
4069
4071 """
4072 Looks up the size of the file in bytes
4073
4074 :return: File size (bytes)
4075 :rtype: Long
4076 """
4077 return self.getFile().size
4078
4080 """
4081 Gets the file name
4082
4083 :return: File name
4084 :rtype: String
4085 """
4086 f = self.getFile()
4087 if f is None or f._obj is None:
4088 return None
4089 fname = f.getName()
4090 if fname is not None and len(fname) > 0:
4091 return fname
4092 fpath = f.getPath()
4093 if fpath is not None and len(fpath) > 0:
4094 return fpath
4095 return f.id
4096
4098 """
4099 Returns a generator yielding chunks of the file data.
4100
4101 :return: Data from file in chunks
4102 :rtype: Generator
4103 """
4104
4105 return self.getFile().getFileInChunks();
4106
4107 AnnotationWrapper._register(FileAnnotationWrapper)
4111 """
4112 omero_model_OriginalFileI class wrapper extends BlitzObjectWrapper.
4113 """
4114
4117
4119 """
4120 Returns a generator yielding chunks of the file data.
4121
4122 :return: Data from file in chunks
4123 :rtype: Generator
4124 """
4125
4126 store = self._conn.createRawFileStore()
4127 store.setFileId(self._obj.id.val, self._conn.SERVICE_OPTS)
4128 size = self._obj.size.val
4129 if size <= buf:
4130 yield store.read(0,long(size))
4131 else:
4132 for pos in range(0,long(size),buf):
4133 data = None
4134 if size-pos < buf:
4135 data = store.read(pos, size-pos)
4136 else:
4137 data = store.read(pos, buf)
4138 yield data
4139 store.close()
4140
4141
4142 OriginalFileWrapper = _OriginalFileWrapper
4143
4144
4145 from omero_model_TimestampAnnotationI import TimestampAnnotationI
4148 """
4149 omero_model_TimestampAnnotatio class wrapper extends AnnotationWrapper.
4150 """
4151
4152 OMERO_TYPE = TimestampAnnotationI
4153
4155 """
4156 Used for building queries in generic methods such as getObjects("TimestampAnnotation")
4157 """
4158 return "select obj from TimestampAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
4159 "join fetch obj.details.creationEvent"
4160
4162 """
4163 Returns a datetime object of the timestamp in seconds
4164
4165 :return: Timestamp value
4166 :rtype: L{datetime}
4167 """
4168
4169 return datetime.fromtimestamp(self._obj.timeValue.val / 1000.0)
4170
4172 """
4173 Sets the timestamp value
4174
4175 :param val: Timestamp value
4176 :type param: L{datetime} OR L{omero.RTime} OR Long
4177 """
4178
4179 if isinstance(val, datetime):
4180 self._obj.timeValue = rtime(long(time.mktime(val.timetuple())*1000))
4181 elif isinstance(val, omero.RTime):
4182 self._obj.timeValue = val
4183 else:
4184 self._obj.timeValue = rtime(long(val * 1000))
4185
4186 AnnotationWrapper._register(TimestampAnnotationWrapper)
4187
4188 from omero_model_BooleanAnnotationI import BooleanAnnotationI
4191 """
4192 omero_model_BooleanAnnotationI class wrapper extends AnnotationWrapper.
4193 """
4194
4195 OMERO_TYPE = BooleanAnnotationI
4196
4198 """
4199 Used for building queries in generic methods such as getObjects("BooleanAnnotation")
4200 """
4201 return "select obj from BooleanAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
4202 "join fetch obj.details.creationEvent"
4203
4205 """
4206 Gets boolean value
4207
4208 :return: Value
4209 :rtype: Boolean
4210 """
4211 return unwrap(self._obj.boolValue)
4212
4214 """
4215 Sets boolean value
4216
4217 :param val: Value
4218 :type val: Boolean
4219 """
4220
4221 self._obj.boolValue = rbool(not not val)
4222
4223 AnnotationWrapper._register(BooleanAnnotationWrapper)
4224
4225 from omero_model_TagAnnotationI import TagAnnotationI
4228 """
4229 omero_model_BooleanAnnotationI class wrapper extends AnnotationWrapper.
4230 """
4231
4232 OMERO_TYPE = TagAnnotationI
4233
4245
4259
4271
4272
4274 """
4275 Used for building queries in generic methods such as getObjects("TagAnnotation")
4276 """
4277 return "select obj from TagAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
4278 "join fetch obj.details.creationEvent"
4279
4281 """
4282 Gets the value of the Tag
4283
4284 :return: Value
4285 :type: String
4286 """
4287
4288 return unwrap(self._obj.textValue)
4289
4291 """
4292 Sets Tag value
4293
4294 :param val: Tag text value
4295 :type val: String
4296 """
4297
4298 self._obj.textValue = omero_type(val)
4299
4300 AnnotationWrapper._register(TagAnnotationWrapper)
4301
4302 from omero_model_CommentAnnotationI import CommentAnnotationI
4336
4337 AnnotationWrapper._register(CommentAnnotationWrapper)
4338
4339 from omero_model_LongAnnotationI import LongAnnotationI
4342 """
4343 omero_model_LongAnnotationI class wrapper extends AnnotationWrapper.
4344 """
4345 OMERO_TYPE = LongAnnotationI
4346
4348 """
4349 Used for building queries in generic methods such as getObjects("LongAnnotation")
4350 """
4351 return "select obj from LongAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
4352 "join fetch obj.details.creationEvent"
4353
4355 """
4356 Gets the value of the Long annotation
4357
4358 :return: Value
4359 :type: Long
4360 """
4361
4362 return unwrap(self._obj.longValue)
4363
4365 """
4366 Sets long annotation value
4367
4368 :param val: Value
4369 :type val: Long
4370 """
4371
4372 self._obj.longValue = rlong(val)
4373
4374 AnnotationWrapper._register(LongAnnotationWrapper)
4375
4376 from omero_model_DoubleAnnotationI import DoubleAnnotationI
4379 """
4380 omero_model_DoubleAnnotationI class wrapper extends AnnotationWrapper.
4381 """
4382 OMERO_TYPE = DoubleAnnotationI
4383
4385 """
4386 Used for building queries in generic methods such as getObjects("DoubleAnnotation")
4387 """
4388 return "select obj from DoubleAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
4389 "join fetch obj.details.creationEvent"
4390
4392 """
4393 Gets the value of the Double Annotation
4394
4395 :return: Value
4396 :type: Double
4397 """
4398 return unwrap(self._obj.doubleValue)
4399
4401 """
4402 Sets Double annotation value
4403
4404 :param val: Value
4405 :type val: Double
4406 """
4407
4408 self._obj.doubleValue = rdouble(val)
4409
4410 AnnotationWrapper._register(DoubleAnnotationWrapper)
4411
4412 from omero_model_TermAnnotationI import TermAnnotationI
4415 """
4416 omero_model_TermAnnotationI class wrapper extends AnnotationWrapper.
4417
4418 only in 4.2+
4419 """
4420 OMERO_TYPE = TermAnnotationI
4421
4423 """
4424 Used for building queries in generic methods such as getObjects("TermAnnotation")
4425 """
4426 return "select obj from TermAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
4427 "join fetch obj.details.creationEvent"
4428
4430 """
4431 Gets the value of the Term
4432
4433 :return: Value
4434 :type: String
4435 """
4436
4437 return unwrap(self._obj.termValue)
4438
4440 """
4441 Sets term value
4442
4443 :param val: Value
4444 :type val: String
4445 """
4446
4447 self._obj.termValue = rstring(val)
4448
4449 AnnotationWrapper._register(TermAnnotationWrapper)
4450
4451 from omero_model_XmlAnnotationI import XmlAnnotationI
4454 """
4455 omero_model_XmlAnnotationI class wrapper extends CommentAnnotationWrapper.
4456 """
4457 OMERO_TYPE = XmlAnnotationI
4458
4459 AnnotationWrapper._register(XmlAnnotationWrapper)
4462
4464 """
4465 Gets the type (class) of the Enumeration
4466
4467 :return: The omero class
4468 :type: Class
4469 """
4470
4471 return self._obj.__class__
4472
4473 EnumerationWrapper = _EnumerationWrapper
4476 """
4477 omero_model_ExperimenterI class wrapper extends BlitzObjectWrapper.
4478 """
4479
4485
4487 rv = super(_ExperimenterWrapper, self).simpleMarshal(xtra=xtra, parents=parents)
4488 rv.update({'firstName': self.firstName,
4489 'middleName': self.middleName,
4490 'lastName': self.lastName,
4491 'email': self.email,
4492 'isAdmin': len(filter(lambda x: x.name.val == 'system', self._conn.getAdminService().containedGroups(self.getId()))) == 1,
4493 })
4494 return rv
4495
4497 """
4498 Returns string for building queries, loading Experimenters only.
4499 """
4500 return "select distinct obj from Experimenter as obj left outer join fetch obj.groupExperimenterMap " \
4501 "as map left outer join fetch map.parent g"
4502
4504 """
4505 Returns the experimenter's preferences annotation contents, as a ConfigParser instance
4506
4507 :return: See above
4508 :rtype: ConfigParser
4509 """
4510
4511 self._obj.unloadAnnotationLinks()
4512 cp = ConfigParser.SafeConfigParser()
4513 prefs = self.getAnnotation('TODO.changeme.preferences')
4514 if prefs is not None:
4515 prefs = prefs.getValue()
4516 if prefs is not None:
4517 cp.readfp(StringIO(prefs))
4518 return cp
4519
4521 """
4522 Sets the experimenter's preferences annotation contents, passed in as a ConfigParser instance
4523
4524 :param prefs: ConfigParser of preferences
4525 :type prefs: ConfigParser
4526 """
4527
4528 ann = self.getAnnotation('TODO.changeme.preferences')
4529 t = StringIO()
4530 prefs.write(t)
4531 if ann is None:
4532 ann = CommentAnnotationWrapper()
4533 ann.setNs('TODO.changeme.preferences')
4534 ann.setValue(t.getvalue())
4535 self.linkAnnotation(ann)
4536 else:
4537 ann.setValue(t.getvalue())
4538 ann.save()
4539 self._obj.unloadAnnotationLinks()
4540
4542 """
4543 Gets a preference for the experimenter
4544
4545 :param key: Preference key
4546 :param default: Default value to return
4547 :param section: Preferences section
4548 :return: Preference value
4549 """
4550
4551 if section is None:
4552 section = 'DEFAULT'
4553 try:
4554 return self.getRawPreferences().get(section, key)
4555 except ConfigParser.Error:
4556 return default
4557 return default
4558
4560 """
4561 Gets all preferences for section
4562
4563 :param section: Preferences section
4564 :return: Dict of preferences
4565 """
4566
4567 if section is None:
4568 section = 'DEFAULT'
4569 prefs = self.getRawPreferences()
4570 if prefs.has_section(section) or section == 'DEFAULT':
4571 return dict(prefs.items(section))
4572 return {}
4573
4575 """
4576 Sets a preference for the experimenter
4577
4578 :param key: Preference key
4579 :param value: Value to set
4580 :param section: Preferences section - created if needed
4581 """
4582
4583 if section is None:
4584 section = 'DEFAULT'
4585 prefs = self.getRawPreferences()
4586 if not section in prefs.sections():
4587 prefs.add_section(section)
4588 prefs.set(section, key, value)
4589 self.setRawPreferences(prefs)
4590
4592 """
4593 Returns Experimenter's omeName
4594
4595 :return: Name
4596 :rtype: String
4597 """
4598
4599 return self.omeName
4600
4602 """
4603 Returns Experimenter's Full Name
4604
4605 :return: Full Name or None
4606 :rtype: String
4607 """
4608
4609 return self.getFullName()
4610
4612 """
4613 Gets full name of this experimenter. E.g. 'William James. Moore' or 'William Moore' if no middle name
4614
4615 :return: Full Name or None
4616 :rtype: String
4617 """
4618
4619 try:
4620 lastName = self.lastName
4621 firstName = self.firstName
4622 middleName = self.middleName
4623
4624 if middleName is not None and middleName != '':
4625 name = "%s %s %s" % (firstName, middleName, lastName)
4626 else:
4627 if firstName == "" and lastName == "":
4628 name = self.omeName
4629 else:
4630 name = "%s %s" % (firstName, lastName)
4631 return name
4632 except:
4633 logger.error(traceback.format_exc())
4634 return None
4635
4637 """
4638 Returns first initial and Last name. E.g. 'W. Moore'
4639
4640 :return: Initial and last name
4641 :rtype: String
4642 """
4643
4644 try:
4645 if self.firstName is not None and self.lastName is not None:
4646 name = "%s. %s" % (self.firstName[:1], self.lastName)
4647 else:
4648 name = self.omeName
4649 return name
4650 except:
4651 logger.error(traceback.format_exc())
4652 return _("Unknown name")
4653
4655 """
4656 Returns true if Experimenter is Admin (if they are in any group named 'system')
4657
4658 :return: True if experimenter is Admin
4659 :rtype: Boolean
4660 """
4661
4662 for ob in self._obj.copyGroupExperimenterMap():
4663 if ob is None:
4664 continue
4665 if ob.parent.name.val == "system":
4666 return True
4667 return False
4668
4670 """
4671 Returns true if Experimenter is Active (if they are in any group named 'user')
4672
4673 :return: True if experimenter is Active
4674 :rtype: Boolean
4675 """
4676
4677 for ob in self._obj.copyGroupExperimenterMap():
4678 if ob is None:
4679 continue
4680 if ob.parent.name.val == "user":
4681 return True
4682 return False
4683
4685 """
4686 Returns true if Experimenter is Guest (if they are in any group named 'guest')
4687
4688 :return: True if experimenter is Admin
4689 :rtype: Boolean
4690 """
4691
4692 for ob in self._obj.copyGroupExperimenterMap():
4693 if ob is None:
4694 continue
4695 if ob.parent.name.val == "guest":
4696 return True
4697 return False
4698
4700 """ Returns True if this Experimenter is the current user """
4701 return self.getId() == self._conn.getUserId()
4702
4703 ExperimenterWrapper = _ExperimenterWrapper
4706 """
4707 omero_model_ExperimenterGroupI class wrapper extends BlitzObjectWrapper.
4708 """
4709
4715
4717 """
4718 Returns string for building queries, loading Experimenters for each group.
4719 """
4720 query = "select distinct obj from ExperimenterGroup as obj left outer join fetch obj.groupExperimenterMap " \
4721 "as map left outer join fetch map.child e"
4722 return query
4723
4724
4725 ExperimenterGroupWrapper = _ExperimenterGroupWrapper
4728 """
4729 omero_model_DetailsI class wrapper extends BlitzObjectWrapper.
4730 """
4731
4736
4738 """
4739 Returns the Owner of the object that these details apply to
4740
4741 :return: Owner
4742 :rtype: L{ExperimenterWrapper}
4743 """
4744 if self._owner is None:
4745 owner = self._obj.getOwner()
4746 self._owner = owner and ExperimenterWrapper(self._conn, self._obj.getOwner()) or None
4747 return self._owner
4748
4750 """
4751 Returns the Group that these details refer to
4752
4753 :return: Group
4754 :rtype: L{ExperimenterGroupWrapper}
4755 """
4756 if self._group is None:
4757 group = self._obj.getGroup()
4758 self._group = group and ExperimenterGroupWrapper(self._conn, self._obj.getGroup()) or None
4759 return self._group
4760
4762 """
4763 omero_model_DatasetI class wrapper extends BlitzObjectWrapper.
4764 """
4765
4771
4773 """ In addition to loading the Dataset, this method also loads the Images """
4774
4775 super(_DatasetWrapper, self).__loadedHotSwap__()
4776 if not self._obj.isImageLinksLoaded():
4777 links = self._conn.getQueryService().findAllByQuery("select l from DatasetImageLink as l join fetch l.child as a where l.parent.id=%i" % (self._oid), None, self._conn.SERVICE_OPTS)
4778 self._obj._imageLinksLoaded = True
4779 self._obj._imageLinksSeq = links
4780
4781 DatasetWrapper = _DatasetWrapper
4784 """
4785 omero_model_ProjectI class wrapper extends BlitzObjectWrapper.
4786 """
4787
4793
4794 ProjectWrapper = _ProjectWrapper
4797 """
4798 omero_model_ScreenI class wrapper extends BlitzObjectWrapper.
4799 """
4800
4806
4807 ScreenWrapper = _ScreenWrapper
4810 """ Convert number to letter label. E.g. 0 -> 'A' and 100 -> 'CW' """
4811 r = chr(ord('A') + i%26)
4812 i = i/26
4813 while i > 0:
4814 i -= 1
4815 r = chr(ord('A') + i%26) + r
4816 i = i/26
4817 return r
4818
4820 """
4821 omero_model_PlateI class wrapper extends BlitzObjectWrapper.
4822 """
4823
4829
4832
4834 """
4835 Clears child cache, so next _listChildren will query the server
4836 """
4837 self._childcache = None
4838 self._gridSize = None
4839
4841 p = omero.sys.Parameters()
4842 p.map = {}
4843 p.map["pid"] = self._obj.id
4844 sql = "select pa from PlateAcquisition as pa join fetch pa.plate as p where p.id=:pid"
4845 self._obj._plateAcquisitionsSeq = self._conn.getQueryService().findAllByQuery(sql, p, self._conn.SERVICE_OPTS)
4846 self._obj._plateAcquisitionsLoaded = True
4847
4849 if self._obj.sizeOfPlateAcquisitions() < 0:
4850 self._loadPlateAcquisitions()
4851 return self._obj.sizeOfPlateAcquisitions()
4852
4858
4859 @timeit
4861 """
4862 Returns tuple of min and max of indexed collection of well samples
4863 per plate acquisition if exists
4864 """
4865
4866 q = self._conn.getQueryService()
4867 sql = "select minIndex(ws), maxIndex(ws) from Well w " \
4868 "join w.wellSamples ws where w.plate.id=:oid"
4869
4870 p = omero.sys.Parameters()
4871 p.map = {}
4872 p.map["oid"] = self._obj.id
4873 if pid is not None:
4874 sql += " and ws.plateAcquisition.id=:pid"
4875 p.map["pid"] = rlong(pid)
4876
4877 fields = None
4878 try:
4879 res = [r for r in unwrap(q.projection(sql, p, self._conn.SERVICE_OPTS))[0] if r != None]
4880 if len(res) == 2:
4881 fields = tuple(res)
4882 except:
4883 pass
4884 return fields
4885
4887 """
4888 Lists Wells in this plate, not sorted. Saves wells to _childcache map, where key is (row, column).
4889 _
4890 :rtype: list of omero.model.WellI objects
4891 :return: child objects.
4892 """
4893 if self._childcache is None:
4894 q = self._conn.getQueryService()
4895 params = omero.sys.Parameters()
4896 params.map = {}
4897 params.map["oid"] = omero_type(self.getId())
4898 query = "select well from Well as well "\
4899 "join fetch well.details.creationEvent "\
4900 "join fetch well.details.owner join fetch well.details.group " \
4901 "left outer join fetch well.plate as pt "\
4902 "left outer join fetch well.wellSamples as ws " \
4903 "left outer join fetch ws.image as img "\
4904 "where well.plate.id = :oid"
4905
4906 self._childcache = {}
4907 for well in q.findAllByQuery(query, params, self._conn.SERVICE_OPTS):
4908 self._childcache[(well.row.val, well.column.val)] = well
4909 return self._childcache.values()
4910
4913
4915 """
4916 Makes sure the grid side count is the exact power of two of row and col arguments,
4917 keeping their ratio, that fits the existing well count.
4918 """
4919 gs = self.getGridSize()
4920 mul = 0
4921 while gs['rows'] > (row*(2**mul)) or gs['columns'] > (col*(2**mul)):
4922 mul += 1
4923 self._gridSize['rows'] = row * (2**mul)
4924 self._gridSize['columns'] = col * (2**mul)
4925
4927 """
4928 Iterates all wells on plate to retrieve grid size as {'rows': rSize, 'columns':cSize} dict.
4929
4930 :rtype: dict of {'rows': rSize, 'columns':cSize}
4931 """
4932 if self._gridSize is None:
4933 r,c = 0,0
4934 for child in self._listChildren():
4935 r,c = max(child.row.val, r), max(child.column.val, c)
4936 self._gridSize = {'rows': r+1, 'columns': c+1}
4937 return self._gridSize
4938
4940 """
4941 Returns a grid of WellWrapper objects, indexed by [row][col].
4942
4943 :rtype: 2D array of L{WellWrapper}s. Empty well positions are None
4944 """
4945 grid = self.getGridSize()
4946 childw = self._getChildWrapper()
4947 rv = [[None]*grid['columns'] for x in range(grid['rows'])]
4948 for child in self._listChildren():
4949 rv[child.row.val][child.column.val] = childw(self._conn, child, index=index)
4950 return rv
4951
4953 """
4954 Returns a list of labels for the columns on this plate. E.g. [1, 2, 3...] or ['A', 'B', 'C'...] etc
4955 """
4956 if self.columnNamingConvention and self.columnNamingConvention.lower()=='letter':
4957
4958 return [_letterGridLabel(x) for x in range(self.getGridSize()['columns'])]
4959 else:
4960 return range(1, self.getGridSize()['columns']+1)
4961
4963 """
4964 Returns a list of labels for the rows on this plate. E.g. [1, 2, 3...] or ['A', 'B', 'C'...] etc
4965 """
4966 if self.rowNamingConvention and self.rowNamingConvention.lower()=='number':
4967 return range(1, self.getGridSize()['rows']+1)
4968 else:
4969
4970 return [_letterGridLabel(x) for x in range(self.getGridSize()['rows'])]
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4989 """
4990 Make sure full project export doesn't pick up wellsample images
4991 TODO: do we want to support this at all?
4992 """
4993 return None
4994
4996 """
4997 Returns a query string for constructing custom queries, loading the screen for each plate.
4998 """
4999 query = "select obj from Plate as obj " \
5000 "join fetch obj.details.owner as owner join fetch obj.details.group "\
5001 "join fetch obj.details.creationEvent "\
5002 "left outer join fetch obj.screenLinks spl " \
5003 "left outer join fetch spl.parent sc"
5004 return query
5005
5006 PlateWrapper = _PlateWrapper
5009
5012
5014 name = super(_PlateAcquisitionWrapper, self).getName()
5015 if name is None:
5016 if self.startTime is not None and self.endTime is not None:
5017 name = "%s - %s" % (datetime.fromtimestamp(self.startTime/1000), datetime.fromtimestamp(self.endTime/1000))
5018 else:
5019 name = "Run %i" % self.id
5020 return name
5021 name = property(getName)
5022
5024 """
5025 Because PlateAcquisitions are direct children of plates, with no links in between,
5026 a special listParents is needed
5027 """
5028 rv = self._conn.getObject('Plate', self.plate.id.val)
5029 if withlinks:
5030 return [(rv, None)]
5031 return [rv]
5032
5033 PlateAcquisitionWrapper = _PlateAcquisitionWrapper
5036 """
5037 omero_model_WellI class wrapper extends BlitzObjectWrapper.
5038 """
5039
5045
5047 try:
5048 self.index = int(kwargs['index'])
5049 except:
5050 self.index = 0
5051 self.__reset__()
5052
5054 """
5055 Clears child cache, so next _listChildren will query the server
5056 """
5057 self._childcache = None
5058
5060 query = "select well from Well as well "\
5061 "join fetch well.details.creationEvent "\
5062 "join fetch well.details.owner join fetch well.details.group " \
5063 "left outer join fetch well.wellSamples as ws " \
5064 "left outer join fetch ws.image as img "\
5065 "where well.id = %d" % self.getId()
5066
5067 self._obj = self._conn.getQueryService().findByQuery(query, None, self._conn.SERVICE_OPTS)
5068
5070 if self._childcache is None:
5071 if not self.isWellSamplesLoaded():
5072 self.__loadedHotSwap__()
5073 if self.isWellSamplesLoaded():
5074 self._childcache = self.copyWellSamples()
5075 return self._childcache
5076
5084
5086 """
5087 Because wells are direct children of plates, with no links in between,
5088 a special listParents is needed
5089 """
5090 rv = self._conn.getObject('Plate', self.plate.id.val)
5091 if withlinks:
5092 return [(rv, None)]
5093 return [rv]
5094
5096 """ returns the screens that link to plates that link to this well """
5097 params = omero.sys.Parameters()
5098 params.map = {'id': omero_type(self.getId())}
5099 query = """select s from Well w
5100 left outer join w.plate p
5101 left outer join p.screenLinks spl
5102 left outer join spl.parent s
5103 where spl.parent.id=s.id and spl.child.id=p.id and w.plate.id=p.id
5104 and w.id=:id"""
5105 return [omero.gateway.ScreenWrapper(self._conn, x) for x in \
5106 self._conn.getQueryService().findAllByQuery(query, params, self._conn.SERVICE_OPTS)]
5107
5108
5110 """
5111 Return True if well samples exist (loaded)
5112
5113 :return: True if well samples loaded
5114 :rtype: Boolean
5115 """
5116
5117 if self.isWellSamplesLoaded():
5118 childnodes = self.copyWellSamples()
5119 logger.debug('listChildren for %s %d: already loaded, %d samples' % (self.OMERO_CLASS, self.getId(), len(childnodes)))
5120 if len(childnodes) > 0:
5121 return True
5122 return False
5123
5125 """
5126 Return the number of well samples loaded
5127
5128 :return: well sample count
5129 :rtype: Int
5130 """
5131 return len(self._listChildren())
5132
5134 """
5135 Return the well sample at the specified index. If index is ommited,
5136 the currently selected index is used instead (self.index) and if
5137 that is not defined, the first one (index 0) is returned.
5138
5139 :param index: the well sample index
5140 :type index: integer
5141 :return: The Well Sample
5142 :rtype: L{WellSampleWrapper}
5143 """
5144 if index is None:
5145 index = self.index
5146 if index is None:
5147 index = 0
5148 index = int(index)
5149 childnodes = self._listChildren()
5150 if len(childnodes) > index:
5151 return self._getChildWrapper()(self._conn, childnodes[index])
5152 return None
5153
5155 """
5156 Return the image at the specified well sample index. If index is ommited,
5157 the currently selected index is used instead (self.index) and if
5158 that is not defined, the first one (index 0) is returned.
5159
5160 :param index: the well sample index
5161 :type index: integer
5162 :return: The Image
5163 :rtype: L{ImageWrapper}
5164 """
5165 wellsample = self.getWellSample(index)
5166 if wellsample:
5167 return wellsample.getImage()
5168 return None
5169
5171 """
5172 Return the well sample at the current index (0 if not set)
5173
5174 :return: The Well Sample wrapper
5175 :rtype: L{WellSampleWrapper}
5176
5177 """
5178 return self.getWellSample()
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204 WellWrapper = _WellWrapper
5207 """
5208 omero_model_WellSampleI class wrapper extends BlitzObjectWrapper.
5209 """
5210
5218
5220 """
5221 Because wellsamples are direct children of wells, with no links in between,
5222 a special listParents is needed
5223 """
5224 rv = self._conn.getQueryService().findAllByQuery("""select w from Well w
5225 left outer join fetch w.wellSamples as ws
5226 where ws.id=%d""" % self.getId(), None, self._conn.SERVICE_OPTS)
5227 if not len(rv):
5228 rv = [None]
5229
5230 pwc = self._getParentWrappers()
5231 if withlinks:
5232 return [(pwc[0](self._conn, x), None) for x in rv]
5233 return [pwc[0](self._conn, x) for x in rv]
5234
5236 """
5237 Gets the Image for this well sample.
5238
5239 :return: The Image
5240 :rtype: L{ImageWrapper}
5241 """
5242 return self._getChildWrapper()(self._conn, self._obj.image)
5243
5245 """
5246 Gets the Image for this well sample.
5247
5248 :return: The Image
5249 :rtype: L{ImageWrapper}
5250 """
5251 return self.getImage()
5252
5254 """
5255 Gets the PlateAcquisition for this well sample, or None
5256
5257 :return: The PlateAcquisition
5258 :rtype: L{PlateAcquisitionWrapper} or None
5259 """
5260 aquisition = self._obj.plateAcquisition
5261 if aquisition is None:
5262 return None
5263 return PlateAcquisitionWrapper(self._conn, aquisition)
5264
5265 WellSampleWrapper = _WellSampleWrapper
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281 -class ColorHolder (object):
5282 """
5283 Stores color internally as (R,G,B,A) and allows setting and getting in multiple formats
5284 """
5285
5286 _color = {'red': 0, 'green': 0, 'blue': 0, 'alpha': 255}
5287
5289 """
5290 If colorname is 'red', 'green' or 'blue', set color accordingly - Otherwise black
5291
5292 :param colorname: 'red', 'green' or 'blue'
5293 :type colorname: String
5294 """
5295
5296 self._color = {'red': 0, 'green': 0, 'blue': 0, 'alpha': 255}
5297 if colorname and colorname.lower() in self._color.keys():
5298 self._color[colorname.lower()] = 255
5299
5300 @classmethod
5302 """
5303 Class method for creating a ColorHolder from r,g,b,a values
5304
5305 :param r: red 0 - 255
5306 :type r: int
5307 :param g: green 0 - 255
5308 :type g: int
5309 :param b: blue 0 - 255
5310 :type b: int
5311 :param a: alpha 0 - 255
5312 :type a: int
5313 :return: new Color object
5314 :rtype: L{ColorHolder}
5315 """
5316
5317 rv = klass()
5318 rv.setRed(r)
5319 rv.setGreen(g)
5320 rv.setBlue(b)
5321 rv.setAlpha(a)
5322 return rv
5323
5325 """
5326 Gets the Red component
5327
5328 :return: red
5329 :rtype: int
5330 """
5331
5332 return self._color['red']
5333
5335 """
5336 Set red, as int 0..255
5337
5338 :param val: value of Red.
5339 :type val: Int
5340 """
5341
5342 self._color['red'] = max(min(255, int(val)), 0)
5343
5345 """
5346 Gets the Green component
5347
5348 :return: green
5349 :rtype: int
5350 """
5351
5352 return self._color['green']
5353
5355 """
5356 Set green, as int 0..255
5357
5358 :param val: value of Green.
5359 :type val: Int
5360 """
5361
5362 self._color['green'] = max(min(255, int(val)), 0)
5363
5365 """
5366 Gets the Blue component
5367
5368 :return: blue
5369 :rtype: int
5370 """
5371
5372 return self._color['blue']
5373
5375 """
5376 Set Blue, as int 0..255
5377
5378 :param val: value of Blue.
5379 :type val: Int
5380 """
5381
5382 self._color['blue'] = max(min(255, int(val)), 0)
5383
5385 """
5386 Gets the Alpha component
5387
5388 :return: alpha
5389 :rtype: int
5390 """
5391
5392 return self._color['alpha']
5393
5395 """
5396 Set alpha, as int 0..255.
5397 :param val: value of alpha.
5398 """
5399
5400 self._color['alpha'] = max(min(255, int(val)), 0)
5401
5403 """
5404 Gets the html usable color. Dumps the alpha information. E.g. 'FF0000'
5405
5406 :return: html color
5407 :rtype: String
5408 """
5409
5410 return "%(red)0.2X%(green)0.2X%(blue)0.2X" % (self._color)
5411
5413 """
5414 Gets the css string: rgba(r,g,b,a)
5415
5416 :return: css color
5417 :rtype: String
5418 """
5419
5420 c = self._color.copy()
5421 c['alpha'] /= 255.0
5422 return "rgba(%(red)i,%(green)i,%(blue)i,%(alpha)0.3f)" % (c)
5423
5425 """
5426 Gets the (r,g,b) as a tuple.
5427
5428 :return: Tuple of (r,g,b) values
5429 :rtype: tuple of ints
5430 """
5431
5432 return (self._color['red'], self._color['green'], self._color['blue'])
5433
5435 """
5436 Returns the color as an Integer
5437
5438 :return: Integer
5439 :rtype: int
5440 """
5441
5442 a = self.getAlpha() << 24
5443 r = self.getRed() << 16
5444 g = self.getGreen() << 8
5445 b = self.getBlue() << 0
5446 return r+g+b+a
5447
5449 """
5450 omero_model_LogicalChannelI class wrapper extends BlitzObjectWrapper.
5451 Specifies a number of _attrs for the channel metadata.
5452 """
5453 _attrs = ('name',
5454 'pinHoleSize',
5455 '#illumination',
5456 'contrastMethod',
5457 'excitationWave',
5458 'emissionWave',
5459 'fluor',
5460 'ndFilter',
5461 'otf',
5462 'detectorSettings|DetectorSettingsWrapper',
5463 'lightSourceSettings|LightSettingsWrapper',
5464 'filterSet|FilterSetWrapper',
5465 'samplesPerPixel',
5466 '#photometricInterpretation',
5467 'mode',
5468 'pockelCellSetting',
5469 '()lightPath|',
5470 'version')
5471
5473 """ Loads the logical channel using the metadata service """
5474 if self._obj is not None:
5475 ctx = self._conn.SERVICE_OPTS.copy()
5476 if ctx.getOmeroGroup() is None:
5477 ctx.setOmeroGroup(-1)
5478 self._obj = self._conn.getMetadataService().loadChannelAcquisitionData([self._obj.id.val],ctx)[0]
5479
5481 """ Make sure we have the channel fully loaded, then return L{LightPathWrapper}"""
5482 self.__loadedHotSwap__()
5483 if self._obj.lightPath is not None:
5484 return LightPathWrapper(self._conn, self._obj.lightPath)
5485
5486 LogicalChannelWrapper = _LogicalChannelWrapper
5489 """
5490 base Light Source class wrapper, extends BlitzObjectWrapper.
5491 """
5492 _attrs = ('dichroic|DichroicWrapper',
5493 '()emissionFilters|',
5494 '()excitationFilters|')
5495
5498
5500 """ Returns list of excitation L{FilterWrapper}s. Ordered collections can contain nulls"""
5501 return [FilterWrapper(self._conn, link.child) for link in self.copyExcitationFilterLink() if link is not None]
5502
5504 """ Returns list of emission L{FilterWrapper}s """
5505 return [FilterWrapper(self._conn, link.child) for link in self.copyEmissionFilterLink()]
5506
5507 LightPathWrapper = _LightPathWrapper
5510 """
5511 omero_model_PixelsI class wrapper extends BlitzObjectWrapper.
5512 """
5513
5516
5518 """
5519 Creates RawPixelsStore and sets the id etc
5520 """
5521 ps = self._conn.createRawPixelsStore()
5522 ps.setPixelsId(self._obj.id.val, True, self._conn.SERVICE_OPTS)
5523 return ps
5524
5526 """
5527 This simply wraps the omero::model::PixelsType object in a
5528 BlitzObjectWrapper. Shouldn't be needed when this is done automatically.
5529
5530 It has the methods `getValue' and `getBitSize'.
5531 """
5532 return BlitzObjectWrapper(self._conn, self._obj.getPixelsType())
5533
5535 """
5536 Loads plane infos and returns sequence of omero.model.PlaneInfo objects
5537 wrapped in BlitzObjectWrappers ordered by planeInfo.deltaT.
5538 Set of plane infos can be filtered by C, T or Z
5539
5540 :param theC: Filter plane infos by Channel index
5541 :type theC: int or None
5542 :param theT: Filter plane infos by Time index
5543 :type theT: int or None
5544 :param theZ: Filter plane infos by Z index
5545 :type theT: int or None
5546
5547 :return: Generator of PlaneInfo wrapped in BlitzObjectWrappers
5548 """
5549
5550 params = omero.sys.Parameters()
5551 params.map = {}
5552 params.map["pid"] = rlong(self._obj.id)
5553 query = "select info from PlaneInfo as info where pixels.id=:pid"
5554 if theC != None:
5555 params.map["theC"] = rint(theC)
5556 query += " and info.theC=:theC"
5557 if theT != None:
5558 params.map["theT"] = rint(theT)
5559 query += " and info.theT=:theT"
5560 if theZ != None:
5561 params.map["theZ"] = rint(theZ)
5562 query += " and info.theZ=:theZ"
5563 query += " order by info.deltaT"
5564 queryService = self._conn.getQueryService()
5565 result = queryService.findAllByQuery(query, params, self._conn.SERVICE_OPTS)
5566 for pi in result:
5567 yield BlitzObjectWrapper(self._conn, pi)
5568
5570 """
5571 Returns generator of numpy 2D planes from this set of pixels for a list of Z, C, T indexes.
5572
5573 :param zctList: A list of indexes: [(z,c,t), ]
5574 """
5575
5576 zctTileList = []
5577 for zct in zctList:
5578 z,c,t = zct
5579 zctTileList.append((z,c,t, None))
5580 return self.getTiles(zctTileList)
5581
5582 - def getPlane (self, theZ=0, theC=0, theT=0):
5583 """
5584 Gets the specified plane as a 2D numpy array by calling L{getPlanes}
5585 If a range of planes are required, L{getPlanes} is approximately 30% faster.
5586 """
5587 planeList = list( self.getPlanes([(theZ, theC, theT)]) )
5588 return planeList[0]
5589
5591 """
5592 Returns generator of numpy 2D planes from this set of pixels for a list of (Z, C, T, tile)
5593 where tile is (x, y, width, height) or None if you want the whole plane.
5594
5595 :param zctrList: A list of indexes: [(z,c,t, region), ]
5596 """
5597
5598 import numpy
5599 from struct import unpack
5600
5601 pixelTypes = {"int8":['b',numpy.int8],
5602 "uint8":['B',numpy.uint8],
5603 "int16":['h',numpy.int16],
5604 "uint16":['H',numpy.uint16],
5605 "int32":['i',numpy.int32],
5606 "uint32":['I',numpy.uint32],
5607 "float":['f',numpy.float32],
5608 "double":['d', numpy.float64]}
5609
5610 rawPixelsStore = self._prepareRawPixelsStore()
5611 sizeX = self.sizeX
5612 sizeY = self.sizeY
5613 pixelType = self.getPixelsType().value
5614 numpyType = pixelTypes[pixelType][1]
5615 exc = None
5616 try:
5617 for zctTile in zctTileList:
5618 z,c,t,tile = zctTile
5619 if tile is None:
5620 rawPlane = rawPixelsStore.getPlane(z, c, t)
5621 planeY = sizeY
5622 planeX = sizeX
5623 else:
5624 x, y, width, height = tile
5625 rawPlane = rawPixelsStore.getTile(z, c, t, x, y, width, height)
5626 planeY = height
5627 planeX = width
5628 convertType ='>%d%s' % ((planeY*planeX), pixelTypes[pixelType][0])
5629 convertedPlane = unpack(convertType, rawPlane)
5630 remappedPlane = numpy.array(convertedPlane, numpyType)
5631 remappedPlane.resize(planeY, planeX)
5632 yield remappedPlane
5633 except Exception, e:
5634 logger.error("Failed to getPlane() or getTile() from rawPixelsStore", exc_info=True)
5635 exc = e
5636 try:
5637 rawPixelsStore.close()
5638 except Exception, e:
5639 logger.error("Failed to close rawPixelsStore", exc_info=True)
5640 if exc is None:
5641 exc = e
5642 if exc is not None:
5643 raise exc
5644
5645 - def getTile (self, theZ=0, theC=0, theT=0, tile=None):
5646 """
5647 Gets the specified plane as a 2D numpy array by calling L{getPlanes}
5648 If a range of tile are required, L{getTiles} is approximately 30% faster.
5649 """
5650 tileList = list( self.getTiles([(theZ, theC, theT, tile)]) )
5651 return tileList[0]
5652
5653 PixelsWrapper = _PixelsWrapper
5657 """
5658 omero_model_FilesetI class wrapper extends BlitzObjectWrapper
5659 """
5660
5663
5665 """
5666 Used for building queries in generic methods such as getObjects("Fileset")
5667 """
5668 return "select obj from Fileset obj "\
5669 "left outer join fetch obj.images as image "\
5670 "left outer join fetch obj.usedFiles as usedFile " \
5671 "join fetch usedFile.originalFile"
5672
5674 """ Returns a list of L{ImageWrapper} linked to this Fileset """
5675 return [ImageWrapper(self._conn, i) for i in self._obj.copyImages()]
5676
5678 """ Returns a list of L{OriginalFileWrapper} linked to this Fileset via Fileset Entries """
5679 return [OriginalFileWrapper(self._conn, f.originalFile) for f in self._obj.copyUsedFiles()]
5680
5681 FilesetWrapper = _FilesetWrapper
5685 """
5686 omero_model_ChannelI class wrapper extends BlitzObjectWrapper.
5687 """
5688
5689 BLUE_MIN = 400
5690 BLUE_MAX = 500
5691 GREEN_MIN = 501
5692 GREEN_MAX = 600
5693 RED_MIN = 601
5694 RED_MAX = 700
5695 COLOR_MAP = ((BLUE_MIN, BLUE_MAX, ColorHolder('Blue')),
5696 (GREEN_MIN, GREEN_MAX, ColorHolder('Green')),
5697 (RED_MIN, RED_MAX, ColorHolder('Red')),
5698 )
5699
5702
5704 """
5705 Sets values of idx, re and img
5706 """
5707 self._re = re
5708 self._idx = idx
5709 self._img = img
5710
5712 """
5713 Extends the superclass save method to save Pixels. Returns result of saving superclass (TODO: currently this is None)
5714 """
5715
5716 self._obj.setPixels(omero.model.PixelsI(self._obj.getPixels().getId(), False))
5717 return super(_ChannelWrapper, self).save()
5718
5720 """
5721 Returns True if the channel is active (turned on in rendering settings)
5722
5723 :return: True if Channel is Active
5724 :rtype: Boolean
5725 """
5726
5727 if self._re is None:
5728 return False
5729 return self._re.isActive(self._idx, self._conn.SERVICE_OPTS)
5730
5732 """
5733 Returns the logical channel
5734
5735 :return: Logical Channel
5736 :rtype: L{LogicalChannelWrapper}
5737 """
5738
5739 if self._obj.logicalChannel is not None:
5740 return LogicalChannelWrapper(self._conn, self._obj.logicalChannel)
5741
5743 """
5744 Returns the logical channel name, emission wave or index. The first that is not null
5745 in the described order.
5746
5747 :return: The logical channel string representation
5748 :rtype: String
5749 """
5750
5751 lc = self.getLogicalChannel()
5752 rv = lc.name
5753 if rv is None or len(rv.strip())==0:
5754 rv = lc.emissionWave
5755 if rv is None or len(unicode(rv).strip())==0:
5756 rv = self._idx
5757 return unicode(rv)
5758
5759
5761 """
5762 Returns the logical channel name or None
5763
5764 :return: The logical channel string representation
5765 :rtype: String
5766 """
5767
5768 lc = self.getLogicalChannel()
5769 rv = lc.name
5770 if rv is not None:
5771 return unicode(rv)
5772
5773
5775 """
5776 Returns the emission wave or None.
5777
5778 :return: Emission wavelength or None
5779 :rtype: int
5780 """
5781
5782 lc = self.getLogicalChannel()
5783 return lc.emissionWave
5784
5786 """
5787 Returns the excitation wave or None.
5788
5789 :return: Excitation wavelength or None
5790 :rtype: int
5791 """
5792
5793 lc = self.getLogicalChannel()
5794 return lc.excitationWave
5795
5797 """
5798 Returns the rendering settings color of this channel
5799
5800 :return: Channel color
5801 :rtype: L{ColorHolder}
5802 """
5803
5804 if self._re is None:
5805 return None
5806 return ColorHolder.fromRGBA(*self._re.getRGBA(self._idx, self._conn.SERVICE_OPTS))
5807
5809 """
5810 Returns the rendering settings window-start of this channel
5811
5812 :return: Window start
5813 :rtype: int
5814 """
5815
5816 return self._re.getChannelWindowStart(self._idx, self._conn.SERVICE_OPTS)
5817
5820
5822 """
5823 Returns the rendering settings window-end of this channel
5824
5825 :return: Window end
5826 :rtype: int
5827 """
5828
5829 return self._re.getChannelWindowEnd(self._idx, self._conn.SERVICE_OPTS)
5830
5833
5835 self._re.setChannelWindow(self._idx, float(minval), float(maxval), self._conn.SERVICE_OPTS)
5836
5838 """
5839 Returns the minimum pixel value of the channel
5840
5841 :return: Min pixel value
5842 :rtype: double
5843 """
5844 si = self._obj.getStatsInfo()
5845 if si is None:
5846 logger.error("getStatsInfo() is null. See #9695")
5847 try:
5848 minVals = {'int8':-128, 'uint8':0, 'int16':-32768, 'uint16':0, 'int32':-32768,
5849 'uint32':0, 'float':-32768, 'double':-32768}
5850 pixtype = self._obj.getPixels().getPixelsType().getValue().getValue()
5851 return minVals[pixtype]
5852 except:
5853 return None
5854 return si.getGlobalMin().val
5855
5857 """
5858 Returns the maximum pixel value of the channel
5859
5860 :return: Min pixel value
5861 :rtype: double
5862 """
5863 si = self._obj.getStatsInfo()
5864 if si is None:
5865 logger.error("getStatsInfo() is null. See #9695")
5866 try:
5867 maxVals = {'int8':127, 'uint8':255, 'int16':32767, 'uint16':65535, 'int32':32767,
5868 'uint32':65535, 'float':32767, 'double':32767}
5869 pixtype = self._obj.getPixels().getPixelsType().getValue().getValue()
5870 return maxVals[pixtype]
5871 except:
5872 return None
5873 return si.getGlobalMax().val
5874
5875 ChannelWrapper = _ChannelWrapper
5878 """
5879 Function decorator to make sure that rendering engine is prepared before
5880 call. Is configurable by various options.
5881 """
5882
5883 - def __init__(self, onPrepareFailureReturnNone=True, ignoreExceptions=None):
5884 """
5885 Initialises the decorator.
5886
5887 :param onPrepareFailureReturnNone: Whether or not on a failure to
5888 prepare the rendering engine the decorator should return 'None' or
5889 allow the execution of the decorated function or method. Defaults to
5890 'True'.
5891 :type onPrepareFailureReturnNone: Boolean
5892 :param ignoreExceptions: A set of exceptions thrown during the
5893 preparation of the rendering engine for whith the decorator should
5894 ignore and allow the execution of the decorated function or method.
5895 Defaults to 'None'.
5896 :type ignoreExceptions: Set
5897 """
5898 self.onPrepareFailureReturnNone = onPrepareFailureReturnNone
5899 self.ignoreExceptions = ignoreExceptions
5900
5902 """
5903 Tries to prepare rendering engine, then calls function and return the
5904 result.
5905 """
5906 def wrapped(self, *args, **kwargs):
5907 try:
5908 if not self._prepareRenderingEngine() \
5909 and ctx.onPrepareFailureReturnNone:
5910 logger.debug('Preparation of rendering engine failed, ' \
5911 'returning None for %r!' % f)
5912 return None
5913 except ctx.ignoreExceptions:
5914 logger.debug('Ignoring exception thrown during preparation ' \
5915 'of rendering engine for %r!' % f, exc_info=True)
5916 pass
5917 return f(self, *args, **kwargs)
5918 return wrapped
5919
5921 """
5922 Function decorator to make sure that pixels are loaded before call
5923
5924 :param func: Function
5925 :type func: Function
5926 :return: Decorated function
5927 :rtype: Function
5928 """
5929
5930 def wrapped (self, *args, **kwargs):
5931 """ Tries to load pixels, then call function and return the result"""
5932
5933 if not self._loadPixels():
5934 return None
5935 return func(self, *args, **kwargs)
5936 return wrapped
5937
5940 """
5941 omero_model_ImageI class wrapper extends BlitzObjectWrapper.
5942 """
5943
5944 _re = None
5945 _pd = None
5946 _rm = {}
5947 _pixels = None
5948 _archivedFileCount = None
5949 _filesetFileCount = None
5950 _importedFilesInfo = None
5951
5952 _pr = None
5953 _prStart = None
5954 _prEnd = None
5955
5956 _invertedAxis = False
5957
5958 PROJECTIONS = {
5959 'normal': -1,
5960 'intmax': omero.constants.projection.ProjectionType.MAXIMUMINTENSITY,
5961 'intmean': omero.constants.projection.ProjectionType.MEANINTENSITY,
5962 'intsum': omero.constants.projection.ProjectionType.SUMINTENSITY,
5963 }
5964
5965 PLANEDEF = omero.romio.XY
5966
5967 @classmethod
5969 """
5970 Creates a new Image wrapper with the image specified by pixels ID
5971
5972 :param conn: The connection
5973 :type conn: L{BlitzGateway}
5974 :param pid: Pixles ID
5975 :type pid: Long
5976 :return: New Image wrapper
5977 :rtype: L{ImageWrapper}
5978 """
5979
5980 q = conn.getQueryService()
5981 p = q.find('Pixels', pid, self._conn.SERVICE_OPTS)
5982 if p is None:
5983 return None
5984 return ImageWrapper(conn, p.image)
5985
5992
5995
6000
6002 """
6003 Returns the Instrument for this image (or None) making sure the instrument is loaded.
6004
6005 :return: Instrument (microscope)
6006 :rtype: L{InstrumentWrapper}
6007 """
6008
6009 i = self._obj.instrument
6010 if i is None:
6011 return None
6012 if not i.loaded:
6013 meta_serv = self._conn.getMetadataService()
6014 ctx = self._conn.SERVICE_OPTS.copy()
6015 if ctx.getOmeroGroup() is None:
6016 ctx.setOmeroGroup(-1)
6017 i = self._obj.instrument = meta_serv.loadInstrument(i.id.val, ctx)
6018 return InstrumentWrapper(self._conn, i)
6019
6021 """
6022 Checks that pixels are loaded
6023
6024 :return: True if loaded
6025 :rtype: Boolean
6026 """
6027
6028 if not self._obj.pixelsLoaded:
6029 self.__loadedHotSwap__()
6030 return self._obj.sizeOfPixels() > 0
6031
6032
6034 """
6035 Return a rendering def ID based on custom logic.
6036
6037 :return: Rendering definition ID or None if no custom
6038 logic has found a rendering definition.
6039 """
6040 rdefns = self._conn.CONFIG.IMG_RDEFNS
6041 if rdefns is None:
6042 return
6043 ann = self.getAnnotation(rdefns)
6044 rdid = ann and ann.getValue() or None
6045 if rdid is None:
6046 return
6047 logger.debug('_getRDef: %s, annid=%d' % (str(rdid), ann.getId()))
6048 logger.debug('now load render options: %s' % str(self._loadRenderOptions()))
6049 self.loadRenderOptions()
6050 return rdid
6051
6053 """
6054 Called whenever a reset defaults is called by the preparation of
6055 the rendering engine or the thumbnail bean.
6056
6057 :param rdid: Current Rendering Def ID
6058 :type rdid: Long
6059 """
6060 rdefns = self._conn.CONFIG.IMG_RDEFNS
6061 if rdefns is None:
6062 return
6063 ann = self.getAnnotation(rdefns)
6064 if ann is None:
6065 a = LongAnnotationWrapper(self)
6066 a.setNs(rdefns)
6067 a.setValue(rdid)
6068 self.linkAnnotation(a, sameOwner=False)
6069
6071 """
6072 Prepare the rendering engine with pixels ID and existing or new rendering def.
6073
6074 :return: The Rendering Engine service
6075 :rtype: L{ProxyObjectWrapper}
6076 """
6077
6078 pid = self.getPrimaryPixels().id
6079 re = self._conn.createRenderingEngine()
6080 ctx = self._conn.SERVICE_OPTS.copy()
6081
6082 ctx.setOmeroGroup(self.details.group.id.val)
6083
6084
6085 re.lookupPixels(pid, ctx)
6086 if rdid is None:
6087 rdid = self._getRDef()
6088 if rdid is None:
6089 if not re.lookupRenderingDef(pid, ctx):
6090 re.resetDefaults(ctx)
6091 re.lookupRenderingDef(pid, ctx)
6092 self._onResetDefaults(re.getRenderingDefId(ctx))
6093 else:
6094 re.loadRenderingDef(rdid, ctx)
6095 re.load(ctx)
6096 return re
6097
6099 """
6100 Checks that the rendering engine is prepared, calling L{_prepareRE} if needed.
6101 Used by the L{assert_re} method to wrap calls requiring rendering engine
6102
6103 :return: True if rendering engine is created
6104 :rtype: Boolean
6105 """
6106
6107 self._loadPixels()
6108 if self._re is None:
6109 if self._obj.sizeOfPixels() < 1:
6110 return False
6111 if self._pd is None:
6112 self._pd = omero.romio.PlaneDef(self.PLANEDEF)
6113 try:
6114 self._re = self._prepareRE(rdid=rdid)
6115 except omero.ValidationException:
6116 logger.debug('on _prepareRE()', exc_info=True)
6117 self._re = None
6118 return self._re is not None
6119
6136
6138 """
6139 Creates a dict representation of the Image, including author and date info.
6140
6141 :param xtra: controls the optional parts of simpleMarshal;
6142 - thumbUrlPrefix - allows customizing the thumb URL by
6143 either a static string prefix or a callable function
6144 that will take a single ImgId int argument and return the
6145 customized URL string
6146 - tiled - if passed and value evaluates to true, add
6147 information on whether this image is tiled on this server.
6148 :type: Dict
6149 :return: Dict
6150 :rtype: Dict
6151 """
6152
6153 rv = super(_ImageWrapper, self).simpleMarshal(xtra=xtra, parents=parents)
6154 rv.update({'author': self.getAuthor(),
6155 'date': time.mktime(self.getDate().timetuple()),})
6156 if xtra:
6157 if 'thumbUrlPrefix' in xtra:
6158 if callable(xtra['thumbUrlPrefix']):
6159 rv['thumb_url'] = xtra['thumbUrlPrefix'](str(self.id))
6160 else:
6161 rv['thumb_url'] = xtra['thumbUrlPrefix'] + str(self.id) + '/'
6162 if xtra.get('tiled', False):
6163
6164 maxplanesize = self._conn.getMaxPlaneSize()
6165 rv['size'] = {'width': self.getSizeX(),
6166 'height': self.getSizeY(),
6167 }
6168 if rv['size']['height'] and rv['size']['width']:
6169 rv['tiled'] = (rv['size']['height'] * rv['size']['width']) > (maxplanesize[0] * maxplanesize[1])
6170 else:
6171 rv['tiles'] = False
6172
6173 return rv
6174
6176 """
6177 Returns the stage label or None
6178
6179 :return: Stage label
6180 :rtype: L{ImageStageLabelWrapper}
6181 """
6182
6183 if self._obj.stageLabel is None:
6184 return None
6185 else:
6186 return ImageStageLabelWrapper(self._conn, self._obj.stageLabel)
6187
6189 """
6190 Provides a truncated name of the image. E.g. ...catedNameOfTheImage.tiff
6191
6192 :param length: The ideal length to return. If truncated, will be ...length
6193 :type length: Int
6194 :param hist: The amount of leeway allowed before trunction (avoid truncating 1 or 2 letters)
6195 :type hist: Int
6196 :return: Truncated ...name
6197 :type: String
6198 """
6199
6200 name = self.name
6201 if not name:
6202 return ""
6203 l = len(name)
6204 if l < length+hist:
6205 return name
6206 return "..." + name[l - length:]
6207
6209 """
6210 Returns 'Firstname Lastname' of image owner
6211
6212 :return: Image owner
6213 :rtype: String
6214 """
6215
6216 q = self._conn.getQueryService()
6217 e = q.findByQuery("select e from Experimenter e where e.id = %i" % self._obj.details.owner.id.val,None, self._conn.SERVICE_OPTS)
6218 self._author = e.firstName.val + " " + e.lastName.val
6219 return self._author
6220
6222 """
6223 XXX: Deprecated since 4.3.2, use listParents(). (See #6660)
6224 Gets the Dataset that image is in, or None.
6225 Returns None if Image is in more than one Dataset.
6226
6227 :return: Dataset
6228 :rtype: L{DatasetWrapper}
6229 """
6230
6231 try:
6232 q = """
6233 select ds from Image i join i.datasetLinks dl join dl.parent ds
6234 where i.id = %i
6235 """ % self._obj.id.val
6236 query = self._conn.getQueryService()
6237 ds = query.findAllByQuery(q, None, self._conn.SERVICE_OPTS)
6238 if ds and len(ds) == 1:
6239 return DatasetWrapper(self._conn, ds[0])
6240 except:
6241 logger.debug('on getDataset')
6242 logger.debug(traceback.format_exc())
6243 return None
6244
6246 """
6247 Gets the Project that image is in, or None. TODO: Assumes image is in only 1 Project. Why not use getAncestory()[-1]
6248 Returns None if Image is in more than one Dataset & Project.
6249
6250 :return: Project
6251 :rtype: L{ProjectWrapper}
6252 """
6253
6254 try:
6255 q = """
6256 select p from Image i join i.datasetLinks dl join dl.parent ds join ds.projectLinks pl join pl.parent p
6257 where i.id = %i
6258 """ % self._obj.id.val
6259 query = self._conn.getQueryService()
6260 prj = query.findAllByQuery(q,None, self._conn.SERVICE_OPTS)
6261 if prj and len(prj) == 1:
6262 return ProjectWrapper(self._conn, prj[0])
6263 except:
6264 logger.debug('on getProject')
6265 logger.debug(traceback.format_exc())
6266 return None
6267
6269 """
6270 If the image is in a Plate/Well hierarchy, returns the parent Plate, otherwise None
6271
6272 :return: Plate
6273 :rtype: L{PlateWrapper}
6274 """
6275
6276 params = omero.sys.Parameters()
6277 params.map = {}
6278 params.map["oid"] = omero.rtypes.rlong(self.getId())
6279 query = "select well from Well as well "\
6280 "join fetch well.details.creationEvent "\
6281 "join fetch well.details.owner join fetch well.details.group " \
6282 "join fetch well.plate as pt "\
6283 "left outer join fetch well.wellSamples as ws " \
6284 "left outer join fetch ws.image as img "\
6285 "where ws.image.id = :oid"
6286 q = self._conn.getQueryService()
6287 for well in q.findAllByQuery(query, params):
6288 return PlateWrapper(self._conn, well.plate)
6289
6291 """
6292 Gets the Ojbective Settings of the Image, or None
6293
6294 :return: Objective Settings
6295 :rtype: L{ObjectiveSettingsWrapper}
6296 """
6297
6298 rv = self.objectiveSettings
6299 if self.objectiveSettings is not None:
6300 rv = ObjectiveSettingsWrapper(self._conn, self.objectiveSettings)
6301 if not self.objectiveSettings.loaded:
6302 self.objectiveSettings = rv._obj
6303 return rv
6304
6306 """
6307 Gets the Imaging Environment of the Image, or None
6308
6309 :return: Imaging Environment
6310 :rtype: L{ImagingEnvironmentWrapper}
6311 """
6312
6313 rv = self.imagingEnvironment
6314 if self.imagingEnvironment is not None:
6315 rv = ImagingEnvironmentWrapper(self._conn, self.imagingEnvironment)
6316 if not self.imagingEnvironment.loaded:
6317 self.imagingEnvironment = rv._obj
6318 return rv
6319
6320 @assert_pixels
6322 """
6323 Returns the Primary Pixels ID for the image.
6324
6325 :return: Pixels ID
6326 :rtype: Long
6327 """
6328
6329 return self._obj.getPrimaryPixels().getId().val
6330
6331
6333 """
6334 Prepares Thumbnail Store for the image.
6335
6336 :param _r: If True, don't reset default rendering (return None if no rDef exists)
6337 :type _r: Boolean
6338 :return: Thumbnail Store or None
6339 :rtype: L{ProxyObjectWrapper}
6340 """
6341
6342 pid = self.getPrimaryPixels().id
6343 rdid = self._getRDef()
6344 tb = self._conn.createThumbnailStore()
6345
6346 ctx = self._conn.SERVICE_OPTS.copy()
6347 ctx.setOmeroGroup(self.details.group.id.val)
6348 has_rendering_settings = tb.setPixelsId(pid, ctx)
6349 logger.debug("tb.setPixelsId(%d) = %s " % (pid, str(has_rendering_settings)))
6350 if rdid is not None:
6351 try:
6352 tb.setRenderingDefId(rdid, ctx)
6353 except omero.ValidationException:
6354
6355 logger.error('IMG %d, defrdef == %d but object does not exist?' % (self.getId(), rdid))
6356 rdid = None
6357 if rdid is None:
6358 if not has_rendering_settings:
6359 if self._conn.canBeAdmin():
6360 ctx.setOmeroUser(self.details.owner.id.val)
6361 try:
6362 tb.resetDefaults(ctx)
6363 except omero.ConcurrencyException, ce:
6364 logger.info( "ConcurrencyException: resetDefaults() failed in _prepareTB with backOff: %s" % ce.backOff)
6365 return tb
6366 tb.setPixelsId(pid, ctx)
6367 try:
6368 rdid = tb.getRenderingDefId(ctx)
6369 except omero.ApiUsageException:
6370 logger.info( "ApiUsageException: getRenderingDefId() failed in _prepareTB")
6371 return tb
6372 self._onResetDefaults(rdid)
6373 return tb
6374
6409
6410 @assert_re()
6412 """
6413 Returns a string holding a rendered JPEG of the projected image, sized to mimic a thumbnail.
6414 This is an 'internal' method of this class, used to generate a thumbnail from a full-sized
6415 projected image (since thumbnails don't support projection). SetProjection should be called
6416 before this method is called, so that this returns a projected, scaled image.
6417
6418 :param size: The length of the longest size, in a list or tuple. E.g. (100,)
6419 :type size: list or tuple
6420 :param pos: The (z, t) position
6421 :type pos: Tuple (z,t)
6422 """
6423
6424 if pos is None:
6425 t = z = 0
6426 else:
6427 z, t = pos
6428 img = self.renderImage(z,t)
6429 if len(size) == 1:
6430 w = self.getSizeX()
6431 h = self.getSizeY()
6432 ratio = float(w) / h
6433 if ratio > 1:
6434 h = h * size[0] / w
6435 w = size[0]
6436 else:
6437 w = w * size[0] / h
6438 h = size[0]
6439 img = img.resize((w,h), Image.NEAREST)
6440 rv = StringIO()
6441 img.save(rv, 'jpeg', quality=70)
6442 return rv.getvalue()
6443
6444
6445 - def getThumbnail (self, size=(64,64), z=None, t=None, direct=True):
6446 """
6447 Returns a string holding a rendered JPEG of the thumbnail.
6448
6449 :type size: tuple or number
6450 :param size: A tuple with one or two ints, or an integer. If a tuple holding a single int,
6451 or a single int is passed as param, then that will be used as the longest size
6452 on the rendered thumb, and image aspect ratio is kept.
6453 If two ints are passed in a tuple, they set the width and height of the
6454 rendered thumb.
6455 :type z: number
6456 :param z: the Z position to use for rendering the thumbnail. If not provided default is used.
6457 :type t: number
6458 :param t: the T position to use for rendering the thumbnail. If not provided default is used.
6459 :param direct: If true, force creation of new thumbnail (don't use cached)
6460 :rtype: string or None
6461 :return: the rendered JPEG, or None if there was an error.
6462 """
6463 tb = None
6464 try:
6465 tb = self._prepareTB()
6466 if tb is None:
6467 return None
6468 if isinstance(size, IntType):
6469 size = (size,)
6470 if z is not None and t is not None:
6471 pos = z,t
6472 else:
6473 pos = None
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489 if self.getProjection() != 'normal':
6490 return self._getProjectedThumbnail(size, pos)
6491 if len(size) == 1:
6492 if pos is None:
6493 if direct:
6494 thumb = tb.getThumbnailByLongestSideDirect
6495 else:
6496 thumb = tb.getThumbnailByLongestSide
6497 else:
6498 thumb = tb.getThumbnailForSectionByLongestSideDirect
6499 else:
6500 if pos is None:
6501 if direct:
6502 thumb = tb.getThumbnailDirect
6503 else:
6504 thumb = tb.getThumbnail
6505 else:
6506 thumb = tb.getThumbnailForSectionDirect
6507 args = map(lambda x: rint(x), size)
6508 if pos is not None:
6509 args = list(pos) + args
6510 ctx = self._conn.SERVICE_OPTS.copy()
6511 ctx.setOmeroGroup(self.details.group.id.val)
6512 args += [ctx]
6513 rv = thumb(*args)
6514 self._thumbInProgress = tb.isInProgress()
6515 tb.close()
6516 return rv
6517 except Exception:
6518 logger.error(traceback.format_exc())
6519 if tb is not None:
6520 tb.close()
6521 return None
6522
6523 @assert_pixels
6525 """
6526 Returns (min, max) values for the pixels type of this image.
6527 TODO: Does not handle floats correctly, though.
6528
6529 :return: Tuple (min, max)
6530 """
6531
6532 pixels_id = self._obj.getPrimaryPixels().getId().val
6533 rp = self._conn.createRawPixelsStore()
6534 rp.setPixelsId(pixels_id, True, self._conn.SERVICE_OPTS)
6535 pmax = 2 ** (8 * rp.getByteWidth())
6536 if rp.isSigned():
6537 return (-(pmax / 2), pmax / 2 - 1)
6538 else:
6539 return (0, pmax-1)
6540
6541 @assert_pixels
6547
6548 @assert_pixels
6550 """
6551 Loads pixels and returns object in a L{PixelsWrapper}
6552 """
6553 return PixelsWrapper(self._conn, self._obj.getPrimaryPixels())
6554
6555 @assert_re(ignoreExceptions=(omero.ConcurrencyException))
6557 """
6558 Returns a list of Channels, each initialised with rendering engine
6559
6560 :return: Channels
6561 :rtype: List of L{ChannelWrapper}
6562 """
6563 if self._re is not None:
6564 return [ChannelWrapper(self._conn, c, idx=n, re=self._re, img=self) for n,c in enumerate(self._re.getPixels(self._conn.SERVICE_OPTS).iterateChannels())]
6565 else:
6566 pid = self.getPixelsId()
6567 params = omero.sys.Parameters()
6568 params.map = {"pid": rlong(pid)}
6569 query = "select p from Pixels p join fetch p.channels as c join fetch c.logicalChannel as lc where p.id=:pid"
6570 pixels = self._conn.getQueryService().findByQuery(query, params, self._conn.SERVICE_OPTS)
6571 return [ChannelWrapper(self._conn, c, idx=n, re=self._re, img=self) for n,c in enumerate(pixels.iterateChannels())]
6572
6573 @assert_re()
6575 """
6576 Returns a dict of zoomLevels:scale (fraction) for tiled 'Big' images.
6577 E.g. {0: 1.0, 1: 0.25, 2: 0.062489446727078291, 3: 0.031237687848258006}
6578 Returns None if this image doesn't support tiles.
6579 """
6580 if not self._re.requiresPixelsPyramid():
6581 return None
6582 levels = self._re.getResolutionDescriptions()
6583 rv = {}
6584 sizeXList = [level.sizeX for level in levels]
6585 for i, level in enumerate(sizeXList):
6586 rv[i] = float(level)/sizeXList[0]
6587 return rv
6588
6590 """
6591 Sets the active channels on the rendering engine.
6592 Also sets rendering windows and channel colors (for channels that are active)
6593
6594 Examples:
6595 # Turn first channel ON, others OFF
6596 image.setActiveChannels([1])
6597 # First OFF, second ON, windows and colors for both
6598 image.setActiveChannels([-1, 2], [[20, 300], [50, 500]], ['00FF00', 'FF0000'])
6599 # Second Channel ON with windows. All others OFF
6600 image.setActiveChannels([2], [[20, 300]])
6601
6602 :param channels: List of active channel indexes ** 1-based index **
6603 :type channels: List of int
6604 :param windows: Start and stop values for active channel rendering settings
6605 :type windows: List of [start, stop]. [[20, 300], [None, None], [50, 500]]. Must be list for each channel
6606 :param colors: List of colors. ['F00', None, '00FF00']. Must be item for each channel
6607 """
6608 abs_channels = [abs(c) for c in channels]
6609 idx = 0
6610 for c in range(len(self.getChannels())):
6611 self._re.setActive(c, (c+1) in channels, self._conn.SERVICE_OPTS)
6612 if (c+1) in channels:
6613 if windows is not None and windows[idx][0] is not None and windows[idx][1] is not None:
6614 self._re.setChannelWindow(c, float(windows[idx][0]), float(windows[idx][1]), self._conn.SERVICE_OPTS)
6615 if colors is not None and colors[idx]:
6616 rgba = splitHTMLColor(colors[idx])
6617 if rgba:
6618 self._re.setRGBA(c, *(rgba + [self._conn.SERVICE_OPTS]))
6619 if (c+1 in abs_channels):
6620 idx += 1
6621 return True
6622
6624 """
6625 Returns list of available keys for projection. E.g. ['intmax', 'intmean']
6626
6627 :return: Projection options
6628 :rtype: List of strings
6629 """
6630
6631 return self.PROJECTIONS.keys()
6632
6634 """
6635 Returns the current projection option (checking it is valid).
6636
6637 :return: Projection key. E.g. 'intmax'
6638 :rtype: String
6639 """
6640
6641 if self._pr in self.PROJECTIONS.keys():
6642 return self._pr
6643 return 'normal'
6644
6646 """
6647 Sets the current projection option.
6648
6649 :param proj: Projection Option. E.g. 'intmax' or 'normal'
6650 :type proj: String
6651 """
6652
6653 self._pr = proj
6654
6656 """
6657 Gets the range used for Z-projection as tuple (proStart, proEnd)
6658 """
6659 return (self._prStart, self._prEnd)
6660
6662 """
6663 Sets the range used for Z-projection. Will only be used
6664 if E.g. setProjection('intmax') is not 'normal'
6665 """
6666 if projStart is not None:
6667 projStart = max(0, int(projStart))
6668 if projEnd is not None:
6669 projEnd = min(int(projEnd), self.getSizeZ()-1)
6670 self._prStart = projStart
6671 self._prEnd = projEnd
6672
6674 """
6675 Returns the inverted axis flag
6676
6677 :return: Inverted Axis
6678 :rtype: Boolean
6679 """
6680
6681 return self._invertedAxis
6682
6684 """
6685 Sets the inverted axis flag
6686
6687 :param inverted: Inverted Axis
6688 :type inverted: Boolean
6689 """
6690
6691 self._invertedAxis = inverted
6692
6693 LINE_PLOT_DTYPES = {
6694 (4, True, True): 'f',
6695 (2, False, False): 'H',
6696 (2, False, True): 'h',
6697 (1, False, False): 'B',
6698 (1, False, True): 'b',
6699 }
6700
6701 - def getPixelLine (self, z, t, pos, axis, channels=None, range=None):
6702 """
6703 Grab a horizontal or vertical line from the image pixel data, for the specified channels
6704 (or 'active' if not specified) and using the specified range (or 1:1 relative to the image size).
6705 Axis may be 'h' or 'v', for horizontal or vertical respectively.
6706
6707 :param z: Z index
6708 :param t: T index
6709 :param pos: X or Y position
6710 :param axis: Axis 'h' or 'v'
6711 :param channels: map of {index: L{ChannelWrapper} }
6712 :param range: height of scale (use image height (or width) by default)
6713 :return: rv List of lists (one per channel)
6714 """
6715
6716 if not self._loadPixels():
6717 logger.debug( "No pixels!")
6718 return None
6719 axis = axis.lower()[:1]
6720 if channels is None:
6721 channels = map(lambda x: x._idx, filter(lambda x: x.isActive(), self.getChannels()))
6722 if range is None:
6723 range = axis == 'h' and self.getSizeY() or self.getSizeX()
6724 if not isinstance(channels, (TupleType, ListType)):
6725 channels = (channels,)
6726 chw = map(lambda x: (x.getWindowMin(), x.getWindowMax()), self.getChannels())
6727 rv = []
6728 pixels_id = self._obj.getPrimaryPixels().getId().val
6729 rp = self._conn.createRawPixelsStore()
6730 rp.setPixelsId(pixels_id, True, self._conn.SERVICE_OPTS)
6731 for c in channels:
6732 bw = rp.getByteWidth()
6733 key = self.LINE_PLOT_DTYPES.get((bw, rp.isFloat(), rp.isSigned()), None)
6734 if key is None:
6735 logger.error("Unknown data type: " + str((bw, rp.isFloat(), rp.isSigned())))
6736 plot = array.array(key, axis == 'h' and rp.getRow(pos, z, c, t) or rp.getCol(pos, z, c, t))
6737 plot.byteswap()
6738
6739 offset = -chw[c][0]
6740 if offset != 0:
6741 plot = map(lambda x: x+offset, plot)
6742 try:
6743 normalize = 1.0/chw[c][1]*(range-1)
6744 except ZeroDivisionError:
6745
6746 continue
6747 if normalize != 1.0:
6748 plot = map(lambda x: x*normalize, plot)
6749 if isinstance(plot, array.array):
6750 plot = plot.tolist()
6751 rv.append(plot)
6752 return rv
6753
6754
6755 - def getRow (self, z, t, y, channels=None, range=None):
6756 """
6757 Grab a horizontal line from the image pixel data, for the specified channels (or active ones)
6758
6759 :param z: Z index
6760 :param t: T index
6761 :param y: Y position of row
6762 :param channels: map of {index: L{ChannelWrapper} }
6763 :param range: height of scale (use image height by default)
6764 :return: rv List of lists (one per channel)
6765 """
6766
6767 return self.getPixelLine(z,t,y,'h',channels,range)
6768
6769 - def getCol (self, z, t, x, channels=None, range=None):
6770 """
6771 Grab a horizontal line from the image pixel data, for the specified channels (or active ones)
6772
6773 :param z: Z index
6774 :param t: T index
6775 :param x: X position of column
6776 :param channels: map of {index: L{ChannelWrapper} }
6777 :param range: height of scale (use image width by default)
6778 :return: rv List of lists (one per channel)
6779 """
6780
6781 return self.getPixelLine(z,t,x,'v',channels,range)
6782
6783 @assert_re()
6785 """
6786 Gets a list of available rendering models.
6787
6788 :return: Rendering models
6789 :rtype: List of L{BlitzObjectWrapper}
6790 """
6791
6792 if not len(self._rm):
6793 for m in [BlitzObjectWrapper(self._conn, m) for m in self._re.getAvailableModels()]:
6794 self._rm[m.value.lower()] = m
6795 return self._rm.values()
6796
6797 @assert_re()
6799 """
6800 Get the current rendering model.
6801
6802 :return: Rendering model
6803 :rtype: L{BlitzObjectWrapper}
6804 """
6805
6806 return BlitzObjectWrapper(self._conn, self._re.getModel())
6807
6809 """
6810 Sets the Greyscale rendering model on this image's current renderer
6811 """
6812
6813 rm = self.getRenderingModels()
6814 self._re.setModel(self._rm.get('greyscale', rm[0])._obj)
6815
6817 """
6818 Sets the HSB rendering model on this image's current renderer
6819 """
6820
6821 rm = self.getRenderingModels()
6822 self._re.setModel(self._rm.get('rgb', rm[0])._obj)
6823
6825 """
6826 Returns True if the current rendering model is 'greyscale'
6827
6828 :return: isGreyscale
6829 :rtype: Boolean
6830 """
6831 return self.getRenderingModel().value.lower() == 'greyscale'
6832
6833 @assert_re()
6835 """
6836 Returns the data from rendering the bird's eye view of the image.
6837
6838 :param size: Maximum size of the longest side of the resulting bird's eye view.
6839 :return: Data containing a bird's eye view jpeg
6840 """
6841
6842 re = self._prepareRE()
6843 z = re.getDefaultZ()
6844 t = re.getDefaultT()
6845 x = 0
6846 y = 0
6847 size_x = self.getSizeX()
6848 size_y = self.getSizeY()
6849 tile_width, tile_height = re.getTileSize()
6850 tiles_wide = math.ceil(float(size_x) / tile_width)
6851 tiles_high = math.ceil(float(size_y) / tile_height)
6852
6853
6854
6855
6856
6857 for i in range(1, re.getResolutionLevels()):
6858 tile_width = round(tile_width / 2.0)
6859 tile_height = round(tile_height / 2.0)
6860 width = int(tiles_wide * tile_width)
6861 height = int(tiles_high * tile_height)
6862 jpeg_data = self.renderJpegRegion(z, t, x, y, width, height, level=0)
6863 if size is None:
6864 return jpeg_data
6865
6866
6867
6868 ratio = float(size) / max(width, height)
6869 if width > height:
6870 size = (int(size), int(height * ratio))
6871 else:
6872 size = (int(width * ratio), int(size))
6873 jpeg_data = Image.open(StringIO(jpeg_data))
6874 jpeg_data.thumbnail(size, Image.ANTIALIAS)
6875 ImageDraw.Draw(jpeg_data)
6876 f = StringIO()
6877 jpeg_data.save(f, "JPEG")
6878 f.seek(0)
6879 return f.read()
6880
6881 @assert_re()
6882 - def renderJpegRegion (self, z, t, x, y, width, height, level=None, compression=0.9):
6883 """
6884 Return the data from rendering a region of an image plane.
6885 NB. Projection not supported by the API currently.
6886
6887 :param z: The Z index. Ignored if projecting image.
6888 :param t: The T index.
6889 :param x: The x coordinate of region (int)
6890 :param y: The y coordinate of region (int)
6891 :param width: The width of region (int)
6892 :param height: The height of region (int)
6893 :param compression: Compression level for jpeg
6894 :type compression: Float
6895 """
6896
6897 self._pd.z = long(z)
6898 self._pd.t = long(t)
6899
6900 regionDef = omero.romio.RegionDef()
6901 regionDef.x = int(x)
6902 regionDef.y = int(y)
6903 regionDef.width = int(width)
6904 regionDef.height = int(height)
6905 self._pd.region = regionDef
6906 try:
6907 if level is not None:
6908 self._re.setResolutionLevel(level)
6909 if compression is not None:
6910 try:
6911 self._re.setCompressionLevel(float(compression))
6912 except omero.SecurityViolation:
6913 self._obj.clearPixels()
6914 self._obj.pixelsLoaded = False
6915 self._re = None
6916 return self.renderJpeg(z,t,None)
6917 rv = self._re.renderCompressed(self._pd, self._conn.SERVICE_OPTS)
6918 return rv
6919 except omero.InternalException:
6920 logger.debug('On renderJpegRegion');
6921 logger.debug(traceback.format_exc())
6922 return None
6923 except Ice.MemoryLimitException:
6924
6925 self._obj.clearPixels()
6926 self._obj.pixelsLoaded = False
6927 self._re = None
6928 raise
6929
6930
6931 @assert_re()
6932 - def renderJpeg (self, z=None, t=None, compression=0.9):
6933 """
6934 Return the data from rendering image, compressed (and projected).
6935 Projection (or not) is specified by calling L{setProjection} before renderJpeg.
6936
6937 :param z: The Z index. Ignored if projecting image. If None, use defaultZ
6938 :param t: The T index. If None, use defaultT
6939 :param compression: Compression level for jpeg
6940 :type compression: Float
6941 """
6942
6943 if z is None:
6944 z = self._re.getDefaultZ()
6945 self._pd.z = long(z)
6946 if t is None:
6947 t = self._re.getDefaultT()
6948 self._pd.t = long(t)
6949 try:
6950 if compression is not None:
6951 try:
6952 self._re.setCompressionLevel(float(compression))
6953 except omero.SecurityViolation:
6954 self._obj.clearPixels()
6955 self._obj.pixelsLoaded = False
6956 self._re = None
6957 return self.renderJpeg(z,t,None)
6958 projection = self.PROJECTIONS.get(self._pr, -1)
6959 if not isinstance(projection, omero.constants.projection.ProjectionType):
6960 rv = self._re.renderCompressed(self._pd, self._conn.SERVICE_OPTS)
6961 else:
6962 prStart, prEnd = 0, self.getSizeZ()-1
6963 if self._prStart is not None:
6964 prStart = self._prStart
6965 if self._prEnd is not None:
6966 prEnd = self._prEnd
6967 rv = self._re.renderProjectedCompressed(projection, self._pd.t, 1, prStart, prEnd, self._conn.SERVICE_OPTS)
6968 return rv
6969 except omero.InternalException:
6970 logger.debug('On renderJpeg');
6971 logger.debug(traceback.format_exc())
6972 return None
6973 except Ice.MemoryLimitException:
6974
6975 self._obj.clearPixels()
6976 self._obj.pixelsLoaded = False
6977 self._re = None
6978 raise
6979
6981 """
6982 Exports the OME-TIFF representation of this image.
6983
6984 :type bufsize: int or tuple
6985 :param bufsize: if 0 return a single string buffer with the whole OME-TIFF
6986 if >0 return a tuple holding total size and generator of chunks
6987 (string buffers) of bufsize bytes each
6988 :return: OME-TIFF file data
6989 :rtype: String or (size, data generator)
6990 """
6991
6992 e = self._conn.createExporter()
6993 e.addImage(self.getId())
6994 size = e.generateTiff(self._conn.SERVICE_OPTS)
6995 if bufsize==0:
6996
6997 return fileread(e, size, 65536)
6998 else:
6999
7000 return (size, fileread_gen(e, size, bufsize))
7001
7003 """
7004 Wraps text into lines that are less than a certain width (when rendered
7005 in specified font)
7006
7007 :param width: The max width to wrap text (pixels)
7008 :type width: Int
7009 :param text: The text to wrap
7010 :type text: String
7011 :param font: Font to use.
7012 :type font: E.g. PIL ImageFont
7013 :return: List of text lines
7014 :rtype: List of Strings
7015 """
7016
7017 rv = []
7018 tokens = filter(None, text.split(' '))
7019 while len(tokens) > 1:
7020 p1 = 0
7021 p2 = 1
7022 while p2 <= len(tokens) and font.getsize(' '.join(tokens[p1:p2]))[0] < width:
7023 p2 += 1
7024 rv.append(' '.join(tokens[p1:p2-1]))
7025 tokens = tokens[p2-1:]
7026 if len(tokens):
7027 rv.append(' '.join(tokens))
7028 logger.debug(rv)
7029 return rv
7030
7031 @assert_re()
7032 - def createMovie (self, outpath, zstart, zend, tstart, tend, opts=None):
7033 """
7034 Creates a movie file from this image.
7035 TODO: makemovie import is commented out in 4.2+
7036
7037 :type outpath: string
7038 :type zstart: int
7039 :type zend: int
7040 :type tstart: int
7041 :type tend: int
7042 :type opts: dict
7043 :param opts: dictionary of extra options. Currently processed options are:
7044 - watermark:string: path to image to use as watermark
7045 - slides:tuple: tuple of tuples with slides to prefix and postfix video with
7046 in format (secs:int, topline:text[, middleline:text[, bottomline:text]])
7047 If more than 2 slides are provided they will be ignored
7048 - fps:int: frames per second
7049 - minsize: tuple of (minwidth, minheight, bgcolor)
7050 - format:string: one of video/mpeg or video/quicktime
7051
7052 :return: Tuple of (file-ext, format)
7053 :rtype: (String, String)
7054 """
7055 todel = []
7056 svc = self._conn.getScriptService()
7057 mms = filter(lambda x: x.name.val == 'Make_Movie.py', svc.getScripts())
7058 if not len(mms):
7059 logger.error('No Make_Movie.py script found!')
7060 return None, None
7061 mms = mms[0]
7062 params = svc.getParams(mms.id.val)
7063 args = ['IDs=%d' % self.getId()]
7064 args.append('Do_Link=False')
7065 args.append('Z_Start=%d' % zstart)
7066 args.append('Z_End=%d' % zend)
7067 args.append('T_Start=%d' % tstart)
7068 args.append('T_End=%d' % tend)
7069 if 'fps' in opts:
7070 args.append('FPS=%d' % opts['fps'])
7071 if 'format' in opts:
7072 if opts['format'] == 'video/mpeg':
7073 args.append('Format=MPEG')
7074 elif opts['format'] == 'video/wmv':
7075 args.append('Format=WMV')
7076 else:
7077 args.append('Format=Quicktime')
7078 rdid = self._getRDef()
7079 if rdid is not None:
7080 args.append('RenderingDef_ID=%d' % rdid)
7081
7082
7083 channels = self.getChannels()
7084 args.append('ChannelsExtended=%s' % (','.join(["%d|%s:%s$%s" % (x._idx+1,
7085 Decimal(str(x.getWindowStart())),
7086 Decimal(str(x.getWindowEnd())),
7087 x.getColor().getHtml())
7088 for x in channels if x.isActive()])))
7089
7090 watermark = opts.get('watermark', None)
7091 logger.debug('watermark: %s' % watermark)
7092 if watermark:
7093 origFile = self._conn.createOriginalFileFromLocalFile(watermark)
7094 args.append('Watermark=OriginalFile:%d' % origFile.getId())
7095 todel.append(origFile.getId())
7096
7097 w,h = self.getSizeX(), self.getSizeY()
7098 if 'minsize' in opts:
7099 args.append('Min_Width=%d' % opts['minsize'][0])
7100 w = max(w, opts['minsize'][0])
7101 args.append('Min_Height=%d' % opts['minsize'][1])
7102 h = max(h, opts['minsize'][1])
7103 args.append('Canvas_Colour=%s' % opts['minsize'][2])
7104
7105 scalebars = (1,1,2,2,5,5,5,5,10,10,10,10)
7106 scalebar = scalebars[max(min(int(w / 256)-1, len(scalebars)), 1) - 1]
7107 args.append('Scalebar=%d' % scalebar)
7108 fsizes = (8,8,12,18,24,32,32,40,48,56,56,64)
7109 fsize = fsizes[max(min(int(w / 256)-1, len(fsizes)), 1) - 1]
7110 font = ImageFont.load('%s/pilfonts/B%0.2d.pil' % (THISPATH, fsize) )
7111 slides = opts.get('slides', [])
7112 for slidepos in range(min(2, len(slides))):
7113 t = slides[slidepos]
7114 slide = Image.new("RGBA", (w,h))
7115 for i, line in enumerate(t[1:4]):
7116 line = line.decode('utf8').encode('iso8859-1')
7117 wwline = self._wordwrap(w, line, font)
7118 for j, line in enumerate(wwline):
7119 tsize = font.getsize(line)
7120 draw = ImageDraw.Draw(slide)
7121 if i == 0:
7122 y = 10+j*tsize[1]
7123 elif i == 1:
7124 y = h / 2 - ((len(wwline)-j)*tsize[1]) + (len(wwline)*tsize[1])/2
7125 else:
7126 y = h - (len(wwline) - j)*tsize[1] - 10
7127 draw.text((w/2-tsize[0]/2,y), line, font=font)
7128 fp = StringIO()
7129 slide.save(fp, "JPEG")
7130 fileSize = len(fp.getvalue())
7131 origFile = self._conn.createOriginalFileFromFileObj(fp, 'slide', '', fileSize)
7132 if slidepos == 0:
7133 args.append('Intro_Slide=OriginalFile:%d' % origFile.getId())
7134 args.append('Intro_Duration=%d' % t[0])
7135 else:
7136 args.append('Ending_Slide=OriginalFile:%d' % origFile.getId())
7137 args.append('Ending_Duration=%d' % t[0])
7138 todel.append(origFile.getId())
7139
7140 m = scripts.parse_inputs(args, params)
7141
7142 try:
7143 proc = svc.runScript(mms.id.val, m, None)
7144 proc.getJob()
7145 except omero.ValidationException, ve:
7146 logger.error('Bad Parameters:\n%s' % ve)
7147 return None, None
7148
7149
7150 cb = scripts.ProcessCallbackI(self._conn.c, proc)
7151 try:
7152 while proc.poll() is None:
7153 cb.block(1000)
7154 rv = proc.getResults(3)
7155 finally:
7156 cb.close()
7157
7158 if not 'File_Annotation' in rv:
7159 logger.error('Error in createMovie:')
7160 if 'stderr' in rv:
7161 x = StringIO()
7162 self._conn.c.download(ofile=rv['stderr'].val, filehandle=x)
7163 logger.error(x.getvalue())
7164 return None, None
7165
7166 f = rv['File_Annotation'].val
7167 ofw = OriginalFileWrapper(self._conn, f)
7168 todel.append(ofw.getId())
7169 logger.debug('writing movie on %s' % (outpath,))
7170 outfile = file(outpath, 'w')
7171 for chunk in ofw.getFileInChunks():
7172 outfile.write(chunk)
7173 outfile.close()
7174 handle = self._conn.deleteObjects('/OriginalFile', todel)
7175 try:
7176 self._conn._waitOnCmd(handle)
7177 finally:
7178 handle.close()
7179
7180 return os.path.splitext(f.name.val)[-1], f.mimetype.val
7181
7183 """
7184 Render the Image, (projected) and compressed.
7185 For projection, call L{setProjection} before renderImage.
7186
7187 :param z: Z index
7188 :param t: T index
7189 @compression: Image compression level
7190 :return: A PIL Image or None
7191 :rtype: PIL Image.
7192 """
7193
7194 rv = self.renderJpeg(z,t,compression)
7195 if rv is not None:
7196 i = StringIO(rv)
7197 rv = Image.open(i)
7198 return rv
7199
7201 """
7202 Prepares a jpeg representation of a 2d grid holding a render of each channel,
7203 along with one for all channels at the set Z and T points.
7204
7205 :param z: Z index
7206 :param t: T index
7207 :param compression: Image compression level
7208 :param border:
7209 :return: value
7210 """
7211
7212 img = self.renderSplitChannelImage(z,t,compression, border)
7213 rv = StringIO()
7214 img.save(rv, 'jpeg', quality=int(compression*100))
7215 return rv.getvalue()
7216
7218 """
7219 Returns a dict of layout parameters for generating split channel image.
7220 E.g. row count, column count etc. for greyscale and color layouts.
7221
7222 :param border: spacing between panels
7223 :type border: int
7224 :return: Dict of parameters
7225 :rtype: Dict
7226 """
7227
7228 c = self.getSizeC()
7229
7230 x = sqrt(c)
7231 y = int(round(x))
7232 if x > y:
7233 x = y+1
7234 else:
7235 x = y
7236 rv = {'g':{'width': self.getSizeX()*x + border*(x+1),
7237 'height': self.getSizeY()*y+border*(y+1),
7238 'border': border,
7239 'gridx': x,
7240 'gridy': y,}
7241 }
7242
7243 c += 1
7244 x = sqrt(c)
7245 y = int(round(x))
7246 if x > y:
7247 x = y+1
7248 else:
7249 x = y
7250 rv['c'] = {'width': self.getSizeX()*x + border*(x+1),
7251 'height': self.getSizeY()*y+border*(y+1),
7252 'border': border,
7253 'gridx': x,
7254 'gridy': y,}
7255 return rv
7256
7259
7261 """
7262 Prepares a PIL Image with a 2d grid holding a render of each channel,
7263 along with one for all channels at the set Z and T points.
7264
7265 :param z: Z index
7266 :param t: T index
7267 :param compression: Compression level
7268 :param border: space around each panel (int)
7269 :return: canvas
7270 :rtype: PIL Image
7271 """
7272
7273 dims = self.splitChannelDims(border=border)[self.isGreyscaleRenderingModel() and 'g' or 'c']
7274 canvas = Image.new('RGBA', (dims['width'], dims['height']), '#fff')
7275 cmap = [ch.isActive() and i+1 or 0 for i,ch in enumerate(self.getChannels())]
7276 c = self.getSizeC()
7277 pxc = 0
7278 px = dims['border']
7279 py = dims['border']
7280
7281
7282 w = self.getSizeX()
7283 if w >= 640:
7284 fsize = (int((w-640)/128)*8) + 24
7285 if fsize > 64:
7286 fsize = 64
7287 elif w >= 512:
7288 fsize = 24
7289 elif w >= 384:
7290 fsize = 18
7291 elif w >= 298:
7292 fsize = 14
7293 elif w >= 256:
7294 fsize = 12
7295 elif w >= 213:
7296 fsize = 10
7297 elif w >= 96:
7298 fsize = 8
7299 else:
7300 fsize = 0
7301 if fsize > 0:
7302 font = ImageFont.load('%s/pilfonts/B%0.2d.pil' % (THISPATH, fsize) )
7303
7304
7305 for i in range(c):
7306 if cmap[i]:
7307 self.setActiveChannels((i+1,))
7308 img = self.renderImage(z,t, compression)
7309 if fsize > 0:
7310 draw = ImageDraw.ImageDraw(img)
7311 draw.text((2,2), "%s" % (self._renderSplit_channelLabel(self.getChannels()[i])), font=font, fill="#fff")
7312 canvas.paste(img, (px, py))
7313 pxc += 1
7314 if pxc < dims['gridx']:
7315 px += self.getSizeX() + border
7316 else:
7317 pxc = 0
7318 px = border
7319 py += self.getSizeY() + border
7320
7321 self.setActiveChannels(cmap)
7322 self.setColorRenderingModel()
7323 img = self.renderImage(z,t, compression)
7324 if fsize > 0:
7325 draw = ImageDraw.ImageDraw(img)
7326 draw.text((2,2), "merged", font=font, fill="#fff")
7327 canvas.paste(img, (px, py))
7328 return canvas
7329
7330 LP_PALLETE = [0,0,0,0,0,0,255,255,255]
7331 LP_TRANSPARENT = 0
7332 LP_BGCOLOR = 1
7333 LP_FGCOLOR = 2
7335 """
7336 Common part of horizontal and vertical line plot rendering.
7337
7338 :returns: (Image, width, height).
7339 """
7340 channels = filter(lambda x: x.isActive(), self.getChannels())
7341 width = self.getSizeX()
7342 height = self.getSizeY()
7343
7344 pal = list(self.LP_PALLETE)
7345
7346 for channel in channels:
7347 pal.extend(channel.getColor().getRGB())
7348
7349
7350 im = Image.new('P', (width, height))
7351 im.putpalette(pal)
7352 return im, width, height
7353
7354
7355 @assert_re()
7357 """
7358 Draws the Row plot as a gif file. Returns gif data.
7359
7360 :param z: Z index
7361 :param t: T index
7362 :param y: Y position
7363 :param linewidth: Width of plot line
7364 :return: gif data as String
7365 :rtype: String
7366 """
7367
7368 self._pd.z = long(z)
7369 self._pd.t = long(t)
7370
7371 im, width, height = self.prepareLinePlotCanvas()
7372 base = height - 1
7373
7374 draw = ImageDraw.ImageDraw(im)
7375
7376 draw.rectangle([0, 0, width-1, base], fill=self.LP_TRANSPARENT, outline=self.LP_TRANSPARENT)
7377 draw.line(((0,y),(width, y)), fill=self.LP_FGCOLOR, width=linewidth)
7378
7379
7380 rows = self.getRow(z,t,y)
7381
7382 for r in range(len(rows)):
7383 chrow = rows[r]
7384 color = r + self.LP_FGCOLOR + 1
7385 last_point = base-chrow[0]
7386 for i in range(len(chrow)):
7387 draw.line(((i, last_point), (i, base-chrow[i])), fill=color, width=linewidth)
7388 last_point = base-chrow[i]
7389 del draw
7390 out = StringIO()
7391 im.save(out, format="gif", transparency=0)
7392 return out.getvalue()
7393
7394 @assert_re()
7396 """
7397 Draws the Column plot as a gif file. Returns gif data.
7398
7399 :param z: Z index
7400 :param t: T index
7401 :param x: X position
7402 :param linewidth: Width of plot line
7403 :return: gif data as String
7404 :rtype: String
7405 """
7406
7407 self._pd.z = long(z)
7408 self._pd.t = long(t)
7409
7410 im, width, height = self.prepareLinePlotCanvas()
7411
7412 draw = ImageDraw.ImageDraw(im)
7413
7414 draw.rectangle([0, 0, width-1, height-1], fill=self.LP_TRANSPARENT, outline=self.LP_TRANSPARENT)
7415 draw.line(((x,0),(x, height)), fill=self.LP_FGCOLOR, width=linewidth)
7416
7417
7418 cols = self.getCol(z,t,x)
7419
7420 for r in range(len(cols)):
7421 chcol = cols[r]
7422 color = r + self.LP_FGCOLOR + 1
7423 last_point = chcol[0]
7424 for i in range(len(chcol)):
7425 draw.line(((last_point, i), (chcol[i], i)), fill=color, width=linewidth)
7426 last_point = chcol[i]
7427 del draw
7428 out = StringIO()
7429 im.save(out, format="gif", transparency=0)
7430 return out.getvalue()
7431
7432 @assert_re()
7434 """
7435 Returns the last used value of Z (E.g. for renderingJpeg or line plot)
7436 Returns 0 if these methods not been used yet.
7437 TODO: How to get default-Z?
7438
7439 :return: current Z index
7440 :rtype: int
7441 """
7442
7443 return self._pd.z
7444
7445 @assert_re()
7447 """
7448 Returns the last used value of T (E.g. for renderingJpeg or line plot)
7449 Returns 0 if these methods not been used yet.
7450 TODO: How to get default-T?
7451
7452 :return: current T index
7453 :rtype: int
7454 """
7455
7456 return self._pd.t
7457
7458 @assert_re()
7460 """
7461 Gets the default Z index from the rendering engine
7462 """
7463 return self._re.getDefaultZ()
7464
7465 @assert_re()
7467 """
7468 Gets the default T index from the rendering engine
7469 """
7470 return self._re.getDefaultT()
7471
7472 @assert_pixels
7474 """
7475 Gets name of pixel data type.
7476
7477 :return: name of the image precision, e.g., float, uint8, etc.
7478 :rtype: String
7479 """
7480 rv = self._obj.getPrimaryPixels().getPixelsType().value
7481 return rv is not None and rv.val or 'unknown'
7482
7483 @assert_pixels
7485 """
7486 Gets the physical size X of pixels in microns
7487
7488 :return: Size of pixel in x or O
7489 :rtype: float
7490 """
7491 rv = self._obj.getPrimaryPixels().getPhysicalSizeX()
7492 return rv is not None and rv.val or 0
7493
7494 @assert_pixels
7496 """
7497 Gets the physical size Y of pixels in microns
7498
7499 :return: Size of pixel in y or O
7500 :rtype: float
7501 """
7502
7503 rv = self._obj.getPrimaryPixels().getPhysicalSizeY()
7504 return rv is not None and rv.val or 0
7505
7506 @assert_pixels
7508 """
7509 Gets the physical size Z of pixels in microns
7510
7511 :return: Size of pixel in z or O
7512 :rtype: float
7513 """
7514
7515 rv = self._obj.getPrimaryPixels().getPhysicalSizeZ()
7516 return rv is not None and rv.val or 0
7517
7518 @assert_pixels
7520 """
7521 Gets width (size X) of the image (in pixels)
7522
7523 :return: width
7524 :rtype: int
7525 """
7526
7527 return self._obj.getPrimaryPixels().getSizeX().val
7528
7529 @assert_pixels
7531 """
7532 Gets height (size Y) of the image (in pixels)
7533
7534 :return: height
7535 :rtype: int
7536 """
7537
7538 return self._obj.getPrimaryPixels().getSizeY().val
7539
7540 @assert_pixels
7553
7554 @assert_pixels
7567
7568 @assert_pixels
7570 """
7571 Gets C count of the image (number of channels)
7572
7573 :return: size C
7574 :rtype: int
7575 """
7576
7577 return self._obj.getPrimaryPixels().getSizeC().val
7578
7580 """
7581 Removes specific color settings from channels
7582
7583 :return: True if allowed to do this
7584 :rtype: Boolean
7585 """
7586
7587 if not self.canWrite():
7588 return False
7589 for c in self.getChannels():
7590 c.unloadRed()
7591 c.unloadGreen()
7592 c.unloadBlue()
7593 c.unloadAlpha()
7594 c.save()
7595 self._deleteSettings()
7596 return True
7597
7604
7606 """
7607 Returns a map of rendering options not stored in rendering settings.
7608 - 'p' : projection
7609 - 'ia' : inverted axis (swap Z and T)
7610
7611 :return: Dict of render options
7612 :rtype: Dict
7613 """
7614
7615 rv = {}
7616 rv['p'] = self.getProjection()
7617 rv['ia'] = self.isInvertedAxis() and "1" or "0"
7618 return rv
7619
7621 """
7622 Loads rendering options from an Annotation on the Image.
7623
7624 :return: Dict of rendering options
7625 :rtype: Dict
7626 """
7627 ns = self._conn.CONFIG.IMG_ROPTSNS
7628 if ns:
7629 ann = self.getAnnotation(ns)
7630 if ann is not None:
7631 opts = dict([x.split('=') for x in ann.getValue().split('&')])
7632 return opts
7633 return {}
7634
7636 """
7637 Loads rendering options from an Annotation on the Image and applies them
7638 to the Image.
7639
7640 :return: True! TODO: Always True??
7641 """
7642 opts = self._loadRenderOptions()
7643 self.setProjection(opts.get('p', None))
7644 self.setInvertedAxis(opts.get('ia', "0") == "1")
7645 return True
7646
7647 @assert_re()
7670
7671 @assert_re()
7687
7697
7705
7718
7720 """
7721 Returns a count of the number of Imported Image files (Archived files for pre-FS images)
7722 This will only be 0 if the image was imported pre-FS and original files NOT archived
7723 """
7724 fCount = self.countFilesetFiles()
7725 if fCount > 0:
7726 return fCount
7727 return self.countArchivedFiles()
7728
7730 """
7731 Returns a generator of L{OriginalFileWrapper}s corresponding to the archived files linked to primary pixels
7732 ** Deprecated ** Use L{getImportedImageFiles}.
7733 """
7734 warnings.warn("Deprecated. Use getImportedImageFiles()", DeprecationWarning)
7735 return self.getImportedImageFiles()
7736
7738 """
7739 Returns a generator of L{OriginalFileWrapper}s corresponding to the Imported image
7740 files that created this image, if available.
7741 """
7742
7743 fs = self.getFileset()
7744 if fs is not None:
7745 for usedfile in fs.copyUsedFiles():
7746 yield OriginalFileWrapper(self._conn, usedfile.originalFile)
7747
7748
7749 pid = self.getPixelsId()
7750 params = omero.sys.Parameters()
7751 params.map = {"pid": rlong(pid)}
7752 query = "select link from PixelsOriginalFileMap link join fetch link.parent as p where link.child.id=:pid"
7753 links = self._conn.getQueryService().findAllByQuery(query, params,self._conn.SERVICE_OPTS)
7754 for l in links:
7755 yield OriginalFileWrapper(self._conn, l.parent)
7756
7758 """
7759 Returns the Fileset linked to this Image.
7760 Fileset images, usedFiles and originalFiles are loaded.
7761 """
7762 if self.countFilesetFiles() > 0:
7763 return self._conn.getObject("Fileset", self.fileset.id.val)
7764
7765 - def getROICount(self, shapeType=None, filterByCurrentUser=False):
7766 """
7767 Count number of ROIs associated to an image
7768
7769 :param shapeType: Filter by shape type ("Rect",...).
7770 :param filterByCurrentUser: Whether or not to filter the count by the
7771 currently logged in user.
7772 :return: Number of ROIs found for the currently logged in user if
7773 C{filterByCurrentUser} is C{True}, otherwise the total number found.
7774 """
7775
7776
7777 def isValidType(shape):
7778 if not shapeType:
7779 return True
7780 elif isinstance(shapeType,list):
7781 for t in shapeType:
7782 if isinstance(shape,getattr(omero.model,t)):
7783 return True
7784 elif isinstance(shape,getattr(omero.model,shapeType)):
7785 return True
7786 return False
7787
7788 def isValidROI(roi):
7789 for shape in roi.copyShapes():
7790 if isValidType(shape):
7791 return True
7792 return False
7793
7794
7795
7796 if shapeType is None:
7797 params = omero.sys.ParametersI()
7798 params.addLong('imageId', self.id)
7799 query = 'select count(*) from Roi as roi ' \
7800 'where roi.image.id = :imageId'
7801 if filterByCurrentUser:
7802 query += ' and roi.details.owner.id = :ownerId'
7803 params.addLong('ownerId', self._conn.getUserId())
7804 count = self._conn.getQueryService().projection(
7805 query, params, self._conn.SERVICE_OPTS)
7806
7807
7808 return count[0][0].getValue()
7809
7810 roiOptions = omero.api.RoiOptions()
7811 if filterByCurrentUser:
7812 roiOptions.userId = omero.rtypes.rlong(self._conn.getUserId())
7813
7814 result = self._conn.getRoiService().findByImage(self.id, roiOptions)
7815 count = sum(1 for roi in result.rois if isValidROI(roi))
7816 return count
7817
7818 ImageWrapper = _ImageWrapper
7823 """
7824 omero_model_StageLabelI class wrapper extends BlitzObjectWrapper.
7825 """
7826 pass
7827
7828 ImageStageLabelWrapper = _ImageStageLabelWrapper
7831 """
7832 omero_model_ImagingEnvironment class wrapper extends BlitzObjectWrapper.
7833 """
7834 pass
7835
7836 ImagingEnvironmentWrapper = _ImagingEnvironmentWrapper
7839 """
7840 omero_model_ImagingEnvironmentI class wrapper extends BlitzObjectWrapper.
7841 """
7842 _attrs = ('temperature',
7843 'airPressure',
7844 'humidity',
7845 'co2percent',
7846 'version')
7847
7850
7851 ImagingEnviromentWrapper = _ImagingEnviromentWrapper
7854 """
7855 omero_model_TransmittanceRangeI class wrapper extends BlitzObjectWrapper.
7856 """
7857 _attrs = ('cutIn',
7858 'cutOut',
7859 'cutInTolerance',
7860 'cutOutTolerance',
7861 'transmittance',
7862 'version')
7863
7866
7867 TransmittanceRangeWrapper = _TransmittanceRangeWrapper
7870 """
7871 omero_model_DetectorSettingsI class wrapper extends BlitzObjectWrapper.
7872 """
7873 _attrs = ('voltage',
7874 'gain',
7875 'offsetValue',
7876 'readOutRate',
7877 'binning|BinningWrapper',
7878 'detector|DetectorWrapper',
7879 'version')
7880
7883
7884 DetectorSettingsWrapper = _DetectorSettingsWrapper
7887 """
7888 omero_model_BinningI class wrapper extends BlitzObjectWrapper.
7889 """
7890
7893
7894 BinningWrapper = _BinningWrapper
7897 """
7898 omero_model_DetectorI class wrapper extends BlitzObjectWrapper.
7899 """
7900 _attrs = ('manufacturer',
7901 'model',
7902 'serialNumber',
7903 'voltage',
7904 'gain',
7905 'offsetValue',
7906 'zoom',
7907 'amplificationGain',
7908 '#type;detectorType',
7909 'version')
7910
7913
7915 """
7916 The type of detector (enum value)
7917
7918 :return: Detector type
7919 :rtype: L{EnumerationWrapper}
7920 """
7921
7922 rv = self.type
7923 if self.type is not None:
7924 rv = EnumerationWrapper(self._conn, self.type)
7925 if not self.type.loaded:
7926 self.type = rv._obj
7927 return rv
7928
7929 DetectorWrapper = _DetectorWrapper
7932 """
7933 omero_model_ObjectiveI class wrapper extends BlitzObjectWrapper.
7934 """
7935 _attrs = ('manufacturer',
7936 'model',
7937 'serialNumber',
7938 'nominalMagnification',
7939 'calibratedMagnification',
7940 'lensNA',
7941 '#immersion',
7942 '#correction',
7943 'workingDistance',
7944 'iris',
7945 'version')
7946
7949
7951 """
7952 The type of immersion for this objective (enum value)
7953
7954 :return: Immersion type, or None
7955 :rtype: L{EnumerationWrapper}
7956 """
7957
7958 rv = self.immersion
7959 if self.immersion is not None:
7960 rv = EnumerationWrapper(self._conn, self.immersion)
7961 if not self.immersion.loaded:
7962 self.immersion = rv._obj
7963 return rv
7964
7966 """
7967 The type of Correction for this objective (enum value)
7968
7969 :return: Correction type, or None
7970 :rtype: L{EnumerationWrapper}
7971 """
7972
7973 rv = self.correction
7974 if self.correction is not None:
7975 rv = EnumerationWrapper(self._conn, self.correction)
7976 if not self.correction.loaded:
7977 self.correction = rv._obj
7978 return rv
7979
7981 """
7982 The type of Iris for this objective (enum value)
7983
7984 :return: Iris type
7985 :rtype: L{EnumerationWrapper}
7986 """
7987
7988 rv = self.iris
7989 if self.iris is not None:
7990 rv = EnumerationWrapper(self._conn, self.iris)
7991 if not self.iris.loaded:
7992 self.iris = rv._obj
7993 return rv
7994
7995 ObjectiveWrapper = _ObjectiveWrapper
7998 """
7999 omero_model_ObjectiveSettingsI class wrapper extends BlitzObjectWrapper.
8000 """
8001 _attrs = ('correctionCollar',
8002 '#medium',
8003 'refractiveIndex',
8004 'objective|ObjectiveWrapper',
8005 'version')
8006
8009
8011 """
8012 Gets the Objective that these settings refer to
8013
8014 :return: Objective
8015 :rtype: L{ObjectiveWrapper}
8016 """
8017
8018 rv = self.objective
8019 if self.objective is not None:
8020 rv = ObjectiveWrapper(self._conn, self.objective)
8021 if not self.objective.loaded:
8022 self.objective = rv._obj
8023 return rv
8024
8026 """
8027 Gets the Medium type that these settings refer to (enum value)
8028
8029 :return: Medium
8030 :rtype: L{EnumerationWrapper}
8031 """
8032
8033 rv = self.medium
8034 if self.medium is not None:
8035 rv = EnumerationWrapper(self._conn, self.medium)
8036 if not self.medium.loaded:
8037 self.medium = rv._obj
8038 return rv
8039
8040 ObjectiveSettingsWrapper = _ObjectiveSettingsWrapper
8044 """
8045 omero_model_FilterI class wrapper extends BlitzObjectWrapper.
8046 """
8047 _attrs = ('manufacturer',
8048 'model',
8049 'lotNumber',
8050 'filterWheel',
8051 '#type;filterType',
8052 'transmittanceRange|TransmittanceRangeWrapper',
8053 'version')
8054
8057
8059 """
8060 Gets the Filter type for this filter (enum value)
8061
8062 :return: Filter type
8063 :rtype: L{EnumerationWrapper}
8064 """
8065
8066 rv = self.type
8067 if self.type is not None:
8068 rv = EnumerationWrapper(self._conn, self.type)
8069 if not self.type.loaded:
8070 self.type = rv._obj
8071 return rv
8072
8073 FilterWrapper = _FilterWrapper
8076 """
8077 omero_model_DichroicI class wrapper extends BlitzObjectWrapper.
8078 """
8079 _attrs = ('manufacturer',
8080 'model',
8081 'lotNumber',
8082 'version')
8083
8086
8087 DichroicWrapper = _DichroicWrapper
8090 """
8091 omero_model_FilterSetI class wrapper extends BlitzObjectWrapper.
8092 """
8093 _attrs = ('manufacturer',
8094 'model',
8095 'lotNumber',
8096 'dichroic|DichroicWrapper',
8097 'version')
8098
8101
8103 """ TODO: not implemented """
8104 pass
8105
8107 """ TODO: not implemented """
8108 pass
8109
8110 FilterSetWrapper = _FilterSetWrapper
8113 """
8114 omero_model_OTFI class wrapper extends BlitzObjectWrapper.
8115 """
8116 _attrs = ('sizeX',
8117 'sizeY',
8118 'opticalAxisAveraged'
8119 'pixelsType',
8120 'path',
8121 'filterSet|FilterSetWrapper',
8122 'objective|ObjectiveWrapper',
8123 'version')
8124
8127
8128 OTFWrapper = _OTFWrapper
8131 """
8132 base Light Source class wrapper, extends BlitzObjectWrapper.
8133 """
8134 _attrs = ('attenuation',
8135 'wavelength',
8136
8137 'microbeamManipulation',
8138 'version')
8139
8142
8144 if self._obj.lightSource is None:
8145 return None
8146 if not self._obj.lightSource.isLoaded():
8147 lid = self._obj.lightSource.id.val
8148 params = omero.sys.Parameters()
8149 params.map = {"id": rlong(lid)}
8150 query = "select l from Laser as l left outer join fetch l.type " \
8151 "left outer join fetch l.laserMedium " \
8152 "left outer join fetch l.pulse as pulse " \
8153 "left outer join fetch l.pump as pump " \
8154 "left outer join fetch pump.type as pt " \
8155 "where l.id = :id"
8156 self._obj.lightSource = self._conn.getQueryService().findByQuery(query, params,self._conn.SERVICE_OPTS)
8157 return LightSourceWrapper(self._conn, self._obj.lightSource)
8158
8159 LightSettingsWrapper = _LightSettingsWrapper
8162 """
8163 base Light Source class wrapper, extends BlitzObjectWrapper.
8164 """
8165 _attrs = ('manufacturer',
8166 'model',
8167 'power',
8168 'serialNumber',
8169 '#type;lightSourceType',
8170 'version')
8171
8173 """
8174 Gets the Light Source type for this light source (enum value)
8175
8176 :return: Light Source type
8177 :rtype: L{EnumerationWrapper}
8178 """
8179
8180 rv = self.type
8181 if self.type is not None:
8182 rv = EnumerationWrapper(self._conn, self.type)
8183 if not self.type.loaded:
8184 self.type = rv._obj
8185 return rv
8186
8187
8188 _LightSourceClasses = {}
8190 """
8191 Creates wrapper instances for omero.model light source objects
8192
8193 :param conn: L{BlitzGateway} connection
8194 :param obj: omero.model object
8195 :return: L{_LightSourceWrapper} subclass
8196 """
8197 for k, v in _LightSourceClasses.items():
8198 if isinstance(obj, k):
8199 return getattr(omero.gateway, v)(conn, obj, **kwargs)
8200 return None
8201
8203 """
8204 omero_model_FilamentI class wrapper extends LightSourceWrapper.
8205 """
8206
8210
8211 FilamentWrapper = _FilamentWrapper
8212 _LightSourceClasses[omero.model.FilamentI] = 'FilamentWrapper'
8215 """
8216 omero_model_ArcI class wrapper extends FilamentWrapper.
8217 """
8221
8222 ArcWrapper = _ArcWrapper
8223 _LightSourceClasses[omero.model.ArcI] = 'ArcWrapper'
8226 """
8227 omero_model_LaserI class wrapper extends LightSourceWrapper.
8228 """
8230 super(_LaserWrapper, self).__bstrap__()
8231 self.OMERO_CLASS = 'Laser'
8232 self._attrs += (
8233 '#laserMedium',
8234 'frequencyMultiplication',
8235 'tuneable',
8236 'pulse',
8237 'wavelength',
8238 'pockelCell',
8239 'pump',
8240 'repetitionRate')
8241
8243 """
8244 Gets the laser medium type for this Laser (enum value)
8245
8246 :return: Laser medium type
8247 :rtype: L{EnumerationWrapper}
8248 """
8249
8250 rv = self.laserMedium
8251 if self.laserMedium is not None:
8252 rv = EnumerationWrapper(self._conn, self.laserMedium)
8253 if not self.laserMedium.loaded:
8254 self.laserMedium = rv._obj
8255 return rv
8256
8257 LaserWrapper = _LaserWrapper
8258 _LightSourceClasses[omero.model.LaserI] = 'LaserWrapper'
8261 """
8262 omero_model_LightEmittingDiodeI class wrapper extends LightSourceWrapper.
8263 """
8267
8268 LightEmittingDiodeWrapper = _LightEmittingDiodeWrapper
8269 _LightSourceClasses[omero.model.LightEmittingDiodeI] = 'LightEmittingDiodeWrapper'
8272 """
8273 omero_model_MicroscopeI class wrapper extends BlitzObjectWrapper.
8274 """
8275 _attrs = ('manufacturer',
8276 'model',
8277 'serialNumber',
8278 '#type;microscopeType',
8279 'version')
8280
8283
8285 """
8286 Returns the 'type' of microscope this is.
8287
8288 :return: Microscope type.
8289 :rtype: L{EnumerationWrapper}
8290 """
8291
8292 rv = self.type
8293 if self.type is not None:
8294 rv = EnumerationWrapper(self._conn, self.type)
8295 if not self.type.loaded:
8296 self.type = rv._obj
8297 return rv
8298
8299 MicroscopeWrapper = _MicroscopeWrapper
8302 """
8303 omero_model_InstrumentI class wrapper extends BlitzObjectWrapper.
8304 """
8305
8306
8307
8308 _attrs = ('microscope|MicroscopeWrapper',)
8309
8312
8314 """
8315 Returns the microscope component of the Instrument.
8316
8317 :return: Microscope
8318 :rtype: omero.model.Microscope
8319 """
8320
8321 if self._obj.microscope is not None:
8322 return MicroscopeWrapper(self._conn, self._obj.microscope)
8323 return None
8324
8326 """
8327 Gets the Instrument detectors.
8328
8329 :return: List of Detectors
8330 :rtype: L{DetectorWrapper} list
8331 """
8332
8333 return [DetectorWrapper(self._conn, x) for x in self._detectorSeq]
8334
8336 """
8337 Gets the Instrument Objectives.
8338
8339 :return: List of Objectives
8340 :rtype: L{ObjectiveWrapper} list
8341 """
8342
8343 return [ObjectiveWrapper(self._conn, x) for x in self._objectiveSeq]
8344
8346 """
8347 Gets the Instrument Filters.
8348
8349 :return: List of Filters
8350 :rtype: L{FilterWrapper} list
8351 """
8352
8353 return [FilterWrapper(self._conn, x) for x in self._filterSeq]
8354
8356 """
8357 Gets the Instrument Dichroics.
8358
8359 :return: List of Dichroics
8360 :rtype: L{DichroicWrapper} list
8361 """
8362
8363 return [DichroicWrapper(self._conn, x) for x in self._dichroicSeq]
8364
8366 """
8367 Gets the Instrument FilterSets.
8368
8369 :return: List of FilterSets
8370 :rtype: L{FilterSetWrapper} list
8371 """
8372
8373 return [FilterSetWrapper(self._conn, x) for x in self._filterSetSeq]
8374
8376 """
8377 Gets the Instrument OTFs.
8378
8379 :return: List of OTFs
8380 :rtype: L{OTFWrapper} list
8381 """
8382
8383 return [OTFWrapper(self._conn, x) for x in self._otfSeq]
8384
8386 """
8387 Gets the Instrument LightSources.
8388
8389 :return: List of LightSources
8390 :rtype: L{LightSourceWrapper} list
8391 """
8392
8393 return [LightSourceWrapper(self._conn, x) for x in self._lightSourceSeq]
8394
8395
8409
8410 InstrumentWrapper = _InstrumentWrapper
8411
8412 KNOWN_WRAPPERS = {}
8415 """
8416 this needs to be called by modules that extend the base wrappers
8417 """
8418 KNOWN_WRAPPERS.update({"project":ProjectWrapper,
8419 "dataset":DatasetWrapper,
8420 "image":ImageWrapper,
8421 "screen":ScreenWrapper,
8422 "plate":PlateWrapper,
8423 "plateacquisition": PlateAcquisitionWrapper,
8424 "acquisition": PlateAcquisitionWrapper,
8425 "well":WellWrapper,
8426 "experimenter":ExperimenterWrapper,
8427 "experimentergroup":ExperimenterGroupWrapper,
8428 "originalfile":OriginalFileWrapper,
8429 "fileset":FilesetWrapper,
8430 "commentannotation":CommentAnnotationWrapper,
8431 "tagannotation":TagAnnotationWrapper,
8432 "longannotation":LongAnnotationWrapper,
8433 "booleanannotation":BooleanAnnotationWrapper,
8434 "fileannotation":FileAnnotationWrapper,
8435 "doubleannotation":DoubleAnnotationWrapper,
8436 "termannotation":TermAnnotationWrapper,
8437 "timestampannotation":TimestampAnnotationWrapper,
8438 "annotation":AnnotationWrapper._wrap})
8439
8440 refreshWrappers()
8441