Index: src/sas/sasgui/perspectives/fitting/basepage.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/basepage.py	(revision a0373d5a680d6dd4bbb571a7d08e588ec9a11040)
+++ src/sas/sasgui/perspectives/fitting/basepage.py	(revision 6c382da7a67e14f0ad75317f0696ce771b802d39)
@@ -933,5 +933,5 @@
         if len(self._disp_obj_dict) > 0:
             for k, v in self._disp_obj_dict.iteritems():
-                self.state._disp_obj_dict[k] = v
+                self.state._disp_obj_dict[k] = v.type
 
             self.state.values = copy.deepcopy(self.values)
@@ -1010,5 +1010,5 @@
             if len(self._disp_obj_dict) > 0:
                 for k, v in self._disp_obj_dict.iteritems():
-                    self.state._disp_obj_dict[k] = v
+                    self.state._disp_obj_dict[k] = v.type
 
             self.state.values = copy.deepcopy(self.values)
@@ -1379,14 +1379,7 @@
         self.weights = copy.deepcopy(state.weights)
 
-        for key, disp in state._disp_obj_dict.iteritems():
-            # From saved file, disp_model can not be sent in model obj.
-            # it will be sent as a string here, then converted to model object.
-            if disp.__class__.__name__ == 'str':
-                disp_model = None
-                com_str = "from sasmodels.weights "
-                com_str += "import %s as disp_func \ndisp_model = disp_func()"
-                exec com_str % disp
-            else:
-                disp_model = disp
+        for key, disp_type in state._disp_obj_dict.iteritems():
+            #disp_model = disp
+            disp_model = POLYDISPERSITY_MODELS[disp_type]()
             self._disp_obj_dict[key] = disp_model
             param_name = key.split('.')[0]
@@ -2520,5 +2513,5 @@
                 self._disp_obj_dict[name1] = disp_model
                 self.model.set_dispersion(param_name, disp_model)
-                self.state._disp_obj_dict[name1] = disp_model
+                self.state._disp_obj_dict[name1] = disp_model.type
 
                 value1 = str(format_number(self.model.getParam(name1), True))
@@ -2543,4 +2536,6 @@
                         item[0].Enable()
                         item[2].Enable()
+                        item[3].Show(True)
+                        item[4].Show(True)
                         item[5].Enable()
                         item[6].Enable()
@@ -2635,5 +2630,5 @@
         self._disp_obj_dict[name] = disp
         self.model.set_dispersion(name.split('.')[0], disp)
-        self.state._disp_obj_dict[name] = disp
+        self.state._disp_obj_dict[name] = disp.type
         self.values[name] = values
         self.weights[name] = weights
@@ -3296,7 +3291,12 @@
                     pd = content[name][1]
                     if name.count('.') > 0:
+                        # If this is parameter.width, then pd may be a floating
+                        # point value or it may be an array distribution.
+                        # Nothing to do for parameter.npts or parameter.nsigmas.
                         try:
                             float(pd)
-                        except:
+                            if name.endswith('.npts'):
+                                pd = int(pd)
+                        except Exception:
                             #continue
                             if not pd and pd != '':
@@ -3306,4 +3306,6 @@
                         # Only array func has pd == '' case.
                         item[2].Enable(False)
+                    else:
+                        item[2].Enable(True)
                     if item[2].__class__.__name__ == "ComboBox":
                         if content[name][1] in self.model.fun_list:
@@ -3332,6 +3334,11 @@
                         pd = value[0]
                         if name.count('.') > 0:
+                            # If this is parameter.width, then pd may be a floating
+                            # point value or it may be an array distribution.
+                            # Nothing to do for parameter.npts or parameter.nsigmas.
                             try:
                                 pd = float(pd)
+                                if name.endswith('.npts'):
+                                    pd = int(pd)
                             except:
                                 #continue
@@ -3342,4 +3349,6 @@
                             # Only array func has pd == '' case.
                             item[2].Enable(False)
+                        else:
+                            item[2].Enable(True)
                         if item[2].__class__.__name__ == "ComboBox":
                             if value[0] in self.model.fun_list:
@@ -3361,62 +3370,84 @@
         Helps get paste for poly function
 
