Changeset ff3f5821 in sasview for src


Ignore:
Timestamp:
Oct 7, 2016 12:31:19 PM (8 years ago)
Author:
krzywon
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
e6de6b8
Parents:
998ca90 (diff), dd72190 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into wx_save_simfit

Location:
src/sas
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sascalc/dataloader/data_info.py

    r45d7662 r1b1a1c1  
    881881                raise ValueError, msg 
    882882            # Here we could also extrapolate between data points 
    883             ZERO = 1.0e-12 
     883            TOLERANCE = 0.01 
    884884            for i in range(len(self.x)): 
    885                 if math.fabs(self.x[i] - other.x[i]) > ZERO: 
     885                if math.fabs((self.x[i] - other.x[i])/self.x[i]) > TOLERANCE: 
    886886                    msg = "Incompatible data sets: x-values do not match" 
    887887                    raise ValueError, msg 
     
    10931093        """ 
    10941094        err_other = None 
     1095        TOLERANCE = 0.01 
    10951096        if isinstance(other, Data2D): 
    10961097            # Check that data lengths are the same 
     
    11011102                raise ValueError, msg 
    11021103            for ind in range(len(self.data)): 
    1103                 if self.qx_data[ind] != other.qx_data[ind]: 
    1104                     msg = "Incompatible data sets: qx-values do not match" 
     1104                if math.fabs((self.qx_data[ind] - other.qx_data[ind])/self.qx_data[ind]) > TOLERANCE: 
     1105                    msg = "Incompatible data sets: qx-values do not match: %s %s" % (self.qx_data[ind], other.qx_data[ind]) 
    11051106                    raise ValueError, msg 
    1106                 if self.qy_data[ind] != other.qy_data[ind]: 
    1107                     msg = "Incompatible data sets: qy-values do not match" 
     1107                if math.fabs((self.qy_data[ind] - other.qy_data[ind])/self.qy_data[ind]) > TOLERANCE: 
     1108                    msg = "Incompatible data sets: qy-values do not match: %s %s" % (self.qy_data[ind], other.qy_data[ind]) 
    11081109                    raise ValueError, msg 
    11091110 
  • src/sas/sasgui/guiframe/dataFitting.py

    rd85c194 r9b6d62d  
    363363        _str = "%s\n" % LoadData2D.__str__(self) 
    364364        return _str  
    365      
    366     def _validity_check(self, other): 
    367         """ 
    368         Checks that the data lengths are compatible. 
    369         Checks that the x vectors are compatible. 
    370         Returns errors vectors equal to original 
    371         errors vectors if they were present or vectors 
    372         of zeros when none was found. 
    373          
    374         :param other: other data set for operation 
    375          
    376         :return: dy for self, dy for other [numpy arrays] 
    377          
    378         :raise ValueError: when lengths are not compatible 
    379          
    380         """ 
    381         err_other = None 
    382         if isinstance(other, Data2D): 
    383             # Check that data lengths are the same 
    384             if len(self.data) != len(other.data) or \ 
    385                 len(self.qx_data) != len(other.qx_data) or \ 
    386                 len(self.qy_data) != len(other.qy_data): 
    387                 msg = "Unable to perform operation: data length are not equal" 
    388                 raise ValueError, msg 
    389             #if len(self.data) < 1: 
    390             #    msg = "Incompatible data sets: I-values do not match" 
    391             #    raise ValueError, msg  
    392             for ind in range(len(self.data)): 
    393                 if self.qx_data[ind] != other.qx_data[ind]: 
    394                     msg = "Incompatible data sets: qx-values do not match" 
    395                     raise ValueError, msg 
    396                 if self.qy_data[ind] != other.qy_data[ind]: 
    397                     msg = "Incompatible data sets: qy-values do not match" 
    398                     raise ValueError, msg 
    399                     
    400             # Check that the scales match 
    401             err_other = other.err_data 
    402             if other.err_data == None or \ 
    403                 (len(other.err_data) != len(other.data)): 
    404                 err_other = numpy.zeros(len(other.data)) 
    405              
    406         # Check that we have errors, otherwise create zero vector 
    407         err = self.err_data 
    408         if self.err_data == None or \ 
    409             (len(self.err_data) != len(self.data)): 
    410             err = numpy.zeros(len(other.data)) 
    411              
    412         return err, err_other 
    413  
    414     def _validity_check_union(self, other): 
    415         """ 
    416         Checks that the data lengths are compatible. 
    417         Checks that the x vectors are compatible. 
    418         Returns errors vectors equal to original 
    419         errors vectors if they were present or vectors 
    420         of zeros when none was found. 
    421          
    422         :param other: other data set for operation 
    423          
    424         :return: bool 
    425          
    426         :raise ValueError: when data types are not compatible 
    427          
    428         """ 
    429         if not isinstance(other, Data2D): 
    430             msg = "Unable to perform operation: different types of data set" 
    431             raise ValueError, msg    
    432         return True 
    433      
     365 
    434366    def _perform_operation(self, other, operation): 
    435367        """ 
  • src/sas/sasgui/perspectives/calculator/data_operator.py

    r0e760e9 r61780e3  
    397397            self._set_textctrl_color(self.data1_cbox, 'pink') 
    398398            self._set_textctrl_color(self.data2_cbox, 'pink') 
    399             msg = "DataOperation: Data types must be same." 
     399            msg = "DataOperation: %s" % sys.exc_value 
    400400            self.send_warnings(msg, 'error') 
    401401            self.output = None 
  • src/sas/sasgui/perspectives/fitting/fitting.py

    re89aed5 rff3f5821  
    17421742                                      data_id=str(page_id) + " " + data.name + " unsmeared") 
    17431743 
    1744                 self.create_theory_1D(x, unsmeared_data, page_id, model, data, state, 
    1745                                       data_description="Data unsmeared", 
    1746                                       data_id="Data  " + data.name + " unsmeared", 
    1747                                       dy=unsmeared_error) 
     1744                if unsmeared_data is not None and unsmeared_error is not None: 
     1745                    self.create_theory_1D(x, unsmeared_data, page_id, model, data, state, 
     1746                                          data_description="Data unsmeared", 
     1747                                          data_id="Data  " + data.name + " unsmeared", 
     1748                                          dy=unsmeared_error) 
    17481749                 
    17491750            if sq_model is not None and pq_model is not None: 
  • src/sas/sasgui/perspectives/fitting/model_thread.py

    rca4d985 r286c757  
    179179            unsmeared_output[first_bin:last_bin+1] = self.model.evalDistribution(mask) 
    180180            output = self.smearer(unsmeared_output, first_bin, last_bin) 
    181              
     181 
    182182            # Rescale data to unsmeared model 
    183             unsmeared_data = numpy.zeros((len(self.data.x))) 
    184             unsmeared_error = numpy.zeros((len(self.data.x))) 
    185             unsmeared_data[first_bin:last_bin+1] = self.data.y[first_bin:last_bin+1]\ 
    186                                                     * unsmeared_output[first_bin:last_bin+1]\ 
    187                                                     / output[first_bin:last_bin+1] 
    188             unsmeared_error[first_bin:last_bin+1] = self.data.dy[first_bin:last_bin+1]\ 
    189                                                     * unsmeared_output[first_bin:last_bin+1]\ 
    190                                                     / output[first_bin:last_bin+1] 
    191             unsmeared_output=unsmeared_output[index] 
    192             unsmeared_data=unsmeared_data[index] 
    193             unsmeared_error=unsmeared_error 
     183            # Check that the arrays are compatible. If we only have a model but no data, 
     184            # the length of data.y will be zero. 
     185            if isinstance(self.data.y, numpy.ndarray) and output.shape == self.data.y.shape: 
     186                unsmeared_data = numpy.zeros((len(self.data.x))) 
     187                unsmeared_error = numpy.zeros((len(self.data.x))) 
     188                unsmeared_data[first_bin:last_bin+1] = self.data.y[first_bin:last_bin+1]\ 
     189                                                        * unsmeared_output[first_bin:last_bin+1]\ 
     190                                                        / output[first_bin:last_bin+1] 
     191                unsmeared_error[first_bin:last_bin+1] = self.data.dy[first_bin:last_bin+1]\ 
     192                                                        * unsmeared_output[first_bin:last_bin+1]\ 
     193                                                        / output[first_bin:last_bin+1] 
     194                unsmeared_output=unsmeared_output[index] 
     195                unsmeared_data=unsmeared_data[index] 
     196                unsmeared_error=unsmeared_error 
    194197        else: 
    195198            output[index] = self.model.evalDistribution(self.data.x[index]) 
  • src/sas/sasgui/guiframe/data_panel.py

    re767897 r998ca90  
    890890 
    891891 
    892     def on_remove(self, event): 
     892    def on_remove(self, event, msg=""): 
    893893        """ 
    894894        Get a list of item checked and remove them from the treectrl 
    895895        Ask the parent to remove reference to this item 
    896896        """ 
    897         msg = "This operation will delete the data sets checked " 
    898         msg += "and all the dependents." 
     897        if msg == "": 
     898            msg = "This operation will delete the data sets checked " 
     899            msg += "and all the dependents." 
    899900        msg_box = wx.MessageDialog(None, msg, 'Warning', wx.OK|wx.CANCEL) 
    900901        if msg_box.ShowModal() != wx.ID_OK: 
    901             return 
     902            return True 
    902903 
    903904        data_to_remove, theory_to_remove, _ = self.set_data_helper() 
  • src/sas/sasgui/guiframe/gui_manager.py

    r3fac0df r998ca90  
    19041904        if self._default_save_location == None: 
    19051905            self._default_save_location = os.getcwd() 
    1906         wx.PostEvent(self, StatusEvent(status="Loading Project file...")) 
    1907         dlg = wx.FileDialog(self, 
     1906        msg = "This operation will set SasView to its freshly opened state " 
     1907        msg += "before loading the project. Do you wish to continue?" 
     1908        if not self._data_panel.on_remove(None, msg): 
     1909            wx.PostEvent(self, StatusEvent(status="Loading Project file...")) 
     1910            dlg = wx.FileDialog(self, 
    19081911                            "Choose a file", 
    19091912                            self._default_save_location, "", 
    19101913                            APPLICATION_WLIST) 
    1911         if dlg.ShowModal() == wx.ID_OK: 
    1912             path = dlg.GetPath() 
     1914            if dlg.ShowModal() == wx.ID_OK: 
     1915                path = dlg.GetPath() 
    19131916            if path is not None: 
    19141917                self._default_save_location = os.path.dirname(path) 
    1915         dlg.Destroy() 
    1916  
    1917         self.load_state(path=path, is_project=True) 
     1918                dlg.Destroy() 
     1919 
     1920            # Reset to a base state 
     1921            self._on_reset_state() 
     1922 
     1923            # Load the project file 
     1924            self.load_state(path=path, is_project=True) 
     1925 
     1926    def _on_reset_state(self): 
     1927        """ 
     1928        Resets SasView to its freshly opened state. 
     1929        :return: None 
     1930        """ 
     1931        # Reset all plugins to their base state 
     1932        for plugin in self.plugins: 
     1933            plugin.clear_panel() 
     1934        # Reset plot number to 0 
     1935        self.graph_num = 0 
     1936        # Remove all loaded data 
     1937        self._data_panel.selection_cbox.SetValue('Select all Data') 
     1938        self._data_panel._on_selection_type(None) 
    19181939 
    19191940    def _on_save_application(self, event): 
     
    20632084            except: 
    20642085                logging.info("Failed to connect to www.sasview.org") 
    2065         self._process_version(version_info, standalone=event == None)     
    2066  
    2067          
    2068          
    2069 #          
    2070 #         try: 
    2071 #             req = urllib2.Request(config.__update_URL__) 
    2072 #             res = urllib2.urlopen(req) 
    2073 #             content = res.read().strip() 
    2074 #             logging.info("Connected to www.sasview.org. Latest version: %s" 
    2075 #                          % (content)) 
    2076 #             version_info = json.loads(content) 
    2077 #         except: 
    2078 #             logging.info("Failed to connect to www.sasview.org") 
    2079 #             version_info = {"version": "0.0.0"} 
    2080 #         self._process_version(version_info, standalone=event == None) 
     2086        self._process_version(version_info, standalone=event == None) 
    20812087 
    20822088    def _process_version(self, version_info, standalone=True): 
  • src/sas/sasgui/perspectives/fitting/fitpanel.py

    r05228b0 r998ca90  
    1313from sas.sasgui.guiframe.events import StatusEvent 
    1414from sas.sasgui.guiframe.dataFitting import check_data_validity 
     15from sas.sasgui.perspectives.fitting.simfitpage import SimultaneousFitPage 
    1516 
    1617import basepage 
     
    1819_BOX_WIDTH = 80 
    1920 
     21 
    2022class FitPanel(nb, PanelBase): 
    2123    """ 
     
    2628 
    2729    """ 
    28     ## Internal name for the AUI manager 
     30    # Internal name for the AUI manager 
    2931    window_name = "Fit panel" 
    30     ## Title to appear on top of the window 
     32    # Title to appear on top of the window 
    3133    window_caption = "Fit Panel " 
    3234    CENTER_PANE = True 
     
    4042                    wx.CLIP_CHILDREN) 
    4143        PanelBase.__init__(self, parent) 
    42         #self.SetWindowStyleFlag(style=nb.FNB_FANCY_TABS) 
     44        # self.SetWindowStyleFlag(style=nb.FNB_FANCY_TABS) 
    4345        self._manager = manager 
    4446        self.parent = parent 
    4547        self.event_owner = None 
    46         #dictionary of miodel {model class name, model class} 
     48        # dictionary of miodel {model class name, model class} 
    4749        self.menu_mng = models.ModelManager() 
    4850        self.model_list_box = self.menu_mng.get_model_list() 
    49         #pageClosedEvent = nb.EVT_FLATNOTEBOOK_PAGE_CLOSING 
     51        # pageClosedEvent = nb.EVT_FLATNOTEBOOK_PAGE_CLOSING 
    5052        self.model_dictionary = self.menu_mng.get_model_dictionary() 
    5153        self.pageClosedEvent = wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE 
    5254 
    5355        self.Bind(self.pageClosedEvent, self.on_close_page) 
    54         ## save the title of the last page tab added 
     56        # save the title of the last page tab added 
    5557        self.fit_page_name = {} 
    56         ## list of existing fit page 
     58        # list of existing fit page 
    5759        self.opened_pages = {} 
    58         #index of fit page 
     60        # index of fit page 
    5961        self.fit_page_index = 0 
    60         #index of batch page 
     62        # index of batch page 
    6163        self.batch_page_index = 0 
    62         #page of simultaneous fit 
     64        # page of simultaneous fit 
    6365        self.sim_page = None 
    6466        self.batch_page = None 
    65         ## get the state of a page 
     67        # get the state of a page 
    6668        self.Bind(basepage.EVT_PAGE_INFO, self._onGetstate) 
    6769        self.Bind(basepage.EVT_PREVIOUS_STATE, self._onUndo) 
     
    8082        """ 
    8183        return an xml node containing state of the panel 
    82          that guiframe can write to file 
    83         """ 
    84         msg = "" 
     84        that guiframe can write to file 
     85        """ 
     86        # Iterate through all pages and check for batch fitting 
     87        batch_state = None 
     88        if self.sim_page is not None: 
     89            batch_state = self.sim_page.set_state() 
     90 
    8591        for uid, page in self.opened_pages.iteritems(): 
    86             if page.batch_on: 
    87                 pos = self.GetPageIndex(page) 
    88                 if pos != -1 and page not in [self.sim_page, self.batch_page]: 
    89                     msg += "%s .\n" % str(self.GetPageText(pos)) 
    90             else: 
    91                 data = page.get_data() 
    92                 # state must be cloned 
    93                 state = page.get_state().clone() 
    94                 if data is not None and page.model is not None: 
    95                     new_doc = self._manager.state_reader.write_toXML(data, 
    96                                                                      state) 
    97                     if doc != None and hasattr(doc, "firstChild"): 
    98                         child = new_doc.firstChild.firstChild 
    99                         doc.firstChild.appendChild(child) 
    100                     else: 
    101                         doc = new_doc 
    102         if msg.strip() != "": 
    103             temp = "Save Project is not supported for Batch page.\n" 
    104             temp += "The following pages will not be save:\n" 
    105             message = temp + msg 
    106             wx.PostEvent(self._manager.parent, StatusEvent(status=message, 
    107                                                             info="warning")) 
     92            data = page.get_data() 
     93            # state must be cloned 
     94            state = page.get_state().clone() 
     95            if data is not None or page.model is not None: 
     96                new_doc = self._manager.state_reader.write_toXML(data, 
     97                                                                 state, 
     98                                                                 batch_state) 
     99                if doc is not None and hasattr(doc, "firstChild"): 
     100                    child = new_doc.firstChild.firstChild 
     101                    doc.firstChild.appendChild(child) 
     102                else: 
     103                    doc = new_doc 
     104 
    108105        return doc 
    109106 
     
    203200            nop = nop - 1 
    204201 
    205         ## save the title of the last page tab added 
     202        # save the title of the last page tab added 
    206203        self.fit_page_name = {} 
    207         ## list of existing fit page 
     204        # list of existing fit page 
    208205        self.opened_pages = {} 
     206        self.fit_page_index = 0 
     207        self.batch_page_index = 0 
    209208 
    210209    def set_state(self, state): 
     
    245244        self.close_all() 
    246245        self._manager.mypanels = [] 
     246        self.sim_page = None 
     247        self.batch_page = None 
    247248 
    248249    def on_close_page(self, event=None): 
     
    363364            panel.set_index_model(self.batch_page_index) 
    364365        else: 
    365             #Increment index of fit page 
     366            # Increment index of fit page 
    366367            panel = FitPage(parent=self) 
    367368            self.fit_page_index += 1 
     
    526527                    self.SetSelection(pos) 
    527528                    return page 
    528         #create new page and add data 
     529        # create new page and add data 
    529530        page = self.add_empty_page() 
    530531        pos = self.GetPageIndex(page) 
  • src/sas/sasgui/perspectives/fitting/pagestate.py

    r6c382da r998ca90  
    22    Class that holds a fit page state 
    33""" 
    4 #TODO: Refactor code so we don't need to use getattr/setattr 
     4# TODO: Refactor code so we don't need to use getattr/setattr 
    55################################################################################ 
    6 #This software was developed by the University of Tennessee as part of the 
    7 #Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
    8 #project funded by the US National Science Foundation. 
     6# This software was developed by the University of Tennessee as part of the 
     7# Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
     8# project funded by the US National Science Foundation. 
    99# 
    10 #See the license text in license.txt 
     10# See the license text in license.txt 
    1111# 
    12 #copyright 2009, University of Tennessee 
     12# copyright 2009, University of Tennessee 
    1313################################################################################ 
    1414import time 
     
    3030from sas.sascalc.dataloader.readers.cansas_reader import Reader as CansasReader 
    3131from sas.sascalc.dataloader.readers.cansas_reader import get_content, write_node 
    32 from sas.sascalc.dataloader.data_info import Data2D 
    33 from sas.sascalc.dataloader.data_info import Collimation 
    34 from sas.sascalc.dataloader.data_info import Detector 
    35 from sas.sascalc.dataloader.data_info import Process 
    36 from sas.sascalc.dataloader.data_info import Aperture 
    37 #Information to read/write state as xml 
     32from sas.sascalc.dataloader.data_info import Data2D, Collimation, Detector 
     33from sas.sascalc.dataloader.data_info import Process, Aperture 
     34# Information to read/write state as xml 
    3835FITTING_NODE_NAME = 'fitting_plug_in' 
    3936CANSAS_NS = "cansas1d/1.0" 
     
    123120            try: 
    124121                return node.get(item[0]).strip() == "True" 
    125  
    126122            except: 
    127123                return None 
     
    146142        """ 
    147143        self.file = None 
    148         #Time of state creation 
     144        # Time of state creation 
    149145        self.timestamp = time.time() 
    150         ## Data member to store the dispersion object created 
     146        # Data member to store the dispersion object created 
    151147        self._disp_obj_dict = {} 
    152         #------------------------ 
    153         #Data used for fitting 
     148        # ------------------------ 
     149        # Data used for fitting 
    154150        self.data = data 
    155151        # model data 
    156152        self.theory_data = None 
    157         #Is 2D 
     153        # Is 2D 
    158154        self.is_2D = False 
    159155        self.images = None 
    160156 
    161         #save additional information on data that dataloader.reader does not read 
     157        # save additional information on data that dataloader.reader 
     158        # does not read 
    162159        self.is_data = None 
    163160        self.data_name = "" 
     
    172169            self.data_group_id = self.data.group_id 
    173170 
    174         ## reset True change the state of exsiting button 
     171        # reset True change the state of existing button 
    175172        self.reset = False 
    176173 
     
    180177        self.model = model 
    181178        self.m_name = None 
    182         #list of process done to model 
     179        # list of process done to model 
    183180        self.process = [] 
    184         #fit page manager 
     181        # fit page manager 
    185182        self.manager = None 
    186         #Store the parent of this panel parent 
     183        # Store the parent of this panel parent 
    187184        # For this application fitpanel is the parent 
    188185        self.parent = parent 
    189186        # Event_owner is the owner of model event 
    190187        self.event_owner = None 
    191         ##page name 
     188        # page name 
    192189        self.page_name = "" 
    193190        # Contains link between model, all its parameters, and panel organization 
     
    196193        self.str_parameters = [] 
    197194        # Contains list of parameters that cannot be fitted and reference to 
    198         #panel objects 
     195        # panel objects 
    199196        self.fixed_param = [] 
    200197        # Contains list of parameters with dispersity and reference to 
    201         #panel objects 
     198        # panel objects 
    202199        self.fittable_param = [] 
    203         ## orientation parameters 
     200        # orientation parameters 
    204201        self.orientation_params = [] 
    205         ## orientation parameters for gaussian dispersity 
     202        # orientation parameters for gaussian dispersity 
    206203        self.orientation_params_disp = [] 
    207         ## smearer info 
     204        # smearer info 
    208205        self.smearer = None 
    209206        self.smear_type = None 
     
    214211        self.dxl = None 
    215212        self.dxw = None 
    216         #list of dispersion parameters 
     213        # list of dispersion parameters 
    217214        self.disp_list = [] 
    218215        if self.model is not None: 
     
    223220        self.weights = {} 
    224221 
    225         #contains link between a model and selected parameters to fit 
     222        # contains link between a model and selected parameters to fit 
    226223        self.param_toFit = [] 
    227         ##dictionary of model type and model class 
     224        # dictionary of model type and model class 
    228225        self.model_list_box = None 
    229         ## save the state of the context menu 
     226        # save the state of the context menu 
    230227        self.saved_states = {} 
    231         ## save selection of combobox 
     228        # save selection of combobox 
    232229        self.formfactorcombobox = None 
    233230        self.categorycombobox = None 
    234231        self.structurecombobox = None 
    235232 
    236         ## radio box to select type of model 
    237         #self.shape_rbutton = False 
    238         #self.shape_indep_rbutton = False 
    239         #self.struct_rbutton = False 
    240         #self.plugin_rbutton = False 
    241         ## the indice of the current selection 
     233        # radio box to select type of model 
     234        # self.shape_rbutton = False 
     235        # self.shape_indep_rbutton = False 
     236        # self.struct_rbutton = False 
     237        # self.plugin_rbutton = False 
     238        # the indice of the current selection 
    242239        self.disp_box = 0 
    243         ## Qrange 
    244         ## Q range 
     240        # Qrange 
     241        # Q range 
    245242        self.qmin = 0.001 
    246243        self.qmax = 0.1 
    247         #reset data range 
     244        # reset data range 
    248245        self.qmax_x = None 
    249246        self.qmin_x = None 
     
    253250        self.multi_factor = None 
    254251        self.magnetic_on = False 
    255         ## enable smearering state 
     252        # enable smearering state 
    256253        self.enable_smearer = False 
    257254        self.disable_smearer = True 
     
    263260        self.dI_sqrdata = False 
    264261        self.dI_idata = False 
    265         ## disperity selection 
     262        # disperity selection 
    266263        self.enable_disp = False 
    267264        self.disable_disp = True 
    268265 
    269         ## state of selected all check button 
     266        # state of selected all check button 
    270267        self.cb1 = False 
    271         ## store value of chisqr 
     268        # store value of chisqr 
    272269        self.tcChi = None 
    273270 
     
    293290        obj.structurecombobox = self.structurecombobox 
    294291 
    295         #obj.shape_rbutton = self.shape_rbutton 
    296         #obj.shape_indep_rbutton = self.shape_indep_rbutton 
    297         #obj.struct_rbutton = self.struct_rbutton 
    298         #obj.plugin_rbutton = self.plugin_rbutton 
     292        # obj.shape_rbutton = self.shape_rbutton 
     293        # obj.shape_indep_rbutton = self.shape_indep_rbutton 
     294        # obj.struct_rbutton = self.struct_rbutton 
     295        # obj.plugin_rbutton = self.plugin_rbutton 
    299296 
    300297        obj.manager = self.manager 
     
    381378 
    382379        rep += "State created: %s\n" % time_str 
    383         rep += "State form factor combobox selection: %s\n" % self.formfactorcombobox 
    384         rep += "State structure factor combobox selection: %s\n" % self.structurecombobox 
     380        rep += "State form factor combobox selection: %s\n" % \ 
     381               self.formfactorcombobox 
     382        rep += "State structure factor combobox selection: %s\n" % \ 
     383               self.structurecombobox 
    385384        rep += "is data : %s\n" % self.is_data 
    386385        rep += "data's name : %s\n" % self.data_name 
    387386        rep += "data's id : %s\n" % self.data_id 
    388         if self.model != None: 
     387        if self.model is not None: 
    389388            m_name = self.model.__class__.__name__ 
    390389            if m_name == 'Model': 
     
    397396        rep += "model type (Category) selected: %s\n" % self.categorycombobox 
    398397        rep += "data : %s\n" % str(self.data) 
    399         rep += "Plotting Range: min: %s, max: %s, steps: %s\n" % (str(self.qmin), 
    400                                                                   str(self.qmax), str(self.npts)) 
     398        rep += "Plotting Range: min: %s, max: %s, steps: %s\n" % \ 
     399               (str(self.qmin),str(self.qmax), str(self.npts)) 
    401400        rep += "Dispersion selection : %s\n" % str(self.disp_box) 
    402401        rep += "Smearing enable : %s\n" % str(self.enable_smearer) 
     
    414413 
    415414        rep += "2D enable : %s\n" % str(self.enable2D) 
    416         rep += "All parameters checkbox selected: %s\n" % (self.cb1) 
     415        rep += "All parameters checkbox selected: %s\n" % str(self.cb1) 
    417416        rep += "Value of Chisqr : %s\n" % str(self.tcChi) 
    418417        rep += "Smear object : %s\n" % str(self.smearer) 
    419         rep += "Smear type : %s\n" % (self.smear_type) 
     418        rep += "Smear type : %s\n" % str(self.smear_type) 
    420419        rep += "dq_l  : %s\n" % self.dq_l 
    421420        rep += "dq_r  : %s\n" % self.dq_r 
     
    434433            if not self.is_2D: 
    435434                for item in self.parameters: 
    436                     if not item in self.orientation_params: 
     435                    if item not in self.orientation_params: 
    437436                        temp_parameters.append(item) 
    438437                for item in self.fittable_param: 
    439                     if not item in self.orientation_params_disp: 
     438                    if item not in self.orientation_params_disp: 
    440439                        temp_fittable_param.append(item) 
    441440            else: 
     
    443442                temp_fittable_param = self.fittable_param 
    444443 
    445             rep += "number parameters(self.parameters): %s\n" % len(temp_parameters) 
     444            rep += "number parameters(self.parameters): %s\n" % \ 
     445                   len(temp_parameters) 
    446446            rep = self._repr_helper(list=temp_parameters, rep=rep) 
    447             rep += "number str_parameters(self.str_parameters): %s\n" % len(self.str_parameters) 
     447            rep += "number str_parameters(self.str_parameters): %s\n" % \ 
     448                   len(self.str_parameters) 
    448449            rep = self._repr_helper(list=self.str_parameters, rep=rep) 
    449             rep += "number fittable_param(self.fittable_param): %s\n" % len(temp_fittable_param) 
     450            rep += "number fittable_param(self.fittable_param): %s\n" % \ 
     451                   len(temp_fittable_param) 
    450452            rep = self._repr_helper(list=temp_fittable_param, rep=rep) 
    451453        return rep 
     
    551553                    paramval_string += CENTRE % param + "\n" 
    552554 
    553         text_string = "\n\n\n%s\n\n%s\n%s\n%s\n\n%s" % (title, file, q_name, chi2, paramval) 
     555        text_string = "\n\n\n%s\n\n%s\n%s\n%s\n\n%s" % \ 
     556                      (title, file, q_name, chi2, paramval) 
    554557 
    555558        title_name = self._check_html_format(title_name) 
     
    632635            element.appendChild(sub_element) 
    633636 
    634     def toXML(self, file="fitting_state.fitv", doc=None, entry_node=None): 
    635         """ 
    636         Writes the state of the InversionControl panel to file, as XML. 
     637    def toXML(self, file="fitting_state.fitv", doc=None, 
     638              entry_node=None, batch_fit_state=None): 
     639        """ 
     640        Writes the state of the fit panel to file, as XML. 
    637641 
    638642        Compatible with standalone writing, or appending to an 
    639         already existing XML document. In that case, the XML document 
    640         is required. An optional entry node in the XML document may also be given. 
     643        already existing XML document. In that case, the XML document is 
     644        required. An optional entry node in the XML document may also be given. 
    641645 
    642646        :param file: file to write to 
    643647        :param doc: XML document object [optional] 
    644         :param entry_node: XML node within the XML document at which we will append the data [optional] 
    645  
     648        :param entry_node: XML node within the XML document at which we 
     649                           will append the data [optional] 
    646650        """ 
    647651        from xml.dom.minidom import getDOMImplementation 
     
    691695        element.setAttributeNode(attr) 
    692696        top_element.appendChild(element) 
     697 
    693698        # Inputs 
    694699        inputs = newdoc.createElement("Attributes") 
     
    741746        for item in LIST_OF_STATE_PARAMETERS: 
    742747            element = newdoc.createElement(item[0]) 
    743             self._toXML_helper(thelist=getattr(self, item[1]), element=element, newdoc=newdoc) 
     748            self._toXML_helper(thelist=getattr(self, item[1]), 
     749                               element=element, newdoc=newdoc) 
    744750            inputs.appendChild(element) 
     751 
     752        # Combined and Simultaneous Fit Parameters 
     753        if batch_fit_state is not None: 
     754            batch_combo = newdoc.createElement('simultaneous_fit') 
     755            top_element.appendChild(batch_combo) 
     756 
     757            # Simultaneous Fit Number For Linking Later 
     758            element = newdoc.createElement('sim_fit_number') 
     759            element.setAttribute('fit_number', str(batch_fit_state.fit_page_no)) 
     760            batch_combo.appendChild(element) 
     761 
     762            # Save constraints 
     763            constraints = newdoc.createElement('constraints') 
     764            batch_combo.appendChild(constraints) 
     765            for constraint in batch_fit_state.constraints_list: 
     766                if constraint.model_cbox.GetValue() != "": 
     767                    # model_cbox, param_cbox, egal_txt, constraint, btRemove, sizer 
     768                    doc_cons = newdoc.createElement('constraint') 
     769                    doc_cons.setAttribute('model_cbox', 
     770                                          str(constraint.model_cbox.GetValue())) 
     771                    doc_cons.setAttribute('param_cbox', 
     772                                          str(constraint.param_cbox.GetValue())) 
     773                    doc_cons.setAttribute('egal_txt', 
     774                                          str(constraint.egal_txt.GetLabel())) 
     775                    doc_cons.setAttribute('constraint', 
     776                                          str(constraint.constraint.GetValue())) 
     777                    constraints.appendChild(doc_cons) 
     778 
     779            # Save all models 
     780            models = newdoc.createElement('model_list') 
     781            batch_combo.appendChild(models) 
     782            for model in batch_fit_state.model_list: 
     783                doc_model = newdoc.createElement('model_list_item') 
     784                doc_model.setAttribute('checked', str(model[0].GetValue())) 
     785                keys = model[1].keys() 
     786                doc_model.setAttribute('name', str(keys[0])) 
     787                values = model[1].get(keys[0]) 
     788                doc_model.setAttribute('fit_number', str(model[2])) 
     789                doc_model.setAttribute('fit_page_source', str(model[3])) 
     790                doc_model.setAttribute('model_name', str(values.model.id)) 
     791                models.appendChild(doc_model) 
     792 
     793            # Select All Checkbox 
     794            element = newdoc.createElement('select_all') 
     795            if batch_fit_state.select_all: 
     796                element.setAttribute('checked', 'True') 
     797            else: 
     798                element.setAttribute('checked', 'False') 
     799            batch_combo.appendChild(element) 
    745800 
    746801        # Save the file 
     
    809864        :param file: .fitv file 
    810865        :param node: node of a XML document to read from 
    811  
    812866        """ 
    813867        if file is not None: 
     
    816870            raise RuntimeError, msg 
    817871 
    818         if node.get('version')and node.get('version') == '1.0': 
     872        if node.get('version') and node.get('version') == '1.0': 
    819873 
    820874            # Get file name 
     
    862916                                value = cls.type 
    863917                            except Exception: 
    864                                 logging.error("unable to load distribution %r for %s" 
    865                                               % (value, parameter)) 
     918                                base = "unable to load distribution %r for %s" 
     919                                logging.error(base % (value, parameter)) 
    866920                                continue 
    867921                        _disp_obj_dict = getattr(self, varname) 
     
    9601014        self.cansas = cansas 
    9611015        self.state = None 
     1016        # batch fitting params for saving 
     1017        self.batchfit_params = [] 
    9621018 
    9631019    def get_state(self): 
     
    9841040            raise RuntimeError, "The cansas writer expects a Data2D instance" 
    9851041 
     1042        title = "cansas1d/%s" % self.version 
     1043        title += "http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" 
    9861044        doc = xml.dom.minidom.Document() 
    9871045        main_node = doc.createElement("SASroot") 
    9881046        main_node.setAttribute("version", self.version) 
    9891047        main_node.setAttribute("xmlns", "cansas1d/%s" % self.version) 
    990         main_node.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") 
    991         main_node.setAttribute("xsi:schemaLocation", 
    992                                "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version) 
     1048        main_node.setAttribute("xmlns:xsi", 
     1049                               "http://www.w3.org/2001/XMLSchema-instance") 
     1050        main_node.setAttribute("xsi:schemaLocation", title) 
    9931051 
    9941052        doc.appendChild(main_node) 
     
    9991057        write_node(doc, entry_node, "Title", datainfo.title) 
    10001058        if datainfo is not None: 
    1001             write_node(doc, entry_node, "data_class", datainfo.__class__.__name__) 
     1059            write_node(doc, entry_node, "data_class", 
     1060                       datainfo.__class__.__name__) 
    10021061        for item in datainfo.run: 
    10031062            runname = {} 
    1004             if datainfo.run_name.has_key(item) and len(str(datainfo.run_name[item])) > 1: 
     1063            if datainfo.run_name.has_key(item) and \ 
     1064                            len(str(datainfo.run_name[item])) > 1: 
    10051065                runname = {'name': datainfo.run_name[item]} 
    10061066            write_node(doc, entry_node, "Run", item, runname) 
     
    12191279 
    12201280        :param entry: XML node to read from 
    1221  
    12221281        :return: PageState object 
    12231282        """ 
     
    12281287            nodes = entry.xpath('ns:%s' % FITTING_NODE_NAME, 
    12291288                                namespaces={'ns': CANSAS_NS}) 
    1230             if nodes != []: 
     1289            if nodes: 
    12311290                # Create an empty state 
    12321291                state = PageState() 
     
    12381297 
    12391298        return state 
     1299 
     1300    def _parse_simfit_state(self, entry): 
     1301        """ 
     1302        Parses the saved data for a simultaneous fit 
     1303        :param entry: XML object to read from 
     1304        :return: XML object for a simultaneous fit or None 
     1305        """ 
     1306        nodes = entry.xpath('ns:%s' % FITTING_NODE_NAME, 
     1307                            namespaces={'ns': CANSAS_NS}) 
     1308        if nodes: 
     1309            simfitstate = nodes[0].xpath('ns:simultaneous_fit', 
     1310                                         namespaces={'ns': CANSAS_NS}) 
     1311            if simfitstate: 
     1312                from simfitpage import SimFitPageState 
     1313                sim_fit_state = SimFitPageState() 
     1314                simfitstate_0 = simfitstate[0] 
     1315                all = simfitstate_0.xpath('ns:select_all', 
     1316                                        namespaces={'ns': CANSAS_NS}) 
     1317                atts = all[0].attrib 
     1318                checked = atts.get('checked') 
     1319                sim_fit_state.select_all = bool(checked) 
     1320                model_list = simfitstate_0.xpath('ns:model_list', 
     1321                                               namespaces={'ns': CANSAS_NS}) 
     1322                model_list_items = model_list[0].xpath('ns:model_list_item', 
     1323                                                   namespaces={'ns': CANSAS_NS}) 
     1324                for model in model_list_items: 
     1325                    attrs = model.attrib 
     1326                    sim_fit_state.model_list.append(attrs) 
     1327 
     1328                constraints = simfitstate_0.xpath('ns:constraints', 
     1329                                                namespaces={'ns': CANSAS_NS}) 
     1330                constraint_list = constraints[0].xpath('ns:constraint', 
     1331                                               namespaces={'ns': CANSAS_NS}) 
     1332                for constraint in constraint_list: 
     1333                    attrs = constraint.attrib 
     1334                    sim_fit_state.constraints_list.append(attrs) 
     1335 
     1336                return sim_fit_state 
     1337            else: 
     1338                return None 
    12401339 
    12411340    def _parse_save_state_entry(self, dom): 
     
    12981397                        data_info.notes.append(note_value) 
    12991398            except Exception: 
    1300                 err_mess = "cansas_reader.read: error processing entry notes\n  %s" % sys.exc_value 
     1399                err_mess = "cansas_reader.read: error processing entry notes\n" 
     1400                err_mess += "  %s" % sys.exc_value 
    13011401                self.errors.append(err_mess) 
    13021402                logging.error(err_mess) 
     
    13081408 
    13091409        self._store_content('ns:SASsample/ns:ID', dom, 'ID', data_info.sample) 
    1310         self._store_float('ns:SASsample/ns:thickness', dom, 'thickness', data_info.sample) 
    1311         self._store_float('ns:SASsample/ns:transmission', dom, 'transmission', data_info.sample) 
    1312         self._store_float('ns:SASsample/ns:temperature', dom, 'temperature', data_info.sample) 
    1313  
    1314         nodes = dom.xpath('ns:SASsample/ns:details', namespaces={'ns': CANSAS_NS}) 
     1410        self._store_float('ns:SASsample/ns:thickness', dom, 'thickness', 
     1411                          data_info.sample) 
     1412        self._store_float('ns:SASsample/ns:transmission', dom, 'transmission', 
     1413                          data_info.sample) 
     1414        self._store_float('ns:SASsample/ns:temperature', dom, 'temperature', 
     1415                          data_info.sample) 
     1416 
     1417        nodes = dom.xpath('ns:SASsample/ns:details', 
     1418                          namespaces={'ns': CANSAS_NS}) 
    13151419        for item in nodes: 
    13161420            try: 
     
    13201424                        data_info.sample.details.append(detail_value) 
    13211425            except Exception: 
    1322                 err_mess = "cansas_reader.read: error processing sample details\n  %s" % sys.exc_value 
     1426                err_mess = "cansas_reader.read: error processing entry notes\n" 
     1427                err_mess += "  %s" % sys.exc_value 
    13231428                self.errors.append(err_mess) 
    13241429                logging.error(err_mess) 
    13251430 
    13261431        # Position (as a vector) 
    1327         self._store_float('ns:SASsample/ns:position/ns:x', dom, 'position.x', data_info.sample) 
    1328         self._store_float('ns:SASsample/ns:position/ns:y', dom, 'position.y', data_info.sample) 
    1329         self._store_float('ns:SASsample/ns:position/ns:z', dom, 'position.z', data_info.sample) 
     1432        self._store_float('ns:SASsample/ns:position/ns:x', dom, 'position.x', 
     1433                          data_info.sample) 
     1434        self._store_float('ns:SASsample/ns:position/ns:y', dom, 'position.y', 
     1435                          data_info.sample) 
     1436        self._store_float('ns:SASsample/ns:position/ns:z', dom, 'position.z', 
     1437                          data_info.sample) 
    13301438 
    13311439        # Orientation (as a vector) 
     
    14611569                        process.term.append(term_attr) 
    14621570                except: 
    1463                     err_mess = "cansas_reader.read: error processing process term\n  %s" % sys.exc_value 
     1571                    err_mess = "cansas_reader.read: error processing " 
     1572                    err_mess += "entry notes\n  %s" % sys.exc_value 
    14641573                    self.errors.append(err_mess) 
    14651574                    logging.error(err_mess) 
     
    14761585        nodes = dom.xpath('ns:SASdata', namespaces={'ns': CANSAS_NS}) 
    14771586        if len(nodes) > 1: 
    1478             raise RuntimeError, "CanSAS reader is not compatible with multiple SASdata entries" 
     1587            raise RuntimeError, "CanSAS reader is not compatible with" + \ 
     1588                                " multiple SASdata entries" 
    14791589 
    14801590        for entry in nodes: 
     
    14881598                value_list = [] 
    14891599                if field is not None: 
    1490                     value_list = [parse_entry_helper(node, item) for node in field] 
     1600                    value_list = \ 
     1601                        [parse_entry_helper(node, item) for node in field] 
    14911602                if len(value_list) < 2: 
    14921603                    setattr(data_info, item[0], None) 
     
    14981609    def _read_cansas(self, path): 
    14991610        """ 
    1500         Load data and P(r) information from a CanSAS XML file. 
     1611        Load data and fitting information from a CanSAS XML file. 
    15011612 
    15021613        :param path: file path 
    1503  
    15041614        :return: Data1D object if a single SASentry was found, 
    15051615                    or a list of Data1D objects if multiple entries were found, 
    15061616                    or None of nothing was found 
    1507  
    15081617        :raise RuntimeError: when the file can't be opened 
    15091618        :raise ValueError: when the length of the data vectors are inconsistent 
    1510  
    15111619        """ 
    15121620        output = [] 
     1621        simfitstate = None 
    15131622        basename = os.path.basename(path) 
    15141623        root, extension = os.path.splitext(basename) 
     
    15161625        try: 
    15171626            if os.path.isfile(path): 
    1518  
    1519                 #TODO: eventually remove the check for .xml once 
    1520                 # the P(r) writer/reader is truly complete. 
    1521                 if  ext in self.ext or \ 
    1522                     ext == '.xml': 
    1523  
     1627                if ext in self.ext or ext == '.xml': 
    15241628                    tree = etree.parse(path, parser=etree.ETCompatXMLParser()) 
    15251629                    # Check the format version number 
    1526                     # Specifying the namespace will take care of the file format version 
     1630                    # Specifying the namespace will take care of the file 
     1631                    # format version 
    15271632                    root = tree.getroot() 
    15281633                    entry_list = root.xpath('ns:SASentry', 
    15291634                                            namespaces={'ns': CANSAS_NS}) 
     1635                    name_map = {} 
    15301636                    for entry in entry_list: 
    15311637                        try: 
     
    15341640                            raise 
    15351641                        fitstate = self._parse_state(entry) 
    1536  
    1537                         #state could be None when .svs file is loaded 
    1538                         #in this case, skip appending to output 
    1539                         if fitstate != None: 
     1642                        simfitstate = self._parse_simfit_state(entry) 
     1643 
     1644                        # state could be None when .svs file is loaded 
     1645                        # in this case, skip appending to output 
     1646                        if fitstate is not None: 
    15401647                            sas_entry.meta_data['fitstate'] = fitstate 
    15411648                            sas_entry.filename = fitstate.file 
    15421649                            output.append(sas_entry) 
     1650 
    15431651            else: 
    15441652                self.call_back(format=ext) 
     
    15801688                        name = original_fname 
    15811689                    state.data.group_id = name 
    1582                     #store state in fitting 
     1690                    # store state in fitting 
    15831691                    self.call_back(state=state, 
    15841692                                   datainfo=output[ind], format=ext) 
    15851693                    self.state = state 
     1694                if simfitstate is not None: 
     1695                    self.call_back(state=simfitstate) 
     1696 
    15861697                return output 
    15871698        except: 
     
    15991710        """ 
    16001711        # Sanity check 
    1601         if self.cansas == True: 
     1712        if self.cansas: 
    16021713            # Add fitting information to the XML document 
    16031714            doc = self.write_toXML(datainfo, fitstate) 
     
    16111722        fd.close() 
    16121723 
    1613     def write_toXML(self, datainfo=None, state=None): 
     1724    def write_toXML(self, datainfo=None, state=None, batchfit=None): 
    16141725        """ 
    16151726        Write toXML, a helper for write(), 
     
    16191730        """ 
    16201731 
    1621         if state.data is None: 
    1622             data = sas.sascalc.dataloader.data_info.Data1D(x=[], y=[]) 
     1732        self.batchfit_params = batchfit 
     1733        if state.data is None or not state.data.is_data: 
    16231734            return None 
    1624         elif not state.data.is_data: 
    1625             return None 
     1735        # make sure title and data run are filled. 
     1736        if state.data.title is None or state.data.title == '': 
     1737            state.data.title = state.data.name 
     1738        if state.data.run_name is None or state.data.run_name == {}: 
     1739            state.data.run = [str(state.data.name)] 
     1740            state.data.run_name[0] = state.data.name 
     1741 
     1742        if issubclass(state.data.__class__, 
     1743                      sas.sascalc.dataloader.data_info.Data1D): 
     1744            data = state.data 
     1745            doc, sasentry = self._to_xml_doc(data) 
    16261746        else: 
    1627             #make sure title and data run is filled up. 
    1628             if state.data.title == None or state.data.title == '': 
    1629                 state.data.title = state.data.name 
    1630             if state.data.run_name == None or state.data.run_name == {}: 
    1631                 state.data.run = [str(state.data.name)] 
    1632                 state.data.run_name[0] = state.data.name 
    1633  
    1634             if issubclass(state.data.__class__, 
    1635                           sas.sascalc.dataloader.data_info.Data1D): 
    1636                 data = state.data 
    1637                 doc, sasentry = self._to_xml_doc(data) 
    1638             else: 
    1639                 data = state.data 
    1640                 doc, sasentry = self._data2d_to_xml_doc(data) 
     1747            data = state.data 
     1748            doc, sasentry = self._data2d_to_xml_doc(data) 
    16411749 
    16421750        if state is not None: 
    1643             doc = state.toXML(doc=doc, file=data.filename, entry_node=sasentry) 
     1751            doc = state.toXML(doc=doc, file=data.filename, entry_node=sasentry, 
     1752                              batch_fit_state=self.batchfit_params) 
    16441753 
    16451754        return doc 
    1646  
    1647 # Simple html report templet 
    1648 HEADER = "<html>\n" 
    1649 HEADER += "<head>\n" 
    1650 HEADER += "<meta http-equiv=Content-Type content='text/html; " 
    1651 HEADER += "charset=windows-1252'> \n" 
    1652 HEADER += "<meta name=Generator >\n" 
    1653 HEADER += "</head>\n" 
    1654 HEADER += "<body lang=EN-US>\n" 
    1655 HEADER += "<div class=WordSection1>\n" 
    1656 HEADER += "<p class=MsoNormal><b><span ><center><font size='4' >" 
    1657 HEADER += "%s</font></center></span></center></b></p>" 
    1658 HEADER += "<p class=MsoNormal>&nbsp;</p>" 
    1659 PARA = "<p class=MsoNormal><font size='4' > %s \n" 
    1660 PARA += "</font></p>" 
    1661 CENTRE = "<p class=MsoNormal><center><font size='4' > %s \n" 
    1662 CENTRE += "</font></center></p>" 
    1663 FEET_1 = \ 
    1664 """ 
    1665 <p class=MsoNormal>&nbsp;</p> 
    1666 <br> 
    1667 <p class=MsoNormal><b><span ><center> <font size='4' > Graph 
    1668 </font></span></center></b></p> 
    1669 <p class=MsoNormal>&nbsp;</p> 
    1670 <center> 
    1671 <br><font size='4' >Model Computation</font> 
    1672 <br><font size='4' >Data: "%s"</font><br> 
    1673 """ 
    1674 FEET_2 = \ 
    1675 """ 
    1676 <img src="%s" > 
    1677 </img> 
    1678 """ 
    1679 FEET_3 = \ 
    1680 """ 
    1681 </center> 
    1682 </div> 
    1683 </body> 
    1684 </html> 
    1685 """ 
    1686 ELINE = "<p class=MsoNormal>&nbsp;</p>" 
    1687  
    1688 if __name__ == "__main__": 
    1689     state = PageState(parent=None) 
    1690     #state.toXML() 
    1691     """ 
    1692  
    1693     file = open("test_state", "w") 
    1694     pickle.dump(state, file) 
    1695     print pickle.dumps(state) 
    1696     state.data_name = "hello---->" 
    1697     pickle.dump(state, file) 
    1698     file = open("test_state", "r") 
    1699     new_state= pickle.load(file) 
    1700     print "new state", new_state 
    1701     new_state= pickle.load(file) 
    1702     print "new state", new_state 
    1703     #print "state", state 
    1704     """ 
    1705     import bsddb 
    1706     import pickle 
    1707     db = bsddb.btopen('file_state.db', 'c') 
    1708     val = (pickle.dumps(state), "hello", "hi") 
    1709     db['state1'] = pickle.dumps(val) 
    1710     print pickle.loads(db['state1']) 
    1711     state.data_name = "hello---->22" 
    1712     db['state2'] = pickle.dumps(state) 
    1713     state.data_name = "hello---->2" 
    1714     db['state3'] = pickle.dumps(state) 
    1715     del db['state3'] 
    1716     state.data_name = "hello---->3" 
    1717     db['state4'] = pickle.dumps(state) 
    1718     new_state = pickle.loads(db['state1']) 
    1719     #print db.last() 
    1720     db.set_location('state2') 
    1721     state.data_name = "hello---->5" 
    1722     db['aastate5'] = pickle.dumps(state) 
    1723     db.keys().sort() 
    1724     print pickle.loads(db['state2']) 
    1725  
    1726     db.close() 
  • src/sas/sasgui/perspectives/fitting/simfitpage.py

    r4cafdff r998ca90  
    99from wx.lib.scrolledpanel import ScrolledPanel 
    1010 
    11 from sas.sasgui.guiframe.events import StatusEvent 
     11from sas.sasgui.guiframe.events import StatusEvent, PanelOnFocusEvent 
    1212from sas.sasgui.guiframe.panel_base import PanelBase 
    13 from sas.sasgui.guiframe.events import PanelOnFocusEvent 
    1413from sas.sasgui.guiframe.utils import IdList 
    1514from sas.sasgui.guiframe.documentation_window import DocumentationWindow 
    1615 
    17 #Control panel width  
     16# Control panel width 
    1817if sys.platform.count("darwin") == 0: 
    1918    PANEL_WID = 420 
     
    2928        'model_cbox param_cbox egal_txt constraint btRemove sizer') 
    3029 
     30 
    3131def get_fittableParam(model): 
    3232    """ 
     
    4747    return fittable_param 
    4848 
     49 
    4950class SimultaneousFitPage(ScrolledPanel, PanelBase): 
    5051    """ 
     
    5354    two data members window_name and window_caption 
    5455    """ 
    55     ## Internal name for the AUI manager 
    56     window_name = "simultaneous Fit page" 
    57     ## Title to appear on top of the window 
     56    # Internal name for the AUI manager 
     57    window_name = "Simultaneous Fit Page" 
     58    # Title to appear on top of the window 
    5859    window_caption = "Simultaneous Fit Page" 
    5960    ID_DOC = wx.NewId() 
     
    7475        self._ids = iter(self._id_pool) 
    7576        self.SetupScrolling() 
    76         ##Font size 
     77        # Font size 
    7778        self.SetWindowVariant(variant=FONT_VARIANT) 
    7879        self.uid = wx.NewId() 
    7980        self.parent = parent 
    8081        self.batch_on = batch_on 
    81         ## store page_finder 
     82        # store page_finder 
    8283        self.page_finder = page_finder 
    83         ## list containing info to set constraint 
    84         ## look like self.constraint_dict[page_id]= page 
     84        # list containing info to set constraint 
     85        # look like self.constraint_dict[page_id]= page 
    8586        self.constraint_dict = {} 
    86         ## item list 
    87         ## self.constraints_list=[combobox1, combobox2,=,textcrtl, button ] 
     87        # item list 
     88        # self.constraints_list=[combobox1, combobox2,=,textcrtl, button ] 
    8889        self.constraints_list = [] 
    89         ## list of current model 
     90        # list of current model 
    9091        self.model_list = [] 
    91         ## selected mdoel to fit 
    92         self.model_toFit = [] 
    93         ## Control the fit state 
     92        # selected model to fit 
     93        self.model_to_fit = [] 
     94        # Control the fit state 
    9495        self.fit_started = False 
    95         ## number of constraint 
     96        # number of constraint 
    9697        self.nb_constraint = 0 
     98        self.state = SimFitPageState() 
    9799        self.model_cbox_left = None 
    98100        self.model_cbox_right = None 
    99         ## draw page 
     101        # draw page 
    100102        self.define_page_structure() 
    101103        self.draw_page() 
     
    107109        """ 
    108110        self.vbox = wx.BoxSizer(wx.VERTICAL) 
    109         self.sizer1 = wx.BoxSizer(wx.VERTICAL) 
    110         self.sizer2 = wx.BoxSizer(wx.VERTICAL) 
    111         self.sizer3 = wx.BoxSizer(wx.VERTICAL) 
    112  
    113         self.sizer1.SetMinSize((PANEL_WID, -1)) 
    114         self.sizer2.SetMinSize((PANEL_WID, -1)) 
    115         self.sizer3.SetMinSize((PANEL_WID, -1)) 
    116         self.vbox.Add(self.sizer1) 
    117         self.vbox.Add(self.sizer2) 
    118         self.vbox.Add(self.sizer3) 
     111        self.data_selection_sizer = wx.BoxSizer(wx.VERTICAL) 
     112        self.constraints_sizer = wx.BoxSizer(wx.VERTICAL) 
     113        self.run_fit_sizer = wx.BoxSizer(wx.VERTICAL) 
     114 
     115        self.data_selection_sizer.SetMinSize((PANEL_WID, -1)) 
     116        self.constraints_sizer.SetMinSize((PANEL_WID, -1)) 
     117        self.run_fit_sizer.SetMinSize((PANEL_WID, -1)) 
     118        self.vbox.Add(self.data_selection_sizer) 
     119        self.vbox.Add(self.constraints_sizer) 
     120        self.vbox.Add(self.run_fit_sizer) 
    119121        self.SetSizer(self.vbox) 
    120122        self.Centre() 
     123 
     124    def set_state(self): 
     125        """ 
     126        Define a set of state parameters for saving simultaneous fits. 
     127        """ 
     128        self._set_constraint() 
     129        self.state.fit_page_no = self.uid 
     130        self.state.select_all = self.cb1.GetValue() 
     131        self.state.model_list = self.model_list 
     132        self.state.model_to_fit = self.model_to_fit 
     133        self.state.no_constraint = self.nb_constraint 
     134        self.state.constraint_dict = self.constraint_dict 
     135        self.state.constraints_list = self.constraints_list 
     136        return self.get_state() 
     137 
     138    def get_state(self): 
     139        """ 
     140        Return the state of the current page 
     141        :return: self.state 
     142        """ 
     143        return self.state 
    121144 
    122145    def draw_page(self): 
     
    131154        # create blank list of constraints 
    132155        self.model_list = [] 
    133         self.model_toFit = [] 
     156        self.model_to_fit = [] 
    134157        self.constraints_list = [] 
    135158        self.constraint_dict = {} 
     
    144167 
    145168        #------------------------------------------------------- 
    146         ## setup sizer1 (which fitpages to include) 
    147         self.sizer1.Clear(True) 
     169        # setup sizer1 (which fitpages to include) 
     170        self.data_selection_sizer.Clear(True) 
    148171        box_description = wx.StaticBox(self, wx.ID_ANY, "Fit Combinations") 
    149172        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) 
     
    151174        sizer_couples = wx.GridBagSizer(5, 5) 
    152175 
    153         #This if statement should be obsolete and can be removed in version 4 
    154         #Leave it here for now as no time to thoroughly test.  However if no 
    155         #fit page is found the menu item that calls this page is inactive  
    156         # Nov. 22 2015  --PDB 
     176        # The wx GUI has a flag to enable a menu item, but can still be 
     177        # reached via scripting. There is no guearantee future GUI 
     178        # implementations force this check, either. 
     179        # IMHO, this if statement should stay -- JRK 2016-OCT-05 
    157180        if len(self.page_finder) == 0: 
    158181            msg = " No fit combinations are found! \n\n" 
     
    161184            sizer_title.Add(wx.StaticText(self, wx.ID_ANY, msg)) 
    162185        else: 
    163             ## store model 
     186            # store model 
    164187            self._store_model() 
    165188 
     
    171194                wx.TOP | wx.BOTTOM | wx.EXPAND | wx.ADJUST_MINSIZE, border=5) 
    172195            sizer_title.Add(self.cb1, 0, 
    173                 wx.TOP | wx.BOTTOM | wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, border=5) 
    174  
    175             ## draw list of model and data names 
     196                wx.TOP | wx.BOTTOM | wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 
     197                border=5) 
     198 
     199            # draw list of model and data names 
    176200            self._fill_sizer_model_list(sizer_couples) 
    177201 
    178202        boxsizer1.Add(sizer_title, flag=wx.TOP | wx.BOTTOM, border=5) 
    179203        boxsizer1.Add(sizer_couples, 1, flag=wx.TOP | wx.BOTTOM, border=5) 
    180         self.sizer1.Add(boxsizer1, 1, wx.EXPAND | wx.ALL, 10) 
    181 #        self.sizer1.Layout() 
     204        self.data_selection_sizer.Add(boxsizer1, 1, wx.EXPAND | wx.ALL, 10) 
     205        # self.sizer1.Layout() 
    182206 
    183207        #-------------------------------------------------------- 
    184         ## set up the other 2 sizers: the constraints list and the 
    185         ## buttons (fit, help etc) sizer at the bottom of the page. 
    186         ## Note: the if statement should be removed along with the above 
    187         ## if statement as soon as it can be properly tested. 
    188         ## Nov. 22 2015  --PDB 
     208        # set up the other 2 sizers: the constraints list and the 
     209        # buttons (fit, help etc) sizer at the bottom of the page. 
     210        # Note: the if statement should be removed along with the above 
     211        # if statement as soon as it can be properly tested. 
     212        # Nov. 22 2015  --PDB 
     213        # As above, this page can be accessed through other means than the 
     214        # base SasView GUI. 
     215        # Oct. 5, 2016 --JRK 
    189216        if len(self.page_finder) > 0: 
    190             ## draw the sizer containing constraint info 
     217            # draw the sizer containing constraint info 
    191218            if not self.batch_on: 
    192219                self._fill_sizer_constraint() 
    193             ## draw fit button sizer 
     220            # draw fit button sizer 
    194221            self._fill_sizer_fit() 
    195  
    196222 
    197223    def _fill_sizer_model_list(self, sizer): 
     
    201227        ix = 0 
    202228        iy = 0 
    203         list = [] 
    204229        sizer.Clear(True) 
    205230 
     
    209234        new_name.SetForegroundColour(wx.WHITE) 
    210235        sizer.Add(new_name, (iy, ix), (1, 1), 
    211                             wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 
     236                  wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 
    212237        ix += 2 
    213238        model_type = wx.StaticText(self, wx.ID_ANY, '  Model ') 
     
    215240        model_type.SetForegroundColour(wx.WHITE) 
    216241        sizer.Add(model_type, (iy, ix), (1, 1), 
    217                             wx.EXPAND | wx.ADJUST_MINSIZE, 0) 
     242                  wx.EXPAND | wx.ADJUST_MINSIZE, 0) 
    218243        ix += 1 
    219244        data_used = wx.StaticText(self, wx.ID_ANY, '  Data ') 
     
    221246        data_used.SetForegroundColour(wx.WHITE) 
    222247        sizer.Add(data_used, (iy, ix), (1, 1), 
    223                             wx.EXPAND | wx.ADJUST_MINSIZE, 0) 
     248                  wx.EXPAND | wx.ADJUST_MINSIZE, 0) 
    224249        ix += 1 
    225250        tab_used = wx.StaticText(self, wx.ID_ANY, '  FitPage ') 
     
    302327        wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    303328 
    304         self.sizer2.Clear(True) 
     329        self.constraints_sizer.Clear(True) 
    305330        if self.batch_on: 
    306             if self.sizer2.IsShown(): 
    307                 self.sizer2.Show(False) 
     331            if self.constraints_sizer.IsShown(): 
     332                self.constraints_sizer.Show(False) 
    308333            return 
    309334        box_description = wx.StaticBox(self, wx.ID_ANY, "Fit Constraints") 
    310         boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) 
     335        box_sizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) 
    311336        sizer_title = wx.BoxSizer(wx.HORIZONTAL) 
    312337        self.sizer_all_constraints = wx.BoxSizer(wx.HORIZONTAL) 
     
    338363 
    339364        self.btAdd = wx.Button(self, self.ID_ADD, 'Add') 
    340         self.btAdd.Bind(wx.EVT_BUTTON, self._onAdd_constraint, 
     365        self.btAdd.Bind(wx.EVT_BUTTON, self._on_add_constraint, 
    341366                        id=self.btAdd.GetId()) 
    342367        self.btAdd.SetToolTipString("Add another constraint?") 
     
    344369 
    345370        text_hint = wx.StaticText(self, wx.ID_ANY, 
    346                                   "Example: [M0][paramter] = M1.parameter") 
     371                                  "Example: [M0][parameter] = M1.parameter") 
    347372        sizer_button.Add(text_hint, 0, 
    348373                         wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 10) 
     
    350375                         wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 10) 
    351376 
    352         boxsizer1.Add(sizer_title, flag=wx.TOP | wx.BOTTOM, border=10) 
    353         boxsizer1.Add(self.sizer_all_constraints, flag=wx.TOP | wx.BOTTOM, 
    354                       border=10) 
    355         boxsizer1.Add(self.sizer_constraints, flag=wx.TOP | wx.BOTTOM, 
    356                       border=10) 
    357         boxsizer1.Add(sizer_button, flag=wx.TOP | wx.BOTTOM, border=10) 
    358  
    359         self.sizer2.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10) 
    360  
     377        box_sizer1.Add(sizer_title, flag=wx.TOP | wx.BOTTOM, border=10) 
     378        box_sizer1.Add(self.sizer_all_constraints, flag=wx.TOP | wx.BOTTOM, 
     379                       border=10) 
     380        box_sizer1.Add(self.sizer_constraints, flag=wx.TOP | wx.BOTTOM, 
     381                       border=10) 
     382        box_sizer1.Add(sizer_button, flag=wx.TOP | wx.BOTTOM, border=10) 
     383 
     384        self.constraints_sizer.Add(box_sizer1, 0, wx.EXPAND | wx.ALL, 10) 
    361385 
    362386    def _fill_sizer_fit(self): 
     
    364388        Draw fit button 
    365389        """ 
    366         self.sizer3.Clear(True) 
     390        self.run_fit_sizer.Clear(True) 
    367391        box_description = wx.StaticBox(self, wx.ID_ANY, "Fit ") 
    368392        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) 
    369393        sizer_button = wx.BoxSizer(wx.HORIZONTAL) 
    370394 
    371         #Fit button 
     395        # Fit button 
    372396        self.btFit = wx.Button(self, self.ID_FIT, 'Fit', size=wx.DefaultSize) 
    373         self.btFit.Bind(wx.EVT_BUTTON, self.onFit, id=self.btFit.GetId()) 
     397        self.btFit.Bind(wx.EVT_BUTTON, self.on_fit, id=self.btFit.GetId()) 
    374398        self.btFit.SetToolTipString("Perform fit.") 
    375399 
    376         #General Help button 
     400        # General Help button 
    377401        self.btHelp = wx.Button(self, wx.ID_HELP, 'HELP') 
    378402        self.btHelp.SetToolTipString("Simultaneous/Constrained Fitting help.") 
    379         self.btHelp.Bind(wx.EVT_BUTTON, self._onHelp) 
    380  
    381         #hint text on button line 
     403        self.btHelp.Bind(wx.EVT_BUTTON, self._on_help) 
     404 
     405        # hint text on button line 
    382406        if self.batch_on: 
    383407            text = " Fit in Parallel all Data sets\n" 
     
    393417 
    394418        boxsizer1.Add(sizer_button, flag=wx.TOP | wx.BOTTOM, border=10) 
    395         self.sizer3.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10) 
    396  
    397     def onRemove(self, event): 
     419        self.run_fit_sizer.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10) 
     420 
     421    def on_remove(self, event): 
    398422        """ 
    399423        Remove constraint fields 
     
    406430            return 
    407431        wx.CallAfter(self._remove_after, event.GetId()) 
    408         #self._onAdd_constraint(None) 
     432        # self._onAdd_constraint(None) 
    409433 
    410434    def _remove_after(self, id): 
     
    416440                self.constraints_list.remove(item) 
    417441                self.nb_constraint -= 1 
    418                 self.sizer2.Layout() 
     442                self.constraints_sizer.Layout() 
    419443                self.FitInside() 
    420444                break 
    421445 
    422     def onFit(self, event): 
     446    def on_fit(self, event): 
    423447        """ 
    424448        signal for fitting 
     
    435459            flag = (self._manager.sim_page.uid == self.uid) 
    436460 
    437         ## making sure all parameters content a constraint 
     461        # making sure all parameters content a constraint 
    438462        if not self.batch_on and self.show_constraint.GetValue(): 
    439463            if not self._set_constraint(): 
    440464                return 
    441         ## model was actually selected from this page to be fit 
    442         if len(self.model_toFit) >= 1: 
     465        # model was actually selected from this page to be fit 
     466        if len(self.model_to_fit) >= 1: 
    443467            self.manager._reset_schedule_problem(value=0) 
    444468            for item in self.model_list: 
     
    456480            msg = "Select at least one model check box to fit " 
    457481            wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
     482        self.set_state() 
    458483 
    459484    def _on_fit_complete(self): 
     
    467492        """ 
    468493        Attempt to stop the fitting thread 
    469         """ 
    470         if event != None: 
     494 
     495        :param event: Event handler when stop fit is clicked 
     496        """ 
     497        if event is not None: 
    471498            event.Skip() 
    472499        self.manager.stop_fit(self.uid) 
     
    485512        self.btFit.Enable(True) 
    486513 
    487     def _onHelp(self, event): 
     514    def _on_help(self, event): 
    488515        """ 
    489516        Bring up the simultaneous Fitting Documentation whenever the HELP 
     
    494521        versions of Wx (before 2.9) and thus not the release version of 
    495522        installers, the help comes up at the top level of the file as 
    496         webbrowser does not pass anything past the # to the browser when it is 
     523        web browser does not pass anything past the # to the browser when it is 
    497524        running "file:///...." 
    498525 
    499     :param evt: Triggers on clicking the help button 
     526    :param event: Triggers on clicking the help button 
    500527    """ 
    501528        _TreeLocation = "user/sasgui/perspectives/fitting/fitting_help.html" 
     
    510537 
    511538        :param manager: instance of plugin fitting 
    512  
    513539        """ 
    514540        self.manager = manager 
     
    518544        check all models names 
    519545        """ 
    520         self.model_toFit = [] 
    521         if self.cb1.GetValue() == True: 
     546        self.model_to_fit = [] 
     547        if self.cb1.GetValue(): 
    522548            for item in self.model_list: 
    523549                if item[0].IsEnabled(): 
    524550                    item[0].SetValue(True) 
    525                     self.model_toFit.append(item) 
    526  
    527             ## constraint info 
     551                    self.model_to_fit.append(item) 
     552 
     553            # constraint info 
    528554            self._store_model() 
    529555            if not self.batch_on: 
    530                 ## display constraint fields 
     556                # display constraint fields 
    531557                if (self.show_constraint.GetValue() and 
    532558                                 len(self.constraints_list) == 0): 
     
    538564 
    539565            if not self.batch_on: 
    540                 ##constraint info 
     566                # constraint info 
    541567                self._hide_constraint() 
    542568 
     
    544570        self.FitInside() 
    545571 
    546  
    547572    def check_model_name(self, event): 
    548573        """ 
    549574        Save information related to checkbox and their states 
    550575        """ 
    551         self.model_toFit = [] 
    552         cbox = event.GetEventObject() 
     576        self.model_to_fit = [] 
    553577        for item in self.model_list: 
    554             if item[0].GetValue() == True: 
    555                 self.model_toFit.append(item) 
     578            if item[0].GetValue(): 
     579                self.model_to_fit.append(item) 
    556580            else: 
    557                 if item in self.model_toFit: 
    558                     self.model_toFit.remove(item) 
     581                if item in self.model_to_fit: 
     582                    self.model_to_fit.remove(item) 
    559583                    self.cb1.SetValue(False) 
    560584 
    561         ## display constraint fields 
    562         if len(self.model_toFit) >= 1: 
     585        # display constraint fields 
     586        if len(self.model_to_fit) >= 1: 
    563587            self._store_model() 
    564588            if not self.batch_on and self.show_constraint.GetValue() and\ 
     
    567591                self._show_constraint() 
    568592 
    569         elif len(self.model_toFit) < 1: 
    570             ##constraint info 
     593        elif len(self.model_to_fit) < 1: 
     594            # constraint info 
    571595            self._hide_constraint() 
    572596 
    573597        self._update_easy_setup_cb() 
    574         ## set the value of the main check button 
    575         if len(self.model_list) == len(self.model_toFit): 
     598        # set the value of the main check button 
     599        if len(self.model_list) == len(self.model_to_fit): 
    576600            self.cb1.SetValue(True) 
    577601            self.FitInside() 
     
    585609        Update easy setup combobox on selecting a model 
    586610        """ 
    587         if self.model_cbox_left == None or self.model_cbox_right == None: 
    588             return 
    589  
    590         models = [(item[3].name, item[3]) for item in self.model_toFit] 
     611        if self.model_cbox_left is None or self.model_cbox_right is None: 
     612            return 
     613 
     614        models = [(item[3].name, item[3]) for item in self.model_to_fit] 
    591615        setComboBoxItems(self.model_cbox_left, models) 
    592616        setComboBoxItems(self.model_cbox_right, models) 
     
    595619        if self.model_cbox_left.GetSelection() == wx.NOT_FOUND: 
    596620            self.model_cbox_left.SetSelection(0) 
    597         self.sizer2.Layout() 
     621        self.constraints_sizer.Layout() 
    598622 
    599623    def _store_model(self): 
     
    601625         Store selected model 
    602626        """ 
    603         if len(self.model_toFit) < 1: 
    604             return 
    605         for item in self.model_toFit: 
     627        if len(self.model_to_fit) < 1: 
     628            return 
     629        for item in self.model_to_fit: 
    606630            model = item[3] 
    607631            page_id = item[2] 
     
    612636        Show fields to add constraint 
    613637        """ 
    614         if len(self.model_toFit) < 1: 
     638        if len(self.model_to_fit) < 1: 
    615639            msg = "Select at least 1 model to add constraint " 
    616640            wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    617             ## hide button 
     641            # hide button 
    618642            self._hide_constraint() 
    619643            return 
     
    632656        """ 
    633657        box_description = wx.StaticBox(self, wx.ID_ANY, "Easy Setup ") 
    634         boxsizer = wx.StaticBoxSizer(box_description, wx.HORIZONTAL) 
     658        box_sizer = wx.StaticBoxSizer(box_description, wx.HORIZONTAL) 
    635659        sizer_constraint = wx.BoxSizer(wx.HORIZONTAL) 
    636660        self.model_cbox_left = wx.ComboBox(self, wx.ID_ANY, style=wx.CB_READONLY) 
     
    650674 
    651675        for id, model in self.constraint_dict.iteritems(): 
    652             ## check if all parameters have been selected for constraint 
    653             ## then do not allow add constraint on parameters 
     676            # check if all parameters have been selected for constraint 
     677            # then do not allow add constraint on parameters 
    654678            self.model_cbox_left.Append(str(model.name), model) 
    655679        self.model_cbox_left.Select(0) 
    656680        for id, model in self.constraint_dict.iteritems(): 
    657             ## check if all parameters have been selected for constraint 
    658             ## then do not allow add constraint on parameters 
     681            # check if all parameters have been selected for constraint 
     682            # then do not allow add constraint on parameters 
    659683            self.model_cbox_right.Append(str(model.name), model) 
    660         boxsizer.Add(self.model_cbox_left, 
     684        box_sizer.Add(self.model_cbox_left, 
    661685                             flag=wx.RIGHT | wx.EXPAND, border=10) 
    662         #boxsizer.Add(wx.StaticText(self, wx.ID_ANY, ".parameters"), 
     686        # box_sizer.Add(wx.StaticText(self, wx.ID_ANY, ".parameters"), 
    663687        #                     flag=wx.RIGHT | wx.EXPAND, border=5) 
    664         boxsizer.Add(egal_txt, flag=wx.RIGHT | wx.EXPAND, border=5) 
    665         boxsizer.Add(self.model_cbox_right, 
     688        box_sizer.Add(egal_txt, flag=wx.RIGHT | wx.EXPAND, border=5) 
     689        box_sizer.Add(self.model_cbox_right, 
    666690                             flag=wx.RIGHT | wx.EXPAND, border=10) 
    667         #boxsizer.Add(wx.StaticText(self, wx.ID_ANY, ".parameters"), 
     691        # box_sizer.Add(wx.StaticText(self, wx.ID_ANY, ".parameters"), 
    668692        #                     flag=wx.RIGHT | wx.EXPAND, border=5) 
    669         boxsizer.Add((20, -1)) 
    670         boxsizer.Add(self.set_button, flag=wx.RIGHT | wx.EXPAND, border=5) 
    671         sizer_constraint.Add(boxsizer, flag=wx.RIGHT | wx.EXPAND, border=5) 
     693        box_sizer.Add((20, -1)) 
     694        box_sizer.Add(self.set_button, flag=wx.RIGHT | wx.EXPAND, border=5) 
     695        sizer_constraint.Add(box_sizer, flag=wx.RIGHT | wx.EXPAND, border=5) 
    672696        self.sizer_all_constraints.Insert(before=0, 
    673697                             item=sizer_constraint, 
     
    699723            return 
    700724        param_list = [] 
    701         param_listB = [] 
     725        param_list_b = [] 
    702726        selection = self.model_cbox_left.GetCurrentSelection() 
    703727        model_left = self.model_cbox_left.GetValue() 
    704728        model = self.model_cbox_left.GetClientData(selection) 
    705         selectionB = self.model_cbox_right.GetCurrentSelection() 
     729        selection_b = self.model_cbox_right.GetCurrentSelection() 
    706730        model_right = self.model_cbox_right.GetValue() 
    707         modelB = self.model_cbox_right.GetClientData(selectionB) 
     731        model_b = self.model_cbox_right.GetClientData(selection_b) 
    708732        for id, dic_model in self.constraint_dict.iteritems(): 
    709733            if model == dic_model: 
    710734                param_list = self.page_finder[id].get_param2fit() 
    711             if modelB == dic_model: 
    712                 param_listB = self.page_finder[id].get_param2fit() 
    713             if len(param_list) > 0 and len(param_listB) > 0: 
     735            if model_b == dic_model: 
     736                param_list_b = self.page_finder[id].get_param2fit() 
     737            if len(param_list) > 0 and len(param_list_b) > 0: 
    714738                break 
    715739        num_cbox = 0 
     
    717741        for param in param_list: 
    718742            num_cbox += 1 
    719             if param in param_listB: 
     743            if param in param_list_b: 
    720744                item = self.constraints_list[-1] 
    721745                item.model_cbox.SetStringSelection(model_left) 
     
    744768        """ 
    745769        Show constraint fields 
     770        :param dict: dictionary mapping constraint values 
    746771        """ 
    747772        self.btAdd.Show(True) 
     
    750775            for id, model in self.constraint_dict.iteritems(): 
    751776                nb_fit_param += len(self.page_finder[id].get_param2fit()) 
    752             ##Don't add anymore 
     777            # Don't add anymore 
    753778            if len(self.constraints_list) == nb_fit_param: 
    754779                msg = "Cannot add another constraint. Maximum of number " 
     
    756781                wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    757782                self.sizer_constraints.Layout() 
    758                 self.sizer2.Layout() 
     783                self.constraints_sizer.Layout() 
    759784                return 
    760         if len(self.model_toFit) < 1: 
     785        if len(self.model_to_fit) < 1: 
    761786            msg = "Select at least 1 model to add constraint " 
    762787            wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    763788            self.sizer_constraints.Layout() 
    764             self.sizer2.Layout() 
     789            self.constraints_sizer.Layout() 
    765790            return 
    766791 
     
    771796        model_cbox.Clear() 
    772797        for id, model in self.constraint_dict.iteritems(): 
    773             ## check if all parameters have been selected for constraint 
    774             ## then do not allow add constraint on parameters 
     798            # check if all parameters have been selected for constraint 
     799            # then do not allow add constraint on parameters 
    775800            model_cbox.Append(str(model.name), model) 
    776801        wx.EVT_COMBOBOX(model_cbox, wx.ID_ANY, self._on_select_model) 
     
    789814        # Remove button 
    790815        #btRemove = wx.Button(self, self.ID_REMOVE, 'Remove') 
    791         btRemove = wx.Button(self, self._ids.next(), 'Remove') 
    792         btRemove.Bind(wx.EVT_BUTTON, self.onRemove, 
    793                       id=btRemove.GetId()) 
    794         btRemove.SetToolTipString("Remove constraint.") 
    795         btRemove.Hide() 
     816        bt_remove = wx.Button(self, self._ids.next(), 'Remove') 
     817        bt_remove.Bind(wx.EVT_BUTTON, self.on_remove, 
     818                      id=bt_remove.GetId()) 
     819        bt_remove.SetToolTipString("Remove constraint.") 
     820        bt_remove.Hide() 
    796821 
    797822        # Hid the add button, if it exists 
     
    804829        sizer_constraint.Add(egal_txt, flag=wx.RIGHT | wx.EXPAND, border=5) 
    805830        sizer_constraint.Add(constraint, flag=wx.RIGHT | wx.EXPAND, border=10) 
    806         sizer_constraint.Add(btRemove, flag=wx.RIGHT | wx.EXPAND, border=10) 
     831        sizer_constraint.Add(bt_remove, flag=wx.RIGHT | wx.EXPAND, border=10) 
    807832 
    808833        self.sizer_constraints.Insert(before=self.nb_constraint, 
     
    810835                border=5) 
    811836        c = ConstraintLine(model_cbox, param_cbox, egal_txt, 
    812                            constraint, btRemove, sizer_constraint) 
     837                           constraint, bt_remove, sizer_constraint) 
    813838        self.constraints_list.append(c) 
    814839 
    815840        self.nb_constraint += 1 
    816841        self.sizer_constraints.Layout() 
    817         self.sizer2.Layout() 
    818         self.Layout 
     842        self.constraints_sizer.Layout() 
     843        self.Layout() 
    819844 
    820845    def _hide_constraint(self): 
     
    841866        self.sizer_constraints.Clear(True) 
    842867        self.sizer_constraints.Layout() 
    843         self.sizer2.Layout() 
    844         self.Layout 
     868        self.constraints_sizer.Layout() 
     869        self.Layout() 
    845870        self.FitInside() 
    846871 
    847872    def _on_select_model(self, event): 
    848873        """ 
    849         fill combox box with list of parameters 
     874        fill combo box with list of parameters 
    850875        """ 
    851876        if not self.constraints_list: 
    852877            return 
    853878 
    854         ##This way PC/MAC both work, instead of using event.GetClientData(). 
     879        # This way PC/MAC both work, instead of using event.GetClientData(). 
    855880        model_cbox = self.constraints_list[-1].model_cbox 
    856881        n = model_cbox.GetCurrentSelection() 
     
    867892        param_cbox = self.constraints_list[-1].param_cbox 
    868893        param_cbox.Clear() 
    869         ## insert only fittable paramaters 
     894        # insert only fittable paramaters 
    870895        for param in param_list: 
    871896            param_cbox.Append(str(param), model) 
    872897        param_cbox.Show(True) 
    873898 
    874         btRemove = self.constraints_list[-1].btRemove 
    875         btRemove.Show(True) 
     899        bt_remove = self.constraints_list[-1].btRemove 
     900        bt_remove.Show(True) 
    876901        self.btAdd.Show(True) 
    877902#        self.Layout() 
     
    882907        Store the appropriate constraint in the page_finder 
    883908        """ 
    884         ##This way PC/MAC both work, instead of using event.GetClientData(). 
    885         #n = self.param_cbox.GetCurrentSelection() 
    886         #model = self.param_cbox.GetClientData(n) 
    887         #param = event.GetString() 
     909        # This way PC/MAC both work, instead of using event.GetClientData(). 
     910        # n = self.param_cbox.GetCurrentSelection() 
     911        # model = self.param_cbox.GetClientData(n) 
     912        # param = event.GetString() 
    888913 
    889914        if self.constraints_list: 
     
    891916            self.constraints_list[-1].constraint.Show(True) 
    892917 
    893     def _onAdd_constraint(self, event): 
     918    def _on_add_constraint(self, event): 
    894919        """ 
    895920        Add another line for constraint 
     
    899924            wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    900925            return 
    901         ## check that a constraint is added 
     926        # check that a constraint is added 
    902927        # before allow to add another constraint 
    903928        for item in self.constraints_list: 
     
    913938                model = item.param_cbox.GetClientData( 
    914939                                        item.param_cbox.GetCurrentSelection()) 
    915                 if model != None: 
     940                if model is not None: 
    916941                    msg = " Enter a constraint for %s.%s! " % (model.name, 
    917942                                        item.param_cbox.GetString(0)) 
     
    920945                wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    921946                return 
    922         ## some model or parameters can be constrained 
     947        # some model or parameters can be constrained 
    923948        self._show_constraint() 
    924949        self.FitInside() 
     
    9801005    def on_set_focus(self, event=None): 
    9811006        """ 
    982         The  derivative class is on focus if implemented 
     1007        The derivative class is on focus if implemented 
    9831008        """ 
    9841009        if self.parent is not None: 
     
    9951020        cbox.Append(name, value) 
    9961021    cbox.SetStringSelection(selected) 
     1022 
     1023 
     1024class SimFitPageState: 
     1025    """ 
     1026    State of the simultaneous fit page for saving purposes 
     1027    """ 
     1028 
     1029    def __init__(self): 
     1030        # Sim Fit Page Number 
     1031        self.fit_page_no = None 
     1032        # Select all data 
     1033        self.select_all = False 
     1034        # Data sets sent to fit page 
     1035        self.model_list = [] 
     1036        # Data sets to be fit 
     1037        self.model_to_fit = [] 
     1038        # Number of constraints 
     1039        self.no_constraint = 0 
     1040        # Dictionary of constraints 
     1041        self.constraint_dict = {} 
     1042        # List of constraints 
     1043        self.constraints_list = [] 
     1044 
     1045    def load_from_save_state(self, fit): 
     1046        """ 
     1047        Load in a simultaneous/constrained fit from a save state 
     1048        :param fit: Fitpanel object 
     1049        :return: None 
     1050        """ 
     1051 
     1052        model_map = {} 
     1053        if fit.fit_panel.sim_page is None: 
     1054            fit.fit_panel.add_sim_page() 
     1055        sim_page = fit.fit_panel.sim_page 
     1056 
     1057        # Process each model and associate old M# with new M# 
     1058        i = 0 
     1059        for model in sim_page.model_list: 
     1060            model_id = self._format_id(model[1].keys()[0]) 
     1061            for saved_model in self.model_list: 
     1062                save_id = saved_model.pop('name') 
     1063                saved_model['name'] = save_id 
     1064                save_id = self._format_id(save_id) 
     1065                if save_id == model_id: 
     1066                    model_map[saved_model.pop('fit_page_source')] = \ 
     1067                        model[3].name 
     1068                    check = bool(saved_model.pop('checked')) 
     1069                    sim_page.model_list[i][0].SetValue(check) 
     1070                    break 
     1071            i += 1 
     1072        sim_page.check_model_name(None) 
     1073 
     1074        if len(self.constraints_list) > 0: 
     1075            sim_page.hide_constraint.SetValue(False) 
     1076            sim_page.show_constraint.SetValue(True) 
     1077            sim_page._display_constraint(None) 
     1078 
     1079        for index, item in enumerate(self.constraints_list): 
     1080            model_cbox = item.pop('model_cbox') 
     1081            if model_cbox != "": 
     1082                constraint_value = item.pop('constraint') 
     1083                param = item.pop('param_cbox') 
     1084                equality = item.pop('egal_txt') 
     1085                for key, value in model_map.iteritems(): 
     1086                    model_cbox.replace(key, value) 
     1087                    constraint_value.replace(key, value) 
     1088 
     1089                sim_page.constraints_list[index][0].SetValue(model_cbox) 
     1090                sim_page._on_select_model(None) 
     1091                sim_page.constraints_list[index][1].SetValue(param) 
     1092                sim_page.constraints_list[index][2].SetLabel(equality) 
     1093                sim_page.constraints_list[index][3].SetValue(constraint_value) 
     1094                sim_page._on_add_constraint(None) 
     1095 
     1096    def _format_id(self, original_id): 
     1097        original_id = original_id.rstrip('1234567890.') 
     1098        new_id_list = original_id.split() 
     1099        new_id = ' '.join(new_id_list) 
     1100        return new_id 
Note: See TracChangeset for help on using the changeset viewer.