Package MDSplus ::
Module tree
|
|
1 from mdsdata import Data,makeData
2 from threading import RLock,Thread
4 """Open an MDSplus Data Storage Hierarchy"""
5
6 _lock=RLock()
7 _activeTree=None
8
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
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
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
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
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
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
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
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
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
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
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
303
305 """Get active tree.
306 @return: Current active tree
307 @rtype: Tree
308 """
309 return cls._activeTree
310 getActiveTree=classmethod(getActiveTree)
311
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
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
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
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
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
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
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
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
420 """Internal use only. Thread synchronization locking.
421 """
422 cls._lock.acquire()
423 lock=classmethod(lock)
424
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
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
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
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
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
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
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
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
544 """Internal use only. Thread synchronization locking.
545 """
546 cls._lock.release()
547 unlock=classmethod(unlock)
548
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
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
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
577 """MDSplus tree with cached data updating"""
578
579 initialized=False
580
581
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
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
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
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