-        :param item: Gui param items
-        :param value: the values for parameter ctrols
-        """
-        is_array = False
-        if len(value[1]) > 0:
-            # Only for dispersion func.s
-            try:
-                item[7].SetValue(value[1])
-                selection = item[7].GetCurrentSelection()
-                name = item[7].Name
-                param_name = name.split('.')[0]
-                dispersity = item[7].GetClientData(selection)
-                disp_model = dispersity()
-                # Only for array disp
-                try:
-                    pd_vals = numpy.array(value[2])
-                    pd_weights = numpy.array(value[3])
-                    if len(pd_vals) > 0 and len(pd_vals) > 0:
-                        if len(pd_vals) == len(pd_weights):
-                            self._set_disp_array_cb(item=item)
-                            self._set_array_disp_model(name=name,
-                                                       disp=disp_model,
-                                                       values=pd_vals,
-                                                       weights=pd_weights)
-                            is_array = True
-                except Exception:
-                    logging.error(traceback.format_exc())
-                if not is_array:
-                    self._disp_obj_dict[name] = disp_model
-                    self.model.set_dispersion(name,
-                                              disp_model)
-                    self.state._disp_obj_dict[name] = \
-                                              disp_model
-                    self.model.set_dispersion(param_name, disp_model)
-                    self.state.values = self.values
-                    self.state.weights = self.weights
-                    self.model._persistency_dict[param_name] = \
-                                            [self.state.values,
-                                             self.state.weights]
-
-            except Exception:
-                logging.error(traceback.format_exc())
-                print "Error in BasePage._paste_poly_help: %s" % \
-                                        sys.exc_info()[1]
-
-    def _set_disp_array_cb(self, item):
+        *item* is the parameter name
+
+        *value* depends on which parameter is being processed, and whether it
+        has array polydispersity.
+
+        For parameters without array polydispersity:
+
+            parameter => ['FLOAT', '']
+            parameter.width => ['FLOAT', 'DISTRIBUTION', '']
+            parameter.npts => ['FLOAT', '']
+            parameter.nsigmas => ['FLOAT', '']
+
+        For parameters with array polydispersity:
+
+            parameter => ['FLOAT', '']
+            parameter.width => ['FILENAME', 'array', [x1, ...], [w1, ...]]
+            parameter.npts => ['FLOAT', '']
+            parameter.nsigmas => ['FLOAT', '']
+        """
+        # Do nothing if not setting polydispersity
+        if len(value[1]) == 0:
+            return
+
+        try:
+            name = item[7].Name
+            param_name = name.split('.')[0]
+            item[7].SetValue(value[1])
+            selection = item[7].GetCurrentSelection()
+            dispersity = item[7].GetClientData(selection)
+            disp_model = dispersity()
+
+            if value[1] == 'array':
+                pd_vals = numpy.array(value[2])
+                pd_weights = numpy.array(value[3])
+                if len(pd_vals) == 0 or len(pd_vals) != len(pd_weights):
+                    msg = ("bad array distribution parameters for %s"
+                           % param_name)
+                    raise ValueError(msg)
+                self._set_disp_cb(True, item=item)
+                self._set_array_disp_model(name=name,
+                                           disp=disp_model,
+                                           values=pd_vals,
+                                           weights=pd_weights)
+            else:
+                self._set_disp_cb(False, item=item)
+                self._disp_obj_dict[name] = disp_model
+                self.model.set_dispersion(param_name, disp_model)
+                self.state._disp_obj_dict[name] = disp_model.type
+                # TODO: It's not an array, why update values and weights?
+                self.model._persistency_dict[param_name] = \
+                    [self.values, self.weights]
+                self.state.values = self.values
+                self.state.weights = self.weights
+
+        except Exception:
+            logging.error(traceback.format_exc())
+            print "Error in BasePage._paste_poly_help: %s" % \
+                                    sys.exc_info()[1]
+
+    def _set_disp_cb(self, isarray, item):
         """
         Set cb for array disp
         """
-        item[0].SetValue(False)
-        item[0].Enable(False)
-        item[2].Enable(False)
-        item[3].Show(False)
-        item[4].Show(False)
-        item[5].SetValue('')
-        item[5].Enable(False)
-        item[6].SetValue('')
-        item[6].Enable(False)
+        if isarray:
+            item[0].SetValue(False)
+            item[0].Enable(False)
+            item[2].Enable(False)
+            item[3].Show(False)
+            item[4].Show(False)
+            item[5].SetValue('')
+            item[5].Enable(False)
+            item[6].SetValue('')
+            item[6].Enable(False)
+        else:
+            item[0].Enable()
+            item[2].Enable()
+            item[3].Show(True)
+            item[4].Show(True)
+            item[5].Enable()
+            item[6].Enable()
 
     def update_pinhole_smear(self):
Index: src/sas/sasgui/perspectives/fitting/fitpage.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/fitpage.py	(revision ee4b3cbc1850f87671526c54335834959ffdfe84)
+++ src/sas/sasgui/perspectives/fitting/fitpage.py	(revision 6c382da7a67e14f0ad75317f0696ce771b802d39)
@@ -10,4 +10,5 @@
 import math
 import time
+import traceback
 
 from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS
@@ -2058,5 +2059,5 @@
             msg = "Error: This model state has missing or outdated "
             msg += "information.\n"
-            msg += "%s" % (sys.exc_value)
+            msg += traceback.format_exc()
             wx.PostEvent(self._manager.parent,
                          StatusEvent(status=msg, info="error"))
