source: sasview/DataLoader/readers/cansas_reader.py @ 553d047

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 553d047 was 28caa03, checked in by Mathieu Doucet <doucetm@…>, 15 years ago

Improved hierarchical reader structure, put back reader plugin, minor fixes.

  • Property mode set to 100644
File size: 35.1 KB
Line 
1"""
2This software was developed by the University of Tennessee as part of the
3Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4project funded by the US National Science Foundation.
5
6See the license text in license.txt
7
8copyright 2008, University of Tennessee
9"""
10# Known issue: reader not compatible with multiple SASdata entries
11# within a single SASentry. Will raise a runtime error.
12
13#TODO: check that all vectors are written only if they have at least one non-empty value
14#TODO: Writing only allows one SASentry per file. Would be best to allow multiple entries.
15#TODO: Store error list
16#TODO: Allow for additional meta data for each section
17#TODO: Notes need to be implemented. They can be any XML structure in version 1.0
18#      Process notes have the same problem.
19#TODO: Unit conversion is not complete (temperature units are missing)
20
21
22import logging
23import numpy
24import os, sys
25from DataLoader.data_info import Data1D, Collimation, Detector, Process, Aperture
26from xml import xpath
27import xml.dom.minidom 
28
29
30has_converter = True
31try:
32    from data_util.nxsunit import Converter
33except:
34    has_converter = False
35
36def write_node(doc, parent, name, value, attr={}):
37    """
38        @param doc: document DOM
39        @param parent: parent node
40        @param name: tag of the element
41        @param value: value of the child text node
42        @param attr: attribute dictionary
43        @return: True if something was appended, otherwise False
44    """
45    if value is not None:
46        node = doc.createElement(name)
47        node.appendChild(doc.createTextNode(str(value)))
48        for item in attr:
49            node.setAttribute(item, attr[item])
50        parent.appendChild(node)
51        return True
52    return False
53
54def get_node_text(node):
55    """
56        Get the text context of a node
57       
58        @param node: node to read from
59        @return: content, attribute list
60    """
61    content = None
62    attr    = {}
63    for item in node.childNodes:
64        if item.nodeName.find('text')>=0 \
65            and len(item.nodeValue.strip())>0:
66            content = item.nodeValue.strip()
67            break
68       
69    if node.hasAttributes():
70        for i in range(node.attributes.length):
71            attr[node.attributes.item(i).nodeName] \
72                = node.attributes.item(i).nodeValue
73
74    return content, attr
75
76def get_content(location, node):
77    """
78        Get the first instance of the content of a xpath location
79       
80        @param location: xpath location
81        @param node: node to start at
82    """
83    value = None
84    attr  = {}
85    nodes = xpath.Evaluate(location, node)
86    if len(nodes)>0:
87        try:
88            # Skip comments and empty lines
89            for item in nodes[0].childNodes:
90                if item.nodeName.find('text')>=0 \
91                    and len(item.nodeValue.strip())>0:
92                    value = item.nodeValue.strip()
93                    break
94               
95            if nodes[0].hasAttributes():
96                for i in range(nodes[0].attributes.length):
97                    attr[nodes[0].attributes.item(i).nodeName] \
98                        = nodes[0].attributes.item(i).nodeValue
99        except:
100            # problem reading the node. Skip it and return that
101            # nothing was found
102            logging.error("cansas_reader.get_content: %s\n  %s" % (location, sys.exc_value))
103       
104    return value, attr
105
106def get_float(location, node):
107    """
108        Get the content of a node as a float
109       
110        @param location: xpath location
111        @param node: node to start at
112    """
113    value = None
114    attr = {}
115    content, attr = get_content(location, node)
116    if content is not None:
117        try:
118            value = float(content)   
119        except:
120            # Could not pass, skip and return None
121            logging.error("cansas_reader.get_float: could not convert '%s' to float" % content)
122       
123    return value, attr
124
125def _store_float(location, node, variable, storage):
126    """
127        Get the content of a xpath location and store
128        the result. Check that the units are compatible
129        with the destination. The value is expected to
130        be a float.
131       
132        The xpath location might or might not exist.
133        If it does not exist, nothing is done
134       
135        @param location: xpath location to fetch
136        @param node: node to read the data from
137        @param variable: name of the data member to store it in [string]
138        @param storage: data object that has the 'variable' data member
139       
140        @raise ValueError: raised when the units are not recognized
141    """
142    value, attr = get_float(location, node)
143    if value is not None:
144        # If the entry has units, check to see that they are
145        # compatible with what we currently have in the data object
146        if attr.has_key('unit'):
147            toks = variable.split('.')
148            exec "local_unit = storage.%s_unit" % toks[0]
149            if attr['unit'].lower()!=local_unit.lower():
150                if has_converter==True:
151                    try:
152                        conv = Converter(attr['unit'])
153                        exec "storage.%s = %g" % (variable, conv(value, units=local_unit))
154                    except:
155                        #Below three lines were added for the unit = 1/A. local unit is defined in 'mm'. Need to check!!!
156                        if variable == 'slit_length' and attr['unit'] !=local_unit:
157                            pass
158                        else:
159                            raise ValueError, "CanSAS reader: could not convert %s unit [%s]; expecting [%s]\n  %s" \
160                            % (variable, attr['unit'], local_unit, sys.exc_value)
161                else:
162                    raise ValueError, "CanSAS reader: unrecognized %s unit [%s]; expecting [%s]" \
163                        % (variable, attr['unit'], local_unit)
164            else:
165                exec "storage.%s = value" % variable
166        else:
167            exec "storage.%s = value" % variable
168           
169
170def _store_content(location, node, variable, storage):
171    """
172        Get the content of a xpath location and store
173        the result. The value is treated as a string.
174       
175        The xpath location might or might not exist.
176        If it does not exist, nothing is done
177       
178        @param location: xpath location to fetch
179        @param node: node to read the data from
180        @param variable: name of the data member to store it in [string]
181        @param storage: data object that has the 'variable' data member
182    """
183    value, attr = get_content(location, node)
184    if value is not None:
185        exec "storage.%s = value" % variable
186
187
188class Reader:
189    """
190        Class to load cansas 1D XML files
191       
192        Dependencies:
193            The CanSas reader requires PyXML 0.8.4 or later.
194    """
195    ## CanSAS version
196    version = '1.0'
197    ## File type
198    type_name = "CanSAS 1D"
199    ## Wildcards
200    type = ["CanSAS 1D files (*.xml)|*.xml"]
201    ## List of allowed extensions
202    ext=['.xml', '.XML'] 
203   
204    def read(self, path):
205        """
206            Load data file
207           
208            @param path: file path
209            @return: Data1D object if a single SASentry was found,
210                        or a list of Data1D objects if multiple entries were found,
211                        or None of nothing was found
212            @raise RuntimeError: when the file can't be opened
213            @raise ValueError: when the length of the data vectors are inconsistent
214        """
215        from xml.dom.minidom import parse
216       
217        output = []
218       
219        if os.path.isfile(path):
220            basename  = os.path.basename(path)
221            root, extension = os.path.splitext(basename)
222            if extension.lower() in self.ext:
223               
224                dom = parse(path)
225               
226                # Check the format version number
227                nodes = xpath.Evaluate('SASroot', dom)
228                if nodes[0].hasAttributes():
229                    for i in range(nodes[0].attributes.length):
230                        if nodes[0].attributes.item(i).nodeName=='version':
231                            if nodes[0].attributes.item(i).nodeValue != self.version:
232                                raise ValueError, "cansas_reader: unrecognized version number %s" % \
233                                    nodes[0].attributes.item(i).nodeValue
234               
235                entry_list = xpath.Evaluate('SASroot/SASentry', dom)
236                for entry in entry_list:
237                    sas_entry = self._parse_entry(entry)
238                    sas_entry.filename = basename
239                    output.append(sas_entry)
240               
241        else:
242            raise RuntimeError, "%s is not a file" % path
243       
244        # Return output consistent with the loader's api
245        if len(output)==0:
246            return None
247        elif len(output)==1:
248            return output[0]
249        else:
250            return output               
251               
252    def _parse_entry(self, dom):
253        """
254            Parse a SASentry
255           
256            @param node: SASentry node
257            @return: Data1D object
258        """
259        x = numpy.zeros(0)
260        y = numpy.zeros(0)
261       
262        data_info = Data1D(x, y)
263       
264        # Look up title
265        _store_content('Title', dom, 'title', data_info)
266        # Look up run number   
267        nodes = xpath.Evaluate('Run', dom)
268        for item in nodes:   
269            value, attr = get_node_text(item)
270            if value is not None:
271                data_info.run.append(value)
272                if attr.has_key('name'):
273                    data_info.run_name[value] = attr['name']         
274                           
275        # Look up instrument name             
276        _store_content('SASinstrument/name', dom, 'instrument', data_info)
277        #value, attr = get_content('SASinstrument', dom)
278        #if attr.has_key('name'):
279        #    data_info.instrument = attr['name']
280
281        note_list = xpath.Evaluate('SASnote', dom)
282        for note in note_list:
283            try:
284                note_value, note_attr = get_node_text(note)
285                if note_value is not None:
286                    data_info.notes.append(note_value)
287            except:
288                logging.error("cansas_reader.read: error processing entry notes\n  %s" % sys.exc_value)
289
290       
291        # Sample info ###################
292        value, attr = get_content('SASsample', dom)
293        if attr.has_key('name'):
294            data_info.sample.name = attr['name']
295           
296        _store_content('SASsample/ID', 
297                     dom, 'ID', data_info.sample)                   
298        _store_float('SASsample/thickness', 
299                     dom, 'thickness', data_info.sample)
300        _store_float('SASsample/transmission', 
301                     dom, 'transmission', data_info.sample)
302        _store_float('SASsample/temperature', 
303                     dom, 'temperature', data_info.sample)
304        nodes = xpath.Evaluate('SASsample/details', dom)
305        for item in nodes:
306            try:
307                detail_value, detail_attr = get_node_text(item)
308                if detail_value is not None:
309                    data_info.sample.details.append(detail_value)
310            except:
311                logging.error("cansas_reader.read: error processing sample details\n  %s" % sys.exc_value)
312       
313        # Position (as a vector)
314        _store_float('SASsample/position/x', 
315                     dom, 'position.x', data_info.sample)         
316        _store_float('SASsample/position/y', 
317                     dom, 'position.y', data_info.sample)         
318        _store_float('SASsample/position/z', 
319                     dom, 'position.z', data_info.sample)         
320       
321        # Orientation (as a vector)
322        _store_float('SASsample/orientation/roll', 
323                     dom, 'orientation.x', data_info.sample)         
324        _store_float('SASsample/orientation/pitch', 
325                     dom, 'orientation.y', data_info.sample)         
326        _store_float('SASsample/orientation/yaw', 
327                     dom, 'orientation.z', data_info.sample)         
328       
329        # Source info ###################
330        value, attr = get_content('SASinstrument/SASsource', dom)
331        if attr.has_key('name'):
332            data_info.source.name = attr['name']
333       
334        _store_content('SASinstrument/SASsource/radiation', 
335                     dom, 'radiation', data_info.source)                   
336        _store_content('SASinstrument/SASsource/beam_shape', 
337                     dom, 'beam_shape', data_info.source)                   
338        _store_float('SASinstrument/SASsource/wavelength', 
339                     dom, 'wavelength', data_info.source)         
340        _store_float('SASinstrument/SASsource/wavelength_min', 
341                     dom, 'wavelength_min', data_info.source)         
342        _store_float('SASinstrument/SASsource/wavelength_max', 
343                     dom, 'wavelength_max', data_info.source)         
344        _store_float('SASinstrument/SASsource/wavelength_spread', 
345                     dom, 'wavelength_spread', data_info.source)   
346       
347        # Beam size (as a vector)   
348        value, attr = get_content('SASinstrument/SASsource/beam_size', dom)
349        if attr.has_key('name'):
350            data_info.source.beam_size_name = attr['name']
351           
352        _store_float('SASinstrument/SASsource/beam_size/x', 
353                     dom, 'beam_size.x', data_info.source)   
354        _store_float('SASinstrument/SASsource/beam_size/y', 
355                     dom, 'beam_size.y', data_info.source)   
356        _store_float('SASinstrument/SASsource/beam_size/z', 
357                     dom, 'beam_size.z', data_info.source)   
358       
359        # Collimation info ###################
360        nodes = xpath.Evaluate('SASinstrument/SAScollimation', dom)
361        for item in nodes:
362            collim = Collimation()
363            value, attr = get_node_text(item)
364            if attr.has_key('name'):
365                collim.name = attr['name']
366            _store_float('length', item, 'length', collim) 
367           
368            # Look for apertures
369            apert_list = xpath.Evaluate('aperture', item)
370            for apert in apert_list:
371                aperture =  Aperture()
372               
373                # Get the name and type of the aperture
374                ap_value, ap_attr = get_node_text(apert)
375                if ap_attr.has_key('name'):
376                    aperture.name = ap_attr['name']
377                if ap_attr.has_key('type'):
378                    aperture.type = ap_attr['type']
379                   
380                _store_float('distance', apert, 'distance', aperture)   
381               
382                value, attr = get_content('size', apert)
383                if attr.has_key('name'):
384                    aperture.size_name = attr['name']
385               
386                _store_float('size/x', apert, 'size.x', aperture)   
387                _store_float('size/y', apert, 'size.y', aperture)   
388                _store_float('size/z', apert, 'size.z', aperture)
389               
390                collim.aperture.append(aperture)
391               
392            data_info.collimation.append(collim)
393       
394        # Detector info ######################
395        nodes = xpath.Evaluate('SASinstrument/SASdetector', dom)
396        for item in nodes:
397           
398            detector = Detector()
399           
400            _store_content('name', item, 'name', detector)
401            _store_float('SDD', item, 'distance', detector)   
402           
403            # Detector offset (as a vector)
404            _store_float('offset/x', item, 'offset.x', detector)   
405            _store_float('offset/y', item, 'offset.y', detector)   
406            _store_float('offset/z', item, 'offset.z', detector)   
407           
408            # Detector orientation (as a vector)
409            _store_float('orientation/roll',  item, 'orientation.x', detector)   
410            _store_float('orientation/pitch', item, 'orientation.y', detector)   
411            _store_float('orientation/yaw',   item, 'orientation.z', detector)   
412           
413            # Beam center (as a vector)
414            _store_float('beam_center/x', item, 'beam_center.x', detector)   
415            _store_float('beam_center/y', item, 'beam_center.y', detector)   
416            _store_float('beam_center/z', item, 'beam_center.z', detector)   
417           
418            # Pixel size (as a vector)
419            _store_float('pixel_size/x', item, 'pixel_size.x', detector)   
420            _store_float('pixel_size/y', item, 'pixel_size.y', detector)   
421            _store_float('pixel_size/z', item, 'pixel_size.z', detector)   
422           
423            _store_float('slit_length', item, 'slit_length', detector)
424           
425            data_info.detector.append(detector)   
426
427        # Processes info ######################
428        nodes = xpath.Evaluate('SASprocess', dom)
429        for item in nodes:
430            process = Process()
431            _store_content('name', item, 'name', process)
432            _store_content('date', item, 'date', process)
433            _store_content('description', item, 'description', process)
434           
435            term_list = xpath.Evaluate('term', item)
436            for term in term_list:
437                try:
438                    term_value, term_attr = get_node_text(term)
439                    term_attr['value'] = term_value
440                    if term_value is not None:
441                        process.term.append(term_attr)
442                except:
443                    logging.error("cansas_reader.read: error processing process term\n  %s" % sys.exc_value)
444           
445            note_list = xpath.Evaluate('SASprocessnote', item)
446            for note in note_list:
447                try:
448                    note_value, note_attr = get_node_text(note)
449                    if note_value is not None:
450                        process.notes.append(note_value)
451                except:
452                    logging.error("cansas_reader.read: error processing process notes\n  %s" % sys.exc_value)
453           
454           
455            data_info.process.append(process)
456           
457           
458        # Data info ######################
459        nodes = xpath.Evaluate('SASdata', dom)
460        if len(nodes)>1:
461            raise RuntimeError, "CanSAS reader is not compatible with multiple SASdata entries"
462       
463        nodes = xpath.Evaluate('SASdata/Idata', dom)
464        x  = numpy.zeros(0)
465        y  = numpy.zeros(0)
466        dx = numpy.zeros(0)
467        dy = numpy.zeros(0)
468        dxw = numpy.zeros(0)
469        dxl = numpy.zeros(0)
470       
471        for item in nodes:
472            _x, attr = get_float('Q', item)
473            _dx, attr_d = get_float('Qdev', item)
474            _dxl, attr_l = get_float('dQl', item)
475            _dxw, attr_w = get_float('dQw', item)
476            if _dx == None:
477                _dx = 0.0
478            if _dxl == None:
479                _dxl = 0.0
480            if _dxw == None:
481                _dxw = 0.0
482               
483            if attr.has_key('unit') and attr['unit'].lower() != data_info.x_unit.lower():
484                if has_converter==True:
485                    try:
486                        data_conv_q = Converter(attr['unit'])
487                        _x = data_conv_q(_x, units=data_info.x_unit)
488                    except:
489                        raise ValueError, "CanSAS reader: could not convert Q unit [%s]; expecting [%s]\n  %s" \
490                        % (attr['unit'], data_info.x_unit, sys.exc_value)
491                else:
492                    raise ValueError, "CanSAS reader: unrecognized Q unit [%s]; expecting [%s]" \
493                        % (attr['unit'], data_info.x_unit)
494            # Error in Q
495            if attr_d.has_key('unit') and attr_d['unit'].lower() != data_info.x_unit.lower():
496                if has_converter==True:
497                    try:
498                        data_conv_q = Converter(attr_d['unit'])
499                        _dx = data_conv_q(_dx, units=data_info.x_unit)
500                    except:
501                        raise ValueError, "CanSAS reader: could not convert dQ unit [%s]; expecting [%s]\n  %s" \
502                        % (attr['unit'], data_info.x_unit, sys.exc_value)
503                else:
504                    raise ValueError, "CanSAS reader: unrecognized dQ unit [%s]; expecting [%s]" \
505                        % (attr['unit'], data_info.x_unit)
506            # Slit length
507            if attr_l.has_key('unit') and attr_l['unit'].lower() != data_info.x_unit.lower():
508                if has_converter==True:
509                    try:
510                        data_conv_q = Converter(attr_l['unit'])
511                        _dxl = data_conv_q(_dxl, units=data_info.x_unit)
512                    except:
513                        raise ValueError, "CanSAS reader: could not convert dQl unit [%s]; expecting [%s]\n  %s" \
514                        % (attr['unit'], data_info.x_unit, sys.exc_value)
515                else:
516                    raise ValueError, "CanSAS reader: unrecognized dQl unit [%s]; expecting [%s]" \
517                        % (attr['unit'], data_info.x_unit)
518            # Slit width
519            if attr_w.has_key('unit') and attr_w['unit'].lower() != data_info.x_unit.lower():
520                if has_converter==True:
521                    try:
522                        data_conv_q = Converter(attr_w['unit'])
523                        _dxw = data_conv_q(_dxw, units=data_info.x_unit)
524                    except:
525                        raise ValueError, "CanSAS reader: could not convert dQw unit [%s]; expecting [%s]\n  %s" \
526                        % (attr['unit'], data_info.x_unit, sys.exc_value)
527                else:
528                    raise ValueError, "CanSAS reader: unrecognized dQw unit [%s]; expecting [%s]" \
529                        % (attr['unit'], data_info.x_unit)
530                   
531            _y, attr = get_float('I', item)
532            _dy, attr_d = get_float('Idev', item)
533            if _dy == None:
534                _dy = 0.0
535            if attr.has_key('unit') and attr['unit'].lower() != data_info.y_unit.lower():
536                if has_converter==True:
537                    try:
538                        data_conv_i = Converter(attr['unit'])
539                        _y = data_conv_i(_y, units=data_info.y_unit)
540                    except:
541                        raise ValueError, "CanSAS reader: could not convert I(q) unit [%s]; expecting [%s]\n  %s" \
542                        % (attr['unit'], data_info.y_unit, sys.exc_value)
543                else:
544                    raise ValueError, "CanSAS reader: unrecognized I(q) unit [%s]; expecting [%s]" \
545                        % (attr['unit'], data_info.y_unit)
546            if attr_d.has_key('unit') and attr_d['unit'].lower() != data_info.y_unit.lower():
547                if has_converter==True:
548                    try:
549                        data_conv_i = Converter(attr_d['unit'])
550                        _dy = data_conv_i(_dy, units=data_info.y_unit)
551                    except:
552                        raise ValueError, "CanSAS reader: could not convert dI(q) unit [%s]; expecting [%s]\n  %s" \
553                        % (attr_d['unit'], data_info.y_unit, sys.exc_value)
554                else:
555                    raise ValueError, "CanSAS reader: unrecognized dI(q) unit [%s]; expecting [%s]" \
556                        % (attr_d['unit'], data_info.y_unit)
557               
558            if _x is not None and _y is not None:
559                x  = numpy.append(x, _x)
560                y  = numpy.append(y, _y)
561                dx = numpy.append(dx, _dx)
562                dy = numpy.append(dy, _dy)
563                dxl = numpy.append(dxl, _dxl)
564                dxw = numpy.append(dxw, _dxw)
565               
566           
567        data_info.x = x
568        data_info.y = y
569        data_info.dx = dx
570        data_info.dy = dy
571        data_info.dxl = dxl
572        data_info.dxw = dxw
573       
574        data_conv_q = None
575        data_conv_i = None
576       
577        if has_converter == True and data_info.x_unit != '1/A':
578            data_conv_q = Converter('1/A')
579            # Test it
580            data_conv_q(1.0, output.Q_unit)
581           
582        if has_converter == True and data_info.y_unit != '1/cm':
583            data_conv_i = Converter('1/cm')
584            # Test it
585            data_conv_i(1.0, output.I_unit)                   
586               
587        if data_conv_q is not None:
588            data_info.xaxis("\\rm{Q}", data_info.x_unit)
589        else:
590            data_info.xaxis("\\rm{Q}", 'A^{-1}')
591        if data_conv_i is not None:
592            data_info.yaxis("\\rm{Intensity}", data_info.y_unit)
593        else:
594            data_info.yaxis("\\rm{Intensity}","cm^{-1}")
595       
596        return data_info
597
598    def write(self, filename, datainfo):
599        """
600            Write the content of a Data1D as a CanSAS XML file
601           
602            @param filename: name of the file to write
603            @param datainfo: Data1D object
604        """
605       
606        if not datainfo.__class__ == Data1D: 
607            raise RuntimeError, "The cansas writer expects a Data1D instance"
608       
609        doc = xml.dom.minidom.Document()
610        main_node = doc.createElement("SASroot")
611        main_node.setAttribute("version", self.version)
612        main_node.setAttribute("xmlns", "cansas1d/%s" % self.version)
613        main_node.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
614        main_node.setAttribute("xsi:schemaLocation", "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version)
615       
616        doc.appendChild(main_node)
617       
618        entry_node = doc.createElement("SASentry")
619        main_node.appendChild(entry_node)
620       
621        write_node(doc, entry_node, "Title", datainfo.title)
622       
623        for item in datainfo.run:
624            runname = {}
625            if datainfo.run_name.has_key(item) and len(str(datainfo.run_name[item]))>1:
626                runname = {'name': datainfo.run_name[item] }
627            write_node(doc, entry_node, "Run", item, runname)
628       
629        # Data info
630        node = doc.createElement("SASdata")
631        entry_node.appendChild(node)
632       
633        for i in range(len(datainfo.x)):
634            pt = doc.createElement("Idata")
635            node.appendChild(pt)
636            write_node(doc, pt, "Q", datainfo.x[i], {'unit':datainfo.x_unit})
637            if len(datainfo.y)>=i:
638                write_node(doc, pt, "I", datainfo.y[i], {'unit':datainfo.y_unit})
639            if datainfo.dx !=None and len(datainfo.dx)>=i:
640                write_node(doc, pt, "Qdev", datainfo.dx[i], {'unit':datainfo.x_unit})
641            if datainfo.dx !=None and len(datainfo.dy)>=i:
642                write_node(doc, pt, "Idev", datainfo.dy[i], {'unit':datainfo.y_unit})
643
644       
645        # Sample info
646        sample = doc.createElement("SASsample")
647        if datainfo.sample.name is not None:
648            sample.setAttribute("name", str(datainfo.sample.name))
649        entry_node.appendChild(sample)
650        write_node(doc, sample, "ID", str(datainfo.sample.ID))
651        write_node(doc, sample, "thickness", datainfo.sample.thickness, {"unit":datainfo.sample.thickness_unit})
652        write_node(doc, sample, "transmission", datainfo.sample.transmission)
653        write_node(doc, sample, "temperature", datainfo.sample.temperature, {"unit":datainfo.sample.temperature_unit})
654       
655        for item in datainfo.sample.details:
656            write_node(doc, sample, "details", item)
657       
658        pos = doc.createElement("position")
659        written = write_node(doc, pos, "x", datainfo.sample.position.x, {"unit":datainfo.sample.position_unit})
660        written = written | write_node(doc, pos, "y", datainfo.sample.position.y, {"unit":datainfo.sample.position_unit})
661        written = written | write_node(doc, pos, "z", datainfo.sample.position.z, {"unit":datainfo.sample.position_unit})
662        if written == True:
663            sample.appendChild(pos)
664       
665        ori = doc.createElement("orientation")
666        written = write_node(doc, ori, "roll",  datainfo.sample.orientation.x, {"unit":datainfo.sample.orientation_unit})
667        written = written | write_node(doc, ori, "pitch", datainfo.sample.orientation.y, {"unit":datainfo.sample.orientation_unit})
668        written = written | write_node(doc, ori, "yaw",   datainfo.sample.orientation.z, {"unit":datainfo.sample.orientation_unit})
669        if written == True:
670            sample.appendChild(ori)
671       
672        # Instrument info
673        instr = doc.createElement("SASinstrument")
674        entry_node.appendChild(instr)
675       
676        write_node(doc, instr, "name", datainfo.instrument)
677       
678        #   Source
679        source = doc.createElement("SASsource")
680        if datainfo.source.name is not None:
681            source.setAttribute("name", str(datainfo.source.name))
682        instr.appendChild(source)
683       
684        write_node(doc, source, "radiation", datainfo.source.radiation)
685        write_node(doc, source, "beam_shape", datainfo.source.beam_shape)
686        size = doc.createElement("beam_size")
687        if datainfo.source.beam_size_name is not None:
688            size.setAttribute("name", str(datainfo.source.beam_size_name))
689        written = write_node(doc, size, "x", datainfo.source.beam_size.x, {"unit":datainfo.source.beam_size_unit})
690        written = written | write_node(doc, size, "y", datainfo.source.beam_size.y, {"unit":datainfo.source.beam_size_unit})
691        written = written | write_node(doc, size, "z", datainfo.source.beam_size.z, {"unit":datainfo.source.beam_size_unit})
692        if written == True:
693            source.appendChild(size)
694           
695        write_node(doc, source, "wavelength", datainfo.source.wavelength, {"unit":datainfo.source.wavelength_unit})
696        write_node(doc, source, "wavelength_min", datainfo.source.wavelength_min, {"unit":datainfo.source.wavelength_min_unit})
697        write_node(doc, source, "wavelength_max", datainfo.source.wavelength_max, {"unit":datainfo.source.wavelength_max_unit})
698        write_node(doc, source, "wavelength_spread", datainfo.source.wavelength_spread, {"unit":datainfo.source.wavelength_spread_unit})
699       
700        #   Collimation
701        for item in datainfo.collimation:
702            coll = doc.createElement("SAScollimation")
703            if item.name is not None:
704                coll.setAttribute("name", str(item.name))
705            instr.appendChild(coll)
706           
707            write_node(doc, coll, "length", item.length, {"unit":item.length_unit})
708           
709            for apert in item.aperture:
710                ap = doc.createElement("aperture")
711                if apert.name is not None:
712                    ap.setAttribute("name", str(apert.name))
713                if apert.type is not None:
714                    ap.setAttribute("type", str(apert.type))
715                coll.appendChild(ap)
716               
717                write_node(doc, ap, "distance", apert.distance, {"unit":apert.distance_unit})
718               
719                size = doc.createElement("size")
720                if apert.size_name is not None:
721                    size.setAttribute("name", str(apert.size_name))
722                written = write_node(doc, size, "x", apert.size.x, {"unit":apert.size_unit})
723                written = written | write_node(doc, size, "y", apert.size.y, {"unit":apert.size_unit})
724                written = written | write_node(doc, size, "z", apert.size.z, {"unit":apert.size_unit})
725                if written == True:
726                    ap.appendChild(size)
727
728        #   Detectors
729        for item in datainfo.detector:
730            det = doc.createElement("SASdetector")
731            written = write_node(doc, det, "name", item.name)
732            written = written | write_node(doc, det, "SDD", item.distance, {"unit":item.distance_unit})
733            written = written | write_node(doc, det, "slit_length", item.slit_length, {"unit":item.slit_length_unit})
734            if written == True:
735                instr.appendChild(det)
736           
737            off = doc.createElement("offset")
738            written = write_node(doc, off, "x", item.offset.x, {"unit":item.offset_unit})
739            written = written | write_node(doc, off, "y", item.offset.y, {"unit":item.offset_unit})
740            written = written | write_node(doc, off, "z", item.offset.z, {"unit":item.offset_unit})
741            if written == True:
742                det.appendChild(off)
743           
744            center = doc.createElement("beam_center")
745            written = write_node(doc, center, "x", item.beam_center.x, {"unit":item.beam_center_unit})
746            written = written | write_node(doc, center, "y", item.beam_center.y, {"unit":item.beam_center_unit})
747            written = written | write_node(doc, center, "z", item.beam_center.z, {"unit":item.beam_center_unit})
748            if written == True:
749                det.appendChild(center)
750               
751            pix = doc.createElement("pixel_size")
752            written = write_node(doc, pix, "x", item.pixel_size.x, {"unit":item.pixel_size_unit})
753            written = written | write_node(doc, pix, "y", item.pixel_size.y, {"unit":item.pixel_size_unit})
754            written = written | write_node(doc, pix, "z", item.pixel_size.z, {"unit":item.pixel_size_unit})
755            if written == True:
756                det.appendChild(pix)
757               
758            ori = doc.createElement("orientation")
759            written = write_node(doc, ori, "roll",  item.orientation.x, {"unit":item.orientation_unit})
760            written = written | write_node(doc, ori, "pitch", item.orientation.y, {"unit":item.orientation_unit})
761            written = written | write_node(doc, ori, "yaw",   item.orientation.z, {"unit":item.orientation_unit})
762            if written == True:
763                det.appendChild(ori)
764               
765       
766        # Processes info
767        for item in datainfo.process:
768            node = doc.createElement("SASprocess")
769            entry_node.appendChild(node)
770
771            write_node(doc, node, "name", item.name)
772            write_node(doc, node, "date", item.date)
773            write_node(doc, node, "description", item.description)
774            for term in item.term:
775                value = term['value']
776                del term['value']
777                write_node(doc, node, "term", value, term)
778            for note in item.notes:
779                write_node(doc, node, "SASprocessnote", note)
780           
781       
782        # Write the file
783        fd = open(filename, 'w')
784        fd.write(doc.toprettyxml())
785        fd.close()
786       
787       
788if __name__ == "__main__": 
789    logging.basicConfig(level=logging.ERROR,
790                        format='%(asctime)s %(levelname)s %(message)s',
791                        filename='cansas_reader.log',
792                        filemode='w')
793    reader = Reader()
794    print reader.read("../test/cansas1d.xml")
795   
796   
797                       
Note: See TracBrowser for help on using the repository browser.