Changeset 1122


Ignore:
Timestamp:
25/10/08 02:55:50 (3 years ago)
Author:
Paul Kienzle
Message:

python: make docs and code correspond; simplify slab interface. Refs #101.

Location:
trunk/bindings/python/nxs
Files:
3 edited

Legend:

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

    r1121 r1122  
    99used as well as the data measured. 
    1010 
    11 The NeXus file interface requires binary libraries to read the 
    12 underlying HDF_ files, and  
    13  
    14 Please be sure that the NeXus libraries are installed.  The 
    15 NeXus format site contains binaries for some platforms.  Details 
    16 of where the nxs package searches for the libraries are in `nxs.napi`. 
     11The NeXus file interface requires compiled libraries to read the 
     12underlying HDF_ files.  Binary packages are available for some 
     13platforms from the NeXus site.  Details of where the nxs package  
     14searches for the libraries are recorded in `nxs.napi`. 
    1715 
    1816Example 
     
    2220 
    2321    import nxs 
    24     f = nxs.read('file.nxs') 
     22    f = nxs.load('file.nxs') 
    2523 
    2624We can examine the file structure using a number of commands:: 
     
    3634We can create a copy of the file using write:: 
    3735 
    38     nxs.write('copy.nxs', tree) 
     36    nxs.save('copy.nxs', tree) 
    3937 
    4038For a complete description of the features available in this tree view 
     
    4543 
    4644When converting code to python from other languages you do not 
    47 necessarily want to redo the file handling code.  The `nxs.napi` 
    48 package provides an interface which more closely follows the 
    49 NeXus application programming interface (NAPI_). 
     45necessarily want to rewrite the file handling code using the 
     46tree view.  The `nxs.napi` module provides an interface which  
     47more closely follows the NeXus application programming  
     48interface (NAPI_). 
    5049 
    5150.. _Nexus: http://www.nexusformat.org/Introduction 
  • trunk/bindings/python/nxs/tree.py

    r1121 r1122  
    55Tree view for NeXus files. 
    66 
    7 Unlike the `nxs.napi` routines which implement the NeXus API directly, the 
    8 `nxs.tree` routines preload the entire file structure into memory and use 
    9 a natural syntax for navigating the data hierarchy.  Large datasets 
    10 are not read until they are needed, and may be read or written one 
    11 slab at a time. 
     7The `nxs.tree` routines provide a natural interface to NeXus datasets. 
     8Entries in a group are referenced much like fields in a class are 
     9referenced in python.  Rather than following the directory model of 
     10the `nxs.napi` interface, users are free to reference separate fields 
     11in the dataset at the same time.  Large datasets are not read until  
     12they are needed, and may be read or written one slab at a time. 
    1213 
    1314There are a number of functions which operate on files:: 
     
    2526NeXus attribute names are tagged with a leading 'A', so for example, 
    2627tree.Histogram1.instrument.detector.distance.Aunits contains the 
    27 units attribute for the detector distances. 
    28  
    29 Properties of the nodes in the tree are referenced by nx attributes. 
     28units attribute for the detector distances.  Entries can also 
     29be referenced by NXclass name, such as tree.NXentry[0].instrument. 
     30Since there may be multiple entries of the same NXclass, the 
     31NXclass attribute returns a possibly empty list. 
     32 
     33Properties of the entry in the tree are referenced by nx attributes. 
    3034Depending on the node type, different nx attributes may be available. 
    3135 
     
    5458 
    5559Unknown fields (class Unknown) are groups with a name that doesn't 
    56 start with 'NX'.  These groups are not read or written. 
     60start with 'NX'.  These groups are not loaded or saved. 
    5761 
    5862NeXus attributes (class NXattr) have a type and a value only:: 
     
    6367on which facility is storing the file.  This makes life difficult 
    6468for reduction and analysis programs which must know the units they 
    65 are working with.  Our solution to this problem is to allow you to 
    66 retrieve data from the file in particular units.  For example, if 
     69are working with.  Our solution to this problem is to allow the reader 
     70to retrieve data from the file in particular units.  For example, if 
    6771detector distance is stored in the file using millimeters you can  
    6872retrieve them in meters using:: 
     
    7781 
    7882    # Read a Ni x Nj x Nk array one vector at a time 
    79     with node.nxslab: 
    80         size = [1,1,node.nxdims[2]] 
    81         for i in range(node.nxdims[0]): 
    82             for j in range(node.nxdims[1]): 
    83                 value = node.nxslab.get([i,j,0],size) # Read counts 
     83    with root.NXentry[0].data.data as slab: 
     84        Ni,Nj,Nk = slab.nxdims 
     85        size = [1,1,Nk] 
     86        for i in range(Ni): 
     87            for j in range(Nj): 
     88                value = slab.get([i,j,0],size) 
    8489 
    8590The equivalent can be done in Python 2.4 and lower using the context 
    8691functions __enter__ and __exit__:: 
    8792 
    88     node.nxslab.__enter__() 
     93    slab = data.nxslab.__enter__() 
    8994    ... do the slab functions ... 
    90     node.nxslab.__exit__() 
     95    data.nxslab.__exit__() 
    9196 
    9297You can traverse the tree by component class instead of component name.   
     
    108113to the data group and title is the title of the NXentry, if available. 
    109114 
    110 The load() and save() functions are implemented within  
     115The load() and save() functions are implemented using the class 
    111116`nxs.tree.NeXusTree`, a subclass of `nxs.napi.NeXus` which allows  
    112117all the usual API functions.  You can subclass NeXusTree with your 
     
    114119NXmonitor object when an NXmonitor class is read.  Your NXmonitor 
    115120class should probably be a subclass of NXgroup. 
    116  
    117 You can also specialize the definitions for the basic types  
    118 NXgroup(), NXattr(), SDS() and NXlink() if you want to make 
    119 radical changes to the returned structure.  The properties of  
    120 these classes are closely coupled to the behaviour of the readfile 
    121 and writefile methods so refer to the source if you need to do this. 
    122121""" 
    123 __all__ = ['read', 'write', 'dir', 'NeXusTree'] 
     122__all__ = ['load', 'save', 'dir', 'NeXusTree'] 
    124123 
    125124from copy import copy, deepcopy 
     
    160159    The NXdata nodes in the returned tree hold the node values. 
    161160 
     161    Subclasses can provide methods for individual NeXus classes such 
     162    as NXbeam or NXdata.  Brave users can also specialize NXgroup,  
     163    NXattr, SDS and NXlink methods. 
    162164    """ 
    163165    def readfile(self): 
    164166        """ 
    165         Read the nexus file structure from the file.  Reading of large datasets 
    166         will be postponed.  Returns a tree of NXgroup, NXattr, SDS and 
    167         NXlink nodes. 
    168          
    169         Subclasses can provide methods for individual NeXus classes such 
    170         as NXbeam or NXdata.  Brave users can also specialize NXgroup,  
    171         NXattr, SDS and NXlink methods.   
     167        Read the nexus file structure from the file.  Large datasets 
     168        are not read until they are needed.   
     169 
     170        Returns a tree of NXgroup, NXattr, SDS and NXlink nodes. 
    172171        """ 
    173172        self.open() 
     
    510509        print self._str_tree(attrs=attrs,recursive=True) 
    511510 
    512 class NXslab_context(object): 
    513     """ 
    514     Context manager for NeXus fields. 
    515      
    516     The context manager opens the file and positions the cursor to the 
    517     correct field.  Data can then be read or written using the get() and 
    518     put() methods.  See SDS for details on how to use this class. 
    519     """ 
    520      
    521     def __init__(self, file, path, unit_converter): 
    522         self._file = file 
    523         self._path = path 
    524         self._converter = unit_converter 
    525  
    526     def __enter__(self): 
    527         """ 
    528         Open the datapath for reading slab by slab. 
    529         """ 
    530         self._close_on_exit = not self._file.isopen 
    531         self._file.open() # Force file open even if closed 
    532         self._file.openpath(self._path) 
    533         return self 
    534  
    535     def __exit__(self, *args): 
    536         """ 
    537         Close the file associated the data after reading. 
    538         """ 
    539         if self._close_on_exit: 
    540             self._file.close() 
    541  
    542     def get(self, offset, size, units=""): 
    543         """ 
    544         Get a slab from the data array. 
    545  
    546         Offsets are 0-origin.  Shape can be inferred from the data. 
    547         Offset and shape must each have one entry per dimension. 
    548          
    549         If units are specified, convert the values to the given units 
    550         before returning them. 
    551  
    552         Raises ValueError if this fails. 
    553  
    554         Corresponds to NXgetslab(handle,data,offset,shape) 
    555         """ 
    556         value = self._file.getslab(offset,size) 
    557         return self._converter(value,units) 
    558  
    559     def put(self, data, offset): 
    560         """ 
    561         Put a slab into the data array. 
    562  
    563         Offsets are 0-origin.  Shape can be inferred from the data. 
    564         Offset and shape must each have one entry per dimension. 
    565  
    566         Raises ValueError if this fails. 
    567  
    568         Corresponds to NXputslab(handle,data,offset,shape) 
    569         """ 
    570         self._file.putslab(data, offset, data.shape) 
    571          
    572511class SDS(NXnode): 
    573512    """ 
     
    596535 
    597536    # Read a Ni x Nj x Nk array one vector at a time 
    598     with node.nxslab: 
    599         size = [1,1,node.nxdims[2]] 
    600         for i in range(node.nxdims[0]): 
    601             for j in range(node.nxdims[1]): 
    602                 value = node.nxslab.get([i,j,0],size) # Read counts 
     537    with root.NXentry[0].data.data as slab: 
     538        Ni,Nj,Nk = slab.nxdims 
     539        size = [1,1,Nk] 
     540        for i in range(Ni): 
     541            for j in range(Nj): 
     542                value = slab.get([i,j,0],size) 
    603543 
    604544 
     
    621561            units = None 
    622562        self._converter = nxs.unit.Converter(units) 
    623         self.nxslab = NXslab_context(file, path, self._converter) 
    624  
     563        self._incontext = False 
     564 
     565    def __enter__(self): 
     566        """ 
     567        Open the datapath for reading slab by slab. 
     568 
     569        Note: the results are undefined if you try accessing 
     570        more than one slab at a time.  Don't nest your  
     571        "with data" statements! 
     572        """ 
     573        # TODO: provide a file lock to prevent movement of the 
     574        # file cursor when in the slab context. 
     575        # TODO: if HDF allows multiple cursors, extend napi to support them 
     576        self._close_on_exit = not self._file.isopen 
     577        self._file.open() # Force file open even if closed 
     578        self._file.openpath(self._path) 
     579        self._incontext = True 
     580        return self 
     581 
     582    def __exit__(self, *args): 
     583        """ 
     584        Close the file associated the data after reading. 
     585        """ 
     586        self._incontext = False 
     587        if self._close_on_exit: 
     588            self._file.close() 
     589 
     590    def get(self, offset, size, units=""): 
     591        """ 
     592        Get a slab from the data array. 
     593 
     594        Offsets are 0-origin.  Shape can be inferred from the data. 
     595        Offset and shape must each have one entry per dimension. 
     596         
     597        If units are specified, convert the values to the given units 
     598        before returning them. 
     599 
     600        This operation should be performed in a "with group.data" 
     601        conext. 
     602 
     603        Raises ValueError cannot convert units. 
     604 
     605        Corresponds to NXgetslab(handle,data,offset,shape) 
     606        """ 
     607        value = self._file.getslab(offset,size) 
     608        return self._converter(value,units) 
     609 
     610    def put(self, data, offset): 
     611        """ 
     612        Put a slab into the data array. 
     613 
     614        Offsets are 0-origin.  Shape can be inferred from the data. 
     615        Offset and shape must each have one entry per dimension. 
     616 
     617        This operation should be performed in a "with group.data" 
     618        conext. 
     619 
     620        Raises ValueError if this fails.  No error is raised when 
     621        writing to a file which is open read-only. 
     622 
     623        Corresponds to NXputslab(handle,data,offset,shape) 
     624        """ 
     625        self._file.putslab(data, offset, data.shape) 
     626         
    625627    def __str__(self): 
    626628        """ 
     
    838840 
    839841# File level operations 
    840 def read(filename, mode='r'): 
     842def load(filename, mode='r'): 
    841843    """ 
    842844    Read a NeXus file, returning a tree of nodes 
     
    847849    return tree 
    848850 
    849 def write(filename, tree, format='w5'): 
     851def save(filename, tree, format='w5'): 
    850852    """ 
    851853    Write a NeXus file from a tree of nodes 
  • trunk/bindings/python/nxs/unit.py

    r1121 r1122  
    1313in the NeXus definition files. 
    1414 
    15 Unlike other units packages, such as that in DANSE, this package does 
    16 not carry the units along with the value, but merely provides a conversion 
    17 function for transforming values. 
     15Unlike other units modules, this module does not carry the units along  
     16with the value, but merely provides a conversion function for  
     17transforming values. 
    1818 
    19 Usage example: 
     19Usage example:: 
    2020 
    2121    import nxs.unit 
     
    2323    v = u(3000,'m')  # Convert the value 3000 mm into meters 
    2424 
    25 NeXus example: 
     25NeXus example:: 
    2626 
    2727    # Load sample orientation in radians regardless of how it is stored. 
Note: See TracChangeset for help on using the changeset viewer.