Index: src/sas/sasgui/guiframe/local_perspectives/plotting/plotting.py
===================================================================
--- src/sas/sasgui/guiframe/local_perspectives/plotting/plotting.py	(revision 235f514ba93b57fa63e44309f182acef0b98bb55)
+++ src/sas/sasgui/guiframe/local_perspectives/plotting/plotting.py	(revision 2d9526dfda3bdfe3c9159ab7d9db8399b4a00848)
@@ -14,4 +14,5 @@
 import wx
 import sys
+from copy import deepcopy
 from sas.sasgui.guiframe.events import EVT_NEW_PLOT
 from sas.sasgui.guiframe.events import EVT_PLOT_QRANGE
@@ -275,6 +276,19 @@
                 action_check = True
             else:
+                if action_string == 'update':
+                    # Update all existing plots of data with this ID
+                    for data in event.plots:
+                        for panel in self.plot_panels.values():
+                            if data.id in panel.plots.keys():
+                                plot_exists = True
+                                # Pass each panel it's own copy of the data
+                                # that's being updated, otherwise things like
+                                # colour and line thickness are unintentionally
+                                # synced across panels
+                                self.update_panel(deepcopy(data), panel)
+                    return
+                    
                 group_id = event.group_id
-                if group_id in self.plot_panels.keys():
+                if group_id in self.plot_panels:
                     #remove data from panel
                     if action_string == 'remove':
Index: src/sas/sasgui/perspectives/fitting/fitting.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/fitting.py	(revision 489f53a68015fe01293d70169de3d0f8ba84369e)
+++ src/sas/sasgui/perspectives/fitting/fitting.py	(revision 2d9526dfda3bdfe3c9159ab7d9db8399b4a00848)
@@ -1742,5 +1742,4 @@
             @param unsmeared_error: data error, rescaled to unsmeared model
         """
-
         number_finite = np.count_nonzero(np.isfinite(y))
         np.nan_to_num(y)
@@ -1748,22 +1747,34 @@
                                          data_description=model.name,
                                          data_id=str(page_id) + " " + data.name)
+        plots_to_update = [] # List of plottables that have changed since last calculation
+        # Create the new theories
         if unsmeared_model is not None:
-            self.create_theory_1D(x, unsmeared_model, page_id, model, data, state,
+            unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model, 
+                                  page_id, model, data, state,
                                   data_description=model.name + " unsmeared",
                                   data_id=str(page_id) + " " + data.name + " unsmeared")
+            plots_to_update.append(unsmeared_model_plot)
 
             if unsmeared_data is not None and unsmeared_error is not None:
-                self.create_theory_1D(x, unsmeared_data, page_id, model, data, state,
+                unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data, 
+                                      page_id, model, data, state,
                                       data_description="Data unsmeared",
                                       data_id="Data  " + data.name + " unsmeared",
                                       dy=unsmeared_error)
-        # Comment this out until we can get P*S models with correctly populated parameters
-        #if sq_model is not None and pq_model is not None:
-        #    self.create_theory_1D(x, sq_model, page_id, model, data, state,
-        #                          data_description=model.name + " S(q)",
-        #                          data_id=str(page_id) + " " + data.name + " S(q)")
-        #    self.create_theory_1D(x, pq_model, page_id, model, data, state,
-        #                          data_description=model.name + " P(q)",
-        #                          data_id=str(page_id) + " " + data.name + " P(q)")
+                plots_to_update.append(unsmeared_data_plot)
+        if sq_model is not None and pq_model is not None:
+            sq_id = str(page_id) + " " + data.name + " S(q)"
+            sq_plot = self.create_theory_1D(x, sq_model, page_id, model, data, state,
+                                  data_description=model.name + " S(q)",
+                                  data_id=sq_id)
+            plots_to_update.append(sq_plot)
+            pq_id = str(page_id) + " " + data.name + " P(q)"
+            pq_plot = self.create_theory_1D(x, pq_model, page_id, model, data, state,
+                                  data_description=model.name + " P(q)",
+                                  data_id=pq_id)
+            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, 
+                                              action='update'))
 
         current_pg = self.fit_panel.get_page_by_id(page_id)
Index: src/sas/sasgui/perspectives/fitting/model_thread.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/model_thread.py	(revision 7432acb919f4013119ca918a73350297e0d4c93f)
+++ src/sas/sasgui/perspectives/fitting/model_thread.py	(revision 0f9ea1cee80a92f71e4bec65998ca56a3de65fd6)
@@ -71,5 +71,5 @@
                     (self.data.qy_data * self.data.qy_data))
 
-        # For theory, qmax is based on 1d qmax 
+        # For theory, qmax is based on 1d qmax
         # so that must be mulitified by sqrt(2) to get actual max for 2d
         index_model = (self.qmin <= radius) & (radius <= self.qmax)
@@ -91,9 +91,10 @@
                 self.data.qy_data[index_model]
             ])
-        output = np.zeros(len(self.data.qx_data))
+        # Initialize output to NaN so masked elements do not get plotted.
+        output = np.empty_like(self.data.qx_data)
         # output default is None
         # This method is to distinguish between masked
         #point(nan) and data point = 0.
-        output = output / output
+        output[:] = np.NaN
         # set value for self.mask==True, else still None to Plottools
         output[index_model] = value
@@ -198,23 +199,22 @@
             output[index] = self.model.evalDistribution(self.data.x[index])
 
+        x=self.data.x[index]
+        y=output[index]
         sq_values = None
         pq_values = None
-        s_model = None
-        p_model = None
         if isinstance(self.model, MultiplicationModel):
             s_model = self.model.s_model
             p_model = self.model.p_model
-        elif hasattr(self.model, "get_composition_models"):
-            p_model, s_model = self.model.get_composition_models()
-
-        if p_model is not None and s_model is not None:
-            sq_values = np.zeros((len(self.data.x)))
-            pq_values = np.zeros((len(self.data.x)))
-            sq_values[index] = s_model.evalDistribution(self.data.x[index])
-            pq_values[index] = p_model.evalDistribution(self.data.x[index])
+            sq_values = s_model.evalDistribution(x)
+            pq_values = p_model.evalDistribution(x)
+        elif hasattr(self.model, "calc_composition_models"):
+            results = self.model.calc_composition_models(x)
+            if results is not None:
+                pq_values, sq_values = results
+
 
         elapsed = time.time() - self.starttime
 
-        self.complete(x=self.data.x[index], y=output[index],
+        self.complete(x=x, y=y,
                       page_id=self.page_id,
                       state=self.state,
Index: src/sas/sasgui/plottools/plottables.py
===================================================================
--- src/sas/sasgui/plottools/plottables.py	(revision 45dffa69cb5935e2da7c77a2f040debb07ceb1c6)
+++ src/sas/sasgui/plottools/plottables.py	(revision 2d9526dfda3bdfe3c9159ab7d9db8399b4a00848)
@@ -239,13 +239,16 @@
     def replace(self, plottable):
         """Replace an existing plottable from the graph"""
-        selected_color = None
+        # If the user has set a custom color, ensure the new plot is the same color
+        selected_color = plottable.custom_color
         selected_plottable = None
         for p in self.plottables.keys():
             if plottable.id == p.id:
                 selected_plottable = p
-                selected_color = self.plottables[p]
+                if selected_color is None:
+                    selected_color = self.plottables[p]
                 break
-        if  selected_plottable is not None and selected_color is not None:
+        if selected_plottable is not None and selected_color is not None:
             del self.plottables[selected_plottable]
+            plottable.custom_color = selected_color
             self.plottables[plottable] = selected_color
 
