source: sasview/sansview/perspectives/fitting/pagestate.py @ 3e943e8

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 3e943e8 was dce84c0, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on freeze

  • Property mode set to 100644
File size: 54.9 KB
RevLine 
[c77d859]1
2
[5062bbf]3################################################################################
4#This software was developed by the University of Tennessee as part of the
5#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
6#project funded by the US National Science Foundation.
7#
8#See the license text in license.txt
9#
10#copyright 2009, University of Tennessee
11################################################################################
12
[11a7e11]13import time
14import os
15import sys
[6f023e8]16import copy
[11a7e11]17import logging
[df7ed14]18import numpy
[c77d859]19
[35b556d]20import xml.dom.minidom
[11a7e11]21from xml.dom.minidom import parse
22from lxml import etree
23
24import DataLoader
[61cada5]25from DataLoader.readers.cansas_reader import Reader as CansasReader
[e9b12eaf]26from DataLoader.readers.cansas_reader import get_content, write_node
[df7ed14]27from DataLoader.data_info import Data2D, Detector
[61cada5]28
[11a7e11]29#Information to read/write state as xml
[61cada5]30FITTING_NODE_NAME = 'fitting_plug_in'
31CANSAS_NS = "cansas1d/1.0"
32
[26f3dd5]33list_of_data_attributes = [["is_data", "is_data", "bool"],
[61cada5]34                      ["group_id", "data_group_id", "string"],
35                      ["data_name", "data_name", "string"],
36                      ["data_id", "data_id", "string"],
37                      ["name", "name", "string"],
[26f3dd5]38                      ["data_name", "data_name", "string"]]
[e3d1423]39list_of_state_attributes = [["engine_type", "engine_type", "string"],
40                       ["qmin", "qmin", "float"],
[61cada5]41                      ["qmax", "qmax", "float"],
42                      ["npts", "npts", "float"],
43                      ["shape_rbutton", "shape_rbutton", "bool"],
44                      ["shape_indep_rbutton", "shape_indep_rbutton", "bool"],
45                      ["plugin_rbutton", "plugin_rbutton","bool"],
46                      ["struct_rbutton", "struct_rbutton", "bool"],
[0b12abb5]47                      ["formfactorcombobox", "formfactorcombobox", "float"],
48                      ["structurecombobox", "structurecombobox", "float"],
49                      ["disp_box", "disp_box", "float"],
[26f3dd5]50                      ["enable_smearer","enable_smearer","bool"],
51                      ["disable_smearer","disable_smearer","bool"],
52                      ["pinhole_smearer","pinhole_smearer","bool"],
53                      ["slit_smearer","slit_smearer","bool"],
54                      ["enable_disp","enable_disp","bool"],
55                      ["disable_disp","disable_disp","bool"],
56                      ["slit_smearer","slit_smearer","bool"],
57                      ["enable2D","enable2D","bool"],
58                      ["cb1","cb1","bool"],
[5cc7001]59                      ["tcChi","tcChi","float"],
60                     ["smearer", "smearer", "float"],
61                     ["smear_type","smear_type", "string"],
62                     ["dq_l", "dq_l", "string"],
63                     ["dq_r","dq_r", "string"]]
64
[11a7e11]65list_of_model_attributes = [["values", "values"],
66                            ["weights", "weights"]]
67
[fb59ed9]68list_of_state_parameters = [["parameters", "parameters"] , 
69                            ["str_parameters", "str_parameters"] ,                     
[61cada5]70                            ["orientation_parameters", "orientation_params"],
71                            ["dispersity_parameters", "orientation_params_disp"],
72                            ["fixed_param", "fixed_param"],                     
73                            ["fittable_param","fittable_param"]]
[df7ed14]74list_of_data_2d_attr = [["xmin", "xmin","float"],
75                        ["xmax","xmax","float"],
76                        ["ymin","ymin","float"],
77                        ["ymax","ymax","float"],
78                        ["_xaxis","_xaxis", "string"],
79                        ["_xunit", "_xunit", "string"],
80                        ["_yaxis","_yaxis","string"],
81                        ["_yunit","_yunit","string"],
82                        ["_zaxis","_zaxis","string"],
83                        ["_zunit","_zunit","string"]]
84list_of_data2d_values = [["qx_data","qx_data","float"],
85                         ["qy_data","qy_data","float"],
86                         ["dqx_data","dqx_data","float"],
87                         ["dqy_data","dqy_data","float"],
88                         ["data","data","float"],
89                         ["q_data","q_data","float"],
90                         ["err_data","err_data","float"],
91                         ["mask","mask","bool"]]
[61cada5]92
[0b12abb5]93def parse_entry_helper( node, item):
94    """
95    Create a numpy list from value extrated from the node
96   
97    :param node: node from each the value is stored
98    :param item: list name of three strings.the two first are name of data
99        attribute and the third one is the type of the value of that
100        attribute. type can be string, float, bool, etc.
101   
102    : return: numpy array
103    """
104    if node is not None:
105        if item[2] == "string":
106            return str(node.get(item[0]).strip())
107        elif item[2] == "bool":
108            try:
[e3d1423]109                return node.get(item[0]).strip() == "True"
110               
[0b12abb5]111            except:
112                return None
113        else:
114            try:
115                return float(node.get(item[0]))
116            except:
117                return None
118           
119           
[cfc0913]120class PageState(object):
[c77d859]121    """
[5062bbf]122    Contains information to reconstruct a page of the fitpanel.
[c77d859]123    """
[61cada5]124    def __init__(self, parent=None, model=None, data=None):
[c77d859]125       
126        """
[5062bbf]127        Initialize the current state
128       
129        :param model: a selected model within a page
130        :param data:
131       
[c77d859]132        """
[61cada5]133        self.file = None
[11a7e11]134        #Time of state creation
135        self.timestamp = time.time()
[c77d859]136        ## Data member to store the dispersion object created
137        self._disp_obj_dict = {}
[61cada5]138        #------------------------
[c77d859]139        #Data used for fitting
140        self.data = data
[61cada5]141        #save additional information on data that dataloader.reader does not read
142        self.is_data = None
143        self.data_name = ""
144       
145        if self.data is not None:
146            self.data_name = self.data.name
147        self.data_id = None
148        if self.data is not None and hasattr(self.data, "id"):
149            self.data_id = self.data.id
150        self.data_group_id = None
151        if self.data is not None and hasattr(self.data, "group_id"):
152            self.data_group_id = self.data.group_id
[0b12abb5]153       
[61cada5]154        ## reset True change the state of exsiting button
155        self.reset = False
156       
[c99a6c5]157        #engine type
158        self.engine_type = None
[c77d859]159        # flag to allow data2D plot
[cfc0913]160        self.enable2D = False
[c77d859]161        # model on which the fit would be performed
162        self.model = model
[dce84c0]163        #list of process done to model
164        self.process = []
[c77d859]165        #fit page manager
166        self.manager = None
167        #Store the parent of this panel parent
168        # For this application fitpanel is the parent
169        self.parent  = parent
170        # Event_owner is the owner of model event
171        self.event_owner = None
[c9a4377]172        ##page name
[cfc0913]173        self.page_name = ""
[c77d859]174        # Contains link between  model ,all its parameters, and panel organization
[61cada5]175        self.parameters = []
[fb59ed9]176        # String parameter list that can not be fitted
177        self.str_parameters = []
[c77d859]178        # Contains list of parameters that cannot be fitted and reference to
179        #panel objects
[61cada5]180        self.fixed_param = []
[c77d859]181        # Contains list of parameters with dispersity and reference to
182        #panel objects
[61cada5]183        self.fittable_param = []
[60132ef]184        ## orientation parameters
[61cada5]185        self.orientation_params = []
[fc6ea43]186        ## orientation parmaters for gaussian dispersity
[61cada5]187        self.orientation_params_disp = []
[3370922]188        ## smearer info
[61cada5]189        self.smearer = None
[7609f1a]190        self.smear_type = None
191        self.dq_l = None
192        self.dq_r = None
193
[c77d859]194        #list of dispersion paramaters
[cfc0913]195        self.disp_list =[]
[61cada5]196        if self.model is not None:
[71f0373]197            self.disp_list = self.model.getDispParamList()
[61cada5]198        self._disp_obj_dict = {}
199        self.disp_cb_dict = {}
200        self.values = []
201        self.weights = []
[dad49a0]202                   
[c77d859]203        #contains link between a model and selected parameters to fit
[61cada5]204        self.param_toFit = []
[a074145]205        ##dictionary of model type and model class
[cfc0913]206        self.model_list_box = None
[a074145]207        ## save the state of the context menu
[61cada5]208        self.saved_states = {}
[240b9966]209        ## save selection of combobox
[3b9e023]210        self.formfactorcombobox = None
211        self.structurecombobox  = None
[240b9966]212        ## radio box to select type of model
213        self.shape_rbutton = False
214        self.shape_indep_rbutton = False
215        self.struct_rbutton = False
216        self.plugin_rbutton = False
[b787e68c]217        ## the indice of the current selection
218        self.disp_box = 0
[c77d859]219        ## Qrange
[cfc0913]220        ## Q range
[61cada5]221        self.qmin = 0.001
222        self.qmax = 0.1
[0b12abb5]223        #reset data range
224        self.qmax_x = None
225        self.qmin_x = None
226       
[cfc0913]227        self.npts = None
[61cada5]228        self.name = ""
[4523b68]229        self.multi_factor = None
[cfc0913]230        ## enable smearering state
231        self.enable_smearer = False
[fc6ea43]232        self.disable_smearer = True
[7609f1a]233        self.pinhole_smearer = False
234        self.slit_smearer   = False
[cfc0913]235        ## disperity selection
[61cada5]236        self.enable_disp = False
237        self.disable_disp = True
[11a7e11]238       
[cfc0913]239        ## state of selected all check button
240        self.cb1 = False
[0aeabc6]241        ## store value of chisqr
[61cada5]242        self.tcChi = None
[240b9966]243   
[6f023e8]244    def clone(self):
[61cada5]245        """
[5062bbf]246        Create a new copy of the current object
[61cada5]247        """
248        model = None
249        if self.model is not None:
[6f023e8]250            model = self.model.clone()
[bb70474]251            model.name = self.model.name
[61cada5]252        obj = PageState(self.parent, model=model)
253        obj.file = copy.deepcopy(self.file)
[6f023e8]254        obj.data = copy.deepcopy(self.data)
[61cada5]255        if self.data is not None:
256            self.data_name = self.data.name
257        obj.data_name = self.data_name
258        obj.is_data = self.is_data
[dcf29d7]259        obj.model_list_box = copy.deepcopy(self.model_list_box)
[c99a6c5]260        obj.engine_type = copy.deepcopy(self.engine_type)
[240b9966]261       
[61cada5]262        obj.formfactorcombobox = self.formfactorcombobox
263        obj.structurecombobox  = self.structurecombobox 
[240b9966]264       
265        obj.shape_rbutton = self.shape_rbutton
266        obj.shape_indep_rbutton = self.shape_indep_rbutton
267        obj.struct_rbutton = self.struct_rbutton
268        obj.plugin_rbutton = self.plugin_rbutton
269       
[dcf29d7]270        obj.manager = self.manager
271        obj.event_owner = self.event_owner
[71f0373]272        obj.disp_list = copy.deepcopy(self.disp_list)
[fc6ea43]273       
[c477b31]274        obj.enable2D = copy.deepcopy(self.enable2D)
[cfc0913]275        obj.parameters = copy.deepcopy(self.parameters)
[fb59ed9]276        obj.str_parameters = copy.deepcopy(self.str_parameters)
[cfc0913]277        obj.fixed_param = copy.deepcopy(self.fixed_param)
278        obj.fittable_param = copy.deepcopy(self.fittable_param)
[60132ef]279        obj.orientation_params =  copy.deepcopy(self.orientation_params)
[fc6ea43]280        obj.orientation_params_disp =  copy.deepcopy(self.orientation_params_disp)
[b787e68c]281        obj.enable_disp = copy.deepcopy(self.enable_disp)
[fc6ea43]282        obj.disable_disp = copy.deepcopy(self.disable_disp)
[0aeabc6]283        obj.tcChi = self.tcChi
284 
[c477b31]285        if len(self._disp_obj_dict)>0:
286            for k , v in self._disp_obj_dict.iteritems():
287                obj._disp_obj_dict[k]= v
[dad49a0]288        if len(self.disp_cb_dict)>0:
289            for k , v in self.disp_cb_dict.iteritems():
290                obj.disp_cb_dict[k]= v
[b421b1a]291               
[dad49a0]292        obj.values = copy.deepcopy(self.values)
293        obj.weights = copy.deepcopy(self.weights)
[b787e68c]294        obj.enable_smearer = copy.deepcopy(self.enable_smearer)
[fc6ea43]295        obj.disable_smearer = copy.deepcopy(self.disable_smearer)
[7609f1a]296        obj.pinhole_smearer = copy.deepcopy(self.pinhole_smearer)
297        obj.slit_smearer = copy.deepcopy(self.slit_smearer)
298        obj.smear_type = copy.deepcopy(self.smear_type)
299        obj.dq_l = copy.deepcopy(self.dq_l)
300        obj.dq_r = copy.deepcopy(self.dq_r)
301
[b787e68c]302        obj.disp_box = copy.deepcopy(self.disp_box)
303        obj.qmin = copy.deepcopy(self.qmin)
304        obj.qmax = copy.deepcopy(self.qmax)
[4523b68]305        obj.multi_factor = copy.deepcopy(self.multi_factor)
[b787e68c]306        obj.npts = copy.deepcopy(self.npts )
307        obj.cb1 = copy.deepcopy(self.cb1)
[3370922]308        obj.smearer = copy.deepcopy(self.smearer)
309       
[a074145]310        for name, state in self.saved_states.iteritems():
311            copy_name = copy.deepcopy(name)
312            copy_state = state.clone()
313            obj.saved_states[copy_name]= copy_state
[6f023e8]314        return obj
[61cada5]315   
316    def _repr_helper(self, list, rep):
317        """
[5062bbf]318        Helper method to print a state
[61cada5]319        """
320        for item in list:
[240b9966]321            rep += "parameter name: %s \n"%str(item[1])
322            rep += "value: %s\n"%str(item[2])
323            rep += "selected: %s\n"%str(item[0])
324            rep += "error displayed : %s \n"%str(item[4][0])
325            rep += "error value:%s \n"%str(item[4][1])
326            rep += "minimum displayed : %s \n"%str(item[5][0])
327            rep += "minimum value : %s \n"%str(item[5][1])
328            rep += "maximum displayed : %s \n"%str(item[6][0])
329            rep += "maximum value : %s \n"%str(item[6][1])
330            rep += "parameter unit: %s\n\n"%str(item[7])
331        return rep
[5ef55d2]332 
[61cada5]333    def __repr__(self):
[11a7e11]334        """
[5062bbf]335        output string for printing
[11a7e11]336        """
337        rep = "\nState name: %s\n"%self.file
338        t = time.localtime(self.timestamp)
339        time_str = time.strftime("%b %d %H:%M", t)
340        rep += "State created on : %s\n"%time_str
341        rep += "State form factor combobox selection: %s\n"%self.formfactorcombobox
342        rep += "State structure factor combobox selection: %s\n"%self.structurecombobox
343        rep += "is data : %s\n"%self.is_data
344        rep += "data's name : %s\n"%self.data_name
345        rep += "data's id : %s\n"%self.data_id
346        rep += "model type (form factor) selected: %s\n"%self.shape_rbutton
347        rep += "model type (shape independent) selected: %s\n"%self.shape_indep_rbutton
348        rep += "model type (structure factor) selected: %s\n"%self.struct_rbutton
349        rep += "model type (plug-in ) selected: %s\n"%self.plugin_rbutton
350        rep += "data : %s\n"% str(self.data)
351        rep += "Plotting Range: min: %s, max: %s, steps: %s\n"%(str(self.qmin),
352                                                str(self.qmax),str(self.npts))
[0b12abb5]353        rep += "Dispersion selection : %s\n"%str(self.disp_box)
354        rep += "Smearing enable : %s\n"%str(self.enable_smearer)
355        rep += "Smearing disable : %s\n"%str(self.disable_smearer)
356        rep += "Pinhole smearer enable : %s\n"%str(self.pinhole_smearer)
357        rep += "Slit smearer enable : %s\n"%str(self.slit_smearer)
358        rep += "Dispersity enable : %s\n"%str(self.enable_disp)
359        rep += "Dispersity disable : %s\n"%str(self.disable_disp)
360        rep += "Slit smearer enable: %s\n"%str(self.slit_smearer)
361        rep += "2D enable : %s\n"%str(self.enable2D)
362        rep += "All parameters checkbox selected: %s\n"%(self.cb1)
363        rep += "Value of Chisqr : %s\n"%str(self.tcChi)
364        rep += "Smear object : %s\n"%str(self.smearer)
365        rep += "Smear type : %s\n"%(self.smear_type)
366        rep += "dq_l  : %s\n"%self.dq_l
367        rep += "dq_r  : %s\n"%self.dq_r
368       
[11a7e11]369        rep += "model  : %s\n\n"% str(self.model)
370        rep += "number parameters(self.parameters): %s\n"%len(self.parameters)
[3c44c66]371        rep = self._repr_helper( list=self.parameters, rep=rep)
[fb59ed9]372        rep += "number str_parameters(self.str_parameters): %s\n"%len(self.str_parameters)
373        rep = self._repr_helper( list=self.str_parameters, rep=rep)
[11a7e11]374        rep += "number orientation parameters"
375        rep += "(self.orientation_params): %s\n"%len(self.orientation_params)
[3c44c66]376        rep = self._repr_helper( list=self.orientation_params, rep=rep)
[11a7e11]377        rep += "number dispersity parameters"
378        rep += "(self.orientation_params_disp): %s\n"%len(self.orientation_params_disp)
[3c44c66]379        rep = self._repr_helper( list=self.orientation_params_disp, rep=rep)
[0b12abb5]380       
[61cada5]381        return rep
382   
383    def _toXML_helper(self, list, element, newdoc):
384        """
[5062bbf]385        Helper method to create xml file for saving state
[61cada5]386        """
387        for item in list:
388            sub_element = newdoc.createElement('parameter')
389            sub_element.setAttribute('name', str(item[1]))
390            sub_element.setAttribute('value', str(item[2]))
391            sub_element.setAttribute('selected_to_fit', str(item[0]))
392            sub_element.setAttribute('error_displayed', str(item[4][0]))
393            sub_element.setAttribute('error_value', str(item[4][1]))
394            sub_element.setAttribute('minimum_displayed', str(item[5][0]))
395            sub_element.setAttribute('minimum_value', str(item[5][1]))
396            sub_element.setAttribute('maximum_displayed', str(item[6][0]))
397            sub_element.setAttribute('maximum_value', str(item[6][1]))
398            sub_element.setAttribute('unit', str(item[7]))
399            element.appendChild(sub_element)
400       
401    def toXML(self, file="fitting_state.fitv", doc=None, entry_node=None):
402        """
[5062bbf]403        Writes the state of the InversionControl panel to file, as XML.
404       
405        Compatible with standalone writing, or appending to an
406        already existing XML document. In that case, the XML document
407        is required. An optional entry node in the XML document may also be given.
408       
409        :param file: file to write to
410        :param doc: XML document object [optional]
411        :param entry_node: XML node within the XML document at which we will append the data [optional]
412       
[61cada5]413        """
414        from xml.dom.minidom import getDOMImplementation
[71f0373]415
[61cada5]416        # Check whether we have to write a standalone XML file
417        if doc is None:
418            impl = getDOMImplementation()
419            doc_type = impl.createDocumentType(FITTING_NODE_NAME, "1.0", "1.0")     
420            newdoc = impl.createDocument(None, FITTING_NODE_NAME, doc_type)
421            top_element = newdoc.documentElement
422        else:
423            # We are appending to an existing document
424            newdoc = doc
425            top_element = newdoc.createElement(FITTING_NODE_NAME)
426            if entry_node is None:
427                newdoc.documentElement.appendChild(top_element)
428            else:
429                entry_node.appendChild(top_element)
430           
431        attr = newdoc.createAttribute("version")
432        attr.nodeValue = '1.0'
433        top_element.setAttributeNode(attr)
[cfc0913]434       
[61cada5]435        # File name
436        element = newdoc.createElement("filename")
437        if self.file is not None:
438            element.appendChild(newdoc.createTextNode(str(self.file)))
439        else:
440            element.appendChild(newdoc.createTextNode(str(file)))
441        top_element.appendChild(element)
[11a7e11]442       
443        element = newdoc.createElement("timestamp")
444        element.appendChild(newdoc.createTextNode(time.ctime(self.timestamp)))
445        attr = newdoc.createAttribute("epoch")
446        attr.nodeValue = str(self.timestamp)
447        element.setAttributeNode(attr)
448        top_element.appendChild(element)
[61cada5]449        # Inputs
450        inputs = newdoc.createElement("Attributes")
451        top_element.appendChild(inputs)
452       
[0b12abb5]453
[61cada5]454        if self.data is not None and hasattr(self.data, "group_id"):
455            self.data_group_id = self.data.group_id
456        if self.data is not None and hasattr(self.data, "is_data"):
457            self.is_data = self.data.is_data
458        if self.data is not None:
459            self.data_name = self.data.name
460        if self.data is not None and hasattr(self.data, "id"):
461            self.data_id = self.data.id
462       
[26f3dd5]463        for item in list_of_data_attributes:
[0b12abb5]464            element = newdoc.createElement(item[0])
[61cada5]465            exec "element.setAttribute(item[0], str(self.%s))"%(item[1])
[0b12abb5]466            inputs.appendChild(element)   
[26f3dd5]467       
468        for item in list_of_state_attributes:
469            element = newdoc.createElement(item[0])
470            exec "element.setAttribute(item[0], str(self.%s))"%(item[1])
471            inputs.appendChild(element)
[11a7e11]472           
473        for item in list_of_model_attributes:
474            element = newdoc.createElement(item[0])
475            exec "list = self.%s"%item[1]
[e9b12eaf]476            for value in list:
[0b12abb5]477                exec "element.appendChild(newdoc.createTextNode(str(%s)))"%value
[11a7e11]478            inputs.appendChild(element)
479           
[61cada5]480        for item in list_of_state_parameters:
481            element = newdoc.createElement(item[0])
482            exec "self._toXML_helper(list=self.%s, element=element, newdoc=newdoc)"%item[1]                       
483            inputs.appendChild(element)
484       
485        # Save the file
486        if doc is None:
487            fd = open(file, 'w')
488            fd.write(newdoc.toprettyxml())
489            fd.close()
490            return None
491        else:
492            return newdoc.toprettyxml()
493       
494    def _fromXML_helper(self, node, list):
495        """
[5062bbf]496        Helper function to write state to xml
[61cada5]497        """
498        for item in node:
[0b12abb5]499            try:
500                name = item.get('name')
501            except:
502                name = None
503            try:
504                value = item.get('value')
505            except:
506                value = None
507            try:
[3ad91de]508                selected_to_fit = (item.get('selected_to_fit') == "True")
[0b12abb5]509            except:
510                selected_to_fit = None
511            try:
[3ad91de]512                error_displayed = (item.get('error_displayed') == "True")
[0b12abb5]513            except:
514                error_displayed = None
515            try: 
516                error_value = item.get('error_value')
517            except:
518                error_value = None
519            try:
[3ad91de]520                minimum_displayed = (item.get('minimum_displayed')== "True")
[0b12abb5]521            except:
522                minimum_displayed = None
523            try:
524                minimum_value = item.get('minimum_value')
525            except:
526                minimum_value = None
527            try:
[3ad91de]528                maximum_displayed = (item.get('maximum_displayed') == "True")
[0b12abb5]529            except:
530                maximum_displayed = None
531            try:
532                maximum_value = item.get('maximum_value')
533            except:
534                maximum_value = None
535            try:
536                unit = item.get('unit')
537            except:
538                unit = None
[61cada5]539            list.append([selected_to_fit, name, value, "+/-",[error_displayed, error_value],
540                         [minimum_displayed,minimum_value],[maximum_displayed,maximum_value], unit])
[cfc0913]541       
[61cada5]542    def fromXML(self, file=None, node=None):
543        """
[5062bbf]544        Load fitting state from a file
545       
546        :param file: .fitv file
547        :param node: node of a XML document to read from
548       
[61cada5]549        """
550        if file is not None:
[11a7e11]551            msg = "PageState no longer supports non-CanSAS"
552            msg += " format for fitting files"
553            raise RuntimeError, msg
[61cada5]554           
[11a7e11]555        if node.get('version')and node.get('version') == '1.0':
[61cada5]556           
557            # Get file name
558            entry = get_content('ns:filename', node)
559            if entry is not None:
560                self.file = entry.text.strip()
[11a7e11]561               
562            # Get time stamp
563            entry = get_content('ns:timestamp', node)
564            if entry is not None and entry.get('epoch'):
565                try:
566                    self.timestamp = float(entry.get('epoch'))
567                except:
568                    msg = "PageState.fromXML: Could not"
569                    msg += " read timestamp\n %s" % sys.exc_value
570                    logging.error(msg)
571           
[61cada5]572            # Parse fitting attributes
573            entry = get_content('ns:Attributes', node)
[0b12abb5]574            for item in list_of_data_attributes:
575                node = get_content('ns:%s'%item[0], entry)
576                try:
577                    exec "self.%s = parse_entry_helper(node, item)"%item[0]
578                   
579                except:
580                    raise
581           
[61cada5]582            if entry is not None:
[0b12abb5]583               
[61cada5]584                for item in list_of_state_attributes:
[0b12abb5]585                    node = get_content('ns:%s'%item[0], entry)
586                    try:
587                        exec "self.%s = parse_entry_helper(node, item)"%str(item[0])
588                    except:
589                        raise
590                   
[11a7e11]591                for item in list_of_model_attributes:
592                    node = get_content("ns:%s"%item[0], entry)
593                    list = []
594                    for value in node:
595                        try:
596                            list.append(float(value)) 
597                        except:
598                            list.append(None)
599                    exec "self.%s = list"%item[1]
[0b12abb5]600               
[61cada5]601                for item in list_of_state_parameters:
[11a7e11]602                    node = get_content("ns:%s"%item[0], entry)
[0b12abb5]603                    exec "self._fromXML_helper(node=node, list=self.%s)"%item[1]
604                   
[61cada5]605
606class Reader(CansasReader):
607    """
[5062bbf]608    Class to load a .fitv fitting file
[61cada5]609    """
610    ## File type
611    type_name = "Fitting"
612   
613    ## Wildcards
[b35d3d1]614    type = ["Fitting files (*.fitv)|*.fitv"
615            "SANSView file (*.svs)|*.svs"]
[61cada5]616    ## List of allowed extensions
[b35d3d1]617    ext=['.fitv', '.FITV', '.svs', 'SVS']   
[61cada5]618   
619    def __init__(self, call_back=None, cansas=True):
[df7ed14]620        CansasReader.__init__(self)
[61cada5]621        """
[5062bbf]622        Initialize the call-back method to be called
623        after we load a file
624       
625        :param call_back: call-back method
626        :param cansas:  True = files will be written/read in CanSAS format
627                        False = write CanSAS format
[61cada5]628           
629        """
630        ## Call back method to be executed after a file is read
631        self.call_back = call_back
632        ## CanSAS format flag
633        self.cansas = cansas
[75fbd17]634        self.state = None
635    def get_state(self):
636        return self.state
[61cada5]637       
638    def read(self, path):
639        """
[5062bbf]640        Load a new P(r) inversion state from file
641       
642        :param path: file path
643       
[61cada5]644        """
[e9b12eaf]645        if self.cansas == True:
[61cada5]646            return self._read_cansas(path)
[e9b12eaf]647     
648    def _data2d_to_xml_doc(self, datainfo):
[61cada5]649        """
[5062bbf]650        Create an XML document to contain the content of a Data2D
651       
652        :param datainfo: Data2D object
653       
[61cada5]654        """
655        if not issubclass(datainfo.__class__, Data2D):
656            raise RuntimeError, "The cansas writer expects a Data2D instance"
657       
658        doc = xml.dom.minidom.Document()
659        main_node = doc.createElement("SASroot")
660        main_node.setAttribute("version", self.version)
[df7ed14]661        main_node.setAttribute("xmlns", "cansas1d/%s" % self.version)
662        main_node.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
663        main_node.setAttribute("xsi:schemaLocation", "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version)
664       
[61cada5]665        doc.appendChild(main_node)
666       
667        entry_node = doc.createElement("SASentry")
668        main_node.appendChild(entry_node)
[df7ed14]669       
[61cada5]670        write_node(doc, entry_node, "Title", datainfo.title)
[df7ed14]671        if datainfo is not None:
672            write_node(doc, entry_node, "data_class", datainfo.__class__.__name__)
[61cada5]673        for item in datainfo.run:
674            runname = {}
675            if datainfo.run_name.has_key(item) and len(str(datainfo.run_name[item]))>1:
676                runname = {'name': datainfo.run_name[item] }
677            write_node(doc, entry_node, "Run", item, runname)
678        # Data info
[df7ed14]679        new_node = doc.createElement("SASdata")
680        entry_node.appendChild(new_node)
[e9b12eaf]681        for item in list_of_data_2d_attr:
682            element = doc.createElement(item[0])
683            exec "element.setAttribute(item[0], str(datainfo.%s))"%(item[1])
[df7ed14]684            new_node.appendChild(element)
685           
[e9b12eaf]686        for item in list_of_data2d_values:
[df7ed14]687            root_node = doc.createElement(item[0])
688            new_node.appendChild(root_node)
689           
[35b556d]690            exec "temp_list = datainfo.%s"%item[1]
[df7ed14]691
[35b556d]692            if temp_list is None or len(temp_list)== 0:
[df7ed14]693                element = doc.createElement(item[0])
[35b556d]694                exec "element.appendChild(doc.createTextNode(str(%s)))"%temp_list
[df7ed14]695                root_node.appendChild(element)
[35b556d]696            else:
697                for value in temp_list:
[df7ed14]698                    element = doc.createElement(item[0])
699                    exec "element.setAttribute(item[0], str(%s))"%value
700                    root_node.appendChild(element)
701       
[61cada5]702        # Sample info
703        sample = doc.createElement("SASsample")
704        if datainfo.sample.name is not None:
705            sample.setAttribute("name", str(datainfo.sample.name))
706        entry_node.appendChild(sample)
707        write_node(doc, sample, "ID", str(datainfo.sample.ID))
708        write_node(doc, sample, "thickness", datainfo.sample.thickness, {"unit":datainfo.sample.thickness_unit})
709        write_node(doc, sample, "transmission", datainfo.sample.transmission)
710        write_node(doc, sample, "temperature", datainfo.sample.temperature, {"unit":datainfo.sample.temperature_unit})
711       
712        for item in datainfo.sample.details:
713            write_node(doc, sample, "details", item)
714       
715        pos = doc.createElement("position")
716        written = write_node(doc, pos, "x", datainfo.sample.position.x, {"unit":datainfo.sample.position_unit})
717        written = written | write_node(doc, pos, "y", datainfo.sample.position.y, {"unit":datainfo.sample.position_unit})
718        written = written | write_node(doc, pos, "z", datainfo.sample.position.z, {"unit":datainfo.sample.position_unit})
719        if written == True:
720            sample.appendChild(pos)
721       
722        ori = doc.createElement("orientation")
723        written = write_node(doc, ori, "roll",  datainfo.sample.orientation.x, {"unit":datainfo.sample.orientation_unit})
724        written = written | write_node(doc, ori, "pitch", datainfo.sample.orientation.y, {"unit":datainfo.sample.orientation_unit})
725        written = written | write_node(doc, ori, "yaw",   datainfo.sample.orientation.z, {"unit":datainfo.sample.orientation_unit})
726        if written == True:
727            sample.appendChild(ori)
728       
729        # Instrument info
730        instr = doc.createElement("SASinstrument")
731        entry_node.appendChild(instr)
732       
733        write_node(doc, instr, "name", datainfo.instrument)
734       
735        #   Source
736        source = doc.createElement("SASsource")
737        if datainfo.source.name is not None:
738            source.setAttribute("name", str(datainfo.source.name))
739        instr.appendChild(source)
740       
741        write_node(doc, source, "radiation", datainfo.source.radiation)
742        write_node(doc, source, "beam_shape", datainfo.source.beam_shape)
743        size = doc.createElement("beam_size")
744        if datainfo.source.beam_size_name is not None:
745            size.setAttribute("name", str(datainfo.source.beam_size_name))
746        written = write_node(doc, size, "x", datainfo.source.beam_size.x, {"unit":datainfo.source.beam_size_unit})
747        written = written | write_node(doc, size, "y", datainfo.source.beam_size.y, {"unit":datainfo.source.beam_size_unit})
748        written = written | write_node(doc, size, "z", datainfo.source.beam_size.z, {"unit":datainfo.source.beam_size_unit})
749        if written == True:
750            source.appendChild(size)
751           
752        write_node(doc, source, "wavelength", datainfo.source.wavelength, {"unit":datainfo.source.wavelength_unit})
753        write_node(doc, source, "wavelength_min", datainfo.source.wavelength_min, {"unit":datainfo.source.wavelength_min_unit})
754        write_node(doc, source, "wavelength_max", datainfo.source.wavelength_max, {"unit":datainfo.source.wavelength_max_unit})
755        write_node(doc, source, "wavelength_spread", datainfo.source.wavelength_spread, {"unit":datainfo.source.wavelength_spread_unit})
756       
757        #   Collimation
758        for item in datainfo.collimation:
759            coll = doc.createElement("SAScollimation")
760            if item.name is not None:
761                coll.setAttribute("name", str(item.name))
762            instr.appendChild(coll)
763           
764            write_node(doc, coll, "length", item.length, {"unit":item.length_unit})
765           
766            for apert in item.aperture:
767                ap = doc.createElement("aperture")
768                if apert.name is not None:
769                    ap.setAttribute("name", str(apert.name))
770                if apert.type is not None:
771                    ap.setAttribute("type", str(apert.type))
772                coll.appendChild(ap)
773               
774                write_node(doc, ap, "distance", apert.distance, {"unit":apert.distance_unit})
775               
776                size = doc.createElement("size")
777                if apert.size_name is not None:
778                    size.setAttribute("name", str(apert.size_name))
779                written = write_node(doc, size, "x", apert.size.x, {"unit":apert.size_unit})
780                written = written | write_node(doc, size, "y", apert.size.y, {"unit":apert.size_unit})
781                written = written | write_node(doc, size, "z", apert.size.z, {"unit":apert.size_unit})
782                if written == True:
783                    ap.appendChild(size)
784
785        #   Detectors
786        for item in datainfo.detector:
787            det = doc.createElement("SASdetector")
788            written = write_node(doc, det, "name", item.name)
789            written = written | write_node(doc, det, "SDD", item.distance, {"unit":item.distance_unit})
790            written = written | write_node(doc, det, "slit_length", item.slit_length, {"unit":item.slit_length_unit})
791            if written == True:
792                instr.appendChild(det)
793           
794            off = doc.createElement("offset")
795            written = write_node(doc, off, "x", item.offset.x, {"unit":item.offset_unit})
796            written = written | write_node(doc, off, "y", item.offset.y, {"unit":item.offset_unit})
797            written = written | write_node(doc, off, "z", item.offset.z, {"unit":item.offset_unit})
798            if written == True:
799                det.appendChild(off)
800           
801            center = doc.createElement("beam_center")
802            written = write_node(doc, center, "x", item.beam_center.x, {"unit":item.beam_center_unit})
803            written = written | write_node(doc, center, "y", item.beam_center.y, {"unit":item.beam_center_unit})
804            written = written | write_node(doc, center, "z", item.beam_center.z, {"unit":item.beam_center_unit})
805            if written == True:
806                det.appendChild(center)
807               
808            pix = doc.createElement("pixel_size")
809            written = write_node(doc, pix, "x", item.pixel_size.x, {"unit":item.pixel_size_unit})
810            written = written | write_node(doc, pix, "y", item.pixel_size.y, {"unit":item.pixel_size_unit})
811            written = written | write_node(doc, pix, "z", item.pixel_size.z, {"unit":item.pixel_size_unit})
812            if written == True:
813                det.appendChild(pix)
814               
815            ori = doc.createElement("orientation")
816            written = write_node(doc, ori, "roll",  item.orientation.x, {"unit":item.orientation_unit})
817            written = written | write_node(doc, ori, "pitch", item.orientation.y, {"unit":item.orientation_unit})
818            written = written | write_node(doc, ori, "yaw",   item.orientation.z, {"unit":item.orientation_unit})
819            if written == True:
820                det.appendChild(ori)
821               
822        # Processes info
823        for item in datainfo.process:
824            node = doc.createElement("SASprocess")
825            entry_node.appendChild(node)
826
827            write_node(doc, node, "name", item.name)
828            write_node(doc, node, "date", item.date)
829            write_node(doc, node, "description", item.description)
830            for term in item.term:
831                value = term['value']
832                del term['value']
833                write_node(doc, node, "term", value, term)
834            for note in item.notes:
835                write_node(doc, node, "SASprocessnote", note)
836        # Return the document, and the SASentry node associated with
837        # the data we just wrote
838        return doc, entry_node
[e9b12eaf]839   
[61cada5]840    def _parse_state(self, entry):
841        """
[5062bbf]842        Read a fit result from an XML node
843       
844        :param entry: XML node to read from
845       
846        :return: PageState object
[61cada5]847        """
848        # Create an empty state
[b35d3d1]849        state = None   
[61cada5]850        # Locate the P(r) node
851        try:
852            nodes = entry.xpath('ns:%s' % FITTING_NODE_NAME, namespaces={'ns': CANSAS_NS})
[b35d3d1]853            if nodes !=[]:
854                # Create an empty state
855                state =  PageState()
856                state.fromXML(node=nodes[0])
[61cada5]857        except:
858            logging.info("XML document does not contain fitting information.\n %s" % sys.exc_value)
859           
860        return state
861   
[0b12abb5]862   
[df7ed14]863                   
864    def _parse_entry(self, dom):
[e9b12eaf]865        """
[5062bbf]866        Parse a SASentry
867       
868        :param node: SASentry node
869       
[df7ed14]870        :return: Data1D/Data2D object
[5062bbf]871       
[e9b12eaf]872        """
[df7ed14]873        node = dom.xpath('ns:data_class', namespaces={'ns': CANSAS_NS})
874        if not node or node[0].text.lstrip().rstrip() != "Data2D":
875            return CansasReader._parse_entry(self, dom)
876       
877        #Parse 2D
[e9b12eaf]878        data_info = Data2D()
879       
880        # Look up title     
881        self._store_content('ns:Title', dom, 'title', data_info)
882       
883        # Look up run number   
884        nodes = dom.xpath('ns:Run', namespaces={'ns': CANSAS_NS})
885        for item in nodes:   
886            if item.text is not None:
887                value = item.text.strip()
888                if len(value) > 0:
889                    data_info.run.append(value)
890                    if item.get('name') is not None:
891                        data_info.run_name[value] = item.get('name')
892                           
893        # Look up instrument name             
894        self._store_content('ns:SASinstrument/ns:name', dom, 'instrument', data_info)
895
896        # Notes
897        note_list = dom.xpath('ns:SASnote', namespaces={'ns': CANSAS_NS})
898        for note in note_list:
899            try:
900                if note.text is not None:
901                    note_value = note.text.strip()
902                    if len(note_value) > 0:
903                        data_info.notes.append(note_value)
904            except:
905                err_mess = "cansas_reader.read: error processing entry notes\n  %s" % sys.exc_value
906                self.errors.append(err_mess)
907                logging.error(err_mess)
908       
909        # Sample info ###################
910        entry = get_content('ns:SASsample', dom)
911        if entry is not None:
912            data_info.sample.name = entry.get('name')
913           
914        self._store_content('ns:SASsample/ns:ID', 
915                     dom, 'ID', data_info.sample)                   
916        self._store_float('ns:SASsample/ns:thickness', 
917                     dom, 'thickness', data_info.sample)
918        self._store_float('ns:SASsample/ns:transmission', 
919                     dom, 'transmission', data_info.sample)
920        self._store_float('ns:SASsample/ns:temperature', 
921                     dom, 'temperature', data_info.sample)
922       
923        nodes = dom.xpath('ns:SASsample/ns:details', namespaces={'ns': CANSAS_NS})
924        for item in nodes:
925            try:
926                if item.text is not None:
927                    detail_value = item.text.strip()
928                    if len(detail_value) > 0:
929                        data_info.sample.details.append(detail_value)
930            except:
931                err_mess = "cansas_reader.read: error processing sample details\n  %s" % sys.exc_value
932                self.errors.append(err_mess)
933                logging.error(err_mess)
934       
935        # Position (as a vector)
936        self._store_float('ns:SASsample/ns:position/ns:x', 
937                     dom, 'position.x', data_info.sample)         
938        self._store_float('ns:SASsample/ns:position/ns:y', 
939                     dom, 'position.y', data_info.sample)         
940        self._store_float('ns:SASsample/ns:position/ns:z', 
941                     dom, 'position.z', data_info.sample)         
942       
943        # Orientation (as a vector)
944        self._store_float('ns:SASsample/ns:orientation/ns:roll', 
945                     dom, 'orientation.x', data_info.sample)         
946        self._store_float('ns:SASsample/ns:orientation/ns:pitch', 
947                     dom, 'orientation.y', data_info.sample)         
948        self._store_float('ns:SASsample/ns:orientation/ns:yaw', 
949                     dom, 'orientation.z', data_info.sample)         
950       
951        # Source info ###################
952        entry = get_content('ns:SASinstrument/ns:SASsource', dom)
953        if entry is not None:
954            data_info.source.name = entry.get('name')
955       
956        self._store_content('ns:SASinstrument/ns:SASsource/ns:radiation', 
957                     dom, 'radiation', data_info.source)                   
958        self._store_content('ns:SASinstrument/ns:SASsource/ns:beam_shape', 
959                     dom, 'beam_shape', data_info.source)                   
960        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength', 
961                     dom, 'wavelength', data_info.source)         
962        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_min', 
963                     dom, 'wavelength_min', data_info.source)         
964        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_max', 
965                     dom, 'wavelength_max', data_info.source)         
966        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_spread', 
967                     dom, 'wavelength_spread', data_info.source)   
968       
969        # Beam size (as a vector)   
970        entry = get_content('ns:SASinstrument/ns:SASsource/ns:beam_size', dom)
971        if entry is not None:
972            data_info.source.beam_size_name = entry.get('name')
973           
974        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:x', 
975                     dom, 'beam_size.x', data_info.source)   
976        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:y', 
977                     dom, 'beam_size.y', data_info.source)   
978        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:z', 
979                     dom, 'beam_size.z', data_info.source)   
980       
981        # Collimation info ###################
982        nodes = dom.xpath('ns:SASinstrument/ns:SAScollimation', namespaces={'ns': CANSAS_NS})
983        for item in nodes:
984            collim = Collimation()
985            if item.get('name') is not None:
986                collim.name = item.get('name')
987            self._store_float('ns:length', item, 'length', collim) 
988           
989            # Look for apertures
990            apert_list = item.xpath('ns:aperture', namespaces={'ns': CANSAS_NS})
991            for apert in apert_list:
992                aperture =  Aperture()
993               
994                # Get the name and type of the aperture
995                aperture.name = apert.get('name')
996                aperture.type = apert.get('type')
997                   
998                self._store_float('ns:distance', apert, 'distance', aperture)   
999               
1000                entry = get_content('ns:size', apert)
1001                if entry is not None:
1002                    aperture.size_name = entry.get('name')
1003               
1004                self._store_float('ns:size/ns:x', apert, 'size.x', aperture)   
1005                self._store_float('ns:size/ns:y', apert, 'size.y', aperture)   
1006                self._store_float('ns:size/ns:z', apert, 'size.z', aperture)
1007               
1008                collim.aperture.append(aperture)
1009               
1010            data_info.collimation.append(collim)
1011       
1012        # Detector info ######################
1013        nodes = dom.xpath('ns:SASinstrument/ns:SASdetector', namespaces={'ns': CANSAS_NS})
1014        for item in nodes:
1015           
1016            detector = Detector()
1017           
1018            self._store_content('ns:name', item, 'name', detector)
1019            self._store_float('ns:SDD', item, 'distance', detector)   
1020           
1021            # Detector offset (as a vector)
1022            self._store_float('ns:offset/ns:x', item, 'offset.x', detector)   
1023            self._store_float('ns:offset/ns:y', item, 'offset.y', detector)   
1024            self._store_float('ns:offset/ns:z', item, 'offset.z', detector)   
1025           
1026            # Detector orientation (as a vector)
1027            self._store_float('ns:orientation/ns:roll',  item, 'orientation.x', detector)   
1028            self._store_float('ns:orientation/ns:pitch', item, 'orientation.y', detector)   
1029            self._store_float('ns:orientation/ns:yaw',   item, 'orientation.z', detector)   
1030           
1031            # Beam center (as a vector)
1032            self._store_float('ns:beam_center/ns:x', item, 'beam_center.x', detector)   
1033            self._store_float('ns:beam_center/ns:y', item, 'beam_center.y', detector)   
1034            self._store_float('ns:beam_center/ns:z', item, 'beam_center.z', detector)   
1035           
1036            # Pixel size (as a vector)
1037            self._store_float('ns:pixel_size/ns:x', item, 'pixel_size.x', detector)   
1038            self._store_float('ns:pixel_size/ns:y', item, 'pixel_size.y', detector)   
1039            self._store_float('ns:pixel_size/ns:z', item, 'pixel_size.z', detector)   
1040           
1041            self._store_float('ns:slit_length', item, 'slit_length', detector)
1042           
1043            data_info.detector.append(detector)   
1044
1045        # Processes info ######################
1046        nodes = dom.xpath('ns:SASprocess', namespaces={'ns': CANSAS_NS})
1047        for item in nodes:
1048            process = Process()
1049            self._store_content('ns:name', item, 'name', process)
1050            self._store_content('ns:date', item, 'date', process)
1051            self._store_content('ns:description', item, 'description', process)
1052           
1053            term_list = item.xpath('ns:term', namespaces={'ns': CANSAS_NS})
1054            for term in term_list:
1055                try:
1056                    term_attr = {}
1057                    for attr in term.keys():
1058                        term_attr[attr] = term.get(attr).strip()
1059                    if term.text is not None:
1060                        term_attr['value'] = term.text.strip()
1061                        process.term.append(term_attr)
1062                except:
1063                    err_mess = "cansas_reader.read: error processing process term\n  %s" % sys.exc_value
1064                    self.errors.append(err_mess)
1065                    logging.error(err_mess)
1066           
1067            note_list = item.xpath('ns:SASprocessnote', namespaces={'ns': CANSAS_NS})
1068            for note in note_list:
1069                if note.text is not None:
1070                    process.notes.append(note.text.strip())
1071           
1072            data_info.process.append(process)
1073           
1074           
1075        # Data info ######################
1076        nodes = dom.xpath('ns:SASdata', namespaces={'ns': CANSAS_NS})
1077        if len(nodes)>1:
1078            raise RuntimeError, "CanSAS reader is not compatible with multiple SASdata entries"
[df7ed14]1079       
1080        for entry in nodes:
1081            for item in list_of_data_2d_attr:
1082                #get node
1083                node = get_content('ns:%s'%item[0], entry)
[0b12abb5]1084                exec "data_info.%s = parse_entry_helper(node, item)"%(item[1])
[e9b12eaf]1085                   
[df7ed14]1086            for item in list_of_data2d_values:
1087                field = get_content('ns:%s'%item[0], entry)
1088                list = []
1089                if field is not None:
[0b12abb5]1090                    list = [parse_entry_helper(node, item) for node in field]
[df7ed14]1091                exec "data_info.%s = numpy.array(list)"%item[0]
[e9b12eaf]1092       
1093        return data_info
1094
[61cada5]1095    def _read_cansas(self, path):
1096        """
[5062bbf]1097        Load data and P(r) information from a CanSAS XML file.
1098       
1099        :param path: file path
1100       
1101        :return: Data1D object if a single SASentry was found,
1102                    or a list of Data1D objects if multiple entries were found,
1103                    or None of nothing was found
1104                   
1105        :raise RuntimeError: when the file can't be opened
1106        :raise ValueError: when the length of the data vectors are inconsistent
1107       
[61cada5]1108        """
1109        output = []
[b63dc6e]1110        basename  = os.path.basename(path)
1111        root, extension = os.path.splitext(basename)
1112        ext = extension.lower()
[61cada5]1113        try:
1114            if os.path.isfile(path):
[b63dc6e]1115               
[61cada5]1116                #TODO: eventually remove the check for .xml once
1117                # the P(r) writer/reader is truly complete.
[b63dc6e]1118                if  ext in self.ext or \
1119                    ext == '.xml':
[61cada5]1120                   
1121                    tree = etree.parse(path, parser=etree.ETCompatXMLParser())
1122                    # Check the format version number
1123                    # Specifying the namespace will take care of the file format version
1124                    root = tree.getroot()
[df7ed14]1125                    entry_list = root.xpath('ns:SASentry', namespaces={'ns': CANSAS_NS})
[b35d3d1]1126                    for entry in entry_list:   
[e9b12eaf]1127                        try:
1128                            sas_entry = self._parse_entry(entry)
1129                        except:
[df7ed14]1130                            raise
[61cada5]1131                        fitstate = self._parse_state(entry)
[b35d3d1]1132                       
1133                        #state could be None when .svs file is loaded
1134                        #in this case, skip appending to output
1135                        if fitstate != None:
1136                            sas_entry.meta_data['fitstate'] = fitstate
1137                            sas_entry.filename = fitstate.file
1138                            output.append(sas_entry)
[61cada5]1139            else:
[b63dc6e]1140                self.call_back(format=ext)
[61cada5]1141                raise RuntimeError, "%s is not a file" % path
[b35d3d1]1142
[61cada5]1143            # Return output consistent with the loader's api
1144            if len(output)==0:
[b63dc6e]1145                self.call_back(state=None, datainfo=None,format=ext)
[61cada5]1146                return None
1147            else:
[b35d3d1]1148                for ind in range(len(output)):
1149                    # Call back to post the new state
1150                    state = output[ind].meta_data['fitstate']
1151                    t = time.localtime(state.timestamp)
1152                    time_str = time.strftime("%b %d %H:%M", t)
1153                    # Check that no time stamp is already appended
1154                    max_char = state.file.find("[")
1155                    if max_char < 0:
1156                        max_char = len(state.file)
[ef16f59]1157                    original_fname = state.file[0:max_char]
1158                    state.file = original_fname +' [' + time_str + ']'
[b35d3d1]1159                   
1160                       
1161                    if state is not None and state.is_data is not None:
1162                        exec 'output[%d].is_data = state.is_data'% ind
1163                     
1164                    output[ind].filename = state.file
1165                    state.data = output[ind]
1166                    state.data.name = output[ind].filename #state.data_name
1167                    state.data.id = state.data_id
1168                    if state.is_data is not None:
1169                        state.data.is_data = state.is_data
[ef16f59]1170                    if output[ind].run_name is not None and len(output[ind].run_name) != 0 :
1171                        name = output[ind].run_name
1172                    else: 
1173                        name=original_fname
1174                    state.data.group_id = name
1175                    #store state in fitting
[90a7bbd]1176                    self.call_back(state=state, datainfo=output[ind],format=ext)
[75fbd17]1177                    self.state= state
[ef16f59]1178                return output
[b35d3d1]1179             
[61cada5]1180        except:
[75fbd17]1181            #self.call_back(format=ext)
1182            self.state= state
[61cada5]1183            raise
1184           
1185    def write(self, filename, datainfo=None, fitstate=None):
1186        """
[b35d3d1]1187        Write the content of a Data1D as a CanSAS XML file only for standalone
[5062bbf]1188       
1189        :param filename: name of the file to write
1190        :param datainfo: Data1D object
1191        :param fitstate: PageState object
1192       
[61cada5]1193        """
1194        # Sanity check
1195        if self.cansas == True:
1196           
1197            # Add fitting information to the XML document
[ef16f59]1198            doc = self.write_toXML(datainfo, fitstate)
[61cada5]1199            # Write the XML document
1200            fd = open(filename, 'w')
1201            fd.write(doc.toprettyxml())
1202            fd.close()
1203        else:
1204            fitstate.toXML(file=filename)
1205       
[b35d3d1]1206    def write_toXML(self, datainfo=None, state=None):
1207        """
1208        Write toXML, a helper for write() , could be used by guimanager._on_save()
1209       
1210        : return: xml doc
1211        """
[3c44c66]1212
[b35d3d1]1213        if state.data is None:
1214            data = DataLoader.data_info.Data1D(x=[], y=[]) 
1215        else: 
1216            #make sure title and data run is filled up.
[028a0e8]1217            if state.data.title == None or state.data.title=='': state.data.title = state.data.name
1218            if state.data.run_name == None or state.data.run_name=={}: 
1219                state.data.run = [str(state.data.name)]
1220                state.data.run_name[0] = state.data.name
[b35d3d1]1221   
1222            if issubclass(state.data.__class__, DataLoader.data_info.Data1D):
[028a0e8]1223
[b35d3d1]1224                data = state.data
1225                doc, sasentry = self._to_xml_doc(data)
1226            else:
1227                data = state.data
1228                doc, sasentry = self._data2d_to_xml_doc(data)
1229           
1230
1231        if state is not None:
1232            state.toXML(doc=doc, file=data.name, entry_node=sasentry)
1233           
1234        return doc
[5062bbf]1235 
[3c44c66]1236if __name__ == "__main__":
1237    state = PageState(parent=None)
1238    #state.toXML()
1239    """
[5062bbf]1240   
[3c44c66]1241    file = open("test_state", "w")
1242    pickle.dump(state, file)
1243    print pickle.dumps(state)
1244    state.data_name = "hello---->"
1245    pickle.dump(state, file)
1246    file = open("test_state", "r")
1247    new_state= pickle.load(file)
1248    print "new state", new_state
1249    new_state= pickle.load(file)
1250    print "new state", new_state
1251    #print "state", state
1252    """
1253    import bsddb
1254    import pickle
1255    db= bsddb.btopen('file_state.db', 'c')
1256    val = (pickle.dumps(state), "hello", "hi")
1257    db['state1']= pickle.dumps(val)
1258    print pickle.loads(db['state1'])
1259    state.data_name = "hello---->22"
1260    db['state2']= pickle.dumps(state)
1261    state.data_name = "hello---->2"
1262    db['state3']= pickle.dumps(state)
1263    del db['state3']
1264    state.data_name = "hello---->3"
1265    db['state4']= pickle.dumps(state)
1266    new_state = pickle.loads(db['state1'])
1267    #print db.last()
1268    db.set_location('state2')
1269    state.data_name = "hello---->5"
1270    db['aastate5']= pickle.dumps(state)
1271    db.keys().sort()
1272    print pickle.loads(db['state2'])
1273 
1274    db.close()
Note: See TracBrowser for help on using the repository browser.