Package MDSplus ::
Module 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
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
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
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
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
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
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
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
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
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
346 """Delete this node from the tree
347 @rtype: None
348 """
349 self.tree.deleteNode(self.fullpath)
350
352 """Delete data from this node
353 @rtype: None
354 """
355 self.putData(None)
356 return
357
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
376 """Return sibling of this node
377 @return: Sibling of this node
378 @rtype: TreeNode
379 """
380 return self.brother
381
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
390 """Return TreeNodeArray of children nodes.
391 @return: Children of this node
392 @rtype: TreeNodeArray
393 """
394 return self.children_nids
395
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
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
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
418 """Return TreeNodeArray of conglomerate elements
419 @return: Nodes in this conglomerate.
420 @rtype: TreeNodeArray
421 """
422 return self.conglomerate_nids
423
425 """Return data
426 @return: data stored in this node
427 @rtype: Data
428 """
429 from _treeshr import TreeGetRecord
430 return TreeGetRecord(self)
431
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
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
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
470 """Return full path of this node
471 @return: full path specification of this node.
472 @rtype: String
473 """
474 return self.fullpath
475
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
484 """Return first member node
485 @return: First member of thie node
486 @rtype: TreeNode
487 """
488 return self.member
489
491 """Return TreeNodeArray of this nodes members
492 @return: members of this node
493 @rtype: TreeNodeArray
494 """
495 return self.member_nids
496
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
505 """Return node index
506 @return: Internal node index of this node
507 @rtype: int
508 """
509 return self.nid
510
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
519 """Return number of children nodes.
520 @return: Number of children
521 @rtype: Int32
522 """
523 return self.number_of_children
524
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
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
540 """Return number of members
541 @return: number of members
542 @rtype: int
543 """
544 return self.number_of_members
545
547 """return number of segments contained in this node
548 @rtype: int
549 """
550 from _treeshr import TreeGetNumSegments
551 return makeData(TreeGetNumSegments(self))
552
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
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
568 """Return parent of this node
569 @return: Parent of this node
570 @rtype: TreeNode
571 """
572 return self.parent
573
575 """Return path of this node
576 @return: Path to this node.
577 @rtype: String
578 """
579 return self.path
580
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
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
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
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
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
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
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
680 gtk.main()
681 print "done with gtk.main()"
682
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
694 import gtk
695
696 cls.gtkThread.join()
697 waitForSetups=classmethod(waitForSetups)
698
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
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
725
727 """Return Tree associated with this node
728 @return: Tree associated with this node
729 @rtype: Tree
730 """
731 return self.tree
732
734 """Return usage of this node
735 @return: usage of this node
736 @rtype: str
737 """
738 return self.usage
739
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1080 """Class to represent an MDSplus node reference (path)."""
1088
1090 """Convert path to string."""
1091 return self.tree_path.value
1092
1100
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):
1113
1115 """Return StringArray of node paths
1116 @return: Node names
1117 @rtype: StringArray
1118 """
1119 return self.path
1120
1122 """Return StringArray of full node paths
1123 @return: Full node paths
1124 @rtype: StringArray
1125 """
1126 return self.fullpath
1127
1129 """Return nid numbers
1130 @return: nid numbers
1131 @rtype: Int32Array
1132 """
1133 return self.nids
1134
1136 """Return bool array
1137 @return: true if node is on
1138 @rtype: Int8Array
1139 """
1140 return self.on
1141
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
1152 """Return data lengths
1153 @return: Array of data lengths
1154 @rtype: Int32Array
1155 """
1156 return self.length
1157
1159 """Return compressed data lengths
1160 @return: Array of compressed data lengths
1161 @rtype: Int32Array
1162 """
1163 return self.rlength
1164
1166 """Return array of bool
1167 @return: True if setup information
1168 @rtype: Uint8Array
1169 """
1170 return self.setup
1171
1173 """Return array of bool
1174 @return: True if node is write once
1175 @rtype: Uint8Array
1176 """
1177 return self.write_once
1178
1179
1181 """Set nodes write once
1182 @rtype: None
1183 """
1184 for nid in self:
1185 nid.setWriteOnce(flag)
1186
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
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
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
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
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
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
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
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
1264 """Node belonging to a cached tree"""
1265
1267 """Return data"""
1268 from _treeshr import RTreeGetRecord
1269 return RTreeGetRecord(self)
1270
1272 """return number of segments contained in this node"""
1273 from _treeshr import RTreeGetNumSegments
1274 return makeData(RTreeGetNumSegments(self))
1275
1277 """return cache policy for this node"""
1278 try:
1279 return self.cachePolicy
1280 except:
1281 return 0
1282
1284 """set cache policy for this node"""
1285 self.cachePolicy=policy
1286
1288 from _treeshr import RTreeFlushNode
1289 RTreeFlushNode(self.tree.ctx,self.nid)
1290
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
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
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
1319 """Update a segment"""
1320 from _treeshr import RTreeUpdateSegment
1321 return RTreeUpdateSegment(self,start,end,dim,idx)
1322
1324 """Get number of segments"""
1325 from _treeshr import RTreeGetNumSegments
1326 return RTreeGetNumSegments(self)
1327
1329 """Put timestamped segment"""
1330 from _treeshr import RTreePutTimestampedSegment
1331 return RTreePutTimestampedSegment(self,array,timestampArray)
1332
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
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