Index: src/sas/sasgui/perspectives/fitting/fitting.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/fitting.py	(revision 2504b5a1018b4b2aff653769b6785e73300296bf)
+++ src/sas/sasgui/perspectives/fitting/fitting.py	(revision 2504b5a1018b4b2aff653769b6785e73300296bf)
@@ -23,5 +23,17 @@
 import traceback
 
+import bumps.options
+from bumps.gui.fit_dialog import show_fit_config
+try:
+    from bumps.gui.fit_dialog import EVT_FITTER_CHANGED
+except ImportError:
+    # CRUFT: bumps 0.7.5.8 and below
+    EVT_FITTER_CHANGED = None  # type: wx.PyCommandEvent
+
 from sas.sascalc.dataloader.loader import Loader
+from sas.sascalc.fit.BumpsFitting import BumpsFit as Fit
+from sas.sascalc.fit.pagestate import Reader, PageState, SimFitPageState
+from sas.sascalc.fit import models
+
 from sas.sasgui.guiframe.dataFitting import Data2D
 from sas.sasgui.guiframe.dataFitting import Data1D
@@ -34,20 +46,19 @@
 from sas.sasgui.guiframe.plugin_base import PluginBase
 from sas.sasgui.guiframe.data_processor import BatchCell
-from sas.sascalc.fit.BumpsFitting import BumpsFit as Fit
-from sas.sasgui.perspectives.fitting.console import ConsoleUpdate
-from sas.sasgui.perspectives.fitting.fitproblem import FitProblemDictionary
-from sas.sasgui.perspectives.fitting.fitpanel import FitPanel
-from sas.sasgui.perspectives.fitting.resultpanel import ResultPanel, PlotResultEvent
-
-from sas.sasgui.perspectives.fitting.fit_thread import FitThread
-from sas.sasgui.perspectives.fitting.pagestate import Reader
-from sas.sasgui.perspectives.fitting.fitpage import Chi2UpdateEvent
+from sas.sasgui.guiframe.gui_manager import MDIFrame
+from sas.sasgui.guiframe.documentation_window import DocumentationWindow
+
 from sas.sasgui.perspectives.calculator.model_editor import TextDialog
 from sas.sasgui.perspectives.calculator.model_editor import EditorWindow
-from sas.sasgui.guiframe.gui_manager import MDIFrame
-from sas.sasgui.guiframe.documentation_window import DocumentationWindow
-from sas.sasgui.perspectives.fitting.gpu_options import GpuOptions
-
-from . import models
+
+from .fitting_widgets import DataDialog
+from .fit_thread import FitThread
+from .fitpage import Chi2UpdateEvent
+from .console import ConsoleUpdate
+from .fitproblem import FitProblemDictionary
+from .fitpanel import FitPanel
+from .model_thread import Calc1D, Calc2D
+from .resultpanel import ResultPanel, PlotResultEvent
+from .gpu_options import GpuOptions
 
 logger = logging.getLogger(__name__)
@@ -63,11 +74,4 @@
     ON_MAC = True
 
-import bumps.options
-from bumps.gui.fit_dialog import show_fit_config
-try:
-    from bumps.gui.fit_dialog import EVT_FITTER_CHANGED
-except ImportError:
-    # CRUFT: bumps 0.7.5.8 and below
-    EVT_FITTER_CHANGED = None  # type: wx.PyCommandEvent
 
 class Plugin(PluginBase):
