Index: src/sas/qtgui/Perspectives/Inversion/DMaxExplorerWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/DMaxExplorerWidget.py	(revision ae34d30993ebe39bd8bb7ec8e8117212afe7e15e)
+++ src/sas/qtgui/Perspectives/Inversion/DMaxExplorerWidget.py	(revision 6da860acc5670055935e7bdc8678d3827d1a057f)
@@ -8,6 +8,4 @@
 
 # global
-import sys
-import os
 import logging
 import numpy as np
@@ -51,16 +49,16 @@
 
         self.plot = PlotterWidget(self, self)
-        self.hasPlot = None
+        self.hasPlot = False
         self.verticalLayout.insertWidget(0, self.plot)
 
         # Let's choose the Standard Item Model.
         self.model = QtGui.QStandardItemModel(self)
-        self.mapper = None
+        self.mapper = QtWidgets.QDataWidgetMapper(self)
 
         # Add validators on line edits
         self.setupValidators()
 
-        # # Connect buttons to slots.
-        # # Needs to be done early so default values propagate properly.
+        # Connect buttons to slots.
+        # Needs to be done early so default values propagate properly.
         self.setupSlots()
 
@@ -89,5 +87,4 @@
 
     def setupMapper(self):
-        self.mapper = QtWidgets.QDataWidgetMapper(self)
         self.mapper.setOrientation(QtCore.Qt.Vertical)
         self.mapper.setModel(self.model)
@@ -112,7 +109,13 @@
         chi2 = []
 
-        xs = np.linspace(float(self.model.item(W.DMIN).text()),
-                         float(self.model.item(W.DMAX).text()),
-                         float(self.model.item(W.NPTS).text()))
+        try:
+            dmin = float(self.model.item(W.DMIN).text())
+            dmax = float(self.model.item(W.DMAX).text())
+            npts = float(self.model.item(W.NPTS).text())
+            xs = np.linspace(dmin, dmax, npts)
+        except ValueError as e:
+            msg = ("An input value is not correctly formatted. Please check {}"
+                   .format(e.message))
+            logger.error(msg)
 
         original = self.pr_state.d_max
@@ -133,5 +136,4 @@
                 msg = "ExploreDialog: inversion failed "
                 msg += "for D_max=%s\n%s" % (str(x), ex)
-                print(msg)
                 logger.error(msg)
 
@@ -143,5 +145,4 @@
             msg = "ExploreDialog: inversion failed "
             msg += "for D_max=%s\n%s" % (str(x), ex)
-            print(msg)
             logger.error(msg)
 
Index: src/sas/qtgui/Perspectives/Inversion/InversionLogic.py
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/InversionLogic.py	(revision 318b353ea4c52f0034692ba0653d7b1769337012)
+++ src/sas/qtgui/Perspectives/Inversion/InversionLogic.py	(revision 6da860acc5670055935e7bdc8678d3827d1a057f)
@@ -1,4 +1,4 @@
 import math
-import pylab
+import logging
 import numpy as np
 
@@ -12,4 +12,7 @@
 GROUP_ID_IQ_DATA = r"$I_{obs}(q)$"
 GROUP_ID_PR_FIT = r"$P_{fit}(r)$"
