Package omero :: Package gateway
[hide private]
[frames] | no frames]

Source Code for Package omero.gateway

   1  #/bin/env python -i 
   2   
   3  # 
   4  # blitz_gateway - python bindings and wrappers to access an OMERO blitz server 
   5  #  
   6  # Copyright (c) 2007, 2008 Glencoe Software, Inc. All rights reserved. 
   7  #  
   8  # This software is distributed under the terms described by the LICENCE file 
   9  # you can find at the root of the distribution bundle, which states you are 
  10  # free to use it only for non commercial purposes. 
  11  # If the file is missing please request a copy by contacting 
  12  # jason@glencoesoftware.com. 
  13   
  14  #WEBLITZ_ANN_NS = {}#'PART':    'com.glencoesoftware.journal_bridge:part'} 
  15   
  16  #class STATIC_DEFS: 
  17  #    MAXIMUM_INTENSITY = 1 
  18  #    MEAN_INTENSITY    = 2 
  19  #    SUM_INTENSITY     = 3 
  20   
  21       
  22   
  23  # Set up the python include paths 
  24  import logging 
  25  import os,sys 
  26  THISPATH = os.path.dirname(os.path.abspath(__file__)) 
  27  #sys.path.append(os.path.join(p,'icepy')) 
  28  #sys.path.append(os.path.join(p,'lib')) 
  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  #import threading 
  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 
