Index: src/sas/qtgui/Perspectives/Fitting/FittingLogic.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingLogic.py	(revision 7248d75d0e91daa6e6c6163bb53fa76c1c8898e3)
+++ src/sas/qtgui/Perspectives/Fitting/FittingLogic.py	(revision 6fd4e36d87aa2c634f1fe31123e473984cad066c)
@@ -128,5 +128,6 @@
 
         # Assign the new Data1D object-wide
-        self._data = new_plot
+        #self._data = new_plot
+        return new_plot
 
     def new2DPlot(self, return_data):
@@ -171,6 +172,5 @@
                                     data_name + "]"
 
-        # Assign the new Data2D object-wide
-        self._data = new_plot
+        return new_plot
 
     def computeDataRange(self):
Index: src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py	(revision a9b568c21935bfbf9ed3ba4328251cab8d061430)
+++ src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py	(revision 6fd4e36d87aa2c634f1fe31123e473984cad066c)
@@ -1,4 +1,10 @@
 from PyQt4 import QtGui
 from PyQt4 import QtCore
+
+import numpy
+from copy import deepcopy
+
+from sas.sasgui.guiframe.dataFitting import Data1D
+from sas.sasgui.guiframe.dataFitting import Data2D
 
 def replaceShellName(param_name, value):
@@ -159,2 +165,62 @@
             model.appendRow([item1, item2, item3, item4, item5])
 
+def calculateChi2(reference_data, current_data):
+    """
+    Calculate Chi2 value between two sets of data
+    """
+
+    # WEIGHING INPUT
+    #from sas.sasgui.perspectives.fitting.utils import get_weight
+    #flag = self.get_weight_flag()
+    #weight = get_weight(data=self.data, is2d=self._is_2D(), flag=flag)
+
+    if reference_data == None:
+       return chisqr
+
+    # temporary default values for index and weight
+    index = None
+    weight = None
+
+    # Get data: data I, theory I, and data dI in order
+    if isinstance(reference_data, Data2D):
+        if index == None:
+            index = numpy.ones(len(current_data.data), dtype=bool)
+        if weight != None:
+            current_data.err_data = weight
+        # get rid of zero error points
+        index = index & (current_data.err_data != 0)
+        index = index & (numpy.isfinite(current_data.data))
+        fn = current_data.data[index]
+        gn = reference_data.data[index]
+        en = current_data.err_data[index]
+    else:
+        # 1 d theory from model_thread is only in the range of index
+        if index == None:
+            index = numpy.ones(len(current_data.y), dtype=bool)
+        if weight != None:
+            current_data.dy = weight
+        if current_data.dy == None or current_data.dy == []:
+            dy = numpy.ones(len(current_data.y))
+        else:
+            ## Set consistently w/AbstractFitengine:
+            # But this should be corrected later.
+            dy = deepcopy(current_data.dy)
+            dy[dy == 0] = 1
+        fn = current_data.y[index]
+        gn = reference_data.y
+        en = dy[index]
+    # Calculate the residual
+    try:
+        res = (fn - gn) / en
+    except ValueError:
+        print "Chi2 calculations: Unmatched lengths %s, %s, %s" % (len(fn), len(gn), len(en))
+        return
+
+    residuals = res[numpy.isfinite(res)]
+    chisqr = numpy.average(residuals * residuals)
+
+    return chisqr
+
+def binary_encode(i, digits):
+    return [i >> d & 1 for d in xrange(digits)]
+
Index: src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision a9b568c21935bfbf9ed3ba4328251cab8d061430)
+++ src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision 6fd4e36d87aa2c634f1fe31123e473984cad066c)
@@ -147,5 +147,5 @@
         assert isinstance(value[0], QtGui.QStandardItem)
         # _index contains the QIndex with data
-        self._index = value
+        self._index = value[0]
 
         # Update logics with data items
@@ -314,9 +314,9 @@
         self.SASModelToQModel(model)
 
-        if self._index is None:
+        if self.data_is_loaded:
+            self.calculateQGridForModel()
+        else:
             # Create default datasets if no data passed
             self.createDefaultDataset()
-        else:
-            self.calculateQGridForModel()
 
     def onSelectStructureFactor(self):
@@ -503,15 +503,44 @@
         # multishell params in self.kernel_module.details[??] = value
 
-
-    def createTheoryIndex(self):
-        """
-        Create a QStandardModelIndex containing default model data
-        """
-        name = self.kernel_module.name
+    def nameForFittedData(self, name):
+        """
+        Generate name for the current fit
+        """
         if self.is2D:
             name += "2d"
         name = "M%i [%s]" % (self.tab_id, name)
