source: sasview/src/sans/perspectives/fitting/pagestate.py @ 77cfcf0

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 77cfcf0 was eddb6ec, checked in by Tobias Richter <tobias.richter@…>, 11 years ago

refs #57 Clean up warnings in Python code

  • Property mode set to 100644
File size: 72.0 KB
RevLine 
[f32d144]1"""
2    Class that holds a fit page state
3"""
[5062bbf]4################################################################################
5#This software was developed by the University of Tennessee as part of the
6#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
[f32d144]7#project funded by the US National Science Foundation.
[5062bbf]8#
9#See the license text in license.txt
10#
11#copyright 2009, University of Tennessee
12################################################################################
[11a7e11]13import time
14import os
15import sys
[6f023e8]16import copy
[11a7e11]17import logging
[df7ed14]18import numpy
[eddb6ec]19import string
[c77d859]20
[35b556d]21import xml.dom.minidom
[11a7e11]22from lxml import etree
23
[c21e87b]24import sans.dataloader
25from sans.dataloader.readers.cansas_reader import Reader as CansasReader
26from sans.dataloader.readers.cansas_reader import get_content, write_node
[724897ad]27from sans.dataloader.data_info import Data2D
28from sans.dataloader.data_info import Collimation
29from sans.dataloader.data_info import Detector
30from sans.dataloader.data_info import Process
31from sans.dataloader.data_info import Aperture
[11a7e11]32#Information to read/write state as xml
[61cada5]33FITTING_NODE_NAME = 'fitting_plug_in'
34CANSAS_NS = "cansas1d/1.0"
35
[26f3dd5]36list_of_data_attributes = [["is_data", "is_data", "bool"],
[61cada5]37                      ["group_id", "data_group_id", "string"],
38                      ["data_name", "data_name", "string"],
39                      ["data_id", "data_id", "string"],
40                      ["name", "name", "string"],
[26f3dd5]41                      ["data_name", "data_name", "string"]]
[e3d1423]42list_of_state_attributes = [["engine_type", "engine_type", "string"],
43                       ["qmin", "qmin", "float"],
[61cada5]44                      ["qmax", "qmax", "float"],
45                      ["npts", "npts", "float"],
[ea5fa58]46                      #["shape_rbutton", "shape_rbutton", "bool"],
47                      #["shape_indep_rbutton", "shape_indep_rbutton", "bool"],
48                      #["plugin_rbutton", "plugin_rbutton", "bool"],
49                      #["struct_rbutton", "struct_rbutton", "bool"],
50                      ["categorycombobox", "categorycombobox", "string"],
[d40038e]51                      ["formfactorcombobox", "formfactorcombobox", "string"],
52                      ["structurecombobox", "structurecombobox", "string"],
[c0ff8cc]53                      ["multi_factor","multi_factor","float"],
[318b5bbb]54                      ["magnetic_on","magnetic_on", "bool"],
[26f3dd5]55                      ["enable_smearer","enable_smearer","bool"],
56                      ["disable_smearer","disable_smearer","bool"],
57                      ["pinhole_smearer","pinhole_smearer","bool"],
58                      ["slit_smearer","slit_smearer","bool"],
59                      ["enable_disp","enable_disp","bool"],
60                      ["disable_disp","disable_disp","bool"],
[55bb249c]61                      ["dI_noweight","dI_noweight","bool"],
62                      ["dI_didata","dI_didata","bool"],
63                      ["dI_sqrdata","dI_sqrdata","bool"],
64                      ["dI_idata","dI_idata","bool"],
[26f3dd5]65                      ["enable2D","enable2D","bool"],
66                      ["cb1","cb1","bool"],
[5cc7001]67                      ["tcChi","tcChi","float"],
[55bb249c]68                      ["smearer", "smearer", "float"],
69                      ["smear_type","smear_type", "string"],
70                      ["dq_l", "dq_l", "string"],
[db8fd5b]71                      ["dq_r","dq_r", "string"],
72                      ["dx_max", "dx_max", "float"],
73                      ["dx_min","dx_min", "float"],
74                      ["dxl", "dxl", "float"],
75                      ["dxw","dxw", "float"]]
[5cc7001]76
[11a7e11]77list_of_model_attributes = [["values", "values"],
78                            ["weights", "weights"]]
79
[f32d144]80list_of_obj_dic = [["disp_obj_dict", "_disp_obj_dict", "string"]]
[2296316]81
[f32d144]82list_of_state_parameters = [["parameters", "parameters"],
83                            ["str_parameters", "str_parameters"],
[61cada5]84                            ["orientation_parameters", "orientation_params"],
85                            ["dispersity_parameters", "orientation_params_disp"],
[f32d144]86                            ["fixed_param", "fixed_param"],
87                            ["fittable_param", "fittable_param"]]
88list_of_data_2d_attr = [["xmin", "xmin", "float"],
89                        ["xmax", "xmax", "float"],
90                        ["ymin", "ymin", "float"],
91                        ["ymax", "ymax", "float"],
92                        ["_xaxis", "_xaxis", "string"],
[df7ed14]93                        ["_xunit", "_xunit", "string"],
[f32d144]94                        ["_yaxis", "_yaxis", "string"],
95                        ["_yunit", "_yunit", "string"],
96                        ["_zaxis", "_zaxis", "string"],
97                        ["_zunit", "_zunit", "string"]]
98list_of_data2d_values = [["qx_data", "qx_data", "float"],
99                         ["qy_data", "qy_data", "float"],
100                         ["dqx_data", "dqx_data", "float"],
101                         ["dqy_data", "dqy_data", "float"],
102                         ["data", "data", "float"],
103                         ["q_data", "q_data", "float"],
104                         ["err_data", "err_data", "float"],
105                         ["mask", "mask", "bool"]]
[61cada5]106
[f32d144]107
108def parse_entry_helper(node, item):
[0b12abb5]109    """
110    Create a numpy list from value extrated from the node
111   
112    :param node: node from each the value is stored
113    :param item: list name of three strings.the two first are name of data
[f32d144]114        attribute and the third one is the type of the value of that
[0b12abb5]115        attribute. type can be string, float, bool, etc.
116   
117    : return: numpy array
118    """
119    if node is not None:
120        if item[2] == "string":
121            return str(node.get(item[0]).strip())
122        elif item[2] == "bool":
123            try:
[e3d1423]124                return node.get(item[0]).strip() == "True"
125               
[0b12abb5]126            except:
127                return None
128        else:
129            try:
130                return float(node.get(item[0]))
131            except:
132                return None
133           
134           
[cfc0913]135class PageState(object):
[c77d859]136    """
[5062bbf]137    Contains information to reconstruct a page of the fitpanel.
[c77d859]138    """
[61cada5]139    def __init__(self, parent=None, model=None, data=None):
[f32d144]140        """
[5062bbf]141        Initialize the current state
142       
143        :param model: a selected model within a page
[f32d144]144        :param data:
[5062bbf]145       
[c77d859]146        """
[61cada5]147        self.file = None
[11a7e11]148        #Time of state creation
149        self.timestamp = time.time()
[c77d859]150        ## Data member to store the dispersion object created
151        self._disp_obj_dict = {}
[61cada5]152        #------------------------
[f32d144]153        #Data used for fitting
[c77d859]154        self.data = data
[2296316]155        # model data
156        self.theory_data = None
157        #Is 2D
158        self.is_2D = False
159        self.images = None
160       
[61cada5]161        #save additional information on data that dataloader.reader does not read
162        self.is_data = None
163        self.data_name = ""
[c0ff8cc]164
[61cada5]165        if self.data is not None:
166            self.data_name = self.data.name
167        self.data_id = None
168        if self.data is not None and hasattr(self.data, "id"):
169            self.data_id = self.data.id
170        self.data_group_id = None
171        if self.data is not None and hasattr(self.data, "group_id"):
172            self.data_group_id = self.data.group_id
[0b12abb5]173       
[61cada5]174        ## reset True change the state of exsiting button
175        self.reset = False
176       
[c99a6c5]177        #engine type
178        self.engine_type = None
[c77d859]179        # flag to allow data2D plot
[cfc0913]180        self.enable2D = False
[c77d859]181        # model on which the fit would be performed
182        self.model = model
[93f0a862]183        self.m_name = None
[dce84c0]184        #list of process done to model
185        self.process = []
[f32d144]186        #fit page manager
[c77d859]187        self.manager = None
188        #Store the parent of this panel parent
189        # For this application fitpanel is the parent
[f32d144]190        self.parent = parent
[c77d859]191        # Event_owner is the owner of model event
192        self.event_owner = None
[c9a4377]193        ##page name
[cfc0913]194        self.page_name = ""
[eddb6ec]195        # Contains link between model, all its parameters, and panel organization
[61cada5]196        self.parameters = []
[fb59ed9]197        # String parameter list that can not be fitted
198        self.str_parameters = []
[f32d144]199        # Contains list of parameters that cannot be fitted and reference to
200        #panel objects
[61cada5]201        self.fixed_param = []
[f32d144]202        # Contains list of parameters with dispersity and reference to
203        #panel objects
[61cada5]204        self.fittable_param = []
[60132ef]205        ## orientation parameters
[61cada5]206        self.orientation_params = []
[eddb6ec]207        ## orientation parameters for gaussian dispersity
[61cada5]208        self.orientation_params_disp = []
[3370922]209        ## smearer info
[61cada5]210        self.smearer = None
[7609f1a]211        self.smear_type = None
212        self.dq_l = None
213        self.dq_r = None
[db8fd5b]214        self.dx_max = None
215        self.dx_min = None
216        self.dxl = None
217        self.dxw = None
[eddb6ec]218        #list of dispersion parameters
[f32d144]219        self.disp_list = []
[61cada5]220        if self.model is not None:
[71f0373]221            self.disp_list = self.model.getDispParamList()
[2296316]222
[61cada5]223        self.disp_cb_dict = {}
[2296316]224        self.values = {}
225        self.weights = {}
[dad49a0]226                   
[f32d144]227        #contains link between a model and selected parameters to fit
[61cada5]228        self.param_toFit = []
[a074145]229        ##dictionary of model type and model class
[cfc0913]230        self.model_list_box = None
[a074145]231        ## save the state of the context menu
[61cada5]232        self.saved_states = {}
[240b9966]233        ## save selection of combobox
[3b9e023]234        self.formfactorcombobox = None
[ea5fa58]235        self.categorycombobox = None
[f32d144]236        self.structurecombobox = None
[c0ff8cc]237
[240b9966]238        ## radio box to select type of model
[ea5fa58]239        #self.shape_rbutton = False
240        #self.shape_indep_rbutton = False
241        #self.struct_rbutton = False
242        #self.plugin_rbutton = False
[b787e68c]243        ## the indice of the current selection
244        self.disp_box = 0
[c77d859]245        ## Qrange
[cfc0913]246        ## Q range
[61cada5]247        self.qmin = 0.001
248        self.qmax = 0.1
[0b12abb5]249        #reset data range
250        self.qmax_x = None
251        self.qmin_x = None
252       
[cfc0913]253        self.npts = None
[61cada5]254        self.name = ""
[4523b68]255        self.multi_factor = None
[318b5bbb]256        self.magnetic_on = False
[cfc0913]257        ## enable smearering state
258        self.enable_smearer = False
[fc6ea43]259        self.disable_smearer = True
[7609f1a]260        self.pinhole_smearer = False
[f32d144]261        self.slit_smearer = False
[55bb249c]262        # weighting options
263        self.dI_noweight = False
264        self.dI_didata = True
265        self.dI_sqrdata = False
[f32d144]266        self.dI_idata = False
[cfc0913]267        ## disperity selection
[61cada5]268        self.enable_disp = False
269        self.disable_disp = True
[11a7e11]270       
[cfc0913]271        ## state of selected all check button
272        self.cb1 = False
[0aeabc6]273        ## store value of chisqr
[61cada5]274        self.tcChi = None
[240b9966]275   
[6f023e8]276    def clone(self):
[61cada5]277        """
[5062bbf]278        Create a new copy of the current object
[61cada5]279        """
280        model = None
281        if self.model is not None:
[6f023e8]282            model = self.model.clone()
[bb70474]283            model.name = self.model.name
[61cada5]284        obj = PageState(self.parent, model=model)
285        obj.file = copy.deepcopy(self.file)
[6f023e8]286        obj.data = copy.deepcopy(self.data)
[61cada5]287        if self.data is not None:
288            self.data_name = self.data.name
289        obj.data_name = self.data_name
290        obj.is_data = self.is_data
[dcf29d7]291        obj.model_list_box = copy.deepcopy(self.model_list_box)
[c99a6c5]292        obj.engine_type = copy.deepcopy(self.engine_type)
[240b9966]293       
[ea5fa58]294        obj.categorycombobox = self.categorycombobox
[61cada5]295        obj.formfactorcombobox = self.formfactorcombobox
[f32d144]296        obj.structurecombobox = self.structurecombobox
[240b9966]297       
[ea5fa58]298        #obj.shape_rbutton = self.shape_rbutton
299        #obj.shape_indep_rbutton = self.shape_indep_rbutton
300        #obj.struct_rbutton = self.struct_rbutton
301        #obj.plugin_rbutton = self.plugin_rbutton
[240b9966]302       
[dcf29d7]303        obj.manager = self.manager
304        obj.event_owner = self.event_owner
[71f0373]305        obj.disp_list = copy.deepcopy(self.disp_list)
[fc6ea43]306       
[c477b31]307        obj.enable2D = copy.deepcopy(self.enable2D)
[cfc0913]308        obj.parameters = copy.deepcopy(self.parameters)
[fb59ed9]309        obj.str_parameters = copy.deepcopy(self.str_parameters)
[cfc0913]310        obj.fixed_param = copy.deepcopy(self.fixed_param)
311        obj.fittable_param = copy.deepcopy(self.fittable_param)
[f32d144]312        obj.orientation_params = copy.deepcopy(self.orientation_params)
313        obj.orientation_params_disp = copy.deepcopy(self.orientation_params_disp)
[b787e68c]314        obj.enable_disp = copy.deepcopy(self.enable_disp)
[fc6ea43]315        obj.disable_disp = copy.deepcopy(self.disable_disp)
[0aeabc6]316        obj.tcChi = self.tcChi
317 
[f32d144]318        if len(self._disp_obj_dict) > 0:
319            for k, v in self._disp_obj_dict.iteritems():
320                obj._disp_obj_dict[k] = v
321        if len(self.disp_cb_dict) > 0:
322            for k, v in self.disp_cb_dict.iteritems():
323                obj.disp_cb_dict[k] = v
324        if len(self.values) > 0:
325            for k, v in self.values.iteritems():
[2296316]326                obj.values[k] = v
[f32d144]327        if len(self.weights) > 0:
328            for k, v in self.weights.iteritems():
[2296316]329                obj.weights[k] = v
[b787e68c]330        obj.enable_smearer = copy.deepcopy(self.enable_smearer)
[fc6ea43]331        obj.disable_smearer = copy.deepcopy(self.disable_smearer)
[7609f1a]332        obj.pinhole_smearer = copy.deepcopy(self.pinhole_smearer)
333        obj.slit_smearer = copy.deepcopy(self.slit_smearer)
334        obj.smear_type = copy.deepcopy(self.smear_type)
[55bb249c]335        obj.dI_noweight = copy.deepcopy(self.dI_noweight)
336        obj.dI_didata = copy.deepcopy(self.dI_didata)
337        obj.dI_sqrdata = copy.deepcopy(self.dI_sqrdata)
338        obj.dI_idata = copy.deepcopy(self.dI_idata)
[7609f1a]339        obj.dq_l = copy.deepcopy(self.dq_l)
340        obj.dq_r = copy.deepcopy(self.dq_r)
[db8fd5b]341        obj.dx_max = copy.deepcopy(self.dx_max)
342        obj.dx_min = copy.deepcopy(self.dx_min)
343        obj.dxl = copy.deepcopy(self.dxl)
344        obj.dxw = copy.deepcopy(self.dxw)       
[b787e68c]345        obj.disp_box = copy.deepcopy(self.disp_box)
346        obj.qmin = copy.deepcopy(self.qmin)
347        obj.qmax = copy.deepcopy(self.qmax)
[c0ff8cc]348        obj.multi_factor = self.multi_factor
[318b5bbb]349        obj.magnetic_on = self.magnetic_on
[f32d144]350        obj.npts = copy.deepcopy(self.npts)
[b787e68c]351        obj.cb1 = copy.deepcopy(self.cb1)
[3370922]352        obj.smearer = copy.deepcopy(self.smearer)
353       
[a074145]354        for name, state in self.saved_states.iteritems():
355            copy_name = copy.deepcopy(name)
356            copy_state = state.clone()
[f32d144]357            obj.saved_states[copy_name] = copy_state
[6f023e8]358        return obj
[61cada5]359   
360    def _repr_helper(self, list, rep):
361        """
[5062bbf]362        Helper method to print a state
[61cada5]363        """
364        for item in list:
[f32d144]365            rep += "parameter name: %s \n" % str(item[1])
366            rep += "value: %s\n" % str(item[2])
367            rep += "selected: %s\n" % str(item[0])
368            rep += "error displayed : %s \n" % str(item[4][0])
369            rep += "error value:%s \n" % str(item[4][1])
370            rep += "minimum displayed : %s \n" % str(item[5][0])
371            rep += "minimum value : %s \n" % str(item[5][1])
372            rep += "maximum displayed : %s \n" % str(item[6][0])
373            rep += "maximum value : %s \n" % str(item[6][1])
374            rep += "parameter unit: %s\n\n" % str(item[7])
[240b9966]375        return rep
[c0ff8cc]376   
[61cada5]377    def __repr__(self):
[f32d144]378        """
[5062bbf]379        output string for printing
[11a7e11]380        """
[f32d144]381        rep = "\nState name: %s\n" % self.file
[11a7e11]382        t = time.localtime(self.timestamp)
[deff488]383        time_str = time.strftime("%b %d %Y %H;%M;%S ", t)
[c0ff8cc]384
[f32d144]385        rep += "State created: %s\n" % time_str
386        rep += "State form factor combobox selection: %s\n" % self.formfactorcombobox
387        rep += "State structure factor combobox selection: %s\n" % self.structurecombobox
388        rep += "is data : %s\n" % self.is_data
389        rep += "data's name : %s\n" % self.data_name
390        rep += "data's id : %s\n" % self.data_id
[74dc0a4]391        if self.model != None:
[93f0a862]392            m_name = self.model.__class__.__name__
393            if m_name == 'Model':
394                m_name = self.m_name
[f32d144]395            rep += "model name : %s\n" % m_name
[74dc0a4]396        else:
397            rep += "model name : None\n"
[ea5fa58]398        #rep += "model type (form factor) selected: %s\n" % self.shape_rbutton
[f32d144]399        rep += "multi_factor : %s\n" % str(self.multi_factor)
[318b5bbb]400        rep += "magnetic_on : %s\n"% str(self.magnetic_on)
[ea5fa58]401        rep += "model type (Category) selected: %s\n" % self.categorycombobox
402        #rep += "model type (shape independent) selected: %s\n" % self.shape_indep_rbutton
403        #rep += "model type (structure factor) selected: %s\n" % self.struct_rbutton
404        #rep += "model type (plug-in ) selected: %s\n" % self.plugin_rbutton
[f32d144]405        rep += "data : %s\n" % str(self.data)
406        rep += "Plotting Range: min: %s, max: %s, steps: %s\n" % (str(self.qmin),
407                                                str(self.qmax), str(self.npts))
408        rep += "Dispersion selection : %s\n" % str(self.disp_box)
409        rep += "Smearing enable : %s\n" % str(self.enable_smearer)
410        rep += "Smearing disable : %s\n" % str(self.disable_smearer)
411        rep += "Pinhole smearer enable : %s\n" % str(self.pinhole_smearer)
412        rep += "Slit smearer enable : %s\n" % str(self.slit_smearer)
413        rep += "Dispersity enable : %s\n" % str(self.enable_disp)
414        rep += "Dispersity disable : %s\n" % str(self.disable_disp)
415        rep += "Slit smearer enable: %s\n" % str(self.slit_smearer)
416       
417        rep += "dI_noweight : %s\n" % str(self.dI_noweight)
418        rep += "dI_didata : %s\n" % str(self.dI_didata)
419        rep += "dI_sqrdata : %s\n" % str(self.dI_sqrdata)
420        rep += "dI_idata : %s\n" % str(self.dI_idata)
421       
422        rep += "2D enable : %s\n" % str(self.enable2D)
423        rep += "All parameters checkbox selected: %s\n" % (self.cb1)
424        rep += "Value of Chisqr : %s\n" % str(self.tcChi)
425        rep += "Smear object : %s\n" % str(self.smearer)
426        rep += "Smear type : %s\n" % (self.smear_type)
427        rep += "dq_l  : %s\n" % self.dq_l
428        rep += "dq_r  : %s\n" % self.dq_r
[db8fd5b]429        rep += "dx_max  : %s\n" % str(self.dx_max)
430        rep += "dx_min : %s\n" % str(self.dx_min) 
431        rep += "dxl  : %s\n" % str(self.dxl)
432        rep += "dxw : %s\n" % str(self.dxw)   
[f32d144]433        rep += "model  : %s\n\n" % str(self.model)
[2296316]434        temp_parameters = []
435        temp_fittable_param = []
436        if self.data.__class__.__name__ == "Data2D":
437            self.is_2D = True
438        else:
439            self.is_2D = False
440        if self.data is not None:
441            if not self.is_2D:
442                for item in self.parameters:
443                    if not item in self.orientation_params:
444                        temp_parameters.append(item)
445                for item in self.fittable_param:
446                    if not item in self.orientation_params_disp:
447                        temp_fittable_param.append(item)
448            else:
449                temp_parameters = self.parameters
450                temp_fittable_param = self.fittable_param
451               
[f32d144]452            rep += "number parameters(self.parameters): %s\n" % len(temp_parameters)
453            rep = self._repr_helper(list=temp_parameters, rep=rep)
454            rep += "number str_parameters(self.str_parameters): %s\n" % len(self.str_parameters)
455            rep = self._repr_helper(list=self.str_parameters, rep=rep)
456            rep += "number fittable_param(self.fittable_param): %s\n" % len(temp_fittable_param)
457            rep = self._repr_helper(list=temp_fittable_param, rep=rep)
458            """
[2296316]459            if is_2D:
460                rep += "number orientation parameters"
461                rep += "(self.orientation_params): %s\n"%len(self.orientation_params)
462                rep = self._repr_helper( list=self.orientation_params, rep=rep)
463                rep += "number dispersity parameters"
464                rep += "(self.orientation_params_disp): %s\n"%len(self.orientation_params_disp)
465                rep = self._repr_helper( list=self.orientation_params_disp, rep=rep)
466            """
[61cada5]467        return rep
[2296316]468
469    def set_report_string(self):
470        """
[f32d144]471        Get the values (strings) from __str__ for report
[2296316]472        """
473        # Dictionary of teh report strings
474        repo_time = ""
475        model_name = ""
476        title = ""
477        title_name = ""
478        file_name = ""
479        param_string = ""
480        paramval_string = ""
481        chi2_string = ""
[c0ff8cc]482        multi_factor_string = ""
[2296316]483        q_range = ""
484        strings = self.__repr__()
485        lines = strings.split('\n')
486
487        # get all string values from __str__()
488        for line in lines:
489            value = ""
490            content = line.split(":")
491            name = content[0]
492            try:
493                value = content[1]
494            except:
495                pass
[b7c6a4a]496            if name.count("State created"):
497                repo_time = "" + value
[2296316]498            if name.count("parameter name"):
499                val_name = value.split(".")
500                if len(val_name) > 1:
501                    if val_name[1].count("width"):
502                        param_string += value + ','
503                    else:
504                        continue
505                else:
506                    param_string += value + ','
507            if name == "value":
508                param_string += value + ','
509            if name == "error value":
510                param_string += value + ','
511            if name == "parameter unit":
[f32d144]512                param_string += value + ':'
[2296316]513            if name == "Value of Chisqr ":
514                chi2 = ("Chi2/Npts = " + value)
515                chi2_string = CENTRE % chi2
[c0ff8cc]516            if name == "multi_factor ":
517                muti_factor = ("muti_factor = " + value)
518                muti_factor_string = CENTRE % muti_factor
[318b5bbb]519            if name == "magentic_on ":
520                magentic_on = ("magentic_on = " + value)
521                if string(value) == 'True':
522                    magentic_on_string = CENTRE % magentic_on
[2296316]523            if name == "Title":
524                if len(value.strip()) == 0:
525                    continue
526                title = value + " [" + repo_time + "]"
527                title_name = HEADER % title
528            if name == "data ":
529                try:
530                    file = ("File name:" + content[2])
531                    file_name = CENTRE % file
532                    if len(title) == 0:
533                        title = content[2] + " [" + repo_time + "]"
534                        title_name = HEADER % title
535                except:
536                    pass
[74dc0a4]537            if name == "model name ":
538                try:
539                    modelname = "Model name:" + content[1]
540                except:
541                    modelname = "Model name:" + " NAN"
[f32d144]542                model_name = CENTRE % modelname
[74dc0a4]543                 
[2296316]544            if name == "Plotting Range":
545                try:
546                    q_range = content[1] + " = " + content[2] \
547                            + " = " + content[3].split(",")[0]
548                    q_name = ("Q Range:    " + q_range)
549                    q_range = CENTRE % q_name
550                except:
551                    pass
552        paramval = ""
[f32d144]553        for lines in param_string.split(":"):
[2296316]554            line = lines.split(",")
[f32d144]555            if len(lines) > 0:
556                param = line[0]
[2296316]557                param += " = " + line[1]
558                if len(line[2].split()) > 0 and not line[2].count("None"):
559                    param += " +- " + line[2]
560                if len(line[3].split()) > 0 and not line[3].count("None"):
561                    param += " " + line[3]
562                if not paramval.count(param):
[f32d144]563                    paramval += param + "\n"
[2296316]564                    paramval_string += CENTRE % param + "\n"
[3a3dd9c]565       
[f5bdb4a]566        text_string = "\n\n\n" + title + "\n\n" + file + \
[f32d144]567                      "\n" + q_name + \
568                      "\n" + chi2 + \
569                      "\n\n" + paramval
[f5bdb4a]570       
571        title_name = self._check_html_format(title_name)
572        file_name = self._check_html_format(file_name)
573        title = self._check_html_format(title)
574                                 
[2296316]575        html_string = title_name + "\n" + file_name + \
[f32d144]576                                   "\n" + model_name + \
[2296316]577                                   "\n" + q_range + \
578                                   "\n" + chi2_string + \
579                                   "\n" + ELINE + \
580                                   "\n" + paramval_string + \
581                                   "\n" + ELINE + \
582                                   "\n" + FEET_1 % title + \
[f32d144]583                                   "\n" + FEET_2
[f5bdb4a]584                                                                     
[2296316]585        return html_string, text_string, title
586   
[f5bdb4a]587    def _check_html_format(self, name):
588        """
589        Check string '%' for html format
590        """
591        if name.count('%'):
592            name = name.replace('%', '&#37')
593       
594        return name
595   
[2296316]596    def report(self, figs=None, canvases=None):
597        """
598        Invoke report dialog panel
599       
600        : param figs: list of pylab figures [list]
601        """
[eddb6ec]602        from sans.perspectives.fitting.report_dialog import ReportDialog
[2296316]603        # get the strings for report
604        html_str, text_str, title = self.set_report_string()
605        # Allow 2 figures to append
606        if len(figs) == 1:
[f32d144]607            add_str = FEET_3
[2296316]608        elif len(figs) == 2:
[f32d144]609            add_str = ELINE
610            add_str += FEET_2 % ("%s")
611            add_str += ELINE
612            add_str += FEET_3
[2296316]613        elif len(figs) > 2:
[f32d144]614            add_str = ELINE
615            add_str += FEET_2 % ("%s")
616            add_str += ELINE
617            add_str += FEET_2 % ("%s")
618            add_str += ELINE
619            add_str += FEET_3
[2296316]620        else:
621            add_str = ""
[c0ff8cc]622
[2296316]623        # final report html strings
624        report_str = html_str % ("%s") + add_str
625
626        # make plot image
627        images = self.set_plot_state(figs, canvases)
[f32d144]628        report_list = [report_str, text_str, images]
[2296316]629        dialog = ReportDialog(report_list, None, -1, "")
630        dialog.ShowModal()
[c0ff8cc]631       
[eddb6ec]632    def _toXML_helper(self, thelist, element, newdoc):
[61cada5]633        """
[5062bbf]634        Helper method to create xml file for saving state
[61cada5]635        """
[eddb6ec]636        for item in thelist:
[61cada5]637            sub_element = newdoc.createElement('parameter')
638            sub_element.setAttribute('name', str(item[1]))
639            sub_element.setAttribute('value', str(item[2]))
640            sub_element.setAttribute('selected_to_fit', str(item[0]))
641            sub_element.setAttribute('error_displayed', str(item[4][0]))
642            sub_element.setAttribute('error_value', str(item[4][1]))
643            sub_element.setAttribute('minimum_displayed', str(item[5][0]))
644            sub_element.setAttribute('minimum_value', str(item[5][1]))
645            sub_element.setAttribute('maximum_displayed', str(item[6][0]))
646            sub_element.setAttribute('maximum_value', str(item[6][1]))
647            sub_element.setAttribute('unit', str(item[7]))
648            element.appendChild(sub_element)
649       
650    def toXML(self, file="fitting_state.fitv", doc=None, entry_node=None):
651        """
[5062bbf]652        Writes the state of the InversionControl panel to file, as XML.
653       
654        Compatible with standalone writing, or appending to an
655        already existing XML document. In that case, the XML document
656        is required. An optional entry node in the XML document may also be given.
657       
658        :param file: file to write to
659        :param doc: XML document object [optional]
660        :param entry_node: XML node within the XML document at which we will append the data [optional]
661       
[61cada5]662        """
663        from xml.dom.minidom import getDOMImplementation
[71f0373]664
[61cada5]665        # Check whether we have to write a standalone XML file
666        if doc is None:
667            impl = getDOMImplementation()
[f32d144]668            doc_type = impl.createDocumentType(FITTING_NODE_NAME, "1.0", "1.0")
[61cada5]669            newdoc = impl.createDocument(None, FITTING_NODE_NAME, doc_type)
670            top_element = newdoc.documentElement
671        else:
672            # We are appending to an existing document
673            newdoc = doc
674            top_element = newdoc.createElement(FITTING_NODE_NAME)
675            if entry_node is None:
676                newdoc.documentElement.appendChild(top_element)
677            else:
678                entry_node.appendChild(top_element)
679           
680        attr = newdoc.createAttribute("version")
681        attr.nodeValue = '1.0'
682        top_element.setAttributeNode(attr)
[cfc0913]683       
[61cada5]684        # File name
685        element = newdoc.createElement("filename")
686        if self.file is not None:
687            element.appendChild(newdoc.createTextNode(str(self.file)))
688        else:
689            element.appendChild(newdoc.createTextNode(str(file)))
690        top_element.appendChild(element)
[11a7e11]691       
692        element = newdoc.createElement("timestamp")
693        element.appendChild(newdoc.createTextNode(time.ctime(self.timestamp)))
694        attr = newdoc.createAttribute("epoch")
695        attr.nodeValue = str(self.timestamp)
696        element.setAttributeNode(attr)
697        top_element.appendChild(element)
[61cada5]698        # Inputs
699        inputs = newdoc.createElement("Attributes")
700        top_element.appendChild(inputs)
701       
702        if self.data is not None and hasattr(self.data, "group_id"):
703            self.data_group_id = self.data.group_id
704        if self.data is not None and hasattr(self.data, "is_data"):
705            self.is_data = self.data.is_data
706        if self.data is not None:
707            self.data_name = self.data.name
708        if self.data is not None and hasattr(self.data, "id"):
709            self.data_id = self.data.id
710       
[26f3dd5]711        for item in list_of_data_attributes:
[0b12abb5]712            element = newdoc.createElement(item[0])
[2296316]713            exec "element.setAttribute(item[0], str(self.%s))" % (item[1])
[f32d144]714            inputs.appendChild(element)
[26f3dd5]715       
716        for item in list_of_state_attributes:
717            element = newdoc.createElement(item[0])
[2296316]718            exec "element.setAttribute(item[0], str(self.%s))" % (item[1])
[26f3dd5]719            inputs.appendChild(element)
[c0ff8cc]720           
[f32d144]721        # For self.values ={ disp_param_name: [vals,...],...}
722        # and for self.weights ={ disp_param_name: [weights,...],...}
[38226d26]723        list = {}
[11a7e11]724        for item in list_of_model_attributes:
725            element = newdoc.createElement(item[0])
[2296316]726            exec "list = self.%s" % item[1]
727            for key, value in list.iteritems():
728                sub_element = newdoc.createElement(key)
729                sub_element.setAttribute('name', str(key))
730                for val in value:
731                    com = "sub_element.appendChild"
732                    com += "(newdoc.createTextNode(str(%s)))"
733                    exec com % val
734                   
[f32d144]735                element.appendChild(sub_element)
[11a7e11]736            inputs.appendChild(element)
[2296316]737       
738        # Create doc for the dictionary of self._disp_obj_dic
739        for item in list_of_obj_dic:
[f32d144]740            element = newdoc.createElement(item[0])
741            exec "list = self.%s" % item[1]
742            for key, val in list.iteritems():
743                value = repr(val)
744                sub_element = newdoc.createElement(key)
745                sub_element.setAttribute('name', str(key))
746                sub_element.setAttribute('value', str(value))
747                element.appendChild(sub_element)
748            inputs.appendChild(element)
[2296316]749                 
[61cada5]750        for item in list_of_state_parameters:
751            element = newdoc.createElement(item[0])
[2296316]752            com = "self._toXML_helper(list=self.%s,"
753            com += " element=element, newdoc=newdoc)"
[f32d144]754            exec com % item[1]
[61cada5]755            inputs.appendChild(element)
[c0ff8cc]756       
[61cada5]757        # Save the file
758        if doc is None:
759            fd = open(file, 'w')
760            fd.write(newdoc.toprettyxml())
761            fd.close()
762            return None
763        else:
764            return newdoc.toprettyxml()
765       
766    def _fromXML_helper(self, node, list):
767        """
[5062bbf]768        Helper function to write state to xml
[61cada5]769        """
770        for item in node:
[0b12abb5]771            try:
772                name = item.get('name')
773            except:
774                name = None
775            try:
776                value = item.get('value')
777            except:
778                value = None
779            try:
[3ad91de]780                selected_to_fit = (item.get('selected_to_fit') == "True")
[0b12abb5]781            except:
782                selected_to_fit = None
783            try:
[3ad91de]784                error_displayed = (item.get('error_displayed') == "True")
[0b12abb5]785            except:
786                error_displayed = None
[f32d144]787            try:
[0b12abb5]788                error_value = item.get('error_value')
789            except:
790                error_value = None
791            try:
[f32d144]792                minimum_displayed = (item.get('minimum_displayed') == "True")
[0b12abb5]793            except:
794                minimum_displayed = None
795            try:
796                minimum_value = item.get('minimum_value')
797            except:
798                minimum_value = None
799            try:
[3ad91de]800                maximum_displayed = (item.get('maximum_displayed') == "True")
[0b12abb5]801            except:
802                maximum_displayed = None
803            try:
804                maximum_value = item.get('maximum_value')
805            except:
806                maximum_value = None
807            try:
808                unit = item.get('unit')
809            except:
810                unit = None
[2296316]811            list.append([selected_to_fit, name, value, "+/-",
812                         [error_displayed, error_value],
[f32d144]813                         [minimum_displayed, minimum_value],
814                         [maximum_displayed, maximum_value], unit])
[cfc0913]815       
[61cada5]816    def fromXML(self, file=None, node=None):
817        """
[5062bbf]818        Load fitting state from a file
819       
820        :param file: .fitv file
821        :param node: node of a XML document to read from
822       
[61cada5]823        """
824        if file is not None:
[11a7e11]825            msg = "PageState no longer supports non-CanSAS"
826            msg += " format for fitting files"
827            raise RuntimeError, msg
[61cada5]828           
[11a7e11]829        if node.get('version')and node.get('version') == '1.0':
[61cada5]830           
831            # Get file name
832            entry = get_content('ns:filename', node)
833            if entry is not None:
834                self.file = entry.text.strip()
[11a7e11]835               
836            # Get time stamp
837            entry = get_content('ns:timestamp', node)
838            if entry is not None and entry.get('epoch'):
839                try:
840                    self.timestamp = float(entry.get('epoch'))
841                except:
842                    msg = "PageState.fromXML: Could not"
843                    msg += " read timestamp\n %s" % sys.exc_value
844                    logging.error(msg)
845           
[61cada5]846            # Parse fitting attributes
847            entry = get_content('ns:Attributes', node)
[0b12abb5]848            for item in list_of_data_attributes:
[f32d144]849                node = get_content('ns:%s' % item[0], entry)
[0b12abb5]850                try:
[2296316]851                    exec "self.%s = parse_entry_helper(node, item)" % item[0]
[0b12abb5]852                   
853                except:
854                    raise
[2296316]855
[61cada5]856            if entry is not None:
[0b12abb5]857               
[61cada5]858                for item in list_of_state_attributes:
[2296316]859                    node = get_content('ns:%s' % item[0], entry)
[0b12abb5]860                    try:
[2296316]861                        exec "self.%s = parse_entry_helper(node, item)" % \
862                                                                str(item[0])
[0b12abb5]863                    except:
864                        raise
865                   
[2296316]866                for item in list_of_state_parameters:
867                    node = get_content("ns:%s" % item[0], entry)
868                    exec "self._fromXML_helper(node=node, list=self.%s)" % \
869                                                                    item[1]
870               
[f32d144]871                # Recover _disp_obj_dict from xml file
872                self._disp_obj_dict = {}
[2c44cf8]873                disp_model = None
[2296316]874                for item in list_of_obj_dic:
875                    # Get node
876                    node = get_content("ns:%s" % item[0], entry)
877                    for attr in node:
878                        name = attr.get('name')
[f32d144]879                        val = attr.get('value')
[2296316]880                        value = val.split(" instance")[0]
881                        disp_name = value.split("<")[1]
[11a7e11]882                        try:
[2296316]883                            # Try to recover disp_model object from strings
[f32d144]884                            com = "from sans.models.dispersion_models "
[2c44cf8]885                            com += "import %s as disp"
[2296316]886                            com_name = disp_name.split(".")[3]
887                            exec com % com_name
[2c44cf8]888                            disp_model = disp()
[2296316]889                            exec "self.%s['%s'] = com_name" % (item[1], name)
[11a7e11]890                        except:
[2296316]891                            pass
892                       
[f32d144]893                # get self.values and self.weights dic. if exists
[2296316]894                for item in list_of_model_attributes:
895                    node = get_content("ns:%s" % item[0], entry)
896                    dic = {}
897                    list = []
898                    for par in node:
899                        name = par.get('name')
900                        values = par.text.split('\n')
901                        # Get lines only with numbers
902                        for line in values:
903                            try:
[f32d144]904                                val = float(line)
905                                list.append(val)
[2296316]906                            except:
907                                # pass if line is empty (it happens)
908                                pass
909                    dic[name] = numpy.array(list)
910                    exec "self.%s = dic" % item[1]
911                   
912    def set_plot_state(self, figs, canvases):
913        """
914        Build image state that wx.html understand
915        by plotting, putting it into wx.FileSystem image object
916
917        """
918        images = []
919        # some imports
920        import wx
921
922        # Reset memory
923        self.imgRAM = None
924        wx.MemoryFSHandler()
925       
926        # For no figures in the list, prepare empty plot
927        if figs == None or len(figs) == 0:
928            figs = [None]
929           
[f32d144]930        # Loop over the list of figures
[2296316]931        # use wx.MemoryFSHandler
[f32d144]932        self.imgRAM = wx.MemoryFSHandler()
[2296316]933        for fig in figs:
934            if figs != None:
935                ind = figs.index(fig)
936                canvas = canvases[ind]
[0b12abb5]937               
[2296316]938            #store the image in wx.FileSystem Object
939            wx.FileSystem.AddHandler(wx.MemoryFSHandler())
940           
941            # index of the fig
942            ind = figs.index(fig)
943           
944            #AddFile, image can be retrieved with 'memory:filename'
[f32d144]945            self.imgRAM.AddFile('img_fit%s.png' % ind,
[2296316]946                                canvas.bitmap, wx.BITMAP_TYPE_PNG)
947           
948            #append figs
949            images.append(fig)
950           
[c0ff8cc]951        return images
[61cada5]952
[f32d144]953
[61cada5]954class Reader(CansasReader):
955    """
[5062bbf]956    Class to load a .fitv fitting file
[61cada5]957    """
958    ## File type
959    type_name = "Fitting"
960   
961    ## Wildcards
[b35d3d1]962    type = ["Fitting files (*.fitv)|*.fitv"
963            "SANSView file (*.svs)|*.svs"]
[61cada5]964    ## List of allowed extensions
[f32d144]965    ext = ['.fitv', '.FITV', '.svs', 'SVS']
[61cada5]966   
967    def __init__(self, call_back=None, cansas=True):
[df7ed14]968        CansasReader.__init__(self)
[61cada5]969        """
[5062bbf]970        Initialize the call-back method to be called
971        after we load a file
972       
973        :param call_back: call-back method
974        :param cansas:  True = files will be written/read in CanSAS format
975                        False = write CanSAS format
[61cada5]976           
977        """
978        ## Call back method to be executed after a file is read
979        self.call_back = call_back
980        ## CanSAS format flag
981        self.cansas = cansas
[75fbd17]982        self.state = None
[f32d144]983       
[75fbd17]984    def get_state(self):
985        return self.state
[61cada5]986       
987    def read(self, path):
[f32d144]988        """
[5062bbf]989        Load a new P(r) inversion state from file
990       
991        :param path: file path
992       
[61cada5]993        """
[e9b12eaf]994        if self.cansas == True:
[61cada5]995            return self._read_cansas(path)
[e9b12eaf]996     
997    def _data2d_to_xml_doc(self, datainfo):
[61cada5]998        """
[5062bbf]999        Create an XML document to contain the content of a Data2D
1000       
1001        :param datainfo: Data2D object
1002       
[61cada5]1003        """
1004        if not issubclass(datainfo.__class__, Data2D):
1005            raise RuntimeError, "The cansas writer expects a Data2D instance"
1006       
1007        doc = xml.dom.minidom.Document()
1008        main_node = doc.createElement("SASroot")
1009        main_node.setAttribute("version", self.version)
[df7ed14]1010        main_node.setAttribute("xmlns", "cansas1d/%s" % self.version)
1011        main_node.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
1012        main_node.setAttribute("xsi:schemaLocation", "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version)
1013       
[61cada5]1014        doc.appendChild(main_node)
1015       
1016        entry_node = doc.createElement("SASentry")
1017        main_node.appendChild(entry_node)
[df7ed14]1018       
[61cada5]1019        write_node(doc, entry_node, "Title", datainfo.title)
[df7ed14]1020        if datainfo is not None:
1021            write_node(doc, entry_node, "data_class", datainfo.__class__.__name__)
[61cada5]1022        for item in datainfo.run:
1023            runname = {}
1024            if datainfo.run_name.has_key(item) and len(str(datainfo.run_name[item]))>1:
1025                runname = {'name': datainfo.run_name[item] }
1026            write_node(doc, entry_node, "Run", item, runname)
1027        # Data info
[df7ed14]1028        new_node = doc.createElement("SASdata")
1029        entry_node.appendChild(new_node)
[e9b12eaf]1030        for item in list_of_data_2d_attr:
1031            element = doc.createElement(item[0])
[f32d144]1032            exec "element.setAttribute(item[0], str(datainfo.%s))" % (item[1])
[df7ed14]1033            new_node.appendChild(element)
1034           
[e9b12eaf]1035        for item in list_of_data2d_values:
[df7ed14]1036            root_node = doc.createElement(item[0])
1037            new_node.appendChild(root_node)
[38226d26]1038            temp_list = None
[f32d144]1039            exec "temp_list = datainfo.%s" % item[1]
[df7ed14]1040
[35b556d]1041            if temp_list is None or len(temp_list)== 0:
[df7ed14]1042                element = doc.createElement(item[0])
[f32d144]1043                exec "element.appendChild(doc.createTextNode(str(%s)))" % temp_list
[df7ed14]1044                root_node.appendChild(element)
[35b556d]1045            else:
1046                for value in temp_list:
[df7ed14]1047                    element = doc.createElement(item[0])
[f32d144]1048                    exec "element.setAttribute(item[0], str(%s))" % value
[df7ed14]1049                    root_node.appendChild(element)
1050       
[61cada5]1051        # Sample info
1052        sample = doc.createElement("SASsample")
1053        if datainfo.sample.name is not None:
1054            sample.setAttribute("name", str(datainfo.sample.name))
1055        entry_node.appendChild(sample)
1056        write_node(doc, sample, "ID", str(datainfo.sample.ID))
[f32d144]1057        write_node(doc, sample, "thickness", datainfo.sample.thickness,
1058                   {"unit": datainfo.sample.thickness_unit})
[61cada5]1059        write_node(doc, sample, "transmission", datainfo.sample.transmission)
[f32d144]1060        write_node(doc, sample, "temperature", datainfo.sample.temperature,
1061                   {"unit": datainfo.sample.temperature_unit})
[61cada5]1062       
1063        for item in datainfo.sample.details:
1064            write_node(doc, sample, "details", item)
1065       
1066        pos = doc.createElement("position")
[f32d144]1067        written = write_node(doc, pos, "x", datainfo.sample.position.x,
1068                             {"unit": datainfo.sample.position_unit})
1069        written = written | write_node(doc, pos, "y",
1070                                       datainfo.sample.position.y,
1071                                       {"unit": datainfo.sample.position_unit})
1072        written = written | write_node(doc, pos, "z",
1073                                       datainfo.sample.position.z,
1074                                       {"unit": datainfo.sample.position_unit})
[61cada5]1075        if written == True:
1076            sample.appendChild(pos)
1077       
1078        ori = doc.createElement("orientation")
[f32d144]1079        written = write_node(doc, ori, "roll", datainfo.sample.orientation.x,
1080                             {"unit": datainfo.sample.orientation_unit})
1081        written = written | write_node(doc, ori, "pitch",
1082                                       datainfo.sample.orientation.y,
1083                                       {"unit": datainfo.sample.orientation_unit})
1084        written = written | write_node(doc, ori, "yaw",
1085                                       datainfo.sample.orientation.z,
1086                                       {"unit": datainfo.sample.orientation_unit})
[61cada5]1087        if written == True:
1088            sample.appendChild(ori)
1089       
1090        # Instrument info
1091        instr = doc.createElement("SASinstrument")
1092        entry_node.appendChild(instr)
1093       
1094        write_node(doc, instr, "name", datainfo.instrument)
1095       
1096        #   Source
1097        source = doc.createElement("SASsource")
1098        if datainfo.source.name is not None:
1099            source.setAttribute("name", str(datainfo.source.name))
1100        instr.appendChild(source)
1101       
1102        write_node(doc, source, "radiation", datainfo.source.radiation)
1103        write_node(doc, source, "beam_shape", datainfo.source.beam_shape)
1104        size = doc.createElement("beam_size")
1105        if datainfo.source.beam_size_name is not None:
1106            size.setAttribute("name", str(datainfo.source.beam_size_name))
[f32d144]1107        written = write_node(doc, size, "x", datainfo.source.beam_size.x,
1108                             {"unit": datainfo.source.beam_size_unit})
1109        written = written | write_node(doc, size, "y",
1110                                       datainfo.source.beam_size.y,
1111                                       {"unit": datainfo.source.beam_size_unit})
1112        written = written | write_node(doc, size, "z",
1113                                       datainfo.source.beam_size.z,
1114                                       {"unit": datainfo.source.beam_size_unit})
[61cada5]1115        if written == True:
1116            source.appendChild(size)
1117           
[f32d144]1118        write_node(doc, source, "wavelength", datainfo.source.wavelength,
1119                   {"unit": datainfo.source.wavelength_unit})
1120        write_node(doc, source, "wavelength_min",
1121                   datainfo.source.wavelength_min,
1122                   {"unit": datainfo.source.wavelength_min_unit})
1123        write_node(doc, source, "wavelength_max",
1124                   datainfo.source.wavelength_max,
1125                   {"unit": datainfo.source.wavelength_max_unit})
1126        write_node(doc, source, "wavelength_spread",
1127                   datainfo.source.wavelength_spread,
1128                   {"unit": datainfo.source.wavelength_spread_unit})
[61cada5]1129       
1130        #   Collimation
1131        for item in datainfo.collimation:
1132            coll = doc.createElement("SAScollimation")
1133            if item.name is not None:
1134                coll.setAttribute("name", str(item.name))
1135            instr.appendChild(coll)
1136           
[f32d144]1137            write_node(doc, coll, "length", item.length,
1138                       {"unit": item.length_unit})
[61cada5]1139           
1140            for apert in item.aperture:
1141                ap = doc.createElement("aperture")
1142                if apert.name is not None:
1143                    ap.setAttribute("name", str(apert.name))
1144                if apert.type is not None:
1145                    ap.setAttribute("type", str(apert.type))
1146                coll.appendChild(ap)
1147               
[f32d144]1148                write_node(doc, ap, "distance", apert.distance,
1149                           {"unit": apert.distance_unit})
[61cada5]1150               
1151                size = doc.createElement("size")
1152                if apert.size_name is not None:
1153                    size.setAttribute("name", str(apert.size_name))
[f32d144]1154                written = write_node(doc, size, "x", apert.size.x,
1155                                     {"unit": apert.size_unit})
1156                written = written | write_node(doc, size, "y", apert.size.y,
1157                                               {"unit": apert.size_unit})
1158                written = written | write_node(doc, size, "z", apert.size.z,
1159                                               {"unit": apert.size_unit})
[61cada5]1160                if written == True:
1161                    ap.appendChild(size)
1162
1163        #   Detectors
1164        for item in datainfo.detector:
1165            det = doc.createElement("SASdetector")
1166            written = write_node(doc, det, "name", item.name)
[f32d144]1167            written = written | write_node(doc, det, "SDD", item.distance,
1168                                           {"unit": item.distance_unit})
1169            written = written | write_node(doc, det, "slit_length",
1170                                           item.slit_length,
1171                                           {"unit": item.slit_length_unit})
[61cada5]1172            if written == True:
1173                instr.appendChild(det)
1174           
1175            off = doc.createElement("offset")
[f32d144]1176            written = write_node(doc, off, "x", item.offset.x,
1177                                 {"unit": item.offset_unit})
1178            written = written | write_node(doc, off, "y", item.offset.y,
1179                                           {"unit": item.offset_unit})
1180            written = written | write_node(doc, off, "z", item.offset.z,
1181                                           {"unit": item.offset_unit})
[61cada5]1182            if written == True:
1183                det.appendChild(off)
1184           
1185            center = doc.createElement("beam_center")
[f32d144]1186            written = write_node(doc, center, "x", item.beam_center.x,
1187                                 {"unit": item.beam_center_unit})
1188            written = written | write_node(doc, center, "y",
1189                                           item.beam_center.y,
1190                                           {"unit": item.beam_center_unit})
1191            written = written | write_node(doc, center, "z",
1192                                           item.beam_center.z,
1193                                           {"unit": item.beam_center_unit})
[61cada5]1194            if written == True:
1195                det.appendChild(center)
1196               
1197            pix = doc.createElement("pixel_size")
[f32d144]1198            written = write_node(doc, pix, "x", item.pixel_size.x,
1199                                 {"unit": item.pixel_size_unit})
1200            written = written | write_node(doc, pix, "y", item.pixel_size.y,
1201                                           {"unit": item.pixel_size_unit})
1202            written = written | write_node(doc, pix, "z", item.pixel_size.z,
1203                                           {"unit": item.pixel_size_unit})
[61cada5]1204            if written == True:
1205                det.appendChild(pix)
1206               
1207            ori = doc.createElement("orientation")
[f32d144]1208            written = write_node(doc, ori, "roll", item.orientation.x,
1209                                 {"unit": item.orientation_unit})
1210            written = written | write_node(doc, ori, "pitch",
1211                                           item.orientation.y,
1212                                           {"unit": item.orientation_unit})
1213            written = written | write_node(doc, ori, "yaw", item.orientation.z,
1214                                           {"unit": item.orientation_unit})
[61cada5]1215            if written == True:
1216                det.appendChild(ori)
1217               
1218        # Processes info
1219        for item in datainfo.process:
1220            node = doc.createElement("SASprocess")
1221            entry_node.appendChild(node)
1222
1223            write_node(doc, node, "name", item.name)
1224            write_node(doc, node, "date", item.date)
1225            write_node(doc, node, "description", item.description)
1226            for term in item.term:
1227                value = term['value']
1228                del term['value']
1229                write_node(doc, node, "term", value, term)
1230            for note in item.notes:
1231                write_node(doc, node, "SASprocessnote", note)
1232        # Return the document, and the SASentry node associated with
1233        # the data we just wrote
1234        return doc, entry_node
[e9b12eaf]1235   
[61cada5]1236    def _parse_state(self, entry):
1237        """
[5062bbf]1238        Read a fit result from an XML node
1239       
[f32d144]1240        :param entry: XML node to read from
[5062bbf]1241       
1242        :return: PageState object
[61cada5]1243        """
1244        # Create an empty state
[b35d3d1]1245        state = None   
[61cada5]1246        # Locate the P(r) node
1247        try:
[f32d144]1248            nodes = entry.xpath('ns:%s' % FITTING_NODE_NAME,
1249                                namespaces={'ns': CANSAS_NS})
1250            if nodes != []:
[b35d3d1]1251                # Create an empty state
[f32d144]1252                state = PageState()
[b35d3d1]1253                state.fromXML(node=nodes[0])
[61cada5]1254        except:
1255            logging.info("XML document does not contain fitting information.\n %s" % sys.exc_value)
1256           
1257        return state
[f32d144]1258     
[df7ed14]1259    def _parse_entry(self, dom):
[e9b12eaf]1260        """
[5062bbf]1261        Parse a SASentry
1262       
1263        :param node: SASentry node
1264       
[df7ed14]1265        :return: Data1D/Data2D object
[5062bbf]1266       
[e9b12eaf]1267        """
[df7ed14]1268        node = dom.xpath('ns:data_class', namespaces={'ns': CANSAS_NS})
1269        if not node or node[0].text.lstrip().rstrip() != "Data2D":
1270            return CansasReader._parse_entry(self, dom)
1271       
1272        #Parse 2D
[e9b12eaf]1273        data_info = Data2D()
1274       
[f32d144]1275        # Look up title
[e9b12eaf]1276        self._store_content('ns:Title', dom, 'title', data_info)
1277       
[f32d144]1278        # Look up run number
[e9b12eaf]1279        nodes = dom.xpath('ns:Run', namespaces={'ns': CANSAS_NS})
[f32d144]1280        for item in nodes:
[e9b12eaf]1281            if item.text is not None:
1282                value = item.text.strip()
1283                if len(value) > 0:
1284                    data_info.run.append(value)
1285                    if item.get('name') is not None:
1286                        data_info.run_name[value] = item.get('name')
1287                           
[f32d144]1288        # Look up instrument name
1289        self._store_content('ns:SASinstrument/ns:name', dom,
1290                            'instrument', data_info)
[e9b12eaf]1291
1292        # Notes
1293        note_list = dom.xpath('ns:SASnote', namespaces={'ns': CANSAS_NS})
1294        for note in note_list:
1295            try:
1296                if note.text is not None:
1297                    note_value = note.text.strip()
1298                    if len(note_value) > 0:
1299                        data_info.notes.append(note_value)
1300            except:
1301                err_mess = "cansas_reader.read: error processing entry notes\n  %s" % sys.exc_value
1302                self.errors.append(err_mess)
1303                logging.error(err_mess)
1304       
1305        # Sample info ###################
1306        entry = get_content('ns:SASsample', dom)
1307        if entry is not None:
1308            data_info.sample.name = entry.get('name')
1309           
[f32d144]1310        self._store_content('ns:SASsample/ns:ID',
1311                     dom, 'ID', data_info.sample)
1312        self._store_float('ns:SASsample/ns:thickness',
[e9b12eaf]1313                     dom, 'thickness', data_info.sample)
[f32d144]1314        self._store_float('ns:SASsample/ns:transmission',
[e9b12eaf]1315                     dom, 'transmission', data_info.sample)
[f32d144]1316        self._store_float('ns:SASsample/ns:temperature',
[e9b12eaf]1317                     dom, 'temperature', data_info.sample)
1318       
[f32d144]1319        nodes = dom.xpath('ns:SASsample/ns:details',
1320                          namespaces={'ns': CANSAS_NS})
[e9b12eaf]1321        for item in nodes:
1322            try:
1323                if item.text is not None:
1324                    detail_value = item.text.strip()
1325                    if len(detail_value) > 0:
1326                        data_info.sample.details.append(detail_value)
1327            except:
1328                err_mess = "cansas_reader.read: error processing sample details\n  %s" % sys.exc_value
1329                self.errors.append(err_mess)
1330                logging.error(err_mess)
1331       
1332        # Position (as a vector)
[f32d144]1333        self._store_float('ns:SASsample/ns:position/ns:x',
1334                     dom, 'position.x', data_info.sample)
1335        self._store_float('ns:SASsample/ns:position/ns:y',
1336                     dom, 'position.y', data_info.sample)
1337        self._store_float('ns:SASsample/ns:position/ns:z',
1338                     dom, 'position.z', data_info.sample)
[e9b12eaf]1339       
1340        # Orientation (as a vector)
[f32d144]1341        self._store_float('ns:SASsample/ns:orientation/ns:roll',
1342                     dom, 'orientation.x', data_info.sample)
1343        self._store_float('ns:SASsample/ns:orientation/ns:pitch',
1344                     dom, 'orientation.y', data_info.sample)
1345        self._store_float('ns:SASsample/ns:orientation/ns:yaw',
1346                     dom, 'orientation.z', data_info.sample)
[e9b12eaf]1347       
1348        # Source info ###################
1349        entry = get_content('ns:SASinstrument/ns:SASsource', dom)
1350        if entry is not None:
1351            data_info.source.name = entry.get('name')
1352       
[f32d144]1353        self._store_content('ns:SASinstrument/ns:SASsource/ns:radiation',
1354                     dom, 'radiation', data_info.source)
1355        self._store_content('ns:SASinstrument/ns:SASsource/ns:beam_shape',
1356                     dom, 'beam_shape', data_info.source)
1357        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength',
1358                     dom, 'wavelength', data_info.source)
1359        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_min',
1360                     dom, 'wavelength_min', data_info.source)
1361        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_max',
1362                     dom, 'wavelength_max', data_info.source)
1363        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_spread',
1364                     dom, 'wavelength_spread', data_info.source)
1365       
1366        # Beam size (as a vector)
[e9b12eaf]1367        entry = get_content('ns:SASinstrument/ns:SASsource/ns:beam_size', dom)
1368        if entry is not None:
1369            data_info.source.beam_size_name = entry.get('name')
1370           
[f32d144]1371        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:x',
1372                     dom, 'beam_size.x', data_info.source)
1373        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:y',
1374                     dom, 'beam_size.y', data_info.source)
1375        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:z',
1376                     dom, 'beam_size.z', data_info.source)
[e9b12eaf]1377       
1378        # Collimation info ###################
[f32d144]1379        nodes = dom.xpath('ns:SASinstrument/ns:SAScollimation',
1380                          namespaces={'ns': CANSAS_NS})
[e9b12eaf]1381        for item in nodes:
1382            collim = Collimation()
1383            if item.get('name') is not None:
1384                collim.name = item.get('name')
[f32d144]1385            self._store_float('ns:length', item, 'length', collim)
[e9b12eaf]1386           
1387            # Look for apertures
[f32d144]1388            apert_list = item.xpath('ns:aperture',
1389                                    namespaces={'ns': CANSAS_NS})
[e9b12eaf]1390            for apert in apert_list:
[f32d144]1391                aperture = Aperture()
[e9b12eaf]1392               
1393                # Get the name and type of the aperture
1394                aperture.name = apert.get('name')
1395                aperture.type = apert.get('type')
1396                   
[f32d144]1397                self._store_float('ns:distance', apert, 'distance', aperture)
[e9b12eaf]1398               
1399                entry = get_content('ns:size', apert)
1400                if entry is not None:
1401                    aperture.size_name = entry.get('name')
1402               
[f32d144]1403                self._store_float('ns:size/ns:x', apert, 'size.x', aperture)
1404                self._store_float('ns:size/ns:y', apert, 'size.y', aperture)
[e9b12eaf]1405                self._store_float('ns:size/ns:z', apert, 'size.z', aperture)
1406               
1407                collim.aperture.append(aperture)
1408               
1409            data_info.collimation.append(collim)
1410       
1411        # Detector info ######################
[f32d144]1412        nodes = dom.xpath('ns:SASinstrument/ns:SASdetector',
1413                          namespaces={'ns': CANSAS_NS})
[e9b12eaf]1414        for item in nodes:
1415           
1416            detector = Detector()
1417           
1418            self._store_content('ns:name', item, 'name', detector)
[f32d144]1419            self._store_float('ns:SDD', item, 'distance', detector)
[e9b12eaf]1420           
1421            # Detector offset (as a vector)
[f32d144]1422            self._store_float('ns:offset/ns:x', item, 'offset.x', detector)
1423            self._store_float('ns:offset/ns:y', item, 'offset.y', detector)
1424            self._store_float('ns:offset/ns:z', item, 'offset.z', detector)
[e9b12eaf]1425           
1426            # Detector orientation (as a vector)
[f32d144]1427            self._store_float('ns:orientation/ns:roll', item,
1428                              'orientation.x', detector)
1429            self._store_float('ns:orientation/ns:pitch', item,
1430                              'orientation.y', detector)
1431            self._store_float('ns:orientation/ns:yaw', item,
1432                              'orientation.z', detector)
[e9b12eaf]1433           
1434            # Beam center (as a vector)
[f32d144]1435            self._store_float('ns:beam_center/ns:x', item,
1436                              'beam_center.x', detector)
1437            self._store_float('ns:beam_center/ns:y', item,
1438                              'beam_center.y', detector)
1439            self._store_float('ns:beam_center/ns:z', item,
1440                              'beam_center.z', detector)
[e9b12eaf]1441           
1442            # Pixel size (as a vector)
[f32d144]1443            self._store_float('ns:pixel_size/ns:x', item,
1444                              'pixel_size.x', detector)
1445            self._store_float('ns:pixel_size/ns:y', item,
1446                              'pixel_size.y', detector)
1447            self._store_float('ns:pixel_size/ns:z', item,
1448                              'pixel_size.z', detector)
[e9b12eaf]1449           
1450            self._store_float('ns:slit_length', item, 'slit_length', detector)
1451           
[f32d144]1452            data_info.detector.append(detector)
[e9b12eaf]1453
1454        # Processes info ######################
1455        nodes = dom.xpath('ns:SASprocess', namespaces={'ns': CANSAS_NS})
1456        for item in nodes:
1457            process = Process()
1458            self._store_content('ns:name', item, 'name', process)
1459            self._store_content('ns:date', item, 'date', process)
1460            self._store_content('ns:description', item, 'description', process)
1461           
1462            term_list = item.xpath('ns:term', namespaces={'ns': CANSAS_NS})
1463            for term in term_list:
1464                try:
1465                    term_attr = {}
1466                    for attr in term.keys():
1467                        term_attr[attr] = term.get(attr).strip()
1468                    if term.text is not None:
1469                        term_attr['value'] = term.text.strip()
1470                        process.term.append(term_attr)
1471                except:
1472                    err_mess = "cansas_reader.read: error processing process term\n  %s" % sys.exc_value
1473                    self.errors.append(err_mess)
1474                    logging.error(err_mess)
1475           
[f32d144]1476            note_list = item.xpath('ns:SASprocessnote',
1477                                   namespaces={'ns': CANSAS_NS})
[e9b12eaf]1478            for note in note_list:
1479                if note.text is not None:
1480                    process.notes.append(note.text.strip())
1481           
1482            data_info.process.append(process)
1483           
1484        # Data info ######################
1485        nodes = dom.xpath('ns:SASdata', namespaces={'ns': CANSAS_NS})
[f32d144]1486        if len(nodes) > 1:
[e9b12eaf]1487            raise RuntimeError, "CanSAS reader is not compatible with multiple SASdata entries"
[df7ed14]1488       
1489        for entry in nodes:
1490            for item in list_of_data_2d_attr:
1491                #get node
[f32d144]1492                node = get_content('ns:%s' % item[0], entry)
1493                exec "data_info.%s = parse_entry_helper(node, item)" % item[1]
[e9b12eaf]1494                   
[df7ed14]1495            for item in list_of_data2d_values:
[f32d144]1496                field = get_content('ns:%s' % item[0], entry)
[df7ed14]1497                list = []
1498                if field is not None:
[0b12abb5]1499                    list = [parse_entry_helper(node, item) for node in field]
[44f7c1b]1500                if len(list) < 2:
1501                    exec "data_info.%s = None" % item[0]
1502                else:
1503                    exec "data_info.%s = numpy.array(list)" % item[0]
[e9b12eaf]1504       
1505        return data_info
1506
[61cada5]1507    def _read_cansas(self, path):
[f32d144]1508        """
[5062bbf]1509        Load data and P(r) information from a CanSAS XML file.
1510       
1511        :param path: file path
1512       
[f32d144]1513        :return: Data1D object if a single SASentry was found,
[5062bbf]1514                    or a list of Data1D objects if multiple entries were found,
1515                    or None of nothing was found
1516                   
1517        :raise RuntimeError: when the file can't be opened
1518        :raise ValueError: when the length of the data vectors are inconsistent
1519       
[61cada5]1520        """
1521        output = []
[f32d144]1522        basename = os.path.basename(path)
[b63dc6e]1523        root, extension = os.path.splitext(basename)
1524        ext = extension.lower()
[61cada5]1525        try:
1526            if os.path.isfile(path):
[b63dc6e]1527               
[61cada5]1528                #TODO: eventually remove the check for .xml once
1529                # the P(r) writer/reader is truly complete.
[b63dc6e]1530                if  ext in self.ext or \
1531                    ext == '.xml':
[61cada5]1532                   
1533                    tree = etree.parse(path, parser=etree.ETCompatXMLParser())
1534                    # Check the format version number
[f32d144]1535                    # Specifying the namespace will take care of the file format version
[61cada5]1536                    root = tree.getroot()
[f32d144]1537                    entry_list = root.xpath('ns:SASentry',
1538                                            namespaces={'ns': CANSAS_NS})
1539                    for entry in entry_list:
[e9b12eaf]1540                        try:
1541                            sas_entry = self._parse_entry(entry)
1542                        except:
[df7ed14]1543                            raise
[61cada5]1544                        fitstate = self._parse_state(entry)
[b35d3d1]1545                       
1546                        #state could be None when .svs file is loaded
1547                        #in this case, skip appending to output
1548                        if fitstate != None:
1549                            sas_entry.meta_data['fitstate'] = fitstate
1550                            sas_entry.filename = fitstate.file
1551                            output.append(sas_entry)
[61cada5]1552            else:
[b63dc6e]1553                self.call_back(format=ext)
[61cada5]1554                raise RuntimeError, "%s is not a file" % path
[b35d3d1]1555
[61cada5]1556            # Return output consistent with the loader's api
[f32d144]1557            if len(output) == 0:
1558                self.call_back(state=None, datainfo=None, format=ext)
[61cada5]1559                return None
1560            else:
[b35d3d1]1561                for ind in range(len(output)):
1562                    # Call back to post the new state
1563                    state = output[ind].meta_data['fitstate']
1564                    t = time.localtime(state.timestamp)
1565                    time_str = time.strftime("%b %d %H:%M", t)
1566                    # Check that no time stamp is already appended
1567                    max_char = state.file.find("[")
1568                    if max_char < 0:
1569                        max_char = len(state.file)
[ef16f59]1570                    original_fname = state.file[0:max_char]
[f32d144]1571                    state.file = original_fname + ' [' + time_str + ']'
1572                     
[b35d3d1]1573                    if state is not None and state.is_data is not None:
[f32d144]1574                        exec 'output[%d].is_data = state.is_data' % ind
[b35d3d1]1575                     
1576                    output[ind].filename = state.file
1577                    state.data = output[ind]
[f32d144]1578                    state.data.name = output[ind].filename  # state.data_name
[b35d3d1]1579                    state.data.id = state.data_id
1580                    if state.is_data is not None:
1581                        state.data.is_data = state.is_data
[f32d144]1582                    if output[ind].run_name is not None\
1583                        and len(output[ind].run_name) != 0:
[ef16f59]1584                        name = output[ind].run_name
[f32d144]1585                    else:
1586                        name = original_fname
[ef16f59]1587                    state.data.group_id = name
1588                    #store state in fitting
[f32d144]1589                    self.call_back(state=state,
1590                                   datainfo=output[ind], format=ext)
1591                    self.state = state
[ef16f59]1592                return output
[b35d3d1]1593             
[61cada5]1594        except:
[4bee68d]1595            self.call_back(format=ext)
1596            #self.state= state
[61cada5]1597            raise
1598           
1599    def write(self, filename, datainfo=None, fitstate=None):
1600        """
[b35d3d1]1601        Write the content of a Data1D as a CanSAS XML file only for standalone
[5062bbf]1602       
1603        :param filename: name of the file to write
1604        :param datainfo: Data1D object
1605        :param fitstate: PageState object
1606       
[61cada5]1607        """
1608        # Sanity check
1609        if self.cansas == True:
1610           
1611            # Add fitting information to the XML document
[ef16f59]1612            doc = self.write_toXML(datainfo, fitstate)
[61cada5]1613            # Write the XML document
1614            fd = open(filename, 'w')
1615            fd.write(doc.toprettyxml())
1616            fd.close()
1617        else:
1618            fitstate.toXML(file=filename)
1619       
[b35d3d1]1620    def write_toXML(self, datainfo=None, state=None):
1621        """
[f32d144]1622        Write toXML, a helper for write(),
1623        could be used by guimanager._on_save()
[b35d3d1]1624       
1625        : return: xml doc
1626        """
[3c44c66]1627
[b35d3d1]1628        if state.data is None:
[f32d144]1629            data = sans.dataloader.data_info.Data1D(x=[], y=[])
[a805118]1630            return None
[3b148c3]1631        elif not state.data.is_data:
1632            return None
[f32d144]1633        else:
[b35d3d1]1634            #make sure title and data run is filled up.
[f32d144]1635            if state.data.title == None or state.data.title == '':
1636                state.data.title = state.data.name
1637            if state.data.run_name == None or state.data.run_name == {}:
[028a0e8]1638                state.data.run = [str(state.data.name)]
1639                state.data.run_name[0] = state.data.name
[b35d3d1]1640   
[f32d144]1641            if issubclass(state.data.__class__,
1642                          sans.dataloader.data_info.Data1D):
[b35d3d1]1643                data = state.data
1644                doc, sasentry = self._to_xml_doc(data)
1645            else:
1646                data = state.data
1647                doc, sasentry = self._data2d_to_xml_doc(data)
1648           
1649        if state is not None:
[7c720e9]1650            state.toXML(doc=doc, file=data.filename, entry_node=sasentry)
[b35d3d1]1651           
[f32d144]1652        return doc
[2296316]1653   
[f32d144]1654# Simple html report templet
[2296316]1655HEADER = "<html>\n"
1656HEADER += "<head>\n"
1657HEADER += "<meta http-equiv=Content-Type content='text/html; "
1658HEADER += "charset=windows-1252'> \n"
1659HEADER += "<meta name=Generator >\n"
1660HEADER += "</head>\n"
1661HEADER += "<body lang=EN-US>\n"
1662HEADER += "<div class=WordSection1>\n"
[14d2daa]1663HEADER += "<p class=MsoNormal><b><span ><center><font size='4' >"
1664HEADER += "%s</font></center></span></center></b></p>"
[2296316]1665HEADER += "<p class=MsoNormal>&nbsp;</p>"
[14d2daa]1666PARA = "<p class=MsoNormal><font size='4' > %s \n"
1667PARA += "</font></p>"
1668CENTRE = "<p class=MsoNormal><center><font size='4' > %s \n"
1669CENTRE += "</font></center></p>"
[2296316]1670FEET_1 = \
1671"""
[3a3dd9c]1672<p class=MsoNormal>&nbsp;</p>
[14d2daa]1673<br>
1674<p class=MsoNormal><b><span ><center> <font size='4' > Graph
[f32d144]1675</font></span></center></b></p>
1676<p class=MsoNormal>&nbsp;</p>
1677<center>
[14d2daa]1678<br><font size='4' >Model Computation</font>
[f32d144]1679<br><font size='4' >Data: "%s"</font><br>
[2296316]1680"""
1681FEET_2 = \
1682"""
[f32d144]1683<img src="%s" >
[2296316]1684</img>
1685"""
1686FEET_3 = \
1687"""
[f32d144]1688</center>
[2296316]1689</div>
1690</body>
1691</html>
1692"""
1693ELINE = "<p class=MsoNormal>&nbsp;</p>"
1694
[3c44c66]1695if __name__ == "__main__":
1696    state = PageState(parent=None)
1697    #state.toXML()
1698    """
[5062bbf]1699   
[3c44c66]1700    file = open("test_state", "w")
1701    pickle.dump(state, file)
1702    print pickle.dumps(state)
1703    state.data_name = "hello---->"
1704    pickle.dump(state, file)
1705    file = open("test_state", "r")
1706    new_state= pickle.load(file)
1707    print "new state", new_state
1708    new_state= pickle.load(file)
1709    print "new state", new_state
1710    #print "state", state
1711    """
1712    import bsddb
1713    import pickle
[f32d144]1714    db = bsddb.btopen('file_state.db', 'c')
[3c44c66]1715    val = (pickle.dumps(state), "hello", "hi")
[f32d144]1716    db['state1'] = pickle.dumps(val)
[3c44c66]1717    print pickle.loads(db['state1'])
1718    state.data_name = "hello---->22"
[f32d144]1719    db['state2'] = pickle.dumps(state)
[3c44c66]1720    state.data_name = "hello---->2"
[f32d144]1721    db['state3'] = pickle.dumps(state)
[3c44c66]1722    del db['state3']
1723    state.data_name = "hello---->3"
[f32d144]1724    db['state4'] = pickle.dumps(state)
[3c44c66]1725    new_state = pickle.loads(db['state1'])
1726    #print db.last()
1727    db.set_location('state2')
1728    state.data_name = "hello---->5"
[f32d144]1729    db['aastate5'] = pickle.dumps(state)
[3c44c66]1730    db.keys().sort()
1731    print pickle.loads(db['state2'])
1732 
[f32d144]1733    db.close()
Note: See TracBrowser for help on using the repository browser.