Index: src/sas/sasgui/perspectives/fitting/basepage.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/basepage.py	(revision 65f39301a9c81af2f10a086dec2a40fcaf25a0bc)
+++ src/sas/sasgui/perspectives/fitting/basepage.py	(revision 277257f6caa3c7a18ad588f88501a89a34aa36e4)
@@ -504,22 +504,20 @@
         self.state.manager = manager
 
-    def populate_box(self, model_dict):
+    def populate_box(self, model_list_box):
         """
         Store list of model
 
-        :param model_dict: dictionary containing list of models
-
-        """
-        self.model_list_box = model_dict
-        self.state.model_list_box = self.model_list_box
+        :param model_list_box: dictionary containing categorized models
+        """
+        self.model_list_box = model_list_box
         self.initialize_combox()
 
-    def set_model_dictionary(self, model_dict):
+    def set_model_dictionary(self, model_dictionary):
         """
         Store a dictionary linking model name -> model object
 
-        :param model_dict: dictionary containing list of models
-        """
-        self.model_dict = model_dict
+        :param model_dictionary: dictionary containing all models
+        """
+        self.model_dictionary = model_dictionary
 
     def initialize_combox(self):
@@ -527,5 +525,5 @@
         put default value in the combo box
         """
-        if self.model_list_box is not None and len(self.model_list_box) > 0:
+        if self.model_list_box:
             self._populate_box(self.structurebox,
                                self.model_list_box["Structure Factors"])
@@ -1218,12 +1216,12 @@
         self.categorybox.Select(category_pos)
         self._show_combox(None)
-        if self.categorybox.GetValue() == CUSTOM_MODEL \
-                and PLUGIN_NAME_BASE not in state.formfactorcombobox:
+        if (self.categorybox.GetValue() == CUSTOM_MODEL
+                and PLUGIN_NAME_BASE not in state.formfactorcombobox):
             state.formfactorcombobox = \
                 PLUGIN_NAME_BASE + state.formfactorcombobox
         formfactor_pos = 0
         for ind_form in range(self.formfactorbox.GetCount()):
-            if self.formfactorbox.GetString(ind_form) == \
-                                                (state.formfactorcombobox):
+            if (self.formfactorbox.GetString(ind_form)
+                    == state.formfactorcombobox):
                 formfactor_pos = int(ind_form)
                 break
@@ -1235,6 +1233,6 @@
             state.structurecombobox = unicode(state.structurecombobox)
             for ind_struct in range(self.structurebox.GetCount()):
-                if self.structurebox.GetString(ind_struct) == \
-                                                (state.structurecombobox):
+                if (self.structurebox.GetString(ind_struct)
+                        == state.structurecombobox):
                     structfactor_pos = int(ind_struct)
                     break
@@ -1840,10 +1838,10 @@
             if mod_cat == CUSTOM_MODEL:
                 for model in self.model_list_box[mod_cat]:
-                    m_list.append(self.model_dict[model.name])
+                    m_list.append(self.model_dictionary[model.name])
             else:
                 cat_dic = self.master_category_dict[mod_cat]
-                for (model, enabled) in cat_dic:
+                for model, enabled in cat_dic:
                     if enabled:
-                        m_list.append(self.model_dict[model])
+                        m_list.append(self.model_dictionary[model])
         except Exception:
             msg = traceback.format_exc()
@@ -3497,5 +3495,5 @@
         self.model_box.Clear()
 
-        if category == 'Plugin Models':
+        if category == CUSTOM_MODEL:
             for model in self.model_list_box[category]:
                 str_m = str(model).split(".")[0]
Index: src/sas/sasgui/perspectives/fitting/fitpage.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/fitpage.py	(revision 50fcb09b3ee47cf23c26b90d9c291f41415c0aa5)
+++ src/sas/sasgui/perspectives/fitting/fitpage.py	(revision 277257f6caa3c7a18ad588f88501a89a34aa36e4)
@@ -1143,18 +1143,23 @@
             self.model.name = "M" + str(self.index_model)
 
-    def _on_select_model(self, event=None):
+    def _on_select_model(self, event=None, keep_pars=False):
         """
         call back for model selection
         """
         self.Show(False)
-        copy_flag = False
-        is_poly_enabled = None
         if event is not None:
-            if (event.GetEventObject() == self.formfactorbox
-                    and self.structurebox.GetLabel() != 'None')\
-                    or event.GetEventObject() == self.structurebox\
-                    or event.GetEventObject() == self.multifactorbox:
-                copy_flag = self.get_copy_params()
-                is_poly_enabled = self.enable_disp.GetValue()
+            control = event.GetEventObject()
+            if ((control == self.formfactorbox
+                 and self.structurebox.GetLabel() != 'None')
+                    or control == self.structurebox
+                    or control == self.multifactorbox):
+                keep_pars = True
+
+        if keep_pars:
+            saved_pars = self.get_copy_params()
+            is_poly_enabled = self.enable_disp.GetValue()
+        else:
+            saved_pars = None
+            is_poly_enabled = None
 
         self._on_select_model_helper()
@@ -1171,5 +1176,5 @@
         try:
             self.set_dispers_sizer()
-        except:
+        except Exception:
             pass
         self.state.enable_disp = self.enable_disp.GetValue()
@@ -1232,31 +1237,31 @@
             self.state.model.name = self.model.name
 
+        # when select a model only from guictr/button
+        if is_poly_enabled is not None:
+            self.enable_disp.SetValue(is_poly_enabled)
+            self.disable_disp.SetValue(not is_poly_enabled)
+            self._set_dipers_Param(event=None)
+            self.state.enable_disp = self.enable_disp.GetValue()
+            self.state.disable_disp = self.disable_disp.GetValue()
+
+        # Keep the previous param values
+        if saved_pars:
+            self.get_paste_params(saved_pars)
+
         if event is not None:
+            # update list of plugins if new plugin is available
+            # mod_cat = self.categorybox.GetStringSelection()
+            # if mod_cat == CUSTOM_MODEL:
+            #     temp = self.parent.update_model_list()
+            #     if temp:
+            #         self.model_list_box = temp
+            #         current_val = self.formfactorbox.GetLabel()
+            #         pos = self.formfactorbox.GetSelection()
+            #         self._show_combox_helper()
+            #         self.formfactorbox.SetStringSelection(current_val)
+            #         self.formfactorbox.SetValue(current_val)
             # post state to fit panel
             new_event = PageInfoEvent(page=self)
             wx.PostEvent(self.parent, new_event)
-            # update list of plugins if new plugin is available
-            custom_model = CUSTOM_MODEL
-            mod_cat = self.categorybox.GetStringSelection()
-            if mod_cat == custom_model:
-                temp = self.parent.update_model_list()
-                if temp:
-                    self.model_list_box = temp
-                    current_val = self.formfactorbox.GetLabel()
-                    pos = self.formfactorbox.GetSelection()
-                    self._show_combox_helper()
-                    self.formfactorbox.SetSelection(pos)
-                    self.formfactorbox.SetValue(current_val)
-            # when select a model only from guictr/button
-            if is_poly_enabled is not None:
-                self.enable_disp.SetValue(is_poly_enabled)
-                self.disable_disp.SetValue(not is_poly_enabled)
-                self._set_dipers_Param(event=None)
-                self.state.enable_disp = self.enable_disp.GetValue()
-                self.state.disable_disp = self.disable_disp.GetValue()
-
-            # Keep the previous param values
-            if copy_flag:
-                self.get_paste_params(copy_flag)
             wx.CallAfter(self._onDraw, None)
 
@@ -1709,4 +1714,5 @@
                 and not self.temp_multi_functional:
             return None
+        print("_set_fun_box_list", self.model.name)
         # Get the func name list
         list = self.model.fun_list
@@ -1716,6 +1722,6 @@
         ind = 0
         while(ind < len(list)):
-            for key, val in list.iteritems():
-                if (val == ind):
+            for key, val in list.items():
+                if val == ind:
                     fun_box.Append(key, val)
                     break
Index: src/sas/sasgui/perspectives/fitting/fitpanel.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/fitpanel.py	(revision 65f39301a9c81af2f10a086dec2a40fcaf25a0bc)
+++ src/sas/sasgui/perspectives/fitting/fitpanel.py	(revision 277257f6caa3c7a18ad588f88501a89a34aa36e4)
@@ -114,5 +114,5 @@
         """
         temp = self.menu_mng.update()
