Index: src/sas/qtgui/MainWindow/DataExplorer.py
===================================================================
--- src/sas/qtgui/MainWindow/DataExplorer.py	(revision ebfe223ac3fa85fb264da68e2e309f48aaf4b236)
+++ src/sas/qtgui/MainWindow/DataExplorer.py	(revision 3ae917937db3898ec8e94fe0aa83d82bec4edd19)
@@ -4,4 +4,5 @@
 import time
 import logging
+import re
 
 from PyQt5 import QtCore
@@ -36,4 +37,5 @@
     # The controller which is responsible for managing signal slots connections
     # for the gui and providing an interface to the data model.
+    theory_plot_ID_pattern = re.compile(r"^([0-9]+)\s+(\[(.*)\]\s+)?(.*)$")
 
     def __init__(self, parent=None, guimanager=None, manager=None):
@@ -504,4 +506,8 @@
                 self.active_plots[plot_id].replacePlot(plot_id, plot)
             else:
+                # Don't plot intermediate data e.g. P(Q), S(Q)
+                match = self.theory_plot_ID_pattern.match(plot_id)
+                if match and match.groups()[1] != None:
+                    continue
                 # 'sophisticated' test to generate standalone plot for residuals
                 if 'esiduals' in plot.title:
Index: src/sas/qtgui/Perspectives/Fitting/FittingLogic.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingLogic.py	(revision 87dfca4108319b9f2e8294ec16eebae1042a3693)
+++ src/sas/qtgui/Perspectives/Fitting/FittingLogic.py	(revision 3ae917937db3898ec8e94fe0aa83d82bec4edd19)
@@ -132,14 +132,9 @@
         self._data.ymax = ymax
 
-    def new1DPlot(self, return_data, tab_id):
-        """
-        Create a new 1D data instance based on fitting results
-        """
-        # Unpack return data from Calc1D
-        x, y, page_id, state, weight,\
-        fid, toggle_mode_on, \
-        elapsed, index, model,\
-        data, update_chisqr, source = return_data
-
+    def _create1DPlot(self, tab_id, x, y, model, data, component=None):
+        """
+        For internal use: create a new 1D data instance based on fitting results
+        component is a string indicating the model component, e.g. "P(Q)"
+        """
         # Create the new plot
         new_plot = Data1D(x=x, y=y)
@@ -150,10 +145,9 @@
 
         new_plot.group_id = data.group_id
-        new_plot.id = str(tab_id) + " " + model.id
-
-        if data.filename:
-            new_plot.name = model.name + " [" + data.filename + "]" # data file
-        else:
-            new_plot.name = model.name + " [" + model.id + "]"  # theory
+        new_plot.id = str(tab_id) + " " + ("[" + component + "] " if component else "") + model.id
+
+        # use data.filename for data, use model.id for theory
+        id_str = data.filename if data.filename else model.id
+        new_plot.name = model.name + ((" " + component) if component else "") + " [" + id_str + "]"
 
         new_plot.title = new_plot.name
@@ -162,4 +156,18 @@
 
         return new_plot
+
+    def new1DPlot(self, return_data, tab_id):
+        """
+        Create a new 1D data instance based on fitting results
+        """
+        # Unpack return data from Calc1D
+        x, y, page_id, state, weight,\
+        fid, toggle_mode_on, \
+        elapsed, index, model, \
+        data, update_chisqr, source, \
+        unsmeared_output, unsmeared_data, unsmeared_error, \
+        pq_values, sq_values = return_data
+
+        return self._create1DPlot(tab_id, x, y, model, data)
 
     def new2DPlot(self, return_data):
@@ -205,4 +213,25 @@
         return new_plot
 
+    def new1DProductPlots(self, return_data, tab_id):
+        """
+        If return_data contains separated P(Q) and S(Q) data, create 1D plots for each and return as a tuple.
+        Returns (None, None) if this data is unavailable.
+        """
+        # Unpack return data from Calc1D
+        x, y, page_id, state, weight, \
+        fid, toggle_mode_on, \
+        elapsed, index, model, \
+        data, update_chisqr, source, \
+        unsmeared_output, unsmeared_data, unsmeared_error, \
+        pq_values, sq_values = return_data
+
+        if pq_values is not None and sq_values is not None:
+            pq_plot = self._create1DPlot(tab_id, x, pq_values, model, data, component="P(Q)")
+            sq_plot = self._create1DPlot(tab_id, x, sq_values, model, data, component="S(Q)")
+
+            return pq_plot, sq_plot
+        else:
+            return None, None
+
     def computeDataRange(self):
         """
Index: src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision a2cc8b97501a69cd475b0ef47ca677fe57b996a4)
+++ src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision 3ae917937db3898ec8e94fe0aa83d82bec4edd19)
@@ -2113,7 +2113,9 @@
             self.updateModelIndex(fitted_data)
         else:
-            name = self.nameForFittedData(self.kernel_module.id)
+            if not fitted_data.name:
+                name = self.nameForFittedData(self.kernel_module.id)
+            else:
+                name = fitted_data.name
             fitted_data.title = name
-            fitted_data.name = name
             fitted_data.filename = name
             fitted_data.symbol = "Line"
@@ -2229,4 +2231,10 @@
         self.model_data = fitted_data
 
+        # Create plots for intermediate product data
+        pq_data, sq_data = self.logic.new1DProductPlots(return_data, self.tab_id)
+        if pq_data is not None and sq_data is not None:
+            self.createNewIndex(pq_data)
+            self.createNewIndex(sq_data)
+
     def complete2D(self, return_data):
         """
Index: src/sas/qtgui/Perspectives/Fitting/ModelThread.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/ModelThread.py	(revision d4dac8028a51b020b8e01f0998d475e053206dea)
+++ src/sas/qtgui/Perspectives/Fitting/ModelThread.py	(revision 3ae917937db3898ec8e94fe0aa83d82bec4edd19)
@@ -222,12 +222,15 @@
             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 = numpy.zeros((len(self.data.x)))
-            pq_values = numpy.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])
+        elif hasattr(self.model, "calc_composition_models"):
+            results = self.model.calc_composition_models(self.data.x[index])
+            if results is not None:
+                pq_values, sq_values = results
+
+        if pq_values is None or sq_values is None:
+            if p_model is not None and s_model is not None:
+                sq_values = numpy.zeros((len(self.data.x)))
+                pq_values = numpy.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])
 
         elapsed = time.time() - self.starttime
@@ -243,5 +246,7 @@
                     self.data,
                     self.update_chisqr,
-                    self.source)
+                    self.source,
+                    unsmeared_output, unsmeared_data, unsmeared_error,
+                    pq_values, sq_values)
         else:
             self.complete(x=self.data.x[index], y=output[index],
