Index: src/sas/qtgui/MainWindow/DataExplorer.py
===================================================================
--- src/sas/qtgui/MainWindow/DataExplorer.py	(revision 60d55a7bee9728940641005a1bf038626e067160)
+++ src/sas/qtgui/MainWindow/DataExplorer.py	(revision 0cd98a1bff2f5cc0a67f68ad681ae7a3c8379c75)
@@ -42,5 +42,4 @@
         # Main model for keeping loaded data
         self.model = QtGui.QStandardItemModel(self)
-
         # Secondary model for keeping frozen data sets
         self.theory_model = QtGui.QStandardItemModel(self)
@@ -98,4 +97,5 @@
         self.communicator.plotUpdateSignal.connect(self.updatePlot)
         self.communicator.maskEditorSignal.connect(self.showEditDataMask)
+        self.communicator.extMaskEditorSignal.connect(self.extShowEditDataMask)
 
         self.cbgraph.editTextChanged.connect(self.enableGraphCombo)
@@ -598,5 +598,5 @@
         plot2D.plot(plot_set)
         self.addPlot(plot2D)
-        self.active_plots[plot2D.data.id] = plot2D
+        self.active_plots[plot2D.data.name] = plot2D
         #============================================
         # Experimental hook for silx charts
@@ -626,5 +626,5 @@
                 new_plot.plot(plot_set, transform=transform)
                 # active_plots may contain multiple charts
-                self.active_plots[plot_set.id] = new_plot
+                self.active_plots[plot_set.name] = new_plot
             elif isinstance(plot_set, Data2D):
                 self.addDataPlot2D(plot_set, item)
@@ -697,5 +697,5 @@
                 old_plot.plot()
                 # need this for lookup - otherwise this plot will never update
-                self.active_plots[plot_set.id] = old_plot
+                self.active_plots[plot_set.name] = old_plot
 
     def updatePlot(self, data):
@@ -711,7 +711,7 @@
 
         ids_keys = list(self.active_plots.keys())
-        ids_vals = [val.data.id for val in self.active_plots.values()]
-
-        data_id = data.id
+        ids_vals = [val.data.name for val in self.active_plots.values()]
+
+        data_id = data.name
         if data_id in ids_keys:
             self.active_plots[data_id].replacePlot(data_id, data)
@@ -952,15 +952,17 @@
         model = proxy.sourceModel()
 
-        if index.isValid():
-            model_item = model.itemFromIndex(proxy.mapToSource(index))
-            # Find the mapped index
-            orig_index = model_item.isCheckable()
-            if orig_index:
-                # Check the data to enable/disable actions
-                is_2D = isinstance(GuiUtils.dataFromItem(model_item), Data2D)
-                self.actionQuick3DPlot.setEnabled(is_2D)
-                self.actionEditMask.setEnabled(is_2D)
-                # Fire up the menu
-                self.context_menu.exec_(self.current_view.mapToGlobal(position))
+        if not index.isValid():
+            return
+        model_item = model.itemFromIndex(proxy.mapToSource(index))
+        # Find the mapped index
+        orig_index = model_item.isCheckable()
+        if not orig_index:
+            return
+        # Check the data to enable/disable actions
+        is_2D = isinstance(GuiUtils.dataFromItem(model_item), Data2D)
+        self.actionQuick3DPlot.setEnabled(is_2D)
+        self.actionEditMask.setEnabled(is_2D)
+        # Fire up the menu
+        self.context_menu.exec_(self.current_view.mapToGlobal(position))
 
     def showDataInfo(self):
@@ -1059,15 +1061,36 @@
         self.new_plot.show()
 
+    def extShowEditDataMask(self):
+        self.showEditDataMask()
+
     def showEditDataMask(self, data=None):
         """
         Mask Editor for 2D plots
         """
