Changeset 61cada5 in sasview


Ignore:
Timestamp:
May 21, 2010 4:57:13 PM (14 years ago)
Author:
Gervaise Alina <gervyh@…>
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
26f3dd5
Parents:
9e8c150
Message:

working on save state of fit page

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sansview/perspectives/fitting/pagestate.py

    r7609f1a r61cada5  
     1import time, os, sys 
     2import logging 
     3import DataLoader 
     4from xml.dom.minidom import parse 
     5from lxml import etree 
    16 
    27 
    38import copy 
     9 
     10from DataLoader.readers.cansas_reader import Reader as CansasReader 
     11from DataLoader.readers.cansas_reader import get_content 
     12 
     13FITTING_NODE_NAME = 'fitting_plug_in' 
     14CANSAS_NS = "cansas1d/1.0" 
     15 
     16list_of_state_attributes = [["is_data", "is_data", "bool"], 
     17                      ["group_id", "data_group_id", "string"], 
     18                      ["data_name", "data_name", "string"], 
     19                      ["data_id", "data_id", "string"], 
     20                      ["name", "name", "string"], 
     21                      ["data_name", "data_name", "string"], 
     22                      ["qmin", "qmin", "float"], 
     23                      ["qmax", "qmax", "float"], 
     24                      ["npts", "npts", "float"], 
     25                      ["shape_rbutton", "shape_rbutton", "bool"], 
     26                      ["shape_indep_rbutton", "shape_indep_rbutton", "bool"], 
     27                      ["plugin_rbutton", "plugin_rbutton","bool"], 
     28                      ["struct_rbutton", "struct_rbutton", "bool"], 
     29                      ["formfactorcombobox", "formfactorcombobox", "bool"], 
     30                      ["structurecombobox", "structurecombobox", "bool"], 
     31                      ["disp_box", "disp_box"]] 
     32list_of_state_parameters = [["parameters", "parameters"] ,                      
     33                            ["orientation_parameters", "orientation_params"], 
     34                            ["dispersity_parameters", "orientation_params_disp"], 
     35                            ["fixed_param", "fixed_param"],                       
     36                            ["fittable_param","fittable_param"]] 
    437 
    538class PageState(object): 
    639    """ 
    7         Contains info to reconstruct a page 
     40        Contains information to reconstruct a page of the fitpanel 
    841    """ 
    9     def __init__(self, parent,model=None, data=None): 
     42    def __init__(self, parent=None, model=None, data=None): 
    1043         
    1144        """  
    12             Initialization of the Panel 
    13         """ 
     45            Initialize the current state 
     46        """ 
     47        self.file = None 
    1448        #TODO: remove this once the inheritence is cleaned up 
    1549        ## Data member to store the dispersion object created 
    1650        self._disp_obj_dict = {} 
     51        #------------------------ 
     52        #Data used for fitting  
     53        self.data = data 
     54        #save additional information on data that dataloader.reader does not read 
     55        self.is_data = None 
     56        self.data_name = "" 
     57         
     58        if self.data is not None: 
     59            self.data_name = self.data.name 
     60        self.data_id = None 
     61        if self.data is not None and hasattr(self.data, "id"): 
     62            self.data_id = self.data.id 
     63        self.data_group_id = None 
     64        if self.data is not None and hasattr(self.data, "group_id"): 
     65            self.data_group_id = self.data.group_id 
     66        #------------------------- 
    1767        ## reset True change the state of exsiting button 
    1868        self.reset = False 
    19         #Data used for fitting  
    20         self.data = data 
     69        
    2170        #engine type 
    2271        self.engine_type = None 
     
    2574        # model on which the fit would be performed 
    2675        self.model = model 
    27         #if not hasattr(self.model, "_persistency_dict"): 
    28         #    self.model._persistency_dict = {} 
    29         #self.model._persistency_dict = copy.deepcopy(model._persistency_dict) 
     76        
    3077        #fit page manager  
    3178        self.manager = None 
     
    3885        self.page_name = "" 
    3986        # Contains link between  model ,all its parameters, and panel organization 
    40         self.parameters =[] 
     87        self.parameters = [] 
    4188        # Contains list of parameters that cannot be fitted and reference to  
    4289        #panel objects  
    43         self.fixed_param =[] 
     90        self.fixed_param = [] 
    4491        # Contains list of parameters with dispersity and reference to  
    4592        #panel objects  
    46         self.fittable_param =[] 
     93        self.fittable_param = [] 
    4794        ## orientation parameters 
    48         self.orientation_params=[] 
     95        self.orientation_params = [] 
    4996        ## orientation parmaters for gaussian dispersity 
    50         self.orientation_params_disp=[] 
     97        self.orientation_params_disp = [] 
    5198        ## smearer info 
    52         self.smearer=None 
     99        self.smearer = None 
    53100        self.smear_type = None 
    54101        self.dq_l = None 
     
    57104        #list of dispersion paramaters 
    58105        self.disp_list =[] 
    59         if self.model !=None: 
     106        if self.model is not None: 
    60107            self.disp_list = self.model.getDispParamList() 
    61         self._disp_obj_dict={} 
    62         self.disp_cb_dict={} 
    63         self.values=[] 
    64         self.weights=[] 
     108        self._disp_obj_dict = {} 
     109        self.disp_cb_dict = {} 
     110        self.values = [] 
     111        self.weights = [] 
    65112                     
    66113        #contains link between a model and selected parameters to fit  
    67         self.param_toFit =[] 
     114        self.param_toFit = [] 
    68115        ##dictionary of model type and model class 
    69116        self.model_list_box = None 
    70117        ## save the state of the context menu 
    71         self.saved_states={} 
     118        self.saved_states = {} 
    72119        ## save selection of combobox 
    73120        self.formfactorcombobox = None 
     
    82129        ## Qrange 
    83130        ## Q range 
    84         self.qmin= 0.001 
    85         self.qmax= 0.1 
     131        self.qmin = 0.001 
     132        self.qmax = 0.1 
    86133        self.npts = None 
    87         self.name="" 
     134        self.name = "" 
    88135        ## enable smearering state 
    89136        self.enable_smearer = False 
     
    92139        self.slit_smearer   = False 
    93140        ## disperity selection 
    94         self.enable_disp= False 
    95         self.disable_disp= True 
     141        self.enable_disp = False 
     142        self.disable_disp = True 
    96143        ## plot 2D data 
    97         self.enable2D= False 
     144        self.enable2D = False 
    98145        ## state of selected all check button 
    99146        self.cb1 = False 
    100147        ## store value of chisqr 
    101         self.tcChi= None 
     148        self.tcChi = None 
    102149     
    103150    def clone(self): 
    104         model=None 
    105         if self.model !=None: 
     151        """ 
     152            Create a new copy of the current object 
     153        """ 
     154        model = None 
     155        if self.model is not None: 
    106156            model = self.model.clone() 
    107157         
    108         obj          = PageState( self.parent,model= model ) 
     158        obj = PageState(self.parent, model=model) 
     159        obj.file = copy.deepcopy(self.file) 
    109160        obj.data = copy.deepcopy(self.data) 
     161        if self.data is not None: 
     162            self.data_name = self.data.name 
     163        obj.data_name = self.data_name 
     164        obj.is_data = self.is_data 
    110165        obj.model_list_box = copy.deepcopy(self.model_list_box) 
    111166        obj.engine_type = copy.deepcopy(self.engine_type) 
    112167         
    113         obj.formfactorcombobox= self.formfactorcombobox 
    114         obj.structurecombobox  =self.structurecombobox   
     168        obj.formfactorcombobox = self.formfactorcombobox 
     169        obj.structurecombobox  = self.structurecombobox   
    115170         
    116171        obj.shape_rbutton = self.shape_rbutton  
     
    150205        obj.dq_r = copy.deepcopy(self.dq_r) 
    151206 
    152         
    153207        obj.disp_box = copy.deepcopy(self.disp_box) 
    154208        obj.qmin = copy.deepcopy(self.qmin) 
     
    163217            obj.saved_states[copy_name]= copy_state 
    164218        return obj 
    165  
    166        
    167     def old__repr__(self): 
    168         """ output string for printing""" 
    169         rep = "\n\nState name: %s\n"%self.name 
    170         rep +="data : %s\n"% str(self.data) 
    171         rep += "Plotting Range: min: %s, max: %s, steps: %s\n"%(str(self.qmin), 
    172                                                 str(self.qmax),str(self.npts)) 
    173         rep +="model  : %s\n\n"% str(self.model) 
    174         rep +="number parameters(self.parameters): %s\n"%len(self.parameters) 
    175         for item in self.parameters: 
     219     
     220    def _repr_helper(self, list, rep): 
     221        """ 
     222        """ 
     223        for item in list: 
    176224            rep += "parameter name: %s \n"%str(item[1]) 
    177225            rep += "value: %s\n"%str(item[2]) 
     
    184232            rep += "maximum value : %s \n"%str(item[6][1]) 
    185233            rep += "parameter unit: %s\n\n"%str(item[7]) 
    186         rep +="number orientation parameters" 
    187         rep +="(self.orientation_params): %s\n"%len(self.orientation_params) 
    188         for item in self.orientation_params: 
    189             rep += "parameter name: %s \n"%str(item[1]) 
    190             rep += "value: %s\n"%str(item[2]) 
    191             rep += "selected: %s\n"%str(item[0]) 
    192             rep += "error displayed : %s \n"%str(item[4][0]) 
    193             rep += "error value:%s \n"%str(item[4][1]) 
    194             rep += "minimum displayed : %s \n"%str(item[5][0]) 
    195             rep += "minimum value : %s \n"%str(item[5][1]) 
    196             rep += "maximum displayed : %s \n"%str(item[6][0]) 
    197             rep += "maximum value : %s \n"%str(item[6][1]) 
    198             rep += "parameter unit: %s\n\n"%str(item[7]) 
    199         rep +="number dispersity parameters" 
    200         rep +="(self.orientation_params_disp): %s\n"%len(self.orientation_params_disp) 
    201         for item in self.orientation_params_disp: 
    202             rep += "parameter name: %s \n"%str(item[1]) 
    203             rep += "value: %s\n"%str(item[2]) 
    204             rep += "selected: %s\n"%str(item[0]) 
    205             rep += "error displayed : %s \n"%str(item[4][0]) 
    206             rep += "error value:%s \n"%str(item[4][1]) 
    207             rep += "minimum displayed : %s \n"%str(item[5][0]) 
    208             rep += "minimum value : %s \n"%str(item[5][1]) 
    209             rep += "maximum displayed : %s \n"%str(item[6][0]) 
    210             rep += "maximum value : %s \n"%str(item[6][1]) 
    211             rep += "parameter unit: %s\n\n"%str(item[7]) 
    212          
    213234        return rep 
    214  
    215          
     235     
     236    def __repr__(self): 
     237        """ output string for printing""" 
     238        rep = "\n\nState name: %s\n"%self.name 
     239        rep += "\n\nState form factor combobox selection: %s\n"%self.formfactorcombobox 
     240        rep += "\n\nState structure factor combobox selection: %s\n"%self.structurecombobox 
     241        rep += "\n\n is data : %s\n"%self.is_data 
     242        rep += "\n\n data's name : %s\n"%self.data_name 
     243        rep += "\n\n data's id : %s\n"%self.data_id 
     244        rep += "\n\n model type (form factor) selected: %s\n"%self.shape_rbutton  
     245        rep += "\n\n model type (shape independent) selected: %s\n "%self.shape_indep_rbutton 
     246        rep += "\n\n model type (structure factor) selected: %s\n"%self.struct_rbutton 
     247        rep += "\n\n model type (plug-in ) selected: %s\n"%self.plugin_rbutton 
     248        #rep +="data : %s\n"% str(self.data) 
     249        #rep += "Plotting Range: min: %s, max: %s, steps: %s\n"%(str(self.qmin), 
     250        #                                        str(self.qmax),str(self.npts)) 
     251        #rep +="model  : %s\n\n"% str(self.model) 
     252        #rep +="number parameters(self.parameters): %s\n"%len(self.parameters) 
     253        #rep += self._repr_helper( list=self.parameters, rep=rep) 
     254        #rep +="number orientation parameters" 
     255        #rep +="(self.orientation_params): %s\n"%len(self.orientation_params) 
     256        #rep += self._repr_helper( list=self.orientation_params, rep=rep) 
     257        #rep +="number dispersity parameters" 
     258        #rep +="(self.orientation_params_disp): %s\n"%len(self.orientation_params_disp) 
     259        #rep += self._repr_helper( list=self.orientation_params_disp, rep=rep) 
    216260        
     261        return rep 
     262    
     263    def _toXML_helper(self, list, element, newdoc): 
     264        """ 
     265        """ 
     266        for item in list: 
     267            sub_element = newdoc.createElement('parameter') 
     268            sub_element.setAttribute('name', str(item[1])) 
     269            sub_element.setAttribute('value', str(item[2])) 
     270            sub_element.setAttribute('selected_to_fit', str(item[0])) 
     271            sub_element.setAttribute('error_displayed', str(item[4][0])) 
     272            sub_element.setAttribute('error_value', str(item[4][1])) 
     273            sub_element.setAttribute('minimum_displayed', str(item[5][0])) 
     274            sub_element.setAttribute('minimum_value', str(item[5][1])) 
     275            sub_element.setAttribute('maximum_displayed', str(item[6][0])) 
     276            sub_element.setAttribute('maximum_value', str(item[6][1])) 
     277            sub_element.setAttribute('unit', str(item[7])) 
     278            element.appendChild(sub_element) 
     279         
     280            
     281    def toXML(self, file="fitting_state.fitv", doc=None, entry_node=None): 
     282        """ 
     283            Writes the state of the InversionControl panel to file, as XML. 
     284             
     285            Compatible with standalone writing, or appending to an 
     286            already existing XML document. In that case, the XML document 
     287            is required. An optional entry node in the XML document may also be given. 
     288             
     289            @param file: file to write to 
     290            @param doc: XML document object [optional] 
     291            @param entry_node: XML node within the XML document at which we will append the data [optional] 
     292        """ 
     293        from xml.dom.minidom import getDOMImplementation 
     294 
     295        # Check whether we have to write a standalone XML file 
     296        if doc is None: 
     297            impl = getDOMImplementation() 
     298            doc_type = impl.createDocumentType(FITTING_NODE_NAME, "1.0", "1.0")      
     299            newdoc = impl.createDocument(None, FITTING_NODE_NAME, doc_type) 
     300            top_element = newdoc.documentElement 
     301        else: 
     302            # We are appending to an existing document 
     303            newdoc = doc 
     304            top_element = newdoc.createElement(FITTING_NODE_NAME) 
     305            if entry_node is None: 
     306                newdoc.documentElement.appendChild(top_element) 
     307            else: 
     308                entry_node.appendChild(top_element) 
     309             
     310        attr = newdoc.createAttribute("version") 
     311        attr.nodeValue = '1.0' 
     312        top_element.setAttributeNode(attr) 
     313         
     314        # File name 
     315        element = newdoc.createElement("filename") 
     316        if self.file is not None: 
     317            element.appendChild(newdoc.createTextNode(str(self.file))) 
     318        else: 
     319            element.appendChild(newdoc.createTextNode(str(file))) 
     320        top_element.appendChild(element) 
     321     
     322        # Inputs 
     323        inputs = newdoc.createElement("Attributes") 
     324        top_element.appendChild(inputs) 
    217325        
     326        element = newdoc.createElement('data_attributes') 
     327        if self.data is not None and hasattr(self.data, "group_id"): 
     328            self.data_group_id = self.data.group_id 
     329        if self.data is not None and hasattr(self.data, "is_data"): 
     330            self.is_data = self.data.is_data 
     331        if self.data is not None: 
     332            self.data_name = self.data.name 
     333        if self.data is not None and hasattr(self.data, "id"): 
     334            self.data_id = self.data.id 
     335        
     336        for item in list_of_state_attributes: 
     337            exec "element.setAttribute(item[0], str(self.%s))"%(item[1]) 
     338        inputs.appendChild(element)    
     339        
     340        for item in list_of_state_parameters: 
     341            element = newdoc.createElement(item[0]) 
     342            exec "self._toXML_helper(list=self.%s, element=element, newdoc=newdoc)"%item[1]                        
     343            inputs.appendChild(element) 
     344        
     345        # Save the file 
     346        if doc is None: 
     347            fd = open(file, 'w') 
     348            fd.write(newdoc.toprettyxml()) 
     349            fd.close() 
     350            return None 
     351        else: 
     352            return newdoc.toprettyxml() 
     353         
     354    def _fromXML_helper(self, node, list): 
     355        """ 
     356        """ 
     357        for item in node: 
     358            name = item.get('name') 
     359            value = item.get('value') 
     360            selected_to_fit = item.get('selected_to_fit') 
     361            error_displayed = item.get('error_displayed') 
     362            error_value = item.get('error_value') 
     363            minimum_displayed = item.get('minimum_displayed') 
     364            minimum_value = item.get('minimum_value') 
     365            maximum_displayed = item.get('maximum_displayed') 
     366            maximum_value = item.get('maximum_value') 
     367            unit = item.get('unit') 
     368            list.append([selected_to_fit, name, value, "+/-",[error_displayed, error_value], 
     369                         [minimum_displayed,minimum_value],[maximum_displayed,maximum_value], unit]) 
     370        
     371    def fromXML(self, file=None, node=None): 
     372        """ 
     373            Load fitting state from a file 
     374             
     375            @param file: .fitv file 
     376            @param node: node of a XML document to read from 
     377        """ 
     378       
     379        if file is not None: 
     380            raise RuntimeError, "PageState no longer supports non-CanSAS format for fitting files" 
     381             
     382        if node.get('version')\ 
     383            and node.get('version') == '1.0': 
     384             
     385            # Get file name 
     386            entry = get_content('ns:filename', node) 
     387            if entry is not None: 
     388                self.file = entry.text.strip() 
     389         
     390            # Parse fitting attributes 
     391            entry = get_content('ns:Attributes', node) 
     392            if entry is not None: 
     393                for item in list_of_state_attributes: 
     394                    field = get_content('ns:%s'%item[0], entry) 
     395                    if field is not None: 
     396                        if item[2] == "string": 
     397                            exec "self.%s= str(field.text)"%item[1] 
     398                        elif item[2] == "bool": 
     399                            try: 
     400                                exec "self.%s= field.get(str(%s))"%(item[1], item[0]) 
     401                            except: 
     402                                exec "self.%s = None"%item[1] 
     403                        else: 
     404                            try: 
     405                                exec "self.%s = float(field.get(%s))"%(item[1], item[0]) 
     406                            except: 
     407                                exec "self.%s = None"%item[1] 
     408                
     409                for item in list_of_state_parameters: 
     410                    field = get_content("ns:%s"%item[0], entry) 
     411                    self._fromXML_helper(node=field, list=self.parameters) 
     412                 
     413 
     414class Reader(CansasReader): 
     415    """ 
     416        Class to load a .fitv fitting file 
     417    """ 
     418    ## File type 
     419    type_name = "Fitting" 
     420     
     421    ## Wildcards 
     422    type = ["Fitting files (*.fitv)|*.fitv"] 
     423    ## List of allowed extensions 
     424    ext=['.fitv', '.FITV']   
     425     
     426    def __init__(self, call_back=None, cansas=True): 
     427        """ 
     428            Initialize the call-back method to be called 
     429            after we load a file 
     430            @param call_back: call-back method 
     431            @param cansas:  True = files will be written/read in CanSAS format 
     432                            False = write CanSAS format 
     433             
     434        """ 
     435        ## Call back method to be executed after a file is read 
     436        self.call_back = call_back 
     437        ## CanSAS format flag 
     438        self.cansas = cansas 
     439         
     440    def read(self, path): 
     441        """  
     442            Load a new P(r) inversion state from file 
     443             
     444            @param path: file path 
     445            @return: None 
     446        """ 
     447        if self.cansas==True: 
     448            return self._read_cansas(path) 
     449        else: 
     450            return self._read_standalone(path) 
     451         
     452    def _data2d_to_xml_doc(self): 
     453        """ 
     454            Create an XML document to contain the content of a Data2D 
     455             
     456            @param datainfo: Data2D object 
     457        """ 
     458        if not issubclass(datainfo.__class__, Data2D): 
     459            raise RuntimeError, "The cansas writer expects a Data2D instance" 
     460         
     461        doc = xml.dom.minidom.Document() 
     462        main_node = doc.createElement("SASroot") 
     463        main_node.setAttribute("version", self.version) 
     464       
     465        doc.appendChild(main_node) 
     466         
     467        entry_node = doc.createElement("SASentry") 
     468        main_node.appendChild(entry_node) 
     469         
     470        write_node(doc, entry_node, "Title", datainfo.title) 
     471         
     472        for item in datainfo.run: 
     473            runname = {} 
     474            if datainfo.run_name.has_key(item) and len(str(datainfo.run_name[item]))>1: 
     475                runname = {'name': datainfo.run_name[item] } 
     476            write_node(doc, entry_node, "Run", item, runname) 
     477         
     478        # Data info 
     479        node = doc.createElement("SASdata") 
     480        entry_node.appendChild(node) 
     481         
     482        for i in range(len(datainfo.x)): 
     483            pt = doc.createElement("Idata") 
     484            node.appendChild(pt) 
     485            write_node(doc, pt, "Q", datainfo.x[i], {'unit':datainfo.x_unit}) 
     486            if len(datainfo.y)>=i: 
     487                write_node(doc, pt, "I", datainfo.y[i], {'unit':datainfo.y_unit}) 
     488            if datainfo.dx !=None and len(datainfo.dx)>=i: 
     489                write_node(doc, pt, "Qdev", datainfo.dx[i], {'unit':datainfo.x_unit}) 
     490            if datainfo.dy !=None and len(datainfo.dy)>=i: 
     491                write_node(doc, pt, "Idev", datainfo.dy[i], {'unit':datainfo.y_unit}) 
     492 
     493         
     494        # Sample info 
     495        sample = doc.createElement("SASsample") 
     496        if datainfo.sample.name is not None: 
     497            sample.setAttribute("name", str(datainfo.sample.name)) 
     498        entry_node.appendChild(sample) 
     499        write_node(doc, sample, "ID", str(datainfo.sample.ID)) 
     500        write_node(doc, sample, "thickness", datainfo.sample.thickness, {"unit":datainfo.sample.thickness_unit}) 
     501        write_node(doc, sample, "transmission", datainfo.sample.transmission) 
     502        write_node(doc, sample, "temperature", datainfo.sample.temperature, {"unit":datainfo.sample.temperature_unit}) 
     503         
     504        for item in datainfo.sample.details: 
     505            write_node(doc, sample, "details", item) 
     506         
     507        pos = doc.createElement("position") 
     508        written = write_node(doc, pos, "x", datainfo.sample.position.x, {"unit":datainfo.sample.position_unit}) 
     509        written = written | write_node(doc, pos, "y", datainfo.sample.position.y, {"unit":datainfo.sample.position_unit}) 
     510        written = written | write_node(doc, pos, "z", datainfo.sample.position.z, {"unit":datainfo.sample.position_unit}) 
     511        if written == True: 
     512            sample.appendChild(pos) 
     513         
     514        ori = doc.createElement("orientation") 
     515        written = write_node(doc, ori, "roll",  datainfo.sample.orientation.x, {"unit":datainfo.sample.orientation_unit}) 
     516        written = written | write_node(doc, ori, "pitch", datainfo.sample.orientation.y, {"unit":datainfo.sample.orientation_unit}) 
     517        written = written | write_node(doc, ori, "yaw",   datainfo.sample.orientation.z, {"unit":datainfo.sample.orientation_unit}) 
     518        if written == True: 
     519            sample.appendChild(ori) 
     520         
     521        # Instrument info 
     522        instr = doc.createElement("SASinstrument") 
     523        entry_node.appendChild(instr) 
     524         
     525        write_node(doc, instr, "name", datainfo.instrument) 
     526         
     527        #   Source 
     528        source = doc.createElement("SASsource") 
     529        if datainfo.source.name is not None: 
     530            source.setAttribute("name", str(datainfo.source.name)) 
     531        instr.appendChild(source) 
     532         
     533        write_node(doc, source, "radiation", datainfo.source.radiation) 
     534        write_node(doc, source, "beam_shape", datainfo.source.beam_shape) 
     535        size = doc.createElement("beam_size") 
     536        if datainfo.source.beam_size_name is not None: 
     537            size.setAttribute("name", str(datainfo.source.beam_size_name)) 
     538        written = write_node(doc, size, "x", datainfo.source.beam_size.x, {"unit":datainfo.source.beam_size_unit}) 
     539        written = written | write_node(doc, size, "y", datainfo.source.beam_size.y, {"unit":datainfo.source.beam_size_unit}) 
     540        written = written | write_node(doc, size, "z", datainfo.source.beam_size.z, {"unit":datainfo.source.beam_size_unit}) 
     541        if written == True: 
     542            source.appendChild(size) 
     543             
     544        write_node(doc, source, "wavelength", datainfo.source.wavelength, {"unit":datainfo.source.wavelength_unit}) 
     545        write_node(doc, source, "wavelength_min", datainfo.source.wavelength_min, {"unit":datainfo.source.wavelength_min_unit}) 
     546        write_node(doc, source, "wavelength_max", datainfo.source.wavelength_max, {"unit":datainfo.source.wavelength_max_unit}) 
     547        write_node(doc, source, "wavelength_spread", datainfo.source.wavelength_spread, {"unit":datainfo.source.wavelength_spread_unit}) 
     548         
     549        #   Collimation 
     550        for item in datainfo.collimation: 
     551            coll = doc.createElement("SAScollimation") 
     552            if item.name is not None: 
     553                coll.setAttribute("name", str(item.name)) 
     554            instr.appendChild(coll) 
     555             
     556            write_node(doc, coll, "length", item.length, {"unit":item.length_unit}) 
     557             
     558            for apert in item.aperture: 
     559                ap = doc.createElement("aperture") 
     560                if apert.name is not None: 
     561                    ap.setAttribute("name", str(apert.name)) 
     562                if apert.type is not None: 
     563                    ap.setAttribute("type", str(apert.type)) 
     564                coll.appendChild(ap) 
     565                 
     566                write_node(doc, ap, "distance", apert.distance, {"unit":apert.distance_unit}) 
     567                 
     568                size = doc.createElement("size") 
     569                if apert.size_name is not None: 
     570                    size.setAttribute("name", str(apert.size_name)) 
     571                written = write_node(doc, size, "x", apert.size.x, {"unit":apert.size_unit}) 
     572                written = written | write_node(doc, size, "y", apert.size.y, {"unit":apert.size_unit}) 
     573                written = written | write_node(doc, size, "z", apert.size.z, {"unit":apert.size_unit}) 
     574                if written == True: 
     575                    ap.appendChild(size) 
     576 
     577        #   Detectors 
     578        for item in datainfo.detector: 
     579            det = doc.createElement("SASdetector") 
     580            written = write_node(doc, det, "name", item.name) 
     581            written = written | write_node(doc, det, "SDD", item.distance, {"unit":item.distance_unit}) 
     582            written = written | write_node(doc, det, "slit_length", item.slit_length, {"unit":item.slit_length_unit}) 
     583            if written == True: 
     584                instr.appendChild(det) 
     585             
     586            off = doc.createElement("offset") 
     587            written = write_node(doc, off, "x", item.offset.x, {"unit":item.offset_unit}) 
     588            written = written | write_node(doc, off, "y", item.offset.y, {"unit":item.offset_unit}) 
     589            written = written | write_node(doc, off, "z", item.offset.z, {"unit":item.offset_unit}) 
     590            if written == True: 
     591                det.appendChild(off) 
     592             
     593            center = doc.createElement("beam_center") 
     594            written = write_node(doc, center, "x", item.beam_center.x, {"unit":item.beam_center_unit}) 
     595            written = written | write_node(doc, center, "y", item.beam_center.y, {"unit":item.beam_center_unit}) 
     596            written = written | write_node(doc, center, "z", item.beam_center.z, {"unit":item.beam_center_unit}) 
     597            if written == True: 
     598                det.appendChild(center) 
     599                 
     600            pix = doc.createElement("pixel_size") 
     601            written = write_node(doc, pix, "x", item.pixel_size.x, {"unit":item.pixel_size_unit}) 
     602            written = written | write_node(doc, pix, "y", item.pixel_size.y, {"unit":item.pixel_size_unit}) 
     603            written = written | write_node(doc, pix, "z", item.pixel_size.z, {"unit":item.pixel_size_unit}) 
     604            if written == True: 
     605                det.appendChild(pix) 
     606                 
     607            ori = doc.createElement("orientation") 
     608            written = write_node(doc, ori, "roll",  item.orientation.x, {"unit":item.orientation_unit}) 
     609            written = written | write_node(doc, ori, "pitch", item.orientation.y, {"unit":item.orientation_unit}) 
     610            written = written | write_node(doc, ori, "yaw",   item.orientation.z, {"unit":item.orientation_unit}) 
     611            if written == True: 
     612                det.appendChild(ori) 
     613                 
     614         
     615        # Processes info 
     616        for item in datainfo.process: 
     617            node = doc.createElement("SASprocess") 
     618            entry_node.appendChild(node) 
     619 
     620            write_node(doc, node, "name", item.name) 
     621            write_node(doc, node, "date", item.date) 
     622            write_node(doc, node, "description", item.description) 
     623            for term in item.term: 
     624                value = term['value'] 
     625                del term['value'] 
     626                write_node(doc, node, "term", value, term) 
     627            for note in item.notes: 
     628                write_node(doc, node, "SASprocessnote", note) 
     629         
     630        # Return the document, and the SASentry node associated with 
     631        # the data we just wrote 
     632        return doc, entry_node 
     633     
     634    def _read_standalone(self, path): 
     635        """  
     636            Load a new P(r) inversion state from file. 
     637            The P(r) node is assumed to be the top element. 
     638             
     639            @param path: file path 
     640            @return: None 
     641        """ 
     642        # Read the new state from file 
     643        state = PageState() 
     644        state.fromXML(file=path) 
     645        # Call back to post the new state 
     646        self.call_back(state) 
     647        return None 
     648     
     649    def _parse_state(self, entry): 
     650        """ 
     651            Read a fit result from an XML node 
     652            @param entry: XML node to read from  
     653            @return: PageState object 
     654        """ 
     655        # Create an empty state 
     656        state = PageState() 
     657        # Locate the P(r) node 
     658        try: 
     659            nodes = entry.xpath('ns:%s' % FITTING_NODE_NAME, namespaces={'ns': CANSAS_NS}) 
     660            state.fromXML(node=nodes[0]) 
     661        except: 
     662            logging.info("XML document does not contain fitting information.\n %s" % sys.exc_value) 
     663             
     664        return state 
     665     
     666    def _read_cansas(self, path): 
     667        """  
     668            Load data and P(r) information from a CanSAS XML file. 
     669             
     670            @param path: file path 
     671            @return: Data1D object if a single SASentry was found,  
     672                        or a list of Data1D objects if multiple entries were found, 
     673                        or None of nothing was found 
     674            @raise RuntimeError: when the file can't be opened 
     675            @raise ValueError: when the length of the data vectors are inconsistent 
     676        """ 
     677        output = [] 
     678        try: 
     679            if os.path.isfile(path): 
     680                basename  = os.path.basename(path) 
     681                root, extension = os.path.splitext(basename) 
     682                #TODO: eventually remove the check for .xml once 
     683                # the P(r) writer/reader is truly complete. 
     684                if  extension.lower() in self.ext or \ 
     685                    extension.lower() == '.xml': 
     686                     
     687                    tree = etree.parse(path, parser=etree.ETCompatXMLParser()) 
     688                    # Check the format version number 
     689                    # Specifying the namespace will take care of the file format version  
     690                    root = tree.getroot() 
     691                    entry_list = root.xpath('/ns:SASroot/ns:SASentry', namespaces={'ns': CANSAS_NS}) 
     692                    for entry in entry_list: 
     693                        sas_entry = self._parse_entry(entry) 
     694                        fitstate = self._parse_state(entry) 
     695                        sas_entry.meta_data['fitstate'] = fitstate 
     696                        sas_entry.filename = fitstate.file 
     697                        output.append(sas_entry) 
     698                     
     699            else: 
     700                raise RuntimeError, "%s is not a file" % path 
     701             
     702            # Return output consistent with the loader's api 
     703            if len(output)==0: 
     704                return None 
     705            elif len(output)==1: 
     706                # Call back to post the new state 
     707                state = output[0].meta_data['fitstate'] 
     708                if state is not None and state.is_data is not None: 
     709                    exec 'output[0].is_data = state.is_data'  
     710                  
     711                output[0].filename = state.data_name 
     712                state.data = output[0] 
     713                state.data.name = state.data_name 
     714                state.data.id = state.data_id 
     715                state.data.group_id = state.data_group_id 
     716                self.call_back(state=state, datainfo=output[0]) 
     717                return output[0] 
     718            else: 
     719                return output                 
     720        except: 
     721            raise 
     722            
     723    def write(self, filename, datainfo=None, fitstate=None): 
     724        """ 
     725            Write the content of a Data1D as a CanSAS XML file 
     726             
     727            @param filename: name of the file to write 
     728            @param datainfo: Data1D object 
     729            @param fitstate: PageState object 
     730        """ 
     731        # Sanity check 
     732        if self.cansas == True: 
     733             
     734            # Add fitting information to the XML document 
     735            if fitstate is not None: 
     736                if fitstate.data is None: 
     737                    data = DataLoader.data_info.Data1D(x=[], y=[])    
     738                elif issubclass(fitstate.data.__class__, DataLoader.data_info.Data1D): 
     739                    data = fitstate.data 
     740                    doc, sasentry = self._to_xml_doc(data) 
     741                else: 
     742                    data = fitstate.data 
     743                    doc, sasentry = self._data2d_to_xml_doc(data) 
     744                fitstate.toXML(doc=doc, entry_node=sasentry) 
     745            # Write the XML document 
     746            fd = open(filename, 'w') 
     747            fd.write(doc.toprettyxml()) 
     748            fd.close() 
     749        else: 
     750            fitstate.toXML(file=filename) 
     751         
     752         
     753if __name__ == "__main__": 
     754    state = PageState(parent=None) 
     755    state.toXML() 
     756   
Note: See TracChangeset for help on using the changeset viewer.