-        new_item = GuiUtils.createModelItemWithPlot(QtCore.QVariant(self.data), name=name)
-        # Notify the GUI manager so it can update the theory model in DataExplorer
+        return name
+
+    def createNewIndex(self, fitted_data):
+        """
+        Create a model or theory index with passed Data1D/Data2D
+        """
+        if self.data_is_loaded:
+            self.updateModelIndex(fitted_data)
+        else:
+            self.createTheoryIndex(fitted_data)
+
+    def updateModelIndex(self, fitted_data):
+        """
+        Update a QStandardModelIndex containing model data
+        """
+        name = self.nameForFittedData(self.logic.data.filename)
+        fitted_data.title = name
+        fitted_data.name = name
+        # Make this a line
+        fitted_data.symbol = 'Line'
+        # Notify the GUI manager so it can update the main model in DataExplorer
+        GuiUtils.updateModelItemWithPlot(self._index, QtCore.QVariant(fitted_data), name)
+
+    def createTheoryIndex(self, fitted_data):
+        """
+        Create a QStandardModelIndex containing model data
+        """
+        name = self.nameForFittedData(self.kernel_module.name)
+        fitted_data.title = name
+        fitted_data.name = name
+        fitted_data.filename = name
+        # Notify the GUI manager so it can create the theory model in DataExplorer
+        new_item = GuiUtils.createModelItemWithPlot(QtCore.QVariant(fitted_data), name=name)
         self.communicate.updateTheoryFromPerspectiveSignal.emit(new_item)
 
@@ -520,4 +549,5 @@
         Perform fitting on the current data
         """
+        # TODO: everything here
         #self.calculate1DForModel()
         pass
@@ -527,6 +557,5 @@
         Plot the current set of data
         """
-        # TODO: reimplement basepage.py/_update_paramv_on_fit
-        if self.data is None or not self.data.is_data:
+        if self.data is None :#or not self.data.is_data:
             self.createDefaultDataset()
         self.calculateQGridForModel()