-        if data is None or not isinstance(data, Data2D):
-            index = self.current_view.selectedIndexes()[0]
-            proxy = self.current_view.model()
-            model = proxy.sourceModel()
-            model_item = model.itemFromIndex(proxy.mapToSource(index))
-
-            data = GuiUtils.dataFromItem(model_item)
+        try:
+            if data is None or not isinstance(data, Data2D):
+                index = self.current_view.selectedIndexes()[0]
+                proxy = self.current_view.model()
+                model = proxy.sourceModel()
+                model_item = model.itemFromIndex(proxy.mapToSource(index))
+
+                data = GuiUtils.dataFromItem(model_item)
+
+            if data is None or not isinstance(data, Data2D):
+                msg = QtWidgets.QMessageBox()
+                msg.setIcon(QtWidgets.QMessageBox.Information)
+                msg.setText("Error: cannot apply mask. \
+                                Please select a 2D dataset.")
+                msg.setStandardButtons(QtWidgets.QMessageBox.Cancel)
+                msg.exec_()
+                return
+        except:
+            msg = QtWidgets.QMessageBox()
+            msg.setIcon(QtWidgets.QMessageBox.Information)
+            msg.setText("Error: No dataset selected. \
+                            Please select a 2D dataset.")
+            msg.setStandardButtons(QtWidgets.QMessageBox.Cancel)
+            msg.exec_()
+            return
 
         mask_editor = MaskEditor(self, data)
Index: src/sas/qtgui/MainWindow/GuiManager.py
===================================================================
--- src/sas/qtgui/MainWindow/GuiManager.py	(revision f84d793343c420fd47b44c3b601e90f9e82ea451)
+++ src/sas/qtgui/MainWindow/GuiManager.py	(revision 339e22b9f5c08262b1d5b0b551ce467bcf83178c)
@@ -422,5 +422,4 @@
         self._workspace.actionExcel.triggered.connect(self.actionExcel)
         self._workspace.actionLatex.triggered.connect(self.actionLatex)
-
         # View
         self._workspace.actionShow_Grid_Window.triggered.connect(self.actionShow_Grid_Window)
@@ -452,4 +451,6 @@
         self._workspace.actionManage_Custom_Models.triggered.connect(self.actionManage_Custom_Models)
         self._workspace.actionAddMult_Models.triggered.connect(self.actionAddMult_Models)
+        self._workspace.actionEditMask.triggered.connect(self.actionEditMask)
+
         # Window
         self._workspace.actionCascade.triggered.connect(self.actionCascade)
@@ -781,4 +782,8 @@
         self.add_mult_editor.show()
 
+    def actionEditMask(self):
+
+        self.communicate.extMaskEditorSignal.emit()
+
     #============ ANALYSIS =================
     def actionFitting(self):
Index: src/sas/qtgui/MainWindow/UI/MainWindowUI.ui
===================================================================
--- src/sas/qtgui/MainWindow/UI/MainWindowUI.ui	(revision dda8f16d5052858e8e3b59357f178cbd74fe3664)
+++ src/sas/qtgui/MainWindow/UI/MainWindowUI.ui	(revision 2f14b5d7fb7a3d8d1023220bb53c48e8763cdf5a)
@@ -113,4 +113,6 @@
     <addaction name="actionManage_Custom_Models"/>
     <addaction name="actionAddMult_Models"/>
+    <addaction name="separator"/>
+    <addaction name="actionEditMask"/>
    </widget>
    <widget class="QMenu" name="menuWindow">
@@ -413,4 +415,9 @@
    </property>
   </action>
+    <action name="actionEditMask">
+   <property name="text">
+    <string>Edit Mask</string>
+   </property>
+  </action>
   <action name="actionCascade">
    <property name="text">
Index: src/sas/qtgui/Perspectives/Fitting/FittingLogic.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingLogic.py	(revision dcabba7be660ff2e140942eb331ca846d1f2a399)
+++ src/sas/qtgui/Perspectives/Fitting/FittingLogic.py	(revision dcabba7be660ff2e140942eb331ca846d1f2a399)
@@ -161,5 +161,4 @@
         Create a new 1D data instance based on fitting results
         """
-
         return self._create1DPlot(tab_id, return_data['x'], return_data['y'],
                                   return_data['model'], return_data['data'])
@@ -212,18 +211,10 @@
         (pq_plot, sq_plot). If either are unavailable, the corresponding plot is None.
         """
-
-        pq_plot = None
-        sq_plot = None
-
-        if return_data.get('pq_values', None) is not None:
-            pq_plot = self._create1DPlot(tab_id, return_data['x'],
-                    return_data['pq_values'], return_data['model'],
-                    return_data['data'], component="P(Q)")
-        if return_data.get('sq_values', None) is not None:
-            sq_plot = self._create1DPlot(tab_id, return_data['x'],
-                    return_data['sq_values'], return_data['model'],
-                    return_data['data'], component="S(Q)")
-
-        return pq_plot, sq_plot
+        plots = []
+        for name, result in return_data['intermediate_results'].items():
+            plots.append(self._create1DPlot(tab_id, return_data['x'], result,
+                         return_data['model'], return_data['data'],
+                         component=name))
+        return plots
 
     def computeDataRange(self):