@@ -238,7 +242,8 @@
         Get the python editor panel
         """
+        from sas.sasgui.perspectives.calculator.pyconsole import PyConsole
+
         event_id = event.GetId()
         label = self.edit_menu.GetLabel(event_id)
-        from sas.sasgui.perspectives.calculator.pyconsole import PyConsole
         filename = os.path.join(models.find_plugins_dir(), label)
         frame = PyConsole(parent=self.parent, manager=self,
@@ -290,5 +295,5 @@
                         break
         except Exception:
-            import traceback; traceback.print_exc()
+            traceback.print_exc()
             msg = 'Delete Error: \nCould not delete the file; Check if in use.'
             wx.MessageBox(msg, 'Error')
@@ -300,5 +305,5 @@
         event_id = event.GetId()
         model_manager = models.ModelManager()
-        model_list = model_manager.get_model_name_list()
+        model_list = model_manager.composable_models()
         plug_dir = models.find_plugins_dir()
         textdial = TextDialog(None, self, wx.ID_ANY, 'Easy Sum/Multi(p1, p2) Editor',
@@ -340,33 +345,39 @@
             self.set_edit_menu_helper(self.parent, self.edit_custom_model)
             self.set_edit_menu_helper(self.parent, self.delete_custom_model)
-            temp = self.fit_panel.reset_pmodel_list()
-            if temp:
-                # Set the new plugin model list for all fit pages
-                for uid, page in self.fit_panel.opened_pages.iteritems():
-                    if hasattr(page, "formfactorbox"):
-                        page.model_list_box = temp
-                        current_val = page.formfactorbox.GetLabel()
-                        #if page.plugin_rbutton.GetValue():
-                        mod_cat = page.categorybox.GetStringSelection()
-                        if mod_cat == custom_model:
-                            #pos = page.formfactorbox.GetSelection()
-                            page._show_combox_helper()
-                            new_val = page.formfactorbox.GetLabel()
-                            if current_val != new_val and new_val != '':
-                                page.formfactorbox.SetLabel(new_val)
-                            else:
-                                page.formfactorbox.SetLabel(current_val)
-                        if hasattr(page, 'structurebox'):
-                            selected_name = page.structurebox.GetStringSelection()
-
-                            page.structurebox.Clear()
-                            page.initialize_combox()
-
-                            index = page.structurebox.FindString(selected_name)
-                            if index == -1:
-                                index = 0
-                            page.structurebox.SetSelection(index)
-                            page._on_select_model()
-        except:
+            new_pmodel_list = self.fit_panel.reset_pmodel_list()
+            if not new_pmodel_list:
+                return
+            # Set the new plugin model list for all fit pages
+            for uid, page in self.fit_panel.opened_pages.iteritems():
+                if hasattr(page, "formfactorbox"):
+                    page.model_list_box = new_pmodel_list
+                    mod_cat = page.categorybox.GetStringSelection()
+                    if mod_cat == custom_model:
+                        box = page.formfactorbox
+                        model_name = box.GetValue()
+                        model = (box.GetClientData(box.GetCurrentSelection())
+                                 if model_name else None)
+                        page._show_combox_helper()
+                        new_index = box.FindString(model_name)
+                        new_model = (box.GetClientData(new_index)
+                                     if new_index >= 0 else None)
+                        if new_index >= 0:
+                            box.SetStringSelection(model_name)
+                        else:
+                            box.SetStringSelection('')
+                        if model and new_model != model:
+                            page._on_select_model(keep_pars=True)
+                    if hasattr(page, 'structurebox'):
+                        selected_name = page.structurebox.GetStringSelection()
+
+                        page.structurebox.Clear()
+                        page.initialize_combox()
+
+                        index = page.structurebox.FindString(selected_name)
+                        if index == -1:
+                            index = 0
+                        page.structurebox.SetSelection(index)
+                        page._on_select_model()
+        except Exception:
             logger.error("update_custom_combo: %s", sys.exc_value)
 
@@ -378,5 +389,5 @@
         #new_model_menu = wx.Menu()
         self.edit_model_menu.Append(wx_id, 'New Plugin Model',
-                                   'Add a new model function')
+                                    'Add a new model function')
         wx.EVT_MENU(owner, wx_id, self.make_new_model)
 
@@ -575,5 +586,4 @@
         else:
             if len(data_list) > MAX_NBR_DATA:
-                from fitting_widgets import DataDialog
                 dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA)
                 if dlg.ShowModal() == wx.ID_OK:
@@ -620,11 +630,11 @@
         : param datainfo: data
         """
-        from pagestate import PageState
-        from simfitpage import SimFitPageState
         if isinstance(state, PageState):
             state = state.clone()
             self.temp_state.append(state)
         elif isinstance(state, SimFitPageState):
-            state.load_from_save_state(self)
+            if self.fit_panel.sim_page is None:
+                self.fit_panel.add_sim_page()
+            self.fit_panel.sim_page.load_from_save_state(state)
         else:
             self.temp_state = []