+PR_PLOT_PTS = 51
+
+logger = logging.getLogger(__name__)
 
 
@@ -19,7 +22,4 @@
     No QStandardModelIndex here.
     """
-
-    # TODO: Add way to change this value
-    _pr_n_pts = 51
 
     def __init__(self, data=None):
@@ -63,5 +63,5 @@
             maxq = pr.q_max
 
-        x = pylab.arange(minq, maxq, maxq / 301.0)
+        x = np.arange(minq, maxq, maxq / 301.0)
         y = np.zeros(len(x))
         err = np.zeros(len(x))
@@ -73,5 +73,5 @@
             except:
                 err[i] = 1.0
-                print(("Error getting error", value, x[i]))
+                logger.log(("Error getting error", value, x[i]))
 
         new_plot = Data1D(x, y)
@@ -89,5 +89,5 @@
         # If we have used slit smearing, plot the smeared I(q) too
         if pr.slit_width > 0 or pr.slit_height > 0:
-            x = pylab.arange(minq, maxq, maxq / 301.0)
+            x = np.arange(minq, maxq, maxq / 301.0)
             y = np.zeros(len(x))
             err = np.zeros(len(x))
@@ -99,5 +99,5 @@
                 except:
                     err[i] = 1.0
-                    print(("Error getting error", value, x[i]))
+                    logger.log(("Error getting error", value, x[i]))
 
             new_plot = Data1D(x, y)
@@ -113,63 +113,9 @@
         return new_plot
 
-    def update1DPlot(self, plot, out, pr, q=None):
-        """
-        Create a new 1D data instance based on fitting results
-        """
-
-        qtemp = pr.x
-        if q is not None:
-            qtemp = q
-
-        # Make a plot
-        maxq = max(qtemp)
-
-        minq = min(qtemp)
-
-        # Check for user min/max
-        if pr.q_min is not None and maxq >= pr.q_min >= minq:
-            minq = pr.q_min
-        if pr.q_max is not None and maxq >= pr.q_max >= minq:
-            maxq = pr.q_max
-
-        x = pylab.arange(minq, maxq, maxq / 301.0)
-        y = np.zeros(len(x))
-        err = np.zeros(len(x))
-        for i in range(len(x)):
-            value = pr.iq(out, x[i])
-            y[i] = value
-            try:
-                err[i] = math.sqrt(math.fabs(value))
-            except:
-                err[i] = 1.0
-                print(("Error getting error", value, x[i]))
-
-        plot.x = x
-        plot.y = y
-
-        # If we have used slit smearing, plot the smeared I(q) too
-        if pr.slit_width > 0 or pr.slit_height > 0:
-            x = pylab.arange(minq, maxq, maxq / 301.0)
-            y = np.zeros(len(x))
-            err = np.zeros(len(x))
-            for i in range(len(x)):
-                value = pr.iq_smeared(pr.out, x[i])
-                y[i] = value
-                try:
-                    err[i] = math.sqrt(math.fabs(value))
-                except:
-                    err[i] = 1.0
-                    print(("Error getting error", value, x[i]))
-
-            plot.x = x
-            plot.y = y
-
-        return plot
-
     def newPRPlot(self, out, pr, cov=None):
         """
         """
         # Show P(r)
-        x = pylab.arange(0.0, pr.d_max, pr.d_max / self._pr_n_pts)
+        x = np.arange(0.0, pr.d_max, pr.d_max / PR_PLOT_PTS)
 
         y = np.zeros(len(x))
@@ -193,11 +139,4 @@
             y[i] = value
 
-        # if self._normalize_output == True:
-        #     y = y / total
-        #     dy = dy / total
-        # elif self._scale_output_unity == True:
-        #     y = y / pmax
-        #     dy = dy / pmax
-
         if cov2 is None:
             new_plot = Data1D(x, y)
@@ -213,41 +152,4 @@
 
         return new_plot
-
-    def updatePRPlot(self, plot, out, pr, cov=None):
-        x = pylab.arange(0.0, pr.d_max, pr.d_max / self._pr_n_pts)
-
-        y = np.zeros(len(x))
-        dy = np.zeros(len(x))
-
-        total = 0.0
-        pmax = 0.0
-        cov2 = np.ascontiguousarray(cov)
-
-        for i in range(len(x)):
-            if cov2 is None:
-                value = pr.pr(out, x[i])
-            else:
-                (value, dy[i]) = pr.pr_err(out, cov2, x[i])
-            total += value * pr.d_max / len(x)
-
-            # keep track of the maximum P(r) value
-            if value > pmax:
-                pmax = value
-
-            y[i] = value
-
-        # if self._normalize_output == True:
-        #     y = y / total
-        #     dy = dy / total
-        # elif self._scale_output_unity == True:
-        #     y = y / pmax
-        #     dy = dy / pmax
-        plot.x = x
-        plot.y = y
-
-        if cov2 is not None:
-            plot.dy = dy
-
-        return plot
 
     def computeDataRange(self):
Index: src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py	(revision d79bb7e70dd3bf2ddf2859491935f47d0dfc8d47)
+++ src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py	(revision 6da860acc5670055935e7bdc8678d3827d1a057f)
@@ -31,4 +31,6 @@
 MAX_DIST = 140.0
 DICT_KEYS = ["Calculator", "PrPlot", "DataPlot"]
+
+logger = logging.getLogger(__name__)
 
 
@@ -354,5 +356,5 @@
             msg = "Unable to update P{r}. The connection between the main GUI "
             msg += "and P(r) was severed. Attempting to restart P(r)."
-            logging.warning(msg)
+            logger.warning(msg)
             self.setClosable(True)
             self.close()
@@ -395,5 +397,7 @@
         """
         from .DMaxExplorerWidget import DmaxWindow