Index: src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py	(revision 70f445859abd127c3fa7cd9f6b8e2700e7bcb1a2)
+++ src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py	(revision 70f445859abd127c3fa7cd9f6b8e2700e7bcb1a2)
@@ -167,5 +167,5 @@
     return rows
 
-def addSimpleParametersToModel(parameters, is2D, parameters_original=None, model=None, view=None):
+def addSimpleParametersToModel(parameters, is2D, parameters_original=None, model=None, view=None, row_num=None):
     """
     Update local ModelModel with sasmodel parameters (non-dispersed, non-magnetic)
@@ -216,7 +216,13 @@
         # Append to the model and use the combobox, if required
         if None not in (model, view):
-            model.appendRow(row)
+            if row_num is None:
+                model.appendRow(row)
+            else:
+                model.insertRow(row_num, row)
+                row_num += 1
+
             if cbox:
                 view.setIndexWidget(item2.index(), cbox)
+
         rows.append(row)
 
Index: src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision 5fb714bc8d76b96b914937e72cffc3f835224dd1)
+++ src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision d4ba5659c28772e9c307ab44a02664ec480d11a5)
@@ -48,5 +48,4 @@
 from sas.qtgui.Perspectives.Fitting.ReportPageLogic import ReportPageLogic
 
-
 TAB_MAGNETISM = 4
 TAB_POLY = 3
@@ -188,4 +187,5 @@
 
         # Overwrite data type descriptor
+
         self.is2D = True if isinstance(self.logic.data, Data2D) else False
 
@@ -563,5 +563,6 @@
         When clicked on white space: model description
         """
-        rows = [s.row() for s in self.lstParams.selectionModel().selectedRows()]
+        rows = [s.row() for s in self.lstParams.selectionModel().selectedRows()
+                if self.isCheckable(s.row())]
         menu = self.showModelDescription() if not rows else self.modelContextMenu(rows)
         try:
@@ -799,14 +800,13 @@
     def getConstraintForRow(self, row):
         """
-        For the given row, return its constraint, if any
-        """
-        if self.isCheckable(row):
-            item = self._model_model.item(row, 1)
-            try:
-                return item.child(0).data()
-            except AttributeError:
-                # return none when no constraints
-                pass
-        return None
+        For the given row, return its constraint, if any (otherwise None)
+        """
+        if not self.isCheckable(row):
+            return None
+        item = self._model_model.item(row, 1)
+        try:
+            return item.child(0).data()
+        except AttributeError:
+            return None
 
     def rowHasConstraint(self, row):
@@ -814,10 +814,12 @@
         Finds out if row of the main model has a constraint child
         """
-        if self.isCheckable(row):
-            item = self._model_model.item(row, 1)
-            if item.hasChildren():
-                c = item.child(0).data()
-                if isinstance(c, Constraint):
-                    return True
+        if not self.isCheckable(row):
+            return False
+        item = self._model_model.item(row, 1)
+        if not item.hasChildren():
+            return False
+        c = item.child(0).data()
+        if isinstance(c, Constraint):
+            return True
         return False
 
@@ -826,10 +828,12 @@
         Finds out if row of the main model has an active constraint child
         """
-        if self.isCheckable(row):
-            item = self._model_model.item(row, 1)
-            if item.hasChildren():
-                c = item.child(0).data()
-                if isinstance(c, Constraint) and c.active:
-                    return True
+        if not self.isCheckable(row):
+            return False
+        item = self._model_model.item(row, 1)
+        if not item.hasChildren():
+            return False
+        c = item.child(0).data()
+        if isinstance(c, Constraint) and c.active:
+            return True
         return False
 
@@ -838,10 +842,12 @@
         Finds out if row of the main model has an active, nontrivial constraint child
         """
-        if self.isCheckable(row):
-            item = self._model_model.item(row, 1)
-            if item.hasChildren():
-                c = item.child(0).data()
-                if isinstance(c, Constraint) and c.func and c.active:
-                    return True
+        if not self.isCheckable(row):
+            return False
+        item = self._model_model.item(row, 1)
+        if not item.hasChildren():
+            return False
+        c = item.child(0).data()
+        if isinstance(c, Constraint) and c.func and c.active:
+            return True
         return False
 