@@ -661,5 +671,5 @@
                 self.parent.add_data(data_list={data.id: data})
                 wx.PostEvent(self.parent, NewPlotEvent(plot=data,
-                                        title=data.title))
+                             title=data.title))
                 #need to be fix later make sure we are sendind guiframe.data
                 #to panel
@@ -672,9 +682,9 @@
                 self.parent.add_data(data_list={data.id: data})
                 wx.PostEvent(self.parent, NewPlotEvent(plot=data,
-                                        title=data.title))
+                             title=data.title))
                 page = self.add_fit_page([data])
                 caption = page.window_caption
                 self.store_data(uid=page.uid, data_list=page.get_data_list(),
-                        caption=caption)
+                                caption=caption)
                 self.mypanels.append(page)
 
@@ -793,5 +803,5 @@
         """
         if item.find(".") >= 0:
-            param_names = re.split("\.", item)
+            param_names = re.split(r"\.", item)
             model_name = param_names[0]
             ##Assume max len is 3; eg., M0.radius.width
@@ -896,6 +906,6 @@
 
             self.draw_model(model=model, data=data, page_id=uid, smearer=smear,
-                enable1D=enable1D, enable2D=enable2D,
-                qmin=qmin, qmax=qmax, weight=weight)
+                            enable1D=enable1D, enable2D=enable2D,
+                            qmin=qmin, qmax=qmax, weight=weight)
 
     def draw_model(self, model, page_id, data=None, smearer=None,
@@ -940,16 +950,16 @@
             ## draw model 2D with no initial data
             self._draw_model2D(model=model,
-                                page_id=page_id,
-                                data=data,
-                                enable2D=enable2D,
-                                smearer=smearer,
-                                qmin=qmin,
-                                qmax=qmax,
-                                fid=fid,
-                                weight=weight,
-                                state=state,
-                                toggle_mode_on=toggle_mode_on,
-                                update_chisqr=update_chisqr,
-                                source=source)
+                               page_id=page_id,
+                               data=data,
+                               enable2D=enable2D,
+                               smearer=smearer,
+                               qmin=qmin,
+                               qmax=qmax,
+                               fid=fid,
+                               weight=weight,
+                               state=state,
+                               toggle_mode_on=toggle_mode_on,
+                               update_chisqr=update_chisqr,
+                               source=source)
 
     def onFit(self, uid):
@@ -960,5 +970,6 @@
         :param uid: id related to the panel currently calling this fit function.
         """
-        if uid is None: raise RuntimeError("no page to fit") # Should never happen
+        if uid is None:
+            raise RuntimeError("no page to fit") # Should never happen
 
         sim_page_uid = getattr(self.sim_page, 'uid', None)
@@ -994,6 +1005,6 @@
                     page = self.fit_panel.get_page_by_id(page_id)
                     self.set_fit_weight(uid=page.uid,
-                                     flag=page.get_weight_flag(),
-                                     is2d=page._is_2D())
+                                        flag=page.get_weight_flag(),
+                                        is2d=page._is_2D())
                     if not page.param_toFit:
                         msg = "No fitting parameters for %s" % page.window_caption
@@ -1019,7 +1030,7 @@
                             fitter = sim_fitter
                         self._add_problem_to_fit(fitproblem=fitproblem,
-                                             pars=pars,
-                                             fitter=fitter,
-                                             fit_id=fit_id)
+                                                 pars=pars,
+                                                 fitter=fitter,
+                                                 fit_id=fit_id)
                         fit_id += 1
                     list_page_id.append(page_id)
@@ -1068,10 +1079,10 @@
             ## Perform more than 1 fit at the time
             calc_fit = FitThread(handler=handler,
-                                    fn=fitter_list,
-                                    batch_inputs=batch_inputs,
-                                    batch_outputs=batch_outputs,
-                                    page_id=list_page_id,
-                                    updatefn=handler.update_fit,
-                                    completefn=self._fit_completed)
+                                 fn=fitter_list,
+                                 batch_inputs=batch_inputs,
+                                 batch_outputs=batch_outputs,
+                                 page_id=list_page_id,
+                                 updatefn=handler.update_fit,
+                                 completefn=self._fit_completed)
         #self.fit_thread_list[current_page_id] = calc_fit
         self.fit_thread_list[uid] = calc_fit
@@ -1134,5 +1145,5 @@
                 evt = StatusEvent(status=msg, info="warning")
                 wx.PostEvent(self.parent, evt)