54 55 -def timeit (func):
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
72 73 -def omero_type(val):
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
97 98 -class NoProxies (object):
99 - def __getitem__ (self, k):
100 raise Ice.ConnectionLostException
101
102 -class _BlitzGateway (object):
103 """ 104 ICE_CONFIG - Defines the path to the Ice configuration 105 """ 106 107 ICE_CONFIG = None#os.path.join(p,'etc/ice.config') 108 # def __init__ (self, username, passwd, server, port, client_obj=None, group=None, clone=False): 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 # The properties we are setting through the interface 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
161 - def getProperty(self, k):
162 return self.c.getProperty(k)
163
164 - def clone (self):
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 #self.server, self.port, clone=True) 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
184 - def keepAlive (self):
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: #pragma: no cover 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: #pragma: no cover 200 # The connection is there, but it has been reset, because the proxy no longer exists... 201 logger.debug(traceback.format_exc()) 202 logger.debug("... reset, not reconnecting") 203 return False 204 except Ice.ConnectionLostException: #pragma: no cover 205 # The connection was lost. This shouldn't happen, as we keep pinging it, but does so... 206 logger.debug(traceback.format_exc()) 207 logger.debug("... lost, reconnecting") 208 return self.connect() 209 except Ice.ConnectionRefusedException: #pragma: no cover 210 # The connection was refused. We lost contact with glacier2router... 211 logger.debug(traceback.format_exc()) 212 logger.debug("... refused, not reconnecting") 213 return False 214 except omero.RemovedSessionException: #pragma: no cover 215 # Session died on us 216 logger.debug(traceback.format_exc()) 217 logger.debug("... session has left the building, not reconnecting") 218 return False 219 except Ice.UnknownException, x: #pragma: no cover 220 # Probably a wrapped RemovedSession 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): #pragma: no cover
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
263 - def __del__ (self):
264 logger.debug("##GARBAGE COLLECTOR KICK IN")
265
266 - def _createProxies (self):
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 #self._proxies['projection'] = ProxyObjectWrapper(self, 'getProjectionService') 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 # self._proxies['ldap'] = ProxyObjectWrapper(self, 'getLdapService') 288 self._proxies['metadata'] = ProxyObjectWrapper(self, 'getMetadataService') 289 self._proxies['rawfile'] = ProxyObjectWrapper(self, 'createRawFileStore') 290 self._proxies['repository'] = ProxyObjectWrapper(self, 'getRepositoryInfoService') 291 # self._proxies['script'] = ProxyObjectWrapper(self, 'getScriptService') 292 # self._proxies['search'] = ProxyObjectWrapper(self, 'createSearchService') 293 # self._proxies['session'] = ProxyObjectWrapper(self, 'getSessionService') 294 self._proxies['share'] = ProxyObjectWrapper(self, 'getShareService') 295 # self._proxies['thumbs'] = ProxyObjectWrapper(self, 'createThumbnailStore') 296 self._proxies['timeline'] = ProxyObjectWrapper(self, 'getTimelineService') 297 self._proxies['types'] = ProxyObjectWrapper(self, 'getTypesService') 298 # self._proxies['update'] = ProxyObjectWrapper(self, 'getUpdateService') 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: #pragma: no cover 304 if self._was_join: 305 self._session_cb.join(self) 306 else: 307 self._session_cb.create(self)
308
309 - def _createSession (self, skipSUuid=False):
310 """ 311 Creates a new session for the principal given in the constructor. 312 """ 313 314 s = self.c.createSession(self._ic_props[omero.constants.USERNAME], 315 self._ic_props[omero.constants.PASSWORD]) 316 self._sessionUuid = self.c.sf.ice_getIdentity().name 317 ss = self.c.sf.getSessionService() 318 self._session = ss.getSession(self._sessionUuid) 319 self._lastGroup = None 320 s.detachOnDestroy() 321 self._was_join = False 322 if self.group is not None: 323 # try something that fails if the user don't have permissions on the group 324 self.c.sf.getAdminService().getEventContext()
325
326 - def _closeSession (self):
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: #pragma: no cover 346 logger.warn(traceback.format_exc()) 347 try: 348 self.c.closeSession() 349 except omero.Glacier2.SessionNotExistException: #pragma: no cover 350 pass
351
352 - def _resetOmeroClient (self):
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))#, pmap=['--Ice.Config='+','.join(self.ice_config)]) 360 else: 361 logger.info('--Ice.Config='+','.join(self.ice_config)) 362 self.c = omero.client(pmap=['--Ice.Config='+','.join(self.ice_config)])
363
364 - def connect (self, sUuid=None):
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: #pragma: no cover 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: #pragma: no cover 395 raise 396 except Exception, x: #pragma: no cover 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: #pragma: no cover 403 logger.debug("Uncaptured sUuid failure!") 404 if self._connected: 405 self._connected = False 406 try: 407 #args = self.c._ic_args 408 #logger.debug(str(args)) 409 self._closeSession() 410 logger.info("called closeSession()") 411 self._resetOmeroClient() 412 #self.c = omero.client(*args) 413 except omero.Glacier2.SessionNotExistException: #pragma: no cover 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 # User don't have access to group 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: #pragma: no cover 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 #time.sleep(10) 437 try: 438 logger.info("(2) calling createSession()") 439 self._createSession() 440 except omero.SecurityViolation: 441 if self.group is not None: 442 # User don't have access to group 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: #pragma: no cover 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 #time.sleep(10) 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: #pragma: no cover 464 logger.debug('This one is a SyscallException') 465 raise 466 except Ice.LocalException, x: #pragma: no cover 467 logger.debug("connect(): " + traceback.format_exc()) 468 self._last_error = x 469 return False 470 except Exception, x: #pragma: no cover 471 logger.debug("connect(): " + traceback.format_exc()) 472 self._last_error = x 473 return False 474 logger.debug(".. connected!") 475 return True
476
477 - def getLastError (self): #pragma: no cover
478 """ 479 Returns error if thrown by _BlitzGateway.connect connect. 480 481 @return: String 482 """ 483 484 return self._last_error 485
486 - def isConnected (self):
487 """ 488 Returns last status of connection. 489 490 @return: Boolean 491 """ 492 493 return self._connected
494 495 ###################### 496 ## Connection Stuff ## 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
512 - def getUser (self):
513 """ 514 Returns current omero_model_ExperimenterI. 515 516 @return: omero.model.ExperimenterI 517 """ 518 519 return self._user
520
521 - def isAdmin (self):
522 """ 523 Checks if a user has administration privileges. 524 525 @return: Boolean 526 """ 527 528 return self.getEventContext().isAdmin
529
530 - def canWrite (self, obj):
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
540 - def setGroupForSession (self, group):
541 if self._session is None: 542 ss = self.c.sf.getSessionService() 543 self._session = ss.getSession(self._sessionUuid) 544 if self._session.getDetails().getGroup().getId().val == group.getId(): 545 # Already correct 546 return 547 a = self.getAdminService() 548 if not group.name in [x.name.val for x in a.containedGroups(self._userid)]: 549 # User not in this group 550 return 551 self._lastGroup = self._session.getDetails().getGroup() 552 self._session.getDetails().setGroup(group._obj) 553 self._session.setTimeToIdle(None) 554 self.getSessionService().updateSession(self._session)
555
556 - def revertGroupForSession (self):
557 if self._lastGroup: 558 self.setGroupForSession(self._lastGroup) 559 self._lastGroup = None
560 561 ############## 562 ## Services ## 563
564 - def getAdminService (self):
565 """ 566 Gets reference to the admin service from ProxyObjectWrapper. 567 568 @return: omero.gateway.ProxyObjectWrapper 569 """ 570 571 return self._proxies['admin']
572
573 - def getQueryService (self):
574 """ 575 Gets reference to the query service from ProxyObjectWrapper. 576 577 @return: omero.gateway.ProxyObjectWrapper 578 """ 579 return self._proxies['query']
580
581 - def getContainerService (self):
582 """ 583 Gets reference to the container service from ProxyObjectWrapper. 584 585 @return: omero.gateway.ProxyObjectWrapper 586 """ 587 588 return self._proxies['container']
589
590 - def getPixelsService (self):
591 """ 592 Gets reference to the pixels service from ProxyObjectWrapper. 593 594 @return: omero.gateway.ProxyObjectWrapper 595 """ 596 597 return ProxyObjectWrapper(self, 'getPixelsService')
598
599 - def getMetadataService (self):
600 """ 601 Gets reference to the metadata service from ProxyObjectWrapper. 602 603 @return: omero.gateway.ProxyObjectWrapper 604 """ 605 606 return self._proxies['metadata']
607
608 - def createRawFileStore (self):
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
619 - def getRepositoryInfoService (self):
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
628 - def getShareService(self):
629 """ 630 Gets reference to the share service from ProxyObjectWrapper. 631 632 @return: omero.gateway.ProxyObjectWrapper 633 """ 634 635 return self._proxies['share']
636
637 - def getTimelineService (self):
638 """ 639 Gets reference to the timeline service from ProxyObjectWrapper. 640 641 @return: omero.gateway.ProxyObjectWrapper 642 """ 643 644 return self._proxies['timeline']
645
646 - def getTypesService(self):
647 """ 648 Gets reference to the types service from ProxyObjectWrapper. 649 650 @return: omero.gateway.ProxyObjectWrapper 651 """ 652 653 return self._proxies['types']
654
655 - def getConfigService (self):
656 """ 657 Gets reference to the config service from ProxyObjectWrapper. 658 659 @return: omero.gateway.ProxyObjectWrapper 660 """ 661 662 return self._proxies['config']
663
664 - def createRenderingEngine (self):
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
679 - def getRenderingSettingsService (self):
680 return self._proxies['rendsettings']
681
682 - def createRawPixelsStore (self):
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
693 - def createThumbnailStore (self):
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
704 - def createSearchService (self):
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
714 - def getUpdateService (self):
715 """ 716 Gets reference to the update service from ProxyObjectWrapper. 717 718 @return: omero.gateway.ProxyObjectWrapper 719 """ 720 return ProxyObjectWrapper(self, 'getUpdateService')
721
722 - def getDeleteService (self):
723 """ 724 Gets reference to the delete service from ProxyObjectWrapper. 725 726 @return: omero.gateway.ProxyObjectWrapper 727 """ 728 return ProxyObjectWrapper(self, 'getDeleteService')
729
730 - def getSessionService (self):
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 # Top level object fetchers # 740
741 - def listProjects (self, only_owned=False):
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 # def listCategoryGroups (self): 761 # q = self.getQueryService() 762 # cache = {} 763 # for e in q.findAll("CategoryGroup", None): 764 # yield CategoryGroupWrapper(self, e, cache) 765
766 - def listExperimenters (self, start=''):
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
785 - def getExperimenter(self, eid):
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
800 - def lookupExperimenter(self, name):
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 # Specific Object Getters # 818
819 - def getProject (self, oid):
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
833 - def getDataset (self, oid):
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
847 - def getImage (self, oid):
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 # Annotation based iterators # 863
864 - def listImages (self, ns, params=None):
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 # Searching stuff # 889 890
891 - def searchImages (self, text):
892 """ 893 Fulltext search for images 894 """ 895 return self.simpleSearch(text,(ImageWrapper,))
896 897
898 - def simpleSearch (self, text, types=None):
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
926 -def safeCallWrap (self, attr, f): #pragma: no cover
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 # Failed 949 logger.debug( "Ice.Exception (1) on safe call %s(%s,%s)" % (attr, str(args), str(kwargs))) 950 logger.debug(traceback.format_exc()) 951 # Recreate the proxy object 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 # Still Failed 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 # Recreate connection 964 self._connect() 965 logger.debug('last try for %s' % attr) 966 # Last try, don't catch exception 967 func = getattr(self._obj, attr) 968 return func(*args, **kwargs) 969 except: 970 raise 971 972 def wrapped (*args, **kwargs): #pragma: no cover 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 #time.sleep(10) 993 return inner(*args, **kwargs) 994 return wrapped 995 996 997 BlitzGateway = _BlitzGateway
998 999 1000 -def splitHTMLColor (color):
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
1024 1025 -class ProxyObjectWrapper (object):
1026 - def __init__ (self, conn, func_str):
1027 self._obj = None 1028 self._func_str = func_str 1029 self._resyncConn(conn) 1030 self._tainted = False
1031
1032 - def clone (self):
1033 return ProxyObjectWrapper(self._conn, self._func_str)
1034
1035 - def _connect (self): #pragma: no cover
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
1054 - def taint (self):
1055 self._tainted = True
1056
1057 - def untaint (self):
1058 self._tainted = False
1059
1060 - def close (self):
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
1070 - def _resyncConn (self, conn):
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
1087 - def _getObj (self):
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
1098 - def _ping (self): #pragma: no cover
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 # The connection is there, but it has been reset, because the proxy no longer exists... 1111 logger.debug("... reset, reconnecting") 1112 self._connect() 1113 return False 1114 except Ice.ConnectionLostException: 1115 # The connection was lost. This shouldn't happen, as we keep pinging it, but does so... 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 # The connection was refused. We lost contact with glacier2router... 1123 logger.debug(traceback.format_stack()) 1124 logger.debug("... refused, reconnecting") 1125 self._connect() 1126 return False 1127 except omero.RemovedSessionException: 1128 # Session died on us 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 # Probably a wrapped RemovedSession 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
1141 - def __getattr__ (self, attr):
1142 """ 1143 1144 @param attr: Connection 1145 @return: rv 1146 """ 1147 # safe call wrapper 1148 obj = self._obj or self._getObj() 1149 rv = getattr(obj, attr) 1150 if callable(rv): 1151 rv = safeCallWrap(self, attr, rv) 1152 #self._conn.updateTimeout() 1153 return rv
1154
1155 1156 -class BlitzObjectWrapper (object):
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
1179 - def __eq__ (self, a):
1180 return type(a) == type(self) and self._obj.id == a._obj.id and self.getName() == a.getName()
1181
1182 - def __bstrap__ (self):
1183 pass
1184
1185 - def __prepare__ (self, **kwargs):
1186 pass
1187
1188 - def __repr__ (self):
1189 if hasattr(self, '_oid'): 1190 return '<%s id=%s>' % (self.__class__.__name__, str(self._oid)) 1191 return super(BlitzObjectWrapper, self).__repr__()
1192
1193 - def _getChildWrapper (self):
1194 if self.CHILD_WRAPPER_CLASS is None: 1195 raise NotImplementedError 1196 if type(self.CHILD_WRAPPER_CLASS) is type(''): 1197 # resolve class 1198 g = globals() 1199 logger.debug('C:' + str(g[self.CHILD_WRAPPER_CLASS])) 1200 if not g.has_key(self.CHILD_WRAPPER_CLASS): #pragma: no cover 1201 raise NotImplementedError 1202 self.__class__.CHILD_WRAPPER_CLASS = self.CHILD_WRAPPER_CLASS = g[self.CHILD_WRAPPER_CLASS] 1203 return self.CHILD_WRAPPER_CLASS
1204
1205 - def _getParentWrapper (self):
1206 if self.PARENT_WRAPPER_CLASS is None: 1207 raise NotImplementedError 1208 if type(self.PARENT_WRAPPER_CLASS) is type(''): 1209 # resolve class 1210 g = globals() 1211 if not g.has_key(self.PARENT_WRAPPER_CLASS): #pragma: no cover 1212 raise NotImplementedError 1213 self.__class__.PARENT_WRAPPER_CLASS = self.PARENT_WRAPPER_CLASS = g[self.PARENT_WRAPPER_CLASS] 1214 return self.PARENT_WRAPPER_CLASS
1215
1216 - def __loadedHotSwap__ (self):
1217 self._obj = self._conn.getContainerService().loadContainerHierarchy(self.OMERO_CLASS, (self._oid,), None)[0]
1218 1229
1230 - def getDetails (self):
1231 return DetailsWrapper (self._conn, self._obj.getDetails())
1232
1233 - def save (self):
1234 self._obj = self._conn.getUpdateService().saveAndReturnObject(self._obj)
1235
1236 - def saveAs (self, details):
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
1259 - def canWrite (self):
1260 return self._conn.canWrite(self._obj)
1261
1262 - def canOwnerWrite (self):
1263 return self._obj.details.permissions.isUserWrite()
1264 1265 #@timeit 1266 #def getUID (self): 1267 # p = self.listParents() 1268 # return p and '%s:%s' % (p.getUID(), str(self.id)) or str(self.id) 1269 1270 #def getChild (self, oid): 1271 # q = self._conn.getQueryService() 1272 # ds = q.find(self.CHILD_WRAPPER_CLASS.OMERO_CLASS, long(oid)) 1273 # if ds is not None: 1274 # ds = self.CHILD_WRAPPER_CLASS(self._conn, ds) 1275 # return ds 1276
1277 - def countChildren (self):
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
1287 - def countChildren_cached (self):
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
1300 - def listChildren (self, ns=None, val=None, params=None):
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 #def listChildren_cached (self): 1331 # """ This version caches all child nodes for all parents, so next parent does not need to search again. 1332 # Good for full depth traversal, but a waste of time otherwise """ 1333 # if self.CHILD_WRAPPER_CLASS is None: #pragma: no cover 1334 # raise NotImplementedError 1335 # if not self._cache.has_key(self.LINK_CLASS): 1336 # pdl = {} 1337 # for link in self._conn.getQueryService().findAll(self.LINK_CLASS, None): 1338 # pid = link.parent.id.val 1339 # if pdl.has_key(pid): 1340 # pdl[pid].append(link.child) 1341 # else: 1342 # pdl[pid] = [link.child] 1343 # self._cache[self.LINK_CLASS] = pdl 1344 # for child in self._cache[self.LINK_CLASS].get(self._oid, ()): 1345 # yield self.CHILD_WRAPPER_CLASS(self._conn, child, self._cache) 1346 1347 @timeit
1348 - def listParents (self, single=True):
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() # TODO: What can I use this for? 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
1366 - def getAncestry (self):
1367 rv = [] 1368 p = self.listParents() 1369 while p: 1370 rv.append(p) 1371 p = p.listParents() 1372 return rv
1373 1374 1382 1383 1390 1391
1392 - def removeAnnotations (self, ns):
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
1400 - def getAnnotation (self, ns=None):
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
1412 - def listAnnotations (self, ns=None):
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
1423 - def _linkAnnotation (self, ann):
1424 if not ann.getId(): 1425 # Not yet in db, save it 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 #else: 1430 # ann.save() 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 #lnk.details.permissions.setUserWrite(True) 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
1442 - def linkAnnotation (self, ann, sameOwner=True):
1443 if sameOwner: 1444 d = self.getDetails() 1445 ad = ann.getDetails() 1446 if self._conn.isAdmin(): 1447 # Keep the annotation owner the same as the linked of object's 1448 if ad.getOwner() and d.getOwner().omeName == ad.getOwner().omeName and d.getGroup().name == ad.getGroup().name: 1449 newConn = ann._conn 1450 else: 1451 p = omero.sys.Principal() 1452 p.name = d.getOwner().omeName 1453 p.group = d.getGroup().name 1454 p.eventType = "User" 1455 newConnId = self._conn.getSessionService().createSessionWithTimeout(p, 60000) 1456 newConn = self._conn.clone() 1457 newConn.connect(sUuid=newConnId.getUuid().val) 1458 clone = self.__class__(newConn, self._obj) 1459 ann = clone._linkAnnotation(ann) 1460 else: 1461 # Try to match group 1462 self._conn.setGroupForSession(d.getGroup()) 1463 ann = self._linkAnnotation(ann) 1464 self._conn.revertGroupForSession() 1465 else: 1466 ann = self._linkAnnotation(ann) 1467 self.unloadAnnotationLinks() 1468 return ann
1469 1470
1471 - def simpleMarshal (self, xtra=None, parents=False):
1472 rv = {'type': self.OMERO_CLASS, 1473 'id': self.getId(), 1474 #'uid': self.getUID(), 1475 'name': self.getName(), 1476 'description': self.getDescription(), 1477 'xref': {},} # TODO remove xref? 1478 if xtra: # TODO check if this can be moved to a more specific place 1479 if xtra.has_key('childCount'): 1480 rv['child_count'] = self.countChildren() 1481 if parents: 1482 def marshalParents (): 1483 return map(lambda x: x.simpleMarshal(), self.getAncestry())
1484 p = timeit(marshalParents)() 1485 rv['parents'] = p 1486 return rv
1487 1488 #def __str__ (self): 1489 # if hasattr(self._obj, 'value'): 1490 # return str(self.value) 1491 # return str(self._obj) 1492
1493 - def __getattr__ (self, attr):
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 # some methods are accessors in _obj and return and omero:: type. The obvious ones we wrap to return a python type 1503
1504 - def getId (self):
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
1514 - def getName (self):
1515 """ 1516 Gets this object name 1517 1518 @return: String or None 1519 """ 1520 1521 return self._obj.getName().val
1522
1523 - def getDescription (self):
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
1533 - def getOwner (self):
1534 """ 1535 Gets user who is the owner of this object. 1536 1537 @return: _ExperimenterWrapper 1538 """ 1539 1540 return self.getDetails().getOwner()
1541
1542 - def getOwnerFullName (self):
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
1563 - def getOwnerOmeName (self):
1564 """ 1565 Gets omeName of the owner of this object. 1566 1567 @return: String 1568 """ 1569 return self.getDetails().getOwner().omeName
1570
1571 - def creationEventDate(self):
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
1587 - def updateEventDate(self):
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 # setters are also provided 1605
1606 - def setName (self, value):
1607 self._obj.setName(omero_type(value))
1608
1609 1610 -class AnnotationWrapper (BlitzObjectWrapper):
1611 """ 1612 omero_model_AnnotationI class wrapper extends BlitzObjectWrapper. 1613 """ 1614 registry = {} 1615 OMERO_TYPE = None 1616
1617 - def __init__ (self, *args, **kwargs):
1618 super(AnnotationWrapper, self).__init__(*args, **kwargs) 1619 if self._obj is None and self.OMERO_TYPE is not None: 1620 self._obj = self.OMERO_TYPE()
1621
1622 - def __eq__ (self, a):
1623 return type(a) == type(self) and self._obj.id == a._obj.id and self.getValue() == a.getValue() and self.getNs() == a.getNs()
1624 1625 @classmethod
1626 - def _register (klass, regklass):
1627 klass.registry[regklass.OMERO_TYPE] = regklass
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: #pragma: no cover 1634 return None
1635 1636 @classmethod 1643
1644 - def getNs (self):
1645 return self._obj.ns.val
1646
1647 - def setNs (self, val):
1648 self._obj.ns = omero_type(val)
1649
1650 - def getValue (self): #pragma: no cover
1651 raise NotImplementedError
1652
1653 - def setValue (self, val): #pragma: no cover
1654 raise NotImplementedError 1655 1656 1657 from omero_model_TimestampAnnotationI import TimestampAnnotationI
1658 1659 -class TimestampAnnotationWrapper (AnnotationWrapper):
1660 """ 1661 omero_model_TimestampAnnotatio class wrapper extends AnnotationWrapper. 1662 """ 1663 1664 OMERO_TYPE = TimestampAnnotationI 1665
1666 - def getValue (self):
1667 return datetime.fromtimestamp(self._obj.timeValue.val / 1000.0)
1668
1669 - def setValue (self, val):
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
1680 1681 -class BooleanAnnotationWrapper (AnnotationWrapper):
1682 """ 1683 omero_model_BooleanAnnotationI class wrapper extends AnnotationWrapper. 1684 """ 1685 1686 OMERO_TYPE = BooleanAnnotationI 1687
1688 - def getValue (self):
1689 return self._obj.boolValue.val
1690
1691 - def setValue (self, val):
1692 self._obj.boolValue = rbool(not not val)
1693 1694 AnnotationWrapper._register(BooleanAnnotationWrapper) 1695 1696 from omero_model_CommentAnnotationI import CommentAnnotationI
1697 1698 -class CommentAnnotationWrapper (AnnotationWrapper):
1699 """ 1700 omero_model_CommentAnnotationI class wrapper extends AnnotationWrapper. 1701 """ 1702 1703 OMERO_TYPE = CommentAnnotationI 1704
1705 - def getValue (self):
1706 return self._obj.textValue.val
1707
1708 - def setValue (self, val):
1709 self._obj.textValue = omero_type(val)
1710 1711 AnnotationWrapper._register(CommentAnnotationWrapper) 1712 1713 from omero_model_LongAnnotationI import LongAnnotationI
1714 1715 -class LongAnnotationWrapper (AnnotationWrapper):
1716 """ 1717 omero_model_LongAnnotationI class wrapper extends AnnotationWrapper. 1718 """ 1719 OMERO_TYPE = LongAnnotationI 1720
1721 - def getValue (self):
1722 return self._obj.longValue.val
1723
1724 - def setValue (self, val):
1725 self._obj.longValue = rlong(val)
1726 1727 AnnotationWrapper._register(LongAnnotationWrapper)
1728 1729 -class _ExperimenterWrapper (BlitzObjectWrapper):
1730 """ 1731 omero_model_ExperimenterI class wrapper extends BlitzObjectWrapper. 1732 """ 1733
1734 - def getDetails (self):
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
1742 1743 -class _ExperimenterGroupWrapper (BlitzObjectWrapper):
1744 """ 1745 omero_model_ExperimenterGroupI class wrapper extends BlitzObjectWrapper. 1746 """ 1747 1748 pass
1749 1750 ExperimenterGroupWrapper = _ExperimenterGroupWrapper
1751 1752 -class DetailsWrapper (BlitzObjectWrapper):
1753 """ 1754 omero_model_DetailsI class wrapper extends BlitzObjectWrapper. 1755 """ 1756
1757 - def __init__ (self, *args, **kwargs):
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
1764 - def getOwner (self):
1765 return self._owner
1766
1767 - def getGroup (self):
1768 return self._group
1769
1770 -class ColorHolder (object):
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
1777 - def __init__ (self, colorname=None):
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
1783 - def fromRGBA(klass,r,g,b,a):
1784 rv = klass() 1785 rv.setRed(r) 1786 rv.setGreen(g) 1787 rv.setBlue(b) 1788 rv.setAlpha(a) 1789 return rv
1790
1791 - def getRed (self):
1792 return self._color['red']
1793
1794 - def setRed (self, val):
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
1803 - def getGreen (self):
1804 return self._color['green']
1805
1806 - def setGreen (self, val):
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
1815 - def getBlue (self):
1816 return self._color['blue']
1817
1818 - def setBlue (self, val):
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
1827 - def getAlpha (self):
1828 return self._color['alpha']
1829
1830 - def setAlpha (self, val):
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
1838 - def getHtml (self):
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
1845 - def getCss (self):
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
1854 - def getRGB (self):
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
1861 -class ChannelWrapper (BlitzObjectWrapper):
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 )
1876 - def __prepare__ (self, idx, re):
1877 self._re = re 1878 self._idx = idx
1879
1880 - def save (self):
1881 self._obj.setPixels(omero.model.PixelsI(self._obj.getPixels().getId(), False)) 1882 return super(ChannelWrapper, self).save()
1883
1884 - def isActive (self):
1885 return self._re.isActive(self._idx)
1886
1887 - def getEmissionWave (self):
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: #pragma: no cover 1893 # This is probably deprecated, as even tinyTest now gets an emissionWave 1894 return self._idx 1895 else: 1896 return emWave.val
1897
1898 - def getColor (self):
1899 return ColorHolder.fromRGBA(*self._re.getRGBA(self._idx))
1900
1901 - def getWindowStart (self):
1902 return int(self._re.getChannelWindowStart(self._idx))
1903
1904 - def setWindowStart (self, val):
1905 self.setWindow(val, self.getWindowEnd())
1906
1907 - def getWindowEnd (self):
1908 return int(self._re.getChannelWindowEnd(self._idx))
1909
1910 - def setWindowEnd (self, val):
1911 self.setWindow(self.getWindowStart(), val)
1912
1913 - def setWindow (self, minval, maxval):
1914 self._re.setChannelWindow(self._idx, float(minval), float(maxval))
1915
1916 - def getWindowMin (self):
1917 return self._obj.getStatsInfo().getGlobalMin().val
1918
1919 - def getWindowMax (self):
1920 return self._obj.getStatsInfo().getGlobalMax().val
1921
1922 -def assert_re (func):
1923 def wrapped (self, *args, **kwargs): 1924 if not self._prepareRenderingEngine(): 1925 return None 1926 return func(self, *args, **kwargs)
1927 return wrapped 1928
1929 -def assert_pixels (func):
1930 def wrapped (self, *args, **kwargs): 1931 if not self._loadPixels(): 1932 return None 1933 return func(self, *args, **kwargs)
1934 return wrapped 1935
1936 -class _ImageWrapper (BlitzObjectWrapper):
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 # projection 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
1957 - def __bstrap__ (self):
1958 self.OMERO_CLASS = 'Image' 1959 self.LINK_CLASS = None 1960 self.CHILD_WRAPPER_CLASS = None 1961 self.PARENT_WRAPPER_CLASS = 'DatasetWrapper'
1962
1963 - def __del__ (self):
1964 self._re and self._re.untaint()
1965
1966 - def __loadedHotSwap__ (self):
1967 self._obj = self._conn.getContainerService().getImages(self.OMERO_CLASS, (self._oid,), None)[0]
1968
1969 - def _loadPixels (self):
1970 if not self._obj.pixelsLoaded: 1971 self.__loadedHotSwap__() 1972 return self._obj.sizeOfPixels() > 0
1973
1974 - def _prepareRE (self):
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: #pragma: no cover 1979 try: 1980 re.resetDefaults() 1981 except omero.ResourceError: 1982 # broken image 1983 return False 1984 re.lookupRenderingDef(pixels_id) 1985 re.load() 1986 return re
1987
1988 - def _prepareRenderingEngine (self):
1989 self._loadPixels() 1990 if self._re is None: 1991 if self._obj.sizeOfPixels() < 1: 1992 return False 1993 if self._pd is None: 1994 self._pd = omero.romio.PlaneDef(self.PLANEDEF) 1995 self._re = self._prepareRE() 1996 return self._re is not None
1997
1998 - def simpleMarshal (self, xtra=None, parents=False):
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
2006 - def shortname(self, length=20, hist=5):
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
2015 - def getAuthor(self):
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
2021 - def getDataset(self):
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: #pragma: no cover 2031 logger.debug(traceback.format_exc()) 2032 return None
2033
2034 - def getProject(self):
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: #pragma: no cover 2044 logger.debug(traceback.format_exc()) 2045 return None
2046
2047 - def getDate(self):
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 # def getDate(self): 2059 # try: 2060 # import time 2061 # query = self._conn.getQueryService() 2062 # event = query.findByQuery("select e from Event e where id = %i" % self._obj.details.creationEvent.id.val, None) 2063 # return time.ctime(event.time.val / 1000) 2064 # except: # pragma: no cover 2065 # logger.debug(traceback.format_exc()) 2066 # self._date = "Today" 2067 # return "Today" 2068
2069 - def _prepareTB (self):
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: #pragma: no cover 2079 tb.resetDefaults() 2080 tb.close() 2081 tb.setPixelsId(pixels_id) 2082 return tb
2083
2084 - def getThumbnail (self, size=(64,64)):
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: #pragma: no cover 2099 logger.error(traceback.print_exc()) 2100 return None
2101 2102 @assert_re
2103 - def getChannels (self):
2104 return [ChannelWrapper(self._conn, c, idx=n, re=self._re) for n,c in enumerate(self._re.getPixels().iterateChannels())]
2105
2106 - def setActiveChannels(self, channels, windows=None, colors=None):
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
2118 - def getProjections (self):
2119 return self.PROJECTIONS.keys()
2120
2121 - def setProjection (self, proj):
2122 self._pr = proj
2123 2124 LINE_PLOT_DTYPES = { 2125 (4, True, True): 'f', # signed float 2126 (2, False, False): 'H', # unsigned short 2127 (2, False, True): 'h', # signed short 2128 (1, False, False): 'B', # unsigned char 2129 (1, False, True): 'b', # signed char 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() # TODO: Assuming ours is a little endian system 2169 # now move data into the windowMin..windowMax range 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):
2183 return self.getPixelLine(z,t,y,'h',channels,range)
2184
2185 - def getCol (self, z, t, x, channels=None, range=None):
2186 return self.getPixelLine(z,t,x,'v',channels,range)
2187 2188 @assert_re
2189 - def getRenderingModels (self):
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
2196 - def getRenderingModel (self):
2197 return BlitzObjectWrapper(self._conn, self._re.getModel())
2198
2199 - def setGreyscaleRenderingModel (self):
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
2207 - def setColorRenderingModel (self):
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
2215 - def isGreyscaleRenderingModel (self):
2216 return self.getRenderingModel().value.lower() == 'greyscale'
2217 2218 @assert_re
2219 - def renderJpeg (self, z, t, compression=0.9):
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: #pragma: no cover 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: #pragma: no cover 2238 logger.debug(traceback.format_exc()) 2239 return None 2240 except Ice.MemoryLimitException: #pragma: no cover 2241 # Make sure renderCompressed isn't called again on this re, as it hangs 2242 self._obj.clearPixels() 2243 self._obj.pixelsLoaded = False 2244 self._re = None 2245 raise
2246
2247 - def renderImage (self, z, t, compression=0.9):
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
2254 - def renderSplitChannel (self, z, t, compression=0.9, border=2):
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
2271 - def splitChannelDims (self, border=2):
2272 c = self.c_count() 2273 # Greyscale, no channel overlayed image 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 # Color, one extra image with all channels overlayed 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
2301 - def renderSplitChannelImage (self, z, t, compression=0.9, border=2):
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 # Font sizes depends on image width 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: #pragma: no cover 2330 fsize = 18 2331 elif w >= 298: #pragma: no cover 2332 fsize = 14 2333 elif w >= 256: #pragma: no cover 2334 fsize = 12 2335 elif w >= 213: #pragma: no cover 2336 fsize = 10 2337 elif w >= 96: #pragma: no cover 2338 fsize = 8 2339 else: #pragma: no cover 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 # Some color 2371 LP_BGCOLOR = 1 # Black 2372 LP_FGCOLOR = 2 # white
2373 - def prepareLinePlotCanvas (self, z, t):
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 # Prepare the palette taking channel colors in consideration 2384 for channel in channels: 2385 pal.extend(channel.getColor().getRGB()) 2386 2387 # Prepare the PIL classes we'll be using 2388 im = Image.new('P', (width, height)) 2389 im.putpalette(pal) 2390 return im, width, height
2391 2392 2393 @assert_re
2394 - def renderRowLinePlotGif (self, z, t, y, linewidth=1):
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 # On your marks, get set... go! 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 # Grab row data 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
2422 - def renderColLinePlotGif (self, z, t, x, linewidth=1):
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 # On your marks, get set... go! 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 # Grab col data 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
2449 - def getZ (self):
2450 return self._pd.z
2451 2452 @assert_re
2453 - def getT (self):
2454 return self._pd.t
2455 2456 @assert_pixels
2457 - def getPixelSizeX (self):
2458 rv = self._obj.getPrimaryPixels().getPhysicalSizeX() 2459 return rv is not None and rv.val or None
2460 2461 @assert_pixels
2462 - def getPixelSizeY (self):
2463 rv = self._obj.getPrimaryPixels().getPhysicalSizeY() 2464 return rv is not None and rv.val or None
2465 2466 @assert_pixels
2467 - def getPixelSizeZ (self):
2468 rv = self._obj.getPrimaryPixels().getPhysicalSizeZ() 2469 return rv is not None and rv.val or None
2470 2471 @assert_pixels
2472 - def getWidth (self):
2473 return self._obj.getPrimaryPixels().getSizeX().val
2474 2475 @assert_pixels
2476 - def getHeight (self):
2477 return self._obj.getPrimaryPixels().getSizeY().val
2478 2479 @assert_pixels
2480 - def z_count (self):
2481 return self._obj.getPrimaryPixels().getSizeZ().val
2482 2483 @assert_pixels
2484 - def t_count (self):
2485 return self._obj.getPrimaryPixels().getSizeT().val
2486 2487 @assert_pixels
2488 - def c_count (self):
2489 return self._obj.getPrimaryPixels().getSizeC().val
2490
2491 - def clearDefaults (self):
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
2510 - def saveDefaults (self):
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
2524 2525 -class _DatasetWrapper (BlitzObjectWrapper):
2526 """ 2527 omero_model_DatasetI class wrapper extends BlitzObjectWrapper. 2528 """ 2529
2530 - def __bstrap__ (self):
2531 self.OMERO_CLASS = 'Dataset' 2532 self.LINK_CLASS = "DatasetImageLink" 2533 self.CHILD_WRAPPER_CLASS = 'ImageWrapper' 2534 self.PARENT_WRAPPER_CLASS = 'ProjectWrapper'
2535
2536 - def __loadedHotSwap__ (self):
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
2544 2545 -class _ProjectWrapper (BlitzObjectWrapper):
2546 """ 2547 omero_model_ProjectI class wrapper extends BlitzObjectWrapper. 2548 """ 2549
2550 - def __bstrap__ (self):
2551 self.OMERO_CLASS = 'Project' 2552 self.LINK_CLASS = "ProjectDatasetLink" 2553 self.CHILD_WRAPPER_CLASS = 'DatasetWrapper' 2554 self.PARENT_WRAPPER_CLASS = None
2555 2556 ProjectWrapper = _ProjectWrapper 2557 2558 #class CategoryWrapper (BlitzObjectWrapper): 2559 # def __bstrap__ (self): 2560 # self.LINK_CLASS = "CategoryImageLink" 2561 # self.CHILD_WRAPPER_CLASS = ImageWrapper 2562 # self.PARENT_WRAPPER_CLASS= 'CategoryGroupWrapper' 2563 # 2564 #class CategoryGroupWrapper (BlitzObjectWrapper): 2565 # def __bstrap__ (self): 2566 # self.LINK_CLASS = "CategoryGroupCategoryLink" 2567 # self.CHILD_WRAPPER_CLASS = CategoryWrapper 2568 # self.PARENT_WRAPPER_CLASS = None 2569