1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import logging
25 import os,sys
26 THISPATH = os.path.dirname(os.path.abspath(__file__))
27
28
29
30 from types import IntType, LongType, ListType, TupleType, UnicodeType, StringType, StringTypes
31 from datetime import datetime
32
33 import omero
34 import Ice
35 import Glacier2
36
37 import traceback
38
39 import time
40 import array
41
42 logger = logging.getLogger('blitz_gateway')
43
44 try:
45 import Image, ImageDraw, ImageFont
46 except:
47 logger.error('No PIL installed, line plots and split channel will fail!')
48 from cStringIO import StringIO
49 from math import sqrt
50 from omero.rtypes import rstring, rint, rlong, rbool, rtime
51
52 import omero_Constants_ice
53 import omero_ROMIO_ice
56 """
57 Measures the execution time of a function using time.time()
58 and the a @ function decorator.
59
60 @param func: function
61 @return: wrapped
62 """
63
64 def wrapped (*args, **kwargs):
65 logger.debug("timing %s" % (func.func_name))
66 now = time.time()
67 rv = func(*args, **kwargs)
68 logger.debug("timed %s: %f" % (func.func_name, time.time()-now))
69 return rv
70 return wrapped
71
74 """
75 Converts rtypes from static factory methods:
76 - StringType to rstring
77 - UnicodeType to rstring
78 - IntType to rint
79 - LongType to rlong
80 elswere return the argument itself
81
82 @param val: value
83 @return: matched RType or value
84 """
85
86 if isinstance(val, StringType):
87 return rstring(val)
88 elif isinstance(val, UnicodeType):
89 return rstring(val.encode('utf-8'))
90 elif isinstance(val, IntType):
91 return rint(val)
92 elif isinstance(val, LongType):
93 return rlong(val)
94 else:
95 return val
96
100 raise Ice.ConnectionLostException
101
103 """
104 ICE_CONFIG - Defines the path to the Ice configuration
105 """
106
107 ICE_CONFIG = None
108
109
110 - def __init__ (self, username=None, passwd=None, client_obj=None, group=None, clone=False, try_super=False, host=None, port=None, extra_config=[]):
111 """
112 TODO: Constructor
113
114 @param username: User name. String
115 @param passwd: Password. String
116 @param client_obj: omero.client
117 @param group: admin group
118 @param clone: Boolean
119 @param try_super: Boolean
120 @param host: Omero server host. String
121 @param port: Omero server port. Integer
122 @param extra_config:
123 """
124
125 super(_BlitzGateway, self).__init__()
126 self.client = client_obj
127 if not type(extra_config) in (type(()), type([])):
128 extra_config=[extra_config]
129 self.extra_config = extra_config
130 self.ice_config = [self.ICE_CONFIG]
131 self.ice_config.extend(extra_config)
132 self.ice_config = map(lambda x: str(x), filter(None, self.ice_config))
133
134 self.host = host
135 self.port = port
136
137 self._resetOmeroClient()
138 if not username:
139 username = self.c.ic.getProperties().getProperty('weblitz.anon_user')
140 passwd = self.c.ic.getProperties().getProperty('weblitz.anon_pass')
141 if try_super:
142 if not group:
143 group = self.c.ic.getProperties().getProperty('weblitz.admin_group')
144 self.group = group and group or None
145 else:
146 self.group = None
147 self._sessionUuid = None
148 self._session_cb = None
149 self._session = None
150 self._lastGroup = None
151 self._anonymous = True
152
153
154 self.setIdentity(username, passwd, not clone)
155
156 self._connected = False
157 self._user = None
158 self._userid = None
159 self._proxies = NoProxies()
160
163
165 return self.__class__(self._ic_props[omero.constants.USERNAME],
166 self._ic_props[omero.constants.PASSWORD],
167 extra_config=self.extra_config,
168 clone=True)
169
170
171 - def setIdentity (self, username, passwd, _internal=False):
172 """
173 TODO: description
174
175 @param username: User name. String
176 @param passwd: Password. String
177 @param _internal: Boolean
178 """
179
180 self._ic_props = {omero.constants.USERNAME: username,
181 omero.constants.PASSWORD: passwd}
182 self._anonymous = _internal
183
185 """
186 Keeps service alive.
187 Returns True if connected. If connection was lost, reconnecting.
188
189 @return: Boolean
190 """
191
192 try:
193 logger.debug('connected? %s' % str(self._connected))
194 logger.debug('... sending keepalive to %s' % self._proxies['admin']._obj)
195 if self.c.sf is None:
196 logger.debug('... c.sf is None, reconnecting')
197 return self.connect()
198 return self.c.sf.keepAlive(self._proxies['admin']._obj)
199 except Ice.ObjectNotExistException:
200
201 logger.debug(traceback.format_exc())
202 logger.debug("... reset, not reconnecting")
203 return False
204 except Ice.ConnectionLostException:
205
206 logger.debug(traceback.format_exc())
207 logger.debug("... lost, reconnecting")
208 return self.connect()
209 except Ice.ConnectionRefusedException:
210
211 logger.debug(traceback.format_exc())
212 logger.debug("... refused, not reconnecting")
213 return False
214 except omero.RemovedSessionException:
215
216 logger.debug(traceback.format_exc())
217 logger.debug("... session has left the building, not reconnecting")
218 return False
219 except Ice.UnknownException, x:
220
221 logger.debug(traceback.format_exc())
222 logger.debug('Ice.UnknownException: %s' % str(x))
223 logger.debug("... ice says something bad happened, not reconnecting")
224 return False
225
226 - def seppuku (self, softclose=False):
227 """
228 Terminates connection. If softclose is False, the session is really
229 terminate disregarding its connection refcount.
230
231 @param softclose: Boolean
232 """
233
234 self._connected = False
235 if self.c:
236 try:
237 self.c.sf.closeOnDestroy()
238 except Ice.ConnectionLostException:
239 pass
240 except omero.Glacier2.SessionNotExistException:
241 pass
242 except AttributeError:
243 pass
244 try:
245 if softclose:
246 try:
247 r = self.c.sf.getSessionService().getReferenceCount(self._sessionUuid)
248 self.c.closeSession()
249 if r < 2:
250 self._session_cb and self._session_cb.close(self)
251 except Ice.OperationNotExistException:
252 self.c.closeSession()
253 else:
254 self._closeSession()
255 except omero.Glacier2.SessionNotExistException:
256 pass
257 except Ice.ConnectionLostException:
258 pass
259 self.c = None
260 self._proxies = NoProxies()
261 logger.info("closed connecion (uuid=%s)" % str(self._sessionUuid))
262
264 logger.debug("##GARBAGE COLLECTOR KICK IN")
265
267 """
268 Creates proxies to the server services.
269 """
270
271 if not isinstance(self._proxies, NoProxies):
272 logger.debug("## Reusing proxies")
273 for k, p in self._proxies.items():
274 p._resyncConn(self)
275 else:
276 logger.debug("## Creating proxies")
277 self._proxies = {}
278 self._proxies['admin'] = ProxyObjectWrapper(self, 'getAdminService')
279 self._proxies['query'] = ProxyObjectWrapper(self, 'getQueryService')
280 self._proxies['rendering'] = ProxyObjectWrapper(self, 'createRenderingEngine')
281 self._proxies['rendsettings'] = ProxyObjectWrapper(self, 'getRenderingSettingsService')
282
283 self._proxies['rawpixels'] = ProxyObjectWrapper(self, 'createRawPixelsStore')
284 self._proxies['thumbs'] = ProxyObjectWrapper(self, 'createThumbnailStore')
285 self._proxies['container'] = ProxyObjectWrapper(self, 'getContainerService')
286 self._proxies['pixel'] = ProxyObjectWrapper(self, 'getPixelsService')
287
288 self._proxies['metadata'] = ProxyObjectWrapper(self, 'getMetadataService')
289 self._proxies['rawfile'] = ProxyObjectWrapper(self, 'createRawFileStore')
290 self._proxies['repository'] = ProxyObjectWrapper(self, 'getRepositoryInfoService')
291
292
293
294 self._proxies['share'] = ProxyObjectWrapper(self, 'getShareService')
295
296 self._proxies['timeline'] = ProxyObjectWrapper(self, 'getTimelineService')
297 self._proxies['types'] = ProxyObjectWrapper(self, 'getTypesService')
298
299 self._proxies['config'] = ProxyObjectWrapper(self, 'getConfigService')
300 self._ctx = self._proxies['admin'].getEventContext()
301 self._userid = self._ctx.userId
302 self._user = self.getExperimenter(self._userid)
303 if self._session_cb:
304 if self._was_join:
305 self._session_cb.join(self)
306 else:
307 self._session_cb.create(self)
308
325
327 """
328 Close session.
329 """
330
331 self._session_cb and self._session_cb.close(self)
332 if self._sessionUuid:
333 s = omero.model.SessionI()
334 s._uuid = omero_type(self._sessionUuid)
335 try:
336 r = 1
337 while r:
338 r = self.c.sf.getSessionService().closeSession(s)
339 except Ice.ObjectNotExistException:
340 pass
341 except omero.RemovedSessionException:
342 pass
343 except ValueError:
344 raise
345 except:
346 logger.warn(traceback.format_exc())
347 try:
348 self.c.closeSession()
349 except omero.Glacier2.SessionNotExistException:
350 pass
351
353 """
354 Resets omero.client object.
355 """
356
357 if self.host is not None:
358 logger.info('host: %s, port: %i' % (str(self.host), int(self.port)))
359 self.c = omero.client(host=str(self.host), port=int(self.port))
360 else:
361 logger.info('--Ice.Config='+','.join(self.ice_config))
362 self.c = omero.client(pmap=['--Ice.Config='+','.join(self.ice_config)])
363
365 """
366 Creates or retrieves connection for the given sessionUuid.
367 Returns True if connected.
368
369 @param sUuid: omero_model_SessionI
370 @return: Boolean
371 """
372
373 logger.debug("Connect attempt, sUuid=%s, group=%s, self.sUuid=%s" % (str(sUuid), str(self.group), self._sessionUuid))
374 if not self.c:
375 self._connected = False
376 logger.debug("Ooops. no self._c")
377 return False
378 try:
379 if self._sessionUuid is None and sUuid:
380 self._sessionUuid = sUuid
381 if self._sessionUuid is not None:
382 try:
383 logger.debug('connected? %s' % str(self._connected))
384 if self._connected:
385 self._connected = False
386 logger.debug("was connected, creating new omero.client")
387 self._resetOmeroClient()
388 logger.debug('joining session %s' % self._sessionUuid)
389 s = self.c.joinSession(self._sessionUuid)
390 logger.debug('setting detachOnDestroy for %s' % str(s))
391 s.detachOnDestroy()
392 logger.debug('joinSession(%s)' % self._sessionUuid)
393 self._was_join = True
394 except Ice.SyscallException:
395 raise
396 except Exception, x:
397 logger.debug("Error: " + str(x))
398 self._sessionUuid = None
399 if sUuid:
400 return False
401 if self._sessionUuid is None:
402 if sUuid:
403 logger.debug("Uncaptured sUuid failure!")
404 if self._connected:
405 self._connected = False
406 try:
407
408
409 self._closeSession()
410 logger.info("called closeSession()")
411 self._resetOmeroClient()
412
413 except omero.Glacier2.SessionNotExistException:
414 pass
415 setprop = self.c.ic.getProperties().setProperty
416 map(lambda x: setprop(x[0],str(x[1])), self._ic_props.items())
417 if self._anonymous:
418 self.c.ic.getImplicitContext().put(omero.constants.EVENT, 'Internal')
419 if self.group is not None:
420 self.c.ic.getImplicitContext().put(omero.constants.GROUP, self.group)
421 try:
422 logger.info("(1) calling createSession()")
423 self._createSession()
424 except omero.SecurityViolation:
425 if self.group is not None:
426
427 logger.info("## User not in '%s' group" % self.group)
428 self.group = None
429 self._closeSession()
430 self._sessionUuid = None
431 self._connected=True
432 return self.connect()
433 else:
434 logger.debug("BlitzGateway.connect().createSession(): " + traceback.format_exc())
435 logger.info('first create session threw SecurityViolation, hold off 10 secs and retry (but only once)')
436
437 try:
438 logger.info("(2) calling createSession()")
439 self._createSession()
440 except omero.SecurityViolation:
441 if self.group is not None:
442
443 logger.info("## User not in '%s' group" % self.group)
444 self.group = None
445 self._connected=True
446 return self.connect()
447 else:
448 raise
449 except Ice.SyscallException:
450 raise
451 except:
452 logger.info("BlitzGateway.connect().createSession(): " + traceback.format_exc())
453 logger.debug(str(self._ic_props))
454 logger.info('first create session had errors, hold off 10 secs and retry (but only once)')
455
456 logger.info("(3) calling createSession()")
457 self._createSession()
458
459 self._last_error = None
460 self._createProxies()
461 self._connected = True
462 logger.info('created connection (uuid=%s)' % str(self._sessionUuid))
463 except Ice.SyscallException:
464 logger.debug('This one is a SyscallException')
465 raise
466 except Ice.LocalException, x:
467 logger.debug("connect(): " + traceback.format_exc())
468 self._last_error = x
469 return False
470 except Exception, x:
471 logger.debug("connect(): " + traceback.format_exc())
472 self._last_error = x
473 return False
474 logger.debug(".. connected!")
475 return True
476
478 """
479 Returns error if thrown by _BlitzGateway.connect connect.
480
481 @return: String
482 """
483
484 return self._last_error
485
487 """
488 Returns last status of connection.
489
490 @return: Boolean
491 """
492
493 return self._connected
494
495
496
497
498 - def getEventContext (self):
499 """
500 Returns omero_System_ice.EventContext.
501 It containes::
502 shareId, sessionId, sessionUuid, userId, userName,
503 groupId, groupName, isAdmin, isReadOnly,
504 eventId, eventType, eventType,
505 memberOfGroups, leaderOfGroups
506
507 @return: omero.sys.EventContext
508 """
509
510 return self._ctx
511
513 """
514 Returns current omero_model_ExperimenterI.
515
516 @return: omero.model.ExperimenterI
517 """
518
519 return self._user
520
522 """
523 Checks if a user has administration privileges.
524
525 @return: Boolean
526 """
527
528 return self.getEventContext().isAdmin
529
531 """
532 Checks if a user has write privileges to the given object.
533
534 @param obj: Given object
535 @return: Boolean
536 """
537
538 return self.isAdmin() or (self._userid == obj.details.owner.id.val and obj.details.permissions.isUserWrite())
539
555
557 if self._lastGroup:
558 self.setGroupForSession(self._lastGroup)
559 self._lastGroup = None
560
561
562
563
565 """
566 Gets reference to the admin service from ProxyObjectWrapper.
567
568 @return: omero.gateway.ProxyObjectWrapper
569 """
570
571 return self._proxies['admin']
572
574 """
575 Gets reference to the query service from ProxyObjectWrapper.
576
577 @return: omero.gateway.ProxyObjectWrapper
578 """
579 return self._proxies['query']
580
582 """
583 Gets reference to the container service from ProxyObjectWrapper.
584
585 @return: omero.gateway.ProxyObjectWrapper
586 """
587
588 return self._proxies['container']
589
591 """
592 Gets reference to the pixels service from ProxyObjectWrapper.
593
594 @return: omero.gateway.ProxyObjectWrapper
595 """
596
597 return ProxyObjectWrapper(self, 'getPixelsService')
598
607
609 """
610 Creates a new raw file store.
611 This service is special in that it does not get cached inside BlitzGateway so every call to this function
612 returns a new object, avoiding unexpected inherited states.
613
614 @return: omero.gateway.ProxyObjectWrapper
615 """
616
617 return self._proxies['rawfile']
618
620 """
621 Gets reference to the repository info service from ProxyObjectWrapper.
622
623 @return: omero.gateway.ProxyObjectWrapper
624 """
625
626 return self._proxies['repository']
627
629 """
630 Gets reference to the share service from ProxyObjectWrapper.
631
632 @return: omero.gateway.ProxyObjectWrapper
633 """
634
635 return self._proxies['share']
636
638 """
639 Gets reference to the timeline service from ProxyObjectWrapper.
640
641 @return: omero.gateway.ProxyObjectWrapper
642 """
643
644 return self._proxies['timeline']
645
647 """
648 Gets reference to the types service from ProxyObjectWrapper.
649
650 @return: omero.gateway.ProxyObjectWrapper
651 """
652
653 return self._proxies['types']
654
656 """
657 Gets reference to the config service from ProxyObjectWrapper.
658
659 @return: omero.gateway.ProxyObjectWrapper
660 """
661
662 return self._proxies['config']
663
665 """
666 Creates a new rendering engine.
667 This service is special in that it does not get cached inside BlitzGateway so every call to this function
668 returns a new object, avoiding unexpected inherited states.
669
670 @return: omero.gateway.ProxyObjectWrapper
671 """
672
673 rv = self._proxies['rendering']
674 if rv._tainted:
675 rv = self._proxies['rendering'] = rv.clone()
676 rv.taint()
677 return rv
678
680 return self._proxies['rendsettings']
681
683 """
684 Creates a new raw pixels store.
685 This service is special in that it does not get cached inside BlitzGateway so every call to this function
686 returns a new object, avoiding unexpected inherited states.
687
688 @return: omero.gateway.ProxyObjectWrapper
689 """
690
691 return self._proxies['rawpixels']
692
694 """
695 Creates a new thumbnail store.
696 This service is special in that it does not get cached inside BlitzGateway so every call to this function
697 returns a new object, avoiding unexpected inherited states.
698
699 @return: omero.gateway.ProxyObjectWrapper
700 """
701
702 return self._proxies['thumbs']
703
705 """
706 Creates a new search service.
707 This service is special in that it does not get cached inside BlitzGateway so every call to this function
708 returns a new object, avoiding unexpected inherited states.
709
710 @return: omero.gateway.ProxyObjectWrapper
711 """
712 return ProxyObjectWrapper(self, 'createSearchService')
713
715 """
716 Gets reference to the update service from ProxyObjectWrapper.
717
718 @return: omero.gateway.ProxyObjectWrapper
719 """
720 return ProxyObjectWrapper(self, 'getUpdateService')
721
723 """
724 Gets reference to the delete service from ProxyObjectWrapper.
725
726 @return: omero.gateway.ProxyObjectWrapper
727 """
728 return ProxyObjectWrapper(self, 'getDeleteService')
729
731 """
732 Gets reference to the session service from ProxyObjectWrapper.
733
734 @return: omero.gateway.ProxyObjectWrapper
735 """
736 return ProxyObjectWrapper(self, 'getSessionService')
737
738
739
740
742 """
743 List every Projects controlled by the security system.
744
745 @param only_owned: Only owned by the logged user. Boolean.
746 @return: Generator yielding _ProjectWrapper
747 """
748
749 q = self.getQueryService()
750 cache = {}
751 if only_owned:
752 params = omero.sys.Parameters()
753 params.map = {'owner_id': rlong(self._userid)}
754 for e in q.findAllByQuery("from Project as p where p.details.owner.id=:owner_id order by p.name", params):
755 yield ProjectWrapper(self, e, cache)
756 else:
757 for e in q.findAll('Project', None):
758 yield ProjectWrapper(self, e, cache)
759
760
761
762
763
764
765
767 """
768 Return a generator for all Experimenters whose omeName starts with 'start'.
769 The generated values follow the alphabetic order on omeName.
770
771 @param start: Only if omero_model_ExperimenterI.omeName starts with. String.
772 @return: Generator yielding _ExperimenterWrapper
773 """
774
775 if isinstance(start, UnicodeType):
776 start = start.encode('utf8')
777 params = omero.sys.Parameters()
778 params.map = {'start': rstring('%s%%' % start.lower())}
779 q = self.getQueryService()
780 rv = q.findAllByQuery("from Experimenter e where lower(e.omeName) like :start", params)
781 rv.sort(lambda x,y: cmp(x.omeName.val,y.omeName.val))
782 for e in rv:
783 yield ExperimenterWrapper(self, e)
784
786 """
787 Return an Experimenter for the given ID.
788
789 @param eid: User ID.
790 @return: _ExperimenterWrapper or None
791 """
792
793 admin_serv = self.getAdminService()
794 try:
795 exp = admin_serv.getExperimenter(long(eid))
796 return ExperimenterWrapper(self, exp)
797 except omero.ApiUsageException:
798 return None
799
801 """
802 Return an Experimenter for the given username.
803
804 @param name: Username. String
805 @return: _ExperimenterWrapper or None
806 """
807
808 admin_serv = self.getAdminService()
809 try:
810 exp = admin_serv.lookupExperimenter(str(name))
811 return ExperimenterWrapper(self, exp)
812 except omero.ApiUsageException:
813 return None
814
815
816
817
818
820 """
821 Return Project for the given ID.
822
823 @param oid: Project ID.
824 @return: _ProjectWrapper or None
825 """
826
827 q = self.getQueryService()
828 pr = q.find("Project", long(oid))
829 if pr is not None:
830 pr = ProjectWrapper(self, pr)
831 return pr
832
834 """
835 Return Dataset for the given ID.
836
837 @param oid: Dataset ID.
838 @return: _DatasetWrapper or None
839 """
840
841 q = self.getQueryService()
842 ds = q.find("Dataset", long(oid))
843 if ds is not None:
844 ds = DatasetWrapper(self, ds)
845 return ds
846
848 """
849 Return Image for the given ID.
850
851 @param oid: Image ID.
852 @return: _ImageWrapper or None
853 """
854
855 q = self.getQueryService()
856 img = q.find("Image", long(oid))
857 if img is not None:
858 img = ImageWrapper(self, img)
859 return img
860
861
862
863
865 """
866 TODO: description
867
868 @return: Generator yielding _ImageWrapper
869 """
870
871 if not params:
872 params = omero.sys.Parameters()
873 if not params.map:
874 params.map = {}
875 params.map["ns"] = omero_type(ns)
876 query = """
877 select i
878 from Image i
879 join i.annotationLinks ial
880 join ial.child as a
881 where a.ns = :ns
882 order by a.id desc """
883 for i in self.getQueryService().findAllByQuery(query, params):
884 yield ImageWrapper(self, i)
885
886
887
888
889
890
892 """
893 Fulltext search for images
894 """
895 return self.simpleSearch(text,(ImageWrapper,))
896
897
899 """
900 Fulltext search on Projects, Datasets and Images.
901 TODO: search other object types?
902 TODO: batch support.
903 """
904 if not text:
905 return []
906 if isinstance(text, UnicodeType):
907 text = text.encode('utf8')
908 if types is None:
909 types = (ProjectWrapper, DatasetWrapper, ImageWrapper)
910 search = self.createSearchService()
911 if text[0] in ('?','*'):
912 search.setAllowLeadingWildcard(True)
913 rv = []
914 for t in types:
915 def actualSearch ():
916 search.onlyType(t().OMERO_CLASS)
917 search.byFullText(text)
918 timeit(actualSearch)()
919 if search.hasNext():
920 def searchProcessing ():
921 rv.extend(map(lambda x: t(self, x), search.results()))
922 timeit(searchProcessing)()
923 search.close()
924 return rv
925
927 """
928 Captures called function. Throws an exception.
929
930 @return:
931 """
932
933 def inner (*args, **kwargs):
934 try:
935 return f(*args, **kwargs)
936 except omero.ResourceError:
937 logger.debug('captured resource error')
938 raise
939 except omero.SecurityViolation:
940 raise
941 except omero.ApiUsageException:
942 raise
943 except Ice.MemoryLimitException:
944 raise
945 except omero.InternalException:
946 raise
947 except Ice.Exception, x:
948
949 logger.debug( "Ice.Exception (1) on safe call %s(%s,%s)" % (attr, str(args), str(kwargs)))
950 logger.debug(traceback.format_exc())
951
952 try:
953 self._obj = self._create_func()
954 func = getattr(self._obj, attr)
955 return func(*args, **kwargs)
956 except Ice.MemoryLimitException:
957 raise
958 except Ice.Exception, x:
959
960 logger.debug("Ice.Exception (2) on safe call %s(%s,%s)" % (attr, str(args), str(kwargs)))
961 logger.debug(traceback.format_exc())
962 try:
963
964 self._connect()
965 logger.debug('last try for %s' % attr)
966
967 func = getattr(self._obj, attr)
968 return func(*args, **kwargs)
969 except:
970 raise
971
972 def wrapped (*args, **kwargs):
973 try:
974 return inner(*args, **kwargs)
975 except Ice.MemoryLimitException:
976 logger.debug("MemoryLimitException! abort, abort...")
977 raise
978 except omero.SecurityViolation:
979 logger.debug("SecurityViolation, bailing out")
980 raise
981 except omero.ApiUsageException:
982 logger.debug("ApiUsageException, bailing out")
983 raise
984 except Ice.Exception, x:
985 if hasattr(x, 'serverExceptionClass'):
986 if x.serverExceptionClass == 'ome.conditions.InternalException' and \
987 x.message.find('java.lang.NullPointerException') > 0:
988 logger.debug("NullPointerException, bailing out")
989 raise
990 logger.debug("exception caught, first time we back off for 10 secs")
991 logger.debug(traceback.format_exc())
992
993 return inner(*args, **kwargs)
994 return wrapped
995
996
997 BlitzGateway = _BlitzGateway
1001 """ splits an hex stream of characters into an array of bytes in format (R,G,B,A).
1002 - abc -> (0xAA, 0xBB, 0xCC, 0xFF)
1003 - abcd -> (0xAA, 0xBB, 0xCC, 0xDD)
1004 - abbccd -> (0xAB, 0xBC, 0xCD, 0xFF)
1005 - abbccdde -> (0xAB, 0xBC, 0xCD, 0xDE)
1006 """
1007 try:
1008 out = []
1009 if len(color) in (3,4):
1010 c = color
1011 color = ''
1012 for e in c:
1013 color += e + e
1014 if len(color) == 6:
1015 color += 'FF'
1016 if len(color) == 8:
1017 for i in range(0, 8, 2):
1018 out.append(int(color[i:i+2], 16))
1019 return out
1020 except:
1021 pass
1022 return None
1023
1027 self._obj = None
1028 self._func_str = func_str
1029 self._resyncConn(conn)
1030 self._tainted = False
1031
1034
1036 """
1037 Returns True if connected.
1038
1039 @return: Boolean
1040 """
1041
1042 logger.debug("proxy_connect: a");
1043 if not self._conn.connect():
1044 logger.debug('connect failed')
1045 logger.debug('/n'.join(traceback.format_stack()))
1046 return False
1047 logger.debug("proxy_connect: b");
1048 self._resyncConn(self._conn)
1049 logger.debug("proxy_connect: c");
1050 self._obj = self._create_func()
1051 logger.debug("proxy_connect: d");
1052 return True
1053
1055 self._tainted = True
1056
1058 self._tainted = False
1059
1061 """
1062 Closes the underlaying service, so next call to the proxy will create a new
1063 instance of it.
1064 """
1065
1066 if self._obj:
1067 self._obj.close()
1068 self._obj = None
1069
1071 """
1072
1073 @param conn: Connection
1074 """
1075
1076 self._conn = conn
1077 self._sf = conn.c.sf
1078 self._create_func = getattr(self._sf, self._func_str)
1079 if self._obj is not None:
1080 try:
1081 logger.debug("## - refreshing %s" % (self._func_str))
1082 obj = conn.c.ic.stringToProxy(str(self._obj))
1083 self._obj = self._obj.checkedCast(obj)
1084 except Ice.ObjectNotExistException:
1085 self._obj = None
1086
1088 """
1089
1090 @return: obj
1091 """
1092 if not self._obj:
1093 self._obj = self._create_func()
1094 else:
1095 self._ping()
1096 return self._obj
1097
1099 """
1100 For some reason, it seems that keepAlive doesn't, so every so often I need to recreate the objects.
1101
1102 @return: Boolean
1103 """
1104
1105 try:
1106 if not self._sf.keepAlive(self._obj):
1107 logger.debug("... died, recreating ...")
1108 self._obj = self._create_func()
1109 except Ice.ObjectNotExistException:
1110
1111 logger.debug("... reset, reconnecting")
1112 self._connect()
1113 return False
1114 except Ice.ConnectionLostException:
1115
1116 logger.debug(traceback.format_stack())
1117 logger.debug("... lost, reconnecting")
1118 self._conn._connected = False
1119 self._connect()
1120 return False
1121 except Ice.ConnectionRefusedException:
1122
1123 logger.debug(traceback.format_stack())
1124 logger.debug("... refused, reconnecting")
1125 self._connect()
1126 return False
1127 except omero.RemovedSessionException:
1128
1129 logger.debug(traceback.format_stack())
1130 logger.debug("... session has left the building, reconnecting")
1131 self._connect()
1132 return False
1133 except Ice.UnknownException:
1134
1135 logger.debug(traceback.format_stack())
1136 logger.debug("... ice says something bad happened, reconnecting")
1137 self._connect()
1138 return False
1139 return True
1140
1142 """
1143
1144 @param attr: Connection
1145 @return: rv
1146 """
1147
1148 obj = self._obj or self._getObj()
1149 rv = getattr(obj, attr)
1150 if callable(rv):
1151 rv = safeCallWrap(self, attr, rv)
1152
1153 return rv
1154
1157 """
1158 Object wrapper class.
1159 """
1160
1161 OMERO_CLASS = None
1162 LINK_CLASS = None
1163 CHILD_WRAPPER_CLASS = None
1164 PARENT_WRAPPER_CLASS = None
1165
1166 - def __init__ (self, conn=None, obj=None, cache={}, **kwargs):
1167 self.__bstrap__()
1168 self._obj = obj
1169 self._cache = cache
1170 self._conn = conn
1171 if conn is None:
1172 return
1173 if hasattr(obj, 'id') and obj.id is not None:
1174 self._oid = obj.id.val
1175 if not self._obj.loaded:
1176 self._obj = self._conn.getQueryService().get(self._obj.__class__.__name__, self._oid)
1177 self.__prepare__ (**kwargs)
1178
1180 return type(a) == type(self) and self._obj.id == a._obj.id and self.getName() == a.getName()
1181
1184
1187
1192
1204
1215
1218
1220 """ moves this object from the current parent container to a new one """
1221 p = self.listParents()
1222 if type(p) == type(newParent):
1223 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)
1224 if len(link):
1225 link[0].parent = newParent._obj
1226 self._conn.getUpdateService().saveObject(link[0])
1227 return True
1228 return False
1229
1232
1235
1237 """ Save this object, keeping the object owner the same as the one on provided details """
1238 if self._conn.isAdmin():
1239 d = self.getDetails()
1240 if d.getOwner() and \
1241 d.getOwner().omeName == details.getOwner().omeName and \
1242 d.getGroup().name == details.getGroup().name:
1243 return self.save()
1244 else:
1245 p = omero.sys.Principal()
1246 p.name = details.getOwner().omeName
1247 p.group = details.getGroup().name
1248 p.eventType = "User"
1249 newConnId = self._conn.getSessionService().createSessionWithTimeout(p, 60000)
1250 newConn = self._conn.clone()
1251 newConn.connect(sUuid=newConnId.getUuid().val)
1252 clone = self.__class__(newConn, self._obj)
1253 clone.save()
1254 self._obj = clone._obj
1255 return
1256 else:
1257 return self.save()
1258
1260 return self._conn.canWrite(self._obj)
1261
1263 return self._obj.details.permissions.isUserWrite()
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1278 """
1279 Counts available number of child objects.
1280
1281 @return: Long. The number of child objects available
1282 """
1283
1284 self._cached_countChildren = len(self._conn.getQueryService().findAllByQuery("from %s as c where c.parent.id=%i" % (self.LINK_CLASS, self._oid), None))
1285 return self._cached_countChildren
1286
1288 """
1289 countChildren, but caching the first result, useful if you need to call this multiple times in
1290 a single sequence, but have no way of storing the value between them.
1291 It is actually a hack to support django template's lack of break in for loops
1292
1293 @return: Long
1294 """
1295
1296 if not hasattr(self, '_cached_countChildren'):
1297 return self.countChildren()
1298 return self._cached_countChildren
1299
1301 """
1302 Lists available child objects.
1303
1304 @return: Generator yielding child objects.
1305 """
1306
1307 childw = self._getChildWrapper()
1308 if not params:
1309 params = omero.sys.Parameters()
1310 if not params.map:
1311 params.map = {}
1312 params.map["dsid"] = omero_type(self._oid)
1313 query = "select c from %s as c" % self.LINK_CLASS
1314 if ns is not None:
1315 params.map["ns"] = omero_type(ns)
1316 query += """ join c.child.annotationLinks ial
1317 join ial.child as a """
1318 query += " where c.parent.id=:dsid"
1319 if ns is not None:
1320 query += " and a.ns=:ns"
1321 if val is not None:
1322 if isinstance(val, StringTypes):
1323 params.map["val"] = omero_type(val)
1324 query +=" and a.textValue=:val"
1325 query += " order by c.child.name"
1326 childnodes = [ x.child for x in self._conn.getQueryService().findAllByQuery(query, params)]
1327 for child in childnodes:
1328 yield childw(self._conn, child, self._cache)
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347 @timeit
1349 """
1350 Lists available parent objects.
1351
1352 @return: Generator yielding parent objects
1353 """
1354
1355 if self.PARENT_WRAPPER_CLASS is None:
1356 return ()
1357 parentw = self._getParentWrapper()
1358 param = omero.sys.Parameters()
1359 parentnodes = [ x.parent for x in self._conn.getQueryService().findAllByQuery("from %s as c where c.child.id=%i" % (parentw().LINK_CLASS, self._oid), param)]
1360 if single:
1361 return len(parentnodes) and parentw(self._conn, parentnodes[0], self._cache) or None
1362 return map(lambda x: parentw(self._conn, x, self._cache), parentnodes)
1363
1364
1365 @timeit
1373
1374
1376 if not hasattr(self._obj, 'isAnnotationLinksLoaded'):
1377 raise NotImplementedError
1378 if not self._obj.isAnnotationLinksLoaded():
1379 links = self._conn.getQueryService().findAllByQuery("select l from %sAnnotationLink as l join fetch l.child as a where l.parent.id=%i" % (self.OMERO_CLASS, self._oid), None)
1380 self._obj._annotationLinksLoaded = True
1381 self._obj._annotationLinksSeq = links
1382
1383
1385 self._loadAnnotationLinks()
1386 rv = self.copyAnnotationLinks()
1387 if ns is not None:
1388 rv = filter(lambda x: x.getChild().getNs() and x.getChild().getNs().val == ns, rv)
1389 return rv
1390
1391
1393 for al in self._getAnnotationLinks(ns=ns):
1394 a = al.child
1395 update = self._conn.getUpdateService()
1396 update.deleteObject(al)
1397 update.deleteObject(a)
1398 self._obj.unloadAnnotationLinks()
1399
1401 """
1402 ets the first annotation in the ns namespace, linked to this object
1403
1404 @return: #AnnotationWrapper or None
1405 """
1406 rv = self._getAnnotationLinks(ns)
1407 if len(rv):
1408 return AnnotationWrapper._wrap(self._conn, rv[0].child)
1409 return None
1410
1411 @timeit
1413 """
1414 List annotations in the ns namespace, linked to this object
1415
1416 @return: Generator yielding AnnotationWrapper
1417 """
1418
1419 for ann in self._getAnnotationLinks(ns):
1420 yield AnnotationWrapper._wrap(self._conn, ann.child)
1421
1422
1424 if not ann.getId():
1425
1426 ann.details.setPermissions(omero.model.PermissionsI())
1427 ann.details.permissions.setWorldRead(True)
1428 ann = ann.__class__(self._conn, self._conn.getUpdateService().saveAndReturnObject(ann._obj))
1429
1430
1431 lnktype = "%sAnnotationLinkI" % self.OMERO_CLASS
1432 lnk = getattr(omero.model, lnktype)()
1433 lnk.details.setPermissions(omero.model.PermissionsI())
1434 lnk.details.permissions.setWorldRead(True)
1435
1436 lnk.setParent(self._obj.__class__(self._obj.id, False))
1437 lnk.setChild(ann._obj.__class__(ann._obj.id, False))
1438 self._conn.getUpdateService().saveObject(lnk)
1439 return ann
1440
1441
1469
1470
1484 p = timeit(marshalParents)()
1485 rv['parents'] = p
1486 return rv
1487
1488
1489
1490
1491
1492
1494 if hasattr(self._obj, attr):
1495 rv = getattr(self._obj, attr)
1496 if hasattr(rv, 'val'):
1497 return isinstance(rv.val, StringType) and rv.val.decode('utf8') or rv.val
1498 return rv
1499 raise AttributeError("'%s' object has no attribute '%s'" % (self._obj.__class__.__name__, attr))
1500
1501
1502
1503
1505 """
1506 Gets this object ID
1507
1508 @return: Long or None
1509 """
1510
1511 oid = self._obj.getId()
1512 return oid is not None and oid.val or None
1513
1515 """
1516 Gets this object name
1517
1518 @return: String or None
1519 """
1520
1521 return self._obj.getName().val
1522
1524 """
1525 Gets this object description
1526
1527 @return: String
1528 """
1529
1530 rv = self._obj.getDescription()
1531 return rv and rv.val or ''
1532
1534 """
1535 Gets user who is the owner of this object.
1536
1537 @return: _ExperimenterWrapper
1538 """
1539
1540 return self.getDetails().getOwner()
1541
1543 """
1544 Gets full name of the owner of this object.
1545
1546 @return: String or None
1547 """
1548
1549 try:
1550 lastName = self.getDetails().getOwner().lastName
1551 firstName = self.getDetails().getOwner().firstName
1552 middleName = self.getDetails().getOwner().middleName
1553
1554 if middleName is not None and middleName != '':
1555 name = "%s %s. %s" % (firstName, middleName, lastName)
1556 else:
1557 name = "%s %s" % (firstName, lastName)
1558 return name
1559 except:
1560 logger.error(traceback.format_exc())
1561 return None
1562
1564 """
1565 Gets omeName of the owner of this object.
1566
1567 @return: String
1568 """
1569 return self.getDetails().getOwner().omeName
1570
1572 """
1573 Gets event time in timestamp format (yyyy-mm-dd hh:mm:ss.fffffff) when object was created.
1574
1575 @return: Long
1576 """
1577
1578 try:
1579 if self._obj.details.creationEvent.time is not None:
1580 t = self._obj.details.creationEvent.time.val
1581 else:
1582 t = self._conn.getQueryService().get("Event", self._obj.details.creationEvent.id.val).time.val
1583 except:
1584 t = self._conn.getQueryService().get("Event", self._obj.details.creationEvent.id.val).time.val
1585 return datetime.fromtimestamp(t/1000)
1586
1588 """
1589 Gets event time in timestamp format (yyyy-mm-dd hh:mm:ss.fffffff) when object was updated.
1590
1591 @return: Long
1592 """
1593
1594 try:
1595 if self._obj.details.updateEvent.time is not None:
1596 t = self._obj.details.updateEvent.time.val
1597 else:
1598 t = self._conn.getQueryService().get("Event", self._obj.details.updateEvent.id.val).time.val
1599 except:
1600 t = self._conn.getQueryService().get("Event", self._obj.details.updateEvent.id.val).time.val
1601 return datetime.fromtimestamp(t/1000)
1602
1603
1604
1605
1608
1611 """
1612 omero_model_AnnotationI class wrapper extends BlitzObjectWrapper.
1613 """
1614 registry = {}
1615 OMERO_TYPE = None
1616
1621
1624
1625 @classmethod
1628
1629 @classmethod
1630 - def _wrap (klass, conn, obj):
1631 if obj.__class__ in klass.registry:
1632 return klass.registry[obj.__class__](conn, obj)
1633 else:
1634 return None
1635
1636 @classmethod
1643
1645 return self._obj.ns.val
1646
1649
1651 raise NotImplementedError
1652
1654 raise NotImplementedError
1655
1656
1657 from omero_model_TimestampAnnotationI import TimestampAnnotationI
1660 """
1661 omero_model_TimestampAnnotatio class wrapper extends AnnotationWrapper.
1662 """
1663
1664 OMERO_TYPE = TimestampAnnotationI
1665
1667 return datetime.fromtimestamp(self._obj.timeValue.val / 1000.0)
1668
1670 if isinstance(val, datetime):
1671 self._obj.timeValue = rtime(long(time.mktime(val.timetuple())*1000))
1672 elif isinstance(val, omero.RTime):
1673 self._obj.timeValue = val
1674 else:
1675 self._obj.timeValue = rtime(long(val * 1000))
1676
1677 AnnotationWrapper._register(TimestampAnnotationWrapper)
1678
1679 from omero_model_BooleanAnnotationI import BooleanAnnotationI
1682 """
1683 omero_model_BooleanAnnotationI class wrapper extends AnnotationWrapper.
1684 """
1685
1686 OMERO_TYPE = BooleanAnnotationI
1687
1689 return self._obj.boolValue.val
1690
1692 self._obj.boolValue = rbool(not not val)
1693
1694 AnnotationWrapper._register(BooleanAnnotationWrapper)
1695
1696 from omero_model_CommentAnnotationI import CommentAnnotationI
1710
1711 AnnotationWrapper._register(CommentAnnotationWrapper)
1712
1713 from omero_model_LongAnnotationI import LongAnnotationI
1716 """
1717 omero_model_LongAnnotationI class wrapper extends AnnotationWrapper.
1718 """
1719 OMERO_TYPE = LongAnnotationI
1720
1722 return self._obj.longValue.val
1723
1725 self._obj.longValue = rlong(val)
1726
1727 AnnotationWrapper._register(LongAnnotationWrapper)
1730 """
1731 omero_model_ExperimenterI class wrapper extends BlitzObjectWrapper.
1732 """
1733
1735 if not self._obj.details.owner:
1736 details = omero.model.DetailsI()
1737 details.owner = self._obj
1738 self._obj._details = details
1739 return DetailsWrapper(self._conn, self._obj.details)
1740
1741 ExperimenterWrapper = _ExperimenterWrapper
1744 """
1745 omero_model_ExperimenterGroupI class wrapper extends BlitzObjectWrapper.
1746 """
1747
1748 pass
1749
1750 ExperimenterGroupWrapper = _ExperimenterGroupWrapper
1753 """
1754 omero_model_DetailsI class wrapper extends BlitzObjectWrapper.
1755 """
1756
1758 super(DetailsWrapper, self).__init__ (*args, **kwargs)
1759 owner = self._obj.getOwner()
1760 group = self._obj.getGroup()
1761 self._owner = owner and ExperimenterWrapper(self._conn, self._obj.getOwner()) or None
1762 self._group = group and ExperimenterGroupWrapper(self._conn, self._obj.getGroup()) or None
1763
1766
1769
1771 """
1772 Stores color internally as (R,G,B,A) and allows setting and getting in multiple formats
1773 """
1774
1775 _color = {'red': 0, 'green': 0, 'blue': 0, 'alpha': 255}
1776
1778 self._color = {'red': 0, 'green': 0, 'blue': 0, 'alpha': 255}
1779 if colorname and colorname.lower() in self._color.keys():
1780 self._color[colorname.lower()] = 255
1781
1782 @classmethod
1790
1792 return self._color['red']
1793
1795 """
1796 Set red, as int 0..255
1797
1798 @param val: value of Red.
1799 """
1800
1801 self._color['red'] = max(min(255, int(val)), 0)
1802
1804 return self._color['green']
1805
1807 """
1808 Set green, as int 0..255
1809
1810 @param val: value of Green.
1811 """
1812
1813 self._color['green'] = max(min(255, int(val)), 0)
1814
1816 return self._color['blue']
1817
1819 """
1820 Set Blue, as int 0..255
1821
1822 @param val: value of Blue.
1823 """
1824
1825 self._color['blue'] = max(min(255, int(val)), 0)
1826
1828 return self._color['alpha']
1829
1831 """
1832 Set alpha, as int 0..255.
1833 @param val: value of alpha.
1834 """
1835
1836 self._color['alpha'] = max(min(255, int(val)), 0)
1837
1839 """
1840 @return: String. The html usable color. Dumps the alpha information.
1841 """
1842
1843 return "%(red)0.2X%(green)0.2X%(blue)0.2X" % (self._color)
1844
1846 """
1847 @return: String. rgba(r,g,b,a) for this color.
1848 """
1849
1850 c = self._color.copy()
1851 c['alpha'] /= 255.0
1852 return "rgba(%(red)i,%(green)i,%(blue)i,%(alpha)0.3f)" % (c)
1853
1855 """
1856 @return: list. A list of (r,g,b) values
1857 """
1858
1859 return (self._color['red'], self._color['green'], self._color['blue'])
1860
1862 """
1863 omero_model_ChannelI class wrapper extends BlitzObjectWrapper.
1864 """
1865
1866 BLUE_MIN = 400
1867 BLUE_MAX = 500
1868 GREEN_MIN = 501
1869 GREEN_MAX = 600
1870 RED_MIN = 601
1871 RED_MAX = 700
1872 COLOR_MAP = ((BLUE_MIN, BLUE_MAX, ColorHolder('Blue')),
1873 (GREEN_MIN, GREEN_MAX, ColorHolder('Green')),
1874 (RED_MIN, RED_MAX, ColorHolder('Red')),
1875 )
1877 self._re = re
1878 self._idx = idx
1879
1883
1886
1888 lc = self._obj.getLogicalChannel()
1889 if lc is not None and lc.name is not None:
1890 return lc.name.val
1891 emWave = lc.getEmissionWave()
1892 if emWave is None:
1893
1894 return self._idx
1895 else:
1896 return emWave.val
1897
1900
1902 return int(self._re.getChannelWindowStart(self._idx))
1903
1906
1908 return int(self._re.getChannelWindowEnd(self._idx))
1909
1912
1914 self._re.setChannelWindow(self._idx, float(minval), float(maxval))
1915
1917 return self._obj.getStatsInfo().getGlobalMin().val
1918
1920 return self._obj.getStatsInfo().getGlobalMax().val
1921
1923 def wrapped (self, *args, **kwargs):
1924 if not self._prepareRenderingEngine():
1925 return None
1926 return func(self, *args, **kwargs)
1927 return wrapped
1928
1930 def wrapped (self, *args, **kwargs):
1931 if not self._loadPixels():
1932 return None
1933 return func(self, *args, **kwargs)
1934 return wrapped
1935
1937 """
1938 omero_model_ImageI class wrapper extends BlitzObjectWrapper.
1939 """
1940
1941 _re = None
1942 _pd = None
1943 _rm = {}
1944 _pixels = None
1945
1946 _pr = None
1947
1948 PROJECTIONS = {
1949 'normal': -1,
1950 'intmax': omero.constants.projection.ProjectionType.MAXIMUMINTENSITY,
1951 'intmean': omero.constants.projection.ProjectionType.MEANINTENSITY,
1952 'intsum': omero.constants.projection.ProjectionType.SUMINTENSITY,
1953 }
1954
1955 PLANEDEF = omero.romio.XY
1956
1962
1965
1968
1970 if not self._obj.pixelsLoaded:
1971 self.__loadedHotSwap__()
1972 return self._obj.sizeOfPixels() > 0
1973
1975 re = self._conn.createRenderingEngine()
1976 pixels_id = self._obj.getPrimaryPixels().id.val
1977 re.lookupPixels(pixels_id)
1978 if re.lookupRenderingDef(pixels_id) == False:
1979 try:
1980 re.resetDefaults()
1981 except omero.ResourceError:
1982
1983 return False
1984 re.lookupRenderingDef(pixels_id)
1985 re.load()
1986 return re
1987
1997
1999 rv = super(_ImageWrapper, self).simpleMarshal(xtra=xtra, parents=parents)
2000 rv.update({'author': self.getAuthor(),
2001 'date': time.mktime(self.getDate().timetuple()),})
2002 if xtra and xtra.has_key('thumbUrlPrefix'):
2003 rv['thumb_url'] = xtra['thumbUrlPrefix'] + str(self.id) + '/'
2004 return rv
2005
2007 name = self.name
2008 if not name:
2009 return ""
2010 l = len(name)
2011 if l < length+hist:
2012 return name
2013 return "..." + name[l - length:]
2014
2016 q = self._conn.getQueryService()
2017 e = q.findByQuery("select e from Experimenter e where e.id = %i" % self._obj.details.owner.id.val,None)
2018 self._author = e.firstName.val + " " + e.lastName.val
2019 return self._author
2020
2022 try:
2023 q = """
2024 select ds from Image i join i.datasetLinks dl join dl.parent ds
2025 where i.id = %i
2026 """ % self._obj.id.val
2027 query = self._conn.getQueryService()
2028 ds = query.findByQuery(q,None)
2029 return ds and DatasetWrapper(self._conn, ds) or None
2030 except:
2031 logger.debug(traceback.format_exc())
2032 return None
2033
2035 try:
2036 q = """
2037 select p from Image i join i.datasetLinks dl join dl.parent ds join ds.projectLinks pl join pl.parent p
2038 where i.id = %i
2039 """ % self._obj.id.val
2040 query = self._conn.getQueryService()
2041 prj = query.findByQuery(q,None)
2042 return prj and ProjectWrapper(self._conn, prj) or None
2043 except:
2044 logger.debug(traceback.format_exc())
2045 return None
2046
2048 try:
2049 if self._obj.acquisitionDate.val is not None and self._obj.acquisitionDate.val > 0:
2050 t = self._obj.acquisitionDate.val
2051 else:
2052 t = self._obj.details.creationEvent.time.val
2053 except:
2054 t = self._conn.getQueryService().get("Event", self._obj.details.creationEvent.id.val).time.val
2055 return datetime.fromtimestamp(t/1000)
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2070 if not self._loadPixels():
2071 return None
2072 pixels_id = self._obj.getPrimaryPixels().getId().val
2073 tb = self._conn.createThumbnailStore()
2074 try:
2075 rv = tb.setPixelsId(pixels_id)
2076 except omero.InternalException:
2077 rv = False
2078 if not rv:
2079 tb.resetDefaults()
2080 tb.close()
2081 tb.setPixelsId(pixels_id)
2082 return tb
2083
2085 try:
2086 tb = self._prepareTB()
2087 if tb is None:
2088 return None
2089 if isinstance(size, IntType):
2090 size = (size,)
2091 if len(size) == 1:
2092 thumb = tb.getThumbnailByLongestSide
2093 else:
2094 thumb = tb.getThumbnail
2095 size = map(lambda x: rint(x), size)
2096 rv = thumb(*size)
2097 return rv
2098 except Exception:
2099 logger.error(traceback.print_exc())
2100 return None
2101
2102 @assert_re
2104 return [ChannelWrapper(self._conn, c, idx=n, re=self._re) for n,c in enumerate(self._re.getPixels().iterateChannels())]
2105
2107 for c in range(len(self.getChannels())):
2108 self._re.setActive(c, (c+1) in channels)
2109 if (c+1) in channels:
2110 if windows is not None and windows[c][0] is not None and windows[c][1] is not None:
2111 self._re.setChannelWindow(c, *windows[c])
2112 if colors is not None and colors[c]:
2113 rgba = splitHTMLColor(colors[c])
2114 if rgba:
2115 self._re.setRGBA(c, *rgba)
2116 return True
2117
2120
2123
2124 LINE_PLOT_DTYPES = {
2125 (4, True, True): 'f',
2126 (2, False, False): 'H',
2127 (2, False, True): 'h',
2128 (1, False, False): 'B',
2129 (1, False, True): 'b',
2130 }
2131
2132 - def getPixelLine (self, z, t, pos, axis, channels=None, range=None):
2133 """
2134 Grab a horizontal or vertical line from the image pixel data, for the specified channels
2135 (or all if not specified) and using the specified range (or 1:1 relative to the image size).
2136 Axis may be 'h' or 'v', for horizontal or vertical respectively.
2137
2138 @param z:
2139 @param t:
2140 @param pos:
2141 @param axis:
2142 @param channels:
2143 @param range:
2144 @return: rv
2145 """
2146
2147 if not self._loadPixels():
2148 logger.debug( "No pixels!")
2149 return None
2150 axis = axis.lower()[:1]
2151 if channels is None:
2152 channels = map(lambda x: x._idx, filter(lambda x: x.isActive(), self.getChannels()))
2153 if range is None:
2154 range = axis == 'h' and self.getHeight() or self.getWidth()
2155 if not isinstance(channels, (TupleType, ListType)):
2156 channels = (channels,)
2157 chw = map(lambda x: (x.getWindowMin(), x.getWindowMax()), self.getChannels())
2158 rv = []
2159 pixels_id = self._obj.getPrimaryPixels().getId().val
2160 rp = self._conn.createRawPixelsStore()
2161 rp.setPixelsId(pixels_id, True)
2162 for c in channels:
2163 bw = rp.getByteWidth()
2164 key = self.LINE_PLOT_DTYPES.get((bw, rp.isFloat(), rp.isSigned()), None)
2165 if key is None:
2166 logger.error("Unknown data type: " + str((bw, rp.isFloat(), rp.isSigned())))
2167 plot = array.array(key, axis == 'h' and rp.getRow(pos, z, c, t) or rp.getCol(pos, z, c, t))
2168 plot.byteswap()
2169
2170 offset = -chw[c][0]
2171 if offset != 0:
2172 plot = map(lambda x: x+offset, plot)
2173 normalize = 1.0/chw[c][1]*(range-1)
2174 if normalize != 1.0:
2175 plot = map(lambda x: x*normalize, plot)
2176 if isinstance(plot, array.array):
2177 plot = plot.tolist()
2178 rv.append(plot)
2179 return rv
2180
2181
2182 - def getRow (self, z, t, y, channels=None, range=None):
2184
2185 - def getCol (self, z, t, x, channels=None, range=None):
2187
2188 @assert_re
2190 if not len(self._rm):
2191 for m in [BlitzObjectWrapper(self._conn, m) for m in self._re.getAvailableModels()]:
2192 self._rm[m.value.lower()] = m
2193 return self._rm.values()
2194
2195 @assert_re
2198
2200 """
2201 Sets the Greyscale rendering model on this image's current renderer
2202 """
2203
2204 rm = self.getRenderingModels()
2205 self._re.setModel(self._rm.get('greyscale', rm[0])._obj)
2206
2208 """
2209 Sets the HSB rendering model on this image's current renderer
2210 """
2211
2212 rm = self.getRenderingModels()
2213 self._re.setModel(self._rm.get('rgb', rm[0])._obj)
2214
2217
2218 @assert_re
2220 self._pd.z = long(z)
2221 self._pd.t = long(t)
2222 try:
2223 if compression is not None:
2224 try:
2225 self._re.setCompressionLevel(float(compression))
2226 except omero.SecurityViolation:
2227 self._obj.clearPixels()
2228 self._obj.pixelsLoaded = False
2229 self._re = None
2230 return self.renderJpeg(z,t,None)
2231 projection = self.PROJECTIONS.get(self._pr, -1)
2232 if not isinstance(projection, omero.constants.projection.ProjectionType):
2233 rv = self._re.renderCompressed(self._pd)
2234 else:
2235 rv = self._re.renderProjectedCompressed(projection, self._pd.t, 1, 0, self.z_count()-1)
2236 return rv
2237 except omero.InternalException:
2238 logger.debug(traceback.format_exc())
2239 return None
2240 except Ice.MemoryLimitException:
2241
2242 self._obj.clearPixels()
2243 self._obj.pixelsLoaded = False
2244 self._re = None
2245 raise
2246
2248 rv = self.renderJpeg(z,t,compression)
2249 if rv is not None:
2250 i = StringIO(rv)
2251 rv = Image.open(i)
2252 return rv
2253
2255 """
2256 Prepares a jpeg representation of a 2d grid holding a render of each channel,
2257 along with one for all channels at the set Z and T points.
2258
2259 @param z:
2260 @param t:
2261 @param compression:
2262 @param border:
2263 @return: value
2264 """
2265
2266 img = self.renderSplitChannelImage(z,t,compression, border)
2267 rv = StringIO()
2268 img.save(rv, 'jpeg', quality=int(compression*100))
2269 return rv.getvalue()
2270
2272 c = self.c_count()
2273
2274 x = sqrt(c)
2275 y = int(round(x))
2276 if x > y:
2277 x = y+1
2278 else:
2279 x = y
2280 rv = {'g':{'width': self.getWidth()*x + border*(x+1),
2281 'height': self.getHeight()*y+border*(y+1),
2282 'border': border,
2283 'gridx': x,
2284 'gridy': y,}
2285 }
2286
2287 c += 1
2288 x = sqrt(c)
2289 y = int(round(x))
2290 if x > y:
2291 x = y+1
2292 else:
2293 x = y
2294 rv['c'] = {'width': self.getWidth()*x + border*(x+1),
2295 'height': self.getHeight()*y+border*(y+1),
2296 'border': border,
2297 'gridx': x,
2298 'gridy': y,}
2299 return rv
2300
2302 """
2303 Prepares a PIL Image with a 2d grid holding a render of each channel,
2304 along with one for all channels at the set Z and T points.
2305
2306 @param z:
2307 @param t:
2308 @param compression:
2309 @param border:
2310 @return: canvas
2311 """
2312
2313 dims = self.splitChannelDims(border=border)[self.isGreyscaleRenderingModel() and 'g' or 'c']
2314 canvas = Image.new('RGBA', (dims['width'], dims['height']), '#fff')
2315 cmap = [ch.isActive() and i+1 or 0 for i,ch in enumerate(self.getChannels())]
2316 c = self.c_count()
2317 pxc = 0
2318 px = dims['border']
2319 py = dims['border']
2320
2321
2322 w = self.getWidth()
2323 if w >= 640:
2324 fsize = (int((w-640)/128)*8) + 24
2325 if fsize > 64:
2326 fsize = 64
2327 elif w >= 512:
2328 fsize = 24
2329 elif w >= 384:
2330 fsize = 18
2331 elif w >= 298:
2332 fsize = 14
2333 elif w >= 256:
2334 fsize = 12
2335 elif w >= 213:
2336 fsize = 10
2337 elif w >= 96:
2338 fsize = 8
2339 else:
2340 fsize = 0
2341 if fsize > 0:
2342 font = ImageFont.load('%s/pilfonts/B%0.2d.pil' % (THISPATH, fsize) )
2343
2344
2345 for i in range(c):
2346 if cmap[i]:
2347 self.setActiveChannels((i+1,))
2348 img = self.renderImage(z,t, compression)
2349 if fsize > 0:
2350 draw = ImageDraw.ImageDraw(img)
2351 draw.text((2,2), "w=%s" % (str(self.getChannels()[i].getEmissionWave())), font=font, fill="#fff")
2352 canvas.paste(img, (px, py))
2353 pxc += 1
2354 if pxc < dims['gridx']:
2355 px += self.getWidth() + border
2356 else:
2357 pxc = 0
2358 px = border
2359 py += self.getHeight() + border
2360 if not self.isGreyscaleRenderingModel():
2361 self.setActiveChannels(cmap)
2362 img = self.renderImage(z,t, compression)
2363 if fsize > 0:
2364 draw = ImageDraw.ImageDraw(img)
2365 draw.text((2,2), "combined", font=font, fill="#fff")
2366 canvas.paste(img, (px, py))
2367 return canvas
2368
2369 LP_PALLETE = [0,0,0,0,0,0,255,255,255]
2370 LP_TRANSPARENT = 0
2371 LP_BGCOLOR = 1
2372 LP_FGCOLOR = 2
2374 """
2375 Common part of horizontal and vertical line plot rendering.
2376 @returns: (Image, width, height).
2377 """
2378 channels = filter(lambda x: x.isActive(), self.getChannels())
2379 width = self.getWidth()
2380 height = self.getHeight()
2381
2382 pal = list(self.LP_PALLETE)
2383
2384 for channel in channels:
2385 pal.extend(channel.getColor().getRGB())
2386
2387
2388 im = Image.new('P', (width, height))
2389 im.putpalette(pal)
2390 return im, width, height
2391
2392
2393 @assert_re
2395 self._pd.z = long(z)
2396 self._pd.t = long(t)
2397
2398 im, width, height = self.prepareLinePlotCanvas(z,t)
2399 base = height - 1
2400
2401 draw = ImageDraw.ImageDraw(im)
2402
2403 draw.rectangle([0, 0, width-1, base], fill=self.LP_TRANSPARENT, outline=self.LP_TRANSPARENT)
2404 draw.line(((0,y),(width, y)), fill=self.LP_FGCOLOR, width=linewidth)
2405
2406
2407 rows = self.getRow(z,t,y)
2408
2409 for r in range(len(rows)):
2410 chrow = rows[r]
2411 color = r + self.LP_FGCOLOR + 1
2412 last_point = base-chrow[0]
2413 for i in range(len(chrow)):
2414 draw.line(((i, last_point), (i, base-chrow[i])), fill=color, width=linewidth)
2415 last_point = base-chrow[i]
2416 del draw
2417 out = StringIO()
2418 im.save(out, format="gif", transparency=0)
2419 return out.getvalue()
2420
2421 @assert_re
2423 self._pd.z = long(z)
2424 self._pd.t = long(t)
2425
2426 im, width, height = self.prepareLinePlotCanvas(z,t)
2427
2428 draw = ImageDraw.ImageDraw(im)
2429
2430 draw.rectangle([0, 0, width-1, height-1], fill=self.LP_TRANSPARENT, outline=self.LP_TRANSPARENT)
2431 draw.line(((x,0),(x, height)), fill=self.LP_FGCOLOR, width=linewidth)
2432
2433
2434 cols = self.getCol(z,t,x)
2435
2436 for r in range(len(cols)):
2437 chcol = cols[r]
2438 color = r + self.LP_FGCOLOR + 1
2439 last_point = chcol[0]
2440 for i in range(len(chcol)):
2441 draw.line(((last_point, i), (chcol[i], i)), fill=color, width=linewidth)
2442 last_point = chcol[i]
2443 del draw
2444 out = StringIO()
2445 im.save(out, format="gif", transparency=0)
2446 return out.getvalue()
2447
2448 @assert_re
2451
2452 @assert_re
2455
2456 @assert_pixels
2458 rv = self._obj.getPrimaryPixels().getPhysicalSizeX()
2459 return rv is not None and rv.val or None
2460
2461 @assert_pixels
2463 rv = self._obj.getPrimaryPixels().getPhysicalSizeY()
2464 return rv is not None and rv.val or None
2465
2466 @assert_pixels
2468 rv = self._obj.getPrimaryPixels().getPhysicalSizeZ()
2469 return rv is not None and rv.val or None
2470
2471 @assert_pixels
2473 return self._obj.getPrimaryPixels().getSizeX().val
2474
2475 @assert_pixels
2477 return self._obj.getPrimaryPixels().getSizeY().val
2478
2479 @assert_pixels
2481 return self._obj.getPrimaryPixels().getSizeZ().val
2482
2483 @assert_pixels
2485 return self._obj.getPrimaryPixels().getSizeT().val
2486
2487 @assert_pixels
2489 return self._obj.getPrimaryPixels().getSizeC().val
2490
2492 """
2493 Removes specific color settings from channels
2494
2495 @return: Boolean
2496 """
2497
2498 if not self.canWrite():
2499 return False
2500 for c in self.getChannels():
2501 c.unloadRed()
2502 c.unloadGreen()
2503 c.unloadBlue()
2504 c.unloadAlpha()
2505 c.save()
2506 self._conn.getDeleteService().deleteSettings(self.getId())
2507 return True
2508
2509 @assert_re
2511 """
2512 Limited support for saving the current prepared image rendering defs.
2513 Right now only channel colors are saved back.
2514
2515 @return: Boolean
2516 """
2517
2518 if not self.canWrite():
2519 return False
2520 self._re.saveCurrentSettings()
2521 return True
2522
2523 ImageWrapper = _ImageWrapper
2526 """
2527 omero_model_DatasetI class wrapper extends BlitzObjectWrapper.
2528 """
2529
2535
2537 super(_DatasetWrapper, self).__loadedHotSwap__()
2538 if not self._obj.isImageLinksLoaded():
2539 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)
2540 self._obj._imageLinksLoaded = True
2541 self._obj._imageLinksSeq = links
2542
2543 DatasetWrapper = _DatasetWrapper
2546 """
2547 omero_model_ProjectI class wrapper extends BlitzObjectWrapper.
2548 """
2549
2555
2556 ProjectWrapper = _ProjectWrapper
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569