Index: src/sas/sasgui/perspectives/fitting/pagestate.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/pagestate.py	(revision 654e8e066dda6b98c221cad28e05fa6996e7fc11)
+++ src/sas/sasgui/perspectives/fitting/pagestate.py	(revision 6c382da7a67e14f0ad75317f0696ce771b802d39)
@@ -24,4 +24,6 @@
 from xml.dom.minidom import parseString
 from lxml import etree
+
+import sasmodels.weights
 
 import sas.sascalc.dataloader
@@ -474,5 +476,6 @@
                 value = content[1]
             except Exception:
-                logging.error(traceback.format_exc())
+                msg = "Report string expected 'name: value' but got %r"%line
+                logging.error(msg)
             if name.count("State created"):
                 repo_time = "" + value
@@ -516,5 +519,6 @@
                         title_name = HEADER % title
                 except Exception:
-                    logging.error(traceback.format_exc())
+                    msg = "While parsing 'data: ...'\n"
+                    logging.error(msg + traceback.format_exc())
             if name == "model name ":
                 try:
@@ -531,5 +535,6 @@
                     q_range = CENTRE % q_name
                 except Exception:
-                    logging.error(traceback.format_exc())
+                    msg = "While parsing 'Plotting Range: ...'\n"
+                    logging.error(msg + traceback.format_exc())
         paramval = ""
         for lines in param_string.split(":"):
@@ -711,5 +716,4 @@
         # For self.values ={ disp_param_name: [vals,...],...}
         # and for self.weights ={ disp_param_name: [weights,...],...}
-        value_list = {}
         for item in LIST_OF_MODEL_ATTRIBUTES:
             element = newdoc.createElement(item[0])
@@ -725,9 +729,8 @@
 
         # Create doc for the dictionary of self._disp_obj_dic
-        for item in DISPERSION_LIST:
-            element = newdoc.createElement(item[0])
-            value_list = getattr(self, item[1])
-            for key, val in value_list.iteritems():
-                value = repr(val)
+        for tagname, varname, tagtype in DISPERSION_LIST:
+            element = newdoc.createElement(tagname)
+            value_list = getattr(self, varname)
+            for key, value in value_list.iteritems():
                 sub_element = newdoc.createElement(key)
                 sub_element.setAttribute('name', str(key))
@@ -847,32 +850,30 @@
                 # Recover _disp_obj_dict from xml file
                 self._disp_obj_dict = {}
-                for item in DISPERSION_LIST:
-                    # Get node
-                    node = get_content("ns:%s" % item[0], entry)
+                for tagname, varname, tagtype in DISPERSION_LIST:
+                    node = get_content("ns:%s" % tagname, entry)
                     for attr in node:
-                        name = str(attr.get('name'))
-                        val = attr.get('value')
-                        value = val.split(" instance")[0]
-                        disp_name = value.split("<")[1]
-                        try:
-                            # Try to recover disp_model object from strings
-                            com = "from sas.models.dispersion_models "
-                            com += "import %s as disp"
-                            com_name = disp_name.split(".")[3]
-                            exec com % com_name
-                            disp_model = disp()
-                            attribute = getattr(self, item[1])
-                            attribute[name] = com_name
-                        except Exception:
-                            logging.error(traceback.format_exc())
+                        parameter = str(attr.get('name'))
+                        value = attr.get('value')
+                        if value.startswith("<"):
+                            try:
+                                # <path.to.NamedDistribution object/instance...>
+                                cls_name = value[1:].split()[0].split('.')[-1]
+                                cls = getattr(sasmodels.weights, cls_name)
+                                value = cls.type
+                            except Exception:
+                                logging.error("unable to load distribution %r for %s"
+                                              % (value, parameter))
+                                continue
+                        _disp_obj_dict = getattr(self, varname)
+                        _disp_obj_dict[parameter] = value
 
                 # get self.values and self.weights dic. if exists
-                for item in LIST_OF_MODEL_ATTRIBUTES:
-                    node = get_content("ns:%s" % item[0], entry)
+                for tagname, varname in LIST_OF_MODEL_ATTRIBUTES:
+                    node = get_content("ns:%s" % tagname, entry)
                     dic = {}
                     value_list = []
                     for par in node:
                         name = par.get('name')
-                        values = par.text.split('\n')
+                        values = par.text.split()
                         # Get lines only with numbers
                         for line in values:
@@ -882,7 +883,9 @@
                             except Exception:
                                 # pass if line is empty (it happens)
-                                logging.error(traceback.format_exc())
+                                msg = ("Error reading %r from %s %s\n"
+                                       % (line, tagname, name))
+                                logging.error(msg + traceback.format_exc())
                         dic[name] = numpy.array(value_list)
-                    setattr(self, item[1], dic)
+                    setattr(self, varname, dic)
 
     def set_plot_state(self, figs, canvases):
@@ -1231,5 +1234,6 @@
 
         except:
-            logging.info("XML document does not contain fitting information.\n %s" % sys.exc_value)
+            logging.info("XML document does not contain fitting information.\n"
+                         + traceback.format_exc())
 
         return state
