Package MDSplus :: Module tree
[frames] | no frames]

Source Code for Module MDSplus.tree

  1  from mdsdata import Data,makeData 
  2  from threading import RLock,Thread 
3 -class Tree(object):
4 """Open an MDSplus Data Storage Hierarchy""" 5 6 _lock=RLock() 7 _activeTree=None 8
9 - def __del__(self):
10 """Delete Tree instance 11 @rtype: None 12 """ 13 try: 14 try: 15 self.lock() 16 except: 17 pass 18 try: 19 from _treeshr import RTreeCloseAll,TreeCloseAll,TreeFree 20 if self.close: 21 if isinstance(self,CachedTree): 22 RtreeCloseAll(self.ctx) 23 else: 24 TreeCloseAll(self.ctx) 25 if hasattr(self,"ctx") and self.ctx is not None: 26 TreeFree(self.ctx) 27 self.ctx=None 28 except: 29 pass 30 finally: 31 try: 32 self.unlock() 33 except: 34 pass 35 return
36
37 - def __getattr__(self,name):
38 """ 39 Implements value=tree.attribute 40 41 Attributes defined: 42 43 - default - TreeNode, Current default node 44 - modified - bool, True if tree structure has been modified 45 - name - str, Tree name 46 - open_for_edit - bool, True if tree open for edit 47 - open_readonly - boo, True if tree was opened readonly 48 - shot - int, Shot number 49 - shotid - int, Shot number 50 - tree - str, Tree name 51 - versions_in_model - bool, True if versions enabled in the model 52 - versions_in_pulse - bool, True if versions enabled in the pulse 53 54 @param name: Name of attribute 55 @type name: str 56 @return: Value of attribute 57 @rtype: various 58 """ 59 from _treeshr import TreeGetDbi 60 if name.lower() == 'default': 61 ans=self.getDefault() 62 else: 63 if name.lower() == 'shot': 64 name='shotid' 65 elif name.lower() == 'tree': 66 name='name' 67 try: 68 ans = TreeGetDbi(self,name) 69 except KeyError: 70 try: 71 ans = self.__dict__[name] 72 except: 73 raise AttributeError,'No such attribute: '+name 74 return ans
75
76 - def __init__(self,*args):
77 """Create a Tree instance. Specify a tree and shot and optionally a mode. 78 If providing the mode argument it should be one of the following strings: 79 'Normal','Edit','New','ReadOnly'. 80 If no arguments provided, create instance of the active tree. (i.e. Tree()) 81 @param tree: Name of tree to open 82 @type tree: str 83 @param shot: Shot number 84 @type shot: int 85 @param mode: Optional mode, one of 'Normal','Edit','New','Readonly' 86 @type mode: str 87 """ 88 from _treeshr import TreeOpen,TreeOpenNew,TreeOpenReadOnly,TreeGetContext,TreeException 89 try: 90 Tree.lock() 91 self.close=False 92 if len(args)==2: 93 self.ctx=TreeOpen(args[0],args[1]) 94 self.close=True 95 elif len(args)==0: 96 try: 97 self.ctx=TreeGetContext() 98 except: 99 try: 100 self.ctx=Tree._activeTree.ctx 101 except: 102 raise TreeException,'tree not open' 103 elif len(args)==3: 104 if args[2].upper()=='NORMAL': 105 self.ctx=TreeOpen(args[0],args[1]) 106 elif args[2].upper()=='EDIT': 107 self.ctx=TreeOpen(args[0],args[1]) 108 self.edit() 109 elif args[2].upper()=='NEW': 110 self.ctx=TreeOpenNew(args[0],args[1]) 111 elif args[2].upper()=='READONLY': 112 self.ctx=TreeOpenReadOnly(args[0],args[1]) 113 else: 114 raise TreeException,'Invalid mode specificed, use "Normal","Edit","New" or "ReadOnly".' 115 self.close=True 116 else: 117 raise TypeError,"Tree() takes 0,2 or 3 arguments (%d given)" % (len(args),) 118 finally: 119 Tree.unlock() 120 Tree.setActiveTree(self) 121 return
122
123 - def __setattr__(self,name,value):
124 """ 125 Implements tree.attribute=value 126 127 Attributes defined: 128 129 - default - TreeNode, default node in tree 130 - versions_in_model - bool, True to enable versions in model 131 - versions_in_pulse - bool, True to enable versions in pulse 132 133 @param name: Name of attribute to set 134 @type name: str 135 @param value: Value of attribute 136 @type value: various 137 @rtype: None 138 """ 139 if name.lower() in ('modified','name','open_for_edit','open_readonly','shot','shotid','tree'): 140 raise AttributeError,'Read only attribute: '+name 141 elif name == 'default': 142 self.setDefault(value) 143 else: 144 try: 145 from _treeshr import TreeSetDbi 146 TreeSetDbi(self,name,value) 147 except KeyError: 148 self.__dict__[name]=value
149
150 - def __str__(self):
151 """Return string representation 152 @return: String representation of open tree 153 @rtype: str 154 """ 155 if self.open_for_edit: 156 mode="Edit" 157 elif self.open_readonly: 158 mode="Readonly" 159 else: 160 mode="Normal" 161 return self.__class__.__name__+'("%s",%d,"%s")' % (self.tree,self.shot,mode)
162
163 - def addDevice(self,nodename,model):
164 """Add a device to the tree of the specified device model type. 165 @param nodename: Absolute or relative path specification of the head node of the device. All ancestors of node must exist. 166 @type nodename: str 167 @param model: Model name of the device being added. 168 @type model: str 169 @return: Head node of device added 170 @rtype: TreeNode 171 """ 172 from _treeshr import TreeAddConglom 173 from treenode import TreeNode 174 try: 175 Tree.lock() 176 nid=TreeAddConglom(self,str(nodename),str(model)) 177 finally: 178 Tree.unlock() 179 return TreeNode(nid,self)
180
181 - def addNode(self,nodename,usage='ANY'):
182 """Add a node to the tree. Tree must be in edit mode. 183 @param nodename: Absolute or relative path specification of new node. All ancestors of node must exist. 184 @type nodename: str 185 @param usage: Usage of node. 186 @type usage: str 187 @return: Node created. 188 @rtype: TreeNode 189 """ 190 from _treeshr import TreeAddNode 191 from treenode import TreeNode 192 try: 193 Tree.lock() 194 nid = TreeAddNode(self,str(nodename),str(usage)) 195 finally: 196 Tree.unlock() 197 return TreeNode(nid,self)
198
199 - def createPulse(self,shot):
200 """Create pulse. 201 @param shot: Shot number to create 202 @type shot: int 203 @rtype: None 204 """ 205 from _treeshr import TreeException,TreeCreatePulseFile 206 from _mdsshr import MdsGetMsg 207 import ctypes as _C 208 from numpy import array 209 try: 210 Tree.lock() 211 try: 212 subtrees=self.getNodeWild('***','subtree') 213 included=subtrees.nid_number.compress(subtrees.include_in_pulse) 214 included=included.toList() 215 included.insert(0,0) 216 included=numpy(included) 217 status = TreeCreatePulseFile(self.ctx,shot,len(included),_C.c_void_p(included.ctypes.data)) 218 except: 219 status = TreeCreatePulseFile(self.ctx,shot,0,_C.c_void_p(0)) 220 finally: 221 Tree.unlock() 222 if not (status & 1): 223 raise TreeException,"Error creating pulse: %s" % (MdsGetMsg(status),)
224
225 - def deleteNode(self,wild):
226 """Delete nodes (and all their descendants) from the tree. Note: If node is a member of a device, 227 all nodes from that device are also deleted as well as any descendants that they might have. 228 @param wild: Wildcard path speficier of nodes to delete from tree. 229 @type wild: str 230 @rtype: None 231 """ 232 from _treeshr import TreeDeleteNodeInitialize,TreeDeleteNode,TreeDeleteNodeExecute 233 try: 234 Tree.lock() 235 TreeDeleteNodeInitialize(self) 236 nodes=self.getNodeWild(wild) 237 for node in nodes: 238 TreeDeleteNode(self,int(node.nid_number)) 239 TreeDeleteNodeExecute(self) 240 finally: 241 Tree.unlock()
242
243 - def deletePulse(self,shot):
244 """Delete pulse. 245 @param shot: Shot number to delete 246 @type shot: int 247 @rtype: None 248 """ 249 from _treeshr import TreeDeletePulse 250 try: 251 Tree.lock() 252 TreeDeletePulse(self,shot) 253 finally: 254 Tree.unlock()
255
256 - def doMethod(nid,method):
257 """For internal use only. Support for PyDoMethod.fun used for python device support""" 258 from treenode import TreeNode 259 n=TreeNode(nid,Tree()) 260 top=n.conglomerate_nids[0] 261 c=top.record 262 q=c.qualifiers 263 model=c.model 264 for i in range(len(q)): 265 exec str(q[0]) 266 try: 267 exec str('makeData('+model+'(n).'+method+'(Data.getTdiVar("__do_method_arg__"))).setTdiVar("_result")') 268 makeData(1).setTdiVar("_method_status") 269 270 except AttributeError,e: 271 makeData(0xfd180b0).setTdiVar("_method_status") 272 except Exception,e: 273 print "Error doing %s on node %s" % (str(method),str(n)) 274 makeData(0).setTdiVar("_method_status") 275 raise 276 return Data.getTdiVar("_result")
277 doMethod=staticmethod(doMethod) 278
279 - def edit(self):
280 """Open tree for editing. 281 @rtype: None""" 282 from _treeshr import TreeOpenEdit 283 try: 284 Tree.lock() 285 TreeOpenEdit(self) 286 finally: 287 Tree.unlock()
288
289 - def findTags(self,wild):
290 """Find tags matching wildcard expression 291 @param wild: wildcard string to match tagnames. 292 @type wild: str 293 @return: Array of tag names matching wildcard expression 294 @rtype: ndarray 295 """ 296 from _treeshr import TreeFindTagWild 297 try: 298 Tree.lock() 299 tags=TreeFindTagWild(self,wild) 300 finally: 301 Tree.unlock() 302 return tags
303
304 - def getActiveTree(cls):
305 """Get active tree. 306 @return: Current active tree 307 @rtype: Tree 308 """ 309 return cls._activeTree
310 getActiveTree=classmethod(getActiveTree) 311
312 - def getCurrent(treename):
313 """Return current shot for specificed treename 314 @param treename: Name of tree 315 @type treename: str 316 @return: Current shot number for the specified tree 317 @rtype: int 318 """ 319 from _treeshr import TreeGetCurrentShotId,TreeException 320 try: 321 Tree.lock() 322 shot=TreeGetCurrentShotId(treename) 323 finally: 324 Tree.unlock() 325 if shot==0: 326 raise TreeException,"Error obtaining current shot of %s" % (treename,) 327 return shot
328 getCurrent=staticmethod(getCurrent) 329
330 - def getDefault(self):
331 """Return current default TreeNode 332 @return: Current default node 333 @rtype: TreeNode 334 """ 335 from _treeshr import TreeGetDefault 336 from treenode import TreeNode 337 try: 338 Tree.lock() 339 ans = TreeNode(TreeGetDefault(self.ctx),self) 340 finally: 341 Tree.unlock() 342 return ans
343
344 - def getNode(self,name):
345 """Locate node in tree. Returns TreeNode if found. Use double backslashes in node names. 346 @param name: Name of node. Absolute or relative path. No wildcards. 347 @type name: str 348 @return: Node if found 349 @rtype: TreeNode 350 """ 351 from treenode import TreeNode 352 from _treeshr import TreeFindNode 353 if isinstance(name,int): 354 return TreeNode(name,self) 355 else: 356 try: 357 Tree.lock() 358 ans=TreeNode(TreeFindNode(self.ctx,str(name)),self) 359 finally: 360 Tree.unlock() 361 return ans
362
363 - def getNodeWild(self,name,*usage):
364 """Find nodes in tree using a wildcard specification. Returns TreeNodeArray if nodes found. 365 @param name: Node name. May include wildcards. 366 @type name: str 367 @param usage: Optional list of node usages (i.e. "Numeric","Signal",...). Reduces return set by including only nodes with these usages. 368 @type usage: str 369 @return: TreeNodeArray of nodes matching the wildcard path specification and usage types. 370 @rtype: TreeNodeArray 371 """ 372 from treenode import TreeNodeArray 373 try: 374 Tree.lock() 375 self.restoreContext() 376 if len(usage) > 0: 377 from numpy import array 378 for i in range(len(usage)): 379 if not isinstance(usage[i],str): 380 raise TypeError,'Usage arguments must be strings' 381 usage=array(usage) 382 nids=Data.compile('getnci($,"NID_NUMBER",$)',name,usage).evaluate() 383 else: 384 nids=Data.compile('getnci($,"NID_NUMBER")',(name,)).evaluate() 385 finally: 386 Tree.unlock() 387 return TreeNodeArray(nids,self)
388
389 - def getVersionDate():
390 """Get date used for retrieving versions 391 @return: Reference date for retrieving data is versions enabled 392 @rtype: str 393 """ 394 from _treeshr import TreeGetVersionDate 395 return TreeGetVersionDate()
396 getVersionDate=staticmethod(getVersionDate) 397
398 - def isModified(self):
399 """Check to see if tree is open for edit and has been modified 400 @return: True if tree structure has been modified. 401 @rtype: bool 402 """ 403 return self.modified
404
405 - def isOpenForEdit(self):
406 """Check to see if tree is open for edit 407 @return: True if tree is open for edit 408 @rtype: bool 409 """ 410 return self.open_for_edit
411
412 - def isReadOnly(self):
413 """Check to see if tree was opened readonly 414 @return: True if tree is open readonly 415 @rtype: bool 416 """ 417 return self.open_readonly
418
419 - def lock(cls):
420 """Internal use only. Thread synchronization locking. 421 """ 422 cls._lock.acquire()
423 lock=classmethod(lock) 424
425 - def quit(self):
426 """Close edit session discarding node structure and tag changes. 427 @rtype: None 428 """ 429 from _treeshr import TreeQuitTree 430 try: 431 Tree.lock() 432 TreeQuitTree(self) 433 finally: 434 Tree.unlock()
435
436 - def removeTag(self,tag):
437 """Remove a tagname from the tree 438 @param tag: Tagname to remove. 439 @type tag: str 440 @rtype: None 441 """ 442 from _treeshr import TreeRemoveTag 443 TreeRemoveTag(self,tag)
444
445 - def restoreContext(self):
446 """Internal use only. Use internal context associated with this tree.""" 447 from _treeshr import TreeRestoreContext 448 Tree._activeTree=self 449 return TreeRestoreContext(self.ctx)
450
451 - def setActiveTree(cls,tree):
452 """Set active tree. Use supplied tree context when performing tree operations in tdi expressions. 453 @param tree: Tree to use as active tree 454 @type tree: Tree 455 @return: Previous active tree 456 @rtype: Tree 457 """ 458 old=cls._activeTree 459 cls._activeTree=tree 460 tree.restoreContext() 461 return old
462 setActiveTree=classmethod(setActiveTree) 463
464 - def setCurrent(treename,shot):
465 """Set current shot for specified treename 466 @param treename: Name of tree 467 @type treename: str 468 @param shot: Shot number 469 @type shot: int 470 @rtype None 471 """ 472 from _treeshr import TreeSetCurrentShotId,TreeException 473 from _mdsshr import MdsGetMsg 474 try: 475 Tree.lock() 476 status=TreeSetCurrentShotId(treename,shot) 477 finally: 478 Tree.unlock() 479 if not (status & 1): 480 raise TreeException,'Error setting current shot of %s: %s' % (treename,MdsGetMsg(status))
481 setCurrent=staticmethod(setCurrent) 482
483 - def setDefault(self,node):
484 """Set current default TreeNode. 485 @param node: Node to make current default. Relative node paths will use the current default when resolving node lookups. 486 @type node: TreeNode 487 @return: Previous default node 488 @rtype: TreeNode 489 """ 490 from _treeshr import TreeSetDefault 491 from treenode import TreeNode 492 old=self.default 493 if isinstance(node,TreeNode): 494 if node.tree is self: 495 TreeSetDefault(self.ctx,node.nid) 496 else: 497 raise TypeError,'TreeNode must be in same tree' 498 else: 499 raise TypeError,'default node must be a TreeNode' 500 return old
501
502 - def setTimeContext(begin,end,delta):
503 """Set time context for retrieving segmented records 504 @param begin: Time value for beginning of segment. 505 @type begin: Data 506 @param end: Ending time value for segment of data 507 @type end: Data 508 @param delta: Delta time for sampling segment 509 @type delta: Data 510 @rtype: None 511 """ 512 from _treeshr import TreeSetTimeContext 513 TreeSetTimeContext(begin,end,delta)
514 setTimeContext=staticmethod(setTimeContext) 515
516 - def setVersionDate(date):
517 """Set date for retrieving versions if versioning is enabled in tree. 518 @param date: Reference date for data retrieval. Must be specified in the format: 'mmm-dd-yyyy hh:mm:ss' or 'now','today' 519 or 'yesterday'. 520 @type date: str 521 @rtype: None 522 """ 523 from _treeshr import TreeSetVersionDate 524 TreeSetVersionDate(date)
525 setVersionDate=staticmethod(setVersionDate) 526
527 - def setVersionsInModel(self,flag):
528 """Enable/Disable versions in model 529 @param flag: True or False. True enables versions 530 @type flag: bool 531 @rtype: None 532 """ 533 self.versions_in_model=bool(flag)
534
535 - def setVersionsInPulse(self,flag):
536 """Enable/Disable versions in pulse 537 @param flag: True or False. True enabled versions 538 @type flag: bool 539 @rtype: None 540 """ 541 self.versions_in_pulse=bool(flag)
542
543 - def unlock(cls):
544 """Internal use only. Thread synchronization locking. 545 """ 546 cls._lock.release()
547 unlock=classmethod(unlock) 548
549 - def versionsInModelEnabled(self):
550 """Check to see if versions in the model are enabled 551 @return: True if versions in model is enabled 552 @rtype: bool 553 """ 554 return self.versions_in_model
555
556 - def versionsInPulseEnabled(self):
557 """Check to see if versions in the pulse are enabled 558 @return: True if versions in pulse is enabled 559 @rtype: bool 560 """ 561 return self.versions_in_pulse
562
563 - def write(self):
564 """Write out edited tree. 565 @rtype: None 566 """ 567 from _treeshr import TreeWriteTree 568 try: 569 name=self.tree 570 shot=self.shot 571 Tree.lock() 572 TreeWriteTree(self,name,shot) 573 finally: 574 Tree.unlock()
575
576 -class CachedTree(Tree):
577 """MDSplus tree with cached data updating""" 578 579 initialized=False 580 581
582 - def __init__(self,tree,shot):
583 """Initialize CachedTree instance. 584 @param tree: Tree name 585 @type tree: str 586 @param shot: Shot number 587 @type shot: int 588 """ 589 from _treeshr import RTreeOpen 590 try: 591 Tree.lock() 592 self.ctx=RTreeOpen(tree,shot) 593 self.close=True 594 Tree._activeTree=self 595 finally: 596 Tree.unlock() 597 return
598
599 - def getCachedNode(self,name):
600 """Locate node in tree. Returns CachedTreeNode if found. Use double backslashes in node names. 601 @param name: Relative or absolute tree path 602 @type name: str 603 @return: node found 604 @rtype: CachedTreeNode 605 """ 606 from treenode import CachedTreeNode 607 node=self.getNode(name) 608 return CachedTreeNode(node.nid,self)
609
610 - def initialize(cachesize,shared):
611 """ Configure the cachesize and shared settings. Must be called 612 before creating any instance of CachedTree. 613 @param cachesize: Size of cache 614 @type cachesize: int 615 @param shared: Flag indicating whether cache is shared or not. 616 @type shared: bool 617 @rtype: None 618 """ 619 if CachedTree.initialized is False: 620 from _treeshr import RTreeConfigure 621 if shared is True: 622 is_shared=1 623 else: 624 is_shared=0 625 RTreeConfigure(is_shared,cachesize) 626 CachedTree.initialized=True
627 initialize=staticmethod(initialize) 628
629 - def synch():
630 """Wait for all pending write operations in WRITE_THOUGH policy 631 @rtype: None 632 """ 633 from _treeshr import RTreeSynch 634 RTreeSynch()
635 synch=staticmethod(synch)
636