-        except:
+        except Exception:
             msg = "Creating Fit page: %s" % sys.exc_value
             wx.PostEvent(self.parent, StatusEvent(status=msg, info="error"))
@@ -1158,8 +1169,8 @@
                     group_id = str(page.uid) + " Model1D"
                     wx.PostEvent(self.parent,
-                             NewPlotEvent(group_id=group_id,
-                                               action="delete"))
+                                 NewPlotEvent(group_id=group_id,
+                                              action="delete"))
                     self.parent.update_data(prev_data=theory_data,
-                                             new_data=data)
+                                            new_data=data)
             else:
                 if theory_data is not None:
@@ -1167,8 +1178,8 @@
                     data.group_id = theory_data.group_id
                     wx.PostEvent(self.parent,
-                             NewPlotEvent(group_id=group_id,
-                                               action="delete"))
+                                 NewPlotEvent(group_id=group_id,
+                                              action="delete"))
                     self.parent.update_data(prev_data=theory_data,
-                                             new_data=data)
+                                            new_data=data)
         self.store_data(uid=page.uid, data_list=page.get_data_list(),
                         caption=page.window_caption)
@@ -1479,5 +1490,4 @@
         if "Data" not in batch_outputs.keys():
             batch_outputs["Data"] = []
-        from sas.sasgui.guiframe.data_processor import BatchCell
         cell = BatchCell()
         cell.label = data.name
@@ -1579,14 +1589,14 @@
                     except KeyboardInterrupt:
                         fit_msg += "\nSingular point: Fitting stopped."
-                    except:
+                    except Exception:
                         fit_msg += "\nSingular point: Fitting error occurred."
                 if fit_msg:
-                   evt = StatusEvent(status=fit_msg, info="warning", type="stop")
-                   wx.PostEvent(self.parent, evt)
-
-        except:
+                    evt = StatusEvent(status=fit_msg, info="warning", type="stop")
+                    wx.PostEvent(self.parent, evt)
+
+        except Exception:
             msg = ("Fit completed but the following error occurred: %s"
                    % sys.exc_value)
-            #import traceback; msg = "\n".join((traceback.format_exc(), msg))
+            #msg = "\n".join((traceback.format_exc(), msg))
             evt = StatusEvent(status=msg, info="warning", type="stop")
             wx.PostEvent(self.parent, evt)
@@ -1743,5 +1753,5 @@
                                                   fid=data.id)
         self.parent.update_theory(data_id=data.id, theory=new_plot,
-                                   state=state)
+                                  state=state)
         return new_plot
 
@@ -1759,4 +1769,8 @@
             @param unsmeared_error: data error, rescaled to unsmeared model
         """
+<<<<<<< HEAD
+
+=======
+>>>>>>> master
         number_finite = np.count_nonzero(np.isfinite(y))
         np.nan_to_num(y)
@@ -1767,5 +1781,5 @@
         # Create the new theories
         if unsmeared_model is not None:
-            unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model, 
+            unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model,
                                   page_id, model, data, state,
                                   data_description=model.name + " unsmeared",
@@ -1774,5 +1788,5 @@
 
             if unsmeared_data is not None and unsmeared_error is not None:
-                unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data, 
+                unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data,
                                       page_id, model, data, state,
                                       data_description="Data unsmeared",
@@ -1792,5 +1806,5 @@
             plots_to_update.append(pq_plot)
         # Update the P(Q), S(Q) and unsmeared theory plots if they exist
-        wx.PostEvent(self.parent, NewPlotEvent(plots=plots_to_update, 
+        wx.PostEvent(self.parent, NewPlotEvent(plots=plots_to_update,
                                               action='update'))
 
@@ -1808,18 +1822,17 @@
 
         self.page_finder[page_id].set_theory_data(data=new_plot,
-                                                      fid=data.id)
+                                                  fid=data.id)
         if toggle_mode_on:
             wx.PostEvent(self.parent,
                          NewPlotEvent(group_id=str(page_id) + " Model2D",
-                                          action="Hide"))
+                                      action="Hide"))
         else:
             if update_chisqr:
-                wx.PostEvent(current_pg,
-                             Chi2UpdateEvent(output=self._cal_chisqr(
-                                                                data=data,
-                                                                fid=fid,
-                                                                weight=weight,
-                                                                page_id=page_id,
-                                                                index=index)))
+                output = self._cal_chisqr(data=data,
+                                          fid=fid,
+                                          weight=weight,
+                                          page_id=page_id,
+                                          index=index)
+                wx.PostEvent(current_pg, Chi2UpdateEvent(output=output))
             else:
                 self._plot_residuals(page_id=page_id, data=data, fid=fid,
@@ -1829,5 +1842,5 @@
             logger.error("Using the present parameters the model does not return any finite value. ")
             msg = "Computing Error: Model did not return any finite value."
-            wx.PostEvent(self.parent, StatusEvent(status = msg, info="error"))
+            wx.PostEvent(self.parent, StatusEvent(status=msg, info="error"))
         else:
             msg = "Computation  completed!"
@@ -1854,6 +1867,6 @@
 
     def _complete2D(self, image, data, model, page_id, elapsed, index, qmin,
-                qmax, fid=None, weight=None, toggle_mode_on=False, state=None,
-                     update_chisqr=True, source='model', plot_result=True):
+                    qmax, fid=None, weight=None, toggle_mode_on=False, state=None,
+                    update_chisqr=True, source='model', plot_result=True):
         """
         Complete get the result of modelthread and create model 2D