-        self.dmaxWindow = DmaxWindow(self._calculator, self.getNFunc(), self)
+        self.dmaxWindow = DmaxWindow(pr_state=self._calculator,
+                                     nfunc=self.getNFunc(),
+                                     parent=self)
         self.dmaxWindow.show()
 
@@ -459,5 +463,5 @@
             nfunc = int(self.noOfTermsInput.text())
         except ValueError:
-            logging.error("Incorrect number of terms specified: %s"
+            logger.error("Incorrect number of terms specified: %s"
                           %self.noOfTermsInput.text())
             self.noOfTermsInput.setText(str(NUMBER_OF_TERMS))
@@ -581,4 +585,6 @@
                 self.dataList.setCurrentIndex(index)
                 self.isBatch = True
+                # Add the index before calculating in case calculation fails
+                self.batchComplete.append(index)
                 break
         if self.isBatch:
@@ -599,4 +605,7 @@
         # Set data before running the calculations
         self.updateCalculator()
+        # Disable calculation buttons to prevent thread interference
+        self.calculateAllButton.setEnabled(False)
+        self.calculateThisButton.setEnabled(False)
 
         # If a thread is already started, stop it
@@ -672,6 +681,8 @@
         """
         alpha, message, elapsed = output_tuple
+        self._calculator.alpha = alpha
+        self._calculator.elapsed += self._calculator.elapsed
         if message:
-            logging.info(message)
+            logger.info(message)
         self.performEstimateNT()
 
@@ -690,5 +701,5 @@
         """
         nterms, alpha, message, elapsed = output_tuple
-        self._calculator.elapsed = elapsed
+        self._calculator.elapsed += elapsed
         self._calculator.suggested_alpha = alpha
         self.nTermsSuggested = nterms
@@ -696,5 +707,5 @@
         self.updateGuiValues()
         if message:
-            logging.info(message)
+            logger.info(message)
         if self.isBatch:
             self.acceptAlpha()
@@ -742,3 +753,3 @@
             Call-back method for calculation errors
         """
-        logging.warning(error)
+        logger.error(error)
Index: src/sas/qtgui/Perspectives/Inversion/UI/dmax.ui
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/UI/dmax.ui	(revision 7f5196e3504984b5661fbf66a471b74d97902eeb)
+++ 	(revision )
@@ -1,125 +1,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>DmaxExplorer</class>
- <widget class="QDialog" name="DmaxExplorer">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>609</width>
-    <height>524</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>Dialog</string>
-  </property>
-  <layout class="QGridLayout" name="gridLayout_2">
-   <item row="0" column="0">
-    <layout class="QVBoxLayout" name="verticalLayout">
-     <item>
-      <spacer name="verticalSpacer">
-       <property name="orientation">
-        <enum>Qt::Vertical</enum>
-       </property>
-       <property name="sizeHint" stdset="0">
-        <size>
-         <width>20</width>
-         <height>40</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
-     <item>
-      <layout class="QGridLayout" name="gridLayout">
-       <item row="1" column="2">
-        <widget class="QLabel" name="label_4">
-         <property name="text">
-          <string>Max Distance [â«]</string>
-         </property>
-        </widget>
-       </item>
-       <item row="1" column="3">
-        <widget class="QLineEdit" name="maxDist"/>
-       </item>
-       <item row="0" column="2">
-        <widget class="QLabel" name="label_2">
-         <property name="text">
-          <string>Npts</string>
-         </property>
-        </widget>
-       </item>
-       <item row="0" column="3">
-        <widget class="QLineEdit" name="Npts"/>
-       </item>
-       <item row="0" column="0">
-        <widget class="QLabel" name="label">
-         <property name="text">
-          <string>Dependent Variable:</string>
-         </property>
-        </widget>
-       </item>
-       <item row="1" column="1">
-        <widget class="QLineEdit" name="minDist"/>
-       </item>
-       <item row="0" column="1">
-        <widget class="QComboBox" name="dependentVariable">
-         <item>
-          <property name="text">
-           <string>1-Ï positive fraction</string>
-          </property>
-         </item>
-         <item>
-          <property name="text">
-           <string>ÏÂ²/dof</string>
-          </property>
-         </item>
-         <item>
-          <property name="text">
-           <string>I(Q=0)</string>
-          </property>
-         </item>
-         <item>
-          <property name="text">
-           <string>Rg</string>
-          </property>
-         </item>
-         <item>
-          <property name="text">
-           <string>Oscillation parameter</string>
-          </property>
-         </item>
-         <item>
-          <property name="text">
-           <string>Background</string>
-          </property>
-         </item>
-         <item>
-          <property name="text">
-           <string>Positive Fraction</string>
-          </property>
-         </item>
-        </widget>
-       </item>
-       <item row="1" column="0">
-        <widget class="QLabel" name="label_3">
-         <property name="text">
-          <string>Min Distance [â«]</string>
-         </property>
-        </widget>
-       </item>
-       <item row="2" column="0" colspan="4">
-        <widget class="QPushButton" name="closeButton">
-         <property name="text">
-          <string>Close</string>
-         </property>
-        </widget>
-       </item>
-      </layout>
-     </item>
-    </layout>
-   </item>
-  </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
Index: src/sas/qtgui/Perspectives/Inversion/dmax.py
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/dmax.py	(revision 477c473ae34115e084e65daf139d3f47726775dd)
+++ 	(revision )
@@ -1,192 +1,0 @@
-# -*- coding: utf-8 -*-
-"""
-Dialog panel to explore the P(r) inversion results for a range
-of D_max value. User picks a number of points and a range of
-distances, then can toggle between inversion outputs and see
-their distribution as a function of D_max.
-"""
-
-# global
-import sys
-import os
-import logging
-import numpy as np
-from PyQt4 import QtCore
-from PyQt4 import QtGui
-from PyQt4 import QtWebKit
-
-from twisted.internet import threads
-
-# sas-global
-from sas.qtgui.Plotting.PlotterData import Data1D
-from sas.qtgui.Plotting.Plotter import PlotterWidget
-import sas.qtgui.Utilities.GuiUtils as GuiUtils
-
-# local
-from UI.dmax import Ui_DmaxExplorer
-# from InvariantDetails import DetailsDialog
-# from InvariantUtils import WIDGETS
-
-logger = logging.getLogger(__name__)
-
-def enum(*sequential, **named):
-    enums = dict(zip(sequential, range(len(sequential))), **named)
-    return type('Enum', (), enums)
-
-W = enum( 'NPTS',           #0
-          'DMIN',               #1
-          'DMAX',               #2
-          'VARIABLE',         #3
-)
-
-class DmaxWindow(QtGui.QDialog, Ui_DmaxExplorer):
-    # The controller which is responsible for managing signal slots connections
-    # for the gui and providing an interface to the data model.
-    name = "Dmax Explorer"  # For displaying in the combo box
-
-    def __init__(self, pr_state, nfunc, parent=None):
-        super(DmaxWindow, self).__init__()
-        self.setupUi(self)
-
-        self.setWindowTitle("Dâââ Explorer")
-
-        self.pr_state = pr_state
-        self.nfunc = nfunc
-        self.communicator = GuiUtils.Communicate()
-
-        self.plot = PlotterWidget(self, self)
-        self.hasPlot = None
-        self.verticalLayout.insertWidget(0, self.plot)
-
-        # Let's choose the Standard Item Model.
-        self.model = QtGui.QStandardItemModel(self)
-        self.mapper = None
-
-        # # Connect buttons to slots.
-        # # Needs to be done early so default values propagate properly.
-        self.setupSlots()
-
-        # Set up the model.
-        self.setupModel()
-
-        # # Set up the mapper
-        self.setupMapper()
-
-    def setupSlots(self):
-        self.closeButton.clicked.connect(self.close)
-
-        self.dependentVariable.currentIndexChanged.connect(self.dVChanged)
-
-        self.model.itemChanged.connect(self.modelChanged)
-
-    def setupModel(self):
-        self.model.setItem(W.NPTS, QtGui.QStandardItem(str(self.nfunc)))
-        self.model.setItem(W.DMIN,
-                           QtGui.QStandardItem(
-                               str(0.9*self.pr_state.d_max)))
-        self.model.setItem(W.DMAX,
-                           QtGui.QStandardItem(
-                               str(1.1*self.pr_state.d_max)))
-        self.model.setItem(W.VARIABLE,
-                           QtGui.QStandardItem( "ÏÂ²/dof"))
-
-    def setupMapper(self):
-        self.mapper = QtGui.QDataWidgetMapper(self)
-        self.mapper.setOrientation(QtCore.Qt.Vertical)
-        self.mapper.setModel(self.model)
-
-        self.mapper.addMapping(self.Npts, W.NPTS)
-        self.mapper.addMapping(self.minDist, W.DMIN)
-        self.mapper.addMapping(self.maxDist, W.DMAX)
-        self.mapper.addMapping(self.dependentVariable, W.VARIABLE)
-
-        self.mapper.toFirst()
-
-    def dVChanged(self):
-        self.modelChanged()
-
-    def modelChanged(self):
-        if not self.mapper:
-            return
-
-        iq0 = []
-        rg = []
-        pos = []
-        pos_err = []
-        osc = []
-        bck = []
-        chi2 = []
-
-        xs = np.linspace(float(self.model.item(W.DMIN).text()),
-                         float(self.model.item(W.DMAX).text()),
-                         float(self.model.item(W.NPTS).text()))
-
-        original = self.pr_state.d_max
-        for x in xs:
-            self.pr_state.d_max = x
-            try:
-                out, cov = self.pr_state.invert(self.pr_state.nfunc)
-
-                iq0.append(self.pr_state.iq0(out))
-                rg.append(self.pr_state.rg(out))
-                pos.append(self.pr_state.get_positive(out))
-                pos_err.append(self.pr_state.get_pos_err(out, cov))
-                osc.append(self.pr_state.oscillations(out))
-                bck.append(self.pr_state.background)
-                chi2.append(self.pr_state.chi2)
-            except:
-                # This inversion failed, skip this D_max value
-                msg = "ExploreDialog: inversion failed "
-                msg += "for D_max=%s\n%s" % (str(x), sys.exc_value)
-                print(msg)
-                # logger.error(msg)
-
-        #Return the invertor to its original state
-        self.pr_state.d_max = original
-        self.pr_state.invert(self.nfunc)
-
-        plotter = unicode(self.model.item(W.VARIABLE).text())
-        if plotter == u"ÏÂ²/dof":
-            ys = chi2
-        elif plotter == u"I(Q=0)":
-            ys = iq0
-        elif plotter == u"Rg":
-            ys = rg
-        elif plotter == u"Oscillation parameter":
-            ys = osc
-        elif plotter == u"Background":
-            ys = bck
-        elif plotter == u"Positive Fraction":
-            ys = pos
-        else:
-            ys = pos_err
-
-        data = Data1D(xs, ys)
-        if self.hasPlot:
-            self.plot.removePlot(None)
-        self.hasPlot = True
-        self.plot.plot(data=data, marker="-")
-
-
-if __name__ == "__main__":
-    APP = QtGui.QApplication([])
-    import qt4reactor
-    qt4reactor.install()
-    # DO NOT move the following import to the top!
-    # (unless you know what you're doing)
-    from twisted.internet import reactor
-    from sas.sascalc.pr.invertor import Invertor
-    from sas.sascalc.dataloader.loader import Loader
-
-    data = Loader().load("test/pr_inversion/test/sphere_80.txt")[0]
-    pr_state = Invertor()
-    pr_state.d_max = 130.0
-    pr_state.alpha = 0.0007
-    pr_state.x = data.x
-    pr_state.y = data.y
-    pr_state.err = 0.15*np.sqrt(data.y[0])*np.sqrt(data.y)
-    pr_state.nfunc = 15
-
-    DLG = DmaxWindow(pr_state, 15, reactor)
-    DLG.show()
-    reactor.run()
Index: src/sas/sascalc/pr/invertor.py
===================================================================
--- src/sas/sascalc/pr/invertor.py	(revision 8f83719fd67e6a72acdcd666e7bf1e2326b52cd0)
+++ src/sas/sascalc/pr/invertor.py	(revision 6da860acc5670055935e7bdc8678d3827d1a057f)
@@ -481,5 +481,5 @@
             float(chi2)
         except:
-            chi2 = [-1.0]
+            chi2 = -1.0
         self.chi2 = chi2
 