-        if len(temp):
+        if temp:
             self.model_list_box = temp
         return temp
@@ -121,8 +121,6 @@
         """
         """
-        temp = self.menu_mng.plugins_reset()
-        if len(temp):
-            self.model_list_box = temp
-        return temp
+        self.model_list_box = self.menu_mng.plugins_reset()
+        return self.model_list_box
 
     def get_page_by_id(self, uid):
@@ -298,9 +296,9 @@
         self.model_list_box = dict
 
-    def set_model_dict(self, m_dict):
+    def set_model_dictionary(self, model_dictionary):
         """
         copy a dictionary of model name -> model object
 
-        :param m_dict: dictionary linking model name -> model object
+        :param model_dictionary: dictionary linking model name -> model object
         """
 
@@ -356,5 +354,5 @@
         panel._set_save_flag(not panel.batch_on)
         panel.set_model_dictionary(self.model_dictionary)
-        panel.populate_box(model_dict=self.model_list_box)
+        panel.populate_box(model_list_box=self.model_list_box)
         panel.formfactor_combo_init()
         panel.set_manager(self._manager)
Index: src/sas/sasgui/perspectives/fitting/fitting.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/fitting.py	(revision 00f7ff108e83f1acedecaa5d4ab9f0032a2ca8d5)
+++ src/sas/sasgui/perspectives/fitting/fitting.py	(revision 277257f6caa3c7a18ad588f88501a89a34aa36e4)
@@ -34,4 +34,5 @@
 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
@@ -60,5 +61,4 @@
 from .resultpanel import ResultPanel, PlotResultEvent
 from .gpu_options import GpuOptions
-from . import models
 
 logger = logging.getLogger(__name__)
@@ -297,5 +297,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',
@@ -337,22 +337,28 @@
             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)
-        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)
+        except Exception:
             logger.error("update_custom_combo: %s", sys.exc_value)
 
@@ -364,5 +370,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)
 
@@ -646,5 +652,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
@@ -657,9 +663,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)
 
@@ -778,5 +784,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
@@ -881,6 +887,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,
@@ -925,16 +931,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):
@@ -945,5 +951,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)
@@ -979,6 +986,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
@@ -1004,7 +1011,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)
@@ -1053,10 +1060,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
@@ -1119,5 +1126,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"))
@@ -1143,8 +1150,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:
@@ -1152,8 +1159,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)
@@ -1557,11 +1564,11 @@
                     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)
@@ -1721,5 +1728,5 @@
                                                   fid=data.id)
         self.parent.update_theory(data_id=data.id, theory=new_plot,
-                                   state=state)
+                                  state=state)
         return new_plot
 
@@ -1775,18 +1782,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,
@@ -1796,5 +1802,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!"
@@ -1821,6 +1827,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
@@ -1863,32 +1869,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!"
@@ -1906,5 +1911,5 @@
                       weight=None,
                       toggle_mode_on=False,
-                       update_chisqr=True, source='model'):
+                      update_chisqr=True, source='model'):
         """
         draw model in 2D
@@ -1952,9 +1957,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