@@ -1053,8 +1059,9 @@
             # Show constraint, if present
             row = rows[0].row()
-            if self.rowHasConstraint(row):
-                func = self.getConstraintForRow(row).func
-                if func is not None:
-                    self.communicate.statusBarUpdateSignal.emit("Active constrain: "+func)
+            if not self.rowHasConstraint(row):
+                return
+            func = self.getConstraintForRow(row).func
+            if func is not None:
+                self.communicate.statusBarUpdateSignal.emit("Active constrain: "+func)
 
     def replaceConstraintName(self, old_name, new_name=""):
@@ -1807,4 +1814,8 @@
         # Force data recalculation so existing charts are updated
         self.showPlot()
+        # This is an important processEvent.
+        # This allows charts to be properly updated in order
+        # of plots being applied.
+        QtWidgets.QApplication.processEvents()
         self.recalculatePlotData()
 
@@ -2091,4 +2102,6 @@
             return
 
+        product_params = None
+
         if self.kernel_module is None:
             # Structure factor is the only selected model; build it and show all its params
@@ -2096,5 +2109,4 @@
             s_params = self.kernel_module._model_info.parameters
             s_params_orig = s_params
-
         else:
             s_kernel = self.models[structure_factor]()
@@ -2113,13 +2125,22 @@
             if "radius_effective_mode" in all_param_names:
                 # Show all parameters
+                # In this case, radius_effective is NOT pruned by sasmodels.product
                 s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len])
                 s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters)
+                product_params = modelinfo.ParameterTable(
+                        self.kernel_module._model_info.parameters.kernel_parameters[p_pars_len+s_pars_len:])
             else:
                 # Ensure radius_effective is not displayed
                 s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters[1:])
                 if "radius_effective" in all_param_names:
+                    # In this case, radius_effective is NOT pruned by sasmodels.product
                     s_params = modelinfo.ParameterTable(all_params[p_pars_len+1:p_pars_len+s_pars_len])
+                    product_params = modelinfo.ParameterTable(
+                            self.kernel_module._model_info.parameters.kernel_parameters[p_pars_len+s_pars_len:])
                 else:
+                    # In this case, radius_effective is pruned by sasmodels.product
                     s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len-1])
+                    product_params = modelinfo.ParameterTable(
+                            self.kernel_module._model_info.parameters.kernel_parameters[p_pars_len+s_pars_len-1:])
 
         # Add heading row
@@ -2129,9 +2150,22 @@
         # Any renamed parameters are stored as data in the relevant item, for later handling
         FittingUtilities.addSimpleParametersToModel(
-                s_params,
-                self.is2D,
-                s_params_orig,
-                self._model_model,
-                self.lstParams)
+                parameters=s_params,
+                is2D=self.is2D,
+                parameters_original=s_params_orig,
+                model=self._model_model,
+                view=self.lstParams)
+
+        # Insert product-only params into QModel
+        if product_params:
+            prod_rows = FittingUtilities.addSimpleParametersToModel(
+                    parameters=product_params,
+                    is2D=self.is2D,
+                    parameters_original=None,
+                    model=self._model_model,
+                    view=self.lstParams,
+                    row_num=2)
+
+            # Since this all happens after shells are dealt with and we've inserted rows, fix this counter
+            self._n_shells_row += len(prod_rows)
 
     def haveParamsToFit(self):
@@ -2394,15 +2428,9 @@
 
         # Create plots for intermediate product data
-        pq_data, sq_data = self.logic.new1DProductPlots(return_data, self.tab_id)
-        if pq_data is not None:
-            pq_data.symbol = "Line"
-            self.createNewIndex(pq_data)
-            # self.communicate.plotUpdateSignal.emit([pq_data])
-            new_plots.append(pq_data)
-        if sq_data is not None:
-            sq_data.symbol = "Line"
-            self.createNewIndex(sq_data)
-            # self.communicate.plotUpdateSignal.emit([sq_data])
-            new_plots.append(sq_data)
+        plots = self.logic.new1DProductPlots(return_data, self.tab_id)
+        for plot in plots:
+            plot.symbol = "Line"
+            self.createNewIndex(plot)
+            new_plots.append(plot)
 
         for plot in new_plots:
@@ -2805,4 +2833,7 @@
         self._num_shell_params = len(new_rows)
         self.current_shell_displayed = index
+
+        # Change 'n' in the parameter model, thereby updating the underlying model
+        self._model_model.item(self._n_shells_row, 1).setText(str(index))
 
         # Update relevant models
@@ -3149,7 +3180,7 @@
             formatted_output = FittingUtilities.formatParameters(param_list)
         elif format == "Excel":
-            formatted_output = FittingUtilities.formatParametersExcel(param_list)
+            formatted_output = FittingUtilities.formatParametersExcel(param_list[1:])
         elif format == "Latex":
-            formatted_output = FittingUtilities.formatParametersLatex(param_list)
+            formatted_output = FittingUtilities.formatParametersLatex(param_list[1:])
         else:
             raise AttributeError("Bad format specifier.")
@@ -3316,2 +3347,4 @@
         self._poly_model.blockSignals(False)
 
+
+
Index: src/sas/qtgui/Perspectives/Fitting/ModelThread.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/ModelThread.py	(revision dcabba7be660ff2e140942eb331ca846d1f2a399)
+++ src/sas/qtgui/Perspectives/Fitting/ModelThread.py	(revision 5181e9b007b6389be27774b541e2fba4a11bec8d)
@@ -164,4 +164,6 @@
         index = (self.qmin <= self.data.x) & (self.data.x <= self.qmax)
 
+        intermediate_results = None
+
         # If we use a smearer, also return the unsmeared model
         unsmeared_output = None
@@ -174,5 +176,11 @@
             mask = self.data.x[first_bin:last_bin+1]
             unsmeared_output = numpy.zeros((len(self.data.x)))
-            unsmeared_output[first_bin:last_bin+1] = self.model.evalDistribution(mask)
+
+            return_data = self.model.calculate_Iq(mask)
+            if isinstance(return_data, tuple):
+                # see sasmodels beta_approx: SasviewModel.calculate_Iq
+                # TODO: implement intermediate results in smearers
+                return_data, _ = return_data
+            unsmeared_output[first_bin:last_bin+1] = return_data
             output = self.smearer(unsmeared_output, first_bin, last_bin)
 
@@ -193,24 +201,43 @@
                 unsmeared_error=unsmeared_error
         else:
-            output[index] = self.model.evalDistribution(self.data.x[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, "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])
+            return_data = self.model.calculate_Iq(self.data.x[index])
+            if isinstance(return_data, tuple):
+                # see sasmodels beta_approx: SasviewModel.calculate_Iq
+                return_data, intermediate_results = return_data
+            output[index] = return_data
+
+        if intermediate_results:
+            # the model returns a callable which is then used to retrieve the data
+            intermediate_results = intermediate_results()
+        else:
+            # TODO: this conditional branch needs refactoring
+            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, "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])
+
+            if pq_values is not None and sq_values is not None:
+                intermediate_results  = {
+                    "P(Q)": pq_values,
+                    "S(Q)": sq_values
+                }
+            else:
+                intermediate_results = {}
 
         elapsed = time.time() - self.starttime
@@ -223,5 +250,5 @@
             source = self.source, unsmeared_output = unsmeared_output,
             unsmeared_data = unsmeared_data, unsmeared_error = unsmeared_error,
-            pq_values = pq_values, sq_values = sq_values)
+            intermediate_results = intermediate_results)
 
         if LocalConfig.USING_TWISTED:
Index: src/sas/qtgui/Perspectives/Fitting/UI/OptionsWidgetUI.ui
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/UI/OptionsWidgetUI.ui	(revision 79bd26891bdd9931709cf7ba69842f6d8cadc62f)
+++ src/sas/qtgui/Perspectives/Fitting/UI/OptionsWidgetUI.ui	(revision 309fa1bc1122d4205485434154892a4b1021a687)
@@ -32,4 +32,10 @@
         <item row="0" column="1">
          <widget class="QLineEdit" name="txtMinRange">
+          <property name="minimumSize">
+           <size>
+            <width>80</width>
+            <height>0</height>
+           </size>
+          </property>
           <property name="toolTip">
            <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Minimum value of Q.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -54,4 +60,10 @@
         <item row="1" column="1">
          <widget class="QLineEdit" name="txtMaxRange">
+          <property name="minimumSize">
+           <size>
+            <width>80</width>
+            <height>0</height>
+           </size>
+          </property>
           <property name="toolTip">
            <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Maximum value of Q.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
