Changes in / [81b524f:c614c02] in sasview


Ignore:
Files:
1 added
124 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • src/sans/dataloader/data_info.py

    r75eeb425 r75eeb425  
    401401        return _str 
    402402     
    403 class TransmissionSpectrum: 
    404     """ 
    405     Class that holds information about transmission spectrum 
    406     for white beams and spallation sources. 
    407     """ 
    408     name = '' 
    409     timestamp = '' 
    410     ## Wavelength (float) [A] 
    411     wavelength = None 
    412     wavelength_unit = 'A' 
    413     ## Transmission (float) [unit less] 
    414     transmission = None 
    415     transmission_unit = '' 
    416     ## Transmission Deviation (float) [unit less] 
    417     transmission_deviation = None 
    418     transmission_deviation_unit = '' 
    419      
    420     def __init__(self): 
    421         self.wavelength = [] 
    422         self.transmission = [] 
    423         self.transmission_deviation = [] 
    424      
    425     def __str__(self): 
    426         _str  = "Transmission Spectrum:\n" 
    427         _str += "   Name:       {0}".format(self.name) 
    428         _str += "   Timestamp:  {1}".format(self.timestamp) 
    429         _str += "   Wavelength [{0}] | Transmission [{1}] | Trans Dev [{2}]\n".format(self.wavelength_unit, self.transmission_unit, self.transmission_deviation_unit) 
    430         for i in range(len(self.wavelength)): 
    431             _str += "   {0}, {1}".format(self.wavelength[i], self.transmission[i]) 
    432             if len(self.transmission_deviation > i): 
    433                 _str += ", {0}".format(self.transmission_deviation[i]) 
    434             _str += "\n" 
    435         return _str 
    436      
    437403   
    438404class DataInfo: 
     
    465431    ## Collimation information 
    466432    collimation = None 
    467     ## Transmission Spectrum INfo 
    468     trans_spectrum = None 
    469433    ## Additional meta-data 
    470434    meta_data  = None 
     
    497461        ## Collimation information 
    498462        self.collimation = [] 
    499         ## Transmission Spectrum 
    500         self.trans_spectrum = TransmissionSpectrum() 
    501463        ## Additional meta-data 
    502464        self.meta_data  = {} 
  • src/sans/dataloader/readers/cansas_reader.py

    r75eeb425 r75eeb425  
    11""" 
    2     CanSAS data reader - new recursive cansasVersion. 
     2    CanSAS data reader 
    33""" 
    44############################################################################ 
     
    1313############################################################################# 
    1414 
     15# Known issue: reader not compatible with multiple SASdata entries 
     16# within a single SASentry. Will raise a runtime error. 
     17 
     18#TODO: check that all vectors are written only if they have at  
     19#    least one non-empty value 
     20#TODO: Writing only allows one SASentry per file. 
     21#     Would be best to allow multiple entries. 
     22#TODO: Store error list 
     23#TODO: Allow for additional meta data for each section 
     24#TODO: Notes need to be implemented. They can be any XML  
     25#    structure in version 1.0 
     26#      Process notes have the same problem. 
     27#TODO: Unit conversion is not complete (temperature units are missing) 
     28 
    1529import logging 
    1630import numpy 
     
    2236from sans.dataloader.data_info import Process 
    2337from sans.dataloader.data_info import Aperture 
    24 import xml_reader 
     38from lxml import etree 
    2539import xml.dom.minidom 
    26 from cansas_constants import cansasConstants 
    27  
    2840_ZERO = 1e-16 
    2941HAS_CONVERTER = True 
     
    3244except: 
    3345    HAS_CONVERTER = False 
    34      
    35 CANSAS_FORMAT = cansasConstants.CANSAS_FORMAT 
    36 CANSAS_NS = cansasConstants.CANSAS_NS 
     46 
     47CANSAS_NS = "cansas1d/1.0" 
    3748ALLOW_ALL = True 
    3849 
     
    5667        return True 
    5768    return False 
    58                  
     69 
    5970 
    6071def get_content(location, node): 
     
    98109    return value, attr 
    99110 
    100  
    101  
    102 class CANSASError(Exception): 
    103     """Base class all CANSAS reader exceptions are derived""" 
    104     pass 
    105  
    106 class NotCANSASFileError(CANSASError): 
    107     def __init__(self): 
    108         self.value = "This is not a proper CanSAS file." 
    109     def __str__(self): 
    110         return repr(self.value) 
    111  
    112 class Reader(): 
     111             
     112class Reader: 
    113113    """ 
    114114    Class to load cansas 1D XML files 
    115115     
    116116    :Dependencies: 
    117         The CanSAS reader requires PyXML 0.8.4 or later. 
     117        The CanSas reader requires PyXML 0.8.4 or later. 
    118118    """ 
    119     ##CanSAS version - defaults to version 1.0 
    120     cansasVersion = "1.0" 
    121     ##Data reader 
    122     reader = xml_reader.XMLreader() 
    123     errors = [] 
    124      
    125     type_name = "canSAS" 
    126      
     119    ## CanSAS version 
     120    version = '1.0' 
     121    ## File type 
     122    type_name = "CanSAS 1D" 
    127123    ## Wildcards 
    128     type = ["XML files (*.xml)|*.xml"] 
     124    type = ["CanSAS 1D files (*.xml)|*.xml", 
     125                        "CanSAS 1D AVE files (*.AVEx)|*.AVEx", 
     126                         "CanSAS 1D AVE files (*.ABSx)|*.ABSx"] 
     127 
    129128    ## List of allowed extensions 
    130     ext = ['.xml', '.XML'] 
    131      
    132     ## Flag to bypass extension check 
    133     allow_all = True 
     129    ext = ['.xml', '.XML', '.avex', '.AVEx', '.absx', 'ABSx'] 
    134130     
    135131    def __init__(self): 
    136132        ## List of errors 
    137133        self.errors = [] 
    138          
    139     def isCansas(self): 
    140         """ 
    141         Checks to see if the xml file is a CanSAS file 
    142         """ 
    143         if self.reader.validateXML(): 
    144             xmlns = self.reader.xmlroot.keys() 
    145             if (CANSAS_NS.get(self.cansasVersion).get("ns") == self.reader.xmlroot.get(xmlns[1]).rsplit(" ")[0]): 
    146                 return True 
    147         return False 
    148134     
    149     def read(self, xml): 
    150         """ 
    151         Validate and read in an xml file in the canSAS format. 
    152          
    153         :param xml: A canSAS file path in proper XML format 
    154         """ 
    155         # X - Q value; Y - Intensity (Abs) 
    156         x = numpy.empty(0) 
    157         y = numpy.empty(0) 
    158         dx = numpy.empty(0) 
    159         dy = numpy.empty(0) 
    160         dxl = numpy.empty(0) 
    161         dxw = numpy.empty(0) 
    162          
    163         # output - Final list of Data1D objects 
     135    def read(self, path): 
     136        """ 
     137        Load data file 
     138         
     139        :param path: file path 
     140         
     141        :return: Data1D object if a single SASentry was found,  
     142                    or a list of Data1D objects if multiple entries were found, 
     143                    or None of nothing was found 
     144                     
     145        :raise RuntimeError: when the file can't be opened 
     146        :raise ValueError: when the length of the data vectors are inconsistent 
     147        """ 
    164148        output = [] 
    165         # ns - Namespace hierarchy for current xml object 
    166         ns = [] 
    167          
    168         # Check that the file exists 
    169         if os.path.isfile(xml): 
    170             basename = os.path.basename(xml) 
    171             _, extension = os.path.splitext(basename) 
    172             # If the fiel type is not allowed, return nothing 
    173             if extension in self.ext or self.allow_all: 
    174                 base_name = xml_reader.__file__ 
    175                 base = base_name.split("\\sans\\")[0] 
    176                  
    177                 # Load in the xml file and get the cansas version from the header 
    178                 self.reader.setXMLFile(xml) 
    179                 root = self.reader.xmlroot 
    180                 if root is None: 
    181                     root = {} 
    182                 self.cansasVersion = root.get("version", "1.0") 
    183                  
    184                 # Generic values for the cansas file based on the version 
    185                 cansas_defaults = CANSAS_NS.get(self.cansasVersion, "1.0") 
    186                 schema_path = "{0}\\sans\\dataloader\\readers\\schema\\{1}".format(base, cansas_defaults.get("schema")).replace("\\", "/") 
    187                  
    188                 # Link a schema to the XML file. 
    189                 self.reader.setSchema(schema_path) 
    190              
    191                 # Try to load the file, but raise an error if unable to. 
    192                 # Check the file matches the XML schema 
     149        if os.path.isfile(path): 
     150            basename = os.path.basename(path) 
     151            root, extension = os.path.splitext(basename) 
     152            if ALLOW_ALL or extension.lower() in self.ext: 
    193153                try: 
    194                     if self.isCansas(): 
    195                         # Get each SASentry from the XML file and add it to a list. 
    196                         entry_list = root.xpath('/ns:SASroot/ns:SASentry', 
    197                                                      namespaces={'ns': cansas_defaults.get("ns")}) 
    198                         ns.append("SASentry") 
     154                    tree = etree.parse(path, parser=etree.ETCompatXMLParser()) 
     155                    # Check the format version number 
     156                    # Specifying the namespace will take care of the file 
     157                    # format version 
     158                    root = tree.getroot() 
     159                     
     160                    entry_list = root.xpath('/ns:SASroot/ns:SASentry', 
     161                                             namespaces={'ns': CANSAS_NS}) 
     162                     
     163                    for entry in entry_list: 
     164                        self.errors = [] 
     165                        sas_entry = self._parse_entry(entry) 
     166                        sas_entry.filename = basename 
    199167                         
    200                         # If there are multiple files, modify the name for each is unique 
    201                         multipleFiles = len(entry_list) - 1 
    202                         n = 0 
    203                         name = basename 
    204                         # Parse each SASentry item 
    205                         for entry in entry_list: 
    206                              
    207                             # Define a new Data1D object with zeroes for x and y 
    208                             data1D = Data1D(x,y,dx,dy) 
    209                             data1D.dxl = dxl 
    210                             data1D.dxw = dxw 
    211                              
    212                             # If more than one SASentry, number each in order 
    213                             if multipleFiles: 
    214                                 name += "_{0}".format(n) 
    215                                 n += 1 
    216                              
    217                             # Set the Data1D name and then parse the entry. The entry is appended to a list of entry values 
    218                             data1D.filename = name 
    219                             data1D.meta_data["loader"] = "CanSAS 1D" 
    220                             return_value, extras = self._parse_entry(entry, ns, data1D) 
    221                             del extras[:] 
    222                              
    223                             #Final cleanup - Remove empty nodes, verify array sizes are correct 
    224                             for error in self.errors: 
    225                                 return_value.errors.append(error) 
    226                             del self.errors[:] 
    227                             numpy.trim_zeros(return_value.x) 
    228                             numpy.trim_zeros(return_value.y) 
    229                             numpy.trim_zeros(return_value.dy) 
    230                             size_dx = return_value.dx.size 
    231                             size_dxl = return_value.dxl.size 
    232                             size_dxw = return_value.dxw.size 
    233                             if size_dxl == 0 and size_dxw == 0: 
    234                                 return_value.dxl = None 
    235                                 return_value.dxw = None 
    236                                 numpy.trim_zeros(return_value.dx) 
    237                             elif size_dx == 0: 
    238                                 return_value.dx = None 
    239                                 size_dx = size_dxl 
    240                                 numpy.trim_zeros(return_value.dxl) 
    241                                 numpy.trim_zeros(return_value.dxw) 
    242                              
    243                             output.append(return_value) 
    244                     else: 
    245                         value = self.reader.findInvalidXML() 
    246                         output.append("Invalid XML at: {0}".format(value)) 
     168                        # Store loading process information 
     169                        sas_entry.errors = self.errors 
     170                        sas_entry.meta_data['loader'] = self.type_name 
     171                        output.append(sas_entry) 
    247172                except: 
    248                     # If the file does not match the schema, raise this error 
    249                     raise RuntimeError, "%s cannot be read \n" % xml 
    250                 return output 
    251         # Return a list of parsed entries that dataloader can manage 
    252         return None 
    253      
    254     def _create_unique_key(self, dictionary, name, i): 
    255         if dictionary.get(name) is not None: 
    256             i += 1 
    257             name = name.split("_")[0] 
    258             name += "_{0}".format(i) 
    259             name = self._create_unique_key(dictionary, name, i) 
    260         return name 
    261      
    262     def _iterate_namespace(self, ns): 
    263         # The current level to look through in cansas_constants. 
    264         current_level = CANSAS_FORMAT.get("SASentry") 
    265         # Defaults for variable and datatype 
    266         ns_variable = "{0}.meta_data[\"{2}\"] = \"{1}\"" 
    267         ns_datatype = "content" 
    268         ns_optional = True 
    269         for name in ns: 
    270             if name != "SASentry": 
    271                 current_level = current_level.get("children").get(name, "") 
    272                 if current_level == "": 
    273                     current_level = current_level.get("<any>", "") 
    274                 cl_variable = current_level.get("variable", "") 
    275                 cl_datatype = current_level.get("storeas", "") 
    276                 cl_units_optional = current_level.get("units_required", "") 
    277                 # Where are how to store the variable for the given namespace 
    278                 # The CANSAS_CONSTANTS tree is hierarchical, so is no value, inherit 
    279                 ns_variable = cl_variable if cl_variable != "" else ns_variable 
    280                 ns_datatype = cl_datatype if cl_datatype != "" else ns_datatype 
    281                 ns_optional = cl_units_optional if cl_units_optional != ns_optional else ns_optional 
    282         return current_level, ns_variable, ns_datatype, ns_optional 
    283      
    284     def _unit_conversion(self, new_current_level, attr, data1D, node_value, optional = True): 
    285         value_unit = '' 
    286         if 'unit' in attr and new_current_level.get('unit') is not None: 
     173                    raise RuntimeError, "%s cannot be read \n" % path 
     174        else: 
     175            raise RuntimeError, "%s is not a file" % path 
     176        # Return output consistent with the loader's api 
     177        if len(output) == 0: 
     178            #cannot return none when it cannot read 
     179            #return None 
     180            raise RuntimeError, "%s cannot be read \n" % path 
     181        elif len(output) == 1: 
     182            return output[0] 
     183        else: 
     184            return output 
     185                 
     186    def _parse_entry(self, dom): 
     187        """ 
     188        Parse a SASentry 
     189         
     190        :param node: SASentry node 
     191         
     192        :return: Data1D object 
     193        """ 
     194        x = numpy.zeros(0) 
     195        y = numpy.zeros(0) 
     196         
     197        data_info = Data1D(x, y) 
     198         
     199        # Look up title 
     200        self._store_content('ns:Title', dom, 'title', data_info) 
     201         
     202        # Look up run number 
     203        nodes = dom.xpath('ns:Run', namespaces={'ns': CANSAS_NS}) 
     204        for item in nodes: 
     205            if item.text is not None: 
     206                value = item.text.strip() 
     207                if len(value) > 0: 
     208                    data_info.run.append(value) 
     209                    if item.get('name') is not None: 
     210                        data_info.run_name[value] = item.get('name') 
     211                            
     212        # Look up instrument name 
     213        self._store_content('ns:SASinstrument/ns:name', dom, 'instrument', 
     214                             data_info) 
     215 
     216        # Notes 
     217        note_list = dom.xpath('ns:SASnote', namespaces={'ns': CANSAS_NS}) 
     218        for note in note_list: 
    287219            try: 
    288                 if isinstance(node_value, float) is False: 
    289                     exec("node_value = float({0})".format(node_value)) 
    290                 default_unit = None 
    291                 unitname = new_current_level.get("unit") 
    292                 exec "default_unit = data1D.{0}".format(unitname) 
    293                 local_unit = attr['unit'] 
    294                 if local_unit.lower() != default_unit.lower() and local_unit is not None\ 
    295                     and local_unit.lower() != "none" and default_unit is not None: 
    296                     if HAS_CONVERTER == True: 
    297                         try: 
    298                             data_conv_q = Converter(attr['unit']) 
    299                             value_unit = default_unit 
    300                             exec "node_value = data_conv_q(node_value, units=data1D.{0})".format(unitname) 
    301                         except: 
    302                             err_msg = "CanSAS reader: could not convert " 
    303                             err_msg += "Q unit {0}; ".format(local_unit) 
    304                             intermediate = "err_msg += \"expecting [{1}]  {2}\".format(data1D.{0}, sys.exc_info()[1])".format(unitname, "{0}", "{1}") 
    305                             exec intermediate 
    306                             self.errors.append(err_msg) 
    307                             if optional: 
    308                                 logging.info(err_msg) 
    309                             else: 
    310                                 raise ValueError, err_msg 
    311                     else: 
    312                         value_unit = local_unit 
    313                         err_msg = "CanSAS reader: unrecognized %s unit [%s];"\ 
    314                         % (node_value, default_unit) 
    315                         err_msg += " expecting [%s]" % local_unit 
    316                         self.errors.append(err_msg) 
    317                         if optional: 
    318                             logging.info(err_msg) 
     220                if note.text is not None: 
     221                    note_value = note.text.strip() 
     222                    if len(note_value) > 0: 
     223                        data_info.notes.append(note_value) 
     224            except: 
     225                err_mess = "cansas_reader.read: error processing" 
     226                err_mess += " entry notes\n  %s" % sys.exc_value 
     227                self.errors.append(err_mess) 
     228                logging.error(err_mess) 
     229         
     230        # Sample info ################### 
     231        entry = get_content('ns:SASsample', dom) 
     232        if entry is not None: 
     233            data_info.sample.name = entry.get('name') 
     234             
     235        self._store_content('ns:SASsample/ns:ID', 
     236                     dom, 'ID', data_info.sample) 
     237        self._store_float('ns:SASsample/ns:thickness', 
     238                     dom, 'thickness', data_info.sample) 
     239        self._store_float('ns:SASsample/ns:transmission', 
     240                     dom, 'transmission', data_info.sample) 
     241        self._store_float('ns:SASsample/ns:temperature', 
     242                     dom, 'temperature', data_info.sample) 
     243         
     244        nodes = dom.xpath('ns:SASsample/ns:details', 
     245                          namespaces={'ns': CANSAS_NS}) 
     246        for item in nodes: 
     247            try: 
     248                if item.text is not None: 
     249                    detail_value = item.text.strip() 
     250                    if len(detail_value) > 0: 
     251                        data_info.sample.details.append(detail_value) 
     252            except: 
     253                err_mess = "cansas_reader.read: error processing " 
     254                err_mess += " sample details\n  %s" % sys.exc_value 
     255                self.errors.append(err_mess) 
     256                logging.error(err_mess) 
     257         
     258        # Position (as a vector) 
     259        self._store_float('ns:SASsample/ns:position/ns:x', 
     260                     dom, 'position.x', data_info.sample) 
     261        self._store_float('ns:SASsample/ns:position/ns:y', 
     262                     dom, 'position.y', data_info.sample) 
     263        self._store_float('ns:SASsample/ns:position/ns:z', 
     264                     dom, 'position.z', data_info.sample) 
     265         
     266        # Orientation (as a vector) 
     267        self._store_float('ns:SASsample/ns:orientation/ns:roll', 
     268                     dom, 'orientation.x', data_info.sample) 
     269        self._store_float('ns:SASsample/ns:orientation/ns:pitch', 
     270                     dom, 'orientation.y', data_info.sample) 
     271        self._store_float('ns:SASsample/ns:orientation/ns:yaw', 
     272                     dom, 'orientation.z', data_info.sample) 
     273        
     274        # Source info ################### 
     275        entry = get_content('ns:SASinstrument/ns:SASsource', dom) 
     276        if entry is not None: 
     277            data_info.source.name = entry.get('name') 
     278         
     279        self._store_content('ns:SASinstrument/ns:SASsource/ns:radiation', 
     280                     dom, 'radiation', data_info.source) 
     281        self._store_content('ns:SASinstrument/ns:SASsource/ns:beam_shape', 
     282                     dom, 'beam_shape', data_info.source) 
     283        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength', 
     284                     dom, 'wavelength', data_info.source) 
     285        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_min', 
     286                     dom, 'wavelength_min', data_info.source) 
     287        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_max', 
     288                     dom, 'wavelength_max', data_info.source) 
     289        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_spread', 
     290                     dom, 'wavelength_spread', data_info.source) 
     291         
     292        # Beam size (as a vector)    
     293        entry = get_content('ns:SASinstrument/ns:SASsource/ns:beam_size', dom) 
     294        if entry is not None: 
     295            data_info.source.beam_size_name = entry.get('name') 
     296             
     297        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:x', 
     298                     dom, 'beam_size.x', data_info.source) 
     299        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:y', 
     300                     dom, 'beam_size.y', data_info.source) 
     301        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:z', 
     302                     dom, 'beam_size.z', data_info.source) 
     303         
     304        # Collimation info ################### 
     305        nodes = dom.xpath('ns:SASinstrument/ns:SAScollimation', 
     306                          namespaces={'ns': CANSAS_NS}) 
     307        for item in nodes: 
     308            collim = Collimation() 
     309            if item.get('name') is not None: 
     310                collim.name = item.get('name') 
     311            self._store_float('ns:length', item, 'length', collim) 
     312             
     313            # Look for apertures 
     314            apert_list = item.xpath('ns:aperture', namespaces={'ns': CANSAS_NS}) 
     315            for apert in apert_list: 
     316                aperture = Aperture() 
     317                 
     318                # Get the name and type of the aperture 
     319                aperture.name = apert.get('name') 
     320                aperture.type = apert.get('type') 
     321                     
     322                self._store_float('ns:distance', apert, 'distance', aperture) 
     323                 
     324                entry = get_content('ns:size', apert) 
     325                if entry is not None: 
     326                    aperture.size_name = entry.get('name') 
     327                 
     328                self._store_float('ns:size/ns:x', apert, 'size.x', aperture) 
     329                self._store_float('ns:size/ns:y', apert, 'size.y', aperture) 
     330                self._store_float('ns:size/ns:z', apert, 'size.z', aperture) 
     331                 
     332                collim.aperture.append(aperture) 
     333                 
     334            data_info.collimation.append(collim) 
     335         
     336        # Detector info ###################### 
     337        nodes = dom.xpath('ns:SASinstrument/ns:SASdetector', 
     338                           namespaces={'ns': CANSAS_NS}) 
     339        for item in nodes: 
     340             
     341            detector = Detector() 
     342             
     343            self._store_content('ns:name', item, 'name', detector) 
     344            self._store_float('ns:SDD', item, 'distance', detector) 
     345             
     346            # Detector offset (as a vector) 
     347            self._store_float('ns:offset/ns:x', item, 'offset.x', detector) 
     348            self._store_float('ns:offset/ns:y', item, 'offset.y', detector) 
     349            self._store_float('ns:offset/ns:z', item, 'offset.z', detector) 
     350             
     351            # Detector orientation (as a vector) 
     352            self._store_float('ns:orientation/ns:roll', item, 'orientation.x', 
     353                               detector) 
     354            self._store_float('ns:orientation/ns:pitch', item, 'orientation.y', 
     355                               detector) 
     356            self._store_float('ns:orientation/ns:yaw', item, 'orientation.z', 
     357                               detector) 
     358             
     359            # Beam center (as a vector) 
     360            self._store_float('ns:beam_center/ns:x', item, 'beam_center.x', 
     361                               detector) 
     362            self._store_float('ns:beam_center/ns:y', item, 'beam_center.y', 
     363                              detector) 
     364            self._store_float('ns:beam_center/ns:z', item, 'beam_center.z', 
     365                               detector) 
     366             
     367            # Pixel size (as a vector) 
     368            self._store_float('ns:pixel_size/ns:x', item, 'pixel_size.x', 
     369                               detector) 
     370            self._store_float('ns:pixel_size/ns:y', item, 'pixel_size.y', 
     371                               detector) 
     372            self._store_float('ns:pixel_size/ns:z', item, 'pixel_size.z', 
     373                               detector) 
     374             
     375            self._store_float('ns:slit_length', item, 'slit_length', detector) 
     376             
     377            data_info.detector.append(detector) 
     378 
     379        # Processes info ###################### 
     380        nodes = dom.xpath('ns:SASprocess', namespaces={'ns': CANSAS_NS}) 
     381        for item in nodes: 
     382            process = Process() 
     383            self._store_content('ns:name', item, 'name', process) 
     384            self._store_content('ns:date', item, 'date', process) 
     385            self._store_content('ns:description', item, 'description', process) 
     386             
     387            term_list = item.xpath('ns:term', namespaces={'ns': CANSAS_NS}) 
     388            for term in term_list: 
     389                try: 
     390                    term_attr = {} 
     391                    for attr in term.keys(): 
     392                        term_attr[attr] = term.get(attr).strip() 
     393                    if term.text is not None: 
     394                        term_attr['value'] = term.text.strip() 
     395                        process.term.append(term_attr) 
     396                except: 
     397                    err_mess = "cansas_reader.read: error processing " 
     398                    err_mess += " process term\n  %s" % sys.exc_value 
     399                    self.errors.append(err_mess) 
     400                    logging.error(err_mess) 
     401             
     402            note_list = item.xpath('ns:SASprocessnote', 
     403                                   namespaces={'ns': CANSAS_NS}) 
     404            for note in note_list: 
     405                if note.text is not None: 
     406                    process.notes.append(note.text.strip()) 
     407             
     408            data_info.process.append(process) 
     409             
     410        # Data info ###################### 
     411        nodes = dom.xpath('ns:SASdata', namespaces={'ns': CANSAS_NS}) 
     412        if len(nodes) > 1: 
     413            msg = "CanSAS reader is not compatible with multiple" 
     414            msg += " SASdata entries" 
     415            raise RuntimeError, msg 
     416         
     417        nodes = dom.xpath('ns:SASdata/ns:Idata', namespaces={'ns': CANSAS_NS}) 
     418 
     419        x = numpy.zeros(0) 
     420        y = numpy.zeros(0) 
     421        dx = numpy.zeros(0) 
     422        dy = numpy.zeros(0) 
     423        dxw = numpy.zeros(0) 
     424        dxl = numpy.zeros(0) 
     425         
     426        for item in nodes: 
     427            _x, attr = get_float('ns:Q', item) 
     428            _dx, attr_d = get_float('ns:Qdev', item) 
     429            _dxl, attr_l = get_float('ns:dQl', item) 
     430            _dxw, attr_w = get_float('ns:dQw', item) 
     431            if _dx == None: 
     432                _dx = 0.0 
     433            if _dxl == None: 
     434                _dxl = 0.0 
     435            if _dxw == None: 
     436                _dxw = 0.0 
     437                 
     438            if 'unit' in attr and \ 
     439                attr['unit'].lower() != data_info.x_unit.lower(): 
     440                if HAS_CONVERTER == True: 
     441                    try: 
     442                        data_conv_q = Converter(attr['unit']) 
     443                        _x = data_conv_q(_x, units=data_info.x_unit) 
     444                    except: 
     445                        msg = "CanSAS reader: could not convert " 
     446                        msg += "Q unit [%s]; " % attr['unit'], 
     447                        msg += "expecting [%s]\n  %s" % (data_info.x_unit, 
     448                                                         sys.exc_value) 
     449                        raise ValueError, msg 
     450                         
     451                else: 
     452                    msg = "CanSAS reader: unrecognized Q unit [%s]; "\ 
     453                    % attr['unit'] 
     454                    msg += "expecting [%s]" % data_info.x_unit 
     455                    raise ValueError, msg 
     456                         
     457            # Error in Q 
     458            if 'unit' in attr_d and \ 
     459                attr_d['unit'].lower() != data_info.x_unit.lower(): 
     460                if HAS_CONVERTER == True: 
     461                    try: 
     462                        data_conv_q = Converter(attr_d['unit']) 
     463                        _dx = data_conv_q(_dx, units=data_info.x_unit) 
     464                    except: 
     465                        msg = "CanSAS reader: could not convert dQ unit [%s]; "\ 
     466                        % attr['unit'] 
     467                        msg += " expecting " 
     468                        msg += "[%s]\n  %s" % (data_info.x_unit, sys.exc_value) 
     469                        raise ValueError, msg 
     470                         
     471                else: 
     472                    msg = "CanSAS reader: unrecognized dQ unit [%s]; "\ 
     473                    % attr['unit'] 
     474                    msg += "expecting [%s]" % data_info.x_unit 
     475                    raise ValueError, msg 
     476                         
     477            # Slit length 
     478            if 'unit' in attr_l and \ 
     479                attr_l['unit'].lower() != data_info.x_unit.lower(): 
     480                if HAS_CONVERTER == True: 
     481                    try: 
     482                        data_conv_q = Converter(attr_l['unit']) 
     483                        _dxl = data_conv_q(_dxl, units=data_info.x_unit) 
     484                    except: 
     485                        msg = "CanSAS reader: could not convert dQl unit [%s];"\ 
     486                        % attr['unit'] 
     487                        msg += " expecting [%s]\n  %s" % (data_info.x_unit, 
     488                                                          sys.exc_value) 
     489                        raise ValueError, msg  
     490                else: 
     491                    msg = "CanSAS reader: unrecognized dQl unit [%s];"\ 
     492                    % attr['unit'] 
     493                    msg += " expecting [%s]" % data_info.x_unit 
     494                    raise ValueError, msg 
     495                         
     496            # Slit width 
     497            if 'unit' in attr_w and \ 
     498            attr_w['unit'].lower() != data_info.x_unit.lower(): 
     499                if HAS_CONVERTER == True: 
     500                    try: 
     501                        data_conv_q = Converter(attr_w['unit']) 
     502                        _dxw = data_conv_q(_dxw, units=data_info.x_unit) 
     503                    except: 
     504                        msg = "CanSAS reader: could not convert dQw unit [%s];"\ 
     505                        % attr['unit'] 
     506                        msg += " expecting [%s]\n  %s" % (data_info.x_unit, 
     507                                                          sys.exc_value) 
     508                        raise ValueError, msg 
     509                         
     510                else: 
     511                    msg = "CanSAS reader: unrecognized dQw unit [%s];"\ 
     512                    % attr['unit'] 
     513                    msg += " expecting [%s]" % data_info.x_unit 
     514                    raise ValueError, msg 
     515            _y, attr = get_float('ns:I', item) 
     516            _dy, attr_d = get_float('ns:Idev', item) 
     517            if _dy == None: 
     518                _dy = 0.0 
     519            if 'unit' in attr and \ 
     520            attr['unit'].lower() != data_info.y_unit.lower(): 
     521                if HAS_CONVERTER == True: 
     522                    try: 
     523                        data_conv_i = Converter(attr['unit']) 
     524                        _y = data_conv_i(_y, units=data_info.y_unit) 
     525                    except: 
     526                        if attr['unit'].lower() == 'count': 
     527                            pass 
    319528                        else: 
    320                             raise ValueError, err_msg 
     529                            msg = "CanSAS reader: could not" 
     530                            msg += " convert I(q) unit [%s];" % str(attr['unit']) 
     531                            msg += " expecting [%s]\n" % str(data_info.y_unit) 
     532                            msg += "  %s" % str(sys.exc_value) 
     533                            raise ValueError, msg 
    321534                else: 
    322                     value_unit = local_unit 
    323             except: 
    324                 err_msg = "CanSAS reader: could not convert " 
    325                 err_msg += "Q unit [%s]; " % attr['unit'], 
    326                 exec "err_msg += \"expecting [%s]\n  %s\" % (data1D.{0}, sys.exc_info()[1])".format(unitname) 
    327                 self.errors.append(err_msg) 
    328                 if optional: 
    329                     logging.info(err_msg) 
     535                    msg = "CanSAS reader: unrecognized I(q) unit [%s];"\ 
     536                    % attr['unit'] 
     537                    msg += " expecting [%s]" % data_info.y_unit 
     538                    raise ValueError, msg  
     539                         
     540            if 'unit' in attr_d and \ 
     541            attr_d['unit'].lower() != data_info.y_unit.lower(): 
     542                if HAS_CONVERTER == True: 
     543                    try: 
     544                        data_conv_i = Converter(attr_d['unit']) 
     545                        _dy = data_conv_i(_dy, units=data_info.y_unit) 
     546                    except: 
     547                        if attr_d['unit'].lower() == 'count': 
     548                            pass 
     549                        else: 
     550                            msg = "CanSAS reader: could not convert dI(q) unit " 
     551                            msg += "[%s]; expecting [%s]\n  %s" % (attr_d['unit'], 
     552                                                 data_info.y_unit, sys.exc_value) 
     553                            raise ValueError, msg 
    330554                else: 
    331                     raise ValueError, err_msg 
    332         elif 'unit' in attr: 
    333             value_unit = attr['unit'] 
    334         node_value = "float({0})".format(node_value) 
    335         return node_value, value_unit 
    336      
    337     def _parse_entry(self, dom, ns, data1D, extras = []): 
    338         """ 
    339         Parse a SASEntry - new recursive method for parsing the dom of 
    340             the CanSAS data format. This will allow multiple data files 
    341             and extra nodes to be read in simultaneously. 
    342          
    343         :param dom: dom object with a namespace base of ns 
    344         :param ns: A list of element names that lead up to the dom object 
    345         :param data1D: The data1D object that will be modified 
    346         """ 
    347           
    348         # A portion of every namespace entry 
    349         base_ns = "{0}{1}{2}".format("{", CANSAS_NS.get(self.cansasVersion).get("ns"), "}") 
    350         unit = '' 
    351          
    352         # Go through each child in the parent element 
    353         for node in dom: 
    354             try: 
    355                 # Get the element name and set the current ns level 
    356                 tagname = node.tag.replace(base_ns, "") 
    357                 tagname_original = tagname 
    358                 ns.append(tagname) 
    359                 attr = node.attrib 
    360                  
    361                 # Look for special cases 
    362                 save_data1D = data1D 
    363                 if tagname == "SASdetector": 
    364                     data1D = Detector() 
    365                 elif tagname == "SAScollimation": 
    366                     data1D = Collimation() 
    367                 elif tagname == "SASprocess": 
    368                     data1D = Process() 
    369                     for child in node: 
    370                         if child.tag.replace(base_ns, "") == "term": 
    371                             term_attr = {} 
    372                             for attr in child.keys(): 
    373                                 term_attr[attr] = ' '.join(child.get(attr).split()) 
    374                             if child.text is not None: 
    375                                 term_attr['value'] = ' '.join(child.text.split()) 
    376                             data1D.term.append(term_attr) 
    377                 elif tagname == "aperture": 
    378                     data1D = Aperture() 
    379                  
    380                 # Get where to store content 
    381                 new_current_level, ns_variable, ns_datatype, optional = self._iterate_namespace(ns) 
    382                 # If the element is a child element, recurse 
    383                 if node.getchildren() is not None: 
    384                     # Returned value is new Data1D object with all previous and new values in it. 
    385                     data1D, extras = self._parse_entry(node, ns, data1D, extras) 
    386                      
    387                 #Get the information from the node 
    388                 node_value = node.text 
    389                 if node_value == "": 
    390                     node_value = None 
    391                 if node_value is not None: 
    392                     node_value = ' '.join(node_value.split()) 
    393                  
    394                 # If the value is a float, compile with units. 
    395                 if ns_datatype == "float": 
    396                     # If an empty value is given, store as zero. 
    397                     if node_value is None or node_value.isspace() or node_value.lower() == "nan": 
    398                         node_value = "0.0" 
    399                     node_value, unit = self._unit_conversion(new_current_level, attr, data1D, node_value, optional) 
    400                      
    401                 # If appending to a dictionary (meta_data | run_name), name sure the key is unique 
    402                 if ns_variable == "{0}.meta_data[\"{2}\"] = \"{1}\"": 
    403                     # If we are within a Process, Detector, Collimation or Aperture instance, pull out old data1D 
    404                     tagname = self._create_unique_key(data1D.meta_data, tagname, 0) 
    405                     if isinstance(data1D, Data1D) == False: 
    406                         store_me = ns_variable.format("data1D", node_value, tagname) 
    407                         extras.append(store_me) 
    408                         ns_variable = None 
    409                 if ns_variable == "{0}.run_name[\"{2}\"] = \"{1}\"": 
    410                     tagname = self._create_unique_key(data1D.run_name, tagname, 0) 
    411                  
    412                 # Check for Data1D object and any extra commands to save 
    413                 if isinstance(data1D, Data1D): 
    414                     for item in extras: 
    415                         exec item 
    416                 # Don't bother saving empty information unless it is a float 
    417                 if ns_variable is not None and node_value is not None and node_value.isspace() == False: 
    418                     # Format a string and then execute it. 
    419                     store_me = ns_variable.format("data1D", node_value, tagname) 
    420                     exec store_me 
    421                 # Get attributes and process them 
    422                 if attr is not None: 
    423                     for key in node.keys(): 
    424                         try: 
    425                             cansas_attrib = new_current_level.get("attributes").get(key) 
    426                             attrib_variable = cansas_attrib.get("variable") 
    427                             if key == 'unit' and unit != '': 
    428                                 attrib_value = unit 
    429                             else: 
    430                                 attrib_value = node.attrib[key] 
    431                             store_attr = attrib_variable.format("data1D", attrib_value, key) 
    432                             exec store_attr 
    433                         except AttributeError as e: 
    434                             pass 
    435                              
    436                       
    437             except Exception as e: 
    438                 exc_type, exc_obj, exc_tb = sys.exc_info() 
    439                 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] 
    440                 print(e, exc_type, fname, exc_tb.tb_lineno, tagname, exc_obj) 
    441             finally: 
    442                 # Save special cases in original data1D object and then restore the data1D 
    443                 if tagname_original == "SASdetector": 
    444                     save_data1D.detector.append(data1D) 
    445                 elif tagname_original == "SAScollimation": 
    446                     save_data1D.collimation.append(data1D) 
    447                 elif tagname_original == "SASprocess": 
    448                     save_data1D.process.append(data1D) 
    449                 elif tagname_original == "aperture": 
    450                     save_data1D.aperture.append(data1D) 
    451                 else: 
    452                     save_data1D = data1D 
    453                 data1D = save_data1D 
    454                 # Remove tagname from ns to restore original base 
    455                 ns.remove(tagname_original) 
    456          
    457         return data1D, extras 
    458          
     555                    msg = "CanSAS reader: unrecognized dI(q) unit [%s]; "\ 
     556                    % attr_d['unit'] 
     557                    msg += "expecting [%s]" % data_info.y_unit 
     558                    raise ValueError, msg 
     559                 
     560            if _x is not None and _y is not None: 
     561                x = numpy.append(x, _x) 
     562                y = numpy.append(y, _y) 
     563                dx = numpy.append(dx, _dx) 
     564                dy = numpy.append(dy, _dy) 
     565                dxl = numpy.append(dxl, _dxl) 
     566                dxw = numpy.append(dxw, _dxw) 
     567        # Zeros in dx, dy 
     568        if not numpy.all(dx == 0): 
     569            dx[dx == 0] = _ZERO 
     570        if not numpy.all(dy == 0): 
     571            dy[dy == 0] = _ZERO 
     572        
     573        data_info.x = x[x != 0] 
     574        data_info.y = y[x != 0] 
     575        data_info.dx = dx[x != 0] 
     576         
     577        data_info.dy = dy[x != 0] 
     578        data_info.dxl = dxl[x != 0] 
     579        data_info.dxw = dxw[x != 0] 
     580         
     581        data_conv_q = None 
     582        data_conv_i = None 
     583         
     584        if HAS_CONVERTER == True and data_info.x_unit != '1/A': 
     585            data_conv_q = Converter('1/A') 
     586            # Test it 
     587            data_conv_q(1.0, data_info.x_unit) 
     588             
     589        if HAS_CONVERTER == True and data_info.y_unit != '1/cm': 
     590            data_conv_i = Converter('1/cm') 
     591            # Test it 
     592            data_conv_i(1.0, data_info.y_unit) 
     593                 
     594        if data_conv_q is not None: 
     595            data_info.xaxis("\\rm{Q}", data_info.x_unit) 
     596        else: 
     597            data_info.xaxis("\\rm{Q}", 'A^{-1}') 
     598        if data_conv_i is not None: 
     599            data_info.yaxis("\\rm{Intensity}", data_info.y_unit) 
     600        else: 
     601            data_info.yaxis("\\rm{Intensity}", "cm^{-1}") 
     602 
     603        return data_info 
     604 
    459605    def _to_xml_doc(self, datainfo): 
    460606        """ 
     
    467613            raise RuntimeError, "The cansas writer expects a Data1D instance" 
    468614         
    469         ns = CANSAS_NS.get(self.cansasVersion).get("ns") 
    470615        doc = xml.dom.minidom.Document() 
    471616        main_node = doc.createElement("SASroot") 
    472         main_node.setAttribute("version", self.cansasVersion) 
    473         main_node.setAttribute("xmlns", ns) 
     617        main_node.setAttribute("version", self.version) 
     618        main_node.setAttribute("xmlns", "cansas1d/%s" % self.version) 
    474619        main_node.setAttribute("xmlns:xsi", 
    475620                               "http://www.w3.org/2001/XMLSchema-instance") 
    476621        main_node.setAttribute("xsi:schemaLocation", 
    477                                "{0} http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd".format(ns)) 
     622                               "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version) 
    478623         
    479624        doc.appendChild(main_node) 
     
    501646                write_node(doc, pt, "I", datainfo.y[i], 
    502647                            {'unit': datainfo.y_unit}) 
    503             if datainfo.dy != None and len(datainfo.dy) >= i: 
    504                 write_node(doc, pt, "Idev", datainfo.dy[i], 
    505                             {'unit': datainfo.y_unit}) 
    506648            if datainfo.dx != None and len(datainfo.dx) >= i: 
    507649                write_node(doc, pt, "Qdev", datainfo.dx[i], 
     650                            {'unit': datainfo.x_unit}) 
     651            if datainfo.dxl != None and len(datainfo.dxl) >= i: 
     652                write_node(doc, pt, "dQl", datainfo.dxl[i], 
    508653                            {'unit': datainfo.x_unit}) 
    509654            if datainfo.dxw != None and len(datainfo.dxw) >= i: 
    510655                write_node(doc, pt, "dQw", datainfo.dxw[i], 
    511656                            {'unit': datainfo.x_unit}) 
    512             if datainfo.dxl != None and len(datainfo.dxl) >= i: 
    513                 write_node(doc, pt, "dQl", datainfo.dxl[i], 
    514                             {'unit': datainfo.x_unit}) 
    515  
    516         # Transmission Spectrum Info 
    517         if len(datainfo.trans_spectrum.wavelength) > 0: 
    518             node = doc.createElement("SAStransmission_spectrum") 
    519             entry_node.appendChild(node) 
    520             for i in range(len(datainfo.trans_spectrum.wavelength)): 
    521                 pt = doc.createElement("Tdata") 
    522                 node.appendChild(pt) 
    523                 write_node(doc, pt, "Lambda", datainfo.trans_spectrum.wavelength[i],  
    524                            {'unit': datainfo.trans_spectrum.wavelength_unit}) 
    525                 write_node(doc, pt, "T", datainfo.trans_spectrum.transmission[i],  
    526                            {'unit': datainfo.trans_spectrum.transmission_unit}) 
    527                 if datainfo.trans_spectrum.transmission_deviation != None \ 
    528                 and len(datainfo.trans_spectrum.transmission_deviation) >= i: 
    529                     write_node(doc, pt, "Tdev", datainfo.trans_spectrum.transmission_deviation[i],  
    530                                {'unit': datainfo.trans_spectrum.transmission_deviation_unit}) 
     657            if datainfo.dy != None and len(datainfo.dy) >= i: 
     658                write_node(doc, pt, "Idev", datainfo.dy[i], 
     659                            {'unit': datainfo.y_unit}) 
    531660 
    532661        # Sample info 
     
    541670        write_node(doc, sample, "temperature", datainfo.sample.temperature, 
    542671                   {"unit": datainfo.sample.temperature_unit}) 
     672         
     673        for item in datainfo.sample.details: 
     674            write_node(doc, sample, "details", item) 
    543675         
    544676        pos = doc.createElement("position") 
     
    567699            sample.appendChild(ori) 
    568700         
    569         for item in datainfo.sample.details: 
    570             write_node(doc, sample, "details", item) 
    571          
    572701        # Instrument info 
    573702        instr = doc.createElement("SASinstrument") 
     
    581710            source.setAttribute("name", str(datainfo.source.name)) 
    582711        instr.appendChild(source) 
     712         
    583713        write_node(doc, source, "radiation", datainfo.source.radiation) 
    584          
     714        write_node(doc, source, "beam_shape", datainfo.source.beam_shape) 
    585715        size = doc.createElement("beam_size") 
    586716        if datainfo.source.beam_size_name is not None: 
     
    597727            source.appendChild(size) 
    598728             
    599         write_node(doc, source, "beam_shape", datainfo.source.beam_shape) 
    600729        write_node(doc, source, "wavelength", 
    601730                   datainfo.source.wavelength, 
     
    629758                coll.appendChild(ap) 
    630759                 
     760                write_node(doc, ap, "distance", apert.distance, 
     761                           {"unit": apert.distance_unit}) 
     762                 
    631763                size = doc.createElement("size") 
    632764                if apert.size_name is not None: 
     
    640772                if written == True: 
    641773                    ap.appendChild(size) 
    642                  
    643                 write_node(doc, ap, "distance", apert.distance, 
    644                            {"unit": apert.distance_unit}) 
    645774 
    646775        #   Detectors 
     
    650779            written = written | write_node(doc, det, "SDD", item.distance, 
    651780                                           {"unit": item.distance_unit}) 
     781            written = written | write_node(doc, det, "slit_length", 
     782                                           item.slit_length, 
     783                                           {"unit": item.slit_length_unit}) 
    652784            if written == True: 
    653785                instr.appendChild(det) 
     
    662794            if written == True: 
    663795                det.appendChild(off) 
     796             
     797            center = doc.createElement("beam_center") 
     798            written = write_node(doc, center, "x", item.beam_center.x, 
     799                                 {"unit": item.beam_center_unit}) 
     800            written = written | write_node(doc, center, "y", 
     801                                           item.beam_center.y, 
     802                                           {"unit": item.beam_center_unit}) 
     803            written = written | write_node(doc, center, "z", 
     804                                           item.beam_center.z, 
     805                                           {"unit": item.beam_center_unit}) 
     806            if written == True: 
     807                det.appendChild(center) 
     808                 
     809            pix = doc.createElement("pixel_size") 
     810            written = write_node(doc, pix, "x", item.pixel_size.x, 
     811                                 {"unit": item.pixel_size_unit}) 
     812            written = written | write_node(doc, pix, "y", item.pixel_size.y, 
     813                                           {"unit": item.pixel_size_unit}) 
     814            written = written | write_node(doc, pix, "z", item.pixel_size.z, 
     815                                           {"unit": item.pixel_size_unit}) 
     816            if written == True: 
     817                det.appendChild(pix) 
    664818                 
    665819            ori = doc.createElement("orientation") 
     
    674828            if written == True: 
    675829                det.appendChild(ori) 
    676              
    677             center = doc.createElement("beam_center") 
    678             written = write_node(doc, center, "x", item.beam_center.x, 
    679                                  {"unit": item.beam_center_unit}) 
    680             written = written | write_node(doc, center, "y", 
    681                                            item.beam_center.y, 
    682                                            {"unit": item.beam_center_unit}) 
    683             written = written | write_node(doc, center, "z", 
    684                                            item.beam_center.z, 
    685                                            {"unit": item.beam_center_unit}) 
    686             if written == True: 
    687                 det.appendChild(center) 
    688                  
    689             pix = doc.createElement("pixel_size") 
    690             written = write_node(doc, pix, "x", item.pixel_size.x, 
    691                                  {"unit": item.pixel_size_unit}) 
    692             written = written | write_node(doc, pix, "y", item.pixel_size.y, 
    693                                            {"unit": item.pixel_size_unit}) 
    694             written = written | write_node(doc, pix, "z", item.pixel_size.z, 
    695                                            {"unit": item.pixel_size_unit}) 
    696             if written == True: 
    697                 det.appendChild(pix) 
    698             written = written | write_node(doc, det, "slit_length", 
    699                                            item.slit_length, 
    700                                            {"unit": item.slit_length_unit}) 
    701              
     830                 
    702831        # Processes info 
    703832        for item in datainfo.process: 
     
    714843            for note in item.notes: 
    715844                write_node(doc, node, "SASprocessnote", note) 
    716             if len(item.notes) == 0: 
    717                 write_node(doc, node, "SASprocessnote", "") 
    718                  
    719         # Note info 
    720         if len(datainfo.notes) == 0: 
    721             node = doc.createElement("SASnote") 
    722             entry_node.appendChild(node) 
    723             if node.hasChildNodes(): 
    724                 for child in node.childNodes: 
    725                     node.removeChild(child) 
    726         else: 
    727             for item in datainfo.notes: 
    728                 node = doc.createElement("SASnote") 
    729                 entry_node.appendChild(node) 
    730                 node.appendChild(doc.createTextNode(item)) 
    731                  
     845         
    732846        # Return the document, and the SASentry node associated with 
    733847        # the data we just wrote 
     
    747861        fd.write(doc.toprettyxml()) 
    748862        fd.close() 
     863         
     864    def _store_float(self, location, node, variable, storage, optional=True): 
     865        """ 
     866        Get the content of a xpath location and store 
     867        the result. Check that the units are compatible 
     868        with the destination. The value is expected to 
     869        be a float. 
     870         
     871        The xpath location might or might not exist. 
     872        If it does not exist, nothing is done 
     873         
     874        :param location: xpath location to fetch 
     875        :param node: node to read the data from 
     876        :param variable: name of the data member to store it in [string] 
     877        :param storage: data object that has the 'variable' data member 
     878        :param optional: if True, no exception will be raised 
     879            if unit conversion can't be done 
     880 
     881        :raise ValueError: raised when the units are not recognized 
     882        """ 
     883        entry = get_content(location, node) 
     884        try: 
     885            value = float(entry.text) 
     886        except: 
     887            value = None 
     888             
     889        if value is not None: 
     890            # If the entry has units, check to see that they are 
     891            # compatible with what we currently have in the data object 
     892            units = entry.get('unit') 
     893            if units is not None: 
     894                toks = variable.split('.') 
     895                local_unit = None 
     896                exec "local_unit = storage.%s_unit" % toks[0] 
     897                if local_unit != None and units.lower() != local_unit.lower(): 
     898                    if HAS_CONVERTER == True: 
     899                        try: 
     900                            conv = Converter(units) 
     901                            exec "storage.%s = %g" % (variable, 
     902                                            conv(value, units=local_unit)) 
     903                        except: 
     904                            err_mess = "CanSAS reader: could not convert" 
     905                            err_mess += " %s unit [%s]; expecting [%s]\n  %s" \ 
     906                                % (variable, units, local_unit, sys.exc_value) 
     907                            self.errors.append(err_mess) 
     908                            if optional: 
     909                                logging.info(err_mess) 
     910                            else: 
     911                                raise ValueError, err_mess 
     912                    else: 
     913                        err_mess = "CanSAS reader: unrecognized %s unit [%s];"\ 
     914                        % (variable, units) 
     915                        err_mess += " expecting [%s]" % local_unit 
     916                        self.errors.append(err_mess) 
     917                        if optional: 
     918                            logging.info(err_mess) 
     919                        else: 
     920                            raise ValueError, err_mess 
     921                else: 
     922                    exec "storage.%s = value" % variable 
     923            else: 
     924                exec "storage.%s = value" % variable 
     925                 
     926    def _store_content(self, location, node, variable, storage): 
     927        """ 
     928        Get the content of a xpath location and store 
     929        the result. The value is treated as a string. 
     930         
     931        The xpath location might or might not exist. 
     932        If it does not exist, nothing is done 
     933         
     934        :param location: xpath location to fetch 
     935        :param node: node to read the data from 
     936        :param variable: name of the data member to store it in [string] 
     937        :param storage: data object that has the 'variable' data member 
     938         
     939        :return: return a list of errors 
     940        """ 
     941        entry = get_content(location, node) 
     942        if entry is not None and entry.text is not None: 
     943            exec "storage.%s = entry.text.strip()" % variable 
  • src/sans/models/c_extension/c_models/c_models.cpp

    r81b524f r81b524f  
    1212 
    1313 // adding generated code  
     14void addCLinearPearlsModel(PyObject *module);  
     15void addCRaspBerryModel(PyObject *module);  
     16void addCCore2ndMomentModel(PyObject *module);  
     17void addCStackedDisksModel(PyObject *module);  
     18void addCCoreShellCylinderModel(PyObject *module);  
     19void addCReflModel(PyObject *module);  
     20void addCSphereSLDModel(PyObject *module);  
     21void addCFractalModel(PyObject *module);  
     22void addCLogNormal(PyObject *module);  
     23void addCPringlesModel(PyObject *module);  
     24void addCCappedCylinderModel(PyObject *module);  
     25void addCLorentzian(PyObject *module);  
     26void addCBCCrystalModel(PyObject *module);  
     27void addCPearlNecklaceModel(PyObject *module);  
     28void addCSCCrystalModel(PyObject *module);  
     29void addCGaussian(PyObject *module);  
     30void addCLamellarModel(PyObject *module);  
     31void addCLamellarPCrystalModel(PyObject *module);  
     32void addCMassFractalModel(PyObject *module);  
     33void addCPoly_GaussCoil(PyObject *module);  
     34void addCTeubnerStreyModel(PyObject *module);  
     35void addCOnionModel(PyObject *module);  
     36void addCHollowCylinderModel(PyObject *module);  
     37void addCTriaxialEllipsoidModel(PyObject *module);  
     38void addCEllipticalCylinderModel(PyObject *module);  
     39void addCSchulz(PyObject *module);  
     40void addCLamellarPSHGModel(PyObject *module);  
     41void addCDABModel(PyObject *module);  
     42void addCStarPolymer(PyObject *module);  
     43void addCFuzzySphereModel(PyObject *module);  
     44void addCParallelepipedModel(PyObject *module);  
     45void addCMassSurfaceFractal(PyObject *module);  
     46void addCVesicleModel(PyObject *module);  
     47void addCGelFitModel(PyObject *module);  
     48void addCCoreShellEllipsoidModel(PyObject *module);  
     49void addCRPAModel(PyObject *module);  
     50void addCHayterMSAStructure(PyObject *module);  
     51void addCCSParallelepipedModel(PyObject *module);  
     52void addCFractalO_Z(PyObject *module);  
     53void addCMultiShellModel(PyObject *module);  
     54void addCLamellarPSModel(PyObject *module);  
     55void addCEllipsoidModel(PyObject *module);  
     56void addCTwoYukawaModel(PyObject *module);  
     57void addCDiamEllipFunc(PyObject *module);  
     58void addCHardsphereStructure(PyObject *module);  
     59void addCLamellarFFHGModel(PyObject *module);  
     60void addCCoreShellBicelleModel(PyObject *module);  
     61void addCFCCrystalModel(PyObject *module);  
     62void addCFlexibleCylinderModel(PyObject *module);  
     63void addCSurfaceFractalModel(PyObject *module);  
     64void addCDiamCylFunc(PyObject *module);  
     65void addCCoreFourShellModel(PyObject *module);  
     66void addCStickyHSStructure(PyObject *module);  
     67void addCReflAdvModel(PyObject *module);  
     68void addCSphereModel(PyObject *module);  
     69void addCFlexCylEllipXModel(PyObject *module);  
     70void addCSquareWellStructure(PyObject *module);  
     71void addCSLDCalFunc(PyObject *module);  
     72void addCCoreShellModel(PyObject *module);  
    1473void addCBarBellModel(PyObject *module);  
    15 void addCBCCrystalModel(PyObject *module);  
    1674void addCBinaryHSModel(PyObject *module);  
    17 void addCCappedCylinderModel(PyObject *module);  
    18 void addCCoreFourShellModel(PyObject *module);  
    19 void addCCore2ndMomentModel(PyObject *module);  
    20 void addCCoreShellModel(PyObject *module);  
    21 void addCCoreShellBicelleModel(PyObject *module);  
    22 void addCCoreShellCylinderModel(PyObject *module);  
    23 void addCCSParallelepipedModel(PyObject *module);  
    2475void addCCylinderModel(PyObject *module);  
    25 void addCDABModel(PyObject *module);  
    26 void addCDiamCylFunc(PyObject *module);  
    27 void addCDiamEllipFunc(PyObject *module);  
    28 void addCEllipsoidModel(PyObject *module);  
    29 void addCEllipticalCylinderModel(PyObject *module);  
    30 void addCFCCrystalModel(PyObject *module);  
    31 void addCFlexCylEllipXModel(PyObject *module);  
    32 void addCFlexibleCylinderModel(PyObject *module);  
    33 void addCFractalModel(PyObject *module);  
    34 void addCFractalO_Z(PyObject *module);  
    35 void addCFuzzySphereModel(PyObject *module);  
    36 void addCGaussian(PyObject *module);  
    37 void addCGelFitModel(PyObject *module);  
    38 void addCHardsphereStructure(PyObject *module);  
    39 void addCHayterMSAStructure(PyObject *module);  
    40 void addCHollowCylinderModel(PyObject *module);  
    41 void addCLamellarModel(PyObject *module);  
    42 void addCLamellarFFHGModel(PyObject *module);  
    43 void addCLamellarPCrystalModel(PyObject *module);  
    44 void addCLamellarPSModel(PyObject *module);  
    45 void addCLamellarPSHGModel(PyObject *module);  
    46 void addCLinearPearlsModel(PyObject *module);  
    47 void addCLogNormal(PyObject *module);  
    48 void addCLorentzian(PyObject *module);  
    49 void addCMassFractalModel(PyObject *module);  
    50 void addCMassSurfaceFractal(PyObject *module);  
    51 void addCMultiShellModel(PyObject *module);  
    52 void addCOnionModel(PyObject *module);  
    53 void addCParallelepipedModel(PyObject *module);  
    54 void addCPearlNecklaceModel(PyObject *module);  
    55 void addCPoly_GaussCoil(PyObject *module);  
    56 void addCPringlesModel(PyObject *module);  
    57 void addCRaspBerryModel(PyObject *module);  
    58 void addCReflModel(PyObject *module);  
    59 void addCReflAdvModel(PyObject *module);  
    60 void addCRPAModel(PyObject *module);  
    61 void addCSCCrystalModel(PyObject *module);  
    62 void addCSchulz(PyObject *module);  
    63 void addCSLDCalFunc(PyObject *module);  
    64 void addCSphereModel(PyObject *module);  
    65 void addCSphereSLDModel(PyObject *module);  
    66 void addCCoreShellEllipsoidModel(PyObject *module);  
    67 void addCSquareWellStructure(PyObject *module);  
    68 void addCStackedDisksModel(PyObject *module);  
    69 void addCStarPolymer(PyObject *module);  
    70 void addCStickyHSStructure(PyObject *module);  
    71 void addCSurfaceFractalModel(PyObject *module);  
    72 void addCTeubnerStreyModel(PyObject *module);  
    73 void addCTriaxialEllipsoidModel(PyObject *module);  
    74 void addCTwoYukawaModel(PyObject *module);  
    75 void addCVesicleModel(PyObject *module);  
    7676 // end generated code  
    7777 
     
    260260 
    261261 // adding generated code  
     262addCLinearPearlsModel(m);  
     263addCRaspBerryModel(m);  
     264addCCore2ndMomentModel(m);  
     265addCStackedDisksModel(m);  
     266addCCoreShellCylinderModel(m);  
     267addCReflModel(m);  
     268addCSphereSLDModel(m);  
     269addCFractalModel(m);  
     270addCLogNormal(m);  
     271addCPringlesModel(m);  
     272addCCappedCylinderModel(m);  
     273addCLorentzian(m);  
     274addCBCCrystalModel(m);  
     275addCPearlNecklaceModel(m);  
     276addCSCCrystalModel(m);  
     277addCGaussian(m);  
     278addCLamellarModel(m);  
     279addCLamellarPCrystalModel(m);  
     280addCMassFractalModel(m);  
     281addCPoly_GaussCoil(m);  
     282addCTeubnerStreyModel(m);  
     283addCOnionModel(m);  
     284addCHollowCylinderModel(m);  
     285addCTriaxialEllipsoidModel(m);  
     286addCEllipticalCylinderModel(m);  
     287addCSchulz(m);  
     288addCLamellarPSHGModel(m);  
     289addCDABModel(m);  
     290addCStarPolymer(m);  
     291addCFuzzySphereModel(m);  
     292addCParallelepipedModel(m);  
     293addCMassSurfaceFractal(m);  
     294addCVesicleModel(m);  
     295addCGelFitModel(m);  
     296addCCoreShellEllipsoidModel(m);  
     297addCRPAModel(m);  
     298addCHayterMSAStructure(m);  
     299addCCSParallelepipedModel(m);  
     300addCFractalO_Z(m);  
     301addCMultiShellModel(m);  
     302addCLamellarPSModel(m);  
     303addCEllipsoidModel(m);  
     304addCTwoYukawaModel(m);  
     305addCDiamEllipFunc(m);  
     306addCHardsphereStructure(m);  
     307addCLamellarFFHGModel(m);  
     308addCCoreShellBicelleModel(m);  
     309addCFCCrystalModel(m);  
     310addCFlexibleCylinderModel(m);  
     311addCSurfaceFractalModel(m);  
     312addCDiamCylFunc(m);  
     313addCCoreFourShellModel(m);  
     314addCStickyHSStructure(m);  
     315addCReflAdvModel(m);  
     316addCSphereModel(m);  
     317addCFlexCylEllipXModel(m);  
     318addCSquareWellStructure(m);  
     319addCSLDCalFunc(m);  
     320addCCoreShellModel(m);  
    262321addCBarBellModel(m);  
    263 addCBCCrystalModel(m);  
    264322addCBinaryHSModel(m);  
    265 addCCappedCylinderModel(m);  
    266 addCCoreFourShellModel(m);  
    267 addCCore2ndMomentModel(m);  
    268 addCCoreShellModel(m);  
    269 addCCoreShellBicelleModel(m);  
    270 addCCoreShellCylinderModel(m);  
    271 addCCSParallelepipedModel(m);  
    272323addCCylinderModel(m);  
    273 addCDABModel(m);  
    274 addCDiamCylFunc(m);  
    275 addCDiamEllipFunc(m);  
    276 addCEllipsoidModel(m);  
    277 addCEllipticalCylinderModel(m);  
    278 addCFCCrystalModel(m);  
    279 addCFlexCylEllipXModel(m);  
    280 addCFlexibleCylinderModel(m);  
    281 addCFractalModel(m);  
    282 addCFractalO_Z(m);  
    283 addCFuzzySphereModel(m);  
    284 addCGaussian(m);  
    285 addCGelFitModel(m);  
    286 addCHardsphereStructure(m);  
    287 addCHayterMSAStructure(m);  
    288 addCHollowCylinderModel(m);  
    289 addCLamellarModel(m);  
    290 addCLamellarFFHGModel(m);  
    291 addCLamellarPCrystalModel(m);  
    292 addCLamellarPSModel(m);  
    293 addCLamellarPSHGModel(m);  
    294 addCLinearPearlsModel(m);  
    295 addCLogNormal(m);  
    296 addCLorentzian(m);  
    297 addCMassFractalModel(m);  
    298 addCMassSurfaceFractal(m);  
    299 addCMultiShellModel(m);  
    300 addCOnionModel(m);  
    301 addCParallelepipedModel(m);  
    302 addCPearlNecklaceModel(m);  
    303 addCPoly_GaussCoil(m);  
    304 addCPringlesModel(m);  
    305 addCRaspBerryModel(m);  
    306 addCReflModel(m);  
    307 addCReflAdvModel(m);  
    308 addCRPAModel(m);  
    309 addCSCCrystalModel(m);  
    310 addCSchulz(m);  
    311 addCSLDCalFunc(m);  
    312 addCSphereModel(m);  
    313 addCSphereSLDModel(m);  
    314 addCCoreShellEllipsoidModel(m);  
    315 addCSquareWellStructure(m);  
    316 addCStackedDisksModel(m);  
    317 addCStarPolymer(m);  
    318 addCStickyHSStructure(m);  
    319 addCSurfaceFractalModel(m);  
    320 addCTeubnerStreyModel(m);  
    321 addCTriaxialEllipsoidModel(m);  
    322 addCTwoYukawaModel(m);  
    323 addCVesicleModel(m);  
    324324addDisperser(m);  
    325325 
  • test/pr_inversion/test/test_output.txt

    r81b524f r81b524f  
    33#alpha=0.0007 
    44#chi2=836.797 
    5 #elapsed=0.000999928 
     5#elapsed=0.000825167 
    66#qmin=None 
    77#qmax=None 
  • test/sansguiframe/test/cansas1d.xml

    r75eeb425 r75eeb425  
    4949                         
    5050                </SASsample> 
    51                 <SASinstrument> 
     51                <SASinstrument name="TEST instrument"> 
    5252                        <name>canSAS instrument</name> 
    5353                        <SASsource name="source name"> 
     
    8585                                        4.150 
    8686                                </SDD> 
    87                                 <offset> 
    88                     <x unit="mm">1</x> 
    89                     <y unit="mm">2</y> 
    90                 </offset> 
    91                 <orientation> 
     87                                <orientation> 
    9288                                        <roll unit="degree">1.00</roll> 
    9389                                        <pitch unit="degree">0.00</pitch> 
    9490                                        <yaw unit="degree">0.00</yaw> 
    9591                                </orientation> 
     92                                <offset> 
     93                                        <x unit="mm">1</x> 
     94                                        <y unit="mm">2</y> 
     95                                </offset> 
    9696                                <beam_center> 
    9797                                        <x unit="mm">322.64</x> 
     
    135135                        <term name="ABS:IZERO">230.09</term> 
    136136                        <term name="ABS:XSECT" unit="mm">1</term> 
    137                         <SASprocessnote>No Information</SASprocessnote> 
     137                        <SASprocessnote/> 
    138138                </SASprocess> 
    139139                <SASnote /> 
  • test/sansguiframe/test/utest_manipulations.py

    r75eeb425 r75eeb425  
    1515     
    1616    def setUp(self): 
    17         data = Loader().load("cansas1d.xml") 
    18         self.data = data[0] 
     17        self.data = Loader().load("cansas1d.xml") 
    1918         
    2019    def test_clone1D(self): 
     
    3029     
    3130    def setUp(self): 
    32         data = Loader().load("cansas1d.xml") 
    33         self.data = data[0] 
     31        self.data = Loader().load("cansas1d.xml") 
    3432         
    3533    def test_clone_theory1D(self): 
  • test/sansinvariant/test/utest_data_handling.py

    r75eeb425 r75eeb425  
    9292    """ 
    9393    def setUp(self): 
    94         data = Loader().load("latex_smeared_slit.xml") 
    95         self.data = data[0] 
     94        self.data = Loader().load("latex_smeared_slit.xml") 
    9695        self.data.dxl = None 
    9796         
  • test/sansmodels/test/cansas1d_slit.xml

    r75eeb425 r75eeb425  
    1414                                <I unit="1/cm">1000</I> 
    1515                                <Idev unit="1/cm">3</Idev> 
     16                                <dQl unit="1/A">0.005</dQl> 
    1617                                <dQw unit="1/A">0.001</dQw> 
    17                                 <dQl unit="1/A">0.005</dQl> 
    18                 <Shadowfactor><!-- Shadowfactor is optional --></Shadowfactor> 
     18                                <Shadowfactor><!-- Shadowfactor is optional --></Shadowfactor> 
    1919                        </Idata> 
    2020                        <Idata> 
     
    2222                                <I unit="1/cm">1001</I> 
    2323                                <Idev unit="1/cm">4</Idev> 
     24                                <dQl unit="1/A">0.005</dQl> 
    2425                                <dQw unit="1/A">0.001</dQw> 
    25                                 <dQl unit="1/A">0.005</dQl> 
    26                 <Shadowfactor><!-- Shadowfactor is optional --></Shadowfactor> 
     26                                <Shadowfactor><!-- Shadowfactor is optional --></Shadowfactor> 
    2727                        </Idata> 
    2828                </SASdata> 
     
    4949                         
    5050                </SASsample> 
    51                 <SASinstrument> 
     51                <SASinstrument name="TEST instrument"> 
    5252                        <name>canSAS instrument</name> 
    5353                        <SASsource name="source name"> 
     
    8585                                        4.150 
    8686                                </SDD> 
    87                                 <offset> 
    88                     <x unit="mm">1</x> 
    89                     <y unit="mm">2</y> 
    90                 </offset> 
    91                 <orientation> 
     87                                <orientation> 
    9288                                        <roll unit="degree">1.00</roll> 
    9389                                        <pitch unit="degree">0.00</pitch> 
    9490                                        <yaw unit="degree">0.00</yaw> 
    9591                                </orientation> 
     92                                <offset> 
     93                                        <x unit="mm">1</x> 
     94                                        <y unit="mm">2</y> 
     95                                </offset> 
    9696                                <beam_center> 
    9797                                        <x unit="mm">322.64</x> 
  • test/sansmodels/test/utest_smearing.py

    r75eeb425 r75eeb425  
    1616     
    1717    def setUp(self): 
    18         data = Loader().load("cansas1d_slit.xml") 
    19         self.data = data[0] 
     18        self.data = Loader().load("cansas1d_slit.xml") 
    2019         
    2120        x = 0.001*numpy.arange(1,11) 
Note: See TracChangeset for help on using the changeset viewer.