@@ -1896,32 +1909,31 @@
                                                   fid=data.id)
         self.parent.update_theory(data_id=data.id,
-                                       theory=new_plot,
-                                       state=state)
+                                  theory=new_plot,
+                                  state=state)
         current_pg = self.fit_panel.get_page_by_id(page_id)
         title = new_plot.title
         if not source == 'fit' and plot_result:
-            wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
-                                               title=title))
+            wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title))
         if toggle_mode_on:
             wx.PostEvent(self.parent,
-                             NewPlotEvent(group_id=str(page_id) + " Model1D",
-                                               action="Hide"))
+                         NewPlotEvent(group_id=str(page_id) + " Model1D",
+                                      action="Hide"))
         else:
             # Chisqr in fitpage
             if update_chisqr:
-                wx.PostEvent(current_pg,
-                             Chi2UpdateEvent(output=self._cal_chisqr(data=data,
-                                                                    weight=weight,
-                                                                    fid=fid,
-                                                         page_id=page_id,
-                                                         index=index)))
+                output = self._cal_chisqr(data=data,
+                                          weight=weight,
+                                          fid=fid,
+                                          page_id=page_id,
+                                          index=index)
+                wx.PostEvent(current_pg, Chi2UpdateEvent(output=output))
             else:
                 self._plot_residuals(page_id=page_id, data=data, fid=fid,
-                                      index=index, weight=weight)
+                                     index=index, weight=weight)
 
         if not number_finite:
             logger.error("Using the present parameters the model does not return any finite value. ")
             msg = "Computing Error: Model did not return any finite value."
-            wx.PostEvent(self.parent, StatusEvent(status = msg, info="error"))
+            wx.PostEvent(self.parent, StatusEvent(status=msg, info="error"))
         else:
             msg = "Computation  completed!"
@@ -1939,5 +1951,5 @@
                       weight=None,
                       toggle_mode_on=False,
-                       update_chisqr=True, source='model'):
+                      update_chisqr=True, source='model'):
         """
         draw model in 2D
@@ -1954,5 +1966,4 @@
             return None
         try:
-            from model_thread import Calc2D
             ## If a thread is already started, stop it
             if (self.calc_2D is not None) and self.calc_2D.isrunning():
@@ -1986,9 +1997,7 @@
     def _draw_model1D(self, model, page_id, data,
                       qmin, qmax, smearer=None,
-                state=None,
-                weight=None,
-                fid=None,
-                toggle_mode_on=False, update_chisqr=True, source='model',
-                enable1D=True):
+                      state=None, weight=None, fid=None,
+                      toggle_mode_on=False, update_chisqr=True, source='model',
+                      enable1D=True):
         """
         Draw model 1D from loaded data1D
@@ -2001,5 +2010,4 @@
             return
         try:
-            from model_thread import Calc1D
             ## If a thread is already started, stop it
             if (self.calc_1D is not None) and self.calc_1D.isrunning():
