1
2
3
4
5
6
7
8
9
10
11
12
13
14 import os,sys
15 THISPATH = os.path.dirname(os.path.abspath(__file__))
16
17 import shutil
18 import tempfile
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, TimeIt
27 import Ice
28 import Glacier2
29
30 import traceback
31 import time
32 import array
33 import math
34
35 import logging
36 logger = logging.getLogger('blitz_gateway')
37
38 try:
39 import Image, ImageDraw, ImageFont
40 except:
41 try:
42 from PIL import Image, ImageDraw, ImageFont
43 except:
44 logger.error('No PIL installed, line plots and split channel will fail!')
45 from cStringIO import StringIO
46 from math import sqrt
47
48 import omero_Constants_ice
49 import omero_ROMIO_ice
50 from omero.rtypes import rstring, rint, rlong, rbool, rtime, rlist, rdouble, unwrap
53 """
54 Converts rtypes from static factory methods:
55 - StringType to rstring
56 - UnicodeType to rstring
57 - IntType to rint
58 - LongType to rlong
59 elswere return the argument itself
60
61 @param val: value
62 @rtype: omero.rtype
63 @return: matched RType or value
64 """
65
66 if isinstance(val, StringType):
67 return rstring(val)
68 elif isinstance(val, UnicodeType):
69 return rstring(val.encode('utf-8'))
70 elif isinstance(val, IntType):
71 return rint(val)
72 elif isinstance(val, LongType):
73 return rlong(val)
74 else:
75 return val
76
78 """
79 Reads everything from fin, in chunks of bufsize.
80
81
82 @type fin: file
83 @param fin: filelike readable object
84 @type fsize: int
85 @param fsize: total number of bytes to read
86 @type bufsize: int
87 @param fsize: size of each chunk of data read from fin
88 @rtype: string
89 @return: string buffer holding the contents read from the file
90 """
91
92 p = 0
93 rv = ''
94 while p < fsize:
95 s = min(bufsize, fsize-p)
96 rv += fin.read(p,s)
97 p += s
98 fin.close()
99 return rv
100
103 """
104 Generator helper function that yields chunks of the file of size fsize.
105
106 @type fin: file
107 @param fin: filelike readable object
108 @type fsize: int
109 @param fsize: total number of bytes to read
110 @type bufsize: int
111 @param fsize: size of each chunk of data read from fin that gets yielded
112 @rtype: generator
113 @return: generator of string buffers of size up to bufsize read from fin
114 """
115 p = 0
116 while p < fsize:
117 s = min(bufsize, fsize-p)
118 yield fin.read(p,s)
119 p += s
120 fin.close()
121
123 """
124 Object wrapper class which provides various methods for hierarchy traversing,
125 saving, handling permissions etc.
126 This is the 'abstract' super class which is subclassed by
127 E.g. _ProjectWrapper, _DatasetWrapper etc.
128 All ojbects have a reference to the L{BlitzGateway} connection, and therefore all services are
129 available for handling calls on the object wrapper. E.g listChildren() uses queryservice etc.
130 """
131
132 OMERO_CLASS = None
133 LINK_CLASS = None
134 LINK_CHILD = 'child'
135 CHILD_WRAPPER_CLASS = None
136 PARENT_WRAPPER_CLASS = None
137
138 @staticmethod
141
142 - def __init__ (self, conn=None, obj=None, cache=None, **kwargs):
143 """
144 Initialises the wrapper object, setting the various class variables etc
145
146 @param conn: The L{omero.gateway.BlitzGateway} connection.
147 @type conn: L{omero.gateway.BlitzGateway}
148 @param obj: The object to wrap. E.g. omero.model.Image
149 @type obj: omero.model object
150 @param cache: Cache which is passed to new child wrappers
151 """
152 self.__bstrap__()
153 self._obj = obj
154 self._cache = cache
155 if self._cache is None:
156 self._cache = {}
157 self._conn = conn
158 self._creationDate = None
159 if conn is None:
160 return
161 if hasattr(obj, 'id') and obj.id is not None:
162 self._oid = obj.id.val
163 if not self._obj.loaded:
164 self._obj = self._conn.getQueryService().get(self._obj.__class__.__name__, self._oid)
165 self.__prepare__ (**kwargs)
166
168 """
169 Returns true if the object is of the same type and has same id and name
170
171 @param a: The object to compare to this one
172 @return: True if objects are same - see above
173 @rtype: Boolean
174 """
175 return type(a) == type(self) and self._obj.id == a._obj.id and self.getName() == a.getName()
176
178 """ Initialisation method which is implemented by subclasses to set their class variables etc. """
179 pass
180
182 """ Initialisation method which is implemented by subclasses to handle various init tasks """
183 pass
184
186 """
187 Returns a String representation of the Object, including ID if set.
188
189 @return: String E.g. '<DatasetWrapper id=123>'
190 @rtype: String
191 """
192 if hasattr(self, '_oid'):
193 return '<%s id=%s>' % (self.__class__.__name__, str(self._oid))
194 return super(BlitzObjectWrapper, self).__repr__()
195
197 """
198 Used for building queries in generic methods such as getObjects("Project")
199 """
200 return "select obj from %s obj join fetch obj.details.owner as owner join fetch obj.details.group "\
201 "join fetch obj.details.creationEvent" % self.OMERO_CLASS
202
204 """
205 Returns the wrapper class of children of this object.
206 Checks that this is one of the Wrapper objects in the L{omero.gateway} module
207 Raises NotImplementedError if this is not true or class is not defined (None)
208 This is used internally by the L{listChildren} and L{countChildren} methods.
209
210 @return: The child wrapper class. E.g. omero.gateway.DatasetWrapper.__class__
211 @rtype: class
212 """
213 if self.CHILD_WRAPPER_CLASS is None:
214 raise NotImplementedError('%s has no child wrapper defined' % self.__class__)
215 if type(self.CHILD_WRAPPER_CLASS) is type(''):
216
217 if hasattr(omero.gateway, self.CHILD_WRAPPER_CLASS):
218 self.__class__.CHILD_WRAPPER_CLASS = self.CHILD_WRAPPER_CLASS = getattr(omero.gateway, self.CHILD_WRAPPER_CLASS)
219 else:
220 raise NotImplementedError
221 return self.CHILD_WRAPPER_CLASS
222
224 """
225 Returns the wrapper classes of the parent of this object.
226 This is used internally by the L{listParents} method.
227
228 @return: List of parent wrapper classes. E.g. omero.gateway.DatasetWrapper.__class__
229 @rtype: class
230 """
231 if self.PARENT_WRAPPER_CLASS is None:
232 raise NotImplementedError
233 pwc = self.PARENT_WRAPPER_CLASS
234 if not isinstance(pwc, ListType):
235 pwc = [pwc,]
236 for i in range(len(pwc)):
237 if isinstance(pwc[i], StringTypes):
238
239 g = globals()
240 if not g.has_key(pwc[i]):
241 raise NotImplementedError
242 pwc[i] = g[pwc[i]]
243
244
245
246
247
248
249
250
251 if pwc != self.PARENT_WRAPPER_CLASS or pwc != self.__class__.PARENT_WRAPPER_CLASS:
252 self.__class__.PARENT_WRAPPER_CLASS = self.PARENT_WRAPPER_CLASS = pwc
253 return self.PARENT_WRAPPER_CLASS
254
256 """
257 Loads the object that is wrapped by this class. This includes linked objects.
258 This method can be overwritten by subclasses that want to specify how/which linked objects
259 are loaded.
260 """
261 self._obj = self._conn.getContainerService().loadContainerHierarchy(self.OMERO_CLASS, (self._oid,), None)[0]
262
264 """
265 Moves this object from a parent container (first one if there are more than one) to a new parent.
266 TODO: might be more useful if it didn't assume only 1 parent - option allowed you to specify the oldParent.
267
268 @param newParent: The new parent Object Wrapper.
269 @return: True if moved from parent to parent.
270 False if no parent exists or newParent has mismatching type
271 @rtype: Boolean
272 """
273 p = self.getParent()
274
275 if p.OMERO_CLASS == newParent.OMERO_CLASS:
276 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)
277 if len(link):
278 link[0].parent = newParent._obj
279 self._conn.getUpdateService().saveObject(link[0])
280 return True
281 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))
282 else:
283 logger.debug("## %s != %s ('%s' - '%s')" % (type(p), type(newParent), str(p), str(newParent)))
284 return False
285
287 """
288 Find the first child object with a matching name, and description if specified.
289
290 @param name: The name which must match the child name
291 @param description: If specified, child description must match too
292 @return: The wrapped child object
293 @rtype: L{BlitzObjectWrapper}
294 """
295 for c in self.listChildren():
296 if c.getName() == name:
297 if description is None or omero_type(description) == omero_type(c.getDescription()):
298 return c
299 return None
300
302 """
303 Gets the details of the wrapped object
304
305 @return: L{omero.gateway.DetailsWrapper} or None if object not loaded
306 @rtype: L{DetailsWrapper}
307 """
308 if self._obj.loaded:
309 return omero.gateway.DetailsWrapper (self._conn, self._obj.getDetails())
310 return None
311
312
314 """
315 Returns the object's acquisitionDate, or creation date (details.creationEvent.time)
316
317 @return: A L{datetime.datetime} object
318 @rtype: datetime
319 """
320
321 try:
322 if self._obj.acquisitionDate.val is not None and self._obj.acquisitionDate.val > 0:
323 t = self._obj.acquisitionDate.val
324 return datetime.fromtimestamp(t/1000)
325 except:
326
327 pass
328
329 return self.creationEventDate()
330
331
339
341 """
342 Save this object, keeping the object owner the same as the one on provided details
343 If the current user is an admin but is NOT the owner specified in 'details',
344 then create a new connection for that owner, clone the current object under that
345 connection and save.
346 Otherwise, simply save.
347
348 @param details: The Details specifying owner to save to
349 @type details: L{DetailsWrapper}
350 @return: None
351 """
352 if self._conn.isAdmin():
353 d = self.getDetails()
354 if d.getOwner() and \
355 d.getOwner().omeName == details.getOwner().omeName and \
356 d.getGroup().name == details.getGroup().name:
357 return self.save()
358 else:
359 newConn = self._conn.suConn(details.getOwner().omeName, details.getGroup().name)
360
361
362
363
364
365
366
367 clone = self.__class__(newConn, self._obj)
368 clone.save()
369 self._obj = clone._obj
370 return
371 else:
372 return self.save()
373
375 """
376 Delegates to the connection L{BlitzGateway.canWrite} method
377
378 @rtype: Boolean
379 """
380 return self._conn.canWrite(self._obj)
381
383 """
384 Returns isUserWrite() from the object's permissions
385
386 @rtype: Boolean
387 @return: True if the objects's permissions allow user to write
388 """
389 return self._obj.details.permissions.isUserWrite()
390
392 """
393 Determines whether the current user can delete this object.
394 Returns True if the object L{isOwned} by the current user or L{isLeaded}
395 (current user is leader of this the group that this object belongs to)
396
397 @rtype: Boolean
398 @return: see above
399 """
400 return self.isOwned() or self.isLeaded()
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.getEventContext().userId)
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 if self._obj.details.group.id.val in self._conn.getEventContext().leaderOfGroups:
419 return True
420 return False
421
423 """
424 Determines whether the current user can edit this object.
425 Returns True if the object L{isOwned} by the current user
426 Also True if object is not L{private<isPrivate>} AND not L{readOnly<isReadOnly>}
427
428 @rtype: Boolean
429 @return: see above
430 """
431 return self.isOwned() or (not self.isPrivate() and not self.isReadOnly())
432
434 """
435 Determines if the object permissions are world readable, ie permissions.isWorldRead()
436
437 @rtype: Boolean
438 @return: see above
439 """
440 return self._obj.details.permissions.isWorldRead()
441
443 """
444 Determines if the object is sharable between groups (but not public)
445
446 @rtype: Boolean
447 @return: True if the object is not L{public<isPublic>} AND the
448 object permissions allow group read.
449 """
450 if not self.isPublic():
451 return self._obj.details.permissions.isGroupRead()
452 return False
453
455 """
456 Determines if the object is private
457
458 @rtype: Boolean
459 @return: True if the object is not L{public<isPublic>} and not L{shared<isShared>} and
460 permissions allow user to read.
461 """
462 if not self.isPublic() and not self.isShared():
463 return self._obj.details.permissions.isUserRead()
464 return False
465
467 """
468 Determines if the object is visible but not writeable
469
470 @rtype: Boolean
471 @return: True if public but not world writable
472 True if shared but not group writable
473 True if private but not user writable
474 """
475 if self.isPublic() and not self._obj.details.permissions.isWorldWrite():
476 return True
477 elif self.isShared() and not self._obj.details.permissions.isGroupWrite():
478 return True
479 elif self.isPrivate() and not self._obj.details.permissions.isUserWrite():
480 return True
481 return False
482
496
498 """
499 countChildren, but caching the first result, useful if you need to call this multiple times in
500 a single sequence, but have no way of storing the value between them.
501 It is actually a hack to support django template's lack of break in for loops
502
503 @return: The number of child objects available
504 @rtype: Long
505 """
506
507 if not hasattr(self, '_cached_countChildren'):
508 return self.countChildren()
509 return self._cached_countChildren
510
512 """
513 Lists available child objects.
514
515 @rtype: generator of Ice client proxy objects for the child nodes
516 @return: child objects.
517 """
518 if not params:
519 params = omero.sys.Parameters()
520 if not params.map:
521 params.map = {}
522 params.map["dsid"] = omero_type(self._oid)
523 query = "select c from %s as c" % self.LINK_CLASS
524 if ns is not None:
525 params.map["ns"] = omero_type(ns)
526 query += """ join fetch c.child as ch
527 left outer join fetch ch.annotationLinks as ial
528 left outer join fetch ial.child as a """
529 query += " where c.parent.id=:dsid"
530 if ns is not None:
531 query += " and a.ns=:ns"
532 if val is not None:
533 if isinstance(val, StringTypes):
534 params.map["val"] = omero_type(val)
535 query +=" and a.textValue=:val"
536 query += " order by c.child.name"
537 for child in ( x.child for x in self._conn.getQueryService().findAllByQuery(query, params) ):
538 yield child
539
541 """
542 Lists available child objects.
543
544 @rtype: generator of L{BlitzObjectWrapper} objs
545 @return: child objects.
546 """
547 childw = self._getChildWrapper()
548 for child in self._listChildren(ns=ns, val=val, params=params):
549 yield childw(self._conn, child, self._cache)
550
552 """
553 List a single parent, if available.
554
555 While the model suports many to many relationships between most objects, there are
556 implementations that assume a single project per dataset, a single dataset per image,
557 etc. This is just a shortcut method to return a single parent object.
558
559 @type withlinks: Boolean
560 @param withlinks: if true result will be a tuple of (linkobj, obj)
561 @rtype: L{BlitzObjectWrapper} ( or tuple(L{BlitzObjectWrapper}, L{BlitzObjectWrapper}) )
562 @return: the parent object with or without the link depending on args
563 """
564
565 rv = self.listParents(withlinks=withlinks)
566 return len(rv) and rv[0] or None
567
569 """
570 Lists available parent objects.
571
572 @type withlinks: Boolean
573 @param withlinks: if true each yielded result will be a tuple of (linkobj, obj)
574 @rtype: list of L{BlitzObjectWrapper} ( or tuple(L{BlitzObjectWrapper}, L{BlitzObjectWrapper}) )
575 @return: the parent objects, with or without the links depending on args
576 """
577 if self.PARENT_WRAPPER_CLASS is None:
578 return ()
579 parentw = self._getParentWrappers()
580 param = omero.sys.Parameters()
581 parentnodes = []
582 for pwc in parentw:
583 pwck = pwc()
584 if withlinks:
585 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)])
586 else:
587 parentnodes.extend([pwc(self._conn, pwck.LINK_PARENT(x), self._cache) 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)])
588 return parentnodes
589
591 """
592 Get a list of Ancestors. First in list is parent of this object.
593 TODO: Assumes getParent() returns a single parent.
594
595 @rtype: List of L{BlitzObjectWrapper}
596 @return: List of Ancestor objects
597 """
598 rv = []
599 p = self.getParent()
600 while p:
601 rv.append(p)
602 p = p.getParent()
603 return rv
604
606 """
607 Get a list of parent objects links.
608
609 @param pids: List of parent IDs
610 @type pids: L{Long}
611 @rtype: List of L{BlitzObjectWrapper}
612 @return: List of parent object links
613 """
614
615 if self.PARENT_WRAPPER_CLASS is None:
616 raise AttributeError("This object has no parent objects")
617 parentwrappers = self._getParentWrappers()
618 link_class = None
619 for v in parentwrappers:
620 link_class = v().LINK_CLASS
621 if link_class is not None:
622 break
623 if link_class is None:
624 raise AttributeError(
625 "This object has no parent objects with a link class!")
626 query_serv = self._conn.getQueryService()
627 p = omero.sys.Parameters()
628 p.map = {}
629 p.map["child"] = rlong(self.id)
630 sql = "select pchl from %s as pchl " \
631 "left outer join fetch pchl.parent as parent " \
632 "left outer join fetch pchl.child as child " \
633 "where child.id=:child" % link_class
634 if isinstance(pids, list) and len(pids) > 0:
635 p.map["parent"] = rlist([rlong(pa) for pa in pids])
636 sql+=" and parent.id in (:parent)"
637 for pchl in query_serv.findAllByQuery(sql, p):
638 yield BlitzObjectWrapper(self, pchl)
639
641 """
642 Get a list of child objects links.
643
644 @param chids: List of children IDs
645 @type chids: L{Long}
646 @rtype: List of L{BlitzObjectWrapper}
647 @return: List of child object links
648 """
649
650 if self.CHILD_WRAPPER_CLASS is None:
651 raise AttributeError("This object has no child objects")
652 childw = self._getChildWrapper()
653 query_serv = self._conn.getQueryService()
654 p = omero.sys.Parameters()
655 p.map = {}
656 p.map["parent"] = rlong(self.id)
657 sql = "select pchl from %s as pchl left outer join fetch pchl.child as child \
658 left outer join fetch pchl.parent as parent where parent.id=:parent" % self.LINK_CLASS
659 if isinstance(chids, list) and len(chids) > 0:
660 p.map["children"] = rlist([rlong(ch) for ch in chids])
661 sql+=" and child.id in (:children)"
662 for pchl in query_serv.findAllByQuery(sql, p):
663 yield BlitzObjectWrapper(self, pchl)
664
666 """ Loads the annotation links for the object (if not already loaded) and saves them to the object """
667 if not hasattr(self._obj, 'isAnnotationLinksLoaded'):
668 raise NotImplementedError
669 if not self._obj.isAnnotationLinksLoaded():
670 query = "select l from %sAnnotationLink as l join fetch l.details.owner join fetch l.details.creationEvent "\
671 "join fetch l.child as a join fetch a.details.owner join fetch a.details.creationEvent "\
672 "where l.parent.id=%i" % (self.OMERO_CLASS, self._oid)
673 links = self._conn.getQueryService().findAllByQuery(query, None)
674 self._obj._annotationLinksLoaded = True
675 self._obj._annotationLinksSeq = links
676
677
679 """
680 Checks links are loaded and returns a list of Annotation Links filtered by
681 namespace if specified
682
683 @param ns: Namespace
684 @type ns: String
685 @return: List of Annotation Links on this object
686 @rtype: List of Annotation Links
687 """
688 self._loadAnnotationLinks()
689 rv = self.copyAnnotationLinks()
690 if ns is not None:
691 rv = filter(lambda x: x.getChild().getNs() and x.getChild().getNs().val == ns, rv)
692 return rv
693
694
696 """
697 Uses updateService to unlink annotations, with specified ns
698
699 @param ns: Namespace
700 @type ns: String
701 """
702 for al in self._getAnnotationLinks(ns=ns):
703 update = self._conn.getUpdateService()
704 update.deleteObject(al)
705 self._obj.unloadAnnotationLinks()
706
708 """
709 Uses updateService to delete annotations, with specified ns, and their links on the object
710
711 @param ns: Namespace
712 @type ns: String
713 """
714 for al in self._getAnnotationLinks(ns=ns):
715 a = al.child
716 update = self._conn.getUpdateService()
717 update.deleteObject(al)
718 update.deleteObject(a)
719 self._obj.unloadAnnotationLinks()
720
721
723 """
724 Gets the first annotation on the object, filtered by ns if specified
725
726 @param ns: Namespace
727 @type ns: String
728 @return: L{AnnotationWrapper} or None
729 """
730 rv = self._getAnnotationLinks(ns)
731 if len(rv):
732 return AnnotationWrapper._wrap(self._conn, rv[0].child, link=rv[0])
733 return None
734
736 """
737 List annotations in the ns namespace, linked to this object
738
739 @return: Generator yielding L{AnnotationWrapper}
740 @rtype: L{AnnotationWrapper} generator
741 """
742 for ann in self._getAnnotationLinks(ns):
743 yield AnnotationWrapper._wrap(self._conn, ann.child, link=ann)
744
746 """
747 Retrieve all Annotations not linked to the given Project, Dataset, Image,
748 Screen, Plate, Well ID controlled by the security system.
749
750 @param o_type: type of Object
751 @type o_type: String
752 @param oid: Object ID
753 @type oid: Long
754 @return: Generator yielding Tags
755 @rtype: L{AnnotationWrapper} generator
756 """
757
758 if anntype is not None:
759 if anntype.title() not in ('Text', 'Tag', 'File', 'Long', 'Boolean'):
760 raise AttributeError('It only retrieves: Text, Tag, File, Long, Boolean')
761 sql = "select an from %sAnnotation as an " % anntype.title()
762 else:
763 sql = "select an from Annotation as an " \
764
765 if anntype.title() == "File":
766 sql += " join fetch an.file "
767
768 sql += "where not exists ( select obal from %sAnnotationLink as obal "\
769 "where obal.child=an.id and obal.parent.id=:oid) " % self.OMERO_CLASS
770
771 q = self._conn.getQueryService()
772 p = omero.sys.Parameters()
773 p.map = {}
774 p.map["oid"] = rlong(self._oid)
775 if ns is None:
776 sql += " and an.ns is null"
777 else:
778 p.map["ns"] = rlist([rstring(n) for n in ns])
779 sql += " and (an.ns not in (:ns) or an.ns is null)"
780 if eid is not None:
781 sql += " and an.details.owner.id=:eid"
782 p.map["eid"] = rlong(eid)
783
784 for e in q.findAllByQuery(sql,p):
785 yield AnnotationWrapper._wrap(self._conn, e)
786
788 """
789 Saves the annotation to DB if needed - setting the permissions manually.
790 Creates the annotation link and saves it, setting permissions manually.
791 TODO: Can't set permissions manually in 4.2 - Assumes world & group writable
792
793 @param ann: The annotation object
794 @type ann: L{AnnotationWrapper}
795 """
796 if not ann.getId():
797
798 ann = ann.__class__(self._conn, self._conn.getUpdateService().saveAndReturnObject(ann._obj))
799
800
801 lnktype = "%sAnnotationLinkI" % self.OMERO_CLASS
802 lnk = getattr(omero.model, lnktype)()
803 lnk.setParent(self._obj.__class__(self._obj.id, False))
804 lnk.setChild(ann._obj.__class__(ann._obj.id, False))
805 self._conn.getUpdateService().saveObject(lnk)
806 return ann
807
808
810 """
811 Link the annotation to this object.
812
813 @param ann: The Annotation object
814 @type ann: L{AnnotationWrapper}
815 @param sameOwner: If True, try to make sure that the link is created by the object owner
816 @type sameOwner: Boolean
817 @return: The annotation
818 @rtype: L{AnnotationWrapper}
819 """
820
821 """
822 My notes (will) to try and work out what's going on!
823 If sameOwner:
824 if current user is admin AND they are not the object owner,
825 if the object owner and annotation owner are the same:
826 use the Annotation connection to do the linking
827 else use a new connection for the object owner (?same owner as ann?)
828 do linking
829 else:
830 try to switch the current group of this object to the group of the annotation - do linking
831 else - just do linking
832
833 """
834 if sameOwner:
835 d = self.getDetails()
836 ad = ann.getDetails()
837 if self._conn.isAdmin() and self._conn._userid != d.getOwner().id:
838
839 if ad.getOwner() and d.getOwner().omeName == ad.getOwner().omeName and d.getGroup().name == ad.getGroup().name:
840 newConn = ann._conn
841 else:
842
843
844 group = None
845 if d.getGroup():
846 group = d.getGroup().name
847
848 newConn = self._conn.suConn(d.getOwner().omeName, group)
849
850
851
852
853 clone = self.__class__(newConn, self._obj)
854 ann = clone._linkAnnotation(ann)
855 if newConn != self._conn:
856 newConn.seppuku()
857 elif d.getGroup():
858
859
860 self._conn.setGroupForSession(d.getGroup().getId())
861 ann = self._linkAnnotation(ann)
862 self._conn.revertGroupForSession()
863 else:
864 ann = self._linkAnnotation(ann)
865 else:
866 ann = self._linkAnnotation(ann)
867 self.unloadAnnotationLinks()
868 return ann
869
870
872 """
873 Creates a dict representation of this object.
874 E.g. for Image: {'description': '', 'author': 'Will Moore', 'date': 1286332557.0,
875 'type': 'Image', 'id': 3841L, 'name': 'cb_4_w500_t03_z01.tif'}
876
877 @param xtra: A dict of extra keys to include. E.g. 'childCount'
878 @type xtra: Dict
879 @param parents: If True, include a list of ancestors (in simpleMarshal form) as 'parents'
880 @type parents: Boolean
881 @return: A dict representation of this object
882 @rtype: Dict
883 """
884 rv = {'type': self.OMERO_CLASS,
885 'id': self.getId(),
886 'name': self.getName(),
887 'description': self.getDescription(),
888 }
889 if hasattr(self, '_attrs'):
890
891
892
893
894 for k in self._attrs:
895 if ';' in k:
896 s = k.split(';')
897 k = s[0]
898 rk = ';'.join(s[1:])
899 else:
900 rk = k
901 rk = rk.replace('#', '')
902 if '|' in k:
903 s = k.split('|')
904 k2 = s[0]
905 w = '|'.join(s[1:])
906 if rk == k:
907 rk = k2
908 k = k2
909 v = getattr(self, k)
910 if v is not None:
911 v = getattr(omero.gateway, w)(self._conn, v).simpleMarshal()
912 else:
913 if k.startswith('#'):
914 v = getattr(self, k[1:])
915 if v is not None:
916 v = v._value
917 else:
918 v = getattr(self, k)
919 if hasattr(v, 'val'):
920 v = v.val
921 rv[rk] = v
922 if xtra:
923 if xtra.has_key('childCount'):
924 rv['child_count'] = self.countChildren()
925 if parents:
926 rv['parents'] = map(lambda x: x.simpleMarshal(), self.getAncestry())
927 return rv
928
929
930
931
932
933
935 """
936 Attempts to return the named attribute of this object. E.g. image.__getattr__('name') or 'getName'
937 In cases where the attribute E.g. 'getImmersion' should return an enumeration, this is specified by the
938 attr name starting with '#' #immersion.
939 In cases where the attribute E.g. 'getLightSource' should return a wrapped object, this is handled
940 by the parent encoding the wrapper in the attribute name. E.g 'lightSource|LightSourceWrapper'
941 In both cases this returns a method that will return the object.
942 In addition, lookup of methods that return an rtype are wrapped to the method instead returns a primitive type.
943 E.g. image.getArchived() will return a boolean instead of rbool.
944
945 @param attr: The name of the attribute to get
946 @type attr: String
947 @return: The named attribute.
948 @rtype: method, value (string, long etc)
949 """
950
951
952 if attr != 'get' and attr.startswith('get') and hasattr(self, '_attrs'):
953 tattr = attr[3].lower() + attr[4:]
954 attrs = filter(lambda x: tattr in x, self._attrs)
955 for a in attrs:
956 if a.startswith('#') and a[1:] == tattr:
957 v = getattr(self, tattr)
958 if v is not None:
959 v = v._value
960 def wrap ():
961 return v
962 return wrap
963 if len(a) > len(tattr) and a[len(tattr)] == '|':
964 def wrap ():
965 return getattr(omero.gateway, a[len(tattr)+1:])(self._conn, getattr(self, tattr))
966 return wrap
967
968
969 if attr != 'get' and attr.startswith('get'):
970 attrName = attr[3].lower() + attr[4:]
971 if hasattr(self._obj, attrName):
972 def wrap():
973 rv = getattr(self._obj, attrName)
974 if hasattr(rv, 'val'):
975 return isinstance(rv.val, StringType) and rv.val.decode('utf8') or rv.val
976 elif isinstance(rv, omero.model.IObject):
977 return BlitzObjectWrapper(self._conn, rv)
978 return rv
979 return wrap
980
981
982
983 if not hasattr(self._obj, attr) and hasattr(self._obj, '_'+attr):
984 attr = '_' + attr
985 if hasattr(self._obj, attr):
986 rv = getattr(self._obj, attr)
987 if hasattr(rv, 'val'):
988 return isinstance(rv.val, StringType) and rv.val.decode('utf8') or rv.val
989 return rv
990 raise AttributeError("'%s' object has no attribute '%s'" % (self._obj.__class__.__name__, attr))
991
992
993
994
996 """
997 Gets this object ID
998
999 @return: Long or None
1000 """
1001 oid = self._obj.getId()
1002 if oid is not None:
1003 return oid.val
1004 return None
1005
1007 """
1008 Gets this object name
1009
1010 @return: String or None
1011 """
1012 if hasattr(self._obj, 'name'):
1013 if hasattr(self._obj.name, 'val'):
1014 return self._obj.getName().val
1015 else:
1016 return self._obj.getName()
1017 else:
1018 return None
1019
1021 """
1022 Gets this object description
1023
1024 @return: String
1025 """
1026 rv = hasattr(self._obj, 'description') and self._obj.getDescription() or None
1027 return rv and rv.val or ''
1028
1030 """
1031 Gets user who is the owner of this object.
1032
1033 @return: _ExperimenterWrapper
1034 """
1035 return self.getDetails().getOwner()
1036
1038 """
1039 Gets full name of the owner of this object.
1040
1041 @return: String or None
1042 """
1043 try:
1044 lastName = self.getDetails().getOwner().lastName
1045 firstName = self.getDetails().getOwner().firstName
1046 middleName = self.getDetails().getOwner().middleName
1047
1048 if middleName is not None and middleName != '':
1049 name = "%s %s. %s" % (firstName, middleName, lastName)
1050 else:
1051 name = "%s %s" % (firstName, lastName)
1052 return name
1053 except:
1054 logger.error(traceback.format_exc())
1055 return None
1056
1058 """
1059 Gets omeName of the owner of this object.
1060
1061 @return: String
1062 """
1063 return self.getDetails().getOwner().omeName
1064
1065
1067 """
1068 Gets event time in timestamp format (yyyy-mm-dd hh:mm:ss.fffffff) when object was created.
1069
1070 @return: The datetime for object creation
1071 @rtype: datetime.datetime
1072 """
1073
1074 if self._creationDate is not None:
1075 return datetime.fromtimestamp(self._creationDate/1000)
1076
1077 try:
1078 if self._obj.details.creationEvent._time is not None:
1079 self._creationDate = self._obj.details.creationEvent._time.val
1080 else:
1081 self._creationDate = self._conn.getQueryService().get("Event", self._obj.details.creationEvent.id.val).time.val
1082 except:
1083 self._creationDate = self._conn.getQueryService().get("Event", self._obj.details.creationEvent.id.val).time.val
1084 return datetime.fromtimestamp(self._creationDate/1000)
1085
1086
1088 """
1089 Gets event time in timestamp format (yyyy-mm-dd hh:mm:ss.fffffff) when object was updated.
1090
1091 @return: The datetime for object update
1092 @rtype: datetime.datetime
1093 """
1094
1095 try:
1096 if self._obj.details.updateEvent.time is not None:
1097 t = self._obj.details.updateEvent.time.val
1098 else:
1099 t = self._conn.getQueryService().get("Event", self._obj.details.updateEvent.id.val).time.val
1100 except:
1101 t = self._conn.getQueryService().get("Event", self._obj.details.updateEvent.id.val).time.val
1102 return datetime.fromtimestamp(t/1000)
1103
1104
1105
1106
1108 """
1109 Sets the name of the object
1110
1111 @param value: New name
1112 @type value: String
1113 """
1114 self._obj.setName(omero_type(value))
1115
1117 """
1118 Sets the description of the object
1119
1120 @param value: New description
1121 @type value: String
1122 """
1123 self._obj.setDescription(omero_type(value))
1124
1128 """ A dummy placeholder to indicate that proxies haven't been created """
1130 raise Ice.ConnectionLostException
1131
1133 """
1134 Connection wrapper. Handles connecting and keeping the session alive, creation of various services,
1135 context switching, security privilidges etc.
1136 """
1137
1138 CONFIG = {}
1139 """
1140 Holder for class wide configuration properties:
1141 - IMG_RDEFNS: a namespace for annotations linked on images holding the default rendering
1142 settings object id.
1143 - IMG_ROPTSNS: a namespace for annotations linked on images holding default rendering options
1144 that don't get saved in the rendering settings.
1145 One good place to define this is on the extending class' connect() method.
1146 """
1147 ICE_CONFIG = None
1148 """
1149 ICE_CONFIG - Defines the path to the Ice configuration
1150 """
1151
1152
1153 - 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):
1154 """
1155 Create the connection wrapper. Does not attempt to connect at this stage
1156 Initialises the omero.client
1157
1158 @param username: User name. If not specified, use 'omero.gateway.anon_user'
1159 @type username: String
1160 @param passwd: Password.
1161 @type passwd: String
1162 @param client_obj: omero.client
1163 @param group: name of group to try to connect to
1164 @type group: String
1165 @param clone: If True, overwrite anonymous with False
1166 @type clone: Boolean
1167 @param try_super: Try to log on as super user ('system' group)
1168 @type try_super: Boolean
1169 @param host: Omero server host.
1170 @type host: String
1171 @param port: Omero server port.
1172 @type port: Integer
1173 @param extra_config: Dictionary of extra configuration
1174 @type extra_config: Dict
1175 @param secure: Initial underlying omero.client connection type (True=SSL/False=insecure)
1176 @type secure: Boolean
1177 @param anonymous:
1178 @type anonymous: Boolean
1179 @param useragent: Log which python clients use this connection. E.g. 'OMERO.webadmin'
1180 @type useragent: String
1181 """
1182
1183 if extra_config is None: extra_config = []
1184 super(_BlitzGateway, self).__init__()
1185 self.c = client_obj
1186 if not type(extra_config) in (type(()), type([])):
1187 extra_config=[extra_config]
1188 self.extra_config = extra_config
1189 self.ice_config = [self.ICE_CONFIG]
1190 self.ice_config.extend(extra_config)
1191 self.ice_config = map(lambda x: str(x), filter(None, self.ice_config))
1192
1193 self.host = host
1194 self.port = port
1195 self.secure = secure
1196 self.useragent = useragent
1197
1198 self._sessionUuid = None
1199 self._session_cb = None
1200 self._session = None
1201 self._lastGroupId = None
1202 self._anonymous = anonymous
1203
1204 self._connected = False
1205 self._user = None
1206 self._userid = None
1207 self._proxies = NoProxies()
1208 if self.c is None:
1209 self._resetOmeroClient()
1210 else:
1211
1212 self._connected = True
1213 self._createProxies()
1214 if not username:
1215 username = self.c.ic.getProperties().getProperty('omero.gateway.anon_user')
1216 passwd = self.c.ic.getProperties().getProperty('omero.gateway.anon_pass')
1217
1218 if try_super:
1219 self.group = 'system'
1220 else:
1221 self.group = group and group or None
1222
1223
1224 self.setIdentity(username, passwd, not clone)
1225
1227 """
1228 Returns the anonymous flag
1229
1230 @return: Anonymous
1231 @rtype: Boolean
1232 """
1233 return not not self._anonymous
1234
1236 """
1237 Returns named property of the wrapped omero.client
1238
1239 @return: named client property
1240 """
1241 return self.c.getProperty(k)
1242
1244 """
1245 Returns a new instance of this class, with all matching properties.
1246 TODO: Add anonymous and userAgent parameters?
1247
1248 @return: Clone of this connection wrapper
1249 @rtype: L{_BlitzGateway}
1250 """
1251 return self.__class__(self._ic_props[omero.constants.USERNAME],
1252 self._ic_props[omero.constants.PASSWORD],
1253 host = self.host,
1254 port = self.port,
1255 extra_config=self.extra_config,
1256 clone=True,
1257 secure=self.secure,
1258 anonymous=self._anonymous,
1259 useragent=self.useragent)
1260
1261
1262 - def setIdentity (self, username, passwd, _internal=False):
1263 """
1264 Saves the username and password for later use, creating session etc
1265
1266 @param username: User name.
1267 @type username: String
1268 @param passwd: Password.
1269 @type passwd: String
1270 @param _internal: If False, set _anonymous = False
1271 @type _internal: Booelan
1272 """
1273 self._ic_props = {omero.constants.USERNAME: username,
1274 omero.constants.PASSWORD: passwd}
1275 if not _internal:
1276 self._anonymous = False
1277
1278 - def suConn (self, username, group=None, ttl=60000):
1279 """
1280 If current user isAdmin, return new connection owned by 'username'
1281
1282 @param username: Username for new connection
1283 @type username: String
1284 @param group: If specified, try to log in to this group
1285 @type group: String
1286 @param ttl: Timeout for new session
1287 @type ttl: Int
1288 @return: Clone of this connection, with username's new Session
1289 @rtype: L{_BlitzGateway} or None if not admin or username unknown
1290 """
1291 if self.isAdmin():
1292 if group is None:
1293 e = self.getObject("Experimenter", attributes={'omeName': username})
1294 if e is None:
1295 return
1296 group = e._obj._groupExperimenterMapSeq[0].parent.name.val
1297 p = omero.sys.Principal()
1298 p.name = username
1299 p.group = group
1300 p.eventType = "User"
1301 newConnId = self.getSessionService().createSessionWithTimeout(p, ttl)
1302 newConn = self.clone()
1303 newConn.connect(sUuid=newConnId.getUuid().val)
1304 return newConn
1305
1307 """
1308 Keeps service alive.
1309 Returns True if connected. If connection was lost, reconnecting.
1310 If connection failed, returns False and error is logged.
1311
1312 @return: True if connection alive.
1313 @rtype: Boolean
1314 """
1315
1316 try:
1317 if self.c.sf is None:
1318 logger.debug('... c.sf is None, reconnecting')
1319 return self.connect()
1320 return self.c.sf.keepAlive(self._proxies['admin']._obj)
1321 except Ice.ObjectNotExistException:
1322
1323 logger.debug(traceback.format_exc())
1324 logger.debug("... reset, not reconnecting")
1325 return False
1326 except Ice.ConnectionLostException:
1327
1328 logger.debug(traceback.format_exc())
1329 logger.debug("... lost, reconnecting")
1330
1331 return False
1332 except Ice.ConnectionRefusedException:
1333
1334 logger.debug(traceback.format_exc())
1335 logger.debug("... refused, not reconnecting")
1336 return False
1337 except omero.SessionTimeoutException:
1338
1339 logger.debug(traceback.format_exc())
1340 logger.debug("... reset, not reconnecting")
1341 return False
1342 except omero.RemovedSessionException:
1343
1344 logger.debug(traceback.format_exc())
1345 logger.debug("... session has left the building, not reconnecting")
1346 return False
1347 except Ice.UnknownException, x:
1348
1349 logger.debug(traceback.format_exc())
1350 logger.debug('Ice.UnknownException: %s' % str(x))
1351 logger.debug("... ice says something bad happened, not reconnecting")
1352 return False
1353 except:
1354
1355 logger.debug(traceback.format_exc())
1356 logger.debug("... error not reconnecting")
1357 return False
1358
1359 - def seppuku (self, softclose=False):
1360 """
1361 Terminates connection with killSession(). If softclose is False, the session is really
1362 terminate disregarding its connection refcount.
1363
1364 @param softclose: Boolean
1365 """
1366 self._connected = False
1367 if softclose:
1368 try:
1369 r = self.c.sf.getSessionService().getReferenceCount(self._sessionUuid)
1370 self.c.closeSession()
1371 if r < 2:
1372 self._session_cb and self._session_cb.close(self)
1373 except Ice.OperationNotExistException:
1374 self.c.closeSession()
1375 else:
1376 self._closeSession()
1377 self._proxies = NoProxies()
1378 logger.info("closed connecion (uuid=%s)" % str(self._sessionUuid))
1379
1380
1381
1382
1384 """
1385 Creates proxies to the server services. Called on connection or security switch.
1386 Doesn't actually create any services themselves. Created if/when needed.
1387 If proxies have been created already, they are resynced and reused.
1388 """
1389
1390 if not isinstance(self._proxies, NoProxies):
1391 logger.debug("## Reusing proxies")
1392 for k, p in self._proxies.items():
1393 p._resyncConn(self)
1394 else:
1395 logger.debug("## Creating proxies")
1396 self._proxies = {}
1397 self._proxies['admin'] = ProxyObjectWrapper(self, 'getAdminService')
1398 self._proxies['config'] = ProxyObjectWrapper(self, 'getConfigService')
1399 self._proxies['container'] = ProxyObjectWrapper(self, 'getContainerService')
1400 self._proxies['delete'] = ProxyObjectWrapper(self, 'getDeleteService')
1401 self._proxies['export'] = ProxyObjectWrapper(self, 'createExporter')
1402 self._proxies['ldap'] = ProxyObjectWrapper(self, 'getLdapService')
1403 self._proxies['metadata'] = ProxyObjectWrapper(self, 'getMetadataService')
1404 self._proxies['query'] = ProxyObjectWrapper(self, 'getQueryService')
1405 self._proxies['pixel'] = ProxyObjectWrapper(self, 'getPixelsService')
1406 self._proxies['projection'] = ProxyObjectWrapper(self, 'getProjectionService')
1407 self._proxies['rawpixels'] = ProxyObjectWrapper(self, 'createRawPixelsStore')
1408 self._proxies['rendering'] = ProxyObjectWrapper(self, 'createRenderingEngine')
1409 self._proxies['rendsettings'] = ProxyObjectWrapper(self, 'getRenderingSettingsService')
1410 self._proxies['thumbs'] = ProxyObjectWrapper(self, 'createThumbnailStore')
1411 self._proxies['rawfile'] = ProxyObjectWrapper(self, 'createRawFileStore')
1412 self._proxies['repository'] = ProxyObjectWrapper(self, 'getRepositoryInfoService')
1413 self._proxies['roi'] = ProxyObjectWrapper(self, 'getRoiService')
1414 self._proxies['script'] = ProxyObjectWrapper(self, 'getScriptService')
1415 self._proxies['search'] = ProxyObjectWrapper(self, 'createSearchService')
1416 self._proxies['session'] = ProxyObjectWrapper(self, 'getSessionService')
1417 self._proxies['share'] = ProxyObjectWrapper(self, 'getShareService')
1418 self._proxies['sharedres'] = ProxyObjectWrapper(self, 'sharedResources')
1419 self._proxies['timeline'] = ProxyObjectWrapper(self, 'getTimelineService')
1420 self._proxies['types'] = ProxyObjectWrapper(self, 'getTypesService')
1421 self._proxies['update'] = ProxyObjectWrapper(self, 'getUpdateService')
1422 self._ctx = self._proxies['admin'].getEventContext()
1423 if self._ctx is not None:
1424 self._userid = self._ctx.userId
1425
1426 self._user = self._ctx.userName!="guest" and self.getObject("Experimenter", self._userid) or None
1427 else:
1428 self._userid = None
1429 self._user = None
1430
1431 if self._session_cb:
1432 if self._was_join:
1433 self._session_cb.join(self)
1434 else:
1435 self._session_cb.create(self)
1436
1438 """
1439 Switches between SSL and insecure (faster) connections to Blitz.
1440 The gateway must already be connected.
1441
1442 @param secure: If False, use an insecure connection
1443 @type secure: Boolean
1444 """
1445 if hasattr(self.c, 'createClient') and (secure ^ self.c.isSecure()):
1446 oldC = self.c
1447 self.c = oldC.createClient(secure=secure)
1448 oldC.__del__()
1449 self.c = self.c.createClient(secure=secure)
1450 self._createProxies()
1451 self.secure = secure
1452
1454 """ Returns 'True' if the underlying omero.clients.BaseClient is connected using SSL """
1455 return hasattr(self.c, 'isSecure') and self.c.isSecure() or False
1456
1459
1477
1479 """
1480 Close session.
1481 """
1482 self._session_cb and self._session_cb.close(self)
1483 try:
1484 self.c.killSession()
1485 except Glacier2.SessionNotExistException:
1486 pass
1487 except:
1488 logger.warn(traceback.format_exc())
1489
1491 """
1492 Creates new omero.client object using self.host or self.ice_config (if host is None)
1493 Also tries to setAgent for the client
1494 """
1495 if self.host is not None:
1496 if self.port is not None:
1497 self.c = omero.client(host=str(self.host), port=int(self.port))
1498 else:
1499 self.c = omero.client(host=str(self.host))
1500 else:
1501 self.c = omero.client(pmap=['--Ice.Config='+','.join(self.ice_config)])
1502
1503 if hasattr(self.c, "setAgent"):
1504 if self.useragent is not None:
1505 self.c.setAgent(self.useragent)
1506 else:
1507 self.c.setAgent("OMERO.py.gateway")
1508
1510 """
1511 Creates or retrieves connection for the given sessionUuid.
1512 Returns True if connected.
1513
1514 @param sUuid: omero_model_SessionI
1515 @return: Boolean
1516 """
1517
1518 logger.debug("Connect attempt, sUuid=%s, group=%s, self.sUuid=%s" % (str(sUuid), str(self.group), self._sessionUuid))
1519 if not self.c:
1520 self._connected = False
1521 logger.debug("Ooops. no self._c")
1522 return False
1523 try:
1524 if self._sessionUuid is None and sUuid:
1525 self._sessionUuid = sUuid
1526 if self._sessionUuid is not None:
1527 try:
1528 logger.debug('connected? %s' % str(self._connected))
1529 if self._connected:
1530 self._connected = False
1531 logger.debug("was connected, creating new omero.client")
1532 self._resetOmeroClient()
1533 s = self.c.joinSession(self._sessionUuid)
1534 s.detachOnDestroy()
1535 logger.debug('Joined Session OK with Uuid: %s and timeToIdle: %s, timeToLive: %s' % (self._sessionUuid, self.getSession().timeToIdle.val, self.getSession().timeToLive.val))
1536 self._was_join = True
1537 except Ice.SyscallException:
1538 raise
1539 except Exception, x:
1540 logger.debug("Error: " + str(x))
1541 self._sessionUuid = None
1542 if sUuid:
1543 return False
1544 if self._sessionUuid is None:
1545 if sUuid:
1546 logger.debug("Uncaptured sUuid failure!")
1547 if self._connected:
1548 self._connected = False
1549 try:
1550 logger.debug("Closing previous connection...creating new client")
1551
1552
1553 self._closeSession()
1554 self._resetOmeroClient()
1555
1556 except Glacier2.SessionNotExistException:
1557 pass
1558 setprop = self.c.ic.getProperties().setProperty
1559 map(lambda x: setprop(x[0],str(x[1])), self._ic_props.items())
1560 if self._anonymous:
1561 self.c.ic.getImplicitContext().put(omero.constants.EVENT, 'Internal')
1562 if self.group is not None:
1563 self.c.ic.getImplicitContext().put(omero.constants.GROUP, self.group)
1564 try:
1565 logger.debug("Creating Session...")
1566 self._createSession()
1567 logger.debug("Session created with timeout: %s & timeToLive: %s" % (self.getSession().timeToIdle.val, self.getSession().timeToLive.val))
1568 except omero.SecurityViolation:
1569 if self.group is not None:
1570
1571 logger.debug("## User not in '%s' group" % self.group)
1572 self.group = None
1573 self._closeSession()
1574 self._sessionUuid = None
1575 self._connected=True
1576 return self.connect()
1577 else:
1578 logger.debug("BlitzGateway.connect().createSession(): " + traceback.format_exc())
1579 logger.info('first create session threw SecurityViolation, retry (but only once)')
1580
1581 try:
1582 self._createSession()
1583 except omero.SecurityViolation:
1584 if self.group is not None:
1585
1586 logger.debug("## User not in '%s' group" % self.group)
1587 self.group = None
1588 self._connected=True
1589 return self.connect()
1590 else:
1591 raise
1592 except Ice.SyscallException:
1593 raise
1594 except:
1595 logger.info("BlitzGateway.connect().createSession(): " + traceback.format_exc())
1596
1597 self._createSession()
1598
1599 self._last_error = None
1600 self._createProxies()
1601 self._connected = True
1602 logger.info('created connection (uuid=%s)' % str(self._sessionUuid))
1603 except Ice.SyscallException:
1604 logger.debug('This one is a SyscallException')
1605 raise
1606 except Ice.LocalException, x:
1607 logger.debug("connect(): " + traceback.format_exc())
1608 self._last_error = x
1609 return False
1610 except Exception, x:
1611 logger.debug("connect(): " + traceback.format_exc())
1612 self._last_error = x
1613 return False
1614 logger.debug(".. connected!")
1615 return True
1616
1618 """
1619 Returns error if thrown by _BlitzGateway.connect connect.
1620
1621 @return: String
1622 """
1623
1624 return self._last_error
1625
1627 """
1628 Returns last status of connection.
1629
1630 @return: Boolean
1631 """
1632
1633 return self._connected
1634
1635
1636
1637
1638 - def getEventContext (self):
1639 """
1640 Returns omero_System_ice.EventContext.
1641 It containes::
1642 shareId, sessionId, sessionUuid, userId, userName,
1643 groupId, groupName, isAdmin, isReadOnly,
1644 eventId, eventType, eventType,
1645 memberOfGroups, leaderOfGroups
1646 Also saves context to self._ctx
1647
1648 @return: Event Context from admin service.
1649 @rtype: L{omero.sys.EventContext}
1650 """
1651 if self._ctx is None:
1652 self._ctx = self._proxies['admin'].getEventContext()
1653 return self._ctx
1654
1656 """
1657 Returns current Experimenter.
1658
1659 @return: Current Experimenter
1660 @rtype: L{ExperimenterWrapper}
1661 """
1662
1663 return self._user
1664
1666 """
1667 Returns current omero_model_ExperimenterGroupI.
1668
1669 @return: omero.model.ExperimenterGroupI
1670 """
1671 admin_service = self.getAdminService()
1672 group = admin_service.getGroup(self.getEventContext().groupId)
1673 return ExperimenterGroupWrapper(self, group)
1674
1676 """
1677 Checks if a user has administration privileges.
1678
1679 @return: Boolean
1680 """
1681
1682 return self.getEventContext().isAdmin
1683
1685 """
1686 Checks if a user is in system group, i.e. can have administration privileges.
1687
1688 @return: Boolean
1689 """
1690 return 0 in self.getEventContext().memberOfGroups
1691
1693 """
1694 Checks if a user has owner privileges of a particular group
1695 or any group if gid is not specified.
1696
1697 @param gid: ID of group to check for ownership
1698 @type gid: Long
1699 @return: True if gid specified and owner belongs to that group
1700 Otherwise True if owner belongs to any group
1701 """
1702 if gid is not None:
1703 if not isinstance(gid, LongType) or not isinstance(gid, IntType):
1704 gid = long(gid)
1705 for gem in self._user.copyGroupExperimenterMap():
1706 if gem.parent.id.val == gid and gem.owner.val == True:
1707 return True
1708 else:
1709 for gem in self._user.copyGroupExperimenterMap():
1710 if gem.owner.val == True:
1711 return True
1712 return False
1713
1715 """
1716 Checks if a user has write privileges to the given object.
1717
1718 @param obj: Given object
1719 @return: Boolean
1720 """
1721
1722 return self.isAdmin() or (self._userid == obj.details.owner.id.val and obj.details.permissions.isUserWrite())
1723
1725 """
1726 Returns the existing session, or creates a new one if needed
1727
1728 @return: The session from session service
1729 @rtype: L{omero.model.session}
1730 """
1731 if self._session is None:
1732 ss = self.c.sf.getSessionService()
1733 self._session = ss.getSession(self._sessionUuid)
1734 return self._session
1735
1736
1737
1738
1739
1740
1741
1743 """
1744 Looks up the group by name, then delegates to L{setGroupForSession}, returning the result
1745
1746 @param group: Group name
1747 @type group: String
1748 @return: True if group set successfully
1749 @rtype: Boolean
1750 """
1751 a = self.getAdminService()
1752 g = a.lookupGroup(group)
1753 return self.setGroupForSession(g.getId().val)
1754
1756 """
1757 Sets the security context of this connection to the specified group
1758
1759 @param groupid: The ID of the group to switch to
1760 @type groupid: Long
1761 @rtype: Boolean
1762 @return: True if the group was switched successfully
1763 """
1764 if self.getEventContext().groupId == groupid:
1765 return True
1766 if groupid not in self._ctx.memberOfGroups:
1767 return False
1768 self._lastGroupId = self._ctx.groupId
1769 if hasattr(self.c.sf, 'setSecurityContext'):
1770
1771 self.c.sf.setSecurityContext(omero.model.ExperimenterGroupI(groupid, False))
1772 else:
1773 self.getSession()
1774 self._session.getDetails().setGroup(omero.model.ExperimenterGroupI(groupid, False))
1775 self._session.setTimeToIdle(None)
1776 self.getSessionService().updateSession(self._session)
1777 return True
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1795 """ Switches the group to the previous group """
1796 if self._lastGroupId is not None:
1797 self.setGroupForSession(self._lastGroupId)
1798 self._lastGroupId = None
1799
1800
1801
1802
1804 """
1805 Gets reference to the admin service from ProxyObjectWrapper.
1806
1807 @return: omero.gateway.ProxyObjectWrapper
1808 """
1809
1810 return self._proxies['admin']
1811
1813 """
1814 Gets reference to the query service from ProxyObjectWrapper.
1815
1816 @return: omero.gateway.ProxyObjectWrapper
1817 """
1818 return self._proxies['query']
1819
1821 """
1822 Gets reference to the container service from ProxyObjectWrapper.
1823
1824 @return: omero.gateway.ProxyObjectWrapper
1825 """
1826
1827 return self._proxies['container']
1828
1830 """
1831 Gets reference to the pixels service from ProxyObjectWrapper.
1832
1833 @return: omero.gateway.ProxyObjectWrapper
1834 """
1835
1836 return self._proxies['pixel']
1837
1846
1848 """
1849 Gets ROI service.
1850
1851 @return: omero.gateway.ProxyObjectWrapper
1852 """
1853
1854 return self._proxies['roi']
1855
1857 """
1858 Gets script service.
1859
1860 @return: omero.gateway.ProxyObjectWrapper
1861 """
1862
1863 return self._proxies['script']
1864
1866 """
1867 Creates a new raw file store.
1868 This service is special in that it does not get cached inside BlitzGateway so every call to this function
1869 returns a new object, avoiding unexpected inherited states.
1870
1871 @return: omero.gateway.ProxyObjectWrapper
1872 """
1873
1874 return self._proxies['rawfile']
1875
1877 """
1878 Gets reference to the repository info service from ProxyObjectWrapper.
1879
1880 @return: omero.gateway.ProxyObjectWrapper
1881 """
1882
1883 return self._proxies['repository']
1884
1886 """
1887 Gets reference to the share service from ProxyObjectWrapper.
1888
1889 @return: omero.gateway.ProxyObjectWrapper
1890 """
1891
1892 return self._proxies['share']
1893
1895 """
1896 Gets reference to the sharedresources from ProxyObjectWrapper.
1897
1898 @return: omero.gateway.ProxyObjectWrapper
1899 """
1900
1901 return self._proxies['sharedres']
1902
1904 """
1905 Gets reference to the timeline service from ProxyObjectWrapper.
1906
1907 @return: omero.gateway.ProxyObjectWrapper
1908 """
1909
1910 return self._proxies['timeline']
1911
1913 """
1914 Gets reference to the types service from ProxyObjectWrapper.
1915
1916 @return: omero.gateway.ProxyObjectWrapper
1917 """
1918
1919 return self._proxies['types']
1920
1922 """
1923 Gets reference to the config service from ProxyObjectWrapper.
1924
1925 @return: omero.gateway.ProxyObjectWrapper
1926 """
1927
1928 return self._proxies['config']
1929
1931 """
1932 Creates a new rendering engine.
1933 This service is special in that it does not get cached inside BlitzGateway so every call to this function
1934 returns a new object, avoiding unexpected inherited states.
1935
1936 @return: omero.gateway.ProxyObjectWrapper
1937 """
1938
1939 rv = self._proxies['rendering']
1940 if rv._tainted:
1941 rv = self._proxies['rendering'] = rv.clone()
1942 rv.taint()
1943 return rv
1944
1946 """
1947 Gets reference to the rendering settings service from ProxyObjectWrapper.
1948
1949 @return: omero.gateway.ProxyObjectWrapper
1950 """
1951
1952 return self._proxies['rendsettings']
1953
1955 """
1956 Creates a new raw pixels store.
1957 This service is special in that it does not get cached inside BlitzGateway so every call to this function
1958 returns a new object, avoiding unexpected inherited states.
1959
1960 @return: omero.gateway.ProxyObjectWrapper
1961 """
1962
1963 return self._proxies['rawpixels']
1964
1966 """
1967 Gets a reference to the thumbnail store on this connection object or creates a new one
1968 if none exists.
1969
1970 @rtype: omero.gateway.ProxyObjectWrapper
1971 @return: The proxy wrapper of the thumbnail store
1972 """
1973
1974 return self._proxies['thumbs']
1975
1977 """
1978 Gets a reference to the searching service on this connection object or creates a new one
1979 if none exists.
1980
1981 @return: omero.gateway.ProxyObjectWrapper
1982 """
1983 return self._proxies['search']
1984
1986 """
1987 Gets reference to the update service from ProxyObjectWrapper.
1988
1989 @return: omero.gateway.ProxyObjectWrapper
1990 """
1991 return self._proxies['update']
1992
1994 """
1995 Gets reference to the delete service from ProxyObjectWrapper.
1996
1997 @return: omero.gateway.ProxyObjectWrapper
1998 """
1999 return self._proxies['delete']
2000
2002 """
2003 Gets reference to the session service from ProxyObjectWrapper.
2004
2005 @return: omero.gateway.ProxyObjectWrapper
2006 """
2007 return self._proxies['session']
2008
2010 """
2011 New instance of non cached Exporter, wrapped in ProxyObjectWrapper.
2012
2013 @return: omero.gateway.ProxyObjectWrapper
2014 """
2015
2016 return self._proxies['export']
2017
2018
2019
2020
2022 """
2023 List every Project controlled by the security system.
2024
2025 @param eid: Filters Projects by owner ID
2026 @param only_owned: Short-cut for filtering Projects by current user
2027 @rtype: L{ProjectWrapper} list
2028 """
2029
2030 params = omero.sys.Parameters()
2031 params.theFilter = omero.sys.Filter()
2032 if only_owned:
2033 params.theFilter.ownerId = rlong(self._userid)
2034 elif eid is not None:
2035 params.theFilter.ownerId = rlong(eid)
2036
2037 return self.getObjects("Project", params=params)
2038
2040 """
2041 List every Screens controlled by the security system.
2042
2043 @param eid: Filters Screens by owner ID
2044 @param only_owned: Short-cut for filtering Screens by current user
2045 @rtype: L{ProjectWrapper} list
2046 """
2047
2048 params = omero.sys.Parameters()
2049 params.theFilter = omero.sys.Filter()
2050 if only_owned:
2051 params.theFilter.ownerId = rlong(self._userid)
2052 elif eid is not None:
2053 params.theFilter.ownerId = rlong(eid)
2054
2055 return self.getObjects("Screen", params=params)
2056
2057
2058
2059
2060
2061
2063 """
2064 Look up all experimenters and related groups.
2065 Groups are also loaded
2066
2067 @return: All experimenters
2068 @rtype: L{ExperimenterWrapper} generator
2069 """
2070
2071 admin_serv = self.getAdminService()
2072 for exp in admin_serv.lookupGroups():
2073 yield ExperimenterGroupWrapper(self, exp)
2074
2076 """
2077 Retrieve the default group for the given user id.
2078
2079 @param eid: Experimenter ID
2080 @type eid: Long
2081 @return: The default group for user
2082 @rtype: L{ExperimenterGroupWrapper}
2083 """
2084
2085 admin_serv = self.getAdminService()
2086 dgr = admin_serv.getDefaultGroup(long(eid))
2087 return ExperimenterGroupWrapper(self, dgr)
2088
2090 """
2091 Fetch all groups of which the given user is a member.
2092 The returned groups will have all fields filled in and all collections unloaded.
2093
2094 @param eid: Experimenter ID
2095 @type eid: Long
2096 @return: Generator of groups for user
2097 @rtype: L{ExperimenterGroupWrapper} generator
2098 """
2099
2100 admin_serv = self.getAdminService()
2101 for gr in admin_serv.containedGroups(long(eid)):
2102 yield ExperimenterGroupWrapper(self, gr)
2103
2105 """
2106 Look up Groups where current user is a leader of.
2107
2108 @return: Groups that current user leads
2109 @rtype: L{ExperimenterGroupWrapper} generator
2110 """
2111
2112 q = self.getQueryService()
2113 p = omero.sys.Parameters()
2114 p.map = {}
2115 p.map["ids"] = rlist([rlong(a) for a in self.getEventContext().leaderOfGroups])
2116 sql = "select e from ExperimenterGroup as e where e.id in (:ids)"
2117 for e in q.findAllByQuery(sql, p):
2118 yield ExperimenterGroupWrapper(self, e)
2119
2121 """
2122 Look up Groups where current user is a member of (except "user" group).
2123
2124 @return: Current users groups
2125 @rtype: L{ExperimenterGroupWrapper} generator
2126 """
2127
2128 q = self.getQueryService()
2129 p = omero.sys.Parameters()
2130 p.map = {}
2131 p.map["ids"] = rlist([rlong(a) for a in self.getEventContext().memberOfGroups])
2132 sql = "select e from ExperimenterGroup as e where e.id in (:ids)"
2133 for e in q.findAllByQuery(sql, p):
2134 if e.name.val == "user":
2135 pass
2136 else:
2137 yield ExperimenterGroupWrapper(self, e)
2138
2139
2140
2142 """
2143 Return a generator for all Experimenters whose omeName starts with 'start'.
2144 Experimenters ordered by omeName.
2145
2146 @param start: omeName must start with these letters
2147 @type start: String
2148 @return: Generator of experimenters
2149 @rtype: L{ExperimenterWrapper} generator
2150 """
2151
2152 if isinstance(start, UnicodeType):
2153 start = start.encode('utf8')
2154 params = omero.sys.Parameters()
2155 params.map = {'start': rstring('%s%%' % start.lower())}
2156 q = self.getQueryService()
2157 rv = q.findAllByQuery("from Experimenter e where lower(e.omeName) like :start", params)
2158 rv.sort(lambda x,y: cmp(x.omeName.val,y.omeName.val))
2159 for e in rv:
2160 yield ExperimenterWrapper(self, e)
2161
2163 """
2164 Fetch all users contained in this group.
2165 The returned users will have all fields filled in and all collections unloaded.
2166
2167 @param gid: Group ID
2168 @type gid: Long
2169 @return: Generator of experimenters
2170 @rtype: L{ExperimenterWrapper} generator
2171 """
2172
2173 admin_serv = self.getAdminService()
2174 for exp in admin_serv.containedExperimenters(long(gid)):
2175 yield ExperimenterWrapper(self, exp)
2176
2178 """
2179 Look up users who are a member of the current user active group.
2180 Returns None if the group is private and isn't lead by the current user
2181
2182 @return: Generator of Experimenters or None
2183 @rtype: L{ExperimenterWrapper} generator
2184 """
2185
2186 default = self.getObject("ExperimenterGroup", self.getEventContext().groupId)
2187 if not default.isPrivate() or default.isLeader():
2188 for d in default.copyGroupExperimenterMap():
2189 if d.child.id.val != self.getEventContext().userId:
2190 yield ExperimenterWrapper(self, d.child)
2191
2193 """
2194 Look up users who are members of groups lead by the current user.
2195
2196 @return: Members of groups lead by current user
2197 @rtype: L{ExperimenterWrapper} generator
2198 """
2199
2200 q = self.getQueryService()
2201 p = omero.sys.Parameters()
2202 p.map = {}
2203 p.map["gids"] = rlist([rlong(a) for a in set(self.getEventContext().leaderOfGroups)])
2204 sql = "select e from Experimenter as e where " \
2205 "exists ( select gem from GroupExperimenterMap as gem where gem.child = e.id " \
2206 "and gem.parent.id in (:gids)) order by e.omeName"
2207 for e in q.findAllByQuery(sql, p):
2208 if e.id.val != self.getEventContext().userId:
2209 yield ExperimenterWrapper(self, e)
2210
2212 """
2213 Looks up owned groups for the logged user.
2214
2215 @return: Groups owned by current user
2216 @rtype: L{ExperimenterGroupWrapper} generator
2217 """
2218
2219 exp = self.getUser()
2220 for gem in exp.copyGroupExperimenterMap():
2221 if gem.owner.val:
2222 yield ExperimenterGroupWrapper(self, gem.parent)
2223
2225 """
2226 Returns the free or available space on this file system
2227 including nested subdirectories.
2228
2229 @return: Free space in bytes
2230 @rtype: Int
2231 """
2232
2233 rep_serv = self.getRepositoryInfoService()
2234 return rep_serv.getFreeSpaceInKilobytes() * 1024
2235
2236
2237
2238
2240 """
2241 List images based on their creation times.
2242 If both tfrom and tto are None, grab the most recent batch.
2243
2244 @param tfrom: milliseconds since the epoch for start date
2245 @param tto: milliseconds since the epoch for end date
2246 @param limit: maximum number of results
2247 @param only_owned: Only owned by the logged user. Boolean.
2248 @return: Generator yielding _ImageWrapper
2249 @rtype: L{ImageWrapper} generator
2250 """
2251
2252 tm = self.getTimelineService()
2253 p = omero.sys.Parameters()
2254 f = omero.sys.Filter()
2255 if only_owned:
2256 f.ownerId = rlong(self.getEventContext().userId)
2257 f.groupId = rlong(self.getEventContext().groupId)
2258 else:
2259 f.ownerId = rlong(-1)
2260 f.groupId = None
2261 f.limit = rint(limit)
2262 p.theFilter = f
2263 if tfrom is None and tto is None:
2264 for e in tm.getMostRecentObjects(['Image'], p, False)["Image"]:
2265 yield ImageWrapper(self, e)
2266 else:
2267 if tfrom is None:
2268 tfrom = 0
2269 if tto is None:
2270 tto = time.time() * 1000
2271 for e in tm.getByPeriod(['Image'], rtime(long(tfrom)), rtime(long(tto)), p, False)['Image']:
2272 yield ImageWrapper(self, e)
2273
2274
2275
2276
2277
2278 - def getObject (self, obj_type, oid=None, params=None, attributes=None):
2279 """
2280 Retrieve single Object by type E.g. "Image" or None if not found.
2281 If more than one object found, raises ome.conditions.ApiUsageException
2282 See L{getObjects} for more info.
2283
2284 @param obj_type: Object type. E.g. "Project" see above
2285 @type obj_type: String
2286 @param ids: object IDs
2287 @type ids: List of Long
2288 @param params: omero.sys.Parameters, can be used for pagination, filtering etc.
2289 @param attributes: Map of key-value pairs to filter results by. Key must be attribute of obj_type. E.g. 'name', 'ns'
2290 @return:
2291 """
2292 oids = (oid!=None) and [oid] or None
2293 query, params, wrapper = self.buildQuery(obj_type, oids, params, attributes)
2294 result = self.getQueryService().findByQuery(query, params)
2295 if result is not None:
2296 return wrapper(self, result)
2297
2298 - def getObjects (self, obj_type, ids=None, params=None, attributes=None):
2299 """
2300 Retrieve Objects by type E.g. "Image"
2301 Returns generator of appropriate L{BlitzObjectWrapper} type. E.g. L{ImageWrapper}.
2302 If ids is None, all available objects will be returned. i.e. listObjects()
2303 Filter objects by attributes. E.g. attributes={'name':name}
2304
2305 @param obj_type: Object type. E.g. "Project" see above
2306 @type obj_type: String
2307 @param ids: object IDs
2308 @type ids: List of Long
2309 @param params: omero.sys.Parameters, can be used for pagination, filtering etc.
2310 @param attributes: Map of key-value pairs to filter results by. Key must be attribute of obj_type. E.g. 'name', 'ns'
2311 @return: Generator of L{BlitzObjectWrapper} subclasses
2312 """
2313 query, params, wrapper = self.buildQuery(obj_type, ids, params, attributes)
2314 result = self.getQueryService().findAllByQuery(query, params)
2315 for r in result:
2316 yield wrapper(self, r)
2317
2318 - def buildQuery (self, obj_type, ids=None, params=None, attributes=None):
2319 """
2320 Prepares a query for iQuery. Also prepares params and determines appropriate wrapper for result
2321 Returns (query, params, wrapper) which can be used with the appropriate query method.
2322 Used by L{getObjects} and L{getObject} above.
2323
2324 @param obj_type: Object type. E.g. "Project" see above
2325 @type obj_type: String
2326 @param ids: object IDs
2327 @type ids: List of Long
2328 @param params: omero.sys.Parameters, can be used for pagination, filtering etc.
2329 @param attributes: Map of key-value pairs to filter results by. Key must be attribute of obj_type. E.g. 'name', 'ns'
2330 @return: (query, params, wrapper)
2331 """
2332
2333 if type(obj_type) is type(''):
2334 wrapper = KNOWN_WRAPPERS.get(obj_type.lower(), None)
2335 if wrapper is None:
2336 raise KeyError("obj_type of %s not supported by getOjbects(). E.g. use 'Image' etc" % obj_type)
2337 else:
2338 raise AttributeError("getObjects uses a string to define obj_type, E.g. 'Image'")
2339
2340 q = self.getQueryService()
2341 if params is None:
2342 params = omero.sys.Parameters()
2343 if params.map is None:
2344 params.map = {}
2345
2346
2347 query = wrapper()._getQueryString()
2348
2349 clauses = []
2350
2351 if ids != None:
2352 clauses.append("obj.id in (:ids)")
2353 params.map["ids"] = rlist([rlong(a) for a in ids])
2354
2355
2356 if params.theFilter and params.theFilter.ownerId and obj_type.lower() not in ["experimentergroup", "experimenter"]:
2357 clauses.append("owner.id = (:eid)")
2358 params.map["eid"] = params.theFilter.ownerId
2359
2360
2361 if attributes != None:
2362 for k,v in attributes.items():
2363 clauses.append('obj.%s=:%s' % (k, k) )
2364 params.map[k] = omero_type(v)
2365
2366 if clauses:
2367 query += " where " + (" and ".join(clauses))
2368
2369 return (query, params, wrapper)
2370
2371
2373 """
2374 Lists FileAnnotations created by users, filtering by namespaces if specified.
2375 If NO namespaces are specified, then 'known' namespaces are excluded by default,
2376 such as original files and companion files etc.
2377 File objects are loaded so E.g. file name is available without lazy loading.
2378
2379 @param eid: Filter results by this owner Id
2380 @param toInclude: Only return annotations with these namespaces. List of strings.
2381 @param toExclude: Don't return annotations with these namespaces. List of strings.
2382 @return: Generator of L{FileAnnotationWrapper}s - with files loaded.
2383 """
2384
2385 params = omero.sys.Parameters()
2386 params.theFilter = omero.sys.Filter()
2387 if eid is not None:
2388 params.theFilter.ownerId = rlong(eid)
2389
2390 if len(toInclude) == 0 and len(toExclude) == 0:
2391 toExclude.append(omero.constants.namespaces.NSCOMPANIONFILE)
2392 toExclude.append(omero.constants.annotation.file.ORIGINALMETADATA)
2393 toExclude.append(omero.constants.namespaces.NSEXPERIMENTERPHOTO)
2394 toExclude.append(omero.constants.analysis.flim.NSFLIM)
2395
2396 anns = self.getMetadataService().loadSpecifiedAnnotations("FileAnnotation", toInclude, toExclude, params)
2397
2398 for a in anns:
2399 yield(FileAnnotationWrapper(self, a))
2400
2401
2402 - def getAnnotationLinks (self, parent_type, parent_ids=None, ann_ids=None, ns=None, params=None):
2403 """
2404 Retrieve Annotation Links by parent_type E.g. "Image". Not Ordered.
2405 Returns generator of L{AnnotationLinkWrapper}
2406 If parent_ids is None, all available objects will be returned. i.e. listObjects()
2407
2408 @param obj_type: Object type. E.g. "Project" see above
2409 @type obj_type: String
2410 @param ids: object IDs
2411 @type ids: List of Long
2412 @return: Generator yielding wrapped objects.
2413 """
2414
2415 if parent_type not in ["Project", "Dataset", "Image", "Screen", "Plate"]:
2416 raise AttributeError("Can only get Annotations on 'Project', 'Dataset', 'Image', 'Screen', 'Plate'")
2417 wrapper = KNOWN_WRAPPERS.get(parent_type.lower(), None)
2418
2419 query = "select annLink from %sAnnotationLink as annLink join fetch annLink.details.owner as owner " \
2420 "join fetch annLink.details.creationEvent " \
2421 "join fetch annLink.child as ann join fetch ann.details.owner join fetch ann.details.creationEvent "\
2422 "join fetch annLink.parent as parent" % wrapper().OMERO_CLASS
2423
2424 q = self.getQueryService()
2425 if params is None:
2426 params = omero.sys.Parameters()
2427 if params.map is None:
2428 params.map = {}
2429
2430 clauses = []
2431 if parent_ids:
2432 clauses.append("parent.id in (:pids)")
2433 params.map["pids"] = rlist([rlong(a) for a in parent_ids])
2434
2435 if ann_ids:
2436 clauses.append("ann.id in (:ann_ids)")
2437 params.map["ann_ids"] = rlist([rlong(a) for a in ann_ids])
2438
2439 if ns:
2440 clauses.append("ann.ns in (:ns)")
2441 params.map["ns"] = rstring(ns)
2442
2443 if params.theFilter and params.theFilter.ownerId:
2444 clauses.append("owner.id = (:eid)")
2445 params.map["eid"] = params.theFilter.ownerId
2446
2447 if len(clauses) > 0:
2448 query += " where %s" % (" and ".join(clauses))
2449
2450 result = q.findAllByQuery(query, params)
2451 for r in result:
2452 yield AnnotationLinkWrapper(self, r)
2453
2454
2455 - def createImageFromNumpySeq (self, zctPlanes, imageName, sizeZ=1, sizeC=1, sizeT=1, description=None, dataset=None):
2456 """
2457 Creates a new multi-dimensional image from the sequence of 2D numpy arrays in zctPlanes.
2458 zctPlanes should be a generator of numpy 2D arrays of shape (sizeY, sizeX) ordered
2459 to iterate through T first, then C then Z.
2460 Example usage:
2461 original = conn.getObject("Image", 1)
2462 sizeZ = original.getSizeZ()
2463 sizeC = original.getSizeC()
2464 sizeT = original.getSizeT()
2465 zctList = []
2466 for z in range(sizeZ):
2467 for c in range(sizeC):
2468 for t in range(sizeT):
2469 zctList.append( (z,c,t) )
2470 def planeGen():
2471 planes = original.getPrimaryPixels().getPlanes(zctList)
2472 for p in planes:
2473 # perform some manipulation on each plane
2474 yield p
2475 createImageFromNumpySeq (planeGen(), imageName, sizeZ=sizeZ, sizeC=sizeC, sizeT=sizeT
2476
2477 @param session An OMERO service factory or equivalent with getQueryService() etc.
2478 @param zctPlanes A generator of numpy 2D arrays, corresponding to Z-planes of new image.
2479 @param imageName Name of new image
2480 @param description Description for the new image
2481 @param dataset If specified, put the image in this dataset. omero.model.Dataset object
2482
2483 @return The new OMERO image: omero.model.ImageI
2484 """
2485 queryService = self.getQueryService()
2486 pixelsService = self.getPixelsService()
2487 rawPixelsStore = self.c.sf.createRawPixelsStore()
2488
2489 containerService = self.getContainerService()
2490 updateService = self.getUpdateService()
2491
2492 def createImage(firstPlane):
2493 """ Create our new Image once we have the first plane in hand """
2494
2495 pTypes = {'int8':'int8', 'int16':'int16', 'uint16':'uint16', 'int32':'int32', 'float_':'float', 'float8':'float',
2496 'float16':'float', 'float32':'float', 'float64':'double', 'complex_':'complex', 'complex64':'complex'}
2497 dType = firstPlane.dtype.name
2498 if dType not in pTypes:
2499 pType = dType
2500 else:
2501 pType = pTypes[dType]
2502 pixelsType = queryService.findByQuery("from PixelsType as p where p.value='%s'" % pType, None)
2503 if pixelsType is None:
2504 raise Exception("Cannot create an image in omero from numpy array with dtype: %s" % dType)
2505 sizeY, sizeX = firstPlane.shape
2506 channelList = range(1, sizeC+1)
2507 iId = pixelsService.createImage(sizeX, sizeY, sizeZ, sizeT, channelList, pixelsType, imageName, description)
2508 imageId = iId.getValue()
2509 return containerService.getImages("Image", [imageId], None)[0]
2510
2511 def uploadPlane(plane, z, c, t):
2512 byteSwappedPlane = plane.byteswap();
2513 convertedPlane = byteSwappedPlane.tostring();
2514 rawPixelsStore.setPlane(convertedPlane, z, c, t)
2515
2516 image = None
2517 channelsMinMax = []
2518 exc = None
2519 try:
2520 for theZ in range(sizeZ):
2521 for theC in range(sizeC):
2522 for theT in range(sizeT):
2523 plane = zctPlanes.next()
2524 if image == None:
2525 image = createImage(plane)
2526 pixelsId = image.getPrimaryPixels().getId().getValue()
2527 rawPixelsStore.setPixelsId(pixelsId, True)
2528 uploadPlane(plane, theZ, theC, theT)
2529
2530 minValue = plane.min()
2531 maxValue = plane.max()
2532 if len(channelsMinMax) < (theC +1):
2533 channelsMinMax.append( [minValue, maxValue] )
2534 else:
2535 channelsMinMax[theC][0] = min(channelsMinMax[theC][0], minValue)
2536 channelsMinMax[theC][1] = max(channelsMinMax[theC][1], maxValue)
2537 except Exception, e:
2538 logger.error("Failed to setPlane() on rawPixelsStore while creating Image", exc_info=True)
2539 exc = e
2540 try:
2541 rawPixelsStore.close()
2542 except Exception, e:
2543 logger.error("Failed to close rawPixelsStore", exc_info=True)
2544 if exc is None:
2545 exc = e
2546 if exc is not None:
2547 raise exc
2548
2549 try:
2550 zctPlanes.next()
2551 except StopIteration:
2552 pass
2553
2554 for theC, mm in enumerate(channelsMinMax):
2555 pixelsService.setChannelGlobalMinMax(pixelsId, theC, float(mm[0]), float(mm[1]))
2556
2557
2558
2559 if dataset:
2560 link = omero.model.DatasetImageLinkI()
2561 link.parent = omero.model.DatasetI(dataset.getId(), False)
2562 link.child = omero.model.ImageI(image.id.val, False)
2563 updateService.saveObject(link)
2564
2565 return ImageWrapper(self, image)
2566
2567
2569 """
2570 Class method to create a L{FileAnnotationWrapper} from a local file.
2571 File is uploaded to create an omero.model.OriginalFileI referenced from this File Annotation.
2572 Returns a new L{FileAnnotationWrapper}
2573
2574 @param conn: Blitz connection
2575 @param localPath: Location to find the local file to upload
2576 @param origFilePathAndName: Provides the 'path' and 'name' of the OriginalFile. If None, use localPath
2577 @param mimetype: The mimetype of the file. String. E.g. 'text/plain'
2578 @return: New L{FileAnnotationWrapper}
2579 """
2580 updateService = self.getUpdateService()
2581 rawFileStore = self.createRawFileStore()
2582
2583
2584 if origFilePathAndName is None:
2585 origFilePathAndName = localPath
2586 originalFile = omero.model.OriginalFileI()
2587 path, name = os.path.split(origFilePathAndName)
2588 originalFile.setName(rstring(name))
2589 originalFile.setPath(rstring(path))
2590 if mimetype:
2591 originalFile.mimetype = rstring(mimetype)
2592 fileSize = os.path.getsize(localPath)
2593 originalFile.setSize(rlong(fileSize))
2594
2595 try:
2596 import hashlib
2597 hash_sha1 = hashlib.sha1
2598 except:
2599 import sha
2600 hash_sha1 = sha.new
2601 fileHandle = open(localPath)
2602 h = hash_sha1()
2603 h.update(fileHandle.read())
2604 shaHast = h.hexdigest()
2605 fileHandle.close()
2606 originalFile.setSha1(rstring(shaHast))
2607 originalFile = updateService.saveAndReturnObject(originalFile)
2608
2609
2610 rawFileStore.setFileId(originalFile.getId().getValue())
2611 fileHandle = open(localPath, 'rb')
2612 buf = 10000
2613 for pos in range(0,long(fileSize),buf):
2614 block = None
2615 if fileSize-pos < buf:
2616 blockSize = fileSize-pos
2617 else:
2618 blockSize = buf
2619 fileHandle.seek(pos)
2620 block = fileHandle.read(blockSize)
2621 rawFileStore.write(block, pos, blockSize)
2622 fileHandle.close()
2623
2624
2625 fa = omero.model.FileAnnotationI()
2626 fa.setFile(originalFile)
2627 if desc:
2628 fa.setDescription(rstring(desc))
2629 if ns:
2630 fa.setNs(rstring(ns))
2631 fa = updateService.saveAndReturnObject(fa)
2632 return FileAnnotationWrapper(self, fa)
2633
2635 """
2636 Retrieve objects linked to the given annotation IDs
2637 controlled by the security system.
2638
2639 @param annids: Annotation IDs
2640 @type annids: L{Long}
2641 @return: Generator yielding Objects
2642 @rtype: L{BlitzObjectWrapper} generator
2643 """
2644
2645 wrapper = KNOWN_WRAPPERS.get(obj_type.lower(), None)
2646 if not wrapper:
2647 raise AttributeError("Don't know how to handle '%s'" % obj_type)
2648
2649 sql = "select ob from %s ob " \
2650 "left outer join fetch ob.annotationLinks obal " \
2651 "left outer join fetch obal.child ann " \
2652 "where ann.id in (:oids)" % wrapper().OMERO_CLASS
2653
2654 q = self.getQueryService()
2655 p = omero.sys.Parameters()
2656 p.map = {}
2657 p.map["oids"] = rlist([rlong(o) for o in set(annids)])
2658 for e in q.findAllByQuery(sql,p):
2659 kwargs = {'link': BlitzObjectWrapper(self, e.copyAnnotationLinks()[0])}
2660 yield wrapper(self, e)
2661
2662
2663
2664
2665
2667 """
2668 Get all enumerations by class
2669
2670 @param klass: Class
2671 @type klass: Class or string
2672 @return: Generator of Enumerations
2673 @rtype: L{EnumerationWrapper} generator
2674 """
2675
2676 types = self.getTypesService()
2677 for e in types.allEnumerations(str(klass)):
2678 yield EnumerationWrapper(self, e)
2679
2681 """
2682 Get enumeration by class and value
2683
2684 @param klass: Class
2685 @type klass: Class or string
2686 @param string: Enum value
2687 @type string: String
2688 @return: Enumeration or None
2689 @rtype: L{EnumerationWrapper}
2690 """
2691
2692 types = self.getTypesService()
2693 obj = types.getEnumeration(str(klass), str(string))
2694 if obj is not None:
2695 return EnumerationWrapper(self, obj)
2696 else:
2697 return None
2698
2700 """
2701 Get enumeration by class and ID
2702
2703 @param klass: Class
2704 @type klass: Class or string
2705 @param eid: Enum ID
2706 @type eid: Long
2707 @return: Enumeration or None
2708 @rtype: L{EnumerationWrapper}
2709 """
2710
2711 query_serv = self.getQueryService()
2712 obj = query_serv.find(klass, long(eid))
2713 if obj is not None:
2714 return EnumerationWrapper(self, obj)
2715 else:
2716 return None
2717
2719 """
2720 Gets original enumerations. Returns a dictionary of enumeration class: list of Enumerations
2721
2722 @return: Original enums
2723 @rtype: Dict of <string: L{EnumerationWrapper} list >
2724 """
2725
2726 types = self.getTypesService()
2727 rv = dict()
2728 for e in types.getOriginalEnumerations():
2729 if rv.get(e.__class__.__name__) is None:
2730 rv[e.__class__.__name__] = list()
2731 rv[e.__class__.__name__].append(EnumerationWrapper(self, e))
2732 return rv
2733
2735 """
2736 Gets list of enumeration types
2737
2738 @return: List of enum types
2739 @rtype: List of Strings
2740 """
2741
2742 types = self.getTypesService()
2743 return types.getEnumerationTypes()
2744
2746 """
2747 Get enumeration types, with lists of Enum entries
2748
2749 @return: Dictionary of type: entries
2750 @rtype: Dict of <string: L{EnumerationWrapper} list >
2751 """
2752
2753 types = self.getTypesService()
2754 rv = dict()
2755 for key, value in types.getEnumerationsWithEntries().items():
2756 r = list()
2757 for e in value:
2758 r.append(EnumerationWrapper(self, e))
2759 rv[key+"I"] = r
2760 return rv
2761
2763 """
2764 Deletes an enumeration object
2765
2766 @param obj: Enumeration object
2767 @type obj: omero.model.IObject
2768 """
2769
2770 types = self.getTypesService()
2771 types.deleteEnumeration(obj)
2772
2774 """
2775 Create an enumeration with given object
2776
2777 @param obj: Object
2778 @type obj: omero.model.IObject
2779 """
2780
2781 types = self.getTypesService()
2782 types.createEnumeration(obj)
2783
2785 """
2786 Resets the enumerations by type
2787
2788 @param klass: Type of enum to reset
2789 @type klass: String
2790 """
2791
2792 types = self.getTypesService()
2793 types.resetEnumerations(klass)
2794
2796 """
2797 Updates enumerations with new entries
2798
2799 @param new_entries: List of objects
2800 @type new_entries: List of omero.model.IObject
2801 """
2802
2803 types = self.getTypesService()
2804 types.updateEnumerations(new_entries)
2805
2806
2807
2808
2810 """
2811 Directly Delete object (removes row from database).
2812 This may fail with various constraint violations if the object is linked to others in the database
2813
2814 @param obj: Object to delete
2815 @type obj: IObject"""
2816
2817 u = self.getUpdateService()
2818 u.deleteObject(obj)
2819
2820 - def deleteObjects(self, obj_type, obj_ids, deleteAnns=False, deleteChildren=False):
2821 """
2822 Generic method for deleting using the delete queue.
2823 Supports deletion of 'Project', 'Dataset', 'Image', 'Screen', 'Plate', 'Well', 'Annotation'.
2824 Options allow to delete 'independent' Annotations (Tag, Term, File) and to delete child objects.
2825
2826 @param obj_type: String to indicate 'Project', 'Image' etc.
2827 @param obj_ids: List of IDs for the objects to delete
2828 @param deleteAnns: If true, delete linked Tag, Term and File annotations
2829 @param deleteChildren: If true, delete children. E.g. Delete Project AND it's Datasets & Images.
2830 @return: Delete handle
2831 @rtype: L{omero.api.delete.DeleteHandle}
2832 """
2833
2834 if not isinstance(obj_ids, list) and len(obj_ids) < 1:
2835 raise AttributeError('Must be a list of object IDs')
2836
2837 op = dict()
2838 if not deleteAnns and obj_type not in ["Annotation", "TagAnnotation"]:
2839 op["/TagAnnotation"] = "KEEP"
2840 op["/TermAnnotation"] = "KEEP"
2841 op["/FileAnnotation"] = "KEEP"
2842
2843 childTypes = {'Project':['/Dataset', '/Image'],
2844 'Dataset':['/Image'],
2845 'Image':[],
2846 'Screen':['/Plate'],
2847 'Plate':['/Image'],
2848 'Well':[],
2849 'Annotation':[] }
2850
2851 obj_type = obj_type.title()
2852 if obj_type not in childTypes:
2853 m = """%s is not an object type. Must be: Project, Dataset, Image, Screen, Plate, Well, Annotation""" % obj_type
2854 raise AttributeError(m)
2855 if not deleteChildren:
2856 for c in childTypes[obj_type]:
2857 op[c] = "KEEP"
2858
2859
2860 dcs = list()
2861 logger.debug('Deleting %s [%s]. Options: %s' % (obj_type, str(obj_ids), op))
2862 for oid in obj_ids:
2863 dcs.append(omero.api.delete.DeleteCommand("/%s" % obj_type, long(oid), op))
2864 handle = self.getDeleteService().queueDelete(dcs)
2865 return handle
2866
2867
2868
2869
2870
2872 """
2873 Search objects of type "Project", "Dataset", "Image", "Screen", "Plate"
2874 Returns a list of results
2875
2876 @param obj_types: E.g. ["Dataset", "Image"]
2877 @param text: The text to search for
2878 @param created: L{omero.rtime} list or tuple (start, stop)
2879 @return: List of Object wrappers. E.g. L{ImageWrapper}
2880 """
2881 if not text:
2882 return []
2883 if isinstance(text, UnicodeType):
2884 text = text.encode('utf8')
2885 if obj_types is None:
2886 types = (ProjectWrapper, DatasetWrapper, ImageWrapper)
2887 else:
2888 def getWrapper(obj_type):
2889 if obj_type.lower() not in ["project", "dataset", "image", "screen", "plate", "well"]:
2890 raise AttributeError("%s not recognised. Can only search for 'Project', 'Dataset', 'Image', 'Screen', 'Plate', 'Well'" % obj_type)
2891 return KNOWN_WRAPPERS.get(obj_type.lower(), None)
2892 types = [getWrapper(o) for o in obj_types]
2893 search = self.createSearchService()
2894 if created:
2895 search.onlyCreatedBetween(created[0], created[1]);
2896 if text[0] in ('?','*'):
2897 search.setAllowLeadingWildcard(True)
2898 rv = []
2899 for t in types:
2900 def actualSearch ():
2901 search.onlyType(t().OMERO_CLASS)
2902 search.byFullText(text)
2903 timeit(actualSearch)()
2904 if search.hasNext():
2905 def searchProcessing ():
2906 rv.extend(map(lambda x: t(self, x), search.results()))
2907 timeit(searchProcessing)()
2908 search.close()
2909 return rv
2910
2913 """
2914 Function or method wrapper that handles certain types of server side
2915 exceptions and debugging of errors.
2916 """
2917
2918 - def __init__(self, proxyObjectWrapper, attr, f):
2919 """
2920 Initialises the function call wrapper.
2921
2922 @param attr: Function name
2923 @type attr: String
2924 @param f: Function to wrap
2925 @type f: Function
2926 """
2927 self.proxyObjectWrapper = proxyObjectWrapper
2928 self.attr = attr
2929 self.f = f
2930 try:
2931 self.__f__name = f.im_self.ice_getIdentity().name
2932 except:
2933 self.__f__name = "unknown"
2934
2935 - def debug(self, exc_class, args, kwargs):
2936 logger.warn("%s on %s to <%s> %s(%r, %r)",
2937 exc_class, self.__class__, self.__f__name, self.attr,
2938 args, kwargs, exc_info=True)
2939
2941 """
2942 Exception handler that is expected to be overridden by sub-classes.
2943 The expected behaviour is either to handle a type of exception and
2944 return the server side result or to raise the already thrown
2945 exception. The calling context is an except block and the original
2946 *args and **kwargs from the wrapped function or method are provided
2947 to allow re-execution of the original.
2948
2949 @param e: The exception that has already been raised.
2950 @type e: Exception
2951 """
2952 raise
2953
2955 try:
2956 return self.f(*args, **kwargs)
2957 except Exception, e:
2958 self.debug(e.__class__.__name__, args, kwargs)
2959 return self.handle_exception(e, *args, **kwargs)
2960
2961
2962
2963
2964
2965 SafeCallWrapper = OmeroGatewaySafeCallWrapper
2966
2967 BlitzGateway = _BlitzGateway
2971 """ splits an hex stream of characters into an array of bytes in format (R,G,B,A).
2972 - abc -> (0xAA, 0xBB, 0xCC, 0xFF)
2973 - abcd -> (0xAA, 0xBB, 0xCC, 0xDD)
2974 - abbccd -> (0xAB, 0xBC, 0xCD, 0xFF)
2975 - abbccdde -> (0xAB, 0xBC, 0xCD, 0xDE)
2976
2977 @param color: Characters to split.
2978 @return: rgba
2979 @rtype: list of Ints
2980 """
2981 try:
2982 out = []
2983 if len(color) in (3,4):
2984 c = color
2985 color = ''
2986 for e in c:
2987 color += e + e
2988 if len(color) == 6:
2989 color += 'FF'
2990 if len(color) == 8:
2991 for i in range(0, 8, 2):
2992 out.append(int(color[i:i+2], 16))
2993 return out
2994 except:
2995 pass
2996 return None
2997
3000 """
3001 Wrapper for services. E.g. Admin Service, Delete Service etc.
3002 Maintains reference to connection.
3003 Handles creation of service when requested.
3004 """
3005
3007 """
3008 Initialisation of proxy object wrapper.
3009
3010 @param conn: The L{BlitzGateway} connection
3011 @type conn: L{BlitzGateway}
3012 @param func_str: The name of the service creation method. E.g 'getAdminService'
3013 @type func_str: String
3014 """
3015 self._obj = None
3016 self._func_str = func_str
3017 self._resyncConn(conn)
3018 self._tainted = False
3019
3021 """
3022 Creates and returns a new L{ProxyObjectWrapper} with the same connection
3023 and service creation method name as this one.
3024
3025 @return: Cloned service wrapper
3026 @rtype: L{ProxyObjectWrapper}
3027 """
3028
3029 return ProxyObjectWrapper(self._conn, self._func_str)
3030
3032 """
3033 Returns True if connected. If connection OK, wrapped service is also created.
3034
3035 @param forcejoin: if True forces the connection to only succeed if we can
3036 rejoin the current sessionid
3037 @type forcejoin: Boolean
3038
3039 @return: True if connection OK
3040 @rtype: Boolean
3041 """
3042 logger.debug("proxy_connect: a");
3043 if forcejoin:
3044 sUuid = self._conn._sessionUuid
3045 else:
3046 sUuid = None
3047 if not self._conn.connect(sUuid=sUuid):
3048 logger.debug('connect failed')
3049 logger.debug('/n'.join(traceback.format_stack()))
3050 return False
3051 logger.debug("proxy_connect: b");
3052 self._resyncConn(self._conn)
3053 logger.debug("proxy_connect: c");
3054 self._obj = self._create_func()
3055 logger.debug("proxy_connect: d");
3056 return True
3057
3059 """ Sets the tainted flag to True """
3060 self._tainted = True
3061
3063 """ Sets the tainted flag to False """
3064 self._tainted = False
3065
3067 """
3068 Closes the underlaying service, so next call to the proxy will create a new
3069 instance of it.
3070 """
3071
3072 if self._obj and isinstance(self._obj, omero.api.StatefulServiceInterfacePrx):
3073 self._obj.close()
3074 self._obj = None
3075
3077 """
3078 Reset refs to connection and session factory. Resets session creation function.
3079 Attempts to reload the wrapped service - if already created (doesn't create service)
3080
3081 @param conn: Connection
3082 @type conn: L{BlitzGateway}
3083 """
3084
3085 self._conn = conn
3086 self._sf = conn.c.sf
3087 self._create_func = getattr(self._sf, self._func_str)
3088 if self._obj is not None:
3089 try:
3090 logger.debug("## - refreshing %s" % (self._func_str))
3091 obj = conn.c.ic.stringToProxy(str(self._obj))
3092 self._obj = self._obj.checkedCast(obj)
3093 except Ice.ObjectNotExistException:
3094 self._obj = None
3095
3097 """
3098 Returns the wrapped service. If it is None, service is created.
3099
3100 @return: The wrapped service
3101 @rtype: omero.api.ServiceInterface subclass
3102 """
3103
3104 if not self._obj:
3105 try:
3106 self._obj = self._create_func()
3107 except Ice.ConnectionLostException:
3108 logger.debug('... lost, reconnecting (_getObj)')
3109 self._connect()
3110
3111 else:
3112 self._ping()
3113 return self._obj
3114
3116 """
3117 For some reason, it seems that keepAlive doesn't, so every so often I need to recreate the objects.
3118 Calls serviceFactory.keepAlive(service). If this returns false, attempt to create service.
3119
3120 @return: True if no exception thrown
3121 @rtype: Boolean
3122 """
3123
3124 try:
3125 if not self._sf.keepAlive(self._obj):
3126 logger.debug("... died, recreating ...")
3127 self._obj = self._create_func()
3128 except Ice.ObjectNotExistException:
3129
3130 logger.debug("... reset, reconnecting")
3131 self._connect()
3132 return False
3133 except Ice.ConnectionLostException:
3134
3135 logger.debug(traceback.format_stack())
3136 logger.debug("... lost, reconnecting (_ping)")
3137 self._conn._connected = False
3138 self._connect()
3139 return False
3140 except Ice.ConnectionRefusedException:
3141
3142 logger.debug(traceback.format_stack())
3143 logger.debug("... refused, reconnecting")
3144 self._connect()
3145 return False
3146 except omero.RemovedSessionException:
3147
3148 logger.debug(traceback.format_stack())
3149 logger.debug("... session has left the building, reconnecting")
3150 self._connect()
3151 return False
3152 except Ice.UnknownException:
3153
3154 logger.debug(traceback.format_stack())
3155 logger.debug("... ice says something bad happened, reconnecting")
3156 self._connect()
3157 return False
3158 return True
3159
3161 """
3162 Returns named attribute of the wrapped service.
3163 If attribute is a method, the method is wrapped to handle exceptions, connection etc.
3164
3165 @param attr: Attribute name
3166 @type attr: String
3167 @return: Attribute or wrapped method
3168 """
3169
3170 obj = self._obj or self._getObj()
3171 rv = getattr(obj, attr)
3172 if callable(rv):
3173 rv = SafeCallWrapper(self, attr, rv)
3174
3175 return rv
3176
3178 """
3179 omero_model_AnnotationI class wrapper extends BlitzObjectWrapper.
3180 """
3181 registry = {}
3182 OMERO_TYPE = None
3183
3185 """
3186 Initialises the Annotation wrapper and 'link' if in kwargs
3187 """
3188 super(AnnotationWrapper, self).__init__(*args, **kwargs)
3189 self.link = kwargs.has_key('link') and kwargs['link'] or None
3190 if self._obj is None and self.OMERO_TYPE is not None:
3191 self._obj = self.OMERO_TYPE()
3192
3194 """
3195 Returns true if type, id, value and ns are equal
3196
3197 @param a: The annotation to compare
3198 @return: True if annotations are the same - see above
3199 @rtype: Boolean
3200 """
3201 return type(a) == type(self) and self._obj.id == a._obj.id and self.getValue() == a.getValue() and self.getNs() == a.getNs()
3202
3204 """
3205 Used for building queries in generic methods such as getObjects("Annotation")
3206 """
3207 return "select obj from Annotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
3208 "join fetch obj.details.creationEvent"
3209
3210 @classmethod
3212 """
3213 Adds the AnnotationWrapper regklass to class registry
3214 @param regklass: The wrapper class, E.g. L{DoubleAnnotationWrapper}
3215 @type regklass: L{AnnotationWrapper} subclass
3216 """
3217
3218 klass.registry[regklass.OMERO_TYPE] = regklass
3219
3220 @classmethod
3221 - def _wrap (klass, conn=None, obj=None, link=None):
3222 """
3223 Class method for creating L{AnnotationWrapper} subclasses based on the type of
3224 annotation object, using previously registered mapping between OMERO types and wrapper classes
3225
3226 @param conn: The L{BlitzGateway} connection
3227 @type conn: L{BlitzGateway}
3228 @param obj: The OMERO annotation object. E.g. omero.model.DoubleAnnotation
3229 @type obj: L{omero.model.Annotation} subclass
3230 @param link: The link for this annotation
3231 @type link: E.g. omero.model.DatasetAnnotationLink
3232 @return: Wrapped AnnotationWrapper object or None if obj.__class__ not registered
3233 @rtype: L{AnnotationWrapper} subclass
3234 """
3235 if obj is None:
3236 return AnnotationWrapper()
3237 if obj.__class__ in klass.registry:
3238 kwargs = dict()
3239 if link is not None:
3240 kwargs['link'] = BlitzObjectWrapper(conn, link)
3241 return klass.registry[obj.__class__](conn, obj, **kwargs)
3242 else:
3243 return None
3244
3245 @classmethod
3247 """
3248 Class method for creating an instance of this AnnotationWrapper, setting ns and value
3249 and linking to the target.
3250
3251 @param target: The object to link annotation to
3252 @type target: L{BlitzObjectWrapper} subclass
3253 @param ns: Annotation namespace
3254 @type ns: String
3255 @param val: Value of annotation. E.g Long, Text, Boolean etc.
3256 """
3257
3258 this = klass()
3259 this.setNs(ns)
3260 if val is not None:
3261 this.setValue(val)
3262 target.linkAnnotation(this)
3263
3265 """
3266 Gets annotation namespace
3267
3268 @return: Namespace or None
3269 @rtype: String
3270 """
3271
3272 return self._obj.ns is not None and self._obj.ns.val or None
3273
3275 """
3276 Sets annotation namespace
3277
3278 @param val: Namespace value
3279 @type val: String
3280 """
3281
3282 self._obj.ns = omero_type(val)
3283
3285 """ Needs to be implemented by subclasses """
3286 raise NotImplementedError
3287
3289 """ Needs to be implemented by subclasses """
3290 raise NotImplementedError
3291
3293 ptype = ptype.lower()
3294 if not ptype in ('project', 'dataset', 'image', 'screen', 'plate', 'well'):
3295 AttributeError('Annotation can be linked only to: project, dataset, image, screen, plate, well')
3296 p = omero.sys.Parameters()
3297 p.map = {}
3298 p.map["aid"] = rlong(self.id)
3299 sql = "select oal from %sAnnotationLink as oal left outer join fetch oal.child as ch " \
3300 "left outer join fetch oal.parent as pa " \
3301 "where ch.id=:aid " % (ptype.title())
3302 if pids is not None:
3303 p.map["pids"] = rlist([rlong(ob) for ob in pids])
3304 sql+=" and pa.id in (:pids)"
3305
3306 for al in self._conn.getQueryService().findAllByQuery(sql, p):
3307 yield AnnotationLinkWrapper(self, al)
3308
3310 """
3311 omero_model_AnnotationLinkI class wrapper extends omero.gateway.BlitzObjectWrapper.
3312 """
3313
3316
3317 AnnotationLinkWrapper = _AnnotationLinkWrapper
3318
3319 from omero_model_FileAnnotationI import FileAnnotationI
3322 """
3323 omero_model_FileAnnotatio class wrapper extends AnnotationWrapper.
3324 """
3325
3326 OMERO_TYPE = FileAnnotationI
3327
3328 _attrs = ('file|OriginalFileWrapper',)
3329
3331 """
3332 Used for building queries in generic methods such as getObjects("FileAnnotation")
3333 """
3334 return "select obj from FileAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
3335 "join fetch obj.details.creationEvent join fetch obj.file"
3336
3338 """ Not implemented """
3339 pass
3340
3342 """ Not implemented """
3343 pass
3344
3359
3361 """
3362 Looks up the size of the file in bytes
3363
3364 @return: File size (bytes)
3365 @rtype: Long
3366 """
3367 return self.getFile().size
3368
3370 """
3371 Gets the file name
3372
3373 @return: File name
3374 @rtype: String
3375 """
3376
3377 return self.getFile().name
3378
3380 """
3381 Returns a generator yielding chunks of the file data.
3382
3383 @return: Data from file in chunks
3384 @rtype: Generator
3385 """
3386
3387 return self.getFile().getFileInChunks();
3388
3389 AnnotationWrapper._register(FileAnnotationWrapper)
3393 """
3394 omero_model_OriginalFileI class wrapper extends BlitzObjectWrapper.
3395 """
3396
3399
3422
3423
3424 OriginalFileWrapper = _OriginalFileWrapper
3425
3426
3427 from omero_model_TimestampAnnotationI import TimestampAnnotationI
3430 """
3431 omero_model_TimestampAnnotatio class wrapper extends AnnotationWrapper.
3432 """
3433
3434 OMERO_TYPE = TimestampAnnotationI
3435
3437 """
3438 Used for building queries in generic methods such as getObjects("TimestampAnnotation")
3439 """
3440 return "select obj from TimestampAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
3441 "join fetch obj.details.creationEvent"
3442
3444 """
3445 Returns a datetime object of the timestamp in seconds
3446
3447 @return: Timestamp value
3448 @rtype: L{datetime}
3449 """
3450
3451 return datetime.fromtimestamp(self._obj.timeValue.val / 1000.0)
3452
3454 """
3455 Sets the timestamp value
3456
3457 @param val: Timestamp value
3458 @type param: L{datetime} OR L{omero.RTime} OR Long
3459 """
3460
3461 if isinstance(val, datetime):
3462 self._obj.timeValue = rtime(long(time.mktime(val.timetuple())*1000))
3463 elif isinstance(val, omero.RTime):
3464 self._obj.timeValue = val
3465 else:
3466 self._obj.timeValue = rtime(long(val * 1000))
3467
3468 AnnotationWrapper._register(TimestampAnnotationWrapper)
3469
3470 from omero_model_BooleanAnnotationI import BooleanAnnotationI
3473 """
3474 omero_model_BooleanAnnotationI class wrapper extends AnnotationWrapper.
3475 """
3476
3477 OMERO_TYPE = BooleanAnnotationI
3478
3480 """
3481 Used for building queries in generic methods such as getObjects("BooleanAnnotation")
3482 """
3483 return "select obj from BooleanAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
3484 "join fetch obj.details.creationEvent"
3485
3487 """
3488 Gets boolean value
3489
3490 @return: Value
3491 @rtype: Boolean
3492 """
3493 return self._obj.boolValue.val
3494
3496 """
3497 Sets boolean value
3498
3499 @param val: Value
3500 @type val: Boolean
3501 """
3502
3503 self._obj.boolValue = rbool(not not val)
3504
3505 AnnotationWrapper._register(BooleanAnnotationWrapper)
3506
3507 from omero_model_TagAnnotationI import TagAnnotationI
3510 """
3511 omero_model_BooleanAnnotationI class wrapper extends AnnotationWrapper.
3512 """
3513
3514 OMERO_TYPE = TagAnnotationI
3515
3527
3541
3543 """
3544 Used for building queries in generic methods such as getObjects("TagAnnotation")
3545 """
3546 return "select obj from TagAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
3547 "join fetch obj.details.creationEvent"
3548
3550 """
3551 Gets the value of the Tag
3552
3553 @return: Value
3554 @type: String
3555 """
3556
3557 return self._obj.textValue.val
3558
3560 """
3561 Sets Tag value
3562
3563 @param val: Tag text value
3564 @type val: String
3565 """
3566
3567 self._obj.textValue = omero_type(val)
3568
3569 AnnotationWrapper._register(TagAnnotationWrapper)
3570
3571 from omero_model_CommentAnnotationI import CommentAnnotationI
3606
3607 AnnotationWrapper._register(CommentAnnotationWrapper)
3608
3609 from omero_model_LongAnnotationI import LongAnnotationI
3612 """
3613 omero_model_LongAnnotationI class wrapper extends AnnotationWrapper.
3614 """
3615 OMERO_TYPE = LongAnnotationI
3616
3618 """
3619 Used for building queries in generic methods such as getObjects("LongAnnotation")
3620 """
3621 return "select obj from LongAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
3622 "join fetch obj.details.creationEvent"
3623
3625 """
3626 Gets the value of the Long annotation
3627
3628 @return: Value
3629 @type: Long
3630 """
3631
3632 return self._obj.longValue and self._obj.longValue.val or None
3633
3635 """
3636 Sets long annotation value
3637
3638 @param val: Value
3639 @type val: Long
3640 """
3641
3642 self._obj.longValue = rlong(val)
3643
3644 AnnotationWrapper._register(LongAnnotationWrapper)
3645
3646 from omero_model_DoubleAnnotationI import DoubleAnnotationI
3649 """
3650 omero_model_DoubleAnnotationI class wrapper extends AnnotationWrapper.
3651 """
3652 OMERO_TYPE = DoubleAnnotationI
3653
3655 """
3656 Used for building queries in generic methods such as getObjects("DoubleAnnotation")
3657 """
3658 return "select obj from DoubleAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
3659 "join fetch obj.details.creationEvent"
3660
3662 """
3663 Gets the value of the Double Annotation
3664
3665 @return: Value
3666 @type: Double
3667 """
3668
3669 return self._obj.doubleValue.val
3670
3672 """
3673 Sets Double annotation value
3674
3675 @param val: Value
3676 @type val: Double
3677 """
3678
3679 self._obj.doubleValue = rdouble(val)
3680
3681 AnnotationWrapper._register(DoubleAnnotationWrapper)
3682
3683 from omero_model_TermAnnotationI import TermAnnotationI
3686 """
3687 omero_model_TermAnnotationI class wrapper extends AnnotationWrapper.
3688
3689 only in 4.2+
3690 """
3691 OMERO_TYPE = TermAnnotationI
3692
3694 """
3695 Used for building queries in generic methods such as getObjects("TermAnnotation")
3696 """
3697 return "select obj from TermAnnotation obj join fetch obj.details.owner as owner join fetch obj.details.group "\
3698 "join fetch obj.details.creationEvent"
3699
3701 """
3702 Gets the value of the Term
3703
3704 @return: Value
3705 @type: String
3706 """
3707
3708 return self._obj.termValue.val
3709
3711 """
3712 Sets term value
3713
3714 @param val: Value
3715 @type val: String
3716 """
3717
3718 self._obj.termValue = rstring(val)
3719
3720 AnnotationWrapper._register(TermAnnotationWrapper)
3721
3722 from omero_model_XmlAnnotationI import XmlAnnotationI
3725 """
3726 omero_model_XmlAnnotationI class wrapper extends CommentAnnotationWrapper.
3727 """
3728 OMERO_TYPE = XmlAnnotationI
3729
3730 AnnotationWrapper._register(XmlAnnotationWrapper)
3733
3735 """
3736 Gets the type (class) of the Enumeration
3737
3738 @return: The omero class
3739 @type: Class
3740 """
3741
3742 return self._obj.__class__
3743
3744 EnumerationWrapper = _EnumerationWrapper
3747 """
3748 omero_model_ExperimenterI class wrapper extends BlitzObjectWrapper.
3749 """
3750
3756
3758 rv = super(_ExperimenterWrapper, self).simpleMarshal(xtra=xtra, parents=parents)
3759 rv.update({'firstName': self.firstName,
3760 'middleName': self.middleName,
3761 'lastName': self.lastName,
3762 'email': self.email,
3763 'isAdmin': len(filter(lambda x: x.name.val == 'system', self._conn.getAdminService().containedGroups(self.getId()))) == 1,
3764 })
3765 return rv
3766
3768 """
3769 Returns string for building queries, loading Experimenters only.
3770 """
3771 return "select distinct obj from Experimenter as obj left outer join fetch obj.groupExperimenterMap " \
3772 "as map left outer join fetch map.parent g"
3773
3775 """
3776 Returns the experimenter's preferences annotation contents, as a ConfigParser instance
3777
3778 @return: See above
3779 @rtype: ConfigParser
3780 """
3781
3782 self._obj.unloadAnnotationLinks()
3783 cp = ConfigParser.SafeConfigParser()
3784 prefs = self.getAnnotation('TODO.changeme.preferences')
3785 if prefs is not None:
3786 prefs = prefs.getValue()
3787 if prefs is not None:
3788 cp.readfp(StringIO(prefs))
3789 return cp
3790
3792 """
3793 Sets the experimenter's preferences annotation contents, passed in as a ConfigParser instance
3794
3795 @param prefs: ConfigParser of preferences
3796 @type prefs: ConfigParser
3797 """
3798
3799 ann = self.getAnnotation('TODO.changeme.preferences')
3800 t = StringIO()
3801 prefs.write(t)
3802 if ann is None:
3803 ann = CommentAnnotationWrapper()
3804 ann.setNs('TODO.changeme.preferences')
3805 ann.setValue(t.getvalue())
3806 self.linkAnnotation(ann)
3807 else:
3808 ann.setValue(t.getvalue())
3809 ann.save()
3810 self._obj.unloadAnnotationLinks()
3811
3813 """
3814 Gets a preference for the experimenter
3815
3816 @param key: Preference key
3817 @param default: Default value to return
3818 @param section: Preferences section
3819 @return: Preference value
3820 """
3821
3822 if section is None:
3823 section = 'DEFAULT'
3824 try:
3825 return self.getRawPreferences().get(section, key)
3826 except ConfigParser.Error:
3827 return default
3828 return default
3829
3831 """
3832 Gets all preferences for section
3833
3834 @param section: Preferences section
3835 @return: Dict of preferences
3836 """
3837
3838 if section is None:
3839 section = 'DEFAULT'
3840 prefs = self.getRawPreferences()
3841 if prefs.has_section(section) or section == 'DEFAULT':
3842 return dict(prefs.items(section))
3843 return {}
3844
3846 """
3847 Sets a preference for the experimenter
3848
3849 @param key: Preference key
3850 @param value: Value to set
3851 @param section: Preferences section - created if needed
3852 """
3853
3854 if section is None:
3855 section = 'DEFAULT'
3856 prefs = self.getRawPreferences()
3857 if not section in prefs.sections():
3858 prefs.add_section(section)
3859 prefs.set(section, key, value)
3860 self.setRawPreferences(prefs)
3861
3863 """
3864 Make sure we have correct details for this experimenter and return them
3865
3866 @return: Experimenter Details
3867 @rtype: L{DetailsWrapper}
3868 """
3869
3870 if not self._obj.details.owner:
3871 details = omero.model.DetailsI()
3872 details.owner = self._obj
3873 self._obj._details = details
3874 return DetailsWrapper(self._conn, self._obj.details)
3875
3877 """
3878 Returns Experimenter's omeName
3879
3880 @return: Name
3881 @rtype: String
3882 """
3883
3884 return self.omeName
3885
3887 """
3888 Returns Experimenter's Full Name
3889
3890 @return: Full Name or None
3891 @rtype: String
3892 """
3893
3894 return self.getFullName()
3895
3897 """
3898 Gets full name of this experimenter. E.g. 'William James. Moore' or 'William Moore' if no middle name
3899
3900 @return: Full Name or None
3901 @rtype: String
3902 """
3903
3904 try:
3905 lastName = self.lastName
3906 firstName = self.firstName
3907 middleName = self.middleName
3908
3909 if middleName is not None and middleName != '':
3910 name = "%s %s. %s" % (firstName, middleName, lastName)
3911 else:
3912 name = "%s %s" % (firstName, lastName)
3913 return name
3914 except:
3915 logger.error(traceback.format_exc())
3916 return None
3917
3919 """
3920 Returns first initial and Last name. E.g. 'W. Moore'
3921
3922 @return: Initial and last name
3923 @rtype: String
3924 """
3925
3926 try:
3927 if self.firstName is not None and self.lastName is not None:
3928 name = "%s. %s" % (self.firstName[:1], self.lastName)
3929 else:
3930 name = self.omeName
3931 return name
3932 except:
3933 logger.error(traceback.format_exc())
3934 return _("Unknown name")
3935
3937 """
3938 Returns true if Experimenter is Admin (if they are in any group named 'system')
3939
3940 @return: True if experimenter is Admin
3941 @rtype: Boolean
3942 """
3943
3944 for ob in self._obj.copyGroupExperimenterMap():
3945 if ob.parent.name.val == "system":
3946 return True
3947 return False
3948
3950 """
3951 Returns true if Experimenter is Active (if they are in any group named 'user')
3952
3953 @return: True if experimenter is Active
3954 @rtype: Boolean
3955 """
3956
3957 for ob in self._obj.copyGroupExperimenterMap():
3958 if ob.parent.name.val == "user":
3959 return True
3960 return False
3961
3963 """
3964 Returns true if Experimenter is Guest (if they are in any group named 'guest')
3965
3966 @return: True if experimenter is Admin
3967 @rtype: Boolean
3968 """
3969
3970 for ob in self._obj.copyGroupExperimenterMap():
3971 if ob.parent.name.val == "guest":
3972 return True
3973 return False
3974
3975 ExperimenterWrapper = _ExperimenterWrapper
3978 """
3979 omero_model_ExperimenterGroupI class wrapper extends BlitzObjectWrapper.
3980 """
3981
3987
3989 """
3990 Is the current group led by the current user?
3991
3992 @return: True if user leads the current group
3993 @rtype: Boolean
3994 """
3995 if self._conn.getEventContext().groupId in self._conn.getEventContext().leaderOfGroups:
3996 return True
3997 return False
3998
4000 """
4001 Returns string for building queries, loading Experimenters for each group.
4002 """
4003 query = "select distinct obj from ExperimenterGroup as obj left outer join fetch obj.groupExperimenterMap " \
4004 "as map left outer join fetch map.child e"
4005 return query
4006
4007
4008 ExperimenterGroupWrapper = _ExperimenterGroupWrapper
4011 """
4012 omero_model_DetailsI class wrapper extends BlitzObjectWrapper.
4013 """
4014
4021
4023 """
4024 Returns the Owner of the object that these details apply to
4025
4026 @return: Owner
4027 @rtype: L{ExperimenterWrapper}
4028 """
4029
4030 return self._owner
4031
4033 """
4034 Returns the Group that these details refer to
4035
4036 @return: Group
4037 @rtype: L{ExperimenterGroupWrapper}
4038 """
4039
4040 return self._group
4041
4043 """
4044 omero_model_DatasetI class wrapper extends BlitzObjectWrapper.
4045 """
4046
4052
4054 """ In addition to loading the Dataset, this method also loads the Images """
4055
4056 super(_DatasetWrapper, self).__loadedHotSwap__()
4057 if not self._obj.isImageLinksLoaded():
4058 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)
4059 self._obj._imageLinksLoaded = True
4060 self._obj._imageLinksSeq = links
4061
4062 DatasetWrapper = _DatasetWrapper
4065 """
4066 omero_model_ProjectI class wrapper extends BlitzObjectWrapper.
4067 """
4068
4074
4075 ProjectWrapper = _ProjectWrapper
4078 """
4079 omero_model_ScreenI class wrapper extends BlitzObjectWrapper.
4080 """
4081
4087
4088 @timeit
4090 """
4091 Iterates all wells on all plates for this screen and returns highest well sample count
4092 """
4093 q = self._conn.getQueryService()
4094 query = "select p.id, maxindex(p.wells.wellSamples)+1"
4095 query += " from ScreenPlateLink spl join spl.parent s join spl.child p"
4096 query += " where s.id=%d group by p.id" % self.getId()
4097 return dict(unwrap(q.projection(query, None)))
4098
4099
4100 ScreenWrapper = _ScreenWrapper
4103 """ Convert number to letter label. E.g. 0 -> 'A' and 100 -> 'CW' """
4104 r = chr(ord('A') + i%26)
4105 i = i/26
4106 while i > 0:
4107 i -= 1
4108 r = chr(ord('A') + i%26) + r
4109 i = i/26
4110 return r
4111
4113 """
4114 omero_model_PlateI class wrapper extends BlitzObjectWrapper.
4115 """
4116
4122
4125
4127 """
4128 Clears child cache, so next _listChildren will query the server
4129 """
4130 self._childcache = None
4131 self._gridSize = None
4132
4134 """
4135 Lists Wells in this plate, not sorted. Saves wells to _childcache map, where key is (row, column).
4136 _
4137 @rtype: list of omero.model.WellI objects
4138 @return: child objects.
4139 """
4140 if self._childcache is None:
4141 q = self._conn.getQueryService()
4142 params = omero.sys.Parameters()
4143 params.map = {}
4144 params.map["oid"] = omero_type(self.getId())
4145 query = "select well from Well as well "\
4146 "join fetch well.details.creationEvent "\
4147 "join fetch well.details.owner join fetch well.details.group " \
4148 "left outer join fetch well.plate as pt "\
4149 "left outer join fetch well.wellSamples as ws " \
4150 "left outer join fetch ws.image as img "\
4151 "where well.plate.id = :oid"
4152
4153
4154 kwargs = {'index': self.defaultSample or 0}
4155 childw = self._getChildWrapper()
4156 self._childcache = {}
4157 for well in q.findAllByQuery(query, params):
4158 self._childcache[(well.row.val, well.column.val)] = well
4159 return self._childcache.values()
4160
4163
4165 """
4166 Makes sure the grid side count is the exact power of two of row and col arguments,
4167 keeping their ratio, that fits the existing well count.
4168 """
4169 gs = self.getGridSize()
4170 mul = 0
4171 while gs['rows'] > (row*(2**mul)) or gs['columns'] > (col*(2**mul)):
4172 mul += 1
4173 self._gridSize['rows'] = row * (2**mul)
4174 self._gridSize['columns'] = col * (2**mul)
4175
4177 """
4178 Iterates all wells on plate to retrieve grid size as {'rows': rSize, 'columns':cSize} dict.
4179
4180 @rtype: dict of {'rows': rSize, 'columns':cSize}
4181 """
4182 if self._gridSize is None:
4183 r,c = 0,0
4184 for child in self._listChildren():
4185 r,c = max(child.row.val, r), max(child.column.val, c)
4186 self._gridSize = {'rows': r+1, 'columns': c+1}
4187 return self._gridSize
4188
4190 """
4191 Returns a grid of WellWrapper objects, indexed by [row][col].
4192
4193 @rtype: 2D array of L{WellWrapper}s. Empty well positions are None
4194 """
4195 grid = self.getGridSize()
4196 childw = self._getChildWrapper()
4197 rv = [[None]*grid['columns'] for x in range(grid['rows'])]
4198 for child in self._listChildren():
4199 rv[child.row.val][child.column.val] = childw(self._conn, child, index=index)
4200 return rv
4201
4203 """
4204 Returns a list of labels for the columns on this plate. E.g. [1, 2, 3...] or ['A', 'B', 'C'...] etc
4205 """
4206 if self.columnNamingConvention is not None and self.columnNamingConvention.lower()=='number':
4207 return range(1, self.getGridSize()['columns']+1)
4208 else:
4209
4210 return [_letterGridLabel(x) for x in range(self.getGridSize()['columns'])]
4211
4213 """
4214 Returns a list of labels for the rows on this plate. E.g. [1, 2, 3...] or ['A', 'B', 'C'...] etc
4215 """
4216 if self.rowNamingConvention is not None and self.rowNamingConvention.lower()=='number':
4217 return range(1, self.getGridSize()['rows']+1)
4218 else:
4219
4220 return [_letterGridLabel(x) for x in range(self.getGridSize()['rows'])]
4221
4222 @timeit
4224 """
4225 Iterates all wells on plate and returns highest well sample count
4226 """
4227 q = self._conn.getQueryService()
4228 query = "select maxindex(p.wells.wellSamples)+1"
4229 query += " from Plate p"
4230 query += " where p.id=%d group by p.id" % self.getId()
4231 return unwrap(q.projection(query, None))[0][0]
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4250 """
4251 Make sure full project export doesn't pick up wellsample images
4252 TODO: do we want to support this at all?
4253 """
4254 return None
4255
4257 """
4258 Returns a query string for constructing custom queries, loading the screen for each plate.
4259 """
4260 query = "select obj from Plate as obj " \
4261 "join fetch obj.details.owner join fetch obj.details.group "\
4262 "join fetch obj.details.creationEvent "\
4263 "left outer join fetch obj.screenLinks spl " \
4264 "left outer join fetch spl.parent sc"
4265 return query
4266
4267
4268 PlateWrapper = _PlateWrapper
4271 """
4272 omero_model_WellI class wrapper extends BlitzObjectWrapper.
4273 """
4274
4280
4282 try:
4283 self.index = int(kwargs['index'])
4284 except:
4285 self.index = 0
4286 self.__reset__()
4287
4289 """
4290 Clears child cache, so next _listChildren will query the server
4291 """
4292 self._childcache = None
4293
4295 query = "select well from Well as well "\
4296 "join fetch well.details.creationEvent "\
4297 "join fetch well.details.owner join fetch well.details.group " \
4298 "left outer join fetch well.wellSamples as ws " \
4299 "left outer join fetch ws.image as img "\
4300 "where well.id = %d" % self.getId()
4301
4302 self._obj = self._conn.getQueryService().findByQuery(query, None)
4303
4305 if self._childcache is None:
4306 if not self.isWellSamplesLoaded():
4307 self.__loadedHotSwap__()
4308 if self.isWellSamplesLoaded():
4309 self._childcache = self.copyWellSamples()
4310 return self._childcache
4311
4319
4321 """
4322 Because wells are direct children of plates, with no links in between,
4323 a special listParents is needed
4324 """
4325 rv = self._conn.getObject('Plate', self.plate.id.val)
4326 if withlinks:
4327 return [(rv, None)]
4328 return [rv]
4329
4331 """ returns the screens that link to plates that link to this well """
4332 params = omero.sys.Parameters()
4333 params.map = {'id': omero_type(self.getId())}
4334 query = """select s from Well w
4335 left outer join w.plate p
4336 left outer join p.screenLinks spl
4337 left outer join spl.parent s
4338 where spl.parent.id=s.id and spl.child.id=p.id and w.plate.id=p.id
4339 and w.id=:id"""
4340 return [omero.gateway.ScreenWrapper(self._conn, x) for x in \
4341 self._conn.getQueryService().findAllByQuery(query, params)]
4342
4343
4345 """
4346 Return True if well samples exist (loaded)
4347
4348 @return: True if well samples loaded
4349 @rtype: Boolean
4350 """
4351
4352 if self.isWellSamplesLoaded():
4353 childnodes = self.copyWellSamples()
4354 logger.debug('listChildren for %s %d: already loaded, %d samples' % (self.OMERO_CLASS, self.getId(), len(childnodes)))
4355 if len(childnodes) > 0:
4356 return True
4357 return False
4358
4360 """
4361 Return the number of well samples loaded
4362
4363 @return: well sample count
4364 @rtype: Int
4365 """
4366 return len(self._listChildren())
4367
4369 """
4370 Return the well sample at the specified index. If index is ommited,
4371 the currently selected index is used instead (self.index) and if
4372 that is not defined, the first one (index 0) is returned.
4373
4374 @param index: the well sample index
4375 @type index: integer
4376 @return: The Well Sample
4377 @rtype: L{WellSampleWrapper}
4378 """
4379 if index is None:
4380 index = self.index
4381 if index is None:
4382 index = 0
4383 index = int(index)
4384 childnodes = self._listChildren()
4385 if len(childnodes) > index:
4386 return self._getChildWrapper()(self._conn, childnodes[index])
4387 return None
4388
4390 """
4391 Return the image at the specified well sample index. If index is ommited,
4392 the currently selected index is used instead (self.index) and if
4393 that is not defined, the first one (index 0) is returned.
4394
4395 @param index: the well sample index
4396 @type index: integer
4397 @return: The Image
4398 @rtype: L{ImageWrapper}
4399 """
4400 wellsample = self.getWellSample(index)
4401 if wellsample:
4402 return wellsample.getImage()
4403 return None
4404
4406 """
4407 Return the well sample at the current index (0 if not set)
4408
4409 @return: The Well Sample wrapper
4410 @rtype: L{WellSampleWrapper}
4411
4412 """
4413 return self.getWellSample()
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439 WellWrapper = _WellWrapper
4442 """
4443 omero_model_WellSampleI class wrapper extends BlitzObjectWrapper.
4444 """
4445
4453
4455 """
4456 Because wellsamples are direct children of wells, with no links in between,
4457 a special listParents is needed
4458 """
4459 rv = self._conn.getQueryService().findAllByQuery("""select w from Well w
4460 left outer join fetch w.wellSamples as ws
4461 where ws.id=%d""" % self.getId(), None)
4462 if not len(rv):
4463 rv = [None]
4464
4465 pwc = self._getParentWrappers()
4466 if withlinks:
4467 return [(pwc[0](self._conn, x), None) for x in rv]
4468 return [pwc[0](self._conn, x) for x in rv]
4469
4471 """
4472 Gets the Image for this well sample.
4473
4474 @return: The Image
4475 @rtype: L{ImageWrapper}
4476 """
4477 return self._getChildWrapper()(self._conn, self._obj.image)
4478
4480 """
4481 Gets the Image for this well sample.
4482
4483 @return: The Image
4484 @rtype: L{ImageWrapper}
4485 """
4486 return self.getImage()
4487
4488 WellSampleWrapper = _WellSampleWrapper
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504 -class ColorHolder (object):
4505 """
4506 Stores color internally as (R,G,B,A) and allows setting and getting in multiple formats
4507 """
4508
4509 _color = {'red': 0, 'green': 0, 'blue': 0, 'alpha': 255}
4510
4512 """
4513 If colorname is 'red', 'green' or 'blue', set color accordingly - Otherwise black
4514
4515 @param colorname: 'red', 'green' or 'blue'
4516 @type colorname: String
4517 """
4518
4519 self._color = {'red': 0, 'green': 0, 'blue': 0, 'alpha': 255}
4520 if colorname and colorname.lower() in self._color.keys():
4521 self._color[colorname.lower()] = 255
4522
4523 @classmethod
4525 """
4526 Class method for creating a ColorHolder from r,g,b,a values
4527
4528 @param r: red 0 - 255
4529 @type r: int
4530 @param g: green 0 - 255
4531 @type g: int
4532 @param b: blue 0 - 255
4533 @type b: int
4534 @param a: alpha 0 - 255
4535 @type a: int
4536 @return: new Color object
4537 @rtype: L{ColorHolder}
4538 """
4539
4540 rv = klass()
4541 rv.setRed(r)
4542 rv.setGreen(g)
4543 rv.setBlue(b)
4544 rv.setAlpha(a)
4545 return rv
4546
4548 """
4549 Gets the Red component
4550
4551 @return: red
4552 @rtype: int
4553 """
4554
4555 return self._color['red']
4556
4558 """
4559 Set red, as int 0..255
4560
4561 @param val: value of Red.
4562 @type val: Int
4563 """
4564
4565 self._color['red'] = max(min(255, int(val)), 0)
4566
4568 """
4569 Gets the Green component
4570
4571 @return: green
4572 @rtype: int
4573 """
4574
4575 return self._color['green']
4576
4578 """
4579 Set green, as int 0..255
4580
4581 @param val: value of Green.
4582 @type val: Int
4583 """
4584
4585 self._color['green'] = max(min(255, int(val)), 0)
4586
4588 """
4589 Gets the Blue component
4590
4591 @return: blue
4592 @rtype: int
4593 """
4594
4595 return self._color['blue']
4596
4598 """
4599 Set Blue, as int 0..255
4600
4601 @param val: value of Blue.
4602 @type val: Int
4603 """
4604
4605 self._color['blue'] = max(min(255, int(val)), 0)
4606
4608 """
4609 Gets the Alpha component
4610
4611 @return: alpha
4612 @rtype: int
4613 """
4614
4615 return self._color['alpha']
4616
4618 """
4619 Set alpha, as int 0..255.
4620 @param val: value of alpha.
4621 """
4622
4623 self._color['alpha'] = max(min(255, int(val)), 0)
4624
4626 """
4627 Gets the html usable color. Dumps the alpha information. E.g. 'FF0000'
4628
4629 @return: html color
4630 @rtype: String
4631 """
4632
4633 return "%(red)0.2X%(green)0.2X%(blue)0.2X" % (self._color)
4634
4636 """
4637 Gets the css string: rgba(r,g,b,a)
4638
4639 @return: css color
4640 @rtype: String
4641 """
4642
4643 c = self._color.copy()
4644 c['alpha'] /= 255.0
4645 return "rgba(%(red)i,%(green)i,%(blue)i,%(alpha)0.3f)" % (c)
4646
4648 """
4649 Gets the (r,g,b) as a tuple.
4650
4651 @return: Tuple of (r,g,b) values
4652 @rtype: tuple of ints
4653 """
4654
4655 return (self._color['red'], self._color['green'], self._color['blue'])
4656
4658 """
4659 omero_model_LogicalChannelI class wrapper extends BlitzObjectWrapper.
4660 Specifies a number of _attrs for the channel metadata.
4661 """
4662 _attrs = ('name',
4663 'pinHoleSize',
4664 '#illumination',
4665 'contrastMethod',
4666 'excitationWave',
4667 'emissionWave',
4668 'fluor',
4669 'ndFilter',
4670 'otf',
4671 'detectorSettings|DetectorSettingsWrapper',
4672 'lightSourceSettings|LightSettingsWrapper',
4673 'filterSet|FilterSetWrapper',
4674 'secondaryEmissionFilter|FilterWrapper',
4675 'secondaryExcitationFilter',
4676 'samplesPerPixel',
4677 '#photometricInterpretation',
4678 'mode',
4679 'pockelCellSetting',
4680 'shapes',
4681 'version')
4682
4684 """ Loads the logical channel using the metadata service """
4685 if self._obj is not None:
4686 self._obj = self._conn.getMetadataService().loadChannelAcquisitionData([self._obj.id.val])[0]
4687
4689 """ Make sure we have the channel fully loaded, then return L{LightPathWrapper}"""
4690 self.__loadedHotSwap__()
4691 if self._obj.lightPath is not None:
4692 return LightPathWrapper(self._conn, self._obj.lightPath)
4693
4694 LogicalChannelWrapper = _LogicalChannelWrapper
4697 """
4698 base Light Source class wrapper, extends BlitzObjectWrapper.
4699 """
4700 _attrs = ('dichroic|DichroicWrapper',)
4701
4704
4706 """ Returns list of excitation L{FilterWrapper}s """
4707 return [FilterWrapper(self._conn, link.child) for link in self.copyExcitationFilterLink()]
4708
4710 """ Returns list of emission L{FilterWrapper}s """
4711 return [FilterWrapper(self._conn, link.child) for link in self.copyEmissionFilterLink()]
4712
4713 LightPathWrapper = _LightPathWrapper
4716 """
4717 omero_model_PixelsI class wrapper extends BlitzObjectWrapper.
4718 """
4719
4722
4724 """
4725 Creates RawPixelsStore and sets the id etc
4726 """
4727 ps = self._conn.createRawPixelsStore()
4728 ps.setPixelsId(self._obj.id.val, True)
4729 return ps
4730
4732 """
4733 This simply wraps the PixelsType object in a BlitzObjectWrapper.
4734 Shouldn't be needed when this is done automatically
4735 """
4736 return BlitzObjectWrapper(self._conn, self._obj.getPixelsType())
4737
4739 """
4740 Loads plane infos and returns sequence of omero.model.PlaneInfo objects wrapped in BlitzObjectWrappers
4741 ordered by planeInfo.deltaT.
4742 Set of plane infos can be filtered by C, T or Z
4743
4744 @param theC: Filter plane infos by Channel index
4745 @param theT: Filter plane infos by Time index
4746 @param theZ: Filter plane infos by Z index
4747 """
4748
4749 params = omero.sys.Parameters()
4750 params.map = {}
4751 params.map["pid"] = rlong(self._obj.id)
4752 query = "select info from PlaneInfo as info where pixels.id=:pid"
4753 if theC != None:
4754 params.map["theC"] = rint(theC)
4755 query += " and info.theC=:theC"
4756 if theT != None:
4757 params.map["theT"] = rint(theT)
4758 query += " and info.theT=:theT"
4759 if theZ != None:
4760 params.map["theZ"] = rint(theZ)
4761 query += " and info.theZ=:theZ"
4762 query += " order by info.deltaT"
4763 queryService = self._conn.getQueryService()
4764 result = queryService.findAllByQuery(query, params)
4765 for pi in result:
4766 yield BlitzObjectWrapper(self._conn, pi)
4767
4769 """
4770 Returns generator of numpy 2D planes from this set of pixels for a list of Z, C, T indexes.
4771
4772 @param zctList: A list of indexes: [(z,c,t), ]
4773 """
4774
4775 zctTileList = []
4776 for zct in zctList:
4777 z,c,t = zct
4778 zctTileList.append((z,c,t, None))
4779 return self.getTiles(zctTileList)
4780
4781 - def getPlane (self, theZ=0, theC=0, theT=0):
4782 """
4783 Gets the specified plane as a 2D numpy array by calling L{getPlanes}
4784 If a range of planes are required, L{getPlanes} is approximately 30% faster.
4785 """
4786 planeList = list( self.getPlanes([(theZ, theC, theT)]) )
4787 return planeList[0]
4788
4790 """
4791 Returns generator of numpy 2D planes from this set of pixels for a list of (Z, C, T, tile)
4792 where tile is (x, y, width, height) or None if you want the whole plane.
4793
4794 @param zctrList: A list of indexes: [(z,c,t, region), ]
4795 """
4796
4797 import numpy
4798 from struct import unpack
4799
4800 pixelTypes = {"int8":['b',numpy.int8],
4801 "uint8":['B',numpy.uint8],
4802 "int16":['h',numpy.int16],
4803 "uint16":['H',numpy.uint16],
4804 "int32":['i',numpy.int32],
4805 "uint32":['I',numpy.uint32],
4806 "float":['f',numpy.float],
4807 "double":['d', numpy.double]}
4808
4809 rawPixelsStore = self._prepareRawPixelsStore()
4810 sizeX = self.sizeX
4811 sizeY = self.sizeY
4812 pixelType = self.getPixelsType().value
4813 numpyType = pixelTypes[pixelType][1]
4814 exc = None
4815 try:
4816 for zctTile in zctTileList:
4817 z,c,t,tile = zctTile
4818 if tile is None:
4819 rawPlane = rawPixelsStore.getPlane(z, c, t)
4820 planeY = sizeY
4821 planeX = sizeX
4822 else:
4823 x, y, width, height = tile
4824 rawPlane = rawPixelsStore.getTile(z, c, t, x, y, width, height)
4825 planeY = height
4826 planeX = width
4827 convertType ='>%d%s' % ((planeY*planeX), pixelTypes[pixelType][0])
4828 convertedPlane = unpack(convertType, rawPlane)
4829 remappedPlane = numpy.array(convertedPlane, numpyType)
4830 remappedPlane.resize(planeY, planeX)
4831 yield remappedPlane
4832 except Exception, e:
4833 logger.error("Failed to getPlane() or getTile() from rawPixelsStore", exc_info=True)
4834 exc = e
4835 try:
4836 rawPixelsStore.close()
4837 except Exception, e:
4838 logger.error("Failed to close rawPixelsStore", exc_info=True)
4839 if exc is None:
4840 exc = e
4841 if exc is not None:
4842 raise exc
4843
4844 - def getTile (self, theZ=0, theC=0, theT=0, tile=None):
4845 """
4846 Gets the specified plane as a 2D numpy array by calling L{getPlanes}
4847 If a range of tile are required, L{getTiles} is approximately 30% faster.
4848 """
4849 tileList = list( self.getTiles([(theZ, theC, theT, tile)]) )
4850 return tileList[0]
4851
4852 PixelsWrapper = _PixelsWrapper
4856 """
4857 omero_model_ChannelI class wrapper extends BlitzObjectWrapper.
4858 """
4859
4860 BLUE_MIN = 400
4861 BLUE_MAX = 500
4862 GREEN_MIN = 501
4863 GREEN_MAX = 600
4864 RED_MIN = 601
4865 RED_MAX = 700
4866 COLOR_MAP = ((BLUE_MIN, BLUE_MAX, ColorHolder('Blue')),
4867 (GREEN_MIN, GREEN_MAX, ColorHolder('Green')),
4868 (RED_MIN, RED_MAX, ColorHolder('Red')),
4869 )
4870
4873
4875 """
4876 Sets values of idx, re and img
4877 """
4878 self._re = re
4879 self._idx = idx
4880 self._img = img
4881
4883 """
4884 Extends the superclass save method to save Pixels. Returns result of saving superclass (TODO: currently this is None)
4885 """
4886
4887 self._obj.setPixels(omero.model.PixelsI(self._obj.getPixels().getId(), False))
4888 return super(_ChannelWrapper, self).save()
4889
4891 """
4892 Returns True if the channel is active (turned on in rendering settings)
4893
4894 @return: True if Channel is Active
4895 @rtype: Boolean
4896 """
4897
4898 if self._re is None:
4899 return False
4900 return self._re.isActive(self._idx)
4901
4903 """
4904 Returns the logical channel
4905
4906 @return: Logical Channel
4907 @rtype: L{LogicalChannelWrapper}
4908 """
4909
4910 if self._obj.logicalChannel is not None:
4911 return LogicalChannelWrapper(self._conn, self._obj.logicalChannel)
4912
4914 """
4915 Returns the logical channel name, emission wave or index. The first that is not null
4916 in the described order.
4917
4918 @return: The logical channel string representation
4919 @rtype: String
4920 """
4921
4922 lc = self.getLogicalChannel()
4923 rv = lc.name
4924 if rv is None:
4925 rv = lc.emissionWave
4926 if rv is None:
4927 rv = self._idx
4928 return unicode(rv)
4929
4930
4932 """
4933 Returns the logical channel name or None
4934
4935 @return: The logical channel string representation
4936 @rtype: String
4937 """
4938
4939 lc = self.getLogicalChannel()
4940 rv = lc.name
4941 if rv is not None:
4942 return unicode(rv)
4943
4944
4946 """
4947 Returns the emission wave or None.
4948
4949 @return: Emission wavelength or None
4950 @rtype: int
4951 """
4952
4953 lc = self.getLogicalChannel()
4954 return lc.emissionWave
4955
4957 """
4958 Returns the excitation wave or None.
4959
4960 @return: Excitation wavelength or None
4961 @rtype: int
4962 """
4963
4964 lc = self.getLogicalChannel()
4965 return lc.excitationWave
4966
4968 """
4969 Returns the rendering settings color of this channel
4970
4971 @return: Channel color
4972 @rtype: L{ColorHolder}
4973 """
4974
4975 if self._re is None:
4976 return None
4977 return ColorHolder.fromRGBA(*self._re.getRGBA(self._idx))
4978
4980 """
4981 Returns the rendering settings window-start of this channel
4982
4983 @return: Window start
4984 @rtype: int
4985 """
4986
4987 return int(self._re.getChannelWindowStart(self._idx))
4988
4991
4993 """
4994 Returns the rendering settings window-end of this channel
4995
4996 @return: Window end
4997 @rtype: int
4998 """
4999
5000 return int(self._re.getChannelWindowEnd(self._idx))
5001
5004
5006 self._re.setChannelWindow(self._idx, float(minval), float(maxval))
5007
5009 """
5010 Returns the minimum pixel value of the channel
5011
5012 @return: Min pixel value
5013 @rtype: double
5014 """
5015
5016 return self._obj.getStatsInfo().getGlobalMin().val
5017
5019 """
5020 Returns the maximum pixel value of the channel
5021
5022 @return: Min pixel value
5023 @rtype: double
5024 """
5025
5026 return self._obj.getStatsInfo().getGlobalMax().val
5027
5028 ChannelWrapper = _ChannelWrapper
5031 """
5032 Function decorator to make sure that rendering engine is prepared before
5033 call. Is configurable by various options.
5034 """
5035
5036 - def __init__(self, onPrepareFailureReturnNone=True, ignoreExceptions=None):
5037 """
5038 Initialises the decorator.
5039
5040 @param onPrepareFailureReturnNone: Whether or not on a failure to
5041 prepare the rendering engine the decorator should return 'None' or
5042 allow the execution of the decorated function or method. Defaults to
5043 'True'.
5044 @type onPrepareFailureReturnNone: Boolean
5045 @param ignoreExceptions: A set of exceptions thrown during the
5046 preparation of the rendering engine for whith the decorator should
5047 ignore and allow the execution of the decorated function or method.
5048 Defaults to 'None'.
5049 @type ignoreExceptions: Set
5050 """
5051 self.onPrepareFailureReturnNone = onPrepareFailureReturnNone
5052 self.ignoreExceptions = ignoreExceptions
5053
5055 """
5056 Tries to prepare rendering engine, then calls function and return the
5057 result.
5058 """
5059 def wrapped(self, *args, **kwargs):
5060 try:
5061 if not self._prepareRenderingEngine() \
5062 and ctx.onPrepareFailureReturnNone:
5063 logger.debug('Preparation of rendering engine failed, ' \
5064 'returning None for %r!' % f)
5065 return None
5066 except ctx.ignoreExceptions, e:
5067 logger.debug('Ignoring exception thrown during preparation ' \
5068 'of rendering engine for %r!' % f, exc_info=True)
5069 pass
5070 return f(self, *args, **kwargs)
5071 return wrapped
5072
5074 """
5075 Function decorator to make sure that pixels are loaded before call
5076
5077 @param func: Function
5078 @type func: Function
5079 @return: Decorated function
5080 @rtype: Function
5081 """
5082
5083 def wrapped (self, *args, **kwargs):
5084 """ Tries to load pixels, then call function and return the result"""
5085
5086 if not self._loadPixels():
5087 return None
5088 return func(self, *args, **kwargs)
5089 return wrapped
5090
5093 """
5094 omero_model_ImageI class wrapper extends BlitzObjectWrapper.
5095 """
5096
5097 _re = None
5098 _pd = None
5099 _rm = {}
5100 _pixels = None
5101 _archivedFileCount = None
5102
5103 _pr = None
5104
5105 _invertedAxis = False
5106
5107 PROJECTIONS = {
5108 'normal': -1,
5109 'intmax': omero.constants.projection.ProjectionType.MAXIMUMINTENSITY,
5110 'intmean': omero.constants.projection.ProjectionType.MEANINTENSITY,
5111 'intsum': omero.constants.projection.ProjectionType.SUMINTENSITY,
5112 }
5113
5114 PLANEDEF = omero.romio.XY
5115
5116 @classmethod
5118 """
5119 Creates a new Image wrapper with the image specified by pixels ID
5120
5121 @param conn: The connection
5122 @type conn: L{BlitzGateway}
5123 @param pid: Pixles ID
5124 @type pid: Long
5125 @return: New Image wrapper
5126 @rtype: L{ImageWrapper}
5127 """
5128
5129 q = conn.getQueryService()
5130 p = q.find('Pixels', pid)
5131 if p is None:
5132 return None
5133 return ImageWrapper(conn, p.image)
5134
5140
5143
5146
5148 """
5149 Returns the Instrument for this image (or None) making sure the instrument is loaded.
5150
5151 @return: Instrument (microscope)
5152 @rtype: L{InstrumentWrapper}
5153 """
5154
5155 i = self._obj.instrument
5156 if i is None:
5157 return None
5158 if not i.loaded:
5159 meta_serv = self._conn.getMetadataService()
5160 i = self._obj.instrument = meta_serv.loadInstrument(i.id.val)
5161 return InstrumentWrapper(self._conn, i)
5162
5164 """
5165 Checks that pixels are loaded
5166
5167 @return: True if loaded
5168 @rtype: Boolean
5169 """
5170
5171 if not self._obj.pixelsLoaded:
5172 self.__loadedHotSwap__()
5173 return self._obj.sizeOfPixels() > 0
5174
5175
5177 """
5178 Return a rendering def ID based on custom logic.
5179
5180 @param pid: Pixels ID
5181 @type pid: Long
5182 @return: Rendering definition ID or None if no custom
5183 logic has found a rendering definition.
5184 """
5185 rdefns = self._conn.CONFIG.get('IMG_RDEFNS', None)
5186 if rdefns is None:
5187 return
5188 rdid = ann.getValue()
5189 if rdid is None:
5190 return
5191 logger.debug('_getRDef: %s, %s' % (str(pid), str(rdid)))
5192 logger.debug('now load render options: %s' % str(self._loadRenderOptions()))
5193 self.loadRenderOptions()
5194 return rdid
5195
5197 """
5198 Called whenever a reset defaults is called by the preparation of
5199 the rendering engine or the thumbnail bean.
5200
5201 @param pid: Pixels ID
5202 @type pid: Long
5203 @param pid: Current Rendering Def ID
5204 @type pid: Long
5205 """
5206 rdefns = self._conn.CONFIG.get('IMG_RDEFNS', None)
5207 if rdefns is None:
5208 return
5209 ann = self.getAnnotation(rdefns)
5210 if ann is None:
5211 a = LongAnnotationWrapper(self)
5212 a.setNs(rdefns)
5213 a.setValue(rdid)
5214 self.linkAnnotation(a, sameOwner=False)
5215
5217 """
5218 Prepare the rendering engine with pixels ID and existing or new rendering def.
5219
5220 @return: The Rendering Engine service
5221 @rtype: L{ProxyObjectWrapper}
5222 """
5223
5224 pid = self.getPrimaryPixels().id
5225 re = self._conn.createRenderingEngine()
5226 re.lookupPixels(pid)
5227 rdid = self._getRDef(pid)
5228 if rdid is None:
5229 if not re.lookupRenderingDef(pid):
5230 re.resetDefaults()
5231 re.lookupRenderingDef(pid)
5232 self._onResetDefaults(pid, re.getRenderingDefId())
5233 else:
5234 re.loadRenderingDef(rdid)
5235 re.load()
5236 return re
5237
5239 """
5240 Checks that the rendering engine is prepared, calling L{_prepareRE} if needed.
5241 Used by the L{assert_re} method to wrap calls requiring rendering engine
5242
5243 @return: True if rendering engine is created
5244 @rtype: Boolean
5245 """
5246
5247 self._loadPixels()
5248 if self._re is None:
5249 if self._obj.sizeOfPixels() < 1:
5250 return False
5251 if self._pd is None:
5252 self._pd = omero.romio.PlaneDef(self.PLANEDEF)
5253 self._re = self._prepareRE()
5254 return self._re is not None
5255
5262
5264 """
5265 Creates a dict representation of the Image, including author and date info.
5266
5267 @return: Dict
5268 @rtype: Dict
5269 """
5270
5271 rv = super(_ImageWrapper, self).simpleMarshal(xtra=xtra, parents=parents)
5272 rv.update({'author': self.getAuthor(),
5273 'date': time.mktime(self.getDate().timetuple()),})
5274 if xtra:
5275 if xtra.has_key('thumbUrlPrefix'):
5276 if callable(xtra['thumbUrlPrefix']):
5277 rv['thumb_url'] = xtra['thumbUrlPrefix'](str(self.id))
5278 else:
5279 rv['thumb_url'] = xtra['thumbUrlPrefix'] + str(self.id) + '/'
5280 return rv
5281
5283 """
5284 Returns the stage label or None
5285
5286 @return: Stage label
5287 @rtype: L{ImageStageLabelWrapper}
5288 """
5289
5290 if self._obj.stageLabel is None:
5291 return None
5292 else:
5293 return ImageStageLabelWrapper(self._conn, self._obj.stageLabel)
5294
5296 """
5297 Provides a truncated name of the image. E.g. ...catedNameOfTheImage.tiff
5298
5299 @param length: The ideal length to return. If truncated, will be ...length
5300 @type length: Int
5301 @param hist: The amount of leeway allowed before trunction (avoid truncating 1 or 2 letters)
5302 @type hist: Int
5303 @return: Truncated ...name
5304 @type: String
5305 """
5306
5307 name = self.name
5308 if not name:
5309 return ""
5310 l = len(name)
5311 if l < length+hist:
5312 return name
5313 return "..." + name[l - length:]
5314
5316 """
5317 Returns 'Firstname Lastname' of image owner
5318
5319 @return: Image owner
5320 @rtype: String
5321 """
5322
5323 q = self._conn.getQueryService()
5324 e = q.findByQuery("select e from Experimenter e where e.id = %i" % self._obj.details.owner.id.val,None)
5325 self._author = e.firstName.val + " " + e.lastName.val
5326 return self._author
5327
5329 """
5330 XXX: Deprecated since 4.3.2, use listParents(). (See #6660)
5331 Gets the Dataset that image is in, or None.
5332 Returns None if Image is in more than one Dataset.
5333
5334 @return: Dataset
5335 @rtype: L{DatasetWrapper}
5336 """
5337
5338 try:
5339 q = """
5340 select ds from Image i join i.datasetLinks dl join dl.parent ds
5341 where i.id = %i
5342 """ % self._obj.id.val
5343 query = self._conn.getQueryService()
5344 ds = query.findByQuery(q,None)
5345 return ds and DatasetWrapper(self._conn, ds) or None
5346 except:
5347 logger.debug('on getDataset')
5348 logger.debug(traceback.format_exc())
5349 return None
5350
5352 """
5353 Gets the Project that image is in, or None. TODO: Assumes image is in only 1 Project. Why not use getAncestory()[-1]
5354 Returns None if Image is in more than one Dataset & Project.
5355
5356 @return: Project
5357 @rtype: L{ProjectWrapper}
5358 """
5359
5360 try:
5361 q = """
5362 select p from Image i join i.datasetLinks dl join dl.parent ds join ds.projectLinks pl join pl.parent p
5363 where i.id = %i
5364 """ % self._obj.id.val
5365 query = self._conn.getQueryService()
5366 prj = query.findByQuery(q,None)
5367 return prj and ProjectWrapper(self._conn, prj) or None
5368 except:
5369 logger.debug('on getProject')
5370 logger.debug(traceback.format_exc())
5371 return None
5372
5374 """
5375 Gets the Ojbective Settings of the Image, or None
5376
5377 @return: Objective Settings
5378 @rtype: L{ObjectiveSettingsWrapper}
5379 """
5380
5381 rv = self.objectiveSettings
5382 if self.objectiveSettings is not None:
5383 rv = ObjectiveSettingsWrapper(self._conn, self.objectiveSettings)
5384 if not self.objectiveSettings.loaded:
5385 self.objectiveSettings = rv._obj
5386 return rv
5387
5389 """
5390 Gets the Imaging Environment of the Image, or None
5391
5392 @return: Imaging Environment
5393 @rtype: L{ImagingEnvironmentWrapper}
5394 """
5395
5396 rv = self.imagingEnvironment
5397 if self.imagingEnvironment is not None:
5398 rv = ImagingEnvironmentWrapper(self._conn, self.imagingEnvironment)
5399 if not self.imagingEnvironment.loaded:
5400 self.imagingEnvironment = rv._obj
5401 return rv
5402
5403 @assert_pixels
5405 """
5406 Returns the Primary Pixels ID for the image.
5407
5408 @return: Pixels ID
5409 @rtype: Long
5410 """
5411
5412 return self._obj.getPrimaryPixels().getId().val
5413
5415 """
5416 Prepares Thumbnail Store for the image.
5417
5418 @param _r: If True, don't reset default rendering (return None if no rDef exists)
5419 @type _r: Boolean
5420 @return: Thumbnail Store or None
5421 @rtype: L{ProxyObjectWrapper}
5422 """
5423
5424 pid = self.getPrimaryPixels().id
5425 tb = self._conn.createThumbnailStore()
5426 rdid = self._getRDef(pid)
5427 has_rendering_settings = tb.setPixelsId(pid)
5428 if rdid is None:
5429 if not has_rendering_settings:
5430 try:
5431 tb.resetDefaults()
5432 except omero.ConcurrencyException, ce:
5433 logger.info( "ConcurrencyException: resetDefaults() failed in _prepareTB with backOff: %s" % ce.backOff)
5434 return tb
5435 tb.setPixelsId(pid)
5436 try:
5437 rdid = tb.getRenderingDefId()
5438 except omero.ApiUsageException:
5439 logger.info( "ApiUsageException: getRenderingDefId() failed in _prepareTB")
5440 return tb
5441 self._onResetDefaults(pid, rdid)
5442 else:
5443 tb.setRenderingDefId(rdid)
5444 return tb
5445
5483
5484 @assert_re()
5486 """
5487 Returns a string holding a rendered JPEG of the projected image, sized to mimic a thumbnail.
5488 This is an 'internal' method of this class, used to generate a thumbnail from a full-sized
5489 projected image (since thumbnails don't support projection). SetProjection should be called
5490 before this method is called, so that this returns a projected, scaled image.
5491
5492 @param size: The length of the longest size, in a list or tuple. E.g. (100,)
5493 @type size: list or tuple
5494 @param pos: The (z, t) position
5495 @type pos: Tuple (z,t)
5496 """
5497
5498 if pos is None:
5499 t = z = 0
5500 else:
5501 z, t = pos
5502 img = self.renderImage(z,t)
5503 if len(size) == 1:
5504 w = self.getSizeX()
5505 h = self.getSizeY()
5506 ratio = float(w) / h
5507 if ratio > 1:
5508 h = h * size[0] / w
5509 w = size[0]
5510 else:
5511 w = w * size[0] / h
5512 h = size[0]
5513 img = img.resize((w,h), Image.NEAREST)
5514 rv = StringIO()
5515 img.save(rv, 'jpeg', quality=70)
5516 return rv.getvalue()
5517
5519 """
5520 Returns a string holding a rendered JPEG of the thumbnail.
5521
5522 @type size: tuple or number
5523 @param size: A tuple with one or two ints, or an integer. If a tuple holding a single int,
5524 or a single int is passed as param, then that will be used as the longest size
5525 on the rendered thumb, and image aspect ratio is kept.
5526 If two ints are passed in a tuple, they set the width and height of the
5527 rendered thumb.
5528 @type z: number
5529 @param z: the Z position to use for rendering the thumbnail. If not provided default is used.
5530 @type t: number
5531 @param t: the T position to use for rendering the thumbnail. If not provided default is used.
5532 @rtype: string or None
5533 @return: the rendered JPEG, or None if there was an error.
5534 """
5535 tb = None
5536 try:
5537 tb = self._prepareTB()
5538 if tb is None:
5539 return None
5540 if isinstance(size, IntType):
5541 size = (size,)
5542 if z is not None and t is not None:
5543 pos = z,t
5544 else:
5545 pos = None
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561 if self.getProjection() != 'normal':
5562 return self._getProjectedThumbnail(size, pos)
5563 if len(size) == 1:
5564 if pos is None:
5565 thumb = tb.getThumbnailByLongestSideDirect
5566 else:
5567 thumb = tb.getThumbnailForSectionByLongestSideDirect
5568 else:
5569 if pos is None:
5570 thumb = tb.getThumbnailDirect
5571 else:
5572 thumb = tb.getThumbnailForSectionDirect
5573 args = map(lambda x: rint(x), size)
5574 if pos is not None:
5575 args = list(pos) + args
5576 rv = thumb(*args)
5577 tb.close()
5578 return rv
5579 except Exception:
5580 logger.error(traceback.format_exc())
5581 if tb is not None:
5582 tb.close()
5583 return None
5584
5585 @assert_pixels
5587 """
5588 Returns (min, max) values for the pixels type of this image.
5589 TODO: Does not handle floats correctly, though.
5590
5591 @return: Tuple (min, max)
5592 """
5593
5594 pixels_id = self._obj.getPrimaryPixels().getId().val
5595 rp = self._conn.createRawPixelsStore()
5596 rp.setPixelsId(pixels_id, True)
5597 pmax = 2 ** (8 * rp.getByteWidth())
5598 if rp.isSigned():
5599 return (-(pmax / 2), pmax / 2 - 1)
5600 else:
5601 return (0, pmax-1)
5602
5603 @assert_pixels
5605 """
5606 Loads pixels and returns object in a L{PixelsWrapper}
5607 """
5608 return PixelsWrapper(self._conn, self._obj.getPrimaryPixels())
5609
5610 @assert_re(ignoreExceptions=(omero.ConcurrencyException))
5612 """
5613 Returns a list of Channels, each initialised with rendering engine
5614
5615 @return: Channels
5616 @rtype: List of L{ChannelWrapper}
5617 """
5618 if self._re is not None:
5619 return [ChannelWrapper(self._conn, c, idx=n, re=self._re, img=self) for n,c in enumerate(self._re.getPixels().iterateChannels())]
5620 else:
5621 pid = self.getPixelsId()
5622 params = omero.sys.Parameters()
5623 params.map = {"pid": rlong(pid)}
5624 query = "select p from Pixels p join fetch p.channels as c join fetch c.logicalChannel as lc where p.id=:pid"
5625 pixels = self._conn.getQueryService().findByQuery(query, params)
5626 return [ChannelWrapper(self._conn, c, idx=n, re=self._re, img=self) for n,c in enumerate(pixels.iterateChannels())]
5627
5629 """
5630 Sets the active channels on the rendering engine.
5631 Also sets rendering windows and channel colors (for channels that are active)
5632
5633 @param channels: List of active channel indexes ** 1-based index **
5634 @type channels: List of int
5635 @param windows: Start and stop values for active channel rendering settings
5636 @type windows: List of tuples. [(20, 300), (None, None), (50, 500)]. Must be tuples for all channels
5637 @param colors: List of colors. ['F00', None, '00FF00']. Must be item for each channel
5638 """
5639
5640 for c in range(len(self.getChannels())):
5641 self._re.setActive(c, (c+1) in channels)
5642 if (c+1) in channels:
5643 if windows is not None and windows[c][0] is not None and windows[c][1] is not None:
5644 self._re.setChannelWindow(c, *windows[c])
5645 if colors is not None and colors[c]:
5646 rgba = splitHTMLColor(colors[c])
5647 if rgba:
5648 self._re.setRGBA(c, *rgba)
5649 return True
5650
5652 """
5653 Returns list of available keys for projection. E.g. ['intmax', 'intmean']
5654
5655 @return: Projection options
5656 @rtype: List of strings
5657 """
5658
5659 return self.PROJECTIONS.keys()
5660
5662 """
5663 Returns the current projection option (checking it is valid).
5664
5665 @return: Projection key. E.g. 'intmax'
5666 @rtype: String
5667 """
5668
5669 if self._pr in self.PROJECTIONS.keys():
5670 return self._pr
5671 return 'normal'
5672
5674 """
5675 Sets the current projection option.
5676
5677 @param proj: Projection Option. E.g. 'intmax' or 'normal'
5678 @type proj: String
5679 """
5680
5681 self._pr = proj
5682
5684 """
5685 Returns the inverted axis flag
5686
5687 @return: Inverted Axis
5688 @rtype: Boolean
5689 """
5690
5691 return self._invertedAxis
5692
5694 """
5695 Sets the inverted axis flag
5696
5697 @param inverted: Inverted Axis
5698 @type inverted: Boolean
5699 """
5700
5701 self._invertedAxis = inverted
5702
5703 LINE_PLOT_DTYPES = {
5704 (4, True, True): 'f',
5705 (2, False, False): 'H',
5706 (2, False, True): 'h',
5707 (1, False, False): 'B',
5708 (1, False, True): 'b',
5709 }
5710
5711 - def getPixelLine (self, z, t, pos, axis, channels=None, range=None):
5712 """
5713 Grab a horizontal or vertical line from the image pixel data, for the specified channels
5714 (or 'active' if not specified) and using the specified range (or 1:1 relative to the image size).
5715 Axis may be 'h' or 'v', for horizontal or vertical respectively.
5716
5717 @param z: Z index
5718 @param t: T index
5719 @param pos: X or Y position
5720 @param axis: Axis 'h' or 'v'
5721 @param channels: map of {index: L{ChannelWrapper} }
5722 @param range: height of scale (use image height (or width) by default)
5723 @return: rv List of lists (one per channel)
5724 """
5725
5726 if not self._loadPixels():
5727 logger.debug( "No pixels!")
5728 return None
5729 axis = axis.lower()[:1]
5730 if channels is None:
5731 channels = map(lambda x: x._idx, filter(lambda x: x.isActive(), self.getChannels()))
5732 if range is None:
5733 range = axis == 'h' and self.getSizeY() or self.getSizeX()
5734 if not isinstance(channels, (TupleType, ListType)):
5735 channels = (channels,)
5736 chw = map(lambda x: (x.getWindowMin(), x.getWindowMax()), self.getChannels())
5737 rv = []
5738 pixels_id = self._obj.getPrimaryPixels().getId().val
5739 rp = self._conn.createRawPixelsStore()
5740 rp.setPixelsId(pixels_id, True)
5741 for c in channels:
5742 bw = rp.getByteWidth()
5743 key = self.LINE_PLOT_DTYPES.get((bw, rp.isFloat(), rp.isSigned()), None)
5744 if key is None:
5745 logger.error("Unknown data type: " + str((bw, rp.isFloat(), rp.isSigned())))
5746 plot = array.array(key, axis == 'h' and rp.getRow(pos, z, c, t) or rp.getCol(pos, z, c, t))
5747 plot.byteswap()
5748
5749 offset = -chw[c][0]
5750 if offset != 0:
5751 plot = map(lambda x: x+offset, plot)
5752 normalize = 1.0/chw[c][1]*(range-1)
5753 if normalize != 1.0:
5754 plot = map(lambda x: x*normalize, plot)
5755 if isinstance(plot, array.array):
5756 plot = plot.tolist()
5757 rv.append(plot)
5758 return rv
5759
5760
5761 - def getRow (self, z, t, y, channels=None, range=None):
5762 """
5763 Grab a horizontal line from the image pixel data, for the specified channels (or active ones)
5764
5765 @param z: Z index
5766 @param t: T index
5767 @param y: Y position of row
5768 @param channels: map of {index: L{ChannelWrapper} }
5769 @param range: height of scale (use image height by default)
5770 @return: rv List of lists (one per channel)
5771 """
5772
5773 return self.getPixelLine(z,t,y,'h',channels,range)
5774
5775 - def getCol (self, z, t, x, channels=None, range=None):
5776 """
5777 Grab a horizontal line from the image pixel data, for the specified channels (or active ones)
5778
5779 @param z: Z index
5780 @param t: T index
5781 @param x: X position of column
5782 @param channels: map of {index: L{ChannelWrapper} }
5783 @param range: height of scale (use image width by default)
5784 @return: rv List of lists (one per channel)
5785 """
5786
5787 return self.getPixelLine(z,t,x,'v',channels,range)
5788
5789 @assert_re()
5791 """
5792 Gets a list of available rendering models.
5793
5794 @return: Rendering models
5795 @rtype: List of L{BlitzObjectWrapper}
5796 """
5797
5798 if not len(self._rm):
5799 for m in [BlitzObjectWrapper(self._conn, m) for m in self._re.getAvailableModels()]:
5800 self._rm[m.value.lower()] = m
5801 return self._rm.values()
5802
5803 @assert_re()
5805 """
5806 Get the current rendering model.
5807
5808 @return: Rendering model
5809 @rtype: L{BlitzObjectWrapper}
5810 """
5811
5812 return BlitzObjectWrapper(self._conn, self._re.getModel())
5813
5815 """
5816 Sets the Greyscale rendering model on this image's current renderer
5817 """
5818
5819 rm = self.getRenderingModels()
5820 self._re.setModel(self._rm.get('greyscale', rm[0])._obj)
5821
5823 """
5824 Sets the HSB rendering model on this image's current renderer
5825 """
5826
5827 rm = self.getRenderingModels()
5828 self._re.setModel(self._rm.get('rgb', rm[0])._obj)
5829
5831 """
5832 Returns True if the current rendering model is 'greyscale'
5833
5834 @return: isGreyscale
5835 @rtype: Boolean
5836 """
5837 return self.getRenderingModel().value.lower() == 'greyscale'
5838
5839 @assert_re()
5841 """
5842 Returns the data from rendering the bird's eye view of the image.
5843
5844 @param size: Maximum size of the longest side of the resulting bird's eye view.
5845 @return: Data containing a bird's eye view jpeg
5846 """
5847
5848 re = self._prepareRE()
5849 z = re.getDefaultZ()
5850 t = re.getDefaultT()
5851 x = 0
5852 y = 0
5853 size_x = self.getSizeX()
5854 size_y = self.getSizeY()
5855 tile_width, tile_height = re.getTileSize()
5856 tiles_wide = math.ceil(float(size_x) / tile_width)
5857 tiles_high = math.ceil(float(size_y) / tile_height)
5858
5859
5860
5861
5862
5863 for i in range(1, re.getResolutionLevels()):
5864 tile_width = round(tile_width / 2.0)
5865 tile_height = round(tile_height / 2.0)
5866 width = int(tiles_wide * tile_width)
5867 height = int(tiles_high * tile_height)
5868 jpeg_data = self.renderJpegRegion(z, t, x, y, width, height, level=0)
5869 if size is None:
5870 return jpeg_data
5871
5872
5873
5874 ratio = float(size) / max(width, height)
5875 if width > height:
5876 size = (int(size), int(height * ratio))
5877 else:
5878 size = (int(width * ratio), int(size))
5879 jpeg_data = Image.open(StringIO(jpeg_data))
5880 jpeg_data.thumbnail(size, Image.ANTIALIAS)
5881 ImageDraw.Draw(jpeg_data)
5882 f = StringIO()
5883 jpeg_data.save(f, "JPEG")
5884 f.seek(0)
5885 return f.read()
5886
5887 @assert_re()
5888 - def renderJpegRegion (self, z, t, x, y, width, height, level=None, compression=0.9):
5889 """
5890 Return the data from rendering a region of an image plane.
5891 NB. Projection not supported by the API currently.
5892
5893 @param z: The Z index. Ignored if projecting image.
5894 @param t: The T index.
5895 @param x: The x coordinate of region (int)
5896 @param y: The y coordinate of region (int)
5897 @param width: The width of region (int)
5898 @param height: The height of region (int)
5899 @param compression: Compression level for jpeg
5900 @type compression: Float
5901 """
5902
5903 self._pd.z = long(z)
5904 self._pd.t = long(t)
5905
5906 regionDef = omero.romio.RegionDef()
5907 regionDef.x = x
5908 regionDef.y = y
5909 regionDef.width = width
5910 regionDef.height = height
5911 self._pd.region = regionDef
5912 try:
5913 if level is not None:
5914 self._re.setResolutionLevel(level)
5915 if compression is not None:
5916 try:
5917 self._re.setCompressionLevel(float(compression))
5918 except omero.SecurityViolation:
5919 self._obj.clearPixels()
5920 self._obj.pixelsLoaded = False
5921 self._re = None
5922 return self.renderJpeg(z,t,None)
5923 rv = self._re.renderCompressed(self._pd)
5924 return rv
5925 except omero.InternalException:
5926 logger.debug('On renderJpegRegion');
5927 logger.debug(traceback.format_exc())
5928 return None
5929 except Ice.MemoryLimitException:
5930
5931 self._obj.clearPixels()
5932 self._obj.pixelsLoaded = False
5933 self._re = None
5934 raise
5935
5936
5937 @assert_re()
5939 """
5940 Return the data from rendering image, compressed (and projected).
5941 Projection (or not) is specified by calling L{setProjection} before renderJpeg.
5942
5943 @param z: The Z index. Ignored if projecting image.
5944 @param t: The T index.
5945 @param compression: Compression level for jpeg
5946 @type compression: Float
5947 """
5948
5949 self._pd.z = long(z)
5950 self._pd.t = long(t)
5951 try:
5952 if compression is not None:
5953 try:
5954 self._re.setCompressionLevel(float(compression))
5955 except omero.SecurityViolation:
5956 self._obj.clearPixels()
5957 self._obj.pixelsLoaded = False
5958 self._re = None
5959 return self.renderJpeg(z,t,None)
5960 projection = self.PROJECTIONS.get(self._pr, -1)
5961 if not isinstance(projection, omero.constants.projection.ProjectionType):
5962 rv = self._re.renderCompressed(self._pd)
5963 else:
5964 rv = self._re.renderProjectedCompressed(projection, self._pd.t, 1, 0, self.getSizeZ()-1)
5965 return rv
5966 except omero.InternalException:
5967 logger.debug('On renderJpeg');
5968 logger.debug(traceback.format_exc())
5969 return None
5970 except Ice.MemoryLimitException:
5971
5972 self._obj.clearPixels()
5973 self._obj.pixelsLoaded = False
5974 self._re = None
5975 raise
5976
5978 """
5979 Exports the OME-TIFF representation of this image.
5980
5981 @type bufsize: int or tuple
5982 @param bufsize: if 0 return a single string buffer with the whole OME-TIFF
5983 if >0 return a tuple holding total size and generator of chunks
5984 (string buffers) of bufsize bytes each
5985 @return: OME-TIFF file data
5986 @rtype: String or (size, data generator)
5987 """
5988
5989 e = self._conn.createExporter()
5990 e.addImage(self.getId())
5991 size = e.generateTiff()
5992 if bufsize==0:
5993
5994 return fileread(e, size, 65536)
5995 else:
5996
5997 return (size, fileread_gen(e, size, bufsize))
5998
6000 """
6001 Wraps text into lines that are less than a certain width (when rendered
6002 in specified font)
6003
6004 @param width: The max width to wrap text (pixels)
6005 @type width: Int
6006 @param text: The text to wrap
6007 @type text: String
6008 @param font: Font to use.
6009 @type font: E.g. PIL ImageFont
6010 @return: List of text lines
6011 @rtype: List of Strings
6012 """
6013
6014 rv = []
6015 tokens = filter(None, text.split(' '))
6016 while len(tokens) > 1:
6017 p1 = 0
6018 p2 = 1
6019 while p2 <= len(tokens) and font.getsize(' '.join(tokens[p1:p2]))[0] < width:
6020 p2 += 1
6021 rv.append(' '.join(tokens[p1:p2-1]))
6022 tokens = tokens[p2-1:]
6023 if len(tokens):
6024 rv.append(' '.join(tokens))
6025 logger.debug(rv)
6026 return rv
6027
6028 @assert_re()
6029 - def createMovie (self, outpath, zstart, zend, tstart, tend, opts=None):
6030 """
6031 Creates a movie file from this image.
6032 TODO: makemovie import is commented out in 4.2+
6033
6034 @type outpath: string
6035 @type zstart: int
6036 @type zend: int
6037 @type tstart: int
6038 @type tend: int
6039 @type opts: dict
6040 @param opts: dictionary of extra options. Currently processed options are:
6041 - watermark:string: path to image to use as watermark
6042 - slides:tuple: tuple of tuples with slides to prefix video with
6043 in format (secs:int, topline:text[, middleline:text[, bottomline:text]])
6044 - fps:int: frames per second
6045 - minsize: tuple of (minwidth, minheight, bgcolor)
6046 - format:string: one of video/mpeg or video/quicktime
6047
6048 @return: Tuple of (file-ext, format)
6049 @rtype: (String, String)
6050 """
6051 logger.warning('createMovie support is currently disabled.')
6052 logger.warning(' - see https://trac.openmicroscopy.org.uk/ome/ticket/3857')
6053 return None, None
6054 if opts is None: opts = {}
6055 slides = opts.get('slides', None)
6056 minsize = opts.get('minsize', None)
6057 w, h = self.getSizeX(), self.getSizeY()
6058 watermark = opts.get('watermark', None)
6059 if watermark:
6060 watermark = Image.open(watermark)
6061 if minsize is not None:
6062 ratio = min(float(w) / minsize[0], float(h) / minsize[1])
6063 if ratio > 1:
6064 watermark = watermark.resize(map(lambda x: x*ratio, watermark.size), Image.ANTIALIAS)
6065 ww, wh = watermark.size
6066 else:
6067 ww, wh = 0, 0
6068 if minsize is not None and (w < minsize[0] or h < minsize[1]):
6069 w = max(w, minsize[0])
6070 h = max(h, minsize[1])
6071 else:
6072 minsize = None
6073 wmpos = 0, h - wh
6074 fps = opts.get('fps', 4)
6075 def recb (*args):
6076 return self._re
6077 fsizes = (8,8,12,18,24,32,32,40,48,56,56,64)
6078 fsize = fsizes[max(min(int(w / 256)-1, len(fsizes)), 1) - 1]
6079 scalebars = (1,1,2,2,5,5,5,5,10,10,10,10)
6080 scalebar = scalebars[max(min(int(w / 256)-1, len(scalebars)), 1) - 1]
6081 font = ImageFont.load('%s/pilfonts/B%0.2d.pil' % (THISPATH, fsize) )
6082 def introcb (pixels, commandArgs):
6083 for t in slides:
6084 slide = Image.new("RGBA", (w,h))
6085 for i, line in enumerate(t[1:4]):
6086 line = line.decode('utf8').encode('iso8859-1')
6087 wwline = self._wordwrap(w, line, font)
6088 for j, line in enumerate(wwline):
6089 tsize = font.getsize(line)
6090 draw = ImageDraw.Draw(slide)
6091 if i == 0:
6092 y = 10+j*tsize[1]
6093 elif i == 1:
6094 y = h / 2 - ((len(wwline)-j)*tsize[1]) + (len(wwline)*tsize[1])/2
6095 else:
6096 y = h - (len(wwline) - j)*tsize[1] - 10
6097 draw.text((w/2-tsize[0]/2,y), line, font=font)
6098 for i in range(t[0]*fps):
6099 yield slide
6100 if minsize is not None:
6101 bg = Image.new("RGBA", (w, h), minsize[2])
6102 ovlpos = (w-self.getSizeX()) / 2, (h-self.getSizeY()) / 2
6103 def resize (image):
6104 img = bg.copy()
6105 img.paste(image, ovlpos, image)
6106 return img
6107 else:
6108 def resize (image):
6109 return image
6110 def imgcb (z, t, pixels, image, commandArgs, frameNo):
6111 image = resize(image)
6112 if watermark:
6113 image.paste(watermark, wmpos, watermark)
6114 return image
6115 d = tempfile.mkdtemp()
6116 orig = os.getcwd()
6117 os.chdir(d)
6118 ca = makemovie.buildCommandArgs(self.getId(), scalebar=scalebar)
6119 ca['imageCB'] = imgcb
6120 if slides:
6121 ca['introCB'] = introcb
6122 ca['fps'] = fps
6123 ca['format'] = opts.get('format', 'video/quicktime')
6124 ca['zStart'] = int(zstart)
6125 ca['zEnd'] = int(zend)
6126 ca['tStart'] = int(tstart)
6127 ca['tEnd'] = int(tend)
6128 ca['font'] = font
6129 logger.debug(ca)
6130 try:
6131 fn = os.path.abspath(makemovie.buildMovie(ca, self._conn.c.getSession(), self, self.getPrimaryPixels()._obj, recb))
6132 except:
6133 logger.error(traceback.format_exc())
6134 raise
6135 os.chdir(orig)
6136 shutil.move(fn, outpath)
6137 shutil.rmtree(d)
6138 return os.path.splitext(fn)[-1], ca['format']
6139
6141 """
6142 Render the Image, (projected) and compressed.
6143 For projection, call L{setProjection} before renderImage.
6144
6145 @param z: Z index
6146 @param t: T index
6147 @compression: Image compression level
6148 @return: A PIL Image or None
6149 @rtype: PIL Image.
6150 """
6151
6152 rv = self.renderJpeg(z,t,compression)
6153 if rv is not None:
6154 i = StringIO(rv)
6155 rv = Image.open(i)
6156 return rv
6157
6159 """
6160 Prepares a jpeg representation of a 2d grid holding a render of each channel,
6161 along with one for all channels at the set Z and T points.
6162
6163 @param z: Z index
6164 @param t: T index
6165 @param compression: Image compression level
6166 @param border:
6167 @return: value
6168 """
6169
6170 img = self.renderSplitChannelImage(z,t,compression, border)
6171 rv = StringIO()
6172 img.save(rv, 'jpeg', quality=int(compression*100))
6173 return rv.getvalue()
6174
6176 """
6177 Returns a dict of layout parameters for generating split channel image.
6178 E.g. row count, column count etc. for greyscale and color layouts.
6179
6180 @param border: spacing between panels
6181 @type border: int
6182 @return: Dict of parameters
6183 @rtype: Dict
6184 """
6185
6186 c = self.getSizeC()
6187
6188 x = sqrt(c)
6189 y = int(round(x))
6190 if x > y:
6191 x = y+1
6192 else:
6193 x = y
6194 rv = {'g':{'width': self.getSizeX()*x + border*(x+1),
6195 'height': self.getSizeY()*y+border*(y+1),
6196 'border': border,
6197 'gridx': x,
6198 'gridy': y,}
6199 }
6200
6201 c += 1
6202 x = sqrt(c)
6203 y = int(round(x))
6204 if x > y:
6205 x = y+1
6206 else:
6207 x = y
6208 rv['c'] = {'width': self.getSizeX()*x + border*(x+1),
6209 'height': self.getSizeY()*y+border*(y+1),
6210 'border': border,
6211 'gridx': x,
6212 'gridy': y,}
6213 return rv
6214
6217
6219 """
6220 Prepares a PIL Image with a 2d grid holding a render of each channel,
6221 along with one for all channels at the set Z and T points.
6222
6223 @param z: Z index
6224 @param t: T index
6225 @param compression: Compression level
6226 @param border: space around each panel (int)
6227 @return: canvas
6228 @rtype: PIL Image
6229 """
6230
6231 dims = self.splitChannelDims(border=border)[self.isGreyscaleRenderingModel() and 'g' or 'c']
6232 canvas = Image.new('RGBA', (dims['width'], dims['height']), '#fff')
6233 cmap = [ch.isActive() and i+1 or 0 for i,ch in enumerate(self.getChannels())]
6234 c = self.getSizeC()
6235 pxc = 0
6236 px = dims['border']
6237 py = dims['border']
6238
6239
6240 w = self.getSizeX()
6241 if w >= 640:
6242 fsize = (int((w-640)/128)*8) + 24
6243 if fsize > 64:
6244 fsize = 64
6245 elif w >= 512:
6246 fsize = 24
6247 elif w >= 384:
6248 fsize = 18
6249 elif w >= 298:
6250 fsize = 14
6251 elif w >= 256:
6252 fsize = 12
6253 elif w >= 213:
6254 fsize = 10
6255 elif w >= 96:
6256 fsize = 8
6257 else:
6258 fsize = 0
6259 if fsize > 0:
6260 font = ImageFont.load('%s/pilfonts/B%0.2d.pil' % (THISPATH, fsize) )
6261
6262
6263 for i in range(c):
6264 if cmap[i]:
6265 self.setActiveChannels((i+1,))
6266 img = self.renderImage(z,t, compression)
6267 if fsize > 0:
6268 draw = ImageDraw.ImageDraw(img)
6269 draw.text((2,2), "%s" % (self._renderSplit_channelLabel(self.getChannels()[i])), font=font, fill="#fff")
6270 canvas.paste(img, (px, py))
6271 pxc += 1
6272 if pxc < dims['gridx']:
6273 px += self.getSizeX() + border
6274 else:
6275 pxc = 0
6276 px = border
6277 py += self.getSizeY() + border
6278 if not self.isGreyscaleRenderingModel():
6279 self.setActiveChannels(cmap)
6280 img = self.renderImage(z,t, compression)
6281 if fsize > 0:
6282 draw = ImageDraw.ImageDraw(img)
6283 draw.text((2,2), "merged", font=font, fill="#fff")
6284 canvas.paste(img, (px, py))
6285 return canvas
6286
6287 LP_PALLETE = [0,0,0,0,0,0,255,255,255]
6288 LP_TRANSPARENT = 0
6289 LP_BGCOLOR = 1
6290 LP_FGCOLOR = 2
6292 """
6293 Common part of horizontal and vertical line plot rendering.
6294
6295 @returns: (Image, width, height).
6296 """
6297 channels = filter(lambda x: x.isActive(), self.getChannels())
6298 width = self.getSizeX()
6299 height = self.getSizeY()
6300
6301 pal = list(self.LP_PALLETE)
6302
6303 for channel in channels:
6304 pal.extend(channel.getColor().getRGB())
6305
6306
6307 im = Image.new('P', (width, height))
6308 im.putpalette(pal)
6309 return im, width, height
6310
6311
6312 @assert_re()
6314 """
6315 Draws the Row plot as a gif file. Returns gif data.
6316
6317 @param z: Z index
6318 @param t: T index
6319 @param y: Y position
6320 @param linewidth: Width of plot line
6321 @return: gif data as String
6322 @rtype: String
6323 """
6324
6325 self._pd.z = long(z)
6326 self._pd.t = long(t)
6327
6328 im, width, height = self.prepareLinePlotCanvas()
6329 base = height - 1
6330
6331 draw = ImageDraw.ImageDraw(im)
6332
6333 draw.rectangle([0, 0, width-1, base], fill=self.LP_TRANSPARENT, outline=self.LP_TRANSPARENT)
6334 draw.line(((0,y),(width, y)), fill=self.LP_FGCOLOR, width=linewidth)
6335
6336
6337 rows = self.getRow(z,t,y)
6338
6339 for r in range(len(rows)):
6340 chrow = rows[r]
6341 color = r + self.LP_FGCOLOR + 1
6342 last_point = base-chrow[0]
6343 for i in range(len(chrow)):
6344 draw.line(((i, last_point), (i, base-chrow[i])), fill=color, width=linewidth)
6345 last_point = base-chrow[i]
6346 del draw
6347 out = StringIO()
6348 im.save(out, format="gif", transparency=0)
6349 return out.getvalue()
6350
6351 @assert_re()
6353 """
6354 Draws the Column plot as a gif file. Returns gif data.
6355
6356 @param z: Z index
6357 @param t: T index
6358 @param x: X position
6359 @param linewidth: Width of plot line
6360 @return: gif data as String
6361 @rtype: String
6362 """
6363
6364 self._pd.z = long(z)
6365 self._pd.t = long(t)
6366
6367 im, width, height = self.prepareLinePlotCanvas()
6368
6369 draw = ImageDraw.ImageDraw(im)
6370
6371 draw.rectangle([0, 0, width-1, height-1], fill=self.LP_TRANSPARENT, outline=self.LP_TRANSPARENT)
6372 draw.line(((x,0),(x, height)), fill=self.LP_FGCOLOR, width=linewidth)
6373
6374
6375 cols = self.getCol(z,t,x)
6376
6377 for r in range(len(cols)):
6378 chcol = cols[r]
6379 color = r + self.LP_FGCOLOR + 1
6380 last_point = chcol[0]
6381 for i in range(len(chcol)):
6382 draw.line(((last_point, i), (chcol[i], i)), fill=color, width=linewidth)
6383 last_point = chcol[i]
6384 del draw
6385 out = StringIO()
6386 im.save(out, format="gif", transparency=0)
6387 return out.getvalue()
6388
6389 @assert_re()
6391 """
6392 Returns the last used value of Z (E.g. for renderingJpeg or line plot)
6393 Returns 0 if these methods not been used yet.
6394 TODO: How to get default-Z?
6395
6396 @return: current Z index
6397 @rtype: int
6398 """
6399
6400 return self._pd.z
6401
6402 @assert_re()
6404 """
6405 Returns the last used value of T (E.g. for renderingJpeg or line plot)
6406 Returns 0 if these methods not been used yet.
6407 TODO: How to get default-T?
6408
6409 @return: current T index
6410 @rtype: int
6411 """
6412
6413 return self._pd.t
6414
6415 @assert_re()
6417 """
6418 Gets the default Z index from the rendering engine
6419 """
6420 return self._re.getDefaultZ()
6421
6422 @assert_re()
6424 """
6425 Gets the default T index from the rendering engine
6426 """
6427 return self._re.getDefaultT()
6428
6429 @assert_pixels
6431 """
6432 Gets the physical size X of pixels in microns
6433
6434 @return: Size of pixel in x or O
6435 @rtype: float
6436 """
6437 rv = self._obj.getPrimaryPixels().getPixelsType().value
6438 return rv is not None and rv.val or 'unknown'
6439
6440 @assert_pixels
6442 """
6443 Gets the physical size X of pixels in microns
6444
6445 @return: Size of pixel in x or O
6446 @rtype: float
6447 """
6448 rv = self._obj.getPrimaryPixels().getPhysicalSizeX()
6449 return rv is not None and rv.val or 0
6450
6451 @assert_pixels
6453 """
6454 Gets the physical size Y of pixels in microns
6455
6456 @return: Size of pixel in y or O
6457 @rtype: float
6458 """
6459
6460 rv = self._obj.getPrimaryPixels().getPhysicalSizeY()
6461 return rv is not None and rv.val or 0
6462
6463 @assert_pixels
6465 """
6466 Gets the physical size Z of pixels in microns
6467
6468 @return: Size of pixel in z or O
6469 @rtype: float
6470 """
6471
6472 rv = self._obj.getPrimaryPixels().getPhysicalSizeZ()
6473 return rv is not None and rv.val or 0
6474
6475 @assert_pixels
6477 """
6478 Gets width (size X) of the image (in pixels)
6479
6480 @return: width
6481 @rtype: int
6482 """
6483
6484 return self._obj.getPrimaryPixels().getSizeX().val
6485
6486 @assert_pixels
6488 """
6489 Gets height (size Y) of the image (in pixels)
6490
6491 @return: height
6492 @rtype: int
6493 """
6494
6495 return self._obj.getPrimaryPixels().getSizeY().val
6496
6497 @assert_pixels
6510
6511 @assert_pixels
6524
6525 @assert_pixels
6527 """
6528 Gets C count of the image (number of channels)
6529
6530 @return: size C
6531 @rtype: int
6532 """
6533
6534 return self._obj.getPrimaryPixels().getSizeC().val
6535
6537 """
6538 Removes specific color settings from channels
6539
6540 @return: True if allowed to do this
6541 @rtype: Boolean
6542 """
6543
6544 if not self.canWrite():
6545 return False
6546 for c in self.getChannels():
6547 c.unloadRed()
6548 c.unloadGreen()
6549 c.unloadBlue()
6550 c.unloadAlpha()
6551 c.save()
6552 self._conn.getDeleteService().deleteSettings(self.getId())
6553 return True
6554
6556 """
6557 Returns a map of rendering options not stored in rendering settings.
6558 - 'p' : projection
6559 - 'ia' : inverted axis (swap Z and T)
6560
6561 @return: Dict of render options
6562 @rtype: Dict
6563 """
6564
6565 rv = {}
6566 rv['p'] = self.getProjection()
6567 rv['ia'] = self.isInvertedAxis() and "1" or "0"
6568 return rv
6569
6571 """
6572 Loads rendering options from an Annotation on the Image.
6573
6574 @return: Dict of rendering options
6575 @rtype: Dict
6576 """
6577 ns = self._conn.CONFIG.get('IMG_ROPTSNS', None)
6578 if ns:
6579 ann = self.getAnnotation(ns)
6580 if ann is not None:
6581 opts = dict([x.split('=') for x in ann.getValue().split('&')])
6582 return opts
6583 return {}
6584
6586 """
6587 Loads rendering options from an Annotation on the Image and applies them
6588 to the Image.
6589
6590 @return: True! TODO: Always True??
6591 """
6592 opts = self._loadRenderOptions()
6593 self.setProjection(opts.get('p', None))
6594 self.setInvertedAxis(opts.get('ia', "0") == "1")
6595 return True
6596
6597 @assert_re()
6618
6630
6632 """
6633 Returns a generator of L{OriginalFileWrapper}s corresponding to the archived files linked to primary pixels
6634 """
6635
6636 pid = self.getPixelsId()
6637 params = omero.sys.Parameters()
6638 params.map = {"pid": rlong(pid)}
6639 query = "select link from PixelsOriginalFileMap link join fetch link.parent as p where link.child.id=:pid"
6640 links = self._conn.getQueryService().findAllByQuery(query, params)
6641
6642 for l in links:
6643 yield OriginalFileWrapper(self._conn, l.parent)
6644
6645 ImageWrapper = _ImageWrapper
6650 """
6651 omero_model_StageLabelI class wrapper extends BlitzObjectWrapper.
6652 """
6653 pass
6654
6655 ImageStageLabelWrapper = _ImageStageLabelWrapper
6658 """
6659 omero_model_ImagingEnvironment class wrapper extends BlitzObjectWrapper.
6660 """
6661 pass
6662
6663 ImagingEnvironmentWrapper = _ImagingEnvironmentWrapper
6666 """
6667 omero_model_ImagingEnvironmentI class wrapper extends BlitzObjectWrapper.
6668 """
6669 _attrs = ('temperature',
6670 'airPressure',
6671 'humidity',
6672 'co2percent',
6673 'version')
6674
6677
6678 ImagingEnviromentWrapper = _ImagingEnviromentWrapper
6681 """
6682 omero_model_TransmittanceRangeI class wrapper extends BlitzObjectWrapper.
6683 """
6684 _attrs = ('cutIn',
6685 'cutOut',
6686 'cutInTolerance',
6687 'cutOutTolerance',
6688 'transmittance',
6689 'version')
6690
6693
6694 TransmittanceRangeWrapper = _TransmittanceRangeWrapper
6697 """
6698 omero_model_DetectorSettingsI class wrapper extends BlitzObjectWrapper.
6699 """
6700 _attrs = ('voltage',
6701 'gain',
6702 'offsetValue',
6703 'readOutRate',
6704 'binning|BinningWrapper',
6705 'detector|DetectorWrapper',
6706 'version')
6707
6710
6711 DetectorSettingsWrapper = _DetectorSettingsWrapper
6714 """
6715 omero_model_BinningI class wrapper extends BlitzObjectWrapper.
6716 """
6717
6720
6721 BinningWrapper = _BinningWrapper
6724 """
6725 omero_model_DetectorI class wrapper extends BlitzObjectWrapper.
6726 """
6727 _attrs = ('manufacturer',
6728 'model',
6729 'serialNumber',
6730 'voltage',
6731 'gain',
6732 'offsetValue',
6733 'zoom',
6734 'amplificationGain',
6735 '#type;detectorType',
6736 'version')
6737
6740
6742 """
6743 The type of detector (enum value)
6744
6745 @return: Detector type
6746 @rtype: L{EnumerationWrapper}
6747 """
6748
6749 rv = self.type
6750 if self.type is not None:
6751 rv = EnumerationWrapper(self._conn, self.type)
6752 if not self.type.loaded:
6753 self.type = rv._obj
6754 return rv
6755
6756 DetectorWrapper = _DetectorWrapper
6759 """
6760 omero_model_ObjectiveI class wrapper extends BlitzObjectWrapper.
6761 """
6762 _attrs = ('manufacturer',
6763 'model',
6764 'serialNumber',
6765 'nominalMagnification',
6766 'calibratedMagnification',
6767 'lensNA',
6768 '#immersion',
6769 '#correction',
6770 'workingDistance',
6771 'iris',
6772 'version')
6773
6776
6778 """
6779 The type of immersion for this objective (enum value)
6780
6781 @return: Immersion type, or None
6782 @rtype: L{EnumerationWrapper}
6783 """
6784
6785 rv = self.immersion
6786 if self.immersion is not None:
6787 rv = EnumerationWrapper(self._conn, self.immersion)
6788 if not self.immersion.loaded:
6789 self.immersion = rv._obj
6790 return rv
6791
6793 """
6794 The type of Correction for this objective (enum value)
6795
6796 @return: Correction type, or None
6797 @rtype: L{EnumerationWrapper}
6798 """
6799
6800 rv = self.correction
6801 if self.correction is not None:
6802 rv = EnumerationWrapper(self._conn, self.correction)
6803 if not self.correction.loaded:
6804 self.correction = rv._obj
6805 return rv
6806
6808 """
6809 The type of Iris for this objective (enum value)
6810
6811 @return: Iris type
6812 @rtype: L{EnumerationWrapper}
6813 """
6814
6815 rv = self.iris
6816 if self.iris is not None:
6817 rv = EnumerationWrapper(self._conn, self.iris)
6818 if not self.iris.loaded:
6819 self.iris = rv._obj
6820 return rv
6821
6822 ObjectiveWrapper = _ObjectiveWrapper
6825 """
6826 omero_model_ObjectiveSettingsI class wrapper extends BlitzObjectWrapper.
6827 """
6828 _attrs = ('correctionCollar',
6829 '#medium',
6830 'refractiveIndex',
6831 'objective|ObjectiveWrapper',
6832 'version')
6833
6836
6838 """
6839 Gets the Objective that these settings refer to
6840
6841 @return: Objective
6842 @rtype: L{ObjectiveWrapper}
6843 """
6844
6845 rv = self.objective
6846 if self.objective is not None:
6847 rv = ObjectiveWrapper(self._conn, self.objective)
6848 if not self.objective.loaded:
6849 self.objective = rv._obj
6850 return rv
6851
6853 """
6854 Gets the Medium type that these settings refer to (enum value)
6855
6856 @return: Medium
6857 @rtype: L{EnumerationWrapper}
6858 """
6859
6860 rv = self.medium
6861 if self.medium is not None:
6862 rv = EnumerationWrapper(self._conn, self.medium)
6863 if not self.medium.loaded:
6864 self.medium = rv._obj
6865 return rv
6866
6867 ObjectiveSettingsWrapper = _ObjectiveSettingsWrapper
6871 """
6872 omero_model_FilterI class wrapper extends BlitzObjectWrapper.
6873 """
6874 _attrs = ('manufacturer',
6875 'model',
6876 'lotNumber',
6877 'filterWheel',
6878 '#type;filterType',
6879 'transmittanceRange|TransmittanceRangeWrapper',
6880 'version')
6881
6884
6886 """
6887 Gets the Filter type for this filter (enum value)
6888
6889 @return: Filter type
6890 @rtype: L{EnumerationWrapper}
6891 """
6892
6893 rv = self.type
6894 if self.type is not None:
6895 rv = EnumerationWrapper(self._conn, self.type)
6896 if not self.type.loaded:
6897 self.type = rv._obj
6898 return rv
6899
6900 FilterWrapper = _FilterWrapper
6903 """
6904 omero_model_DichroicI class wrapper extends BlitzObjectWrapper.
6905 """
6906 _attrs = ('manufacturer',
6907 'model',
6908 'lotNumber',
6909 'version')
6910
6913
6914 DichroicWrapper = _DichroicWrapper
6917 """
6918 omero_model_FilterSetI class wrapper extends BlitzObjectWrapper.
6919 """
6920 _attrs = ('manufacturer',
6921 'model',
6922 'lotNumber',
6923 'dichroic|DichroicWrapper',
6924 'version')
6925
6928
6930 """ TODO: not implemented """
6931 pass
6932
6934 """ TODO: not implemented """
6935 pass
6936
6937 FilterSetWrapper = _FilterSetWrapper
6940 """
6941 omero_model_OTFI class wrapper extends BlitzObjectWrapper.
6942 """
6943 _attrs = ('sizeX',
6944 'sizeY',
6945 'opticalAxisAveraged'
6946 'pixelsType',
6947 'path',
6948 'filterSet|FilterSetWrapper',
6949 'objective|ObjectiveWrapper',
6950 'version')
6951
6954
6955 OTFWrapper = _OTFWrapper
6958 """
6959 base Light Source class wrapper, extends BlitzObjectWrapper.
6960 """
6961 _attrs = ('attenuation',
6962 'wavelength',
6963
6964 'microbeamManipulation',
6965 'version')
6966
6969
6971 if self._obj.lightSource is None:
6972 return None
6973 if not self._obj.lightSource.isLoaded():
6974 lid = self._obj.lightSource.id.val
6975 params = omero.sys.Parameters()
6976 params.map = {"id": rlong(lid)}
6977 query = "select l from Laser as l left outer join fetch l.type " \
6978 "left outer join fetch l.laserMedium " \
6979 "left outer join fetch l.pulse as pulse " \
6980 "left outer join fetch l.pump as pump " \
6981 "left outer join fetch pump.type as pt " \
6982 "where l.id = :id"
6983 self._obj.lightSource = self._conn.getQueryService().findByQuery(query, params)
6984 return LightSourceWrapper(self._conn, self._obj.lightSource)
6985
6986 LightSettingsWrapper = _LightSettingsWrapper
6989 """
6990 base Light Source class wrapper, extends BlitzObjectWrapper.
6991 """
6992 _attrs = ('manufacturer',
6993 'model',
6994 'power',
6995 'serialNumber',
6996 '#type;lightSourceType',
6997 'version')
6998
7000 """
7001 Gets the Light Source type for this light source (enum value)
7002
7003 @return: Light Source type
7004 @rtype: L{EnumerationWrapper}
7005 """
7006
7007 rv = self.type
7008 if self.type is not None:
7009 rv = EnumerationWrapper(self._conn, self.type)
7010 if not self.type.loaded:
7011 self.type = rv._obj
7012 return rv
7013
7014
7015 _LightSourceClasses = {}
7017 """
7018 Creates wrapper instances for omero.model light source objects
7019
7020 @param conn: L{BlitzGateway} connection
7021 @param obj: omero.model object
7022 @return: L{_LightSourceWrapper} subclass
7023 """
7024 for k, v in _LightSourceClasses.items():
7025 if isinstance(obj, k):
7026 return getattr(omero.gateway, v)(conn, obj, **kwargs)
7027 return None
7028
7030 """
7031 omero_model_FilamentI class wrapper extends LightSourceWrapper.
7032 """
7033
7037
7038 FilamentWrapper = _FilamentWrapper
7039 _LightSourceClasses[omero.model.FilamentI] = 'FilamentWrapper'
7042 """
7043 omero_model_ArcI class wrapper extends FilamentWrapper.
7044 """
7048
7049 ArcWrapper = _ArcWrapper
7050 _LightSourceClasses[omero.model.ArcI] = 'ArcWrapper'
7053 """
7054 omero_model_LaserI class wrapper extends LightSourceWrapper.
7055 """
7057 super(_LaserWrapper, self).__bstrap__()
7058 self.OMERO_CLASS = 'Laser'
7059 self._attrs += (
7060 '#laserMedium',
7061 'frequencyMultiplication',
7062 'tuneable',
7063 'pulse',
7064 'wavelength',
7065 'pockelCell',
7066 'pump',
7067 'repetitionRate')
7068
7070 """
7071 Gets the laser medium type for this Laser (enum value)
7072
7073 @return: Laser medium type
7074 @rtype: L{EnumerationWrapper}
7075 """
7076
7077 rv = self.laserMedium
7078 if self.laserMedium is not None:
7079 rv = EnumerationWrapper(self._conn, self.laserMedium)
7080 if not self.laserMedium.loaded:
7081 self.laserMedium = rv._obj
7082 return rv
7083
7084 LaserWrapper = _LaserWrapper
7085 _LightSourceClasses[omero.model.LaserI] = 'LaserWrapper'
7088 """
7089 omero_model_LightEmittingDiodeI class wrapper extends LightSourceWrapper.
7090 """
7094
7095 LightEmittingDiodeWrapper = _LightEmittingDiodeWrapper
7096 _LightSourceClasses[omero.model.LightEmittingDiodeI] = 'LightEmittingDiodeWrapper'
7099 """
7100 omero_model_MicroscopeI class wrapper extends BlitzObjectWrapper.
7101 """
7102 _attrs = ('manufacturer',
7103 'model',
7104 'serialNumber',
7105 '#type;microscopeType',
7106 'version')
7107
7110
7112 """
7113 Returns the 'type' of microscope this is.
7114
7115 @return: Microscope type.
7116 @rtype: L{EnumerationWrapper}
7117 """
7118
7119 rv = self.type
7120 if self.type is not None:
7121 rv = EnumerationWrapper(self._conn, self.type)
7122 if not self.type.loaded:
7123 self.type = rv._obj
7124 return rv
7125
7126 MicroscopeWrapper = _MicroscopeWrapper
7129 """
7130 omero_model_InstrumentI class wrapper extends BlitzObjectWrapper.
7131 """
7132
7133
7134
7135 _attrs = ('microscope|MicroscopeWrapper',)
7136
7139
7141 """
7142 Returns the microscope component of the Instrument.
7143
7144 @return: Microscope
7145 @rtype: omero.model.Microscope
7146 """
7147
7148 if self._obj.microscope is not None:
7149 return MicroscopeWrapper(self._conn, self._obj.microscope)
7150 return None
7151
7153 """
7154 Gets the Instrument detectors.
7155
7156 @return: List of Detectors
7157 @rtype: L{DetectorWrapper} list
7158 """
7159
7160 return [DetectorWrapper(self._conn, x) for x in self._detectorSeq]
7161
7163 """
7164 Gets the Instrument Objectives.
7165
7166 @return: List of Objectives
7167 @rtype: L{ObjectiveWrapper} list
7168 """
7169
7170 return [ObjectiveWrapper(self._conn, x) for x in self._objectiveSeq]
7171
7173 """
7174 Gets the Instrument Filters.
7175
7176 @return: List of Filters
7177 @rtype: L{FilterWrapper} list
7178 """
7179
7180 return [FilterWrapper(self._conn, x) for x in self._filterSeq]
7181
7183 """
7184 Gets the Instrument Dichroics.
7185
7186 @return: List of Dichroics
7187 @rtype: L{DichroicWrapper} list
7188 """
7189
7190 return [DichroicWrapper(self._conn, x) for x in self._dichroicSeq]
7191
7193 """
7194 Gets the Instrument FilterSets.
7195
7196 @return: List of FilterSets
7197 @rtype: L{FilterSetWrapper} list
7198 """
7199
7200 return [FilterSetWrapper(self._conn, x) for x in self._filterSetSeq]
7201
7203 """
7204 Gets the Instrument OTFs.
7205
7206 @return: List of OTFs
7207 @rtype: L{OTFWrapper} list
7208 """
7209
7210 return [OTFWrapper(self._conn, x) for x in self._otfSeq]
7211
7213 """
7214 Gets the Instrument LightSources.
7215
7216 @return: List of LightSources
7217 @rtype: L{LightSourceWrapper} list
7218 """
7219
7220 return [LightSourceWrapper(self._conn, x) for x in self._lightSourceSeq]
7221
7222
7236
7237 InstrumentWrapper = _InstrumentWrapper
7238
7239 KNOWN_WRAPPERS = {}
7242 """
7243 this needs to be called by modules that extend the base wrappers
7244 """
7245 KNOWN_WRAPPERS.update({"project":ProjectWrapper,
7246 "dataset":DatasetWrapper,
7247 "image":ImageWrapper,
7248 "screen":ScreenWrapper,
7249 "plate":PlateWrapper,
7250 "well":WellWrapper,
7251 "experimenter":ExperimenterWrapper,
7252 "experimentergroup":ExperimenterGroupWrapper,
7253 "originalfile":OriginalFileWrapper,
7254 "commentannotation":CommentAnnotationWrapper,
7255 "tagannotation":TagAnnotationWrapper,
7256 "longannotation":LongAnnotationWrapper,
7257 "booleanannotation":BooleanAnnotationWrapper,
7258 "fileannotation":FileAnnotationWrapper,
7259 "doubleannotation":DoubleAnnotationWrapper,
7260 "termannotation":TermAnnotationWrapper,
7261 "timestampannotation":TimestampAnnotationWrapper,
7262 "annotation":AnnotationWrapper._wrap})
7263
7264 refreshWrappers()
7265