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

Source Code for Module MDSplus.treenode

   1  from mdsdata import Data,makeData 
   2  from mdsscalar import Uint8 
   3  from mdsarray import Int32Array 
   4  from tree import Tree 
   5  import threading 
   6  nciAttributes = ('BROTHER','CACHED','CHILD','CHILDREN_NIDS','MCLASS','CLASS_STR', 
   7                       'COMPRESSIBLE','COMPRESS_ON_PUT','CONGLOMERATE_ELT','CONGLOMERATE_NIDS', 
   8                       'DATA_IN_NCI','DEPTH','DISABLED','DO_NOT_COMPRESS','DTYPE','DTYPE_STR', 
   9                       'ERROR_ON_PUT','ESSENTIAL','FULLPATH','GET_FLAGS','INCLUDE_IN_PULSE', 
  10                       'IO_STATUS','IO_STV','IS_CHILD','IS_MEMBER','LENGTH','MEMBER','MEMBER_NIDS', 
  11                       'MINPATH','NID_NUMBER','NID_REFERENCE','NODE_NAME','NO_WRITE_MODEL', 
  12                       'NO_WRITE_SHOT','NUMBER_OF_CHILDREN','NUMBER_OF_ELTS','NUMBER_OF_MEMBERS','ON', 
  13                       'ORIGINAL_PART_NAME','OWNER_ID','PARENT','PARENT_DISABLED','PARENT_RELATIONSHIP', 
  14                       'PARENT_STATE','PATH','PATH_REFERENCE','RECORD','RFA','RLENGTH','SEGMENTED', 
  15                       'SETUP_INFORMATION','STATE','STATUS','TIME_INSERTED','USAGE','USAGE_ANY', 
  16                       'USAGE_AXIS','USAGE_COMPOUND_DATA','USAGE_DEVICE','USAGE_DISPATCH','USAGE_NONE', 
  17                       'USAGE_NUMERIC','USAGE_STR','USAGE_STRUCTURE','USAGE_SUBTREE','USAGE_TASK', 
  18                       'USAGE_TEXT','USAGE_WINDOW','VERSIONS','WRITE_ONCE') 
  19   
  20  usage_table={'ANY':0,'NONE':1,'STRUCTURE':1,'ACTION':2,'DEVICE':3,'DISPATCH':4,'NUMERIC':5,'SIGNAL':6, 
  21               'TASK':7,'TEXT':8,'WINDOW':9,'AXIS':10,'SUBTREE':11,'COMPOUND_DATA':12,'SUBTREE':-1} 
  22   
