source: sasview/sansview/perspectives/fitting/pagestate.py @ 6d48919

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 6d48919 was 4523b68, checked in by Jae Cho <jhjcho@…>, 14 years ago

added coremultishellmodel/multifunctional model

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