@@ -607,27 +636,29 @@
         Plot the current 1D data
         """
-        self.logic.new1DPlot(return_data)
-        self.createTheoryIndex()
-
-        #output=self._cal_chisqr(data=data,
+        fitted_data = self.logic.new1DPlot(return_data)
+        self.calculateResiduals(self.logic.new1DPlot(return_data))
+
+    def complete2D(self, return_data):
+        """
+        Plot the current 2D data
+        """
+        fitted_data = self.logic.new2DPlot(return_data)
+        self.calculateResiduals(fitted_data)
+
+    def calculateResiduals(self, fitted_data):
+        """
+        Calculate and print Chi2 and display chart of residuals
+        """
+        # Create a new index for holding data
+        self.createNewIndex(fitted_data)
+        # Calculate difference between return_data and logic.data
+        chi2 = FittingUtilities.calculateChi2(fitted_data, self.logic.data)
+        # Update the control
+        self.lblChi2Value.setText(GuiUtils.formatNumber(chi2, high=True))
+
+        # TODO: plot residuals
+        #self._plot_residuals(page_id=page_id, data=current_data,
         #                        fid=fid,
-        #                        weight=weight,
-        #                        page_id=page_id,
-        #                        index=index)
-
-    def complete2D(self, return_data):
-        """
-        Plot the current 2D data
-        """
-        self.logic.new2DPlot(return_data)
-        self.createTheoryIndex()
-
-        #output=self._cal_chisqr(data=data,
-        #                        weight=weight,
-        #                        fid=fid,
-        #                        page_id=page_id,
-        #                        index=index)
-        #    self._plot_residuals(page_id=page_id, data=data, fid=fid,
-        #                            index=index, weight=weight)
+        #                        weight=weight, index=index)
 
     def calcException(self, etype, value, tb):
Index: src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingLogicTest.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingLogicTest.py	(revision 351b53ec7df03f611b0f054c0dde289dc8a5089f)
+++ src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingLogicTest.py	(revision 6fd4e36d87aa2c634f1fe31123e473984cad066c)
@@ -104,11 +104,11 @@
                         data, False, None)
 
-        self.logic.new1DPlot(return_data=return_data)
+        new_plot = self.logic.new1DPlot(return_data=return_data)
 
-        self.assertIsInstance(self.logic.data, Data1D)
-        self.assertFalse(self.logic.data.is_data)
-        self.assertEqual(self.logic.data.dy.size, 3)
-        self.assertEqual(self.logic.data.title, "boop")
-        self.assertEqual(self.logic.data.name, "boop [boop]")
+        self.assertIsInstance(new_plot, Data1D)
+        self.assertFalse(new_plot.is_data)
+        self.assertEqual(new_plot.dy.size, 3)
+        self.assertEqual(new_plot.title, "boop")
+        self.assertEqual(new_plot.name, "boop [boop]")
 
     def testNew2DPlot(self):
@@ -142,10 +142,10 @@
                         0.1, False, None)
 
-        self.logic.new2DPlot(return_data=return_data)
+        new_plot = self.logic.new2DPlot(return_data=return_data)
 
-        self.assertIsInstance(self.logic.data, Data2D)
-        self.assertFalse(self.logic.data.is_data)
-        self.assertEqual(self.logic.data.title, "Analytical model 2D ")
-        self.assertEqual(self.logic.data.name, "boop [boop]")
+        self.assertIsInstance(new_plot, Data2D)
+        self.assertFalse(new_plot.is_data)
+        self.assertEqual(new_plot.title, "Analytical model 2D ")
+        self.assertEqual(new_plot.name, "boop [boop]")
 
 
Index: src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingUtilitiesTest.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingUtilitiesTest.py	(revision b1e36a387414e3a8dc9726bbef5c0651364e2b64)
+++ src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingUtilitiesTest.py	(revision 6fd4e36d87aa2c634f1fe31123e473984cad066c)
@@ -3,6 +3,9 @@
 from PyQt4 import QtGui
 
+from sas.sasgui.guiframe.dataFitting import Data1D
+from sas.sasgui.guiframe.dataFitting import Data2D
+
 from UnitTesting.TestUtils import WarningTestNotImplemented
-#from sasmodels.sasview_model import load_standard_models
+
 from sasmodels import generate
 from sasmodels import modelinfo
@@ -180,4 +183,72 @@
         self.assertEqual(model.item(1).child(0).child(0,1).text(), "40.0")
 
+    def testCalculate1DChi2(self):
+        """
+        Test the chi2 calculator for Data1D
+        """
+        reference_data = Data1D(x=[0.1, 0.2], y=[0.0, 0.0])
+
+        # 1. identical data
+        current_data = Data1D(x=[0.1, 0.2], y=[0.0, 0.0])
+
+        chi = FittingUtilities.calculateChi2(reference_data, current_data)
+
+        # Should be zero
+        self.assertAlmostEqual(chi, 0.0, 8)
+
+        # 2. far data
+        current_data = Data1D(x=[0.1, 0.2], y=[200.0, 150.0])
+
+        chi = FittingUtilities.calculateChi2(reference_data, current_data)
+
+        # Should not be zero
+        self.assertAlmostEqual(chi, 31250.0, 8)
+
+        # 3. Wrong data
+        current_data = Data1D(x=[0.1, 0.2], y=[200.0, 150.0, 200.0])
+        chi = FittingUtilities.calculateChi2(reference_data, current_data)
+        # Should be None
+        self.assertIsNone(chi)
+
+    def testCalculate2DChi2(self):
+        """
+        Test the chi2 calculator for Data2D
+        """
+        reference_data = Data2D(image=[1.0, 2.0, 3.0],
+                      err_image=[0.01, 0.02, 0.03],
+                      qx_data=[0.1, 0.2, 0.3],
+                      qy_data=[0.1, 0.2, 0.3])
+
+        # 1. identical data
+        current_data = Data2D(image=[1.0, 2.0, 3.0],
+                      err_image=[0.01, 0.02, 0.03],
+                      qx_data=[0.1, 0.2, 0.3],
+                      qy_data=[0.1, 0.2, 0.3])
+
+        chi = FittingUtilities.calculateChi2(reference_data, current_data)
+
+        # Should be zero
+        self.assertAlmostEqual(chi, 0.0, 8)
+
+        # 2. far data
+        current_data = Data2D(image=[100.0, 200.0, 300.0],
+                      err_image=[1.01, 2.02, 3.03],
+                      qx_data=[0.1, 0.2, 0.3],
+                      qy_data=[100.0, 200., 300.])
+
+        chi = FittingUtilities.calculateChi2(reference_data, current_data)
+
+        # Should not be zero
+        self.assertAlmostEqual(chi, 9607.88, 2)
+
+        # 3. Wrong data
+        current_data = Data2D(image=[1.0, 2.0, 3.0],
+                      err_image=[0.01, 0.02],
+                      qx_data=[0.1, 0.2],
+                      qy_data=[0.1, 0.2, 0.3])
+        # Should throw
+        with self.assertRaises(ValueError):
+            chi = FittingUtilities.calculateChi2(reference_data, current_data)
+
 if __name__ == "__main__":
     unittest.main()
Index: src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py	(revision 9934e484226b58f541e17d74e149adff09368b0b)
+++ src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py	(revision 6fd4e36d87aa2c634f1fe31123e473984cad066c)
@@ -215,6 +215,6 @@
         self.assertFalse(self.widget.calculateQGridForModel.called)
 
-        # Let's set a dummy index on widget
-        self.widget._index = QtGui.QStandardItem()
+        # Let's tell the widget that data has been loaded
+        self.widget.data_is_loaded = True
         # Reset the sasmodel index
         self.widget.cbModel.setCurrentIndex(1)
Index: src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py
===================================================================
--- src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py	(revision b1e36a387414e3a8dc9726bbef5c0651364e2b64)
+++ src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py	(revision 6fd4e36d87aa2c634f1fe31123e473984cad066c)
@@ -59,5 +59,5 @@
         self._manager = parent
         #self._manager = manager
-        self._reactor = self._manager.reactor()
+        self._reactor = reactor
         self._model_item = QtGui.QStandardItem()
 