23 -class TreeNode(Data):
24 """Class to represent an MDSplus node reference (nid). 25 @ivar nid: node index of this node. 26 @type nid: int 27 @ivar tree: Tree instance that this node belongs to. 28 @type tree: Tree 29 """ 30
31 - def __getattr__(self,name):
32 """ 33 Implements value=node.attribute 34 35 Attributes defined: 36 37 - brother - TreeNode,Next node in tree 38 - child - TreeNode,First ancestor 39 - children_nids - TreeNodeArray, Children nodes 40 - mclass - Uint8, Internal numeric MDSplus descriptor class 41 - class_str - String, Name of MDSplus descriptor class 42 - compressible - Bool, Flag indicating node contains compressible data 43 - compress_on_put - Bool, Flag indicating automatic compression 44 - conglomerate_elt - Int32, Index of node in a conglomerate 45 - conglomerate_nids - TreeNodeArray, Nodes in same conglomerate 46 - data_in_nci - Uint32, Flag indicating data stored in nci record 47 - descendants - TreeNodeArray, One level descendants of this node 48 - depth - Int32, Level of node from the top node of the tree 49 - disabled - Bool, Opposite of on flag 50 - do_not_compress - Bool, Flag indicating data should not be compressed 51 - dtype - Uint8, Internal numeric MDSplus data type 52 - dtype_str - String, Name of MDSplus data type 53 - essential - Bool, Flag indicating node is essential, used for actions 54 - fullpath - String, Full absolute path of node in tree 55 - include_in_pulse - Bool, Flag indicating node should be included in pulse 56 - is_child - Bool, Flag indicating node is a child node 57 - is_member - Bool, Flag indicating node is a member bnode 58 - length - Int32, Length of data in bytes (uncompressed) 59 - member - TreeNode, First member of this node 60 - member_nids - TreeNodeArray, Members nodes 61 - minpath - String, Minimum length string representing path to node 62 - nid_number - Int32, Internal index to node in tree 63 - nid_reference - Bool, Flag indicating that data contains references to nodes 64 - node_name - String, This nodes name 65 - no_write_model - Bool, Flag indicating that data cannot be written into model 66 - no_write_shot - Bool, Flag indicating that data cannot be written into shot 67 - number_of_children - Int32, Number of children of this node 68 - number_of_descentants - Int32, Numer of first level descendants 69 - number_of elts - Int32, Number of nodes in this conglomerate 70 - number_of_members - Int32, Number of members of this node 71 - on - Bool, Flag indicating if this node is turned on 72 - original_part_name - String, Original node name when conglomerate was created 73 - owner_id - Int32, Id/gid of account which stored the data 74 - parent - TreeNode, Parent of this node 75 - parent_disabled - Bool, Flag indicating parent is turned off 76 - path - String, Path to this node 77 - path_reference - Bool, Flag indicating that data contains references to nodes 78 - record - Data, Contents of this node 79 - rfa - Int64, Byte offset to this node 80 - rlength - Int32, Data length in bytes (compressed) 81 - segmented - Bool, Flag indicating node contains segmented records 82 - setup_information - Bool, Flag indicating node contains setup information 83 - status - Int32, Completion status of action 84 - tags - StringArray, List of tagnames for this node 85 - time_inserted - Uint64, Time data was inserted 86 - usage - String, Usage of this node 87 - versions - Bool, Flag indicating that data contains versions 88 - write_once - Bool, Flag indicating that data can only be written if node is empty. 89 @param name: Name of attribute 90 @type name: str 91 @return: Value of attribute 92 @rtype: various 93 """ 94 95 from mdsscalar import String 96 if name.lower() == 'nid': 97 try: 98 return self.__dict__['nid'] 99 except KeyError: 100 try: 101 return self.tree.getNode(self.tree_path) 102 except: 103 return None 104 return self.tree.getNode(str(self)) 105 try: 106 return self.__dict__[name] 107 except: 108 pass 109 if name.lower() == 'record': 110 return self.getData() 111 if name.lower() == 'tags': 112 return self.getTags() 113 if name.lower() == 'usage': 114 return String(self.usage_str.value[10:]) 115 if name.lower() == 'descendants': 116 return self.getDescendants() 117 if name.lower() == 'number_of_descendants': 118 return self.number_of_members+self.number_of_children 119 if name.lower() == 'segmented': 120 return self.getNumSegments().value > 0 121 if name.upper() in nciAttributes: 122 from _tdishr import TdiException 123 try: 124 if name.lower() == 'mclass': 125 name='class'; 126 Tree.lock() 127 self.restoreContext() 128 try: 129 ans = Data.execute('getnci($,$)',self,name) 130 if isinstance(ans,Uint8): 131 if name not in ('class','dtype'): 132 ans = bool(ans) 133 except TdiException,e: 134 if 'TreeNNF' in str(e): 135 ans=None 136 else: 137 raise 138 finally: 139 Tree.unlock() 140 if isinstance(ans,String): 141 return String(ans.rstrip()) 142 return ans 143 raise AttributeError,'Attribute %s is not defined' % (name,)
144
145 - def __init__(self,n,tree=None):
146 """Initialze TreeNode 147 @param n: Index of the node in the tree. 148 @type n: int 149 @param tree: Tree associated with this node 150 @type tree: Tree 151 """ 152 self.__dict__['nid']=int(n); 153 if tree is None: 154 try: 155 self.tree=Tree._activeTree 156 except: 157 self.tree=Tree() 158 else: 159 self.tree=tree
160
161 - def __setattr__(self,name,value):
162 """ 163 Implements node.attribute=value 164 165 Attributes which can be set: 166 167 - compress_on_put - Bool, Flag indicating whether data should be compressed when written 168 - do_not_compress - Bool, Flag to disable compression 169 - essential - Bool, Flag indicating successful action completion required 170 - include_in_pulse - Bool, Flag to include in pulse 171 - no_write_model - Bool, Flag to disable writing in model 172 - no_write_shot - Bool, Flag to disable writing in pulse file 173 - record - Data, Data contents of node 174 - subtree - Bool, Set node to be subtree or not (edit mode only) 175 - tag - str, Add tag to node (edit mode only) 176 - write_once - Bool, Flag to only allow writing to empty node 177 @param name: Name of attribute 178 @type name: str 179 @param value: Value for attribute 180 @type value: various 181 @rtype: None 182 """ 183 uname=name.upper() 184 if uname=="RECORD": 185 self.putData(value) 186 elif uname=="ON": 187 self.setOn(value) 188 elif uname=="NO_WRITE_MODEL": 189 self.setNoWriteModel(value) 190 elif uname=="NO_WRITE_SHOT": 191 self.setNoWriteShot(value) 192 elif uname=="WRITE_ONCE": 193 self.setWriteOnce(value) 194 elif uname=="INCLUDE_IN_PULSE": 195 self.setIncludedInPulse(value) 196 elif uname=="COMPRESS_ON_PUT": 197 self.setCompressOnPut(value) 198 elif uname=="DO_NOT_COMPRESS": 199 self.setDoNotCompress(value) 200 elif uname=="ESSENTIAL": 201 self.setEssential(value) 202 elif uname=="SUBTREE": 203 self.setSubtree(value) 204 elif uname=="TAG": 205 self.addTag(value) 206 elif uname in nciAttributes: 207 raise AttributeError,'Attribute %s is read only' %(name,) 208 elif uname == "NID": 209 raise AttributeError,'Attribute nid is read only' 210 else: 211 self.__dict__[name]=value
212
213 - def __setNode(self,qualifier,flag,reversed=False):
214 """For internal use only""" 215 self.restoreContext() 216 if flag is True or flag is False: 217 if reversed is True: 218 flag = not flag 219 if flag is True: 220 switch="/" 221 else: 222 if flag is False: 223 switch="/no" 224 else: 225 raise TypeError,'Argument must be True or False' 226 try: 227 Tree.lock() 228 self.restoreContext() 229 cmd='tcl("set node \\'+self.fullpath+switch+qualifier+'")' 230 status = Data.compile(cmd).evaluate() 231 if not (status & 1): 232 from _descriptor import MdsGetMsg 233 from _treeshr import TreeException 234 msg=MdsGetMsg(int(status)) 235 if 'TreeFAILURE' in msg: 236 raise TreeException,'Error writing to tree, possibly file protection problem' 237 else: 238 raise TreeException,msg 239 finally: 240 Tree.unlock() 241 return
242
243 - def __str__(self):
244 """Convert TreeNode to string.""" 245 from _treeshr import TreeGetPath 246 if self.nid is None: 247 ans="NODEREF(*)" 248 else: 249 ans=TreeGetPath(self) 250 return ans
251
252 - def addDevice(self,name,model):
253 """Add device descendant. 254 @param name: Node name of device. 1-12 characters, no path delimiters 255 @type name: str 256 @param model: Type of device to add 257 @type model: str 258 @return: Head node of device 259 @rtype: TreeNode 260 """ 261 if name.find(':') >=0 or name.find('.') >= 0: 262 from _treeshr import TreeException 263 raise TreeException,"Invalid node name, do not include path delimiters in nodename" 264 return self.tree.addDevice(self.fullpath+":"+name.upper(),model)
265
266 - def addNode(self,name,usage='ANY'):
267 """Add node 268 @param name: Node name of new node to add 269 @type name: str 270 @param usage: Usage of the new node. If omitted set to ANY. 271 @type usage: str 272 @return: New now added 273 @rtype: TreeNode 274 """ 275 try: 276 usagenum=usage_table[usage.upper()] 277 except KeyError: 278 raise KeyError,'Invalid usage specified. Use one of %s' % (str(usage_table.keys()),) 279 name=str(name).upper() 280 if name[0]==':' or name[0]=='.': 281 name=str(self.fullpath)+name 282 elif name[0] != "\\": 283 if usagenum==1 or usagenum==-1: 284 name=str(self.fullpath)+"."+name 285 else: 286 name=self.fullpath+":"+name 287 return self.tree.addNode(name,usage)
288
289 - def addTag(self,tag):
290 """Add a tagname to this node 291 @param tag: tagname for this node 292 @type tag: str 293 @rtype: None 294 """ 295 from _treeshr import TreeAddTag 296 TreeAddTag(self.tree,self.nid,str(tag))
297
298 - def beginSegment(self,start,end,dimension,initialValueArray,idx=-1):
299 """Begin a record segment 300 @param start: Index of first row of data 301 @type start: Data 302 @param end: Index of last row of data 303 @type end: Data 304 @param dimension: Dimension information of segment 305 @type dimension: Dimension 306 @param initialValueArray: Initial data array. Defines shape of segment 307 @type initialValueArray: Array 308 @rtype: None 309 """ 310 try: 311 Tree.lock() 312 self.restoreContext() 313 status=Data.execute('BeginSegment($,$,$,$,$,$)',self.nid,start,end,dimension,initialValue,idx) 314 if not (status & 1)==1: 315 raise TreeException,'Error beginning segment:'+MdsGetMsg(int(status)) 316 finally: 317 Tree.unlock() 318 return
319
320 - def beginTimestampedSegment(self,array,idx=-1):
321 """Allocate space for a timestamped segment 322 @param array: Initial data array to define shape of segment 323 @type array: Array 324 @param idx: Optional segment index. Defaults to -1 meaning next segment. 325 @type idx: int 326 @rtype: None 327 """ 328 try: 329 Tree.lock() 330 self.restoreContext() 331 status=Data.execute('BeginTimestampedSegment($,$,$)',self.nid,array,idx) 332 if not (status & 1)==1: 333 raise TreeException,'Error beginning timestampd segment:'+MdsGetMsg(int(status)) 334 finally: 335 Tree.unlock() 336 return
337
338 - def containsVersions(self):
339 """Return true if this node contains data versions 340 @return: True if node contains versions 341 @rtype: bool 342 """ 343 return self.versions
344
345 - def delete(self):
346 """Delete this node from the tree 347 @rtype: None 348 """ 349 self.tree.deleteNode(self.fullpath)
350
351 - def deleteData(self):
352 """Delete data from this node 353 @rtype: None 354 """ 355 self.putData(None) 356 return
357
358 - def doMethod(self,method,arg=None):
359 """Execute method on conglomerate element 360 @param method: method name to perform 361 @type method: str 362 @param arg: Optional argument for method 363 @type arg: Data 364 @rtype: None 365 """ 366 from _treeshr import TreeDoMethod 367 try: 368 Tree.lock() 369 self.restoreContext() 370 TreeDoMethod(self,str(method),arg) 371 finally: 372 Tree.unlock() 373 return
374
375 - def getBrother(self):
376 """Return sibling of this node 377 @return: Sibling of this node 378 @rtype: TreeNode 379 """ 380 return self.brother
381
382 - def getChild(self):
383 """Return first child of this node. 384 @return: Return first child of this node or None if it has no children. 385 @rtype: TreeNode 386 """ 387 return self.child
388
389 - def getChildren(self):
390 """Return TreeNodeArray of children nodes. 391 @return: Children of this node 392 @rtype: TreeNodeArray 393 """ 394 return self.children_nids
395
396 - def getClass(self):
397 """Return MDSplus class name of this node 398 @return: MDSplus class name of the data stored in this node. 399 @rtype: String 400 """ 401 return self.class_str
402
403 - def getCompressedLength(self):
404 """Return compressed data length of this node 405 @return: Compress data length of this node 406 @rtype: int 407 """ 408 return self.rlength
409
410 - def getConglomerateElt(self):
411 """Return index of this node in a conglomerate 412 @return: element index of this node in a conglomerate. 0 if not in a conglomerate. 413 @rtype: Int32 414 """ 415 return self.conglomerate_elt
416
417 - def getConglomerateNodes(self):
418 """Return TreeNodeArray of conglomerate elements 419 @return: Nodes in this conglomerate. 420 @rtype: TreeNodeArray 421 """ 422 return self.conglomerate_nids
423
424 - def getData(self):
425 """Return data 426 @return: data stored in this node 427 @rtype: Data 428 """ 429 from _treeshr import TreeGetRecord 430 return TreeGetRecord(self)
431
432 - def getDepth(self):
433 """Get depth of this node in the tree 434 @return: number of levels between this node and the top of the currently opened tree. 435 @rtype: Int32 436 """ 437 return self.depth
438
439 - def getDescendants(self):
440 """Return TreeNodeArray of first level descendants (children and members). 441 @return: First level descendants of this node 442 @rtype: TreeNodeArray 443 """ 444 try: 445 members=self.member_nids 446 try: 447 children=self.children_nids 448 ans=list() 449 for i in range(len(members)): 450 ans.append(members.nids[i].value) 451 for i in range(len(children)): 452 ans.append(children.nids[i].value) 453 return TreeNodeArray(Int32Array(ans)) 454 except: 455 return members 456 except: 457 try: 458 return self.children_nids 459 except: 460 return None
461
462 - def getDtype(self):
463 """Return the name of the data type stored in this node 464 @return: MDSplus data type name of data stored in this node. 465 @rtype: String 466 """ 467 return self.dtype_str
468
469 - def getFullPath(self):
470 """Return full path of this node 471 @return: full path specification of this node. 472 @rtype: String 473 """ 474 return self.fullpath
475
476 - def getLength(self):
477 """Return uncompressed data length of this node 478 @return: Uncompressed data length of this node 479 @rtype: int 480 """ 481 return self.length
482
483 - def getMember(self):
484 """Return first member node 485 @return: First member of thie node 486 @rtype: TreeNode 487 """ 488 return self.member
489
490 - def getMembers(self):
491 """Return TreeNodeArray of this nodes members 492 @return: members of this node 493 @rtype: TreeNodeArray 494 """ 495 return self.member_nids
496
497 - def getMinPath(self):
498 """Return shortest path string for this node 499 @return: shortest path designation depending on the current node default and whether the node has tag names or not. 500 @rtype: String 501 """ 502 return self.minpath
503
504 - def getNid(self):
505 """Return node index 506 @return: Internal node index of this node 507 @rtype: int 508 """ 509 return self.nid
510
511 - def getNodeName(self):
512 """Return node name 513 @return: Node name of this node. 1 to 12 characters 514 @rtype: String 515 """ 516 return self.node_name
517
518 - def getNumChildren(self):
519 """Return number of children nodes. 520 @return: Number of children 521 @rtype: Int32 522 """ 523 return self.number_of_children
524
525 - def getNumDescendants(self):
526 """Return number of first level descendants (children and members) 527 @return: total number of first level descendants of this node 528 @rtype: int 529 """ 530 return self.number_of_descendants
531
532 - def getNumElts(self):
533 """Return number of nodes in this conglomerate 534 @return: Number of nodes in this conglomerate or 0 if not in a conglomerate. 535 @rtype: Int32 536 """ 537 return self.number_of_elts
538
539 - def getNumMembers(self):
540 """Return number of members 541 @return: number of members 542 @rtype: int 543 """ 544 return self.number_of_members
545
546 - def getNumSegments(self):
547 """return number of segments contained in this node 548 @rtype: int 549 """ 550 from _treeshr import TreeGetNumSegments 551 return makeData(TreeGetNumSegments(self))
552
553 - def getOriginalPartName(self):
554 """Return the original part name of node in conglomerate 555 @return: Original part name of this node when conglomerate was first instantiated. 556 @rtype: String 557 """ 558 return self.original_part_name
559
560 - def getOwnerId(self):
561 """Get id/gid value of account which wrote data to this node 562 @return: Return user id of last account used to write data to this node 563 @rtype: int 564 """ 565 return self.owner_id
566
567 - def getParent(self):
568 """Return parent of this node 569 @return: Parent of this node 570 @rtype: TreeNode 571 """ 572 return self.parent
573
574 - def getPath(self):
575 """Return path of this node 576 @return: Path to this node. 577 @rtype: String 578 """ 579 return self.path
580
581 - def getSegment(self,idx):
582 """Return segment 583 @param idx: The index of the segment to return. Indexes start with 0. 584 @type idx: int 585 @return: Data segment 586 @rtype: Signal | None 587 """ 588 num=self.getNumSegments() 589 if num > 0 and idx < num: 590 try: 591 Tree.lock() 592 self.restoreContexT() 593 ans = Data.execute('getSegment($,$)',self.nid,idx) 594 finally: 595 Tree.unlock() 596 return ans 597 else: 598 return None
599
600 - def getSegmentDim(self,idx):
601 """Return dimension of segment 602 @param idx: The index of the segment to return. Indexes start with 0. 603 @type idx: int 604 @return: Segment dimension 605 @rtype: Dimension 606 """ 607 num=self.getNumSegments() 608 if num > 0 and idx < num: 609 return self.getSegment(idx).getDimension(0) 610 else: 611 return None
612
613 - def getSegmentEnd(self,idx):
614 """return end of segment 615 @param idx: segment index to query 616 @type idx: int 617 @rtype: Data 618 """ 619 num=self.getNumSegments() 620 if num > 0 and idx < num: 621 try: 622 Tree.lock() 623 self.restoreContext() 624 l=Data.execute('getSegmentLimits($,$)',self.nid,idx) 625 finally: 626 Tree.unlock() 627 return l[1] 628 else: 629 return None
630
631 - def getSegmentStart(self,idx):
632 """return start of segment 633 @param idx: segment index to query 634 @type idx: int 635 @rtype: Data 636 """ 637 num=self.getNumSegments() 638 if num > 0 and idx < num: 639 try: 640 Tree.lock() 641 self.restoreContext() 642 l=Data.execute('getSegmentLimits($,$)',self.nid,idx) 643 finally: 644 Tree.unlock() 645 return l[0] 646 else: 647 return None
648
649 - def doSetup(self):
650 import os,gtk 651 from widgets import MDSplusWidget 652 headnode=self.conglomerate_nids[0] 653 devtype=str(headnode.record.model).lower() 654 try: 655 window=gtk.glade.XML(os.getenv("MDSPLUS_DEVICE_PATH","/home/twf/mdsplus/mdsobjects/python")+os.sep+devtype+".glade").get_widget(devtype) 656 window.device_node=self 657 window.set_title(window.get_title()+' - '+str(self)+' - '+str(self.tree)) 658 MDSplusWidget.resetAll(window) 659 except Exception,e: 660 raise Exception,"No setup available, %s" % (str(e),) 661 window.connect("destroy",self.onSetupWindowClose) 662 window.show_all() 663 self.startGtkThread()
664
665 - def onSetupWindowClose(self,window):
666 import gtk 667 windows=[toplevel for toplevel in gtk.window_list_toplevels() 668 if toplevel.get_property('type') == gtk.WINDOW_TOPLEVEL] 669 if len(windows) == 1: 670 gtk.main_quit()
671 672
673 - def startGtkThread(cls):
674 class gtkMain(threading.Thread): 675 def run(self): 676 import gtk 677 gtk.gdk.threads_init() 678 print "about to start gtk.main()" 679 #gtk.gdk.threads_enter() 680 gtk.main() 681 print "done with gtk.main()"
682 #gtk.gdk.threads_leave() 683 684 try: 685 running=cls.gtkThread.isAlive() 686 except: 687 running=False 688 if not running: 689 cls.gtkThread=gtkMain() 690 cls.gtkThread.start() 691 startGtkThread=classmethod(startGtkThread) 692
693 - def waitForSetups(cls):
694 import gtk 695 #gtk.main() 696 cls.gtkThread.join()
697 waitForSetups=classmethod(waitForSetups) 698
699 - def getStatus(self):
700 """Return action completion status 701 @return: action completion status stored by dispatcher if this node is a dispacted action. Low bit set is success. 702 @rtype: int 703 """ 704 return self.status
705
706 - def getTimeInserted(self):
707 """Return time data was written 708 @return: time data was written to this node as Uint64. Use answer.date to retrieve date/time string 709 @rtype: Uint64 710 """ 711 return self.time_inserted
712
713 - def getTags(self):
714 """Return tags of this node 715 @return: Tag names pointing to this node 716 @rtype: ndarray 717 """ 718 from _treeshr import TreeFindNodeTags 719 try: 720 Tree.lock() 721 ans=TreeFindNodeTags(self) 722 finally: 723 Tree.unlock() 724 return ans
725
726 - def getTree(self):
727 """Return Tree associated with this node 728 @return: Tree associated with this node 729 @rtype: Tree 730 """ 731 return self.tree
732
733 - def getUsage(self):
734 """Return usage of this node 735 @return: usage of this node 736 @rtype: str 737 """ 738 return self.usage
739
740 - def isChild(self):
741 """Return true if this is a child node 742 @return: True if this is a child node instead of a member node. 743 @rtype: bool 744 """ 745 return self.is_child
746
747 - def isCompressible(self):
748 """Return true if node contains data which can be compressed 749 @return: True of this node contains compressible data 750 @rtype: bool 751 """ 752 return self.compressible
753
754 - def isCompressOnPut(self):
755 """Return true if node is set to compress on put 756 @return: True if compress on put 757 @rtype: bool 758 """ 759 return self.compress_on_put
760
761 - def isDoNotCompress(self):
762 """Return true of compression is disabled for this node 763 @return: True if this node has compression disabled 764 @rtype: bool 765 """ 766 return self.do_not_compress
767
768 - def isEssential(self):
769 """Return true if successful action completion is essential 770 @return: True if this node is marked essential. 771 @rtype: bool 772 """ 773 return self.essential
774
775 - def isIncludedInPulse(self):
776 """Return true if this subtree is to be included in pulse file 777 @return: True if subtree is to be included in pulse file creation. 778 @rtype: bool 779 """ 780 return self.include_in_pulse
781
782 - def isMember(self):
783 """Return true if this is a member node 784 @return: True if this is a member node 785 @rtype: bool 786 """ 787 return self.is_member
788
789 - def isNoWriteModel(self):
790 """Return true if data storage to model is disabled for this node 791 @return: Return True if storing data in this node in the model tree is disabled 792 @rtype: bool 793 """ 794 return self.no_write_model
795
796 - def isNoWriteShot(self):
797 """Return true if data storage to pulse file is disabled for this node 798 @return: Return True if storing data in this node in the pulse tree is disabled 799 @rtype: bool 800 """ 801 return self.no_write_shot
802
803 - def isOn(self):
804 """Return True if node is turned on, False if not. 805 @return: Return True if node is turned on 806 @rtype: bool 807 """ 808 return self.on
809
810 - def isSegmented(self):
811 """Return true if this node contains segmented records 812 @return: True if node contains segmented records 813 @rtype: bool 814 """ 815 return self.segmented
816
817 - def isSetup(self):
818 """Return true if data is setup information. 819 @return: True if data is setup information (originally written in the model) 820 @rtype: bool 821 """ 822 return self.setup_information
823
824 - def isWriteOnce(self):
825 """Return true if node is set write once 826 @return: Return True if data overwrite in this node is disabled 827 @rtype: bool 828 """ 829 return self.write_once
830
831 - def move(self,parent,newname=None):
832 """Move node to another location in the tree and optionally rename the node 833 @param parent: New parent of this node 834 @type parent: TreeNode 835 @param newname: Optional new node name of this node. 1-12 characters, no path delimiters. 836 @type newname: str 837 @rtype: None 838 """ 839 from _treeshr import TreeRenameNode 840 if newname is None: 841 newname=str(self.node_name) 842 if self.usage=='SUBTREE' or self.usage=='STRUCTURE': 843 TreeRenameNode(self,str(parent.fullpath)+"."+newname) 844 else: 845 TreeRenameNode(self,str(parent.fullpath)+":"+newname)
846
847 - def putData(self,data):
848 """Store data 849 @param data: Data to store in this node. 850 @type data: Data 851 @rtype: None 852 """ 853 from _treeshr import TreePutRecord 854 try: 855 Tree.lock() 856 TreePutRecord(self,data) 857 finally: 858 Tree.unlock() 859 return
860
861 - def putRow(self,bufsize,array,timestamp):
862 """Load a timestamped segment row 863 @param bufsize: number of rows in segment 864 @type bufsize: int 865 @param array: data for this row 866 @type array: Array or Scalar 867 @param timestamp: Timestamp of this row 868 @type timestamp: Uint64 869 @rtype: None 870 """ 871 try: 872 Tree.lock() 873 status=Data.execute('putRow($,$,$,$)',self.nid,bufsize,timestamp,array) 874 if not (status & 1)==1: 875 raise TreeException,'Error putting timestampd row:'+MdsGetMsg(int(status)) 876 finally: 877 Tree.unlock() 878 return
879
880 - def putSegment(self,data,idx):
881 """Load a segment in a node 882 @param data: data to load into segment 883 @type data: Array or Scalar 884 @param idx: index into segment to load data 885 @type idx: int 886 @rtype: None 887 """ 888 try: 889 Tree.lock() 890 self.restoreContext() 891 status=Data.execute('PutSegment($,$,$)',self.nid,idx,data) 892 if not (status & 1)==1: 893 raise TreeException,'Error putting segment:'+MdsGetMsg(int(status)) 894 finally: 895 Tree.unlock() 896 return
897
898 - def putTimestampedSegment(self,array,timestampArray):
899 """Load a timestamped segment 900 @param array: Data to load into segment 901 @type array: Array 902 @param timestampArray: Array of time stamps 903 @type timestampArray: Uint64Array 904 @rtype: None 905 """ 906 try: 907 Tree.lock() 908 self.restoreContext() 909 status=Data.execute('putTimestampedSegment($,$,$)',self.nid,timestampArray,array) 910 if not (status & 1)==1: 911 raise TreeException,'Error putting timestampd segment:'+MdsGetMsg(int(status)) 912 finally: 913 Tree.unlock() 914 return
915
916 - def removeTag(self,tag):
917 """Remove a tagname from this node 918 @param tag: Tagname to remove from this node 919 @type tag: str 920 @rtype: None 921 """ 922 from _treeshr import TreeException 923 try: 924 n=self.tree.getNode('\\'+str(tag)) 925 if n.nid != self.nid: 926 raise TreeException,"Node %s does not have a tag called %s. That tag refers to %s" % (str(self),str(tag),str(n)) 927 except TreeException,e: 928 print e 929 if str(e).find('TreeNNF') > 0: 930 raise TreeException,"Tag %s is not defined" % (str(tag),) 931 else: 932 raise 933 self.tree.removeTag(tag)
934
935 - def rename(self,newname):
936 """Rename node this node 937 @param newname: new name of this node. 1-12 characters, no path delimiters. 938 @type newname: str 939 @rtype: None 940 """ 941 from _treeshr import TreeRenameNode,TreeException 942 if newname.find(':') >=0 or newname.find('.') >= 0: 943 raise TreeException,"Invalid node name, do not include path delimiters in nodename" 944 try: 945 olddefault=self.tree.default 946 self.tree.setDefault(self.parent) 947 if self.isChild(): 948 newname="."+str(newname) 949 TreeRenameNode(self,str(newname)) 950 finally: 951 self.tree.setDefault(olddefault)
952
953 - def restoreContext(self):
954 """Restore tree context. Used by internal functions. 955 @rtype: None 956 """ 957 if self.tree is not None: 958 self.tree.restoreContext()
959
960 - def setCompressOnPut(self,flag):
961 """Set compress on put state of this node 962 @param flag: State to set the compress on put characteristic 963 @type flag: bool 964 @rtype: None 965 """ 966 self.__setNode('compress_on_put',flag)
967
968 - def setDoNotCompress(self,flag):
969 """Set do not compress state of this node 970 @param flag: True do disable compression, False to enable compression 971 @type flag: bool 972 @rtype: None 973 """ 974 self.__setNode('do_not_compress',flag) 975 return
976
977 - def setEssential(self,flag):
978 """Set essential state of this node 979 @param flag: State to set the essential characteristic. This is used on action nodes when phases are dispacted. 980 @type flag: bool 981 @rtype: None 982 """ 983 return self.__setNode('essential',flag)
984
985 - def setIncludedInPulse(self,flag):
986 """Set include in pulse state of this node 987 @param flag: State to set the include in pulse characteristic. If true and this node is the top node of a subtree the subtree will be included in the pulse. 988 @type flag: bool 989 @rtype: None 990 """ 991 return self.__setNode('included',flag)
992
993 - def setNoWriteModel(self,flag):
994 """Set no write model state for this node 995 @param flag: State to set the no write in model characteristic. If true then no data can be stored in this node in the model. 996 @type flag: bool 997 @rtype: None 998 """ 999 self.__setNode('model_write',not flag) 1000 return
1001
1002 - def setNoWriteShot(self,flag):
1003 """Set no write shot state for this node 1004 @param flag: State to set the no write in shot characteristic. If true then no data can be stored in this node in a shot file. 1005 @type flag: bool 1006 @rtype: None 1007 """ 1008 self.__setNode('shot_write',not flag) 1009 return
1010
1011 - def setOn(self,flag):
1012 """Turn node on or off 1013 @param flag: State to set the on characteristic. If true then the node is turned on. If false the node is turned off. 1014 @type flag: bool 1015 @rtype: None 1016 """ 1017 from _treeshr import TreeTurnOn,TreeTurnOff 1018 try: 1019 Tree.lock() 1020 if flag is True: 1021 TreeTurnOn(self) 1022 else: 1023 if flag is False: 1024 TreeTurnOff(self) 1025 else: 1026 raise TypeError,'argument must be True or False' 1027 finally: 1028 Tree.unlock() 1029 return
1030
1031 - def setSubtree(self,flag):
1032 """Enable/Disable node as a subtree 1033 @param flag: True to make node a subtree reference. Node must be a child node with no descendants. 1034 @type flag: bool 1035 @rtype: None 1036 """ 1037 from _treeshr import TreeSetSubtree 1038 TreeSetSubtree(self,flag)
1039
1040 - def setTree(self,tree):
1041 """Set Tree associated with this node 1042 @param tree: Tree instance to associated with this node 1043 @type tree: Tree 1044 @rtype: None 1045 """ 1046 self.tree=tree
1047
1048 - def setWriteOnce(self,flag):
1049 """Set write once state of node 1050 @param flag: State to set the write once characteristic. If true then data can only be written if the node is empty. 1051 @type flag: bool 1052 @rtype: None 1053 """ 1054 self.__setNode('write_once',flag) 1055 return
1056
1057 - def updateSegment(self,start,end,dim,idx):
1058 """Update a segment 1059 @param start: index of first row of segment 1060 @type start: Data 1061 @param end: index of last row of segment 1062 @type end: Data 1063 @param dim: Dimension of segment 1064 @type dim: Dimension 1065 @param idx: Index of segment 1066 @type idx: int 1067 @rtype: None 1068 """ 1069 try: 1070 Tree.lock() 1071 self.restoreContext() 1072 status=Data.execute('TreeShr->TreeUpdateSegment(val($),descr($),descr($),descr($),val($))',self.nid,start,end,dim,idx) 1073 if not (status & 1)==1: 1074 raise TreeException,'Error beginning segment:'+MdsGetMsg(int(status)) 1075 finally: 1076 Tree.unlock() 1077 return
1078
1079 -class TreePath(TreeNode):
1080 """Class to represent an MDSplus node reference (path)."""
1081 - def __init__(self,path,tree=None):
1082 self.tree_path=makeData(path); 1083 if tree is None: 1084 self.tree=Tree._activeTree 1085 else: 1086 self.tree=tree 1087 return
1088
1089 - def __str__(self):
1090 """Convert path to string.""" 1091 return self.tree_path.value
1092
1093 -class TreeNodeArray(Data):
1094 - def __init__(self,nids,tree=None):
1095 self.nids=nids 1096 if tree is None: 1097 self.tree=Tree._activeTree 1098 else: 1099 self.tree=tree
1100
1101 - def __getitem__(self,n):
1102 """Return TreeNode from mdsarray. array[n] 1103 @param n: Index into array beginning with index 0 1104 @type n: int 1105 @return: node 1106 @rtype: TreeNode 1107 """ 1108 ans=TreeNode(self.nids[n],self.tree) 1109 return ans
1110
1111 - def restoreContext(self):
1112 self.tree.restoreContext()
1113
1114 - def getPath(self):
1115 """Return StringArray of node paths 1116 @return: Node names 1117 @rtype: StringArray 1118 """ 1119 return self.path
1120
1121 - def getFullPath(self):
1122 """Return StringArray of full node paths 1123 @return: Full node paths 1124 @rtype: StringArray 1125 """ 1126 return self.fullpath
1127
1128 - def getNid(self):
1129 """Return nid numbers 1130 @return: nid numbers 1131 @rtype: Int32Array 1132 """ 1133 return self.nids
1134
1135 - def isOn(self):
1136 """Return bool array 1137 @return: true if node is on 1138 @rtype: Int8Array 1139 """ 1140 return self.on
1141
1142 - def setOn(self,flag):
1143 """Turn nodes on or off 1144 @param flag: True to turn nodes on, False to turn them off 1145 @type flag: Bool 1146 @rtype: None 1147 """ 1148 for nid in self: 1149 nid.setOn(flag)
1150
1151 - def getLength(self):
1152 """Return data lengths 1153 @return: Array of data lengths 1154 @rtype: Int32Array 1155 """ 1156 return self.length
1157
1158 - def getCompressedLength(self):
1159 """Return compressed data lengths 1160 @return: Array of compressed data lengths 1161 @rtype: Int32Array 1162 """ 1163 return self.rlength
1164
1165 - def isSetup(self):
1166 """Return array of bool 1167 @return: True if setup information 1168 @rtype: Uint8Array 1169 """ 1170 return self.setup
1171
1172 - def isWriteOnce(self):
1173 """Return array of bool 1174 @return: True if node is write once 1175 @rtype: Uint8Array 1176 """ 1177 return self.write_once
1178 1179
1180 - def setWriteOnce(self,flag):
1181 """Set nodes write once 1182 @rtype: None 1183 """ 1184 for nid in self: 1185 nid.setWriteOnce(flag)
1186
1187 - def isCompressOnPut(self):
1188 """Is nodes set to compress on put 1189 @return: state of compress on put flags 1190 @rtype: Uint8Array 1191 """ 1192 return self.compress_on_put
1193
1194 - def setCompressOnPut(self,flag):
1195 """Set compress on put flag 1196 @param flag: True if compress on put, False if not 1197 @type flag: bool 1198 """ 1199 for nid in self: 1200 nid.setCompressOnPut(flag)
1201
1202 - def isNoWriteModel(self):
1203 """True if nodes set to no write model 1204 @return: True if nodes set to no write model mode 1205 @rtype: Uint8Array 1206 """ 1207 return self.no_write_model
1208
1209 - def setNoWriteModel(self,flag):
1210 """Set no write model flag 1211 @param flag: True to disallow writing to model 1212 @type flag: bool 1213 """ 1214 for nid in self: 1215 nid.setNoWriteModel(flag)
1216
1217 - def isNoWriteShot(self):
1218 """True if nodes are set no write shot 1219 @return: 1 of set no write shot 1220 @rtype: Uint8Array() 1221 """ 1222 return self.no_write_shot
1223
1224 - def setNoWriteShot(self,flag):
1225 """set no write shot flags 1226 @param flag: True if setting no write shot 1227 @type flag: bool 1228 """ 1229 for nid in self: 1230 nid.setNoWriteShot(flag)
1231
1232 - def getUsage(self):
1233 """Get usage of nodes 1234 @return: Usage 1235 @rtype: StringArray 1236 """ 1237 from mdsarray import makeArray 1238 a=list() 1239 for nid in self: 1240 a.append(str(nid.usage)) 1241 return makeArray(a)
1242 1243 1244
1245 - def __getattr__(self,name):
1246 try: 1247 Tree.lock() 1248 try: 1249 self.restoreContext() 1250 ans = Data.execute('getnci($,$)',self.nids,name) 1251 except Exception,e: 1252 if 'TdiBAD_INDEX' in str(e): 1253 raise AttributeError,'Attribute %s is not defined' % (name,) 1254 else: 1255 raise 1256 finally: 1257 Tree.unlock() 1258 return ans
1259 1260 1261 1262
1263 -class CachedTreeNode(TreeNode):
1264 """Node belonging to a cached tree""" 1265
1266 - def getData(self):
1267 """Return data""" 1268 from _treeshr import RTreeGetRecord 1269 return RTreeGetRecord(self)
1270
1271 - def getNumSegments(self):
1272 """return number of segments contained in this node""" 1273 from _treeshr import RTreeGetNumSegments 1274 return makeData(RTreeGetNumSegments(self))
1275
1276 - def getCachePolicy(self):
1277 """return cache policy for this node""" 1278 try: 1279 return self.cachePolicy 1280 except: 1281 return 0
1282
1283 - def setCachePolicy(self,policy):
1284 """set cache policy for this node""" 1285 self.cachePolicy=policy
1286
1287 - def flush(self):
1288 from _treeshr import RTreeFlushNode 1289 RTreeFlushNode(self.tree.ctx,self.nid)
1290
1291 - def putData(self,value):
1292 from _treeshr import RTreePutRecord 1293 return RTreePutRecord(self,value,self)
1294
1295 - def beginSegment(self,start,end,dimension,initialValueArray,idx=-1):
1296 from _treeshr import RTreeBeginSegment 1297 return RTreeBeginSegment(self,start,end,dimension,initialValueArray,idx)
1298
1299 - def putSegment(self,data,idx):
1300 from _treeshr import RTreePutSegment 1301 return RTreePutSegment(self,data,idx)
1302
1303 - def putRow(self,bufsize,array,timestamp):
1304 from _treeshr import RTreePutRow 1305 return RTreePutRow(self,bufsize,array,timestamp)
1306
1307 - def putLastRow(self,bufsize,array,timestamp):
1308 from _treeshr import RTreePutRow 1309 try: 1310 if self.cachePolicy == 3: 1311 self.cachePolicy = 4 1312 status = RTreePutRow(self,bufsize,array,timestamp) 1313 finally: 1314 if self.cachePolicy == 4: 1315 self.cachePolicy = 3 1316 return status
1317
1318 - def updateSegment(self,start,end,dim,idx):
1319 """Update a segment""" 1320 from _treeshr import RTreeUpdateSegment 1321 return RTreeUpdateSegment(self,start,end,dim,idx)
1322
1323 - def getNumSegments(self):
1324 """Get number of segments""" 1325 from _treeshr import RTreeGetNumSegments 1326 return RTreeGetNumSegments(self)
1327
1328 - def putTimestampedSegment(self,array,timestampArray):
1329 """Put timestamped segment""" 1330 from _treeshr import RTreePutTimestampedSegment 1331 return RTreePutTimestampedSegment(self,array,timestampArray)
1332
1333 - def getSegmentStart(self,idx):
1334 """return start of segment""" 1335 num=self.getNumSegments() 1336 if num > 0 and idx < num: 1337 l=RTreeGetSegmentStart(self,idx) 1338 return l[0] 1339 else: 1340 return None
1341
1342 - def getSegmentEnd(self,idx):
1343 """return end of segment""" 1344 num=self.getNumSegments() 1345 if num > 0 and idx < num: 1346 l=RTreeGetSegmentEnd(self,idx) 1347 return l[1] 1348 else: 1349 return None
1350