Index: src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingLogicTest.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingLogicTest.py	(revision e752ab8241051d2dfff8481f44214d3ad205adac)
+++ src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingLogicTest.py	(revision bfb5d9edc7b8eb23b289ae01c36b2024e4936b05)
@@ -99,9 +99,14 @@
         data.name = "boop"
         data.id = "poop"
-        return_data = (data.x,data.y, 7, None, None,
-                       0, True, 0.0, 1, data,
-                       data, False, None,
-                       None, None, None,
-                       None, None)
+        # Condensed return data (new1DPlot only uses these fields)
+        return_data = dict(x = data.x,
+                           y = data.y,
+                           model = data,
+                           data = data)
+        # return_data = (data.x,data.y, 7, None, None,
+        #                0, True, 0.0, 1, data,
+        #                data, False, None,
+        #                None, None, None,
+        #                None, None)
 
         new_plot = self.logic.new1DPlot(return_data=return_data, tab_id=0)
@@ -139,7 +144,12 @@
         qmin, qmax, npts = self.logic.computeDataRange()
 
-        return_data = (x_0, data, 7, data, None,
-                        True, 0.0, 1, 0, qmin, qmax,
-                        0.1, False, None)
+        # Condensed return data (new2DPlot only uses these fields)
+        return_data = dict(image = x_0,
+                           data = data,
+                           page_id = 7,
+                           model = data)
+        # return_data = (x_0, data, 7, data, None,
+        #                 True, 0.0, 1, 0, qmin, qmax,
+        #                 0.1, False, None)
 
         new_plot = self.logic.new2DPlot(return_data=return_data)
Index: src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingOptionsTest.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingOptionsTest.py	(revision 725d9c06c2a66018f1352faba2f96cd31d8e9654)
+++ src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingOptionsTest.py	(revision bfb5d9edc7b8eb23b289ae01c36b2024e4936b05)
@@ -38,5 +38,5 @@
         # The combo box
         self.assertIsInstance(self.widget.cbAlgorithm, QtWidgets.QComboBox)
-        self.assertEqual(self.widget.cbAlgorithm.count(), 5)
+        self.assertEqual(self.widget.cbAlgorithm.count(), 6)
         self.assertEqual(self.widget.cbAlgorithm.itemText(0), 'Nelder-Mead Simplex')
         self.assertEqual(self.widget.cbAlgorithm.itemText(4), 'Levenberg-Marquardt')
Index: src/sas/qtgui/Plotting/Plotter.py
===================================================================
--- src/sas/qtgui/Plotting/Plotter.py	(revision c2f3ca2c72aeba33d19dcf49f5793abf90fa7a3b)
+++ src/sas/qtgui/Plotting/Plotter.py	(revision 0cd98a1bff2f5cc0a67f68ad681ae7a3c8379c75)
@@ -182,7 +182,7 @@
 
         # Update the list of data sets (plots) in chart
-        self.plot_dict[self._data.id] = self.data
-
-        self.plot_lines[self._data.id] = line
+        self.plot_dict[self._data.name] = self.data
+
+        self.plot_lines[self._data.name] = line
 
         # Now add the legend with some customizations.
@@ -201,8 +201,4 @@
         # refresh canvas
         self.canvas.draw()
-        # This is an important processEvent.
-        # This allows charts to be properly updated in order
-        # of plots being applied.
-        QtWidgets.QApplication.processEvents()
 
     def createContextMenu(self):
@@ -420,5 +416,4 @@
         This effectlvely refreshes the chart with changes to one of its plots
         """
-        import logging
         self.removePlot(id)
         self.plot(data=new_plot)
Index: src/sas/qtgui/Utilities/GuiUtils.py
===================================================================
--- src/sas/qtgui/Utilities/GuiUtils.py	(revision 0eff6153f4208fa47673e1006f3be34f6a55724a)
+++ src/sas/qtgui/Utilities/GuiUtils.py	(revision 339e22b9f5c08262b1d5b0b551ce467bcf83178c)
@@ -265,4 +265,7 @@
     # Mask Editor requested
     maskEditorSignal = QtCore.pyqtSignal(Data2D)
+
+    #second Mask Editor for external
+    extMaskEditorSignal = QtCore.pyqtSignal()
 
     # Fitting parameter copy to clipboard
