Changeset 1808


Ignore:
Timestamp:
24/01/12 16:01:23 (4 months ago)
Author:
Ray Osborn
Message:

Refs #322: Further improvements to make file saves work more intuitively.

  • Added a read method to both NXfields and NXgroups to allow data to be restored to

the previously saved values.

  • Added setters for the nxsignal and nxaxes properties to allow them to be set

after the NXdata group is created.

  • Added a recursive option to 'set_unchanged'.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/bindings/python/nxs/tree.py

    r1806 r1808  
    133133    * component('nxclass')  return group entries of a particular class 
    134134    * dir()    print the list of entries in the group 
    135     * tree     print the list of entries and subentries in the group 
     135    * tree     return the list of entries and subentries in the group 
    136136    * plot()   plot signal and axes for the group, if available 
    137137 
     
    515515        # find gids for targets 
    516516        for target in gid.iterkeys(): 
    517             #sprint "target",target 
    518517            self.openpath(target) 
    519518            # Can't tell from the name if we are linking to a group or 
     
    530529                # ignore self-links 
    531530                parent = "/".join(path.split("/")[:-1]) 
    532                 #print "link %s -> %s"%(parent,target) 
    533531                self.openpath(parent) 
    534532                self.makelink(gid[target]) 
     
    711709 
    712710    tree: 
    713         Print the object's tree. 
     711        Return the object's tree as a string. 
    714712 
    715713        It invokes the 'dir' method with both 'attrs' and 'recursive' 
    716         set to True. Note that this method is defined as a property attribute and 
     714        set to True. Note that this is defined as a property attribute and 
    717715        does not require parentheses. 
    718716 
     
    784782 
    785783    def walk(self): 
    786         print "yielding",self.nxname,self.nxclass 
    787784        if False: yield 
    788785 
     
    801798    def tree(self): 
    802799        """ 
    803         Print the directory tree. 
     800        Return the directory tree as a string. 
    804801 
    805802        The tree contains all child objects of this object and their children. 
     
    807804        to True. 
    808805        """ 
    809         return self._str_tree(attrs=True,recursive=True) 
    810  
    811     @property 
    812     def tree_with_attrs(self, attrs=True): 
    813         """Return directory tree string""" 
    814806        return self._str_tree(attrs=True,recursive=True) 
    815807 
     
    913905        return self._changed 
    914906     
    915     def set_unchanged(self): 
     907    def set_unchanged(self, recursive=False): 
    916908        """ 
    917909        Set an object's change status to unchanged. 
    918910        """ 
    919         self._changed = False 
     911        if recursive: 
     912            for node in self.walk(): 
     913                node._changed = False 
     914        else: 
     915            self._changed = False 
    920916     
    921917    def _getclass(self): 
     
    11851181 
    11861182    tree: 
    1187         Print the NXfield's tree. 
     1183        Return the NXfield's tree. 
    11881184 
    11891185        It invokes the 'dir' method with both 'attrs' and 'recursive' 
    1190         set to True. Note that this method is defined as a property attribute and 
     1186        set to True. Note that this is defined as a property attribute and 
    11911187        does not require parentheses. 
    11921188 
     
    12141210    """ 
    12151211 
    1216     def __init__(self, value=None, name='field', dtype=None, shape=(), attrs={}, group=None, 
    1217                  **attr): 
     1212    def __init__(self, value=None, name='field', dtype=None, shape=(), group=None, 
     1213                 attrs={}, **attr): 
    12181214        if isinstance(value, list) or isinstance(value, tuple): 
    12191215            value = np.array(value) 
     
    21172113            self._class = opts["nxclass"] 
    21182114            del opts["nxclass"] 
     2115        if "group" in opts.keys(): 
     2116            self._group = opts["group"] 
     2117            del opts["group"] 
    21192118        for k,v in opts.items(): 
    21202119            setattr(self, k, v) 
     
    22552254        """ 
    22562255        if key in self.entries:  
    2257             infile = self[key]._infile 
    2258             attrs = self[key].attrs 
    2259             if isinstance(self[key], NXlink): 
     2256            infile = self._entries[key]._infile 
     2257            if isinstance(self._entries[key], NXlink): 
    22602258                if self._entries[key].nxlink: 
    22612259                    setattr(self._entries[key].nxlink.nxgroup, key, value) 
    22622260                return 
     2261            attrs = self._entries[key].attrs 
    22632262        else: 
    22642263            infile = None 
     
    23412340        else: 
    23422341            raise NeXusError, "Link target must be an NXobject" 
     2342 
     2343    def read(self): 
     2344        """ 
     2345        Read the NXgroup and all its children from the NeXus file. 
     2346        """ 
     2347        if self.nxfile: 
     2348            with self as path: 
     2349                n, nxname, nxclass = path.getgroupinfo() 
     2350                if nxclass != self.nxclass: 
     2351                    raise NeXusError("The NeXus group class does not match the file") 
     2352                self._setattrs(path.getattrs()) 
     2353                entries = path.entries() 
     2354            for name,nxclass in entries: 
     2355                path = self.nxpath + '/' + name 
     2356                if nxclass == 'SDS': 
     2357                    attrs = self.nxfile.getattrs() 
     2358                    if 'target' in attrs and attrs['target'] != path: 
     2359                        self._entries[name] = NXlinkfield(target=attrs['target'])             
     2360                    else: 
     2361                        self._entries[name] = NXfield(name=name) 
     2362                else: 
     2363                    attrs = self.nxfile.getattrs() 
     2364                    if 'target' in attrs and attrs['target'] != path: 
     2365                        self._entries[name] = NXlinkgroup(name=name, 
     2366                                                          target=attrs['target']) 
     2367                    else: 
     2368                        self._entries[name] = NXgroup(nxclass=nxclass) 
     2369                self._entries[name]._group = self 
     2370            #Make sure non-linked variables are processed first. 
     2371            for entry in self._entries.values(): 
     2372                for node in entry.walk(): 
     2373                    if not isinstance(node, NXlink): node.read() 
     2374            for entry in self._entries.values(): 
     2375                for node in entry.walk(): 
     2376                    if isinstance(node, NXlink): node.read() 
     2377            self._infile = self._saved = self._changed = True 
     2378        else: 
     2379            raise IOError("Data is not attached to a file") 
    23432380 
    23442381    def write(self): 
     
    24422479                return self[obj.nxname] 
    24432480        return None 
     2481     
     2482    def _set_signal(self, signal): 
     2483        """ 
     2484        Setter for the signal attribute. 
     2485         
     2486        The argument should be a valid NXfield within the group. 
     2487        """ 
     2488        self[signal.nxname].signal = NXattr(1) 
    24442489 
    24452490    def _axes(self): 
     
    24562501            return [axes[key] for key in sorted(axes.keys())] 
    24572502 
     2503    def _set_axes(self, axes): 
     2504        """ 
     2505        Setter for the signal attribute. 
     2506         
     2507        The argument should be a list of valid NXfields within the group. 
     2508        """ 
     2509        if not isinstance(axes, list): 
     2510            axes = [axes] 
     2511        self.nxsignal.axes = NXattr(":".join([axis.nxname for axis in axes])) 
     2512 
    24582513    def _errors(self): 
    24592514        """ 
     
    24882543        return self._entries 
    24892544 
    2490     nxsignal = property(_signal, "Signal NXfield within group") 
    2491     nxaxes = property(_axes, "List of axes within group") 
     2545    nxsignal = property(_signal, _set_signal, "Signal NXfield within group") 
     2546    nxaxes = property(_axes, _set_axes, "List of axes within group") 
    24922547    nxerrors = property(_errors, "Errors NXfield within group") 
    24932548    nxtitle = property(_title, "Title for group plot") 
     
    25702625    def __init__(self, target=None, name='link', group=None): 
    25712626        self._group = group 
     2627        self._class = "NXlink" 
    25722628        if isinstance(target, NXobject): 
    25732629            self._name = target.nxname 
     
    26292685    attrs = property(_getattrs,doc="NeXus attributes for object") 
    26302686 
     2687    def read(self): 
     2688        """ 
     2689        Read the linked NXobject. 
     2690        """ 
     2691        self.nxlink.read() 
     2692        self._infile = self._saved = self._changed = True 
     2693 
    26312694 
    26322695class NXlinkfield(NXlink, NXfield): 
     
    26492712                path.makelink(target) 
    26502713            self._infile = self._saved = True 
    2651  
    26522714 
    26532715    def get(self, offset, size): 
     
    27852847    of axes, for multidimensional data. These arguments can either be NXfield 
    27862848    objects or Numpy arrays, which are converted to NXfield objects with default 
    2787     names. 
    2788  
     2849    names. Alternatively, the signal and axes NXfields can be defined using the 
     2850    'nxsignal' and 'nxaxes' properties. See the examples below. 
     2851     
    27892852    Various arithmetic operations (addition, subtraction, multiplication, 
    27902853    and division) have been defined for combining NXdata groups with other 
     
    28012864    Methods 
    28022865    ------- 
    2803     plot(self, over=False, log=False, **opts) 
     2866    plot(self, fmt, over=False, log=False, logy=False, logx=False, **opts) 
    28042867        Plot the NXdata group using the defined signal and axes. Valid 
    28052868        Matplotlib parameters, specifying markers, colors, etc, can be 
    2806         specified using the 'opts' dictionary. 
     2869        specified using format argument or through keyword arguments. 
     2870 
     2871    logplot(self, fmt, over=False, logy=False, logx=False, **opts) 
     2872        Plot the NXdata group using the defined signal and axes with 
     2873        the intensity plotted on a logarithmic scale. In one-dimensional 
     2874        plots, this is the y-axis. In two-dimensional plots, it is the  
     2875        color scale. 
     2876 
     2877    oplot(self, fmt, **opts) 
     2878        Plot the NXdata group using the defined signal and axes over 
     2879        the current plot. 
    28072880 
    28082881    moment(self, order=1) 
     
    28132886    Examples 
    28142887    -------- 
     2888    There are three methods of creating valid NXdata groups with the 
     2889    signal and axes NXfields defined according to the NeXus standard. 
     2890     
     2891    1) Create the NXdata group with Numpy arrays that will be assigned 
     2892       default names. 
     2893        
    28152894    >>> x = np.linspace(0, 2*np.pi, 101) 
    28162895    >>> line = NXdata(sin(x), x) 
     
    28192898        @axes = x 
    28202899        @signal = 1 
    2821       x = float64(101) 
    2822     >>> X, Y = np.meshgrid(x, x) 
    2823     >>> z = NXfield(sin(X) * sin(Y), name='intensity') 
     2900      axis1 = float64(101) 
     2901       
     2902    2) Create the NXdata group with NXfields that have their internal 
     2903       names already assigned. 
     2904 
     2905    >>> x = NXfield(linspace(0,2*pi,101), name='x') 
     2906    >>> y = NXfield(linspace(0,2*pi,101), name='y')     
     2907    >>> X, Y = np.meshgrid(x, y) 
     2908    >>> z = NXfield(sin(X) * sin(Y), name='z') 
    28242909    >>> entry = NXentry() 
    2825     >>> entry.grid = NXdata(z, (x, x)) 
     2910    >>> entry.grid = NXdata(z, (x, y)) 
    28262911    >>> grid.tree() 
    28272912    entry:NXentry 
    28282913      grid:NXdata 
    2829         axis1 = float64(101) 
    2830         axis2 = float64(101) 
    2831         intensity = float64(101x101) 
    2832           @axes = axis1:axis2 
     2914        x = float64(101) 
     2915        y = float64(101) 
     2916        z = float64(101x101) 
     2917          @axes = x:y 
    28332918          @signal = 1 
    28342919 
    2835     See the NXgroup documentation for more details. 
     2920    3) Create the NXdata group with keyword arguments defining the names  
     2921       and set the signal and axes using the nxsignal and nxaxes properties. 
     2922 
     2923    >>> x = linspace(0,2*pi,101) 
     2924    >>> y = linspace(0,2*pi,101)   
     2925    >>> X, Y = np.meshgrid(x, y) 
     2926    >>> z = sin(X) * sin(Y) 
     2927    >>> entry = NXentry() 
     2928    >>> entry.grid = NXdata(z=sin(X)*sin(Y), x=x, y=y) 
     2929    >>> entry.grid.nxsignal = entry.grid.z 
     2930    >>> entry.grid.nxaxes = [entry.grid.x.entry.grid.y] 
     2931    >>> grid.tree() 
     2932    entry:NXentry 
     2933      grid:NXdata 
     2934        x = float64(101) 
     2935        y = float64(101) 
     2936        z = float64(101x101) 
     2937          @axes = x:y 
     2938          @signal = 1 
    28362939    """ 
    28372940 
Note: See TracChangeset for help on using the changeset viewer.